Index: lib/child/frameScript.js |
diff --git a/lib/child/frameScript.js b/lib/child/frameScript.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bc90eeb1bbd1380cff52cf6ffdd9ea0314661c12 |
--- /dev/null |
+++ b/lib/child/frameScript.js |
@@ -0,0 +1,132 @@ |
+/* |
+ * This Source Code is subject to the terms of the Mozilla Public License |
+ * version 2.0 (the "License"). You can obtain a copy of the License at |
+ * http://mozilla.org/MPL/2.0/. |
+ */ |
+"use strict"; |
Wladimir Palant
2016/09/14 16:11:47
Nit: How about an empty line before that?
sergei
2016/09/29 09:58:11
Done.
|
+ |
+const {classes: Cc, interfaces: Ci, utils: Cu, Cr: results} = Components; |
+ |
+/** |
+ * @param e exception |
+ */ |
+function reportException(e) |
+{ |
+ let stack = ""; |
+ if (e && typeof e == "object" && "stack" in e) |
+ stack = e.stack + "\n"; |
+ |
+ Cu.reportError(e); |
+ dump(e + "\n" + stack + "\n"); |
+} |
+ |
+let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); |
+let {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {}); |
+ |
+/** |
+ * Waits for finishing of the page loading, calls `gatherPageInfo` and sends |
+ * gahter information using "abpcrawler:pageInfoGathered" message. |
+ * https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIWebProgressListener |
Wladimir Palant
2016/09/14 16:11:48
Nit: How about:
* Progress listener capturing the
sergei
2016/09/29 09:58:12
I have changed the comment. In addition webProgres
|
+ */ |
+let webProgressListener = |
+{ |
+ onStateChange: function(webProgress, request, flags, status) |
+ { |
+ // use isTopLevel to filter beacon requests out |
Wladimir Palant
2016/09/14 16:11:46
This comment doesn't make sense - not just beacon
sergei
2016/09/29 09:58:12
Done. It seems it does indeed work, however I thin
|
+ if (webProgress.isTopLevel && |
+ (flags & Ci.nsIWebProgressListener.STATE_STOP) && |
+ (flags & Ci.nsIWebProgressListener.STATE_IS_WINDOW)) |
+ { |
+ if (request instanceof Ci.nsIHttpChannel) |
+ { |
+ let pageInfo = {headers: []}; |
Wladimir Palant
2016/09/14 16:11:48
What about `channelStatus: status`? We used to cap
sergei
2016/09/29 09:58:11
Restored.
|
+ try |
+ { |
+ pageInfo.headers.push("HTTP/x.x " + request.responseStatus + " " + request.responseStatusText); |
+ request.visitResponseHeaders((header, value) => pageInfo.headers.push(header + ": " + value)); |
+ } |
+ catch (e) |
+ { |
+ // Ignore if called before the response has been received (before |
+ // onStartRequest()). |
+ if (e.result == Cr.NS_ERROR_NOT_AVAILABLE) |
+ return; |
Wladimir Palant
2016/09/14 16:11:48
So what happens if a host name doesn't resolve? We
sergei
2016/09/29 09:58:13
If the hostname is not resolved we don't get here
Wladimir Palant
2016/09/29 11:44:57
I don't really see why the page isn't loaded when
sergei
2016/09/29 15:36:21
Sorry for confusion, I meant under the page the pa
sergei
2016/10/04 10:57:31
What about creation of a new tab in TabAllocator.r
Wladimir Palant
2016/10/04 11:10:38
No, I'd rather not make the code more complicated
sergei
2016/10/06 14:26:58
Of course it should be in a follow-up issue, the q
|
+ reportException(e); |
+ } |
+ Object.assign(pageInfo, gatherPageInfo(content)); |
+ sendAsyncMessage("abpcrawler:pageInfoGathered", pageInfo); |
Wladimir Palant
2016/09/14 16:11:47
The two lines above don't depend on the request ob
sergei
2016/09/29 09:58:12
Moved.
|
+ } |
+ } |
+ }, |
+ |
+ // definitions of the remaining functions see related documentation |
Wladimir Palant
2016/09/14 16:11:48
Nit: this comment doesn't add any value, remove?
sergei
2016/09/29 09:58:11
Done.
|
+ onLocationChange: function(webProgress, request, URI, flag) {}, |
+ onProgressChange: function(aWebProgress, aRequest, curSelf, maxSelf, curTot, maxTot) {}, |
Wladimir Palant
2016/09/14 16:11:47
So, Hungarian notation or not? Our style guide say
sergei
2016/09/29 09:58:12
Done.
|
+ onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) {}, |
+ onSecurityChange: function(aWebProgress, aRequest, aState) {}, |
+ |
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]) |
Wladimir Palant
2016/09/14 16:11:48
I don't think that progress listeners can be weak
sergei
2016/09/29 09:58:13
According to the documentation, "This object must
|
+}; |
+ |
+let filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"] |
+ .createInstance(Ci.nsIWebProgress); |
Wladimir Palant
2016/09/14 16:11:48
Nit: we usually align the dot with the [ on the pr
sergei
2016/09/29 09:58:12
Removed. BTW, in the example from mozilla they are
Wladimir Palant
2016/09/29 11:44:57
Yes, there is an example mentioning it - but no do
sergei
2016/09/29 15:36:21
Acknowledged.
|
+filter.addProgressListener(webProgressListener, Ci.nsIWebProgress.NOTIFY_ALL); |
+ |
+let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor) |
+ .getInterface(Ci.nsIWebProgress); |
+webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL); |
Wladimir Palant
2016/09/14 16:11:48
The reason why the original code is receiving all
sergei
2016/09/29 09:58:12
Done.
|
+ |
+/** |
+ * Gathers information about page using DOM window. |
Wladimir Palant
2016/09/14 16:11:47
Just "Gathers information about a DOM window." may
sergei
2016/09/29 09:58:13
Done.
|
+ * Currently |
+ * - creates a screenshot of the page |
+ * - serializes the page source code |
+ * @param {nsIDOMWindow} wnd window to process |
+ * @return {Object} the object containing "screenshot" and "source" properties. |
+ */ |
+function gatherPageInfo(wnd) |
+{ |
+ let document = wnd.document; |
+ let result = {errors:[]}; |
+ if (document.documentElement) |
+ { |
+ try |
+ { |
+ let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); |
+ // Firefox does not work with large canvas elements. |
+ // http://stackoverflow.com/questions/6081483/maximum-size-of-a-canvas-element |
Wladimir Palant
2016/09/14 16:11:48
Great, you could have linked to http://stackoverfl
sergei
2016/09/29 09:58:11
Removed from here.
|
+ canvas.width = document.documentElement.scrollWidth; |
+ canvas.height = document.documentElement.scrollHeight; |
+ if (canvas.width > 0 && canvas.height > 0) |
+ { |
+ if (canvas.width > 32767) |
+ { |
+ result.errors.push("Width exceeds supported limit, " + canvas.width); |
+ canvas.width = 32767; |
+ } |
+ if (canvas.height > 32767) |
+ { |
+ result.errors.push("Height exceeds supported limit, " + canvas.height); |
+ canvas.height = 32767; |
+ } |
+ if (canvas.width * canvas.height > 472907776) |
+ { |
+ result.errrors.push("Area exceeds supported limit, " + canvas.height + " * " + canvas.width); |
+ canvas.height = 472907776 / canvas.width; |
+ } |
+ let context = canvas.getContext("2d"); |
+ context.drawWindow(wnd, 0, 0, canvas.width, canvas.height, "rgb(255, 255, 255)"); |
+ result.screenshot = canvas.toDataURL("image/jpeg", 0.8); |
+ } |
+ // TODO: Capture frames as well? |
+ let serializer = new wnd.XMLSerializer(); |
+ result.source = serializer.serializeToString(document.documentElement); |
+ } |
+ catch (e) |
+ { |
+ reportException(e); |
+ result.errors.push("Cannot gather page info"); |
Wladimir Palant
2016/09/14 16:11:47
The original code had the canvas in a separate try
sergei
2016/09/29 09:58:13
Done.
|
+ } |
+ } |
+ return result; |
+} |