mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge m-c to fx-team; a=merge
This commit is contained in:
commit
e16550584f
@ -61,6 +61,10 @@ input[type=button] {
|
||||
right: auto;
|
||||
}
|
||||
|
||||
#newtab-scrollbox[page-disabled] #newtab-intro-what {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#newtab-intro-panel {
|
||||
color: #6a7b86;
|
||||
font-size: 15px;
|
||||
|
@ -391,7 +391,8 @@ loop.conversation = (function(mozL10n) {
|
||||
if (progressData.state !== "terminated")
|
||||
return;
|
||||
|
||||
if (progressData.reason === "cancel") {
|
||||
if (progressData.reason === "cancel" ||
|
||||
progressData.reason === "closed") {
|
||||
this._abortIncomingCall();
|
||||
return;
|
||||
}
|
||||
|
@ -391,7 +391,8 @@ loop.conversation = (function(mozL10n) {
|
||||
if (progressData.state !== "terminated")
|
||||
return;
|
||||
|
||||
if (progressData.reason === "cancel") {
|
||||
if (progressData.reason === "cancel" ||
|
||||
progressData.reason === "closed") {
|
||||
this._abortIncomingCall();
|
||||
return;
|
||||
}
|
||||
|
@ -406,6 +406,46 @@ describe("loop.conversation", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("progress - terminated - closed", function() {
|
||||
it("should stop alerting", function(done) {
|
||||
promise.then(function() {
|
||||
icView._websocket.trigger("progress", {
|
||||
state: "terminated",
|
||||
reason: "closed"
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(navigator.mozLoop.stopAlerting);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should close the websocket", function(done) {
|
||||
promise.then(function() {
|
||||
icView._websocket.trigger("progress", {
|
||||
state: "terminated",
|
||||
reason: "closed"
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(icView._websocket.close);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should close the window", function(done) {
|
||||
promise.then(function() {
|
||||
icView._websocket.trigger("progress", {
|
||||
state: "terminated",
|
||||
reason: "closed"
|
||||
});
|
||||
|
||||
sandbox.clock.tick(1);
|
||||
|
||||
sinon.assert.calledOnce(window.close);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("progress - terminated - timeout (previousState = alerting)", function() {
|
||||
it("should stop alerting", function(done) {
|
||||
promise.then(function() {
|
||||
|
@ -1,45 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["RevivableWindows"];
|
||||
|
||||
// List of closed windows that we can revive when closing
|
||||
// windows in succession until the browser quits.
|
||||
let closedWindows = [];
|
||||
|
||||
/**
|
||||
* This module keeps track of closed windows that are revivable. On Windows
|
||||
* and Linux we can revive windows before saving to disk - i.e. moving them
|
||||
* from state._closedWindows[] to state.windows[] so that they're opened
|
||||
* automatically on next startup. This feature lets us properly support
|
||||
* closing windows in succession until the browser quits.
|
||||
*
|
||||
* The length of the list is not capped by max_undo_windows unlike
|
||||
* state._closedWindows[].
|
||||
*/
|
||||
this.RevivableWindows = Object.freeze({
|
||||
// Returns whether there are windows to revive.
|
||||
get isEmpty() {
|
||||
return closedWindows.length == 0;
|
||||
},
|
||||
|
||||
// Add a window to the list.
|
||||
add(winState) {
|
||||
#ifndef XP_MACOSX
|
||||
closedWindows.push(winState);
|
||||
#endif
|
||||
},
|
||||
|
||||
// Get the list of revivable windows.
|
||||
get() {
|
||||
return [...closedWindows];
|
||||
},
|
||||
|
||||
// Clear the list of revivable windows.
|
||||
clear() {
|
||||
closedWindows.length = 0;
|
||||
}
|
||||
});
|
@ -19,8 +19,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "console",
|
||||
"resource://gre/modules/devtools/Console.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivacyFilter",
|
||||
"resource:///modules/sessionstore/PrivacyFilter.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RevivableWindows",
|
||||
"resource:///modules/sessionstore/RevivableWindows.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
|
||||
"resource:///modules/sessionstore/SessionStore.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SessionFile",
|
||||
@ -207,24 +205,23 @@ let SessionSaverInternal = {
|
||||
delete state.deferredInitialState;
|
||||
}
|
||||
|
||||
// We want to revive closed windows that have been closed in succession
|
||||
// without any user action in between closing those. This happens here in
|
||||
// the SessionSaver because we only want to revive when saving to disk.
|
||||
// On Mac OS X this list will always be empty.
|
||||
let windowsToRevive = RevivableWindows.get();
|
||||
state.windows.unshift(...windowsToRevive);
|
||||
let revivedWindows = state._closedWindows.splice(0, windowsToRevive.length);
|
||||
#ifdef DEBUG
|
||||
// Check that the windows to revive equal the windows
|
||||
// that we removed from the list of closed windows.
|
||||
let match = revivedWindows.every((win, idx) => {
|
||||
return win == windowsToRevive[windowsToRevive.length - 1 - idx];
|
||||
});
|
||||
#ifndef XP_MACOSX
|
||||
// We want to restore closed windows that are marked with _shouldRestore.
|
||||
// We're doing this here because we want to control this only when saving
|
||||
// the file.
|
||||
while (state._closedWindows.length) {
|
||||
let i = state._closedWindows.length - 1;
|
||||
|
||||
if (!match) {
|
||||
throw new Error("SessionStore: revived windows didn't match closed windows");
|
||||
if (!state._closedWindows[i]._shouldRestore) {
|
||||
// We only need to go until _shouldRestore
|
||||
// is falsy since we're going in reverse.
|
||||
break;
|
||||
}
|
||||
|
||||
delete state._closedWindows[i]._shouldRestore;
|
||||
state.windows.unshift(state._closedWindows.pop());
|
||||
}
|
||||
#endif DEBUG
|
||||
#endif
|
||||
|
||||
stopWatchFinish("COLLECT_DATA_MS", "COLLECT_DATA_LONGEST_OP_MS");
|
||||
return this._writeState(state);
|
||||
|
@ -107,8 +107,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "GlobalState",
|
||||
"resource:///modules/sessionstore/GlobalState.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivacyFilter",
|
||||
"resource:///modules/sessionstore/PrivacyFilter.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RevivableWindows",
|
||||
"resource:///modules/sessionstore/RevivableWindows.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RunState",
|
||||
"resource:///modules/sessionstore/RunState.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ScratchpadManager",
|
||||
@ -703,9 +701,7 @@ let SessionStoreInternal = {
|
||||
this.saveStateDelayed(win);
|
||||
break;
|
||||
}
|
||||
|
||||
// Any event handled here indicates a user action.
|
||||
RevivableWindows.clear();
|
||||
this._clearRestoringWindows();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1017,6 +1013,12 @@ let SessionStoreInternal = {
|
||||
SessionCookies.update([winData]);
|
||||
}
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
// Until we decide otherwise elsewhere, this window is part of a series
|
||||
// of closing windows to quit.
|
||||
winData._shouldRestore = true;
|
||||
#endif
|
||||
|
||||
// Store the window's close date to figure out when each individual tab
|
||||
// was closed. This timestamp should allow re-arranging data based on how
|
||||
// recently something was closed.
|
||||
@ -1037,8 +1039,9 @@ let SessionStoreInternal = {
|
||||
// with tabs we deem not worth saving then we might end up with a
|
||||
// random closed or even a pop-up window re-opened. To prevent that
|
||||
// we explicitly allow saving an "empty" window state.
|
||||
let numOpenWindows = Object.keys(this._windows).length;
|
||||
let isLastWindow = numOpenWindows == 1 && RevivableWindows.isEmpty;
|
||||
let isLastWindow =
|
||||
Object.keys(this._windows).length == 1 &&
|
||||
!this._closedWindows.some(win => win._shouldRestore || false);
|
||||
|
||||
if (hasSaveableTabs || isLastWindow) {
|
||||
// we don't want to save the busy state
|
||||
@ -1047,10 +1050,6 @@ let SessionStoreInternal = {
|
||||
this._closedWindows.unshift(winData);
|
||||
this._capClosedWindows();
|
||||
}
|
||||
|
||||
// Until we decide otherwise elsewhere, this window
|
||||
// is part of a series of closing windows to quit.
|
||||
RevivableWindows.add(winData);
|
||||
}
|
||||
|
||||
// clear this window from the list
|
||||
@ -1156,11 +1155,8 @@ let SessionStoreInternal = {
|
||||
delete this._windows[ix];
|
||||
}
|
||||
}
|
||||
|
||||
// also clear all data about closed windows
|
||||
this._closedWindows = [];
|
||||
RevivableWindows.clear();
|
||||
|
||||
// give the tabbrowsers a chance to clear their histories first
|
||||
var win = this._getMostRecentBrowserWindow();
|
||||
if (win) {
|
||||
@ -1168,6 +1164,8 @@ let SessionStoreInternal = {
|
||||
} else if (RunState.isRunning) {
|
||||
SessionSaver.run();
|
||||
}
|
||||
|
||||
this._clearRestoringWindows();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1221,12 +1219,11 @@ let SessionStoreInternal = {
|
||||
}
|
||||
}
|
||||
|
||||
// Purging domain data indicates a user action.
|
||||
RevivableWindows.clear();
|
||||
|
||||
if (RunState.isRunning) {
|
||||
SessionSaver.run();
|
||||
}
|
||||
|
||||
this._clearRestoringWindows();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -3349,6 +3346,21 @@ let SessionStoreInternal = {
|
||||
this._closedWindows.splice(spliceTo, this._closedWindows.length);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clears the set of windows that are "resurrected" before writing to disk to
|
||||
* make closing windows one after the other until shutdown work as expected.
|
||||
*
|
||||
* This function should only be called when we are sure that there has been
|
||||
* a user action that indicates the browser is actively being used and all
|
||||
* windows that have been closed before are not part of a series of closing
|
||||
* windows.
|
||||
*/
|
||||
_clearRestoringWindows: function ssi_clearRestoringWindows() {
|
||||
for (let i = 0; i < this._closedWindows.length; i++) {
|
||||
delete this._closedWindows[i]._shouldRestore;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Reset state to prepare for a new session state to be restored.
|
||||
*/
|
||||
|
@ -46,7 +46,6 @@ EXTRA_JS_MODULES.sessionstore = [
|
||||
]
|
||||
|
||||
EXTRA_PP_JS_MODULES.sessionstore += [
|
||||
'RevivableWindows.jsm',
|
||||
'SessionSaver.jsm',
|
||||
'SessionStore.jsm',
|
||||
]
|
||||
|
@ -81,7 +81,6 @@ skip-if = buildapp == 'mulet'
|
||||
[browser_merge_closed_tabs.js]
|
||||
[browser_pageStyle.js]
|
||||
[browser_privatetabs.js]
|
||||
[browser_revive_windows.js]
|
||||
[browser_scrollPositions.js]
|
||||
[browser_sessionHistory.js]
|
||||
skip-if = e10s
|
||||
|
@ -1,160 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const IS_MAC = ("nsILocalFileMac" in Ci);
|
||||
const URL_PREFIX = "about:mozilla?t=browser_revive_windows&r=";
|
||||
const PREF_MAX_UNDO = "browser.sessionstore.max_windows_undo";
|
||||
|
||||
const URL_MAIN_WINDOW = URL_PREFIX + Math.random();
|
||||
const URL_ADD_WINDOW1 = URL_PREFIX + Math.random();
|
||||
const URL_ADD_WINDOW2 = URL_PREFIX + Math.random();
|
||||
const URL_CLOSED_WINDOW = URL_PREFIX + Math.random();
|
||||
|
||||
add_task(function* setup() {
|
||||
registerCleanupFunction(() => Services.prefs.clearUserPref(PREF_MAX_UNDO));
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensure that when closing windows in succession until the browser
|
||||
* quits we are able to revive more windows than we keep around for the
|
||||
* "Undo Close Window" feature.
|
||||
*/
|
||||
add_task(function* test_revive_windows() {
|
||||
// We can restore a single window max.
|
||||
Services.prefs.setIntPref(PREF_MAX_UNDO, 1);
|
||||
|
||||
// Clear list of closed windows.
|
||||
forgetClosedWindows();
|
||||
|
||||
let windows = [];
|
||||
|
||||
// Create three windows.
|
||||
for (let i = 0; i < 3; i++) {
|
||||
let win = yield promiseNewWindow();
|
||||
windows.push(win);
|
||||
|
||||
let tab = win.gBrowser.addTab("about:mozilla");
|
||||
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||
}
|
||||
|
||||
// Create a private window.
|
||||
// This window must not be revived.
|
||||
{
|
||||
let win = yield promiseNewWindow({private: true});
|
||||
windows.push(win);
|
||||
|
||||
let tab = win.gBrowser.addTab("about:mozilla");
|
||||
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||
}
|
||||
|
||||
// Close all windows.
|
||||
for (let win of windows) {
|
||||
yield promiseWindowClosed(win);
|
||||
}
|
||||
|
||||
is(ss.getClosedWindowCount(), 1, "one window restorable");
|
||||
|
||||
// Save to disk and read.
|
||||
let state = JSON.parse(yield promiseRecoveryFileContents());
|
||||
|
||||
// Check number of windows.
|
||||
if (IS_MAC) {
|
||||
is(state.windows.length, 1, "one open window");
|
||||
is(state._closedWindows.length, 1, "one closed window");
|
||||
} else {
|
||||
is(state.windows.length, 4, "four open windows");
|
||||
is(state._closedWindows.length, 0, "closed windows");
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* This test ensures that when closing windows one after the other until the
|
||||
* browser shuts down (on Windows and Linux) we revive closed windows in the
|
||||
* right order.
|
||||
*/
|
||||
add_task(function* test_revive_windows_order() {
|
||||
// We can restore up to three windows max.
|
||||
Services.prefs.setIntPref(PREF_MAX_UNDO, 3);
|
||||
|
||||
// Clear list of closed windows.
|
||||
forgetClosedWindows();
|
||||
|
||||
let tab = gBrowser.addTab(URL_MAIN_WINDOW);
|
||||
yield promiseBrowserLoaded(tab.linkedBrowser);
|
||||
TabState.flush(tab.linkedBrowser);
|
||||
registerCleanupFunction(() => gBrowser.removeTab(tab));
|
||||
|
||||
let win0 = yield promiseNewWindow();
|
||||
let tab0 = win0.gBrowser.addTab(URL_CLOSED_WINDOW);
|
||||
yield promiseBrowserLoaded(tab0.linkedBrowser);
|
||||
|
||||
yield promiseWindowClosed(win0);
|
||||
let data = ss.getClosedWindowData();
|
||||
ok(data.contains(URL_CLOSED_WINDOW), "window is restorable");
|
||||
|
||||
let win1 = yield promiseNewWindow();
|
||||
let tab1 = win1.gBrowser.addTab(URL_ADD_WINDOW1);
|
||||
yield promiseBrowserLoaded(tab1.linkedBrowser);
|
||||
|
||||
let win2 = yield promiseNewWindow();
|
||||
let tab2 = win2.gBrowser.addTab(URL_ADD_WINDOW2);
|
||||
yield promiseBrowserLoaded(tab2.linkedBrowser);
|
||||
|
||||
// Close both windows so that |win1| will be opened first and would be
|
||||
// behind |win2| that was closed later.
|
||||
yield promiseWindowClosed(win1);
|
||||
yield promiseWindowClosed(win2);
|
||||
|
||||
// Repeat the checks once.
|
||||
for (let i = 0; i < 2; i++) {
|
||||
info(`checking window data, iteration #${i}`);
|
||||
let contents = yield promiseRecoveryFileContents();
|
||||
let {windows, _closedWindows: closedWindows} = JSON.parse(contents);
|
||||
|
||||
if (IS_MAC) {
|
||||
// Check number of windows.
|
||||
is(windows.length, 1, "one open window");
|
||||
is(closedWindows.length, 3, "three closed windows");
|
||||
|
||||
// Check open window.
|
||||
ok(JSON.stringify(windows).contains(URL_MAIN_WINDOW),
|
||||
"open window is correct");
|
||||
|
||||
// Check closed windows.
|
||||
ok(JSON.stringify(closedWindows[0]).contains(URL_ADD_WINDOW2),
|
||||
"correct first additional window");
|
||||
ok(JSON.stringify(closedWindows[1]).contains(URL_ADD_WINDOW1),
|
||||
"correct second additional window");
|
||||
ok(JSON.stringify(closedWindows[2]).contains(URL_CLOSED_WINDOW),
|
||||
"correct main window");
|
||||
} else {
|
||||
// Check number of windows.
|
||||
is(windows.length, 3, "three open windows");
|
||||
is(closedWindows.length, 1, "one closed window");
|
||||
|
||||
// Check closed window.
|
||||
ok(JSON.stringify(closedWindows).contains(URL_CLOSED_WINDOW),
|
||||
"closed window is correct");
|
||||
|
||||
// Check that windows are in the right order.
|
||||
ok(JSON.stringify(windows[0]).contains(URL_ADD_WINDOW1),
|
||||
"correct first additional window");
|
||||
ok(JSON.stringify(windows[1]).contains(URL_ADD_WINDOW2),
|
||||
"correct second additional window");
|
||||
ok(JSON.stringify(windows[2]).contains(URL_MAIN_WINDOW),
|
||||
"correct main window");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function promiseNewWindow(opts = {private: false}) {
|
||||
return new Promise(resolve => whenNewWindowLoaded(opts, resolve));
|
||||
}
|
||||
|
||||
function forgetClosedWindows() {
|
||||
while (ss.getClosedWindowCount()) {
|
||||
ss.forgetClosedWindow(0);
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ skip-if = true
|
||||
[browser_layoutview_update-after-navigation.js]
|
||||
[browser_layoutview_update-after-reload.js]
|
||||
[browser_layoutview_update-in-iframes.js]
|
||||
skip-if = true # Bug 1020038 layout-view updates for iframe elements changes
|
||||
[browser_editablemodel.js]
|
||||
# [browser_editablemodel_allproperties.js]
|
||||
# Disabled for too many intermittent failures (bug 1009322)
|
||||
|
@ -2760,7 +2760,7 @@ public class BrowserApp extends GeckoApp
|
||||
share.setVisible(shareEnabled);
|
||||
share.setEnabled(StringUtils.isShareableUrl(url) && shareEnabled);
|
||||
MenuUtils.safeSetEnabled(aMenu, R.id.apps, RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_INSTALL_APPS));
|
||||
MenuUtils.safeSetEnabled(aMenu, R.id.addons, RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_INSTALL_EXTENSIONS));
|
||||
MenuUtils.safeSetEnabled(aMenu, R.id.addons, RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_INSTALL_EXTENSION));
|
||||
MenuUtils.safeSetEnabled(aMenu, R.id.downloads, RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_DOWNLOADS));
|
||||
|
||||
// NOTE: Use MenuUtils.safeSetEnabled because some actions might
|
||||
|
@ -81,6 +81,7 @@ import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.os.StrictMode;
|
||||
@ -978,6 +979,12 @@ public abstract class GeckoApp
|
||||
image = BitmapUtils.decodeByteArray(imgBuffer);
|
||||
}
|
||||
if (image != null) {
|
||||
// Some devices don't have a DCIM folder and the Media.insertImage call will fail.
|
||||
File dcimDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
|
||||
if (!dcimDir.mkdirs() && !dcimDir.isDirectory()) {
|
||||
Toast.makeText((Context) this, R.string.set_image_path_fail, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
String path = Media.insertImage(getContentResolver(),image, null, null);
|
||||
if (path == null) {
|
||||
Toast.makeText((Context) this, R.string.set_image_path_fail, Toast.LENGTH_SHORT).show();
|
||||
|
@ -55,14 +55,16 @@ public class RestrictedProfiles {
|
||||
*/
|
||||
public static enum Restriction {
|
||||
DISALLOW_DOWNLOADS(1, "no_download_files"),
|
||||
DISALLOW_INSTALL_EXTENSIONS(2, "no_install_extensions"),
|
||||
DISALLOW_INSTALL_EXTENSION(2, "no_install_extensions"),
|
||||
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_MODIFY_ACCOUNTS(9, "no_modify_accounts"), // UserManager.DISALLOW_MODIFY_ACCOUNTS
|
||||
DISALLOW_REMOTE_DEBUGGING(10, "no_remote_debugging"),
|
||||
DISALLOW_IMPORT_SETTINGS(11, "no_import_settings");
|
||||
|
||||
public final int id;
|
||||
public final String name;
|
||||
|
@ -10,7 +10,10 @@ import org.mozilla.gecko.animation.BounceAnimator;
|
||||
import org.mozilla.gecko.animation.BounceAnimator.Attributes;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.support.v4.view.PagerTabStrip;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
@ -37,8 +40,11 @@ class HomePagerTabStrip extends PagerTabStrip {
|
||||
private static final int BOUNCE4_MS = 100;
|
||||
private static final int INIT_OFFSET = 100;
|
||||
|
||||
private final Paint shadowPaint;
|
||||
private final int shadowSize;
|
||||
|
||||
public HomePagerTabStrip(Context context) {
|
||||
super(context);
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public HomePagerTabStrip(Context context, AttributeSet attrs) {
|
||||
@ -50,6 +56,13 @@ class HomePagerTabStrip extends PagerTabStrip {
|
||||
|
||||
setTabIndicatorColor(color);
|
||||
|
||||
final Resources res = getResources();
|
||||
shadowSize = res.getDimensionPixelSize(R.dimen.tabs_strip_shadow_size);
|
||||
|
||||
shadowPaint = new Paint();
|
||||
shadowPaint.setColor(res.getColor(R.color.url_bar_shadow));
|
||||
shadowPaint.setStrokeWidth(0.0f);
|
||||
|
||||
getViewTreeObserver().addOnPreDrawListener(new PreDrawListener());
|
||||
}
|
||||
|
||||
@ -61,6 +74,14 @@ class HomePagerTabStrip extends PagerTabStrip {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
super.draw(canvas);
|
||||
|
||||
final int height = getHeight();
|
||||
canvas.drawRect(0, height - shadowSize, getWidth(), height, shadowPaint);
|
||||
}
|
||||
|
||||
private void animateTitles() {
|
||||
final View prevTextView = getChildAt(0);
|
||||
final View nextTextView = getChildAt(getChildCount() - 1);
|
||||
|
@ -8,8 +8,10 @@ package org.mozilla.gecko.home;
|
||||
import org.mozilla.gecko.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
@ -35,16 +37,35 @@ public class TabMenuStrip extends HorizontalScrollView
|
||||
private final int titleOffset;
|
||||
private final TabMenuStripLayout layout;
|
||||
|
||||
private final Paint shadowPaint;
|
||||
private final int shadowSize;
|
||||
|
||||
public TabMenuStrip(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
// Disable the scroll bar.
|
||||
setHorizontalScrollBarEnabled(false);
|
||||
|
||||
titleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);
|
||||
final Resources res = getResources();
|
||||
|
||||
titleOffset = (int) (TITLE_OFFSET_DIPS * res.getDisplayMetrics().density);
|
||||
|
||||
layout = new TabMenuStripLayout(context, attrs);
|
||||
addView(layout, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
|
||||
shadowSize = res.getDimensionPixelSize(R.dimen.tabs_strip_shadow_size);
|
||||
|
||||
shadowPaint = new Paint();
|
||||
shadowPaint.setColor(res.getColor(R.color.url_bar_shadow));
|
||||
shadowPaint.setStrokeWidth(0.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
super.draw(canvas);
|
||||
|
||||
final int height = getHeight();
|
||||
canvas.drawRect(0, height - shadowSize, getWidth(), height, shadowPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -7,19 +7,31 @@ package org.mozilla.gecko.preferences;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.RestrictedProfiles;
|
||||
import org.mozilla.gecko.RestrictedProfiles.Restriction;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
||||
class AndroidImportPreference extends MultiPrefMultiChoicePreference {
|
||||
private static final String LOGTAG = "AndroidImport";
|
||||
public static final String PREF_KEY = "android.not_a_preference.import_android";
|
||||
private static final String PREF_KEY_PREFIX = "import_android.data.";
|
||||
private final Context mContext;
|
||||
|
||||
public static class Handler implements GeckoPreferences.PrefHandler {
|
||||
public boolean setupPref(Context context, Preference pref) {
|
||||
return RestrictedProfiles.isAllowed(Restriction.DISALLOW_IMPORT_SETTINGS);
|
||||
}
|
||||
|
||||
public void onChange(Context context, Preference pref, Object newValue) { }
|
||||
}
|
||||
|
||||
public AndroidImportPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
|
@ -19,12 +19,13 @@ public class ClearOnShutdownPref implements GeckoPreferences.PrefHandler {
|
||||
public static final String PREF = GeckoPreferences.NON_PREF_PREFIX + "history.clear_on_exit";
|
||||
|
||||
@Override
|
||||
public void setupPref(Context context, Preference pref) {
|
||||
public boolean setupPref(Context context, Preference pref) {
|
||||
// The pref is initialized asynchronously. Read the pref explicitly
|
||||
// here to make sure we have the data.
|
||||
final SharedPreferences prefs = GeckoSharedPrefs.forProfile(context);
|
||||
final Set<String> clearItems = PrefUtils.getStringSet(prefs, PREF, new HashSet<String>());
|
||||
((ListCheckboxPreference) pref).setChecked(clearItems.size() > 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -700,6 +700,12 @@ OnSharedPreferenceChangeListener
|
||||
i--;
|
||||
continue;
|
||||
} else if (PREFS_DEVTOOLS_REMOTE_ENABLED.equals(key)) {
|
||||
if (!RestrictedProfiles.isAllowed(RestrictedProfiles.Restriction.DISALLOW_REMOTE_DEBUGGING)) {
|
||||
preferences.removePreference(pref);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
final Context thisContext = this;
|
||||
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
@ -744,7 +750,11 @@ OnSharedPreferenceChangeListener
|
||||
continue;
|
||||
} else if (handlers.containsKey(key)) {
|
||||
PrefHandler handler = handlers.get(key);
|
||||
handler.setupPref(this, pref);
|
||||
if (!handler.setupPref(this, pref)) {
|
||||
preferences.removePreference(pref);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Some Preference UI elements are not actually preferences,
|
||||
@ -1026,13 +1036,16 @@ OnSharedPreferenceChangeListener
|
||||
}
|
||||
|
||||
public interface PrefHandler {
|
||||
public void setupPref(Context context, Preference pref);
|
||||
// Allows the pref to do any initialization it needs. Return false to have the pref removed
|
||||
// from the prefs screen entirely.
|
||||
public boolean setupPref(Context context, Preference pref);
|
||||
public void onChange(Context context, Preference pref, Object newValue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private final Map<String, PrefHandler> handlers = new HashMap<String, PrefHandler>() {{
|
||||
put(ClearOnShutdownPref.PREF, new ClearOnShutdownPref());
|
||||
put(AndroidImportPreference.PREF_KEY, new AndroidImportPreference.Handler());
|
||||
}};
|
||||
|
||||
@Override
|
||||
|
@ -14,7 +14,7 @@
|
||||
android:background="@android:color/white">
|
||||
|
||||
<org.mozilla.gecko.home.TabMenuStrip android:layout_width="match_parent"
|
||||
android:layout_height="32dip"
|
||||
android:layout_height="@dimen/tabs_strip_height"
|
||||
android:background="@color/background_light"
|
||||
android:layout_gravity="top"
|
||||
gecko:strip="@drawable/home_tab_menu_strip"/>
|
||||
|
@ -14,7 +14,7 @@
|
||||
android:background="@android:color/white">
|
||||
|
||||
<org.mozilla.gecko.home.HomePagerTabStrip android:layout_width="match_parent"
|
||||
android:layout_height="40dip"
|
||||
android:layout_height="@dimen/tabs_strip_height"
|
||||
android:layout_gravity="top"
|
||||
android:gravity="center_vertical"
|
||||
android:background="@color/background_light"
|
||||
|
@ -71,9 +71,4 @@
|
||||
<item name="android:layout_gravity">center</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Home.HomeList">
|
||||
<item name="topDivider">true</item>
|
||||
<item name="android:scrollbarStyle">outsideOverlay</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@ -19,11 +19,6 @@
|
||||
<item name="android:verticalSpacing">20dp</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Home.HomeList">
|
||||
<item name="android:scrollbarStyle">outsideOverlay</item>
|
||||
<item name="topDivider">true</item>
|
||||
</style>
|
||||
|
||||
<!-- Tabs panel -->
|
||||
<style name="TabsPanelFrame.RemoteTabs" parent="TabsPanelFrameBase">
|
||||
<item name="android:paddingLeft">0dp</item>
|
||||
|
@ -16,11 +16,6 @@
|
||||
<item name="android:layout_height">48dip</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Home.HomeList">
|
||||
<item name="android:scrollbarStyle">outsideOverlay</item>
|
||||
<item name="topDivider">true</item>
|
||||
</style>
|
||||
|
||||
<!-- Tabs panel -->
|
||||
<style name="TabsPanelFrame.RemoteTabs" parent="TabsPanelFrameBase">
|
||||
<item name="android:paddingLeft">212dp</item>
|
||||
|
@ -105,8 +105,10 @@
|
||||
<dimen name="tabs_panel_list_padding">16dip</dimen>
|
||||
<dimen name="tabs_list_divider_height">2dp</dimen>
|
||||
<dimen name="tabs_sidebar_width">200dp</dimen>
|
||||
<dimen name="tabs_strip_height">40dp</dimen>
|
||||
<dimen name="tabs_strip_button_width">100dp</dimen>
|
||||
<dimen name="tabs_strip_button_padding">18dp</dimen>
|
||||
<dimen name="tabs_strip_shadow_size">1dp</dimen>
|
||||
<dimen name="tabs_tray_horizontal_height">156dp</dimen>
|
||||
<dimen name="text_selection_handle_width">47dp</dimen>
|
||||
<dimen name="text_selection_handle_height">58dp</dimen>
|
||||
|
@ -63,10 +63,6 @@
|
||||
</style>
|
||||
|
||||
<style name="Widget.Home.HomeList">
|
||||
<item name="android:paddingTop">0dip</item>
|
||||
<item name="android:paddingRight">0dip</item>
|
||||
<item name="android:paddingLeft">0dip</item>
|
||||
<item name="topDivider">true</item>
|
||||
<item name="android:scrollbarStyle">outsideOverlay</item>
|
||||
</style>
|
||||
|
||||
@ -229,7 +225,7 @@
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">32dp</item>
|
||||
<item name="android:textAppearance">@style/TextAppearance.Widget.Home.Header</item>
|
||||
<item name="android:background">#fff5f7f9</item>
|
||||
<item name="android:background">@color/background_light</item>
|
||||
<item name="android:focusable">false</item>
|
||||
<item name="android:gravity">center|left</item>
|
||||
<item name="android:paddingLeft">10dip</item>
|
||||
|
@ -465,7 +465,7 @@ var BrowserApp = {
|
||||
if (this._startupStatus)
|
||||
this.onAppUpdated();
|
||||
|
||||
if (!ParentalControls.isAllowed(ParentalControls.INSTALL_EXTENSIONS)) {
|
||||
if (!ParentalControls.isAllowed(ParentalControls.INSTALL_EXTENSION)) {
|
||||
// Disable extension installs
|
||||
Services.prefs.setIntPref("extensions.enabledScopes", 1);
|
||||
Services.prefs.setIntPref("extensions.autoDisableScopes", 1);
|
||||
|
@ -102,8 +102,13 @@ public class SearchWidget extends AppWidgetProvider {
|
||||
|
||||
// Utility to create the view for this widget and attach any event listeners to it
|
||||
private void addView(final AppWidgetManager manager, final Context context, final int id, final Bundle options) {
|
||||
final int category = options.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1);
|
||||
final boolean isKeyguard = category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;
|
||||
final boolean isKeyguard;
|
||||
if (options != null) {
|
||||
final int category = options.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1);
|
||||
isKeyguard = category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;
|
||||
} else {
|
||||
isKeyguard = false;
|
||||
}
|
||||
|
||||
final RemoteViews views;
|
||||
if (isKeyguard) {
|
||||
|
@ -11,7 +11,7 @@ interface nsIFile;
|
||||
interface nsIInterfaceRequestor;
|
||||
interface nsIArray;
|
||||
|
||||
[scriptable, uuid(4bde6754-406a-45d1-b18e-dc685adc1db4)]
|
||||
[scriptable, uuid(e7bcc22c-e9fc-4e7d-88b9-7482399b322d)]
|
||||
interface nsIParentalControlsService : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -26,6 +26,8 @@ interface nsIParentalControlsService : nsISupports
|
||||
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
|
||||
|
||||
/**
|
||||
* @returns true if the current user account has parental controls
|
||||
|
Loading…
Reference in New Issue
Block a user