Bug 830983 - Make 'webapps-clear-data' handler working for real when browserOnly is true. r=sicking
authorMounir Lamouri <mounir.lamouri@gmail.com>
Sat, 19 Jan 2013 00:15:55 +0000
changeset 119318 4886df89ef45d8684c518f0489bb50ba6b20b988
parent 119317 9120cc3988d85ef4706c51ad78558ac6a43d2ad2
child 119319 84edc4c471822fb0dd001f36cab6475f5a6bf435
push id21609
push usermlamouri@mozilla.com
push dateSat, 19 Jan 2013 00:16:14 +0000
treeherdermozilla-inbound@4886df89ef45 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs830983
milestone21.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 830983 - Make 'webapps-clear-data' handler working for real when browserOnly is true. r=sicking
extensions/cookie/nsPermissionManager.cpp
extensions/cookie/nsPermissionManager.h
extensions/cookie/test/Makefile.in
extensions/cookie/test/frame_clear_browser_data.html
extensions/cookie/test/test_app_cleardata_permissions.html
extensions/cookie/test/unit/test_permmanager_cleardata.js
extensions/cookie/test/unit/xpcshell.ini
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -1168,17 +1168,18 @@ NS_IMETHODIMP nsPermissionManager::Obser
 PLDHashOperator
 nsPermissionManager::GetPermissionsForApp(nsPermissionManager::PermissionHashKey* entry, void* arg)
 {
   GetPermissionsForAppStruct* data = static_cast<GetPermissionsForAppStruct*>(arg);
 
   for (uint32_t i = 0; i < entry->GetPermissions().Length(); ++i) {
     nsPermissionManager::PermissionEntry& permEntry = entry->GetPermissions()[i];
 
-    if (entry->GetKey()->mAppId != data->appId) {
+    if (entry->GetKey()->mAppId != data->appId ||
+        (data->browserOnly && !entry->GetKey()->mIsInBrowserElement)) {
       continue;
     }
 
     data->permissions.AppendObject(new nsPermission(entry->GetKey()->mHost,
                                                     entry->GetKey()->mAppId,
                                                     entry->GetKey()->mIsInBrowserElement,
                                                     gPermissionManager->mTypeArray.ElementAt(permEntry.mType),
                                                     permEntry.mPermission,
@@ -1214,17 +1215,17 @@ nsPermissionManager::RemovePermissionsFo
   nsCOMPtr<mozIStorageAsyncStatement> removeStmt;
   nsresult rv = mDBConn->CreateAsyncStatement(sql, getter_AddRefs(removeStmt));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<mozIStoragePendingStatement> pending;
   rv = removeStmt->ExecuteAsync(nullptr, getter_AddRefs(pending));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  GetPermissionsForAppStruct data(aAppId);
+  GetPermissionsForAppStruct data(aAppId, aBrowserOnly);
   mPermissionTable.EnumerateEntries(GetPermissionsForApp, &data);
 
   for (int32_t i=0; i<data.permissions.Count(); ++i) {
     nsAutoCString host;
     bool isInBrowserElement;
     nsAutoCString type;
 
     data.permissions[i]->GetHost(host);
--- a/extensions/cookie/nsPermissionManager.h
+++ b/extensions/cookie/nsPermissionManager.h
@@ -251,26 +251,30 @@ private:
                        int64_t aExpireTime,
                        uint32_t aAppId,
                        bool aIsInBrowserElement);
 
   nsresult RemoveExpiredPermissionsForApp(uint32_t aAppId);
 
   /**
    * This struct has to be passed as an argument to GetPermissionsForApp.
-   * |appId| has to be defined.
+   * |appId| and |browserOnly| have to be defined.
    * |permissions| will be filed with permissions that are related to the app.
+   * If |browserOnly| is true, only permissions related to a browserElement will
+   * be in |permissions|.
    */
   struct GetPermissionsForAppStruct {
     uint32_t                  appId;
+    bool                      browserOnly;
     nsCOMArray<nsIPermission> permissions;
 
     GetPermissionsForAppStruct() MOZ_DELETE;
-    GetPermissionsForAppStruct(uint32_t aAppId)
+    GetPermissionsForAppStruct(uint32_t aAppId, bool aBrowserOnly)
       : appId(aAppId)
+      , browserOnly(aBrowserOnly)
     {}
   };
 
   /**
    * This method will return the list of all permissions that are related to a
    * specific app.
    * @param arg has to be an instance of GetPermissionsForAppStruct.
    */
--- a/extensions/cookie/test/Makefile.in
+++ b/extensions/cookie/test/Makefile.in
@@ -49,20 +49,18 @@ MOCHITEST_FILES = \
   file_localhost_inner.html \
   test_same_base_domain_5.html \
   test_same_base_domain_6.html \
   file_loopback_inner.html \
   $(NULL)
 
 MOCHITEST_CHROME_FILES = \
   test_permissionmanager_app_isolation.html \
-  test_app_cleardata_permissions.html \
   test_app_uninstall_permissions.html \
   test_app_uninstall_cookies.html \
-  frame_clear_browser_data.html \
   channel_utils.js \
   $(NULL)
 
 MOCHITEST_BROWSER_FILES = \
   browser_test_favicon.js \
   $(NULL)
 
 XPCSHELL_TESTS = unit
deleted file mode 100644
--- a/extensions/cookie/test/frame_clear_browser_data.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <body>
-  </body>
-  <script>
-    addEventListener('message', function(e) {
-      if (e.data == 'clear') {
-        navigator.mozApps.getSelf().onsuccess = function() {
-          this.result.clearBrowserData();
-          document.body.innerHTML = "<done></done>";
-        };
-      }
-    });
-  </script>
-</html>
deleted file mode 100644
--- a/extensions/cookie/test/test_app_cleardata_permissions.html
+++ /dev/null
@@ -1,213 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <meta charset="utf-8">
-  <title>Tests that clearing mozbrowser private data removes the onlyInBrowser permissions</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
-</head>
-<body>
-<p id="display"></p>
-<div id="content">
-  <iframe src="http://example.com/tests/error404"></iframe>
-</div>
-<pre id="test">
-<script type="application/javascript;version=1.7">
-
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cu = Components.utils;
-
-SimpleTest.waitForExplicitFinish();
-
-var permManager = Cc["@mozilla.org/permissionmanager;1"]
-                    .getService(Ci.nsIPermissionManager);
-var appsService = Cc['@mozilla.org/AppsService;1']
-                    .getService(Ci.nsIAppsService);
-var secMan = Cc['@mozilla.org/scriptsecuritymanager;1']
-               .getService(Ci.nsIScriptSecurityManager);
-var ioService = Cc["@mozilla.org/network/io-service;1"]
-                  .getService(Components.interfaces.nsIIOService);
-
-var Webapps = {};
-Cu.import("resource://gre/modules/Webapps.jsm", Webapps);
-
-/**
- * This function will make sure that the next applications we try to install
- * will be installed. That means it will behave like if the user allowed the app
- * to be installed in the door hanger.
- */
-function confirmNextInstall() {
-  var panel = window.top.QueryInterface(Ci.nsIInterfaceRequestor)
-                        .getInterface(Ci.nsIWebNavigation)
-                        .QueryInterface(Ci.nsIDocShell)
-                        .chromeEventHandler.ownerDocument.defaultView
-                        .PopupNotifications.panel
-
-  panel.addEventListener("popupshown", function() {
-    panel.removeEventListener("popupshown", arguments.callee, false);
-    this.childNodes[0].button.doCommand();
-  }, false);
-}
-
-// If aAppId = -1, returns permissions count, regardless of app.
-function getPermissionCountForApp(aAppId) {
-  var nbPermissions = 0;
-  var enumerator = permManager.enumerator;
-
-  while (enumerator.hasMoreElements()) {
-    var permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
-
-    if (permission.appId == aAppId || aAppId == -1) {
-      nbPermissions++;
-    }
-  }
-
-  return nbPermissions;
-}
-
-permManager.addFromPrincipal(window.document.nodePrincipal, "webapps-manage",
-                             Ci.nsIPermissionManager.ALLOW_ACTION);
-permManager.addFromPrincipal(window.document.nodePrincipal, "browser",
-                             Ci.nsIPermissionManager.ALLOW_ACTION);
-
-var previousPrefs = {
-  mozBrowserFramesEnabled: null,
-  installerDryRun: null,
-};
-
-// Save the prefs we want to change (so we can re-set them later) and set them
-// to the needed value.
-try {
-  previousPrefs.mozBrowserFramesEnabled = SpecialPowers.getBoolPref('dom.mozBrowserFramesEnabled');
-} catch(e)
-{
-}
-SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', true);
-
-try {
-  previousPrefs.installerDryRun = SpecialPowers.getBoolPref('browser.mozApps.installer.dry_run');
-} catch(e) {
-}
-SpecialPowers.setBoolPref('browser.mozApps.installer.dry_run', true);
-
-// We want to simulate that all apps are launchable, for testing purpose.
-var gPreviousLaunchableValue = Webapps.DOMApplicationRegistry.allAppsLaunchable;
-Webapps.DOMApplicationRegistry.allAppsLaunchable = true;
-
-// URL of the manifest of the app we want to install.
-const gManifestURL = "http://www.example.com/chrome/dom/tests/mochitest/webapps/apps/basic.webapp";
-// ID of the installed app.
-var gTestAppId = 0;
-
-addLoadEvent(function() {
-  confirmNextInstall();
-
-  navigator.mozApps.install(gManifestURL, null).onsuccess = function() {
-    gTestAppId = appsService.getAppLocalIdByManifestURL(gManifestURL);
-
-    is(getPermissionCountForApp(gTestAppId), 0, "App should have no permission");
-
-    var currentPermissionCount = getPermissionCountForApp(-1);
-
-    var principal = secMan.getAppCodebasePrincipal(ioService.newURI("http://www.example.com", null, null),
-                                                   gTestAppId, true);
-
-    permManager.addFromPrincipal(principal, "foobar", Ci.nsIPermissionManager.ALLOW_ACTION);
-    permManager.addFromPrincipal(principal, "foo", Ci.nsIPermissionManager.DENY_ACTION);
-    permManager.addFromPrincipal(principal, "bar", Ci.nsIPermissionManager.ALLOW_ACTION, Ci.nsIPermissionManager.EXPIRE_SESSION, 0);
-
-    principal = secMan.getAppCodebasePrincipal(ioService.newURI("http://www.example.org", null, null),
-                                               gTestAppId, true);
-    permManager.addFromPrincipal(principal, "foobar", Ci.nsIPermissionManager.ALLOW_ACTION);
-
-    is(getPermissionCountForApp(gTestAppId), 4, "App should have 4 permissions");
-
-    var frame = document.createElement('iframe');
-    frame.setAttribute('mozbrowser', '');
-    frame.setAttribute('mozapp', gManifestURL);
-    frame.src = 'http://www.example.com/chrome/extensions/cookie/test/frame_clear_browser_data.html';
-    frame.name = 'app';
-
-    frame.addEventListener('load', appFrameLoadEvent);
-
-    document.body.appendChild(frame);
-  };
-});
-
-function appFrameLoadEvent() {
-  /*
-   * The app frame has been loaded. We can now add permissions for the app to
-   * create browsers and we will load a page in this browser and wait for the
-   * load event.
-   */
-  permManager.addFromPrincipal(window.frames[1].document.nodePrincipal, "browser",
-                               Ci.nsIPermissionManager.ALLOW_ACTION);
-
-  var frame = document.createElement('iframe');
-  frame.setAttribute('mozbrowser', '');
-  frame.src = 'http://example.com/tests/error404_2';
-
-  frame.addEventListener('load', browserLoadEvent);
-
-  document.getElementsByName('app')[0].contentDocument.body.appendChild(frame);
-}
-
-function browserLoadEvent() {
-  /*
-   * The browser inside the app has loaded.
-   */
-
-  frames[1].postMessage("clear", "http://www.example.com");
-
-  waitForClearBrowserData();
-};
-
-function waitForClearBrowserData() {
-  SimpleTest.executeSoon(function() {
-    if (frames[1].document.getElementsByTagName('done').length == 0) {
-      waitForClearBrowserData();
-    } else {
-      checks();
-    }
-  });
-}
-function checks() {
-  navigator.mozApps.mgmt.getAll().onsuccess = function() {
-    for (i in this.result) {
-      var app = this.result[i];
-      if (app.manifestURL == gManifestURL) {
-        is(getPermissionCountForApp(gTestAppId), 0, "App should have 0 permissions");
-
-        Webapps.DOMApplicationRegistry.allAppsLaunchable = gPreviousLaunchableValue;
-
-        // Now we uninstall the app and make sure everything is clean.
-        navigator.mozApps.mgmt.uninstall(app).onsuccess = function() {
-          is(getPermissionCountForApp(gTestAppId), 0, "App should have 0 permissions");
-          finish();
-        };
-      }
-    }
-  };
-}
-
-/**
- * This method will be called when the test will be done. It is going to clear
- * all storage data, permissions, etc.
- */
-function finish() {
-  permManager.removeFromPrincipal(window.document.nodePrincipal, "webapps-manage",
-                                  Ci.nsIPermissionManager.ALLOW_ACTION);
-  permManager.removeFromPrincipal(window.document.nodePrincipal, "browser",
-                                  Ci.nsIPermissionManager.ALLOW_ACTION);
-
-  SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', previousPrefs.mozBrowserFramesEnabled);
-  SpecialPowers.setBoolPref('browser.mozApps.installer.dry_run', previousPrefs.installerDryRun);
-
-  SimpleTest.finish();
-}
-
-</script>
-</pre>
-</body>
-</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/unit/test_permmanager_cleardata.js
@@ -0,0 +1,72 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let pm;
+
+// Create a principal based on the { origin, appId, browserElement }.
+function createPrincipal(aOrigin, aAppId, aBrowserElement)
+{
+  return Services.scriptSecurityManager.getAppCodebasePrincipal(NetUtil.newURI(aOrigin), aAppId, aBrowserElement);
+}
+
+// Return the subject required by 'webapps-clear-data' notification.
+function getSubject(aAppId, aBrowserOnly)
+{
+  return {
+    appId: aAppId,
+    browserOnly: aBrowserOnly,
+    QueryInterface: XPCOMUtils.generateQI([Ci.mozIApplicationClearPrivateDataParams])
+  };
+}
+
+// Use aEntries to create principals, add permissions to them and check that they have them.
+// Then, it is notifying 'webapps-clear-data' with the given aSubject and check if the permissions
+// of principals[i] matches the permission in aResults[i].
+function test(aEntries, aSubject, aResults)
+{
+  let principals = [];
+
+  for (entry of aEntries) {
+    principals.push(createPrincipal(entry.origin, entry.appId, entry.browserElement));
+  }
+
+  for (principal of principals) {
+    do_check_eq(pm.testPermissionFromPrincipal(principal, "test/webapps-clear"), pm.UNKNOWN_ACTION);
+    pm.addFromPrincipal(principal, "test/webapps-clear", pm.ALLOW_ACTION, pm.EXPIRE_NEVER, 0);
+    do_check_eq(pm.testPermissionFromPrincipal(principal, "test/webapps-clear"), pm.ALLOW_ACTION);
+  }
+
+  Services.obs.notifyObservers(aSubject, 'webapps-clear-data', null);
+
+  var length = aEntries.length;
+  for (let i=0; i<length; ++i) {
+    do_check_eq(pm.testPermissionFromPrincipal(principals[i], 'test/webapps-clear'), aResults[i]);
+
+    // Remove allowed actions.
+    if (aResults[i] == pm.ALLOW_ACTION) {
+      pm.removeFromPrincipal(principals[i], 'test/webapps-clear');
+    }
+  }
+}
+
+function run_test()
+{
+  do_get_profile();
+
+  pm = Cc["@mozilla.org/permissionmanager;1"]
+         .getService(Ci.nsIPermissionManager);
+
+  let entries = [
+    { origin: 'http://example.com', appId: 1, browserElement: false },
+    { origin: 'http://example.com', appId: 1, browserElement: true },
+    { origin: 'http://example.com', appId: Ci.nsIScriptSecurityManager.NO_APPID, browserElement: false },
+    { origin: 'http://example.com', appId: 2, browserElement: false },
+  ];
+
+  // In that case, all permissions from app 1 should be removed but not the other ones.
+  test(entries, getSubject(1, false), [ pm.UNKNOWN_ACTION, pm.UNKNOWN_ACTION, pm.ALLOW_ACTION, pm.ALLOW_ACTION ]);
+
+  // In that case, only the permissions of app 1 related to a browserElement should be removed.
+  // All the other permissions should stay.
+  test(entries, getSubject(1, true), [ pm.ALLOW_ACTION, pm.UNKNOWN_ACTION, pm.ALLOW_ACTION, pm.ALLOW_ACTION ]);
+}
--- a/extensions/cookie/test/unit/xpcshell.ini
+++ b/extensions/cookie/test/unit/xpcshell.ini
@@ -15,10 +15,11 @@ skip-if = perwindowprivatebrowsing
 [test_cookies_sync_failure.js]
 [test_cookies_thirdparty.js]
 [test_cookies_thirdparty_session.js]
 [test_domain_eviction.js]
 [test_eviction.js]
 [test_permmanager_expiration.js]
 [test_permmanager_notifications.js]
 [test_permmanager_removeall.js]
+[test_permmanager_cleardata.js]
 [test_schema_2_migration.js]
 [test_schema_3_migration.js]