Bug 974406 - Bookmarking UI doesn't work correctly to HSTS pages. r=gavin, a=sledru
authorMarco Bonardo <mbonardo@mozilla.com>
Sat, 01 Mar 2014 14:37:23 +0100
changeset 175443 8fa484975bc23e4617de2dbb63720e7c5813dbff
parent 175442 bca05e4b9df9913562c0f757c734bd9781308588
child 175444 d50fcbb2ad06b545001ea2c6d14bc80d587fe0c9
push id3311
push userryanvm@gmail.com
push dateMon, 03 Mar 2014 15:59:09 +0000
treeherdermozilla-beta@8fa484975bc2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgavin, sledru
bugs974406
milestone28.0
Bug 974406 - Bookmarking UI doesn't work correctly to HSTS pages. r=gavin, a=sledru
browser/base/content/test/general/browser.ini
browser/base/content/test/general/browser_star_hsts.js
browser/base/content/test/general/browser_star_hsts.sjs
toolkit/components/places/PlacesUtils.jsm
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -10,16 +10,17 @@ support-files =
   blockPluginVulnerableNoUpdate.xml
   blockPluginVulnerableUpdatable.xml
   browser_bug479408_sample.html
   browser_bug678392-1.html
   browser_bug678392-2.html
   browser_clearplugindata.html
   browser_clearplugindata_noage.html
   browser_registerProtocolHandler_notification.html
+  browser_star_hsts.sjs
   browser_tab_dragdrop2_frame1.xul
   bug564387.html
   bug564387_video1.ogv
   bug564387_video1.ogv^headers^
   bug592338.html
   bug792517-2.html
   bug792517.html
   bug792517.sjs
@@ -299,16 +300,17 @@ skip-if = true # bug 432425
 skip-if = true  # disabled until the tree view is added
                 # back to the clear recent history dialog (sanitize.xul), if
                 # it ever is (bug 480169)
 [browser_save_link-perwindowpb.js]
 [browser_save_private_link_perwindowpb.js]
 [browser_save_video.js]
 [browser_scope.js]
 [browser_selectTabAtIndex.js]
