Bug 874408: Join safe browsing, add download protection to security prefs. r=gcp,francois,past
authorJohann Hofmann <jhofmann@mozilla.com>
Mon, 18 Apr 2016 15:46:04 +0200
changeset 332388 2df96c0510daa5f604256647090dba70d7670e40
parent 332387 f9177e655c8c7c3250087d71c0b6fed5e335e1b5
child 332389 463fc6d36ff561f17a34f1688bd8c38833de8966
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)
reviewersgcp, francois, past
bugs874408
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 874408: Join safe browsing, add download protection to security prefs. r=gcp,francois,past MozReview-Commit-ID: L6ZmvTmndml
browser/components/preferences/in-content/security.js
browser/components/preferences/in-content/security.xul
browser/components/preferences/in-content/tests/browser.ini
browser/components/preferences/in-content/tests/browser_security.js
browser/locales/en-US/chrome/browser/preferences/security.dtd
mobile/android/chrome/content/aboutRights.xhtml
toolkit/content/aboutRights.xhtml
toolkit/locales/en-US/chrome/global/aboutRights.dtd
--- a/browser/components/preferences/in-content/security.js
+++ b/browser/components/preferences/in-content/security.js
@@ -15,16 +15,17 @@ var gSecurityPane = {
     function setEventListener(aId, aEventType, aCallback)
     {
       document.getElementById(aId)
               .addEventListener(aEventType, aCallback.bind(gSecurityPane));
     }
 
     this._pane = document.getElementById("paneSecurity");
     this._initMasterPasswordUI();
+    this._initSafeBrowsing();
 
     setEventListener("addonExceptions", "command",
       gSecurityPane.showAddonExceptions);
     setEventListener("passwordExceptions", "command",
       gSecurityPane.showPasswordExceptions);
     setEventListener("useMasterPassword", "command",
       gSecurityPane.updateMasterPasswordButton);
     setEventListener("changeMasterPassword", "command",
@@ -139,16 +140,87 @@ var gSecurityPane = {
 
     var button = document.getElementById("changeMasterPassword");
     button.disabled = noMP;
 
     var checkbox = document.getElementById("useMasterPassword");
     checkbox.checked = !noMP;
   },
 
+  _initSafeBrowsing() {
+    let enableSafeBrowsing = document.getElementById("enableSafeBrowsing");
+    let blockDownloads = document.getElementById("blockDownloads");
+    let blockUncommonUnwanted = document.getElementById("blockUncommonUnwanted");
+
+    let safeBrowsingPhishingPref = document.getElementById("browser.safebrowsing.enabled");
+    let safeBrowsingMalwarePref = document.getElementById("browser.safebrowsing.malware.enabled");
+
+    let blockDownloadsPref = document.getElementById("browser.safebrowsing.downloads.enabled");
+    let malwareTable = document.getElementById("urlclassifier.malwareTable");
+
+    let blockUnwantedPref = document.getElementById("browser.safebrowsing.downloads.remote.block_potentially_unwanted");
+    let blockUncommonPref = document.getElementById("browser.safebrowsing.downloads.remote.block_uncommon");
+
+    enableSafeBrowsing.addEventListener("command", function() {
+      safeBrowsingPhishingPref.value = enableSafeBrowsing.checked;
+      safeBrowsingMalwarePref.value = enableSafeBrowsing.checked;
+
+      if (enableSafeBrowsing.checked) {
+        blockDownloads.removeAttribute("disabled");
+        blockUncommonUnwanted.removeAttribute("disabled");
+      } else {
+        blockDownloads.setAttribute("disabled", "true");
+        blockUncommonUnwanted.setAttribute("disabled", "true");
+      }
+    });
+
+    blockDownloads.addEventListener("command", function() {
+      blockDownloadsPref.value = blockDownloads.checked;
+      if (blockDownloads.checked) {
+        blockUncommonUnwanted.removeAttribute("disabled");
+      } else {
+        blockUncommonUnwanted.setAttribute("disabled", "true");
+      }
+    });
+
+    blockUncommonUnwanted.addEventListener("command", function() {
+      blockUnwantedPref.value = blockUncommonUnwanted.checked;
+      blockUncommonPref.value = blockUncommonUnwanted.checked;
+
+      let malware = malwareTable.value
+        .split(",")
+        .filter(x => x !== "goog-unwanted-simple" && x !== "test-unwanted-simple");
+
+      if (blockUncommonUnwanted.checked) {
+        malware.push("goog-unwanted-simple");
+        malware.push("test-unwanted-simple");
+      }
+
+      // sort alphabetically to keep the pref consistent
+      malware.sort();
+
+      malwareTable.value = malware.join(",");
+    });
+
+    // set initial values
+
+    enableSafeBrowsing.checked = safeBrowsingPhishingPref.value && safeBrowsingMalwarePref.value;
+    if (!enableSafeBrowsing.checked) {
+      blockDownloads.setAttribute("disabled", "true");
+      blockUncommonUnwanted.setAttribute("disabled", "true");
+    }
+
+    blockDownloads.checked = blockDownloadsPref.value;
+    if (!blockDownloadsPref.value) {
+      blockUncommonUnwanted.setAttribute("disabled", "true");
+    }
+
+    blockUncommonUnwanted.checked = blockUnwantedPref.value && blockUncommonPref.value;
+  },
+
   /**
    * Returns true if the user has a master password set and false otherwise.
    */
   _masterPasswordSet: function ()
   {
     var secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].
                    getService(Ci.nsIPKCS11ModuleDB);
     var slot = secmodDB.findSlotByName("");
--- a/browser/components/preferences/in-content/security.xul
+++ b/browser/components/preferences/in-content/security.xul
@@ -15,23 +15,39 @@
   <preference id="pref.privacy.disable_button.view_passwords_exceptions"
               name="pref.privacy.disable_button.view_passwords_exceptions"
               type="bool"/>
 
   <!-- Add-ons, malware, phishing -->
   <preference id="xpinstall.whitelist.required"
               name="xpinstall.whitelist.required"
               type="bool"/>
+
   <preference id="browser.safebrowsing.malware.enabled"
               name="browser.safebrowsing.malware.enabled"
               type="bool"/>
   <preference id="browser.safebrowsing.enabled"
               name="browser.safebrowsing.enabled"
               type="bool"/>
 
+  <preference id="browser.safebrowsing.downloads.enabled"
+              name="browser.safebrowsing.downloads.enabled"
+              type="bool"/>
+
+  <preference id="urlclassifier.malwareTable"
+              name="urlclassifier.malwareTable"
+              type="string"/>
+
+  <preference id="browser.safebrowsing.downloads.remote.block_potentially_unwanted"
+              name="browser.safebrowsing.downloads.remote.block_potentially_unwanted"
+              type="bool"/>
+  <preference id="browser.safebrowsing.downloads.remote.block_uncommon"
+              name="browser.safebrowsing.downloads.remote.block_uncommon"
+              type="bool"/>
+
   <!-- Passwords -->
   <preference id="signon.rememberSignons" name="signon.rememberSignons" type="bool"/>
 
 </preferences>
 
 <hbox id="header-security"
       class="header"
       hidden="true"
@@ -54,24 +70,27 @@
     <spacer flex="1"/>
     <button id="addonExceptions"
             label="&addonExceptions.label;"
             accesskey="&addonExceptions.accesskey;"/>
   </hbox>
 
   <separator class="thin"/>
   <vbox align="start">
-    <checkbox id="blockAttackSites"
-              label="&blockAttackSites.label;"
-              accesskey="&blockAttackSites.accesskey;"
-              preference="browser.safebrowsing.malware.enabled" />
-    <checkbox id="blockWebForgeries"
-              label="&blockWebForgeries.label;"
-              accesskey="&blockWebForgeries.accesskey;"
-              preference="browser.safebrowsing.enabled" />
+    <checkbox id="enableSafeBrowsing"
+              label="&enableSafeBrowsing.label;"
+              accesskey="&enableSafeBrowsing.accesskey;" />
+    <vbox class="indent">
+      <checkbox id="blockDownloads"
+                label="&blockDownloads.label;"
+                accesskey="&blockDownloads.accesskey;" />
+      <checkbox id="blockUncommonUnwanted"
+                label="&blockUncommonUnwanted.label;"
+                accesskey="&blockUncommonUnwanted.accesskey;" />
+    </vbox>
   </vbox>
 </groupbox>
 
 <!-- Passwords -->
 <groupbox id="passwordsGroup" orient="vertical" data-category="paneSecurity" hidden="true">
   <caption><label>&logins.label;</label></caption>
 
   <hbox id="savePasswordsBox">
--- a/browser/components/preferences/in-content/tests/browser.ini
+++ b/browser/components/preferences/in-content/tests/browser.ini
@@ -26,15 +26,16 @@ skip-if = true || !healthreport # Bug 11
 [browser_proxy_backup.js]
 [browser_privacypane_1.js]
 [browser_privacypane_3.js]
 [browser_privacypane_4.js]
 [browser_privacypane_5.js]
 [browser_privacypane_8.js]
 [browser_sanitizeOnShutdown_prefLocked.js]
 [browser_searchsuggestions.js]
+[browser_security.js]
 [browser_subdialogs.js]
 support-files =
   subdialog.xul
   subdialog2.xul
 [browser_telemetry.js]
 # Skip this test on Android and B2G as FHR and Telemetry are separate systems there.
 skip-if = !healthreport || !telemetry || (os == 'linux' && debug) || (os == 'android') || (os == 'b2g')
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_security.js
@@ -0,0 +1,129 @@
+const PREFS = [
+  "browser.safebrowsing.enabled",
+  "browser.safebrowsing.malware.enabled",
+
+  "browser.safebrowsing.downloads.enabled",
+
+  "browser.safebrowsing.downloads.remote.block_potentially_unwanted",
+  "browser.safebrowsing.downloads.remote.block_uncommon"
+];
+
+let originals = PREFS.map(pref => [pref, Services.prefs.getBoolPref(pref)])
+let originalMalwareTable = Services.prefs.getCharPref("urlclassifier.malwareTable");
+registerCleanupFunction(function() {
+  originals.forEach(([pref, val]) => Services.prefs.setBoolPref(pref, val))
+  Services.prefs.setCharPref("urlclassifier.malwareTable", originalMalwareTable);
+});
+
+// test the safebrowsing preference
+add_task(function*() {
+  function* checkPrefSwitch(val1, val2) {
+    Services.prefs.setBoolPref("browser.safebrowsing.enabled", val1);
+    Services.prefs.setBoolPref("browser.safebrowsing.malware.enabled", val2);
+
+    yield openPreferencesViaOpenPreferencesAPI("security", undefined, { leaveOpen: true });
+
+    let doc = gBrowser.selectedBrowser.contentDocument;
+    let checkbox = doc.getElementById("enableSafeBrowsing");
+    let blockDownloads = doc.getElementById("blockDownloads");
+    let blockUncommon = doc.getElementById("blockUncommonUnwanted");
+    let checked = checkbox.checked;
+    is(checked, val1 && val2, "safebrowsing preference is initialized correctly");
+    // should be disabled when checked is false (= pref is turned off)
+    is(blockDownloads.hasAttribute("disabled"), !checked, "block downloads checkbox is set correctly");
+    is(blockUncommon.hasAttribute("disabled"), !checked, "block uncommon checkbox is set correctly");
+
+    // click the checkbox
+    EventUtils.synthesizeMouseAtCenter(checkbox, {}, gBrowser.selectedBrowser.contentWindow);
+
+    // check that both settings are now turned on or off
+    is(Services.prefs.getBoolPref("browser.safebrowsing.enabled"), !checked,
+       "safebrowsing.enabled is set correctly");
+    is(Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled"), !checked,
+       "safebrowsing.malware.enabled is set correctly");
+
+    // check if the other checkboxes have updated
+    is(blockDownloads.hasAttribute("disabled"), checked, "block downloads checkbox is set correctly");
+    is(blockUncommon.hasAttribute("disabled"), checked, "block uncommon checkbox is set correctly");
+
+    yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+  }
+
+  yield checkPrefSwitch(true, true);
+  yield checkPrefSwitch(false, true);
+  yield checkPrefSwitch(true, false);
+  yield checkPrefSwitch(false, false);
+});
+
+// test the download protection preference
+add_task(function*() {
+  function* checkPrefSwitch(val) {
+    Services.prefs.setBoolPref("browser.safebrowsing.downloads.enabled", val);
+
+    yield openPreferencesViaOpenPreferencesAPI("security", undefined, { leaveOpen: true });
+
+    let doc = gBrowser.selectedBrowser.contentDocument;
+    let checkbox = doc.getElementById("blockDownloads");
+    let blockUncommon = doc.getElementById("blockUncommonUnwanted");
+    let checked = checkbox.checked;
+    is(checked, val, "downloads preference is initialized correctly");
+    // should be disabled when val is false (= pref is turned off)
+    is(blockUncommon.hasAttribute("disabled"), !val, "block uncommon checkbox is set correctly");
+
+    // click the checkbox
+    EventUtils.synthesizeMouseAtCenter(checkbox, {}, gBrowser.selectedBrowser.contentWindow);
+
+    // check that setting is now turned on or off
+    is(Services.prefs.getBoolPref("browser.safebrowsing.downloads.enabled"), !checked,
+       "safebrowsing.downloads preference is set correctly");
+
+    // check if the uncommon warning checkbox has updated
+    is(blockUncommon.hasAttribute("disabled"), val, "block uncommon checkbox is set correctly");
+
+    yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+  }
+
+  yield checkPrefSwitch(true);
+  yield checkPrefSwitch(false);
+});
+
+// test the unwanted/uncommon software warning preference
+add_task(function*() {
+  function* checkPrefSwitch(val1, val2) {
+    Services.prefs.setBoolPref("browser.safebrowsing.downloads.remote.block_potentially_unwanted", val1);
+    Services.prefs.setBoolPref("browser.safebrowsing.downloads.remote.block_uncommon", val2);
+
+    yield openPreferencesViaOpenPreferencesAPI("security", undefined, { leaveOpen: true });
+
+    let doc = gBrowser.selectedBrowser.contentDocument;
+    let checkbox = doc.getElementById("blockUncommonUnwanted");
+    let checked = checkbox.checked;
+    is(checked, val1 && val2, "unwanted/uncommon preference is initialized correctly");
+
+    // click the checkbox
+    EventUtils.synthesizeMouseAtCenter(checkbox, {}, gBrowser.selectedBrowser.contentWindow);
+
+    // check that both settings are now turned on or off
+    is(Services.prefs.getBoolPref("browser.safebrowsing.downloads.remote.block_potentially_unwanted"), !checked,
+       "block_potentially_unwanted is set correctly");
+    is(Services.prefs.getBoolPref("browser.safebrowsing.downloads.remote.block_uncommon"), !checked,
+       "block_uncommon is set correctly");
+
+    // when the preference is on, the malware table should include these ids
+    let malwareTable = Services.prefs.getCharPref("urlclassifier.malwareTable").split(",");
+    is(malwareTable.includes("goog-unwanted-simple"), !checked,
+       "malware table doesn't include goog-unwanted-simple");
+    is(malwareTable.includes("test-unwanted-simple"), !checked,
+       "malware table doesn't include test-unwanted-simple");
+    let sortedMalware = malwareTable.slice(0);
+    sortedMalware.sort();
+    Assert.deepEqual(malwareTable, sortedMalware, "malware table has been sorted");
+
+    yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+  }
+
+  yield checkPrefSwitch(true, true);
+  yield checkPrefSwitch(false, true);
+  yield checkPrefSwitch(true, false);
+  yield checkPrefSwitch(false, false);
+});
--- a/browser/locales/en-US/chrome/browser/preferences/security.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/security.dtd
@@ -2,28 +2,28 @@
    - 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/. -->
 
 <!ENTITY  general.label                 "General">
 
 <!ENTITY  warnAddonInstall.label        "Warn me when sites try to install add-ons">
 <!ENTITY  warnAddonInstall.accesskey    "W">
 
-<!-- LOCALIZATION NOTE (blockWebForgeries.label, blockAttackSites.label):
-  The methods by which forged (phished) and attack sites will be detected by
-  phishing providers will vary from human review to machine-based heuristics to a
-  combination of both, so it's important that these strings and
-  useDownloadedList.label convey the meaning "reported" (and not something like
-  "known").
+<!-- LOCALIZATION NOTE (enableSafeBrowsing.label, blockDownloads.label, blockUncommonUnwanted.label):
+  It is important that wording follows the guidelines outlined on this page:
+  https://developers.google.com/safe-browsing/developers_guide_v2#AcceptableUsage
 -->
-<!ENTITY  blockAttackSites.label     "Block reported attack sites">
-<!ENTITY  blockAttackSites.accesskey "k">
+<!ENTITY  enableSafeBrowsing.label        "Block dangerous and deceptive content">
+<!ENTITY  enableSafeBrowsing.accesskey    "B">
 
-<!ENTITY  blockWebForgeries.label     "Block reported web forgeries">
-<!ENTITY  blockWebForgeries.accesskey "B">
+<!ENTITY  blockDownloads.label            "Block dangerous downloads">
+<!ENTITY  blockDownloads.accesskey        "D">
+
+<!ENTITY  blockUncommonUnwanted.label     "Warn me about unwanted and uncommon software">
+<!ENTITY  blockUncommonUnwanted.accesskey "C">
 
 <!ENTITY  addonExceptions.label         "Exceptions…">
 <!ENTITY  addonExceptions.accesskey     "E">
 
 
 <!ENTITY  logins.label                  "Logins">
 
 <!ENTITY  rememberLogins.label          "Remember logins for sites">
--- a/mobile/android/chrome/content/aboutRights.xhtml
+++ b/mobile/android/chrome/content/aboutRights.xhtml
@@ -44,17 +44,17 @@
 
   <div id="disabling-webservices-container" style="margin-left:40px;">
     <a name="disabling-webservices"/>
     <!-- Safe Browsing cannot be disabled in Firefox Mobile; these instructions show how to do it on desktop
     <p><strong>&rights.safebrowsing-a;</strong>&rights.safebrowsing-b;</p>
     <ul>
       <li>&rights.safebrowsing-term1;</li>
       <li>&rights.safebrowsing-term2;</li>
-      <li>&rights.safebrowsing-term3;</li>
+      <li>&rights2.safebrowsing-term3;</li>
       <li>&rights.safebrowsing-term4;</li>
     </ul>
     -->
 
     <p><strong>&rights.locationawarebrowsing-a;</strong>&rights.locationawarebrowsing-b;</p>
     <ul>
       <li>&rights.locationawarebrowsing-term1a;<code>&rights.locationawarebrowsing-term1b;</code></li>
       <li>&rights.locationawarebrowsing-term2;</li>
--- a/toolkit/content/aboutRights.xhtml
+++ b/toolkit/content/aboutRights.xhtml
@@ -46,17 +46,17 @@
   <p>&rights2.webservices-a;<a href="about:rights#disabling-webservices" onclick="showDisablingServices();">&rights2.webservices-b;</a>&rights3.webservices-c;</p>
 
   <div id="disabling-webservices-container" style="margin-left:40px;">
     <a name="disabling-webservices"/>
     <p><strong>&rights.safebrowsing-a;</strong>&rights.safebrowsing-b;</p>
     <ul>
       <li>&rights.safebrowsing-term1;</li>
       <li>&rights.safebrowsing-term2;</li>
-      <li>&rights.safebrowsing-term3;</li>
+      <li>&rights2.safebrowsing-term3;</li>
       <li>&rights.safebrowsing-term4;</li>
     </ul>
 
     <p><strong>&rights.locationawarebrowsing-a;</strong>&rights.locationawarebrowsing-b;</p>
     <ul>
       <li>&rights.locationawarebrowsing-term1a;<code>&rights.locationawarebrowsing-term1b;</code></li>
       <li>&rights.locationawarebrowsing-term2;</li>
       <li>&rights.locationawarebrowsing-term3;</li>
--- a/toolkit/locales/en-US/chrome/global/aboutRights.dtd
+++ b/toolkit/locales/en-US/chrome/global/aboutRights.dtd
@@ -58,17 +58,17 @@
 <!ENTITY rights2.webservices-b "here">
 <!ENTITY rights3.webservices-c ". Other features and Services can be disabled in the application preferences.">
 
 <!-- safe browsing points for branded builds -->
 <!ENTITY rights.safebrowsing-a "SafeBrowsing: ">
 <!ENTITY rights.safebrowsing-b "Disabling the Safe Browsing feature is not recommended as it may result in you going to unsafe sites.  If you wish to disable the feature completely, follow these steps:">
 <!ENTITY rights.safebrowsing-term1 "Open the application preferences">
 <!ENTITY rights.safebrowsing-term2 "Select the Security selection">
-<!ENTITY rights.safebrowsing-term3 "Uncheck the options to &quot;&blockAttackSites.label;&quot; and &quot;&blockWebForgeries.label;&quot;">
+<!ENTITY rights2.safebrowsing-term3 "Uncheck the option to &quot;&enableSafeBrowsing.label;&quot;">
 <!ENTITY rights.safebrowsing-term4 "Safe Browsing is now disabled">
 
 <!-- location aware browsing points for branded builds -->
 <!ENTITY rights.locationawarebrowsing-a "Location Aware Browsing: ">
 <!ENTITY rights.locationawarebrowsing-b "is always opt-in.  No location information is ever sent without your permission.  If you wish to disable the feature completely, follow these steps:">
 <!ENTITY rights.locationawarebrowsing-term1a "In the URL bar, type ">
 <!ENTITY rights.locationawarebrowsing-term1b "about:config">
 <!ENTITY rights.locationawarebrowsing-term2 "Type geo.enabled">