| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 1 /* | 1 /* |
| 2 * This Source Code is subject to the terms of the Mozilla Public License | 2 * This Source Code is subject to the terms of the Mozilla Public License |
| 3 * version 2.0 (the "License"). You can obtain a copy of the License at | 3 * version 2.0 (the "License"). You can obtain a copy of the License at |
| 4 * http://mozilla.org/MPL/2.0/. | 4 * http://mozilla.org/MPL/2.0/. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * @module crawler | 8 * @module crawler |
|
saroyanm
2015/05/04 18:13:43
I think this should be file overview, maybe smth l
Wladimir Palant
2015/05/07 00:04:59
As Sebastian noted elsewhere, @module is actually
| |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 Cu.import("resource://gre/modules/Services.jsm"); | 11 Cu.import("resource://gre/modules/Services.jsm"); |
| 12 Cu.import("resource://gre/modules/Task.jsm"); | 12 Cu.import("resource://gre/modules/Task.jsm"); |
| 13 Cu.import("resource://gre/modules/Promise.jsm"); | 13 Cu.import("resource://gre/modules/Promise.jsm"); |
| 14 | |
| 15 let {reportException} = require("debug"); | |
| 14 | 16 |
| 15 function abprequire(module) | 17 function abprequire(module) |
| 16 { | 18 { |
| 17 let result = {}; | 19 let result = {}; |
|
saroyanm
2015/05/04 18:13:43
We can create here Object without Object prototype
Sebastian Noack
2015/05/04 20:39:01
It seems that we don't need to bother about confli
Wladimir Palant
2015/05/07 00:04:59
Yes, this isn't a place where property conflicts c
| |
| 18 result.wrappedJSObject = result; | 20 result.wrappedJSObject = result; |
| 19 Services.obs.notifyObservers(result, "adblockplus-require", module); | 21 Services.obs.notifyObservers(result, "adblockplus-require", module); |
| 20 return result.exports; | 22 return result.exports; |
| 21 } | 23 } |
| 22 | 24 |
| 23 let {Policy} = abprequire("contentPolicy"); | 25 let {Policy} = abprequire("contentPolicy"); |
| 24 let {RequestNotifier} = abprequire("requestNotifier"); | 26 let {RequestNotifier} = abprequire("requestNotifier"); |
| 25 let {Utils} = abprequire("utils"); | 27 let {Utils} = abprequire("utils"); |
| 26 | 28 |
| 27 let dataForTab = new WeakMap(); | 29 let dataForTab = new WeakMap(); |
| 28 | 30 |
| 29 /** | 31 /** |
| 30 * Creates a pool of tabs and allocates them to tasks on request. | 32 * Creates a pool of tabs and allocates them to tasks on request. |
| 31 * | 33 * |
| 32 * @param {tabbrowser} browser | 34 * @param {tabbrowser} browser |
| 33 * The tabbed browser where tabs should be created | 35 * The tabbed browser where tabs should be created |
| 34 * @param {int} maxtabs | 36 * @param {int} maxtabs |
| 35 * The maximum number of tabs to be allocated | 37 * The maximum number of tabs to be allocated |
| 36 * @constructor | 38 * @constructor |
| 37 */ | 39 */ |
| 38 function TabAllocator(browser, maxtabs) | 40 function TabAllocator(browser, maxtabs) |
|
saroyanm
2015/05/04 18:13:43
Why don't we use default amount of maxtab equal to
Wladimir Palant
2015/05/07 00:04:59
Because the text file has 50 thousand URLs.
| |
| 39 { | 41 { |
| 40 browser.removeAllTabsBut(browser.tabs[0]) | 42 browser.removeAllTabsBut(browser.tabs[0]) |
| 41 | 43 |
| 42 this._tabs = []; | 44 this._tabs = []; |
| 43 for (let i = 0; i < maxtabs; i++) | 45 for (let i = 0; i < maxtabs; i++) |
| 44 this._tabs.push(browser.addTab("about:blank")); | 46 this._tabs.push(browser.addTab("about:blank")); |
| 45 | 47 |
| 46 browser.removeTab(browser.tabs[0]); | 48 browser.removeTab(browser.tabs[0]); |
| 47 | 49 |
| 48 this._deferred = []; | 50 this._queue = []; |
| 49 } | 51 } |
| 50 TabAllocator.prototype = { | 52 TabAllocator.prototype = { |
| 51 /** | 53 /** |
| 52 * Returns a promise that will resolve into a tab once a tab can be allocated. | 54 * Returns a promise that will resolve into a tab once a tab can be allocated. |
| 53 * The tab cannot be used by other tasks until releaseTab() is called. | 55 * The tab cannot be used by other tasks until releaseTab() is called. |
| 54 * | 56 * |
| 55 * @result {Promise} | 57 * @return {Promise} |
|
saroyanm
2015/05/04 18:13:43
Nit: @return ?
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| 56 */ | 58 */ |
| 57 getTab: function() | 59 getTab: function() |
| 58 { | 60 { |
| 59 if (this._tabs.length) | 61 if (this._tabs.length) |
| 60 return this._tabs.shift(); | 62 return this._tabs.shift(); |
| 61 else | 63 else |
| 62 { | 64 return new Promise((resolve, reject) => this._queue.push(resolve)); |
| 63 let deferred = Promise.defer(); | |
|
saroyanm
2015/05/04 18:13:43
The Deffered object is obsolete starting from Geck
Wladimir Palant
2015/05/07 00:04:59
Promise constructor in Promise.jsm is actually sup
| |
| 64 this._deferred.push(deferred); | |
| 65 return deferred.promise; | |
| 66 } | |
| 67 }, | 65 }, |
| 68 | 66 |
| 69 /** | 67 /** |
| 70 * Adds a tab back to the pool so that it can be used by other tasks. | 68 * Adds a tab back to the pool so that it can be used by other tasks. |
| 71 * | 69 * |
| 72 * @param {tab} tab | 70 * @param {tab} tab |
| 73 */ | 71 */ |
| 74 releaseTab: function(tab) | 72 releaseTab: function(tab) |
| 75 { | 73 { |
| 76 let browser = tab.parentNode.tabbrowser; | 74 let browser = tab.parentNode.tabbrowser; |
| 77 browser.removeTab(tab); | 75 browser.removeTab(tab); |
| 78 tab = browser.addTab("about:blank"); | 76 tab = browser.addTab("about:blank"); |
| 79 | 77 |
| 80 if (this._deferred.length) | 78 if (this._queue.length) |
| 81 this._deferred.shift().resolve(tab); | 79 this._queue.shift()(tab); |
|
saroyanm
2015/05/04 18:13:43
As mentioned above, the Deffered object is obsolet
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| 82 else | 80 else |
| 83 this._tabs.push(tab); | 81 this._tabs.push(tab); |
| 84 } | 82 } |
| 85 }; | 83 }; |
| 86 | 84 |
| 87 /** | 85 /** |
| 88 * Observes page loads in a particular tabbed browser. | 86 * Observes page loads in a particular tabbed browser. |
| 89 * | 87 * |
| 90 * @param {tabbrowser} browser | 88 * @param {tabbrowser} browser |
| 91 * The tabbed browser to be observed | 89 * The tabbed browser to be observed |
| 92 * @param {int} timeout | 90 * @param {int} timeout |
| 93 * Load timeout in milliseconds | 91 * Load timeout in milliseconds |
| 94 * @constructor | 92 * @constructor |
| 95 */ | 93 */ |
| 96 function LoadListener(browser, timeout) | 94 function LoadListener(browser, timeout) |
| 97 { | 95 { |
| 98 this._browser = browser; | 96 this._browser = browser; |
| 99 this._deferred = new Map(); | 97 this._queue = new Map(); |
| 100 this._timeout = timeout; | 98 this._timeout = timeout; |
| 101 browser.addTabsProgressListener(this); | 99 browser.addTabsProgressListener(this); |
| 102 } | 100 } |
| 103 LoadListener.prototype = { | 101 LoadListener.prototype = { |
| 104 /** | 102 /** |
| 105 * Returns a promise that will be resolved when the page in the specified tab | 103 * Returns a promise that will be resolved when the page in the specified tab |
| 106 * finishes loading. Loading will be stopped if the timeout is reached. | 104 * finishes loading. Loading will be stopped if the timeout is reached. |
| 107 * | 105 * |
| 108 * @param {tab} tab | 106 * @param {tab} tab |
| 109 * @result {Promise} | 107 * @return {Promise} |
|
saroyanm
2015/05/04 18:13:43
Nit: @return
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| 110 */ | 108 */ |
| 111 waitForLoad: function(tab) | 109 waitForLoad: function(tab) |
| 112 { | 110 { |
| 113 let deferred = Promise.defer(); | 111 return new Promise((resolve, reject) => |
|
saroyanm
2015/05/04 18:13:43
As mentioned above this is Obsolete, this comment
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| 114 this._deferred.set(tab.linkedBrowser, deferred); | 112 { |
| 115 | 113 this._queue.set(tab.linkedBrowser, resolve); |
| 116 tab.ownerDocument.defaultView.setTimeout(function() | 114 |
| 117 { | 115 tab.ownerDocument.defaultView.setTimeout(function() |
| 118 tab.linkedBrowser.stop(); | 116 { |
| 119 }, this._timeout); | 117 tab.linkedBrowser.stop(); |
| 120 | 118 }, this._timeout); |
| 121 return deferred.promise; | 119 }); |
| 122 }, | 120 }, |
| 123 | 121 |
| 124 /** | 122 /** |
| 125 * Deactivates this object. | 123 * Deactivates this object. |
| 126 */ | 124 */ |
| 127 stop: function() | 125 stop: function() |
| 128 { | 126 { |
| 129 this._browser.removeTabsProgressListener(this); | 127 this._browser.removeTabsProgressListener(this); |
| 130 }, | 128 }, |
| 131 | 129 |
| 132 onStateChange: function(browser, progress, request, flags, status) | 130 onStateChange: function(browser, progress, request, flags, status) |
| 133 { | 131 { |
| 134 if ((flags & Ci.nsIWebProgressListener.STATE_STOP) && (flags & Ci.nsIWebProg ressListener.STATE_IS_WINDOW)) | 132 if ((flags & Ci.nsIWebProgressListener.STATE_STOP) && |
|
saroyanm
2015/05/04 18:13:43
Nit: This case can be splitted into multiple lines
|
saroyanm
2015/05/07 13:19:00
Nit: We usually also move operators to new line, f
|
| 135 { | 133 (flags & Ci.nsIWebProgressListener.STATE_IS_WINDOW)) |
| 136 let deferred = this._deferred.get(browser); | 134 { |
| 137 if (deferred) | 135 let resolve = this._queue.get(browser); |
| 136 if (resolve) | |
| 138 { | 137 { |
| 139 this._deferred.delete(browser); | 138 this._queue.delete(browser); |
| 140 | 139 |
| 141 let headers = []; | 140 let headers = []; |
| 142 if (request instanceof Ci.nsIHttpChannel) | 141 if (request instanceof Ci.nsIHttpChannel) |
| 143 { | 142 { |
| 144 try | 143 try |
| 145 { | 144 { |
| 146 headers.push("HTTP/x.x " + request.responseStatus + " " + request.re sponseStatusText); | 145 headers.push("HTTP/x.x " + request.responseStatus + " " + request.re sponseStatusText); |
| 147 request.visitResponseHeaders((header, value) => headers.push(header + ": " + value)); | 146 request.visitResponseHeaders((header, value) => headers.push(header + ": " + value)); |
| 148 } | 147 } |
| 149 catch (e) | 148 catch (e) |
| 150 { | 149 { |
| 151 // Exceptions are expected here | 150 // Exceptions are expected here |
|
saroyanm
2015/05/04 18:13:43
Please also handle the exception.
reportException
Wladimir Palant
2015/05/07 00:04:59
As the comment explains, exceptions are expected h
| |
| 152 } | 151 } |
| 153 } | 152 } |
| 154 deferred.resolve([status, headers]); | 153 resolve([status, headers]); |
| 155 } | 154 } |
| 156 } | 155 } |
| 157 } | 156 } |
| 158 }; | 157 }; |
| 159 | 158 |
| 160 /** | 159 /** |
| 161 * Once created, this object will make sure all new windows are dismissed | 160 * Once created, this object will make sure all new windows are dismissed |
| 162 * immediately. | 161 * immediately. |
| 163 * | 162 * |
| 164 * @constructor | 163 * @constructor |
| 165 */ | 164 */ |
| 166 function WindowCloser() | 165 function WindowCloser() |
| 167 { | 166 { |
| 168 Services.obs.addObserver(this, "xul-window-registered", true) | 167 Services.obs.addObserver(this, "xul-window-registered", true); |
|
saroyanm
2015/05/04 18:13:43
Missing semicolon
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| 169 } | 168 } |
| 170 WindowCloser.prototype = { | 169 WindowCloser.prototype = { |
| 171 /** | 170 /** |
| 172 * Deactivates this object. | 171 * Deactivates this object. |
| 173 */ | 172 */ |
| 174 stop: function() | 173 stop: function() |
| 175 { | 174 { |
| 176 Services.obs.removeObserver(this, "xul-window-registered") | 175 Services.obs.removeObserver(this, "xul-window-registered"); |
|
saroyanm
2015/05/04 18:13:43
Missing semicolon
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| 177 }, | 176 }, |
| 178 | 177 |
| 179 observe: function(subject, topic, data) | 178 observe: function(subject, topic, data) |
| 180 { | 179 { |
| 181 let window = subject.QueryInterface(Ci.nsIInterfaceRequestor) | 180 let window = subject.QueryInterface(Ci.nsIInterfaceRequestor) |
| 182 .getInterface(Ci.nsIDOMWindow) | 181 .getInterface(Ci.nsIDOMWindow); |
|
saroyanm
2015/05/04 18:13:43
Missing semicolon
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| 183 window.addEventListener("load", function() | 182 window.addEventListener("load", function() |
| 184 { | 183 { |
| 185 if (window.document.documentElement.localName == 'dialog') | 184 if (window.document.documentElement.localName == "dialog") |
|
saroyanm
2015/05/04 18:13:43
Nit: Please use double quote.
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| 186 window.document.documentElement.acceptDialog(); | 185 window.document.documentElement.acceptDialog(); |
| 187 else | 186 else |
| 188 window.close(); | 187 window.close(); |
| 189 }, false); | 188 }, false); |
| 190 }, | 189 }, |
| 191 | 190 |
| 192 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakRefer ence]) | 191 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakRefer ence]) |
| 193 }; | 192 }; |
| 194 | 193 |
| 195 /** | 194 /** |
| 196 * Retrieves crawler results associated with a particular content window. | 195 * Retrieves crawler results associated with a particular content window. |
| 197 * | 196 * |
| 198 * @param {Window} window | 197 * @param {Window} window |
| 199 * Content window to retrieve crawler results for | 198 * Content window to retrieve crawler results for |
| 200 * @result {Object} | 199 * @return {Object} |
|
saroyanm
2015/05/04 18:13:43
Nit: @return
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| 201 * Crawler results or undefined if the window wasn't created by the crawler. | 200 * Crawler results or undefined if the window wasn't created by the crawler. |
| 202 */ | 201 */ |
| 203 function getDataForWindow(window) | 202 function getDataForWindow(window) |
| 204 { | 203 { |
| 205 let topWindow = window.top; | 204 let topWindow = window.top; |
| 206 if (!topWindow.document) | 205 if (!topWindow.document) |
| 207 throw new Error("No document associated with the node's top window"); | 206 throw new Error("No document associated with the node's top window"); |
| 208 let tabbrowser = Utils.getChromeWindow(topWindow).getBrowser(); | 207 let tabbrowser = Utils.getChromeWindow(topWindow).getBrowser(); |
| 209 if (!tabbrowser) | 208 if (!tabbrowser) |
| 210 throw new Error("Unable to get a tabbrowser reference from the window"); | 209 throw new Error("Unable to get a tabbrowser reference from the window"); |
| 211 let browser = tabbrowser.getBrowserForDocument(topWindow.document); | 210 let browser = tabbrowser.getBrowserForDocument(topWindow.document); |
| 212 if (!browser) | 211 if (!browser) |
| 213 throw new Error("Unable to get browser for the content window"); | 212 throw new Error("Unable to get browser for the content window"); |
| 214 let tab = tabbrowser.getTabForBrowser(browser); | 213 let tab = tabbrowser.getTabForBrowser(browser); |
| 215 if (!tab) | 214 if (!tab) |
| 216 throw new Error("Unable to get tab for the browser"); | 215 throw new Error("Unable to get tab for the browser"); |
| 217 return dataForTab.get(tab); | 216 return dataForTab.get(tab); |
| 218 }; | 217 } |
|
saroyanm
2015/05/04 18:13:43
Nit: Semicolon is redundant here.
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| 219 | 218 |
| 220 /** | 219 /** |
| 221 * Starts the crawling session. The crawler opens each URL in a tab and stores | 220 * Starts the crawling session. The crawler opens each URL in a tab and stores |
| 222 * the results. | 221 * the results. |
| 223 * | 222 * |
| 224 * @param {Window} window | 223 * @param {Window} window |
| 225 * The browser window we're operating in | 224 * The browser window we're operating in |
| 226 * @param {String[]} urls | 225 * @param {String[]} urls |
| 227 * URLs to be crawled | 226 * URLs to be crawled |
| 228 * @param {int} number_of_tabs | 227 * @param {int} number_of_tabs |
| 229 * Maximum number of tabs to be opened | 228 * Maximum number of tabs to be opened |
| 230 * @param {String} targetURL | 229 * @param {String} targetURL |
| 231 * URL that should receive the results | 230 * URL that should receive the results |
|
saroyanm
2015/05/04 18:13:43
Nit: Please also document onDone parameter for con
Sebastian Noack
2015/05/04 20:39:01
Also note that JsDoc 3 will mistakenly document th
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| 231 * @param {Function} onDone | |
| 232 * Callback to be executed once the processing finishes | |
| 233 * @static | |
| 232 */ | 234 */ |
| 233 function run(window, urls, timeout, maxtabs, targetURL, onDone) | 235 function run(window, urls, timeout, maxtabs, targetURL, onDone) |
| 234 { | 236 { |
| 235 let requestNotifier = new RequestNotifier(null, function() {}); | 237 let requestNotifier = new RequestNotifier(null, function() {}); |
| 236 | 238 |
| 237 let origProcessNode = Policy.processNode; | 239 let origProcessNode = Policy.processNode; |
| 238 Policy.processNode = processNodeReplacement.bind(null, origProcessNode, reques tNotifier); | 240 Policy.processNode = processNodeReplacement.bind(null, origProcessNode, reques tNotifier); |
| 239 | 241 |
| 240 let tabAllocator = new TabAllocator(window.getBrowser(), maxtabs); | 242 let tabAllocator = new TabAllocator(window.getBrowser(), maxtabs); |
| 241 let loadListener = new LoadListener(window.getBrowser(), timeout); | 243 let loadListener = new LoadListener(window.getBrowser(), timeout); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 281 } | 283 } |
| 282 } | 284 } |
| 283 exports.run = run; | 285 exports.run = run; |
| 284 | 286 |
| 285 /** | 287 /** |
| 286 * Crawls a URL. This is a generator meant to be used via a Task object. | 288 * Crawls a URL. This is a generator meant to be used via a Task object. |
| 287 * | 289 * |
| 288 * @param {String} url | 290 * @param {String} url |
| 289 * @param {TabAllocator} tabAllocator | 291 * @param {TabAllocator} tabAllocator |
| 290 * @param {loadListener} loadListener | 292 * @param {loadListener} loadListener |
| 291 * @result {Object} | 293 * @return {Object} |
|
saroyanm
2015/05/04 18:13:43
Nit: @return {Object} Crawling result
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| 292 * Crawling result | 294 * Crawling result |
| 293 */ | 295 */ |
| 294 function* crawl_url(url, tabAllocator, loadListener) | 296 function* crawl_url(url, tabAllocator, loadListener) |
|
Sebastian Noack
2015/05/07 12:33:04
Nit: camel case
| |
| 295 { | 297 { |
| 296 let tab = yield tabAllocator.getTab(); | 298 let tab = yield tabAllocator.getTab(); |
| 297 let result = {url: url}; | 299 let result = {url: url}; |
| 298 | 300 |
| 299 dataForTab.set(tab, result); | 301 dataForTab.set(tab, result); |
| 300 try | 302 try |
| 301 { | 303 { |
| 302 result.startTime = Date.now(); | 304 result.startTime = Date.now(); |
| 303 tab.linkedBrowser.loadURI(url, null, null); | 305 tab.linkedBrowser.loadURI(url, null, null); |
| 304 [result.channelStatus, result.headers] = yield loadListener.waitForLoad(tab) ; | 306 [result.channelStatus, result.headers] = yield loadListener.waitForLoad(tab) ; |
| 305 result.endTime = Date.now(); | 307 result.endTime = Date.now(); |
| 306 result.finalUrl = tab.linkedBrowser.currentURI.spec; | 308 result.finalUrl = tab.linkedBrowser.currentURI.spec; |
| 307 | 309 |
| 308 let document = tab.linkedBrowser.contentDocument; | 310 let document = tab.linkedBrowser.contentDocument; |
| 309 if (document.documentElement) | 311 if (document.documentElement) |
| 310 { | 312 { |
| 311 try | 313 try |
| 312 { | 314 { |
| 313 let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "c anvas"); | 315 let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "c anvas"); |
| 314 canvas.width = document.documentElement.scrollWidth; | 316 canvas.width = document.documentElement.scrollWidth; |
| 315 canvas.height = document.documentElement.scrollHeight; | 317 canvas.height = document.documentElement.scrollHeight; |
| 316 | 318 |
| 317 let context = canvas.getContext("2d"); | 319 let context = canvas.getContext("2d"); |
| 318 context.drawWindow(document.defaultView, 0, 0, canvas.width, canvas.heig ht, "rgb(255, 255, 255)"); | 320 context.drawWindow(document.defaultView, 0, 0, canvas.width, canvas.heig ht, "rgb(255, 255, 255)"); |
| 319 result.screenshot = canvas.toDataURL("image/jpeg", 0.8); | 321 result.screenshot = canvas.toDataURL("image/jpeg", 0.8); |
|
saroyanm
2015/05/04 18:13:43
Maybe make sense to let user specify the quality o
Wladimir Palant
2015/05/07 00:04:59
Well, changing maxtabs is very useful when testing
saroyanm
2015/05/07 13:19:00
Good point.
| |
| 320 } | 322 } |
| 321 catch (e) | 323 catch (e) |
| 322 { | 324 { |
| 323 reportException(e); | 325 reportException(e); |
| 324 result.error = "Capturing screenshot failed: " + e; | 326 result.error = "Capturing screenshot failed: " + e; |
|
saroyanm
2015/05/04 18:13:43
Isn't result.error redundant ?
Wladimir Palant
2015/05/07 00:04:59
No. The exception is merely reported to the consol
saroyanm
2015/05/07 13:19:00
Yes, missed that.
Good point.
| |
| 325 } | 327 } |
| 326 | 328 |
| 327 // TODO: Capture frames as well? | 329 // TODO: Capture frames as well? |
|
saroyanm
2015/05/04 18:13:43
Nit: I think we shouldn't have TODO comments in re
Wladimir Palant
2015/05/07 00:04:59
Why not? This is something we might want to do in
| |
| 328 let serializer = new tab.ownerDocument.defaultView.XMLSerializer(); | 330 let serializer = new tab.ownerDocument.defaultView.XMLSerializer(); |
| 329 result.source = serializer.serializeToString(document.documentElement); | 331 result.source = serializer.serializeToString(document.documentElement); |
| 330 } | 332 } |
| 331 } | 333 } |
| 332 finally | 334 finally |
| 333 { | 335 { |
| 334 tabAllocator.releaseTab(tab); | 336 tabAllocator.releaseTab(tab); |
| 335 } | 337 } |
| 336 return result; | 338 return result; |
| 337 } | |
| 338 | |
| 339 function reportException(e) | |
| 340 { | |
| 341 let stack = ""; | |
| 342 if (e && typeof e == "object" && "stack" in e) | |
| 343 stack = e.stack + "\n"; | |
| 344 | |
| 345 Cu.reportError(e); | |
| 346 dump(e + "\n" + stack + "\n"); | |
| 347 } | 339 } |
| 348 | 340 |
| 349 /** | 341 /** |
| 350 * Wrapper for the Policy.processNode() function in ABP. Calls the original | 342 * Wrapper for the Policy.processNode() function in ABP. Calls the original |
| 351 * function and records all the data. | 343 * function and records all the data. |
| 352 * | 344 * |
| 353 * @param {Function} origProcessNode | 345 * @param {Function} origProcessNode |
| 354 * The original processNode function. | 346 * The original processNode function. |
| 355 * @param {RequestNotifier} requestNotifier | 347 * @param {RequestNotifier} requestNotifier |
| 356 * The crawler's RequestNotifier object instance. | 348 * The crawler's RequestNotifier object instance. |
| 357 * @param {nsIDOMWindow} wnd | 349 * @param {nsIDOMWindow} wnd |
| 358 * @param {nsIDOMElement} node | 350 * @param {nsIDOMElement} node |
| 359 * @param {Number} contentType | 351 * @param {Number} contentType |
| 360 * @param {nsIURI} location | 352 * @param {nsIURI} location |
| 361 * @param {Boolean} collapse | 353 * @param {Boolean} collapse |
| 362 * @return {Boolean} | 354 * @return {Boolean} |
| 363 */ | 355 */ |
| 364 function processNodeReplacement(origProcessNode, requestNotifier, wnd, node, con tentType, location, collapse) | 356 function processNodeReplacement(origProcessNode, requestNotifier, wnd, node, con tentType, location, collapse) |
| 365 { | 357 { |
| 366 let filters = []; | 358 let filters = []; |
| 367 let origListener = requestNotifier.listener; | 359 let origListener = requestNotifier.listener; |
| 368 requestNotifier.listener = function(window, node, entry) | 360 requestNotifier.listener = function(window, node, entry) |
| 369 { | 361 { |
| 370 if (entry.filter) | 362 if (entry.filter) |
| 371 filters.push(entry.filter.text); | 363 filters.push(entry.filter.text); |
| 372 }; | 364 }; |
| 373 | 365 |
| 374 /* | 366 // Call the original processNode. If the original throws, then we will too, |
| 375 * Call the original processNode. If the original throws, then we will too, so this is outside a try clause. | 367 // so this is outside a try clause. |
|
saroyanm
2015/05/04 18:13:43
Nit: the line is too long.
Sebastian Noack
2015/05/04 20:39:01
Also I suggest to use simply // for comments expla
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| 376 */ | |
| 377 let result; | 368 let result; |
| 378 try | 369 try |
| 379 { | 370 { |
| 380 result = origProcessNode(wnd, node, contentType, location, collapse); | 371 result = origProcessNode(wnd, node, contentType, location, collapse); |
| 381 } | 372 } |
| 382 finally | 373 finally |
| 383 { | 374 { |
| 384 requestNotifier.listener = origListener; | 375 requestNotifier.listener = origListener; |
| 385 } | 376 } |
| 386 | 377 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 397 blocked: result != Ci.nsIContentPolicy.ACCEPT, | 388 blocked: result != Ci.nsIContentPolicy.ACCEPT, |
| 398 filters: filters | 389 filters: filters |
| 399 }); | 390 }); |
| 400 } | 391 } |
| 401 } | 392 } |
| 402 catch (e) | 393 catch (e) |
| 403 { | 394 { |
| 404 reportException(e); | 395 reportException(e); |
| 405 } | 396 } |
| 406 return result; | 397 return result; |
| 407 }; | 398 } |
|
saroyanm
2015/05/04 18:13:43
Nit: Semicolon is redundant here.
Wladimir Palant
2015/05/07 00:04:59
Done.
| |
| LEFT | RIGHT |