+[browser_star_hsts.js]
 [browser_tabDrop.js]
 [browser_tabMatchesInAwesomebar_perwindowpb.js]
 [browser_tab_drag_drop_perwindow.js]
 [browser_tab_dragdrop.js]
 [browser_tab_dragdrop2.js]
 [browser_tab_dragdrop2_frame1.xul]
 [browser_tabfocus.js]
 [browser_tabopen_reflows.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_star_hsts.js
@@ -0,0 +1,114 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+let secureURL = "https://example.com/browser/browser/base/content/test/general/browser_star_hsts.sjs";
+let unsecureURL = "http://example.com/browser/browser/base/content/test/general/browser_star_hsts.sjs";
+
+add_task(function* test_star_redirect() {
+  registerCleanupFunction(function() {
+    // Ensure to remove example.com from the HSTS list.
+    let sss = Cc["@mozilla.org/ssservice;1"]
+                .getService(Ci.nsISiteSecurityService);
+    sss.removeState(Ci.nsISiteSecurityService.HEADER_HSTS,
+                    NetUtil.newURI("http://example.com/"), 0);
+    PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
+    gBrowser.removeCurrentTab();
+  });
+
+  let tab = gBrowser.selectedTab = gBrowser.addTab();
+  // This will add the page to the HSTS cache.
+  yield promiseTabLoadEvent(tab, secureURL, secureURL);
+  // This should transparently be redirected to the secure page.
+  yield promiseTabLoadEvent(tab, unsecureURL, secureURL);
+
+  yield promiseStarState(BookmarkingUI.STATUS_UNSTARRED);
+
+  let promiseBookmark = promiseOnItemAdded(gBrowser.currentURI);
+  BookmarkingUI.star.click();
+  // This resolves on the next tick, so the star should have already been
+  // updated at that point.
+  yield promiseBookmark;
+
+  is(BookmarkingUI.status, BookmarkingUI.STATUS_STARRED, "The star is starred");
+});
+
+/**
+ * Waits for the star to reflect the expected state.
+ */
+function promiseStarState(aValue) {
+  let deferred = Promise.defer();
+  let expectedStatus = aValue ? BookmarkingUI.STATUS_STARRED
+                              : BookmarkingUI.STATUS_UNSTARRED;
+  (function checkState() {
+    if (BookmarkingUI.status == BookmarkingUI.STATUS_UPDATING ||
+        BookmarkingUI.status != expectedStatus) {
+      info("Waiting for star button change.");
+      setTimeout(checkState, 1000);
+    } else {
+      deferred.resolve();
+    }
+  })();
+  return deferred.promise;
+}
+
+/**
+ * Starts a load in an existing tab and waits for it to finish (via some event).
+ *
+ * @param aTab
+ *        The tab to load into.
+ * @param aUrl
+ *        The url to load.
+ * @param [optional] aFinalURL
+ *        The url to wait for, same as aURL if not defined.
+ * @return {Promise} resolved when the event is handled.
+ */
+function promiseTabLoadEvent(aTab, aURL, aFinalURL)
+{
+  if (!aFinalURL)
+    aFinalURL = aURL;
+  let deferred = Promise.defer();
+  info("Wait for load tab event");
+  aTab.linkedBrowser.addEventListener("load", function load(event) {
+    if (event.originalTarget != aTab.linkedBrowser.contentDocument ||
+        event.target.location.href == "about:blank" ||
+        event.target.location.href != aFinalURL) {
+      info("skipping spurious load event");
+      return;
+    }
+    aTab.linkedBrowser.removeEventListener("load", load, true);
+    info("Tab load event received");
+    deferred.resolve();
+  }, true, true);
+  aTab.linkedBrowser.loadURI(aURL);
+  return deferred.promise;
+}
+
+/**
+ * Waits for a bookmark to be added for the given uri.
+ */
+function promiseOnItemAdded(aExpectedURI) {
+  let defer = Promise.defer();
+  let bookmarksObserver = {
+    onItemAdded: function (aItemId, aFolderId, aIndex, aItemType, aURI) {
+      info("Added a bookmark to " + aURI.spec);
+      PlacesUtils.bookmarks.removeObserver(bookmarksObserver);
+      if (aURI.equals(aExpectedURI))
+        defer.resolve();
+      else
+        defer.reject(new Error("Added an unexpected bookmark"));
+    },
+    onBeginUpdateBatch: function () {},
+    onEndUpdateBatch: function () {},
+    onItemRemoved: function () {},
+    onItemChanged: function () {},
+    onItemVisited: function () {},
+    onItemMoved: function () {},
+    QueryInterface: XPCOMUtils.generateQI([
+      Ci.nsINavBookmarkObserver,
+    ])
+  };
+  info("Waiting for a bookmark to be added");
+  PlacesUtils.bookmarks.addObserver(bookmarksObserver, false);
+  return defer.promise;
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_star_hsts.sjs
@@ -0,0 +1,13 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function handleRequest(request, response)
+{
+  let page = "<!DOCTYPE html><html><body><p>HSTS page</p></body></html>";
+  response.setStatusLine(request.httpVersion, "200", "OK");
+  response.setHeader("Strict-Transport-Security", "max-age=60");
+  response.setHeader("Content-Type", "text/html", false);
+  response.setHeader("Content-Length", page.length + "", false);
+  response.write(page);
+}
--- a/toolkit/components/places/PlacesUtils.jsm
+++ b/toolkit/components/places/PlacesUtils.jsm
@@ -1931,25 +1931,25 @@ TransactionItemCache.prototype = {
     this._parentId || -1,
   keyword: null,
   title: null,
   dateAdded: null,
   lastModified: null,
   postData: null,
   itemType: null,
   set uri(v)
-    this._uri = (v instanceof Ci.nsIURI ? NetUtil.newURI(v.spec) : null),
+    this._uri = (v instanceof Ci.nsIURI ? v.clone() : null),
   get uri()
     this._uri || null,
   set feedURI(v)
-    this._feedURI = (v instanceof Ci.nsIURI ? NetUtil.newURI(v.spec) : null),
+    this._feedURI = (v instanceof Ci.nsIURI ? v.clone() : null),
   get feedURI()
     this._feedURI || null,
   set siteURI(v)
-    this._siteURI = (v instanceof Ci.nsIURI ? NetUtil.newURI(v.spec) : null),
+    this._siteURI = (v instanceof Ci.nsIURI ? v.clone() : null),
   get siteURI()
     this._siteURI || null,
   set index(v)
     this._index = (parseInt(v) >= 0 ? v : null),
   // Index can be 0.
   get index()
     this._index != null ? this._index : PlacesUtils.bookmarks.DEFAULT_INDEX,
   set annotations(v)