Merge to latest green m-c changeset

This commit is contained in:
Benoit Girard 2011-11-30 11:41:34 -05:00
commit fcfb3785d8
245 changed files with 22082 additions and 1598 deletions

View File

@ -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)) {

View File

@ -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);

View File

@ -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>

View File

@ -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"?>

View File

@ -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;
}

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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();

View File

@ -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

View File

@ -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 \

View File

@ -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);
}
}

View File

@ -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] }] }] };

View File

@ -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});

View File

@ -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

View File

@ -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 \

View File

@ -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");

View File

@ -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]);

View 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();
});
}

View File

@ -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.

View File

@ -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;

View File

@ -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: ""},
]

View File

@ -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()

View File

@ -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
*

View File

@ -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">

View File

@ -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 \

View File

@ -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";
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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/*

View File

@ -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

View File

@ -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…

View File

@ -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 {

View File

@ -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 */

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -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)

View File

@ -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 {

View File

@ -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;
}

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -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)

View File

@ -75,6 +75,11 @@
-moz-margin-start: -3px;
position: relative;
}
.menu-accel,
.menu-iconic-accel {
color: graytext;
}
}
@media all and (-moz-windows-compositor) {

View File

@ -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 {

View File

@ -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,

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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,

View File

@ -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();
}

View File

@ -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);

View File

@ -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) {

View File

@ -66,6 +66,7 @@ DIRS = \
interfaces/notification \
interfaces/svg \
interfaces/smil \
interfaces/apps \
$(NULL)
DIRS += \

View File

@ -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
View 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
View 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
View 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}

View File

@ -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

View 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;
};

View File

@ -57,7 +57,7 @@ SDK_XPIDLSRCS = \
XPIDLSRCS = \
nsIFrameRequestCallback.idl \
nsIBrowserDOMWindow.idl \
nsIContentPermissionPrompt.idl \
nsIContentPermissionPrompt.idl \
nsIContentPrefService.idl \
nsIContentURIGrouper.idl \
nsIDOMClientInformation.idl \

View File

@ -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);

View File

@ -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)

View File

@ -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) },

View File

@ -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() {

View File

@ -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;
}

View File

@ -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();

View File

@ -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;

View File

@ -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);

View File

@ -0,0 +1,3 @@
// |jit-test| error: SyntaxError: invalid quantifier
String.fromCharCode(256).replace(/[^a$]{4294967295}/,"aaaa");

View 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));

View 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']);
}

View 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);

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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)
{

View File

@ -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());

View File

@ -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

View File

@ -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, &currentCallFrameSize))
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, &currentCallFrameSize))
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, &currentCallFrameSize))
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, &currentAlternativeCallFrameSize))
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;
}

View File

@ -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',

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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
/*

View File

@ -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

View File

@ -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++;

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View 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