Bug 756645 - Implement IndexedDB apps isolation. r=bent
☠☠ backed out by 29ca472bf2d2 ☠ ☠
authorMounir Lamouri <mounir.lamouri@gmail.com>
Thu, 23 Aug 2012 11:45:01 -0700
changeset 103235 4bb90f8c690974bc60f9df01a36f275729248c24
parent 103234 53f3963dedc01f50f36a94c39f9110622f1f2040
child 103236 3c39442f9f19c5c3e5db6453242dc38ca39fd4e7
push id13890
push userryanvm@gmail.com
push dateThu, 23 Aug 2012 23:50:55 +0000
treeherdermozilla-inbound@e137f28dfe70 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs756645
milestone17.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 756645 - Implement IndexedDB apps isolation. r=bent
dom/indexedDB/IDBFactory.cpp
dom/indexedDB/IndexedDatabaseManager.cpp
dom/indexedDB/test/Makefile.in
dom/indexedDB/test/file_app_isolation.html
dom/indexedDB/test/file_app_isolation.js
dom/indexedDB/test/test_app_isolation_inproc.html
dom/indexedDB/test/test_app_isolation_oop.html
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -203,21 +203,16 @@ IDBFactory::Create(ContentParent* aConte
       NS_ASSERTION(!lastCx, "We should only be called from C++!");
     }
     else {
       NS_ERROR("nsIThreadJSContextStack::Peek should never fail!");
     }
   }
 #endif
 
-  nsCString origin;
-  nsresult rv =
-    IndexedDatabaseManager::GetASCIIOriginFromWindow(nullptr, origin);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   nsCOMPtr<nsIPrincipal> principal =
     do_CreateInstance("@mozilla.org/nullprincipal;1");
   NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
 
   JSContext* cx = nsContentUtils::GetSafeJSContext();
   NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
 
   nsCxPusher pusher;
@@ -227,17 +222,17 @@ IDBFactory::Create(ContentParent* aConte
   }
 
   JSAutoRequest ar(cx);
 
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
   NS_ASSERTION(xpc, "This should never be null!");
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> globalHolder;
-  rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(globalHolder));
+  nsresult rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(globalHolder));
   NS_ENSURE_SUCCESS(rv, rv);
 
   JSObject* global;
   rv = globalHolder->GetJSObject(&global);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // The CreateSandbox call returns a proxy to the actual sandbox object. We
   // don't need a proxy here.
@@ -630,9 +625,9 @@ IDBFactory::Cmp(const jsval& aFirst,
   }
 
   if (first.IsUnset() || second.IsUnset()) {
     return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
   }
 
   *_retval = Key::CompareKeys(first, second);
   return NS_OK;
