mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge to latest green m-c changeset
This commit is contained in:
commit
fcfb3785d8
@ -1414,6 +1414,9 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
|
||||
RETURN_LAYOUT_ANSWER(false, "Has role attribute, weak role, and role is table");
|
||||
}
|
||||
|
||||
if (mContent->Tag() != nsGkAtoms::table)
|
||||
RETURN_LAYOUT_ANSWER(true, "table built by CSS display:table style");
|
||||
|
||||
// Check if datatable attribute has "0" value.
|
||||
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::datatable,
|
||||
NS_LITERAL_STRING("0"), eCaseMatters)) {
|
||||
|
@ -176,6 +176,8 @@ __try {
|
||||
*aNSelections = 0;
|
||||
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
if (textAcc->IsDefunct())
|
||||
return E_FAIL;
|
||||
|
||||
PRInt32 selCount = 0;
|
||||
nsresult rv = textAcc->GetSelectionCount(&selCount);
|
||||
|
@ -98,6 +98,9 @@
|
||||
// layout table having datatable="0" attribute and containing data table structure (tfoot element)
|
||||
testAttrs("table22", attr, true);
|
||||
|
||||
// css table with non-table tag
|
||||
testAttrs("table23", attr, true);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -117,6 +120,11 @@
|
||||
title="Data table elements used to determine layout-guess attribute shouldn't be picked from nested tables">
|
||||
Mozilla Bug 690222
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=693948"
|
||||
title="Expose layout-guess: true object attribute on CSS table accessible">
|
||||
Mozilla Bug 693948
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
@ -431,5 +439,14 @@
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<!-- css table with noon-table tag -->
|
||||
<div id="table23" style="display:table;">
|
||||
<div style="display:table-row;">
|
||||
<div style="display:table-cell;">Row 1, column 1</div>
|
||||
<div style="display:table-cell;">Row 1, column 2</div>
|
||||
<div style="display:table-cell;">Row 1, column 3</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -54,7 +54,7 @@
|
||||
|
||||
<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/webConsole.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/webconsole.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
|
||||
|
||||
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
|
||||
|
@ -12,10 +12,10 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#highlighter-veil-container:not([locked]) > .highlighter-veil,
|
||||
#highlighter-veil-container:not([locked]) > #highlighter-veil-middlebox,
|
||||
#highlighter-veil-container:not([locked]) > #highlighter-veil-middlebox > .highlighter-veil,
|
||||
#highlighter-veil-container:not([locked]) > #highlighter-veil-middlebox > #highlighter-veil-transparentbox {
|
||||
#highlighter-veil-container:not([disable-transitions]) > .highlighter-veil,
|
||||
#highlighter-veil-container:not([disable-transitions]) > #highlighter-veil-middlebox,
|
||||
#highlighter-veil-container:not([disable-transitions]) > #highlighter-veil-middlebox > .highlighter-veil,
|
||||
#highlighter-veil-container:not([disable-transitions]) > #highlighter-veil-middlebox > #highlighter-veil-transparentbox {
|
||||
-moz-transition-property: width, height;
|
||||
-moz-transition-duration: 0.1s;
|
||||
-moz-transition-timing-function: linear;
|
||||
@ -51,7 +51,7 @@
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#highlighter-nodeinfobar-container:not([locked]) {
|
||||
#highlighter-nodeinfobar-container:not([disable-transitions]) {
|
||||
-moz-transition-property: top, left;
|
||||
-moz-transition-duration: 0.1s;
|
||||
-moz-transition-timing-function: linear;
|
||||
@ -63,6 +63,17 @@
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
#highlighter-nodeinfobar-container[locked] > #highlighter-nodeinfobar {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
#highlighter-nodeinfobar-id,
|
||||
.highlighter-nodeinfobar-class,
|
||||
#highlighter-nodeinfobar-tagname {
|
||||
-moz-user-select: text;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.highlighter-nodeinfobar-arrow {
|
||||
display: none;
|
||||
}
|
||||
@ -83,14 +94,6 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
#highlighter-nodeinfobar-id::before {
|
||||
content: "#";
|
||||
}
|
||||
|
||||
.highlighter-nodeinfobar-class::before {
|
||||
content: ".";
|
||||
}
|
||||
|
||||
#highlighter-nodeinfobar-tagname {
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
@ -859,15 +859,15 @@ nsContextMenu.prototype = {
|
||||
},
|
||||
|
||||
fullScreenVideo: function () {
|
||||
let video = this.target;
|
||||
let video = this.target;
|
||||
if (document.mozFullScreenEnabled)
|
||||
video.mozRequestFullScreen();
|
||||
else {
|
||||
// Fallback for the legacy full-screen video implementation.
|
||||
video.pause();
|
||||
openDialog("chrome://browser/content/fullscreen-video.xhtml",
|
||||
"", "chrome,centerscreen,dialog=no", video);
|
||||
}
|
||||
// Fallback for the legacy full-screen video implementation.
|
||||
video.pause();
|
||||
openDialog("chrome://browser/content/fullscreen-video.xhtml",
|
||||
"", "chrome,centerscreen,dialog=no", video);
|
||||
}
|
||||
},
|
||||
|
||||
// Change current window to the URL of the background image.
|
||||
|
@ -55,6 +55,22 @@ tier_app_dirs += browser
|
||||
# Never add other tier_app_dirs after browser. They won't get packaged
|
||||
# properly on mac.
|
||||
|
||||
################################################
|
||||
# Parallel build on Windows with GNU make check
|
||||
|
||||
default::
|
||||
ifeq (,$(findstring pymake,$(MAKE)))
|
||||
ifeq ($(HOST_OS_ARCH),WINNT)
|
||||
ifneq (1,$(NUMBER_OF_PROCESSORS))
|
||||
@echo $(if $(findstring -j,$(value MAKEFLAGS)), \
|
||||
$(error You are using GNU make to build Firefox with -jN on Windows. \
|
||||
This will randomly deadlock. To compile a parallel build on Windows \
|
||||
run "python -OO build/pymake/make.py -f client.mk build". \
|
||||
See https://developer.mozilla.org/en/pymake for more details.))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
installer:
|
||||
@$(MAKE) -C browser/installer installer
|
||||
|
||||
|
@ -479,7 +479,7 @@ ChromeProfileMigrator.prototype = {
|
||||
*
|
||||
* @return true if supported
|
||||
*/
|
||||
sourceExists: function Chrome_sourceExists()
|
||||
get sourceExists()
|
||||
{
|
||||
let result = this.getMigrateData(null, false);
|
||||
return result != 0;
|
||||
@ -495,7 +495,7 @@ ChromeProfileMigrator.prototype = {
|
||||
*
|
||||
* @return home page URL
|
||||
*/
|
||||
sourceHomePageURL: function Chrome_sourceHomePageURL()
|
||||
get sourceHomePageURL()
|
||||
{
|
||||
try {
|
||||
if (this._homepageURL)
|
||||
|
@ -1532,10 +1532,10 @@ ContentPermissionPrompt.prototype = {
|
||||
|
||||
// Different message/options if it is a local file
|
||||
if (requestingURI.schemeIs("file")) {
|
||||
message = browserBundle.formatStringFromName("geolocation.fileWantsToKnow",
|
||||
message = browserBundle.formatStringFromName("geolocation.shareWithFile",
|
||||
[requestingURI.path], 1);
|
||||
} else {
|
||||
message = browserBundle.formatStringFromName("geolocation.siteWantsToKnow",
|
||||
message = browserBundle.formatStringFromName("geolocation.shareWithSite",
|
||||
[requestingURI.host], 1);
|
||||
|
||||
// Don't offer to "always/never share" in PB mode
|
||||
@ -1545,16 +1545,16 @@ ContentPermissionPrompt.prototype = {
|
||||
|
||||
if (!inPrivateBrowsing) {
|
||||
secondaryActions.push({
|
||||
label: browserBundle.GetStringFromName("geolocation.alwaysShare"),
|
||||
accessKey: browserBundle.GetStringFromName("geolocation.alwaysShare.accesskey"),
|
||||
label: browserBundle.GetStringFromName("geolocation.alwaysShareLocation"),
|
||||
accessKey: browserBundle.GetStringFromName("geolocation.alwaysShareLocation.accesskey"),
|
||||
callback: function () {
|
||||
Services.perms.add(requestingURI, "geo", Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
request.allow();
|
||||
}
|
||||
});
|
||||
secondaryActions.push({
|
||||
label: browserBundle.GetStringFromName("geolocation.neverShare"),
|
||||
accessKey: browserBundle.GetStringFromName("geolocation.neverShare.accesskey"),
|
||||
label: browserBundle.GetStringFromName("geolocation.neverShareLocation"),
|
||||
accessKey: browserBundle.GetStringFromName("geolocation.neverShareLocation.accesskey"),
|
||||
callback: function () {
|
||||
Services.perms.add(requestingURI, "geo", Ci.nsIPermissionManager.DENY_ACTION);
|
||||
request.cancel();
|
||||
|
@ -359,7 +359,7 @@ SessionStoreService.prototype = {
|
||||
// replace the crashed session with a restore-page-only session
|
||||
let pageData = {
|
||||
url: "about:sessionrestore",
|
||||
formdata: { "#sessionData": JSON.stringify(this._initialState) }
|
||||
formdata: { "#sessionData": this._initialState }
|
||||
};
|
||||
this._initialState = { windows: [{ tabs: [{ entries: [pageData] }] }] };
|
||||
}
|
||||
@ -2140,10 +2140,17 @@ SessionStoreService.prototype = {
|
||||
}
|
||||
var isHTTPS = this._getURIFromString((aContent.parent || aContent).
|
||||
document.location.href).schemeIs("https");
|
||||
if (aFullData || this._checkPrivacyLevel(isHTTPS, aIsPinned) ||
|
||||
aContent.top.document.location.href == "about:sessionrestore") {
|
||||
let isAboutSR = aContent.top.document.location.href == "about:sessionrestore";
|
||||
if (aFullData || this._checkPrivacyLevel(isHTTPS, aIsPinned) || isAboutSR) {
|
||||
if (aFullData || aUpdateFormData) {
|
||||
let formData = this._collectFormDataForFrame(aContent.document);
|
||||
|
||||
// We want to avoid saving data for about:sessionrestore as a string.
|
||||
// Since it's stored in the form as stringified JSON, stringifying further
|
||||
// causes an explosion of escape characters. cf. bug 467409
|
||||
if (formData && isAboutSR)
|
||||
formData["#sessionData"] = JSON.parse(formData["#sessionData"]);
|
||||
|
||||
if (formData)
|
||||
aData.formdata = formData;
|
||||
else if (aData.formdata)
|
||||
@ -2981,8 +2988,9 @@ SessionStoreService.prototype = {
|
||||
restoreHistory:
|
||||
function sss_restoreHistory(aWindow, aTabs, aTabData, aIdMap, aDocIdentMap) {
|
||||
var _this = this;
|
||||
while (aTabs.length > 0 && (!aTabs[0].linkedBrowser.__SS_tabStillLoading || !aTabs[0].parentNode)) {
|
||||
aTabs.shift(); // this tab got removed before being completely restored
|
||||
// if the tab got removed before being completely restored, then skip it
|
||||
while (aTabs.length > 0 && !(this._canRestoreTabHistory(aTabs[0]))) {
|
||||
aTabs.shift();
|
||||
aTabData.shift();
|
||||
}
|
||||
if (aTabs.length == 0) {
|
||||
@ -3379,6 +3387,13 @@ SessionStoreService.prototype = {
|
||||
|
||||
let eventType;
|
||||
let value = aData[key];
|
||||
|
||||
// for about:sessionrestore we saved the field as JSON to avoid nested
|
||||
// instances causing humongous sessionstore.js files. cf. bug 467409
|
||||
if (aURL == "about:sessionrestore" && typeof value == "object") {
|
||||
value = JSON.stringify(value);
|
||||
}
|
||||
|
||||
if (typeof value == "string" && node.type != "file") {
|
||||
if (node.value == value)
|
||||
continue; // don't dispatch an input event for no change
|
||||
@ -3996,6 +4011,20 @@ SessionStoreService.prototype = {
|
||||
!aTabState.userTypedValue);
|
||||
},
|
||||
|
||||
/**
|
||||
* Determine if we can restore history into this tab.
|
||||
* This will be false when a tab has been removed (usually between
|
||||
* restoreHistoryPrecursor && restoreHistory) or if the tab is still marked
|
||||
* as loading.
|
||||
*
|
||||
* @param aTab
|
||||
* @returns boolean
|
||||
*/
|
||||
_canRestoreTabHistory: function sss__canRestoreTabHistory(aTab) {
|
||||
return aTab.parentNode && aTab.linkedBrowser &&
|
||||
aTab.linkedBrowser.__SS_tabStillLoading;
|
||||
},
|
||||
|
||||
/**
|
||||
* This is going to take a state as provided at startup (via
|
||||
* nsISessionStartup.state) and split it into 2 parts. The first part
|
||||
|
@ -100,6 +100,7 @@ _BROWSER_TEST_FILES = \
|
||||
browser_465223.js \
|
||||
browser_466937.js \
|
||||
browser_466937_sample.html \
|
||||
browser_467409-backslashplosion.js \
|
||||
browser_477657.js \
|
||||
browser_480148.js \
|
||||
browser_480893.js \
|
||||
|
@ -0,0 +1,90 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test Summary:
|
||||
// 1. Open about:sessionrestore via setBrowserState where formdata is a JS object, not a string
|
||||
// 1a. Check that #sessionData on the page is readable after JSON.parse (skipped, checking formdata is sufficient)
|
||||
// 1b. Check that there are no backslashes in the formdata
|
||||
// 1c. Check that formdata (via getBrowserState) doesn't require JSON.parse
|
||||
//
|
||||
// 2. Use the current state (currently about:sessionrestore with data) and then open than in a new instance of about:sessionrestore
|
||||
// 2a. Check that there are no backslashes in the formdata
|
||||
// 2b. Check that formdata (via getBrowserState) doesn't require JSON.parse
|
||||
//
|
||||
// 3. [backwards compat] Use a stringified state as formdata when opening about:sessionrestore
|
||||
// 3a. Make sure there are nodes in the tree on about:sessionrestore (skipped, checking formdata is sufficient)
|
||||
// 3b. Check that there are no backslashes in the formdata
|
||||
// 3c. Check that formdata (via getBrowserState) doesn't require JSON.parse
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let blankState = { windows: [{ tabs: [{ entries: [{ url: "about:blank" }] }]}]};
|
||||
let crashState = { windows: [{ tabs: [{ entries: [{ url: "about:mozilla" }] }]}]};
|
||||
|
||||
let pagedata = { url: "about:sessionrestore",
|
||||
formdata: { "#sessionData": crashState } };
|
||||
let state = { windows: [{ tabs: [{ entries: [pagedata] }] }] };
|
||||
|
||||
// test1 calls test2 calls test3 calls finish
|
||||
test1(state);
|
||||
|
||||
|
||||
function test1(aState) {
|
||||
waitForBrowserState(aState, function() {
|
||||
checkState("test1", test2);
|
||||
});
|
||||
}
|
||||
|
||||
function test2(aState) {
|
||||
let pagedata2 = { url: "about:sessionrestore",
|
||||
formdata: { "#sessionData": aState } };
|
||||
let state2 = { windows: [{ tabs: [{ entries: [pagedata2] }] }] };
|
||||
|
||||
waitForBrowserState(state2, function() {
|
||||
checkState("test2", test3);
|
||||
});
|
||||
}
|
||||
|
||||
function test3(aState) {
|
||||
let pagedata3 = { url: "about:sessionrestore",
|
||||
formdata: { "#sessionData": JSON.stringify(crashState) } };
|
||||
let state3 = { windows: [{ tabs: [{ entries: [pagedata3] }] }] };
|
||||
waitForBrowserState(state3, function() {
|
||||
// In theory we should do inspection of the treeview on about:sessionrestore,
|
||||
// but we don't actually need to. If we fail tests in checkState then
|
||||
// about:sessionrestore won't be able to turn the form value into a usable page.
|
||||
checkState("test3", function() waitForBrowserState(blankState, finish));
|
||||
});
|
||||
}
|
||||
|
||||
function checkState(testName, callback) {
|
||||
let curState = JSON.parse(ss.getBrowserState());
|
||||
let formdata = curState.windows[0].tabs[0].entries[0].formdata;
|
||||
|
||||
ok(formdata["#sessionData"], testName + ": we have form data for about:sessionrestore");
|
||||
|
||||
let sessionData_raw = JSON.stringify(formdata["#sessionData"]);
|
||||
ok(!/\\/.test(sessionData_raw), testName + ": #sessionData contains no backslashes");
|
||||
info(sessionData_raw);
|
||||
|
||||
let gotError = false;
|
||||
try {
|
||||
JSON.parse(formdata["#sessionData"]);
|
||||
}
|
||||
catch (e) {
|
||||
info(testName + ": got error: " + e);
|
||||
gotError = true;
|
||||
}
|
||||
ok(gotError, testName + ": attempting to JSON.parse form data threw error");
|
||||
|
||||
// Panorama sticks JSON into extData, which we stringify causing the
|
||||
// naive backslash check to fail. extData doesn't matter in the grand
|
||||
// scheme here, so we'll delete the extData so doesn't end up in future states.
|
||||
delete curState.windows[0].extData;
|
||||
delete curState.windows[0].tabs[0].extData;
|
||||
callback(curState);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ function test() {
|
||||
};
|
||||
let pageData = {
|
||||
url: "about:sessionrestore",
|
||||
formdata: { "#sessionData": "(" + JSON.stringify(oldState) + ")" }
|
||||
formdata: { "#sessionData": oldState }
|
||||
};
|
||||
let state = { windows: [{ tabs: [{ entries: [pageData] }] }] };
|
||||
|
||||
|
@ -1091,8 +1091,8 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// immediately - don't animate
|
||||
remove: function GroupItem_remove(a, options) {
|
||||
try {
|
||||
var $el;
|
||||
var item;
|
||||
let $el;
|
||||
let item;
|
||||
|
||||
if (a.isAnItem) {
|
||||
item = a;
|
||||
@ -1105,7 +1105,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
var index = this._children.indexOf(item);
|
||||
let index = this._children.indexOf(item);
|
||||
if (index != -1)
|
||||
this._children.splice(index, 1);
|
||||
|
||||
@ -1142,7 +1142,9 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
options.dontClose = true;
|
||||
|
||||
let closed = options.dontClose ? false : this.closeIfEmpty();
|
||||
if (closed) {
|
||||
if (closed ||
|
||||
(this._children.length == 0 && !gBrowser.selectedTab.pinned &&
|
||||
!item.isDragging)) {
|
||||
this._makeLastActiveGroupItemActive();
|
||||
} else if (!options.dontArrange) {
|
||||
this.arrange({animate: !options.immediately});
|
||||
|
@ -260,9 +260,15 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
|
||||
function TabItem_loadThumbnail_callback(error, imageData) {
|
||||
// we could have been unlinked while waiting for the thumbnail to load
|
||||
if (error || !imageData || !self.tab)
|
||||
if (!self.tab)
|
||||
return;
|
||||
|
||||
if (error || !imageData) {
|
||||
// paint the canvas to avoid leaving traces when dragging tab over it
|
||||
self.tabCanvas.paint();
|
||||
return;
|
||||
}
|
||||
|
||||
self._sendToSubscribers("loadedCachedImageData");
|
||||
|
||||
// If we have a cached image, then show it if the loaded URL matches
|
||||
|
@ -164,6 +164,7 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug685692.js \
|
||||
browser_tabview_bug686654.js \
|
||||
browser_tabview_bug697390.js \
|
||||
browser_tabview_bug705621.js \
|
||||
browser_tabview_click_group.js \
|
||||
browser_tabview_dragdrop.js \
|
||||
browser_tabview_exit_button.js \
|
||||
|
@ -49,6 +49,10 @@ function onTabViewWindowLoaded() {
|
||||
is(appTabCount(groupItemTwo), 1,
|
||||
"there's an app tab icon in the second group");
|
||||
|
||||
// When the tab was pinned, the last active group with an item got the focus.
|
||||
// Therefore, switching the focus back to group item one.
|
||||
contentWindow.UI.setActive(groupItemOne);
|
||||
|
||||
// unpin the tab, make sure the icon goes away and the TabItem comes on
|
||||
gBrowser.unpinTab(xulTab);
|
||||
is(groupItemOne._children.length, 1, "the app tab's TabItem is back");
|
||||
|
@ -104,6 +104,10 @@ function onTabViewShown(win) {
|
||||
ok(!trayContainer.hasClass("appTabTrayContainerTruncated"),
|
||||
"$appTabTray container does not have .appTabTrayContainerTruncated");
|
||||
|
||||
// When the tab was pinned, the last active group with an item got the focus.
|
||||
// Therefore, switching the focus back to group item one.
|
||||
contentWindow.UI.setActive(groupItem);
|
||||
|
||||
// unpin the last remaining tab
|
||||
gBrowser.unpinTab(xulTabs[0]);
|
||||
|
||||
|
30
browser/components/tabview/test/browser_tabview_bug705621.js
Normal file
30
browser/components/tabview/test/browser_tabview_bug705621.js
Normal file
@ -0,0 +1,30 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithTabView(function(win) {
|
||||
registerCleanupFunction(function() {
|
||||
win.close();
|
||||
});
|
||||
|
||||
let cw = win.TabView.getContentWindow();
|
||||
|
||||
let groupItemOne = cw.GroupItems.groupItems[0];
|
||||
is(groupItemOne.getChildren().length, 1, "Group one has 1 tab item");
|
||||
|
||||
let groupItemTwo = createGroupItemWithBlankTabs(win, 300, 300, 40, 1);
|
||||
is(groupItemTwo.getChildren().length, 1, "Group two has 2 tab items");
|
||||
|
||||
whenTabViewIsHidden(function() {
|
||||
executeSoon(function() {
|
||||
win.gBrowser.removeTab(win.gBrowser.selectedTab);
|
||||
is(cw.UI.getActiveTab(), groupItemOne.getChild(0), "TabItem in Group one is selected");
|
||||
finish();
|
||||
});
|
||||
}, win);
|
||||
groupItemTwo.getChild(0).zoomIn();
|
||||
});
|
||||
}
|
||||
|
@ -784,7 +784,7 @@ let UI = {
|
||||
return;
|
||||
}
|
||||
|
||||
var groupItem = GroupItems.getActiveGroupItem();
|
||||
let groupItem = GroupItems.getActiveGroupItem();
|
||||
|
||||
// 1) Only go back to the TabView tab when there you close the last
|
||||
// tab of a groupItem.
|
||||
|
@ -147,9 +147,16 @@ Highlighter.prototype = {
|
||||
|
||||
this.buildInfobar(controlsBox);
|
||||
|
||||
if (!this.IUI.store.getValue(this.winID, "inspecting")) {
|
||||
this.veilContainer.setAttribute("locked", true);
|
||||
this.nodeInfo.container.setAttribute("locked", true);
|
||||
}
|
||||
|
||||
this.browser.addEventListener("resize", this, true);
|
||||
this.browser.addEventListener("scroll", this, true);
|
||||
|
||||
this.transitionDisabler = null;
|
||||
|
||||
this.handleResize();
|
||||
},
|
||||
|
||||
@ -487,7 +494,7 @@ Highlighter.prototype = {
|
||||
this.nodeInfo.tagNameLabel.textContent = this.node.tagName;
|
||||
|
||||
// ID
|
||||
this.nodeInfo.idLabel.textContent = this.node.id;
|
||||
this.nodeInfo.idLabel.textContent = this.node.id ? "#" + this.node.id : "";
|
||||
|
||||
// Classes
|
||||
let classes = this.nodeInfo.classesBox;
|
||||
@ -500,7 +507,7 @@ Highlighter.prototype = {
|
||||
for (let i = 0; i < this.node.classList.length; i++) {
|
||||
let classLabel = this.chromeDoc.createElement("label");
|
||||
classLabel.className = "highlighter-nodeinfobar-class plain";
|
||||
classLabel.textContent = this.node.classList[i];
|
||||
classLabel.textContent = "." + this.node.classList[i];
|
||||
fragment.appendChild(classLabel);
|
||||
}
|
||||
classes.appendChild(fragment);
|
||||
@ -665,6 +672,7 @@ Highlighter.prototype = {
|
||||
this.handleMouseMove(aEvent);
|
||||
break;
|
||||
case "resize":
|
||||
this.brieflyDisableTransitions();
|
||||
this.handleResize(aEvent);
|
||||
break;
|
||||
case "dblclick":
|
||||
@ -674,11 +682,32 @@ Highlighter.prototype = {
|
||||
aEvent.preventDefault();
|
||||
break;
|
||||
case "scroll":
|
||||
this.brieflyDisableTransitions();
|
||||
this.highlight();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable the CSS transitions for a short time to avoid laggy animations
|
||||
* during scrolling or resizing.
|
||||
*/
|
||||
brieflyDisableTransitions: function Highlighter_brieflyDisableTransitions()
|
||||
{
|
||||
if (this.transitionDisabler) {
|
||||
this.IUI.win.clearTimeout(this.transitionDisabler);
|
||||
} else {
|
||||
this.veilContainer.setAttribute("disable-transitions", "true");
|
||||
this.nodeInfo.container.setAttribute("disable-transitions", "true");
|
||||
}
|
||||
this.transitionDisabler =
|
||||
this.IUI.win.setTimeout(function() {
|
||||
this.veilContainer.removeAttribute("disable-transitions");
|
||||
this.nodeInfo.container.removeAttribute("disable-transitions");
|
||||
this.transitionDisabler = null;
|
||||
}.bind(this), 500);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle clicks.
|
||||
*
|
||||
@ -963,6 +992,8 @@ InspectorUI.prototype = {
|
||||
initializeHighlighter: function IUI_initializeHighlighter()
|
||||
{
|
||||
this.highlighter = new Highlighter(this);
|
||||
this.browser.addEventListener("keypress", this, true);
|
||||
this.highlighter.highlighterContainer.addEventListener("keypress", this, true);
|
||||
this.highlighterReady();
|
||||
},
|
||||
|
||||
@ -1086,10 +1117,6 @@ InspectorUI.prototype = {
|
||||
this.treePanel.closeEditor();
|
||||
|
||||
this.inspectToolbutton.checked = true;
|
||||
// Attach event listeners to content window and child windows to enable
|
||||
// highlighting and click to stop inspection.
|
||||
this.browser.addEventListener("keypress", this, true);
|
||||
this.highlighter.highlighterContainer.addEventListener("keypress", this, true);
|
||||
this.highlighter.attachInspectListeners();
|
||||
|
||||
this.inspecting = true;
|
||||
|
@ -24,9 +24,9 @@ function test()
|
||||
function setupInfobarTest()
|
||||
{
|
||||
nodes = [
|
||||
{node: doc.querySelector("#top"), position: "bottom", tag: "DIV", id: "top", classes: "class1 class2"},
|
||||
{node: doc.querySelector("#vertical"), position: "overlap", tag: "DIV", id: "vertical", classes: ""},
|
||||
{node: doc.querySelector("#bottom"), position: "top", tag: "DIV", id: "bottom", classes: ""},
|
||||
{node: doc.querySelector("#top"), position: "bottom", tag: "DIV", id: "#top", classes: ".class1 .class2"},
|
||||
{node: doc.querySelector("#vertical"), position: "overlap", tag: "DIV", id: "#vertical", classes: ""},
|
||||
{node: doc.querySelector("#bottom"), position: "top", tag: "DIV", id: "#bottom", classes: ""},
|
||||
{node: doc.querySelector("body"), position: "overlap", tag: "BODY", id: "", classes: ""},
|
||||
]
|
||||
|
||||
|
@ -187,10 +187,18 @@ function inspectorFocusTab2()
|
||||
is(InspectorUI.store.length, 2, "Inspector.store.length is 2");
|
||||
isnot(InspectorUI.selection, div, "selection does not match the div element");
|
||||
|
||||
// Switch back to tab 1.
|
||||
Services.obs.addObserver(inspectorSecondFocusTab1,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY, false);
|
||||
gBrowser.selectedTab = tab1;
|
||||
// Make sure keybindings still sork
|
||||
EventUtils.synthesizeKey("VK_RETURN", { });
|
||||
|
||||
executeSoon(function() {
|
||||
ok(InspectorUI.inspecting, "Inspector is highlighting");
|
||||
InspectorUI.toggleInspection();
|
||||
|
||||
// Switch back to tab 1.
|
||||
Services.obs.addObserver(inspectorSecondFocusTab1,
|
||||
InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY, false);
|
||||
gBrowser.selectedTab = tab1;
|
||||
});
|
||||
}
|
||||
|
||||
function inspectorSecondFocusTab1()
|
||||
|
@ -29,6 +29,7 @@
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
* Michael Ratcliffe <mratcliffe@mozilla.com>
|
||||
* Joe Walker <jwalker@mozilla.com>
|
||||
* Sonny Piers <sonny.piers@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -284,6 +285,9 @@ const ERRORS = { LOG_MESSAGE_MISSING_ARGS:
|
||||
// The indent of a console group in pixels.
|
||||
const GROUP_INDENT = 12;
|
||||
|
||||
// The pref prefix for webconsole filters
|
||||
const PREFS_PREFIX = "devtools.webconsole.filter.";
|
||||
|
||||
/**
|
||||
* Implements the nsIStreamListener and nsIRequestObserver interface. Used
|
||||
* within the HS_httpObserverFactory function to get the response body of
|
||||
@ -1790,9 +1794,18 @@ HUD_SERVICE.prototype =
|
||||
if (!aHUDId){
|
||||
throw new Error(ERRORS.MISSING_ARGS);
|
||||
}
|
||||
this.filterPrefs[aHUDId] = this.defaultFilterPrefs;
|
||||
// init storage objects:
|
||||
this.storage.createDisplay(aHUDId);
|
||||
this.filterPrefs[aHUDId] = {
|
||||
network: Services.prefs.getBoolPref(PREFS_PREFIX + "network"),
|
||||
networkinfo: Services.prefs.getBoolPref(PREFS_PREFIX + "networkinfo"),
|
||||
csserror: Services.prefs.getBoolPref(PREFS_PREFIX + "csserror"),
|
||||
cssparser: Services.prefs.getBoolPref(PREFS_PREFIX + "cssparser"),
|
||||
exception: Services.prefs.getBoolPref(PREFS_PREFIX + "exception"),
|
||||
jswarn: Services.prefs.getBoolPref(PREFS_PREFIX + "jswarn"),
|
||||
error: Services.prefs.getBoolPref(PREFS_PREFIX + "error"),
|
||||
info: Services.prefs.getBoolPref(PREFS_PREFIX + "info"),
|
||||
warn: Services.prefs.getBoolPref(PREFS_PREFIX + "warn"),
|
||||
log: Services.prefs.getBoolPref(PREFS_PREFIX + "log"),
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1839,9 +1852,6 @@ HUD_SERVICE.prototype =
|
||||
|
||||
delete this.hudReferences[aHUDId];
|
||||
|
||||
// remove the related storage object
|
||||
this.storage.removeDisplay(aHUDId);
|
||||
|
||||
for (let windowID in this.windowIds) {
|
||||
if (this.windowIds[windowID] == aHUDId) {
|
||||
delete this.windowIds[windowID];
|
||||
@ -1882,10 +1892,6 @@ HUD_SERVICE.prototype =
|
||||
return;
|
||||
}
|
||||
|
||||
this.storage = new ConsoleStorage();
|
||||
this.defaultFilterPrefs = this.storage.defaultDisplayPrefs;
|
||||
this.defaultGlobalConsolePrefs = this.storage.defaultGlobalConsolePrefs;
|
||||
|
||||
// begin observing HTTP traffic
|
||||
this.startHTTPObservation();
|
||||
|
||||
@ -1911,10 +1917,7 @@ HUD_SERVICE.prototype =
|
||||
this.openRequests = {};
|
||||
this.openResponseHeaders = {};
|
||||
|
||||
// delete the storage as it holds onto channels
|
||||
delete this.storage;
|
||||
delete this.defaultFilterPrefs;
|
||||
delete this.defaultGlobalConsolePrefs;
|
||||
|
||||
delete this.lastFinishedRequestCallback;
|
||||
|
||||
@ -3938,7 +3941,7 @@ HeadsUpDisplay.prototype = {
|
||||
let menuPopup = this.makeXULNode("menupopup");
|
||||
toolbarButton.appendChild(menuPopup);
|
||||
|
||||
let allChecked = true;
|
||||
let someChecked = false;
|
||||
for (let i = 0; i < aDescriptor.severities.length; i++) {
|
||||
let severity = aDescriptor.severities[i];
|
||||
let menuItem = this.makeXULNode("menuitem");
|
||||
@ -3952,8 +3955,8 @@ HeadsUpDisplay.prototype = {
|
||||
|
||||
let checked = this.filterPrefs[prefKey];
|
||||
menuItem.setAttribute("checked", checked);
|
||||
if (!checked) {
|
||||
allChecked = false;
|
||||
if (checked) {
|
||||
someChecked = true;
|
||||
}
|
||||
|
||||
menuItem.addEventListener("command", toggleFilter, false);
|
||||
@ -3961,7 +3964,7 @@ HeadsUpDisplay.prototype = {
|
||||
menuPopup.appendChild(menuItem);
|
||||
}
|
||||
|
||||
toolbarButton.setAttribute("checked", allChecked);
|
||||
toolbarButton.setAttribute("checked", someChecked);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -6331,175 +6334,6 @@ HeadsUpDisplayUICommands = {
|
||||
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ConsoleStorage
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var prefs = Services.prefs;
|
||||
|
||||
const GLOBAL_STORAGE_INDEX_ID = "GLOBAL_CONSOLE";
|
||||
const PREFS_PREFIX = "devtools.webconsole.filter.";
|
||||
const PREFS = { network: PREFS_PREFIX + "network",
|
||||
networkinfo: PREFS_PREFIX + "networkinfo",
|
||||
csserror: PREFS_PREFIX + "csserror",
|
||||
cssparser: PREFS_PREFIX + "cssparser",
|
||||
exception: PREFS_PREFIX + "exception",
|
||||
jswarn: PREFS_PREFIX + "jswarn",
|
||||
error: PREFS_PREFIX + "error",
|
||||
info: PREFS_PREFIX + "info",
|
||||
warn: PREFS_PREFIX + "warn",
|
||||
log: PREFS_PREFIX + "log",
|
||||
};
|
||||
|
||||
function ConsoleStorage()
|
||||
{
|
||||
this.sequencer = null;
|
||||
this.consoleDisplays = {};
|
||||
// each display will have an index that tracks each ConsoleEntry
|
||||
this.displayIndexes = {};
|
||||
this.globalStorageIndex = [];
|
||||
this.globalDisplay = {};
|
||||
this.createDisplay(GLOBAL_STORAGE_INDEX_ID);
|
||||
// TODO: need to create a method that truncates the message
|
||||
// see bug 570543
|
||||
|
||||
this.defaultDisplayPrefs = {
|
||||
network: prefs.getBoolPref(PREFS.network),
|
||||
networkinfo: prefs.getBoolPref(PREFS.networkinfo),
|
||||
csserror: prefs.getBoolPref(PREFS.csserror),
|
||||
cssparser: prefs.getBoolPref(PREFS.cssparser),
|
||||
exception: prefs.getBoolPref(PREFS.exception),
|
||||
jswarn: prefs.getBoolPref(PREFS.jswarn),
|
||||
error: prefs.getBoolPref(PREFS.error),
|
||||
info: prefs.getBoolPref(PREFS.info),
|
||||
warn: prefs.getBoolPref(PREFS.warn),
|
||||
log: prefs.getBoolPref(PREFS.log),
|
||||
};
|
||||
}
|
||||
|
||||
ConsoleStorage.prototype = {
|
||||
|
||||
sequenceId: function CS_sequencerId()
|
||||
{
|
||||
if (!this.sequencer) {
|
||||
this.sequencer = this.createSequencer();
|
||||
}
|
||||
return this.sequencer.next();
|
||||
},
|
||||
|
||||
createSequencer: function CS_createSequencer()
|
||||
{
|
||||
function sequencer(aInt) {
|
||||
while(1) {
|
||||
aInt++;
|
||||
yield aInt;
|
||||
}
|
||||
}
|
||||
return sequencer(-1);
|
||||
},
|
||||
|
||||
globalStore: function CS_globalStore(aIndex)
|
||||
{
|
||||
return this.displayStore(GLOBAL_CONSOLE_DOM_NODE_ID);
|
||||
},
|
||||
|
||||
displayStore: function CS_displayStore(aId)
|
||||
{
|
||||
var self = this;
|
||||
var idx = -1;
|
||||
var id = aId;
|
||||
var aLength = self.displayIndexes[id].length;
|
||||
|
||||
function displayStoreGenerator(aInt, aLength)
|
||||
{
|
||||
// create a generator object to iterate through any of the display stores
|
||||
// from any index-starting-point
|
||||
while(1) {
|
||||
// throw if we exceed the length of displayIndexes?
|
||||
aInt++;
|
||||
var indexIt = self.displayIndexes[id];
|
||||
var index = indexIt[aInt];
|
||||
if (aLength < aInt) {
|
||||
// try to see if we have more entries:
|
||||
var newLength = self.displayIndexes[id].length;
|
||||
if (newLength > aLength) {
|
||||
aLength = newLength;
|
||||
}
|
||||
else {
|
||||
throw new StopIteration();
|
||||
}
|
||||
}
|
||||
var entry = self.consoleDisplays[id][index];
|
||||
yield entry;
|
||||
}
|
||||
}
|
||||
|
||||
return displayStoreGenerator(-1, aLength);
|
||||
},
|
||||
|
||||
recordEntries: function CS_recordEntries(aHUDId, aConfigArray)
|
||||
{
|
||||
var len = aConfigArray.length;
|
||||
for (var i = 0; i < len; i++){
|
||||
this.recordEntry(aHUDId, aConfigArray[i]);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
recordEntry: function CS_recordEntry(aHUDId, aConfig)
|
||||
{
|
||||
var id = this.sequenceId();
|
||||
|
||||
this.globalStorageIndex[id] = { hudId: aHUDId };
|
||||
|
||||
var displayStorage = this.consoleDisplays[aHUDId];
|
||||
|
||||
var displayIndex = this.displayIndexes[aHUDId];
|
||||
|
||||
if (displayStorage && displayIndex) {
|
||||
var entry = new ConsoleEntry(aConfig, id);
|
||||
displayIndex.push(entry.id);
|
||||
displayStorage[entry.id] = entry;
|
||||
return entry;
|
||||
}
|
||||
else {
|
||||
throw new Error("Cannot get displayStorage or index object for id " + aHUDId);
|
||||
}
|
||||
},
|
||||
|
||||
getEntry: function CS_getEntry(aId)
|
||||
{
|
||||
var display = this.globalStorageIndex[aId];
|
||||
var storName = display.hudId;
|
||||
return this.consoleDisplays[storName][aId];
|
||||
},
|
||||
|
||||
updateEntry: function CS_updateEntry(aUUID)
|
||||
{
|
||||
// update an individual entry
|
||||
// TODO: see bug 568634
|
||||
},
|
||||
|
||||
createDisplay: function CS_createdisplay(aId)
|
||||
{
|
||||
if (!this.consoleDisplays[aId]) {
|
||||
this.consoleDisplays[aId] = {};
|
||||
this.displayIndexes[aId] = [];
|
||||
}
|
||||
},
|
||||
|
||||
removeDisplay: function CS_removeDisplay(aId)
|
||||
{
|
||||
try {
|
||||
delete this.consoleDisplays[aId];
|
||||
delete this.displayIndexes[aId];
|
||||
}
|
||||
catch (ex) {
|
||||
Cu.reportError("Could not remove console display for id " + aId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A Console log entry
|
||||
*
|
||||
|
@ -49,7 +49,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" href="chrome://global/skin/webConsole_networkPanel.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/devtools/webconsole_networkpanel.css" type="text/css"/>
|
||||
</head>
|
||||
<body role="application">
|
||||
<table id="header">
|
||||
|
@ -22,6 +22,7 @@
|
||||
# Patrick Walton <pcwalton@mozilla.com>
|
||||
# Mihai Șucan <mihai.sucan@gmail.com>
|
||||
# Rob Campbell <rcampbell@mozilla.com>
|
||||
# Sonny Piers <sonny.piers@gmail.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
@ -81,10 +82,6 @@ _BROWSER_TEST_FILES = \
|
||||
browser_webconsole_property_panel.js \
|
||||
browser_webconsole_property_provider.js \
|
||||
browser_webconsole_registries.js \
|
||||
browser_webconsole_storage_create_display.js \
|
||||
browser_webconsole_storage_iteration.js \
|
||||
browser_webconsole_storage_record_entry.js \
|
||||
browser_webconsole_storage_record_many_entries.js \
|
||||
browser_webconsole_bug_587617_output_copy.js \
|
||||
browser_webconsole_bug_585237_line_limit.js \
|
||||
browser_webconsole_bug_581231_close_button.js \
|
||||
|
@ -3,57 +3,114 @@
|
||||
|
||||
function test() {
|
||||
let prefService = Services.prefs;
|
||||
let prefs = [
|
||||
"network",
|
||||
"networkinfo",
|
||||
"csserror",
|
||||
"cssparser",
|
||||
"exception",
|
||||
"jswarn",
|
||||
"error",
|
||||
"warn",
|
||||
"info",
|
||||
"log"
|
||||
];
|
||||
|
||||
//Set all prefs to true
|
||||
prefs.forEach(function(pref) {
|
||||
prefService.setBoolPref("devtools.webconsole.filter." + pref, true);
|
||||
});
|
||||
let prefs = {
|
||||
"net": [
|
||||
"network",
|
||||
"networkinfo"
|
||||
],
|
||||
"css": [
|
||||
"csserror",
|
||||
"cssparser"
|
||||
],
|
||||
"js": [
|
||||
"exception",
|
||||
"jswarn"
|
||||
],
|
||||
"logging": [
|
||||
"error",
|
||||
"warn",
|
||||
"info",
|
||||
"log"
|
||||
]
|
||||
};
|
||||
|
||||
// Set all prefs to true
|
||||
for (let category in prefs) {
|
||||
prefs[category].forEach(function(pref) {
|
||||
prefService.setBoolPref("devtools.webconsole.filter." + pref, true);
|
||||
});
|
||||
}
|
||||
|
||||
addTab("about:blank");
|
||||
openConsole();
|
||||
|
||||
let hud = HUDService.getHudByWindow(content);
|
||||
let hudId = HUDService.getHudIdByWindow(content);
|
||||
|
||||
//Check if the filters menuitems exists and is checked
|
||||
prefs.forEach(function(pref) {
|
||||
let checked = hud.HUDBox.querySelector("menuitem[prefKey=" + pref + "]").
|
||||
getAttribute("checked");
|
||||
is(checked, "true", "menuitem for " + pref + " exists and is checked");
|
||||
});
|
||||
|
||||
//Set all prefs to false
|
||||
prefs.forEach(function(pref) {
|
||||
HUDService.setFilterState(hudId, pref, false);
|
||||
});
|
||||
let hud = HUDService.getHudByWindow(content);
|
||||
|
||||
// Check if the filters menuitems exists and are checked
|
||||
for (let category in prefs) {
|
||||
let button = hud.HUDBox.querySelector(".webconsole-filter-button[category=\""
|
||||
+ category + "\"]");
|
||||
ok(isChecked(button), "main button for " + category + " category is checked");
|
||||
|
||||
prefs[category].forEach(function(pref) {
|
||||
let menuitem = hud.HUDBox.querySelector("menuitem[prefKey=" + pref + "]");
|
||||
ok(isChecked(menuitem), "menuitem for " + pref + " is checked");
|
||||
});
|
||||
}
|
||||
|
||||
// Set all prefs to false
|
||||
for (let category in prefs) {
|
||||
prefs[category].forEach(function(pref) {
|
||||
HUDService.setFilterState(hud.hudId, pref, false);
|
||||
});
|
||||
}
|
||||
|
||||
//Re-init the console
|
||||
closeConsole();
|
||||
openConsole();
|
||||
|
||||
hud = HUDService.getHudByWindow(content);
|
||||
|
||||
//Check if filters menuitems exists and are unchecked
|
||||
prefs.forEach(function(pref) {
|
||||
let checked = hud.HUDBox.querySelector("menuitem[prefKey=" + pref + "]").
|
||||
getAttribute("checked");
|
||||
is(checked, "false", "menuitem for " + pref + " exists and is not checked");
|
||||
prefService.clearUserPref("devtools.webconsole.filter." + pref);
|
||||
});
|
||||
|
||||
|
||||
// Check if the filter button and menuitems are unchecked
|
||||
for (let category in prefs) {
|
||||
let button = hud.HUDBox.querySelector(".webconsole-filter-button[category=\""
|
||||
+ category + "\"]");
|
||||
ok(isUnchecked(button), "main button for " + category + " category is not checked");
|
||||
|
||||
prefs[category].forEach(function(pref) {
|
||||
let menuitem = hud.HUDBox.querySelector("menuitem[prefKey=" + pref + "]");
|
||||
ok(isUnchecked(menuitem), "menuitem for " + pref + " is not checked");
|
||||
});
|
||||
}
|
||||
|
||||
// Set first pref in each category to true
|
||||
for (let category in prefs) {
|
||||
HUDService.setFilterState(hud.hudId, prefs[category][0], true);
|
||||
}
|
||||
|
||||
// Re-init the console
|
||||
closeConsole();
|
||||
openConsole();
|
||||
|
||||
hud = HUDService.getHudByWindow(content);
|
||||
|
||||
// Check the main category button is checked and first menuitem is checked
|
||||
for (let category in prefs) {
|
||||
let button = hud.HUDBox.querySelector(".webconsole-filter-button[category=\""
|
||||
+ category + "\"]");
|
||||
ok(isChecked(button), category + " button is checked when first pref is true");
|
||||
|
||||
let pref = prefs[category][0];
|
||||
let menuitem = hud.HUDBox.querySelector("menuitem[prefKey=" + pref + "]");
|
||||
ok(isChecked(menuitem), "first " + category + " menuitem is checked");
|
||||
}
|
||||
|
||||
// Clear prefs
|
||||
for (let category in prefs) {
|
||||
prefs[category].forEach(function(pref) {
|
||||
prefService.clearUserPref("devtools.webconsole.filter." + pref);
|
||||
});
|
||||
}
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
function isChecked(aNode) {
|
||||
return aNode.getAttribute("checked") === "true";
|
||||
}
|
||||
|
||||
function isUnchecked(aNode) {
|
||||
return aNode.getAttribute("checked") === "false";
|
||||
}
|
||||
|
@ -1,92 +0,0 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is DevTools test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* David Dahl <ddahl@mozilla.com>
|
||||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
* Julian Viereck <jviereck@mozilla.com>
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// Test that the iterator API of the console message store works.
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//browser/test-console.html";
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", testStorageIteration, false);
|
||||
}
|
||||
|
||||
function testStorageIteration() {
|
||||
browser.removeEventListener("DOMContentLoaded", testStorageIteration,
|
||||
false);
|
||||
|
||||
openConsole();
|
||||
|
||||
let cs = HUDService.storage;
|
||||
|
||||
// Must have enough entries present to avoid exhausting the iterators below.
|
||||
cs.createDisplay("foo");
|
||||
for (let i = 0; i < 300; i++) {
|
||||
cs.recordEntry("foo", { logLevel: "network", message: "foo" });
|
||||
}
|
||||
|
||||
var id = "foo";
|
||||
var it = cs.displayStore(id);
|
||||
var entry = it.next();
|
||||
var entry2 = it.next();
|
||||
|
||||
let entries = [];
|
||||
for (var i = 0; i < 100; i++) {
|
||||
let _entry = it.next();
|
||||
entries.push(_entry);
|
||||
}
|
||||
|
||||
ok(entries.length == 100, "entries length == 100");
|
||||
|
||||
let entries2 = [];
|
||||
|
||||
for (var i = 0; i < 100; i++){
|
||||
let _entry = it.next();
|
||||
entries2.push(_entry);
|
||||
}
|
||||
|
||||
ok(entries[0].id != entries2[0].id,
|
||||
"two distinct pages of log entries");
|
||||
|
||||
cs.removeDisplay("foo");
|
||||
cs = null;
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
@ -1,81 +0,0 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is DevTools test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* David Dahl <ddahl@mozilla.com>
|
||||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
* Julian Viereck <jviereck@mozilla.com>
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// Tests that the recordEntry() method of the console store works.
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//browser/test-console.html";
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", testStorageRecordEntry,
|
||||
false);
|
||||
}
|
||||
|
||||
function testStorageRecordEntry() {
|
||||
browser.removeEventListener("DOMContentLoaded", testStorageRecordEntry,
|
||||
false);
|
||||
openConsole();
|
||||
|
||||
let cs = HUDService.storage;
|
||||
|
||||
cs.createDisplay("foo");
|
||||
|
||||
var config = {
|
||||
logLevel: "network",
|
||||
message: "HumminaHummina!",
|
||||
activity: {
|
||||
stage: "barStage",
|
||||
data: "bar bar bar bar"
|
||||
}
|
||||
};
|
||||
var entry = cs.recordEntry("foo", config);
|
||||
var res = entry.id;
|
||||
ok(entry.id != null, "Entry.id is: " + res);
|
||||
ok(cs.displayIndexes["foo"].length == 1,
|
||||
"We added one entry.");
|
||||
entry = cs.getEntry(res);
|
||||
ok(entry.id > -1,
|
||||
"We got an entry through the global interface");
|
||||
|
||||
cs.removeDisplay("foo");
|
||||
cs = null;
|
||||
finishTest();
|
||||
}
|
||||
|
@ -134,6 +134,7 @@
|
||||
@BINPATH@/components/directory.xpt
|
||||
@BINPATH@/components/docshell.xpt
|
||||
@BINPATH@/components/dom.xpt
|
||||
@BINPATH@/components/dom_apps.xpt
|
||||
@BINPATH@/components/dom_base.xpt
|
||||
@BINPATH@/components/dom_battery.xpt
|
||||
@BINPATH@/components/dom_canvas.xpt
|
||||
@ -375,6 +376,8 @@
|
||||
#endif
|
||||
@BINPATH@/components/TelemetryPing.js
|
||||
@BINPATH@/components/TelemetryPing.manifest
|
||||
@BINPATH@/components/Webapps.js
|
||||
@BINPATH@/components/Webapps.manifest
|
||||
|
||||
; Modules
|
||||
@BINPATH@/modules/*
|
||||
|
@ -252,6 +252,7 @@ res/fonts/mathfontMath4.properties
|
||||
res/fonts/mathfontPUA.properties
|
||||
res/fonts/pangoFontEncoding.properties
|
||||
res/forms.css
|
||||
res/full-screen-override.css
|
||||
res/hiddenWindow.html
|
||||
res/html.css
|
||||
res/html/gopher-audio.gif
|
||||
|
@ -244,18 +244,16 @@ puAlertText=Click here for details
|
||||
|
||||
# Geolocation UI
|
||||
|
||||
# LOCALIZATION NOTE (geolocation.shareLocation geolocation.dontShareLocation geolocation.alwaysShare geolocation.neverShare):
|
||||
# LOCALIZATION NOTE (geolocation.shareLocation geolocation.alwaysShareLocation geolocation.neverShareLocation):
|
||||
#If you're having trouble with the word Share, please use Allow and Block in your language.
|
||||
geolocation.shareLocation=Share Location
|
||||
geolocation.shareLocation.accesskey=a
|
||||
geolocation.dontShareLocation=Don't Share
|
||||
geolocation.dontShareLocation.accesskey=o
|
||||
geolocation.alwaysShare=Always Share
|
||||
geolocation.alwaysShare.accesskey=A
|
||||
geolocation.neverShare=Never Share
|
||||
geolocation.neverShare.accesskey=N
|
||||
geolocation.siteWantsToKnow=%S wants to know your location.
|
||||
geolocation.fileWantsToKnow=The file %S wants to know your location.
|
||||
geolocation.alwaysShareLocation=Always Share Location
|
||||
geolocation.alwaysShareLocation.accesskey=A
|
||||
geolocation.neverShareLocation=Never Share Location
|
||||
geolocation.neverShareLocation.accesskey=N
|
||||
geolocation.shareWithSite=Would you like to share your location with %S?
|
||||
geolocation.shareWithFile=Would you like to share your location with the file %S?
|
||||
# LOCALIZATION NOTE (geolocation.learnMore): Use the unicode ellipsis char, \u2026,
|
||||
# or use "..." if \u2026 doesn't suit traditions in your locale.
|
||||
geolocation.learnMore=Learn More…
|
||||
|
@ -1959,7 +1959,7 @@ panel[dimmed="true"] {
|
||||
/* Highlighter */
|
||||
|
||||
.highlighter-veil {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
background-color: rgba(25, 25, 25, 0.5);
|
||||
}
|
||||
|
||||
#highlighter-closebutton {
|
||||
|
@ -70,7 +70,7 @@
|
||||
}
|
||||
|
||||
.hud-msg-node {
|
||||
list-style-image: url(chrome://global/skin/icons/webconsole.png);
|
||||
list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
|
||||
-moz-image-region: rect(0, 1px, 0, 0);
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@
|
||||
.webconsole-filter-button > .toolbarbutton-menubutton-button,
|
||||
.webconsole-filter-button:not([type="menu-button"]) {
|
||||
-moz-box-orient: horizontal;
|
||||
list-style-image: url("chrome://global/skin/icons/webconsole.png");
|
||||
list-style-image: url("chrome://browser/skin/devtools/webconsole.png");
|
||||
}
|
||||
|
||||
/* Network styles */
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@ -86,6 +86,9 @@ browser.jar:
|
||||
skin/classic/browser/devtools/arrows.png (devtools/arrows.png)
|
||||
skin/classic/browser/devtools/goto-mdn.png (devtools/goto-mdn.png)
|
||||
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
|
||||
skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
||||
skin/classic/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
|
||||
skin/classic/browser/devtools/webconsole.png (devtools/webconsole.png)
|
||||
skin/classic/browser/devtools/gcli.css (devtools/gcli.css)
|
||||
skin/classic/browser/devtools/breadcrumbs/ltr-end-pressed.png (devtools/breadcrumbs/ltr-end-pressed.png)
|
||||
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png (devtools/breadcrumbs/ltr-end-selected-pressed.png)
|
||||
|
@ -2690,7 +2690,7 @@ panel[dimmed="true"] {
|
||||
/* Highlighter */
|
||||
|
||||
.highlighter-veil {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
background-color: rgba(25, 25, 25, 0.5);
|
||||
}
|
||||
|
||||
#highlighter-closebutton {
|
||||
|
@ -37,7 +37,7 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
%include shared.inc
|
||||
%include ../shared.inc
|
||||
|
||||
.hud-box {
|
||||
border-bottom: 1px solid #aaa;
|
||||
@ -73,7 +73,7 @@
|
||||
}
|
||||
|
||||
.hud-msg-node {
|
||||
list-style-image: url(chrome://global/skin/icons/webconsole.png);
|
||||
list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
|
||||
-moz-image-region: rect(0, 1px, 0, 0);
|
||||
}
|
||||
|
||||
@ -187,7 +187,7 @@
|
||||
-moz-appearance: none;
|
||||
margin: 0;
|
||||
padding: 1px 0;
|
||||
list-style-image: url("chrome://global/skin/icons/webconsole.png");
|
||||
list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
|
||||
-moz-box-orient: horizontal;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@ -127,6 +127,9 @@ browser.jar:
|
||||
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
|
||||
skin/classic/browser/devtools/gcli.css (devtools/gcli.css)
|
||||
skin/classic/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png)
|
||||
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
||||
skin/classic/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
|
||||
skin/classic/browser/devtools/webconsole.png (devtools/webconsole.png)
|
||||
skin/classic/browser/devtools/breadcrumbs/ltr-end-pressed.png (devtools/breadcrumbs/ltr-end-pressed.png)
|
||||
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png (devtools/breadcrumbs/ltr-end-selected-pressed.png)
|
||||
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected.png (devtools/breadcrumbs/ltr-end-selected.png)
|
||||
|
@ -75,6 +75,11 @@
|
||||
-moz-margin-start: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.menu-accel,
|
||||
.menu-iconic-accel {
|
||||
color: graytext;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (-moz-windows-compositor) {
|
||||
|
@ -2625,7 +2625,7 @@ panel[dimmed="true"] {
|
||||
/* Highlighter */
|
||||
|
||||
.highlighter-veil {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
background-color: rgba(25, 25, 25, 0.5);
|
||||
}
|
||||
|
||||
#highlighter-closebutton {
|
||||
|
@ -69,7 +69,7 @@
|
||||
}
|
||||
|
||||
.hud-msg-node {
|
||||
list-style-image: url(chrome://global/skin/icons/webconsole.png);
|
||||
list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
|
||||
-moz-image-region: rect(0, 1px, 0, 0);
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@
|
||||
|
||||
.webconsole-filter-button > .toolbarbutton-menubutton-button {
|
||||
-moz-box-orient: horizontal;
|
||||
list-style-image: url("chrome://global/skin/icons/webconsole.png");
|
||||
list-style-image: url("chrome://browser/skin/devtools/webconsole.png");
|
||||
}
|
||||
|
||||
.webconsole-filter-button > .toolbarbutton-menubutton-button,
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@ -111,6 +111,9 @@ browser.jar:
|
||||
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
|
||||
skin/classic/browser/devtools/gcli.css (devtools/gcli.css)
|
||||
skin/classic/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png)
|
||||
skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
||||
skin/classic/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
|
||||
skin/classic/browser/devtools/webconsole.png (devtools/webconsole.png)
|
||||
skin/classic/browser/devtools/breadcrumbs/ltr-end-pressed.png (devtools/breadcrumbs/ltr-end-pressed.png)
|
||||
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png (devtools/breadcrumbs/ltr-end-selected-pressed.png)
|
||||
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected.png (devtools/breadcrumbs/ltr-end-selected.png)
|
||||
@ -264,6 +267,9 @@ browser.jar:
|
||||
skin/classic/aero/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
|
||||
skin/classic/aero/browser/devtools/gcli.css (devtools/gcli.css)
|
||||
skin/classic/aero/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png)
|
||||
skin/classic/aero/browser/devtools/webconsole.css (devtools/webconsole.css)
|
||||
skin/classic/aero/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
|
||||
skin/classic/aero/browser/devtools/webconsole.png (devtools/webconsole.png)
|
||||
skin/classic/aero/browser/devtools/breadcrumbs/ltr-end-pressed.png (devtools/breadcrumbs/ltr-end-pressed.png)
|
||||
skin/classic/aero/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png (devtools/breadcrumbs/ltr-end-selected-pressed.png)
|
||||
skin/classic/aero/browser/devtools/breadcrumbs/ltr-end-selected.png (devtools/breadcrumbs/ltr-end-selected.png)
|
||||
|
@ -138,7 +138,8 @@ log = logging.getLogger()
|
||||
|
||||
def isURL(thing):
|
||||
"""Return True if |thing| looks like a URL."""
|
||||
return urlparse(thing).scheme != ''
|
||||
# We want to download URLs like http://... but not Windows paths like c:\...
|
||||
return len(urlparse(thing).scheme) >= 2
|
||||
|
||||
def addCommonOptions(parser, defaults={}):
|
||||
parser.add_option("--xre-path",
|
||||
@ -284,7 +285,7 @@ def getDebuggerInfo(directory, debugger, debuggerArgs, debuggerInteractive = Fal
|
||||
debuggerInfo["args"] = debuggerArgs.split()
|
||||
if debuggerInteractive:
|
||||
debuggerInfo["interactive"] = debuggerInteractive
|
||||
|
||||
|
||||
return debuggerInfo
|
||||
|
||||
|
||||
|
@ -2491,6 +2491,16 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
||||
&haveCharset, &charsetStart,
|
||||
&charsetEnd);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// special case: the extracted charset is quoted with single quotes
|
||||
// -- for the purpose of preserving what was set we want to handle
|
||||
// them as delimiters (although they aren't really)
|
||||
if (specifiedCharset.Length() >= 2 &&
|
||||
specifiedCharset.First() == '\'' &&
|
||||
specifiedCharset.Last() == '\'') {
|
||||
specifiedCharset = Substring(specifiedCharset, 1,
|
||||
specifiedCharset.Length() - 2);
|
||||
}
|
||||
|
||||
// If the content-type the page set already has a charset parameter,
|
||||
// and it's the same charset, up to case, as |charset|, just send the
|
||||
// page-set content-type header. Apparently at least
|
||||
|
@ -2064,6 +2064,10 @@ void nsHTMLMediaElement::MetadataLoaded(PRUint32 aChannels, PRUint32 aRate)
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
|
||||
if (!mBegun) {
|
||||
// Something ended our downloaded. We're probably done with downloading already.
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
|
||||
}
|
||||
if (mDecoder && mDecoder->IsSeekable()) {
|
||||
ProcessMediaFragmentURI();
|
||||
mDecoder->SetEndTime(mFragmentEnd);
|
||||
|
@ -1293,12 +1293,10 @@ nsHTMLDocument::GetURL(nsAString& aURL)
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
nsHTMLDocument::GetBody(nsresult *aResult)
|
||||
nsHTMLDocument::GetBody()
|
||||
{
|
||||
Element* body = GetBodyElement();
|
||||
|
||||
*aResult = NS_OK;
|
||||
|
||||
if (body) {
|
||||
// There is a body element, return that as the body.
|
||||
return body;
|
||||
@ -1317,10 +1315,9 @@ nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody)
|
||||
{
|
||||
*aBody = nsnull;
|
||||
|
||||
nsresult rv;
|
||||
nsIContent *body = GetBody(&rv);
|
||||
nsIContent *body = GetBody();
|
||||
|
||||
return body ? CallQueryInterface(body, aBody) : rv;
|
||||
return body ? CallQueryInterface(body, aBody) : NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -135,7 +135,8 @@ public:
|
||||
nsWrapperCache **aCache,
|
||||
nsresult *aResult);
|
||||
|
||||
nsIContent *GetBody(nsresult *aResult);
|
||||
nsIContent *GetBody();
|
||||
Element *GetHead() { return GetHeadElement(); }
|
||||
already_AddRefed<nsContentList> GetElementsByName(const nsAString & aName)
|
||||
{
|
||||
return NS_GetFuncStringContentList(this, MatchNameAttribute, nsnull,
|
||||
|
@ -352,7 +352,7 @@ function MediaTestManager() {
|
||||
this.started = function(token) {
|
||||
this.tokens.push(token);
|
||||
this.numTestsRunning++;
|
||||
is(this.numTestsRunning, this.tokens.length, "[started] Length of array should match number of running tests");
|
||||
is(this.numTestsRunning, this.tokens.length, "[started " + token + "] Length of array should match number of running tests");
|
||||
}
|
||||
|
||||
// Registers that the test corresponding to 'token' has finished. Call when
|
||||
@ -366,7 +366,7 @@ function MediaTestManager() {
|
||||
this.tokens.splice(i, 1);
|
||||
}
|
||||
this.numTestsRunning--;
|
||||
is(this.numTestsRunning, this.tokens.length, "[finished] Length of array should match number of running tests");
|
||||
is(this.numTestsRunning, this.tokens.length, "[finished " + token + "] Length of array should match number of running tests");
|
||||
if (this.tokens.length < PARALLEL_TESTS) {
|
||||
this.nextTest();
|
||||
}
|
||||
|
@ -45,6 +45,10 @@ function log(m) {
|
||||
}
|
||||
|
||||
function maybeFinish(v, n) {
|
||||
if (v._finished) {
|
||||
return;
|
||||
}
|
||||
v._finished = true;
|
||||
log(n + ",");
|
||||
if (v.parentNode) {
|
||||
v.parentNode.removeChild(v);
|
||||
@ -56,8 +60,7 @@ function filename(uri) {
|
||||
return uri.substr(uri.lastIndexOf("/")+1);
|
||||
}
|
||||
|
||||
// Every test must have a setup(v) function, and must set _finished field on target v to
|
||||
// true when test is complete.
|
||||
// Every test must have a setup(v) function, and must call maybeFinish() when test is complete.
|
||||
var tests = [
|
||||
{
|
||||
// 1. Add preload:none video with src to document. Load should halt at NETWORK_IDLE and HAVE_NOTHING,
|
||||
@ -71,7 +74,6 @@ var tests = [
|
||||
is(v._gotLoadedMetaData, false, "(1) Must not get loadedmetadata.");
|
||||
is(v.readyState, v.HAVE_NOTHING, "(1) ReadyState must be HAVE_NOTHING");
|
||||
is(v.networkState, v.NETWORK_IDLE, "(1) NetworkState must be NETWORK_IDLE");
|
||||
v._finished = true;
|
||||
maybeFinish(v, 1);
|
||||
},
|
||||
|
||||
@ -79,7 +81,6 @@ var tests = [
|
||||
function(v) {
|
||||
v._gotLoadStart = false;
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "none";
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||
@ -98,7 +99,6 @@ var tests = [
|
||||
is(v._gotLoadedMetaData, true, "(2) Must get loadedmetadata.");
|
||||
ok(v.readyState >= v.HAVE_CURRENT_DATA, "(2) ReadyState must be >= HAVE_CURRENT_DATA");
|
||||
is(v.networkState, v.NETWORK_IDLE, "(2) NetworkState must be NETWORK_IDLE");
|
||||
v._finished = true;
|
||||
maybeFinish(v, 2);
|
||||
},
|
||||
|
||||
@ -106,7 +106,6 @@ var tests = [
|
||||
function(v) {
|
||||
v._gotLoadStart = false;
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "metadata";
|
||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
@ -123,7 +122,6 @@ var tests = [
|
||||
var v = e.target;
|
||||
is(v._gotLoadStart, true, "(3) Must get loadstart.");
|
||||
is(v._gotLoadedMetaData, true, "(3) Must get loadedmetadata.");
|
||||
v._finished = true;
|
||||
maybeFinish(v, 3);
|
||||
},
|
||||
|
||||
@ -131,7 +129,6 @@ var tests = [
|
||||
function(v) {
|
||||
v._gotLoadStart = false;
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "auto";
|
||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
@ -159,7 +156,6 @@ var tests = [
|
||||
ended:
|
||||
function(e) {
|
||||
ok(true, "(4) Got playback ended");
|
||||
e.target._finished = true;
|
||||
maybeFinish(e.target, 4);
|
||||
},
|
||||
|
||||
@ -168,7 +164,6 @@ var tests = [
|
||||
v._gotLoadStart = false;
|
||||
v._gotLoadedMetaData = false;
|
||||
v._gotSuspend = false;
|
||||
v._finished = false;
|
||||
v.preload = "none";
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||
@ -188,7 +183,6 @@ var tests = [
|
||||
is(v._gotLoadedMetaData, false, "(5) Must not get loadedmetadata.");
|
||||
is(v.readyState, v.HAVE_NOTHING, "(5) ReadyState must be HAVE_NOTHING");
|
||||
is(v.networkState, v.NETWORK_IDLE, "(5) NetworkState must be NETWORK_IDLE");
|
||||
v._finished = true;
|
||||
maybeFinish(v, 5);
|
||||
},
|
||||
|
||||
@ -196,7 +190,6 @@ var tests = [
|
||||
function(v) {
|
||||
v._gotLoadStart = false;
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "none";
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||
@ -215,7 +208,6 @@ var tests = [
|
||||
is(v._gotLoadedMetaData, false, "(6) Must not get loadedmetadata.");
|
||||
is(v.readyState, v.HAVE_NOTHING, "(6) ReadyState must be HAVE_NOTHING");
|
||||
is(v.networkState, v.NETWORK_IDLE, "(6) NetworkState must be NETWORK_IDLE");
|
||||
v._finished = true;
|
||||
maybeFinish(v, 6);
|
||||
},
|
||||
|
||||
@ -223,7 +215,6 @@ var tests = [
|
||||
function(v) {
|
||||
v._gotLoadStart = false;
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "none";
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||
@ -255,7 +246,6 @@ var tests = [
|
||||
function(e) {
|
||||
ok(true, "(7) Got playback ended");
|
||||
var v = e.target;
|
||||
v._finished = true;
|
||||
is(v._gotErrorEvent, true, "(7) Should get error event from first source load failure");
|
||||
maybeFinish(v, 7);
|
||||
},
|
||||
@ -264,7 +254,6 @@ var tests = [
|
||||
function(v) {
|
||||
v._gotLoadStart = false;
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "none";
|
||||
v._gotErrorEvent = false;
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
@ -291,14 +280,12 @@ var tests = [
|
||||
is(v._gotLoadedMetaData, true, "(8) Must get loadedmetadata.");
|
||||
ok(v.readyState >= v.HAVE_CURRENT_DATA, "(8) ReadyState must be >= HAVE_CURRENT_DATA on suspend.");
|
||||
is(v.networkState, v.NETWORK_IDLE, "(8) NetworkState must be NETWORK_IDLE when load is halted");
|
||||
v._finished = true;
|
||||
maybeFinish(v, 8);
|
||||
},
|
||||
|
||||
setup:
|
||||
function(v) {
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "none";
|
||||
v.addEventListener("loadstart", function(e){v.preload = "metadata";}, false);
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
@ -314,11 +301,8 @@ var tests = [
|
||||
canplaythrough:
|
||||
function(e) {
|
||||
var v = e.target;
|
||||
if (v._finished)
|
||||
return;
|
||||
is(v._gotLoadStart, true, "(9) Must get loadstart.");
|
||||
is(v._gotLoadedMetaData, true, "(9) Must get loadedmetadata.");
|
||||
v._finished = true;
|
||||
maybeFinish(v, 9);
|
||||
},
|
||||
|
||||
@ -326,7 +310,6 @@ var tests = [
|
||||
function(v) {
|
||||
v._gotLoadStart = false;
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "metadata";
|
||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
@ -342,14 +325,12 @@ var tests = [
|
||||
function(e) {
|
||||
var v = e.target;
|
||||
is(v._gotLoadedMetaData, true, "(10) Must get loadedmetadata.");
|
||||
v._finished = true;
|
||||
maybeFinish(v, 10);
|
||||
},
|
||||
|
||||
setup:
|
||||
function(v) {
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "none";
|
||||
v.addEventListener("loadstart", function(e){v.preload = "auto";}, false);
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
@ -366,14 +347,12 @@ var tests = [
|
||||
is(v._gotLoadedMetaData, true, "(11) Must get loadedmetadata.");
|
||||
ok(v.readyState >= v.HAVE_CURRENT_DATA, "(11) ReadyState must be >= HAVE_CURRENT_DATA.");
|
||||
is(v.networkState, v.NETWORK_IDLE, "(11) NetworkState must be NETWORK_IDLE.");
|
||||
v._finished = true;
|
||||
maybeFinish(v, 11);
|
||||
},
|
||||
|
||||
setup:
|
||||
function(v) {
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "none";
|
||||
v.addEventListener("loadstart", function(e){v.preload = "metadata";}, false);
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
@ -390,7 +369,6 @@ var tests = [
|
||||
var v = e.target;
|
||||
is(v._gotLoadedMetaData, true, "(12) Must get loadedmetadata.");
|
||||
is(v._gotLoadStart, true, "(12) Must get loadstart.");
|
||||
v._finished = true;
|
||||
maybeFinish(v, 12);
|
||||
},
|
||||
|
||||
@ -398,7 +376,6 @@ var tests = [
|
||||
function(v) {
|
||||
v._gotLoadStart = false;
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "auto";
|
||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
@ -419,7 +396,6 @@ var tests = [
|
||||
is(v._gotLoadedMetaData, true, "(13) Must get loadedmetadata.");
|
||||
ok(v.readyState >= v.HAVE_CURRENT_DATA, "(13) ReadyState must be >= HAVE_CURRENT_DATA.");
|
||||
is(v.networkState, v.NETWORK_IDLE, "(13) NetworkState must be NETWORK_IDLE.");
|
||||
v._finished = true;
|
||||
maybeFinish(v, 13);
|
||||
},
|
||||
|
||||
@ -427,7 +403,6 @@ var tests = [
|
||||
function(v) {
|
||||
v._gotLoadStart = false;
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "metadata";
|
||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
@ -453,7 +428,6 @@ var tests = [
|
||||
function(e) {
|
||||
ok(true, "(14) Got playback ended");
|
||||
var v = e.target;
|
||||
v._finished = true;
|
||||
maybeFinish(v, 14);
|
||||
},
|
||||
|
||||
@ -461,7 +435,6 @@ var tests = [
|
||||
function(v) {
|
||||
v._gotLoadStart = false;
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "metadata";
|
||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||
v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
|
||||
@ -478,7 +451,6 @@ var tests = [
|
||||
function(e) {
|
||||
ok(true, "(15) Got playback ended.");
|
||||
var v = e.target;
|
||||
v._finished = true;
|
||||
maybeFinish(v, 15);
|
||||
},
|
||||
|
||||
@ -486,7 +458,6 @@ var tests = [
|
||||
function(v) {
|
||||
v._gotLoadStart = false;
|
||||
v._gotLoadedMetaData = false;
|
||||
v._finished = false;
|
||||
v.preload = "none";
|
||||
v.autoplay = true;
|
||||
v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
|
||||
@ -502,13 +473,11 @@ var tests = [
|
||||
function(e) {
|
||||
ok(true, "(16) Got playback ended.");
|
||||
var v = e.target;
|
||||
v._finished = true;
|
||||
maybeFinish(v, 16);
|
||||
},
|
||||
|
||||
setup:
|
||||
function(v) {
|
||||
v._finished = false;
|
||||
v.preload = "metadata";
|
||||
v.autoplay = true;
|
||||
v.addEventListener("ended", this.ended, false);
|
||||
@ -522,14 +491,12 @@ var tests = [
|
||||
function(e) {
|
||||
ok(true, "(17) Got playback ended.");
|
||||
var v = e.target;
|
||||
v._finished = true;
|
||||
maybeFinish(v, 17);
|
||||
},
|
||||
|
||||
setup:
|
||||
function(v) {
|
||||
v.addEventListener("ended", this.ended, false);
|
||||
v._finished = false;
|
||||
v.preload = "none";
|
||||
document.body.appendChild(v); // Causes implicit load, which will be halted due to preload:none.
|
||||
v.autoplay = true;
|
||||
@ -543,14 +510,12 @@ var tests = [
|
||||
function(e) {
|
||||
ok(true, "(18) Got playback ended.");
|
||||
var v = e.target;
|
||||
v._finished = true;
|
||||
maybeFinish(v, 18);
|
||||
},
|
||||
|
||||
setup:
|
||||
function(v) {
|
||||
v.addEventListener("ended", this.ended, false);
|
||||
v._finished = false;
|
||||
v.preload = "none";
|
||||
v.src = test.name; // Schedules async section to continue load algorithm.
|
||||
document.body.appendChild(v);
|
||||
|
@ -439,7 +439,7 @@ nsSVGPathElement::GetPathLengthScale(PathLengthScaleForType aFor)
|
||||
// For textPath, a transform on the referenced path affects the
|
||||
// textPath layout, so when calculating the actual path length
|
||||
// we need to take that into account.
|
||||
matrix = PrependLocalTransformTo(gfxMatrix());
|
||||
matrix = PrependLocalTransformTo(matrix);
|
||||
}
|
||||
nsRefPtr<gfxFlattenedPath> path = GetFlattenedPath(matrix);
|
||||
if (path) {
|
||||
|
@ -66,6 +66,7 @@ DIRS = \
|
||||
interfaces/notification \
|
||||
interfaces/svg \
|
||||
interfaces/smil \
|
||||
interfaces/apps \
|
||||
$(NULL)
|
||||
|
||||
DIRS += \
|
||||
|
@ -52,7 +52,13 @@ EXTRA_PP_COMPONENTS = \
|
||||
ConsoleAPI.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
Webapps.js \
|
||||
Webapps.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = ConsoleAPIStorage.jsm \
|
||||
Webapps.jsm \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
|
346
dom/base/Webapps.js
Normal file
346
dom/base/Webapps.js
Normal file
@ -0,0 +1,346 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Open Web Apps.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Fabrice Desré <fabrice@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function WebappsRegistry() {
|
||||
this.messages = ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
|
||||
"Webapps:Uninstall:Return:OK", "Webapps:Uninstall:Return:KO",
|
||||
"Webapps:Enumerate:Return:OK", "Webapps:Enumerate:Return:KO"];
|
||||
|
||||
this.mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
|
||||
|
||||
this.messages.forEach((function(msgName) {
|
||||
this.mm.addMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
|
||||
this._window = null;
|
||||
this._id = this._getRandomId();
|
||||
this._callbacks = [];
|
||||
}
|
||||
|
||||
WebappsRegistry.prototype = {
|
||||
_onerror: null,
|
||||
_oninstall: null,
|
||||
_onuninstall: null,
|
||||
|
||||
/** from https://developer.mozilla.org/en/OpenWebApps/The_Manifest
|
||||
* only the name property is mandatory
|
||||
*/
|
||||
checkManifest: function(aManifest, aInstallOrigin) {
|
||||
// TODO : check for install_allowed_from
|
||||
if (aManifest.name == undefined)
|
||||
return false;
|
||||
|
||||
if (aManifest.installs_allowed_from) {
|
||||
ok = false;
|
||||
aManifest.installs_allowed_from.forEach(function(aOrigin) {
|
||||
if (aOrigin == "*" || aOrigin == aInstallOrigin)
|
||||
ok = true;
|
||||
});
|
||||
return ok;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
getCallbackId: function(aCallback) {
|
||||
let id = "id" + this._getRandomId();
|
||||
this._callbacks[id] = aCallback;
|
||||
return id;
|
||||
},
|
||||
|
||||
getCallback: function(aId) {
|
||||
return this._callbacks[aId];
|
||||
},
|
||||
|
||||
removeCallback: function(aId) {
|
||||
if (this._callbacks[aId])
|
||||
delete this._callbacks[aId];
|
||||
},
|
||||
|
||||
_getRandomId: function() {
|
||||
return Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
|
||||
},
|
||||
|
||||
_convertAppsArray: function(aApps) {
|
||||
let apps = new Array();
|
||||
for (let i = 0; i < aApps.length; i++) {
|
||||
let app = aApps[i];
|
||||
apps.push(new WebappsApplication(app.origin, app.manifest, app.receipt, app.installOrigin, app.installTime));
|
||||
}
|
||||
return apps;
|
||||
},
|
||||
|
||||
set oninstall(aCallback) {
|
||||
if (this.hasPrivileges)
|
||||
this._oninstall = aCallback;
|
||||
else
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
set onuninstall(aCallback) {
|
||||
if (this.hasPrivileges)
|
||||
this._onuninstall = aCallback;
|
||||
else
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
set onerror(aCallback) {
|
||||
this._onerror = aCallback;
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
let msg = aMessage.json;
|
||||
if (!(msg.oid == this._id || aMessage.name == "Webapps:Install:Return:OK" || aMessage.name == "Webapps:Uninstall:Return:OK"))
|
||||
return
|
||||
let app = msg.app;
|
||||
let cb;
|
||||
switch (aMessage.name) {
|
||||
case "Webapps:Install:Return:OK":
|
||||
if (this._oninstall)
|
||||
this._oninstall.handleEvent(new WebappsApplication(app.origin, app.manifest, app.receipt,
|
||||
app.installOrigin, app.installTime));
|
||||
break;
|
||||
case "Webapps:Install:Return:KO":
|
||||
if (this._onerror)
|
||||
this._onerror.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.DENIED));
|
||||
break;
|
||||
case "Webapps:Uninstall:Return:OK":
|
||||
if (this._onuninstall)
|
||||
this._onuninstall.handleEvent(new WebappsApplication(msg.origin, null, null, null, 0));
|
||||
break;
|
||||
case "Webapps:Uninstall:Return:KO":
|
||||
if (this._onerror)
|
||||
this._onerror.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.PERMISSION_DENIED));
|
||||
break;
|
||||
case "Webapps:Enumerate:Return:OK":
|
||||
cb = this.getCallback(msg.callbackID);
|
||||
if (cb.success) {
|
||||
let apps = this._convertAppsArray(msg.apps);
|
||||
cb.success.handleEvent(apps, apps.length);
|
||||
}
|
||||
break;
|
||||
case "Webapps:Enumerate:Return:KO":
|
||||
cb = this.getCallback(msg.callbackID);
|
||||
if (cb.error)
|
||||
cb.error.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.PERMISSION_DENIED));
|
||||
break;
|
||||
}
|
||||
this.removeCallback(msg.callbackID);
|
||||
},
|
||||
|
||||
_fireError: function(aCode) {
|
||||
if (!this._onerror)
|
||||
return;
|
||||
this._onerror.handleEvent(new RegistryError(aCode));
|
||||
},
|
||||
|
||||
_getOrigin: function(aURL) {
|
||||
let uri = Services.io.newURI(aURL, null, null);
|
||||
return uri.prePath;
|
||||
},
|
||||
|
||||
// mozIDOMApplicationRegistry implementation
|
||||
|
||||
install: function(aURL, aReceipt) {
|
||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.open("GET", aURL, true);
|
||||
|
||||
xhr.addEventListener("load", (function() {
|
||||
if (xhr.status == 200) {
|
||||
try {
|
||||
let installOrigin = this._getOrigin(this._window.location.href);
|
||||
let manifest = JSON.parse(xhr.responseText, installOrigin);
|
||||
if (!this.checkManifest(manifest, installOrigin)) {
|
||||
this._fireError(Ci.mozIDOMApplicationRegistryError.INVALID_MANIFEST);
|
||||
} else {
|
||||
this.mm.sendAsyncMessage("Webapps:Install", { app: { installOrigin: installOrigin,
|
||||
origin: this._getOrigin(aURL),
|
||||
manifest: manifest,
|
||||
receipt: aReceipt },
|
||||
from: this._window.location.href,
|
||||
oid: this._id });
|
||||
}
|
||||
} catch(e) {
|
||||
this._fireError(Ci.mozIDOMApplicationRegistryError.MANIFEST_PARSE_ERROR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this._fireError(Ci.mozIDOMApplicationRegistryError.MANIFEST_URL_ERROR);
|
||||
}
|
||||
}).bind(this), false);
|
||||
|
||||
xhr.addEventListener("error", (function() {
|
||||
this._fireError(Ci.mozIDOMApplicationRegistryError.NETWORK_ERROR);
|
||||
}).bind(this), false);
|
||||
|
||||
xhr.send(null);
|
||||
},
|
||||
|
||||
uninstall: function(aOrigin) {
|
||||
if (this.hasPrivileges)
|
||||
this.mm.sendAsyncMessage("Webapps:Uninstall", { from: this._window.location.href,
|
||||
origin: aOrigin,
|
||||
oid: this._id });
|
||||
else
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
launch: function(aOrigin) {
|
||||
this.mm.sendAsyncMessage("Webapps:Launch", { origin: aOrigin,
|
||||
from: this._window.location.href});
|
||||
},
|
||||
|
||||
enumerate: function(aSuccess, aError) {
|
||||
this.mm.sendAsyncMessage("Webapps:Enumerate", { from: this._window.location.href,
|
||||
origin: this._getOrigin(this._window.location.href),
|
||||
oid: this._id,
|
||||
callbackID: this.getCallbackId({ success: aSuccess, error: aError }) });
|
||||
},
|
||||
|
||||
handleEvent: function(aEvent) {
|
||||
if (aEvent.type == "unload") {
|
||||
// remove all callbacks and event handlers so we don't call anything on a cleared scope
|
||||
try {
|
||||
this._oninstall = null;
|
||||
this._onuninstall = null;
|
||||
this._onerror = null;
|
||||
this._callbacks = [];
|
||||
} catch(e) {
|
||||
dump("WebappsRegistry error:" + e + "\n");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// nsIDOMGlobalPropertyInitializer implementation
|
||||
init: function(aWindow) {
|
||||
dump("DOMApplicationRegistry::init() " + aWindow + "\n");
|
||||
this._window = aWindow;
|
||||
this._window.addEventListener("unload", this, false);
|
||||
this._window.appId = this._id;
|
||||
let from = Services.io.newURI(this._window.location.href, null, null);
|
||||
let perm = Services.perms.testExactPermission(from, "webapps-manage");
|
||||
|
||||
//only pages with perm set and chrome or about pages can uninstall, enumerate all set oninstall an onuninstall
|
||||
this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION || from.schemeIs("chrome") || from.schemeIs("about");
|
||||
},
|
||||
|
||||
classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationRegistry, Ci.nsIDOMGlobalPropertyInitializer]),
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
|
||||
contractID: "@mozilla.org/webapps;1",
|
||||
interfaces: [Ci.mozIDOMApplicationRegistry],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "Webapps Registry"})
|
||||
}
|
||||
|
||||
function WebappsApplication(aOrigin, aManifest, aReceipt, aInstallOrigin, aInstallTime) {
|
||||
this._origin = aOrigin;
|
||||
this._manifest = aManifest;
|
||||
this._receipt = aReceipt;
|
||||
this._installOrigin = aInstallOrigin;
|
||||
this._installTime = aInstallTime;
|
||||
}
|
||||
|
||||
WebappsApplication.prototype = {
|
||||
_origin: null,
|
||||
_manifest: null,
|
||||
_receipt: null,
|
||||
_installOrigin: null,
|
||||
_installTime: 0,
|
||||
|
||||
get origin() {
|
||||
return this._origin;
|
||||
},
|
||||
|
||||
get manifest() {
|
||||
return this._manifest;
|
||||
},
|
||||
|
||||
get receipt() {
|
||||
return this._receipt;
|
||||
},
|
||||
|
||||
get installOrigin() {
|
||||
return this._installOrigin;
|
||||
},
|
||||
|
||||
get installTime() {
|
||||
return this._installTime;
|
||||
},
|
||||
|
||||
classID: Components.ID("{723ed303-7757-4fb0-b261-4f78b1f6bd22}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplication]),
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{723ed303-7757-4fb0-b261-4f78b1f6bd22}"),
|
||||
contractID: "@mozilla.org/webapps/application;1",
|
||||
interfaces: [Ci.mozIDOMApplication],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "Webapps Application"})
|
||||
}
|
||||
|
||||
function RegistryError(aCode) {
|
||||
this._code = aCode;
|
||||
}
|
||||
|
||||
RegistryError.prototype = {
|
||||
_code: null,
|
||||
|
||||
get code() {
|
||||
return this._code;
|
||||
},
|
||||
|
||||
classID: Components.ID("{b4937718-11a3-400b-a69f-ab442a418569}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationRegistryError]),
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{b4937718-11a3-400b-a69f-ab442a418569}"),
|
||||
contractID: "@mozilla.org/webapps/error;1",
|
||||
interfaces: [Ci.mozIDOMApplicationRegistryError],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "Webapps Registry Error"})
|
||||
}
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsRegistry, WebappsApplication, RegistryError]);
|
380
dom/base/Webapps.jsm
Normal file
380
dom/base/Webapps.jsm
Normal file
@ -0,0 +1,380 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Mobile Browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Fabrice Desré <fabrice@mozilla.com>
|
||||
* Mark Finkle <mfinkle@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
let EXPORTED_SYMBOLS = ["DOMApplicationRegistry", "DOMApplicationManifest"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
return NetUtil;
|
||||
});
|
||||
|
||||
let DOMApplicationRegistry = {
|
||||
appsDir: null,
|
||||
appsFile: null,
|
||||
webapps: { },
|
||||
|
||||
init: function() {
|
||||
this.mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
|
||||
let messages = ["Webapps:Install", "Webapps:Uninstall",
|
||||
"Webapps:Enumerate", "Webapps:Launch"];
|
||||
|
||||
messages.forEach((function(msgName) {
|
||||
this.mm.addMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
|
||||
let file = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile);
|
||||
file.append("webapps");
|
||||
if (!file.exists() || !file.isDirectory()) {
|
||||
file.create(Ci.nsIFile.DIRECTORY_TYPE, 0700);
|
||||
}
|
||||
this.appsDir = file;
|
||||
this.appsFile = file.clone();
|
||||
this.appsFile.append("webapps.json");
|
||||
if (!this.appsFile.exists())
|
||||
return;
|
||||
|
||||
try {
|
||||
let channel = NetUtil.newChannel(this.appsFile);
|
||||
channel.contentType = "application/json";
|
||||
let self = this;
|
||||
NetUtil.asyncFetch(channel, function(aStream, aResult) {
|
||||
if (!Components.isSuccessCode(aResult)) {
|
||||
Cu.reportError("DOMApplicationRegistry: Could not read from json file " + this.appsFile.path);
|
||||
return;
|
||||
}
|
||||
|
||||
// Read json file into a string
|
||||
let data = null;
|
||||
try {
|
||||
self.webapps = JSON.parse(NetUtil.readInputStreamToString(aStream, aStream.available()) || "");
|
||||
aStream.close();
|
||||
} catch (ex) {
|
||||
Cu.reportError("DOMApplicationRegistry: Could not parse JSON: " + ex);
|
||||
}
|
||||
});
|
||||
} catch (ex) {
|
||||
Cu.reportError("DOMApplicationRegistry: Could not read from " + aFile.path + " : " + ex);
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
let msg = aMessage.json;
|
||||
let from = Services.io.newURI(msg.from, null, null);
|
||||
let perm = Services.perms.testExactPermission(from, "webapps-manage");
|
||||
|
||||
//only pages with perm set and chrome or about pages can uninstall, enumerate all set oninstall an onuninstall
|
||||
let hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION || from.schemeIs("chrome") || from.schemeIs("about");
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "Webapps:Install":
|
||||
// always ask for UI to install
|
||||
Services.obs.notifyObservers(this, "webapps-ask-install", JSON.stringify(msg));
|
||||
break;
|
||||
case "Webapps:Uninstall":
|
||||
if (hasPrivileges)
|
||||
this.uninstall(msg);
|
||||
break;
|
||||
case "Webapps:Launch":
|
||||
Services.obs.notifyObservers(this, "webapps-launch", JSON.stringify(msg));
|
||||
break;
|
||||
case "Webapps:Enumerate":
|
||||
if (hasPrivileges)
|
||||
this.enumerateAll(msg)
|
||||
else
|
||||
this.enumerate(msg);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_writeFile: function ss_writeFile(aFile, aData, aCallbak) {
|
||||
// Initialize the file output stream.
|
||||
let ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
|
||||
ostream.init(aFile, 0x02 | 0x08 | 0x20, 0600, ostream.DEFER_OPEN);
|
||||
|
||||
// Obtain a converter to convert our data to a UTF-8 encoded input stream.
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
|
||||
// Asynchronously copy the data to the file.
|
||||
let istream = converter.convertToInputStream(aData);
|
||||
NetUtil.asyncCopy(istream, ostream, function(rc) {
|
||||
if (aCallbak)
|
||||
aCallbak();
|
||||
});
|
||||
},
|
||||
|
||||
// clones a app object, without the manifest
|
||||
_cloneAppObject: function(aApp) {
|
||||
let clone = {
|
||||
installOrigin: aApp.installOrigin,
|
||||
origin: aApp.origin,
|
||||
receipt: aApp.receipt,
|
||||
installTime: aApp.installTime
|
||||
};
|
||||
return clone;
|
||||
},
|
||||
|
||||
denyInstall: function(aData) {
|
||||
this.mm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
|
||||
},
|
||||
|
||||
confirmInstall: function(aData) {
|
||||
let app = aData.app;
|
||||
let id = this._appId(app.origin);
|
||||
|
||||
// install an application again is considered as an update
|
||||
if (id) {
|
||||
let dir = this.appsDir.clone();
|
||||
dir.append(id);
|
||||
try {
|
||||
dir.remove(true);
|
||||
} catch(e) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
|
||||
id = uuidGenerator.generateUUID().toString();
|
||||
}
|
||||
|
||||
let dir = this.appsDir.clone();
|
||||
dir.append(id);
|
||||
dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0700);
|
||||
|
||||
let manFile = dir.clone();
|
||||
manFile.append("manifest.json");
|
||||
this._writeFile(manFile, JSON.stringify(app.manifest));
|
||||
|
||||
this.webapps[id] = this._cloneAppObject(app);
|
||||
delete this.webapps[id].manifest;
|
||||
this.webapps[id].installTime = (new Date()).getTime()
|
||||
|
||||
this._writeFile(this.appsFile, JSON.stringify(this.webapps), (function() {
|
||||
this.mm.sendAsyncMessage("Webapps:Install:Return:OK", aData);
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
_appId: function(aURI) {
|
||||
for (let id in this.webapps) {
|
||||
if (this.webapps[id].origin == aURI)
|
||||
return id;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
_readManifest: function(aId) {
|
||||
let file = this.appsDir.clone();
|
||||
file.append(aId);
|
||||
file.append("manifest.json");
|
||||
let data = "";
|
||||
let fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
|
||||
var cstream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(Ci.nsIConverterInputStream);
|
||||
fstream.init(file, -1, 0, 0);
|
||||
cstream.init(fstream, "UTF-8", 0, 0);
|
||||
let (str = {}) {
|
||||
let read = 0;
|
||||
do {
|
||||
read = cstream.readString(0xffffffff, str); // read as much as we can and put it in str.value
|
||||
data += str.value;
|
||||
} while (read != 0);
|
||||
}
|
||||
cstream.close(); // this closes fstream
|
||||
try {
|
||||
return JSON.parse(data);
|
||||
} catch(e) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
uninstall: function(aData) {
|
||||
for (let id in this.webapps) {
|
||||
let app = this.webapps[id];
|
||||
if (app.origin == aData.origin) {
|
||||
delete this.webapps[id];
|
||||
this._writeFile(this.appsFile, JSON.stringify(this.webapps));
|
||||
let dir = this.appsDir.clone();
|
||||
dir.append(id);
|
||||
try {
|
||||
dir.remove(true);
|
||||
} catch (e) {
|
||||
}
|
||||
this.mm.sendAsyncMessage("Webapps:Uninstall:Return:OK", aData);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
enumerate: function(aData) {
|
||||
aData.apps = [];
|
||||
|
||||
let id = this._appId(aData.origin);
|
||||
// if it's an app, add itself to the result
|
||||
if (id) {
|
||||
let app = this._cloneAppObject(this.webapps[id]);
|
||||
app.manifest = this._readManifest(id);
|
||||
aData.apps.push(app);
|
||||
}
|
||||
|
||||
// check if it's a store.
|
||||
let isStore = false;
|
||||
for (id in this.webapps) {
|
||||
let app = this._cloneAppObject(this.webapps[id]);
|
||||
if (app.installOrigin == aData.origin) {
|
||||
isStore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// add all the apps from this store
|
||||
if (isStore) {
|
||||
for (id in this.webapps) {
|
||||
let app = this._cloneAppObject(this.webapps[id]);
|
||||
if (app.installOrigin == aData.origin) {
|
||||
app.manifest = this._readManifest(id);
|
||||
aData.apps.push(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.mm.sendAsyncMessage("Webapps:Enumerate:Return:OK", aData);
|
||||
},
|
||||
|
||||
denyEnumerate: function(aData) {
|
||||
this.mm.sendAsyncMessage("Webapps:Enumerate:Return:KO", aData);
|
||||
},
|
||||
|
||||
enumerateAll: function(aData) {
|
||||
aData.apps = [];
|
||||
|
||||
for (id in this.webapps) {
|
||||
let app = this._cloneAppObject(this.webapps[id]);
|
||||
app.manifest = this._readManifest(id);
|
||||
aData.apps.push(app);
|
||||
}
|
||||
|
||||
this.mm.sendAsyncMessage("Webapps:Enumerate:Return:OK", aData);
|
||||
},
|
||||
|
||||
getManifestFor: function(aOrigin) {
|
||||
let id = this._appId(aOrigin);
|
||||
if (!id)
|
||||
return null;
|
||||
return this._readManifest(id);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper object to access manifest information with locale support
|
||||
*/
|
||||
DOMApplicationManifest = function(aManifest, aOrigin) {
|
||||
this._origin = Services.io.newURI(aOrigin, null, null);
|
||||
this._manifest = aManifest;
|
||||
let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry)
|
||||
.QueryInterface(Ci.nsIToolkitChromeRegistry);
|
||||
let locale = chrome.getSelectedLocale("browser").toLowerCase();
|
||||
this._localeRoot = this._manifest;
|
||||
|
||||
if (this._manifest.locales && this._manifest.locales[locale]) {
|
||||
this._localeRoot = this._manifest.locales[locale];
|
||||
}
|
||||
else if (this._manifest.locales) {
|
||||
// try with the language part of the locale ("en" for en-GB) only
|
||||
let lang = locale.split('-')[0];
|
||||
if (land != locale && this._manifest.locales[lang])
|
||||
this._localeRoot = this._manifest.locales[lang];
|
||||
}
|
||||
}
|
||||
|
||||
DOMApplicationManifest.prototype = {
|
||||
_localeProp: function(aProp) {
|
||||
if (this._localeRoot[aProp] != undefined)
|
||||
return this._localeRoot[aProp];
|
||||
return this._manifest[aProp];
|
||||
},
|
||||
|
||||
get name() {
|
||||
return this._localeProp("name");
|
||||
},
|
||||
|
||||
get description() {
|
||||
return this._localeProp("description");
|
||||
},
|
||||
|
||||
get version() {
|
||||
return this._localeProp("version");
|
||||
},
|
||||
|
||||
get launch_path() {
|
||||
return this._localeProp("launch_path");
|
||||
},
|
||||
|
||||
get developer() {
|
||||
return this._localeProp("developer");
|
||||
},
|
||||
|
||||
get icons() {
|
||||
return this._localeProp("icons");
|
||||
},
|
||||
|
||||
iconURLForSize: function(aSize) {
|
||||
let icons = this._localeProp("icons");
|
||||
if (!icons)
|
||||
return null;
|
||||
let dist = 100000;
|
||||
let icon = null;
|
||||
for (let size in icons) {
|
||||
let iSize = parseInt(size);
|
||||
if (Math.abs(iSize - aSize) < dist) {
|
||||
icon = this._origin.resolve(icons[size]);
|
||||
dist = Math.abs(iSize - aSize);
|
||||
}
|
||||
}
|
||||
return icon;
|
||||
},
|
||||
|
||||
fullLaunchPath: function() {
|
||||
let launchPath = this._localeProp("launch_path");
|
||||
return this._origin.resolve(launchPath ? launchPath : "");
|
||||
}
|
||||
}
|
||||
|
||||
DOMApplicationRegistry.init();
|
10
dom/base/Webapps.manifest
Normal file
10
dom/base/Webapps.manifest
Normal file
@ -0,0 +1,10 @@
|
||||
# Webapps.js
|
||||
component {fff440b3-fae2-45c1-bf03-3b5a2e432270} Webapps.js
|
||||
contract @mozilla.org/webapps;1 {fff440b3-fae2-45c1-bf03-3b5a2e432270}
|
||||
category JavaScript-navigator-property mozApps @mozilla.org/webapps;1
|
||||
|
||||
component {723ed303-7757-4fb0-b261-4f78b1f6bd22} Webapps.js
|
||||
contract @mozilla.org/webapps/application;1 {723ed303-7757-4fb0-b261-4f78b1f6bd22}
|
||||
|
||||
component {b4937718-11a3-400b-a69f-ab442a418569} Webapps.js
|
||||
contract @mozilla.org/webapps/error;1 {b4937718-11a3-400b-a69f-ab442a418569}
|
@ -11,14 +11,14 @@
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Open Web Apps.
|
||||
# The Original Code is web apps.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Ben Goodger.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2004
|
||||
# The Initial Developer of the Original Code is Mozilla Foundation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Fabrice Desré <fabrice@mozilla.com>
|
||||
# Andreas Gal <gal@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -34,24 +34,20 @@
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = openwebapps
|
||||
MODULE = dom
|
||||
XPIDL_MODULE = dom_apps
|
||||
GRE_MODULE = 1
|
||||
|
||||
XPIDLSRCS = OpenWebapps.idl
|
||||
|
||||
EXTRA_COMPONENTS += \
|
||||
OpenWebapps.js \
|
||||
OpenWebapps.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
OpenWebapps.jsm \
|
||||
$(NULL)
|
||||
XPIDLSRCS = \
|
||||
nsIDOMApplicationRegistry.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
89
dom/interfaces/apps/nsIDOMApplicationRegistry.idl
Normal file
89
dom/interfaces/apps/nsIDOMApplicationRegistry.idl
Normal file
@ -0,0 +1,89 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is web apps.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Andreas Gal <gal@mozilla.com> (Original Author)
|
||||
* Fabrice Desré <fabrice@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(e0c271cb-266b-48c9-a7e4-96590b445c26)]
|
||||
interface mozIDOMApplicationRegistryError : nsISupports
|
||||
{
|
||||
const unsigned short DENIED = 1;
|
||||
const unsigned short PERMISSION_DENIED = 2;
|
||||
const unsigned short MANIFEST_URL_ERROR = 3;
|
||||
const unsigned short NETWORK_ERROR = 4;
|
||||
const unsigned short MANIFEST_PARSE_ERROR = 5;
|
||||
const unsigned short INVALID_MANIFEST = 6;
|
||||
|
||||
readonly attribute short code;
|
||||
};
|
||||
|
||||
[scriptable, uuid(a6856a3d-dece-43ce-89b9-72dba07f4246)]
|
||||
interface mozIDOMApplication : nsISupports
|
||||
{
|
||||
readonly attribute jsval manifest;
|
||||
readonly attribute DOMString receipt;
|
||||
readonly attribute DOMString origin;
|
||||
readonly attribute DOMString installOrigin;
|
||||
readonly attribute unsigned long installTime;
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(be170df5-9154-463b-9197-10a6195eba52)]
|
||||
interface mozIDOMApplicationRegistryEnumerateCallback : nsISupports
|
||||
{
|
||||
void handleEvent([array, size_is(count)] in mozIDOMApplication apps,
|
||||
in unsigned long count);
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(ae0ed33d-35cf-443a-837b-a6cebf16bd49)]
|
||||
interface mozIDOMApplicationRegistryErrorCallback : nsISupports
|
||||
{
|
||||
void handleEvent(in mozIDOMApplicationRegistryError error);
|
||||
};
|
||||
|
||||
[scriptable, uuid(4070ea6f-dca1-4052-8bc6-7a9bcfc314ac)]
|
||||
interface mozIDOMApplicationRegistry : nsISupports
|
||||
{
|
||||
void install(in DOMString manifestUrl,
|
||||
[optional] in DOMString receipt);
|
||||
void uninstall(in DOMString origin);
|
||||
void enumerate(in mozIDOMApplicationRegistryEnumerateCallback success,
|
||||
[optional] in mozIDOMApplicationRegistryErrorCallback error);
|
||||
void launch(in DOMString origin);
|
||||
|
||||
attribute nsIDOMEventListener oninstall;
|
||||
attribute nsIDOMEventListener onuninstall;
|
||||
attribute nsIDOMEventListener onerror;
|
||||
};
|
@ -57,7 +57,7 @@ SDK_XPIDLSRCS = \
|
||||
XPIDLSRCS = \
|
||||
nsIFrameRequestCallback.idl \
|
||||
nsIBrowserDOMWindow.idl \
|
||||
nsIContentPermissionPrompt.idl \
|
||||
nsIContentPermissionPrompt.idl \
|
||||
nsIContentPrefService.idl \
|
||||
nsIContentURIGrouper.idl \
|
||||
nsIDOMClientInformation.idl \
|
||||
|
@ -590,13 +590,16 @@ nsEditorEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
|
||||
if (ctrlKey)
|
||||
mailEditor = do_QueryObject(mEditor);
|
||||
|
||||
PRInt32 clipboard;
|
||||
|
||||
#if defined(XP_OS2) || defined(XP_WIN32)
|
||||
clipboard = nsIClipboard::kGlobalClipboard;
|
||||
#else
|
||||
clipboard = nsIClipboard::kSelectionClipboard;
|
||||
#endif
|
||||
PRInt32 clipboard = nsIClipboard::kGlobalClipboard;
|
||||
nsCOMPtr<nsIClipboard> clipboardService =
|
||||
do_GetService("@mozilla.org/widget/clipboard;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
bool selectionSupported;
|
||||
rv = clipboardService->SupportsSelectionClipboard(&selectionSupported);
|
||||
if (NS_SUCCEEDED(rv) && selectionSupported) {
|
||||
clipboard = nsIClipboard::kSelectionClipboard;
|
||||
}
|
||||
}
|
||||
|
||||
if (mailEditor)
|
||||
mailEditor->PasteAsQuotation(clipboard);
|
||||
|
@ -87,6 +87,7 @@ _TEST_FILES = \
|
||||
test_bug668599.html \
|
||||
test_bug674770-1.html \
|
||||
file_bug674770-1.html \
|
||||
test_bug674770-2.html \
|
||||
test_bug674861.html \
|
||||
test_bug676401.html \
|
||||
test_bug677752.html \
|
||||
@ -99,11 +100,6 @@ _TEST_FILES = \
|
||||
test_root_element_replacement.html \
|
||||
$(NULL)
|
||||
|
||||
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
_TEST_FILES += test_bug674770-2.html \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifneq (mobile,$(MOZ_BUILD_APP))
|
||||
_TEST_FILES += test_spellcheck_pref.html \
|
||||
$(NULL)
|
||||
|
@ -64,9 +64,9 @@ SimpleTest.waitForFocus(function() {
|
||||
|
||||
SimpleTest.executeSoon(function() {
|
||||
synthesizeKey("a", { accelKey: true }, frameWindow);
|
||||
// Windows doesn't have primary selection, we should copy the text to the
|
||||
// global clipboard.
|
||||
if (navigator.platform.indexOf("Win") == 0) {
|
||||
// Windows and Mac don't have primary selection, we should copy the text to
|
||||
// the global clipboard.
|
||||
if (!SpecialPowers.supportsSelectionClipboard()) {
|
||||
SimpleTest.waitForClipboard("pasted",
|
||||
function() { synthesizeKey("c", { accelKey: true }, frameWindow); },
|
||||
function() { SimpleTest.executeSoon(runInputTests1) },
|
||||
|
@ -1313,7 +1313,7 @@ public:
|
||||
CONTEXT_NO_ERROR = 0,
|
||||
CONTEXT_GUILTY_CONTEXT_RESET_ARB = 0x8253,
|
||||
CONTEXT_INNOCENT_CONTEXT_RESET_ARB = 0x8254,
|
||||
CONTEXT_UNKNOWN_CONTEXT_RESET_ARB = 0x8255,
|
||||
CONTEXT_UNKNOWN_CONTEXT_RESET_ARB = 0x8255
|
||||
};
|
||||
|
||||
bool HasRobustness() {
|
||||
|
@ -78,6 +78,7 @@
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@ -406,11 +407,16 @@ gfxPlatformFontList::FindFontForChar(const PRUint32 aCh, gfxFont *aPrevFont)
|
||||
return fontEntry;
|
||||
}
|
||||
|
||||
static bool first = true;
|
||||
TimeStamp start = TimeStamp::Now();
|
||||
|
||||
FontSearch data(aCh, aPrevFont);
|
||||
|
||||
// iterate over all font families to find a font that support the character
|
||||
mFontFamilies.Enumerate(gfxPlatformFontList::FindFontForCharProc, &data);
|
||||
|
||||
TimeDuration elapsed = TimeStamp::Now() - start;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo *log = gfxPlatform::GetLog(eGfxLog_textrun);
|
||||
|
||||
@ -420,13 +426,15 @@ gfxPlatformFontList::FindFontForChar(const PRUint32 aCh, gfxFont *aPrevFont)
|
||||
PRUint32 hbscript = gfxUnicodeProperties::GetScriptCode(aCh);
|
||||
PR_LOG(log, PR_LOG_DEBUG,\
|
||||
("(textrun-systemfallback) char: u+%6.6x "
|
||||
"char-range: %d unicode-range: %d script: %d match: [%s] count: %d\n",
|
||||
"char-range: %d unicode-range: %d script: %d match: [%s]"
|
||||
" count: %d time: %dus\n",
|
||||
aCh,
|
||||
charRange, unicodeRange, hbscript,
|
||||
(data.mBestMatch ?
|
||||
NS_ConvertUTF16toUTF8(data.mBestMatch->Name()).get() :
|
||||
"<none>"),
|
||||
data.mCount));
|
||||
data.mCount,
|
||||
PRInt32(elapsed.ToMicroseconds())));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -437,6 +445,13 @@ gfxPlatformFontList::FindFontForChar(const PRUint32 aCh, gfxFont *aPrevFont)
|
||||
mReplacementCharFallbackFamily = data.mBestMatch->FamilyName();
|
||||
}
|
||||
|
||||
PRInt32 intElapsed = PRInt32(first ? elapsed.ToMilliseconds() :
|
||||
elapsed.ToMicroseconds());
|
||||
Telemetry::Accumulate((first ? Telemetry::SYSTEM_FONT_FALLBACK_FIRST :
|
||||
Telemetry::SYSTEM_FONT_FALLBACK),
|
||||
intElapsed);
|
||||
first = false;
|
||||
|
||||
return data.mBestMatch;
|
||||
}
|
||||
|
||||
|
@ -517,8 +517,13 @@ ExecuteRegExp(JSContext *cx, Native native, uintN argc, Value *vp)
|
||||
RegExpObject *reobj = obj->asRegExp();
|
||||
|
||||
RegExpMatcher matcher(cx);
|
||||
if (!matcher.reset(reobj))
|
||||
return false;
|
||||
if (reobj->startsWithAtomizedGreedyStar()) {
|
||||
if (!matcher.resetWithTestOptimized(reobj))
|
||||
return false;
|
||||
} else {
|
||||
if (!matcher.reset(reobj))
|
||||
return false;
|
||||
}
|
||||
|
||||
RegExpStatics *res = cx->regExpStatics();
|
||||
|
||||
|
@ -693,6 +693,10 @@ InitTypeConstructor(JSContext* cx,
|
||||
if (instanceProps && !JS_DefineProperties(cx, dataProto, instanceProps))
|
||||
return false;
|
||||
|
||||
// Link the type prototype to the data prototype.
|
||||
if (!JS_SetReservedSlot(cx, typeProto, SLOT_OURDATAPROTO, OBJECT_TO_JSVAL(dataProto)))
|
||||
return false;
|
||||
|
||||
if (!JS_FreezeObject(cx, obj) ||
|
||||
//!JS_FreezeObject(cx, dataProto) || // XXX fixme - see bug 541212!
|
||||
!JS_FreezeObject(cx, typeProto))
|
||||
@ -740,7 +744,7 @@ AttachProtos(JSContext* cx, JSObject* proto, JSObject** protos)
|
||||
{
|
||||
// For a given 'proto' of [[Class]] "CTypeProto", attach each of the 'protos'
|
||||
// to the appropriate CTypeProtoSlot. (SLOT_UINT64PROTO is the last slot
|
||||
// of [[Class]] "CTypeProto".)
|
||||
// of [[Class]] "CTypeProto" that we fill in this automated manner.)
|
||||
for (JSUint32 i = 0; i <= SLOT_UINT64PROTO; ++i) {
|
||||
if (!JS_SetReservedSlot(cx, proto, i, OBJECT_TO_JSVAL(protos[i])))
|
||||
return false;
|
||||
@ -784,6 +788,11 @@ InitTypeClasses(JSContext* cx, JSObject* parent)
|
||||
if (!CDataProto)
|
||||
return false;
|
||||
|
||||
// Link CTypeProto to CDataProto.
|
||||
if (!JS_SetReservedSlot(cx, CTypeProto, SLOT_OURDATAPROTO,
|
||||
OBJECT_TO_JSVAL(CDataProto)))
|
||||
return false;
|
||||
|
||||
// Create and attach the special class constructors: ctypes.PointerType,
|
||||
// ctypes.ArrayType, ctypes.StructType, and ctypes.FunctionType.
|
||||
// Each of these constructors 'c' has, respectively:
|
||||
@ -2829,6 +2838,12 @@ CType::IsCType(JSContext* cx, JSObject* obj)
|
||||
return JS_GET_CLASS(cx, obj) == &sCTypeClass;
|
||||
}
|
||||
|
||||
bool
|
||||
CType::IsCTypeProto(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
return JS_GET_CLASS(cx, obj) == &sCTypeProtoClass;
|
||||
}
|
||||
|
||||
TypeCode
|
||||
CType::GetTypeCode(JSContext* cx, JSObject* typeObj)
|
||||
{
|
||||
@ -3034,7 +3049,7 @@ CType::GetProtoFromCtor(JSContext* cx, JSObject* obj, CTypeProtoSlot slot)
|
||||
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_FN_CTORPROTO, &protoslot));
|
||||
JSObject* proto = JSVAL_TO_OBJECT(protoslot);
|
||||
JS_ASSERT(proto);
|
||||
JS_ASSERT(JS_GET_CLASS(cx, proto) == &sCTypeProtoClass);
|
||||
JS_ASSERT(CType::IsCTypeProto(cx, proto));
|
||||
|
||||
// Get the desired prototype.
|
||||
jsval result;
|
||||
@ -3050,7 +3065,7 @@ CType::GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot)
|
||||
// Get the prototype of the type object.
|
||||
JSObject* proto = JS_GetPrototype(cx, obj);
|
||||
JS_ASSERT(proto);
|
||||
JS_ASSERT(JS_GET_CLASS(cx, proto) == &sCTypeProtoClass);
|
||||
JS_ASSERT(CType::IsCTypeProto(cx, proto));
|
||||
|
||||
// Get the requested ctypes.{Pointer,Array,Struct,Function}Type.prototype.
|
||||
jsval result;
|
||||
@ -3061,12 +3076,14 @@ CType::GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot)
|
||||
JSBool
|
||||
CType::PrototypeGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
|
||||
{
|
||||
if (!CType::IsCType(cx, obj)) {
|
||||
JS_ReportError(cx, "not a CType");
|
||||
if (!(CType::IsCType(cx, obj) || CType::IsCTypeProto(cx, obj))) {
|
||||
JS_ReportError(cx, "not a CType or CTypeProto");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_PROTO, vp));
|
||||
unsigned slot = CType::IsCTypeProto(cx, obj) ? (unsigned) SLOT_OURDATAPROTO
|
||||
: (unsigned) SLOT_PROTO;
|
||||
ASSERT_OK(JS_GetReservedSlot(cx, obj, slot, vp));
|
||||
JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp) || JSVAL_IS_VOID(*vp));
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -3151,19 +3168,28 @@ JSBool
|
||||
CType::ToString(JSContext* cx, uintN argc, jsval* vp)
|
||||
{
|
||||
JSObject* obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj || !CType::IsCType(cx, obj)) {
|
||||
if (!obj ||
|
||||
!(CType::IsCType(cx, obj) || CType::IsCTypeProto(cx, obj)))
|
||||
{
|
||||
JS_ReportError(cx, "not a CType");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
AutoString type;
|
||||
AppendString(type, "type ");
|
||||
AppendString(type, GetName(cx, obj));
|
||||
|
||||
JSString* result = NewUCString(cx, type);
|
||||
// Create the appropriate string depending on whether we're sCTypeClass or
|
||||
// sCTypeProtoClass.
|
||||
JSString* result;
|
||||
if (CType::IsCType(cx, obj)) {
|
||||
AutoString type;
|
||||
AppendString(type, "type ");
|
||||
AppendString(type, GetName(cx, obj));
|
||||
result = NewUCString(cx, type);
|
||||
}
|
||||
else {
|
||||
result = JS_NewStringCopyZ(cx, "[CType proto object]");
|
||||
}
|
||||
if (!result)
|
||||
return JS_FALSE;
|
||||
|
||||
|
||||
JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(result));
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -3172,17 +3198,26 @@ JSBool
|
||||
CType::ToSource(JSContext* cx, uintN argc, jsval* vp)
|
||||
{
|
||||
JSObject* obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj || !CType::IsCType(cx, obj)) {
|
||||
if (!obj ||
|
||||
!(CType::IsCType(cx, obj) || CType::IsCTypeProto(cx, obj)))
|
||||
{
|
||||
JS_ReportError(cx, "not a CType");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
AutoString source;
|
||||
BuildTypeSource(cx, obj, false, source);
|
||||
JSString* result = NewUCString(cx, source);
|
||||
// Create the appropriate string depending on whether we're sCTypeClass or
|
||||
// sCTypeProtoClass.
|
||||
JSString* result;
|
||||
if (CType::IsCType(cx, obj)) {
|
||||
AutoString source;
|
||||
BuildTypeSource(cx, obj, false, source);
|
||||
result = NewUCString(cx, source);
|
||||
} else {
|
||||
result = JS_NewStringCopyZ(cx, "[CType proto object]");
|
||||
}
|
||||
if (!result)
|
||||
return JS_FALSE;
|
||||
|
||||
|
||||
JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(result));
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -3196,7 +3231,7 @@ CType::HasInstance(JSContext* cx, JSObject* obj, const jsval* v, JSBool* bp)
|
||||
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_PROTO, &slot));
|
||||
JSObject* prototype = JSVAL_TO_OBJECT(slot);
|
||||
JS_ASSERT(prototype);
|
||||
JS_ASSERT(JS_GET_CLASS(cx, prototype) == &sCDataProtoClass);
|
||||
JS_ASSERT(CData::IsCDataProto(cx, prototype));
|
||||
|
||||
*bp = JS_FALSE;
|
||||
if (JSVAL_IS_PRIMITIVE(*v))
|
||||
@ -5269,7 +5304,7 @@ CClosure::Create(JSContext* cx,
|
||||
// which stores our JSContext for use with the closure.
|
||||
JSObject* proto = JS_GetPrototype(cx, typeObj);
|
||||
JS_ASSERT(proto);
|
||||
JS_ASSERT(JS_GET_CLASS(cx, proto) == &sCTypeProtoClass);
|
||||
JS_ASSERT(CType::IsCTypeProto(cx, proto));
|
||||
|
||||
// Get a JSContext for use with the closure.
|
||||
jsval slot;
|
||||
@ -5699,6 +5734,12 @@ CData::IsCData(JSContext* cx, JSObject* obj)
|
||||
return JS_GET_CLASS(cx, obj) == &sCDataClass;
|
||||
}
|
||||
|
||||
bool
|
||||
CData::IsCDataProto(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
return JS_GET_CLASS(cx, obj) == &sCDataProtoClass;
|
||||
}
|
||||
|
||||
JSBool
|
||||
CData::ValueGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
|
||||
{
|
||||
@ -5933,29 +5974,35 @@ CData::ToSource(JSContext* cx, uintN argc, jsval* vp)
|
||||
}
|
||||
|
||||
JSObject* obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj || !CData::IsCData(cx, obj)) {
|
||||
if (!obj ||
|
||||
!(CData::IsCData(cx, obj) || CData::IsCDataProto(cx, obj))) {
|
||||
JS_ReportError(cx, "not a CData");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSObject* typeObj = CData::GetCType(cx, obj);
|
||||
void* data = CData::GetData(cx, obj);
|
||||
JSString* result;
|
||||
if (CData::IsCData(cx, obj)) {
|
||||
JSObject* typeObj = CData::GetCType(cx, obj);
|
||||
void* data = CData::GetData(cx, obj);
|
||||
|
||||
// Walk the types, building up the toSource() string.
|
||||
// First, we build up the type expression:
|
||||
// 't.ptr' for pointers;
|
||||
// 't.array([n])' for arrays;
|
||||
// 'n' for structs, where n = t.name, the struct's name. (We assume this is
|
||||
// bound to a variable in the current scope.)
|
||||
AutoString source;
|
||||
BuildTypeSource(cx, typeObj, true, source);
|
||||
AppendString(source, "(");
|
||||
if (!BuildDataSource(cx, typeObj, data, false, source))
|
||||
return JS_FALSE;
|
||||
// Walk the types, building up the toSource() string.
|
||||
// First, we build up the type expression:
|
||||
// 't.ptr' for pointers;
|
||||
// 't.array([n])' for arrays;
|
||||
// 'n' for structs, where n = t.name, the struct's name. (We assume this is
|
||||
// bound to a variable in the current scope.)
|
||||
AutoString source;
|
||||
BuildTypeSource(cx, typeObj, true, source);
|
||||
AppendString(source, "(");
|
||||
if (!BuildDataSource(cx, typeObj, data, false, source))
|
||||
return JS_FALSE;
|
||||
|
||||
AppendString(source, ")");
|
||||
AppendString(source, ")");
|
||||
|
||||
JSString* result = NewUCString(cx, source);
|
||||
result = NewUCString(cx, source);
|
||||
}
|
||||
else
|
||||
result = JS_NewStringCopyZ(cx, "[CData proto object]");
|
||||
if (!result)
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -392,7 +392,8 @@ enum CTypeProtoSlot {
|
||||
SLOT_FUNCTIONDATAPROTO = 8, // common ancestor of all CData objects of FunctionType
|
||||
SLOT_INT64PROTO = 9, // ctypes.Int64.prototype object
|
||||
SLOT_UINT64PROTO = 10, // ctypes.UInt64.prototype object
|
||||
SLOT_CLOSURECX = 11, // JSContext for use with FunctionType closures
|
||||
SLOT_OURDATAPROTO = 11, // the data prototype corresponding to this object
|
||||
SLOT_CLOSURECX = 12, // JSContext for use with FunctionType closures
|
||||
CTYPEPROTO_SLOTS
|
||||
};
|
||||
|
||||
@ -457,6 +458,7 @@ namespace CType {
|
||||
jsval size, jsval align, ffi_type* ffiType);
|
||||
|
||||
bool IsCType(JSContext* cx, JSObject* obj);
|
||||
bool IsCTypeProto(JSContext* cx, JSObject* obj);
|
||||
TypeCode GetTypeCode(JSContext* cx, JSObject* typeObj);
|
||||
bool TypesEqual(JSContext* cx, JSObject* t1, JSObject* t2);
|
||||
size_t GetSize(JSContext* cx, JSObject* obj);
|
||||
@ -520,6 +522,7 @@ namespace CData {
|
||||
JSObject* GetCType(JSContext* cx, JSObject* dataObj);
|
||||
void* GetData(JSContext* cx, JSObject* dataObj);
|
||||
bool IsCData(JSContext* cx, JSObject* obj);
|
||||
bool IsCDataProto(JSContext* cx, JSObject* obj);
|
||||
|
||||
// Attached by JSAPI as the function 'ctypes.cast'
|
||||
JSBool Cast(JSContext* cx, uintN argc, jsval* vp);
|
||||
|
3
js/src/jit-test/tests/basic/bug691299-regexp.js
Normal file
3
js/src/jit-test/tests/basic/bug691299-regexp.js
Normal file
@ -0,0 +1,3 @@
|
||||
// |jit-test| error: SyntaxError: invalid quantifier
|
||||
|
||||
String.fromCharCode(256).replace(/[^a$]{4294967295}/,"aaaa");
|
4
js/src/jit-test/tests/basic/bug691797-regexp-1.js
Normal file
4
js/src/jit-test/tests/basic/bug691797-regexp-1.js
Normal file
@ -0,0 +1,4 @@
|
||||
var re = /.*star.*/i;
|
||||
var str = "The Shawshank Redemption (1994)";
|
||||
for (var k = 0; k < 100; k++)
|
||||
assertEq(false, re.test(str));
|
6
js/src/jit-test/tests/basic/bug691797-regexp-2.js
Normal file
6
js/src/jit-test/tests/basic/bug691797-regexp-2.js
Normal file
@ -0,0 +1,6 @@
|
||||
var re = /.*(a\w).*/i;
|
||||
var str = "abccccccad";
|
||||
for (var k = 0; k < 100; k++) {
|
||||
re.test(str);
|
||||
assertEq('ad', RegExp['$1']);
|
||||
}
|
18
js/src/jit-test/tests/jaeger/bug706110.js
Normal file
18
js/src/jit-test/tests/jaeger/bug706110.js
Normal file
@ -0,0 +1,18 @@
|
||||
function test() {
|
||||
function Bug() { this.prototype }
|
||||
var actual = (new Bug instanceof Bug);
|
||||
assertEq(actual, true);
|
||||
}
|
||||
test();
|
||||
test();
|
||||
|
||||
function testLambdaCtor() {
|
||||
var q;
|
||||
for (var x = 0; x < 2; ++x) {
|
||||
var f = function(){};
|
||||
if (x == 1) gc();
|
||||
q = new f;
|
||||
}
|
||||
return q.__proto__ === f.prototype;
|
||||
}
|
||||
assertEq(testLambdaCtor(), true);
|
@ -130,6 +130,7 @@ namespace detail {
|
||||
|
||||
class RegExpPrivate;
|
||||
class RegExpPrivateCode;
|
||||
class RegExpPrivateCacheValue;
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
@ -236,7 +237,10 @@ typedef HashMap<jsbytecode *, BreakpointSite *, DefaultHasher<jsbytecode *>, Run
|
||||
class Debugger;
|
||||
class WatchpointMap;
|
||||
|
||||
typedef HashMap<JSAtom *, detail::RegExpPrivate *, DefaultHasher<JSAtom *>, RuntimeAllocPolicy>
|
||||
typedef HashMap<JSAtom *,
|
||||
detail::RegExpPrivateCacheValue,
|
||||
DefaultHasher<JSAtom *>,
|
||||
RuntimeAllocPolicy>
|
||||
RegExpPrivateCache;
|
||||
|
||||
typedef JSNative Native;
|
||||
|
@ -7272,8 +7272,12 @@ mjit::Compiler::constructThis()
|
||||
JSFunction *fun = script->function();
|
||||
|
||||
do {
|
||||
if (!cx->typeInferenceEnabled() || fun->getType(cx)->unknownProperties())
|
||||
if (!cx->typeInferenceEnabled() ||
|
||||
!fun->hasSingletonType() ||
|
||||
fun->getType(cx)->unknownProperties())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
jsid id = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom);
|
||||
types::TypeSet *protoTypes = fun->getType(cx)->getProperty(cx, id, false);
|
||||
|
@ -1,6 +1,6 @@
|
||||
url-prefix ../../jsreftest.html?test=js1_5/GC/
|
||||
script regress-104584.js
|
||||
skip-if(!xulRuntime.shell&&xulRuntime.OS=="Darwin") slow script regress-203278-2.js
|
||||
script regress-203278-2.js
|
||||
script regress-203278-3.js
|
||||
script regress-278725.js
|
||||
script regress-306788.js
|
||||
|
@ -41,7 +41,7 @@ script regress-191633.js
|
||||
script regress-191668.js
|
||||
script regress-192414.js
|
||||
script regress-193418.js
|
||||
skip script regress-203278-1.js # slow
|
||||
script regress-203278-1.js
|
||||
script regress-203402.js
|
||||
script regress-203841.js
|
||||
script regress-204210.js
|
||||
|
@ -64,7 +64,7 @@ script regress-468711.js
|
||||
script regress-469547.js
|
||||
script regress-469625-02.js
|
||||
script regress-469625-03.js
|
||||
skip-if(Android) script regress-471373.js # bug xxx No test results reported
|
||||
script regress-471373.js
|
||||
script regress-471660.js
|
||||
script regress-472450-01.js
|
||||
script regress-472450-02.js
|
||||
|
@ -89,6 +89,23 @@ HasRegExpMetaChars(const jschar *chars, size_t length)
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool
|
||||
RegExpObject::startsWithAtomizedGreedyStar() const
|
||||
{
|
||||
JSLinearString *source = getSource();
|
||||
|
||||
if (!source->isAtom())
|
||||
return false;
|
||||
|
||||
if (source->length() < 3)
|
||||
return false;
|
||||
|
||||
const jschar *chars = source->chars();
|
||||
return chars[0] == detail::GreedyStarChars[0] &&
|
||||
chars[1] == detail::GreedyStarChars[1] &&
|
||||
chars[2] != '?';
|
||||
}
|
||||
|
||||
inline size_t *
|
||||
RegExpObject::addressOfPrivateRefCount() const
|
||||
{
|
||||
@ -257,6 +274,7 @@ detail::RegExpPrivate::getOrCreateCache(JSContext *cx)
|
||||
|
||||
inline bool
|
||||
detail::RegExpPrivate::cacheLookup(JSContext *cx, JSAtom *atom, RegExpFlag flags,
|
||||
RegExpPrivateCacheKind targetKind,
|
||||
AlreadyIncRefed<RegExpPrivate> *result)
|
||||
{
|
||||
RegExpPrivateCache *cache = getOrCreateCache(cx);
|
||||
@ -264,8 +282,9 @@ detail::RegExpPrivate::cacheLookup(JSContext *cx, JSAtom *atom, RegExpFlag flags
|
||||
return false;
|
||||
|
||||
if (RegExpPrivateCache::Ptr p = cache->lookup(atom)) {
|
||||
NeedsIncRef<RegExpPrivate> cached(p->value);
|
||||
if (cached->getFlags() == flags) {
|
||||
RegExpPrivateCacheValue &cacheValue = p->value;
|
||||
if (cacheValue.kind() == targetKind && cacheValue.rep()->getFlags() == flags) {
|
||||
NeedsIncRef<RegExpPrivate> cached(cacheValue.rep());
|
||||
cached->incref(cx);
|
||||
*result = AlreadyIncRefed<RegExpPrivate>(cached.get());
|
||||
return true;
|
||||
@ -277,7 +296,8 @@ detail::RegExpPrivate::cacheLookup(JSContext *cx, JSAtom *atom, RegExpFlag flags
|
||||
}
|
||||
|
||||
inline bool
|
||||
detail::RegExpPrivate::cacheInsert(JSContext *cx, JSAtom *atom, RegExpPrivate *priv)
|
||||
detail::RegExpPrivate::cacheInsert(JSContext *cx, JSAtom *atom, RegExpPrivateCacheKind kind,
|
||||
RegExpPrivate *priv)
|
||||
{
|
||||
JS_ASSERT(priv);
|
||||
|
||||
@ -291,11 +311,12 @@ detail::RegExpPrivate::cacheInsert(JSContext *cx, JSAtom *atom, RegExpPrivate *p
|
||||
return false;
|
||||
|
||||
if (RegExpPrivateCache::AddPtr addPtr = cache->lookupForAdd(atom)) {
|
||||
/* We clobber existing entries with the same source (but different flags). */
|
||||
JS_ASSERT(addPtr->value->getFlags() != priv->getFlags());
|
||||
addPtr->value = priv;
|
||||
/* We clobber existing entries with the same source (but different flags or kind). */
|
||||
JS_ASSERT(addPtr->value.rep()->getFlags() != priv->getFlags() ||
|
||||
addPtr->value.kind() != kind);
|
||||
addPtr->value.reset(priv, kind);
|
||||
} else {
|
||||
if (!cache->add(addPtr, atom, priv)) {
|
||||
if (!cache->add(addPtr, atom, RegExpPrivateCacheValue(priv, kind))) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
@ -329,7 +350,7 @@ detail::RegExpPrivate::create(JSContext *cx, JSLinearString *source, RegExpFlag
|
||||
JSAtom *sourceAtom = &source->asAtom();
|
||||
|
||||
AlreadyIncRefed<RegExpPrivate> cached;
|
||||
if (!cacheLookup(cx, sourceAtom, flags, &cached))
|
||||
if (!cacheLookup(cx, sourceAtom, flags, RegExpPrivateCache_ExecCapable, &cached))
|
||||
return RetType(NULL);
|
||||
|
||||
if (cached)
|
||||
@ -339,7 +360,7 @@ detail::RegExpPrivate::create(JSContext *cx, JSLinearString *source, RegExpFlag
|
||||
if (!priv)
|
||||
return RetType(NULL);
|
||||
|
||||
if (!cacheInsert(cx, sourceAtom, priv))
|
||||
if (!cacheInsert(cx, sourceAtom, RegExpPrivateCache_ExecCapable, priv))
|
||||
return RetType(NULL);
|
||||
|
||||
return RetType(priv);
|
||||
@ -491,7 +512,7 @@ detail::RegExpPrivate::decref(JSContext *cx)
|
||||
RegExpPrivateCache *cache;
|
||||
if (source->isAtom() && (cache = cx->threadData()->getRegExpPrivateCache())) {
|
||||
RegExpPrivateCache::Ptr ptr = cache->lookup(&source->asAtom());
|
||||
if (ptr && ptr->value == this)
|
||||
if (ptr && ptr->value.rep() == this)
|
||||
cache->remove(ptr);
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,34 @@ JS_STATIC_ASSERT(GlobalFlag == JSREG_GLOB);
|
||||
JS_STATIC_ASSERT(MultilineFlag == JSREG_MULTILINE);
|
||||
JS_STATIC_ASSERT(StickyFlag == JSREG_STICKY);
|
||||
|
||||
/* RegExpMatcher */
|
||||
|
||||
bool
|
||||
RegExpMatcher::resetWithTestOptimized(RegExpObject *reobj)
|
||||
{
|
||||
JS_ASSERT(reobj->startsWithAtomizedGreedyStar());
|
||||
|
||||
JSAtom *source = &reobj->getSource()->asAtom();
|
||||
AlreadyIncRefed<RegExpPrivate> priv =
|
||||
RegExpPrivate::createTestOptimized(cx, source, reobj->getFlags());
|
||||
if (!priv)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Create a dummy RegExpObject to persist this RegExpPrivate until the next GC.
|
||||
* Note that we give the ref we have to this new object.
|
||||
*/
|
||||
RegExpObjectBuilder builder(cx);
|
||||
RegExpObject *dummy = builder.build(priv);
|
||||
if (!dummy) {
|
||||
priv->decref(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
arc.reset(NeedsIncRef<RegExpPrivate>(priv.get()));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* RegExpObjectBuilder */
|
||||
|
||||
bool
|
||||
@ -468,7 +496,7 @@ js::ParseRegExpFlags(JSContext *cx, JSString *flagStr, RegExpFlag *flagsOut)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ RegExpPrivate *
|
||||
RegExpPrivate *
|
||||
RegExpPrivate::createUncached(JSContext *cx, JSLinearString *source, RegExpFlag flags,
|
||||
TokenStream *tokenStream)
|
||||
{
|
||||
@ -484,6 +512,38 @@ RegExpPrivate::createUncached(JSContext *cx, JSLinearString *source, RegExpFlag
|
||||
return priv;
|
||||
}
|
||||
|
||||
AlreadyIncRefed<RegExpPrivate>
|
||||
RegExpPrivate::createTestOptimized(JSContext *cx, JSAtom *cacheKey, RegExpFlag flags)
|
||||
{
|
||||
typedef AlreadyIncRefed<RegExpPrivate> RetType;
|
||||
|
||||
RetType cached;
|
||||
if (!cacheLookup(cx, cacheKey, flags, RegExpPrivateCache_TestOptimized, &cached))
|
||||
return RetType(NULL);
|
||||
|
||||
if (cached)
|
||||
return cached;
|
||||
|
||||
/* Strip off the greedy star characters, create a new RegExpPrivate, and cache. */
|
||||
JS_ASSERT(cacheKey->length() > JS_ARRAY_LENGTH(GreedyStarChars));
|
||||
JSDependentString *stripped =
|
||||
JSDependentString::new_(cx, cacheKey, cacheKey->chars() + JS_ARRAY_LENGTH(GreedyStarChars),
|
||||
cacheKey->length() - JS_ARRAY_LENGTH(GreedyStarChars));
|
||||
if (!stripped)
|
||||
return RetType(NULL);
|
||||
|
||||
RegExpPrivate *priv = createUncached(cx, cacheKey, flags, NULL);
|
||||
if (!priv)
|
||||
return RetType(NULL);
|
||||
|
||||
if (!cacheInsert(cx, cacheKey, RegExpPrivateCache_TestOptimized, priv)) {
|
||||
priv->decref(cx);
|
||||
return RetType(NULL);
|
||||
}
|
||||
|
||||
return RetType(priv);
|
||||
}
|
||||
|
||||
AlreadyIncRefed<RegExpPrivate>
|
||||
RegExpPrivate::create(JSContext *cx, JSLinearString *str, JSString *opt, TokenStream *ts)
|
||||
{
|
||||
|
@ -134,6 +134,8 @@ class RegExpObject : public ::JSObject
|
||||
return RegExpFlag(flags);
|
||||
}
|
||||
|
||||
inline bool startsWithAtomizedGreedyStar() const;
|
||||
|
||||
/* JIT only. */
|
||||
|
||||
inline size_t *addressOfPrivateRefCount() const;
|
||||
@ -215,6 +217,8 @@ class RegExpObjectBuilder
|
||||
|
||||
RegExpObject *build(AlreadyIncRefed<RegExpPrivate> rep);
|
||||
|
||||
friend class RegExpMatcher;
|
||||
|
||||
public:
|
||||
RegExpObjectBuilder(JSContext *cx, RegExpObject *reobj = NULL)
|
||||
: cx(cx), reobj_(reobj)
|
||||
@ -231,6 +235,8 @@ class RegExpObjectBuilder
|
||||
|
||||
namespace detail {
|
||||
|
||||
static const jschar GreedyStarChars[] = {'.', '*'};
|
||||
|
||||
/* Abstracts away the gross |RegExpPrivate| backend details. */
|
||||
class RegExpPrivateCode
|
||||
{
|
||||
@ -306,6 +312,44 @@ class RegExpPrivateCode
|
||||
int *output, size_t outputCount);
|
||||
};
|
||||
|
||||
enum RegExpPrivateCacheKind
|
||||
{
|
||||
RegExpPrivateCache_TestOptimized,
|
||||
RegExpPrivateCache_ExecCapable
|
||||
};
|
||||
|
||||
class RegExpPrivateCacheValue
|
||||
{
|
||||
union {
|
||||
RegExpPrivate *rep_;
|
||||
uintptr_t bits;
|
||||
};
|
||||
|
||||
public:
|
||||
RegExpPrivateCacheValue() : rep_(NULL) {}
|
||||
|
||||
RegExpPrivateCacheValue(RegExpPrivate *rep, RegExpPrivateCacheKind kind) {
|
||||
reset(rep, kind);
|
||||
}
|
||||
|
||||
RegExpPrivateCacheKind kind() const {
|
||||
return (bits & 0x1)
|
||||
? RegExpPrivateCache_TestOptimized
|
||||
: RegExpPrivateCache_ExecCapable;
|
||||
}
|
||||
|
||||
RegExpPrivate *rep() {
|
||||
return reinterpret_cast<RegExpPrivate *>(bits & ~uintptr_t(1));
|
||||
}
|
||||
|
||||
void reset(RegExpPrivate *rep, RegExpPrivateCacheKind kind) {
|
||||
rep_ = rep;
|
||||
if (kind == RegExpPrivateCache_TestOptimized)
|
||||
bits |= 0x1;
|
||||
JS_ASSERT(this->kind() == kind);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* The "meat" of the builtin regular expression objects: it contains the
|
||||
* mini-program that represents the source of the regular expression.
|
||||
@ -344,8 +388,9 @@ class RegExpPrivate
|
||||
|
||||
static RegExpPrivateCache *getOrCreateCache(JSContext *cx);
|
||||
static bool cacheLookup(JSContext *cx, JSAtom *atom, RegExpFlag flags,
|
||||
AlreadyIncRefed<RegExpPrivate> *result);
|
||||
static bool cacheInsert(JSContext *cx, JSAtom *atom, RegExpPrivate *priv);
|
||||
RegExpPrivateCacheKind kind, AlreadyIncRefed<RegExpPrivate> *result);
|
||||
static bool cacheInsert(JSContext *cx, JSAtom *atom,
|
||||
RegExpPrivateCacheKind kind, RegExpPrivate *priv);
|
||||
|
||||
public:
|
||||
static AlreadyIncRefed<RegExpPrivate>
|
||||
@ -354,6 +399,9 @@ class RegExpPrivate
|
||||
static AlreadyIncRefed<RegExpPrivate>
|
||||
create(JSContext *cx, JSLinearString *source, JSString *flags, TokenStream *ts);
|
||||
|
||||
static AlreadyIncRefed<RegExpPrivate>
|
||||
createTestOptimized(JSContext *cx, JSAtom *originalSource, RegExpFlag flags);
|
||||
|
||||
RegExpRunStatus execute(JSContext *cx, const jschar *chars, size_t length, size_t *lastIndex,
|
||||
LifoAllocScope &allocScope, MatchPairs **output);
|
||||
|
||||
@ -422,6 +470,8 @@ class RegExpMatcher
|
||||
|
||||
inline bool reset(JSLinearString *patstr, JSString *opt);
|
||||
|
||||
bool resetWithTestOptimized(RegExpObject *reobj);
|
||||
|
||||
RegExpRunStatus execute(JSContext *cx, const jschar *chars, size_t length, size_t *lastIndex,
|
||||
LifoAllocScope &allocScope, MatchPairs **output) {
|
||||
JS_ASSERT(!arc.null());
|
||||
|
@ -522,6 +522,11 @@ private:
|
||||
ASSERT(!m_err);
|
||||
ASSERT(min <= max);
|
||||
|
||||
if (min == unsigned(-1)) {
|
||||
m_err = QuantifierTooLarge;
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastTokenWasAnAtom)
|
||||
m_delegate.quantifyAtom(min, max, !tryConsume('?'));
|
||||
else
|
||||
|
@ -516,7 +516,7 @@ public:
|
||||
m_alternative = m_alternative->m_parent->addNewAlternative();
|
||||
}
|
||||
|
||||
unsigned setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition)
|
||||
ErrorCode setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition, unsigned *callFrameSizeOut)
|
||||
{
|
||||
alternative->m_hasFixedSize = true;
|
||||
unsigned currentInputPosition = initialInputPosition;
|
||||
@ -567,18 +567,22 @@ public:
|
||||
if (term.quantityCount == 1 && !term.parentheses.isCopy) {
|
||||
if (term.quantityType != QuantifierFixedCount)
|
||||
currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesOnce;
|
||||
currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition);
|
||||
if (ErrorCode error = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition, ¤tCallFrameSize))
|
||||
return error;
|
||||
// If quantity is fixed, then pre-check its minimum size.
|
||||
if (term.quantityType == QuantifierFixedCount)
|
||||
currentInputPosition += term.parentheses.disjunction->m_minimumSize;
|
||||
term.inputPosition = currentInputPosition;
|
||||
} else if (term.parentheses.isTerminal) {
|
||||
currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesTerminal;
|
||||
currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition);
|
||||
if (ErrorCode error = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition, ¤tCallFrameSize))
|
||||
return error;
|
||||
term.inputPosition = currentInputPosition;
|
||||
} else {
|
||||
term.inputPosition = currentInputPosition;
|
||||
setupDisjunctionOffsets(term.parentheses.disjunction, BASE_FRAME_SIZE, currentInputPosition);
|
||||
unsigned dummy;
|
||||
if (ErrorCode error = setupDisjunctionOffsets(term.parentheses.disjunction, BASE_FRAME_SIZE, currentInputPosition, &dummy))
|
||||
return error;
|
||||
currentCallFrameSize += YarrStackSpaceForBackTrackInfoParentheses;
|
||||
}
|
||||
// Fixed count of 1 could be accepted, if they have a fixed size *AND* if all alternatives are of the same length.
|
||||
@ -588,16 +592,18 @@ public:
|
||||
case PatternTerm::TypeParentheticalAssertion:
|
||||
term.inputPosition = currentInputPosition;
|
||||
term.frameLocation = currentCallFrameSize;
|
||||
currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + YarrStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition);
|
||||
if (ErrorCode error = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + YarrStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition, ¤tCallFrameSize))
|
||||
return error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
alternative->m_minimumSize = currentInputPosition - initialInputPosition;
|
||||
return currentCallFrameSize;
|
||||
*callFrameSizeOut = currentCallFrameSize;
|
||||
return NoError;
|
||||
}
|
||||
|
||||
unsigned setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition)
|
||||
ErrorCode setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition, unsigned *maximumCallFrameSizeOut)
|
||||
{
|
||||
if ((disjunction != m_pattern.m_body) && (disjunction->m_alternatives.size() > 1))
|
||||
initialCallFrameSize += YarrStackSpaceForBackTrackInfoAlternative;
|
||||
@ -608,24 +614,30 @@ public:
|
||||
|
||||
for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
|
||||
PatternAlternative* alternative = disjunction->m_alternatives[alt];
|
||||
unsigned currentAlternativeCallFrameSize = setupAlternativeOffsets(alternative, initialCallFrameSize, initialInputPosition);
|
||||
unsigned currentAlternativeCallFrameSize;
|
||||
if (ErrorCode error = setupAlternativeOffsets(alternative, initialCallFrameSize, initialInputPosition, ¤tAlternativeCallFrameSize))
|
||||
return error;
|
||||
minimumInputSize = std::min(minimumInputSize, alternative->m_minimumSize);
|
||||
maximumCallFrameSize = std::max(maximumCallFrameSize, currentAlternativeCallFrameSize);
|
||||
hasFixedSize &= alternative->m_hasFixedSize;
|
||||
}
|
||||
|
||||
ASSERT(minimumInputSize != UINT_MAX);
|
||||
if (minimumInputSize == UINT_MAX)
|
||||
return PatternTooLarge;
|
||||
|
||||
ASSERT(maximumCallFrameSize >= initialCallFrameSize);
|
||||
|
||||
disjunction->m_hasFixedSize = hasFixedSize;
|
||||
disjunction->m_minimumSize = minimumInputSize;
|
||||
disjunction->m_callFrameSize = maximumCallFrameSize;
|
||||
return maximumCallFrameSize;
|
||||
*maximumCallFrameSizeOut = maximumCallFrameSize;
|
||||
return NoError;
|
||||
}
|
||||
|
||||
void setupOffsets()
|
||||
ErrorCode setupOffsets()
|
||||
{
|
||||
setupDisjunctionOffsets(m_pattern.m_body, BASE_FRAME_SIZE, 0);
|
||||
unsigned dummy;
|
||||
return setupDisjunctionOffsets(m_pattern.m_body, BASE_FRAME_SIZE, 0, &dummy);
|
||||
}
|
||||
|
||||
// This optimization identifies sets of parentheses that we will never need to backtrack.
|
||||
@ -718,7 +730,8 @@ ErrorCode YarrPattern::compile(const UString& patternString)
|
||||
constructor.checkForTerminalParentheses();
|
||||
constructor.optimizeBOL();
|
||||
|
||||
constructor.setupOffsets();
|
||||
if (ErrorCode error = constructor.setupOffsets())
|
||||
return error;
|
||||
|
||||
return NoError;
|
||||
}
|
||||
|
@ -230,6 +230,7 @@ members = [
|
||||
'nsIDOMHTMLDocument.domain',
|
||||
'nsIDOMHTMLDocument.getSelection',
|
||||
'nsIDOMHTMLDocument.designMode',
|
||||
'nsIDOMHTMLDocument.head',
|
||||
'nsIDOMHTMLElement.*',
|
||||
'nsIDOMHTMLFormElement.elements',
|
||||
'nsIDOMHTMLFormElement.name',
|
||||
@ -650,7 +651,13 @@ customMethodCalls = {
|
||||
},
|
||||
'nsIDOMHTMLDocument_GetBody': {
|
||||
'thisType': 'nsHTMLDocument',
|
||||
'code': ' nsIContent *result = self->GetBody(&rv);'
|
||||
'code': ' nsIContent *result = self->GetBody();',
|
||||
'canFail': False
|
||||
},
|
||||
'nsIDOMHTMLDocument_GetHead': {
|
||||
'thisType': 'nsHTMLDocument',
|
||||
'code': ' nsIContent *result = self->GetHead();',
|
||||
'canFail': False
|
||||
},
|
||||
'nsIDOMHTMLDocument_GetElementsByName': {
|
||||
'thisType': 'nsHTMLDocument',
|
||||
|
@ -2219,6 +2219,11 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
|
||||
styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, sheet);
|
||||
}
|
||||
|
||||
sheet = nsLayoutStylesheetCache::FullScreenOverrideSheet();
|
||||
if (sheet) {
|
||||
styleSet->PrependStyleSheet(nsStyleSet::eOverrideSheet, sheet);
|
||||
}
|
||||
|
||||
// Make sure to clone the quirk sheet so that it can be usefully
|
||||
// enabled/disabled as needed.
|
||||
nsRefPtr<nsCSSStyleSheet> quirkClone;
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -12,17 +11,15 @@
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is DevTools test code.
|
||||
* The Original Code is Mozilla code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* David Dahl <ddahl@mozilla.com>
|
||||
* Patrick Walton <pcwalton@mozilla.com>
|
||||
* Julian Viereck <jviereck@mozilla.com>
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
* Chris Pearce <chris@pearce.org.nz>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -38,36 +35,22 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// Tests that the console message store is initialized properly.
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//browser/test-console.html";
|
||||
|
||||
function test() {
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", testStorageCreateDisplay,
|
||||
false);
|
||||
}
|
||||
|
||||
function testStorageCreateDisplay() {
|
||||
browser.removeEventListener("DOMContentLoaded", testStorageCreateDisplay,
|
||||
false);
|
||||
|
||||
openConsole();
|
||||
|
||||
let cs = HUDService.storage;
|
||||
|
||||
ok(typeof cs.consoleDisplays == "object",
|
||||
"consoledisplays exist");
|
||||
ok(typeof cs.displayIndexes == "object",
|
||||
"console indexes exist");
|
||||
cs.createDisplay("foo");
|
||||
ok(typeof cs.consoleDisplays["foo"] == "object",
|
||||
"foo display exists");
|
||||
ok(typeof cs.displayIndexes["foo"] == "object",
|
||||
"foo index exists");
|
||||
|
||||
cs.removeDisplay("foo");
|
||||
|
||||
finishTest();
|
||||
*|*:-moz-full-screen-ancestor {
|
||||
/* Ancestors of a full-screen element should not induce stacking contexts
|
||||
that would prevent the full-screen element from being on top. */
|
||||
z-index: auto;
|
||||
/* Ancestors of a full-screen element should not be partially transparent,
|
||||
since that would apply to the full-screen element and make the page visible
|
||||
behind it. It would also create a pseudo-stacking-context that would let content
|
||||
draw on top of the full-screen element. */
|
||||
opacity: 1;
|
||||
/* Ancestors of a full-screen element should not apply SVG masking, clipping, or
|
||||
filtering, since that would affect the full-screen element and create a pseudo-
|
||||
stacking context. */
|
||||
mask: none;
|
||||
clip: auto;
|
||||
filter: none;
|
||||
-moz-transform: none;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ toolkit.jar:
|
||||
* res/ua.css (ua.css)
|
||||
res/html.css (html.css)
|
||||
res/quirk.css (quirk.css)
|
||||
res/full-screen-override.css (full-screen-override.css)
|
||||
res/viewsource.css (viewsource.css)
|
||||
* res/forms.css (forms.css)
|
||||
res/arrow.gif (arrow.gif)
|
||||
|
@ -155,6 +155,16 @@ nsLayoutStylesheetCache::QuirkSheet()
|
||||
return gStyleCache->mQuirkSheet;
|
||||
}
|
||||
|
||||
nsCSSStyleSheet*
|
||||
nsLayoutStylesheetCache::FullScreenOverrideSheet()
|
||||
{
|
||||
EnsureGlobal();
|
||||
if (!gStyleCache)
|
||||
return nsnull;
|
||||
|
||||
return gStyleCache->mFullScreenOverrideSheet;
|
||||
}
|
||||
|
||||
void
|
||||
nsLayoutStylesheetCache::Shutdown()
|
||||
{
|
||||
@ -191,6 +201,13 @@ nsLayoutStylesheetCache::nsLayoutStylesheetCache()
|
||||
LoadSheet(uri, mQuirkSheet, true);
|
||||
}
|
||||
NS_ASSERTION(mQuirkSheet, "Could not load quirk.css");
|
||||
|
||||
NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/full-screen-override.css");
|
||||
if (uri) {
|
||||
LoadSheet(uri, mFullScreenOverrideSheet, true);
|
||||
}
|
||||
NS_ASSERTION(mFullScreenOverrideSheet, "Could not load full-screen-override.css");
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -64,6 +64,7 @@ class nsLayoutStylesheetCache
|
||||
static nsCSSStyleSheet* UserChromeSheet();
|
||||
static nsCSSStyleSheet* UASheet();
|
||||
static nsCSSStyleSheet* QuirkSheet();
|
||||
static nsCSSStyleSheet* FullScreenOverrideSheet();
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
@ -85,6 +86,7 @@ private:
|
||||
nsRefPtr<nsCSSStyleSheet> mUserChromeSheet;
|
||||
nsRefPtr<nsCSSStyleSheet> mUASheet;
|
||||
nsRefPtr<nsCSSStyleSheet> mQuirkSheet;
|
||||
nsRefPtr<nsCSSStyleSheet> mFullScreenOverrideSheet;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -260,23 +260,6 @@
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
*|*:-moz-full-screen-ancestor {
|
||||
/* Ancestors of a full-screen element should not induce stacking contexts
|
||||
that would prevent the full-screen element from being on top. */
|
||||
z-index:auto !important;
|
||||
/* Ancestors of a full-screen element should not be partially transparent,
|
||||
since that would apply to the full-screen element and make the page visible
|
||||
behind it. It would also create a pseudo-stacking-context that would let content
|
||||
draw on top of the full-screen element. */
|
||||
opacity:1 !important;
|
||||
/* Ancestors of a full-screen element should not apply SVG masking, clipping, or
|
||||
filtering, since that would affect the full-screen element and create a pseudo-
|
||||
stacking context. */
|
||||
mask:none !important;
|
||||
clip:none !important;
|
||||
filter:none !important;
|
||||
}
|
||||
|
||||
/* XML parse error reporting */
|
||||
|
||||
parsererror|parsererror {
|
||||
|
@ -1084,6 +1084,52 @@ struct arena_s {
|
||||
static unsigned ncpus;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When MALLOC_STATIC_SIZES is defined most of the parameters
|
||||
* controlling the malloc behavior are defined as compile-time constants
|
||||
* for best performance and cannot be altered at runtime.
|
||||
*/
|
||||
#define MALLOC_STATIC_SIZES 1
|
||||
|
||||
#ifdef MALLOC_STATIC_SIZES
|
||||
|
||||
/*
|
||||
* VM page size. It must divide the runtime CPU page size or the code
|
||||
* will abort.
|
||||
*/
|
||||
#define pagesize_2pow ((size_t) 12)
|
||||
#define pagesize ((size_t) 1 << pagesize_2pow)
|
||||
#define pagesize_mask (pagesize - 1)
|
||||
|
||||
/* Various quantum-related settings. */
|
||||
|
||||
#define QUANTUM_DEFAULT ((size_t) 1 << QUANTUM_2POW_MIN)
|
||||
static const size_t quantum = QUANTUM_DEFAULT;
|
||||
static const size_t quantum_mask = QUANTUM_DEFAULT - 1;
|
||||
|
||||
/* Various bin-related settings. */
|
||||
|
||||
static const size_t small_min = (QUANTUM_DEFAULT >> 1) + 1;
|
||||
static const size_t small_max = (size_t) SMALL_MAX_DEFAULT;
|
||||
|
||||
/* Max size class for bins. */
|
||||
static const size_t bin_maxclass = pagesize >> 1;
|
||||
|
||||
/* Number of (2^n)-spaced tiny bins. */
|
||||
static const unsigned ntbins = (unsigned)
|
||||
(QUANTUM_2POW_MIN - TINY_MIN_2POW);
|
||||
|
||||
/* Number of quantum-spaced bins. */
|
||||
static const unsigned nqbins = (unsigned)
|
||||
(SMALL_MAX_DEFAULT >> QUANTUM_2POW_MIN);
|
||||
|
||||
/* Number of (2^n)-spaced sub-page bins. */
|
||||
static const unsigned nsbins = (unsigned)
|
||||
(pagesize_2pow -
|
||||
SMALL_MAX_2POW_DEFAULT - 1);
|
||||
|
||||
#else /* !MALLOC_STATIC_SIZES */
|
||||
|
||||
/* VM page size. */
|
||||
static size_t pagesize;
|
||||
static size_t pagesize_mask;
|
||||
@ -1101,12 +1147,41 @@ static size_t small_max;
|
||||
static size_t quantum;
|
||||
static size_t quantum_mask; /* (quantum - 1). */
|
||||
|
||||
#endif
|
||||
|
||||
/* Various chunk-related settings. */
|
||||
|
||||
/*
|
||||
* Compute the header size such that it is large enough to contain the page map
|
||||
* and enough nodes for the worst case: one node per non-header page plus one
|
||||
* extra for situations where we briefly have one more node allocated than we
|
||||
* will need.
|
||||
*/
|
||||
#define calculate_arena_header_size() \
|
||||
(sizeof(arena_chunk_t) + sizeof(arena_chunk_map_t) * (chunk_npages - 1))
|
||||
|
||||
#define calculate_arena_header_pages() \
|
||||
((calculate_arena_header_size() >> pagesize_2pow) + \
|
||||
((calculate_arena_header_size() & pagesize_mask) ? 1 : 0))
|
||||
|
||||
/* Max size class for arenas. */
|
||||
#define calculate_arena_maxclass() \
|
||||
(chunksize - (arena_chunk_header_npages << pagesize_2pow))
|
||||
|
||||
#ifdef MALLOC_STATIC_SIZES
|
||||
#define CHUNKSIZE_DEFAULT ((size_t) 1 << CHUNK_2POW_DEFAULT)
|
||||
static const size_t chunksize = CHUNKSIZE_DEFAULT;
|
||||
static const size_t chunksize_mask =CHUNKSIZE_DEFAULT - 1;
|
||||
static const size_t chunk_npages = CHUNKSIZE_DEFAULT >> pagesize_2pow;
|
||||
#define arena_chunk_header_npages calculate_arena_header_pages()
|
||||
#define arena_maxclass calculate_arena_maxclass()
|
||||
#else
|
||||
static size_t chunksize;
|
||||
static size_t chunksize_mask; /* (chunksize - 1). */
|
||||
static size_t chunk_npages;
|
||||
static size_t arena_chunk_header_npages;
|
||||
static size_t arena_maxclass; /* Max size class for arenas. */
|
||||
#endif
|
||||
|
||||
/********/
|
||||
/*
|
||||
@ -1218,9 +1293,15 @@ static size_t opt_dirty_max = DIRTY_MAX_DEFAULT;
|
||||
static uint64_t opt_balance_threshold = BALANCE_THRESHOLD_DEFAULT;
|
||||
#endif
|
||||
static bool opt_print_stats = false;
|
||||
#ifdef MALLOC_STATIC_SIZES
|
||||
#define opt_quantum_2pow QUANTUM_2POW_MIN
|
||||
#define opt_small_max_2pow SMALL_MAX_2POW_DEFAULT
|
||||
#define opt_chunk_2pow CHUNK_2POW_DEFAULT
|
||||
#else
|
||||
static size_t opt_quantum_2pow = QUANTUM_2POW_MIN;
|
||||
static size_t opt_small_max_2pow = SMALL_MAX_2POW_DEFAULT;
|
||||
static size_t opt_chunk_2pow = CHUNK_2POW_DEFAULT;
|
||||
#endif
|
||||
#ifdef MALLOC_PAGEFILE
|
||||
static bool opt_pagefile = false;
|
||||
#endif
|
||||
@ -5559,8 +5640,6 @@ malloc_init_hard(void)
|
||||
GetSystemInfo(&info);
|
||||
result = info.dwPageSize;
|
||||
|
||||
pagesize = (unsigned) result;
|
||||
|
||||
#ifndef MOZ_MEMORY_NARENAS_DEFAULT_ONE
|
||||
ncpus = info.dwNumberOfProcessors;
|
||||
#endif
|
||||
@ -5572,18 +5651,23 @@ malloc_init_hard(void)
|
||||
|
||||
result = sysconf(_SC_PAGESIZE);
|
||||
assert(result != -1);
|
||||
|
||||
pagesize = (unsigned) result;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We assume that pagesize is a power of 2 when calculating
|
||||
* pagesize_mask and pagesize_2pow.
|
||||
*/
|
||||
/* We assume that the page size is a power of 2. */
|
||||
assert(((result - 1) & result) == 0);
|
||||
pagesize_mask = result - 1;
|
||||
#ifdef MALLOC_STATIC_SIZES
|
||||
if (pagesize % (size_t) result) {
|
||||
_malloc_message(_getprogname(),
|
||||
"Compile-time page size does not divide the runtime one.\n",
|
||||
"", "");
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
pagesize = (size_t) result;
|
||||
pagesize_mask = (size_t) result - 1;
|
||||
pagesize_2pow = ffs((int)result) - 1;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MALLOC_PAGEFILE
|
||||
/*
|
||||
* Determine where to create page files. It is insufficient to
|
||||
@ -5732,6 +5816,7 @@ MALLOC_OUT:
|
||||
opt_junk = true;
|
||||
break;
|
||||
#endif
|
||||
#ifndef MALLOC_STATIC_SIZES
|
||||
case 'k':
|
||||
/*
|
||||
* Chunks always require at least one
|
||||
@ -5746,6 +5831,7 @@ MALLOC_OUT:
|
||||
(sizeof(size_t) << 3))
|
||||
opt_chunk_2pow++;
|
||||
break;
|
||||
#endif
|
||||
case 'n':
|
||||
opt_narenas_lshift--;
|
||||
break;
|
||||
@ -5768,6 +5854,7 @@ MALLOC_OUT:
|
||||
case 'P':
|
||||
opt_print_stats = true;
|
||||
break;
|
||||
#ifndef MALLOC_STATIC_SIZES
|
||||
case 'q':
|
||||
if (opt_quantum_2pow > QUANTUM_2POW_MIN)
|
||||
opt_quantum_2pow--;
|
||||
@ -5787,6 +5874,7 @@ MALLOC_OUT:
|
||||
- 1)
|
||||
opt_small_max_2pow++;
|
||||
break;
|
||||
#endif
|
||||
#ifdef MALLOC_UTRACE
|
||||
case 'u':
|
||||
opt_utrace = false;
|
||||
@ -5849,6 +5937,7 @@ MALLOC_OUT:
|
||||
pthread_atfork(_malloc_prefork, _malloc_postfork, _malloc_postfork);
|
||||
#endif
|
||||
|
||||
#ifndef MALLOC_STATIC_SIZES
|
||||
/* Set variables according to the value of opt_small_max_2pow. */
|
||||
if (opt_small_max_2pow < opt_quantum_2pow)
|
||||
opt_small_max_2pow = opt_quantum_2pow;
|
||||
@ -5875,23 +5964,10 @@ MALLOC_OUT:
|
||||
chunksize = (1LU << opt_chunk_2pow);
|
||||
chunksize_mask = chunksize - 1;
|
||||
chunk_npages = (chunksize >> pagesize_2pow);
|
||||
{
|
||||
size_t header_size;
|
||||
|
||||
/*
|
||||
* Compute the header size such that it is large
|
||||
* enough to contain the page map and enough nodes for the
|
||||
* worst case: one node per non-header page plus one extra for
|
||||
* situations where we briefly have one more node allocated
|
||||
* than we will need.
|
||||
*/
|
||||
header_size = sizeof(arena_chunk_t) +
|
||||
(sizeof(arena_chunk_map_t) * (chunk_npages - 1));
|
||||
arena_chunk_header_npages = (header_size >> pagesize_2pow) +
|
||||
((header_size & pagesize_mask) != 0);
|
||||
}
|
||||
arena_maxclass = chunksize - (arena_chunk_header_npages <<
|
||||
pagesize_2pow);
|
||||
arena_chunk_header_npages = calculate_arena_header_pages();
|
||||
arena_maxclass = calculate_arena_maxclass();
|
||||
#endif
|
||||
|
||||
#ifdef JEMALLOC_USES_MAP_ALIGN
|
||||
/*
|
||||
|
@ -277,7 +277,6 @@
|
||||
@BINPATH@/components/xuldoc.xpt
|
||||
@BINPATH@/components/xultmpl.xpt
|
||||
@BINPATH@/components/zipwriter.xpt
|
||||
@BINPATH@/components/openwebapps.xpt
|
||||
|
||||
; JavaScript components
|
||||
@BINPATH@/components/ConsoleAPI.manifest
|
||||
@ -331,7 +330,6 @@
|
||||
@BINPATH@/components/amContentHandler.js
|
||||
@BINPATH@/components/amWebInstallListener.js
|
||||
@BINPATH@/components/nsBlocklistService.js
|
||||
@BINPATH@/components/OpenWebapps.manifest
|
||||
|
||||
#ifdef MOZ_UPDATER
|
||||
@BINPATH@/components/nsUpdateService.manifest
|
||||
@ -607,7 +605,6 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
|
||||
@BINPATH@/components/PromptService.js
|
||||
@BINPATH@/components/SessionStore.js
|
||||
@BINPATH@/components/Sidebar.js
|
||||
@BINPATH@/components/OpenWebapps.js
|
||||
#ifdef MOZ_SAFE_BROWSING
|
||||
@BINPATH@/components/SafeBrowsing.js
|
||||
#endif
|
||||
|
@ -808,7 +808,7 @@ net_FindMediaDelimiter(const nsCString& flatStr,
|
||||
do {
|
||||
// searchStart points to the spot from which we should start looking
|
||||
// for the delimiter.
|
||||
const char delimStr[] = { delimiter, '"', '\'', '\0' };
|
||||
const char delimStr[] = { delimiter, '"', '\0' };
|
||||
PRUint32 curDelimPos = flatStr.FindCharInSet(delimStr, searchStart);
|
||||
if (curDelimPos == PRUint32(kNotFound))
|
||||
return flatStr.Length();
|
||||
@ -893,7 +893,7 @@ net_ParseMediaType(const nsACString &aMediaTypeStr,
|
||||
// '(' in the trailing trim set to catch media-type comments, which are
|
||||
// not at all standard, but may occur in rare cases.
|
||||
charset = net_FindCharNotInSet(charset, charsetEnd, HTTP_LWS);
|
||||
if (*charset == '"' || *charset == '\'') {
|
||||
if (*charset == '"') {
|
||||
charsetEnd =
|
||||
start + net_FindStringEnd(flatStr, charset - start, *charset);
|
||||
charset++;
|
||||
|
@ -121,15 +121,15 @@ function run_test() {
|
||||
hadCharset =
|
||||
netutil.extractCharsetFromContentType("text/html; charset='ISO-8859-1'",
|
||||
charset, charsetStart, charsetEnd);
|
||||
check(true, "ISO-8859-1", 9, 31);
|
||||
check(true, "'ISO-8859-1'", 9, 31);
|
||||
|
||||
hadCharset =
|
||||
netutil.extractCharsetFromContentType("text/html; charset='ISO-8859-1', text/html",
|
||||
netutil.extractCharsetFromContentType("text/html; charset=\"ISO-8859-1\", text/html",
|
||||
charset, charsetStart, charsetEnd);
|
||||
check(true, "ISO-8859-1", 9, 31);
|
||||
|
||||
hadCharset =
|
||||
netutil.extractCharsetFromContentType("text/html; charset='ISO-8859-1', text/html; charset=UTF8",
|
||||
netutil.extractCharsetFromContentType("text/html; charset=\"ISO-8859-1\", text/html; charset=UTF8",
|
||||
charset, charsetStart, charsetEnd);
|
||||
check(true, "UTF8", 42, 56);
|
||||
|
||||
@ -144,17 +144,17 @@ function run_test() {
|
||||
check(false, "", 41, 41);
|
||||
|
||||
hadCharset =
|
||||
netutil.extractCharsetFromContentType("text/plain, TEXT/HTML; charset='ISO-8859-1', text/html, TEXT/HTML",
|
||||
netutil.extractCharsetFromContentType("text/plain, TEXT/HTML; charset=\"ISO-8859-1\", text/html, TEXT/HTML",
|
||||
charset, charsetStart, charsetEnd);
|
||||
check(true, "ISO-8859-1", 21, 43);
|
||||
|
||||
hadCharset =
|
||||
netutil.extractCharsetFromContentType('text/plain, TEXT/HTML; param="charset=UTF8"; charset=\'ISO-8859-1\'; param2="charset=UTF16", text/html, TEXT/HTML',
|
||||
netutil.extractCharsetFromContentType('text/plain, TEXT/HTML; param="charset=UTF8"; charset="ISO-8859-1"; param2="charset=UTF16", text/html, TEXT/HTML',
|
||||
charset, charsetStart, charsetEnd);
|
||||
check(true, "ISO-8859-1", 43, 65);
|
||||
|
||||
hadCharset =
|
||||
netutil.extractCharsetFromContentType('text/plain, TEXT/HTML; param=charset=UTF8; charset=\'ISO-8859-1\'; param2=charset=UTF16, text/html, TEXT/HTML',
|
||||
netutil.extractCharsetFromContentType('text/plain, TEXT/HTML; param=charset=UTF8; charset="ISO-8859-1"; param2=charset=UTF16, text/html, TEXT/HTML',
|
||||
charset, charsetStart, charsetEnd);
|
||||
check(true, "ISO-8859-1", 41, 63);
|
||||
|
||||
|
@ -56,6 +56,7 @@ function check(aType, aCharset, aHadCharset) {
|
||||
function run_test() {
|
||||
var netutil = Components.classes["@mozilla.org/network/util;1"]
|
||||
.getService(Components.interfaces.nsINetUtil);
|
||||
|
||||
type = netutil.parseContentType("text/html", charset, hadCharset);
|
||||
check("text/html", "", false);
|
||||
|
||||
@ -88,13 +89,13 @@ function run_test() {
|
||||
|
||||
type = netutil.parseContentType("text/html; charset='ISO-8859-1'",
|
||||
charset, hadCharset);
|
||||
check("text/html", "ISO-8859-1", true);
|
||||
check("text/html", "'ISO-8859-1'", true);
|
||||
|
||||
type = netutil.parseContentType("text/html; charset='ISO-8859-1', text/html",
|
||||
type = netutil.parseContentType("text/html; charset=\"ISO-8859-1\", text/html",
|
||||
charset, hadCharset);
|
||||
check("text/html", "ISO-8859-1", true);
|
||||
|
||||
type = netutil.parseContentType("text/html; charset='ISO-8859-1', text/html; charset=UTF8",
|
||||
type = netutil.parseContentType("text/html; charset=\"ISO-8859-1\", text/html; charset=UTF8",
|
||||
charset, hadCharset);
|
||||
check("text/html", "UTF8", true);
|
||||
|
||||
@ -104,13 +105,13 @@ function run_test() {
|
||||
type = netutil.parseContentType("text/html; charset=ISO-8859-1, TEXT/plain", charset, hadCharset);
|
||||
check("text/plain", "", true);
|
||||
|
||||
type = netutil.parseContentType("text/plain, TEXT/HTML; charset='ISO-8859-1', text/html, TEXT/HTML", charset, hadCharset);
|
||||
type = netutil.parseContentType("text/plain, TEXT/HTML; charset=ISO-8859-1, text/html, TEXT/HTML", charset, hadCharset);
|
||||
check("text/html", "ISO-8859-1", true);
|
||||
|
||||
type = netutil.parseContentType('text/plain, TEXT/HTML; param="charset=UTF8"; charset=\'ISO-8859-1\'; param2="charset=UTF16", text/html, TEXT/HTML', charset, hadCharset);
|
||||
type = netutil.parseContentType('text/plain, TEXT/HTML; param="charset=UTF8"; charset="ISO-8859-1"; param2="charset=UTF16", text/html, TEXT/HTML', charset, hadCharset);
|
||||
check("text/html", "ISO-8859-1", true);
|
||||
|
||||
type = netutil.parseContentType('text/plain, TEXT/HTML; param=charset=UTF8; charset=\'ISO-8859-1\'; param2=charset=UTF16, text/html, TEXT/HTML', charset, hadCharset);
|
||||
type = netutil.parseContentType('text/plain, TEXT/HTML; param=charset=UTF8; charset="ISO-8859-1"; param2=charset=UTF16, text/html, TEXT/HTML', charset, hadCharset);
|
||||
check("text/html", "ISO-8859-1", true);
|
||||
|
||||
type = netutil.parseContentType("text/plain; param= , text/html", charset, hadCharset);
|
||||
@ -134,4 +135,13 @@ function run_test() {
|
||||
type = netutil.parseContentType('text/plain, TEXT/HTML; param="charset=UTF8"; ; param2="charset=UTF16", text/html, TEXT/HTML', charset, hadCharset);
|
||||
check("text/html", "", false);
|
||||
|
||||
// Bug 700589
|
||||
|
||||
// check that single quote doesn't confuse parsing of subsequent parameters
|
||||
type = netutil.parseContentType("text/plain; x='; charset=\"UTF-8\"", charset, hadCharset);
|
||||
check("text/plain", "UTF-8", true);
|
||||
|
||||
// check that single quotes do not get removed from extracted charset
|
||||
type = netutil.parseContentType("text/plain; charset='UTF-8'", charset, hadCharset);
|
||||
check("text/plain", "'UTF-8'", true);
|
||||
}
|
||||
|
@ -687,6 +687,14 @@ SpecialPowersAPI.prototype = {
|
||||
cbHelperSvc.copyString(preExpectedVal);
|
||||
},
|
||||
|
||||
supportsSelectionClipboard: function() {
|
||||
if (this._cb == null) {
|
||||
this._cb = Components.classes["@mozilla.org/widget/clipboard;1"].
|
||||
getService(Components.interfaces.nsIClipboard);
|
||||
}
|
||||
return this._cb.supportsSelectionClipboard();
|
||||
},
|
||||
|
||||
snapshotWindow: function (win, withCaret) {
|
||||
var el = this.window.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
el.width = win.innerWidth;
|
||||
|
73
testing/mozbase/Makefile.in
Normal file
73
testing/mozbase/Makefile.in
Normal file
@ -0,0 +1,73 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozbase.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# The Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Andrew Halberstadt <halbersa@gmail.com> (Original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = testing_mozbase
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
# Harness packages from the srcdir;
|
||||
# python packages to be installed IN INSTALLATION ORDER.
|
||||
# Packages later in the list can depend only on packages earlier in the list.
|
||||
MOZBASE_PACKAGES = \
|
||||
manifestdestiny \
|
||||
mozdevice \
|
||||
mozhttpd \
|
||||
mozinfo \
|
||||
mozinstall \
|
||||
mozlog \
|
||||
mozprocess \
|
||||
mozprofile \
|
||||
mozrunner \
|
||||
$(NULL)
|
||||
|
||||
MOZBASE_EXTRAS = \
|
||||
setup_development.py \
|
||||
README \
|
||||
$(NULL)
|
||||
|
||||
stage-package: PKG_STAGE = $(DIST)/test-package-stage
|
||||
stage-package:
|
||||
$(NSINSTALL) -D $(PKG_STAGE)/mozbase
|
||||
@(cd $(srcdir) && tar $(TAR_CREATE_FLAGS) - $(MOZBASE_PACKAGES)) | (cd $(PKG_STAGE)/mozbase && tar -xf -)
|
||||
@(cd $(srcdir) && tar $(TAR_CREATE_FLAGS) - $(MOZBASE_EXTRAS)) | (cd $(PKG_STAGE)/mozbase && tar -xf -)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user