Bug 1256652 - [webext] Add webNavigation form_submit transitions implementation and test case. r=krizsa draft
authorLuca Greco <lgreco@mozilla.com>
Fri, 15 Apr 2016 14:50:27 +0200
changeset 352271 e502766b3b95fcd8ff8a43e4a6a5655fb42eeada
parent 352270 30b6f4444580b6ca9b09811c1696f6c01f43b0f9
child 352272 396762bc3949b7b22c3e1722d6840413221c1550
push id15670
push userluca.greco@alcacoop.it
push dateSat, 16 Apr 2016 12:49:27 +0000
reviewerskrizsa
bugs1256652
milestone48.0a1
Bug 1256652 - [webext] Add webNavigation form_submit transitions implementation and test case. r=krizsa MozReview-Commit-ID: GiMnQpCpHHm
toolkit/components/extensions/test/mochitest/file_WebNavigation_page1.html
toolkit/components/extensions/test/mochitest/test_ext_webnavigation.html
toolkit/modules/addons/WebNavigationContent.js
--- a/toolkit/components/extensions/test/mochitest/file_WebNavigation_page1.html
+++ b/toolkit/components/extensions/test/mochitest/file_WebNavigation_page1.html
@@ -1,9 +1,12 @@
 <!DOCTYPE HTML>
 
 <html>
 <body>
 
 <iframe src="file_WebNavigation_page2.html" width="200" height="200"></iframe>
 
+<form>
+</form>
+
 </body>
 </html>
