Bug 1125312 - Bug 1125313 - Restriced profiles: Hide "Tools" and "Report Site Issue" menu items. r=ally
authorSebastian Kaspari <s.kaspari@gmail.com>
Mon, 06 Jul 2015 17:08:06 +0200
changeset 251874 64d240b53e52a6939a8521537dee7ab01fd2f855
parent 251873 f6fed0c761ab5d409b20ee0f9f8dce3a0a58e878
child 251875 741bb6d3448bdf093be282481a8d3a223076bdd7
push id29015
push userryanvm@gmail.com
push dateWed, 08 Jul 2015 18:21:41 +0000
treeherdermozilla-central@2469f45c4770 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersally
bugs1125312, 1125313
milestone42.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 1125312 - Bug 1125313 - Restriced profiles: Hide "Tools" and "Report Site Issue" menu items. r=ally
mobile/android/base/BrowserApp.java
mobile/android/base/RestrictedProfiles.java
mobile/android/chrome/content/WebcompatReporter.js
toolkit/components/parentalcontrols/nsIParentalControlsService.idl
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -3324,16 +3324,20 @@ public class BrowserApp extends GeckoApp
 
                             shareIntent.putExtra("share_screenshot_uri", Uri.parse(outFile.getPath()));
                         }
                     }
                 }
             }
         }
 
+        // Hide tools menu if restriction is active
+        final boolean toolsVisible = RestrictedProfiles.isAllowed(this, RestrictedProfiles.Restriction.DISALLOW_TOOLS_MENU);
+        MenuUtils.safeSetVisible(aMenu, R.id.tools, toolsVisible);
+
         // Disable save as PDF for about:home and xul pages.
         saveAsPDF.setEnabled(!(isAboutHome(tab) ||
                                tab.getContentType().equals("application/vnd.mozilla.xul+xml") ||
                                tab.getContentType().startsWith("video/")));
 
         // Disable find in page for about:home, since it won't work on Java content.
         findInPage.setEnabled(!isAboutHome(tab));
 
--- a/mobile/android/base/RestrictedProfiles.java
+++ b/mobile/android/base/RestrictedProfiles.java
@@ -1,16 +1,17 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
  * 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/. */
 
 package org.mozilla.gecko;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.mozilla.gecko.AppConstants.Versions;
 import org.mozilla.gecko.mozglue.RobocopTarget;
 import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
 import android.annotation.TargetApi;
@@ -69,38 +70,60 @@ public class RestrictedProfiles {
         DISALLOW_INSTALL_APPS(3, "no_install_apps"), // UserManager.DISALLOW_INSTALL_APPS
         DISALLOW_BROWSE_FILES(4, "no_browse_files"),
         DISALLOW_SHARE(5, "no_share"),
         DISALLOW_BOOKMARK(6, "no_bookmark"),
         DISALLOW_ADD_CONTACTS(7, "no_add_contacts"),
         DISALLOW_SET_IMAGE(8, "no_set_image"),
         DISALLOW_MODIFY_ACCOUNTS(9, "no_modify_accounts"), // UserManager.DISALLOW_MODIFY_ACCOUNTS
         DISALLOW_REMOTE_DEBUGGING(10, "no_remote_debugging"),
-        DISALLOW_IMPORT_SETTINGS(11, "no_import_settings");
+        DISALLOW_IMPORT_SETTINGS(11, "no_import_settings"),
+        DISALLOW_TOOLS_MENU(12, "no_tools_menu"),
+        DISALLOW_REPORT_SITE_ISSUE(13, "no_report_site_issue");
 
         public final int id;
         public final String name;
 
         private Restriction(final int id, final String name) {
             this.id = id;
             this.name = name;
         }
     }
 
