|
1 #ifdef 0 |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 #endif |
|
6 |
|
7 Cu.import("resource://gre/modules/NewTabUtils.jsm"); |
|
8 |
|
9 /** |
|
10 * Keeps thumbnails of open web pages up-to-date. |
|
11 */ |
|
12 let gBrowserThumbnails = { |
|
13 /** |
|
14 * Pref that controls whether we can store SSL content on disk |
|
15 */ |
|
16 PREF_DISK_CACHE_SSL: "browser.cache.disk_cache_ssl", |
|
17 |
|
18 _captureDelayMS: 1000, |
|
19 |
|
20 /** |
|
21 * Used to keep track of disk_cache_ssl preference |
|
22 */ |
|
23 _sslDiskCacheEnabled: null, |
|
24 |
|
25 /** |
|
26 * Map of capture() timeouts assigned to their browsers. |
|
27 */ |
|
28 _timeouts: null, |
|
29 |
|
30 /** |
|
31 * List of tab events we want to listen for. |
|
32 */ |
|
33 _tabEvents: ["TabClose", "TabSelect"], |
|
34 |
|
35 init: function Thumbnails_init() { |
|
36 // Bug 863512 - Make page thumbnails work in electrolysis |
|
37 if (gMultiProcessBrowser) |
|
38 return; |
|
39 |
|
40 PageThumbs.addExpirationFilter(this); |
|
41 gBrowser.addTabsProgressListener(this); |
|
42 Services.prefs.addObserver(this.PREF_DISK_CACHE_SSL, this, false); |
|
43 |
|
44 this._sslDiskCacheEnabled = |
|
45 Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL); |
|
46 |
|
47 this._tabEvents.forEach(function (aEvent) { |
|
48 gBrowser.tabContainer.addEventListener(aEvent, this, false); |
|
49 }, this); |
|
50 |
|
51 this._timeouts = new WeakMap(); |
|
52 }, |
|
53 |
|
54 uninit: function Thumbnails_uninit() { |
|
55 // Bug 863512 - Make page thumbnails work in electrolysis |
|
56 if (gMultiProcessBrowser) |
|
57 return; |
|
58 |
|
59 PageThumbs.removeExpirationFilter(this); |
|
60 gBrowser.removeTabsProgressListener(this); |
|
61 Services.prefs.removeObserver(this.PREF_DISK_CACHE_SSL, this); |
|
62 |
|
63 this._tabEvents.forEach(function (aEvent) { |
|
64 gBrowser.tabContainer.removeEventListener(aEvent, this, false); |
|
65 }, this); |
|
66 }, |
|
67 |
|
68 handleEvent: function Thumbnails_handleEvent(aEvent) { |
|
69 switch (aEvent.type) { |
|
70 case "scroll": |
|
71 let browser = aEvent.currentTarget; |
|
72 if (this._timeouts.has(browser)) |
|
73 this._delayedCapture(browser); |
|
74 break; |
|
75 case "TabSelect": |
|
76 this._delayedCapture(aEvent.target.linkedBrowser); |
|
77 break; |
|
78 case "TabClose": { |
|
79 this._clearTimeout(aEvent.target.linkedBrowser); |
|
80 break; |
|
81 } |
|
82 } |
|
83 }, |
|
84 |
|
85 observe: function Thumbnails_observe() { |
|
86 this._sslDiskCacheEnabled = |
|
87 Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL); |
|
88 }, |
|
89 |
|
90 filterForThumbnailExpiration: |
|
91 function Thumbnails_filterForThumbnailExpiration(aCallback) { |
|
92 aCallback(this._topSiteURLs); |
|
93 }, |
|
94 |
|
95 /** |
|
96 * State change progress listener for all tabs. |
|
97 */ |
|
98 onStateChange: function Thumbnails_onStateChange(aBrowser, aWebProgress, |
|
99 aRequest, aStateFlags, aStatus) { |
|
100 if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP && |
|
101 aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) |
|
102 this._delayedCapture(aBrowser); |
|
103 }, |
|
104 |
|
105 _capture: function Thumbnails_capture(aBrowser) { |
|
106 if (this._shouldCapture(aBrowser)) |
|
107 PageThumbs.captureAndStoreIfStale(aBrowser); |
|
108 }, |
|
109 |
|
110 _delayedCapture: function Thumbnails_delayedCapture(aBrowser) { |
|
111 if (this._timeouts.has(aBrowser)) |
|
112 clearTimeout(this._timeouts.get(aBrowser)); |
|
113 else |
|
114 aBrowser.addEventListener("scroll", this, true); |
|
115 |
|
116 let timeout = setTimeout(function () { |
|
117 this._clearTimeout(aBrowser); |
|
118 this._capture(aBrowser); |
|
119 }.bind(this), this._captureDelayMS); |
|
120 |
|
121 this._timeouts.set(aBrowser, timeout); |
|
122 }, |
|
123 |
|
124 _shouldCapture: function Thumbnails_shouldCapture(aBrowser) { |
|
125 // Capture only if it's the currently selected tab. |
|
126 if (aBrowser != gBrowser.selectedBrowser) |
|
127 return false; |
|
128 |
|
129 // Only capture about:newtab top sites. |
|
130 if (this._topSiteURLs.indexOf(aBrowser.currentURI.spec) < 0) |
|
131 return false; |
|
132 |
|
133 // Don't capture in per-window private browsing mode. |
|
134 if (PrivateBrowsingUtils.isWindowPrivate(window)) |
|
135 return false; |
|
136 |
|
137 let doc = aBrowser.contentDocument; |
|
138 |
|
139 // FIXME Bug 720575 - Don't capture thumbnails for SVG or XML documents as |
|
140 // that currently regresses Talos SVG tests. |
|
141 if (doc instanceof SVGDocument || doc instanceof XMLDocument) |
|
142 return false; |
|
143 |
|
144 // There's no point in taking screenshot of loading pages. |
|
145 if (aBrowser.docShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE) |
|
146 return false; |
|
147 |
|
148 // Don't take screenshots of about: pages. |
|
149 if (aBrowser.currentURI.schemeIs("about")) |
|
150 return false; |
|
151 |
|
152 let channel = aBrowser.docShell.currentDocumentChannel; |
|
153 |
|
154 // No valid document channel. We shouldn't take a screenshot. |
|
155 if (!channel) |
|
156 return false; |
|
157 |
|
158 // Don't take screenshots of internally redirecting about: pages. |
|
159 // This includes error pages. |
|
160 let uri = channel.originalURI; |
|
161 if (uri.schemeIs("about")) |
|
162 return false; |
|
163 |
|
164 let httpChannel; |
|
165 try { |
|
166 httpChannel = channel.QueryInterface(Ci.nsIHttpChannel); |
|
167 } catch (e) { /* Not an HTTP channel. */ } |
|
168 |
|
169 if (httpChannel) { |
|
170 // Continue only if we have a 2xx status code. |
|
171 try { |
|
172 if (Math.floor(httpChannel.responseStatus / 100) != 2) |
|
173 return false; |
|
174 } catch (e) { |
|
175 // Can't get response information from the httpChannel |
|
176 // because mResponseHead is not available. |
|
177 return false; |
|
178 } |
|
179 |
|
180 // Cache-Control: no-store. |
|
181 if (httpChannel.isNoStoreResponse()) |
|
182 return false; |
|
183 |
|
184 // Don't capture HTTPS pages unless the user explicitly enabled it. |
|
185 if (uri.schemeIs("https") && !this._sslDiskCacheEnabled) |
|
186 return false; |
|
187 } |
|
188 |
|
189 return true; |
|
190 }, |
|
191 |
|
192 get _topSiteURLs() { |
|
193 return NewTabUtils.links.getLinks().reduce((urls, link) => { |
|
194 if (link) |
|
195 urls.push(link.url); |
|
196 return urls; |
|
197 }, []); |
|
198 }, |
|
199 |
|
200 _clearTimeout: function Thumbnails_clearTimeout(aBrowser) { |
|
201 if (this._timeouts.has(aBrowser)) { |
|
202 aBrowser.removeEventListener("scroll", this, false); |
|
203 clearTimeout(this._timeouts.get(aBrowser)); |
|
204 this._timeouts.delete(aBrowser); |
|
205 } |
|
206 } |
|
207 }; |