merge fx-team to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-09-15 14:29:01 +02:00
commit 31e4f608a4
30 changed files with 602 additions and 79 deletions

View File

@ -1407,7 +1407,6 @@ pref("devtools.tilt.outro_transition", true);
// - enableAutocompletion: Whether to enable JavaScript autocompletion.
pref("devtools.scratchpad.recentFilesMax", 10);
pref("devtools.scratchpad.showTrailingSpace", false);
pref("devtools.scratchpad.enableCodeFolding", true);
pref("devtools.scratchpad.enableAutocompletion", true);
// Enable the Storage Inspector
@ -1513,6 +1512,7 @@ pref("devtools.editor.expandtab", true);
pref("devtools.editor.keymap", "default");
pref("devtools.editor.autoclosebrackets", true);
pref("devtools.editor.detectindentation", true);
pref("devtools.editor.enableCodeFolding", true);
pref("devtools.editor.autocomplete", true);
// Enable the Font Inspector

View File

@ -233,7 +233,8 @@ let DebuggerView = {
showAnnotationRuler: true,
gutters: gutters,
extraKeys: extraKeys,
contextMenu: "sourceEditorContextMenu"
contextMenu: "sourceEditorContextMenu",
enableCodeFolding: false
});
this.editor.appendTo(document.getElementById("editor")).then(() => {

View File

@ -34,8 +34,8 @@ const SCRATCHPAD_L10N = "chrome://browser/locale/devtools/scratchpad.properties"
const DEVTOOLS_CHROME_ENABLED = "devtools.chrome.enabled";
const PREF_RECENT_FILES_MAX = "devtools.scratchpad.recentFilesMax";
const SHOW_TRAILING_SPACE = "devtools.scratchpad.showTrailingSpace";
const ENABLE_CODE_FOLDING = "devtools.scratchpad.enableCodeFolding";
const ENABLE_AUTOCOMPLETION = "devtools.scratchpad.enableAutocompletion";
const TAB_SIZE = "devtools.editor.tabsize";
const VARIABLES_VIEW_URL = "chrome://browser/content/devtools/widgets/VariablesView.xul";
@ -655,7 +655,7 @@ var Scratchpad = {
*/
prettyPrint: function SP_prettyPrint() {
const uglyText = this.getText();
const tabsize = Services.prefs.getIntPref("devtools.editor.tabsize");
const tabsize = Services.prefs.getIntPref(TAB_SIZE);
const id = Math.random();
const deferred = promise.defer();
@ -1604,7 +1604,6 @@ var Scratchpad = {
lineNumbers: true,
contextMenu: "scratchpad-text-popup",
showTrailingSpace: Services.prefs.getBoolPref(SHOW_TRAILING_SPACE),
enableCodeFolding: Services.prefs.getBoolPref(ENABLE_CODE_FOLDING),
autocomplete: Services.prefs.getBoolPref(ENABLE_AUTOCOMPLETION),
};

View File

@ -9,6 +9,7 @@
const { Cu, Cc, Ci, components } = require("chrome");
const TAB_SIZE = "devtools.editor.tabsize";
const ENABLE_CODE_FOLDING = "devtools.editor.enableCodeFolding";
const EXPAND_TAB = "devtools.editor.expandtab";
const KEYMAP = "devtools.editor.keymap";
const AUTO_CLOSE = "devtools.editor.autoclosebrackets";
@ -188,14 +189,12 @@ function Editor(config) {
});
});
// Set the code folding gutter, if needed.
if (this.config.enableCodeFolding) {
this.config.foldGutter = true;
if (!this.config.gutters) {
this.config.gutters = this.config.lineNumbers ? ["CodeMirror-linenumbers"] : [];
this.config.gutters.push("CodeMirror-foldgutter");
}
if (!this.config.gutters) {
this.config.gutters = [];
}
if (this.config.lineNumbers
&& this.config.gutters.indexOf("CodeMirror-linenumbers") === -1) {
this.config.gutters.push("CodeMirror-linenumbers");
}
// Remember the initial value of autoCloseBrackets.
@ -333,6 +332,7 @@ Editor.prototype = {
this._prefObserver.on(AUTO_CLOSE, this.reloadPreferences);
this._prefObserver.on(AUTOCOMPLETE, this.reloadPreferences);
this._prefObserver.on(DETECT_INDENT, this.reloadPreferences);
this._prefObserver.on(ENABLE_CODE_FOLDING, this.reloadPreferences);
this.reloadPreferences();
def.resolve();
@ -430,6 +430,7 @@ Editor.prototype = {
this.setOption("keyMap", keyMap)
else
this.setOption("keyMap", "default");
this.updateCodeFoldingGutter();
this.resetIndentUnit();
this.setupAutoCompletion();
@ -955,6 +956,12 @@ Editor.prototype = {
} else {
cm.setOption(o, v);
}
if (o === "enableCodeFolding") {
// The new value maybe explicitly force foldGUtter on or off, ignoring
// the prefs service.
this.updateCodeFoldingGutter();
}
},
/**
@ -1036,10 +1043,46 @@ Editor.prototype = {
this._prefObserver.off(AUTO_CLOSE, this.reloadPreferences);
this._prefObserver.off(AUTOCOMPLETE, this.reloadPreferences);
this._prefObserver.off(DETECT_INDENT, this.reloadPreferences);
this._prefObserver.off(ENABLE_CODE_FOLDING, this.reloadPreferences);
this._prefObserver.destroy();
}
this.emit("destroy");
},
updateCodeFoldingGutter: function () {
let shouldFoldGutter = this.config.enableCodeFolding,
foldGutterIndex = this.config.gutters.indexOf("CodeMirror-foldgutter"),
cm = editors.get(this);
if (shouldFoldGutter === undefined) {
shouldFoldGutter = Services.prefs.getBoolPref(ENABLE_CODE_FOLDING);
}
if (shouldFoldGutter) {
// Add the gutter before enabling foldGutter
if (foldGutterIndex === -1) {
let gutters = this.config.gutters.slice();
gutters.push("CodeMirror-foldgutter");
this.setOption("gutters", gutters);
}
this.setOption("foldGutter", true);
} else {
// No code should remain folded when folding is off.
if (cm) {
cm.execCommand("unfoldAll");
}
// Remove the gutter so it doesn't take up space
if (foldGutterIndex !== -1) {
let gutters = this.config.gutters.slice();
gutters.splice(foldGutterIndex, 1);
this.setOption("gutters", gutters);
}
this.setOption("foldGutter", false);
}
}
};

View File

@ -7,6 +7,7 @@
// Test to make sure that the editor reacts to preference changes
const TAB_SIZE = "devtools.editor.tabsize";
const ENABLE_CODE_FOLDING = "devtools.editor.enableCodeFolding";
const EXPAND_TAB = "devtools.editor.expandtab";
const KEYMAP = "devtools.editor.keymap";
const AUTO_CLOSE = "devtools.editor.autoclosebrackets";
@ -17,6 +18,11 @@ function test() {
waitForExplicitFinish();
setup((ed, win) => {
Assert.deepEqual(ed.getOption("gutters"), [
"CodeMirror-linenumbers",
"breakpoints",
"CodeMirror-foldgutter"], "gutters is correct");
ed.setText("Checking preferences.");
info ("Turning prefs off");
@ -24,14 +30,21 @@ function test() {
ed.setOption("autocomplete", true);
Services.prefs.setIntPref(TAB_SIZE, 2);
Services.prefs.setBoolPref(ENABLE_CODE_FOLDING, false);
Services.prefs.setBoolPref(EXPAND_TAB, false);
Services.prefs.setCharPref(KEYMAP, "default");
Services.prefs.setBoolPref(AUTO_CLOSE, false);
Services.prefs.setBoolPref(AUTOCOMPLETE, false);
Services.prefs.setBoolPref(DETECT_INDENT, false);
Assert.deepEqual(ed.getOption("gutters"), [
"CodeMirror-linenumbers",
"breakpoints"], "gutters is correct");
is(ed.getOption("tabSize"), 2, "tabSize is correct");
is(ed.getOption("indentUnit"), 2, "indentUnit is correct");
is(ed.getOption("foldGutter"), false, "foldGutter is correct");
is(ed.getOption("enableCodeFolding"), undefined, "enableCodeFolding is correct");
is(ed.getOption("indentWithTabs"), true, "indentWithTabs is correct");
is(ed.getOption("keyMap"), "default", "keyMap is correct");
is(ed.getOption("autoCloseBrackets"), "", "autoCloseBrackets is correct");
@ -41,19 +54,46 @@ function test() {
info ("Turning prefs on");
Services.prefs.setIntPref(TAB_SIZE, 4);
Services.prefs.setBoolPref(ENABLE_CODE_FOLDING, true);
Services.prefs.setBoolPref(EXPAND_TAB, true);
Services.prefs.setCharPref(KEYMAP, "sublime");
Services.prefs.setBoolPref(AUTO_CLOSE, true);
Services.prefs.setBoolPref(AUTOCOMPLETE, true);
Assert.deepEqual(ed.getOption("gutters"), [
"CodeMirror-linenumbers",
"breakpoints",
"CodeMirror-foldgutter"], "gutters is correct");
is(ed.getOption("tabSize"), 4, "tabSize is correct");
is(ed.getOption("indentUnit"), 4, "indentUnit is correct");
is(ed.getOption("foldGutter"), true, "foldGutter is correct");
is(ed.getOption("enableCodeFolding"), undefined, "enableCodeFolding is correct");
is(ed.getOption("indentWithTabs"), false, "indentWithTabs is correct");
is(ed.getOption("keyMap"), "sublime", "keyMap is correct");
is(ed.getOption("autoCloseBrackets"), "()[]{}''\"\"", "autoCloseBrackets is correct");
is(ed.getOption("autocomplete"), true, "autocomplete is correct");
ok(ed.isAutocompletionEnabled(), "Autocompletion is enabled");
info ("Forcing foldGutter off using enableCodeFolding");
ed.setOption("enableCodeFolding", false);
is(ed.getOption("foldGutter"), false, "foldGutter is correct");
is(ed.getOption("enableCodeFolding"), false, "enableCodeFolding is correct");
Assert.deepEqual(ed.getOption("gutters"), [
"CodeMirror-linenumbers",
"breakpoints"], "gutters is correct");
info ("Forcing foldGutter on using enableCodeFolding");
ed.setOption("enableCodeFolding", true);
is(ed.getOption("foldGutter"), true, "foldGutter is correct");
is(ed.getOption("enableCodeFolding"), true, "enableCodeFolding is correct");
Assert.deepEqual(ed.getOption("gutters"), [
"CodeMirror-linenumbers",
"breakpoints",
"CodeMirror-foldgutter"], "gutters is correct");
info ("Checking indentation detection");
Services.prefs.setBoolPref(DETECT_INDENT, true);

View File

@ -35,14 +35,14 @@ let test = asyncTest(function*() {
let onHighlighted = editor.once("node-highlighted");
info("Simulate a mousemove event on the div selector");
editor._onMouseMove({clientX: 40, clientY: 10});
editor._onMouseMove({clientX: 56, clientY: 10});
yield onHighlighted;
ok(editor.highlighter.isShown, "The highlighter is now shown");
is(editor.highlighter.options.selector, "div", "The selector is correct");
info("Simulate a mousemove event elsewhere in the editor");
editor._onMouseMove({clientX: 0, clientY: 0});
editor._onMouseMove({clientX: 16, clientY: 0});
ok(!editor.highlighter.isShown, "The highlighter is now hidden");
});

View File

@ -496,7 +496,7 @@ let UI = {
Task.spawn(function() {
if (project.type == "runtimeApp") {
yield UI.busyUntil(AppManager.runRuntimeApp(), "running app");
yield UI.busyUntil(AppManager.launchRuntimeApp(), "running app");
}
yield UI.createToolbox();
});
@ -1014,7 +1014,7 @@ let Cmds = {
case "hosted":
return UI.busyUntil(AppManager.installAndRunProject(), "installing and running app");
case "runtimeApp":
return UI.busyUntil(AppManager.runRuntimeApp(), "running app");
return UI.busyUntil(AppManager.launchOrReloadRuntimeApp(), "launching / reloading app");
case "tab":
return UI.busyUntil(AppManager.reloadTab(), "reloading tab");
}

View File

@ -326,7 +326,9 @@ exports.AppManager = AppManager = {
_selectedProject: null,
set selectedProject(value) {
if (value != this.selectedProject) {
// A regular comparison still sees a difference when equal in some cases
if (JSON.stringify(this._selectedProject) !==
JSON.stringify(value)) {
this._selectedProject = value;
// Clear out tab store's selected state, if any
@ -439,9 +441,19 @@ exports.AppManager = AppManager = {
return deferred.promise;
},
runRuntimeApp: function() {
launchRuntimeApp: function() {
if (this.selectedProject && this.selectedProject.type != "runtimeApp") {
return promise.reject("attempting to run a non-runtime app");
return promise.reject("attempting to launch a non-runtime app");
}
let client = this.connection.client;
let actor = this._listTabsResponse.webappsActor;
let manifest = this.getProjectManifestURL(this.selectedProject);
return AppActorFront.launchApp(client, actor, manifest);
},
launchOrReloadRuntimeApp: function() {
if (this.selectedProject && this.selectedProject.type != "runtimeApp") {
return promise.reject("attempting to launch / reload a non-runtime app");
}
let client = this.connection.client;
let actor = this._listTabsResponse.webappsActor;

View File

@ -303,7 +303,7 @@ class Automation(object):
permDB = sqlite3.connect(os.path.join(profileDir, "permissions.sqlite"))
cursor = permDB.cursor();
cursor.execute("PRAGMA user_version=3");
cursor.execute("PRAGMA user_version=4");
# SQL copied from nsPermissionManager.cpp
cursor.execute("""CREATE TABLE IF NOT EXISTS moz_hosts (
@ -313,13 +313,14 @@ class Automation(object):
permission INTEGER,
expireType INTEGER,
expireTime INTEGER,
modificationTime INTEGER,
appId INTEGER,
isInBrowserElement INTEGER)""")
# Insert desired permissions
for perm in permissions.keys():
for host,allow in permissions[perm]:
cursor.execute("INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0, 0, 0)",
cursor.execute("INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0, 0, 0, 0)",
(host, perm, 1 if allow else 2))
# Commit and close

View File

@ -1714,12 +1714,16 @@ ContentChild::RecvAddPermission(const IPC::Permission& permission)
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, true);
// child processes don't care about modification time.
int64_t modificationTime = 0;
permissionManager->AddInternal(principal,
nsCString(permission.type),
permission.capability,
0,
permission.expireType,
permission.expireTime,
modificationTime,
nsPermissionManager::eNotify,
nsPermissionManager::eNoDBOperation);
#endif

View File

@ -357,7 +357,7 @@ nsPermissionManager::AppClearDataObserverInit()
// nsPermissionManager Implementation
static const char kPermissionsFileName[] = "permissions.sqlite";
#define HOSTS_SCHEMA_VERSION 3
#define HOSTS_SCHEMA_VERSION 4
static const char kHostpermFileName[] = "hostperm.1";
@ -432,8 +432,12 @@ nsPermissionManager::Init()
rv = GetPrincipal(perm.host, perm.appId, perm.isInBrowserElement, getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
// The child process doesn't care about modification times - it neither
// reads nor writes, nor removes them based on the date - so 0 (which
// will end up as now()) is fine.
uint64_t modificationTime = 0;
AddInternal(principal, perm.type, perm.capability, 0, perm.expireType,
perm.expireTime, eNotify, eNoDBOperation);
perm.expireTime, modificationTime, eNotify, eNoDBOperation);
}
// Stop here; we don't need the DB in the child process
@ -546,6 +550,23 @@ nsPermissionManager::InitDB(bool aRemoveFile)
// fall through to the next upgrade
// Version 3->4 is the creation of the modificationTime field.
case 3:
{
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"ALTER TABLE moz_hosts ADD modificationTime INTEGER"));
NS_ENSURE_SUCCESS(rv, rv);
// We leave the modificationTime at zero for all existing records; using
// now() would mean, eg, that doing "remove all from the last hour"
// within the first hour after migration would remove all permissions.
rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
NS_ENSURE_SUCCESS(rv, rv);
}
// fall through to the next upgrade
// current version.
case HOSTS_SCHEMA_VERSION:
break;
@ -561,7 +582,7 @@ nsPermissionManager::InitDB(bool aRemoveFile)
// check if all the expected columns exist
nsCOMPtr<mozIStorageStatement> stmt;
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT host, type, permission, expireType, expireTime, appId, isInBrowserElement FROM moz_hosts"),
"SELECT host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement FROM moz_hosts"),
getter_AddRefs(stmt));
if (NS_SUCCEEDED(rv))
break;
@ -583,8 +604,8 @@ nsPermissionManager::InitDB(bool aRemoveFile)
// cache frequently used statements (for insertion, deletion, and updating)
rv = mDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
"INSERT INTO moz_hosts "
"(id, host, type, permission, expireType, expireTime, appId, isInBrowserElement) "
"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)"), getter_AddRefs(mStmtInsert));
"(id, host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement) "
"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)"), getter_AddRefs(mStmtInsert));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
@ -594,7 +615,7 @@ nsPermissionManager::InitDB(bool aRemoveFile)
rv = mDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
"UPDATE moz_hosts "
"SET permission = ?2, expireType= ?3, expireTime = ?4 WHERE id = ?1"),
"SET permission = ?2, expireType= ?3, expireTime = ?4, modificationTime = ?5 WHERE id = ?1"),
getter_AddRefs(mStmtUpdate));
NS_ENSURE_SUCCESS(rv, rv);
@ -626,6 +647,7 @@ nsPermissionManager::CreateTable()
",permission INTEGER"
",expireType INTEGER"
",expireTime INTEGER"
",modificationTime INTEGER"
",appId INTEGER"
",isInBrowserElement INTEGER"
")"));
@ -679,8 +701,11 @@ nsPermissionManager::AddFromPrincipal(nsIPrincipal* aPrincipal,
return NS_ERROR_INVALID_ARG;
}
// A modificationTime of zero will cause AddInternal to use now().
int64_t modificationTime = 0;
return AddInternal(aPrincipal, nsDependentCString(aType), aPermission, 0,
aExpireType, aExpireTime, eNotify, eWriteToDB);
aExpireType, aExpireTime, modificationTime, eNotify, eWriteToDB);
}
nsresult
@ -690,6 +715,7 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
int64_t aID,
uint32_t aExpireType,
int64_t aExpireTime,
int64_t aModificationTime,
NotifyOperationType aNotifyOperation,
DBOperationType aDBOperation)
{
@ -760,15 +786,27 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
// even if the new permission is UNKNOWN_ACTION (which means a "logical
// remove" of the default)
op = eOperationReplacingDefault;
else if (aID == cIDPermissionIsDefault)
// We are adding a default permission but a "real" permission already
// exists. This almost-certainly means we just did a removeAllSince and
// are re-importing defaults - so we can ignore this.
op = eOperationNone;
else if (aPermission == nsIPermissionManager::UNKNOWN_ACTION)
op = eOperationRemoving;
else
op = eOperationChanging;
}
// child processes should *always* be passed a modificationTime of zero.
MOZ_ASSERT(!IsChildProcess() || aModificationTime == 0);
// do the work for adding, deleting, or changing a permission:
// update the in-memory list, write to the db, and notify consumers.
int64_t id;
if (aModificationTime == 0) {
aModificationTime = PR_Now() / 1000;
}
switch (op) {
case eOperationNone:
{
@ -786,7 +824,9 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
id = aID;
}
entry->GetPermissions().AppendElement(PermissionEntry(id, typeIndex, aPermission, aExpireType, aExpireTime));
entry->GetPermissions().AppendElement(PermissionEntry(id, typeIndex, aPermission,
aExpireType, aExpireTime,
aModificationTime));
if (aDBOperation == eWriteToDB && aExpireType != nsIPermissionManager::EXPIRE_SESSION) {
uint32_t appId;
@ -797,7 +837,7 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement);
NS_ENSURE_SUCCESS(rv, rv);
UpdateDB(op, mStmtInsert, id, host, aType, aPermission, aExpireType, aExpireTime, appId, isInBrowserElement);
UpdateDB(op, mStmtInsert, id, host, aType, aPermission, aExpireType, aExpireTime, aModificationTime, appId, isInBrowserElement);
}
if (aNotifyOperation == eNotify) {
@ -824,7 +864,7 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
// We care only about the id here so we pass dummy values for all other
// parameters.
UpdateDB(op, mStmtDelete, id, EmptyCString(), EmptyCString(), 0,
nsIPermissionManager::EXPIRE_NEVER, 0, 0, false);
nsIPermissionManager::EXPIRE_NEVER, 0, 0, 0, false);
if (aNotifyOperation == eNotify) {
NotifyObserversWithPermission(host,
@ -866,12 +906,13 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
entry->GetPermissions()[index].mPermission = aPermission;
entry->GetPermissions()[index].mExpireType = aExpireType;
entry->GetPermissions()[index].mExpireTime = aExpireTime;
entry->GetPermissions()[index].mModificationTime = aModificationTime;
if (aDBOperation == eWriteToDB && aExpireType != nsIPermissionManager::EXPIRE_SESSION)
// We care only about the id, the permission and expireType/expireTime here.
// We care only about the id, the permission and expireType/expireTime/modificationTime here.
// We pass dummy values for all other parameters.
UpdateDB(op, mStmtUpdate, id, EmptyCString(), EmptyCString(),
aPermission, aExpireType, aExpireTime, 0, false);
aPermission, aExpireType, aExpireTime, aModificationTime, 0, false);
if (aNotifyOperation == eNotify) {
NotifyObserversWithPermission(host,
@ -915,6 +956,7 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
entry->GetPermissions()[index].mPermission = aPermission;
entry->GetPermissions()[index].mExpireType = aExpireType;
entry->GetPermissions()[index].mExpireTime = aExpireTime;
entry->GetPermissions()[index].mModificationTime = aModificationTime;
// If requested, create the entry in the DB.
if (aDBOperation == eWriteToDB) {
@ -926,7 +968,8 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement);
NS_ENSURE_SUCCESS(rv, rv);
UpdateDB(eOperationAdding, mStmtInsert, id, host, aType, aPermission, aExpireType, aExpireTime, appId, isInBrowserElement);
UpdateDB(eOperationAdding, mStmtInsert, id, host, aType, aPermission,
aExpireType, aExpireTime, aModificationTime, appId, isInBrowserElement);
}
if (aNotifyOperation == eNotify) {
@ -983,6 +1026,7 @@ nsPermissionManager::RemoveFromPrincipal(nsIPrincipal* aPrincipal,
0,
nsIPermissionManager::EXPIRE_NEVER,
0,
0,
eNotify,
eWriteToDB);
}
@ -994,6 +1038,13 @@ nsPermissionManager::RemoveAll()
return RemoveAllInternal(true);
}
NS_IMETHODIMP
nsPermissionManager::RemoveAllSince(int64_t aSince)
{
ENSURE_NOT_CHILD_PROCESS;
return RemoveAllModifiedSince(aSince);
}
void
nsPermissionManager::CloseDB(bool aRebuildOnSuccess)
{
@ -1323,12 +1374,16 @@ nsPermissionManager::GetPermissionHashKey(const nsACString& aHost,
// helper struct for passing arguments into hash enumeration callback.
struct nsGetEnumeratorData
{
nsGetEnumeratorData(nsCOMArray<nsIPermission> *aArray, const nsTArray<nsCString> *aTypes)
nsGetEnumeratorData(nsCOMArray<nsIPermission> *aArray,
const nsTArray<nsCString> *aTypes,
int64_t aSince = 0)
: array(aArray)
, types(aTypes) {}
, types(aTypes)
, since(aSince) {}
nsCOMArray<nsIPermission> *array;
const nsTArray<nsCString> *types;
int64_t since;
};
static PLDHashOperator
@ -1395,6 +1450,76 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT
return NS_OK;
}
static PLDHashOperator
AddPermissionsModifiedSinceToList(
nsPermissionManager::PermissionHashKey* entry, void* arg)
{
nsGetEnumeratorData* data = static_cast<nsGetEnumeratorData *>(arg);
for (size_t i = 0; i < entry->GetPermissions().Length(); ++i) {
const nsPermissionManager::PermissionEntry& permEntry = entry->GetPermissions()[i];
if (data->since > permEntry.mModificationTime) {
continue;
}
nsPermission* perm = new nsPermission(entry->GetKey()->mHost,
entry->GetKey()->mAppId,
entry->GetKey()->mIsInBrowserElement,
data->types->ElementAt(permEntry.mType),
permEntry.mPermission,
permEntry.mExpireType,
permEntry.mExpireTime);
data->array->AppendObject(perm);
}
return PL_DHASH_NEXT;
}
nsresult
nsPermissionManager::RemoveAllModifiedSince(int64_t aModificationTime)
{
ENSURE_NOT_CHILD_PROCESS;
// roll an nsCOMArray of all our permissions, then hand out an enumerator
nsCOMArray<nsIPermission> array;
nsGetEnumeratorData data(&array, &mTypeArray, aModificationTime);
mPermissionTable.EnumerateEntries(AddPermissionsModifiedSinceToList, &data);
for (int32_t i = 0; i<array.Count(); ++i) {
nsAutoCString host;
bool isInBrowserElement = false;
nsAutoCString type;
uint32_t appId = 0;
array[i]->GetHost(host);
array[i]->GetIsInBrowserElement(&isInBrowserElement);
array[i]->GetType(type);
array[i]->GetAppId(&appId);
nsCOMPtr<nsIPrincipal> principal;
if (NS_FAILED(GetPrincipal(host, appId, isInBrowserElement,
getter_AddRefs(principal)))) {
NS_ERROR("GetPrincipal() failed!");
continue;
}
// AddInternal handles removal, so let it do the work...
AddInternal(
principal,
type,
nsIPermissionManager::UNKNOWN_ACTION,
0,
nsIPermissionManager::EXPIRE_NEVER, 0, 0,
nsPermissionManager::eNotify,
nsPermissionManager::eWriteToDB);
}
// now re-import any defaults as they may now be required if we just deleted
// an override.
ImportDefaults();
return NS_OK;
}
PLDHashOperator
nsPermissionManager::GetPermissionsForApp(nsPermissionManager::PermissionHashKey* entry, void* arg)
{
@ -1475,6 +1600,7 @@ nsPermissionManager::RemovePermissionsForApp(uint32_t aAppId, bool aBrowserOnly)
0,
nsIPermissionManager::EXPIRE_NEVER,
0,
0,
nsPermissionManager::eNotify,
nsPermissionManager::eNoDBOperation);
}
@ -1646,7 +1772,7 @@ nsPermissionManager::Read()
nsCOMPtr<mozIStorageStatement> stmt;
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT id, host, type, permission, expireType, expireTime, appId, isInBrowserElement "
"SELECT id, host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement "
"FROM moz_hosts"), getter_AddRefs(stmt));
NS_ENSURE_SUCCESS(rv, rv);
@ -1655,6 +1781,7 @@ nsPermissionManager::Read()
uint32_t permission;
uint32_t expireType;
int64_t expireTime;
int64_t modificationTime;
uint32_t appId;
bool isInBrowserElement;
bool hasResult;
@ -1682,15 +1809,17 @@ nsPermissionManager::Read()
permission = stmt->AsInt32(3);
expireType = stmt->AsInt32(4);
// convert into int64_t value (milliseconds)
// convert into int64_t values (milliseconds)
expireTime = stmt->AsInt64(5);
modificationTime = stmt->AsInt64(6);
if (stmt->AsInt64(6) < 0) {
if (stmt->AsInt64(7) < 0) {
readError = true;
continue;
}
appId = static_cast<uint32_t>(stmt->AsInt64(6));
isInBrowserElement = static_cast<bool>(stmt->AsInt32(7));
appId = static_cast<uint32_t>(stmt->AsInt64(7));
isInBrowserElement = static_cast<bool>(stmt->AsInt32(8));
nsCOMPtr<nsIPrincipal> principal;
nsresult rv = GetPrincipal(host, appId, isInBrowserElement, getter_AddRefs(principal));
@ -1700,7 +1829,7 @@ nsPermissionManager::Read()
}
rv = AddInternal(principal, type, permission, id, expireType, expireTime,
eDontNotify, eNoDBOperation);
modificationTime, eDontNotify, eNoDBOperation);
if (NS_FAILED(rv)) {
readError = true;
continue;
@ -1848,8 +1977,14 @@ nsPermissionManager::_DoImport(nsIInputStream *inputStream, mozIStorageConnectio
nsresult rv = GetPrincipal(lineArray[3], getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
// the import file format doesn't handle modification times, so we use
// 0, which AddInternal will convert to now()
int64_t modificationTime = 0;
rv = AddInternal(principal, lineArray[1], permission, id,
nsIPermissionManager::EXPIRE_NEVER, 0, eDontNotify, operation);
nsIPermissionManager::EXPIRE_NEVER, 0,
modificationTime,
eDontNotify, operation);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -1880,6 +2015,7 @@ nsPermissionManager::UpdateDB(OperationType aOp,
uint32_t aPermission,
uint32_t aExpireType,
int64_t aExpireTime,
int64_t aModificationTime,
uint32_t aAppId,
bool aIsInBrowserElement)
{
@ -1912,10 +2048,13 @@ nsPermissionManager::UpdateDB(OperationType aOp,
rv = aStmt->BindInt64ByIndex(5, aExpireTime);
if (NS_FAILED(rv)) break;
rv = aStmt->BindInt64ByIndex(6, aAppId);
rv = aStmt->BindInt64ByIndex(6, aModificationTime);
if (NS_FAILED(rv)) break;
rv = aStmt->BindInt64ByIndex(7, aIsInBrowserElement);
rv = aStmt->BindInt64ByIndex(7, aAppId);
if (NS_FAILED(rv)) break;
rv = aStmt->BindInt64ByIndex(8, aIsInBrowserElement);
break;
}
@ -1937,6 +2076,9 @@ nsPermissionManager::UpdateDB(OperationType aOp,
if (NS_FAILED(rv)) break;
rv = aStmt->BindInt64ByIndex(3, aExpireTime);
if (NS_FAILED(rv)) break;
rv = aStmt->BindInt64ByIndex(4, aModificationTime);
break;
}

View File

@ -37,12 +37,14 @@ public:
{
public:
PermissionEntry(int64_t aID, uint32_t aType, uint32_t aPermission,
uint32_t aExpireType, int64_t aExpireTime)
uint32_t aExpireType, int64_t aExpireTime,
int64_t aModificationTime)
: mID(aID)
, mType(aType)
, mPermission(aPermission)
, mExpireType(aExpireType)
, mExpireTime(aExpireTime)
, mModificationTime(aModificationTime)
, mNonSessionPermission(aPermission)
, mNonSessionExpireType(aExpireType)
, mNonSessionExpireTime(aExpireTime)
@ -53,6 +55,7 @@ public:
uint32_t mPermission;
uint32_t mExpireType;
int64_t mExpireTime;
int64_t mModificationTime;
uint32_t mNonSessionPermission;
uint32_t mNonSessionExpireType;
uint32_t mNonSessionExpireTime;
@ -154,7 +157,7 @@ public:
// unknown permission... return relevant data
return PermissionEntry(-1, aType, nsIPermissionManager::UNKNOWN_ACTION,
nsIPermissionManager::EXPIRE_NEVER, 0);
nsIPermissionManager::EXPIRE_NEVER, 0, 0);
}
private:
@ -200,6 +203,7 @@ public:
int64_t aID,
uint32_t aExpireType,
int64_t aExpireTime,
int64_t aModificationTime,
NotifyOperationType aNotifyOperation,
DBOperationType aDBOperation);
@ -260,6 +264,7 @@ private:
uint32_t aPermission,
uint32_t aExpireType,
int64_t aExpireTime,
int64_t aModificationTime,
uint32_t aAppId,
bool aIsInBrowserElement);
@ -299,6 +304,13 @@ private:
RemoveExpiredPermissionsForAppEnumerator(PermissionHashKey* entry,
void* nonused);
/**
* This method removes all permissions modified after the specified time.
*/
nsresult
RemoveAllModifiedSince(int64_t aModificationTime);
nsCOMPtr<nsIObserverService> mObserverService;
nsCOMPtr<nsIIDNService> mIDNService;

View File

@ -3,8 +3,15 @@
// The origin we use in most of the tests.
const TEST_ORIGIN = "example.org";
const TEST_ORIGIN_2 = "example.com";
const TEST_PERMISSION = "test-permission";
function promiseTimeout(delay) {
let deferred = Promise.defer();
do_timeout(delay, deferred.resolve);
return deferred.promise;
}
function run_test() {
run_next_test();
}
@ -28,6 +35,7 @@ add_task(function* do_test() {
conv.writeString("# this is a comment\n");
conv.writeString("\n"); // a blank line!
conv.writeString("host\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN + "\n");
conv.writeString("host\t" + TEST_PERMISSION + "\t1\t" + TEST_ORIGIN_2 + "\n");
ostream.close();
// Set the preference used by the permission manager so the file is read.
@ -92,6 +100,47 @@ add_task(function* do_test() {
do_check_eq(Ci.nsIPermissionManager.PROMPT_ACTION, findCapabilityViaEnum());
yield checkCapabilityViaDB(Ci.nsIPermissionManager.PROMPT_ACTION);
// --------------------------------------------------------------
// check default permissions and removeAllSince work as expected.
pm.removeAll(); // ensure only defaults are there.
let permURI2 = NetUtil.newURI("http://" + TEST_ORIGIN_2);
let principal2 = Services.scriptSecurityManager.getNoAppCodebasePrincipal(permURI2);
// default for both principals is allow.
do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION,
pm.testPermissionFromPrincipal(principal, TEST_PERMISSION));
do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION,
pm.testPermissionFromPrincipal(principal2, TEST_PERMISSION));
// Add a default override for TEST_ORIGIN_2 - this one should *not* be
// restored in removeAllSince()
pm.addFromPrincipal(principal2, TEST_PERMISSION, Ci.nsIPermissionManager.DENY_ACTION);
do_check_eq(Ci.nsIPermissionManager.DENY_ACTION,
pm.testPermissionFromPrincipal(principal2, TEST_PERMISSION));
yield promiseTimeout(20);
let since = Number(Date.now());
yield promiseTimeout(20);
// explicitly add a permission which overrides the default for the first
// principal - this one *should* be removed by removeAllSince.
pm.addFromPrincipal(principal, TEST_PERMISSION, Ci.nsIPermissionManager.DENY_ACTION);
do_check_eq(Ci.nsIPermissionManager.DENY_ACTION,
pm.testPermissionFromPrincipal(principal, TEST_PERMISSION));
// do a removeAllSince.
pm.removeAllSince(since);
// the default for the first principal should re-appear as we modified it
// later then |since|
do_check_eq(Ci.nsIPermissionManager.ALLOW_ACTION,
pm.testPermissionFromPrincipal(principal, TEST_PERMISSION));
// but the permission for principal2 should remain as we added that before |since|.
do_check_eq(Ci.nsIPermissionManager.DENY_ACTION,
pm.testPermissionFromPrincipal(principal2, TEST_PERMISSION));
// remove the temp file we created.
file.remove(false);
});

View File

@ -113,13 +113,25 @@ function run_test() {
);
}
let earliestNow = Number(Date.now());
// Initialize the permission manager service
var pm = Cc["@mozilla.org/permissionmanager;1"]
.getService(Ci.nsIPermissionManager);
let latestNow = Number(Date.now());
// The schema should still be 3. We want this test to be updated for each
// schema update.
do_check_eq(connection.schemaVersion, 3);
// The schema should be upgraded to 4, and a 'modificationTime' column should
// exist with all records having a value of 0.
do_check_eq(connection.schemaVersion, 4);
let select = connection.createStatement("SELECT modificationTime FROM moz_hosts")
let numMigrated = 0;
while (select.executeStep()) {
let thisModTime = select.getInt64(0);
do_check_true(thisModTime == 0, "new modifiedTime field is correct");
numMigrated += 1;
}
// check we found at least 1 record that was migrated.
do_check_true(numMigrated > 0, "we found at least 1 record that was migrated");
// This permission should always be there.
let principal = Cc["@mozilla.org/scriptsecuritymanager;1"]

View File

@ -0,0 +1,69 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that removing permissions since a specified time behaves as expected.
let test_generator = do_run_test();
function run_test() {
do_test_pending();
test_generator.next();
}
function continue_test()
{
do_run_generator(test_generator);
}
function do_run_test() {
// Set up a profile.
let profile = do_get_profile();
let pm = Services.perms;
// to help with testing edge-cases, we will arrange for .removeAllSince to
// remove *all* permissions from one principal and one permission from another.
let permURI1 = NetUtil.newURI("http://example.com");
let principal1 = Services.scriptSecurityManager.getNoAppCodebasePrincipal(permURI1);
let permURI2 = NetUtil.newURI("http://example.org");
let principal2 = Services.scriptSecurityManager.getNoAppCodebasePrincipal(permURI2);
// add a permission now - this isn't going to be removed.
pm.addFromPrincipal(principal1, "test/remove-since", 1);
// sleep briefly, then record the time - we'll remove all since then.
do_timeout(20, continue_test);
yield;
let since = Number(Date.now());
// *sob* - on Windows at least, the now recorded by nsPermissionManager.cpp
// might be a couple of ms *earlier* than what JS sees. So another sleep
// to ensure our |since| is greater than the time of the permissions we
// are now adding. Sadly this means we'll never be able to test when since
// exactly equals the modTime, but there you go...
do_timeout(20, continue_test);
yield;
// add another item - this second one should get nuked.
pm.addFromPrincipal(principal1, "test/remove-since-2", 1);
// add 2 items for the second principal - both will be removed.
pm.addFromPrincipal(principal2, "test/remove-since", 1);
pm.addFromPrincipal(principal2, "test/remove-since-2", 1);
// do the removal.
pm.removeAllSince(since);
// principal1 - the first one should remain.
do_check_eq(1, pm.testPermissionFromPrincipal(principal1, "test/remove-since"));
// but the second should have been removed.
do_check_eq(0, pm.testPermissionFromPrincipal(principal1, "test/remove-since-2"));
// principal2 - both should have been removed.
do_check_eq(0, pm.testPermissionFromPrincipal(principal2, "test/remove-since"));
do_check_eq(0, pm.testPermissionFromPrincipal(principal2, "test/remove-since-2"));
do_finish_generator_test(test_generator);
}

View File

@ -23,6 +23,7 @@ support-files =
[test_permmanager_getPermissionObject.js]
[test_permmanager_notifications.js]
[test_permmanager_removeall.js]
[test_permmanager_removesince.js]
[test_permmanager_load_invalid_entries.js]
skip-if = debug == true
[test_permmanager_idn.js]

View File

@ -84,8 +84,10 @@ CSS_KEY(-moz-isolate, _moz_isolate)
CSS_KEY(-moz-isolate-override, _moz_isolate_override)
CSS_KEY(-moz-left, _moz_left)
CSS_KEY(-moz-list, _moz_list)
CSS_KEY(-moz-mac-buttonactivetext, _moz_mac_buttonactivetext)
CSS_KEY(-moz-mac-chrome-active, _moz_mac_chrome_active)
CSS_KEY(-moz-mac-chrome-inactive, _moz_mac_chrome_inactive)
CSS_KEY(-moz-mac-defaultbuttontext, _moz_mac_defaultbuttontext)
CSS_KEY(-moz-mac-focusring, _moz_mac_focusring)
CSS_KEY(-moz-mac-fullscreen-button, _moz_mac_fullscreen_button)
CSS_KEY(-moz-mac-menuselect, _moz_mac_menuselect)

View File

@ -948,8 +948,10 @@ const KTableValue nsCSSProps::kColorKTable[] = {
eCSSKeyword__moz_hyperlinktext, NS_COLOR_MOZ_HYPERLINKTEXT,
eCSSKeyword__moz_html_cellhighlight, LookAndFeel::eColorID__moz_html_cellhighlight,
eCSSKeyword__moz_html_cellhighlighttext, LookAndFeel::eColorID__moz_html_cellhighlighttext,
eCSSKeyword__moz_mac_buttonactivetext, LookAndFeel::eColorID__moz_mac_buttonactivetext,
eCSSKeyword__moz_mac_chrome_active, LookAndFeel::eColorID__moz_mac_chrome_active,
eCSSKeyword__moz_mac_chrome_inactive, LookAndFeel::eColorID__moz_mac_chrome_inactive,
eCSSKeyword__moz_mac_defaultbuttontext, LookAndFeel::eColorID__moz_mac_defaultbuttontext,
eCSSKeyword__moz_mac_focusring, LookAndFeel::eColorID__moz_mac_focusring,
eCSSKeyword__moz_mac_menuselect, LookAndFeel::eColorID__moz_mac_menuselect,
eCSSKeyword__moz_mac_menushadow, LookAndFeel::eColorID__moz_mac_menushadow,

View File

@ -200,8 +200,11 @@ public class BrowserDB {
return sDb.getFaviconForUrl(cr, faviconURL);
}
public static String getFaviconUrlForHistoryUrl(ContentResolver cr, String url) {
return sDb.getFaviconUrlForHistoryUrl(cr, url);
/**
* Try to find a usable favicon URL in the history or bookmarks table.
*/
public static String getFaviconURLFromPageURL(ContentResolver cr, String url) {
return sDb.getFaviconURLFromPageURL(cr, url);
}
public static void updateFaviconForUrl(ContentResolver cr, String pageUri, byte[] encodedFavicon, String faviconUri) {

View File

@ -58,6 +58,8 @@ public class LocalBrowserDB {
// Calculate these once, at initialization. isLoggable is too expensive to
// have in-line in each log call.
private static final String LOGTAG = "GeckoLocalBrowserDB";
private static final Integer FAVICON_ID_NOT_FOUND = Integer.MIN_VALUE;
private static final boolean logDebug = Log.isLoggable(LOGTAG, Log.DEBUG);
protected static void debug(String message) {
if (logDebug) {
@ -998,19 +1000,38 @@ public class LocalBrowserDB {
return FaviconDecoder.decodeFavicon(b);
}
public String getFaviconUrlForHistoryUrl(ContentResolver cr, String uri) {
final Cursor c = cr.query(mHistoryUriWithProfile,
new String[] { History.FAVICON_URL },
Combined.URL + " = ?",
new String[] { uri },
null);
/**
* Try to find a usable favicon URL in the history or bookmarks table.
*/
public String getFaviconURLFromPageURL(ContentResolver cr, String uri) {
// Check first in the history table.
Cursor c = cr.query(mHistoryUriWithProfile,
new String[] { History.FAVICON_URL },
Combined.URL + " = ?",
new String[] { uri },
null);
try {
if (!c.moveToFirst()) {
return null;
if (c.moveToFirst()) {
return c.getString(c.getColumnIndexOrThrow(History.FAVICON_URL));
}
} finally {
c.close();
}
// If that fails, check in the bookmarks table.
c = cr.query(mBookmarksUriWithProfile,
new String[] { Bookmarks.FAVICON_URL },
Bookmarks.URL + " = ?",
new String[] { uri },
null);
try {
if (c.moveToFirst()) {
return c.getString(c.getColumnIndexOrThrow(Bookmarks.FAVICON_URL));
}
return c.getString(c.getColumnIndexOrThrow(History.FAVICON_URL));
return null;
} finally {
c.close();
}
@ -1027,10 +1048,66 @@ public class LocalBrowserDB {
Uri faviconsUri = getAllFaviconsUri().buildUpon().
appendQueryParameter(BrowserContract.PARAM_INSERT_IF_NEEDED, "true").build();
cr.update(faviconsUri,
values,
Favicons.URL + " = ?",
new String[] { faviconUri });
final int updated = cr.update(faviconsUri,
values,
Favicons.URL + " = ?",
new String[] { faviconUri });
if (updated == 0) {
return;
}
// After writing the encodedFavicon, ensure that the favicon_id in both the bookmark and
// history tables are also up-to-date.
final Integer id = getIDForFaviconURL(cr, faviconUri);
if (id == FAVICON_ID_NOT_FOUND) {
return;
}
updateHistoryAndBookmarksFaviconID(cr, pageUri, id);
}
/**
* Locates and returns the favicon ID of a target URL as an Integer.
*/
private Integer getIDForFaviconURL(ContentResolver cr, String faviconURL) {
final Cursor c = cr.query(mFaviconsUriWithProfile,
new String[] { Favicons._ID },
Favicons.URL + " = ? AND " + Favicons.DATA + " IS NOT NULL",
new String[] { faviconURL },
null);
try {
final int col = c.getColumnIndexOrThrow(Favicons._ID);
if (c.moveToFirst() && !c.isNull(col)) {
return c.getInt(col);
}
// IDs can be negative, so we return a sentinel value indicating "not found".
return FAVICON_ID_NOT_FOUND;
} finally {
c.close();
}
}
/**
* Update the favicon ID in the history and bookmark tables after a new
* favicon table entry is added.
*/
private void updateHistoryAndBookmarksFaviconID(ContentResolver cr, String pageURL, int id) {
final ContentValues bookmarkValues = new ContentValues();
bookmarkValues.put(Bookmarks.FAVICON_ID, id);
cr.update(mBookmarksUriWithProfile,
bookmarkValues,
Bookmarks.URL + " = ?",
new String[] { pageURL });
final ContentValues historyValues = new ContentValues();
historyValues.put(History.FAVICON_ID, id);
cr.update(mHistoryUriWithProfile,
historyValues,
History.URL + " = ?",
new String[] { pageURL });
}
public void updateThumbnailForUrl(ContentResolver cr, String uri,

View File

@ -17,6 +17,7 @@ import org.mozilla.gecko.util.GeckoJarReader;
import org.mozilla.gecko.util.NonEvictingLruCache;
import org.mozilla.gecko.util.ThreadUtils;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@ -53,8 +54,6 @@ public class Favicons {
public static final int NOT_LOADING = 0;
public static final int LOADED = 1;
public static final int FLAG_PERSIST = 2;
public static final int FLAG_SCALE = 4;
// The default Favicon to show if no other can be found.
public static Bitmap defaultFavicon;
@ -260,12 +259,15 @@ public class Favicons {
}
}
targetURL = BrowserDB.getFaviconUrlForHistoryUrl(context.getContentResolver(), pageURL);
if (targetURL == null) {
// Nothing in the history database. Fall back to the default URL and hope for the best.
targetURL = guessDefaultFaviconURL(pageURL);
// Try to find the faviconURL in the history and/or bookmarks table.
final ContentResolver resolver = context.getContentResolver();
targetURL = BrowserDB.getFaviconURLFromPageURL(resolver, pageURL);
if (targetURL != null) {
return targetURL;
}
return targetURL;
// If we still can't find it, fall back to the default URL and hope for the best.
return guessDefaultFaviconURL(pageURL);
}
/**

View File

@ -46,7 +46,6 @@ public class LoadFaviconTask {
private static final HashMap<String, LoadFaviconTask> loadsInFlight = new HashMap<>();
public static final int FLAG_PERSIST = 1;
public static final int FLAG_SCALE = 2;
private static final int MAX_REDIRECTS_TO_FOLLOW = 5;
// The default size of the buffer to use for downloading Favicons in the event no size is given
// by the server.

View File

@ -37,7 +37,7 @@ interface nsIDOMWindow;
interface nsIPermission;
interface nsISimpleEnumerator;
[scriptable, uuid(c9fec678-f194-43c9-96b0-7bd9dbdd6bb0)]
[scriptable, uuid(620d9b61-8997-4d13-aa64-ec03341dd75b)]
interface nsIPermissionManager : nsISupports
{
/**
@ -132,6 +132,11 @@ interface nsIPermissionManager : nsISupports
*/
void removeAll();
/**
* Clear all permission information added since the specified time.
*/
void removeAllSince(in int64_t since);
/**
* Test whether a website has permission to perform the given action.
* @param uri the uri to be tested

View File

@ -241,8 +241,12 @@ class Permissions(object):
rows = cursor.execute("PRAGMA table_info(moz_hosts)")
count = len(rows.fetchall())
# if the db contains 9 columns, we're using user_version 4
if count == 9:
statement = "INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0, 0, 0, 0)"
cursor.execute("PRAGMA user_version=4;")
# if the db contains 8 columns, we're using user_version 3
if count == 8:
elif count == 8:
statement = "INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0, 0, 0)"
cursor.execute("PRAGMA user_version=3;")
else:

View File

@ -40,7 +40,18 @@ http://127.0.0.1:8888 privileged
cursor.execute("PRAGMA user_version=%d;" % version)
if version == 3:
if version == 4:
cursor.execute("""CREATE TABLE IF NOT EXISTS moz_hosts (
id INTEGER PRIMARY KEY,
host TEXT,
type TEXT,
permission INTEGER,
expireType INTEGER,
expireTime INTEGER,
modificationTime INTEGER,
appId INTEGER,
isInBrowserElement INTEGER)""")
elif version == 3:
cursor.execute("""CREATE TABLE IF NOT EXISTS moz_hosts (
id INTEGER PRIMARY KEY,
host TEXT,
@ -59,7 +70,7 @@ http://127.0.0.1:8888 privileged
expireType INTEGER,
expireTime INTEGER)""")
else:
raise Exception("version must be 2 or 3")
raise Exception("version must be 2, 3 or 4")
permDB.commit()
cursor.close()
@ -149,7 +160,7 @@ http://127.0.0.1:8888 privileged
self.assertEqual(len(entries), 3)
columns = 8 if version == 3 else 6
columns = 9 if version == 4 else (8 if version == 3 else 6)
self.assertEqual(len(entries[0]), columns)
for x in range(4, columns):
self.assertEqual(entries[0][x], 0)
@ -160,6 +171,8 @@ http://127.0.0.1:8888 privileged
def test_existing_permissions_db_v3(self):
self.verify_user_version(3)
def test_existing_permissions_db_v4(self):
self.verify_user_version(4)
if __name__ == '__main__':
unittest.main()

View File

@ -14,6 +14,22 @@ button {
text-shadow: none;
}
button:hover:active {
color: -moz-mac-buttonactivetext;
}
/* When the window isn't focused, the default button background isn't drawn,
* so don't change the text color then: */
button[default="true"]:not(:-moz-window-inactive) {
color: -moz-mac-defaultbuttontext;
}
/* Likewise, when active (mousedown) but not hovering, the default button
* background isn't drawn, override the previous selector for that case: */
button[default="true"]:not(:hover):active {
color: ButtonText;
}
.button-text {
margin: 1px 0 !important;
-moz-margin-start: 3px !important;

View File

@ -126,10 +126,14 @@ public:
// colors needed by the Mac OS X theme
// foreground color of :hover:active buttons
eColorID__moz_mac_buttonactivetext,
// background color of chrome toolbars in active windows
eColorID__moz_mac_chrome_active,
// background color of chrome toolbars in inactive windows
eColorID__moz_mac_chrome_inactive,
// foreground color of default buttons
eColorID__moz_mac_defaultbuttontext,
//ring around text fields and lists
eColorID__moz_mac_focusring,
//colour used when mouse is over a menu item

View File

@ -137,6 +137,13 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
// Thanks to mpt26@student.canterbury.ac.nz for the hardcoded values that form the defaults
// if querying the Appearance Manager fails ;)
//
case eColorID__moz_mac_buttonactivetext:
case eColorID__moz_mac_defaultbuttontext:
if (nsCocoaFeatures::OnYosemiteOrLater()) {
aColor = NS_RGB(0xFF,0xFF,0xFF);
break;
}
// Otherwise fall through and return the regular button text:
case eColorID_buttontext:
case eColorID__moz_buttonhovertext:

View File

@ -66,8 +66,10 @@ var colors = {
"-moz-hyperlinktext": ["rgb(0, 0, 238)"],
"-moz-html-cellhighlight": ["rgb(212, 212, 212)"],
"-moz-html-cellhighlighttext": ["rgb(0, 0, 0)"],
"-moz-mac-buttonactivetext": ["rgb(0, 0, 0)", "rgb(255, 255, 255)"],
"-moz-mac-chrome-active": ["rgb(150, 150, 150)", "rgb(167, 167, 167)", "rgb(178, 178, 178)"],
"-moz-mac-chrome-inactive": ["rgb(202, 202, 202)", "rgb(216, 216, 216)", "rgb(225, 225, 225)"],
"-moz-mac-defaultbuttontext": ["rgb(0, 0, 0)", "rgb(255, 255, 255)"],
//"-moz-mac-focusring": ["rgb(83, 144, 210)", "rgb(95, 112, 130)", "rgb(63, 152, 221)", "rgb(108, 126, 141)"],
"-moz-mac-menuselect": ["rgb(115, 132, 153)", "rgb(127, 127, 127)", "rgb(56, 117, 215)", "rgb(255, 193, 31)", "rgb(243, 70, 72)", "rgb(255, 138, 34)", "rgb(102, 197, 71)", "rgb(140, 78, 184)"],
"-moz-mac-menushadow": ["rgb(163, 163, 163)"],

View File

@ -215,8 +215,10 @@ const char nsXPLookAndFeel::sColorPrefs[][38] =
"ui.-moz_menubarhovertext",
"ui.-moz_eventreerow",
"ui.-moz_oddtreerow",
"ui.-moz-mac-buttonactivetext",
"ui.-moz_mac_chrome_active",
"ui.-moz_mac_chrome_inactive",
"ui.-moz-mac-defaultbuttontext",
"ui.-moz-mac-focusring",
"ui.-moz-mac-menuselect",
"ui.-moz-mac-menushadow",