+    private static List<Restriction> restrictionsOfGuestProfile = Arrays.asList(
+        Restriction.DISALLOW_DOWNLOADS,
+        Restriction.DISALLOW_INSTALL_EXTENSION,
+        Restriction.DISALLOW_INSTALL_APPS,
+        Restriction.DISALLOW_BROWSE_FILES,
+        Restriction.DISALLOW_SHARE,
+        Restriction.DISALLOW_BOOKMARK,
+        Restriction.DISALLOW_ADD_CONTACTS,
+        Restriction.DISALLOW_SET_IMAGE,
+        Restriction.DISALLOW_MODIFY_ACCOUNTS,
+        Restriction.DISALLOW_REMOTE_DEBUGGING,
+        Restriction.DISALLOW_IMPORT_SETTINGS
+    );
+
+    // Restricted profiles will automatically have these restrictions by default
+    private static List<Restriction> defaultRestrictionsOfRestrictedProfiles = Arrays.asList(
+        Restriction.DISALLOW_TOOLS_MENU,
+        Restriction.DISALLOW_REPORT_SITE_ISSUE
+    );
+
     private static Restriction geckoActionToRestriction(int action) {
         for (Restriction rest : Restriction.values()) {
             if (rest.id == action) {
                 return rest;
             }
         }
 
         throw new IllegalArgumentException("Unknown action " + action);
     }
 
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
     private static Bundle getRestrictions(final Context context) {
         final UserManager mgr = (UserManager) context.getSystemService(Context.USER_SERVICE);
         return mgr.getUserRestrictions();
     }
 
     /**
      * This method does the system version check for you.
      *
@@ -112,16 +135,21 @@ public class RestrictedProfiles {
      */
     private static boolean getRestriction(final Context context, final String name) {
         // Early versions don't support restrictions at all,
         // so no action can be restricted.
         if (Versions.preJBMR2) {
             return false;
         }
 
+        // Hardcoded restrictions. Make restrictions configurable and read from UserManager (Bug 1180653)
+        if (isUserRestricted(context) && defaultRestrictionsOfRestrictedProfiles.contains(Restriction.DISALLOW_TOOLS_MENU)) {
+            return true;
+        }
+
         return getRestrictions(context).getBoolean(name, false);
     }
 
     private static boolean canLoadUrl(final Context context, final String url) {
         // Null URLs are always permitted.
         if (url == null) {
             return true;
         }
@@ -166,17 +194,17 @@ public class RestrictedProfiles {
         if (Versions.preJBMR2) {
             return false;
         }
 
         return !getRestrictions(context).isEmpty();
     }
 
     public static boolean isAllowed(final Context context, final Restriction action) {
-        return isAllowed(context, action.id, null);
+        return isAllowed(context, action, null);
     }
 
     @WrapElementForJNI
     public static boolean isAllowed(int action, String url) {
         return isAllowed(GeckoAppShell.getContext(), action, url);
     }
 
     private static boolean isAllowed(final Context context, int action, String url) {
@@ -185,23 +213,26 @@ public class RestrictedProfiles {
             restriction = geckoActionToRestriction(action);
         } catch (IllegalArgumentException ex) {
             // Unknown actions represent a coding error, so we
             // refuse the action and log.
             Log.e(LOGTAG, "Unknown action " + action + "; check calling code.");
             return false;
         }
 
+        return isAllowed(context, restriction, url);
+    }
+
+    private static boolean isAllowed(final Context context, final Restriction restriction, String url) {
         if (getInGuest()) {
             if (Restriction.DISALLOW_BROWSE_FILES == restriction) {
                 return canLoadUrl(context, url);
             }
 
-            // Guest users can't do anything.
-            return false;
+            return !restrictionsOfGuestProfile.contains(restriction);
         }
 
         // NOTE: Restrictions hold the opposite intention, so we need to flip it.
         return !getRestriction(context, restriction.name);
     }
 
     @WrapElementForJNI
     public static String getUserRestrictions() {
--- a/mobile/android/chrome/content/WebcompatReporter.js
+++ b/mobile/android/chrome/content/WebcompatReporter.js
@@ -2,25 +2,34 @@
  * 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/. */
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/ctypes.jsm");
+Cu.import("resource://gre/modules/JNI.jsm");
 
 var WebcompatReporter = {
   menuItem: null,
   menuItemEnabled: null,
   init: function() {
     Services.obs.addObserver(this, "DesktopMode:Change", false);
     Services.obs.addObserver(this, "chrome-document-global-created", false);
     Services.obs.addObserver(this, "content-document-global-created", false);
-    this.addMenuItem();
+
+    let visible = true;
+    if ("@mozilla.org/parental-controls-service;1" in Cc) {
+      let pc = Cc["@mozilla.org/parental-controls-service;1"].createInstance(Ci.nsIParentalControlsService);
+      visible = pc.isAllowed(Ci.nsIParentalControlsService.REPORT_SITE_ISSUE);
+    }
+
+    this.addMenuItem(visible);
   },
 
   observe: function(subject, topic, data) {
     if (topic == "content-document-global-created" || topic == "chrome-document-global-created") {
       let win = subject;
       let currentURI = win.document.documentURI;
 
       // Ignore non top-level documents
@@ -40,24 +49,25 @@ var WebcompatReporter = {
       let tab = BrowserApp.getTabForId(args.tabId);
       let currentURI = tab.browser.currentURI.spec;
       if (args.desktopMode && this.isReportableUrl(currentURI)) {
         this.reportDesktopModePrompt();
       }
     }
   },
 
-  addMenuItem: function() {
+  addMenuItem: function(visible) {
     this.menuItem = NativeWindow.menu.add({
       name: this.strings.GetStringFromName("webcompat.menu.name"),
       callback: () => {
         let currentURI = BrowserApp.selectedTab.browser.currentURI.spec;
         this.reportIssue(currentURI);
       },
       enabled: false,
+      visible: visible,
     });
   },
 
   isReportableUrl: function(url) {
     return url && !(url.startsWith("about") ||
                     url.startsWith("chrome") ||
                     url.startsWith("file") ||
                     url.startsWith("resource"));
--- a/toolkit/components/parentalcontrols/nsIParentalControlsService.idl
+++ b/toolkit/components/parentalcontrols/nsIParentalControlsService.idl
@@ -6,38 +6,40 @@
 
 #include "nsISupports.idl"
 
 interface nsIURI;
 interface nsIFile;
 interface nsIInterfaceRequestor;
 interface nsIArray;
 
-[scriptable, uuid(e7bcc22c-e9fc-4e7d-88b9-7482399b322d)]
+[scriptable, uuid(406808a5-2838-4c29-9e39-5bfb885c89bf)]
 interface nsIParentalControlsService : nsISupports
 {
   /**
    * Action types that can be blocked for users.
    */
   const short DOWNLOAD = 1; // Downloading files
   const short INSTALL_EXTENSION = 2; // Installing extensions
   const short INSTALL_APP = 3; // Installing webapps
   const short VISIT_FILE_URLS = 4; // Opening file:/// urls
   const short SHARE = 5; // Sharing
   const short BOOKMARK = 6; // Creating bookmarks
   const short ADD_CONTACT = 7; // Add contacts to the system database
   const short SET_IMAGE = 8; // Setting images as wall paper
   const short MODIFY_ACCOUNTS = 9; // Modifying system accounts
   const short REMOTE_DEBUGGING = 10; // Remote debugging
   const short IMPORT_SETTINGS = 11; // Importing settings from other apps
+  const short TOOLS_MENU = 12; // Hide tools menu entry
+  const short REPORT_SITE_ISSUE = 13; // Hide "Report Site Issue" menu entry
 
   /**
    * @returns true if the current user account has parental controls
    * restrictions enabled.
-   */ 
+   */
   readonly attribute boolean parentalControlsEnabled;
 
   /**
    * @returns true if the current user account parental controls
    * restrictions include the blocking of all file downloads.
    */ 
   readonly attribute boolean blockFileDownloadsEnabled;