import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,34 @@
/* -*- 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.restrictions;
/**
* Default implementation of RestrictionConfiguration interface. Used whenever no restrictions are enforced for the
* current profile.
*/
public class DefaultConfiguration implements RestrictionConfiguration {
@Override
public boolean isAllowed(Restrictable restrictable) {
if (restrictable == Restrictable.BLOCK_LIST) {
return false;
}
return true;
}
@Override
public boolean canLoadUrl(String url) {
return true;
}
@Override
public boolean isRestricted() {
return false;
}
@Override
public void update() {}
}

View file

@ -0,0 +1,83 @@
/* -*- 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.restrictions;
import android.net.Uri;
import java.util.Arrays;
import java.util.List;
/**
* RestrictionConfiguration implementation for guest profiles.
*/
public class GuestProfileConfiguration implements RestrictionConfiguration {
static List<Restrictable> DISABLED_FEATURES = Arrays.asList(
Restrictable.DOWNLOAD,
Restrictable.INSTALL_EXTENSION,
Restrictable.INSTALL_APPS,
Restrictable.BROWSE,
Restrictable.SHARE,
Restrictable.BOOKMARK,
Restrictable.ADD_CONTACT,
Restrictable.SET_IMAGE,
Restrictable.MODIFY_ACCOUNTS,
Restrictable.REMOTE_DEBUGGING,
Restrictable.IMPORT_SETTINGS,
Restrictable.BLOCK_LIST,
Restrictable.DATA_CHOICES,
Restrictable.DEFAULT_THEME
);
@SuppressWarnings("serial")
private static final List<String> BANNED_SCHEMES = Arrays.asList(
"file",
"chrome",
"resource",
"jar",
"wyciwyg"
);
private static final List<String> BANNED_URLS = Arrays.asList(
"about:config",
"about:addons"
);
@Override
public boolean isAllowed(Restrictable restrictable) {
return !DISABLED_FEATURES.contains(restrictable);
}
@Override
public boolean canLoadUrl(String url) {
// Null URLs are always permitted.
if (url == null) {
return true;
}
final Uri u = Uri.parse(url);
final String scheme = u.getScheme();
if (BANNED_SCHEMES.contains(scheme)) {
return false;
}
url = url.toLowerCase();
for (String banned : BANNED_URLS) {
if (url.startsWith(banned)) {
return false;
}
}
return true;
}
@Override
public boolean isRestricted() {
return true;
}
@Override
public void update() {}
}

View file

@ -0,0 +1,112 @@
/* -*- 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.restrictions;
import org.mozilla.gecko.R;
import android.content.Context;
import android.support.annotation.StringRes;
/**
* This is a list of things we can restrict you from doing. Some of these are reflected in Android UserManager constants.
* Others are specific to us.
* These constants should be in sync with the ones from toolkit/components/parentalcontrols/nsIParentalControlsService.idl
*/
public enum Restrictable {
DOWNLOAD(1, "downloads", 0, 0),
INSTALL_EXTENSION(
2, "no_install_extensions",
R.string.restrictable_feature_addons_installation,
R.string.restrictable_feature_addons_installation_description),
// UserManager.DISALLOW_INSTALL_APPS
INSTALL_APPS(3, "no_install_apps", 0 , 0),
BROWSE(4, "browse", 0, 0),
SHARE(5, "share", 0, 0),
BOOKMARK(6, "bookmark", 0, 0),
ADD_CONTACT(7, "add_contact", 0, 0),
SET_IMAGE(8, "set_image", 0, 0),
// UserManager.DISALLOW_MODIFY_ACCOUNTS
MODIFY_ACCOUNTS(9, "no_modify_accounts", 0, 0),
REMOTE_DEBUGGING(10, "remote_debugging", 0, 0),
IMPORT_SETTINGS(11, "import_settings", 0, 0),
PRIVATE_BROWSING(
12, "private_browsing",
R.string.restrictable_feature_private_browsing,
R.string.restrictable_feature_private_browsing_description),
DATA_CHOICES(13, "data_coices", 0, 0),
CLEAR_HISTORY(14, "clear_history",
R.string.restrictable_feature_clear_history,
R.string.restrictable_feature_clear_history_description),
MASTER_PASSWORD(15, "master_password", 0, 0),
GUEST_BROWSING(16, "guest_browsing", 0, 0),
ADVANCED_SETTINGS(17, "advanced_settings",
R.string.restrictable_feature_advanced_settings,
R.string.restrictable_feature_advanced_settings_description),
CAMERA_MICROPHONE(18, "camera_microphone",
R.string.restrictable_feature_camera_microphone,
R.string.restrictable_feature_camera_microphone_description),
BLOCK_LIST(19, "block_list",
R.string.restrictable_feature_block_list,
R.string.restrictable_feature_block_list_description),
TELEMETRY(20, "telemetry",
R.string.datareporting_telemetry_title,
R.string.datareporting_telemetry_summary),
HEALTH_REPORT(21, "health_report",
R.string.datareporting_fhr_title,
R.string.datareporting_fhr_summary2),
DEFAULT_THEME(22, "default_theme", 0, 0);
public final int id;
public final String name;
@StringRes
public final int title;
@StringRes
public final int description;
Restrictable(final int id, final String name, @StringRes int title, @StringRes int description) {
this.id = id;
this.name = name;
this.title = title;
this.description = description;
}
public String getTitle(Context context) {
if (title == 0) {
return toString();
}
return context.getResources().getString(title);
}
public String getDescription(Context context) {
if (description == 0) {
return null;
}
return context.getResources().getString(description);
}
}

