Bug 1387580 - Some top sites never get screenshots of redirected pages. r?adw draft
authorEd Lee <edilee@mozilla.com>
Sat, 05 Aug 2017 00:34:25 -0700
changeset 641065 e7b4194cab551e24105545abc5717642466241e7
parent 621399 4cfb674227051e22bab651e5759f3de503a50560
child 641071 bb2cd5d4d5e4e390ecfbd7ea39732cd3f7721f51
push id72423
push userbmo:edilee@mozilla.com
push dateSat, 05 Aug 2017 07:47:19 +0000
reviewersadw
bugs1387580
milestone57.0a1
Bug 1387580 - Some top sites never get screenshots of redirected pages. r?adw MozReview-Commit-ID: IzmzXhGnPcH
toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
--- a/toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
+++ b/toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
@@ -1,22 +1,26 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* eslint-env mozilla/frame-script */
 
-var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
 
 Cu.importGlobalProperties(["Blob", "FileReader"]);
 
 Cu.import("resource://gre/modules/PageThumbUtils.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
+// Let the page settle for this amount of milliseconds before capturing to allow
+// for any in-page changes or redirects.
+const SETTLE_WAIT_TIME = 2500;
+
 const STATE_LOADING = 1;
 const STATE_CAPTURING = 2;
 const STATE_CANCELED = 3;
 
 // NOTE: Copied from nsSandboxFlags.h
 /**
  * This flag prevents content from creating new auxiliary browsing contexts,
  * e.g. using the target attribute, the window.open() method, or the
@@ -117,20 +121,33 @@ const backgroundPageThumbsContent = {
           this._finishCurrentCapture();
           delete this._currentCapture;
           this._startNextCapture();
         } else if (this._state == STATE_CANCELED) {
           delete this._currentCapture;
           this._startNextCapture();
         }
       } else if (this._state == STATE_LOADING &&
-               Components.isSuccessCode(status)) {
-        // The requested page has loaded.  Capture it.
-        this._state = STATE_CAPTURING;
-        this._captureCurrentPage();
+                 (Components.isSuccessCode(status) ||
+                  status === Cr.NS_BINDING_ABORTED)) {
+        // The requested page has loaded or stopped/aborted, so capture the page
+        // soon but first let it settle in case of in-page redirects
+        if (this._captureTimer) {
+          // There was additional activity, so restart the wait timer
+          this._captureTimer.delay = SETTLE_WAIT_TIME;
+        } else {
+          // Stay in LOADING until we're actually ready to be CAPTURING
+          this._captureTimer =
+            Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+          this._captureTimer.init(() => {
+            this._state = STATE_CAPTURING;
+            this._captureCurrentPage();
+            delete this._captureTimer;
+          }, SETTLE_WAIT_TIME, Ci.nsITimer.TYPE_ONE_SHOT);
+        }
       } else if (this._state != STATE_CANCELED) {
         // Something went wrong.  Cancel the capture.  Loading about:blank
         // while onStateChange is still on the stack does not actually stop
         // the request if it redirects, so do it asyncly.
         this._state = STATE_CANCELED;
         if (!this._cancelTimer) {
           this._cancelTimer =
             Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);