Merge mozilla-central to mozilla-inbound

This commit is contained in:
Carsten "Tomcat" Book 2013-10-16 13:11:30 +02:00
Родитель 52e19b318b fd5be0de78
Коммит cfcb3551f1
166 изменённых файлов: 2299 добавлений и 1230 удалений

Просмотреть файл

@ -1,4 +1,4 @@
{
"revision": "e811ee9b89a2a4cbb789fb88e532113dc5105e2a",
"revision": "36aa3e5d226a844b07b3e4b2219f54b549456ec1",
"repo_path": "/integration/gaia-central"
}

Просмотреть файл

@ -1082,9 +1082,10 @@ pref("devtools.toolbar.visible", false);
pref("devtools.gcli.allowSet", false);
pref("devtools.commands.dir", "");
// Disable the app manager
// Enable the app manager
pref("devtools.appmanager.enabled", true);
pref("devtools.appmanager.firstrun", true);
pref("devtools.appmanager.manifestEditor.enabled", false);
// Toolbox preferences
pref("devtools.toolbox.footer.height", 250);

Просмотреть файл

@ -19,9 +19,9 @@ let gDataNotificationInfoBar = {
},
get _log() {
let log4moz = Cu.import("resource://services-common/log4moz.js", {}).Log4Moz;
let Log = Cu.import("resource://gre/modules/Log.jsm", {}).Log;
delete this._log;
return this._log = log4moz.repository.getLogger("Services.DataReporting.InfoBar");
return this._log = Log.repository.getLogger("Services.DataReporting.InfoBar");
},
init: function() {

Просмотреть файл

@ -473,6 +473,9 @@ var PlacesCommandHook = {
////////////////////////////////////////////////////////////////////////////////
//// HistoryMenu
XPCOMUtils.defineLazyModuleGetter(this, "RecentlyClosedTabsAndWindowsMenuUtils",
"resource:///modules/sessionstore/RecentlyClosedTabsAndWindowsMenuUtils.jsm");
// View for the history menu.
function HistoryMenu(aPopupShowingEvent) {
// Workaround for Bug 610187. The sidebar does not include all the Places
@ -531,45 +534,8 @@ HistoryMenu.prototype = {
undoMenu.removeAttribute("disabled");
// populate menu
var undoItems = JSON.parse(SessionStore.getClosedTabData(window));
for (var i = 0; i < undoItems.length; i++) {
var m = document.createElement("menuitem");
m.setAttribute("label", undoItems[i].title);
if (undoItems[i].image) {
let iconURL = undoItems[i].image;
// don't initiate a connection just to fetch a favicon (see bug 467828)
if (/^https?:/.test(iconURL))
iconURL = "moz-anno:favicon:" + iconURL;
m.setAttribute("image", iconURL);
}
m.setAttribute("class", "menuitem-iconic bookmark-item menuitem-with-favicon");
m.setAttribute("value", i);
m.setAttribute("oncommand", "undoCloseTab(" + i + ");");
// Set the targetURI attribute so it will be shown in tooltip and trigger
// onLinkHovered. SessionStore uses one-based indexes, so we need to
// normalize them.
let tabData = undoItems[i].state;
let activeIndex = (tabData.index || tabData.entries.length) - 1;
if (activeIndex >= 0 && tabData.entries[activeIndex])
m.setAttribute("targetURI", tabData.entries[activeIndex].url);
m.addEventListener("click", this._undoCloseMiddleClick, false);
if (i == 0)
m.setAttribute("key", "key_undoCloseTab");
undoPopup.appendChild(m);
}
// "Restore All Tabs"
var strings = gNavigatorBundle;
undoPopup.appendChild(document.createElement("menuseparator"));
m = undoPopup.appendChild(document.createElement("menuitem"));
m.id = "menu_restoreAllTabs";
m.setAttribute("label", strings.getString("menuRestoreAllTabs.label"));
m.addEventListener("command", function() {
for (var i = 0; i < undoItems.length; i++)
undoCloseTab(0);
}, false);
let tabsFragment = RecentlyClosedTabsAndWindowsMenuUtils.getTabsFragment(window, "menuitem");
undoPopup.appendChild(tabsFragment);
},
toggleRecentlyClosedWindows: function PHM_toggleRecentlyClosedWindows() {
@ -607,45 +573,8 @@ HistoryMenu.prototype = {
undoMenu.removeAttribute("disabled");
// populate menu
let undoItems = JSON.parse(SessionStore.getClosedWindowData());
for (let i = 0; i < undoItems.length; i++) {
let undoItem = undoItems[i];
let otherTabsCount = undoItem.tabs.length - 1;
let label = (otherTabsCount == 0) ? menuLabelStringSingleTab
: PluralForm.get(otherTabsCount, menuLabelString);
let menuLabel = label.replace("#1", undoItem.title)
.replace("#2", otherTabsCount);
let m = document.createElement("menuitem");
m.setAttribute("label", menuLabel);
let selectedTab = undoItem.tabs[undoItem.selected - 1];
if (selectedTab.image) {
let iconURL = selectedTab.image;
// don't initiate a connection just to fetch a favicon (see bug 467828)
if (/^https?:/.test(iconURL))
iconURL = "moz-anno:favicon:" + iconURL;
m.setAttribute("image", iconURL);
}
m.setAttribute("class", "menuitem-iconic bookmark-item menuitem-with-favicon");
m.setAttribute("oncommand", "undoCloseWindow(" + i + ");");
// Set the targetURI attribute so it will be shown in tooltip.
// SessionStore uses one-based indexes, so we need to normalize them.
let activeIndex = (selectedTab.index || selectedTab.entries.length) - 1;
if (activeIndex >= 0 && selectedTab.entries[activeIndex])
m.setAttribute("targetURI", selectedTab.entries[activeIndex].url);
if (i == 0)
m.setAttribute("key", "key_undoCloseWindow");
undoPopup.appendChild(m);
}
// "Open All in Windows"
undoPopup.appendChild(document.createElement("menuseparator"));
let m = undoPopup.appendChild(document.createElement("menuitem"));
m.id = "menu_restoreAllWindows";
m.setAttribute("label", gNavigatorBundle.getString("menuRestoreAllWindows.label"));
m.setAttribute("oncommand",
"for (var i = 0; i < " + undoItems.length + "; i++) undoCloseWindow();");
let windowsFragment = RecentlyClosedTabsAndWindowsMenuUtils.getWindowsFragment(window, "menuitem");
undoPopup.appendChild(windowsFragment);
},
toggleTabsFromOtherComputers: function PHM_toggleTabsFromOtherComputers() {

Просмотреть файл

@ -7127,7 +7127,14 @@ function safeModeRestart()
let rv = Services.prompt.confirmEx(window, promptTitle, promptMessage,
buttonFlags, restartText, null, null,
null, {});
if (rv == 0) {
if (rv != 0)
return;
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
if (!cancelQuit.data) {
Services.startup.restartInSafeMode(Ci.nsIAppStartup.eAttemptQuit);
}
}

Просмотреть файл

@ -1671,9 +1671,26 @@
throw new Error("Invalid argument: " + aCloseTabs);
}
if (tabsToClose <= 1 ||
aCloseTabs != this.closingTabsEnum.ALL ||
!Services.prefs.getBoolPref("browser.tabs.warnOnClose"))
let maxUndo =
Services.prefs.getIntPref("browser.sessionstore.max_tabs_undo");
let warnOnCloseOtherTabs =
Services.prefs.getBoolPref("browser.tabs.warnOnCloseOtherTabs");
let warnOnCloseWindow =
Services.prefs.getBoolPref("browser.tabs.warnOnClose");
let isWindowClosing = aCloseTabs == this.closingTabsEnum.ALL;
let skipWarning =
// 1) If there is only one tab to close, we'll never warn the user.
tabsToClose <= 1 ||
// 2) If the whole window is going to be closed, don't warn the
// user if the user has browser.tabs.warnOnClose set to false.
(isWindowClosing && !warnOnCloseWindow) ||
// 3) If the number of tabs are less than the undo threshold
// or if the user has specifically opted-in to ignoring
// this warning via the warnOnCloseOtherTabs pref.
(!isWindowClosing && (!warnOnCloseOtherTabs ||
tabsToClose <= maxUndo));
if (skipWarning)
return true;
var ps = Services.prompt;
@ -1702,8 +1719,11 @@
var reallyClose = (buttonPressed == 0);
// don't set the pref unless they press OK and it's false
if (reallyClose && !warnOnClose.value)
Services.prefs.setBoolPref("browser.tabs.warnOnClose", false);
if (reallyClose && !warnOnClose.value) {
let pref = isWindowClosing ? "browser.tabs.warnOnClose" :
"browser.tabs.warnOnCloseOtherTabs";
Services.prefs.setBoolPref(pref, false);
}
return reallyClose;
]]>

Просмотреть файл

@ -199,6 +199,7 @@ support-files =
[browser_bug880101.js]
[browser_bug882977.js]
[browser_bug887515.js]
[browser_bug896291_closeMaxSessionStoreTabs.js]
[browser_bug902156.js]
[browser_canonizeURL.js]
[browser_clearplugindata.html]

Просмотреть файл

@ -0,0 +1,108 @@
function numClosedTabs()
Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore).
getNumberOfTabsClosedLast(window);
let originalTab;
let maxTabsUndo;
let maxTabsUndoPlusOne;
let acceptRemoveAllTabsDialogListener;
let cancelRemoveAllTabsDialogListener;
function test() {
waitForExplicitFinish();
Services.prefs.setBoolPref("browser.tabs.animate", false);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("browser.tabs.animate");
originalTab.linkedBrowser.loadURI("about:blank");
originalTab = null;
});
// Creating and throwing away this tab guarantees that the
// number of tabs closed in the previous tab-close operation is 1.
let throwaway_tab = gBrowser.addTab("http://mochi.test:8888/");
gBrowser.removeTab(throwaway_tab);
let undoCloseTabElement = document.getElementById("context_undoCloseTab");
updateTabContextMenu();
is(undoCloseTabElement.label, undoCloseTabElement.getAttribute("singletablabel"),
"The label should be showing that the command will restore a single tab");
originalTab = gBrowser.selectedTab;
gBrowser.selectedBrowser.loadURI("http://mochi.test:8888/");
maxTabsUndo = Services.prefs.getIntPref("browser.sessionstore.max_tabs_undo");
maxTabsUndoPlusOne = maxTabsUndo + 1;
let numberOfTabsLoaded = 0;
for (let i = 0; i < maxTabsUndoPlusOne; i++) {
let tab = gBrowser.addTab("http://mochi.test:8888/");
let browser = gBrowser.getBrowserForTab(tab);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
if (++numberOfTabsLoaded == maxTabsUndoPlusOne)
verifyUndoMultipleClose();
}, true);
}
}
function verifyUndoMultipleClose() {
info("all tabs opened and loaded");
cancelRemoveAllTabsDialogListener = new WindowListener("chrome://global/content/commonDialog.xul", cancelRemoveAllTabsDialog);
Services.wm.addListener(cancelRemoveAllTabsDialogListener);
gBrowser.removeAllTabsBut(originalTab);
}
function cancelRemoveAllTabsDialog(domWindow) {
ok(true, "dialog appeared in response to multiple tab close action");
domWindow.document.documentElement.cancelDialog();
Services.wm.removeListener(cancelRemoveAllTabsDialogListener);
acceptRemoveAllTabsDialogListener = new WindowListener("chrome://global/content/commonDialog.xul", acceptRemoveAllTabsDialog);
Services.wm.addListener(acceptRemoveAllTabsDialogListener);
waitForCondition(function () gBrowser.tabs.length == 1 + maxTabsUndoPlusOne, function verifyCancel() {
is(gBrowser.tabs.length, 1 + maxTabsUndoPlusOne, /* The '1 +' is for the original tab */
"All tabs should still be open after the 'Cancel' option on the prompt is chosen");
gBrowser.removeAllTabsBut(originalTab);
}, "Waited too long to find that no tabs were closed.");
}
function acceptRemoveAllTabsDialog(domWindow) {
ok(true, "dialog appeared in response to multiple tab close action");
domWindow.document.documentElement.acceptDialog();
Services.wm.removeListener(acceptRemoveAllTabsDialogListener);
waitForCondition(function () gBrowser.tabs.length == 1, function verifyAccept() {
is(gBrowser.tabs.length, 1,
"All other tabs should be closed after the 'OK' option on the prompt is chosen");
finish();
}, "Waited too long for the other tabs to be closed.");
}
function WindowListener(aURL, aCallback) {
this.callback = aCallback;
this.url = aURL;
}
WindowListener.prototype = {
onOpenWindow: function(aXULWindow) {
var domWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
var self = this;
domWindow.addEventListener("load", function() {
domWindow.removeEventListener("load", arguments.callee, false);
info("domWindow.document.location.href: " + domWindow.document.location.href);
if (domWindow.document.location.href != self.url)
return;
// Allow other window load listeners to execute before passing to callback
executeSoon(function() {
self.callback(domWindow);
});
}, false);
},
onCloseWindow: function(aXULWindow) {},
onWindowTitleChange: function(aXULWindow, aNewTitle) {}
}

Просмотреть файл

