1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/thumbnails/content/backgroundPageThumbsContent.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,171 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +(function () { // bug 673569 workaround :( 1.9 + 1.10 +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; 1.11 + 1.12 +Cu.import("resource://gre/modules/PageThumbs.jsm"); 1.13 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.14 +Cu.import("resource://gre/modules/Services.jsm"); 1.15 + 1.16 +const STATE_LOADING = 1; 1.17 +const STATE_CAPTURING = 2; 1.18 +const STATE_CANCELED = 3; 1.19 + 1.20 +const backgroundPageThumbsContent = { 1.21 + 1.22 + init: function () { 1.23 + Services.obs.addObserver(this, "document-element-inserted", true); 1.24 + 1.25 + // We want a low network priority for this service - lower than b/g tabs 1.26 + // etc - so set it to the lowest priority available. 1.27 + this._webNav.QueryInterface(Ci.nsIDocumentLoader). 1.28 + loadGroup.QueryInterface(Ci.nsISupportsPriority). 1.29 + priority = Ci.nsISupportsPriority.PRIORITY_LOWEST; 1.30 + 1.31 + docShell.allowMedia = false; 1.32 + docShell.allowPlugins = false; 1.33 + docShell.allowContentRetargeting = false; 1.34 + let defaultFlags = Ci.nsIRequest.LOAD_ANONYMOUS | 1.35 + Ci.nsIRequest.LOAD_BYPASS_CACHE | 1.36 + Ci.nsIRequest.INHIBIT_CACHING | 1.37 + Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY; 1.38 + docShell.defaultLoadFlags = defaultFlags; 1.39 + 1.40 + addMessageListener("BackgroundPageThumbs:capture", 1.41 + this._onCapture.bind(this)); 1.42 + docShell. 1.43 + QueryInterface(Ci.nsIInterfaceRequestor). 1.44 + getInterface(Ci.nsIWebProgress). 1.45 + addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_WINDOW); 1.46 + }, 1.47 + 1.48 + observe: function (subj, topic, data) { 1.49 + // Arrange to prevent (most) popup dialogs for this window - popups done 1.50 + // in the parent (eg, auth) aren't prevented, but alert() etc are. 1.51 + // disableDialogs only works on the current inner window, so it has 1.52 + // to be called every page load, but before scripts run. 1.53 + if (subj == content.document) { 1.54 + content. 1.55 + QueryInterface(Ci.nsIInterfaceRequestor). 1.56 + getInterface(Ci.nsIDOMWindowUtils). 1.57 + disableDialogs(); 1.58 + } 1.59 + }, 1.60 + 1.61 + get _webNav() { 1.62 + return docShell.QueryInterface(Ci.nsIWebNavigation); 1.63 + }, 1.64 + 1.65 + _onCapture: function (msg) { 1.66 + this._nextCapture = { 1.67 + id: msg.data.id, 1.68 + url: msg.data.url, 1.69 + }; 1.70 + if (this._currentCapture) { 1.71 + if (this._state == STATE_LOADING) { 1.72 + // Cancel the current capture. 1.73 + this._state = STATE_CANCELED; 1.74 + this._loadAboutBlank(); 1.75 + } 1.76 + // Let the current capture finish capturing, or if it was just canceled, 1.77 + // wait for onStateChange due to the about:blank load. 1.78 + return; 1.79 + } 1.80 + this._startNextCapture(); 1.81 + }, 1.82 + 1.83 + _startNextCapture: function () { 1.84 + if (!this._nextCapture) 1.85 + return; 1.86 + this._currentCapture = this._nextCapture; 1.87 + delete this._nextCapture; 1.88 + this._state = STATE_LOADING; 1.89 + this._currentCapture.pageLoadStartDate = new Date(); 1.90 + this._webNav.loadURI(this._currentCapture.url, 1.91 + Ci.nsIWebNavigation.LOAD_FLAGS_STOP_CONTENT, 1.92 + null, null, null); 1.93 + }, 1.94 + 1.95 + onStateChange: function (webProgress, req, flags, status) { 1.96 + if (webProgress.isTopLevel && 1.97 + (flags & Ci.nsIWebProgressListener.STATE_STOP) && 1.98 + this._currentCapture) { 1.99 + if (req.name == "about:blank") { 1.100 + if (this._state == STATE_CAPTURING) { 1.101 + // about:blank has loaded, ending the current capture. 1.102 + this._finishCurrentCapture(); 1.103 + delete this._currentCapture; 1.104 + this._startNextCapture(); 1.105 + } 1.106 + else if (this._state == STATE_CANCELED) { 1.107 + // A capture request was received while the current capture's page 1.108 + // was still loading. 1.109 + delete this._currentCapture; 1.110 + this._startNextCapture(); 1.111 + } 1.112 + } 1.113 + else if (this._state == STATE_LOADING) { 1.114 + // The requested page has loaded. Capture it. 1.115 + this._state = STATE_CAPTURING; 1.116 + this._captureCurrentPage(); 1.117 + } 1.118 + } 1.119 + }, 1.120 + 1.121 + _captureCurrentPage: function () { 1.122 + let capture = this._currentCapture; 1.123 + capture.finalURL = this._webNav.currentURI.spec; 1.124 + capture.pageLoadTime = new Date() - capture.pageLoadStartDate; 1.125 + 1.126 + let canvas = PageThumbs._createCanvas(content); 1.127 + let canvasDrawDate = new Date(); 1.128 + PageThumbs._captureToCanvas(content, canvas); 1.129 + capture.canvasDrawTime = new Date() - canvasDrawDate; 1.130 + 1.131 + canvas.toBlob(blob => { 1.132 + capture.imageBlob = blob; 1.133 + // Load about:blank to finish the capture and wait for onStateChange. 1.134 + this._loadAboutBlank(); 1.135 + }); 1.136 + }, 1.137 + 1.138 + _finishCurrentCapture: function () { 1.139 + let capture = this._currentCapture; 1.140 + let fileReader = Cc["@mozilla.org/files/filereader;1"]. 1.141 + createInstance(Ci.nsIDOMFileReader); 1.142 + fileReader.onloadend = () => { 1.143 + sendAsyncMessage("BackgroundPageThumbs:didCapture", { 1.144 + id: capture.id, 1.145 + imageData: fileReader.result, 1.146 + finalURL: capture.finalURL, 1.147 + telemetry: { 1.148 + CAPTURE_PAGE_LOAD_TIME_MS: capture.pageLoadTime, 1.149 + CAPTURE_CANVAS_DRAW_TIME_MS: capture.canvasDrawTime, 1.150 + }, 1.151 + }); 1.152 + }; 1.153 + fileReader.readAsArrayBuffer(capture.imageBlob); 1.154 + }, 1.155 + 1.156 + // We load about:blank to finish all captures, even canceled captures. Two 1.157 + // reasons: GC the captured page, and ensure it can't possibly load any more 1.158 + // resources. 1.159 + _loadAboutBlank: function _loadAboutBlank() { 1.160 + this._webNav.loadURI("about:blank", 1.161 + Ci.nsIWebNavigation.LOAD_FLAGS_STOP_CONTENT, 1.162 + null, null, null); 1.163 + }, 1.164 + 1.165 + QueryInterface: XPCOMUtils.generateQI([ 1.166 + Ci.nsIWebProgressListener, 1.167 + Ci.nsISupportsWeakReference, 1.168 + Ci.nsIObserver, 1.169 + ]), 1.170 +}; 1.171 + 1.172 +backgroundPageThumbsContent.init(); 1.173 + 1.174 +})();