Bug 1256652 - [webext] Add webNavigation form_submit transitions implementation and test case. r=krizsa
authorLuca Greco <lgreco@mozilla.com>
Fri, 15 Apr 2016 14:50:27 +0200
changeset 331661 fe58e0490f35027dc62a9d63a25e6a7f498df6ad
parent 331660 79a7dc93f547639405dd99c939978cbfbc2999fb
child 331662 962cb71c40b103c6d7ab96908ec223d82f179068
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskrizsa
bugs1256652
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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();
   }
 });