mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 518666 - Add Firefox win7 jump list support. r=sdwilsh, r=dao.
This commit is contained in:
parent
7dcc1cd83f
commit
b411f52ae0
@ -906,5 +906,10 @@ pref("toolbar.customization.usesheet", false);
|
||||
pref("browser.taskbar.previews.enable", true);
|
||||
pref("browser.taskbar.previews.max", 20);
|
||||
pref("browser.taskbar.previews.cachetime", 20);
|
||||
pref("browser.taskbar.lists.enabled", true);
|
||||
pref("browser.taskbar.lists.frequent.enabled", true);
|
||||
pref("browser.taskbar.lists.recent.enabled", false);
|
||||
pref("browser.taskbar.lists.maxListItemCount", 7);
|
||||
pref("browser.taskbar.lists.tasks.enabled", true);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -354,6 +354,15 @@ BrowserGlue.prototype = {
|
||||
// been warned about them yet, open the plugins update page.
|
||||
if (this._prefs.getBoolPref(PREF_PLUGINS_NOTIFYUSER))
|
||||
this._showPluginUpdatePage();
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifndef WINCE
|
||||
// For windows seven, initialize the jump list module.
|
||||
let temp = {};
|
||||
Cu.import("resource://gre/modules/wintaskbar/winJumpLists.jsm", temp);
|
||||
temp.WinTaskbarJumpList.startup();
|
||||
#endif
|
||||
#endif
|
||||
},
|
||||
|
||||
_onQuitRequest: function(aCancelQuit, aQuitType)
|
||||
|
@ -50,6 +50,7 @@ MODULE = wintaskbar
|
||||
|
||||
_WINTASKBAR_FILES = \
|
||||
preview-per-tab.jsm \
|
||||
jumpLists.jsm \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
526
browser/components/wintaskbar/jumpLists.jsm
Normal file
526
browser/components/wintaskbar/jumpLists.jsm
Normal file
@ -0,0 +1,526 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jim Mathies <jmathies@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
/**
|
||||
* Constants
|
||||
*/
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
// Prefs
|
||||
const PREF_TASKBAR_BRANCH = "browser.taskbar.lists.";
|
||||
const PREF_TASKBAR_ENABLED = "enabled";
|
||||
const PREF_TASKBAR_ITEMCOUNT = "maxListItemCount";
|
||||
const PREF_TASKBAR_FREQUENT = "frequent.enabled";
|
||||
const PREF_TASKBAR_RECENT = "recent.enabled";
|
||||
const PREF_TASKBAR_TASKS = "tasks.enabled";
|
||||
|
||||
// The amount of time between updates for jump lists
|
||||
const TIMER_TASKBAR_REFRESH = 1000*60*2; // 2 min.
|
||||
|
||||
/**
|
||||
* Exports
|
||||
*/
|
||||
|
||||
let EXPORTED_SYMBOLS = [
|
||||
"WinTaskbarJumpList",
|
||||
];
|
||||
|
||||
/**
|
||||
* Smart getters
|
||||
*/
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_prefs", function() {
|
||||
return Cc["@mozilla.org/preferences-service;1"]
|
||||
.getService(Ci.nsIPrefService)
|
||||
.getBranch(PREF_TASKBAR_BRANCH)
|
||||
.QueryInterface(Ci.nsIPrefBranch2);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_stringBundle", function() {
|
||||
return Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Ci.nsIStringBundleService)
|
||||
.createBundle("chrome://browser/locale/taskbar.properties");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "_taskbarService",
|
||||
"@mozilla.org/windows-taskbar;1",
|
||||
"nsIWinTaskbar");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "_navHistoryService",
|
||||
"@mozilla.org/browser/nav-history-service;1",
|
||||
"nsINavHistoryService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "_observerService",
|
||||
"@mozilla.org/observer-service;1",
|
||||
"nsIObserverService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "_directoryService",
|
||||
"@mozilla.org/file/directory_service;1",
|
||||
"nsIProperties");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "_ioService",
|
||||
"@mozilla.org/network/io-service;1",
|
||||
"nsIIOService");
|
||||
|
||||
/**
|
||||
* Global functions
|
||||
*/
|
||||
|
||||
function _getString(name) {
|
||||
return _stringBundle.GetStringFromName(name);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Task list configuration data object.
|
||||
|
||||
var tasksCfg = [
|
||||
/**
|
||||
* Task configuration options: title, description, args, iconIndex, open, close.
|
||||
*
|
||||
* title - Task title displayed in the list. (strings in the table are temp fillers.)
|
||||
* description - Tooltip description on the list item.
|
||||
* args - Command line args to invoke the task.
|
||||
* iconIndex - Optional win icon index into the main application for the
|
||||
* list item.
|
||||
* open - Boolean indicates if the command should be visible after the browser opens.
|
||||
* close - Boolean indicates if the command should be visible after the browser closes.
|
||||
*/
|
||||
// Open new window
|
||||
{
|
||||
get title() _getString("taskbar.tasks.newTab.label"),
|
||||
get description() _getString("taskbar.tasks.newTab.description"),
|
||||
args: "-new-tab about:blank",
|
||||
iconIndex: 0, // Fx app icon
|
||||
open: true,
|
||||
close: false, // The jump list already has an app launch icon
|
||||
},
|
||||
|
||||
// Open new tab
|
||||
{
|
||||
get title() _getString("taskbar.tasks.newWindow.label"),
|
||||
get description() _getString("taskbar.tasks.newWindow.description"),
|
||||
args: "-browser",
|
||||
iconIndex: 0, // Fx app icon
|
||||
open: true,
|
||||
close: false, // no point
|
||||
},
|
||||
];
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation
|
||||
|
||||
var WinTaskbarJumpList =
|
||||
{
|
||||
_builder: null,
|
||||
_tasks: null,
|
||||
_shuttingDown: false,
|
||||
|
||||
/**
|
||||
* Startup, shutdown, and update
|
||||
*/
|
||||
|
||||
startup: function WTBJL_startup() {
|
||||
// exit if this isn't win7 or higher.
|
||||
if (!this._initTaskbar())
|
||||
return;
|
||||
|
||||
// Store our task list config data
|
||||
this._tasks = tasksCfg;
|
||||
|
||||
// retrieve taskbar related prefs.
|
||||
this._refreshPrefs();
|
||||
|
||||
// observer for private browsing and our prefs branch
|
||||
this._initObs();
|
||||
|
||||
// jump list refresh timer
|
||||
this._initTimer();
|
||||
|
||||
// build the list
|
||||
this.update();
|
||||
},
|
||||
|
||||
update: function WTBJL_update() {
|
||||
// are we disabled via prefs? don't do anything!
|
||||
if (!this._enabled)
|
||||
return;
|
||||
|
||||
// hide jump lists when we're enabled and in private browsing mode
|
||||
if (this._inPrivateBrowsing) {
|
||||
this._deleteActiveJumpList();
|
||||
return;
|
||||
}
|
||||
|
||||
// do what we came here to do, update the taskbar jumplist
|
||||
this._buildList();
|
||||
},
|
||||
|
||||
_shutdown: function WTBJL__shutdown() {
|
||||
this._shuttingDown = true;
|
||||
this.update();
|
||||
this._free();
|
||||
},
|
||||
|
||||
/**
|
||||
* List building
|
||||
*/
|
||||
|
||||
_buildList: function WTBJL__buildList() {
|
||||
// anything to build?
|
||||
if (!this._showFrequent && !this._showRecent && !this._showTasks) {
|
||||
// don't leave the last list hanging on the taskbar.
|
||||
this._deleteActiveJumpList();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._startBuild())
|
||||
return;
|
||||
|
||||
if (this._showTasks && !this._buildTasks())
|
||||
return;
|
||||
|
||||
// Space for frequent items takes priority over recent.
|
||||
|
||||
if (this._showFrequent && !this._buildFrequent())
|
||||
return;
|
||||
|
||||
if (this._showRecent && !this._buildRecent())
|
||||
return;
|
||||
|
||||
this._commitBuild();
|
||||
},
|
||||
|
||||
/**
|
||||
* Taskbar api wrappers
|
||||
*/
|
||||
|
||||
_startBuild: function WTBJL__startBuild() {
|
||||
var removedItems = Cc["@mozilla.org/array;1"].
|
||||
createInstance(Ci.nsIMutableArray);
|
||||
this._builder.abortListBuild();
|
||||
if (this._builder.initListBuild(removedItems)) {
|
||||
// Prior to building, delete removed items from history.
|
||||
this._clearHistory(removedItems);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_commitBuild: function WTBJL__commitBuild() {
|
||||
if (!this._builder.commitListBuild())
|
||||
this._builder.abortListBuild();
|
||||
},
|
||||
|
||||
_buildTasks: function WTBJL__buildTasks() {
|
||||
var items = Cc["@mozilla.org/array;1"].
|
||||
createInstance(Ci.nsIMutableArray);
|
||||
this._tasks.forEach(function (task) {
|
||||
if ((this._shuttingDown && !task.close) || (!this._shuttingDown && !task.open))
|
||||
return;
|
||||
var item = this._getHandlerAppItem(task.title, task.description,
|
||||
task.args, task.iconIndex);
|
||||
items.appendElement(item, false);
|
||||
}, this);
|
||||
|
||||
if (items.length == 0)
|
||||
return true;
|
||||
|
||||
return this._builder.addListToBuild(this._builder.JUMPLIST_CATEGORY_TASKS, items);
|
||||
},
|
||||
|
||||
_buildCustom: function WTBJL__buildCustom(title, items) {
|
||||
if (items.length == 0)
|
||||
return true;
|
||||
return this._builder.addListToBuild(this._builder.JUMPLIST_CATEGORY_CUSTOMLIST, items, title);
|
||||
},
|
||||
|
||||
_buildFrequent: function WTBJL__buildFrequent() {
|
||||
// Windows supports default frequent and recent lists,
|
||||
// but those depend on internal windows visit tracking
|
||||
// which we don't populate. So we build our own custom
|
||||
// frequent and recent lists using our nav history data.
|
||||
|
||||
var items = Cc["@mozilla.org/array;1"].
|
||||
createInstance(Ci.nsIMutableArray);
|
||||
var list = this._getNavFrequent(this._maxItemCount);
|
||||
|
||||
if (!list || list.length == 0)
|
||||
return true;
|
||||
|
||||
// track frequent items so that we don't add them to
|
||||
// the recent list.
|
||||
this._frequentHashList = [];
|
||||
|
||||
list.forEach(function (entry) {
|
||||
let shortcut = this._getHandlerAppItem(entry.title, entry.title, entry.uri, 1);
|
||||
items.appendElement(shortcut, false);
|
||||
this._frequentHashList.push(entry.uri);
|
||||
}, this);
|
||||
return this._buildCustom(_getString("taskbar.frequent.label"), items);
|
||||
},
|
||||
|
||||
_buildRecent: function WTBJL__buildRecent() {
|
||||
var items = Cc["@mozilla.org/array;1"].
|
||||
createInstance(Ci.nsIMutableArray);
|
||||
var list = this._getNavRecent(this._maxItemCount*2);
|
||||
|
||||
if (!list || list.length == 0)
|
||||
return true;
|
||||
|
||||
for (let idx = 0; idx < list.length; idx++) {
|
||||
let entry = list[idx];
|
||||
let shortcut = this._getHandlerAppItem(entry.title, entry.title, entry.uri, 1);
|
||||
if (idx >= this._maxItemCount)
|
||||
break;
|
||||
// do not add items to recent that have already been added
|
||||
// to frequent.
|
||||
if (this._frequentHashList &&
|
||||
this._frequentHashList.indexOf(entry.uri) != -1)
|
||||
return;
|
||||
items.appendElement(shortcut, false);
|
||||
}
|
||||
return this._buildCustom(_getString("taskbar.recent.label"), items);
|
||||
},
|
||||
|
||||
_deleteActiveJumpList: function WTBJL__deleteAJL() {
|
||||
return this._builder.deleteActiveList();
|
||||
},
|
||||
|
||||
/**
|
||||
* Jump list item creation helpers
|
||||
*/
|
||||
|
||||
_getHandlerAppItem: function WTBJL__getHandlerAppItem(name, description, args, icon) {
|
||||
var file = _directoryService.get("XCurProcD", Ci.nsILocalFile);
|
||||
|
||||
// XXX where can we grab this from in the build? Do we need to?
|
||||
file.append("firefox.exe");
|
||||
|
||||
var handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
|
||||
createInstance(Ci.nsILocalHandlerApp);
|
||||
handlerApp.executable = file;
|
||||
// handlers default to the leaf name if a name is not specified
|
||||
if (name.length != 0)
|
||||
handlerApp.name = name;
|
||||
handlerApp.detailedDescription = description;
|
||||
handlerApp.appendParameter(args);
|
||||
|
||||
var item = Cc["@mozilla.org/windows-jumplistshortcut;1"].
|
||||
createInstance(Ci.nsIJumpListShortcut);
|
||||
item.app = handlerApp;
|
||||
item.iconIndex = icon;
|
||||
return item;
|
||||
},
|
||||
|
||||
_getSeparatorItem: function WTBJL__getSeparatorItem() {
|
||||
var item = Cc["@mozilla.org/windows-jumplistseparator;1"].
|
||||
createInstance(Ci.nsIJumpListSeparator);
|
||||
return item;
|
||||
},
|
||||
|
||||
/**
|
||||
* Nav history helpers
|
||||
*/
|
||||
|
||||
_getNavFrequent: function WTBJL__getNavFrequent(depth) {
|
||||
var options = _navHistoryService.getNewQueryOptions();
|
||||
var query = _navHistoryService.getNewQuery();
|
||||
|
||||
query.beginTimeReference = query.TIME_RELATIVE_NOW;
|
||||
query.beginTime = -24 * 30 * 60 * 60 * 1000000; // one month
|
||||
query.endTimeReference = query.TIME_RELATIVE_NOW;
|
||||
|
||||
options.maxResults = depth;
|
||||
options.queryType = options.QUERY_TYPE_HISTORY;
|
||||
options.sortingMode = options.SORT_BY_VISITCOUNT_DESCENDING;
|
||||
options.resultType = options.RESULT_TYPE_URI;
|
||||
|
||||
var result = _navHistoryService.executeQuery(query, options);
|
||||
|
||||
var list = [];
|
||||
|
||||
var rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
|
||||
for (let idx = 0; idx < rootNode.childCount; idx++) {
|
||||
let node = rootNode.getChild(idx);
|
||||
list.push({uri: node.uri, title: node.title});
|
||||
}
|
||||
rootNode.containerOpen = false;
|
||||
|
||||
return list;
|
||||
},
|
||||
|
||||
_getNavRecent: function WTBJL__getNavRecent(depth) {
|
||||
var options = _navHistoryService.getNewQueryOptions();
|
||||
var query = _navHistoryService.getNewQuery();
|
||||
|
||||
query.beginTimeReference = query.TIME_RELATIVE_NOW;
|
||||
query.beginTime = -48 * 60 * 60 * 1000000; // two days
|
||||
query.endTimeReference = query.TIME_RELATIVE_NOW;
|
||||
|
||||
options.maxResults = depth;
|
||||
options.queryType = options.QUERY_TYPE_HISTORY;
|
||||
options.sortingMode = options.SORT_BY_LASTMODIFIED_DESCENDING;
|
||||
options.resultType = options.RESULT_TYPE_URI;
|
||||
|
||||
var result = _navHistoryService.executeQuery(query, options);
|
||||
|
||||
var list = [];
|
||||
|
||||
var rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
|
||||
for (var idx = 0; idx < rootNode.childCount; idx++) {
|
||||
var node = rootNode.getChild(idx);
|
||||
list.push({uri: node.uri, title: node.title});
|
||||
}
|
||||
rootNode.containerOpen = false;
|
||||
|
||||
return list;
|
||||
},
|
||||
|
||||
_clearHistory: function WTBJL__clearHistory(items) {
|
||||
if (!items)
|
||||
return;
|
||||
var enum = items.enumerate();
|
||||
while (enum.hasMoreElements()) {
|
||||
let oldItem = enum.getNext().QueryInterface(Ci.nsIJumpListShortcut);
|
||||
if (oldItem) {
|
||||
try { // in case we get a bad uri
|
||||
let uriSpec = oldItem.app.getParameter(0);
|
||||
_navHistoryService.QueryInterface(Ci.nsIBrowserHistory).removePage(
|
||||
_ioService.newURI(uriSpec));
|
||||
} catch (err) { }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Prefs utilities
|
||||
*/
|
||||
|
||||
_refreshPrefs: function WTBJL__refreshPrefs() {
|
||||
this._enabled = _prefs.getBoolPref(PREF_TASKBAR_ENABLED);
|
||||
this._showFrequent = _prefs.getBoolPref(PREF_TASKBAR_FREQUENT);
|
||||
this._showRecent = _prefs.getBoolPref(PREF_TASKBAR_RECENT);
|
||||
this._showTasks = _prefs.getBoolPref(PREF_TASKBAR_TASKS);
|
||||
this._maxItemCount = _prefs.getIntPref(PREF_TASKBAR_ITEMCOUNT);
|
||||
|
||||
// retrieve the initial status of the Private Browsing mode.
|
||||
this._inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService).
|
||||
privateBrowsingEnabled;
|
||||
},
|
||||
|
||||
/**
|
||||
* Init and shutdown utilities
|
||||
*/
|
||||
|
||||
_initTaskbar: function WTBJL__initTaskbar() {
|
||||
this._builder = _taskbarService.createJumpListBuilder();
|
||||
if (!this._builder || !this._builder.available)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
_initObs: function WTBJL__initObs() {
|
||||
_observerService.addObserver(this, "private-browsing", false);
|
||||
_observerService.addObserver(this, "quit-application-granted", false);
|
||||
_prefs.addObserver("", this, false);
|
||||
},
|
||||
|
||||
_freeObs: function WTBJL__freeObs() {
|
||||
_observerService.removeObserver(this, "private-browsing");
|
||||
_observerService.removeObserver(this, "quit-application-granted");
|
||||
_prefs.removeObserver("", this);
|
||||
},
|
||||
|
||||
_initTimer: function WTBJL__initTimer(aTimer) {
|
||||
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this._timer.initWithCallback(this, TIMER_TASKBAR_REFRESH, this._timer.TYPE_REPEATING_SLACK);
|
||||
},
|
||||
|
||||
_free: function WTBJL__free() {
|
||||
this._freeObs();
|
||||
delete this._builder;
|
||||
delete this._timer;
|
||||
},
|
||||
|
||||
/**
|
||||
* Notification handlers
|
||||
*/
|
||||
|
||||
notify: function WTBJL_notify(aTimer) {
|
||||
this.update();
|
||||
},
|
||||
|
||||
observe: function WTBJL_observe(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "nsPref:changed":
|
||||
this._refreshPrefs();
|
||||
this.update();
|
||||
break;
|
||||
|
||||
case "quit-application-granted":
|
||||
this._shutdown();
|
||||
break;
|
||||
|
||||
case "browser:purge-session-history":
|
||||
this.update();
|
||||
break;
|
||||
|
||||
case "private-browsing":
|
||||
switch (aData) {
|
||||
case "enter":
|
||||
this._inPrivateBrowsing = true;
|
||||
break;
|
||||
case "exit":
|
||||
this._inPrivateBrowsing = false;
|
||||
break;
|
||||
}
|
||||
this.update();
|
||||
break;
|
||||
}
|
||||
},
|
||||
};
|
6
browser/locales/en-US/chrome/browser/taskbar.properties
Normal file
6
browser/locales/en-US/chrome/browser/taskbar.properties
Normal file
@ -0,0 +1,6 @@
|
||||
taskbar.tasks.newTab.label=Open new tab
|
||||
taskbar.tasks.newTab.description=Open a new browser tab.
|
||||
taskbar.tasks.newWindow.label=Open new window
|
||||
taskbar.tasks.newWindow.description=Open a new browser window.
|
||||
taskbar.frequent.label=Frequent
|
||||
taskbar.recent.label=Recent
|
@ -28,6 +28,7 @@
|
||||
locale/browser/shellservice.properties (%chrome/browser/shellservice.properties)
|
||||
locale/browser/tabbrowser.dtd (%chrome/browser/tabbrowser.dtd)
|
||||
locale/browser/tabbrowser.properties (%chrome/browser/tabbrowser.properties)
|
||||
locale/browser/taskbar.properties (%chrome/browser/taskbar.properties)
|
||||
locale/browser/places/places.dtd (%chrome/browser/places/places.dtd)
|
||||
locale/browser/places/places.properties (%chrome/browser/places/places.properties)
|
||||
locale/browser/places/editBookmarkOverlay.dtd (%chrome/browser/places/editBookmarkOverlay.dtd)
|
||||
|
Loading…
Reference in New Issue
Block a user