-}
\ No newline at end of file
+}
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -1013,17 +1013,17 @@ IndexedDatabaseManager::GetASCIIOriginFr
 
   nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal();
   NS_ENSURE_TRUE(principal, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   if (nsContentUtils::IsSystemPrincipal(principal)) {
     aASCIIOrigin.AssignLiteral("chrome");
   }
   else {
-    nsresult rv = nsContentUtils::GetASCIIOrigin(principal, aASCIIOrigin);
+    nsresult rv = principal->GetExtendedOrigin(aASCIIOrigin);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
     if (aASCIIOrigin.EqualsLiteral("null")) {
       NS_WARNING("IndexedDB databases not allowed for this principal!");
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
   }
 
--- a/dom/indexedDB/test/Makefile.in
+++ b/dom/indexedDB/test/Makefile.in
@@ -96,16 +96,20 @@ MOCHITEST_FILES = \
   test_transaction_ordering.html \
   test_setVersion.html \
   test_setVersion_abort.html \
   test_setVersion_events.html \
   test_setVersion_exclusion.html \
   test_unique_index_update.html \
   third_party_iframe1.html \
   third_party_iframe2.html \
+  test_app_isolation_inproc.html \
+  test_app_isolation_oop.html \
+  file_app_isolation.html \
+  file_app_isolation.js \
   $(NULL)
 
 #   test_writer_starvation.html  disabled for infinite loops, bug 595368
 
 ifeq (browser,$(MOZ_BUILD_APP))
 MOCHITEST_BROWSER_FILES = \
   browser_forgetThisSite.js \
   browser_forgetThisSiteAdd.html \
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/file_app_isolation.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    foobar!
+  </body>
+  <script>
+    var data = [
+      { id: "0", name: "foo" },
+    ];
+
+    var action = window.location.search.substring(1);
+    var finished = false;
+    var created = false; // We use that for 'read-no' action.
+
+    function finish(value) {
+      value ? alert('success') : alert('failure');
+      finished = true;
+    }
+
+    var request = window.indexedDB.open('AppIsolationTest');
+
+    request.onupgradeneeded = function(event) {
+      if (finished) {
+        finish(false);
+        return;
+      }
+
+      switch (action) {
+        case 'read-no':
+          created = true;
+          break;
+        case 'read-yes':
+          finish(false);
+          break;
+        case 'write':
+          created = true;
+
+          var db = event.target.result;
+
+          var objectStore = db.createObjectStore("test", { keyPath: "id" });
+          for (var i in data) {
+            objectStore.add(data[i]);
+          }
+          break;
+      }
+    }
+
+    request.onsuccess = function(event) {
+      if (finished) {
+        finish(false);
+        return;
+      }
+
+      var db = event.target.result;
+
+      // Think about close the db!
+      switch (action) {
+        case 'read-no':
+          db.close();
+
+          if (created) { // That means we have created it.
+            indexedDB.deleteDatabase('AppIsolationTest').onsuccess = function() {
+              finish(true);
+            };
+          } else {
+            finish(false);
+          }
+          break;
+        case 'read-yes':
+          db.transaction("test").objectStore("test").get("0").onsuccess = function(event) {
+            var name = event.target.result.name;
+            db.close();
+
+            indexedDB.deleteDatabase('AppIsolationTest').onsuccess = function() {
+              finish(name == 'foo');
+            };
+          };
+          break;
+        case 'write':
+          db.close();
+
+          // Success only if the db was actually created.
+          finish(created);
+          break;
+      }
+    };
+  </script>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/file_app_isolation.js
@@ -0,0 +1,169 @@
+SimpleTest.waitForExplicitFinish();
+
+var fileTestOnCurrentOrigin = (location.protocol + '//' + location.host + location.pathname)
+                              .replace('test_', 'file_')
+                              .replace('_inproc', '').replace('_oop', '');
+
+var previousPrefs = {
+  mozBrowserFramesEnabled: undefined,
+  mozBrowserFramesWhitelist: undefined,
+  oop_by_default: undefined,
+};
+
+try {
+  previousPrefs.mozBrowserFramesEnabled = SpecialPowers.getBoolPref('dom.mozBrowserFramesEnabled');
+} catch(e)
+{
+}
+
+try {
+  previousPrefs.mozBrowserFramesWhitelist = SpecialPowers.getCharPref('dom.mozBrowserFramesWhitelist');
+} catch(e) {
+}
+
+try {
+  previousPrefs.oop_by_default = SpecialPowers.getBoolPref('dom.ipc.browser_frames.oop_by_default');
+} catch(e) {
+}
+
+SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', true);
+SpecialPowers.setCharPref('dom.mozBrowserFramesWhitelist', location.protocol + "//" + location.host);
+SpecialPowers.setBoolPref("dom.ipc.browser_frames.oop_by_default", location.pathname.indexOf('_inproc') == -1);
+
+var gData = [
+  // APP 1
+  {
+    app: 'http://example.org/manifest.webapp',
+    action: 'read-no',
+    src: fileTestOnCurrentOrigin,
+  },
+  {
+    app: 'http://example.org/manifest.webapp',
+    action: 'write',
+    src: fileTestOnCurrentOrigin,
+  },
+  {
+    app: 'http://example.org/manifest.webapp',
+    action: 'read-yes',
+    src: fileTestOnCurrentOrigin,
+  },
+  // APP 2
+  {
+    app: 'https://example.com/manifest.webapp',
+    action: 'read-no',
+    src: fileTestOnCurrentOrigin,
+  },
+  {
+    app: 'https://example.com/manifest.webapp',
+    action: 'write',
+    src: fileTestOnCurrentOrigin,
+  },
+  {
+    app: 'https://example.com/manifest.webapp',
+    action: 'read-yes',
+    src: fileTestOnCurrentOrigin,
+  },
+  // Browser
+  {
+    browser: true,
+    action: 'read-no',
+    src: fileTestOnCurrentOrigin,
+  },
+  {
+    browser: true,
+    action: 'write',
+    src: fileTestOnCurrentOrigin,
+  },
+  {
+    browser: true,
+    action: 'read-yes',
+    src: fileTestOnCurrentOrigin,
+  },
+];
+
+function runTest() {
+  for (var i in gData) {
+    var iframe = document.createElement('iframe');
+    var data = gData[i];
+
+    if (data.app) {
+      iframe.setAttribute('mozbrowser', '');
+      iframe.setAttribute('mozapp', data.app);
+    } else if (data.browser) {
+      iframe.setAttribute('mozbrowser', '');
+    }
+
+    if (data.app || data.browser) {
+      iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
+        is(e.detail.message, 'success', 'test number ' + i);
+
+//        document.getElementById('content').removeChild(iframe);
+
+        i++;
+        if (i >= gData.length) {
+          if (previousPrefs.mozBrowserFramesEnabled !== undefined) {
+            SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', previousPrefs.mozBrowserFramesEnabled);
+          }
+          if (previousPrefs.mozBrowserFramesWhitelist !== undefined) {
+            SpecialPowers.setCharPref('dom.mozBrowserFramesWhitelist', previousPrefs.mozBrowserFramesWhitelist);
+          }
+          if (previousPrefs.oop_by_default !== undefined) {
+            SpecialPowers.setBoolPref("dom.ipc.browser_frames.oop_by_default", previousPrefs.oop_by_default);
+          }
+
+          indexedDB.deleteDatabase('AppIsolationTest').onsuccess = function() {
+            SimpleTest.finish();
+          };
+        } else {
+          gTestRunner.next();
+        }
+      });
+    }
+
+    iframe.src = data.src + '?' + data.action;
+
+    document.getElementById('content').appendChild(iframe);
+
+    yield;
+  }
+}
+
+var gTestRunner = runTest();
+
+function startTest() {
+  var request = window.indexedDB.open('AppIsolationTest');
+  var created = false;
+
+  request.onupgradeneeded = function(event) {
+    created = true;
+    var db = event.target.result;
+    var data = [
+      { id: "0", name: "foo" },
+    ];
+    var objectStore = db.createObjectStore("test", { keyPath: "id" });
+    for (var i in data) {
+      objectStore.add(data[i]);
+    }
+  }
+
+  request.onsuccess = function(event) {
+    var db = event.target.result;
+    is(created, true, "we should have created the db");
+
+    db.transaction("test").objectStore("test").get("0").onsuccess = function(event) {
+      is(event.target.result.name, 'foo', 'data have been written');
+      db.close();
+
+      gTestRunner.next();
+    };
+  }
+}
+
+// test_ipc.html executes all the tests in this directory in content process.
+// It will fail on this one for the moment.
+if (!SpecialPowers.isMainProcess()) {
+  todo(false, "We should make this work on content process");
+  SimpleTest.finish();
+} else {
+  startTest();
+}
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_app_isolation_inproc.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=756645
+-->
+<head>
+  <title>Test for IndexedDB app isolation (unique process)</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=756645">Mozilla Bug 756645</a>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7" src="file_app_isolation.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_app_isolation_oop.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=756645
+-->
+<head>
+  <title>Test for IndexedDB app isolation (unique process)</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=756645">Mozilla Bug 756645</a>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7" src="file_app_isolation.js">
+</script>
+</pre>
+</body>
+</html>