@ -58,10 +58,10 @@ function test() {
waitForExplicitFinish();
let ns = {};
Components.utils.import("resource://services-common/log4moz.js", ns);
rootLogger = ns.Log4Moz.repository.rootLogger;
dumpAppender = new ns.Log4Moz.DumpAppender();
dumpAppender.level = ns.Log4Moz.Level.All;
Components.utils.import("resource://gre/modules/Log.jsm", ns);
rootLogger = ns.Log.repository.rootLogger;
dumpAppender = new ns.Log.DumpAppender();
dumpAppender.level = ns.Log.Level.All;
rootLogger.addAppender(dumpAppender);
let notification = document.getElementById("global-notificationbox");

Просмотреть файл

@ -0,0 +1,139 @@
/* 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/. */
this.EXPORTED_SYMBOLS = ["RecentlyClosedTabsAndWindowsMenuUtils"];
const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var Ci = Components.interfaces;
var Cc = Components.classes;
var Cr = Components.results;
var Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
let navigatorBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
this.RecentlyClosedTabsAndWindowsMenuUtils = {
/**
* Builds up a document fragment of UI items for the recently closed tabs.
* @param aWindow
* The window that the tabs were closed in.
* @param aTagName
* The tag name that will be used when creating the UI items.
* @returns A document fragment with UI items for each recently closed tab.
*/
getTabsFragment: function(aWindow, aTagName) {
let doc = aWindow.document;
let fragment = doc.createDocumentFragment();
if (ss.getClosedTabCount(aWindow) != 0) {
let closedTabs = JSON.parse(ss.getClosedTabData(aWindow));
for (let i = 0; i < closedTabs.length; i++) {
let element = doc.createElementNS(kNSXUL, aTagName);
element.setAttribute("label", closedTabs[i].title);
if (closedTabs[i].image) {
setImage(closedTabs[i], element);
}
element.setAttribute("value", i);
if (aTagName == "menuitem") {
element.setAttribute("class", "menuitem-iconic bookmark-item menuitem-with-favicon");
}
element.setAttribute("oncommand", "undoCloseTab(" + i + ");");
// Set the targetURI attribute so it will be shown in tooltip and trigger
// onLinkHovered. SessionStore uses one-based indexes, so we need to
// normalize them.
let tabData = closedTabs[i].state;
let activeIndex = (tabData.index || tabData.entries.length) - 1;
if (activeIndex >= 0 && tabData.entries[activeIndex]) {
element.setAttribute("targetURI", tabData.entries[activeIndex].url);
}
element.addEventListener("click", this._undoCloseMiddleClick, false);
if (i == 0)
element.setAttribute("key", "key_undoCloseTab");
fragment.appendChild(element);
}
fragment.appendChild(doc.createElementNS(kNSXUL, "menuseparator"));
let restoreAllTabs = fragment.appendChild(doc.createElementNS(kNSXUL, aTagName));
restoreAllTabs.setAttribute("label", navigatorBundle.GetStringFromName("menuRestoreAllTabs.label"));
restoreAllTabs.addEventListener("command", function() {
for (var i = 0; i < closedTabs.length; i++)
undoCloseTab(0);
}, false);
}
return fragment;
},
/**
* Builds up a document fragment of UI items for the recently closed windows.
* @param aWindow
* A window that can be used to create the elements and document fragment.
* @param aTagName
* The tag name that will be used when creating the UI items.
* @returns A document fragment with UI items for each recently closed window.
*/
getWindowsFragment: function(aWindow, aTagName) {
let closedWindowData = JSON.parse(ss.getClosedWindowData());
let fragment = aWindow.document.createDocumentFragment();
if (closedWindowData.length != 0) {
let menuLabelString = navigatorBundle.GetStringFromName("menuUndoCloseWindowLabel");
let menuLabelStringSingleTab =
navigatorBundle.GetStringFromName("menuUndoCloseWindowSingleTabLabel");
let doc = aWindow.document;
for (let i = 0; i < closedWindowData.length; i++) {
let undoItem = closedWindowData[i];
let otherTabsCount = undoItem.tabs.length - 1;
let label = (otherTabsCount == 0) ? menuLabelStringSingleTab
: PluralForm.get(otherTabsCount, menuLabelString);
let menuLabel = label.replace("#1", undoItem.title)
.replace("#2", otherTabsCount);
let item = doc.createElementNS(kNSXUL, aTagName);
item.setAttribute("label", menuLabel);
let selectedTab = undoItem.tabs[undoItem.selected - 1];
if (selectedTab.image) {
setImage(selectedTab, item);
}
if (aTagName == "menuitem") {
item.setAttribute("class", "menuitem-iconic bookmark-item menuitem-with-favicon");
}
item.setAttribute("oncommand", "undoCloseWindow(" + i + ");");
// Set the targetURI attribute so it will be shown in tooltip.
// SessionStore uses one-based indexes, so we need to normalize them.
let activeIndex = (selectedTab.index || selectedTab.entries.length) - 1;
if (activeIndex >= 0 && selectedTab.entries[activeIndex])
item.setAttribute("targetURI", selectedTab.entries[activeIndex].url);
if (i == 0)
item.setAttribute("key", "key_undoCloseWindow");
fragment.appendChild(item);
}
// "Open All in Windows"
fragment.appendChild(doc.createElementNS(kNSXUL, "menuseparator"));
let restoreAllWindows = fragment.appendChild(doc.createElementNS(kNSXUL, aTagName));
restoreAllWindows.setAttribute("label", navigatorBundle.GetStringFromName("menuRestoreAllWindows.label"));
restoreAllWindows.setAttribute("oncommand",
"for (var i = 0; i < " + closedWindowData.length + "; i++) undoCloseWindow();");
}
return fragment;
},
};
function setImage(aItem, aElement) {
let iconURL = aItem.image;
// don't initiate a connection just to fetch a favicon (see bug 467828)
if (/^https?:/.test(iconURL))
iconURL = "moz-anno:favicon:" + iconURL;
aElement.setAttribute("image", iconURL);
}

Просмотреть файл

@ -202,15 +202,6 @@ let SessionSaverInternal = {
}
}
#ifndef XP_MACOSX
// Don't save invalid states.
// Looks like we currently have private windows, only.
if (state.windows.length == 0) {
stopWatchCancel("COLLECT_DATA_MS", "COLLECT_DATA_LONGEST_OP_MS");
return;
}
#endif
// Remove private windows from the list of closed windows.
for (let i = state._closedWindows.length - 1; i >= 0; i--) {
if (state._closedWindows[i].isPrivate) {
@ -218,6 +209,13 @@ let SessionSaverInternal = {
}
}
// Make sure that we keep the previous session if we started with a single
// private window and no non-private windows have been opened, yet.
if (state.deferredInitialState) {
state.windows = state.deferredInitialState.windows || [];
delete state.deferredInitialState;
}
#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

Просмотреть файл

@ -352,7 +352,7 @@ let SessionStoreInternal = {
/* ........ Public Getters .............. */
get canRestoreLastSession() {
return this._lastSessionState;
return !!this._lastSessionState;
},
set canRestoreLastSession(val) {
@ -728,7 +728,7 @@ let SessionStoreInternal = {
// We're starting with a single private window. Save the state we
// actually wanted to restore so that we can do it later in case
// the user opens another, non-private window.
this._deferredInitialState = aInitialState;
this._deferredInitialState = gSessionStartup.state;
// Nothing to restore now, notify observers things are complete.
Services.obs.notifyObservers(null, NOTIFY_WINDOWS_RESTORED, "");
@ -1346,6 +1346,9 @@ let SessionStoreInternal = {
// Don't include the last session state in getBrowserState().
delete state.lastSessionState;
// Don't include any deferred initial state.
delete state.deferredInitialState;
return this._toJSONString(state);
},
@ -2074,6 +2077,13 @@ let SessionStoreInternal = {
state.lastSessionState = this._lastSessionState;
}
// If we were called by the SessionSaver and started with only a private
// window we want to pass the deferred initial state to not lose the
// previous session.
if (this._deferredInitialState) {
state.deferredInitialState = this._deferredInitialState;
}
return state;
},
@ -3524,6 +3534,14 @@ let SessionStoreInternal = {
* @returns [defaultState, state]
*/
_prepDataForDeferredRestore: function ssi_prepDataForDeferredRestore(state) {
// Make sure that we don't modify the global state as provided by
// nsSessionStartup.state. Converting the object to a JSON string and
// parsing it again is the easiest way to do that, although not the most
// efficient one. Deferred sessions that don't have automatic session
// restore enabled tend to be a lot smaller though so that this shouldn't
// be a big perf hit.
state = JSON.parse(JSON.stringify(state));
let defaultState = { windows: [], selectedWindow: 1 };
state.selectedWindow = state.selectedWindow || 1;
@ -3715,9 +3733,9 @@ let SessionStoreInternal = {
* @param aTab the which has been restored
*/
_sendTabRestoredNotification: function ssi_sendTabRestoredNotification(aTab) {
let event = aTab.ownerDocument.createEvent("Events");
event.initEvent("SSTabRestored", true, false);
aTab.dispatchEvent(event);
let event = aTab.ownerDocument.createEvent("Events");
event.initEvent("SSTabRestored", true, false);
aTab.dispatchEvent(event);
},
/**
@ -4248,7 +4266,7 @@ let TabState = {
}
if (disallow.length > 0) {
tabData.disallow = disallow.join(",");
tabData.disallow = disallow.join(",");
}
// Save text and scroll data.
@ -4395,9 +4413,9 @@ let TabState = {
if (!options || !options.omitDocShellCapabilities) {
let disallow = DocShellCapabilities.collect(browser.docShell);
if (disallow.length > 0)
tabData.disallow = disallow.join(",");
tabData.disallow = disallow.join(",");
else if (tabData.disallow)
delete tabData.disallow;
delete tabData.disallow;
}
// Save tab attributes.
@ -4604,5 +4622,3 @@ let TabState = {
return "";
}
};

Просмотреть файл

@ -17,6 +17,7 @@ EXTRA_JS_MODULES = [
'DocumentUtils.jsm',
'Messenger.jsm',
'PrivacyLevel.jsm',
'RecentlyClosedTabsAndWindowsMenuUtils.jsm',
'SessionCookies.jsm',
'SessionHistory.jsm',
'SessionMigration.jsm',

Просмотреть файл

@ -24,24 +24,31 @@ AppValidator.prototype.warning = function (message) {
this.warnings.push(message);
}
AppValidator.prototype._getPackagedManifestURL = function () {
AppValidator.prototype._getPackagedManifestFile = function () {
let manifestFile = FileUtils.File(this.project.location);
if (!manifestFile.exists()) {
this.error(strings.GetStringFromName("validator.nonExistingFolder"));
return;
return null;
}
if (!manifestFile.isDirectory()) {
this.error(strings.GetStringFromName("validator.expectProjectFolder"));
return;
return null;
}
manifestFile.append("manifest.webapp");
if (!manifestFile.exists() || !manifestFile.isFile()) {
this.error(strings.GetStringFromName("validator.wrongManifestFileName"));
return;
return null;
}
return manifestFile;
};
AppValidator.prototype._getPackagedManifestURL = function () {
let manifestFile = this._getPackagedManifestFile();
if (!manifestFile) {
return null;
}
return Services.io.newFileURI(manifestFile).spec;
}
};
AppValidator.prototype._fetchManifest = function (manifestURL) {
let deferred = promise.defer();
@ -54,7 +61,7 @@ AppValidator.prototype._fetchManifest = function (manifestURL) {
deferred.resolve(null);
return deferred.promise;
}
req.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
req.onload = (function () {
let manifest = null;
try {

Просмотреть файл

@ -0,0 +1,106 @@
/* 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";
Cu.import("resource://gre/modules/osfile.jsm");
const {VariablesView} =
Cu.import("resource:///modules/devtools/VariablesView.jsm", {});
const VARIABLES_VIEW_URL =
"chrome://browser/content/devtools/widgets/VariablesView.xul";
function ManifestEditor(project) {
this.project = project;
this._onContainerReady = this._onContainerReady.bind(this);
this._onEval = this._onEval.bind(this);
this._onSwitch = this._onSwitch.bind(this);
this._onDelete = this._onDelete.bind(this);
}
ManifestEditor.prototype = {
get manifest() { return this.project.manifest; },
show: function(containerElement) {
let deferred = promise.defer();
let iframe = document.createElement("iframe");
iframe.addEventListener("load", function onIframeLoad() {
iframe.removeEventListener("load", onIframeLoad, true);
deferred.resolve(iframe.contentWindow);
}, true);
iframe.setAttribute("src", VARIABLES_VIEW_URL);
iframe.classList.add("variables-view");
containerElement.appendChild(iframe);
return deferred.promise.then(this._onContainerReady);
},
_onContainerReady: function(varWindow) {
let variablesContainer = varWindow.document.querySelector("#variables");
let editor = this.editor = new VariablesView(variablesContainer);
editor.onlyEnumVisible = true;
editor.eval = this._onEval;
editor.switch = this._onSwitch;
editor.delete = this._onDelete;
return this.update();
},
_onEval: function(evalString) {
let manifest = this.manifest;
eval("manifest" + evalString);
this.update();
},
_onSwitch: function(variable, newName) {
let manifest = this.manifest;
let newSymbolicName = variable.ownerView.symbolicName +
"['" + newName + "']";
if (newSymbolicName == variable.symbolicName) {
return;
}
let evalString = "manifest" + newSymbolicName + " = " +
"manifest" + variable.symbolicName + ";" +
"delete manifest" + variable.symbolicName;
eval(evalString);
this.update();
},
_onDelete: function(variable) {
let manifest = this.manifest;
let evalString = "delete manifest" + variable.symbolicName;
eval(evalString);
},
update: function() {
this.editor.createHierarchy();
this.editor.rawObject = this.manifest;
this.editor.commitHierarchy();
// Wait until the animation from commitHierarchy has completed
let deferred = promise.defer();
setTimeout(deferred.resolve, this.editor.lazyEmptyDelay + 1);
return deferred.promise;
},
save: function() {
if (this.project.type == "packaged") {
let validator = new AppValidator(this.project);
let manifestFile = validator._getPackagedManifestFile();
let path = manifestFile.path;
let encoder = new TextEncoder();
let data = encoder.encode(JSON.stringify(this.manifest, null, 2));
return OS.File.writeAtomic(path, data, { tmpPath: path + ".tmp" });
}
return promise.resolve();
}
};

Просмотреть файл

@ -15,9 +15,12 @@ const {AppValidator} = require("devtools/app-manager/app-validator");
const {Services} = Cu.import("resource://gre/modules/Services.jsm");
const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm");
const {installHosted, installPackaged, getTargetForApp} = require("devtools/app-actor-front");
const {EventEmitter} = Cu.import("resource:///modules/devtools/shared/event-emitter.js");
const promise = require("sdk/core/promise");
const MANIFEST_EDITOR_ENABLED = "devtools.appmanager.manifestEditor.enabled";
window.addEventListener("message", function(event) {
try {
let json = JSON.parse(event.data);
@ -35,12 +38,20 @@ window.addEventListener("message", function(event) {
}, false);
let UI = {
isReady: false,
onload: function() {
if (Services.prefs.getBoolPref(MANIFEST_EDITOR_ENABLED)) {
document.querySelector("#lense").setAttribute("manifest-editable", "");
}
this.template = new Template(document.body, AppProjects.store, Utils.l10n);
this.template.start();
AppProjects.load().then(() => {
AppProjects.store.object.projects.forEach(UI.validate);
this.isReady = true;
this.emit("ready");
});
},
@ -88,11 +99,11 @@ let UI = {
let urlInput = document.querySelector("#url-input");
let manifestURL = urlInput.value;
AppProjects.addHosted(manifestURL)
.then(function (project) {
UI.validate(project);
UI.selectProject(project.location);
});
return AppProjects.addHosted(manifestURL)
.then(function (project) {
UI.validate(project);
UI.selectProject(project.location);
});
},
_getLocalIconURL: function(project, manifest) {
@ -121,7 +132,6 @@ let UI = {
return validation.validate()
.then(function () {
if (validation.manifest) {
project.name = validation.manifest.name;
project.icon = UI._getLocalIconURL(project, validation.manifest);
project.manifest = validation.manifest;
}
@ -153,7 +163,10 @@ let UI = {
update: function(button, location) {
button.disabled = true;
let project = AppProjects.get(location);
this.validate(project)
this.manifestEditor.save()
.then(() => {
return this.validate(project);
})
.then(() => {
// Install the app to the device if we are connected,
// and there is no error
@ -386,5 +399,16 @@ let UI = {
let lense = document.querySelector("#lense");
lense.setAttribute("template-for", template);
this.template._processFor(lense);
let project = projects[idx];
this._showManifestEditor(project).then(() => this.emit("project-selected"));
},
}
_showManifestEditor: function(project) {
let editorContainer = document.querySelector("#lense .manifest-editor");
this.manifestEditor = new ManifestEditor(project);
return this.manifestEditor.show(editorContainer);
}
};
EventEmitter.decorate(UI);

Просмотреть файл

@ -14,6 +14,10 @@
<base href="chrome://browser/content/devtools/app-manager/"></base>
<title>&projects.title;</title>
<link rel="stylesheet" href="chrome://browser/skin/devtools/app-manager/projects.css" type="text/css"/>
<script type="application/javascript;version=1.8" src="utils.js"></script>
<script type="application/javascript;version=1.8" src="projects.js"></script>
<script type="application/javascript;version=1.8" src="template.js"></script>
<script type="application/javascript;version=1.8" src="manifest-editor.js"></script>
</head>
<body onload="UI.onload()">
@ -25,7 +29,7 @@
<div id="new-packaged-project" onclick="UI.addPackaged()" title="&projects.addPackagedTooltip;">&projects.addPackaged;</div>
<div id="new-hosted-project">&projects.addHosted;
<form onsubmit="UI.addHosted(); return false;" id="new-hosted-project-wrapper">
<input value="" id="url-input" type="url" required="true" pattern="https?://.+" placeholder="&projects.hostedManifestPlaceHolder2;" size="50" />
<input value="" id="url-input" type="url" required="true" pattern="(https?|chrome)://.+" placeholder="&projects.hostedManifestPlaceHolder2;" size="50" />
<div onclick="UI.addHosted()" id="new-hosted-project-click" title="&projects.addHostedTooltip;"></div>
<input type="submit" hidden="true"></input>
</form>
@ -40,7 +44,7 @@
<img class="project-item-icon" template='{"type":"attribute","path":"icon","name":"src"}' />
<div class="project-item-meta">
<div class="button-remove" onclick="UI.remove(this.dataset.location, event)" template='{"type":"attribute","path":"location","name":"data-location"}' title="&projects.removeAppFromList;"></div>
<strong template='{"type":"textContent","path":"name"}'></strong>
<strong template='{"type":"textContent","path":"manifest.name"}'></strong>
<span class="project-item-type" template='{"type":"textContent","path":"type"}'></span>
<p class="project-item-description" template='{"type":"textContent","path":"manifest.description"}'></p>
<div template='{"type":"attribute","path":"validationStatus","name":"status"}'>
@ -56,9 +60,9 @@
<div class="project-details" template='{"type":"attribute","path":"validationStatus","name":"status"}'>
<div class="project-header">
<img class="project-icon" template='{"type":"attribute","path":"icon","name":"src"}'/>
<div class="project-details">
<div class="project-metadata">
<div class="project-title">
<h1 template='{"type":"textContent","path":"name"}'></h1>
<h1 template='{"type":"textContent","path":"manifest.name"}'></h1>
<div class="project-status" template='{"type":"attribute","path":"validationStatus","name":"status"}'>
<p class="project-validation" template='{"type":"textContent","path":"validationStatus"}'></p>
<p class="project-type" template='{"type":"textContent","path":"type"}'></p>
@ -76,11 +80,9 @@
<div class="project-errors" template='{"type":"textContent","path":"errors"}'></div>
<div class="project-warnings" template='{"type":"textContent","path":"warnings"}'></div>
</div>
<div class="manifest-editor">
<h2>&projects.manifestEditor;</h2>
</div>
</div>
</template>
<script type="application/javascript;version=1.8" src="utils.js"></script>
<script type="application/javascript;version=1.8" src="projects.js"></script>
<script type="application/javascript;version=1.8" src="template.js"></script>
</html>

Просмотреть файл

@ -0,0 +1,6 @@
[DEFAULT]
support-files =
head.js
hosted_app.manifest
[browser_manifest_editor.js]

Просмотреть файл

@ -0,0 +1,54 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const {Services} = Cu.import("resource://gre/modules/Services.jsm");
const MANIFEST_EDITOR_ENABLED = "devtools.appmanager.manifestEditor.enabled";
function test() {
waitForExplicitFinish();
Task.spawn(function() {
Services.prefs.setBoolPref(MANIFEST_EDITOR_ENABLED, true);
let tab = yield openAppManager();
yield selectProjectsPanel();
yield addSampleHostedApp();
yield showSampleProjectDetails();
yield changeManifestValue("name", "the best app");
yield removeSampleHostedApp();
yield removeTab(tab);
Services.prefs.setBoolPref(MANIFEST_EDITOR_ENABLED, false);
finish();
});
}
function changeManifestValue(key, value) {
return Task.spawn(function() {
let manifestWindow = getManifestWindow();
let manifestEditor = getProjectsWindow().UI.manifestEditor;
let propElem = manifestWindow.document
.querySelector("[id ^= '" + key + "']");
is(propElem.querySelector(".name").value, key,
"Key doesn't match expected value");
let valueElem = propElem.querySelector(".value");
EventUtils.sendMouseEvent({ type: "mousedown" }, valueElem, manifestWindow);
let valueInput = propElem.querySelector(".element-value-input");
valueInput.value = '"' + value + '"';
EventUtils.sendKey("RETURN", manifestWindow);
// Wait until the animation from commitHierarchy has completed
yield waitForTime(manifestEditor.editor.lazyEmptyDelay + 1);
// Elements have all been replaced, re-select them
propElem = manifestWindow.document.querySelector("[id ^= '" + key + "']");
valueElem = propElem.querySelector(".value");
is(valueElem.value, '"' + value + '"',
"Value doesn't match expected value");
is(manifestEditor.manifest[key], value,
"Manifest doesn't contain expected value");
});
}

Просмотреть файл

@ -0,0 +1,152 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const {utils: Cu} = Components;
const {Promise: promise} =
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
const {devtools} =
Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const {require} = devtools;
const {AppProjects} = require("devtools/app-manager/app-projects");
const APP_MANAGER_URL = "about:app-manager";
const TEST_BASE =
"chrome://mochitests/content/browser/browser/devtools/app-manager/test/";
const HOSTED_APP_MANIFEST = TEST_BASE + "hosted_app.manifest";
function addTab(url, targetWindow = window) {
info("Adding tab: " + url);
let deferred = promise.defer();
let targetBrowser = targetWindow.gBrowser;
targetWindow.focus();
let tab = targetBrowser.selectedTab = targetBrowser.addTab(url);
let linkedBrowser = tab.linkedBrowser;
linkedBrowser.addEventListener("load", function onLoad() {
linkedBrowser.removeEventListener("load", onLoad, true);
info("Tab added and finished loading: " + url);
deferred.resolve(tab);
}, true);
return deferred.promise;
}
function removeTab(tab, targetWindow = window) {
info("Removing tab.");
let deferred = promise.defer();
let targetBrowser = targetWindow.gBrowser;
let tabContainer = targetBrowser.tabContainer;
tabContainer.addEventListener("TabClose", function onClose(aEvent) {
tabContainer.removeEventListener("TabClose", onClose, false);
info("Tab removed and finished closing.");
deferred.resolve();
}, false);
targetBrowser.removeTab(tab);
return deferred.promise;
}
function openAppManager() {
return addTab(APP_MANAGER_URL);
}
function addSampleHostedApp() {
info("Adding sample hosted app");
let projectsWindow = getProjectsWindow();
let projectsDocument = projectsWindow.document;
let url = projectsDocument.querySelector("#url-input");
url.value = HOSTED_APP_MANIFEST;
return projectsWindow.UI.addHosted();
}
function removeSampleHostedApp() {
info("Removing sample hosted app");
return AppProjects.remove(HOSTED_APP_MANIFEST);
}
function getProjectsWindow() {
return content.document.querySelector(".projects-panel").contentWindow;
}
function getManifestWindow() {
return getProjectsWindow().document.querySelector(".variables-view")
.contentWindow;
}
function waitForProjectsPanel(deferred = promise.defer()) {
info("Wait for projects panel");
let projectsWindow = getProjectsWindow();
let projectsUI = projectsWindow.UI;
if (!projectsUI) {
projectsWindow.addEventListener("load", function onLoad() {
projectsWindow.removeEventListener("load", onLoad);
waitForProjectsPanel(deferred);
});
return deferred.promise;
}
if (projectsUI.isReady) {
deferred.resolve();
return deferred.promise;
}
projectsUI.once("ready", deferred.resolve);
return deferred.promise;
}
function selectProjectsPanel() {
return Task.spawn(function() {
let projectsButton = content.document.querySelector(".projects-button");
EventUtils.sendMouseEvent({ type: "click" }, projectsButton, content);
yield waitForProjectsPanel();
});
}
function waitForProjectSelection() {
info("Wait for project selection");
let deferred = promise.defer();
getProjectsWindow().UI.once("project-selected", deferred.resolve);
return deferred.promise;
}
function selectFirstProject() {
return Task.spawn(function() {
let projectsFrame = content.document.querySelector(".projects-panel");
let projectsWindow = projectsFrame.contentWindow;
let projectsDoc = projectsWindow.document;
let projectItem = projectsDoc.querySelector(".project-item");
EventUtils.sendMouseEvent({ type: "click" }, projectItem, projectsWindow);
yield waitForProjectSelection();
});
}
function showSampleProjectDetails() {
return Task.spawn(function() {
yield selectProjectsPanel();
yield selectFirstProject();
});
}
function waitForTick() {
let deferred = promise.defer();
executeSoon(deferred.resolve);
return deferred.promise;
}
function waitForTime(aDelay) {
let deferred = promise.defer();
setTimeout(deferred.resolve, aDelay);
return deferred.promise;
}

Просмотреть файл

@ -4,5 +4,5 @@
# 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/.
BROWSER_CHROME_MANIFESTS += ['browser.ini']
MOCHITEST_CHROME_MANIFESTS += ['chrome.ini']

Просмотреть файл

@ -100,19 +100,26 @@ function test() {
ok(!testScope.expanded,
"The testScope should remember it is collapsed after it is reshown.");
EventUtils.sendMouseEvent({ type: "mousedown", button: 1 },
testScope.target.querySelector(".title"),
aPanel.panelWin);
ok(!testScope.expanded,
"Clicking the testScope title with the right mouse button should't expand it.");
EventUtils.sendMouseEvent({ type: "mousedown" },
testScope.target.querySelector(".title"),
aPanel.panelWin);
ok(testScope.expanded,
"Clicking the testScope tilte should expand it.");
"Clicking the testScope title should expand it.");
EventUtils.sendMouseEvent({ type: "mousedown" },
testScope.target.querySelector(".title"),
aPanel.panelWin);
ok(!testScope.expanded,
"Clicking again the testScope tilte should collapse it.");
"Clicking again the testScope title should collapse it.");
closeDebuggerAndFinish(aPanel);
});

Просмотреть файл

@ -45,6 +45,6 @@
<section id="connecting">
<p><img src="chrome://browser/skin/tabbrowser/loading.png"></img> &connecting;</p>
</section>
<footer>&help;</footer>
<footer>&help2;</footer>
</body>
</html>

Просмотреть файл

@ -743,6 +743,15 @@ InspectorPanel.prototype = {
}
},
/**
* Trigger a high-priority layout change for things that need to be
* updated immediately
*/
immediateLayoutChange: function Inspector_immediateLayoutChange()
{
this.emit("layout-change");
},
/**
* Schedule a low-priority change event for things like paint
* and resize.

Просмотреть файл

@ -17,7 +17,7 @@ function test() {
}
function getInspectorProp(aName)
function getInspectorComputedProp(aName)
{
let computedview = inspector.sidebar.getWindowForTab("computedview").computedview.view;
for each (let view in computedview.propertyViews) {
@ -28,6 +28,19 @@ function test() {
return null;
}
function getInspectorRuleProp(aName)
{
let ruleview = inspector.sidebar.getWindowForTab("ruleview").ruleview.view;
let inlineStyles = ruleview._elementStyle.rules[0];
for each (let prop in inlineStyles.textProps) {
if (prop.name == aName) {
return prop;
}
}
return null;
}
function runInspectorTests(aInspector)
{
inspector = aInspector;
@ -40,59 +53,97 @@ function test() {
testDiv.style.fontSize = "10px";
// Start up the style inspector panel...
inspector.once("computed-view-refreshed", stylePanelTests);
inspector.once("computed-view-refreshed", computedStylePanelTests);
inspector.selection.setNode(testDiv);
});
}
function stylePanelTests()
function computedStylePanelTests()
{
let computedview = inspector.sidebar.getWindowForTab("computedview").computedview;
ok(computedview, "Style Panel has a cssHtmlTree");
let propView = getInspectorProp("font-size");
let propView = getInspectorComputedProp("font-size");
is(propView.value, "10px", "Style inspector should be showing the correct font size.");
inspector.once("computed-view-refreshed", stylePanelAfterChange);
testDiv.style.cssText = "font-size: 15px; color: red;";
testDiv.style.fontSize = "15px";
// FIXME: This shouldn't be needed but as long as we don't fix the bug
// where the rule/computed views are not updated when the selected node's
// styles change, it has to stay here
inspector.emit("layout-change");
// Wait until layout-change fires from mutation to skip earlier refresh event
inspector.once("layout-change", () => {
inspector.once("computed-view-refreshed", computedStylePanelAfterChange);
});
}
function stylePanelAfterChange()
function computedStylePanelAfterChange()
{
let propView = getInspectorProp("font-size");
let propView = getInspectorComputedProp("font-size");
is(propView.value, "15px", "Style inspector should be showing the new font size.");
stylePanelNotActive();
let propView = getInspectorComputedProp("color");
is(propView.value, "#F00", "Style inspector should be showing the new color.");
computedStylePanelNotActive();
}
function stylePanelNotActive()
function computedStylePanelNotActive()
{
// Tests changes made while the style panel is not active.
inspector.sidebar.select("ruleview");
executeSoon(function() {
inspector.once("computed-view-refreshed", stylePanelAfterSwitch);
testDiv.style.fontSize = "20px";
inspector.sidebar.select("computedview");
testDiv.style.fontSize = "20px";
testDiv.style.color = "blue";
testDiv.style.textAlign = "center";
// FIXME: This shouldn't be needed but as long as we don't fix the bug
// where the rule/computed views are not updated when the selected node's
// styles change, it has to stay here
inspector.emit("layout-change");
});
inspector.once("computed-view-refreshed", computedStylePanelAfterSwitch);
inspector.sidebar.select("computedview");
}
function stylePanelAfterSwitch()
function computedStylePanelAfterSwitch()
{
let propView = getInspectorProp("font-size");
is(propView.value, "20px", "Style inspector should be showing the newest font size.");
let propView = getInspectorComputedProp("font-size");
is(propView.value, "20px", "Style inspector should be showing the new font size.");
let propView = getInspectorComputedProp("color");
is(propView.value, "#00F", "Style inspector should be showing the new color.");
let propView = getInspectorComputedProp("text-align");
is(propView.value, "center", "Style inspector should be showing the new text align.");
rulePanelTests();
}
function rulePanelTests()
{
inspector.sidebar.select("ruleview");
let ruleview = inspector.sidebar.getWindowForTab("ruleview").ruleview;
ok(ruleview, "Style Panel has a ruleview");
let propView = getInspectorRuleProp("text-align");
is(propView.value, "center", "Style inspector should be showing the new text align.");
testDiv.style.textAlign = "right";
testDiv.style.color = "lightgoldenrodyellow";
testDiv.style.fontSize = "3em";
testDiv.style.textTransform = "uppercase";
inspector.once("rule-view-refreshed", rulePanelAfterChange);
}
function rulePanelAfterChange()
{
let propView = getInspectorRuleProp("text-align");
is(propView.value, "right", "Style inspector should be showing the new text align.");
let propView = getInspectorRuleProp("color");
is(propView.value, "#FAFAD2", "Style inspector should be showing the new color.")
let propView = getInspectorRuleProp("font-size");
is(propView.value, "3em", "Style inspector should be showing the new font size.");
let propView = getInspectorRuleProp("text-transform");
is(propView.value, "uppercase", "Style inspector should be showing the new text transform.");
finishTest();
}

Просмотреть файл

@ -85,3 +85,4 @@ browser.jar:
content/browser/devtools/app-manager/index.xul (app-manager/content/index.xul)
content/browser/devtools/app-manager/index.js (app-manager/content/index.js)
content/browser/devtools/app-manager/help.xhtml (app-manager/content/help.xhtml)
content/browser/devtools/app-manager/manifest-editor.js (app-manager/content/manifest-editor.js)

Просмотреть файл

@ -387,6 +387,7 @@ MarkupView.prototype = {
* Mutation observer used for included nodes.
*/
_mutationObserver: function(aMutations) {
let requiresLayoutChange = false;
for (let mutation of aMutations) {
let type = mutation.type;
let target = mutation.target;
@ -409,6 +410,11 @@ MarkupView.prototype = {
}
if (type === "attributes" || type === "characterData") {
container.update();
// Auto refresh style properties on selected node when they change.
if (type === "attributes" && container.selected) {
requiresLayoutChange = true;
}
} else if (type === "childList") {
container.childrenDirty = true;
// Update the children to take care of changes in the DOM
@ -417,6 +423,10 @@ MarkupView.prototype = {
this._updateChildren(container, {flash: true});
}
}
if (requiresLayoutChange) {
this._inspector.immediateLayoutChange();
}
this._waitForChildren().then(() => {
this._flashMutatedNodes(aMutations);
this._inspector.emit("markupmutation");

Просмотреть файл

@ -32,7 +32,7 @@ Parser.prototype = {
* @param string aSource
* The source text content.
*/
get: function P_get(aUrl, aSource) {
get: function(aUrl, aSource) {
// Try to use the cached AST nodes, to avoid useless parsing operations.
if (this._cache.has(aUrl)) {
return this._cache.get(aUrl);
@ -89,7 +89,7 @@ Parser.prototype = {
/**
* Clears all the parsed sources from cache.
*/
clearCache: function P_clearCache() {
clearCache: function() {
this._cache.clear();
},
@ -99,7 +99,7 @@ Parser.prototype = {
* @param String aUrl
* The URL of the source that is being cleared.
*/
clearSource: function P_clearSource(aUrl) {
clearSource: function(aUrl) {
this._cache.delete(aUrl);
},
@ -121,17 +121,10 @@ SyntaxTreesPool.prototype = {
/**
* @see SyntaxTree.prototype.getNamedFunctionDefinitions
*/
getNamedFunctionDefinitions: function STP_getNamedFunctionDefinitions(aSubstring) {
getNamedFunctionDefinitions: function(aSubstring) {
return this._call("getNamedFunctionDefinitions", aSubstring);
},
/**
* @see SyntaxTree.prototype.getFunctionAtLocation
*/
getFunctionAtLocation: function STP_getFunctionAtLocation(aLine, aColumn) {
return this._call("getFunctionAtLocation", [aLine, aColumn]);
},
/**
* Finds the offset and length of the script containing the specified offset
* relative to its parent source.
@ -141,7 +134,7 @@ SyntaxTreesPool.prototype = {
* @return array
* The offset and length relative to the enclosing script.
*/
getScriptInfo: function STP_getScriptInfo(aOffset) {
getScriptInfo: function(aOffset) {
for (let { offset, length } of this._trees) {
if (offset <= aOffset && offset + length >= aOffset) {
return [offset, length];
@ -160,7 +153,7 @@ SyntaxTreesPool.prototype = {
* @return array
* The results given by all known syntax trees.
*/
_call: function STP__call(aFunction, aParams) {
_call: function(aFunction, aParams) {
let results = [];
let requestId = aFunction + aParams; // Cache all the things!
@ -221,7 +214,7 @@ SyntaxTree.prototype = {
* All the matching function declarations and expressions, as
* { functionName, functionLocation ... } object hashes.
*/
getNamedFunctionDefinitions: function ST_getNamedFunctionDefinitions(aSubstring) {
getNamedFunctionDefinitions: function(aSubstring) {
let lowerCaseToken = aSubstring.toLowerCase();
let store = [];
@ -230,7 +223,7 @@ SyntaxTree.prototype = {
* Callback invoked for each function declaration node.
* @param Node aNode
*/
onFunctionDeclaration: function STW_onFunctionDeclaration(aNode) {
onFunctionDeclaration: function(aNode) {
let functionName = aNode.id.name;
if (functionName.toLowerCase().contains(lowerCaseToken)) {
store.push({
@ -244,31 +237,27 @@ SyntaxTree.prototype = {
* Callback invoked for each function expression node.
* @param Node aNode
*/
onFunctionExpression: function STW_onFunctionExpression(aNode) {
let parent = aNode._parent;
let functionName, inferredName, inferredChain, inferredLocation;
onFunctionExpression: function(aNode) {
// Function expressions don't necessarily have a name.
if (aNode.id) {
functionName = aNode.id.name;
}
let functionName = aNode.id ? aNode.id.name : "";
let functionLocation = aNode.loc || null;
// Infer the function's name from an enclosing syntax tree node.
if (parent) {
let inferredInfo = ParserHelpers.inferFunctionExpressionInfo(aNode);
inferredName = inferredInfo.name;
inferredChain = inferredInfo.chain;
inferredLocation = inferredInfo.loc;
}
let inferredInfo = ParserHelpers.inferFunctionExpressionInfo(aNode);
let inferredName = inferredInfo.name;
let inferredChain = inferredInfo.chain;
let inferredLocation = inferredInfo.loc;
// Current node may be part of a larger assignment expression stack.
if (parent.type == "AssignmentExpression") {
this.onFunctionExpression(parent);
if (aNode._parent.type == "AssignmentExpression") {
this.onFunctionExpression(aNode._parent);
}
if ((functionName && functionName.toLowerCase().contains(lowerCaseToken)) ||
(inferredName && inferredName.toLowerCase().contains(lowerCaseToken))) {
store.push({
functionName: functionName,
functionLocation: aNode.loc,
functionLocation: functionLocation,
inferredName: inferredName,
inferredChain: inferredChain,
inferredLocation: inferredLocation
@ -280,19 +269,16 @@ SyntaxTree.prototype = {
* Callback invoked for each arrow expression node.
* @param Node aNode
*/
onArrowExpression: function STW_onArrowExpression(aNode) {
let parent = aNode._parent;
let inferredName, inferredChain, inferredLocation;
onArrowExpression: function(aNode) {
// Infer the function's name from an enclosing syntax tree node.
let inferredInfo = ParserHelpers.inferFunctionExpressionInfo(aNode);
inferredName = inferredInfo.name;
inferredChain = inferredInfo.chain;
inferredLocation = inferredInfo.loc;
let inferredName = inferredInfo.name;
let inferredChain = inferredInfo.chain;
let inferredLocation = inferredInfo.loc;
// Current node may be part of a larger assignment expression stack.
if (parent.type == "AssignmentExpression") {
this.onFunctionExpression(parent);
if (aNode._parent.type == "AssignmentExpression") {
this.onFunctionExpression(aNode._parent);
}
if (inferredName && inferredName.toLowerCase().contains(lowerCaseToken)) {
@ -308,100 +294,6 @@ SyntaxTree.prototype = {
return store;
},
/**
* Gets the "new" or "call" expression at the specified location.
*
* @param number aLine
* The line in the source.
* @param number aColumn
* The column in the source.
* @return object
* An { functionName, functionLocation } object hash,
* or null if nothing is found at the specified location.
*/
getFunctionAtLocation: function STW_getFunctionAtLocation([aLine, aColumn]) {
let self = this;
let func = null;
SyntaxTreeVisitor.walk(this.AST, {
/**
* Callback invoked for each node.
* @param Node aNode
*/
onNode: function STW_onNode(aNode) {
// Make sure the node is part of a branch that's guaranteed to be
// hovered. Otherwise, return true to abruptly halt walking this
// syntax tree branch. This is a really efficient optimization.
return ParserHelpers.isWithinLines(aNode, aLine);
},
/**
* Callback invoked for each identifier node.
* @param Node aNode
*/
onIdentifier: function STW_onIdentifier(aNode) {
// Make sure the identifier itself is hovered.
let hovered = ParserHelpers.isWithinBounds(aNode, aLine, aColumn);
if (!hovered) {
return;
}
// Make sure the identifier is part of a "new" expression or
// "call" expression node.
let expression = ParserHelpers.getEnclosingFunctionExpression(aNode);
if (!expression) {
return;
}
// Found an identifier node that is part of a "new" expression or
// "call" expression node. However, it may be an argument, not a callee.
if (ParserHelpers.isFunctionCalleeArgument(aNode)) {
// It's an argument.
if (self.functionIdentifiersCache.has(aNode.name)) {
// It's a function as an argument.
func = {
functionName: aNode.name,
functionLocation: aNode.loc || aNode._parent.loc
};
}
return;
}
// Found a valid "new" expression or "call" expression node.
func = {
functionName: aNode.name,
functionLocation: ParserHelpers.getFunctionCalleeInfo(expression).loc
};
// Abruptly halt walking the syntax tree.
this.break = true;
}
});
return func;
},
/**
* Gets all the function identifiers in this syntax tree (both the
* function names and their inferred names).
*
* @return array
* An array of strings.
*/
get functionIdentifiersCache() {
if (this._functionIdentifiersCache) {
return this._functionIdentifiersCache;
}
let functionDefinitions = this.getNamedFunctionDefinitions("");
let functionIdentifiers = new Set();
for (let { functionName, inferredName } of functionDefinitions) {
functionIdentifiers.add(functionName);
functionIdentifiers.add(inferredName);
}
return this._functionIdentifiersCache = functionIdentifiers;
},
AST: null,
url: "",
length: 0,
@ -422,7 +314,7 @@ let ParserHelpers = {
* @return boolean
* True if the line and column is contained in the node's bounds.
*/
isWithinLines: function PH_isWithinLines(aNode, aLine) {
isWithinLines: function(aNode, aLine) {
// Not all nodes have location information attached.
if (!aNode.loc) {
return this.isWithinLines(aNode._parent, aLine);
@ -442,7 +334,7 @@ let ParserHelpers = {
* @return boolean
* True if the line and column is contained in the node's bounds.
*/
isWithinBounds: function PH_isWithinBounds(aNode, aLine, aColumn) {
isWithinBounds: function(aNode, aLine, aColumn) {
// Not all nodes have location information attached.
if (!aNode.loc) {
return this.isWithinBounds(aNode._parent, aLine, aColumn);
@ -453,16 +345,16 @@ let ParserHelpers = {
/**
* Try to infer a function expression's name & other details based on the
* enclosing VariableDeclarator, AssignmentExpression or ObjectExpression node.
* enclosing VariableDeclarator, AssignmentExpression or ObjectExpression.
*
* @param Node aNode
* The function expression node to get the name for.
* @return object
* The inferred function name, or empty string can't infer name,
* The inferred function name, or empty string can't infer the name,
* along with the chain (a generic "context", like a prototype chain)
* and location if available.
*/
inferFunctionExpressionInfo: function PH_inferFunctionExpressionInfo(aNode) {
inferFunctionExpressionInfo: function(aNode) {
let parent = aNode._parent;
// A function expression may be defined in a variable declarator,
@ -480,11 +372,11 @@ let ParserHelpers = {
// e.g. foo = function(){} or foo.bar = function(){}, in which case it is
// possible to infer the assignee name ("foo" and "bar" respectively).
if (parent.type == "AssignmentExpression") {
let assigneeChain = this.getAssignmentExpressionAssigneeChain(parent);
let assigneeLeaf = assigneeChain.pop();
let propertyChain = this.getMemberExpressionPropertyChain(parent.left);
let propertyLeaf = propertyChain.pop();
return {
name: assigneeLeaf,
chain: assigneeChain,
name: propertyLeaf,
chain: propertyChain,
loc: parent.left.loc
};
}
@ -493,13 +385,13 @@ let ParserHelpers = {
// e.g. { foo: function(){} }, then it is possible to infer the name
// from the corresponding property.
if (parent.type == "ObjectExpression") {
let propertyDetails = this.getObjectExpressionPropertyKeyForValue(aNode);
let propertyKey = this.getObjectExpressionPropertyKeyForValue(aNode);
let propertyChain = this.getObjectExpressionPropertyChain(parent);
let propertyLeaf = propertyDetails.name;
let propertyLeaf = propertyKey.name;
return {
name: propertyLeaf,
chain: propertyChain,
loc: propertyDetails.loc
loc: propertyKey.loc
};
}
@ -512,17 +404,18 @@ let ParserHelpers = {
},
/**
* Gets details about an object expression's property to which a specified
* value is assigned. For example, the node returned for the value 42 in
* "{ foo: { bar: 42 } }" is "bar".
* Gets the name of an object expression's property to which a specified
* value is assigned.
*
* For example, if aNode represents the "bar" identifier in a hypothetical
* "{ foo: bar }" object expression, the returned node is the "foo" identifier.
*
* @param Node aNode
* The value node assigned to a property in an object expression.
* The value node in an object expression.
* @return object
* The details about the assignee property node.
* The key identifier node in the object expression.
*/
getObjectExpressionPropertyKeyForValue:
function PH_getObjectExpressionPropertyKeyForValue(aNode) {
getObjectExpressionPropertyKeyForValue: function(aNode) {
let parent = aNode._parent;
if (parent.type != "ObjectExpression") {
return null;
@ -535,9 +428,12 @@ let ParserHelpers = {
},
/**
* Gets an object expression property chain to its parent variable declarator.
* For example, the chain to "baz" in "foo = { bar: { baz: { } } }" is
* ["foo", "bar", "baz"].
* Gets an object expression's property chain to its parent
* variable declarator or assignment expression, if available.
*
* For example, if aNode represents the "baz: {}" object expression in a
* hypothetical "foo = { bar: { baz: {} } }" assignment expression, the
* returned chain is ["foo", "bar", "baz"].
*
* @param Node aNode
* The object expression node to begin the scan from.
@ -546,59 +442,56 @@ let ParserHelpers = {
* @return array
* The chain to the parent variable declarator, as strings.
*/
getObjectExpressionPropertyChain:
function PH_getObjectExpressionPropertyChain(aNode, aStore = []) {
getObjectExpressionPropertyChain: function(aNode, aStore = []) {
switch (aNode.type) {
case "ObjectExpression":
this.getObjectExpressionPropertyChain(aNode._parent, aStore);
let propertyDetails = this.getObjectExpressionPropertyKeyForValue(aNode);
if (propertyDetails) {
aStore.push(this.getObjectExpressionPropertyKeyForValue(aNode).name);
let propertyKey = this.getObjectExpressionPropertyKeyForValue(aNode);
if (propertyKey) {
aStore.push(propertyKey.name);
}
break;
// Handle "foo.bar = { ... }" since it's commonly used when defining an
// object's prototype methods; for example: "Foo.prototype = { ... }".
// Handle "var foo = { ... }" variable declarators.
case "VariableDeclarator":
aStore.push(aNode.id.name);
break;
// Handle "foo.bar = { ... }" assignment expressions, since they're
// commonly used when defining an object's prototype methods; e.g:
// "Foo.prototype = { ... }".
case "AssignmentExpression":
this.getAssignmentExpressionAssigneeChain(aNode, aStore);
this.getMemberExpressionPropertyChain(aNode.left, aStore);
break;
// Additionally handle stuff like "foo = bar.baz({ ... })", because it's
// commonly used in prototype-based inheritance in many libraries;
// for example: "Foo.Bar = Baz.extend({ ... })".
// commonly used in prototype-based inheritance in many libraries; e.g:
// "Foo = Bar.extend({ ... })".
case "NewExpression":
case "CallExpression":
this.getObjectExpressionPropertyChain(aNode._parent, aStore);
break;
// End of the chain.
case "VariableDeclarator":
aStore.push(aNode.id.name);
break;
}
return aStore;
},
/**
* Gets the assignee property chain in an assignment expression.
* For example, the chain in "foo.bar.baz = 42" is ["foo", "bar", "baz"].
* Gets a member expression's property chain.
*
* For example, if aNode represents a hypothetical "foo.bar.baz"
* member expression, the returned chain ["foo", "bar", "baz"].
*
* More complex expressions like foo.bar().baz are intentionally not handled.
*
* @param Node aNode
* The assignment expression node to begin the scan from.
* @param array aStore
* The chain to store the nodes into.
* The member expression node to begin the scan from.
* @param array aStore [optional]
* The chain to store the nodes into.
* @return array
* The full assignee chain, as strings.
* The full member chain, as strings.
*/
getAssignmentExpressionAssigneeChain:
function PH_getAssignmentExpressionAssigneeChain(aNode, aStore = []) {
getMemberExpressionPropertyChain: function(aNode, aStore = []) {
switch (aNode.type) {
case "AssignmentExpression":
this.getAssignmentExpressionAssigneeChain(aNode.left, aStore);
break;
case "MemberExpression":
this.getAssignmentExpressionAssigneeChain(aNode.object, aStore);
this.getAssignmentExpressionAssigneeChain(aNode.property, aStore);
this.getMemberExpressionPropertyChain(aNode.object, aStore);
this.getMemberExpressionPropertyChain(aNode.property, aStore);
break;
case "ThisExpression":
// Such expressions may appear in an assignee chain, for example
@ -610,80 +503,6 @@ let ParserHelpers = {
break;
}
return aStore;
},
/**
* Gets the "new" expression or "call" expression containing the specified
* node. If the node is not enclosed in either of these expression types,
* null is returned.
*
* @param Node aNode
* The child node of an enclosing "new" expression or "call" expression.
* @return Node
* The enclosing "new" expression or "call" expression node, or
* null if nothing is found.
*/
getEnclosingFunctionExpression:
function PH_getEnclosingFunctionExpression(aNode) {
switch (aNode.type) {
case "NewExpression":
case "CallExpression":
return aNode;
case "MemberExpression":
case "Identifier":
return this.getEnclosingFunctionExpression(aNode._parent);
default:
return null;
}
},
/**
* Gets the name and { line, column } location of a "new" expression or
* "call" expression's callee node.
*
* @param Node aNode
* The "new" expression or "call" expression to get the callee info for.
* @return object
* An object containing the name and location as properties, or
* null if nothing is found.
*/
getFunctionCalleeInfo: function PH_getFunctionCalleeInfo(aNode) {
switch (aNode.type) {
case "NewExpression":
case "CallExpression":
return this.getFunctionCalleeInfo(aNode.callee);
case "MemberExpression":
return this.getFunctionCalleeInfo(aNode.property);
case "Identifier":
return {
name: aNode.name,
loc: aNode.loc || (aNode._parent || {}).loc
};
default:
return null;
}
},
/**
* Determines if an identifier node is part of a "new" expression or
* "call" expression's callee arguments.
*
* @param Node aNode
* The node to determine if part of a function's arguments.
* @return boolean
* True if the identifier is an argument, false otherwise.
*/
isFunctionCalleeArgument: function PH_isFunctionCalleeArgument(aNode) {
if (!aNode._parent) {
return false;
}
switch (aNode._parent.type) {
case "NewExpression":
case "CallExpression":
return aNode._parent.arguments.indexOf(aNode) != -1;
default:
return this.isFunctionCalleeArgument(aNode._parent);
}
}
};
@ -707,7 +526,7 @@ let SyntaxTreeVisitor = {
* A map of all the callbacks to invoke when passing through certain
* types of noes (e.g: onFunctionDeclaration, onBlockStatement etc.).
*/
walk: function STV_walk(aTree, aCallbacks) {
walk: function(aTree, aCallbacks) {
this[aTree.type](aTree, aCallbacks);
},
@ -725,7 +544,7 @@ let SyntaxTreeVisitor = {
* body: [ Statement ];
* }
*/
Program: function STV_Program(aNode, aCallbacks) {
Program: function(aNode, aCallbacks) {
if (aCallbacks.onProgram) {
aCallbacks.onProgram(aNode);
}
@ -739,7 +558,7 @@ let SyntaxTreeVisitor = {
*
* interface Statement <: Node { }
*/
Statement: function STV_Statement(aNode, aParent, aCallbacks) {
Statement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -762,7 +581,7 @@ let SyntaxTreeVisitor = {
* type: "EmptyStatement";
* }
*/
EmptyStatement: function STV_EmptyStatement(aNode, aParent, aCallbacks) {
EmptyStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -786,7 +605,7 @@ let SyntaxTreeVisitor = {
* body: [ Statement ];
* }
*/
BlockStatement: function STV_BlockStatement(aNode, aParent, aCallbacks) {
BlockStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -813,7 +632,7 @@ let SyntaxTreeVisitor = {
* expression: Expression;
* }
*/
ExpressionStatement: function STV_ExpressionStatement(aNode, aParent, aCallbacks) {
ExpressionStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -840,7 +659,7 @@ let SyntaxTreeVisitor = {
* alternate: Statement | null;
* }
*/
IfStatement: function STV_IfStatement(aNode, aParent, aCallbacks) {
IfStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -870,7 +689,7 @@ let SyntaxTreeVisitor = {
* body: Statement;
* }
*/
LabeledStatement: function STV_LabeledStatement(aNode, aParent, aCallbacks) {
LabeledStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -896,7 +715,7 @@ let SyntaxTreeVisitor = {
* label: Identifier | null;
* }
*/
BreakStatement: function STV_BreakStatement(aNode, aParent, aCallbacks) {
BreakStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -923,7 +742,7 @@ let SyntaxTreeVisitor = {
* label: Identifier | null;
* }
*/
ContinueStatement: function STV_ContinueStatement(aNode, aParent, aCallbacks) {
ContinueStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -951,7 +770,7 @@ let SyntaxTreeVisitor = {
* body: Statement;
* }
*/
WithStatement: function STV_WithStatement(aNode, aParent, aCallbacks) {
WithStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -981,7 +800,7 @@ let SyntaxTreeVisitor = {
* lexical: boolean;
* }
*/
SwitchStatement: function STV_SwitchStatement(aNode, aParent, aCallbacks) {
SwitchStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1009,7 +828,7 @@ let SyntaxTreeVisitor = {
* argument: Expression | null;
* }
*/
ReturnStatement: function STV_ReturnStatement(aNode, aParent, aCallbacks) {
ReturnStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1036,7 +855,7 @@ let SyntaxTreeVisitor = {
* argument: Expression;
* }
*/
ThrowStatement: function STV_ThrowStatement(aNode, aParent, aCallbacks) {
ThrowStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1064,7 +883,7 @@ let SyntaxTreeVisitor = {
* finalizer: BlockStatement | null;
* }
*/
TryStatement: function STV_TryStatement(aNode, aParent, aCallbacks) {
TryStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1099,7 +918,7 @@ let SyntaxTreeVisitor = {
* body: Statement;
* }
*/
WhileStatement: function STV_WhileStatement(aNode, aParent, aCallbacks) {
WhileStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1126,7 +945,7 @@ let SyntaxTreeVisitor = {
* test: Expression;
* }
*/
DoWhileStatement: function STV_DoWhileStatement(aNode, aParent, aCallbacks) {
DoWhileStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1155,7 +974,7 @@ let SyntaxTreeVisitor = {
* body: Statement;
* }
*/
ForStatement: function STV_ForStatement(aNode, aParent, aCallbacks) {
ForStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1192,7 +1011,7 @@ let SyntaxTreeVisitor = {
* each: boolean;
* }
*/
ForInStatement: function STV_ForInStatement(aNode, aParent, aCallbacks) {
ForInStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1221,7 +1040,7 @@ let SyntaxTreeVisitor = {
* body: Statement;
* }
*/
ForOfStatement: function STV_ForOfStatement(aNode, aParent, aCallbacks) {
ForOfStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1249,7 +1068,7 @@ let SyntaxTreeVisitor = {
* body: Statement;
* }
*/
LetStatement: function STV_LetStatement(aNode, aParent, aCallbacks) {
LetStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1279,7 +1098,7 @@ let SyntaxTreeVisitor = {
* type: "DebuggerStatement";
* }
*/
DebuggerStatement: function STV_DebuggerStatement(aNode, aParent, aCallbacks) {
DebuggerStatement: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1302,7 +1121,7 @@ let SyntaxTreeVisitor = {
*
* interface Declaration <: Statement { }
*/
Declaration: function STV_Declaration(aNode, aParent, aCallbacks) {
Declaration: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1332,7 +1151,7 @@ let SyntaxTreeVisitor = {
* expression: boolean;
* }
*/
FunctionDeclaration: function STV_FunctionDeclaration(aNode, aParent, aCallbacks) {
FunctionDeclaration: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1368,7 +1187,7 @@ let SyntaxTreeVisitor = {
* kind: "var" | "let" | "const";
* }
*/
VariableDeclaration: function STV_VariableDeclaration(aNode, aParent, aCallbacks) {
VariableDeclaration: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1396,7 +1215,7 @@ let SyntaxTreeVisitor = {
* init: Expression | null;
* }
*/
VariableDeclarator: function STV_VariableDeclarator(aNode, aParent, aCallbacks) {
VariableDeclarator: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1422,7 +1241,7 @@ let SyntaxTreeVisitor = {
*
* interface Expression <: Node, Pattern { }
*/
Expression: function STV_Expression(aNode, aParent, aCallbacks) {
Expression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1445,7 +1264,7 @@ let SyntaxTreeVisitor = {
* type: "ThisExpression";
* }
*/
ThisExpression: function STV_ThisExpression(aNode, aParent, aCallbacks) {
ThisExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1469,7 +1288,7 @@ let SyntaxTreeVisitor = {
* elements: [ Expression | null ];
* }
*/
ArrayExpression: function STV_ArrayExpression(aNode, aParent, aCallbacks) {
ArrayExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1505,7 +1324,7 @@ let SyntaxTreeVisitor = {
* kind: "init" | "get" | "set" } ];
* }
*/
ObjectExpression: function STV_ObjectExpression(aNode, aParent, aCallbacks) {
ObjectExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1539,7 +1358,7 @@ let SyntaxTreeVisitor = {
* expression: boolean;
* }
*/
FunctionExpression: function STV_FunctionExpression(aNode, aParent, aCallbacks) {
FunctionExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1581,7 +1400,7 @@ let SyntaxTreeVisitor = {
* expression: boolean;
* }
*/
ArrowExpression: function STV_ArrowExpression(aNode, aParent, aCallbacks) {
ArrowExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1615,7 +1434,7 @@ let SyntaxTreeVisitor = {
* expressions: [ Expression ];
* }
*/
SequenceExpression: function STV_SequenceExpression(aNode, aParent, aCallbacks) {
SequenceExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1644,7 +1463,7 @@ let SyntaxTreeVisitor = {
* argument: Expression;
* }
*/
UnaryExpression: function STV_UnaryExpression(aNode, aParent, aCallbacks) {
UnaryExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1671,7 +1490,7 @@ let SyntaxTreeVisitor = {
* right: Expression;
* }
*/
BinaryExpression: function STV_BinaryExpression(aNode, aParent, aCallbacks) {
BinaryExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1699,7 +1518,7 @@ let SyntaxTreeVisitor = {
* right: Expression;
* }
*/
AssignmentExpression: function STV_AssignmentExpression(aNode, aParent, aCallbacks) {
AssignmentExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1727,7 +1546,7 @@ let SyntaxTreeVisitor = {
* prefix: boolean;
* }
*/
UpdateExpression: function STV_UpdateExpression(aNode, aParent, aCallbacks) {
UpdateExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1754,7 +1573,7 @@ let SyntaxTreeVisitor = {
* right: Expression;
* }
*/
LogicalExpression: function STV_LogicalExpression(aNode, aParent, aCallbacks) {
LogicalExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1782,7 +1601,7 @@ let SyntaxTreeVisitor = {
* consequent: Expression;
* }
*/
ConditionalExpression: function STV_ConditionalExpression(aNode, aParent, aCallbacks) {
ConditionalExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1810,7 +1629,7 @@ let SyntaxTreeVisitor = {
* arguments: [ Expression | null ];
* }
*/
NewExpression: function STV_NewExpression(aNode, aParent, aCallbacks) {
NewExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1841,7 +1660,7 @@ let SyntaxTreeVisitor = {
* arguments: [ Expression | null ];
* }
*/
CallExpression: function STV_CallExpression(aNode, aParent, aCallbacks) {
CallExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1876,7 +1695,7 @@ let SyntaxTreeVisitor = {
* computed: boolean;
* }
*/
MemberExpression: function STV_MemberExpression(aNode, aParent, aCallbacks) {
MemberExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1901,7 +1720,7 @@ let SyntaxTreeVisitor = {
* argument: Expression | null;
* }
*/
YieldExpression: function STV_YieldExpression(aNode, aParent, aCallbacks) {
YieldExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1931,7 +1750,7 @@ let SyntaxTreeVisitor = {
* filter: Expression | null;
* }
*/
ComprehensionExpression: function STV_ComprehensionExpression(aNode, aParent, aCallbacks) {
ComprehensionExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1965,7 +1784,7 @@ let SyntaxTreeVisitor = {
* filter: Expression | null;
* }
*/
GeneratorExpression: function STV_GeneratorExpression(aNode, aParent, aCallbacks) {
GeneratorExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -1996,7 +1815,7 @@ let SyntaxTreeVisitor = {
* expression: Literal;
* }
*/
GraphExpression: function STV_GraphExpression(aNode, aParent, aCallbacks) {
GraphExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -2020,7 +1839,7 @@ let SyntaxTreeVisitor = {
* index: uint32;
* }
*/
GraphIndexExpression: function STV_GraphIndexExpression(aNode, aParent, aCallbacks) {
GraphIndexExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -2045,7 +1864,7 @@ let SyntaxTreeVisitor = {
* body: Expression;
* }
*/
LetExpression: function STV_LetExpression(aNode, aParent, aCallbacks) {
LetExpression: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -2073,7 +1892,7 @@ let SyntaxTreeVisitor = {
*
* interface Pattern <: Node { }
*/
Pattern: function STV_Pattern(aNode, aParent, aCallbacks) {
Pattern: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -2098,7 +1917,7 @@ let SyntaxTreeVisitor = {
* properties: [ { key: Literal | Identifier, value: Pattern } ];
* }
*/
ObjectPattern: function STV_ObjectPattern(aNode, aParent, aCallbacks) {
ObjectPattern: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -2126,7 +1945,7 @@ let SyntaxTreeVisitor = {
* elements: [ Pattern | null ];
* }
*/
ArrayPattern: function STV_ArrayPattern(aNode, aParent, aCallbacks) {
ArrayPattern: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -2157,7 +1976,7 @@ let SyntaxTreeVisitor = {
* consequent: [ Statement ];
* }
*/
SwitchCase: function STV_SwitchCase(aNode, aParent, aCallbacks) {
SwitchCase: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -2190,7 +2009,7 @@ let SyntaxTreeVisitor = {
* body: BlockStatement;
* }
*/
CatchClause: function STV_CatchClause(aNode, aParent, aCallbacks) {
CatchClause: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -2220,7 +2039,7 @@ let SyntaxTreeVisitor = {
* each: boolean;
* }
*/
ComprehensionBlock: function STV_ComprehensionBlock(aNode, aParent, aCallbacks) {
ComprehensionBlock: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -2247,7 +2066,7 @@ let SyntaxTreeVisitor = {
* name: string;
* }
*/
Identifier: function STV_Identifier(aNode, aParent, aCallbacks) {
Identifier: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {
@ -2271,7 +2090,7 @@ let SyntaxTreeVisitor = {
* value: string | boolean | null | number | RegExp;
* }
*/
Literal: function STV_Literal(aNode, aParent, aCallbacks) {
Literal: function(aNode, aParent, aCallbacks) {
aNode._parent = aParent;
if (this.break) {

Просмотреть файл

@ -35,7 +35,10 @@
winUtils.loadSheet(newThemeUrl, winUtils.AUTHOR_SHEET);
// Floating scrollbars à la osx
if (!window.matchMedia("(-moz-overlay-scrollbars)").matches) {
let hiddenDOMWindow = Cc["@mozilla.org/appshell/appShellService;1"]
.getService(Ci.nsIAppShellService)
.hiddenDOMWindow;
if (!hiddenDOMWindow.matchMedia("(-moz-overlay-scrollbars)").matches) {
let scrollbarsUrl = Services.io.newURI(
DEVTOOLS_SKIN_URL + "floating-scrollbars-light.css", null, null);

Просмотреть файл

@ -167,7 +167,7 @@ SideMenuWidget.prototype = {
* The element associated with the displayed item.
*/
removeChild: function(aChild) {
if (aChild.className == "side-menu-widget-item-contents") {
if (aChild.classList.contains("side-menu-widget-item-contents")) {
// Remove the item itself, not the contents.
aChild.parentNode.remove();
} else {

Просмотреть файл

@ -21,6 +21,7 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
Cu.import("resource:///modules/devtools/shared/event-emitter.js");
Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
"resource://gre/modules/devtools/Loader.jsm");
@ -108,7 +109,9 @@ VariablesView.prototype = {
*/
set rawObject(aObject) {
this.empty();
this.addScope().addItem().populate(aObject, { sorted: true });
this.addScope()
.addItem("", { enumerable: true })
.populate(aObject, { sorted: true });
},
/**
@ -1120,14 +1123,6 @@ function Scope(aView, aName, aFlags = {}) {
this.contextMenuId = aView.contextMenuId;
this.separatorStr = aView.separatorStr;
// Creating maps and arrays thousands of times for variables or properties
// with a large number of children fills up a lot of memory. Make sure
// these are instantiated only if needed.
XPCOMUtils.defineLazyGetter(this, "_store", () => new Map());
XPCOMUtils.defineLazyGetter(this, "_enumItems", () => []);
XPCOMUtils.defineLazyGetter(this, "_nonEnumItems", () => []);
XPCOMUtils.defineLazyGetter(this, "_batchItems", () => []);
this._init(aName.trim(), aFlags);
}
@ -1649,7 +1644,8 @@ Scope.prototype = {
* The click listener for this scope's title.
*/
_onClick: function(e) {
if (e.target == this._inputNode ||
if (e.button != 0 ||
e.target == this._inputNode ||
e.target == this._editNode ||
e.target == this._deleteNode) {
return;
@ -2036,6 +2032,14 @@ Scope.prototype = {
_throbber: null
};
// Creating maps and arrays thousands of times for variables or properties
// with a large number of children fills up a lot of memory. Make sure
// these are instantiated only if needed.
DevToolsUtils.defineLazyPrototypeGetter(Scope.prototype, "_store", Map);
DevToolsUtils.defineLazyPrototypeGetter(Scope.prototype, "_enumItems", Array);
DevToolsUtils.defineLazyPrototypeGetter(Scope.prototype, "_nonEnumItems", Array);
DevToolsUtils.defineLazyPrototypeGetter(Scope.prototype, "_batchItems", Array);
/**
* A Variable is a Scope holding Property instances.
* Iterable via "for (let [name, property] in instance) { }".
@ -2776,6 +2780,10 @@ Variable.prototype = Heritage.extend(Scope.prototype, {
* The click listener for the edit button.
*/
_onEdit: function(e) {
if (e.button != 0) {
return;
}
e.preventDefault();
e.stopPropagation();
this._activateValueInput();
@ -2785,6 +2793,10 @@ Variable.prototype = Heritage.extend(Scope.prototype, {
* The click listener for the delete button.
*/
_onDelete: function(e) {
if ("button" in e && e.button != 0) {
return;
}
e.preventDefault();
e.stopPropagation();

Просмотреть файл

@ -1283,13 +1283,13 @@ CssRuleView.prototype = {
{
// Ignore refreshes during editing or when no element is selected.
if (this.isEditing || !this._elementStyle) {
return promise.resolve(null);
return;
}
this._clearRules();
// Repopulate the element style.
return this._populate();
this._populate();
},
_populate: function() {

Просмотреть файл

@ -7,6 +7,7 @@ let doc;
let inspector;
let ruleView;
let testElement;
let rule;
function startTest(aInspector, aRuleView)
{
@ -29,9 +30,7 @@ function startTest(aInspector, aRuleView)
testElement.setAttribute("style", elementStyle);
inspector.selection.setNode(testElement);
inspector.once("inspector-updated", () => {
testRuleChanges();
}, true);
inspector.once("rule-view-refreshed", testRuleChanges);
}
function testRuleChanges()
@ -43,25 +42,29 @@ function testRuleChanges()
is(selectors[2].textContent.indexOf(".testclass"), 0, "Third item is class rule.");
// Change the id and refresh.
inspector.once("rule-view-refreshed", testRuleChange1);
testElement.setAttribute("id", "differentid");
promiseDone(ruleView.nodeChanged().then(() => {
let selectors = ruleView.doc.querySelectorAll(".ruleview-selector");
is(selectors.length, 2, "Two rules visible.");
is(selectors[0].textContent.indexOf("element"), 0, "First item is inline style.");
is(selectors[1].textContent.indexOf(".testclass"), 0, "Second item is class rule.");
}
testElement.setAttribute("id", "testid");
return ruleView.nodeChanged();
}).then(() => {
// Put the id back.
let selectors = ruleView.doc.querySelectorAll(".ruleview-selector");
is(selectors.length, 3, "Three rules visible.");
is(selectors[0].textContent.indexOf("element"), 0, "First item is inline style.");
is(selectors[1].textContent.indexOf("#testid"), 0, "Second item is id rule.");
is(selectors[2].textContent.indexOf(".testclass"), 0, "Third item is class rule.");
function testRuleChange1()
{
let selectors = ruleView.doc.querySelectorAll(".ruleview-selector");
is(selectors.length, 2, "Two rules visible.");
is(selectors[0].textContent.indexOf("element"), 0, "First item is inline style.");
is(selectors[1].textContent.indexOf(".testclass"), 0, "Second item is class rule.");
testPropertyChanges();
}));
inspector.once("rule-view-refreshed", testRuleChange2);
testElement.setAttribute("id", "testid");
}
function testRuleChange2()
{
let selectors = ruleView.doc.querySelectorAll(".ruleview-selector");
is(selectors.length, 3, "Three rules visible.");
is(selectors[0].textContent.indexOf("element"), 0, "First item is inline style.");
is(selectors[1].textContent.indexOf("#testid"), 0, "Second item is id rule.");
is(selectors[2].textContent.indexOf(".testclass"), 0, "Third item is class rule.");
testPropertyChanges();
}
function validateTextProp(aProp, aEnabled, aName, aValue, aDesc)
@ -77,65 +80,86 @@ function validateTextProp(aProp, aEnabled, aName, aValue, aDesc)
function testPropertyChanges()
{
// Add a second margin-top value, just to make things interesting.
let rule = ruleView._elementStyle.rules[0];
rule = ruleView._elementStyle.rules[0];
let ruleEditor = ruleView._elementStyle.rules[0].editor;
inspector.once("rule-view-refreshed", testPropertyChange0);
// Add a second margin-top value, just to make things interesting.
ruleEditor.addProperty("margin-top", "5px", "");
promiseDone(expectRuleChange(rule).then(() => {
// Set the element style back to a 1px margin-top.
testElement.setAttribute("style", "margin-top: 1px; padding-top: 5px");
return ruleView.nodeChanged();
}).then(() => {
is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3, "Correct number of properties");
validateTextProp(rule.textProps[0], true, "margin-top", "1px", "First margin property re-enabled");
validateTextProp(rule.textProps[2], false, "margin-top", "5px", "Second margin property disabled");
}
// Now set it back to 5px, the 5px value should be re-enabled.
testElement.setAttribute("style", "margin-top: 5px; padding-top: 5px;");
return ruleView.nodeChanged();
function testPropertyChange0()
{
validateTextProp(rule.textProps[0], false, "margin-top", "1px", "Original margin property active");
}).then(() => {
is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3, "Correct number of properties");
validateTextProp(rule.textProps[0], false, "margin-top", "1px", "First margin property re-enabled");
validateTextProp(rule.textProps[2], true, "margin-top", "5px", "Second margin property disabled");
inspector.once("rule-view-refreshed", testPropertyChange1);
testElement.setAttribute("style", "margin-top: 1px; padding-top: 5px");
}
function testPropertyChange1()
{
is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3, "Correct number of properties");
validateTextProp(rule.textProps[0], true, "margin-top", "1px", "First margin property re-enabled");
validateTextProp(rule.textProps[2], false, "margin-top", "5px", "Second margin property disabled");
// Set the margin property to a value that doesn't exist in the editor.
// Should reuse the currently-enabled element (the second one.)
testElement.setAttribute("style", "margin-top: 15px; padding-top: 5px;");
return ruleView.nodeChanged();
}).then(() => {
is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3, "Correct number of properties");
validateTextProp(rule.textProps[0], false, "margin-top", "1px", "First margin property re-enabled");
validateTextProp(rule.textProps[2], true, "margin-top", "15px", "Second margin property disabled");
inspector.once("rule-view-refreshed", testPropertyChange2);
// Remove the padding-top attribute. Should disable the padding property but not remove it.
testElement.setAttribute("style", "margin-top: 5px;");
return ruleView.nodeChanged();
}).then(() => {
is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3, "Correct number of properties");
validateTextProp(rule.textProps[1], false, "padding-top", "5px", "Padding property disabled");
// Now set it back to 5px, the 5px value should be re-enabled.
testElement.setAttribute("style", "margin-top: 5px; padding-top: 5px;");
}
function testPropertyChange2()
{
is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3, "Correct number of properties");
validateTextProp(rule.textProps[0], false, "margin-top", "1px", "First margin property re-enabled");
validateTextProp(rule.textProps[2], true, "margin-top", "5px", "Second margin property disabled");
// Put the padding-top attribute back in, should re-enable the padding property.
testElement.setAttribute("style", "margin-top: 5px; padding-top: 25px");
return ruleView.nodeChanged();
}).then(() => {
is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3, "Correct number of properties");
validateTextProp(rule.textProps[1], true, "padding-top", "25px", "Padding property enabled");
inspector.once("rule-view-refreshed", testPropertyChange3);
// Add an entirely new property.
testElement.setAttribute("style", "margin-top: 5px; padding-top: 25px; padding-left: 20px;");
return ruleView.nodeChanged();
}).then(() => {
is(rule.editor.element.querySelectorAll(".ruleview-property").length, 4, "Added a property");
validateTextProp(rule.textProps[3], true, "padding-left", "20px", "Padding property enabled");
// Set the margin property to a value that doesn't exist in the editor.
// Should reuse the currently-enabled element (the second one.)
testElement.setAttribute("style", "margin-top: 15px; padding-top: 5px;");
}
function testPropertyChange3()
{
is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3, "Correct number of properties");
validateTextProp(rule.textProps[0], false, "margin-top", "1px", "First margin property re-enabled");
validateTextProp(rule.textProps[2], true, "margin-top", "15px", "Second margin property disabled");
finishTest();
}));
inspector.once("rule-view-refreshed", testPropertyChange4);
// Remove the padding-top attribute. Should disable the padding property but not remove it.
testElement.setAttribute("style", "margin-top: 5px;");
}
function testPropertyChange4()
{
is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3, "Correct number of properties");
validateTextProp(rule.textProps[1], false, "padding-top", "5px", "Padding property disabled");
inspector.once("rule-view-refreshed", testPropertyChange5);
// Put the padding-top attribute back in, should re-enable the padding property.
testElement.setAttribute("style", "margin-top: 5px; padding-top: 25px");
}
function testPropertyChange5()
{
is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3, "Correct number of properties");
validateTextProp(rule.textProps[1], true, "padding-top", "25px", "Padding property enabled");
inspector.once("rule-view-refreshed", testPropertyChange6);
// Add an entirely new property
testElement.setAttribute("style", "margin-top: 5px; padding-top: 25px; padding-left: 20px;");
}
function testPropertyChange6()
{
is(rule.editor.element.querySelectorAll(".ruleview-property").length, 4, "Added a property");
validateTextProp(rule.textProps[3], true, "padding-left", "20px", "Padding property enabled");
finishTest();
}
function finishTest()
{
inspector = ruleView = null;
inspector = ruleView = rule = null;
doc = null;
gBrowser.removeCurrentTab();
finish();

Просмотреть файл

@ -73,6 +73,7 @@
<!ENTITY projects.debugAppTooltip "Open Developer Tools connected to this app">
<!ENTITY projects.hostedManifestPlaceHolder2 "http://example.com/app/manifest.webapp">
<!ENTITY projects.noProjects "No projects. Add a new packaged app below (local directory) or a hosted app (link to a manifest file).">
<!ENTITY projects.manifestEditor "Manifest Editor">
<!ENTITY help.title "App Manager">
<!ENTITY help.close "Close">

Просмотреть файл

@ -19,4 +19,4 @@
<!ENTITY errorTimeout "Error: connection timeout.">
<!ENTITY errorRefused "Error: connection refused.">
<!ENTITY errorUnexpected "Unexpected error.">
<!ENTITY help "Firefox Developer Tools can debug remote devices (Firefox for Android and Firefox OS, for example). Make sure that you have turned on the 'Remote debugging' option in the remote device. See the <a target='_' href='https://developer.mozilla.org/docs/Tools/Debugger#Remote_Debugging'>documentation</a> for more.">
<!ENTITY help2 "Firefox Developer Tools can debug remote devices (Firefox for Android and Firefox OS, for example). Make sure that you have turned on the 'Remote debugging' option in the remote device. See the <a target='_' href='https://developer.mozilla.org/docs/Tools/Remote_Debugging'>documentation</a> for more.">

Просмотреть файл

@ -548,6 +548,7 @@ let DOMEvents = {
DOMEvents.init();
let ContentScroll = {
// The most recent offset set by APZC for the root scroll frame
_scrollOffset: { x: 0, y: 0 },
init: function() {
@ -617,9 +618,13 @@ let ContentScroll = {
// Set the scroll offset for this element if specified
if (json.scrollX >= 0 || json.scrollY >= 0) {
this.setScrollOffsetForElement(element, json.scrollX, json.scrollY)
if (json.id == 1)
this.setScrollOffsetForElement(element, json.scrollX, json.scrollY);
if (element == content.document.documentElement) {
// scrollTo can make some small adjustments to the offset before
// actually scrolling the document. To ensure that _scrollOffset
// actually matches the offset stored in the window, re-query it.
this._scrollOffset = this.getScrollOffset(content);
}
}
// Set displayport. We want to set this after setting the scroll offset, because
@ -690,6 +695,9 @@ let ContentScroll = {
if (target == content.document) {
if (this._scrollOffset.x == scrollOffset.x && this._scrollOffset.y == scrollOffset.y) {
// Don't send a scroll message back to APZC if it's the same as the
// last one set by APZC. We use this to avoid sending APZC back an
// event that it originally triggered.
return;
}
this._scrollOffset = scrollOffset;

Просмотреть файл

@ -66,6 +66,10 @@
display: none;
}
#sources .side-menu-widget-item.selected > .side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-arrow {
background-image: none;
}
/* Black box message and source progress meter */
#black-boxed-message,

Просмотреть файл

@ -64,6 +64,10 @@
display: none;
}
#sources .side-menu-widget-item.selected > .side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-arrow {
background-image: none;
}
/* Black box message and source progress meter */
#black-boxed-message,

Просмотреть файл

@ -231,6 +231,7 @@ strong {
#lense > div {
display: flex;
flex-grow: 1;
flex-direction: column;
}
@ -240,8 +241,13 @@ strong {
.project-details {
background-color: rgb(225, 225, 225);
padding: 10px;
flex-grow: 1;
line-height: 160%;
display: flex;
flex-direction: column;
}
.project-metadata {
flex-grow: 1;
}
.project-status {
@ -438,3 +444,44 @@ strong {
padding-left: 16px;
font-weight: bold;
}
/********* MANIFEST EDITOR ***********/
.manifest-editor {
display: flex;
flex-direction: column;
flex-grow: 1;
background-color: #E1E1E1;
}
.manifest-editor > h2 {
font-size: 18px;
margin: 1em 30px;
}
.variables-view {
flex-grow: 1;
border: 0;
border-top: 5px solid #C9C9C9;
}
/* Bug 925921: Remove when the manifest editor is always on */
.manifest-editor {
display: none;
}
.project-details {
flex-grow: 1;
}
#lense[manifest-editable] .manifest-editor {
display: flex;
}
#lense[manifest-editable] .project-details {
flex-grow: 0;
}
/* End blocks to remove */

Просмотреть файл

@ -64,6 +64,10 @@
display: none;
}
#sources .side-menu-widget-item.selected > .side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-arrow {
background-image: none;
}
/* Black box message and source progress meter */
#black-boxed-message,

Просмотреть файл

@ -77,7 +77,7 @@ class nsGeolocationRequest
void Shutdown();
void SendLocation(nsIDOMGeoPosition* location);
bool WantsHighAccuracy() {return mOptions && mOptions->mEnableHighAccuracy;}
bool WantsHighAccuracy() {return !mShutdown && mOptions && mOptions->mEnableHighAccuracy;}
void SetTimeoutTimer();
nsIPrincipal* GetPrincipal();
@ -445,7 +445,7 @@ nsGeolocationRequest::Allow()
maximumAge = mOptions->mMaximumAge;
}
}
gs->SetHigherAccuracy(mOptions && mOptions->mEnableHighAccuracy);
gs->UpdateAccuracy(WantsHighAccuracy());
bool canUseCache = lastPosition && maximumAge > 0 &&
(PRTime(PR_Now() / PR_USEC_PER_MSEC) - maximumAge <=
@ -585,12 +585,12 @@ nsGeolocationRequest::Shutdown()
mTimeoutTimer = nullptr;
}
// This should happen last, to ensure that this request isn't taken into consideration
// when deciding whether existing requests still require high accuracy.
// If there are no other high accuracy requests, the geolocation service will
// notify the provider to switch to the default accuracy.
if (mOptions && mOptions->mEnableHighAccuracy) {
nsRefPtr<nsGeolocationService> gs = nsGeolocationService::GetGeolocationService();
if (gs) {
gs->SetHigherAccuracy(false);
gs->UpdateAccuracy();
}
}
}
@ -901,9 +901,9 @@ nsGeolocationService::HighAccuracyRequested()
}
void
nsGeolocationService::SetHigherAccuracy(bool aEnable)
nsGeolocationService::UpdateAccuracy(bool aForceHigh)
{
bool highRequired = aEnable || HighAccuracyRequested();
bool highRequired = aForceHigh || HighAccuracyRequested();
if (XRE_GetProcessType() == GeckoProcessType_Content) {
ContentChild* cpc = ContentChild::GetSingleton();
@ -1061,6 +1061,7 @@ Geolocation::Shutdown()
if (mService) {
mService->RemoveLocator(this);
mService->UpdateAccuracy();
}
mService = nullptr;

Просмотреть файл

@ -85,8 +85,8 @@ public:
// create, or reinitalize the callback timer
void SetDisconnectTimer();
// request higher accuracy, if possible
void SetHigherAccuracy(bool aEnable);
// Update the accuracy and notify the provider if changed
void UpdateAccuracy(bool aForceHigh = false);
bool HighAccuracyRequested();
private:

Просмотреть файл

@ -73,6 +73,9 @@ function WifiGeoPositionProvider() {
this.timer = null;
this.hasSeenWiFi = false;
this.started = false;
// this is only used when logging is enabled, to debug interactions with the
// geolocation service
this.highAccuracy = false;
}
WifiGeoPositionProvider.prototype = {
@ -132,10 +135,12 @@ WifiGeoPositionProvider.prototype = {
},
setHighAccuracy: function(enable) {
this.highAccuracy = enable;
LOG("setting highAccuracy to " + (this.highAccuracy?"TRUE":"FALSE"));
},
onChange: function(accessPoints) {
LOG("onChange called");
LOG("onChange called, highAccuracy = " + (this.highAccuracy?"TRUE":"FALSE"));
this.hasSeenWiFi = true;
let url = Services.urlFormatter.formatURLPref("geo.wifi.uri");

Просмотреть файл

@ -0,0 +1,104 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const providerCID = Components.ID("{14aa4b81-e266-45cb-88f8-89595dece114}");
const providerContract = "@mozilla.org/geolocation/provider;1";
const categoryName = "geolocation-provider";
var provider = {
QueryInterface: function eventsink_qi(iid) {
if (iid.equals(Components.interfaces.nsISupports) ||
iid.equals(Components.interfaces.nsIFactory) ||
iid.equals(Components.interfaces.nsIGeolocationProvider))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
createInstance: function eventsink_ci(outer, iid) {
if (outer)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return this.QueryInterface(iid);
},
lockFactory: function eventsink_lockf(lock) {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
startup: function() {
},
watch: function() {
},
shutdown: function() {
},
setHighAccuracy: function(enable) {
this._isHigh = enable;
if (enable) {
this._seenHigh = true;
}
},
_isHigh: false,
_seenHigh: false
};
let runningInParent = true;
try {
runningInParent = Components.classes["@mozilla.org/xre/runtime;1"].
getService(Components.interfaces.nsIXULRuntime).processType
== Components.interfaces.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
}
catch (e) { }
function successCallback()
{
do_check_true(false);
do_test_finished();
}
function errorCallback()
{
do_check_true(false);
do_test_finished();
}
function run_test()
{
if (runningInParent) {
// XPCShell does not get a profile by default. The geolocation service
// depends on the settings service which uses IndexedDB and IndexedDB
// needs a place where it can store databases.
do_get_profile();
Components.manager.nsIComponentRegistrar.registerFactory(providerCID,
"Unit test geo provider", providerContract, provider);
var catMan = Components.classes["@mozilla.org/categorymanager;1"]
.getService(Components.interfaces.nsICategoryManager);
catMan.nsICategoryManager.addCategoryEntry(categoryName, "unit test",
providerContract, false, true);
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setBoolPref("geo.testing.ignore_ipc_principal", true);
prefs.setBoolPref("geo.wifi.scan", false);
}
let geolocation = Cc["@mozilla.org/geolocation;1"].createInstance(Ci.nsISupports);
do_test_pending();
let watchID1 = geolocation.watchPosition(successCallback, errorCallback);
let watchID2 = geolocation.watchPosition(successCallback, errorCallback,
{enableHighAccuracy: true});
do_timeout(1000, function() {
geolocation.clearWatch(watchID2);
do_timeout(1000, check_results);
});
}
function check_results()
{
if (runningInParent) {
// check the provider was set to high accuracy during the test
do_check_true(provider._seenHigh);
// check the provider is not currently set to high accuracy
do_check_false(provider._isHigh);
}
do_test_finished();
}

Просмотреть файл

@ -0,0 +1,70 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const providerCID = Components.ID("{14aa4b81-e266-45cb-88f8-89595dece114}");
const providerContract = "@mozilla.org/geolocation/provider;1";
const categoryName = "geolocation-provider";
var provider = {
QueryInterface: function eventsink_qi(iid) {
if (iid.equals(Components.interfaces.nsISupports) ||
iid.equals(Components.interfaces.nsIFactory) ||
iid.equals(Components.interfaces.nsIGeolocationProvider))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
createInstance: function eventsink_ci(outer, iid) {
if (outer)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return this.QueryInterface(iid);
},
lockFactory: function eventsink_lockf(lock) {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
startup: function() {
},
watch: function() {
},
shutdown: function() {
},
setHighAccuracy: function(enable) {
this._isHigh = enable;
if (enable) {
this._seenHigh = true;
}
},
_isHigh: false,
_seenHigh: false
};
function run_test()
{
// XPCShell does not get a profile by default. The geolocation service
// depends on the settings service which uses IndexedDB and IndexedDB
// needs a place where it can store databases.
do_get_profile();
Components.manager.nsIComponentRegistrar.registerFactory(providerCID,
"Unit test geo provider", providerContract, provider);
var catMan = Components.classes["@mozilla.org/categorymanager;1"]
.getService(Components.interfaces.nsICategoryManager);
catMan.nsICategoryManager.addCategoryEntry(categoryName, "unit test",
providerContract, false, true);
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setBoolPref("geo.testing.ignore_ipc_principal", true);
prefs.setBoolPref("geo.wifi.scan", false);
run_test_in_child("test_geolocation_reset_accuracy.js", check_results);
}
function check_results()
{
// check the provider was set to high accuracy during the test
do_check_true(provider._seenHigh);
// check the provider is not currently set to high accuracy
do_check_false(provider._isHigh);
do_test_finished();
}

Просмотреть файл

@ -12,3 +12,8 @@ skip-if = os == "android"
skip-if = os == "android"
[test_geolocation_timeout_wrap.js]
skip-if = os == "mac" || os == "android"
[test_geolocation_reset_accuracy.js]
# Bug 919946: test hangs consistently on Android
skip-if = os == "android"
[test_geolocation_reset_accuracy_wrap.js]
skip-if = os == "mac" || os == "android"

Просмотреть файл

@ -27,6 +27,7 @@ import org.mozilla.gecko.R;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.NoSuchFieldException;
import java.net.MalformedURLException;
import java.net.URL;
@ -81,6 +82,19 @@ public final class BitmapUtils {
return;
}
if(data.startsWith("-moz-icon://")) {
Uri imageUri = Uri.parse(data);
String resource = imageUri.getSchemeSpecificPart();
resource = resource.substring(resource.lastIndexOf('/') + 1);
try {
Drawable d = context.getPackageManager().getApplicationIcon(resource);
loader.onBitmapFound(d);
} catch(Exception ex) { }
return;
}
if(data.startsWith("drawable://")) {
Uri imageUri = Uri.parse(data);
int id = getResource(imageUri, R.drawable.ic_status_logo);
@ -282,11 +296,34 @@ public final class BitmapUtils {
if ("drawable".equals(scheme)) {
String resource = resourceUrl.getSchemeSpecificPart();
resource = resource.substring(resource.lastIndexOf('/') + 1);
try {
return Integer.parseInt(resource);
} catch(NumberFormatException ex) {
// This isn't a resource id, try looking for a string
}
try {
final Class<R.drawable> drawableClass = R.drawable.class;
final Field f = drawableClass.getField(resource);
icon = f.getInt(null);
} catch (final Exception e) {} // just means the resource doesn't exist
} catch (final NoSuchFieldException e1) {
// just means the resource doesn't exist for fennec. Check in Android resources
try {
final Class<android.R.drawable> drawableClass = android.R.drawable.class;
final Field f = drawableClass.getField(resource);
icon = f.getInt(null);
} catch (final NoSuchFieldException e2) {
// This drawable doesn't seem to exist...
} catch(Exception e3) {
Log.i(LOGTAG, "Exception getting drawable", e3);
}
} catch (Exception e4) {
Log.i(LOGTAG, "Exception getting drawable", e4);
}
resourceUrl = null;
}
return icon;

Просмотреть файл

@ -20,7 +20,6 @@ import android.widget.TextView;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
/**
* This class is an extension of BaseTest that helps with interaction with about:home
@ -28,7 +27,7 @@ import java.util.Arrays;
* The purpose of this class is to collect all the logically connected methods that deal with about:home
* To use any of these methods in your test make sure it extends AboutHomeTest instead of BaseTest
*/
abstract class AboutHomeTest extends BaseTest {
abstract class AboutHomeTest extends PixelTest {
protected enum AboutHomeTabs {HISTORY, MOST_RECENT, TABS_FROM_LAST_TIME, TOP_SITES, BOOKMARKS, READING_LIST};
private ArrayList<String> aboutHomeTabs = new ArrayList<String>() {{
add("TOP_SITES");
@ -98,10 +97,6 @@ abstract class AboutHomeTest extends BaseTest {
// @return the View associated with bookmark for the provided url or null if the link is not bookmarked
protected View getDisplayedBookmark(String url) {
openAboutHomeTab(AboutHomeTabs.BOOKMARKS);
if (!mDevice.type.equals("tablet")) {
toggleVKB(); // dismiss the keyboard to make sure this works on small screen devices
}
getInstrumentation().waitForIdleSync();
ListView bookmarksTabList = findListViewWithTag("bookmarks");
waitForNonEmptyListToLoad(bookmarksTabList);
ListAdapter adapter = bookmarksTabList.getAdapter();
@ -182,30 +177,59 @@ abstract class AboutHomeTest extends BaseTest {
}
/**
* @param1 a String with the original url
* @param2 a String array with the new values for all fields
* FIXME: rewrite this to work with fig when rewriting the testBookmarksTab test
* This method will edit the bookmark with index = bookmarkIndex from the list of bookmarks
* For the field index:
* fieldIndex = 1 - the Bookmark name
* fieldIndex = 2 - the Bookmark url
* fieldIndex = 3 - the Bookmark keyword
*/
protected void editBookmark(String originalUrl, String[] newValues) {
openBookmarkContextMenu(originalUrl);
protected void editBookmark(int bookmarkIndex, int fieldIndex, String addedText, ListView list) {
// Open the Edit Bookmark context menu
View child;
mSolo.clickOnText("Bookmarks");
child = list.getChildAt(bookmarkIndex);
mAsserter.ok(child != null, "edit item can be retrieved", child != null ? child.toString() : "null!");
waitForText("Switch to tab");
mSolo.clickLongOnView(child);
waitForText("Share");
mSolo.clickOnText("Edit");
waitForText("Edit Bookmark");
for (String value:newValues) {
mSolo.clearEditText(Arrays.asList(newValues).indexOf(value));
mSolo.clickOnEditText(Arrays.asList(newValues).indexOf(value));
mActions.sendKeys(value);
}
mSolo.clickOnButton("OK");
// Clear the Field
mSolo.clearEditText(fieldIndex);
// Enter the new text
mSolo.clickOnEditText(fieldIndex);
mActions.sendKeys(addedText);
mSolo.clickOnText("OK");
waitForText("Bookmark updated");
}
protected void checkBookmarkEdit(String bookmarkUrl, String[] values) {
openBookmarkContextMenu(bookmarkUrl);
// FIXME: rewrite this to work with fig when rewriting the testBookmarksTab test
protected boolean checkBookmarkEdit(int bookmarkIndex, String addedText, ListView list) {
// Open the Edit Bookmark context menu
View child;
mSolo.clickOnText("Bookmarks");
child = list.getChildAt(bookmarkIndex);
mAsserter.ok(child != null, "check item can be retrieved", child != null ? child.toString() : "null!");
waitForText("Switch to tab");
mSolo.clickLongOnView(child);
waitForText("Share");
mSolo.clickOnText("Edit");
for (String value:values) {
mAsserter.ok(mSolo.searchText(value), "Checking that the value is correct", "The value = " + value + " is correct");
waitForText("Edit Bookmark");
// Check if the new text was added
if (mSolo.searchText(addedText)) {
clickOnButton("Cancel");
waitForText("about:home");
return true;
} else {
clickOnButton("Cancel");
waitForText("about:home");
return false;
}
clickOnButton("Cancel");
waitForText("BOOKMARKS");
}
// A wait in order for the about:home tab to be rendered after drag/tab selection
@ -256,12 +280,15 @@ abstract class AboutHomeTest extends BaseTest {
protected void openAboutHomeTab(AboutHomeTabs tab) {
focusUrlBar();
ViewPager pager = (ViewPager)mSolo.getView(ViewPager.class, 0);
final int currentTabIndex = pager.getCurrentItem();
int tabOffset;
// Handle tablets by just clicking the visible tab title.
if (mDevice.type.equals("tablet")) {
// Just click for tablets, since all the titles are visible.
if (AboutHomeTabs.MOST_RECENT == tab || AboutHomeTabs.TABS_FROM_LAST_TIME == tab) {
mSolo.clickOnText(AboutHomeTabs.HISTORY.toString());
tabOffset = aboutHomeTabs.indexOf(AboutHomeTabs.HISTORY.toString()) - currentTabIndex;
swipeAboutHome(tabOffset);
waitForAboutHomeTab(aboutHomeTabs.indexOf(StringHelper.HISTORY_LABEL));
TabWidget tabwidget = (TabWidget)mSolo.getView(TabWidget.class, 0);
switch (tab) {
@ -284,8 +311,7 @@ abstract class AboutHomeTest extends BaseTest {
}
// Handle phones (non-tablets).
final int currentTabIndex = pager.getCurrentItem();
int tabOffset = aboutHomeTabs.indexOf(tab.toString()) - currentTabIndex;
tabOffset = aboutHomeTabs.indexOf(tab.toString()) - currentTabIndex;
switch (tab) {
case TOP_SITES : {
swipeAboutHome(tabOffset);

Просмотреть файл

@ -45,8 +45,6 @@ class StringHelper {
"Add to Home Screen"
};
public static final String[] BOOKMARK_CONTEXT_MENU_ITEMS = {"Open in New Tab", "Open in Private Tab", "Share", "Edit", "Remove", "Add to Home Screen"};
// Robocop page urls
// Note: please use getAbsoluteUrl(String url) on each robocop url to get the correct url
public static final String ROBOCOP_BIG_LINK_URL = "/robocop/robocop_big_link.html";

Просмотреть файл

@ -1,7 +1,6 @@
[testAwesomebar]
# [testAwesomebarSwipes] # disabled on fig - bug 880060
[testBookmark]
[testBookmarksPage]
# [testBookmarklets] # see bug 915350
# [testBookmarkKeyword] # see bug 915350
[testBrowserSearchVisibility]
@ -46,6 +45,7 @@
[testMasterPassword]
[testDeviceSearchEngine]
[testPrivateBrowsing]
[testReaderMode]
# Used for Talos, please don't use in mochitest
#[testPan]

Просмотреть файл

@ -1,223 +0,0 @@
#filter substitution
package @ANDROID_PACKAGE_NAME@.tests;
import @ANDROID_PACKAGE_NAME@.*;
import com.jayway.android.robotium.solo.Condition;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.ContentUris;
import android.database.Cursor;
import android.net.Uri;
import android.view.View;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
public class testBookmarksPage extends AboutHomeTest {
private static String BOOKMARK_URL;
private static String DESKTOP_BOOKMARK_URL;
@Override
protected int getTestType() {
return TEST_MOCHITEST;
}
public void testBookmarksPage() {
BOOKMARK_URL = getAbsoluteUrl(StringHelper.ROBOCOP_BLANK_PAGE_01_URL);
DESKTOP_BOOKMARK_URL = getAbsoluteUrl(StringHelper.ROBOCOP_BLANK_PAGE_02_URL);
setUpDesktopBookmarks();
checkBookmarkList();
checkBookmarkContextMenu();
}
private void checkBookmarkList() {
// Check that the default bookmarks are displayed
for (String url:StringHelper.DEFAULT_BOOKMARKS_URLS) {
mAsserter.ok(isBookmarkDisplayed(url), "Checking that default bookmark: " + url + " is displayed in the bookmarks list", url + " is displayed as a bookmark");
}
mAsserter.ok(isBookmarkDisplayed(BOOKMARK_URL), "Checking that added bookmark: " + BOOKMARK_URL + " is displayed in the bookmarks list", BOOKMARK_URL + " is displayed as a bookmark");
waitForText(StringHelper.DESKTOP_FOLDER_LABEL);
clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL);
waitForText(StringHelper.TOOLBAR_FOLDER_LABEL);
// Verify the number of folders displayed in the Desktop Bookmarks folder is correct
ListView desktopFolderContent = findListViewWithTag("bookmarks");
ListAdapter adapter = desktopFolderContent.getAdapter();
if (mDevice.type.equals("tablet")) { // On tablets it's 4 folders and 1 view for top padding
mAsserter.is(adapter.getCount(), 5, "Checking that the correct number of folders is displayed in the Desktop Bookmarks folder");
} else { // On phones it's just the 4 folders
mAsserter.is(adapter.getCount(), 4, "Checking that the correct number of folders is displayed in the Desktop Bookmarks folder");
}
clickOnBookmarkFolder(StringHelper.TOOLBAR_FOLDER_LABEL);
// Go up in the bookmark folder hierarchy
clickOnBookmarkFolder(StringHelper.TOOLBAR_FOLDER_LABEL);
mAsserter.ok(waitForText(StringHelper.BOOKMARKS_MENU_FOLDER_LABEL), "Going up in the folder hierarchy", "We are back in the Desktop Bookmarks folder");
clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL);
mAsserter.ok(waitForText(StringHelper.DESKTOP_FOLDER_LABEL), "Going up in the folder hierarchy", "We are back in the main Bookmarks List View");
clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL);
clickOnBookmarkFolder(StringHelper.TOOLBAR_FOLDER_LABEL);
mAsserter.ok(isBookmarkDisplayed(DESKTOP_BOOKMARK_URL), "Checking that added bookmark: " + DESKTOP_BOOKMARK_URL + " is displayed in the bookmarks list", DESKTOP_BOOKMARK_URL + " is displayed as a bookmark");
// Open the bookmark from a bookmark folder hierarchy
loadBookmark(DESKTOP_BOOKMARK_URL);
waitForText(StringHelper.ROBOCOP_BLANK_PAGE_02_TITLE);
verifyPageTitle(StringHelper.ROBOCOP_BLANK_PAGE_02_TITLE);
openAboutHomeTab(AboutHomeTabs.BOOKMARKS);
// Check that folders don't have a context menu
boolean success = waitForCondition(new Condition() {
@Override
public boolean isSatisfied() {
View desktopFolder = getBookmarkFolderView(StringHelper.DESKTOP_FOLDER_LABEL);
if (desktopFolder != null) {
mSolo.clickLongOnView(desktopFolder);
return true;
}
return false;
}
}, MAX_WAIT_MS);
mAsserter.ok(success, "Trying to long click on the Desktop Bookmarks","Desktop Bookmarks folder could not be long clicked");
mAsserter.ok(!waitForText("Share"), "Folders do not have context menus", "The context menu was not opened");
// Even if no context menu is opened long clicking a folder still opens it. We need to close it.
clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL);
}
private void checkBookmarkContextMenu() {
// Open default bookmarks in a new tab and a new private tab since the url is substituted with "Switch to tab" after opening the link
openBookmarkContextMenu(StringHelper.DEFAULT_BOOKMARKS_URLS[1]);
// Test that the options are all displayed
for (String contextMenuOption:StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS) {
mAsserter.ok(mSolo.searchText(contextMenuOption), "Checking that the context menu option is present", contextMenuOption + " is present");
}
// Test that "Open in New Tab" works
final Element tabCount = mDriver.findElement(getActivity(), "tabs_counter");
final int tabCountInt = Integer.parseInt(tabCount.getText());
Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added");
mSolo.clickOnText(StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[0]);
tabEventExpecter.blockForEvent();
tabEventExpecter.unregisterListener();
// Test that "Open in Private Tab" works
openBookmarkContextMenu(StringHelper.DEFAULT_BOOKMARKS_URLS[2]);
tabEventExpecter = mActions.expectGeckoEvent("Tab:Added");
mSolo.clickOnText(StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[1]);
tabEventExpecter.blockForEvent();
tabEventExpecter.unregisterListener();
// Test that "Share" works
openBookmarkContextMenu(BOOKMARK_URL);
mSolo.clickOnText(StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[2]);
mAsserter.ok(waitForText("Share via"), "Checking to see if the share menu has been opened","The share menu has been opened");
mActions.sendSpecialKey(Actions.SpecialKey.BACK);
waitForText(StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE);
// Test that "Edit" works
String[] editedBookmarkValues = {"New bookmark title", "www.NewBookmark.url", "newBookmarkKeyword"};
editBookmark(BOOKMARK_URL,editedBookmarkValues);
checkBookmarkEdit(editedBookmarkValues[1],editedBookmarkValues);
// Test that "Remove" works
openBookmarkContextMenu(editedBookmarkValues[1]);
mSolo.clickOnText(StringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[4]);
waitForText("Bookmark removed");
mAsserter.ok(!mDatabaseHelper.isBookmark(editedBookmarkValues[1]), "Checking that the bookmark was removed", "The bookmark was removed");
}
private void clickOnBookmarkFolder(final String folderName) {
boolean success = waitForCondition(new Condition() {
@Override
public boolean isSatisfied() {
View bookmarksFolder = getBookmarkFolderView(folderName);
if (bookmarksFolder != null) {
mSolo.clickOnView(bookmarksFolder);
return true;
}
return false;
}
}, MAX_WAIT_MS);
mAsserter.ok(success, "Trying to click on the " + folderName + " folder","The " + folderName + " folder was clicked");
}
private View getBookmarkFolderView(String folderName) {
ListView bookmarksTabList = findListViewWithTag("bookmarks");
ListAdapter adapter = bookmarksTabList.getAdapter();
if (adapter != null) {
for (int i = 0; i < adapter.getCount(); i++ ) {
View bookmarkView = bookmarksTabList.getChildAt(i);
if (bookmarkView instanceof TextView) {
TextView folderTextView = (TextView) bookmarkView;
if (folderTextView.getText().equals(folderName)) {
return bookmarkView;
}
}
}
}
return null;
}
// Add a bookmark in the Desktop folder so we can check the folder navigation in the bookmarks page
private void setUpDesktopBookmarks() {
// Get the folder id of the StringHelper.DESKTOP_FOLDER_LABEL folder
Long desktopFolderId = mDatabaseHelper.getFolderIdFromGuid("toolbar");
// Generate a Guid for the bookmark
String generatedGuid = null;
try {
ClassLoader classLoader = getActivity().getClassLoader();
Class syncUtilityClass = classLoader.loadClass("org.mozilla.gecko.sync.Utils");
Method generateGuid = syncUtilityClass.getMethod("generateGuid", (Class[]) null);
generatedGuid = (String)generateGuid.invoke(null);
} catch (Exception e) {
mAsserter.dumpLog("Exception in setUpDesktopBookmarks" + e);
}
mAsserter.ok((generatedGuid != null), "Generating a random Guid for the bookmark", "We could not generate a Guid for the bookmark");
// Insert the bookmark
ContentResolver resolver = getActivity().getContentResolver();
Uri bookmarksUri = mDatabaseHelper.buildUri(DatabaseHelper.BrowserDataType.BOOKMARKS);
ContentValues values = new ContentValues();
values.put("title", StringHelper.ROBOCOP_BLANK_PAGE_02_TITLE);
values.put("url", DESKTOP_BOOKMARK_URL);
values.put("parent", desktopFolderId);
long now = System.currentTimeMillis();
values.put("modified", now);
values.put("type", 1);
values.put("guid", generatedGuid);
values.put("position", 10);
values.put("created", now);
int updated = resolver.update(bookmarksUri,
values,
"url = ?",
new String[] { DESKTOP_BOOKMARK_URL });
if (updated == 0) {
Uri uri = resolver.insert(bookmarksUri, values);
mAsserter.ok(true, "Inserted at: ", uri.toString());
} else {
mAsserter.ok(false, "Failed to insert the Desktop bookmark", "Something went wrong");
}
// Add a mobile bookmark
mDatabaseHelper.addOrUpdateMobileBookmark(StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, BOOKMARK_URL);
}
@Override
public void tearDown() throws Exception {
mDatabaseHelper.deleteBookmark(DESKTOP_BOOKMARK_URL);
super.tearDown();
}
}

Просмотреть файл

@ -0,0 +1,170 @@
#filter substitution
package @ANDROID_PACKAGE_NAME@.tests;
import @ANDROID_PACKAGE_NAME@.*;
import com.jayway.android.robotium.solo.Solo;
import android.widget.ListView;
import android.view.View;
import java.util.ArrayList;
import android.view.ViewGroup;
import org.json.JSONException;
import org.json.JSONObject;
/**
* This patch tests the Reader Mode feature by adding and removing items in reading list
* checks the reader toolbar functionality(share, add/remove to reading list, go to reading list)
* accessing a page from reading list menu, checks that the reader icon is associated in History tab
* and that the reading list is properly populated after adding or removing reader items
*/
public class testReaderMode extends AboutHomeTest {
int height,width;
@Override
protected int getTestType() {
return TEST_MOCHITEST;
}
public void testReaderMode() {
blockForGeckoReady();
Actions.EventExpecter contentEventExpecter;
Actions.EventExpecter contentReaderAddedExpecter;
Actions.EventExpecter faviconExpecter;
ListView list;
View child;
String textUrl = getAbsoluteUrl(StringHelper.ROBOCOP_TEXT_PAGE_URL);
String devType = mDevice.type;
int childNo;
contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
loadAndPaint(textUrl);
contentEventExpecter.blockForEvent();
contentEventExpecter.unregisterListener();
View readerIcon = getReaderIcon();
// Add the page to the Reading List using log click on the reader icon
contentReaderAddedExpecter = mActions.expectGeckoEvent("Reader:Added");
mSolo.clickLongOnView(readerIcon);
String eventData = contentReaderAddedExpecter.blockForEventData();
isAdded(eventData);
contentReaderAddedExpecter.unregisterListener();
// Try to add the page to the Reading List using log click on the reader icon a second time
contentReaderAddedExpecter = mActions.expectGeckoEvent("Reader:Added");
mSolo.clickLongOnView(readerIcon);
eventData = contentReaderAddedExpecter.blockForEventData();
isAdded(eventData);
contentReaderAddedExpecter.unregisterListener();
// Waiting for the favicon since is the last element loaded usually
faviconExpecter = mActions.expectGeckoEvent("Reader:FaviconRequest");
mSolo.clickOnView(getReaderIcon());
// Changing devices orientation to be sure that all devices are in portrait when will access the reader toolbar
mSolo.setActivityOrientation(Solo.PORTRAIT);
faviconExpecter.blockForEvent();
faviconExpecter.unregisterListener();
verifyPageTitle("Robocop Text Page");
// Open the share menu for the reader toolbar
height = mDriver.getGeckoTop() + mDriver.getGeckoHeight() - 10;
width = mDriver.getGeckoLeft() + mDriver.getGeckoWidth() - 10;
mAsserter.dumpLog("Long Clicking at width = " + String.valueOf(width) + " and height = " + String.valueOf(height));
mSolo.clickOnScreen(width,height);
mAsserter.ok(mSolo.waitForText("Share via"), "Waiting for the share menu", "The share menu is present");
mActions.sendSpecialKey(Actions.SpecialKey.BACK); // Close the share menu
// Remove page from the Reading List using reader toolbar
height = mDriver.getGeckoTop() + mDriver.getGeckoHeight() - 10;
width = mDriver.getGeckoLeft() + 50;
mAsserter.dumpLog("Long Clicking at width = " + String.valueOf(width) + " and height = " + String.valueOf(height));
mSolo.clickOnScreen(width,height);
mAsserter.ok(mSolo.waitForText("Page removed from your Reading List"), "Waiting for the page to removed from your Reading List", "The page is removed from your Reading List");
//Add page to the Reading List using reader toolbar
mSolo.clickOnScreen(width,height);
mAsserter.ok(mSolo.waitForText("Page added to your Reading List"), "Waiting for the page to be added to your Reading List", "The page was added to your Reading List");
// Open the Reading List menu for the toolbar
height = mDriver.getGeckoTop() + mDriver.getGeckoHeight() - 10;
width = mDriver.getGeckoLeft() + mDriver.getGeckoWidth()/2 - 10;
mAsserter.dumpLog("Long Clicking at width = " + String.valueOf(width) + " and height = " + String.valueOf(height));
contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
mSolo.clickOnScreen(width,height);
contentEventExpecter.blockForEvent();
contentEventExpecter.unregisterListener();
// Check if the page is present in the Reading List
mAsserter.ok(mSolo.waitForText("Robocop Text Page"), "Verify if the page is added to your Reading List", "The page is present in your Reading List");
// Check if the page is added in History tab like a Reading List item
openAboutHomeTab(AboutHomeTabs.MOST_RECENT);
list = findListViewWithTag("most_recent");
child = list.getChildAt(1);
mAsserter.ok(child != null, "item can be retrieved", child != null ? child.toString() : "null!");
mSolo.clickLongOnView(child);
mAsserter.ok(mSolo.waitForText("Open in Reader"), "Verify if the page is present in history as a Reading List item", "The page is present in history as a Reading List item");
mActions.sendSpecialKey(Actions.SpecialKey.BACK); // Dismiss the context menu
mSolo.waitForText("Robocop Text Page");
// Verify separately the Reading List entries for tablets and phone because for tablets there is an extra child in UI design
if (devType.equals("phone")) {
childNo = 1;
}
else {
childNo = 2;
}
// Verify if the page is present to your Reading List
openAboutHomeTab(AboutHomeTabs.READING_LIST);
list = findListViewWithTag("reading_list");
child = list.getChildAt(childNo-1);
mAsserter.ok(child != null, "Verify if the page is present to your Reading List", "The page is present in your Reading List");
contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
mSolo.clickOnView(child);
contentEventExpecter.blockForEvent();
contentEventExpecter.unregisterListener();
verifyPageTitle("Robocop Text Page");
// Verify that we are in reader mode and remove the page from Reading List
height = mDriver.getGeckoTop() + mDriver.getGeckoHeight() - 10;
width = mDriver.getGeckoLeft() + 50;
mAsserter.dumpLog("Long Clicking at width = " + String.valueOf(width) + " and height = " + String.valueOf(height));
mSolo.clickOnScreen(width,height);
mAsserter.ok(mSolo.waitForText("Page removed from your Reading List"), "Waiting for the page to removed from your Reading List", "The page is removed from your Reading List");
verifyPageTitle("Robocop Text Page");
//Check if the Reading List is empty
openAboutHomeTab(AboutHomeTabs.READING_LIST);
list = findListViewWithTag("reading_list");
child = list.getChildAt(childNo-1);
mAsserter.ok(child == null, "Verify if the Reading List is empty", "The Reading List is empty");
}
// Get the reader icon method
protected View getReaderIcon() {
View pageActionLayout = mSolo.getView(0x7f070025);
ArrayList<String> pageActionLayoutChilds = new ArrayList();
View actionLayoutItem = pageActionLayout;
ViewGroup actionLayoutEntry = (ViewGroup)actionLayoutItem;
View icon = actionLayoutEntry.getChildAt(1);
return icon;
}
// This method check to see if a reader item is added to the reader list
private boolean isAdded(String eventData) {
try {
JSONObject data = new JSONObject(eventData);
if (data.getInt("result") == 0) {
mAsserter.ok(true, "Waiting for the page to be added to your Reading List", "The page was added to your Reading List");
}
else {
if (data.getInt("result") == 2) {
mAsserter.ok(true, "Trying to add a second time the page in your Reading List", "The page is already in your Reading List");
}
}
} catch (JSONException e) {
mAsserter.ok(false, "Error parsing the event data", e.toString());
return false;
}
return true;
}
}

Просмотреть файл

@ -3,7 +3,6 @@
# You can obtain one at http://mozilla.org/MPL/2.0/.
modules := \
log4moz.js \
storageservice.js \
stringbundle.js \
tokenserverclient.js \

Просмотреть файл

@ -24,7 +24,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/rest.js");
Cu.import("resource://services-common/utils.js");
@ -47,8 +47,8 @@ Object.freeze(BagheeraClientRequestResult.prototype);
function BagheeraRequest(uri) {
RESTRequest.call(this, uri);
this._log = Log4Moz.repository.getLogger("Services.BagheeraClient");
this._log.level = Log4Moz.Level.Debug;
this._log = Log.repository.getLogger("Services.BagheeraClient");
this._log.level = Log.Level.Debug;
}
BagheeraRequest.prototype = Object.freeze({
@ -69,8 +69,8 @@ this.BagheeraClient = function BagheeraClient(baseURI) {
throw new Error("baseURI argument must be defined.");
}
this._log = Log4Moz.repository.getLogger("Services.BagheeraClient");
this._log.level = Log4Moz.Level.Debug;
this._log = Log.repository.getLogger("Services.BagheeraClient");
this._log.level = Log.Level.Debug;
this.baseURI = baseURI;

Просмотреть файл

@ -8,7 +8,7 @@ const {utils: Cu} = Components;
this.EXPORTED_SYMBOLS = ["BagheeraServer"];
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://testing-common/httpd.js");
@ -23,7 +23,7 @@ Cu.import("resource://testing-common/httpd.js");
* The Bagheera server is essentially a glorified document store.
*/
this.BagheeraServer = function BagheeraServer() {
this._log = Log4Moz.repository.getLogger("metrics.BagheeraServer");
this._log = Log.repository.getLogger("metrics.BagheeraServer");
this.server = new HttpServer();
this.namespaces = {};

Просмотреть файл

@ -11,7 +11,7 @@ this.EXPORTED_SYMBOLS = [
const {utils: Cu} = Components;
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
this.initTestLogging = function initTestLogging(level) {
function LogStats() {
@ -19,7 +19,7 @@ this.initTestLogging = function initTestLogging(level) {
}
LogStats.prototype = {
format: function format(message) {
if (message.level == Log4Moz.Level.Error) {
if (message.level == Log.Level.Error) {
this.errorsLogged += 1;
}
@ -27,20 +27,20 @@ this.initTestLogging = function initTestLogging(level) {
message.message + "\n";
}
};
LogStats.prototype.__proto__ = new Log4Moz.Formatter();
LogStats.prototype.__proto__ = new Log.Formatter();
let log = Log4Moz.repository.rootLogger;
let log = Log.repository.rootLogger;
let logStats = new LogStats();
let appender = new Log4Moz.DumpAppender(logStats);
let appender = new Log.DumpAppender(logStats);
if (typeof(level) == "undefined") {
level = "Debug";
}
getTestLogger().level = Log4Moz.Level[level];
Log4Moz.repository.getLogger("Services").level = Log4Moz.Level[level];
getTestLogger().level = Log.Level[level];
Log.repository.getLogger("Services").level = Log.Level[level];
log.level = Log4Moz.Level.Trace;
appender.level = Log4Moz.Level.Trace;
log.level = Log.Level.Trace;
appender.level = Log.Level.Trace;
// Overwrite any other appenders (e.g. from previous incarnations)
log.ownAppenders = [appender];
log.updateAppenders();
@ -49,6 +49,6 @@ this.initTestLogging = function initTestLogging(level) {
}
this.getTestLogger = function getTestLogger(component) {
return Log4Moz.repository.getLogger("Testing");
return Log.repository.getLogger("Testing");
}

Просмотреть файл

@ -20,7 +20,7 @@ this.EXPORTED_SYMBOLS = [
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/utils.js");
const STORAGE_HTTP_LOGGER = "Services.Common.Test.Server";
@ -74,7 +74,7 @@ this.ServerBSO = function ServerBSO(id, payload, modified) {
throw new Error("BSO ID is invalid: " + id);
}
this._log = Log4Moz.repository.getLogger(STORAGE_HTTP_LOGGER);
this._log = Log.repository.getLogger(STORAGE_HTTP_LOGGER);
this.id = id;
if (!payload) {
@ -287,7 +287,7 @@ this.StorageServerCollection =
CommonUtils.ensureMillisecondsTimestamp(timestamp);
this._timestamp = timestamp;
this._log = Log4Moz.repository.getLogger(STORAGE_HTTP_LOGGER);
this._log = Log.repository.getLogger(STORAGE_HTTP_LOGGER);
}
StorageServerCollection.prototype = {
BATCH_MAX_COUNT: 100, // # of records.
@ -872,7 +872,7 @@ this.StorageServer = function StorageServer(callback) {
this.started = false;
this.users = {};
this.requestCount = 0;
this._log = Log4Moz.repository.getLogger(STORAGE_HTTP_LOGGER);
this._log = Log.repository.getLogger(STORAGE_HTTP_LOGGER);
// Install our own default handler. This allows us to mess around with the
// whole URL space.

Просмотреть файл

@ -17,7 +17,7 @@ this.EXPORTED_SYMBOLS = [
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/utils.js");
XPCOMUtils.defineLazyModuleGetter(this, "CryptoUtils",
@ -91,9 +91,9 @@ this.RESTRequest = function RESTRequest(uri) {
this.uri = uri;
this._headers = {};
this._log = Log4Moz.repository.getLogger(this._logName);
this._log = Log.repository.getLogger(this._logName);
this._log.level =
Log4Moz.Level[Prefs.get("log.logger.rest.request")];
Log.Level[Prefs.get("log.logger.rest.request")];
}
RESTRequest.prototype = {
@ -309,7 +309,7 @@ RESTRequest.prototype = {
}
this._log.debug(method + " Length: " + data.length);
if (this._log.level <= Log4Moz.Level.Trace) {
if (this._log.level <= Log.Level.Trace) {
this._log.trace(method + " Body: " + data);
}
@ -444,7 +444,7 @@ RESTRequest.prototype = {
this._log.debug(this.method + " " + uri + " " + this.response.status);
// Additionally give the full response body when Trace logging.
if (this._log.level <= Log4Moz.Level.Trace) {
if (this._log.level <= Log.Level.Trace) {
this._log.trace(this.method + " body: " + this.response.body);
}
@ -593,9 +593,9 @@ RESTRequest.prototype = {
* the RESTRequest.
*/
this.RESTResponse = function RESTResponse() {
this._log = Log4Moz.repository.getLogger(this._logName);
this._log = Log.repository.getLogger(this._logName);
this._log.level =
Log4Moz.Level[Prefs.get("log.logger.rest.response")];
Log.Level[Prefs.get("log.logger.rest.response")];
}
RESTResponse.prototype = {

Просмотреть файл

@ -35,7 +35,7 @@ const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/rest.js");
Cu.import("resource://services-common/utils.js");
@ -470,8 +470,8 @@ this.StorageServiceRequestError = function StorageServiceRequestError() {
* to implement it transparently.
*/
function StorageServiceRequest() {
this._log = Log4Moz.repository.getLogger("Sync.StorageService.Request");
this._log.level = Log4Moz.Level[Prefs.get("log.level")];
this._log = Log.repository.getLogger("Sync.StorageService.Request");
this._log.level = Log.Level[Prefs.get("log.level")];
this.notModified = false;
@ -1521,8 +1521,8 @@ Object.freeze(StorageCollectionBatchedDelete.prototype);
* (string) Base URI for all requests.
*/
this.StorageServiceClient = function StorageServiceClient(baseURI) {
this._log = Log4Moz.repository.getLogger("Services.Common.StorageServiceClient");
this._log.level = Log4Moz.Level[Prefs.get("log.level")];
this._log = Log.repository.getLogger("Services.Common.StorageServiceClient");
this._log.level = Log.Level[Prefs.get("log.level")];
this._baseURI = baseURI;

Просмотреть файл

@ -2,13 +2,13 @@
* 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/. */
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://testing-common/services-common/logging.js");
let btoa = Cu.import("resource://services-common/log4moz.js").btoa;
let atob = Cu.import("resource://services-common/log4moz.js").atob;
let btoa = Cu.import("resource://gre/modules/Log.jsm").btoa;
let atob = Cu.import("resource://gre/modules/Log.jsm").atob;
function do_check_empty(obj) {
do_check_attribute_count(obj, 0);

Просмотреть файл

@ -4,7 +4,6 @@
const modules = [
"async.js",
"bagheeraclient.js",
"log4moz.js",
"rest.js",
"storageservice.js",
"stringbundle.js",

Просмотреть файл

@ -2,15 +2,15 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/rest.js");
Cu.import("resource://services-common/utils.js");
//DEBUG = true;
function run_test() {
Log4Moz.repository.getLogger("Services.Common.RESTRequest").level =
Log4Moz.Level.Trace;
Log.repository.getLogger("Services.Common.RESTRequest").level =
Log.Level.Trace;
initTestLogging("Trace");
run_next_test();

Просмотреть файл

@ -105,8 +105,8 @@ function doDeleteRequest(request) {
}
function run_test() {
Log4Moz.repository.getLogger("Services.Common.Test.StorageServer").level =
Log4Moz.Level.Trace;
Log.repository.getLogger("Services.Common.Test.StorageServer").level =
Log.Level.Trace;
initTestLogging();
run_next_test();

Просмотреть файл

@ -25,7 +25,6 @@ firefox-appdir = browser
[test_async_querySpinningly.js]
[test_bagheera_server.js]
[test_bagheera_client.js]
[test_log4moz.js]
[test_observers.js]
[test_restrequest.js]
[test_tokenauthenticatedrequest.js]

Просмотреть файл

@ -14,7 +14,7 @@ this.EXPORTED_SYMBOLS = [
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/rest.js");
Cu.import("resource://services-common/utils.js");
@ -114,8 +114,8 @@ TokenServerClientServerError.prototype.constructor =
* at fault (e.g. differentiating a 503 from a 401).
*/
this.TokenServerClient = function TokenServerClient() {
this._log = Log4Moz.repository.getLogger("Common.TokenServerClient");
this._log.level = Log4Moz.Level[Prefs.get("logger.level")];
this._log = Log.repository.getLogger("Common.TokenServerClient");
this._log.level = Log.Level[Prefs.get("logger.level")];
}
TokenServerClient.prototype = {
/**

Просмотреть файл

@ -10,7 +10,7 @@ Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/osfile.jsm")
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
this.CommonUtils = {
exceptionStr: function exceptionStr(e) {
@ -88,7 +88,7 @@ this.CommonUtils = {
try {
return Services.io.newURI(URIString, null, null);
} catch (e) {
let log = Log4Moz.repository.getLogger("Common.Utils");
let log = Log.repository.getLogger("Common.Utils");
log.debug("Could not create URI: " + CommonUtils.exceptionStr(e));
return null;
}
@ -464,7 +464,7 @@ this.CommonUtils = {
* @param def
* (Number) The default value to use if the preference is not defined.
* @param log
* (Log4Moz.Logger) Logger to write warnings to.
* (Log.Logger) Logger to write warnings to.
*/
getEpochPref: function getEpochPref(branch, pref, def=0, log=null) {
if (!Number.isInteger(def)) {
@ -507,7 +507,7 @@ this.CommonUtils = {
* (Number) The default value (in milliseconds) if the preference is
* not defined or invalid.
* @param log
* (Log4Moz.Logger) Logger to write warnings to.
* (Log.Logger) Logger to write warnings to.
* @param oldestYear
* (Number) Oldest year to accept in read values.
*/

Просмотреть файл

@ -223,7 +223,7 @@ DataReportingService.prototype = Object.freeze({
Cu.import("resource://gre/modules/Task.jsm", ns);
Cu.import("resource://gre/modules/HealthReport.jsm", ns);
Cu.import("resource://services-common/log4moz.js", ns);
Cu.import("resource://gre/modules/Log.jsm", ns);
// How many times will we rewrite this code before rolling it up into a
// generic module? See also bug 451283.
@ -238,22 +238,22 @@ DataReportingService.prototype = Object.freeze({
let loggingPrefs = new Preferences(HEALTHREPORT_LOGGING_BRANCH);
if (loggingPrefs.get("consoleEnabled", true)) {
let level = loggingPrefs.get("consoleLevel", "Warn");
let appender = new ns.Log4Moz.ConsoleAppender();
appender.level = ns.Log4Moz.Level[level] || ns.Log4Moz.Level.Warn;
let appender = new ns.Log.ConsoleAppender();
appender.level = ns.Log.Level[level] || ns.Log.Level.Warn;
for (let name of LOGGERS) {
let logger = ns.Log4Moz.repository.getLogger(name);
let logger = ns.Log.repository.getLogger(name);
logger.addAppender(appender);
}
}
if (loggingPrefs.get("dumpEnabled", false)) {
let level = loggingPrefs.get("dumpLevel", "Debug");
let appender = new ns.Log4Moz.DumpAppender();
appender.level = ns.Log4Moz.Level[level] || ns.Log4Moz.Level.Debug;
let appender = new ns.Log.DumpAppender();
appender.level = ns.Log.Level[level] || ns.Log.Level.Debug;
for (let name of LOGGERS) {
let logger = ns.Log4Moz.repository.getLogger(name);
let logger = ns.Log.repository.getLogger(name);
logger.addAppender(appender);
}
}

Просмотреть файл

@ -8,12 +8,12 @@ this.EXPORTED_SYMBOLS = ["MockPolicyListener"];
const {utils: Cu} = Components;
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
this.MockPolicyListener = function MockPolicyListener() {
this._log = Log4Moz.repository.getLogger("Services.DataReporting.Testing.MockPolicyListener");
this._log.level = Log4Moz.Level["Debug"];
this._log = Log.repository.getLogger("Services.DataReporting.Testing.MockPolicyListener");
this._log.level = Log.Level["Debug"];
this.requestDataUploadCount = 0;
this.lastDataRequest = null;

Просмотреть файл

@ -27,7 +27,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
#endif
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/utils.js");
const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
@ -263,8 +263,8 @@ this.DataSubmissionRequest.prototype = Object.freeze({
* events.
*/
this.DataReportingPolicy = function (prefs, healthReportPrefs, listener) {
this._log = Log4Moz.repository.getLogger("Services.DataReporting.Policy");
this._log.level = Log4Moz.Level["Debug"];
this._log = Log.repository.getLogger("Services.DataReporting.Policy");
this._log.level = Log.Level["Debug"];
for (let handler of this.REQUIRED_LISTENERS) {
if (!listener[handler]) {

Просмотреть файл

@ -16,7 +16,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/utils.js");
@ -69,7 +69,7 @@ this.SessionRecorder = function (branch) {
throw new Error("branch argument must end with '.': " + branch);
}
this._log = Log4Moz.repository.getLogger("Services.DataReporting.SessionRecorder");
this._log = Log.repository.getLogger("Services.DataReporting.SessionRecorder");
this._prefs = new Preferences(branch);
this._lastActivityWasInactive = false;

Просмотреть файл

@ -18,7 +18,7 @@ Cu.import("resource://services-common/async.js");
Cu.import("resource://services-common/bagheeraclient.js");
#endif
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
@ -260,7 +260,7 @@ function AbstractHealthReporter(branch, policy, sessionRecorder) {
throw new Error("Must provide policy to HealthReporter constructor.");
}
this._log = Log4Moz.repository.getLogger("Services.HealthReport.HealthReporter");
this._log = Log.repository.getLogger("Services.HealthReport.HealthReporter");
this._log.info("Initializing health reporter instance against " + branch);
this._branch = branch;

Просмотреть файл

@ -25,7 +25,7 @@ const REQUIRED_UINT32_TYPE = {type: "TYPE_UINT32"};
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/osfile.jsm")
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/utils.js");
// Profile creation time access.

Просмотреть файл

@ -20,7 +20,7 @@ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/utils.js");
@ -86,7 +86,7 @@ this.Measurement = function () {
}
}
this._log = Log4Moz.repository.getLogger("Services.Metrics.Measurement." + this.name);
this._log = Log.repository.getLogger("Services.Metrics.Measurement." + this.name);
this.id = null;
this.storage = null;
@ -502,7 +502,7 @@ this.Provider = function () {
throw new Error("Provider must define measurement types.");
}
this._log = Log4Moz.repository.getLogger("Services.Metrics.Provider." + this.name);
this._log = Log.repository.getLogger("Services.Metrics.Provider." + this.name);
this.measurements = null;
this.storage = null;

Просмотреть файл

@ -14,7 +14,7 @@ Cu.import("resource://gre/modules/services/metrics/dataprovider.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/utils.js");
@ -25,7 +25,7 @@ Cu.import("resource://services-common/utils.js");
* provides APIs for bulk collection of data.
*/
this.ProviderManager = function (storage) {
this._log = Log4Moz.repository.getLogger("Services.Metrics.ProviderManager");
this._log = Log.repository.getLogger("Services.Metrics.ProviderManager");
this._providers = new Map();
this._storage = storage;

Просмотреть файл

@ -22,7 +22,7 @@ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/Sqlite.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/utils.js");
@ -698,7 +698,7 @@ this.MetricsStorageBackend = function (path) {
* FUTURE enforce 1 read/write connection per database limit.
*/
function MetricsStorageSqliteBackend(connection) {
this._log = Log4Moz.repository.getLogger("Services.Metrics.MetricsStorage");
this._log = Log.repository.getLogger("Services.Metrics.MetricsStorage");
this._connection = connection;
this._enabledWALCheckpointPages = null;

Просмотреть файл

@ -16,7 +16,7 @@ const {utils: Cu} = Components;
Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/util.js");
let btoa = Cu.import("resource://services-common/log4moz.js").btoa;
let btoa = Cu.import("resource://gre/modules/Log.jsm").btoa;
this.FakeFilesystemService = function FakeFilesystemService(contents) {
this.fakeContents = contents;

Просмотреть файл

@ -19,7 +19,7 @@
const Cu = Components.utils;
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://gre/modules/AddonManager.jsm");
@ -113,9 +113,9 @@ this.EXPORTED_SYMBOLS = ["AddonsReconciler", "CHANGE_INSTALLED",
* heed them like they were normal. In the end, the state is proper.
*/
this.AddonsReconciler = function AddonsReconciler() {
this._log = Log4Moz.repository.getLogger("Sync.AddonsReconciler");
this._log = Log.repository.getLogger("Sync.AddonsReconciler");
let level = Svc.Prefs.get("log.logger.addonsreconciler", "Debug");
this._log.level = Log4Moz.Level[level];
this._log.level = Log.Level[level];
Svc.Obs.add("xpcom-shutdown", this.stopListening, this);
};
@ -140,7 +140,7 @@ AddonsReconciler.prototype = {
*/
_shouldPersist: true,
/** log4moz logger instance */
/** Log logger instance */
_log: null,
/**

Просмотреть файл

@ -9,7 +9,7 @@ this.EXPORTED_SYMBOLS = ["AddonUtils"];
const {interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-sync/util.js");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
@ -18,8 +18,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository",
"resource://gre/modules/AddonRepository.jsm");
function AddonUtilsInternal() {
this._log = Log4Moz.repository.getLogger("Sync.AddonUtils");
this._log.Level = Log4Moz.Level[Svc.Prefs.get("log.logger.addonutils")];
this._log = Log.repository.getLogger("Sync.AddonUtils");
this._log.Level = Log.Level[Svc.Prefs.get("log.logger.addonutils")];
}
AddonUtilsInternal.prototype = {
/**

Просмотреть файл

@ -13,7 +13,7 @@ this.EXPORTED_SYMBOLS = [
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://services-sync/constants.js");
@ -42,9 +42,9 @@ this.Tracker = function Tracker(name, engine) {
this.name = this.file = name.toLowerCase();
this.engine = engine;
this._log = Log4Moz.repository.getLogger("Sync.Tracker." + name);
this._log = Log.repository.getLogger("Sync.Tracker." + name);
let level = Svc.Prefs.get("log.logger.engine." + this.name, "Debug");
this._log.level = Log4Moz.Level[level];
this._log.level = Log.Level[level];
this._score = 0;
this._ignored = [];
@ -197,9 +197,9 @@ this.Store = function Store(name, engine) {
this.name = name.toLowerCase();
this.engine = engine;
this._log = Log4Moz.repository.getLogger("Sync.Store." + name);
this._log = Log.repository.getLogger("Sync.Store." + name);
let level = Svc.Prefs.get("log.logger.engine." + this.name, "Debug");
this._log.level = Log4Moz.Level[level];
this._log.level = Log.Level[level];
XPCOMUtils.defineLazyGetter(this, "_timer", function() {
return Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
@ -383,8 +383,8 @@ this.EngineManager = function EngineManager(service) {
this.service = service;
this._engines = {};
this._log = Log4Moz.repository.getLogger("Sync.EngineManager");
this._log.level = Log4Moz.Level[Svc.Prefs.get(
this._log = Log.repository.getLogger("Sync.EngineManager");
this._log.level = Log.Level[Svc.Prefs.get(
"log.logger.service.engines", "Debug")];
}
EngineManager.prototype = {
@ -476,9 +476,9 @@ this.Engine = function Engine(name, service) {
this.service = service;
this._notify = Utils.notify("weave:engine:");
this._log = Log4Moz.repository.getLogger("Sync.Engine." + this.Name);
this._log = Log.repository.getLogger("Sync.Engine." + this.Name);
let level = Svc.Prefs.get("log.logger.engine." + this.name, "Debug");
this._log.level = Log4Moz.Level[level];
this._log.level = Log.Level[level];
this._tracker; // initialize tracker to load previously changed IDs
this._log.debug("Engine initialized");
@ -1056,7 +1056,7 @@ SyncEngine.prototype = {
* Truthy if incoming record should be applied. False if not.
*/
_reconcile: function _reconcile(item) {
if (this._log.level <= Log4Moz.Level.Trace) {
if (this._log.level <= Log.Level.Trace) {
this._log.trace("Incoming: " + item);
}
@ -1273,7 +1273,7 @@ SyncEngine.prototype = {
for each (let id in modifiedIDs) {
try {
let out = this._createRecord(id);
if (this._log.level <= Log4Moz.Level.Trace)
if (this._log.level <= Log.Level.Trace)
this._log.trace("Outgoing: " + out);
out.encrypt(this.service.collectionKeys.keyForCollection(this.name));

Просмотреть файл

@ -14,7 +14,7 @@ Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
const FORMS_TTL = 5184000; // 60 days
@ -31,7 +31,7 @@ Utils.deferGetSet(FormRec, "cleartext", ["name", "value"]);
let FormWrapper = {
_log: Log4Moz.repository.getLogger("Sync.Engine.Forms"),
_log: Log.repository.getLogger("Sync.Engine.Forms"),
_getEntryCols: ["fieldname", "value"],
_guidCols: ["guid"],

Просмотреть файл

@ -13,7 +13,7 @@ const HISTORY_TTL = 5184000; // 60 days
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/record.js");

Просмотреть файл

@ -10,7 +10,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-sync/util.js");
// Lazy import to prevent unnecessary load on startup.
@ -57,8 +57,8 @@ for (let symbol of ["BulkKeyBundle", "SyncKeyBundle"]) {
* and any other function that involves the built-in functionality.
*/
this.IdentityManager = function IdentityManager() {
this._log = Log4Moz.repository.getLogger("Sync.Identity");
this._log.Level = Log4Moz.Level[Svc.Prefs.get("log.logger.identity")];
this._log = Log.repository.getLogger("Sync.Identity");
this._log.Level = Log.Level[Svc.Prefs.get("log.logger.identity")];
this._basicPassword = null;
this._basicPasswordAllowLookup = true;

Просмотреть файл

@ -6,7 +6,7 @@ this.EXPORTED_SYMBOLS = ["JPAKEClient", "SendCredentialsController"];
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/rest.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/util.js");
@ -114,8 +114,8 @@ const JPAKE_VERIFY_VALUE = "0123456789ABCDEF";
this.JPAKEClient = function JPAKEClient(controller) {
this.controller = controller;
this._log = Log4Moz.repository.getLogger("Sync.JPAKEClient");
this._log.level = Log4Moz.Level[Svc.Prefs.get(
this._log = Log.repository.getLogger("Sync.JPAKEClient");
this._log.level = Log.Level[Svc.Prefs.get(
"log.logger.service.jpakeclient", "Debug")];
this._serverURL = Svc.Prefs.get("jpake.serverURL");
@ -700,8 +700,8 @@ JPAKEClient.prototype = {
*/
this.SendCredentialsController =
function SendCredentialsController(jpakeclient, service) {
this._log = Log4Moz.repository.getLogger("Sync.SendCredentialsController");
this._log.level = Log4Moz.Level[Svc.Prefs.get("log.logger.service.main")];
this._log = Log.repository.getLogger("Sync.SendCredentialsController");
this._log.level = Log.Level[Svc.Prefs.get("log.logger.service.main")];
this._log.trace("Loading.");
this.jpakeclient = jpakeclient;

Просмотреть файл

@ -12,7 +12,7 @@ this.EXPORTED_SYMBOLS = [
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-sync/util.js");
/**
@ -120,7 +120,7 @@ KeyBundle.prototype = {
* This is just a KeyBundle with a collection attached.
*/
this.BulkKeyBundle = function BulkKeyBundle(collection) {
let log = Log4Moz.repository.getLogger("Sync.BulkKeyBundle");
let log = Log.repository.getLogger("Sync.BulkKeyBundle");
log.info("BulkKeyBundle being created for " + collection);
KeyBundle.call(this);
@ -177,7 +177,7 @@ BulkKeyBundle.prototype = {
* If the username or Sync Key is invalid, an Error will be thrown.
*/
this.SyncKeyBundle = function SyncKeyBundle(username, syncKey) {
let log = Log4Moz.repository.getLogger("Sync.SyncKeyBundle");
let log = Log.repository.getLogger("Sync.SyncKeyBundle");
log.info("SyncKeyBundle being created.");
KeyBundle.call(this);

Просмотреть файл

@ -10,7 +10,7 @@ const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-sync/util.js");
this.Notifications = {
@ -115,7 +115,7 @@ this.NotificationButton =
try {
callback.apply(this, arguments);
} catch (e) {
let logger = Log4Moz.repository.getLogger("Sync.Notifications");
let logger = Log.repository.getLogger("Sync.Notifications");
logger.error("An exception occurred: " + Utils.exceptionStr(e));
logger.info(Utils.stackTrace(e));
throw e;

Просмотреть файл

@ -9,7 +9,7 @@ this.EXPORTED_SYMBOLS = [
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/status.js");
@ -20,7 +20,7 @@ this.SyncScheduler = function SyncScheduler(service) {
this.init();
}
SyncScheduler.prototype = {
_log: Log4Moz.repository.getLogger("Sync.SyncScheduler"),
_log: Log.repository.getLogger("Sync.SyncScheduler"),
_fatalLoginStatus: [LOGIN_FAILED_NO_USERNAME,
LOGIN_FAILED_NO_PASSWORD,
@ -67,7 +67,7 @@ SyncScheduler.prototype = {
set numClients(value) Svc.Prefs.set("numClients", value),
init: function init() {
this._log.level = Log4Moz.Level[Svc.Prefs.get("log.logger.service.main")];
this._log.level = Log.Level[Svc.Prefs.get("log.logger.service.main")];
this.setDefaults();
Svc.Obs.add("weave:engine:score:updated", this);
Svc.Obs.add("network:offline-status-changed", this);
@ -500,24 +500,24 @@ ErrorHandler.prototype = {
},
initLogs: function initLogs() {
this._log = Log4Moz.repository.getLogger("Sync.ErrorHandler");
this._log.level = Log4Moz.Level[Svc.Prefs.get("log.logger.service.main")];
this._log = Log.repository.getLogger("Sync.ErrorHandler");
this._log.level = Log.Level[Svc.Prefs.get("log.logger.service.main")];
this._cleaningUpFileLogs = false;
let root = Log4Moz.repository.getLogger("Sync");
root.level = Log4Moz.Level[Svc.Prefs.get("log.rootLogger")];
let root = Log.repository.getLogger("Sync");
root.level = Log.Level[Svc.Prefs.get("log.rootLogger")];
let formatter = new Log4Moz.BasicFormatter();
let capp = new Log4Moz.ConsoleAppender(formatter);
capp.level = Log4Moz.Level[Svc.Prefs.get("log.appender.console")];
let formatter = new Log.BasicFormatter();
let capp = new Log.ConsoleAppender(formatter);
capp.level = Log.Level[Svc.Prefs.get("log.appender.console")];
root.addAppender(capp);
let dapp = new Log4Moz.DumpAppender(formatter);
dapp.level = Log4Moz.Level[Svc.Prefs.get("log.appender.dump")];
let dapp = new Log.DumpAppender(formatter);
dapp.level = Log.Level[Svc.Prefs.get("log.appender.dump")];
root.addAppender(dapp);
let fapp = this._logAppender = new Log4Moz.StorageStreamAppender(formatter);
fapp.level = Log4Moz.Level[Svc.Prefs.get("log.appender.file.level")];
let fapp = this._logAppender = new Log.StorageStreamAppender(formatter);
fapp.level = Log.Level[Svc.Prefs.get("log.appender.file.level")];
root.addAppender(fapp);
},

Просмотреть файл

@ -18,7 +18,7 @@ const Cu = Components.utils;
const CRYPTO_COLLECTION = "crypto";
const KEYS_WBO = "keys";
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/keys.js");
Cu.import("resource://services-sync/resource.js");
@ -111,7 +111,7 @@ Utils.deferGetSet(WBORecord, "data", ["id", "modified", "sortindex", "payload"])
this.RecordManager = function RecordManager(service) {
this.service = service;
this._log = Log4Moz.repository.getLogger(this._logName);
this._log = Log.repository.getLogger(this._logName);
this._records = {};
}
RecordManager.prototype = {
@ -281,7 +281,7 @@ this.CollectionKeyManager = function CollectionKeyManager() {
this._collections = {};
this._default = null;
this._log = Log4Moz.repository.getLogger("Sync.CollectionKeyManager");
this._log = Log.repository.getLogger("Sync.CollectionKeyManager");
}
// TODO: persist this locally as an Identity. Bug 610913.

Просмотреть файл

@ -14,7 +14,7 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://services-sync/constants.js");
@ -50,9 +50,9 @@ const DEFAULT_LOAD_FLAGS =
* the status of the HTTP response.
*/
this.AsyncResource = function AsyncResource(uri) {
this._log = Log4Moz.repository.getLogger(this._logName);
this._log = Log.repository.getLogger(this._logName);
this._log.level =
Log4Moz.Level[Svc.Prefs.get("log.logger.network.resources")];
Log.Level[Svc.Prefs.get("log.logger.network.resources")];
this.uri = uri;
this._headers = {};
this._onComplete = Utils.bind2(this, this._onComplete);
@ -265,7 +265,7 @@ AsyncResource.prototype = {
this._log.debug(mesg);
// Additionally give the full response body when Trace logging.
if (this._log.level <= Log4Moz.Level.Trace)
if (this._log.level <= Log.Level.Trace)
this._log.trace(action + " body: " + data);
} catch(ex) {
@ -588,8 +588,8 @@ ChannelListener.prototype = {
function ChannelNotificationListener(headersToCopy) {
this._headersToCopy = headersToCopy;
this._log = Log4Moz.repository.getLogger(this._logName);
this._log.level = Log4Moz.Level[Svc.Prefs.get("log.logger.network.resources")];
this._log = Log.repository.getLogger(this._logName);
this._log.level = Log.Level[Svc.Prefs.get("log.logger.network.resources")];
}
ChannelNotificationListener.prototype = {
_logName: "Sync.Resource",
@ -609,7 +609,7 @@ ChannelNotificationListener.prototype = {
},
notifyCertProblem: function certProblem(socketInfo, sslStatus, targetHost) {
let log = Log4Moz.repository.getLogger("Sync.CertListener");
let log = Log.repository.getLogger("Sync.CertListener");
log.warn("Invalid HTTPS certificate encountered!");
// This suppresses the UI warning only. The request is still cancelled.

Просмотреть файл

@ -4,7 +4,7 @@
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/rest.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/constants.js");

Просмотреть файл

@ -20,7 +20,7 @@ const KEYS_WBO = "keys";
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/engines.js");
@ -317,9 +317,9 @@ Sync11Service.prototype = {
this.errorHandler = new ErrorHandler(this);
this._log = Log4Moz.repository.getLogger("Sync.Service");
this._log = Log.repository.getLogger("Sync.Service");
this._log.level =
Log4Moz.Level[Svc.Prefs.get("log.logger.service.main")];
Log.Level[Svc.Prefs.get("log.logger.service.main")];
this._log.info("Loading Weave " + WEAVE_VERSION);

Просмотреть файл

@ -6,7 +6,7 @@ this.EXPORTED_SYMBOLS = ["ClusterManager"];
const {utils: Cu} = Components;
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/policies.js");
Cu.import("resource://services-sync/util.js");
@ -15,8 +15,8 @@ Cu.import("resource://services-sync/util.js");
* Contains code for managing the Sync cluster we are in.
*/
this.ClusterManager = function ClusterManager(service) {
this._log = Log4Moz.repository.getLogger("Sync.Service");
this._log.level = Log4Moz.Level[Svc.Prefs.get("log.logger.service.main")];
this._log = Log.repository.getLogger("Sync.Service");
this._log.level = Log.Level[Svc.Prefs.get("log.logger.service.main")];
this.service = service;
}

Просмотреть файл

@ -10,7 +10,7 @@ this.EXPORTED_SYMBOLS = ["EngineSynchronizer"];
const {utils: Cu} = Components;
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/engines.js");
Cu.import("resource://services-sync/policies.js");
@ -22,8 +22,8 @@ Cu.import("resource://services-sync/util.js");
* This was originally split out of service.js. The API needs lots of love.
*/
this.EngineSynchronizer = function EngineSynchronizer(service) {
this._log = Log4Moz.repository.getLogger("Sync.Synchronizer");
this._log.level = Log4Moz.Level[Svc.Prefs.get("log.logger.synchronizer")];
this._log = Log.repository.getLogger("Sync.Synchronizer");
this._log.level = Log.Level[Svc.Prefs.get("log.logger.synchronizer")];
this.service = service;

Просмотреть файл

@ -10,12 +10,12 @@ const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://gre/modules/Services.jsm");
this.Status = {
_log: Log4Moz.repository.getLogger("Sync.Status"),
_log: Log.repository.getLogger("Sync.Status"),
_authManager: new IdentityManager(),
ready: false,
@ -114,7 +114,7 @@ this.Status = {
} catch (ex) {
// Use default.
}
this._log.level = Log4Moz.Level[logLevel];
this._log.level = Log.Level[logLevel];
this._log.info("Resetting Status.");
this.service = STATUS_OK;

Просмотреть файл

@ -10,7 +10,7 @@ this.EXPORTED_SYMBOLS = [
const {utils: Cu} = Components;
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/rest.js");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://services-sync/identity.js");
@ -24,8 +24,8 @@ Cu.import("resource://services-sync/util.js");
* Instances are constructed with the base URI of the service.
*/
this.UserAPI10Client = function UserAPI10Client(baseURI) {
this._log = Log4Moz.repository.getLogger("Sync.UserAPI");
this._log.level = Log4Moz.Level[Svc.Prefs.get("log.logger.userapi")];
this._log = Log.repository.getLogger("Sync.UserAPI");
this._log.level = Log.Level[Svc.Prefs.get("log.logger.userapi")];
this.baseURI = baseURI;
}

Просмотреть файл

@ -7,7 +7,7 @@ this.EXPORTED_SYMBOLS = ["XPCOMUtils", "Services", "NetUtil", "PlacesUtils",
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-common/stringbundle.js");
Cu.import("resource://services-common/utils.js");

Просмотреть файл

@ -1,7 +1,7 @@
const Cm = Components.manager;
// Shared logging for all HTTP server functions.
Cu.import("resource://services-common/log4moz.js");
Cu.import("resource://gre/modules/Log.jsm");
const SYNC_HTTP_LOGGER = "Sync.Test.Server";
const SYNC_API_VERSION = "1.1";
@ -163,7 +163,7 @@ function ServerCollection(wbos, acceptNew, timestamp) {
* has a modified time.
*/
this.timestamp = timestamp || new_timestamp();
this._log = Log4Moz.repository.getLogger(SYNC_HTTP_LOGGER);
this._log = Log.repository.getLogger(SYNC_HTTP_LOGGER);
}
ServerCollection.prototype = {
@ -527,7 +527,7 @@ function SyncServer(callback) {
this.server = new HttpServer();
this.started = false;
this.users = {};
this._log = Log4Moz.repository.getLogger(SYNC_HTTP_LOGGER);
this._log = Log.repository.getLogger(SYNC_HTTP_LOGGER);
// Install our own default handler. This allows us to mess around with the
// whole URL space.

Просмотреть файл

@ -240,13 +240,13 @@ add_test(function cleanup() {
function run_test() {
initTestLogging("Trace");
Log4Moz.repository.getLogger("Sync.Engine.Addons").level =
Log4Moz.Level.Trace;
Log4Moz.repository.getLogger("Sync.Store.Addons").level = Log4Moz.Level.Trace;
Log4Moz.repository.getLogger("Sync.Tracker.Addons").level =
Log4Moz.Level.Trace;
Log4Moz.repository.getLogger("Sync.AddonsRepository").level =
Log4Moz.Level.Trace;
Log.repository.getLogger("Sync.Engine.Addons").level =
Log.Level.Trace;
Log.repository.getLogger("Sync.Store.Addons").level = Log.Level.Trace;
Log.repository.getLogger("Sync.Tracker.Addons").level =
Log.Level.Trace;
Log.repository.getLogger("Sync.AddonsRepository").level =
Log.Level.Trace;
reconciler.startListening();

Просмотреть файл

@ -14,9 +14,9 @@ startupManager();
function run_test() {
initTestLogging("Trace");
Log4Moz.repository.getLogger("Sync.AddonsReconciler").level = Log4Moz.Level.Trace;
Log4Moz.repository.getLogger("Sync.AddonsReconciler").level =
Log4Moz.Level.Trace;
Log.repository.getLogger("Sync.AddonsReconciler").level = Log.Level.Trace;
Log.repository.getLogger("Sync.AddonsReconciler").level =
Log.Level.Trace;
Svc.Prefs.set("engine.addons", true);
Service.engineManager.register(AddonsEngine);

Просмотреть файл

@ -67,9 +67,9 @@ function createAndStartHTTPServer(port) {
function run_test() {
initTestLogging("Trace");
Log4Moz.repository.getLogger("Sync.Engine.Addons").level = Log4Moz.Level.Trace;
Log4Moz.repository.getLogger("Sync.AddonsRepository").level =
Log4Moz.Level.Trace;
Log.repository.getLogger("Sync.Engine.Addons").level = Log.Level.Trace;
Log.repository.getLogger("Sync.AddonsRepository").level =
Log.Level.Trace;
reconciler.startListening();

Просмотреть файл

@ -43,9 +43,9 @@ function cleanup_and_advance() {
function run_test() {
initTestLogging("Trace");
Log4Moz.repository.getLogger("Sync.Engine.Addons").level = Log4Moz.Level.Trace;
Log4Moz.repository.getLogger("Sync.AddonsReconciler").level =
Log4Moz.Level.Trace;
Log.repository.getLogger("Sync.Engine.Addons").level = Log.Level.Trace;
Log.repository.getLogger("Sync.AddonsReconciler").level =
Log.Level.Trace;
cleanup_and_advance();
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше