Bug 1362994 - Implement browsingData.settings WebExtension API method on android. r=bsilverberg,mattw,sebastian
authorTushar Saini (:shatur) <tushar.saini1285@gmail.com>
Fri, 02 Jun 2017 23:11:49 +0530
changeset 418857 ea938674f10268887982c61f26b7462374a902c7
parent 418856 6d589dfabec7ab8fdce1dda3c7e64873b608832f
child 418858 499d18aed4f008115fd69135abf8988f9f3b7fbb
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsilverberg, mattw, sebastian
bugs1362994
milestone56.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 1362994 - Implement browsingData.settings WebExtension API method on android. r=bsilverberg,mattw,sebastian MozReview-Commit-ID: G9frPBFPHCT
mobile/android/components/extensions/ext-android.js
mobile/android/components/extensions/ext-browsingData.js
mobile/android/components/extensions/jar.mn
mobile/android/components/extensions/schemas/browsing_data.json
mobile/android/components/extensions/schemas/jar.mn
mobile/android/components/extensions/test/mochitest/chrome.ini
mobile/android/components/extensions/test/mochitest/test_ext_browsingData_settings.html
--- a/mobile/android/components/extensions/ext-android.js
+++ b/mobile/android/components/extensions/ext-android.js
@@ -54,16 +54,25 @@ extensions.registerModules({
     url: "chrome://browser/content/ext-browserAction.js",
     schema: "chrome://browser/content/schemas/browser_action.json",
     scopes: ["addon_parent"],
     manifest: ["browser_action"],
     paths: [
       ["browserAction"],
     ],
   },
+  browsingData: {
+    url: "chrome://browser/content/ext-browsingData.js",
+    schema: "chrome://browser/content/schemas/browsing_data.json",
+    scopes: ["addon_parent"],
+    manifest: ["browsing_data"],
+    paths: [
+      ["browsingData"],
+    ],
+  },
   pageAction: {
     url: "chrome://browser/content/ext-pageAction.js",
     schema: "chrome://browser/content/schemas/page_action.json",
     scopes: ["addon_parent"],
     manifest: ["page_action"],
     paths: [
       ["pageAction"],
     ],
new file mode 100644
--- /dev/null
+++ b/mobile/android/components/extensions/ext-browsingData.js
@@ -0,0 +1,57 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+Cu.import("resource://gre/modules/Task.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "Services",
+                                  "resource://gre/modules/Services.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "SharedPreferences",
+                                  "resource://gre/modules/SharedPreferences.jsm");
+
+this.browsingData = class extends ExtensionAPI {
+  getAPI(context) {
+    return {
+      browsingData: {
+        settings() {
+          const PREF_DOMAIN = "android.not_a_preference.privacy.clear";
+          const PREF_KEY_PREFIX = "private.data.";
+          // The following prefs are the only ones in Firefox that match corresponding
+          // values used by Chrome when returning settings.
+          const PREF_LIST = ["cache", "history", "formdata", "cookies_sessions", "downloadFiles"];
+
+          let dataTrue = SharedPreferences.forProfile().getSetPref(PREF_DOMAIN);
+          let name;
+
+          let dataToRemove = {};
+          let dataRemovalPermitted = {};
+
+          for (let item of PREF_LIST) {
+            // The property formData needs a different case than the
+            // formdata preference.
+            switch(item){
+              case "formdata":
+                name = "formData";
+                break;
+              case "cookies_sessions":
+                name = "cookies";
+                break;
+              case "downloadFiles":
+                name = "downloads";
+                break;
+              default:
+                name = item;
+            }
+            dataToRemove[name] = dataTrue.includes(`${PREF_KEY_PREFIX}${item}`);
+            // Firefox doesn't have the same concept of dataRemovalPermitted
+            // as Chrome, so it will always be true.
+            dataRemovalPermitted[name] = true;
+          }
+          // We do not provide option to delete history by time
+          // so, since value is given 0, which means Everything
+          return Promise.resolve({options: {since: 0}, dataToRemove, dataRemovalPermitted});
+        },
+      },
+    };
+  }
+};
\ No newline at end of file
--- a/mobile/android/components/extensions/jar.mn
+++ b/mobile/android/components/extensions/jar.mn
@@ -2,11 +2,12 @@
 # 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/.
 
 chrome.jar:
     content/ext-android.js
     content/ext-c-android.js
     content/ext-c-tabs.js
     content/ext-browserAction.js
+    content/ext-browsingData.js
     content/ext-pageAction.js
     content/ext-tabs.js
     content/ext-utils.js
copy from browser/components/extensions/schemas/browsing_data.json
copy to mobile/android/components/extensions/schemas/browsing_data.json
--- a/browser/components/extensions/schemas/browsing_data.json
+++ b/mobile/android/components/extensions/schemas/browsing_data.json
@@ -157,16 +157,17 @@
           }
         ]
       },
       {
         "name": "remove",
         "description": "Clears various types of browsing data stored in a user's profile.",
         "type": "function",
         "async": "callback",
+        "unsupported": true,
         "parameters": [
           {
             "$ref": "RemovalOptions",
             "name": "options"
           },
           {
             "name": "dataToRemove",
             "$ref": "DataTypeSet",
@@ -201,16 +202,17 @@
           }
         ]
       },
       {
         "name": "removeCache",
         "description": "Clears the browser's cache.",
         "type": "function",
         "async": "callback",
+        "unsupported": true,
         "parameters": [
           {
             "$ref": "RemovalOptions",
             "name": "options"
           },
           {
             "name": "callback",
             "type": "function",
@@ -220,16 +222,17 @@
           }
         ]
       },
       {
         "name": "removeCookies",
         "description": "Clears the browser's cookies and server-bound certificates modified within a particular timeframe.",
         "type": "function",
         "async": "callback",
+        "unsupported": true,
         "parameters": [
           {
             "$ref": "RemovalOptions",
             "name": "options"
           },
           {
             "name": "callback",
             "type": "function",
@@ -239,16 +242,17 @@
           }
         ]
       },
       {
         "name": "removeDownloads",
         "description": "Clears the browser's list of downloaded files (<em>not</em> the downloaded files themselves).",
         "type": "function",
         "async": "callback",
+        "unsupported": true,
         "parameters": [
           {
             "$ref": "RemovalOptions",
             "name": "options"
           },
           {
             "name": "callback",
             "type": "function",
@@ -278,16 +282,17 @@
           }
         ]
       },
       {
         "name": "removeFormData",
         "description": "Clears the browser's stored form data (autofill).",
         "type": "function",
         "async": "callback",
+        "unsupported": true,
         "parameters": [
           {
             "$ref": "RemovalOptions",
             "name": "options"
           },
           {
             "name": "callback",
             "type": "function",
@@ -297,16 +302,17 @@
           }
         ]
       },
       {
         "name": "removeHistory",
         "description": "Clears the browser's history.",
         "type": "function",
         "async": "callback",
+        "unsupported": true,
         "parameters": [
           {
             "$ref": "RemovalOptions",
             "name": "options"
           },
           {
             "name": "callback",
             "type": "function",
@@ -356,16 +362,17 @@
           }
         ]
       },
       {
         "name": "removePluginData",
         "description": "Clears plugins' data.",
         "type": "function",
         "async": "callback",
+        "unsupported": true,
         "parameters": [
           {
             "$ref": "RemovalOptions",
             "name": "options"
           },
           {
             "name": "callback",
             "type": "function",
@@ -375,16 +382,17 @@
           }
         ]
       },
       {
         "name": "removePasswords",
         "description": "Clears the browser's stored passwords.",
         "type": "function",
         "async": "callback",
+        "unsupported": true,
         "parameters": [
           {
             "$ref": "RemovalOptions",
             "name": "options"
           },
           {
             "name": "callback",
             "type": "function",
--- a/mobile/android/components/extensions/schemas/jar.mn
+++ b/mobile/android/components/extensions/schemas/jar.mn
@@ -1,8 +1,9 @@
 # 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/.
 
 chrome.jar:
     content/schemas/browser_action.json
+    content/schemas/browsing_data.json
     content/schemas/page_action.json
     content/schemas/tabs.json
--- a/mobile/android/components/extensions/test/mochitest/chrome.ini
+++ b/mobile/android/components/extensions/test/mochitest/chrome.ini
@@ -1,11 +1,12 @@
 [DEFAULT]
 support-files =
   head.js
   ../../../../../../toolkit/components/extensions/test/mochitest/chrome_cleanup_script.js
 tags = webextensions
 
 [test_ext_browserAction_getTitle_setTitle.html]
 [test_ext_browserAction_onClicked.html]
+[test_ext_browsingData_settings.html]
 [test_ext_pageAction_show_hide.html]
 [test_ext_pageAction_getPopup_setPopup.html]
 skip-if = os == 'android' # bug 1373170
new file mode 100644
--- /dev/null
+++ b/mobile/android/components/extensions/test/mochitest/test_ext_browsingData_settings.html
@@ -0,0 +1,101 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>BrowsingData Settings test</title>
+  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
+  <script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
+  <script type="text/javascript" src="head.js"></script>
+  <link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<script type="text/javascript">
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+
+var {SharedPreferences} = Cu.import("resource://gre/modules/SharedPreferences.jsm", {});
+
+const PREF_DOMAIN = "android.not_a_preference.privacy.clear";
+const PREF_KEY_PREFIX = "private.data.";
+const SETTINGS_LIST = ["cache", "cookies", "history", "formData", "downloads"];
+
+function checkPrefs(key, actualValue, prefs, prefSuffix) {
+  let prefValue = prefs.includes(`${PREF_KEY_PREFIX}${prefSuffix}`);
+  is(actualValue, prefValue, `${key} property of dataToRemove matches the expected pref.`);
+}
+
+function testSettingsPreferences(dataToRemove){
+  let prefs = SharedPreferences.forProfile().getSetPref(PREF_DOMAIN);
+
+  for (let key of Object.keys(dataToRemove)) {
+    switch(key){
+      case "formData":
+        checkPrefs(key, dataToRemove[key], prefs, "formdata");
+        break;
+      case "cookies":
+        checkPrefs(key, dataToRemove[key], prefs, "cookies_sessions");
+        break;
+      case "downloads":
+        checkPrefs(key, dataToRemove[key], prefs, "downloadFiles");
+        break;
+      default:
+        checkPrefs(key, dataToRemove[key], prefs, key);
+    }
+  }
+}
+
+add_task(async function testSettings() {
+  function background() {
+    browser.test.onMessage.addListener(async (msg) => {
+      if (msg == "retrieve-settings") {
+        let settings = await browser.browsingData.settings();
+        browser.test.sendMessage("settings", settings);
+      }
+    });
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    background,
+    manifest: {
+      "permissions": ["browsingData"],
+    },
+  });
+
+  await extension.startup();
+
+  extension.sendMessage("retrieve-settings");
+  let {options, dataToRemove, dataRemovalPermitted} = await extension.awaitMessage("settings");
+
+  // Verify that we get the keys we expect.
+  is(SETTINGS_LIST.length, Object.keys(dataToRemove).length, `dataToRemove contains expected no of keys`);
+  is(SETTINGS_LIST.length, Object.keys(dataRemovalPermitted).length, `dataRemovalPermitted contains expected no of keys`);
+  for (let key of SETTINGS_LIST) {
+    is(true, dataRemovalPermitted[key],
+      `${key} property of dataRemovalPermitted matches the expected value.`);
+  }
+
+  // Verify values of dataToRemove keys are as expected.
+  testSettingsPreferences(dataToRemove);
+
+  // Verify object options returned as expected.
+  // For now, We do not provide option to delete history by time, so,
+  // since value is given 0, which means Everything.
+  is(options.since, 0, `options contains expected value.`);
+
+  // Explicitly set some prefs to true
+  const NEW_PREFS = ["private.data.cache", "private.data.cookies_sessions"];
+
+  SharedPreferences.forProfile().setSetPref(PREF_DOMAIN, NEW_PREFS);
+
+  extension.sendMessage("retrieve-settings");
+  let settings = await extension.awaitMessage("settings");
+  testSettingsPreferences(settings.dataToRemove);
+
+  await extension.unload();
+});
+</script>
+
+</body>
+</html>
\ No newline at end of file