View file

@ -0,0 +1,129 @@
/* -*- 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.restrictions;
import org.mozilla.gecko.AboutPages;
import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.util.ThreadUtils;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.os.UserManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class RestrictedProfileConfiguration implements RestrictionConfiguration {
// Mapping from restrictable feature to default state (on/off)
private static Map<Restrictable, Boolean> configuration = new LinkedHashMap<>();
static {
configuration.put(Restrictable.INSTALL_EXTENSION, false);
configuration.put(Restrictable.PRIVATE_BROWSING, false);
configuration.put(Restrictable.CLEAR_HISTORY, false);
configuration.put(Restrictable.MASTER_PASSWORD, false);
configuration.put(Restrictable.GUEST_BROWSING, false);
configuration.put(Restrictable.ADVANCED_SETTINGS, false);
configuration.put(Restrictable.CAMERA_MICROPHONE, false);
configuration.put(Restrictable.DATA_CHOICES, false);
configuration.put(Restrictable.BLOCK_LIST, false);
configuration.put(Restrictable.TELEMETRY, false);
configuration.put(Restrictable.HEALTH_REPORT, true);
configuration.put(Restrictable.DEFAULT_THEME, true);
}
/**
* These restrictions are hidden from the admin configuration UI.
*/
private static List<Restrictable> hiddenRestrictions = new ArrayList<>();
static {
hiddenRestrictions.add(Restrictable.MASTER_PASSWORD);
hiddenRestrictions.add(Restrictable.GUEST_BROWSING);
hiddenRestrictions.add(Restrictable.DATA_CHOICES);
hiddenRestrictions.add(Restrictable.DEFAULT_THEME);
// Hold behind Nightly flag until we have an actual block list deployed.
if (!AppConstants.NIGHTLY_BUILD) {
hiddenRestrictions.add(Restrictable.BLOCK_LIST);
}
}
/* package-private */ static boolean shouldHide(Restrictable restrictable) {
return hiddenRestrictions.contains(restrictable);
}
/* package-private */ static Map<Restrictable, Boolean> getConfiguration() {
return configuration;
}
private Context context;
public RestrictedProfileConfiguration(Context context) {
this.context = context.getApplicationContext();
}
@Override
public synchronized boolean isAllowed(Restrictable restrictable) {
// Special casing system/user restrictions
if (restrictable == Restrictable.INSTALL_APPS || restrictable == Restrictable.MODIFY_ACCOUNTS) {
return RestrictionCache.getUserRestriction(context, restrictable.name);
}
if (!RestrictionCache.hasApplicationRestriction(context, restrictable.name) && !configuration.containsKey(restrictable)) {
// Always allow features that are not in the configuration
return true;
}
return RestrictionCache.getApplicationRestriction(context, restrictable.name, configuration.get(restrictable));
}
@Override
public boolean canLoadUrl(String url) {
if (!isAllowed(Restrictable.INSTALL_EXTENSION) && AboutPages.isAboutAddons(url)) {
return false;
}
if (!isAllowed(Restrictable.PRIVATE_BROWSING) && AboutPages.isAboutPrivateBrowsing(url)) {
return false;
}
if (AboutPages.isAboutConfig(url)) {
// Always block access to about:config to prevent circumventing restrictions (Bug 1189233)
return false;
}
return true;
}
@Override
public boolean isRestricted() {
return true;
}
@Override
public synchronized void update() {
RestrictionCache.invalidate();
}
public static List<Restrictable> getVisibleRestrictions() {
final List<Restrictable> visibleList = new ArrayList<>();
for (Restrictable restrictable : configuration.keySet()) {
if (hiddenRestrictions.contains(restrictable)) {
continue;
}
visibleList.add(restrictable);
}
return visibleList;
}
}

