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 251873 64d240b53e52a6939a8521537dee7ab01fd2f855
parent 251872 f6fed0c761ab5d409b20ee0f9f8dce3a0a58e878
child 251874 741bb6d3448bdf093be282481a8d3a223076bdd7
push id13902
push users.kaspari@gmail.com
push dateWed, 08 Jul 2015 11:59:20 +0000
treeherderfx-team@64d240b53e52 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersally
bugs1125312, 1125313
milestone42.0a1
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;