--- a/toolkit/components/extensions/test/mochitest/test_ext_webnavigation.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_webnavigation.html
@@ -163,16 +163,33 @@ add_task(function* webnav_transitions_pr
 
   if (found) {
     is(found.details.transitionType, "auto_subframe",
        "Got the expected 'auto_subframe' transitionType in the OnCommitted event");
     ok(Array.isArray(found.details.transitionQualifiers),
        "transitionQualifiers found in the OnCommitted events");
   }
 
+  // transitionType: form_submit
+  received = [];
+  yield loadAndWait(win, "onCompleted", URL, () => {
+    win.document.querySelector("form").submit();
+  });
+
+  found = received.find((data) => (data.event == "onCommitted" && data.url == URL));
+
+  ok(found, "Got the onCommitted event");
+
+  if (found) {
+    is(found.details.transitionType, "form_submit",
+       "Got the expected 'form_submit' transitionType in the OnCommitted event");
+    ok(Array.isArray(found.details.transitionQualifiers),
+       "transitionQualifiers found in the OnCommitted events");
+  }
+
   // transitionQualifier: server_redirect
   received = [];
   yield loadAndWait(win, "onCompleted", REDIRECTED, () => { win.location = REDIRECT; });
 
   found = received.find((data) => (data.event == "onCommitted" && data.url == REDIRECTED));
 
   ok(found, "Got the onCommitted event");
 
--- a/toolkit/modules/addons/WebNavigationContent.js
+++ b/toolkit/modules/addons/WebNavigationContent.js
@@ -18,16 +18,45 @@ function loadListener(event) {
   sendAsyncMessage("Extension:DOMContentLoaded", {windowId, parentWindowId, url});
 }
 
 addEventListener("DOMContentLoaded", loadListener);
 addMessageListener("Extension:DisableWebNavigation", () => {
   removeEventListener("DOMContentLoaded", loadListener);
 });
 
+var FormSubmitListener = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
+                                          Ci.nsIFormSubmitObserver,
+                                          Ci.nsISupportsWeakReference]),
+  init() {
+    this.formSubmitWindows = new WeakSet();
+    Services.obs.addObserver(FormSubmitListener, "earlyformsubmit", false);
+  },
+
+  uninit() {
+    Services.obs.removeObserver(FormSubmitListener, "earlyformsubmit", false);
+    this.formSubmitWindows = new WeakSet();
+  },
+
+  notify: function(form, window, actionURI) {
+    try {
+      this.formSubmitWindows.add(window);
+    } catch (e) {
+      Cu.reportError("Error in FormSubmitListener.notify");
+    }
+  },
+
+  hasAndForget: function(window) {
+    let has = this.formSubmitWindows.has(window);
+    this.formSubmitWindows.delete(window);
+    return has;
+  },
+};
+
 var WebProgressListener = {
   init: function() {
     // This WeakMap (DOMWindow -> nsIURI) keeps track of the pathname and hash
     // of the previous location for all the existent docShells.
     this.previousURIMap = new WeakMap();
 
     // Populate the above previousURIMap by iterating over the docShells tree.
     for (let currentDocShell of WebNavigationFrames.iterateDocShellTree(docShell)) {
@@ -120,31 +149,31 @@ var WebProgressListener = {
       status,
       stateFlags,
     };
 
     sendAsyncMessage("Extension:StateChange", data);
   },
 
   sendDocumentChange({webProgress, locationURI, request}) {
-    let {loadType} = webProgress;
-    let frameTransitionData = this.getFrameTransitionData({loadType, request});
+    let {loadType, DOMWindow} = webProgress;
+    let frameTransitionData = this.getFrameTransitionData({loadType, request, DOMWindow});
 
     let data = {
       frameTransitionData,
       location: locationURI ? locationURI.spec : "",
       windowId: webProgress.DOMWindowID,
       parentWindowId: WebNavigationFrames.getParentWindowId(webProgress.DOMWindow),
     };
 
     sendAsyncMessage("Extension:DocumentChange", data);
   },
 
   sendHistoryChange({webProgress, previousURI, locationURI, request}) {
-    let {loadType} = webProgress;
+    let {loadType, DOMWindow} = webProgress;
 
     let isHistoryStateUpdated = false;
     let isReferenceFragmentUpdated = false;
 
     let pathChanged = !(previousURI && locationURI.equalsExceptRef(previousURI));
     let hashChanged = !(previousURI && previousURI.ref == locationURI.ref);
 
     // When the location changes but the document is the same:
@@ -158,60 +187,67 @@ var WebProgressListener = {
       isReferenceFragmentUpdated = true;
     } else if (loadType & Ci.nsIDocShell.LOAD_CMD_PUSHSTATE) {
       isHistoryStateUpdated = true;
     } else if (loadType & Ci.nsIDocShell.LOAD_CMD_HISTORY) {
       isHistoryStateUpdated = true;
     }
 
     if (isHistoryStateUpdated || isReferenceFragmentUpdated) {
-      let frameTransitionData = this.getFrameTransitionData({loadType, request});
+      let frameTransitionData = this.getFrameTransitionData({loadType, request, DOMWindow});
 
       let data = {
         frameTransitionData,
         isHistoryStateUpdated, isReferenceFragmentUpdated,
         location: locationURI ? locationURI.spec : "",
         windowId: webProgress.DOMWindowID,
         parentWindowId: WebNavigationFrames.getParentWindowId(webProgress.DOMWindow),
       };
 
       sendAsyncMessage("Extension:HistoryChange", data);
     }
   },
 
-  getFrameTransitionData({loadType, request}) {
+  getFrameTransitionData({loadType, request, DOMWindow}) {
     let frameTransitionData = {};
 
     if (loadType & Ci.nsIDocShell.LOAD_CMD_HISTORY) {
       frameTransitionData.forward_back = true;
     }
 
     if (loadType & Ci.nsIDocShell.LOAD_CMD_RELOAD) {
       frameTransitionData.reload = true;
     }
 
     if (request instanceof Ci.nsIChannel) {
       if (request.loadInfo.redirectChain.length) {
         frameTransitionData.server_redirect = true;
       }
     }
 
+    if (FormSubmitListener.hasAndForget(DOMWindow)) {
+      frameTransitionData.form_submit = true;
+    }
+
+
     return frameTransitionData;
   },
 
-
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]),
 };
 
 var disabled = false;
 WebProgressListener.init();
+FormSubmitListener.init();
 addEventListener("unload", () => {
   if (!disabled) {
     disabled = true;
     WebProgressListener.uninit();
+    FormSubmitListener.uninit();
   }
 });
 addMessageListener("Extension:DisableWebNavigation", () => {
   if (!disabled) {
     disabled = true;
     WebProgressListener.uninit();
+    FormSubmitListener.uninit();
   }
 });