View file

@ -0,0 +1,99 @@
/* -*- 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.restrictions;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.os.UserManager;
import org.mozilla.gecko.util.ThreadUtils;
/**
* Cache for user and application restrictions.
*/
public class RestrictionCache {
private static Bundle cachedAppRestrictions;
private static Bundle cachedUserRestrictions;
private static boolean isCacheInvalid = true;
private RestrictionCache() {}
public static synchronized boolean getUserRestriction(Context context, String restriction) {
updateCacheIfNeeded(context);
return cachedUserRestrictions.getBoolean(restriction);
}
public static synchronized boolean hasApplicationRestriction(Context context, String restriction) {
updateCacheIfNeeded(context);
return cachedAppRestrictions.containsKey(restriction);
}
public static synchronized boolean getApplicationRestriction(Context context, String restriction, boolean defaultValue) {
updateCacheIfNeeded(context);
return cachedAppRestrictions.getBoolean(restriction, defaultValue);
}
public static synchronized boolean hasApplicationRestrictions(Context context) {
updateCacheIfNeeded(context);
return !cachedAppRestrictions.isEmpty();
}
public static synchronized void invalidate() {
isCacheInvalid = true;
}
private static void updateCacheIfNeeded(Context context) {
// If we are not on the UI thread then we can just go ahead and read the values (Bug 1189347).
// Otherwise we read from the cache to avoid blocking the UI thread. If the cache is invalid
// then we hazard the consequences and just do the read.
if (isCacheInvalid || !ThreadUtils.isOnUiThread()) {
readRestrictions(context);
isCacheInvalid = false;
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private static void readRestrictions(Context context) {
final UserManager mgr = (UserManager) context.getSystemService(Context.USER_SERVICE);
// If we do not have anything in the cache yet then this read might happen on the UI thread (Bug 1189347).
final StrictMode.ThreadPolicy policy = StrictMode.allowThreadDiskReads();
try {
Bundle appRestrictions = mgr.getApplicationRestrictions(context.getPackageName());
migrateRestrictionsIfNeeded(appRestrictions);
cachedAppRestrictions = appRestrictions;
cachedUserRestrictions = mgr.getUserRestrictions(); // Always implies disk read
} finally {
StrictMode.setThreadPolicy(policy);
}
}
/**
* This method migrates the old set of DISALLOW_ restrictions to the new restrictable feature ones (Bug 1189336).
*/
/* package-private */ static void migrateRestrictionsIfNeeded(Bundle bundle) {
if (!bundle.containsKey(Restrictable.INSTALL_EXTENSION.name) && bundle.containsKey("no_install_extensions")) {
bundle.putBoolean(Restrictable.INSTALL_EXTENSION.name, !bundle.getBoolean("no_install_extensions"));
}
if (!bundle.containsKey(Restrictable.PRIVATE_BROWSING.name) && bundle.containsKey("no_private_browsing")) {
bundle.putBoolean(Restrictable.PRIVATE_BROWSING.name, !bundle.getBoolean("no_private_browsing"));
}
if (!bundle.containsKey(Restrictable.CLEAR_HISTORY.name) && bundle.containsKey("no_clear_history")) {
bundle.putBoolean(Restrictable.CLEAR_HISTORY.name, !bundle.getBoolean("no_clear_history"));
}
if (!bundle.containsKey(Restrictable.ADVANCED_SETTINGS.name) && bundle.containsKey("no_advanced_settings")) {
bundle.putBoolean(Restrictable.ADVANCED_SETTINGS.name, !bundle.getBoolean("no_advanced_settings"));
}
}
}

View file

@ -0,0 +1,31 @@
/* -*- 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.restrictions;
/**
* Interface for classes that Restrictions will delegate to for making decisions.
*/
public interface RestrictionConfiguration {
/**
* Is the user allowed to perform this action?
*/
boolean isAllowed(Restrictable restrictable);
/**
* Is the user allowed to load the given URL?
*/
boolean canLoadUrl(String url);
/**
* Is this user restricted in any way?
*/
boolean isRestricted();
/**
* Update restrictions if needed.
*/
void update();
}

View file

@ -0,0 +1,84 @@
/* -*- 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.restrictions;
import org.mozilla.gecko.AppConstants;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.RestrictionEntry;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.Map;
/**
* Broadcast receiver providing supported restrictions to the system.
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class RestrictionProvider extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {
if (AppConstants.Versions.preJBMR2) {
// This broadcast does not make any sense prior to Jelly Bean MR2.
return;
}
final PendingResult result = goAsync();
new Thread() {
@Override
public void run() {
final Bundle oldRestrictions = intent.getBundleExtra(Intent.EXTRA_RESTRICTIONS_BUNDLE);
RestrictionCache.migrateRestrictionsIfNeeded(oldRestrictions);
final Bundle extras = new Bundle();
ArrayList<RestrictionEntry> entries = initRestrictions(context, oldRestrictions);
extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS_LIST, entries);
result.setResult(Activity.RESULT_OK, null, extras);
result.finish();
}
}.start();
}
private ArrayList<RestrictionEntry> initRestrictions(Context context, Bundle oldRestrictions) {
ArrayList<RestrictionEntry> entries = new ArrayList<RestrictionEntry>();
final Map<Restrictable, Boolean> configuration = RestrictedProfileConfiguration.getConfiguration();
for (Restrictable restrictable : configuration.keySet()) {
if (RestrictedProfileConfiguration.shouldHide(restrictable)) {
continue;
}
RestrictionEntry entry = createRestrictionEntryWithDefaultValue(context, restrictable,
oldRestrictions.getBoolean(restrictable.name, configuration.get(restrictable)));
entries.add(entry);
}
return entries;
}
private RestrictionEntry createRestrictionEntryWithDefaultValue(Context context, Restrictable restrictable, boolean defaultValue) {
RestrictionEntry entry = new RestrictionEntry(restrictable.name, defaultValue);
entry.setTitle(restrictable.getTitle(context));
final String description = restrictable.getDescription(context);
if (!TextUtils.isEmpty(description)) {
entry.setDescription(description);
}
return entry;
}
}

View file

@ -0,0 +1,127 @@
/* -*- 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.restrictions;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.GeckoProfile;
import org.mozilla.gecko.annotation.RobocopTarget;
import org.mozilla.gecko.annotation.WrapForJNI;
@RobocopTarget
public class Restrictions {
private static final String LOGTAG = "GeckoRestrictedProfiles";
private static RestrictionConfiguration configuration;
private static RestrictionConfiguration getConfiguration(Context context) {
if (configuration == null) {
configuration = createConfiguration(context);
}
return configuration;
}
public static synchronized RestrictionConfiguration createConfiguration(Context context) {
if (configuration != null) {
// This method is synchronized and another thread might already have created the configuration.
return configuration;
}
if (isGuestProfile(context)) {
return new GuestProfileConfiguration();
} else if (isRestrictedProfile(context)) {
return new RestrictedProfileConfiguration(context);
} else {
return new DefaultConfiguration();
}
}
private static boolean isGuestProfile(Context context) {
if (configuration != null) {
return configuration instanceof GuestProfileConfiguration;
}
GeckoAppShell.GeckoInterface geckoInterface = GeckoAppShell.getGeckoInterface();
if (geckoInterface != null) {
return geckoInterface.getProfile().inGuestMode();
}
return GeckoProfile.get(context).inGuestMode();
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public static boolean isRestrictedProfile(Context context) {
if (configuration != null) {
return configuration instanceof RestrictedProfileConfiguration;
}
if (Versions.preJBMR2) {
// Early versions don't support restrictions at all
return false;
}
// The user is on a restricted profile if, and only if, we injected application restrictions during account setup.
return RestrictionCache.hasApplicationRestrictions(context);
}
public static void update(Context context) {
getConfiguration(context).update();
}
private static Restrictable geckoActionToRestriction(int action) {
for (Restrictable rest : Restrictable.values()) {
if (rest.id == action) {
return rest;
}
}
throw new IllegalArgumentException("Unknown action " + action);
}
private static boolean canLoadUrl(final Context context, final String url) {
return getConfiguration(context).canLoadUrl(url);
}
@WrapForJNI(calledFrom = "gecko")
public static boolean isUserRestricted() {
return isUserRestricted(GeckoAppShell.getApplicationContext());
}
public static boolean isUserRestricted(final Context context) {
return getConfiguration(context).isRestricted();
}
public static boolean isAllowed(final Context context, final Restrictable restrictable) {
return getConfiguration(context).isAllowed(restrictable);
}
@WrapForJNI(calledFrom = "gecko")
public static boolean isAllowed(int action, String url) {
final Restrictable restrictable;
try {
restrictable = 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;
}
final Context context = GeckoAppShell.getApplicationContext();
if (Restrictable.BROWSE == restrictable) {
return canLoadUrl(context, url);
} else {
return isAllowed(context, restrictable);
}
}
}