Merge m-c to b2g-inbound. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-04-23 17:24:21 -04:00
Родитель b9f814e012 c39b31d3fd
Коммит c70caa5220
410 изменённых файлов: 9921 добавлений и 6594 удалений

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

@ -1608,6 +1608,11 @@ pref("devtools.fontinspector.enabled", true);
// version for each user.
pref("devtools.telemetry.tools.opened.version", "{}");
// Set imgur upload client ID
pref("devtools.gcli.imgurClientID", '0df414e888d7240');
// Imgur's upload URL
pref("devtools.gcli.imgurUploadURL", "https://api.imgur.com/3/image");
// Whether the character encoding menu is under the main Firefox button. This
// preference is a string so that localizers can alter it.
pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.properties");

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

@ -56,7 +56,7 @@ var StarUI = {
},
// nsIDOMEventListener
handleEvent: function SU_handleEvent(aEvent) {
handleEvent(aEvent) {
switch (aEvent.type) {
case "popuphidden":
if (aEvent.originalTarget == this.panel) {
@ -69,26 +69,32 @@ var StarUI = {
}
this._restoreCommandsState();
this._itemId = -1;
if (this._batching) {
PlacesUtils.transactionManager.endBatch(false);
this._batching = false;
}
if (this._batching)
this.endBatch();
switch (this._actionOnHide) {
case "cancel": {
PlacesUtils.transactionManager.undoTransaction();
if (!PlacesUIUtils.useAsyncTransactions) {
PlacesUtils.transactionManager.undoTransaction();
break;
}
PlacesTransactions.undo().catch(Cu.reportError);
break;
}
case "remove": {
// Remove all bookmarks for the bookmark's url, this also removes
// the tags for the url.
PlacesUtils.transactionManager.beginBatch(null);
let itemIds = PlacesUtils.getBookmarksForURI(this._uriForRemoval);
for (let i = 0; i < itemIds.length; i++) {
let txn = new PlacesRemoveItemTransaction(itemIds[i]);
PlacesUtils.transactionManager.doTransaction(txn);
if (!PlacesUIUtils.useAsyncTransactions) {
let itemIds = PlacesUtils.getBookmarksForURI(this._uriForRemoval);
for (let itemId of itemIds) {
let txn = new PlacesRemoveItemTransaction(itemId);
PlacesUtils.transactionManager.doTransaction(txn);
}
break;
}
PlacesUtils.transactionManager.endBatch(false);
PlacesTransactions.RemoveBookmarksForUrls(this._uriForRemoval)
.transact().catch(Cu.reportError);
break;
}
}
@ -122,15 +128,30 @@ var StarUI = {
_overlayLoaded: false,
_overlayLoading: false,
showEditBookmarkPopup:
function SU_showEditBookmarkPopup(aItemId, aAnchorElement, aPosition) {
showEditBookmarkPopup: Task.async(function* (aNode, aAnchorElement, aPosition) {
// TODO: Deprecate this once async transactions are enabled and the legacy
// transactions code is gone (bug 1131491) - we don't want addons to to use
// the completeNodeLikeObjectForItemId, so it's better if they keep passing
// the item-id for now).
if (typeof(aNode) == "number") {
let itemId = aNode;
if (PlacesUIUtils.useAsyncTransactions) {
let guid = yield PlacesUtils.promiseItemGuid(itemId);
aNode = yield PlacesUIUtils.promiseNodeLike(guid);
}
else {
aNode = { itemId };
yield PlacesUIUtils.completeNodeLikeObjectForItemId(aNode);
}
}
// Performance: load the overlay the first time the panel is opened
// (see bug 392443).
if (this._overlayLoading)
return;
if (this._overlayLoaded) {
this._doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition);
this._doShowEditBookmarkPanel(aNode, aAnchorElement, aPosition);
return;
}
@ -147,13 +168,12 @@ var StarUI = {
this._overlayLoading = false;
this._overlayLoaded = true;
this._doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition);
this._doShowEditBookmarkPanel(aNode, aAnchorElement, aPosition);
}).bind(this)
);
},
}),
_doShowEditBookmarkPanel:
function SU__doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition) {
_doShowEditBookmarkPanel: Task.async(function* (aNode, aAnchorElement, aPosition) {
if (this.panel.state != "closed")
return;
@ -179,15 +199,15 @@ var StarUI = {
// The label of the remove button differs if the URI is bookmarked
// multiple times.
var bookmarks = PlacesUtils.getBookmarksForURI(gBrowser.currentURI);
var forms = gNavigatorBundle.getString("editBookmark.removeBookmarks.label");
var label = PluralForm.get(bookmarks.length, forms).replace("#1", bookmarks.length);
let bookmarks = PlacesUtils.getBookmarksForURI(gBrowser.currentURI);
let forms = gNavigatorBundle.getString("editBookmark.removeBookmarks.label");
let label = PluralForm.get(bookmarks.length, forms).replace("#1", bookmarks.length);
this._element("editBookmarkPanelRemoveButton").label = label;
// unset the unstarred state, if set
this._element("editBookmarkPanelStarIcon").removeAttribute("unstarred");
this._itemId = aItemId !== undefined ? aItemId : this._itemId;
this._itemId = aNode.itemId;
this.beginBatch();
if (aAnchorElement) {
@ -207,10 +227,10 @@ var StarUI = {
}
this.panel.openPopup(aAnchorElement, aPosition);
gEditItemOverlay.initPanel(this._itemId,
{ hiddenRows: ["description", "location",
gEditItemOverlay.initPanel({ node: aNode
, hiddenRows: ["description", "location",
"loadInSidebar", "keyword"] });
},
}),
panelShown:
function SU_panelShown(aEvent) {
@ -247,13 +267,46 @@ var StarUI = {
this.panel.hidePopup();
},
beginBatch: function SU_beginBatch() {
if (!this._batching) {
PlacesUtils.transactionManager.beginBatch(null);
this._batching = true;
// Matching the way it is used in the Library, editBookmarkOverlay implements
// an instant-apply UI, having no batched-Undo/Redo support.
// However, in this context (the Star UI) we have a Cancel button whose
// expected behavior is to undo all the operations done in the panel.
// Sometime in the future this needs to be reimplemented using a
// non-instant apply code path, but for the time being, we patch-around
// editBookmarkOverlay so that all of the actions done in the panel
// are treated by PlacesTransactions as a single batch. To do so,
// we start a PlacesTransactions batch when the star UI panel is shown, and
// we keep the batch ongoing until the panel is hidden.
_batchBlockingDeferred: null,
beginBatch() {
if (this._batching)
return;
if (PlacesUIUtils.useAsyncTransactions) {
this._batchBlockingDeferred = PromiseUtils.defer();
PlacesTransactions.batch(function* () {
yield this._batchBlockingDeferred.promise;
}.bind(this));
}
else {
PlacesUtils.transactionManager.beginBatch(null);
}
this._batching = true;
},
endBatch() {
if (!this._batching)
return;
if (PlacesUIUtils.useAsyncTransactions) {
this._batchBlockingDeferred.resolve();
this._batchBlockingDeferred = null;
}
else {
PlacesUtils.transactionManager.endBatch(false);
}
this._batching = false;
}
}
};
////////////////////////////////////////////////////////////////////////////////
//// PlacesCommandHook
@ -269,8 +322,11 @@ var PlacesCommandHook = {
* aBrowser isn't bookmarked yet, defaults to the unfiled root.
* @param [optional] aShowEditUI
* whether or not to show the edit-bookmark UI for the bookmark item
*/
bookmarkPage: function PCH_bookmarkPage(aBrowser, aParent, aShowEditUI) {
*/
bookmarkPage: Task.async(function* (aBrowser, aParent, aShowEditUI) {
if (PlacesUIUtils.useAsyncTransactions)
return (yield this._bookmarkPagePT(aBrowser, aParent, aShowEditUI));
var uri = aBrowser.currentURI;
var itemId = PlacesUtils.getMostRecentBookmarkForURI(uri);
if (itemId == -1) {
@ -296,7 +352,7 @@ var PlacesCommandHook = {
StarUI.beginBatch();
}
var parent = aParent != undefined ?
var parent = aParent !== undefined ?
aParent : PlacesUtils.unfiledBookmarksFolderId;
var descAnno = { name: PlacesUIUtils.DESCRIPTION_ANNO, value: description };
var txn = new PlacesCreateBookmarkTransaction(uri, parent,
@ -304,7 +360,7 @@ var PlacesCommandHook = {
title, null, [descAnno]);
PlacesUtils.transactionManager.doTransaction(txn);
itemId = txn.item.id;
// Set the character-set
// Set the character-set.
if (charset && !PrivateBrowsingUtils.isBrowserPrivate(aBrowser))
PlacesUtils.setCharsetForURI(uri, charset);
}
@ -334,7 +390,82 @@ var PlacesCommandHook = {
} else {
StarUI.showEditBookmarkPopup(itemId, aBrowser, "overlap");
}
},
}),
// TODO: Replace bookmarkPage code with this function once legacy
// transactions are removed.
_bookmarkPagePT: Task.async(function* (aBrowser, aParentId, aShowEditUI) {
let url = new URL(aBrowser.currentURI.spec);
let info = yield PlacesUtils.bookmarks.fetch({ url });
if (!info) {
let parentGuid = aParentId !== undefined ?
yield PlacesUtils.promiseItemGuid(aParentId) :
PlacesUtils.bookmarks.unfiledGuid;
info = { url, parentGuid };
// Bug 1148838 - Make this code work for full page plugins.
let description = null;
let charset = null;
try {
let isErrorPage = /^about:(neterror|certerror|blocked)/
.test(aBrowser.contentDocumentAsCPOW.documentURI);
info.title = isErrorPage ?
(yield PlacesUtils.promisePlaceInfo(aBrowser.currentURI)).title :
aBrowser.contentTitle;
info.title = info.title || url.href;
description = PlacesUIUtils.getDescriptionFromDocument(aBrowser.contentDocumentAsCPOW);
charset = aBrowser.characterSet;
}
catch (e) {
Components.utils.reportError(e);
}
if (aShowEditUI) {
// If we bookmark the page here (i.e. page was not "starred" already)
// but open right into the "edit" state, start batching here, so
// "Cancel" in that state removes the bookmark.
StarUI.beginBatch();
}
if (description) {
info.annotations = [{ name: PlacesUIUtils.DESCRIPTION_ANNO
, value: description }];
}
info.guid = yield PlacesTransactions.NewBookmark(info).transact();
// Set the character-set
if (charset && !PrivateBrowsingUtils.isBrowserPrivate(aBrowser))
PlacesUtils.setCharsetForURI(makeURI(url.href), charset);
}
// Revert the contents of the location bar
if (gURLBar)
gURLBar.handleRevert();
// If it was not requested to open directly in "edit" mode, we are done.
if (!aShowEditUI)
return;
let node = yield PlacesUIUtils.promiseNodeLikeFromFetchInfo(info);
// Try to dock the panel to:
// 1. the bookmarks menu button
// 2. the page-proxy-favicon
// 3. the content area
if (BookmarkingUI.anchor) {
StarUI.showEditBookmarkPopup(node, BookmarkingUI.anchor,
"bottomcenter topright");
return;
}
let pageProxyFavicon = document.getElementById("page-proxy-favicon");
if (isElementVisible(pageProxyFavicon)) {
StarUI.showEditBookmarkPopup(node, pageProxyFavicon,
"bottomcenter topright");
} else {
StarUI.showEditBookmarkPopup(node, aBrowser, "overlap");
}
}),
/**
* Adds a bookmark to the page loaded in the current tab.
@ -353,10 +484,27 @@ var PlacesCommandHook = {
* @param aTitle
* The link text
*/
bookmarkLink: function PCH_bookmarkLink(aParent, aURL, aTitle) {
var linkURI = makeURI(aURL);
var itemId = PlacesUtils.getMostRecentBookmarkForURI(linkURI);
if (itemId == -1) {
bookmarkLink: Task.async(function* (aParentId, aURL, aTitle) {
let node = null;
if (PlacesUIUtils.useAsyncTransactions) {
node = yield PlacesUIUtils.fetchNodeLike({ url: aURL });
}
else {
let linkURI = makeURI(aURL);
let itemId = PlacesUtils.getMostRecentBookmarkForURI(linkURI);
if (itemId != -1) {
node = { itemId, uri: aURL };
PlacesUIUtils.completeNodeLikeObjectForItemId(node);
}
}
if (node) {
PlacesUIUtils.showBookmarkDialog({ action: "edit"
, type: "bookmark"
, node
}, window);
}
else {
PlacesUIUtils.showBookmarkDialog({ action: "add"
, type: "bookmark"
, uri: linkURI
@ -367,13 +515,7 @@ var PlacesCommandHook = {
, "keyword" ]
}, window);
}
else {
PlacesUIUtils.showBookmarkDialog({ action: "edit"
, type: "bookmark"
, itemId: itemId
}, window);
}
},
}),
/**
* List of nsIURI objects characterizing the tabs currently open in the

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

@ -24,6 +24,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
"resource://gre/modules/BrowserUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
"resource://gre/modules/PromiseUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
"resource://gre/modules/CharsetMenu.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
@ -49,6 +51,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
"resource://gre/modules/LightweightThemeManager.jsm");
const nsIWebNavigation = Ci.nsIWebNavigation;
var gLastBrowserCharset = null;
@ -950,6 +953,7 @@ var gBrowserInit = {
mm.loadFrameScript("chrome://browser/content/tab-content.js", true);
mm.loadFrameScript("chrome://browser/content/content.js", true);
mm.loadFrameScript("chrome://browser/content/content-UITour.js", true);
mm.loadFrameScript("chrome://global/content/manifestMessages.js", true);
window.messageManager.addMessageListener("Browser:LoadURI", RedirectLoad);
@ -2391,6 +2395,8 @@ function URLBarSetURI(aURI) {
function losslessDecodeURI(aURI) {
var value = aURI.spec;
if (aURI.schemeIs("moz-action"))
throw new Error("losslessDecodeURI should never get a moz-action URI");
// Try to decode as UTF-8 if there's no encoding sequence that we would break.
if (!/%25(?:3B|2F|3F|3A|40|26|3D|2B|24|2C|23)/i.test(value))
try {

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

@ -466,6 +466,7 @@ skip-if = e10s # Bug 1094240 - has findbar-related failures
[browser_registerProtocolHandler_notification.js]
skip-if = e10s # Bug 940206 - nsIWebContentHandlerRegistrar::registerProtocolHandler doesn't work in e10s
[browser_no_mcb_on_http_site.js]
[browser_bug1104165-switchtab-decodeuri.js]
[browser_bug1003461-switchtab-override.js]
[browser_bug1024133-switchtab-override-keynav.js]
[browser_bug1025195_switchToTabHavingURI_aOpenParams.js]

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

@ -0,0 +1,29 @@
add_task(function* test_switchtab_decodeuri() {
info("Opening first tab");
let tab = gBrowser.addTab("http://example.org/browser/browser/base/content/test/general/dummy_page.html#test%7C1");
yield promiseTabLoadEvent(tab);
info("Opening and selecting second tab");
let newTab = gBrowser.selectedTab = gBrowser.addTab();
info("Wait for autocomplete")
yield promiseAutocompleteResultPopup("dummy_page");
info("Select autocomplete popup entry");
EventUtils.synthesizeKey("VK_DOWN" , {});
ok(gURLBar.value.startsWith("moz-action:switchtab"), "switch to tab entry found");
info("switch-to-tab");
yield new Promise((resolve, reject) => {
// In case of success it should switch tab.
gBrowser.tabContainer.addEventListener("TabSelect", function select() {
gBrowser.tabContainer.removeEventListener("TabSelect", select, false);
is(gBrowser.selectedTab, tab, "Should have switched to the right tab");
resolve();
}, false);
EventUtils.synthesizeKey("VK_RETURN" , { });
});
gBrowser.removeCurrentTab();
yield PlacesTestUtils.clearHistory();
});

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

@ -305,7 +305,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
if (this.hasAttribute("actiontype")) {
this.handleRevert();
let prevTab = gBrowser.selectedTab;
if (switchToTabHavingURI(url) &&
if (switchToTabHavingURI(action.params.originalUrl || url) &&
isTabEmpty(prevTab))
gBrowser.removeTab(prevTab);
return;
@ -716,9 +716,24 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
]]></getter>
<setter>
<![CDATA[
let uri;
try {
val = losslessDecodeURI(makeURI(val));
} catch (ex) { }
uri = makeURI(val);
} catch (ex) {}
if (uri) {
let action = this._parseActionUrl(val);
if (action) {
if (action.params.url) {
// Store the original URL in the action URL.
action.params.originalUrl = action.params.url;
action.params.url = losslessDecodeURI(makeURI(action.params.url));
val = "moz-action:" + action.type + "," + JSON.stringify(action.params);
}
} else {
val = losslessDecodeURI(uri);
}
}
// Trim popup selected values, but never trim results coming from
// autofill.
@ -758,6 +773,12 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
try {
action.params = JSON.parse(params);
if (action.params.input) {
action.params.input = decodeURIComponent(action.params.input);
}
if (action.params.searchQuery) {
action.params.searchQuery = decodeURIComponent(action.params.searchQuery);
}
} catch (e) {
// If this failed, we assume that params is not a JSON object, and
// is instead just a flat string. This will happen when

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

@ -1211,6 +1211,155 @@ this.PlacesUIUtils = {
let cloudSyncEnabled = CloudSync && CloudSync.ready && CloudSync().tabsReady && CloudSync().tabs.hasRemoteTabs();
return weaveEnabled || cloudSyncEnabled;
},
/**
* WARNING TO ADDON AUTHORS: DO NOT USE THIS METHOD. IT'S LIKELY TO BE REMOVED IN A
* FUTURE RELEASE.
*
* Checks if a place: href represents a folder shortcut.
*
* @param queryString
* the query string to check (a place: href)
* @return whether or not queryString represents a folder shortcut.
* @throws if queryString is malformed.
*/
isFolderShortcutQueryString(queryString) {
// Based on GetSimpleBookmarksQueryFolder in nsNavHistory.cpp.
let queriesParam = { }, optionsParam = { };
PlacesUtils.history.queryStringToQueries(queryString,
queriesParam,
{ },
optionsParam);
let queries = queries.value;
if (queries.length == 0)
throw new Error(`Invalid place: uri: ${queryString}`);
return queries.length == 1 &&
queries[0].folderCount == 1 &&
!queries[0].hasBeginTime &&
!queries[0].hasEndTime &&
!queries[0].hasDomain &&
!queries[0].hasURI &&
!queries[0].hasSearchTerms &&
!queries[0].tags.length == 0 &&
optionsParam.value.maxResults == 0;
},
/**
* WARNING TO ADDON AUTHORS: DO NOT USE THIS METHOD. IT"S LIKELY TO BE REMOVED IN A
* FUTURE RELEASE.
*
* Helpers for consumers of editBookmarkOverlay which don't have a node as their input.
* Given a partial node-like object, having at least the itemId property set, this
* method completes the rest of the properties necessary for initialising the edit
* overlay with it.
*
* @param aNodeLike
* an object having at least the itemId nsINavHistoryResultNode property set,
* along with any other properties available.
*/
completeNodeLikeObjectForItemId(aNodeLike) {
if (this.useAsyncTransactions) {
// When async-transactions are enabled, node-likes must have
// bookmarkGuid set, and we cannot set it synchronously.
throw new Error("completeNodeLikeObjectForItemId cannot be used when " +
"async transactions are enabled");
}
if (!("itemId" in aNodeLike))
throw new Error("itemId missing in aNodeLike");
let itemId = aNodeLike.itemId;
let defGetter = XPCOMUtils.defineLazyGetter.bind(XPCOMUtils, aNodeLike);
if (!("title" in aNodeLike))
defGetter("title", () => PlacesUtils.bookmarks.getItemTitle(itemId));
if (!("uri" in aNodeLike)) {
defGetter("uri", () => {
let uri = null;
try {
uri = PlacesUtils.bookmarks.getBookmarkURI(itemId);
}
catch(ex) { }
return uri ? uri.spec : "";
});
}
if (!("type" in aNodeLike)) {
defGetter("type", () => {
if (aNodeLike.uri.length > 0) {
if (/^place:/.test(aNodeLike.uri)) {
if (this.isFolderShortcutQueryString(aNodeLike.uri))
return Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT;
return Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY;
}
return Ci.nsINavHistoryResultNode.RESULT_TYPE_URI;
}
let itemType = PlacesUtils.bookmarks.getItemType(itemId);
if (itemType == PlacesUtils.bookmarks.TYPE_FOLDER)
return Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER;
throw new Error("Unexpected item type");
});
}
},
/**
* Helpers for consumers of editBookmarkOverlay which don't have a node as their input.
*
* Given a bookmark object for either a url bookmark or a folder, returned by
* Bookmarks.fetch (see Bookmark.jsm), this creates a node-like object suitable for
* initialising the edit overlay with it.
*
* @param aFetchInfo
* a bookmark object returned by Bookmarks.fetch.
* @return a node-like object suitable for initialising editBookmarkOverlay.
* @throws if aFetchInfo is representing a separator.
*/
promiseNodeLikeFromFetchInfo: Task.async(function* (aFetchInfo) {
if (aFetchInfo.itemType == PlacesUtils.bookmarks.TYPE_SEPARATOR)
throw new Error("promiseNodeLike doesn't support separators");
return Object.freeze({
itemId: yield PlacesUtils.promiseItemId(aFetchInfo.guid),
bookmarkGuid: aFetchInfo.guid,
title: aFetchInfo.title,
uri: aFetchInfo.url !== undefined ? aFetchInfo.url.href : "",
get type() {
if (aFetchInfo.itemType == PlacesUtils.bookmarks.TYPE_FOLDER)
return Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER;
if (this.uri.length == 0)
throw new Error("Unexpected item type");
if (/^place:/.test(this.uri)) {
if (this.isFolderShortcutQueryString(this.uri))
return Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT;
return Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY;
}
return Ci.nsINavHistoryResultNode.RESULT_TYPE_URI;
}
});
}),
/**
* Shortcut for calling promiseNodeLikeFromFetchInfo on the result of
* Bookmarks.fetch for the given guid/info object.
*
* @see promiseNodeLikeFromFetchInfo above and Bookmarks.fetch in Bookmarks.jsm.
*/
fetchNodeLike: Task.async(function* (aGuidOrInfo) {
let info = yield PlacesUtils.bookmarks.fetch(aGuidOrInfo);
if (!info)
return null;
return (yield this.promiseNodeLikeFromFetchInfo(info));
})
};

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

@ -37,9 +37,11 @@
* - "edit" - for editing a bookmark item or a folder.
* @ type (String). Possible values:
* - "bookmark"
* @ itemId (Integer) - the id of the bookmark item.
* @ node (an nsINavHistoryResultNode object) - a node representing
* the bookmark.
* - "folder" (also applies to livemarks)
* @ itemId (Integer) - the id of the folder.
* @ node (an nsINavHistoryResultNode object) - a node representing
* the folder.
* @ hiddenRows (Strings array) - optional, list of rows to be hidden
* regardless of the item edited or added by the dialog.
* Possible values:
@ -49,10 +51,7 @@
* - "keyword"
* - "tags"
* - "loadInSidebar"
* - "feedLocation"
* - "siteLocation"
* - "folderPicker" - hides both the tree and the menu.
* @ readOnly (Boolean) - optional, states if the panel should be read-only
*
* window.arguments[0].performed is set to true if any transaction has
* been performed by the dialog.
@ -61,6 +60,10 @@
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
"resource://gre/modules/PromiseUtils.jsm");
const BOOKMARK_ITEM = 0;
const BOOKMARK_FOLDER = 1;
@ -97,7 +100,6 @@ var BookmarkPropertiesPanel = {
_defaultInsertionPoint: null,
_hiddenRows: [],
_batching: false,
_readOnly: false,
/**
* This method returns the correct label for the dialog's "accept"
@ -146,8 +148,8 @@ var BookmarkPropertiesPanel = {
/**
* Determines the initial data for the item edited or added by this dialog
*/
_determineItemInfo: function BPP__determineItemInfo() {
var dialogInfo = window.arguments[0];
_determineItemInfo() {
let dialogInfo = window.arguments[0];
this._action = dialogInfo.action == "add" ? ACTION_ADD : ACTION_EDIT;
this._hiddenRows = dialogInfo.hiddenRows ? dialogInfo.hiddenRows : [];
if (this._action == ACTION_ADD) {
@ -159,11 +161,12 @@ var BookmarkPropertiesPanel = {
if ("defaultInsertionPoint" in dialogInfo) {
this._defaultInsertionPoint = dialogInfo.defaultInsertionPoint;
}
else
else {
this._defaultInsertionPoint =
new InsertionPoint(PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.bookmarks.DEFAULT_INDEX,
Ci.nsITreeView.DROP_ON);
}
switch (dialogInfo.type) {
case "bookmark":
@ -230,52 +233,15 @@ var BookmarkPropertiesPanel = {
this._description = dialogInfo.description;
}
else { // edit
NS_ASSERT("itemId" in dialogInfo);
this._itemId = dialogInfo.itemId;
this._title = PlacesUtils.bookmarks.getItemTitle(this._itemId);
this._readOnly = !!dialogInfo.readOnly;
this._node = dialogInfo.node;
switch (dialogInfo.type) {
case "bookmark":
this._itemType = BOOKMARK_ITEM;
this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._itemId);
// keyword
this._keyword = PlacesUtils.bookmarks
.getKeywordForBookmark(this._itemId);
// Load In Sidebar
this._loadInSidebar = PlacesUtils.annotations
.itemHasAnnotation(this._itemId,
PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO);
break;
case "folder":
this._itemType = BOOKMARK_FOLDER;
PlacesUtils.livemarks.getLivemark({ id: this._itemId })
.then(aLivemark => {
this._itemType = LIVEMARK_CONTAINER;
this._feedURI = aLivemark.feedURI;
this._siteURI = aLivemark.siteURI;
this._fillEditProperties();
let acceptButton = document.documentElement.getButton("accept");
acceptButton.disabled = !this._inputIsValid();
let newHeight = window.outerHeight +
this._element("descriptionField").boxObject.height;
window.resizeTo(window.outerWidth, newHeight);
}, () => undefined);
break;
}
// Description
if (PlacesUtils.annotations
.itemHasAnnotation(this._itemId, PlacesUIUtils.DESCRIPTION_ANNO)) {
this._description = PlacesUtils.annotations
.getItemAnnotation(this._itemId,
PlacesUIUtils.DESCRIPTION_ANNO);
}
}
},
@ -301,7 +267,7 @@ var BookmarkPropertiesPanel = {
* This method should be called by the onload of the Bookmark Properties
* dialog to initialize the state of the panel.
*/
onDialogLoad: function BPP_onDialogLoad() {
onDialogLoad: Task.async(function* () {
this._determineItemInfo();
document.title = this._getDialogTitle();
@ -312,11 +278,23 @@ var BookmarkPropertiesPanel = {
switch (this._action) {
case ACTION_EDIT:
this._fillEditProperties();
acceptButton.disabled = this._readOnly;
gEditItemOverlay.initPanel({ node: this._node
, hiddenRows: this._hiddenRows });
acceptButton.disabled = gEditItemOverlay.readOnly;
break;
case ACTION_ADD:
this._fillAddProperties();
this._node = yield this._promiseNewItem();
// Edit the new item
gEditItemOverlay.initPanel({ node: this._node
, hiddenRows: this._hiddenRows });
// Empty location field if the uri is about:blank, this way inserting a new
// url will be easier for the user, Accept button will be automatically
// disabled by the input listener until the user fills the field.
let locationField = this._element("locationField");
if (locationField.value == "about:blank")
locationField.value = "";
// if this is an uri related dialog disable accept button until
// the user fills an uri value.
if (this._itemType == BOOKMARK_ITEM)
@ -324,6 +302,11 @@ var BookmarkPropertiesPanel = {
break;
}
// Adjust the dialog size to the changes done by initPanel. This is necessary because
// initPanel, which shows and hides elements, may run after some async work was done
// here - i.e. after the DOM load event was processed.
window.sizeToContent();
// When collapsible elements change their collapsed attribute we must
// resize the dialog.
// sizeToContent is not usable due to bug 90276, so we'll use resizeTo
@ -338,7 +321,7 @@ var BookmarkPropertiesPanel = {
.addEventListener("DOMAttrModified", this, false);
}
if (!this._readOnly) {
if (!gEditItemOverlay.readOnly) {
// Listen on uri fields to enable accept button if input is valid
if (this._itemType == BOOKMARK_ITEM) {
this._element("locationField")
@ -348,16 +331,10 @@ var BookmarkPropertiesPanel = {
.addEventListener("input", this, false);
}
}
else if (this._itemType == LIVEMARK_CONTAINER) {
this._element("feedLocationField")
.addEventListener("input", this, false);
this._element("siteLocationField")
.addEventListener("input", this, false);
}
}
window.sizeToContent();
},
}),
// nsIDOMEventListener
_elementsHeight: [],
@ -366,8 +343,6 @@ var BookmarkPropertiesPanel = {
switch (aEvent.type) {
case "input":
if (target.id == "editBMPanel_locationField" ||
target.id == "editBMPanel_feedLocationField" ||
target.id == "editBMPanel_siteLocationField" ||
target.id == "editBMPanel_keywordField") {
// Check uri fields to enable accept button if input is valid
document.documentElement
@ -397,41 +372,39 @@ var BookmarkPropertiesPanel = {
}
},
_beginBatch: function BPP__beginBatch() {
// Hack for implementing batched-Undo around the editBookmarkOverlay
// instant-apply code. For all the details see the comment above beginBatch
// in browser-places.js
_batchBlockingDeferred: null,
_beginBatch() {
if (this._batching)
return;
PlacesUtils.transactionManager.beginBatch(null);
if (PlacesUIUtils.useAsyncTransactions) {
this._batchBlockingDeferred = PromiseUtils.defer();
PlacesTransactions.batch(function* () {
yield this._batchBlockingDeferred.promise;
}.bind(this));
}
else {
PlacesUtils.transactionManager.beginBatch(null);
}
this._batching = true;
},
_endBatch: function BPP__endBatch() {
_endBatch() {
if (!this._batching)
return;
PlacesUtils.transactionManager.endBatch(false);
if (PlacesUIUtils.useAsyncTransactions) {
this._batchBlockingDeferred.resolve();
this._batchBlockingDeferred = null;
}
else {
PlacesUtils.transactionManager.endBatch(false);
}
this._batching = false;
},
_fillEditProperties: function BPP__fillEditProperties() {
gEditItemOverlay.initPanel(this._itemId,
{ hiddenRows: this._hiddenRows,
forceReadOnly: this._readOnly });
},
_fillAddProperties: function BPP__fillAddProperties() {
this._createNewItem();
// Edit the new item
gEditItemOverlay.initPanel(this._itemId,
{ hiddenRows: this._hiddenRows });
// Empty location field if the uri is about:blank, this way inserting a new
// url will be easier for the user, Accept button will be automatically
// disabled by the input listener until the user fills the field.
var locationField = this._element("locationField");
if (locationField.value == "about:blank")
locationField.value = "";
},
// nsISupports
QueryInterface: function BPP_QueryInterface(aIID) {
if (aIID.equals(Ci.nsIDOMEventListener) ||
@ -445,7 +418,7 @@ var BookmarkPropertiesPanel = {
return document.getElementById("editBMPanel_" + aID);
},
onDialogUnload: function BPP_onDialogUnload() {
onDialogUnload() {
// gEditItemOverlay does not exist anymore here, so don't rely on it.
// Calling removeEventListener with arguments which do not identify any
// currently registered EventListener on the EventTarget has no effect.
@ -455,13 +428,9 @@ var BookmarkPropertiesPanel = {
.removeEventListener("DOMAttrModified", this, false);
this._element("locationField")
.removeEventListener("input", this, false);
this._element("feedLocationField")
.removeEventListener("input", this, false);
this._element("siteLocationField")
.removeEventListener("input", this, false);
},
onDialogAccept: function BPP_onDialogAccept() {
onDialogAccept() {
// We must blur current focused element to save its changes correctly
document.commandDispatcher.focusedElement.blur();
// The order here is important! We have to uninit the panel first, otherwise
@ -471,13 +440,16 @@ var BookmarkPropertiesPanel = {
window.arguments[0].performed = true;
},
onDialogCancel: function BPP_onDialogCancel() {
onDialogCancel() {
// The order here is important! We have to uninit the panel first, otherwise
// changes done as part of Undo may change the panel contents and by
// that force it to commit more transactions.
gEditItemOverlay.uninitPanel(true);
this._endBatch();
PlacesUtils.transactionManager.undoTransaction();
if (PlacesUIUtils.useAsyncTransactions)
PlacesTransactions.undo().catch(Components.utils.reportError);
else
PlacesUtils.transactionManager.undoTransaction();
window.arguments[0].performed = false;
},
@ -583,15 +555,14 @@ var BookmarkPropertiesPanel = {
*/
_getTransactionsForURIList: function BPP__getTransactionsForURIList() {
var transactions = [];
for (var i = 0; i < this._URIs.length; ++i) {
var uri = this._URIs[i];
var title = this._getURITitleFromHistory(uri);
var createTxn = new PlacesCreateBookmarkTransaction(uri, -1,
for (let uri of this._URIs) {
let title = this._getURITitleFromHistory(uri);
let createTxn = new PlacesCreateBookmarkTransaction(uri, -1,
PlacesUtils.bookmarks.DEFAULT_INDEX,
title);
transactions.push(createTxn);
}
return transactions;
return transactions;
},
/**
@ -624,9 +595,6 @@ var BookmarkPropertiesPanel = {
aContainer, aIndex);
},
/**
* Dialog-accept code-path for creating a new item (any type)
*/
_createNewItem: function BPP__getCreateItemTransaction() {
var [container, index] = this._getInsertionPointDetails();
var txn;
@ -637,12 +605,93 @@ var BookmarkPropertiesPanel = {
break;
case LIVEMARK_CONTAINER:
txn = this._getCreateNewLivemarkTransaction(container, index);
break;
break;
default: // BOOKMARK_ITEM
txn = this._getCreateNewBookmarkTransaction(container, index);
}
PlacesUtils.transactionManager.doTransaction(txn);
this._itemId = PlacesUtils.bookmarks.getIdForItemAt(container, index);
}
return Object.freeze({
itemId: this._itemId,
get bookmarkGuid() {
throw new Error("Node-like bookmarkGuid getter called even though " +
"async transactions are disabled");
},
title: this._title,
uri: this._uri ? this._uri.spec : "",
type: this._itemType == BOOKMARK_ITEM ?
Ci.nsINavHistoryResultNode.RESULT_TYPE_URI :
Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER
});
},
_promiseNewItem: Task.async(function* () {
if (!PlacesUIUtils.useAsyncTransactions)
return this._createNewItem();
let txnFunc =
{ [BOOKMARK_FOLDER]: PlacesTransactions.NewFolder,
[LIVEMARK_CONTAINER]: PlacesTransactions.NewLivemark,
[BOOKMARK_ITEM]: PlacesTransactions.NewBookmark
}[this._itemType];
let [containerId, index] = this._getInsertionPointDetails();
let parentGuid = yield PlacesUtils.promiseItemGuid(containerId);
let annotations = [];
if (this._description) {
annotations.push({ name: PlacesUIUtils.DESCRIPTION_ANNO
, value: this._description });
}
if (this._loadInSidebar) {
annotations.push({ name: PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO
, value: true });
}
let itemGuid;
let info = { parentGuid, index, title: this._title, annotations };
if (this._itemType == BOOKMARK_ITEM) {
info.url = this._uri;
if (this._keyword)
info.keyword = this._keyword;
if (this._postData)
info.postData = this._postData;
if (this._charSet && !PrivateBrowsingUtils.isWindowPrivate(window))
PlacesUtils.setCharsetForURI(this._uri, this._charSet);
itemGuid = yield PlacesTransactions.NewBookmark(info).transact();
}
else if (this._itemType == LIVEMARK_CONTAINER) {
info.feedUrl = this._feedURI;
if (this._siteURI)
info.siteUrl = this._siteURI;
itemGuid = yield PlacesTransactions.NewLivemark(info).transact();
}
else if (this._itemType == BOOKMARK_FOLDER) {
itemGuid = yield PlacesTransactions.NewFolder(info).transact();
for (let uri of this._URIs) {
let placeInfo = yield PlacesUtils.promisePlaceInfo(uri);
let title = placeInfo ? placeInfo.title : "";
yield PlacesTransactions.transact({ parentGuid: itemGuid, uri, title });
}
}
else {
throw new Error(`unexpected value for _itemType: ${this._itemType}`);
}
this._itemGuid = itemGuid;
this._itemId = yield PlacesUtils.promiseItemId(itemGuid);
return Object.freeze({
itemId: this._itemId,
bookmarkGuid: this._itemGuid,
title: this._title,
uri: this._uri ? this._uri.spec : "",
type: this._itemType == BOOKMARK_ITEM ?
Ci.nsINavHistoryResultNode.RESULT_TYPE_URI :
Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER
});
})
};

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

@ -129,15 +129,6 @@ PlacesController.prototype = {
},
isCommandEnabled: function PC_isCommandEnabled(aCommand) {
if (PlacesUIUtils.useAsyncTransactions) {
switch (aCommand) {
case "placesCmd_new:folder":
case "placesCmd_new:bookmark":
case "placesCmd_createBookmark":
return false;
}
}
switch (aCommand) {
case "cmd_undo":
if (!PlacesUIUtils.useAsyncTransactions)
@ -279,7 +270,7 @@ PlacesController.prototype = {
this.newItem("bookmark");
break;
case "placesCmd_new:separator":
this.newSeparator().then(null, Components.utils.reportError);
this.newSeparator().catch(Cu.reportError);
break;
case "placesCmd_show:info":
this.showBookmarkPropertiesForSelection();
@ -666,27 +657,13 @@ PlacesController.prototype = {
/**
* Opens the bookmark properties for the selected URI Node.
*/
showBookmarkPropertiesForSelection:
function PC_showBookmarkPropertiesForSelection() {
var node = this._view.selectedNode;
showBookmarkPropertiesForSelection() {
let node = this._view.selectedNode;
if (!node)
return;
var itemType = PlacesUtils.nodeIsFolder(node) ||
PlacesUtils.nodeIsTagQuery(node) ? "folder" : "bookmark";
var concreteId = PlacesUtils.getConcreteItemId(node);
var isRootItem = PlacesUtils.isRootItem(concreteId);
var itemId = node.itemId;
if (isRootItem || PlacesUtils.nodeIsTagQuery(node)) {
// If this is a root or the Tags query we use the concrete itemId to catch
// the correct title for the node.
itemId = concreteId;
}
PlacesUIUtils.showBookmarkDialog({ action: "edit"
, type: itemType
, itemId: itemId
, readOnly: isRootItem
, node
, hiddenRows: [ "folderPicker" ]
}, window.top);
},

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -29,7 +29,8 @@
class="editBMPanel_rowLabel"
accesskey="&editBookmarkOverlay.name.accesskey;"
control="editBMPanel_namePicker"/>
<textbox id="editBMPanel_namePicker"/>
<textbox id="editBMPanel_namePicker"
onchange="gEditItemOverlay.onNamePickerChange();"/>
</row>
<row align="center" id="editBMPanel_locationRow">
@ -38,25 +39,8 @@
accesskey="&editBookmarkOverlay.location.accesskey;"
control="editBMPanel_locationField"/>
<textbox id="editBMPanel_locationField"
class="uri-element"/>
</row>
<row align="center" id="editBMPanel_feedLocationRow">
<label value="&editBookmarkOverlay.feedLocation.label;"
class="editBMPanel_rowLabel"
accesskey="&editBookmarkOverlay.feedLocation.accesskey;"
control="editBMPanel_feedLocationField"/>
<textbox id="editBMPanel_feedLocationField"
class="uri-element"/>
</row>
<row align="center" id="editBMPanel_siteLocationRow">
<label value="&editBookmarkOverlay.siteLocation.label;"
class="editBMPanel_rowLabel"
accesskey="&editBookmarkOverlay.siteLocation.accesskey;"
control="editBMPanel_siteLocationField"/>
<textbox id="editBMPanel_siteLocationField"
class="uri-element"/>
class="uri-element"
onchange="gEditItemOverlay.onLocationFieldChange();"/>
</row>
<row align="center" id="editBMPanel_folderRow">
@ -114,7 +98,7 @@
<button label="&editBookmarkOverlay.newFolderButton.label;"
id="editBMPanel_newFolderButton"
accesskey="&editBookmarkOverlay.newFolderButton.accesskey;"
oncommand="gEditItemOverlay.newFolder();"/>
oncommand="gEditItemOverlay.newFolder().catch(Components.utils.reportError);"/>
</hbox>
</vbox>
</row>
@ -133,7 +117,8 @@
completedefaultindex="true"
tabscrolling="true"
showcommentcolumn="true"
placeholder="&editBookmarkOverlay.tagsEmptyDesc.label;"/>
placeholder="&editBookmarkOverlay.tagsEmptyDesc.label;"
onchange="gEditItemOverlay.onTagsFieldChange();"/>
<button id="editBMPanel_tagsSelectorExpander"
class="expander-down"
tooltiptext="&editBookmarkOverlay.tagsExpanderDown.tooltip;"
@ -157,7 +142,8 @@
class="editBMPanel_rowLabel"
accesskey="&editBookmarkOverlay.keyword.accesskey;"
control="editBMPanel_keywordField"/>
<textbox id="editBMPanel_keywordField"/>
<textbox id="editBMPanel_keywordField"
onchange="gEditItemOverlay.onKeywordFieldChange();"/>
</row>
<row id="editBMPanel_descriptionRow">
@ -168,7 +154,8 @@
control="editBMPanel_descriptionField"/>
<textbox id="editBMPanel_descriptionField"
multiline="true"
rows="4"/>
rows="4"
onchange="gEditItemOverlay.onDescriptionFieldChange();"/>
</row>
</rows>
</grid>

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

@ -615,7 +615,8 @@ var PlacesOrganizer = {
// Make sure the infoBox UI is visible if we need to use it, we hide it
// below when we don't.
infoBox.hidden = false;
var aSelectedNode = aNodeList.length == 1 ? aNodeList[0] : null;
let selectedNode = aNodeList.length == 1 ? aNodeList[0] : null;
// If a textbox within a panel is focused, force-blur it so its contents
// are saved
if (gEditItemOverlay.itemId != -1) {
@ -627,12 +628,12 @@ var PlacesOrganizer = {
// don't update the panel if we are already editing this node unless we're
// in multi-edit mode
if (aSelectedNode) {
var concreteId = PlacesUtils.getConcreteItemId(aSelectedNode);
var nodeIsSame = gEditItemOverlay.itemId == aSelectedNode.itemId ||
if (selectedNode) {
var concreteId = PlacesUtils.getConcreteItemId(selectedNode);
var nodeIsSame = gEditItemOverlay.itemId == selectedNode.itemId ||
gEditItemOverlay.itemId == concreteId ||
(aSelectedNode.itemId == -1 && gEditItemOverlay.uri &&
gEditItemOverlay.uri == aSelectedNode.uri);
(selectedNode.itemId == -1 && gEditItemOverlay.uri &&
gEditItemOverlay.uri == selectedNode.uri);
if (nodeIsSame && detailsDeck.selectedIndex == 1 &&
!gEditItemOverlay.multiEdit)
return;
@ -642,70 +643,54 @@ var PlacesOrganizer = {
// Clean up the panel before initing it again.
gEditItemOverlay.uninitPanel(false);
if (aSelectedNode && !PlacesUtils.nodeIsSeparator(aSelectedNode)) {
if (selectedNode && !PlacesUtils.nodeIsSeparator(selectedNode)) {
detailsDeck.selectedIndex = 1;
// Using the concrete itemId is arguably wrong. The bookmarks API
// does allow setting properties for folder shortcuts as well, but since
// the UI does not distinct between the couple, we better just show
// the concrete item properties for shortcuts to root nodes.
var concreteId = PlacesUtils.getConcreteItemId(aSelectedNode);
var concreteId = PlacesUtils.getConcreteItemId(selectedNode);
var isRootItem = concreteId != -1 && PlacesUtils.isRootItem(concreteId);
var readOnly = isRootItem ||
aSelectedNode.parent.itemId == PlacesUIUtils.leftPaneFolderId;
selectedNode.parent.itemId == PlacesUIUtils.leftPaneFolderId;
var useConcreteId = isRootItem ||
PlacesUtils.nodeIsTagQuery(aSelectedNode);
PlacesUtils.nodeIsTagQuery(selectedNode);
var itemId = -1;
if (concreteId != -1 && useConcreteId)
itemId = concreteId;
else if (aSelectedNode.itemId != -1)
itemId = aSelectedNode.itemId;
else if (selectedNode.itemId != -1)
itemId = selectedNode.itemId;
else
itemId = PlacesUtils._uri(aSelectedNode.uri);
itemId = PlacesUtils._uri(selectedNode.uri);
gEditItemOverlay.initPanel(itemId, { hiddenRows: ["folderPicker"]
, forceReadOnly: readOnly
, titleOverride: aSelectedNode.title
});
gEditItemOverlay.initPanel({ node: selectedNode
, hiddenRows: ["folderPicker"] });
// Dynamically generated queries, like history date containers, have
// itemId !=0 and do not exist in history. For them the panel is
// read-only, but empty, since it can't get a valid title for the object.
// In such a case we force the title using the selectedNode one, for UI
// polishness.
if (aSelectedNode.itemId == -1 &&
(PlacesUtils.nodeIsDay(aSelectedNode) ||
PlacesUtils.nodeIsHost(aSelectedNode)))
gEditItemOverlay._element("namePicker").value = aSelectedNode.title;
this._detectAndSetDetailsPaneMinimalState(aSelectedNode);
this._detectAndSetDetailsPaneMinimalState(selectedNode);
}
else if (!aSelectedNode && aNodeList[0]) {
var itemIds = [];
for (var i = 0; i < aNodeList.length; i++) {
if (!PlacesUtils.nodeIsBookmark(aNodeList[i]) &&
!PlacesUtils.nodeIsURI(aNodeList[i])) {
detailsDeck.selectedIndex = 0;
var selectItemDesc = document.getElementById("selectItemDescription");
var itemsCountLabel = document.getElementById("itemsCountText");
selectItemDesc.hidden = false;
itemsCountLabel.value =
PlacesUIUtils.getPluralString("detailsPane.itemsCountLabel",
aNodeList.length, [aNodeList.length]);
infoBox.hidden = true;
return;
}
itemIds[i] = aNodeList[i].itemId != -1 ? aNodeList[i].itemId :
PlacesUtils._uri(aNodeList[i].uri);
else if (!selectedNode && aNodeList[0]) {
if (aNodeList.every(PlacesUtils.nodeIsURI)) {
let uris = [for (node of aNodeList) PlacesUtils._uri(node.uri)];
detailsDeck.selectedIndex = 1;
gEditItemOverlay.initPanel({ uris
, hiddenRows: ["folderPicker",
"loadInSidebar",
"location",
"keyword",
"description",
"name"]});
this._detectAndSetDetailsPaneMinimalState(selectedNode);
}
else {
detailsDeck.selectedIndex = 0;
let selectItemDesc = document.getElementById("selectItemDescription");
let itemsCountLabel = document.getElementById("itemsCountText");
selectItemDesc.hidden = false;
itemsCountLabel.value =
PlacesUIUtils.getPluralString("detailsPane.itemsCountLabel",
aNodeList.length, [aNodeList.length]);
infoBox.hidden = true;
}
detailsDeck.selectedIndex = 1;
gEditItemOverlay.initPanel(itemIds,
{ hiddenRows: ["folderPicker",
"loadInSidebar",
"location",
"keyword",
"description",
"name"]});
this._detectAndSetDetailsPaneMinimalState(aSelectedNode);
}
else {
detailsDeck.selectedIndex = 0;

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

@ -1691,8 +1691,13 @@ PlacesTreeView.prototype = {
// We may only get here if the cell is editable.
let node = this._rows[aRow];
if (node.title != aText) {
let txn = new PlacesEditItemTitleTransaction(node.itemId, aText);
PlacesUtils.transactionManager.doTransaction(txn);
if (!PlacesUIUtils.useAsyncTransactions) {
let txn = new PlacesEditItemTitleTransaction(node.itemId, aText);
PlacesUtils.transactionManager.doTransaction(txn);
return;
}
PlacesTransactions.EditTitle({ guid: node.bookmarkGuid, title: aText })
.transact().catch(Cu.reportError);
}
},

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

@ -113,8 +113,7 @@ gTests.push({
run: function() {
// Check that the dialog is read-only.
ok(this.window.BookmarkPropertiesPanel._readOnly, "Dialog is read-only");
ok(this.window.gEditItemOverlay.readOnly, "Dialog is read-only");
// Check that accept button is disabled
var acceptButton = this.window.document.documentElement.getButton("accept");
ok(acceptButton.disabled, "Accept button is disabled");
@ -126,7 +125,7 @@ gTests.push({
PlacesUtils.bookmarks.getItemTitle(PlacesUtils.unfiledBookmarksFolderId),
"Node title is correct");
// Blur the field and ensure root's name has not been changed.
this.window.gEditItemOverlay.onNamePickerBlur();
this.window.gEditItemOverlay._namePicker.blur();
is(namepicker.value,
PlacesUtils.bookmarks.getItemTitle(PlacesUtils.unfiledBookmarksFolderId),
"Root title is correct");
@ -149,7 +148,6 @@ gTests.push({
//------------------------------------------------------------------------------
// Bug 462662 - Pressing Enter to select tag from autocomplete closes bookmarks properties dialog
gTests.push({
desc: "Bug 462662 - Pressing Enter to select tag from autocomplete closes bookmarks properties dialog",
sidebar: SIDEBAR_BOOKMARKS_ID,
@ -226,9 +224,11 @@ gTests.push({
// Open tags autocomplete popup.
info("About to focus the tagsField");
tagsField.focus();
tagsField.value = "";
EventUtils.synthesizeKey("t", {}, this.window);
executeSoon(() => {
tagsField.focus();
tagsField.value = "";
EventUtils.synthesizeKey("t", {}, this.window);
});
},
finish: function() {
@ -247,9 +247,10 @@ gTests.push({
}
});
//------------------------------------------------------------------------------
// Bug 475529 - Add button in new folder dialog not default anymore
/*
gTests.push({
desc: "Bug 475529 - Add button in new folder dialog not default anymore",
sidebar: SIDEBAR_BOOKMARKS_ID,
@ -271,7 +272,7 @@ gTests.push({
},
run: function() {
this._itemId = this.window.gEditItemOverlay._itemId;
this._itemId = this.window.gEditItemOverlay._paneInfo.itemId;
// Change folder name
var namePicker = this.window.document.getElementById("editBMPanel_namePicker");
var self = this;
@ -283,9 +284,9 @@ gTests.push({
});
}, false);
namePicker.value = "n";
info("About to focus the namePicker field");
namePicker.focus();
EventUtils.synthesizeKey("n", {}, this.window);
EventUtils.synthesizeKey("VK_RETURN", {}, this.window);
},
@ -304,6 +305,7 @@ gTests.push({
PlacesUtils.bookmarks.removeItem(this._itemId);
}
});
*/
//------------------------------------------------------------------------------
// Bug 476020 - Pressing Esc while having the tag autocomplete open closes the bookmarks panel
@ -562,7 +564,7 @@ function open_properties_dialog() {
// Windows has been loaded, execute our test now.
executeSoon(function () {
// Ensure overlay is loaded
ok(win.gEditItemOverlay._initialized, "EditItemOverlay is initialized");
ok(win.gEditItemOverlay.initialized, "EditItemOverlay is initialized");
gCurrentTest.window = win;
try {
gCurrentTest.run();

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

@ -25,7 +25,7 @@ function test() {
isnot(organizer.PlacesOrganizer, null, "Sanity check: PlacesOrganizer should exist");
isnot(organizer.gEditItemOverlay, null, "Sanity check: gEditItemOverlay should exist");
ok(organizer.gEditItemOverlay._initialized, "gEditItemOverlay is initialized");
ok(organizer.gEditItemOverlay.initialized, "gEditItemOverlay is initialized");
isnot(organizer.gEditItemOverlay.itemId, -1, "Editing a bookmark");
// Select History in the left pane.

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

@ -56,9 +56,9 @@
// Init panel.
ok(gEditItemOverlay, "gEditItemOverlay is in context");
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
gEditItemOverlay.initPanel(itemId);
ok(gEditItemOverlay._initialized, "gEditItemOverlay is initialized");
let node = yield PlacesUIUtils.promiseNodeLikeFromFetchInfo(bm);
gEditItemOverlay.initPanel({ node });
ok(gEditItemOverlay.initialized, "gEditItemOverlay is initialized");
let tree = gEditItemOverlay._element("folderTree");
yield openFolderTree(tree);

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

@ -55,19 +55,19 @@
// Init panel
ok(gEditItemOverlay, "gEditItemOverlay is in context");
let itemId = yield PlacesUtils.promiseItemId(bm.guid);
gEditItemOverlay.initPanel(itemId);
let node = yield PlacesUIUtils.promiseNodeLikeFromFetchInfo(bm);
gEditItemOverlay.initPanel({ node });
// add a tag
document.getElementById("editBMPanel_tagsField").value = testTag;
gEditItemOverlay.onTagsFieldBlur();
gEditItemOverlay.onTagsFieldChange();
// test that the tag has been added in the backend
is(PlacesUtils.tagging.getTagsForURI(testURI)[0], testTag, "tags match");
// change the tag
document.getElementById("editBMPanel_tagsField").value = testTagUpper;
gEditItemOverlay.onTagsFieldBlur();
gEditItemOverlay.onTagsFieldChange();
// test that the tag has been added in the backend
is(PlacesUtils.tagging.getTagsForURI(testURI)[0], testTagUpper, "tags match");

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

@ -73,9 +73,9 @@
// Init panel.
ok(gEditItemOverlay, "gEditItemOverlay is in context");
let id1 = yield PlacesUtils.promiseItemId(bm1.guid);
gEditItemOverlay.initPanel(id1);
ok(gEditItemOverlay._initialized, "gEditItemOverlay is initialized");
let node1 = yield PlacesUIUtils.promiseNodeLikeFromFetchInfo(bm1);
gEditItemOverlay.initPanel({ node: node1 });
ok(gEditItemOverlay.initialized, "gEditItemOverlay is initialized");
yield openTagSelector();
let tagsSelector = document.getElementById("editBMPanel_tagsSelector");

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

@ -75,8 +75,8 @@
});
// Init panel.
itemId = yield PlacesUtils.promiseItemId(bm.guid);
gEditItemOverlay.initPanel(itemId);
let node = yield PlacesUIUtils.promiseNodeLikeFromFetchInfo(bm);
gEditItemOverlay.initPanel({ node });
// Add a tag.
PlacesUtils.tagging.tagURI(TEST_URI, [TEST_TAG]);
@ -104,11 +104,10 @@
url: TEST_URI2.spec
});
// Init panel with multiple bookmarks.
itemId2 = yield PlacesUtils.promiseItemId(bm2.guid);
gEditItemOverlay.initPanel([itemId, itemId2]);
// Init panel with multiple uris.
gEditItemOverlay.initPanel({ uris: [TEST_URI, TEST_URI2] });
// Add a tag to the first bookmark.
// Add a tag to the first uri.
PlacesUtils.tagging.tagURI(TEST_URI, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI)[0], TEST_TAG,
"Correctly added a tag to the first bookmark.");
@ -116,7 +115,7 @@
"Editing multiple bookmarks without matching tags should not show any tag.");
checkTagsSelector([TEST_TAG], []);
// Add a tag to the second bookmark.
// Add a tag to the second uri.
PlacesUtils.tagging.tagURI(TEST_URI2, [TEST_TAG]);
is(PlacesUtils.tagging.getTagsForURI(TEST_URI2)[0], TEST_TAG,
"Correctly added a tag to the second bookmark.");
@ -141,7 +140,7 @@
checkTagsSelector([], []);
// Init panel with a nsIURI entry.
gEditItemOverlay.initPanel(TEST_URI);
gEditItemOverlay.initPanel({ uris: [TEST_URI] });
// Add a tag.
PlacesUtils.tagging.tagURI(TEST_URI, [TEST_TAG]);
@ -160,7 +159,7 @@
checkTagsSelector([], []);
// Init panel with multiple nsIURI entries.
gEditItemOverlay.initPanel([TEST_URI, TEST_URI2]);
gEditItemOverlay.initPanel({ uris: [TEST_URI, TEST_URI2] });
// Add a tag to the first entry.
PlacesUtils.tagging.tagURI(TEST_URI, [TEST_TAG]);

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

@ -55,6 +55,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "SessionWorker",
const PREF_UPGRADE_BACKUP = "browser.sessionstore.upgradeBackup.latestBuildID";
const PREF_MAX_UPGRADE_BACKUPS = "browser.sessionstore.upgradeBackup.maxUpgradeBackups";
const PREF_MAX_SERIALIZE_BACK = "browser.sessionstore.max_serialize_back";
const PREF_MAX_SERIALIZE_FWD = "browser.sessionstore.max_serialize_forward";
this.SessionFile = {
/**
* Read the contents of the session file, asynchronously.
@ -256,11 +259,11 @@ let SessionFileInternal = {
// Initialize the worker to let it handle backups and also
// as a workaround for bug 964531.
SessionWorker.post("init", [
result.origin,
this.Paths,
Preferences.get(PREF_MAX_UPGRADE_BACKUPS, 3)
]);
SessionWorker.post("init", [result.origin, this.Paths, {
maxUpgradeBackups: Preferences.get(PREF_MAX_UPGRADE_BACKUPS, 3),
maxSerializeBack: Preferences.get(PREF_MAX_SERIALIZE_BACK, 10),
maxSerializeForward: Preferences.get(PREF_MAX_SERIALIZE_FWD, -1)
}]);
return result;
}),

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

@ -70,53 +70,16 @@ let SessionHistoryInternal = {
let history = webNavigation.sessionHistory.QueryInterface(Ci.nsISHistoryInternal);
if (history && history.count > 0) {
let oldest;
let maxSerializeBack =
Services.prefs.getIntPref("browser.sessionstore.max_serialize_back");
if (maxSerializeBack >= 0) {
oldest = Math.max(0, history.index - maxSerializeBack);
} else { // History.getEntryAtIndex(0, ...) is the oldest.
oldest = 0;
}
let newest;
let maxSerializeFwd =
Services.prefs.getIntPref("browser.sessionstore.max_serialize_forward");
if (maxSerializeFwd >= 0) {
newest = Math.min(history.count - 1, history.index + maxSerializeFwd);
} else { // History.getEntryAtIndex(history.count - 1, ...) is the newest.
newest = history.count - 1;
}
// Loop over the transaction linked list directly so we can get the
// persist property for each transaction.
let txn = history.rootTransaction;
let i = 0;
while (txn && i < oldest) {
txn = txn.next;
i++;
}
while (txn && i <= newest) {
let shEntry = txn.sHEntry;
let entry = this.serializeEntry(shEntry, isPinned);
for (let txn = history.rootTransaction; txn; txn = txn.next) {
let entry = this.serializeEntry(txn.sHEntry, isPinned);
entry.persist = txn.persist;
data.entries.push(entry);
txn = txn.next;
i++;
}
if (i <= newest) {
// In some cases, there don't seem to be as many history entries as
// history.count claims. we'll save whatever history we can, print an
// error message, and still save sessionstore.js.
debug("SessionStore failed gathering complete history " +
"for the focused window/tab. See bug 669196.");
}
// Set the one-based index of the currently active tab,
// ensuring it isn't out of bounds if an exception was thrown above.
data.index = Math.min(history.index - oldest + 1, data.entries.length);
// Ensure the index isn't out of bounds if an exception was thrown above.
data.index = Math.min(history.index + 1, data.entries.length);
}
// If either the session history isn't available yet or doesn't have any

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

@ -246,12 +246,7 @@ let SessionSaverInternal = {
* Write the given state object to disk.
*/
_writeState: function (state) {
// Inform observers
notify(null, "sessionstore-state-write");
stopWatchStart("SERIALIZE_DATA_MS", "SERIALIZE_DATA_LONGEST_OP_MS", "WRITE_STATE_LONGEST_OP_MS");
let data = JSON.stringify(state);
stopWatchFinish("SERIALIZE_DATA_MS", "SERIALIZE_DATA_LONGEST_OP_MS");
stopWatchStart("WRITE_STATE_LONGEST_OP_MS");
// We update the time stamp before writing so that we don't write again
// too soon, if saving is requested before the write completes. Without
@ -262,10 +257,9 @@ let SessionSaverInternal = {
// Write (atomically) to a session file, using a tmp file. Once the session
// file is successfully updated, save the time stamp of the last save and
// notify the observers.
stopWatchStart("SEND_SERIALIZED_STATE_LONGEST_OP_MS");
let promise = SessionFile.write(data);
stopWatchFinish("WRITE_STATE_LONGEST_OP_MS",
"SEND_SERIALIZED_STATE_LONGEST_OP_MS");
let promise = SessionFile.write(state);
stopWatchFinish("WRITE_STATE_LONGEST_OP_MS");
promise = promise.then(() => {
this.updateLastSaveTime();
notify(null, "sessionstore-state-write-complete");

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

@ -88,15 +88,25 @@ let Agent = {
* @param {string} origin Which of sessionstore.js or its backups
* was used. One of the `STATE_*` constants defined above.
* @param {object} paths The paths at which to find the various files.
* @param {number} maxUpgradeBackups The number of old upgrade backups that should be kept.
* @param {object} prefs The preferences the worker needs to known.
*/
init: function (origin, paths, maxUpgradeBackups) {
init(origin, paths, prefs = {}) {
if (!(origin in paths || origin == STATE_EMPTY)) {
throw new TypeError("Invalid origin: " + origin);
}
// Check that all required preference values were passed.
for (let pref of ["maxUpgradeBackups", "maxSerializeBack", "maxSerializeForward"]) {
if (!prefs.hasOwnProperty(pref)) {
throw new TypeError(`Missing preference value for ${pref}`);
}
}
this.state = origin;
this.Paths = paths;
this.maxUpgradeBackups = maxUpgradeBackups || 3;
this.maxUpgradeBackups = prefs.maxUpgradeBackups;
this.maxSerializeBack = prefs.maxSerializeBack;
this.maxSerializeForward = prefs.maxSerializeForward;
this.upgradeBackupNeeded = paths.nextUpgradeBackup != paths.upgradeBackup;
return {result: true};
},
@ -106,7 +116,7 @@ let Agent = {
* Write the session to disk, performing any necessary backup
* along the way.
*
* @param {string} stateString The state to write to disk.
* @param {object} state The state to write to disk.
* @param {object} options
* - performShutdownCleanup If |true|, we should
* perform shutdown-time cleanup to ensure that private data
@ -114,10 +124,31 @@ let Agent = {
* - isFinalWrite If |true|, write to Paths.clean instead of
* Paths.recovery
*/
write: function (stateString, options = {}) {
write: function (state, options = {}) {
let exn;
let telemetry = {};
// Cap the number of backward and forward shistory entries on shutdown.
if (options.isFinalWrite) {
for (let window of state.windows) {
for (let tab of window.tabs) {
let lower = 0;
let upper = tab.entries.length;
if (this.maxSerializeBack > -1) {
lower = Math.max(lower, tab.index - this.maxSerializeBack - 1);
}
if (this.maxSerializeForward > -1) {
upper = Math.min(upper, tab.index + this.maxSerializeForward);
}
tab.entries = tab.entries.slice(lower, upper);
tab.index -= lower;
}
}
}
let stateString = JSON.stringify(state);
let data = Encoder.encode(stateString);
let startWriteMs, stopWriteMs;

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

@ -83,7 +83,6 @@ skip-if = buildapp == 'mulet'
[browser_frametree.js]
[browser_frame_history.js]
[browser_global_store.js]
[browser_history_cap.js]
[browser_history_persist.js]
[browser_label_and_icon.js]
[browser_merge_closed_tabs.js]

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

@ -1,121 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* This test ensures that the preferences (added in bug 943339) that control how
* many back and forward button session history entries we store work correctly.
*
* It adds a number of entries to the session history, restores them and checks
* that the restored state matches the preferences.
*/
add_task(function *test_history_cap() {
const baseURL = "http://example.com/browser_history_cap#"
const maxEntries = 9; // The number of generated session history entries.
const middleEntry = 4; // The zero-based index of the middle entry.
const maxBack1 = 2; // The history cap settings used for the first test,
const maxFwd1 = 3; // where maxBack1 + 1 + maxFwd1 < maxEntries.
const maxBack2 = 5; // The history cap settings used for the other tests,
const maxFwd2 = 5; // where maxBack2 + 1 + maxFwd2 > maxEntries.
// Set the relevant preferences for the first test.
gPrefService.setIntPref("browser.sessionhistory.max_entries", maxEntries);
gPrefService.setIntPref("browser.sessionstore.max_serialize_back", maxBack1);
gPrefService.setIntPref("browser.sessionstore.max_serialize_forward", maxFwd1);
// Make sure the settings we modify are reset afterward.
registerCleanupFunction(() => {
gPrefService.clearUserPref("browser.sessionhistory.max_entries");
gPrefService.clearUserPref("browser.sessionstore.max_serialize_back");
gPrefService.clearUserPref("browser.sessionstore.max_serialize_forward");
});
let tab = gBrowser.addTab();
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
// Generate the tab state entries and set the one-based
// tab-state index to the middle session history entry.
let tabState = {entries: [], index: middleEntry + 1};
for (let i = 0; i < maxEntries; i++) {
tabState.entries.push({url: baseURL + i});
}
info("Testing situation where only a subset of session history entries should be restored.");
yield promiseTabState(tab, tabState);
TabState.flush(tab.linkedBrowser);
let restoredTabState = JSON.parse(ss.getTabState(tab));
is(restoredTabState.entries.length, maxBack1 + 1 + maxFwd1,
"The expected number of session history entries was restored.");
is(restoredTabState.index, maxBack1 + 1, "The restored tab-state index is correct");
let indexURLOffset = middleEntry - (restoredTabState.index - 1);
for (let i = 0; i < restoredTabState.entries.length; i++) {
is(restoredTabState.entries[i].url, baseURL + (i + indexURLOffset),
"URL of restored entry matches the expected URL.");
}
// Set the relevant preferences for the other tests.
gPrefService.setIntPref("browser.sessionstore.max_serialize_back", maxBack2);
gPrefService.setIntPref("browser.sessionstore.max_serialize_forward", maxFwd2);
info("Testing situation where all of the entries in the session history should be restored.");
yield promiseTabState(tab, tabState);
TabState.flush(tab.linkedBrowser);
restoredTabState = JSON.parse(ss.getTabState(tab));
is(restoredTabState.entries.length, maxEntries,
"The expected number of session history entries was restored.");
is(restoredTabState.index, middleEntry + 1, "The restored tab-state index is correct");
for (let i = middleEntry - 2; i <= middleEntry + 2; i++) {
is(restoredTabState.entries[i].url, baseURL + i,
"URL of restored entry matches the expected URL.");
}
info("Testing situation where only the 1 + maxFwd2 oldest entries should be restored.");
// Set the one-based tab-state index to the oldest session history entry.
tabState.index = 1;
yield promiseTabState(tab, tabState);
TabState.flush(tab.linkedBrowser);
restoredTabState = JSON.parse(ss.getTabState(tab));
is(restoredTabState.entries.length, 1 + maxFwd2,
"The expected number of session history entries was restored.");
is(restoredTabState.index, 1, "The restored tab-state index is correct");
for (let i = 0; i <= 2; i++) {
is(restoredTabState.entries[i].url, baseURL + i,
"URL of restored entry matches the expected URL.");
}
info("Testing situation where only the maxBack2 + 1 newest entries should be restored.");
// Set the one-based tab-state index to the newest session history entry.
tabState.index = maxEntries;
yield promiseTabState(tab, tabState);
TabState.flush(tab.linkedBrowser);
restoredTabState = JSON.parse(ss.getTabState(tab));
is(restoredTabState.entries.length, maxBack2 + 1,
"The expected number of session history entries was restored.");
is(restoredTabState.index, maxBack2 + 1, "The restored tab-state index is correct");
indexURLOffset = (maxEntries - 1) - maxBack2;
for (let i = maxBack2 - 2; i <= maxBack2; i++) {
is(restoredTabState.entries[i].url, baseURL + (i + indexURLOffset),
"URL of restored entry matches the expected URL.");
}
gBrowser.removeTab(tab);
});

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

@ -239,7 +239,7 @@ function waitForTopic(aTopic, aTimeout, aCallback) {
* Wait until session restore has finished collecting its data and is
* has written that data ("sessionstore-state-write-complete").
*
* @param {function} aCallback If sessionstore-state-write is sent
* @param {function} aCallback If sessionstore-state-write-complete is sent
* within buffering interval + 100 ms, the callback is passed |true|,
* otherwise, it is passed |false|.
*/

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

@ -79,24 +79,27 @@ function promise_check_contents(path, expect) {
return Task.spawn(function*() {
do_print("Checking whether " + path + " has the right contents");
let actual = yield OS.File.read(path, { encoding: "utf-8"});
if (actual != expect) {
throw new Error("File " + path + " should contain\n\t" + expect + "\nbut contains " + actual);
}
Assert.deepEqual(JSON.parse(actual), expect, `File ${path} contains the expected data.`);
});
}
function generateFileContents(id) {
let url = `http://example.com/test_backup_once#${id}_${Math.random()}`;
return {windows: [{tabs: [{entries: [{url}], index: 1}]}]}
}
// Write to the store, and check that it creates:
// - $Path.recovery with the new data
// - $Path.nextUpgradeBackup with the old data
add_task(function* test_first_write_backup() {
let initial_content = "initial content " + Math.random();
let new_content = "test_1 " + Math.random();
let initial_content = generateFileContents("initial");
let new_content = generateFileContents("test_1");
do_print("Before the first write, none of the files should exist");
yield promise_check_exist(Paths.backups, false);
yield File.makeDir(Paths.backups);
yield File.writeAtomic(Paths.clean, initial_content, { encoding: "utf-8" });
yield File.writeAtomic(Paths.clean, JSON.stringify(initial_content), { encoding: "utf-8" });
yield SessionFile.write(new_content);
do_print("After first write, a few files should have been created");
@ -116,8 +119,9 @@ add_task(function* test_first_write_backup() {
// - $Path.recovery contains the new data
// - $Path.recoveryBackup contains the previous data
add_task(function* test_second_write_no_backup() {
let new_content = "test_2 " + Math.random();
let new_content = generateFileContents("test_2");
let previous_backup_content = yield File.read(Paths.recovery, { encoding: "utf-8" });
previous_backup_content = JSON.parse(previous_backup_content);
yield OS.File.remove(Paths.cleanBackup);
@ -136,7 +140,7 @@ add_task(function* test_second_write_no_backup() {
// Make sure that we create $Paths.clean and remove $Paths.recovery*
// upon shutdown
add_task(function* test_shutdown() {
let output = "test_3 " + Math.random();
let output = generateFileContents("test_3");
yield File.writeAtomic(Paths.recovery, "I should disappear");
yield File.writeAtomic(Paths.recoveryBackup, "I should also disappear");
@ -145,7 +149,5 @@ add_task(function* test_shutdown() {
do_check_false((yield File.exists(Paths.recovery)));
do_check_false((yield File.exists(Paths.recoveryBackup)));
let input = yield File.read(Paths.clean, { encoding: "utf-8"});
do_check_eq(input, output);
yield promise_check_contents(Paths.clean, output);
});

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

@ -0,0 +1,151 @@
"use strict";
/**
* This test ensures that we correctly clean up the session state before
* writing to disk a last time on shutdown. For now it only tests that each
* tab's shistory is capped to a maximum number of preceding and succeeding
* entries.
*/
const {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
const {SessionWorker} = Cu.import("resource:///modules/sessionstore/SessionWorker.jsm", {});
const profd = do_get_profile();
const {SessionFile} = Cu.import("resource:///modules/sessionstore/SessionFile.jsm", {});
const {Paths} = SessionFile;
const {OS} = Cu.import("resource://gre/modules/osfile.jsm", {});
const {File} = OS;
const MAX_ENTRIES = 9;
const URL = "http://example.com/#";
// We need a XULAppInfo to initialize SessionFile
let XULAppInfo = {
vendor: "Mozilla",
name: "SessionRestoreTest",
ID: "{230de50e-4cd1-11dc-8314-0800200c9a66}",
version: "1",
appBuildID: "2007010101",
platformVersion: "",
platformBuildID: "2007010101",
inSafeMode: false,
logConsoleErrors: true,
OS: "XPCShell",
XPCOMABI: "noarch-spidermonkey",
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIXULAppInfo,
Ci.nsIXULRuntime,
])
};
let XULAppInfoFactory = {
createInstance: function (outer, iid) {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
return XULAppInfo.QueryInterface(iid);
}
};
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
registrar.registerFactory(Components.ID("{fbfae60b-64a4-44ef-a911-08ceb70b9f31}"),
"XULAppInfo", "@mozilla.org/xre/app-info;1",
XULAppInfoFactory);
add_task(function* setup() {
let source = do_get_file("data/sessionstore_valid.js");
source.copyTo(profd, "sessionstore.js");
// Finish SessionFile initialization.
yield SessionFile.read();
// Reset prefs on cleanup.
do_register_cleanup(() => {
Services.prefs.clearUserPref("browser.sessionstore.max_serialize_back");
Services.prefs.clearUserPref("browser.sessionstore.max_serialize_forward");
});
});
function createSessionState(index) {
// Generate the tab state entries and set the one-based
// tab-state index to the middle session history entry.
let tabState = {entries: [], index};
for (let i = 0; i < MAX_ENTRIES; i++) {
tabState.entries.push({url: URL + i});
}
return {windows: [{tabs: [tabState]}]};
}
function* setMaxBackForward(back, fwd) {
Services.prefs.setIntPref("browser.sessionstore.max_serialize_back", back);
Services.prefs.setIntPref("browser.sessionstore.max_serialize_forward", fwd);
yield SessionFile.read();
}
function* writeAndParse(state, path, options = {}) {
yield SessionWorker.post("write", [state, options]);
return JSON.parse(yield File.read(path, {encoding: "utf-8"}));
}
add_task(function* test_shistory_cap_none() {
let state = createSessionState(5);
// Don't limit the number of shistory entries.
yield setMaxBackForward(-1, -1);
// Check that no caps are applied.
let diskState = yield writeAndParse(state, Paths.clean, {isFinalWrite: true});
Assert.deepEqual(state, diskState, "no cap applied");
});
add_task(function* test_shistory_cap_middle() {
let state = createSessionState(5);
yield setMaxBackForward(2, 3);
// Cap is only applied on clean shutdown.
let diskState = yield writeAndParse(state, Paths.recovery);
Assert.deepEqual(state, diskState, "no cap applied");
// Check that the right number of shistory entries was discarded
// and the shistory index updated accordingly.
diskState = yield writeAndParse(state, Paths.clean, {isFinalWrite: true});
let tabState = state.windows[0].tabs[0];
tabState.entries = tabState.entries.slice(2, 8);
tabState.index = 3;
Assert.deepEqual(state, diskState, "cap applied");
});
add_task(function* test_shistory_cap_lower_bound() {
let state = createSessionState(1);
yield setMaxBackForward(5, 5);
// Cap is only applied on clean shutdown.
let diskState = yield writeAndParse(state, Paths.recovery);
Assert.deepEqual(state, diskState, "no cap applied");
// Check that the right number of shistory entries was discarded.
diskState = yield writeAndParse(state, Paths.clean, {isFinalWrite: true});
let tabState = state.windows[0].tabs[0];
tabState.entries = tabState.entries.slice(0, 6);
Assert.deepEqual(state, diskState, "cap applied");
});
add_task(function* test_shistory_cap_upper_bound() {
let state = createSessionState(MAX_ENTRIES);
yield setMaxBackForward(5, 5);
// Cap is only applied on clean shutdown.
let diskState = yield writeAndParse(state, Paths.recovery);
Assert.deepEqual(state, diskState, "no cap applied");
// Check that the right number of shistory entries was discarded
// and the shistory index updated accordingly.
diskState = yield writeAndParse(state, Paths.clean, {isFinalWrite: true});
let tabState = state.windows[0].tabs[0];
tabState.entries = tabState.entries.slice(3);
tabState.index = 6;
Assert.deepEqual(state, diskState, "cap applied");
});

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

@ -9,7 +9,8 @@ support-files =
data/sessionstore_valid.js
[test_backup_once.js]
[test_histogram_corrupt_files.js]
[test_shutdown_cleanup.js]
[test_startup_nosession_async.js]
[test_startup_session_async.js]
[test_startup_invalid_session.js]
[test_histogram_corrupt_files.js]

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

@ -4,9 +4,56 @@
"use strict";
const gcli = require("gcli/index");
const { createSystem, connectFront, disconnectFront } = require("gcli/system");
const { GcliFront } = require("devtools/server/actors/gcli");
const commandModules = [
/**
* This is the basic list of modules that should be loaded into each
* requisition instance whether server side or client side
*/
exports.baseModules = [
"gcli/types/delegate",
"gcli/types/selection",
"gcli/types/array",
"gcli/types/boolean",
"gcli/types/command",
"gcli/types/date",
"gcli/types/file",
"gcli/types/javascript",
"gcli/types/node",
"gcli/types/number",
"gcli/types/resource",
"gcli/types/setting",
"gcli/types/string",
"gcli/types/union",
"gcli/types/url",
"gcli/fields/fields",
"gcli/fields/delegate",
"gcli/fields/selection",
"gcli/ui/focus",
"gcli/ui/intro",
"gcli/converters/converters",
"gcli/converters/basic",
"gcli/converters/terminal",
"gcli/languages/command",
"gcli/languages/javascript",
"gcli/commands/clear",
"gcli/commands/context",
"gcli/commands/help",
"gcli/commands/pref",
];
/**
* Some commands belong to a tool (see getToolModules). This is a list of the
* modules that are *not* owned by a tool.
*/
exports.devtoolsModules = [
"devtools/tilt/tilt-commands",
"gcli/commands/addon",
"gcli/commands/appcache",
@ -28,15 +75,83 @@ const commandModules = [
"gcli/commands/tools",
];
gcli.addItemsByModule(commandModules, { delayedLoad: true });
/**
* Register commands from tools with 'command: [ "some/module" ]' definitions.
* The map/reduce incantation squashes the array of arrays to a single array.
*/
const defaultTools = require("definitions").defaultTools;
exports.devtoolsToolModules = defaultTools.map(def => def.commands || [])
.reduce((prev, curr) => prev.concat(curr), []);
const defaultTools = require("main").defaultTools;
for (let definition of defaultTools) {
if (definition.commands) {
gcli.addItemsByModule(definition.commands, { delayedLoad: true });
/**
* Add modules to a system for use in a content process (but don't call load)
*/
exports.addAllItemsByModule = function(system) {
system.addItemsByModule(exports.baseModules, { delayedLoad: true });
system.addItemsByModule(exports.devtoolsModules, { delayedLoad: true });
system.addItemsByModule(exports.devtoolsToolModules, { delayedLoad: true });
const { mozDirLoader } = require("gcli/commands/cmd");
system.addItemsByModule("mozcmd", { delayedLoad: true, loader: mozDirLoader });
};
/**
* This is WeakMap<Target, Links> where Links is an object that looks like
* { refs: number, promise: Promise<System>, front: GcliFront }
*/
var linksForTarget = new WeakMap();
/**
* The toolbox uses the following properties on a command to allow it to be
* added to the toolbox toolbar
*/
var customProperties = [ "buttonId", "buttonClass", "tooltipText" ];
/**
* Create a system which connects to a GCLI in a remote target
* @return Promise<System> for the given target
*/
exports.getSystem = function(target) {
const existingLinks = linksForTarget.get(target);
if (existingLinks != null) {
existingLinks.refs++;
return existingLinks.promise;
}
}
const { mozDirLoader } = require("gcli/commands/cmd");
const system = createSystem({ location: "client" });
gcli.addItemsByModule("mozcmd", { delayedLoad: true, loader: mozDirLoader });
exports.addAllItemsByModule(system);
// Load the client system
const links = {
refs: 1,
system,
promise: system.load().then(() => {
return GcliFront.create(target).then(front => {
links.front = front;
return connectFront(system, front, customProperties).then(() => system);
});
})
};
linksForTarget.set(target, links);
return links.promise;
};
/**
* Someone that called getSystem doesn't need it any more, so decrement the
* count of users of the system for that target, and destroy if needed
*/
exports.releaseSystem = function(target) {
const links = linksForTarget.get(target);
if (links == null) {
throw new Error("releaseSystem called for unknown target");
}
links.refs--;
if (links.refs === 0) {
disconnectFront(links.system, links.front);
links.system.destroy();
linksForTarget.delete(target);
}
};

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

@ -7,7 +7,7 @@ function test() {
return Task.spawn(spawnTest).then(finish, helpers.handleError);
}
function spawnTest() {
function* spawnTest() {
let options = yield helpers.openTab("about:blank");
yield helpers.openToolbar(options);

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

@ -11,7 +11,7 @@ function test() {
return Task.spawn(spawnTest).then(finish, helpers.handleError);
}
function spawnTest() {
function* spawnTest() {
let lines = [
'Manifest has a character encoding of ISO-8859-1. Manifests must have the ' +
'utf-8 character encoding.',

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

@ -10,7 +10,7 @@ function test() {
return Task.spawn(spawnTest).then(finish, helpers.handleError);
}
function spawnTest() {
function* spawnTest() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);

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

@ -8,7 +8,7 @@ const TEST_URI = "data:text/html;charset=utf-8,gcli-calllog";
let tests = {};
function test() {
return Task.spawn(function() {
return Task.spawn(function*() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);

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

@ -8,7 +8,7 @@ const TEST_URI = "data:text/html;charset=utf-8,cmd-calllog-chrome";
let tests = {};
function test() {
return Task.spawn(function() {
return Task.spawn(function*() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);

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

@ -9,7 +9,7 @@ function test() {
return Task.spawn(spawnTest).then(finish, helpers.handleError);
}
function spawnTest() {
function* spawnTest() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
@ -49,7 +49,7 @@ function spawnTest() {
yield helpers.audit(options, [
{
setup: "console close",
exec: { output: true }
exec: { output: "" }
}
]);

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

@ -33,18 +33,21 @@ add_task(function*() {
* Visit all the pages in the test
*/
function* navigate(usage, options) {
yield usage.start();
yield usage.start(options.chromeWindow, options.target);
ok(usage.isRunning(), "csscoverage is running");
let load1Promise = helpers.listenOnce(options.browser, "load", true);
yield helpers.navigate(PAGE_1, options);
// Wait for the test pages to auto-cycle
let ev = yield helpers.listenOnce(options.browser, "load", true);
is(ev.target.location.href, PAGE_1, "page 1 loaded");
yield load1Promise;
is(options.window.location.href, PAGE_1, "page 1 loaded");
ev = yield helpers.listenOnce(options.browser, "load", true);
is(ev.target.location.href, PAGE_3, "page 3 loaded");
// Page 2 is a frame in page 1. JS in the page navigates to page 3.
yield helpers.listenOnce(options.browser, "load", true);
is(options.window.location.href, PAGE_3, "page 3 loaded");
yield usage.stop();

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

@ -10,7 +10,7 @@ function test() {
return Task.spawn(testTask).then(finish, helpers.handleError);
}
function testTask() {
function* testTask() {
let options = yield helpers.openTab("about:blank");
yield helpers.openToolbar(options);
@ -29,7 +29,10 @@ function testTask() {
{
setup: 'jsb ' + TEST_URI,
// Should result in a new scratchpad window
exec: { }
exec: {
output: '',
error: false
}
}
]);

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

@ -74,7 +74,7 @@ let tests = {
};
function test() {
return Task.spawn(function() {
return Task.spawn(function*() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);

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

@ -10,7 +10,7 @@ function test() {
return Task.spawn(spawnTest).then(finish, helpers.handleError);
}
function spawnTest() {
function* spawnTest() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
@ -302,7 +302,8 @@ function spawnTest() {
args: {
searchAttributes: { value: undefined, status: 'INCOMPLETE' },
searchElements: { value: undefined, status: 'INCOMPLETE' },
root: { value: undefined },
// root: { value: undefined }, // 'root' is a node which is remote
// so we can't see the value in tests
ignoreCase: { value: false },
}
},
@ -317,7 +318,8 @@ function spawnTest() {
args: {
searchAttributes: { value: 'foo' },
searchElements: { value: 'bar' },
root: { value: undefined },
// root: { value: undefined }, // 'root' is a node which is remote
// so we can't see the value in tests
ignoreCase: { value: false },
}
},

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

@ -13,7 +13,7 @@ function test() {
return Task.spawn(spawnTest).then(finish, helpers.handleError);
}
function spawnTest() {
function* spawnTest() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);

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

@ -13,7 +13,7 @@ function test() {
return Task.spawn(spawnTest).then(finish, helpers.handleError);
}
function spawnTest() {
function* spawnTest() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);

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

@ -16,7 +16,7 @@ function test() {
return Task.spawn(spawnTest).then(finish, helpers.handleError);
}
function spawnTest() {
function* spawnTest() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);

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

@ -11,7 +11,7 @@ function test() {
return Task.spawn(spawnTest).then(finish, helpers.handleError);
}
function spawnTest() {
function* spawnTest() {
waitForExplicitFinish();
info("RUN TEST: non-private window");
@ -81,11 +81,6 @@ function addTabWithToolbarRunTests(win) {
input: 'screenshot --selector img#testImage',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
selector: {
value: options.window.document.getElementById("testImage")
},
}
},
},
]);

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

@ -16,14 +16,18 @@ function test() {
return Task.spawn(spawnTest).then(finish, helpers.handleError);
}
function spawnTest() {
function* spawnTest() {
// Setup
let options = yield helpers.openTab(TEST_URI);
require("devtools/commandline/commands-index");
let gcli = require("gcli/index");
yield gcli.load();
let settings = gcli.settings;
const { createSystem } = require("gcli/system");
const system = createSystem({ location: "server" });
const gcliInit = require("devtools/commandline/commands-index");
gcliInit.addAllItemsByModule(system);
yield system.load();
let settings = system.settings;
let hideIntroEnabled = settings.get("devtools.gcli.hideIntro");
let tabSize = settings.get("devtools.editor.tabsize");

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testAsync.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_async.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testBasic = function(options) {
@ -74,7 +59,6 @@ exports.testBasic = function(options) {
args: {
command: { name: 'tsslow' },
hello: {
value: undefined,
arg: '',
status: 'INCOMPLETE'
},
@ -95,7 +79,6 @@ exports.testBasic = function(options) {
args: {
command: { name: 'tsslow' },
hello: {
value: undefined,
arg: ' S',
status: 'INCOMPLETE'
},
@ -116,7 +99,6 @@ exports.testBasic = function(options) {
args: {
command: { name: 'tsslow' },
hello: {
value: 'Shalom',
arg: ' Shalom ',
status: 'VALID',
message: ''

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCanon.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_canon.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');
var Commands = require('gcli/commands/commands').Commands;
@ -219,6 +204,9 @@ exports.testAltCommands = function(options) {
{ name: 'num', type: 'number' },
{ name: 'opt', type: { name: 'selection', data: [ '1', '2', '3' ] } },
],
customProp1: 'localValue',
customProp2: true,
customProp3: 42,
exec: function(args, context) {
return context.commandName + ':' +
args.str + ':' + args.num + ':' + args.opt;
@ -235,6 +223,24 @@ exports.testAltCommands = function(options) {
'],"isParent":false}]',
'JSON.stringify(commandSpecs)');
var customProps = [ 'customProp1', 'customProp2', 'customProp3', ];
var commandSpecs2 = altCommands.getCommandSpecs(customProps);
assert.is(JSON.stringify(commandSpecs2),
'[{' +
'"item":"command",' +
'"name":"tss",' +
'"params":[' +
'{"name":"str","type":"string"},' +
'{"name":"num","type":"number"},' +
'{"name":"opt","type":{"name":"selection","data":["1","2","3"]}}' +
'],' +
'"isParent":false,' +
'"customProp1":"localValue",' +
'"customProp2":true,' +
'"customProp3":42' +
'}]',
'JSON.stringify(commandSpecs)');
var remoter = function(args, context) {
assert.is(context.commandName, 'tss', 'commandName is tss');

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCli1.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_cli1.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');
@ -268,7 +253,6 @@ exports.testTsv = function(options) {
}
},
{
skipRemainingIf: options.isNoDom,
name: '|tsv option',
setup: function() {
return helpers.setInput(options, 'tsv option', 0);

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

@ -15,45 +15,18 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCli2.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_cli2.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
var nodetype = require('gcli/types/node');
exports.setup = function(options) {
if (options.window) {
nodetype.setDocument(options.window.document);
}
};
exports.shutdown = function(options) {
nodetype.unsetDocument();
};
exports.testSingleString = function(options) {
return helpers.audit(options, [
{
@ -376,7 +349,6 @@ exports.testSingleFloat = function(options) {
}
},
{
skipRemainingIf: options.isNoDom,
name: 'tsf x (cursor=4)',
setup: function() {
return helpers.setInput(options, 'tsf x', 4);
@ -406,21 +378,14 @@ exports.testSingleFloat = function(options) {
};
exports.testElementWeb = function(options) {
var inputElement = options.isNoDom ?
null :
options.window.document.getElementById('gcli-input');
return helpers.audit(options, [
{
skipIf: function gcliInputElementExists() {
return inputElement == null;
},
setup: 'tse #gcli-input',
setup: 'tse #gcli-root',
check: {
input: 'tse #gcli-input',
input: 'tse #gcli-root',
hints: ' [options]',
markup: 'VVVVVVVVVVVVVVV',
cursor: 15,
markup: 'VVVVVVVVVVVVVV',
cursor: 14,
current: 'node',
status: 'VALID',
predictions: [ ],
@ -428,8 +393,7 @@ exports.testElementWeb = function(options) {
args: {
command: { name: 'tse' },
node: {
value: inputElement,
arg: ' #gcli-input',
arg: ' #gcli-root',
status: 'VALID',
message: ''
},
@ -444,7 +408,6 @@ exports.testElementWeb = function(options) {
exports.testElement = function(options) {
return helpers.audit(options, [
{
skipRemainingIf: options.isNoDom,
setup: 'tse',
check: {
input: 'tse',
@ -457,7 +420,7 @@ exports.testElement = function(options) {
unassigned: [ ],
args: {
command: { name: 'tse' },
node: { value: undefined, arg: '', status: 'INCOMPLETE' },
node: { arg: '', status: 'INCOMPLETE' },
nodes: { arg: '', status: 'VALID', message: '' },
nodes2: { arg: '', status: 'VALID', message: '' },
}
@ -605,7 +568,7 @@ exports.testNestedCommand = function(options) {
}
},
{
skipIf: options.isPhantomjs,
skipIf: options.isPhantomjs, // PhantomJS gets predictions wrong
setup: 'tsn x',
check: {
input: 'tsn x',

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCompletion1.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_completion1.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testActivate = function(options) {
@ -183,7 +168,7 @@ exports.testActivate = function(options) {
}
},
{
skipIf: options.isPhantomjs,
skipIf: options.isPhantomjs, // PhantomJS gets predictions wrong
setup: 'tsg d',
check: {
hints: ' [options] -> ccc'

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCompletion2.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_completion2.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testLong = function(options) {
@ -170,7 +155,6 @@ exports.testNoTab = function(options) {
}
},
{
skipIf: options.isNoDom,
name: '<TAB>',
setup: function() {
// Doing it this way avoids clearing the input buffer

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testContext.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_context.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testBaseline = function(options) {

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testDate.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_date.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');
@ -66,15 +51,15 @@ exports.testMaxMin = function(options) {
var date = types.createType({ name: 'date', max: max, min: min });
assert.is(date.getMax(), max, 'max setup');
var incremented = date.increment(min);
var incremented = date.nudge(min, 1);
assert.is(incremented, max, 'incremented');
};
exports.testIncrement = function(options) {
var date = options.requisition.system.types.createType('date');
return date.parseString('now').then(function(conversion) {
var plusOne = date.increment(conversion.value);
var minusOne = date.decrement(plusOne);
var plusOne = date.nudge(conversion.value, 1);
var minusOne = date.nudge(plusOne, -1);
// See comments in testParse
var gap = new Date().getTime() - minusOne.getTime();
@ -126,7 +111,7 @@ exports.testInput = function(options) {
},
exec: {
output: [ /^Exec: tsdate/, /2001/, /1980/ ],
type: 'string',
type: 'testCommandOutput',
error: false
}
},
@ -172,7 +157,7 @@ exports.testInput = function(options) {
},
exec: {
output: [ /^Exec: tsdate/, /2001/, /1980/ ],
type: 'string',
type: 'testCommandOutput',
error: false
}
},
@ -213,7 +198,7 @@ exports.testInput = function(options) {
},
exec: {
output: [ /^Exec: tsdate/, new Date().getFullYear() ],
type: 'string',
type: 'testCommandOutput',
error: false
}
},
@ -253,7 +238,7 @@ exports.testInput = function(options) {
},
exec: {
output: [ /^Exec: tsdate/, new Date().getFullYear() ],
type: 'string',
type: 'testCommandOutput',
error: false
}
}
@ -264,7 +249,7 @@ exports.testIncrDecr = function(options) {
return helpers.audit(options, [
{
// createRequisitionAutomator doesn't fake UP/DOWN well enough
skipRemainingIf: options.isNoDom,
skipRemainingIf: options.isNode,
setup: 'tsdate 2001-01-01<UP>',
check: {
input: 'tsdate 2001-01-02',

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

@ -15,54 +15,18 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testExec.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_exec.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');
var nodetype = require('gcli/types/node');
var mockBody = {
style: {}
};
var mockEmptyNodeList = {
length: 0,
item: function() { return null; }
};
var mockRootNodeList = {
length: 1,
item: function(i) { return mockBody; }
};
var mockDoc = {
querySelectorAll: function(css) {
return (css === ':root') ? mockRootNodeList : mockEmptyNodeList;
}
};
exports.testParamGroup = function(options) {
var tsg = options.requisition.system.commands.get('tsg');
@ -121,7 +85,7 @@ exports.testWithHelpers = function(options) {
}
},
exec: {
output: 'Exec: tsv optionType=string, optionValue=10'
output: 'Exec: tsv optionType=option1 optionValue=10'
}
},
{
@ -151,7 +115,7 @@ exports.testWithHelpers = function(options) {
}
},
exec: {
output: 'Exec: tsv optionType=number, optionValue=10'
output: 'Exec: tsv optionType=option2 optionValue=10'
}
},
// Delegated remote types can't transfer value types so we only test for
@ -163,7 +127,7 @@ exports.testWithHelpers = function(options) {
args: { optionValue: { value: '10' } }
},
exec: {
output: 'Exec: tsv optionType=string, optionValue=10'
output: 'Exec: tsv optionType=option1 optionValue=10'
}
},
{
@ -173,7 +137,7 @@ exports.testWithHelpers = function(options) {
args: { optionValue: { value: 10 } }
},
exec: {
output: 'Exec: tsv optionType=number, optionValue=10'
output: 'Exec: tsv optionType=option2 optionValue=10'
}
}
]);
@ -228,7 +192,7 @@ exports.testExecText = function(options) {
}
},
exec: {
output: 'Exec: tsr text=fred bloggs'
output: 'Exec: tsr text=fred\\ bloggs'
}
},
{
@ -253,7 +217,7 @@ exports.testExecText = function(options) {
}
},
exec: {
output: 'Exec: tsr text=fred bloggs'
output: 'Exec: tsr text=fred\\ bloggs'
}
},
{
@ -278,7 +242,7 @@ exports.testExecText = function(options) {
}
},
exec: {
output: 'Exec: tsr text=fred bloggs'
output: 'Exec: tsr text=fred\\ bloggs'
}
}
]);
@ -403,7 +367,6 @@ exports.testExecScript = function(options) {
args: {
command: { name: 'tsj' },
javascript: {
value: '1 + 1',
arg: ' { 1 + 1 }',
status: 'VALID',
message: ''
@ -418,12 +381,9 @@ exports.testExecScript = function(options) {
};
exports.testExecNode = function(options) {
var origDoc = nodetype.getDocument();
nodetype.setDocument(mockDoc);
return helpers.audit(options, [
{
skipIf: options.isNoDom,
skipIf: options.isRemote,
setup: 'tse :root',
check: {
input: 'tse :root',
@ -437,19 +397,16 @@ exports.testExecNode = function(options) {
args: {
command: { name: 'tse' },
node: {
value: mockBody,
arg: ' :root',
status: 'VALID',
message: ''
},
nodes: {
value: mockEmptyNodeList,
arg: '',
status: 'VALID',
message: ''
},
nodes2: {
value: mockEmptyNodeList,
arg: '',
status: 'VALID',
message: ''
@ -459,8 +416,10 @@ exports.testExecNode = function(options) {
exec: {
output: /^Exec: tse/
},
post: function() {
nodetype.setDocument(origDoc);
post: function(output) {
assert.is(output.data.args.node, ':root', 'node should be :root');
assert.is(output.data.args.nodes, 'Error', 'nodes should be Error');
assert.is(output.data.args.nodes2, 'Error', 'nodes2 should be Error');
}
}
]);
@ -552,7 +511,7 @@ exports.testExecArray = function(options) {
}
},
exec: {
output: 'Exec: tselarr num=1, arr='
output: 'Exec: tselarr num=1 arr='
}
},
{
@ -573,7 +532,7 @@ exports.testExecArray = function(options) {
}
},
exec: {
output: 'Exec: tselarr num=1, arr=a'
output: 'Exec: tselarr num=1 arr=a'
}
},
{
@ -594,7 +553,7 @@ exports.testExecArray = function(options) {
}
},
exec: {
output: 'Exec: tselarr num=1, arr=a,b'
output: 'Exec: tselarr num=1 arr=a b'
}
}
]);
@ -621,7 +580,7 @@ exports.testExecMultiple = function(options) {
}
},
exec: {
output: 'Exec: tsm abc=a, txt=10, num=10'
output: 'Exec: tsm abc=a txt=10 num=10'
}
}
]);
@ -651,9 +610,47 @@ exports.testExecDefaults = function(options) {
}
},
exec: {
output: 'Exec: tsg solo=aaa, txt1=null, bool=false, txt2=d, num=42'
output: 'Exec: tsg solo=aaa txt1= bool=false txt2=d num=42'
}
}
]);
};
exports.testNested = function(options) {
var commands = options.requisition.system.commands;
commands.add({
name: 'nestorama',
exec: function(args, context) {
return context.updateExec('tsb').then(function(tsbOutput) {
return context.updateExec('tsu 6').then(function(tsuOutput) {
return JSON.stringify({
tsb: tsbOutput.data,
tsu: tsuOutput.data
});
});
});
}
});
return helpers.audit(options, [
{
setup: 'nestorama',
exec: {
output:
'{' +
'"tsb":{' +
'"name":"tsb",' +
'"args":{"toggle":"false"}' +
'},' +
'"tsu":{' +
'"name":"tsu",' +
'"args":{"num":"6"}' +
'}' +
'}'
},
post: function() {
commands.remove('nestorama');
}
}
]);
};

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFail.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_fail.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testBasic = function(options) {

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFile.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_file.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
var local = false;
@ -47,10 +32,7 @@ var local = false;
exports.testBasic = function(options) {
return helpers.audit(options, [
{
// These tests require us to be using node directly or to be in
// PhantomJS connected to an execute enabled node server or to be in
// firefox.
skipRemainingIf: options.isPhantomjs || options.isFirefox,
skipRemainingIf: options.isFirefox, // No file implementation in Firefox
setup: 'tsfile open /',
check: {
input: 'tsfile open /',

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFileparser.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_fileparser.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
var fileparser = require('gcli/util/fileparser');

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFilesystem.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_filesystem.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');
var filesystem = require('gcli/util/filesystem');

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFocus.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_focus.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testBasic = function(options) {

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testHistory.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_history.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
var History = require('gcli/ui/history').History;

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testIncomplete.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_incomplete.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testInputter.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_inputter.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
var KeyEvent = require('gcli/util/util').KeyEvent;
@ -89,7 +74,7 @@ exports.testOutput = function(options) {
var ev1 = { keyCode: KeyEvent.DOM_VK_RETURN };
return terminal.handleKeyUp(ev1).then(function() {
assert.ok(latestEvent != null, 'events this test');
assert.is(latestData, 'Exec: tss ', 'last command is tss');
assert.is(latestData.name, 'tss', 'last command is tss');
assert.is(terminal.getInputState().typed,
'',

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testIntro.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_intro.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testIntroStatus = function(options) {
@ -67,7 +52,6 @@ exports.testIntroStatus = function(options) {
},
{
setup: 'intro',
skipIf: options.isNoDom,
check: {
typed: 'intro',
markup: 'VVVVV',

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

@ -15,73 +15,55 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testJs.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_js.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');
var javascript = require('gcli/types/javascript');
var tempWindow;
exports.setup = function(options) {
if (options.isNoDom) {
if (jsTestDisallowed(options)) {
return;
}
tempWindow = javascript.getGlobalObject();
Object.defineProperty(options.window, 'donteval', {
// Check that we're not trespassing on 'donteval'
var win = options.requisition.environment.window;
Object.defineProperty(win, 'donteval', {
get: function() {
assert.ok(false, 'donteval should not be used');
console.trace();
return { cant: '', touch: '', 'this': '' };
},
enumerable: true,
configurable : true
configurable: true
});
javascript.setGlobalObject(options.window);
};
exports.shutdown = function(options) {
if (options.isNoDom) {
if (jsTestDisallowed(options)) {
return;
}
javascript.setGlobalObject(tempWindow);
tempWindow = undefined;
delete options.window.donteval;
delete options.requisition.environment.window.donteval;
};
function jsTestAllowed(options) {
return options.isRemote || options.isNoDom ||
function jsTestDisallowed(options) {
return options.isRemote || // Altering the environment (which isn't remoted)
options.isNode ||
options.requisition.system.commands.get('{') == null;
}
exports.testBasic = function(options) {
return helpers.audit(options, [
{
skipRemainingIf: jsTestAllowed,
skipRemainingIf: jsTestDisallowed,
setup: '{',
check: {
input: '{',
@ -236,7 +218,7 @@ exports.testBasic = function(options) {
exports.testDocument = function(options) {
return helpers.audit(options, [
{
skipRemainingIf: jsTestAllowed,
skipRemainingIf: jsTestDisallowed,
setup: '{ docu',
check: {
input: '{ docu',
@ -315,7 +297,8 @@ exports.testDocument = function(options) {
command: { name: '{' },
javascript: {
value: 'document.title',
arg: '{ document.title ',
// arg: '{ document.title ',
// Node/JSDom gets this wrong and omits the trailing space. Why?
status: 'VALID',
message: ''
}
@ -348,14 +331,9 @@ exports.testDocument = function(options) {
};
exports.testDonteval = function(options) {
if (!options.isNoDom) {
// nodom causes an eval here, maybe that's node/v8?
assert.ok('donteval' in options.window, 'donteval exists');
}
return helpers.audit(options, [
{
skipRemainingIf: jsTestAllowed,
skipRemainingIf: true, // Commented out until we fix non-enumerable props
setup: '{ don',
check: {
input: '{ don',
@ -476,7 +454,7 @@ exports.testDonteval = function(options) {
exports.testExec = function(options) {
return helpers.audit(options, [
{
skipRemainingIf: jsTestAllowed,
skipRemainingIf: jsTestDisallowed,
setup: '{ 1+1',
check: {
input: '{ 1+1',

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

@ -15,46 +15,19 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard1.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_keyboard1.js");
}
// <INJECTED SOURCE:END>
var javascript = require('gcli/types/javascript');
// var helpers = require('./helpers');
var tempWindow;
exports.setup = function(options) {
tempWindow = javascript.getGlobalObject();
javascript.setGlobalObject(options.window);
};
exports.shutdown = function(options) {
javascript.setGlobalObject(tempWindow);
tempWindow = undefined;
};
exports.testSimple = function(options) {
return helpers.audit(options, [
{
@ -75,16 +48,12 @@ exports.testSimple = function(options) {
exports.testScript = function(options) {
return helpers.audit(options, [
{
skipIf: function commandJsMissing() {
return options.requisition.system.commands.get('{') == null;
},
skipRemainingIf: options.isRemote ||
options.requisition.system.commands.get('{') == null,
setup: '{ wind<TAB>',
check: { input: '{ window' }
},
{
skipIf: function commandJsMissing() {
return options.requisition.system.commands.get('{') == null;
},
setup: '{ window.docum<TAB>',
check: { input: '{ window.document' }
}
@ -94,9 +63,8 @@ exports.testScript = function(options) {
exports.testJsdom = function(options) {
return helpers.audit(options, [
{
skipIf: function jsDomOrCommandJsMissing() {
return options.requisition.system.commands.get('{') == null;
},
skipIf: options.isRemote ||
options.requisition.system.commands.get('{') == null,
setup: '{ window.document.titl<TAB>',
check: { input: '{ window.document.title ' }
}

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard2.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_keyboard2.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testIncr = function(options) {

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard3.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_keyboard3.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testDecr = function(options) {

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard4.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_keyboard4.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testIncrFloat = function(options) {

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard5.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_keyboard5.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testCompleteDown = function(options) {

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard6.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_keyboard6.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testCompleteUp = function(options) {

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testMenu.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_menu.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testOptions = function(options) {

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

@ -15,49 +15,22 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testNode.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_node.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');
var nodetype = require('gcli/types/node');
exports.setup = function(options) {
if (options.window) {
nodetype.setDocument(options.window.document);
}
};
exports.shutdown = function(options) {
nodetype.unsetDocument();
};
exports.testNode = function(options) {
return helpers.audit(options, [
{
skipRemainingIf: options.isNoDom,
setup: 'tse ',
check: {
input: 'tse ',
@ -165,11 +138,8 @@ exports.testNode = function(options) {
};
exports.testNodeDom = function(options) {
var requisition = options.requisition;
return helpers.audit(options, [
{
skipRemainingIf: options.isNoDom,
setup: 'tse :root',
check: {
input: 'tse :root',
@ -202,10 +172,12 @@ exports.testNodeDom = function(options) {
nodes2: { status: 'VALID' }
}
},
post: function() {
assert.is(requisition.getAssignment('node').value.tagName,
'HTML',
'root id');
exec: {
},
post: function(output) {
if (!options.isRemote) {
assert.is(output.args.node.tagName, 'HTML', ':root tagName');
}
}
},
{
@ -234,11 +206,8 @@ exports.testNodeDom = function(options) {
};
exports.testNodes = function(options) {
var requisition = options.requisition;
return helpers.audit(options, [
{
skipRemainingIf: options.isNoDom,
setup: 'tse :root --nodes *',
check: {
input: 'tse :root --nodes *',
@ -253,10 +222,18 @@ exports.testNodes = function(options) {
nodes2: { status: 'VALID' }
}
},
post: function() {
assert.is(requisition.getAssignment('node').value.tagName,
'HTML',
'#gcli-input id');
exec: {
},
post: function(output) {
if (!options.isRemote) {
assert.is(output.args.node.tagName, 'HTML', ':root tagName');
assert.ok(output.args.nodes.length > 3, 'nodes length');
assert.is(output.args.nodes2.length, 0, 'nodes2 length');
}
assert.is(output.data.args.node, ':root', 'node data');
assert.is(output.data.args.nodes, '*', 'nodes data');
assert.is(output.data.args.nodes2, 'Error', 'nodes2 data');
}
},
{
@ -275,10 +252,18 @@ exports.testNodes = function(options) {
nodes2: { arg: ' --nodes2 div', status: 'VALID' }
}
},
post: function() {
assert.is(requisition.getAssignment('node').value.tagName,
'HTML',
'root id');
exec: {
},
post: function(output) {
if (!options.isRemote) {
assert.is(output.args.node.tagName, 'HTML', ':root tagName');
assert.is(output.args.nodes.length, 0, 'nodes length');
assert.is(output.args.nodes2.item(0).tagName, 'DIV', 'div tagName');
}
assert.is(output.data.args.node, ':root', 'node data');
assert.is(output.data.args.nodes, 'Error', 'nodes data');
assert.is(output.data.args.nodes2, 'div', 'nodes2 data');
}
},
{
@ -305,13 +290,6 @@ exports.testNodes = function(options) {
},
nodes2: { arg: '', status: 'VALID', message: '' }
}
},
post: function() {
/*
assert.is(requisition.getAssignment('nodes2').value.constructor.name,
'NodeList',
'#gcli-input id');
*/
}
},
{
@ -333,16 +311,6 @@ exports.testNodes = function(options) {
nodes: { arg: '', status: 'VALID', message: '' },
nodes2: { arg: ' --nodes2 ffff', status: 'VALID', message: '' }
}
},
post: function() {
/*
assert.is(requisition.getAssignment('nodes').value.constructor.name,
'NodeList',
'#gcli-input id');
assert.is(requisition.getAssignment('nodes2').value.constructor.name,
'NodeList',
'#gcli-input id');
*/
}
},
]);

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testPref1.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_pref1.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testPrefShowStatus = function(options) {
@ -67,7 +52,7 @@ exports.testPrefShowStatus = function(options) {
setup: 'pref show ',
check: {
typed: 'pref show ',
hints: 'allowSet',
hints: 'eagerHelper',
markup: 'VVVVVVVVVV',
status: 'ERROR'
}
@ -144,7 +129,7 @@ exports.testPrefSetStatus = function(options) {
setup: 'pref set ',
check: {
typed: 'pref set ',
hints: 'allowSet <value>',
hints: 'eagerHelper <value>',
markup: 'VVVVVVVVV',
status: 'ERROR'
}
@ -159,6 +144,7 @@ exports.testPrefSetStatus = function(options) {
}
},
{
skipIf: options.isRemote,
setup: 'pref set tempTBool 4',
check: {
typed: 'pref set tempTBool 4',

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testPref2.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_pref2.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');
var mockSettings = require('./mockSettings');
@ -55,10 +40,6 @@ exports.testPrefExec = function(options) {
return;
}
var allowSet = settings.getSetting('allowSet');
var initialAllowSet = allowSet.value;
allowSet.value = false;
assert.is(mockSettings.tempNumber.value, 42, 'set to 42');
return helpers.audit(options, [
@ -73,7 +54,6 @@ exports.testPrefExec = function(options) {
}
},
{
skipRemainingIf: options.isNoDom,
setup: 'pref set tempNumber 4',
check: {
input: 'pref set tempNumber 4',
@ -98,16 +78,6 @@ exports.testPrefExec = function(options) {
}
}
},
exec: {
output: [ /void your warranty/, /I promise/ ]
},
post: function() {
assert.is(mockSettings.tempNumber.value, 42, 'still set to 42');
allowSet.value = true;
}
},
{
setup: 'pref set tempNumber 4',
exec: {
output: ''
},
@ -128,8 +98,6 @@ exports.testPrefExec = function(options) {
},
post: function() {
assert.is(mockSettings.tempNumber.value, 42, 'reset to 42');
allowSet.value = initialAllowSet;
}
},
{

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testRemoteWs.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_remotews.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');
@ -83,8 +68,8 @@ exports.testRemoteWebsocket = function(options) {
check: {
args: {
prefix: {
value: function(connection) {
assert.is(connection.prefix, 'remote', 'disconnecting remote');
value: function(front) {
assert.is(front.prefix, 'remote', 'disconnecting remote');
}
}
}
@ -112,8 +97,8 @@ exports.testRemoteWebsocket = function(options) {
check: {
args: {
prefix: {
value: function(connection) {
assert.is(connection.prefix, 'remote', 'disconnecting remote');
value: function(front) {
assert.is(front.prefix, 'remote', 'disconnecting remote');
}
}
}
@ -466,8 +451,8 @@ exports.testRemoteWebsocket = function(options) {
unassigned: [ ],
args: {
prefix: {
value: function(connection) {
assert.is(connection.prefix, 'remote', 'disconnecting remote');
value: function(front) {
assert.is(front.prefix, 'remote', 'disconnecting remote');
},
arg: ' remote',
status: 'VALID',

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testRemoteXhr.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_remotexhr.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');
@ -83,8 +68,8 @@ exports.testRemoteXhr = function(options) {
check: {
args: {
prefix: {
value: function(connection) {
assert.is(connection.prefix, 'remote', 'disconnecting remote');
value: function(front) {
assert.is(front.prefix, 'remote', 'disconnecting remote');
}
}
}
@ -112,8 +97,8 @@ exports.testRemoteXhr = function(options) {
check: {
args: {
prefix: {
value: function(connection) {
assert.is(connection.prefix, 'remote', 'disconnecting remote');
value: function(front) {
assert.is(front.prefix, 'remote', 'disconnecting remote');
}
}
}
@ -466,8 +451,8 @@ exports.testRemoteXhr = function(options) {
unassigned: [ ],
args: {
prefix: {
value: function(connection) {
assert.is(connection.prefix, 'remote', 'disconnecting remote');
value: function(front) {
assert.is(front.prefix, 'remote', 'disconnecting remote');
},
arg: ' remote',
status: 'VALID',

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

@ -15,31 +15,17 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testResource.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_resource.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
// var assert = require('../testharness/assert');
var Promise = require('gcli/util/promise').Promise;
@ -47,84 +33,85 @@ var util = require('gcli/util/util');
var resource = require('gcli/types/resource');
var Status = require('gcli/types/types').Status;
var tempDocument;
exports.setup = function(options) {
tempDocument = resource.getDocument();
if (options.window) {
resource.setDocument(options.window.document);
}
};
exports.shutdown = function(options) {
resource.setDocument(tempDocument);
tempDocument = undefined;
exports.testCommand = function(options) {
return helpers.audit(options, [
{
setup: 'tsres ',
check: {
predictionsContains: [ 'inline-css' ],
}
}
]);
};
exports.testAllPredictions1 = function(options) {
if (options.isFirefox || options.isNoDom) {
assert.log('Skipping checks due to firefox document.stylsheets support.');
if (options.isRemote) {
assert.log('Can\'t directly test remote types locally.');
return;
}
var context = options.requisition.conversionContext;
var resource = options.requisition.system.types.createType('resource');
return resource.getLookup().then(function(opts) {
return resource.getLookup(context).then(function(opts) {
assert.ok(opts.length > 1, 'have all resources');
return util.promiseEach(opts, function(prediction) {
return checkPrediction(resource, prediction);
return checkPrediction(resource, prediction, context);
});
});
};
exports.testScriptPredictions = function(options) {
if (options.isFirefox || options.isNoDom) {
assert.log('Skipping checks due to firefox document.stylsheets support.');
if (options.isRemote || options.isNode) {
assert.log('Can\'t directly test remote types locally.');
return;
}
var context = options.requisition.conversionContext;
var types = options.requisition.system.types;
var resource = types.createType({ name: 'resource', include: 'text/javascript' });
return resource.getLookup().then(function(opts) {
return resource.getLookup(context).then(function(opts) {
assert.ok(opts.length > 1, 'have js resources');
return util.promiseEach(opts, function(prediction) {
return checkPrediction(resource, prediction);
return checkPrediction(resource, prediction, context);
});
});
};
exports.testStylePredictions = function(options) {
if (options.isFirefox || options.isNoDom) {
assert.log('Skipping checks due to firefox document.stylsheets support.');
if (options.isRemote) {
assert.log('Can\'t directly test remote types locally.');
return;
}
var context = options.requisition.conversionContext;
var types = options.requisition.system.types;
var resource = types.createType({ name: 'resource', include: 'text/css' });
return resource.getLookup().then(function(opts) {
return resource.getLookup(context).then(function(opts) {
assert.ok(opts.length >= 1, 'have css resources');
return util.promiseEach(opts, function(prediction) {
return checkPrediction(resource, prediction);
return checkPrediction(resource, prediction, context);
});
});
};
exports.testAllPredictions2 = function(options) {
if (options.isNoDom) {
assert.log('Skipping checks due to nodom document.stylsheets support.');
if (options.isRemote) {
assert.log('Can\'t directly test remote types locally.');
return;
}
var context = options.requisition.conversionContext;
var types = options.requisition.system.types;
var scriptRes = types.createType({ name: 'resource', include: 'text/javascript' });
return scriptRes.getLookup().then(function(scriptOptions) {
return scriptRes.getLookup(context).then(function(scriptOptions) {
var styleRes = types.createType({ name: 'resource', include: 'text/css' });
return styleRes.getLookup().then(function(styleOptions) {
return styleRes.getLookup(context).then(function(styleOptions) {
var allRes = types.createType({ name: 'resource' });
return allRes.getLookup().then(function(allOptions) {
return allRes.getLookup(context).then(function(allOptions) {
assert.is(scriptOptions.length + styleOptions.length,
allOptions.length,
'split');
@ -134,27 +121,26 @@ exports.testAllPredictions2 = function(options) {
};
exports.testAllPredictions3 = function(options) {
if (options.isNoDom) {
assert.log('Skipping checks due to nodom document.stylsheets support.');
if (options.isRemote) {
assert.log('Can\'t directly test remote types locally.');
return;
}
var context = options.requisition.conversionContext;
var types = options.requisition.system.types;
var res1 = types.createType({ name: 'resource' });
return res1.getLookup().then(function(options1) {
return res1.getLookup(context).then(function(options1) {
var res2 = types.createType('resource');
return res2.getLookup().then(function(options2) {
return res2.getLookup(context).then(function(options2) {
assert.is(options1.length, options2.length, 'type spec');
});
});
};
function checkPrediction(res, prediction) {
function checkPrediction(res, prediction, context) {
var name = prediction.name;
var value = prediction.value;
// resources don't need context so cheat and pass in null
var context = null;
return res.parseString(name, context).then(function(conversion) {
assert.is(conversion.getStatus(), Status.VALID, 'status VALID for ' + name);
assert.is(conversion.value, value, 'value for ' + name);

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testShort.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_short.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testBasic = function(options) {

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

@ -14,31 +14,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testSpell.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_spell.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
var spell = require('gcli/util/spell');

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testSplit.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_split.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
var cli = require('gcli/cli');

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testString.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_string.js");
}
// <INJECTED SOURCE:END>
// var helpers = require('./helpers');
exports.testNewLine = function(options) {

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testTokenize.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_tokenize.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
var cli = require('gcli/cli');

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

@ -15,40 +15,20 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testTooltip.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_tooltip.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');
exports.testActivate = function(options) {
if (!options.display) {
assert.log('No display. Skipping activate tests');
return;
}
return helpers.audit(options, [
{
setup: ' ',

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

@ -15,49 +15,25 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testTypes.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_types.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
var util = require('gcli/util/util');
var Promise = require('gcli/util/promise').Promise;
var nodetype = require('gcli/types/node');
exports.setup = function(options) {
if (options.window) {
nodetype.setDocument(options.window.document);
}
};
exports.shutdown = function(options) {
nodetype.unsetDocument();
};
function forEachType(options, typeSpec, callback) {
function forEachType(options, templateTypeSpec, callback) {
var types = options.requisition.system.types;
return util.promiseEach(types.getTypeNames(), function(name) {
var typeSpec = {};
util.copyProperties(templateTypeSpec, typeSpec);
typeSpec.name = name;
typeSpec.requisition = options.requisition;
@ -79,29 +55,19 @@ function forEachType(options, typeSpec, callback) {
else if (name === 'union') {
typeSpec.alternatives = [{ name: 'string' }];
}
else if (options.isRemote) {
if (name === 'node' || name === 'nodelist') {
return;
}
}
var type = types.createType(typeSpec);
var reply = callback(type);
return Promise.resolve(reply).then(function(value) {
// Clean up
delete typeSpec.name;
delete typeSpec.requisition;
delete typeSpec.data;
delete typeSpec.delegateType;
delete typeSpec.subtype;
delete typeSpec.alternatives;
return value;
});
return Promise.resolve(reply);
});
}
exports.testDefault = function(options) {
if (options.isNoDom) {
assert.log('Skipping tests due to issues with resource type.');
return;
}
return forEachType(options, {}, function(type) {
var context = options.requisition.executionContext;
var blank = type.getBlank(context).value;

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

@ -15,31 +15,16 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testUnion.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_union.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');
@ -126,7 +111,7 @@ exports.testDefault = function(options) {
}
},
{
skipIf: options.isPhantomjs, // Phantom goes weird with predictions
skipIf: options.isPhantomjs, // PhantomJS gets predictions wrong
setup: 'unionc1 5',
check: {
input: 'unionc1 5',
@ -160,7 +145,7 @@ exports.testDefault = function(options) {
}
},
{
skipRemainingIf: options.isPhantomjs,
skipIf: options.isPhantomjs, // PhantomJS URL type is broken
setup: 'unionc2 on',
check: {
input: 'unionc2 on',

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

@ -15,38 +15,23 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var exports = {};
var TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testUrl.js</p>";
const exports = {};
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
gcli.addItems(mockCommands.items);
yield helpers.runTests(options, exports);
gcli.removeItems(mockCommands.items);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
helpers.runTestModule(exports, "browser_gcli_url.js");
}
// <INJECTED SOURCE:END>
// var assert = require('../testharness/assert');
// var helpers = require('./helpers');
exports.testDefault = function(options) {
return helpers.audit(options, [
{
skipRemainingIf: options.isPhantomjs,
skipRemainingIf: options.isPhantomjs, // PhantomJS URL type is broken
setup: 'urlc',
check: {
input: 'urlc',

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

@ -18,7 +18,7 @@
// A copy of this code exists in firefox mochitests. They should be kept
// in sync. Hence the exports synonym for non AMD contexts.
var { helpers, gcli, assert } = (function() {
var { helpers, assert } = (function() {
var helpers = {};
@ -30,23 +30,24 @@ var util = require('gcli/util/util');
var Promise = require('gcli/util/promise').Promise;
var cli = require('gcli/cli');
var KeyEvent = require('gcli/util/util').KeyEvent;
var gcli = require('gcli/index');
const { GcliFront } = require("devtools/server/actors/gcli");
/**
* See notes in helpers.checkOptions()
*/
var createFFDisplayAutomator = function(display) {
var createDeveloperToolbarAutomator = function(toolbar) {
var automator = {
setInput: function(typed) {
return display.inputter.setInput(typed);
return toolbar.inputter.setInput(typed);
},
setCursor: function(cursor) {
return display.inputter.setCursor(cursor);
return toolbar.inputter.setCursor(cursor);
},
focus: function() {
return display.inputter.focus();
return toolbar.inputter.focus();
},
fakeKey: function(keyCode) {
@ -56,36 +57,36 @@ var createFFDisplayAutomator = function(display) {
timeStamp: new Date().getTime()
};
display.inputter.onKeyDown(fakeEvent);
toolbar.inputter.onKeyDown(fakeEvent);
if (keyCode === KeyEvent.DOM_VK_BACK_SPACE) {
var input = display.inputter.element;
var input = toolbar.inputter.element;
input.value = input.value.slice(0, -1);
}
return display.inputter.handleKeyUp(fakeEvent);
return toolbar.inputter.handleKeyUp(fakeEvent);
},
getInputState: function() {
return display.inputter.getInputState();
return toolbar.inputter.getInputState();
},
getCompleterTemplateData: function() {
return display.completer._getCompleterTemplateData();
return toolbar.completer._getCompleterTemplateData();
},
getErrorMessage: function() {
return display.tooltip.errorEle.textContent;
return toolbar.tooltip.errorEle.textContent;
}
};
Object.defineProperty(automator, 'focusManager', {
get: function() { return display.focusManager; },
get: function() { return toolbar.focusManager; },
enumerable: true
});
Object.defineProperty(automator, 'field', {
get: function() { return display.tooltip.field; },
get: function() { return toolbar.tooltip.field; },
enumerable: true
});
@ -223,9 +224,9 @@ helpers.openToolbar = function(options) {
options.chromeWindow = options.chromeWindow || window;
return options.chromeWindow.DeveloperToolbar.show(true).then(function() {
var display = options.chromeWindow.DeveloperToolbar.display;
options.automator = createFFDisplayAutomator(display);
options.requisition = display.requisition;
var toolbar = options.chromeWindow.DeveloperToolbar;
options.automator = createDeveloperToolbarAutomator(toolbar);
options.requisition = toolbar.requisition;
return options;
});
};
@ -331,17 +332,17 @@ helpers.promiseify = function(functionWithLastParamCallback, scope) {
* Warning: For use with Firefox Mochitests only.
*
* As addTab, but that also opens the developer toolbar. In addition a new
* 'automator' property is added to the options object with the display from GCLI
* in the developer toolbar
* 'automator' property is added to the options object which uses the
* developer toolbar
*/
helpers.addTabWithToolbar = function(url, callback, options) {
return helpers.addTab(url, function(innerOptions) {
var win = innerOptions.chromeWindow;
return win.DeveloperToolbar.show(true).then(function() {
var display = win.DeveloperToolbar.display;
innerOptions.automator = createFFDisplayAutomator(display);
innerOptions.requisition = display.requisition;
var toolbar = win.DeveloperToolbar;
innerOptions.automator = createDeveloperToolbarAutomator(toolbar);
innerOptions.requisition = toolbar.requisition;
var reply = callback.call(null, innerOptions);
@ -376,7 +377,7 @@ helpers.runTests = function(options, tests) {
var recover = function(error) {
ok(false, error);
console.error(error);
console.error(error, error.stack);
};
info("SETUP");
@ -410,6 +411,87 @@ helpers.runTests = function(options, tests) {
}, recover);
};
const MOCK_COMMANDS_URI = "chrome://mochitests/content/browser/browser/devtools/commandline/test/mockCommands.js";
const defer = function() {
const deferred = { };
deferred.promise = new Promise(function(resolve, reject) {
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
};
/**
* This does several actions associated with running a GCLI test in mochitest
* 1. Create a new tab containing basic markup for GCLI tests
* 2. Open the developer toolbar
* 3. Register the mock commands with the server process
* 4. Wait for the proxy commands to be auto-regitstered with the client
* 5. Register the mock converters with the client process
* 6. Run all the tests
* 7. Tear down all the setup
*/
helpers.runTestModule = function(exports, name) {
return Task.spawn(function*() {
const uri = "data:text/html;charset=utf-8," +
"<style>div{color:red;}</style>" +
"<div id='gcli-root'>" + name + "</div>";
const options = yield helpers.openTab(uri);
options.isRemote = true;
yield helpers.openToolbar(options);
const system = options.requisition.system;
// Register a one time listener with the local set of commands
const addedDeferred = defer();
const removedDeferred = defer();
let state = 'preAdd'; // Then 'postAdd' then 'postRemove'
system.commands.onCommandsChange.add(function(ev) {
if (system.commands.get('tsslow') != null) {
if (state === 'preAdd') {
addedDeferred.resolve();
state = 'postAdd';
}
}
else {
if (state === 'postAdd') {
removedDeferred.resolve();
state = 'postRemove';
}
}
});
// Send a message to add the commands to the content process
const front = yield GcliFront.create(options.target);
yield front._testOnly_addItemsByModule(MOCK_COMMANDS_URI);
// This will cause the local set of commands to be updated with the
// command proxies, wait for that to complete.
yield addedDeferred.promise;
// Now we need to add the converters to the local GCLI
const converters = mockCommands.items.filter(item => item.item === 'converter');
system.addItems(converters);
// Next run the tests
yield helpers.runTests(options, exports);
// Finally undo the mock commands and converters
system.removeItems(converters);
const removePromise = system.commands.onCommandsChange.once();
yield front._testOnly_removeItemsByModule(MOCK_COMMANDS_URI);
yield removedDeferred.promise;
// And close everything down
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
};
///////////////////////////////////////////////////////////////////////////////
/**
@ -759,15 +841,15 @@ helpers._check = function(options, name, checks) {
var outstanding = [];
var suffix = name ? ' (for \'' + name + '\')' : '';
if (!options.isNoDom && 'input' in checks) {
if (!options.isNode && 'input' in checks) {
assert.is(helpers._actual.input(options), checks.input, 'input' + suffix);
}
if (!options.isNoDom && 'cursor' in checks) {
if (!options.isNode && 'cursor' in checks) {
assert.is(helpers._actual.cursor(options), checks.cursor, 'cursor' + suffix);
}
if (!options.isNoDom && 'current' in checks) {
if (!options.isNode && 'current' in checks) {
assert.is(helpers._actual.current(options), checks.current, 'current' + suffix);
}
@ -775,18 +857,18 @@ helpers._check = function(options, name, checks) {
assert.is(helpers._actual.status(options), checks.status, 'status' + suffix);
}
if (!options.isNoDom && 'markup' in checks) {
if (!options.isNode && 'markup' in checks) {
assert.is(helpers._actual.markup(options), checks.markup, 'markup' + suffix);
}
if (!options.isNoDom && 'hints' in checks) {
if (!options.isNode && 'hints' in checks) {
var hintCheck = function(actualHints) {
assert.is(actualHints, checks.hints, 'hints' + suffix);
};
outstanding.push(helpers._actual.hints(options).then(hintCheck));
}
if (!options.isNoDom && 'predictions' in checks) {
if (!options.isNode && 'predictions' in checks) {
var predictionsCheck = function(actualPredictions) {
helpers.arrayIs(actualPredictions,
checks.predictions,
@ -795,12 +877,16 @@ helpers._check = function(options, name, checks) {
outstanding.push(helpers._actual.predictions(options).then(predictionsCheck));
}
if (!options.isNoDom && 'predictionsContains' in checks) {
if (!options.isNode && 'predictionsContains' in checks) {
var containsCheck = function(actualPredictions) {
checks.predictionsContains.forEach(function(prediction) {
var index = actualPredictions.indexOf(prediction);
assert.ok(index !== -1,
'predictionsContains:' + prediction + suffix);
if (index === -1) {
log('Actual predictions (' + actualPredictions.length + '): ' +
actualPredictions.join(', '));
}
});
};
outstanding.push(helpers._actual.predictions(options).then(containsCheck));
@ -813,26 +899,26 @@ helpers._check = function(options, name, checks) {
}
/* TODO: Fix this
if (!options.isNoDom && 'tooltipState' in checks) {
if (!options.isNode && 'tooltipState' in checks) {
assert.is(helpers._actual.tooltipState(options),
checks.tooltipState,
'tooltipState' + suffix);
}
*/
if (!options.isNoDom && 'outputState' in checks) {
if (!options.isNode && 'outputState' in checks) {
assert.is(helpers._actual.outputState(options),
checks.outputState,
'outputState' + suffix);
}
if (!options.isNoDom && 'options' in checks) {
if (!options.isNode && 'options' in checks) {
helpers.arrayIs(helpers._actual.options(options),
checks.options,
'options' + suffix);
}
if (!options.isNoDom && 'error' in checks) {
if (!options.isNode && 'error' in checks) {
assert.is(helpers._actual.message(options), checks.error, 'error' + suffix);
}
@ -894,7 +980,7 @@ helpers._check = function(options, name, checks) {
'arg.' + paramName + '.status' + suffix);
}
if (!options.isNoDom && 'message' in check) {
if (!options.isNode && 'message' in check) {
if (typeof check.message.test === 'function') {
assert.ok(check.message.test(assignment.message),
'arg.' + paramName + '.message' + suffix);
@ -952,12 +1038,12 @@ helpers._exec = function(options, name, expected) {
var context = requisition.conversionContext;
var convertPromise;
if (options.isNoDom) {
if (options.isNode) {
convertPromise = output.convert('string', context);
}
else {
convertPromise = output.convert('dom', context).then(function(node) {
return node.textContent.trim();
return (node == null) ? '' : node.textContent.trim();
});
}
@ -1171,9 +1257,8 @@ helpers.audit = function(options, audits) {
'';
assert.log('Skipped ' + name + ' ' + skipReason);
// Tests need at least one pass, fail or todo. Let's create a dummy pass
// in case there are none.
ok(true, "Each test requires at least one pass, fail or todo so here is a pass.");
// Tests need at least one pass, fail or todo. Create a dummy pass
assert.ok(true, 'Each test requires at least one pass, fail or todo');
return Promise.resolve(undefined);
}
@ -1270,5 +1355,5 @@ function log(message) {
}
}
return { helpers: helpers, gcli: gcli, assert: assert };
return { helpers: helpers, assert: assert };
})();

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

@ -15,16 +15,21 @@
*/
'use strict';
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
// <INJECTED SOURCE:END>
// PLEASE TALK TO SOMEONE IN DEVELOPER TOOLS BEFORE EDITING IT
var Promise = require('gcli/util/promise').Promise;
var mockCommands = {};
var mockCommands;
if (typeof exports !== 'undefined') {
// If we're being loaded via require();
mockCommands = exports;
}
else {
// If we're being loaded via loadScript in mochitest
mockCommands = {};
}
// We use an alias for exports here because this module is used in Firefox
// mochitests where we don't have define/require
@ -41,32 +46,70 @@ mockCommands.shutdown = function(requisition) {
};
function createExec(name) {
return function(args, executionContext) {
var argsOut = Object.keys(args).map(function(key) {
return key + '=' + args[key];
}).join(', ');
return 'Exec: ' + name + ' ' + argsOut;
return function(args, context) {
var promises = [];
Object.keys(args).map(function(argName) {
var value = args[argName];
var type = this.getParameterByName(argName).type;
var promise = Promise.resolve(type.stringify(value, context));
promises.push(promise.then(function(str) {
return { name: argName, value: str };
}.bind(this)));
}.bind(this));
return Promise.all(promises).then(function(data) {
var argValues = {};
data.forEach(function(entry) { argValues[entry.name] = entry.value; });
return context.typedData('testCommandOutput', {
name: name,
args: argValues
});
}.bind(this));
};
}
mockCommands.items = [
{
item: 'converter',
from: 'json',
to: 'string',
exec: function(json, context) {
return JSON.stringify(json, null, ' ');
from: 'testCommandOutput',
to: 'dom',
exec: function(testCommandOutput, context) {
var view = context.createView({
data: testCommandOutput,
html: '' +
'<table>' +
'<thead>' +
'<tr>' +
'<th colspan="3">Exec: ${name}</th>' +
'</tr>' +
'</thead>' +
'<tbody>' +
'<tr foreach="key in ${args}">' +
'<td> ${key}</td>' +
'<td>=</td>' +
'<td>${args[key]}</td>' +
'</tr>' +
'</tbody>' +
'</table>',
options: {
allowEval: true
}
});
return view.toDom(context.document);
}
},
{
item: 'converter',
from: 'json',
to: 'view',
exec: function(json, context) {
var html = JSON.stringify(json, null, '&#160;').replace(/\n/g, '<br/>');
return {
html: '<pre>' + html + '</pre>'
};
from: 'testCommandOutput',
to: 'string',
exec: function(testCommandOutput, context) {
var argsOut = Object.keys(testCommandOutput.args).map(function(key) {
return key + '=' + testCommandOutput.args[key];
}).join(' ');
return 'Exec: ' + testCommandOutput.name + ' ' + argsOut;
}
},
{
@ -508,7 +551,7 @@ mockCommands.items = [
exec: function(args, context) {
if (args.method === 'reject') {
return new Promise(function(resolve, reject) {
setTimeout(function() {
context.environment.window.setTimeout(function() {
reject('rejected promise');
}, 10);
});
@ -516,7 +559,7 @@ mockCommands.items = [
if (args.method === 'rejecttyped') {
return new Promise(function(resolve, reject) {
setTimeout(function() {
context.environment.window.setTimeout(function() {
reject(context.typedData('number', 54));
}, 10);
});
@ -524,7 +567,7 @@ mockCommands.items = [
if (args.method === 'throwinpromise') {
return new Promise(function(resolve, reject) {
setTimeout(function() {
context.environment.window.setTimeout(function() {
resolve('should be lost');
}, 10);
}).then(function() {
@ -655,7 +698,7 @@ mockCommands.items = [
name: 'selection',
data: function(context) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
context.environment.window.setTimeout(function() {
resolve([
'Shalom', 'Namasté', 'Hallo', 'Dydd-da',
'Chào', 'Hej', 'Saluton', 'Sawubona'
@ -738,5 +781,16 @@ mockCommands.items = [
exec: function(args, context) {
return args;
}
},
{
item: 'command',
name: 'tsres',
params: [
{
name: 'resource',
type: 'resource'
}
],
exec: createExec('tsres'),
}
];

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

@ -5,7 +5,7 @@
"use strict";
const { Cc, Ci, Cu } = require("chrome");
const gcli = require("gcli/index");
const l10n = require("gcli/l10n");
loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
@ -67,8 +67,8 @@ function getAllSources(dbg) {
*/
exports.items.push({
name: "break",
description: gcli.lookup("breakDesc"),
manual: gcli.lookup("breakManual")
description: l10n.lookup("breakDesc"),
manual: l10n.lookup("breakManual")
});
/**
@ -76,7 +76,9 @@ exports.items.push({
*/
exports.items.push({
name: "break list",
description: gcli.lookup("breaklistDesc"),
item: "command",
runAt: "client",
description: l10n.lookup("breaklistDesc"),
returnType: "breakpoints",
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger", { ensureOpened: true });
@ -102,7 +104,7 @@ exports.items.push({
} else {
return context.createView({
html: "<p>${message}</p>",
data: { message: gcli.lookup("breaklistNone") }
data: { message: l10n.lookup("breaklistNone") }
});
}
}
@ -126,7 +128,7 @@ var breakListHtml = "" +
" data-command='break del ${breakpoint.label}'" +
" onclick='${onclick}'" +
" ondblclick='${ondblclick}'>" +
" " + gcli.lookup("breaklistOutRemove") + "</span>" +
" " + l10n.lookup("breaklistOutRemove") + "</span>" +
" </td>" +
" </tr>" +
" </tbody>" +
@ -141,16 +143,18 @@ var MAX_LABEL_LENGTH = 20;
*/
exports.items.push({
name: "break add",
description: gcli.lookup("breakaddDesc"),
manual: gcli.lookup("breakaddManual")
description: l10n.lookup("breakaddDesc"),
manual: l10n.lookup("breakaddManual")
});
/**
* 'break add line' command
*/
exports.items.push({
item: "command",
runAt: "client",
name: "break add line",
description: gcli.lookup("breakaddlineDesc"),
description: l10n.lookup("breakaddlineDesc"),
params: [
{
name: "file",
@ -160,19 +164,19 @@ exports.items.push({
return getAllSources(getPanel(context, "jsdebugger"));
}
},
description: gcli.lookup("breakaddlineFileDesc")
description: l10n.lookup("breakaddlineFileDesc")
},
{
name: "line",
type: { name: "number", min: 1, step: 10 },
description: gcli.lookup("breakaddlineLineDesc")
description: l10n.lookup("breakaddlineLineDesc")
}
],
returnType: "string",
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
return l10n.lookup("debuggerStopped");
}
let deferred = context.defer();
@ -182,9 +186,9 @@ exports.items.push({
let position = { actor: item.value, line: args.line };
dbg.addBreakpoint(position).then(() => {
deferred.resolve(gcli.lookup("breakaddAdded"));
deferred.resolve(l10n.lookup("breakaddAdded"));
}, aError => {
deferred.resolve(gcli.lookupFormat("breakaddFailed", [aError]));
deferred.resolve(l10n.lookupFormat("breakaddFailed", [aError]));
});
return deferred.promise;
@ -195,8 +199,10 @@ exports.items.push({
* 'break del' command
*/
exports.items.push({
item: "command",
runAt: "client",
name: "break del",
description: gcli.lookup("breakdelDesc"),
description: l10n.lookup("breakdelDesc"),
params: [
{
name: "breakpoint",
@ -214,14 +220,14 @@ exports.items.push({
}));
}
},
description: gcli.lookup("breakdelBreakidDesc")
description: l10n.lookup("breakdelBreakidDesc")
}
],
returnType: "string",
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
return l10n.lookup("debuggerStopped");
}
let source = dbg._view.Sources.getItemForAttachment(a => {
@ -233,9 +239,9 @@ exports.items.push({
line: args.breakpoint.lineNumber };
dbg.removeBreakpoint(position).then(() => {
deferred.resolve(gcli.lookup("breakdelRemoved"));
deferred.resolve(l10n.lookup("breakdelRemoved"));
}, () => {
deferred.resolve(gcli.lookup("breakNotFound"));
deferred.resolve(l10n.lookup("breakNotFound"));
});
return deferred.promise;
@ -247,16 +253,18 @@ exports.items.push({
*/
exports.items.push({
name: "dbg",
description: gcli.lookup("dbgDesc"),
manual: gcli.lookup("dbgManual")
description: l10n.lookup("dbgDesc"),
manual: l10n.lookup("dbgManual")
});
/**
* 'dbg open' command
*/
exports.items.push({
item: "command",
runAt: "client",
name: "dbg open",
description: gcli.lookup("dbgOpen"),
description: l10n.lookup("dbgOpen"),
params: [],
exec: function(args, context) {
let target = context.environment.target;
@ -268,8 +276,10 @@ exports.items.push({
* 'dbg close' command
*/
exports.items.push({
item: "command",
runAt: "client",
name: "dbg close",
description: gcli.lookup("dbgClose"),
description: l10n.lookup("dbgClose"),
params: [],
exec: function(args, context) {
if (!getPanel(context, "jsdebugger")) {
@ -284,13 +294,15 @@ exports.items.push({
* 'dbg interrupt' command
*/
exports.items.push({
item: "command",
runAt: "client",
name: "dbg interrupt",
description: gcli.lookup("dbgInterrupt"),
description: l10n.lookup("dbgInterrupt"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
return l10n.lookup("debuggerStopped");
}
let controller = dbg._controller;
@ -305,13 +317,15 @@ exports.items.push({
* 'dbg continue' command
*/
exports.items.push({
item: "command",
runAt: "client",
name: "dbg continue",
description: gcli.lookup("dbgContinue"),
description: l10n.lookup("dbgContinue"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
return l10n.lookup("debuggerStopped");
}
let controller = dbg._controller;
@ -326,22 +340,26 @@ exports.items.push({
* 'dbg step' command
*/
exports.items.push({
item: "command",
runAt: "client",
name: "dbg step",
description: gcli.lookup("dbgStepDesc"),
manual: gcli.lookup("dbgStepManual")
description: l10n.lookup("dbgStepDesc"),
manual: l10n.lookup("dbgStepManual")
});
/**
* 'dbg step over' command
*/
exports.items.push({
item: "command",
runAt: "client",
name: "dbg step over",
description: gcli.lookup("dbgStepOverDesc"),
description: l10n.lookup("dbgStepOverDesc"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
return l10n.lookup("debuggerStopped");
}
let controller = dbg._controller;
@ -356,13 +374,15 @@ exports.items.push({
* 'dbg step in' command
*/
exports.items.push({
item: "command",
runAt: "client",
name: 'dbg step in',
description: gcli.lookup("dbgStepInDesc"),
description: l10n.lookup("dbgStepInDesc"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
return l10n.lookup("debuggerStopped");
}
let controller = dbg._controller;
@ -377,13 +397,15 @@ exports.items.push({
* 'dbg step over' command
*/
exports.items.push({
item: "command",
runAt: "client",
name: 'dbg step out',
description: gcli.lookup("dbgStepOutDesc"),
description: l10n.lookup("dbgStepOutDesc"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
return l10n.lookup("debuggerStopped");
}
let controller = dbg._controller;
@ -398,14 +420,16 @@ exports.items.push({
* 'dbg list' command
*/
exports.items.push({
item: "command",
runAt: "client",
name: "dbg list",
description: gcli.lookup("dbgListSourcesDesc"),
description: l10n.lookup("dbgListSourcesDesc"),
params: [],
returnType: "dom",
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerClosed");
return l10n.lookup("debuggerClosed");
}
let sources = getAllSources(dbg);
@ -440,10 +464,12 @@ exports.items.push({
}
].forEach(function(cmd) {
const lookup = function(id) {
return gcli.lookup(cmd.l10nPrefix + id);
return l10n.lookup(cmd.l10nPrefix + id);
};
exports.items.push({
item: "command",
runAt: "client",
name: "dbg " + cmd.name,
description: lookup("Desc"),
params: [
@ -475,7 +501,7 @@ exports.items.push({
const dbg = getPanel(context, "jsdebugger");
const doc = context.environment.chromeDocument;
if (!dbg) {
throw new Error(gcli.lookup("debuggerClosed"));
throw new Error(l10n.lookup("debuggerClosed"));
}
const { promise, resolve, reject } = context.defer();

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

@ -0,0 +1,409 @@
/* 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";
const {Cc, Ci, Cu} = require("chrome");
const { Services } = require("resource://gre/modules/Services.jsm");
loader.lazyGetter(this, "osString", () => Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS);
// Panels
loader.lazyGetter(this, "OptionsPanel", () => require("devtools/framework/toolbox-options").OptionsPanel);
loader.lazyGetter(this, "InspectorPanel", () => require("devtools/inspector/inspector-panel").InspectorPanel);
loader.lazyGetter(this, "WebConsolePanel", () => require("devtools/webconsole/panel").WebConsolePanel);
loader.lazyGetter(this, "DebuggerPanel", () => require("devtools/debugger/panel").DebuggerPanel);
loader.lazyGetter(this, "StyleEditorPanel", () => require("devtools/styleeditor/styleeditor-panel").StyleEditorPanel);
loader.lazyGetter(this, "ShaderEditorPanel", () => require("devtools/shadereditor/panel").ShaderEditorPanel);
loader.lazyGetter(this, "CanvasDebuggerPanel", () => require("devtools/canvasdebugger/panel").CanvasDebuggerPanel);
loader.lazyGetter(this, "WebAudioEditorPanel", () => require("devtools/webaudioeditor/panel").WebAudioEditorPanel);
loader.lazyGetter(this, "PerformancePanel", () => require("devtools/performance/panel").PerformancePanel);
loader.lazyGetter(this, "NetMonitorPanel", () => require("devtools/netmonitor/panel").NetMonitorPanel);
loader.lazyGetter(this, "StoragePanel", () => require("devtools/storage/panel").StoragePanel);
loader.lazyGetter(this, "ScratchpadPanel", () => require("devtools/scratchpad/scratchpad-panel").ScratchpadPanel);
// Strings
const toolboxProps = "chrome://browser/locale/devtools/toolbox.properties";
const inspectorProps = "chrome://browser/locale/devtools/inspector.properties";
const webConsoleProps = "chrome://browser/locale/devtools/webconsole.properties";
const debuggerProps = "chrome://browser/locale/devtools/debugger.properties";
const styleEditorProps = "chrome://browser/locale/devtools/styleeditor.properties";
const shaderEditorProps = "chrome://browser/locale/devtools/shadereditor.properties";
const canvasDebuggerProps = "chrome://browser/locale/devtools/canvasdebugger.properties";
const webAudioEditorProps = "chrome://browser/locale/devtools/webaudioeditor.properties";
const profilerProps = "chrome://browser/locale/devtools/profiler.properties";
const netMonitorProps = "chrome://browser/locale/devtools/netmonitor.properties";
const storageProps = "chrome://browser/locale/devtools/storage.properties";
const scratchpadProps = "chrome://browser/locale/devtools/scratchpad.properties";
loader.lazyGetter(this, "toolboxStrings", () => Services.strings.createBundle(toolboxProps));
loader.lazyGetter(this, "profilerStrings",() => Services.strings.createBundle(profilerProps));
loader.lazyGetter(this, "webConsoleStrings", () => Services.strings.createBundle(webConsoleProps));
loader.lazyGetter(this, "debuggerStrings", () => Services.strings.createBundle(debuggerProps));
loader.lazyGetter(this, "styleEditorStrings", () => Services.strings.createBundle(styleEditorProps));
loader.lazyGetter(this, "shaderEditorStrings", () => Services.strings.createBundle(shaderEditorProps));
loader.lazyGetter(this, "canvasDebuggerStrings", () => Services.strings.createBundle(canvasDebuggerProps));
loader.lazyGetter(this, "webAudioEditorStrings", () => Services.strings.createBundle(webAudioEditorProps));
loader.lazyGetter(this, "inspectorStrings", () => Services.strings.createBundle(inspectorProps));
loader.lazyGetter(this, "netMonitorStrings", () => Services.strings.createBundle(netMonitorProps));
loader.lazyGetter(this, "storageStrings", () => Services.strings.createBundle(storageProps));
loader.lazyGetter(this, "scratchpadStrings", () => Services.strings.createBundle(scratchpadProps));
let Tools = {};
exports.Tools = Tools;
// Definitions
Tools.options = {
id: "options",
ordinal: 0,
url: "chrome://browser/content/devtools/framework/toolbox-options.xul",
icon: "chrome://browser/skin/devtools/tool-options.svg",
invertIconForLightTheme: true,
bgTheme: "theme-body",
label: l10n("options.label", toolboxStrings),
iconOnly: true,
panelLabel: l10n("options.panelLabel", toolboxStrings),
tooltip: l10n("optionsButton.tooltip", toolboxStrings),
inMenu: false,
isTargetSupported: function(target) {
return true;
},
build: function(iframeWindow, toolbox) {
return new OptionsPanel(iframeWindow, toolbox);
}
}
Tools.inspector = {
id: "inspector",
accesskey: l10n("inspector.accesskey", inspectorStrings),
key: l10n("inspector.commandkey", inspectorStrings),
ordinal: 1,
modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift",
icon: "chrome://browser/skin/devtools/tool-inspector.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/inspector/inspector.xul",
label: l10n("inspector.label", inspectorStrings),
panelLabel: l10n("inspector.panelLabel", inspectorStrings),
tooltip: l10n("inspector.tooltip", inspectorStrings),
inMenu: true,
commands: [
"devtools/resize-commands",
"devtools/inspector/inspector-commands",
"devtools/eyedropper/commands.js"
],
preventClosingOnKey: true,
onkey: function(panel) {
panel.toolbox.highlighterUtils.togglePicker();
},
isTargetSupported: function(target) {
return target.hasActor("inspector");
},
build: function(iframeWindow, toolbox) {
return new InspectorPanel(iframeWindow, toolbox);
}
};
Tools.webConsole = {
id: "webconsole",
key: l10n("cmd.commandkey", webConsoleStrings),
accesskey: l10n("webConsoleCmd.accesskey", webConsoleStrings),
modifiers: Services.appinfo.OS == "Darwin" ? "accel,alt" : "accel,shift",
ordinal: 2,
icon: "chrome://browser/skin/devtools/tool-webconsole.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/webconsole.xul",
label: l10n("ToolboxTabWebconsole.label", webConsoleStrings),
menuLabel: l10n("MenuWebconsole.label", webConsoleStrings),
panelLabel: l10n("ToolboxWebConsole.panelLabel", webConsoleStrings),
tooltip: l10n("ToolboxWebconsole.tooltip", webConsoleStrings),
inMenu: true,
commands: "devtools/webconsole/console-commands",
preventClosingOnKey: true,
onkey: function(panel, toolbox) {
if (toolbox.splitConsole)
return toolbox.focusConsoleInput();
panel.focusInput();
},
isTargetSupported: function(target) {
return true;
},
build: function(iframeWindow, toolbox) {
return new WebConsolePanel(iframeWindow, toolbox);
}
};
Tools.jsdebugger = {
id: "jsdebugger",
key: l10n("debuggerMenu.commandkey", debuggerStrings),
accesskey: l10n("debuggerMenu.accesskey", debuggerStrings),
modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift",
ordinal: 3,
icon: "chrome://browser/skin/devtools/tool-debugger.svg",
invertIconForLightTheme: true,
highlightedicon: "chrome://browser/skin/devtools/tool-debugger-paused.svg",
url: "chrome://browser/content/devtools/debugger.xul",
label: l10n("ToolboxDebugger.label", debuggerStrings),
panelLabel: l10n("ToolboxDebugger.panelLabel", debuggerStrings),
tooltip: l10n("ToolboxDebugger.tooltip", debuggerStrings),
inMenu: true,
commands: "devtools/debugger/debugger-commands",
isTargetSupported: function(target) {
return true;
},
build: function(iframeWindow, toolbox) {
return new DebuggerPanel(iframeWindow, toolbox);
}
};
Tools.styleEditor = {
id: "styleeditor",
key: l10n("open.commandkey", styleEditorStrings),
ordinal: 4,
accesskey: l10n("open.accesskey", styleEditorStrings),
modifiers: "shift",
icon: "chrome://browser/skin/devtools/tool-styleeditor.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/styleeditor.xul",
label: l10n("ToolboxStyleEditor.label", styleEditorStrings),
panelLabel: l10n("ToolboxStyleEditor.panelLabel", styleEditorStrings),
tooltip: l10n("ToolboxStyleEditor.tooltip2", styleEditorStrings),
inMenu: true,
commands: "devtools/styleeditor/styleeditor-commands",
isTargetSupported: function(target) {
return target.hasActor("styleEditor") || target.hasActor("styleSheets");
},
build: function(iframeWindow, toolbox) {
return new StyleEditorPanel(iframeWindow, toolbox);
}
};
Tools.shaderEditor = {
id: "shadereditor",
ordinal: 5,
visibilityswitch: "devtools.shadereditor.enabled",
icon: "chrome://browser/skin/devtools/tool-styleeditor.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/shadereditor.xul",
label: l10n("ToolboxShaderEditor.label", shaderEditorStrings),
panelLabel: l10n("ToolboxShaderEditor.panelLabel", shaderEditorStrings),
tooltip: l10n("ToolboxShaderEditor.tooltip", shaderEditorStrings),
isTargetSupported: function(target) {
return target.hasActor("webgl") && !target.chrome;
},
build: function(iframeWindow, toolbox) {
return new ShaderEditorPanel(iframeWindow, toolbox);
}
};
Tools.canvasDebugger = {
id: "canvasdebugger",
ordinal: 6,
visibilityswitch: "devtools.canvasdebugger.enabled",
icon: "chrome://browser/skin/devtools/tool-styleeditor.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/canvasdebugger.xul",
label: l10n("ToolboxCanvasDebugger.label", canvasDebuggerStrings),
panelLabel: l10n("ToolboxCanvasDebugger.panelLabel", canvasDebuggerStrings),
tooltip: l10n("ToolboxCanvasDebugger.tooltip", canvasDebuggerStrings),
// Hide the Canvas Debugger in the Add-on Debugger and Browser Toolbox
// (bug 1047520).
isTargetSupported: function(target) {
return target.hasActor("canvas") && !target.chrome;
},
build: function (iframeWindow, toolbox) {
return new CanvasDebuggerPanel(iframeWindow, toolbox);
}
};
Tools.performance = {
id: "performance",
ordinal: 7,
icon: "chrome://browser/skin/devtools/tool-profiler.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/performance.xul",
visibilityswitch: "devtools.performance.enabled",
label: l10n("profiler.label2", profilerStrings),
panelLabel: l10n("profiler.panelLabel2", profilerStrings),
tooltip: l10n("profiler.tooltip2", profilerStrings),
accesskey: l10n("profiler.accesskey", profilerStrings),
key: l10n("profiler.commandkey2", profilerStrings),
modifiers: "shift",
inMenu: true,
isTargetSupported: function (target) {
return target.hasActor("profiler");
},
build: function (frame, target) {
return new PerformancePanel(frame, target);
}
};
Tools.netMonitor = {
id: "netmonitor",
accesskey: l10n("netmonitor.accesskey", netMonitorStrings),
key: l10n("netmonitor.commandkey", netMonitorStrings),
ordinal: 9,
modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift",
visibilityswitch: "devtools.netmonitor.enabled",
icon: "chrome://browser/skin/devtools/tool-network.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/netmonitor.xul",
label: l10n("netmonitor.label", netMonitorStrings),
panelLabel: l10n("netmonitor.panelLabel", netMonitorStrings),
tooltip: l10n("netmonitor.tooltip", netMonitorStrings),
inMenu: true,
isTargetSupported: function(target) {
return target.getTrait("networkMonitor");
},
build: function(iframeWindow, toolbox) {
return new NetMonitorPanel(iframeWindow, toolbox);
}
};
Tools.storage = {
id: "storage",
key: l10n("storage.commandkey", storageStrings),
ordinal: 10,
accesskey: l10n("storage.accesskey", storageStrings),
modifiers: "shift",
visibilityswitch: "devtools.storage.enabled",
icon: "chrome://browser/skin/devtools/tool-storage.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/storage.xul",
label: l10n("storage.label", storageStrings),
menuLabel: l10n("storage.menuLabel", storageStrings),
panelLabel: l10n("storage.panelLabel", storageStrings),
tooltip: l10n("storage.tooltip2", storageStrings),
inMenu: true,
isTargetSupported: function(target) {
return target.isLocalTab ||
( target.hasActor("storage") &&
target.getTrait("storageInspector") );
},
build: function(iframeWindow, toolbox) {
return new StoragePanel(iframeWindow, toolbox);
}
};
Tools.webAudioEditor = {
id: "webaudioeditor",
ordinal: 11,
visibilityswitch: "devtools.webaudioeditor.enabled",
icon: "chrome://browser/skin/devtools/tool-webaudio.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/webaudioeditor.xul",
label: l10n("ToolboxWebAudioEditor1.label", webAudioEditorStrings),
panelLabel: l10n("ToolboxWebAudioEditor1.panelLabel", webAudioEditorStrings),
tooltip: l10n("ToolboxWebAudioEditor1.tooltip", webAudioEditorStrings),
isTargetSupported: function(target) {
return !target.chrome && target.hasActor("webaudio");
},
build: function(iframeWindow, toolbox) {
return new WebAudioEditorPanel(iframeWindow, toolbox);
}
};
Tools.scratchpad = {
id: "scratchpad",
ordinal: 12,
visibilityswitch: "devtools.scratchpad.enabled",
icon: "chrome://browser/skin/devtools/tool-scratchpad.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/scratchpad.xul",
label: l10n("scratchpad.label", scratchpadStrings),
panelLabel: l10n("scratchpad.panelLabel", scratchpadStrings),
tooltip: l10n("scratchpad.tooltip", scratchpadStrings),
inMenu: false,
commands: "devtools/scratchpad/scratchpad-commands",
isTargetSupported: function(target) {
return target.isRemote;
},
build: function(iframeWindow, toolbox) {
return new ScratchpadPanel(iframeWindow, toolbox);
}
};
let defaultTools = [
Tools.options,
Tools.webConsole,
Tools.inspector,
Tools.jsdebugger,
Tools.styleEditor,
Tools.shaderEditor,
Tools.canvasDebugger,
Tools.webAudioEditor,
Tools.performance,
Tools.netMonitor,
Tools.storage,
Tools.scratchpad
];
exports.defaultTools = defaultTools;
Tools.darkTheme = {
id: "dark",
label: l10n("options.darkTheme.label", toolboxStrings),
ordinal: 1,
stylesheets: ["chrome://browser/skin/devtools/dark-theme.css"],
classList: ["theme-dark"],
};
Tools.lightTheme = {
id: "light",
label: l10n("options.lightTheme.label", toolboxStrings),
ordinal: 2,
stylesheets: ["chrome://browser/skin/devtools/light-theme.css"],
classList: ["theme-light"],
};
exports.defaultThemes = [
Tools.darkTheme,
Tools.lightTheme,
];
/**
* Lookup l10n string from a string bundle.
*
* @param {string} name
* The key to lookup.
* @param {StringBundle} bundle
* The key to lookup.
* @returns A localized version of the given key.
*/
function l10n(name, bundle)
{
try {
return bundle.GetStringFromName(name);
} catch (ex) {
Services.console.logStringMessage("Error reading '" + name + "'");
throw new Error("l10n error with " + name);
}
}

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

@ -2,7 +2,7 @@
* 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/. */
const gcli = require("gcli/index");
const l10n = require("gcli/l10n");
const EventEmitter = require("devtools/toolkit/event-emitter");
const eventEmitter = new EventEmitter();
@ -12,14 +12,19 @@ let { Eyedropper, EyedropperManager } = require("devtools/eyedropper/eyedropper"
* 'eyedropper' command
*/
exports.items = [{
item: "command",
runAt: "client",
name: "eyedropper",
description: gcli.lookup("eyedropperDesc"),
manual: gcli.lookup("eyedropperManual"),
description: l10n.lookup("eyedropperDesc"),
manual: l10n.lookup("eyedropperManual"),
buttonId: "command-button-eyedropper",
buttonClass: "command-button command-button-invertable",
tooltipText: gcli.lookup("eyedropperTooltip"),
tooltipText: l10n.lookup("eyedropperTooltip"),
state: {
isChecked: function(target) {
if (!target.tab) {
return false;
}
let chromeWindow = target.tab.ownerDocument.defaultView;
let dropper = EyedropperManager.getInstance(chromeWindow);
if (dropper) {

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

@ -120,7 +120,7 @@ ToolSidebar.prototype = {
let tabs = this._tabbox.tabs;
// Create a container and insert it first in the tabbox
let allTabsContainer = this._panelDoc.createElementNS(XULNS, "box");
let allTabsContainer = this._panelDoc.createElementNS(XULNS, "stack");
this._tabbox.insertBefore(allTabsContainer, tabs);
// Move the tabs inside and make them flex
@ -130,8 +130,10 @@ ToolSidebar.prototype = {
// Create the dropdown menu next to the tabs
this._allTabsBtn = this._panelDoc.createElementNS(XULNS, "toolbarbutton");
this._allTabsBtn.setAttribute("class", "devtools-sidebar-alltabs");
this._allTabsBtn.setAttribute("right", "0");
this._allTabsBtn.setAttribute("top", "0");
this._allTabsBtn.setAttribute("width", "15");
this._allTabsBtn.setAttribute("type", "menu");
this._allTabsBtn.setAttribute("label", l10n("sidebar.showAllTabs.label"));
this._allTabsBtn.setAttribute("tooltiptext", l10n("sidebar.showAllTabs.tooltip"));
this._allTabsBtn.setAttribute("hidden", "true");
allTabsContainer.appendChild(this._allTabsBtn);
@ -162,7 +164,7 @@ ToolSidebar.prototype = {
// Moving back the tabs as a first child of the tabbox
this._tabbox.insertBefore(tabs, this._tabbox.tabpanels);
this._tabbox.querySelector("box").remove();
this._tabbox.querySelector("stack").remove();
this._allTabsBtn = null;
},

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

@ -118,6 +118,10 @@ function test() {
todo(false, "Front for " + actor + " still held in pool!");
continue;
}
// gcliActor is for the commandline which is separate to the toolbox
if (actor.contains("gcliActor")) {
continue;
}
ok(false, "Front for " + actor + " still held in pool!");
}
}

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

@ -713,10 +713,13 @@ Toolbox.prototype = {
this._buildPickerButton();
}
let spec = CommandUtils.getCommandbarSpec("devtools.toolbox.toolbarSpec");
let environment = CommandUtils.createEnvironment(this, '_target');
return CommandUtils.createRequisition(environment).then(requisition => {
const options = {
environment: CommandUtils.createEnvironment(this, '_target')
};
return CommandUtils.createRequisition(this.target, options).then(requisition => {
this._requisition = requisition;
const spec = CommandUtils.getCommandbarSpec("devtools.toolbox.toolbarSpec");
return CommandUtils.createButtons(spec, this.target, this.doc,
requisition).then(buttons => {
let container = this.doc.getElementById("toolbox-buttons");
@ -1752,7 +1755,7 @@ Toolbox.prototype = {
let win = this.frame.ownerGlobal;
if (this._requisition) {
this._requisition.destroy();
CommandUtils.destroyRequisition(this._requisition, this.target);
}
this._telemetry.toolClosed("toolbox");
this._telemetry.destroy();

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

@ -4,18 +4,20 @@
"use strict";
const gcli = require("gcli/index");
const l10n = require("gcli/l10n");
exports.items = [{
item: "command",
runAt: "server",
name: "inspect",
description: gcli.lookup("inspectDesc"),
manual: gcli.lookup("inspectManual"),
description: l10n.lookup("inspectDesc"),
manual: l10n.lookup("inspectManual"),
params: [
{
name: "selector",
type: "node",
description: gcli.lookup("inspectNodeDesc"),
manual: gcli.lookup("inspectNodeManual")
description: l10n.lookup("inspectNodeDesc"),
manual: l10n.lookup("inspectNodeManual")
}
],
exec: function(args, context) {

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

@ -833,6 +833,12 @@ InspectorPanel.prototype = {
let button = this._paneToggleButton;
let isVisible = !button.hasAttribute("pane-collapsed");
// Make sure the sidebar has a width attribute before collapsing because
// ViewHelpers needs it.
if (isVisible && !sidePane.hasAttribute("width")) {
sidePane.setAttribute("width", sidePane.getBoundingClientRect().width);
}
ViewHelpers.togglePane({
visible: !isVisible,
animated: true,

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

@ -4,11 +4,20 @@
"use strict";
const {Cc, Ci, Cu} = require("chrome");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const { Cu } = require("chrome");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
const { gDevTools } = require("resource:///modules/devtools/gDevTools.jsm");
const { defaultTools, defaultThemes } = require("definitions");
defaultTools.forEach(definition => gDevTools.registerTool(definition));
defaultThemes.forEach(definition => gDevTools.registerTheme(definition));
// Re-export for backwards compatibility, but we should probably the
// definitions from require("definitions") in the future
exports.defaultTools = require("definitions").defaultTools;
exports.defaultThemes = require("definitions").defaultThemes;
exports.Tools = require("definitions").Tools;
Object.defineProperty(exports, "Toolbox", {
get: () => require("devtools/framework/toolbox").Toolbox
@ -17,398 +26,7 @@ Object.defineProperty(exports, "TargetFactory", {
get: () => require("devtools/framework/target").TargetFactory
});
loader.lazyGetter(this, "osString", () => Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS);
let events = require("sdk/system/events");
// Panels
loader.lazyGetter(this, "OptionsPanel", () => require("devtools/framework/toolbox-options").OptionsPanel);
loader.lazyGetter(this, "InspectorPanel", () => require("devtools/inspector/inspector-panel").InspectorPanel);
loader.lazyGetter(this, "WebConsolePanel", () => require("devtools/webconsole/panel").WebConsolePanel);
loader.lazyGetter(this, "DebuggerPanel", () => require("devtools/debugger/panel").DebuggerPanel);
loader.lazyGetter(this, "StyleEditorPanel", () => require("devtools/styleeditor/styleeditor-panel").StyleEditorPanel);
loader.lazyGetter(this, "ShaderEditorPanel", () => require("devtools/shadereditor/panel").ShaderEditorPanel);
loader.lazyGetter(this, "CanvasDebuggerPanel", () => require("devtools/canvasdebugger/panel").CanvasDebuggerPanel);
loader.lazyGetter(this, "WebAudioEditorPanel", () => require("devtools/webaudioeditor/panel").WebAudioEditorPanel);
loader.lazyGetter(this, "PerformancePanel", () => require("devtools/performance/panel").PerformancePanel);
loader.lazyGetter(this, "NetMonitorPanel", () => require("devtools/netmonitor/panel").NetMonitorPanel);
loader.lazyGetter(this, "StoragePanel", () => require("devtools/storage/panel").StoragePanel);
loader.lazyGetter(this, "ScratchpadPanel", () => require("devtools/scratchpad/scratchpad-panel").ScratchpadPanel);
// Strings
const toolboxProps = "chrome://browser/locale/devtools/toolbox.properties";
const inspectorProps = "chrome://browser/locale/devtools/inspector.properties";
const webConsoleProps = "chrome://browser/locale/devtools/webconsole.properties";
const debuggerProps = "chrome://browser/locale/devtools/debugger.properties";
const styleEditorProps = "chrome://browser/locale/devtools/styleeditor.properties";
const shaderEditorProps = "chrome://browser/locale/devtools/shadereditor.properties";
const canvasDebuggerProps = "chrome://browser/locale/devtools/canvasdebugger.properties";
const webAudioEditorProps = "chrome://browser/locale/devtools/webaudioeditor.properties";
const profilerProps = "chrome://browser/locale/devtools/profiler.properties";
const netMonitorProps = "chrome://browser/locale/devtools/netmonitor.properties";
const storageProps = "chrome://browser/locale/devtools/storage.properties";
const scratchpadProps = "chrome://browser/locale/devtools/scratchpad.properties";
loader.lazyGetter(this, "toolboxStrings", () => Services.strings.createBundle(toolboxProps));
loader.lazyGetter(this, "profilerStrings",() => Services.strings.createBundle(profilerProps));
loader.lazyGetter(this, "webConsoleStrings", () => Services.strings.createBundle(webConsoleProps));
loader.lazyGetter(this, "debuggerStrings", () => Services.strings.createBundle(debuggerProps));
loader.lazyGetter(this, "styleEditorStrings", () => Services.strings.createBundle(styleEditorProps));
loader.lazyGetter(this, "shaderEditorStrings", () => Services.strings.createBundle(shaderEditorProps));
loader.lazyGetter(this, "canvasDebuggerStrings", () => Services.strings.createBundle(canvasDebuggerProps));
loader.lazyGetter(this, "webAudioEditorStrings", () => Services.strings.createBundle(webAudioEditorProps));
loader.lazyGetter(this, "inspectorStrings", () => Services.strings.createBundle(inspectorProps));
loader.lazyGetter(this, "netMonitorStrings", () => Services.strings.createBundle(netMonitorProps));
loader.lazyGetter(this, "storageStrings", () => Services.strings.createBundle(storageProps));
loader.lazyGetter(this, "scratchpadStrings", () => Services.strings.createBundle(scratchpadProps));
let Tools = {};
exports.Tools = Tools;
// Definitions
Tools.options = {
id: "options",
ordinal: 0,
url: "chrome://browser/content/devtools/framework/toolbox-options.xul",
icon: "chrome://browser/skin/devtools/tool-options.svg",
invertIconForLightTheme: true,
bgTheme: "theme-body",
label: l10n("options.label", toolboxStrings),
iconOnly: true,
panelLabel: l10n("options.panelLabel", toolboxStrings),
tooltip: l10n("optionsButton.tooltip", toolboxStrings),
inMenu: false,
isTargetSupported: function(target) {
return true;
},
build: function(iframeWindow, toolbox) {
return new OptionsPanel(iframeWindow, toolbox);
}
}
Tools.inspector = {
id: "inspector",
accesskey: l10n("inspector.accesskey", inspectorStrings),
key: l10n("inspector.commandkey", inspectorStrings),
ordinal: 1,
modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift",
icon: "chrome://browser/skin/devtools/tool-inspector.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/inspector/inspector.xul",
label: l10n("inspector.label", inspectorStrings),
panelLabel: l10n("inspector.panelLabel", inspectorStrings),
tooltip: l10n("inspector.tooltip", inspectorStrings),
inMenu: true,
commands: [
"devtools/resize-commands",
"devtools/inspector/inspector-commands",
"devtools/eyedropper/commands.js"
],
preventClosingOnKey: true,
onkey: function(panel) {
panel.toolbox.highlighterUtils.togglePicker();
},
isTargetSupported: function(target) {
return target.hasActor("inspector");
},
build: function(iframeWindow, toolbox) {
return new InspectorPanel(iframeWindow, toolbox);
}
};
Tools.webConsole = {
id: "webconsole",
key: l10n("cmd.commandkey", webConsoleStrings),
accesskey: l10n("webConsoleCmd.accesskey", webConsoleStrings),
modifiers: Services.appinfo.OS == "Darwin" ? "accel,alt" : "accel,shift",
ordinal: 2,
icon: "chrome://browser/skin/devtools/tool-webconsole.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/webconsole.xul",
label: l10n("ToolboxTabWebconsole.label", webConsoleStrings),
menuLabel: l10n("MenuWebconsole.label", webConsoleStrings),
panelLabel: l10n("ToolboxWebConsole.panelLabel", webConsoleStrings),
tooltip: l10n("ToolboxWebconsole.tooltip", webConsoleStrings),
inMenu: true,
commands: "devtools/webconsole/console-commands",
preventClosingOnKey: true,
onkey: function(panel, toolbox) {
if (toolbox.splitConsole)
return toolbox.focusConsoleInput();
panel.focusInput();
},
isTargetSupported: function(target) {
return true;
},
build: function(iframeWindow, toolbox) {
return new WebConsolePanel(iframeWindow, toolbox);
}
};
Tools.jsdebugger = {
id: "jsdebugger",
key: l10n("debuggerMenu.commandkey", debuggerStrings),
accesskey: l10n("debuggerMenu.accesskey", debuggerStrings),
modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift",
ordinal: 3,
icon: "chrome://browser/skin/devtools/tool-debugger.svg",
invertIconForLightTheme: true,
highlightedicon: "chrome://browser/skin/devtools/tool-debugger-paused.svg",
url: "chrome://browser/content/devtools/debugger.xul",
label: l10n("ToolboxDebugger.label", debuggerStrings),
panelLabel: l10n("ToolboxDebugger.panelLabel", debuggerStrings),
tooltip: l10n("ToolboxDebugger.tooltip", debuggerStrings),
inMenu: true,
commands: "devtools/debugger/debugger-commands",
isTargetSupported: function(target) {
return true;
},
build: function(iframeWindow, toolbox) {
return new DebuggerPanel(iframeWindow, toolbox);
}
};
Tools.styleEditor = {
id: "styleeditor",
key: l10n("open.commandkey", styleEditorStrings),
ordinal: 4,
accesskey: l10n("open.accesskey", styleEditorStrings),
modifiers: "shift",
icon: "chrome://browser/skin/devtools/tool-styleeditor.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/styleeditor.xul",
label: l10n("ToolboxStyleEditor.label", styleEditorStrings),
panelLabel: l10n("ToolboxStyleEditor.panelLabel", styleEditorStrings),
tooltip: l10n("ToolboxStyleEditor.tooltip2", styleEditorStrings),
inMenu: true,
commands: "devtools/styleeditor/styleeditor-commands",
isTargetSupported: function(target) {
return target.hasActor("styleEditor") || target.hasActor("styleSheets");
},
build: function(iframeWindow, toolbox) {
return new StyleEditorPanel(iframeWindow, toolbox);
}
};
Tools.shaderEditor = {
id: "shadereditor",
ordinal: 5,
visibilityswitch: "devtools.shadereditor.enabled",
icon: "chrome://browser/skin/devtools/tool-styleeditor.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/shadereditor.xul",
label: l10n("ToolboxShaderEditor.label", shaderEditorStrings),
panelLabel: l10n("ToolboxShaderEditor.panelLabel", shaderEditorStrings),
tooltip: l10n("ToolboxShaderEditor.tooltip", shaderEditorStrings),
isTargetSupported: function(target) {
return target.hasActor("webgl") && !target.chrome;
},
build: function(iframeWindow, toolbox) {
return new ShaderEditorPanel(iframeWindow, toolbox);
}
};
Tools.canvasDebugger = {
id: "canvasdebugger",
ordinal: 6,
visibilityswitch: "devtools.canvasdebugger.enabled",
icon: "chrome://browser/skin/devtools/tool-styleeditor.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/canvasdebugger.xul",
label: l10n("ToolboxCanvasDebugger.label", canvasDebuggerStrings),
panelLabel: l10n("ToolboxCanvasDebugger.panelLabel", canvasDebuggerStrings),
tooltip: l10n("ToolboxCanvasDebugger.tooltip", canvasDebuggerStrings),
// Hide the Canvas Debugger in the Add-on Debugger and Browser Toolbox
// (bug 1047520).
isTargetSupported: function(target) {
return target.hasActor("canvas") && !target.chrome;
},
build: function (iframeWindow, toolbox) {
return new CanvasDebuggerPanel(iframeWindow, toolbox);
}
};
Tools.performance = {
id: "performance",
ordinal: 7,
icon: "chrome://browser/skin/devtools/tool-profiler.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/performance.xul",
visibilityswitch: "devtools.performance.enabled",
label: l10n("profiler.label2", profilerStrings),
panelLabel: l10n("profiler.panelLabel2", profilerStrings),
tooltip: l10n("profiler.tooltip2", profilerStrings),
accesskey: l10n("profiler.accesskey", profilerStrings),
key: l10n("profiler.commandkey2", profilerStrings),
modifiers: "shift",
inMenu: true,
isTargetSupported: function (target) {
return target.hasActor("profiler");
},
build: function (frame, target) {
return new PerformancePanel(frame, target);
}
};
Tools.netMonitor = {
id: "netmonitor",
accesskey: l10n("netmonitor.accesskey", netMonitorStrings),
key: l10n("netmonitor.commandkey", netMonitorStrings),
ordinal: 9,
modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift",
visibilityswitch: "devtools.netmonitor.enabled",
icon: "chrome://browser/skin/devtools/tool-network.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/netmonitor.xul",
label: l10n("netmonitor.label", netMonitorStrings),
panelLabel: l10n("netmonitor.panelLabel", netMonitorStrings),
tooltip: l10n("netmonitor.tooltip", netMonitorStrings),
inMenu: true,
isTargetSupported: function(target) {
return target.getTrait("networkMonitor");
},
build: function(iframeWindow, toolbox) {
return new NetMonitorPanel(iframeWindow, toolbox);
}
};
Tools.storage = {
id: "storage",
key: l10n("storage.commandkey", storageStrings),
ordinal: 10,
accesskey: l10n("storage.accesskey", storageStrings),
modifiers: "shift",
visibilityswitch: "devtools.storage.enabled",
icon: "chrome://browser/skin/devtools/tool-storage.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/storage.xul",
label: l10n("storage.label", storageStrings),
menuLabel: l10n("storage.menuLabel", storageStrings),
panelLabel: l10n("storage.panelLabel", storageStrings),
tooltip: l10n("storage.tooltip2", storageStrings),
inMenu: true,
isTargetSupported: function(target) {
return target.isLocalTab ||
( target.hasActor("storage") &&
target.getTrait("storageInspector") );
},
build: function(iframeWindow, toolbox) {
return new StoragePanel(iframeWindow, toolbox);
}
};
Tools.webAudioEditor = {
id: "webaudioeditor",
ordinal: 11,
visibilityswitch: "devtools.webaudioeditor.enabled",
icon: "chrome://browser/skin/devtools/tool-webaudio.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/webaudioeditor.xul",
label: l10n("ToolboxWebAudioEditor1.label", webAudioEditorStrings),
panelLabel: l10n("ToolboxWebAudioEditor1.panelLabel", webAudioEditorStrings),
tooltip: l10n("ToolboxWebAudioEditor1.tooltip", webAudioEditorStrings),
isTargetSupported: function(target) {
return !target.chrome && target.hasActor("webaudio");
},
build: function(iframeWindow, toolbox) {
return new WebAudioEditorPanel(iframeWindow, toolbox);
}
};
Tools.scratchpad = {
id: "scratchpad",
ordinal: 12,
visibilityswitch: "devtools.scratchpad.enabled",
icon: "chrome://browser/skin/devtools/tool-scratchpad.svg",
invertIconForLightTheme: true,
url: "chrome://browser/content/devtools/scratchpad.xul",
label: l10n("scratchpad.label", scratchpadStrings),
panelLabel: l10n("scratchpad.panelLabel", scratchpadStrings),
tooltip: l10n("scratchpad.tooltip", scratchpadStrings),
inMenu: false,
commands: "devtools/scratchpad/scratchpad-commands",
isTargetSupported: function(target) {
return target.isRemote;
},
build: function(iframeWindow, toolbox) {
return new ScratchpadPanel(iframeWindow, toolbox);
}
};
let defaultTools = [
Tools.options,
Tools.webConsole,
Tools.inspector,
Tools.jsdebugger,
Tools.styleEditor,
Tools.shaderEditor,
Tools.canvasDebugger,
Tools.webAudioEditor,
Tools.performance,
Tools.netMonitor,
Tools.storage,
Tools.scratchpad
];
exports.defaultTools = defaultTools;
for (let definition of defaultTools) {
gDevTools.registerTool(definition);
}
Tools.darkTheme = {
id: "dark",
label: l10n("options.darkTheme.label", toolboxStrings),
ordinal: 1,
stylesheets: ["chrome://browser/skin/devtools/dark-theme.css"],
classList: ["theme-dark"],
};
Tools.lightTheme = {
id: "light",
label: l10n("options.lightTheme.label", toolboxStrings),
ordinal: 2,
stylesheets: ["chrome://browser/skin/devtools/light-theme.css"],
classList: ["theme-light"],
};
let defaultThemes = [
Tools.darkTheme,
Tools.lightTheme,
];
for (let definition of defaultThemes) {
gDevTools.registerTheme(definition);
}
var unloadObserver = {
const unloadObserver = {
observe: function(subject, topic, data) {
if (subject.wrappedJSObject === require("@loader/unload")) {
Services.obs.removeObserver(unloadObserver, "sdk:loader:destroy");
@ -423,23 +41,5 @@ var unloadObserver = {
};
Services.obs.addObserver(unloadObserver, "sdk:loader:destroy", false);
const events = require("sdk/system/events");
events.emit("devtools-loaded", {});
/**
* Lookup l10n string from a string bundle.
*
* @param {string} name
* The key to lookup.
* @param {StringBundle} bundle
* The key to lookup.
* @returns A localized version of the given key.
*/
function l10n(name, bundle)
{
try {
return bundle.GetStringFromName(name);
} catch (ex) {
Services.console.logStringMessage("Error reading '" + name + "'");
throw new Error("l10n error with " + name);
}
}

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

@ -41,5 +41,6 @@ EXTRA_COMPONENTS += [
JAR_MANIFESTS += ['jar.mn']
EXTRA_JS_MODULES.devtools += [
'definitions.js',
'main.js',
]

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

@ -11,43 +11,54 @@ const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"].
createBundle("chrome://branding/locale/brand.properties").
GetStringFromName("brandShortName");
const gcli = require("gcli/index");
const l10n = require("gcli/l10n");
exports.items = [
{
name: 'resize',
description: gcli.lookup('resizeModeDesc')
description: l10n.lookup('resizeModeDesc')
},
{
item: "command",
runAt: "client",
name: 'resize on',
description: gcli.lookup('resizeModeOnDesc'),
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
description: l10n.lookup('resizeModeOnDesc'),
manual: l10n.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
exec: gcli_cmd_resize
},
{
item: "command",
runAt: "client",
name: 'resize off',
description: gcli.lookup('resizeModeOffDesc'),
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
description: l10n.lookup('resizeModeOffDesc'),
manual: l10n.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
exec: gcli_cmd_resize
},
{
item: "command",
runAt: "client",
name: 'resize toggle',
buttonId: "command-button-responsive",
buttonClass: "command-button command-button-invertable",
tooltipText: gcli.lookup("resizeModeToggleTooltip"),
description: gcli.lookup('resizeModeToggleDesc'),
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
tooltipText: l10n.lookup("resizeModeToggleTooltip"),
description: l10n.lookup('resizeModeToggleDesc'),
manual: l10n.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
state: {
isChecked: function(aTarget) {
if (!aTarget.tab) {
return false;
}
let browserWindow = aTarget.tab.ownerDocument.defaultView;
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
return mgr.isActiveForTab(aTarget.tab);
},
onChange: function(aTarget, aChangeHandler) {
let browserWindow = aTarget.tab.ownerDocument.defaultView;
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
mgr.on("on", aChangeHandler);
mgr.on("off", aChangeHandler);
if (aTarget.tab) {
let browserWindow = aTarget.tab.ownerDocument.defaultView;
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
mgr.on("on", aChangeHandler);
mgr.on("off", aChangeHandler);
}
},
offChange: function(aTarget, aChangeHandler) {
if (aTarget.tab) {
@ -61,18 +72,20 @@ exports.items = [
exec: gcli_cmd_resize
},
{
item: "command",
runAt: "client",
name: 'resize to',
description: gcli.lookup('resizeModeToDesc'),
description: l10n.lookup('resizeModeToDesc'),
params: [
{
name: 'width',
type: 'number',
description: gcli.lookup("resizePageArgWidthDesc"),
description: l10n.lookup("resizePageArgWidthDesc"),
},
{
name: 'height',
type: 'number',
description: gcli.lookup("resizePageArgHeightDesc"),
description: l10n.lookup("resizePageArgHeightDesc"),
},
],
exec: gcli_cmd_resize

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

@ -4,13 +4,15 @@
"use strict";
const gcli = require("gcli/index");
const l10n = require("gcli/l10n");
exports.items = [{
item: "command",
runAt: "client",
name: "scratchpad",
buttonId: "command-button-scratchpad",
buttonClass: "command-button command-button-invertable",
tooltipText: gcli.lookup("scratchpadOpenTooltip"),
tooltipText: l10n.lookup("scratchpadOpenTooltip"),
hidden: true,
exec: function(args, context) {
let Scratchpad = context.environment.chromeWindow.Scratchpad;

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