mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
[JAEGER] Merge from tracemonkey.
This commit is contained in:
commit
53500d5d01
@ -322,6 +322,7 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
|
||||
notifications are */
|
||||
.notification-anchor-icon {
|
||||
display: none;
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
#notification-popup-box[anchorid="geo-notification-icon"] > #geo-notification-icon,
|
||||
|
@ -159,9 +159,13 @@ XPCOMUtils.defineLazyGetter(this, "Weave", function() {
|
||||
XPCOMUtils.defineLazyGetter(this, "PopupNotifications", function () {
|
||||
let tmp = {};
|
||||
Cu.import("resource://gre/modules/PopupNotifications.jsm", tmp);
|
||||
return new tmp.PopupNotifications(gBrowser,
|
||||
document.getElementById("notification-popup"),
|
||||
document.getElementById("notification-popup-box"));
|
||||
try {
|
||||
return new tmp.PopupNotifications(gBrowser,
|
||||
document.getElementById("notification-popup"),
|
||||
document.getElementById("notification-popup-box"));
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
});
|
||||
|
||||
let gInitialPages = [
|
||||
|
@ -222,7 +222,8 @@
|
||||
noautofocus="true"
|
||||
noautohide="true"
|
||||
onclick="InspectorUI.stopInspecting();"
|
||||
onmousemove="InspectorUI.highlighter.handleMouseMove(event);"/>
|
||||
onmousemove="InspectorUI.highlighter.handleMouseMove(event);"
|
||||
onMozMousePixelScroll="InspectorUI.highlighter.handlePixelScroll(event);"/>
|
||||
|
||||
<panel id="inspector-panel"
|
||||
orient="vertical"
|
||||
@ -694,8 +695,8 @@
|
||||
onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'"
|
||||
onblur="setTimeout(function() document.getElementById('identity-box').style.MozUserFocus = '', 0);">
|
||||
<box id="notification-popup-box" hidden="true" align="center">
|
||||
<image id="geo-notification-icon" class="notification-anchor-icon"/>
|
||||
<image id="addons-notification-icon" class="notification-anchor-icon"/>
|
||||
<image id="geo-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
</box>
|
||||
<!-- Use onclick instead of normal popup= syntax since the popup
|
||||
code fires onmousedown, and hence eats our favicon drag events.
|
||||
|
@ -24,6 +24,7 @@
|
||||
* Contributor(s):
|
||||
* Rob Campbell <rcampbell@mozilla.com> (original author)
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
* Julian Viereck <jviereck@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
|
||||
@ -320,6 +321,29 @@ PanelHighlighter.prototype = {
|
||||
InspectorUI.inspectNode(element);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle MozMousePixelScroll in panel when InspectorUI.inspecting is true.
|
||||
*
|
||||
* @param aEvent
|
||||
* The onMozMousePixelScrollEvent triggering the method.
|
||||
* @returns void
|
||||
*/
|
||||
handlePixelScroll: function PanelHighlighter_handlePixelScroll(aEvent) {
|
||||
if (!InspectorUI.inspecting) {
|
||||
return;
|
||||
}
|
||||
let browserRect = this.browser.getBoundingClientRect();
|
||||
let element = InspectorUI.elementFromPoint(this.win.document,
|
||||
aEvent.clientX - browserRect.left, aEvent.clientY - browserRect.top);
|
||||
let win = element.ownerDocument.defaultView;
|
||||
|
||||
if (aEvent.axis == aEvent.HORIZONTAL_AXIS) {
|
||||
win.scrollBy(aEvent.detail, 0);
|
||||
} else {
|
||||
win.scrollBy(0, aEvent.detail);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -488,33 +488,38 @@
|
||||
},
|
||||
|
||||
onLocationChange: function (aWebProgress, aRequest, aLocation) {
|
||||
// The document loaded correctly, clear the value if we should
|
||||
if (this.mBrowser.userTypedClear > 0)
|
||||
this.mBrowser.userTypedValue = null;
|
||||
// OnLocationChange is called for both the top-level content
|
||||
// and the subframes.
|
||||
let topLevel = aWebProgress.DOMWindow == this.mBrowser.contentWindow;
|
||||
|
||||
// Don't clear the favicon if this onLocationChange was triggered
|
||||
// by a pushState or a replaceState. See bug 550565.
|
||||
if (aWebProgress.DOMWindow == this.mBrowser.contentWindow &&
|
||||
aWebProgress.isLoadingDocument &&
|
||||
!(this.mBrowser.docShell.loadType & Ci.nsIDocShell.LOAD_CMD_PUSHSTATE)) {
|
||||
this.mBrowser.mIconURL = null;
|
||||
if (topLevel) {
|
||||
// The document loaded correctly, clear the value if we should
|
||||
if (this.mBrowser.userTypedClear > 0)
|
||||
this.mBrowser.userTypedValue = null;
|
||||
|
||||
// Clear out the missing plugins list since it's related to the
|
||||
// previous location.
|
||||
this.mBrowser.missingPlugins = null;
|
||||
|
||||
// Don't clear the favicon if this onLocationChange was
|
||||
// triggered by a pushState or a replaceState. See bug 550565.
|
||||
if (aWebProgress.isLoadingDocument &&
|
||||
!(this.mBrowser.docShell.loadType & Ci.nsIDocShell.LOAD_CMD_PUSHSTATE))
|
||||
this.mBrowser.mIconURL = null;
|
||||
|
||||
let browserHistory = this.mTabBrowser.mBrowserHistory;
|
||||
if (this.mBrowser.lastURI)
|
||||
browserHistory.unregisterOpenPage(this.mBrowser.lastURI);
|
||||
browserHistory.registerOpenPage(aLocation);
|
||||
}
|
||||
|
||||
// changing location, clear out the missing plugins list
|
||||
this.mBrowser.missingPlugins = null;
|
||||
|
||||
var browserHistory = this.mTabBrowser.mBrowserHistory;
|
||||
if ("lastURI" in this.mBrowser && this.mBrowser.lastURI)
|
||||
browserHistory.unregisterOpenPage(this.mBrowser.lastURI);
|
||||
browserHistory.registerOpenPage(aLocation);
|
||||
|
||||
if (!this.mBlank) {
|
||||
this._callProgressListeners("onLocationChange",
|
||||
[aWebProgress, aRequest, aLocation]);
|
||||
}
|
||||
|
||||
this.mBrowser.lastURI = aLocation;
|
||||
|
||||
if (topLevel)
|
||||
this.mBrowser.lastURI = aLocation;
|
||||
},
|
||||
|
||||
onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) {
|
||||
@ -1410,9 +1415,8 @@
|
||||
filter.removeProgressListener(this.mTabListeners[aTab._tPos]);
|
||||
this.mTabListeners[aTab._tPos].destroy();
|
||||
|
||||
let closedBrowser = this.getBrowserForTab(aTab);
|
||||
if (closedBrowser.currentURI)
|
||||
this.mBrowserHistory.unregisterOpenPage(closedBrowser.currentURI);
|
||||
if (browser.currentURI)
|
||||
this.mBrowserHistory.unregisterOpenPage(browser.currentURI);
|
||||
|
||||
// We are no longer the primary content area.
|
||||
browser.setAttribute("type", "content-targetable");
|
||||
|
155
browser/base/content/tabview/modules/AllTabs.jsm
Normal file
155
browser/base/content/tabview/modules/AllTabs.jsm
Normal file
@ -0,0 +1,155 @@
|
||||
/* ***** 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 TabView AllTabs.
|
||||
*
|
||||
* 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):
|
||||
* Edward Lee <edilee@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;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let EXPORTED_SYMBOLS = ["AllTabs"];
|
||||
|
||||
let AllTabs = {
|
||||
/**
|
||||
* Get an array of all tabs from all tabbrowser windows.
|
||||
*
|
||||
* @usage let numAllTabs = AllTabs.tabs.length;
|
||||
* AllTabs.tabs.forEach(handleAllTabs);
|
||||
*/
|
||||
get tabs() {
|
||||
// Get tabs from each browser window and flatten them into one array
|
||||
return Array.concat.apply(null, browserWindows.map(function(browserWindow) {
|
||||
return Array.slice(browserWindow.gBrowser.tabs);
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach a callback for a given tab event.
|
||||
*
|
||||
* @param eventName
|
||||
* Name of the corresponding Tab* Event; one of "attrModified",
|
||||
* "close", "move", "open", "select".
|
||||
* @param callback
|
||||
* Callback that gets called with the tab as the first argument and
|
||||
* the event as the second argument.
|
||||
* @usage AllTabs.register("change", function handleChange(tab, event) {});
|
||||
*/
|
||||
register: function register(eventName, callback) {
|
||||
// Either add additional callbacks or create the first entry
|
||||
let listeners = eventListeners[eventName];
|
||||
if (listeners)
|
||||
listeners.push(callback);
|
||||
else
|
||||
eventListeners[eventName] = [callback];
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a callback for a given tab event.
|
||||
*
|
||||
* @param eventName
|
||||
* Name of the corresponding Tab* Event; one of "attrModified",
|
||||
* "close", "move", "open", "select".
|
||||
* @param callback
|
||||
* The callback given for the original AllTabs.register call.
|
||||
* @usage AllTabs.unregister("close", handleClose);
|
||||
*/
|
||||
unregister: function unregister(eventName, callback) {
|
||||
// Nothing to remove for this event
|
||||
let listeners = eventListeners[eventName];
|
||||
if (!listeners)
|
||||
return;
|
||||
|
||||
// Can only remove a callback if we have it
|
||||
let index = listeners.indexOf(callback);
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
listeners.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
__defineGetter__("browserWindows", function browserWindows() {
|
||||
let browserWindows = [];
|
||||
let windows = Services.wm.getEnumerator("navigator:browser");
|
||||
while (windows.hasMoreElements())
|
||||
browserWindows.push(windows.getNext());
|
||||
return browserWindows;
|
||||
});
|
||||
|
||||
let events = ["attrModified", "close", "move", "open", "select"];
|
||||
let eventListeners = {};
|
||||
|
||||
function registerBrowserWindow(browserWindow) {
|
||||
events.forEach(function(eventName) {
|
||||
let tabEvent = "Tab" + eventName[0].toUpperCase() + eventName.slice(1);
|
||||
browserWindow.addEventListener(tabEvent, function(event) {
|
||||
// Make sure we've gotten listeners before trying to call
|
||||
let listeners = eventListeners[eventName];
|
||||
if (!listeners)
|
||||
return;
|
||||
|
||||
let tab = event.target;
|
||||
|
||||
// Make a copy of the listeners, so it can't change as we call back
|
||||
listeners.slice().forEach(function(callback) {
|
||||
try {
|
||||
callback(tab, event);
|
||||
}
|
||||
// Don't let failing callbacks stop us but report the failure
|
||||
catch(ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
function observer(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "domwindowopened":
|
||||
subject.addEventListener("load", function() {
|
||||
subject.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
// Now that the window has loaded, only register on browser windows
|
||||
let doc = subject.document.documentElement;
|
||||
if (doc.getAttribute("windowtype") == "navigator:browser")
|
||||
registerBrowserWindow(subject);
|
||||
}, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Register listeners on all browser windows and future ones
|
||||
browserWindows.forEach(registerBrowserWindow);
|
||||
Services.obs.addObserver(observer, "domwindowopened", false);
|
@ -151,6 +151,7 @@ _BROWSER_FILES = \
|
||||
browser_inspector_highlighter.js \
|
||||
browser_inspector_stylePanel.js \
|
||||
browser_inspector_iframeTest.js \
|
||||
browser_inspector_scrolling.js \
|
||||
browser_pageInfo.js \
|
||||
browser_page_style_menu.js \
|
||||
browser_pinnedTabs.js \
|
||||
|
113
browser/base/content/test/browser_inspector_scrolling.js
Normal file
113
browser/base/content/test/browser_inspector_scrolling.js
Normal file
@ -0,0 +1,113 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* ***** 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 Inspector iframe Tests.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Rob Campbell <rcampbell@mozilla.com>
|
||||
* Mihai Șucan <mihai.sucan@gmail.com>
|
||||
* Julian Viereck <jviereck@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 ***** */
|
||||
|
||||
let doc;
|
||||
let div;
|
||||
let iframe;
|
||||
|
||||
function createDocument()
|
||||
{
|
||||
doc.title = "Inspector scrolling Tests";
|
||||
|
||||
iframe = doc.createElement("iframe");
|
||||
|
||||
iframe.addEventListener("load", function () {
|
||||
iframe.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
div = iframe.contentDocument.createElement("div");
|
||||
div.textContent = "big div";
|
||||
div.setAttribute("style", "height:500px; width:500px; border:1px solid gray;");
|
||||
iframe.contentDocument.body.appendChild(div);
|
||||
toggleInspector();
|
||||
}, false);
|
||||
|
||||
iframe.src = "data:text/html,foo bar";
|
||||
doc.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
function toggleInspector()
|
||||
{
|
||||
document.addEventListener("popupshown", inspectNode, false);
|
||||
InspectorUI.toggleInspectorUI();
|
||||
}
|
||||
|
||||
function inspectNode(aEvent)
|
||||
{
|
||||
if (aEvent.target.id != "inspector-panel") {
|
||||
return true;
|
||||
}
|
||||
|
||||
document.removeEventListener("popupshown", inspectNode, false);
|
||||
document.addEventListener("popupshown", performScrollingTest, false);
|
||||
|
||||
InspectorUI.inspectNode(div)
|
||||
}
|
||||
|
||||
function performScrollingTest(aEvent)
|
||||
{
|
||||
if (aEvent.target.id != "highlighter-panel") {
|
||||
return true;
|
||||
}
|
||||
|
||||
document.removeEventListener("popupshown", performScrollingTest, false);
|
||||
|
||||
EventUtils.synthesizeMouseScroll(aEvent.target, 10, 10,
|
||||
{axis:"vertical", delta:50, type:"MozMousePixelScroll"}, window);
|
||||
|
||||
is(iframe.contentDocument.body.scrollTop, 50, "inspected iframe scrolled");
|
||||
|
||||
InspectorUI.closeInspectorUI();
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
doc = content.document;
|
||||
waitForFocus(createDocument, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,mouse scrolling test for inspector";
|
||||
}
|
@ -296,7 +296,7 @@ var tests = [
|
||||
this.firstNotification = showNotification(this.notifyObj);
|
||||
this.notifyObj2 = new basicNotification();
|
||||
this.notifyObj2.id += "-2";
|
||||
this.notifyObj2.anchorID = "urlbar";
|
||||
this.notifyObj2.anchorID = "addons-notification-icon";
|
||||
// Second showNotification() overrides the first
|
||||
this.secondNotification = showNotification(this.notifyObj2);
|
||||
},
|
||||
@ -485,15 +485,17 @@ function triggerSecondaryCommand(popup, index) {
|
||||
}
|
||||
|
||||
function loadURI(uri, callback) {
|
||||
gBrowser.addEventListener("load", function() {
|
||||
// Ignore the about:blank load
|
||||
if (gBrowser.currentURI.spec != uri)
|
||||
return;
|
||||
if (callback) {
|
||||
gBrowser.addEventListener("load", function() {
|
||||
// Ignore the about:blank load
|
||||
if (gBrowser.currentURI.spec != uri)
|
||||
return;
|
||||
|
||||
gBrowser.removeEventListener("load", arguments.callee, true);
|
||||
gBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
callback();
|
||||
}, true);
|
||||
callback();
|
||||
}, true);
|
||||
}
|
||||
gBrowser.loadURI(uri);
|
||||
}
|
||||
|
||||
@ -502,4 +504,4 @@ function dismissNotification(popup) {
|
||||
executeSoon(function () {
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
});
|
||||
}
|
||||
}
|
@ -102,6 +102,23 @@ var gTestSteps = [
|
||||
ensure_opentabs_match_db();
|
||||
nextStep()
|
||||
});
|
||||
},
|
||||
function() {
|
||||
info("Running step 6 - ensure we don't register subframes as open pages");
|
||||
let tab = gBrowser.addTab();
|
||||
tab.linkedBrowser.addEventListener("load", function () {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
// Start the sub-document load.
|
||||
executeSoon(function () {
|
||||
tab.linkedBrowser.addEventListener("load", function (e) {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
ensure_opentabs_match_db();
|
||||
nextStep()
|
||||
}, true);
|
||||
tab.linkedBrowser.contentDocument.querySelector("iframe").src = "http://test2.example.org/";
|
||||
});
|
||||
}, true);
|
||||
tab.linkedBrowser.loadURI('data:text/html,<body><iframe src=""></iframe></body>');
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -36,6 +36,20 @@ function closeContextMenu() {
|
||||
contextMenu.hidePopup();
|
||||
}
|
||||
|
||||
function executeCopyCommand(command, expectedValue)
|
||||
{
|
||||
// Just execute the command directly rather than simulating a context menu
|
||||
// press to avoid having to deal with its asynchronous nature
|
||||
subwindow.controllers.getControllerForCommand(command).doCommand(command);
|
||||
|
||||
// The easiest way to check the clipboard is to paste the contents into a
|
||||
// textbox
|
||||
input.focus();
|
||||
input.value = "";
|
||||
input.controllers.getControllerForCommand("cmd_paste").doCommand("cmd_paste");
|
||||
is(input.value, expectedValue, "paste for command " + command);
|
||||
}
|
||||
|
||||
function getVisibleMenuItems(aMenu) {
|
||||
var items = [];
|
||||
var accessKeys = {};
|
||||
@ -391,6 +405,13 @@ function runTest(testNum) {
|
||||
"spell-add-dictionaries", true], null]);
|
||||
|
||||
closeContextMenu();
|
||||
openContextMenuFor(link); // Invoke context menu for next test.
|
||||
break;
|
||||
|
||||
case 15:
|
||||
executeCopyCommand("cmd_copyLink", "http://mozilla.com/");
|
||||
closeContextMenu();
|
||||
|
||||
subwindow.close();
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
|
@ -207,6 +207,7 @@ repackage-win32-installer: $(WIN32_INSTALLER_IN) $(SUBMAKEFILES)
|
||||
# those are just for language packs
|
||||
cp -r $(DIST)/xpi-stage/locale-$(AB_CD) l10n-stage/localized
|
||||
$(RM) l10n-stage/localized/install.rdf l10n-stage/localized/chrome.manifest
|
||||
mv l10n-stage/localized/chrome/$(AB_CD).manifest l10n-stage/localized/chrome/localized.manifest
|
||||
$(MAKE) -C ../installer/windows CONFIG_DIR=l10ngen l10ngen/setup.exe l10ngen/7zSD.sfx
|
||||
cp ../installer/windows/l10ngen/setup.exe l10n-stage
|
||||
$(NSINSTALL) -D l10n-stage/localized/uninstall
|
||||
|
@ -1007,6 +1007,10 @@ toolbar[iconsize="small"] #fullscreen-button {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.notification-anchor-icon:-moz-focusring {
|
||||
outline: 1px dotted -moz-DialogText;
|
||||
}
|
||||
|
||||
#geo-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
|
||||
}
|
||||
|
@ -1868,6 +1868,11 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.notification-anchor-icon:-moz-focusring {
|
||||
-moz-box-shadow: 0 0 3px 1px -moz-mac-focusring inset,
|
||||
0 0 3px 2px -moz-mac-focusring;
|
||||
}
|
||||
|
||||
#geo-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
|
||||
}
|
||||
|
@ -1107,9 +1107,16 @@ richlistitem[type="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-i
|
||||
|
||||
#TabsToolbar:not(:-moz-lwtheme),
|
||||
#TabsToolbar[tabsontop="false"] {
|
||||
background-image: -moz-linear-gradient(transparent, transparent 50%,
|
||||
rgba(0,0,0,.05) 90%, rgba(0,0,0,.1));
|
||||
}
|
||||
|
||||
#TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme) {
|
||||
-moz-box-shadow: 0 -1px ThreeDShadow inset;
|
||||
background-image: -moz-linear-gradient(transparent, transparent 10%,
|
||||
rgba(0,0,0,.03) 50%, rgba(0,0,0,.1) 90%, rgba(0,0,0,.2));
|
||||
}
|
||||
|
||||
#TabsToolbar[tabsontop="false"] {
|
||||
border-bottom: 1px solid ThreeDShadow !important;
|
||||
}
|
||||
|
||||
.tabbrowser-tabs:-moz-system-metric(touch-enabled) {
|
||||
@ -1611,6 +1618,11 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.notification-anchor-icon:-moz-focusring {
|
||||
outline: 1px dotted -moz-DialogText;
|
||||
outline-offset: -3px;
|
||||
}
|
||||
|
||||
#geo-notification-icon {
|
||||
list-style-image: url(chrome://browser/skin/Geolocation-16.png);
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ check::
|
||||
mkdir unify-sort-test unify-sort-test/a unify-sort-test/b
|
||||
printf "lmn\nabc\nxyz\n" > unify-sort-test/a/file.foo
|
||||
printf "xyz\nlmn\nabc" > unify-sort-test/b/file.foo
|
||||
printf "abc\nlmn\nxyz\n" > unify-sort-test/expected-result
|
||||
printf "lmn\nabc\nxyz\n" > unify-sort-test/expected-result
|
||||
@if ! $(srcdir)/macosx/universal/unify --unify-with-sort "\.foo$$" \
|
||||
./unify-sort-test/a ./unify-sort-test/b \
|
||||
./unify-sort-test/c; then \
|
||||
|
@ -201,7 +201,6 @@ sub copyIfIdentical($$$);
|
||||
sub slurp($);
|
||||
sub get_sorted($);
|
||||
sub compare_sorted($$);
|
||||
sub copy_sorted($$);
|
||||
sub copyIfIdenticalWhenSorted($$$);
|
||||
sub createUniqueFile($$);
|
||||
sub makeUniversal($$$);
|
||||
@ -541,21 +540,6 @@ sub compare_sorted($$) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
# copy_sorted($source, $destination)
|
||||
#
|
||||
# $source and $destination are filenames. Read the contents of $source
|
||||
# into an array, sort it, and then write the sorted contents to $destination.
|
||||
# Returns 1 on success, and undef on failure.
|
||||
sub copy_sorted($$) {
|
||||
my ($src, $dest) = @_;
|
||||
my @lines = get_sorted($src);
|
||||
return undef unless @lines;
|
||||
open FILE, "> $dest" or return undef;
|
||||
print FILE @lines;
|
||||
close FILE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
# copyIfIdenticalWhenSorted($source1, $source2, $target)
|
||||
#
|
||||
# $source1 and $source2 are FileAttrCache objects that are compared, and if
|
||||
@ -605,8 +589,8 @@ sub copyIfIdenticalWhenSorted($$$) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!copy_sorted($source1->path(), $target)) {
|
||||
complain(1, 'copyIfIdenticalWhenSorted: copy_sorted: '.$!
|
||||
if (!copy($source1->path(), $target)) {
|
||||
complain(1, 'copyIfIdenticalWhenSorted: copy: '.$!
|
||||
.' while copying',
|
||||
$source1->path(),
|
||||
$target);
|
||||
|
@ -1,5 +1,2 @@
|
||||
repo: f5ab154deef2ffa97f1b2139589ae4a1962090a4
|
||||
node: e50be3234e397322410b29a9e226365e23cb322e
|
||||
branch: default
|
||||
latesttag: null
|
||||
latesttagdistance: 255
|
||||
node: 7ae0b4af32617677698f9de3ab76bcb154bbf085
|
||||
|
@ -10,10 +10,8 @@ import sys, os
|
||||
import pymake.command, pymake.process
|
||||
|
||||
import gc
|
||||
gc.disable()
|
||||
|
||||
if __name__ == '__main__':
|
||||
gc.disable()
|
||||
|
||||
pymake.command.main(sys.argv[1:], os.environ, os.getcwd(), cb=sys.exit)
|
||||
pymake.process.ParallelContext.spin()
|
||||
assert False, "Not reached"
|
||||
pymake.command.main(sys.argv[1:], os.environ, os.getcwd(), cb=sys.exit)
|
||||
pymake.process.ParallelContext.spin()
|
||||
assert False, "Not reached"
|
||||
|
@ -1,68 +1,10 @@
|
||||
# Basic commands implemented in Python
|
||||
import sys, os, shutil, time
|
||||
from getopt import getopt, GetoptError
|
||||
"""
|
||||
Implicit variables; perhaps in the future this will also include some implicit
|
||||
rules, at least match-anything cancellation rules.
|
||||
"""
|
||||
|
||||
from process import PythonException
|
||||
|
||||
__all__ = ["rm", "sleep", "touch"]
|
||||
|
||||
def rm(args):
|
||||
"""
|
||||
Emulate most of the behavior of rm(1).
|
||||
Only supports the -r (--recursive) and -f (--force) arguments.
|
||||
"""
|
||||
try:
|
||||
opts, args = getopt(args, "rRf", ["force", "recursive"])
|
||||
except GetoptError, e:
|
||||
raise PythonException, ("rm: %s" % e, 1)
|
||||
force = False
|
||||
recursive = False
|
||||
for o, a in opts:
|
||||
if o in ('-f', '--force'):
|
||||
force = True
|
||||
elif o in ('-r', '-R', '--recursive'):
|
||||
recursive = True
|
||||
for f in args:
|
||||
if os.path.isdir(f):
|
||||
if not recursive:
|
||||
raise PythonException, ("rm: cannot remove '%s': Is a directory" % f, 1)
|
||||
else:
|
||||
shutil.rmtree(f, force)
|
||||
elif os.path.exists(f):
|
||||
try:
|
||||
os.unlink(f)
|
||||
except:
|
||||
if not force:
|
||||
raise PythonException, ("rm: failed to remove '%s': %s" % (f, sys.exc_info()[0]), 1)
|
||||
elif not force:
|
||||
raise PythonException, ("rm: cannot remove '%s': No such file or directory" % f, 1)
|
||||
|
||||
def sleep(args):
|
||||
"""
|
||||
Emulate the behavior of sleep(1).
|
||||
"""
|
||||
total = 0
|
||||
values = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}
|
||||
for a in args:
|
||||
multiplier = 1
|
||||
for k, v in values.iteritems():
|
||||
if a.endswith(k):
|
||||
a = a[:-1]
|
||||
multiplier = v
|
||||
break
|
||||
try:
|
||||
f = float(a)
|
||||
total += f * multiplier
|
||||
except ValueError:
|
||||
raise PythonException, ("sleep: invalid time interval '%s'" % a, 1)
|
||||
time.sleep(total)
|
||||
|
||||
def touch(args):
|
||||
"""
|
||||
Emulate the behavior of touch(1).
|
||||
"""
|
||||
for f in args:
|
||||
if os.path.exists(f):
|
||||
os.utime(f, None)
|
||||
else:
|
||||
open(f, 'w').close()
|
||||
variables = {
|
||||
'RM': 'rm -f',
|
||||
'.LIBPATTERNS': 'lib%.so lib%.a',
|
||||
'.PYMAKE': '1',
|
||||
}
|
||||
|
@ -106,8 +106,7 @@ class _MakeContext(object):
|
||||
makeoverrides=self.overrides,
|
||||
workdir=self.workdir,
|
||||
context=self.context, env=self.env, makelevel=self.makelevel,
|
||||
targets=self.targets, keepgoing=self.options.keepgoing,
|
||||
silent=self.options.silent)
|
||||
targets=self.targets, keepgoing=self.options.keepgoing)
|
||||
|
||||
self.restarts += 1
|
||||
|
||||
@ -187,8 +186,6 @@ def main(args, env, cwd, cb):
|
||||
dest="printdir")
|
||||
op.add_option('--no-print-directory', action="store_false",
|
||||
dest="printdir", default=True)
|
||||
op.add_option('-s', '--silent', action="store_true",
|
||||
dest="silent", default=False)
|
||||
|
||||
options, arguments1 = op.parse_args(parsemakeflags(env))
|
||||
options, arguments2 = op.parse_args(args, values=options)
|
||||
@ -211,10 +208,6 @@ def main(args, env, cwd, cb):
|
||||
if options.printdir:
|
||||
shortflags.append('w')
|
||||
|
||||
if options.silent:
|
||||
shortflags.append('s')
|
||||
options.printdir = False
|
||||
|
||||
loglevel = logging.WARNING
|
||||
if options.verbose:
|
||||
loglevel = logging.DEBUG
|
||||
|
@ -3,7 +3,7 @@ A representation of makefile data structures.
|
||||
"""
|
||||
|
||||
import logging, re, os, sys
|
||||
import parserdata, parser, functions, process, util, implicit
|
||||
import parserdata, parser, functions, process, util, builtins
|
||||
from cStringIO import StringIO
|
||||
|
||||
_log = logging.getLogger('pymake.data')
|
||||
@ -1142,18 +1142,17 @@ def splitcommand(command):
|
||||
|
||||
def findmodifiers(command):
|
||||
"""
|
||||
Find any of +-@% prefixed on the command.
|
||||
@returns (command, isHidden, isRecursive, ignoreErrors, isNative)
|
||||
Find any of +-@ prefixed on the command.
|
||||
@returns (command, isHidden, isRecursive, ignoreErrors)
|
||||
"""
|
||||
|
||||
isHidden = False
|
||||
isRecursive = False
|
||||
ignoreErrors = False
|
||||
isNative = False
|
||||
|
||||
realcommand = command.lstrip(' \t\n@+-%')
|
||||
realcommand = command.lstrip(' \t\n@+-')
|
||||
modset = set(command[:-len(realcommand)])
|
||||
return realcommand, '@' in modset, '+' in modset, '-' in modset, '%' in modset
|
||||
return realcommand, '@' in modset, '+' in modset, '-' in modset
|
||||
|
||||
class _CommandWrapper(object):
|
||||
def __init__(self, cline, ignoreErrors, loc, context, **kwargs):
|
||||
@ -1174,32 +1173,6 @@ class _CommandWrapper(object):
|
||||
self.usercb = cb
|
||||
process.call(self.cline, loc=self.loc, cb=self._cb, context=self.context, **self.kwargs)
|
||||
|
||||
class _NativeWrapper(_CommandWrapper):
|
||||
def __init__(self, cline, ignoreErrors, loc, context,
|
||||
pycommandpath, **kwargs):
|
||||
_CommandWrapper.__init__(self, cline, ignoreErrors, loc, context,
|
||||
**kwargs)
|
||||
# get the module and method to call
|
||||
parts, badchar = process.clinetoargv(cline)
|
||||
if parts is None:
|
||||
raise DataError("native command '%s': shell metacharacter '%s' in command line" % (cline, badchar), self.loc)
|
||||
if len(parts) < 2:
|
||||
raise DataError("native command '%s': no method name specified" % cline, self.loc)
|
||||
if pycommandpath:
|
||||
self.pycommandpath = re.split('[%s\s]+' % os.pathsep,
|
||||
pycommandpath)
|
||||
else:
|
||||
self.pycommandpath = None
|
||||
self.module = parts[0]
|
||||
self.method = parts[1]
|
||||
self.cline_list = parts[2:]
|
||||
|
||||
def __call__(self, cb):
|
||||
self.usercb = cb
|
||||
process.call_native(self.module, self.method, self.cline_list,
|
||||
loc=self.loc, cb=self._cb, context=self.context,
|
||||
pycommandpath=self.pycommandpath, **self.kwargs)
|
||||
|
||||
def getcommandsforrule(rule, target, makefile, prerequisites, stem):
|
||||
v = Variables(parent=target.variables)
|
||||
setautomaticvariables(v, makefile, target, prerequisites)
|
||||
@ -1211,22 +1184,13 @@ def getcommandsforrule(rule, target, makefile, prerequisites, stem):
|
||||
for c in rule.commands:
|
||||
cstring = c.resolvestr(makefile, v)
|
||||
for cline in splitcommand(cstring):
|
||||
cline, isHidden, isRecursive, ignoreErrors, isNative = findmodifiers(cline)
|
||||
if isHidden or makefile.silent:
|
||||
cline, isHidden, isRecursive, ignoreErrors = findmodifiers(cline)
|
||||
if isHidden:
|
||||
echo = None
|
||||
else:
|
||||
echo = "%s$ %s" % (c.loc, cline)
|
||||
if not isNative:
|
||||
yield _CommandWrapper(cline, ignoreErrors=ignoreErrors, env=env, cwd=makefile.workdir, loc=c.loc, context=makefile.context,
|
||||
echo=echo)
|
||||
else:
|
||||
f, s, e = v.get("PYCOMMANDPATH", True)
|
||||
if e:
|
||||
e = e.resolvestr(makefile, v, ["PYCOMMANDPATH"])
|
||||
yield _NativeWrapper(cline, ignoreErrors=ignoreErrors,
|
||||
env=env, cwd=makefile.workdir,
|
||||
loc=c.loc, context=makefile.context,
|
||||
echo=echo, pycommandpath=e)
|
||||
yield _CommandWrapper(cline, ignoreErrors=ignoreErrors, env=env, cwd=makefile.workdir, loc=c.loc, context=makefile.context,
|
||||
echo=echo)
|
||||
|
||||
class Rule(object):
|
||||
"""
|
||||
@ -1371,8 +1335,7 @@ class Makefile(object):
|
||||
|
||||
def __init__(self, workdir=None, env=None, restarts=0, make=None,
|
||||
makeflags='', makeoverrides='',
|
||||
makelevel=0, context=None, targets=(), keepgoing=False,
|
||||
silent=False):
|
||||
makelevel=0, context=None, targets=(), keepgoing=False):
|
||||
self.defaulttarget = None
|
||||
|
||||
if env is None:
|
||||
@ -1386,7 +1349,6 @@ class Makefile(object):
|
||||
self.exportedvars = {}
|
||||
self._targets = {}
|
||||
self.keepgoing = keepgoing
|
||||
self.silent = silent
|
||||
self._patternvariables = [] # of (pattern, variables)
|
||||
self.implicitrules = []
|
||||
self.parsingfinished = False
|
||||
@ -1406,8 +1368,6 @@ class Makefile(object):
|
||||
self.variables.set('MAKE_RESTARTS', Variables.FLAVOR_SIMPLE,
|
||||
Variables.SOURCE_AUTOMATIC, restarts > 0 and str(restarts) or '')
|
||||
|
||||
self.variables.set('.PYMAKE', Variables.FLAVOR_SIMPLE,
|
||||
Variables.SOURCE_MAKEFILE, "1")
|
||||
if make is not None:
|
||||
self.variables.set('MAKE', Variables.FLAVOR_SIMPLE,
|
||||
Variables.SOURCE_MAKEFILE, make)
|
||||
@ -1432,7 +1392,7 @@ class Makefile(object):
|
||||
self.variables.set('MAKECMDGOALS', Variables.FLAVOR_SIMPLE,
|
||||
Variables.SOURCE_AUTOMATIC, ' '.join(targets))
|
||||
|
||||
for vname, val in implicit.variables.iteritems():
|
||||
for vname, val in builtins.variables.iteritems():
|
||||
self.variables.set(vname,
|
||||
Variables.FLAVOR_SIMPLE,
|
||||
Variables.SOURCE_IMPLICIT, val)
|
||||
|
@ -1,13 +0,0 @@
|
||||
"""
|
||||
Implicit variables; perhaps in the future this will also include some implicit
|
||||
rules, at least match-anything cancellation rules.
|
||||
"""
|
||||
|
||||
variables = {
|
||||
'RM': '%pymake.builtins rm -f',
|
||||
'SLEEP': '%pymake.builtins sleep',
|
||||
'TOUCH': '%pymake.builtins touch',
|
||||
'.LIBPATTERNS': 'lib%.so lib%.a',
|
||||
'.PYMAKE': '1',
|
||||
}
|
||||
|
@ -3,9 +3,7 @@ Skipping shell invocations is good, when possible. This wrapper around subproces
|
||||
parsing command lines into argv and making sure that no shell magic is being used.
|
||||
"""
|
||||
|
||||
#TODO: ship pyprocessing?
|
||||
from multiprocessing import Pool, Condition
|
||||
import subprocess, shlex, re, logging, sys, traceback, os, imp
|
||||
import subprocess, shlex, re, logging, sys, traceback, os
|
||||
import command, util
|
||||
if sys.platform=='win32':
|
||||
import win32process
|
||||
@ -81,11 +79,6 @@ def call(cline, env, cwd, loc, cb, context, echo):
|
||||
|
||||
context.call(argv, executable=executable, shell=False, env=env, cwd=cwd, cb=cb, echo=echo)
|
||||
|
||||
def call_native(module, method, argv, env, cwd, loc, cb, context, echo,
|
||||
pycommandpath=None):
|
||||
context.call_native(module, method, argv, env=env, cwd=cwd, cb=cb,
|
||||
echo=echo, pycommandpath=pycommandpath)
|
||||
|
||||
def statustoresult(status):
|
||||
"""
|
||||
Convert the status returned from waitpid into a prettier numeric result.
|
||||
@ -96,127 +89,17 @@ def statustoresult(status):
|
||||
|
||||
return status >>8
|
||||
|
||||
class Job(object):
|
||||
"""
|
||||
A single job to be executed on the process pool.
|
||||
"""
|
||||
done = False # set to true when the job completes
|
||||
|
||||
def __init__(self):
|
||||
self.exitcode = -127
|
||||
|
||||
def notify(self, condition, result):
|
||||
condition.acquire()
|
||||
self.done = True
|
||||
self.exitcode = result
|
||||
condition.notify()
|
||||
condition.release()
|
||||
|
||||
def get_callback(self, condition):
|
||||
return lambda result: self.notify(condition, result)
|
||||
|
||||
class PopenJob(Job):
|
||||
"""
|
||||
A job that executes a command using subprocess.Popen.
|
||||
"""
|
||||
def __init__(self, argv, executable, shell, env, cwd):
|
||||
Job.__init__(self)
|
||||
self.argv = argv
|
||||
self.executable = executable
|
||||
self.shell = shell
|
||||
self.env = env
|
||||
self.cwd = cwd
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
p = subprocess.Popen(self.argv, executable=self.executable, shell=self.shell, env=self.env, cwd=self.cwd)
|
||||
return p.wait()
|
||||
except OSError, e:
|
||||
print >>sys.stderr, e
|
||||
return -127
|
||||
|
||||
class PythonException(Exception):
|
||||
def __init__(self, message, exitcode):
|
||||
Exception.__init__(self)
|
||||
self.message = message
|
||||
self.exitcode = exitcode
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
|
||||
def load_module_recursive(module, path):
|
||||
"""
|
||||
Emulate the behavior of __import__, but allow
|
||||
passing a custom path to search for modules.
|
||||
"""
|
||||
bits = module.split('.')
|
||||
for i, bit in enumerate(bits):
|
||||
dotname = '.'.join(bits[:i+1])
|
||||
try:
|
||||
f, path, desc = imp.find_module(bit, path)
|
||||
m = imp.load_module(dotname, f, path, desc)
|
||||
if f is None:
|
||||
path = m.__path__
|
||||
except ImportError:
|
||||
return
|
||||
|
||||
class PythonJob(Job):
|
||||
"""
|
||||
A job that calls a Python method.
|
||||
"""
|
||||
def __init__(self, module, method, argv, env, cwd, pycommandpath=None):
|
||||
self.module = module
|
||||
self.method = method
|
||||
self.argv = argv
|
||||
self.env = env
|
||||
self.cwd = cwd
|
||||
self.pycommandpath = pycommandpath or []
|
||||
|
||||
def run(self):
|
||||
oldenv = os.environ
|
||||
try:
|
||||
os.chdir(self.cwd)
|
||||
os.environ = self.env
|
||||
if self.module not in sys.modules:
|
||||
load_module_recursive(self.module,
|
||||
sys.path + self.pycommandpath)
|
||||
if self.module not in sys.modules:
|
||||
print >>sys.stderr, "No module named '%s'" % self.module
|
||||
return -127
|
||||
m = sys.modules[self.module]
|
||||
if self.method not in m.__dict__:
|
||||
print >>sys.stderr, "No method named '%s' in module %s" % (method, module)
|
||||
return -127
|
||||
m.__dict__[self.method](self.argv)
|
||||
except PythonException, e:
|
||||
print >>sys.stderr, e
|
||||
return e.exitcode
|
||||
except:
|
||||
print >>sys.stderr, sys.exc_info()[1]
|
||||
return -127
|
||||
finally:
|
||||
os.environ = oldenv
|
||||
return 0
|
||||
|
||||
def job_runner(job):
|
||||
"""
|
||||
Run a job. Called in a Process pool.
|
||||
"""
|
||||
return job.run()
|
||||
|
||||
class ParallelContext(object):
|
||||
"""
|
||||
Manages the parallel execution of processes.
|
||||
"""
|
||||
|
||||
_allcontexts = set()
|
||||
_condition = Condition()
|
||||
|
||||
def __init__(self, jcount):
|
||||
self.jcount = jcount
|
||||
self.exit = False
|
||||
|
||||
self.pool = Pool(processes=jcount)
|
||||
self.pending = [] # list of (cb, args, kwargs)
|
||||
self.running = [] # list of (subprocess, cb)
|
||||
|
||||
@ -224,8 +107,6 @@ class ParallelContext(object):
|
||||
|
||||
def finish(self):
|
||||
assert len(self.pending) == 0 and len(self.running) == 0, "pending: %i running: %i" % (len(self.pending), len(self.running))
|
||||
self.pool.close()
|
||||
self.pool.join()
|
||||
self._allcontexts.remove(self)
|
||||
|
||||
def run(self):
|
||||
@ -238,19 +119,16 @@ class ParallelContext(object):
|
||||
self.pending.append((cb, args, kwargs))
|
||||
|
||||
def _docall(self, argv, executable, shell, env, cwd, cb, echo):
|
||||
if echo is not None:
|
||||
print echo
|
||||
job = PopenJob(argv, executable=executable, shell=shell, env=env, cwd=cwd)
|
||||
self.pool.apply_async(job_runner, args=(job,), callback=job.get_callback(ParallelContext._condition))
|
||||
self.running.append((job, cb))
|
||||
if echo is not None:
|
||||
print echo
|
||||
try:
|
||||
p = subprocess.Popen(argv, executable=executable, shell=shell, env=env, cwd=cwd)
|
||||
except OSError, e:
|
||||
print >>sys.stderr, e
|
||||
cb(-127)
|
||||
return
|
||||
|
||||
def _docallnative(self, module, method, argv, env, cwd, cb, echo,
|
||||
pycommandpath=None):
|
||||
if echo is not None:
|
||||
print echo
|
||||
job = PythonJob(module, method, argv, env, cwd, pycommandpath)
|
||||
self.pool.apply_async(job_runner, args=(job,), callback=job.get_callback(ParallelContext._condition))
|
||||
self.running.append((job, cb))
|
||||
self.running.append((p, cb))
|
||||
|
||||
def call(self, argv, shell, env, cwd, cb, echo, executable=None):
|
||||
"""
|
||||
@ -259,43 +137,24 @@ class ParallelContext(object):
|
||||
|
||||
self.defer(self._docall, argv, executable, shell, env, cwd, cb, echo)
|
||||
|
||||
def call_native(self, module, method, argv, env, cwd, cb,
|
||||
echo, pycommandpath=None):
|
||||
"""
|
||||
Asynchronously call the native function
|
||||
"""
|
||||
if sys.platform == 'win32':
|
||||
@staticmethod
|
||||
def _waitany():
|
||||
return win32process.WaitForAnyProcess([p for c in ParallelContext._allcontexts for p, cb in c.running])
|
||||
|
||||
self.defer(self._docallnative, module, method, argv, env, cwd, cb,
|
||||
echo, pycommandpath)
|
||||
@staticmethod
|
||||
def _comparepid(pid, process):
|
||||
return pid == process
|
||||
|
||||
@staticmethod
|
||||
def _waitany():
|
||||
def _checkdone():
|
||||
jobs = []
|
||||
for c in ParallelContext._allcontexts:
|
||||
for i in xrange(0, len(c.running)):
|
||||
if c.running[i][0].done:
|
||||
jobs.append(c.running[i])
|
||||
for j in jobs:
|
||||
if j in c.running:
|
||||
c.running.remove(j)
|
||||
return jobs
|
||||
else:
|
||||
@staticmethod
|
||||
def _waitany():
|
||||
return os.waitpid(-1, 0)
|
||||
|
||||
# We must acquire the lock, and then check to see if any jobs have
|
||||
# finished. If we don't check after acquiring the lock it's possible
|
||||
# that all outstanding jobs will have completed before we wait and we'll
|
||||
# wait for notifications that have already occurred.
|
||||
ParallelContext._condition.acquire()
|
||||
jobs = _checkdone()
|
||||
@staticmethod
|
||||
def _comparepid(pid, process):
|
||||
return pid == process.pid
|
||||
|
||||
if jobs == []:
|
||||
ParallelContext._condition.wait()
|
||||
jobs = _checkdone()
|
||||
|
||||
ParallelContext._condition.release()
|
||||
|
||||
return jobs
|
||||
|
||||
@staticmethod
|
||||
def spin():
|
||||
"""
|
||||
@ -307,10 +166,39 @@ class ParallelContext(object):
|
||||
for c in clist:
|
||||
c.run()
|
||||
|
||||
# In python 2.4, subprocess instances wait on child processes under the hood when they are created... this
|
||||
# unfortunate behavior means that before using os.waitpid, we need to check the status using .poll()
|
||||
# see http://bytes.com/groups/python/675403-os-wait-losing-child
|
||||
found = False
|
||||
for c in clist:
|
||||
for i in xrange(0, len(c.running)):
|
||||
p, cb = c.running[i]
|
||||
result = p.poll()
|
||||
if result != None:
|
||||
del c.running[i]
|
||||
cb(result)
|
||||
found = True
|
||||
break
|
||||
|
||||
if found: break
|
||||
if found: continue
|
||||
|
||||
dowait = util.any((len(c.running) for c in ParallelContext._allcontexts))
|
||||
|
||||
if dowait:
|
||||
for job, cb in ParallelContext._waitany():
|
||||
cb(job.exitcode)
|
||||
pid, status = ParallelContext._waitany()
|
||||
result = statustoresult(status)
|
||||
|
||||
for c in ParallelContext._allcontexts:
|
||||
for i in xrange(0, len(c.running)):
|
||||
p, cb = c.running[i]
|
||||
if ParallelContext._comparepid(pid, p):
|
||||
del c.running[i]
|
||||
cb(result)
|
||||
found = True
|
||||
break
|
||||
|
||||
if found: break
|
||||
else:
|
||||
assert any(len(c.pending) for c in ParallelContext._allcontexts)
|
||||
|
||||
|
@ -1,10 +0,0 @@
|
||||
#T gmake skip
|
||||
export EXPECTED := some data
|
||||
|
||||
CMD = %pycmd writeenvtofile
|
||||
PYCOMMANDPATH = $(TESTPATH)
|
||||
|
||||
all:
|
||||
$(CMD) results EXPECTED
|
||||
test "$$(cat results)" = "$(EXPECTED)"
|
||||
@echo TEST-PASS
|
@ -1,21 +0,0 @@
|
||||
#T gmake skip
|
||||
EXPECTED := some data
|
||||
|
||||
# verify that we can load native command modules from
|
||||
# multiple directories in PYCOMMANDPATH separated by the native
|
||||
# path separator
|
||||
ifdef __WIN32__
|
||||
PS:=;
|
||||
else
|
||||
PS:=:
|
||||
endif
|
||||
CMD = %pycmd writetofile
|
||||
CMD2 = %pymod writetofile
|
||||
PYCOMMANDPATH = $(TESTPATH)$(PS)$(TESTPATH)/subdir
|
||||
|
||||
all:
|
||||
$(CMD) results $(EXPECTED)
|
||||
test "$$(cat results)" = "$(EXPECTED)"
|
||||
$(CMD2) results2 $(EXPECTED)
|
||||
test "$$(cat results2)" = "$(EXPECTED)"
|
||||
@echo TEST-PASS
|
@ -1,15 +0,0 @@
|
||||
#T gmake skip
|
||||
EXPECTED := some data
|
||||
|
||||
# verify that we can load native command modules from
|
||||
# multiple space-separated directories in PYCOMMANDPATH
|
||||
CMD = %pycmd writetofile
|
||||
CMD2 = %pymod writetofile
|
||||
PYCOMMANDPATH = $(TESTPATH) $(TESTPATH)/subdir
|
||||
|
||||
all:
|
||||
$(CMD) results $(EXPECTED)
|
||||
test "$$(cat results)" = "$(EXPECTED)"
|
||||
$(CMD2) results2 $(EXPECTED)
|
||||
test "$$(cat results2)" = "$(EXPECTED)"
|
||||
@echo TEST-PASS
|
@ -1,10 +0,0 @@
|
||||
ifndef TOUCH
|
||||
TOUCH = touch
|
||||
endif
|
||||
|
||||
all: testfile
|
||||
test -f testfile
|
||||
@echo TEST-PASS
|
||||
|
||||
testfile:
|
||||
$(TOUCH) $@
|
@ -1,21 +0,0 @@
|
||||
#T commandline: ['-j2']
|
||||
|
||||
# ensure that calling python commands doesn't block other targets
|
||||
ifndef SLEEP
|
||||
SLEEP := sleep
|
||||
endif
|
||||
|
||||
PRINTF = printf "$@:0:" >>results
|
||||
EXPECTED = target2:0:target1:0:
|
||||
|
||||
all:: target1 target2
|
||||
cat results
|
||||
test "$$(cat results)" = "$(EXPECTED)"
|
||||
@echo TEST-PASS
|
||||
|
||||
target1:
|
||||
$(SLEEP) 0.1
|
||||
$(PRINTF)
|
||||
|
||||
target2:
|
||||
$(PRINTF)
|
@ -1,9 +0,0 @@
|
||||
import os
|
||||
|
||||
def writetofile(args):
|
||||
with open(args[0], 'w') as f:
|
||||
f.write(' '.join(args[1:]))
|
||||
|
||||
def writeenvtofile(args):
|
||||
with open(args[0], 'w') as f:
|
||||
f.write(os.environ[args[1]])
|
@ -1,7 +0,0 @@
|
||||
#T returncode: 2
|
||||
all:
|
||||
mkdir newdir
|
||||
test -d newdir
|
||||
touch newdir/newfile
|
||||
$(RM) newdir
|
||||
@echo TEST-PASS
|
@ -1,13 +0,0 @@
|
||||
all:
|
||||
# $(RM) defaults to -f
|
||||
$(RM) nosuchfile
|
||||
touch newfile
|
||||
test -f newfile
|
||||
$(RM) newfile
|
||||
test ! -f newfile
|
||||
mkdir newdir
|
||||
test -d newdir
|
||||
touch newdir/newfile
|
||||
$(RM) -r newdir
|
||||
test ! -d newdir
|
||||
@echo TEST-PASS
|
@ -1,4 +1,3 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Run the test(s) listed on the command line. If a directory is listed, the script will recursively
|
||||
walk the directory for files named .mk and run each.
|
||||
|
@ -1,3 +0,0 @@
|
||||
def writetofile(args):
|
||||
with open(args[0], 'w') as f:
|
||||
f.write(' '.join(args[1:]))
|
@ -52,8 +52,9 @@ from MozZipFile import ZipFile
|
||||
from cStringIO import StringIO
|
||||
from datetime import datetime
|
||||
|
||||
from utils import pushback_iter
|
||||
from utils import pushback_iter, lockFile
|
||||
from Preprocessor import Preprocessor
|
||||
from buildlist import addEntriesToListFile
|
||||
|
||||
__all__ = ['JarMaker']
|
||||
|
||||
@ -164,7 +165,7 @@ class JarMaker(object):
|
||||
pass
|
||||
|
||||
def finalizeJar(self, jarPath, chromebasepath, register,
|
||||
doZip=True):
|
||||
doZip=True):
|
||||
'''Helper method to write out the chrome registration entries to
|
||||
jarfile.manifest or chrome.manifest, or both.
|
||||
|
||||
@ -173,35 +174,42 @@ class JarMaker(object):
|
||||
# rewrite the manifest, if entries given
|
||||
if not register:
|
||||
return
|
||||
|
||||
chromeManifest = os.path.join(os.path.dirname(jarPath),
|
||||
'..', 'chrome.manifest')
|
||||
|
||||
if self.useJarfileManifest:
|
||||
self.updateManifest(jarPath + '.manifest', chromebasepath % '',
|
||||
register)
|
||||
addEntriesToListFile(chromeManifest, ['manifest chrome/%s.manifest' % (os.path.basename(jarPath),)])
|
||||
if self.useChromeManifest:
|
||||
manifestPath = os.path.join(os.path.dirname(jarPath),
|
||||
'..', 'chrome.manifest')
|
||||
self.updateManifest(manifestPath, chromebasepath % 'chrome/',
|
||||
self.updateManifest(chromeManifest, chromebasepath % 'chrome/',
|
||||
register)
|
||||
|
||||
def updateManifest(self, manifestPath, chromebasepath, register):
|
||||
'''updateManifest replaces the % in the chrome registration entries
|
||||
with the given chrome base path, and updates the given manifest file.
|
||||
'''
|
||||
myregister = dict.fromkeys(map(lambda s: s.replace('%', chromebasepath),
|
||||
register.iterkeys()))
|
||||
manifestExists = os.path.isfile(manifestPath)
|
||||
mode = (manifestExists and 'r+b') or 'wb'
|
||||
mf = open(manifestPath, mode)
|
||||
if manifestExists:
|
||||
# import previous content into hash, ignoring empty ones and comments
|
||||
imf = re.compile('(#.*)?$')
|
||||
for l in re.split('[\r\n]+', mf.read()):
|
||||
if imf.match(l):
|
||||
continue
|
||||
myregister[l] = None
|
||||
mf.seek(0)
|
||||
for k in myregister.iterkeys():
|
||||
mf.write(k + os.linesep)
|
||||
mf.close()
|
||||
lock = lockFile(manifestPath + '.lck')
|
||||
try:
|
||||
myregister = dict.fromkeys(map(lambda s: s.replace('%', chromebasepath),
|
||||
register.iterkeys()))
|
||||
manifestExists = os.path.isfile(manifestPath)
|
||||
mode = (manifestExists and 'r+b') or 'wb'
|
||||
mf = open(manifestPath, mode)
|
||||
if manifestExists:
|
||||
# import previous content into hash, ignoring empty ones and comments
|
||||
imf = re.compile('(#.*)?$')
|
||||
for l in re.split('[\r\n]+', mf.read()):
|
||||
if imf.match(l):
|
||||
continue
|
||||
myregister[l] = None
|
||||
mf.seek(0)
|
||||
for k in myregister.iterkeys():
|
||||
mf.write(k + os.linesep)
|
||||
mf.close()
|
||||
finally:
|
||||
lock = None
|
||||
|
||||
def makeJar(self, infile=None,
|
||||
jardir='',
|
||||
|
@ -908,6 +908,7 @@ ifdef IS_COMPONENT
|
||||
$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
|
||||
$(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
|
||||
ifndef NO_COMPONENTS_MANIFEST
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest"
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)"
|
||||
endif
|
||||
ifdef BEOS_ADDON_WORKAROUND
|
||||
@ -1782,6 +1783,7 @@ ifndef NO_DIST_INSTALL
|
||||
$(INSTALL) $(IFLAGS1) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(FINAL_TARGET)/components
|
||||
ifndef NO_INTERFACES_MANIFEST
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPIDL_MODULE).xpt"
|
||||
@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest"
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -1897,7 +1899,12 @@ ifndef NO_DIST_INSTALL
|
||||
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \
|
||||
done
|
||||
endif
|
||||
endif
|
||||
|
||||
EXTRA_MANIFESTS = $(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))
|
||||
ifneq (,$(EXTRA_MANIFESTS))
|
||||
libs::
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest $(patsubst %,"manifest components/%",$(notdir $(EXTRA_MANIFESTS)))
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
@ -2338,6 +2345,8 @@ FREEZE_VARIABLES = \
|
||||
REQUIRES \
|
||||
SHORT_LIBNAME \
|
||||
TIERS \
|
||||
EXTRA_COMPONENTS \
|
||||
EXTRA_PP_COMPONENTS \
|
||||
$(NULL)
|
||||
|
||||
$(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))
|
||||
|
@ -43,7 +43,7 @@ class TestJarMaker(unittest.TestCase):
|
||||
"""
|
||||
Unit tests for JarMaker.py
|
||||
"""
|
||||
debug = False # set to True to debug failing tests on disk
|
||||
debug = True # set to True to debug failing tests on disk
|
||||
def setUp(self):
|
||||
self.tmpdir = mkdtemp()
|
||||
self.srcdir = os.path.join(self.tmpdir, 'src')
|
||||
@ -142,6 +142,10 @@ class TestJarMaker(unittest.TestCase):
|
||||
os.mkdir(ldir)
|
||||
open(os.path.join(ldir, relpath), 'w').write(relpath+" content\n")
|
||||
# create reference
|
||||
mf = open(os.path.join(self.refdir, 'chrome.manifest'), 'w')
|
||||
mf.write('manifest chrome/ab-CD.manifest\n')
|
||||
mf.close()
|
||||
|
||||
chrome_ref = os.path.join(self.refdir, 'chrome')
|
||||
os.mkdir(chrome_ref)
|
||||
mf = open(os.path.join(chrome_ref, 'ab-CD.manifest'), 'wb')
|
||||
|
73
configure.in
73
configure.in
@ -132,7 +132,7 @@ GCONF_VERSION=1.2.1
|
||||
GIO_VERSION=2.0
|
||||
STARTUP_NOTIFICATION_VERSION=0.8
|
||||
DBUS_VERSION=0.60
|
||||
SQLITE_VERSION=3.6.23.1
|
||||
SQLITE_VERSION=3.7.0.1
|
||||
LIBNOTIFY_VERSION=0.4
|
||||
|
||||
MSMANIFEST_TOOL=
|
||||
@ -5915,42 +5915,43 @@ if test -n "$MOZ_WEBM"; then
|
||||
dnl For Darwin x86, Darwin x86_64, Linux x86, and WINNT x86_64
|
||||
dnl we can use YASM.
|
||||
AC_MSG_CHECKING([for YASM assembler])
|
||||
AC_CHECK_PROGS(VPX_AS, yasm, "")
|
||||
if test -n "$VPX_AS"; then
|
||||
dnl We have YASM, see if we have assembly on this platform.
|
||||
case "$OS_ARCH:$OS_TEST" in
|
||||
Linux:x86|Linux:i?86)
|
||||
VPX_ASFLAGS="-f elf32 -rnasm -pnasm"
|
||||
AC_CHECK_PROGS(VPX_AS, $YASM yasm, "")
|
||||
dnl We have YASM, see if we have assembly on this platform.
|
||||
case "$OS_ARCH:$OS_TEST" in
|
||||
Linux:x86|Linux:i?86)
|
||||
VPX_ASFLAGS="-f elf32 -rnasm -pnasm"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
Linux:x86_64)
|
||||
VPX_ASFLAGS="-f elf64 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
SunOS:i?86)
|
||||
VPX_ASFLAGS="-f elf32 -rnasm -pnasm"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
SunOS:x86_64)
|
||||
VPX_ASFLAGS="-f elf64 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
Darwin:i?86)
|
||||
VPX_ASFLAGS="-f macho32 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
Darwin:x86_64)
|
||||
VPX_ASFLAGS="-f macho64 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
WINNT:x86_64)
|
||||
if test -z "$GNU_CC"; then
|
||||
VPX_ASFLAGS="-f x64 -rnasm -pnasm"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
Linux:x86_64)
|
||||
VPX_ASFLAGS="-f elf64 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
SunOS:i?86)
|
||||
VPX_ASFLAGS="-f elf32 -rnasm -pnasm"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
SunOS:x86_64)
|
||||
VPX_ASFLAGS="-f elf64 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
Darwin:i?86)
|
||||
VPX_ASFLAGS="-f macho32 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
Darwin:x86_64)
|
||||
VPX_ASFLAGS="-f macho64 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
;;
|
||||
WINNT:x86_64)
|
||||
if test -z "$GNU_CC"; then
|
||||
VPX_ASFLAGS="-f x64 -rnasm -pnasm"
|
||||
VPX_X86_ASM=1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi # end have YASM
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if test -n "$VPX_X86_ASM" -a -z "$VPX_AS"; then
|
||||
AC_MSG_ERROR([yasm is a required build tool for this architecture when webm is enabled. You may either install yasm or --disable-webm (which disables the WebM video format). See https://developer.mozilla.org/en/YASM for more details.])
|
||||
fi
|
||||
fi # end !WINNT_x86_MSVC
|
||||
|
||||
if test -n "$VPX_X86_ASM"; then
|
||||
|
@ -1889,7 +1889,11 @@ nsFrameLoader::EnsureMessageManager()
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!mIsTopLevelContent) {
|
||||
if (!mIsTopLevelContent
|
||||
#ifdef MOZ_IPC
|
||||
&& !mRemoteFrame
|
||||
#endif
|
||||
) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,6 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "nsFrameMessageManager.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIXPConnect.h"
|
||||
@ -44,6 +43,9 @@
|
||||
#include "jsarray.h"
|
||||
#include "jsinterp.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameMessageManager)
|
||||
|
||||
@ -505,3 +507,168 @@ NS_NewGlobalMessageManager(nsIChromeFrameMessageManager** aResult)
|
||||
NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY);
|
||||
return CallQueryInterface(mm, aResult);
|
||||
}
|
||||
|
||||
nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>*
|
||||
nsFrameScriptExecutor::sCachedScripts = nsnull;
|
||||
|
||||
void
|
||||
nsFrameScriptExecutor::DidCreateCx()
|
||||
{
|
||||
NS_ASSERTION(mCx, "Should have mCx!");
|
||||
if (!sCachedScripts) {
|
||||
sCachedScripts =
|
||||
new nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>;
|
||||
sCachedScripts->Init();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameScriptExecutor::DestroyCx()
|
||||
{
|
||||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
if (xpc) {
|
||||
xpc->ReleaseJSContext(mCx, PR_TRUE);
|
||||
} else {
|
||||
JS_DestroyContext(mCx);
|
||||
}
|
||||
mCx = nsnull;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
CachedScriptUnrooter(const nsAString& aKey,
|
||||
nsFrameScriptExecutorJSObjectHolder*& aData,
|
||||
void* aUserArg)
|
||||
{
|
||||
JSContext* cx = static_cast<JSContext*>(aUserArg);
|
||||
JS_RemoveObjectRoot(cx, &(aData->mObject));
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsFrameScriptExecutor::Shutdown()
|
||||
{
|
||||
if (sCachedScripts) {
|
||||
JSContext* cx = nsnull;
|
||||
nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&cx);
|
||||
if (cx) {
|
||||
#ifdef DEBUG_smaug
|
||||
printf("Will clear cached frame manager scripts!\n");
|
||||
#endif
|
||||
JSAutoRequest ar(cx);
|
||||
NS_ASSERTION(sCachedScripts != nsnull, "Need cached scripts");
|
||||
sCachedScripts->Enumerate(CachedScriptUnrooter, cx);
|
||||
} else {
|
||||
NS_WARNING("No context available. Leaking cached scripts!\n");
|
||||
}
|
||||
|
||||
delete sCachedScripts;
|
||||
sCachedScripts = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL)
|
||||
{
|
||||
if (!mGlobal || !mCx) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsFrameScriptExecutorJSObjectHolder* holder = sCachedScripts->Get(aURL);
|
||||
if (holder) {
|
||||
nsContentUtils::ThreadJSContextStack()->Push(mCx);
|
||||
{
|
||||
// Need to scope JSAutoRequest to happen after Push but before Pop,
|
||||
// at least for now. See bug 584673.
|
||||
JSAutoRequest ar(mCx);
|
||||
JSObject* global = nsnull;
|
||||
mGlobal->GetJSObject(&global);
|
||||
if (global) {
|
||||
jsval val;
|
||||
JS_ExecuteScript(mCx, global,
|
||||
(JSScript*)JS_GetPrivate(mCx, holder->mObject),
|
||||
&val);
|
||||
}
|
||||
}
|
||||
JSContext* unused;
|
||||
nsContentUtils::ThreadJSContextStack()->Pop(&unused);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString url = NS_ConvertUTF16toUTF8(aURL);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
NS_NewChannel(getter_AddRefs(channel), uri);
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> input;
|
||||
channel->Open(getter_AddRefs(input));
|
||||
nsString dataString;
|
||||
if (input) {
|
||||
const PRUint32 bufferSize = 1024;
|
||||
char buffer[bufferSize];
|
||||
nsCString data;
|
||||
PRUint32 avail = 0;
|
||||
input->Available(&avail);
|
||||
PRUint32 read = 0;
|
||||
if (avail) {
|
||||
while (NS_SUCCEEDED(input->Read(buffer, bufferSize, &read)) && read) {
|
||||
data.Append(buffer, read);
|
||||
read = 0;
|
||||
}
|
||||
}
|
||||
nsScriptLoader::ConvertToUTF16(channel, (PRUint8*)data.get(), data.Length(),
|
||||
EmptyString(), nsnull, dataString);
|
||||
}
|
||||
|
||||
if (!dataString.IsEmpty()) {
|
||||
nsContentUtils::ThreadJSContextStack()->Push(mCx);
|
||||
{
|
||||
// Need to scope JSAutoRequest to happen after Push but before Pop,
|
||||
// at least for now. See bug 584673.
|
||||
JSAutoRequest ar(mCx);
|
||||
JSObject* global = nsnull;
|
||||
mGlobal->GetJSObject(&global);
|
||||
if (global) {
|
||||
JSPrincipals* jsprin = nsnull;
|
||||
mPrincipal->GetJSPrincipals(mCx, &jsprin);
|
||||
nsContentUtils::XPConnect()->FlagSystemFilenamePrefix(url.get(), PR_TRUE);
|
||||
JSScript* script =
|
||||
JS_CompileUCScriptForPrincipals(mCx, nsnull, jsprin,
|
||||
(jschar*)dataString.get(),
|
||||
dataString.Length(),
|
||||
url.get(), 1);
|
||||
|
||||
if (script) {
|
||||
JSObject* scriptObj = JS_NewScriptObject(mCx, script);
|
||||
JS_AddObjectRoot(mCx, &scriptObj);
|
||||
nsCAutoString scheme;
|
||||
uri->GetScheme(scheme);
|
||||
// We don't cache data: scripts!
|
||||
if (!scheme.EqualsLiteral("data")) {
|
||||
nsFrameScriptExecutorJSObjectHolder* holder =
|
||||
new nsFrameScriptExecutorJSObjectHolder(scriptObj);
|
||||
// Root the object also for caching.
|
||||
JS_AddNamedObjectRoot(mCx, &(holder->mObject),
|
||||
"Cached message manager script");
|
||||
sCachedScripts->Put(aURL, holder);
|
||||
}
|
||||
jsval val;
|
||||
JS_ExecuteScript(mCx, global,
|
||||
(JSScript*)JS_GetPrivate(mCx, scriptObj), &val);
|
||||
JS_RemoveObjectRoot(mCx, &scriptObj);
|
||||
}
|
||||
//XXX Argh, JSPrincipals are manually refcounted!
|
||||
JSPRINCIPALS_DROP(mCx, jsprin);
|
||||
}
|
||||
}
|
||||
JSContext* unused;
|
||||
nsContentUtils::ThreadJSContextStack()->Pop(&unused);
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,9 @@
|
||||
#include "nsIAtom.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
class nsAXPCNativeCallContext;
|
||||
struct JSContext;
|
||||
@ -150,4 +153,26 @@ protected:
|
||||
nsTArray<nsString> mPendingScripts;
|
||||
};
|
||||
|
||||
struct nsFrameScriptExecutorJSObjectHolder
|
||||
{
|
||||
nsFrameScriptExecutorJSObjectHolder(JSObject* aObject) : mObject(aObject) {}
|
||||
JSObject* mObject;
|
||||
};
|
||||
|
||||
class nsFrameScriptExecutor
|
||||
{
|
||||
public:
|
||||
static void Shutdown();
|
||||
protected:
|
||||
nsFrameScriptExecutor() : mCx(nsnull) {}
|
||||
void DidCreateCx();
|
||||
// Call this when you want to destroy mCx.
|
||||
void DestroyCx();
|
||||
void LoadFrameScriptInternal(const nsAString& aURL);
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
|
||||
JSContext* mCx;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
static nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>* sCachedScripts;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -110,7 +110,7 @@ bool SendAsyncMessageToParent(void* aCallbackData,
|
||||
nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
|
||||
nsIContent* aOwner,
|
||||
nsFrameMessageManager* aChrome)
|
||||
: mCx(nsnull), mDocShell(aShell), mInitialized(PR_FALSE), mLoadingScript(PR_FALSE),
|
||||
: mDocShell(aShell), mInitialized(PR_FALSE), mLoadingScript(PR_FALSE),
|
||||
mDelayedDisconnect(PR_FALSE), mOwner(aOwner), mChromeMessageManager(aChrome)
|
||||
{
|
||||
}
|
||||
@ -196,8 +196,7 @@ nsInProcessTabChildGlobal::Disconnect()
|
||||
}
|
||||
if (!mLoadingScript) {
|
||||
if (mCx) {
|
||||
JS_DestroyContext(mCx);
|
||||
mCx = nsnull;
|
||||
DestroyCx();
|
||||
}
|
||||
} else {
|
||||
mDelayedDisconnect = PR_TRUE;
|
||||
@ -296,7 +295,7 @@ nsInProcessTabChildGlobal::InitTabChildGlobal()
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
JS_SetGlobalObject(cx, global);
|
||||
|
||||
DidCreateCx();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -307,69 +306,10 @@ nsInProcessTabChildGlobal::LoadFrameScript(const nsAString& aURL)
|
||||
mInitialized = PR_TRUE;
|
||||
Init();
|
||||
}
|
||||
if (!mGlobal || !mCx) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString url = NS_ConvertUTF16toUTF8(aURL);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
NS_NewChannel(getter_AddRefs(channel), uri);
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> input;
|
||||
channel->Open(getter_AddRefs(input));
|
||||
nsString dataString;
|
||||
if (input) {
|
||||
const PRUint32 bufferSize = 256;
|
||||
char buffer[bufferSize];
|
||||
nsCString data;
|
||||
PRUint32 avail = 0;
|
||||
input->Available(&avail);
|
||||
PRUint32 read = 0;
|
||||
if (avail) {
|
||||
while (NS_SUCCEEDED(input->Read(buffer, bufferSize, &read)) && read) {
|
||||
data.Append(buffer, read);
|
||||
read = 0;
|
||||
}
|
||||
}
|
||||
nsScriptLoader::ConvertToUTF16(channel, (PRUint8*)data.get(), data.Length(),
|
||||
EmptyString(), nsnull, dataString);
|
||||
}
|
||||
|
||||
if (!dataString.IsEmpty()) {
|
||||
nsContentUtils::ThreadJSContextStack()->Push(mCx);
|
||||
{
|
||||
// Need to scope JSAutoRequest to happen after Push but before Pop,
|
||||
// at least for now. See bug 584673.
|
||||
JSAutoRequest ar(mCx);
|
||||
jsval retval;
|
||||
JSObject* global = nsnull;
|
||||
mGlobal->GetJSObject(&global);
|
||||
if (global) {
|
||||
JSPrincipals* jsprin = nsnull;
|
||||
mPrincipal->GetJSPrincipals(mCx, &jsprin);
|
||||
nsContentUtils::XPConnect()->FlagSystemFilenamePrefix(url.get(), PR_TRUE);
|
||||
PRBool tmp = mLoadingScript;
|
||||
mLoadingScript = PR_TRUE;
|
||||
JS_EvaluateUCScriptForPrincipals(mCx, global, jsprin,
|
||||
(jschar*)dataString.get(),
|
||||
dataString.Length(),
|
||||
url.get(), 1, &retval);
|
||||
//XXX Argh, JSPrincipals are manually refcounted!
|
||||
JSPRINCIPALS_DROP(mCx, jsprin);
|
||||
mLoadingScript = tmp;
|
||||
}
|
||||
}
|
||||
JSContext* unused;
|
||||
nsContentUtils::ThreadJSContextStack()->Pop(&unused);
|
||||
}
|
||||
PRBool tmp = mLoadingScript;
|
||||
mLoadingScript = PR_TRUE;
|
||||
LoadFrameScriptInternal(aURL);
|
||||
mLoadingScript = tmp;
|
||||
if (!mLoadingScript && mDelayedDisconnect) {
|
||||
mDelayedDisconnect = PR_FALSE;
|
||||
Disconnect();
|
||||
|
@ -43,18 +43,17 @@
|
||||
#include "nsFrameMessageManager.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
class nsInProcessTabChildGlobal : public nsDOMEventTargetHelper,
|
||||
public nsFrameScriptExecutor,
|
||||
public nsIInProcessContentFrameMessageManager,
|
||||
public nsIScriptObjectPrincipal,
|
||||
public nsIScriptContextPrincipal
|
||||
@ -126,9 +125,6 @@ protected:
|
||||
nsresult Init();
|
||||
nsresult InitTabChildGlobal();
|
||||
nsCOMPtr<nsIContentFrameMessageManager> mMessageManager;
|
||||
JSContext* mCx;
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
PRPackedBool mInitialized;
|
||||
PRPackedBool mLoadingScript;
|
||||
|
@ -42,7 +42,6 @@
|
||||
*/
|
||||
|
||||
#include "nsTextFragment.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsMemory.h"
|
||||
@ -241,27 +240,6 @@ nsTextFragment::SetTo(const PRUnichar* aBuffer, PRInt32 aLength)
|
||||
mState.mLength = aLength;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFragment::AppendTo(nsAString& aString) const
|
||||
{
|
||||
if (mState.mIs2b) {
|
||||
aString.Append(m2b, mState.mLength);
|
||||
} else {
|
||||
AppendASCIItoUTF16(Substring(m1b, m1b + mState.mLength),
|
||||
aString);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFragment::AppendTo(nsAString& aString, PRInt32 aOffset, PRInt32 aLength) const
|
||||
{
|
||||
if (mState.mIs2b) {
|
||||
aString.Append(m2b + aOffset, aLength);
|
||||
} else {
|
||||
AppendASCIItoUTF16(Substring(m1b + aOffset, m1b + aOffset + aLength), aString);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFragment::CopyTo(PRUnichar *aDest, PRInt32 aOffset, PRInt32 aCount)
|
||||
{
|
||||
|
@ -44,7 +44,7 @@
|
||||
#ifndef nsTextFragment_h___
|
||||
#define nsTextFragment_h___
|
||||
|
||||
#include "nsAString.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
class nsString;
|
||||
class nsCString;
|
||||
@ -165,14 +165,27 @@ public:
|
||||
/**
|
||||
* Append the contents of this string fragment to aString
|
||||
*/
|
||||
void AppendTo(nsAString& aString) const;
|
||||
void AppendTo(nsAString& aString) const {
|
||||
if (mState.mIs2b) {
|
||||
aString.Append(m2b, mState.mLength);
|
||||
} else {
|
||||
AppendASCIItoUTF16(Substring(m1b, m1b + mState.mLength),
|
||||
aString);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a substring of the contents of this string fragment to aString.
|
||||
* @param aOffset where to start the substring in this text fragment
|
||||
* @param aLength the length of the substring
|
||||
*/
|
||||
void AppendTo(nsAString& aString, PRInt32 aOffset, PRInt32 aLength) const;
|
||||
void AppendTo(nsAString& aString, PRInt32 aOffset, PRInt32 aLength) const {
|
||||
if (mState.mIs2b) {
|
||||
aString.Append(m2b + aOffset, aLength);
|
||||
} else {
|
||||
AppendASCIItoUTF16(Substring(m1b + aOffset, m1b + aOffset + aLength), aString);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a copy of the fragments contents starting at offset for
|
||||
|
@ -339,17 +339,6 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
|
||||
printf_stderr ("--- WebGL context created: %p\n", gl.get());
|
||||
|
||||
if (gl->IsGLES2()) {
|
||||
// On native GLES2, no need to validate, the compiler will do it
|
||||
mShaderValidation = PR_FALSE;
|
||||
} else {
|
||||
// Otherwise, check the shader validator pref
|
||||
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
|
||||
|
||||
prefService->GetBoolPref("webgl.shader_validator", &mShaderValidation);
|
||||
}
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mResetLayer = PR_TRUE;
|
||||
|
@ -56,7 +56,7 @@
|
||||
|
||||
#include "jstypedarray.h"
|
||||
|
||||
#if !defined(USE_GLES2) && defined(USE_ANGLE)
|
||||
#if defined(USE_ANGLE)
|
||||
// shader translator
|
||||
#include "angle/ShaderLang.h"
|
||||
#endif
|
||||
@ -2840,7 +2840,7 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj)
|
||||
return NS_OK;
|
||||
MakeContextCurrent();
|
||||
|
||||
#if !defined(USE_GLES2) && defined(USE_ANGLE)
|
||||
#if defined(USE_ANGLE)
|
||||
if (shader->NeedsTranslation() && mShaderValidation) {
|
||||
ShHandle compiler = 0;
|
||||
int debugFlags = 0;
|
||||
@ -2864,7 +2864,12 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj)
|
||||
const char *s = src.get();
|
||||
|
||||
if (!ShCompile(compiler, &s, 1, EShOptSimple, debugFlags)) {
|
||||
shader->SetTranslationFailure(nsDependentCString(ShGetInfoLog(compiler)));
|
||||
const char* info = ShGetInfoLog(compiler);
|
||||
if (info) {
|
||||
shader->SetTranslationFailure(nsDependentCString(info));
|
||||
} else {
|
||||
shader->SetTranslationFailure(NS_LITERAL_CSTRING("Internal error: failed to get shader info log"));
|
||||
}
|
||||
ShDestruct(compiler);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -39,9 +39,12 @@
|
||||
|
||||
#include "WebGLContext.h"
|
||||
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#include "CheckedInt.h"
|
||||
|
||||
#if !defined(USE_GLES2) && defined(USE_ANGLE)
|
||||
#if defined(USE_ANGLE)
|
||||
#include "angle/ShaderLang.h"
|
||||
#endif
|
||||
|
||||
@ -444,17 +447,26 @@ WebGLContext::InitAndValidateGL()
|
||||
gl->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||
}
|
||||
|
||||
#if !defined(USE_GLES2) && defined(USE_ANGLE)
|
||||
// initialize shader translator
|
||||
static bool didTranslatorInit = false;
|
||||
if (!didTranslatorInit && mShaderValidation) {
|
||||
if (!ShInitialize()) {
|
||||
LogMessage("GLSL translator initialization failed!");
|
||||
return PR_FALSE;
|
||||
static bool didTranslatorCheck = false;
|
||||
if (!didTranslatorCheck) {
|
||||
// Check the shader validator pref
|
||||
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
|
||||
|
||||
prefService->GetBoolPref("webgl.shader_validator", &mShaderValidation);
|
||||
|
||||
#if defined(USE_ANGLE)
|
||||
// initialize shader translator
|
||||
if (mShaderValidation) {
|
||||
if (!ShInitialize()) {
|
||||
LogMessage("GLSL translator initialization failed!");
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
didTranslatorInit = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
didTranslatorCheck = true;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ nsHTMLButtonElement::IsHTMLFocusable(PRBool aWithMouse, PRBool *aIsFocusable, PR
|
||||
|
||||
*aIsFocusable =
|
||||
#ifdef XP_MACOSX
|
||||
!aWithMouse &&
|
||||
(!aWithMouse || nsFocusManager::sMouseFocusesFormControl) &&
|
||||
#endif
|
||||
!HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
|
||||
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsFocusManager.h"
|
||||
|
||||
#include "imgIContainer.h"
|
||||
#include "imgILoader.h"
|
||||
@ -480,7 +481,7 @@ nsHTMLImageElement::IsHTMLFocusable(PRBool aWithMouse,
|
||||
|
||||
*aIsFocusable =
|
||||
#ifdef XP_MACOSX
|
||||
!aWithMouse &&
|
||||
(!aWithMouse || nsFocusManager::sMouseFocusesFormControl) &&
|
||||
#endif
|
||||
(tabIndex >= 0 || HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex));
|
||||
|
||||
|
@ -2880,7 +2880,7 @@ nsHTMLInputElement::IsHTMLFocusable(PRBool aWithMouse, PRBool *aIsFocusable, PRI
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
const PRBool defaultFocusable = !aWithMouse;
|
||||
const PRBool defaultFocusable = !aWithMouse || nsFocusManager::sMouseFocusesFormControl;
|
||||
#else
|
||||
const PRBool defaultFocusable = PR_TRUE;
|
||||
#endif
|
||||
|
@ -221,18 +221,6 @@ nsXULPopupListener::PreLaunchPopup(nsIDOMEvent* aMouseEvent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get the document with the popup.
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mElement);
|
||||
|
||||
// Turn the document into a XUL document so we can use SetPopupNode.
|
||||
nsCOMPtr<nsIDOMXULDocument> xulDocument = do_QueryInterface(content->GetDocument());
|
||||
if (!xulDocument) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Store clicked-on node in xul document for context menus and menu popups.
|
||||
xulDocument->SetPopupNode(targetNode);
|
||||
|
||||
nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aMouseEvent));
|
||||
|
||||
if (mIsContext) {
|
||||
|
@ -378,7 +378,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULDocument, nsXMLDocument)
|
||||
cb.NoteXPCOMChild(static_cast<nsIScriptGlobalObjectOwner*>(tmp->mPrototypes[i]));
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTooltipNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLocalStore)
|
||||
|
||||
if (tmp->mOverlayLoadObservers.IsInitialized())
|
||||
@ -388,7 +387,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULDocument, nsXMLDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULDocument, nsXMLDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTooltipNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsXULDocument, nsXMLDocument)
|
||||
@ -1527,26 +1525,23 @@ nsXULDocument::GetHeight(PRInt32* aHeight)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::GetPopupNode(nsIDOMNode** aNode)
|
||||
{
|
||||
// Get popup node.
|
||||
nsresult rv = TrustedGetPopupNode(aNode); // addref happens here
|
||||
|
||||
if (NS_SUCCEEDED(rv) && *aNode && !nsContentUtils::CanCallerAccess(*aNode)) {
|
||||
NS_RELEASE(*aNode);
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::TrustedGetPopupNode(nsIDOMNode** aNode)
|
||||
{
|
||||
*aNode = nsnull;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsPIWindowRoot> rootWin = GetWindowRoot();
|
||||
if (rootWin)
|
||||
rootWin->GetPopupNode(aNode); // addref happens here
|
||||
node = rootWin->GetPopupNode(); // addref happens here
|
||||
|
||||
if (!node) {
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm) {
|
||||
node = pm->GetLastTriggerPopupNode(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (node && nsContentUtils::CanCallerAccess(node))
|
||||
node.swap(*aNode);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1615,25 +1610,22 @@ nsXULDocument::GetPopupRangeOffset(PRInt32* aRangeOffset)
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::GetTooltipNode(nsIDOMNode** aNode)
|
||||
{
|
||||
if (mTooltipNode && !nsContentUtils::CanCallerAccess(mTooltipNode)) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
*aNode = mTooltipNode;
|
||||
NS_IF_ADDREF(*aNode);
|
||||
return NS_OK;
|
||||
}
|
||||
*aNode = nsnull;
|
||||
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm) {
|
||||
nsCOMPtr<nsIDOMNode> node = pm->GetLastTriggerTooltipNode(this);
|
||||
if (node && nsContentUtils::CanCallerAccess(node))
|
||||
node.swap(*aNode);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::TrustedGetTooltipNode(nsIDOMNode** aNode)
|
||||
{
|
||||
NS_IF_ADDREF(*aNode = mTooltipNode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::SetTooltipNode(nsIDOMNode* aNode)
|
||||
{
|
||||
mTooltipNode = aNode;
|
||||
// do nothing
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=449457
|
||||
<script type="application/javascript"><![CDATA[
|
||||
|
||||
/** Test for Bug 449457 **/
|
||||
document.tooltipNode = document;
|
||||
document.popupNode = document;
|
||||
ok(true, "This is just a leak test");
|
||||
|
||||
]]></script>
|
||||
|
@ -1,6 +1,6 @@
|
||||
This is sqlite 3.6.23.1
|
||||
This is sqlite 3.7.0.1
|
||||
|
||||
-- Shawn Wilsher <me@shawnwilsher.com>, 03/2010
|
||||
-- Shawn Wilsher <me@shawnwilsher.com>, 08/2010
|
||||
|
||||
See http://www.sqlite.org/ for more info.
|
||||
|
||||
|
13408
db/sqlite3/src/sqlite3.c
13408
db/sqlite3/src/sqlite3.c
File diff suppressed because it is too large
Load Diff
@ -107,9 +107,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.6.23.1"
|
||||
#define SQLITE_VERSION_NUMBER 3006023
|
||||
#define SQLITE_SOURCE_ID "2010-03-26 22:28:06 b078b588d617e07886ad156e9f54ade6d823568e"
|
||||
#define SQLITE_VERSION "3.7.0.1"
|
||||
#define SQLITE_VERSION_NUMBER 3007000
|
||||
#define SQLITE_SOURCE_ID "2010-08-04 12:31:11 042a1abb030a0711386add7eb6e10832cc8b0f57"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -146,7 +146,6 @@ SQLITE_API const char *sqlite3_libversion(void);
|
||||
SQLITE_API const char *sqlite3_sourceid(void);
|
||||
SQLITE_API int sqlite3_libversion_number(void);
|
||||
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Compilation Options Diagnostics
|
||||
**
|
||||
@ -169,9 +168,10 @@ SQLITE_API int sqlite3_libversion_number(void);
|
||||
** See also: SQL functions [sqlite_compileoption_used()] and
|
||||
** [sqlite_compileoption_get()] and the [compile_options pragma].
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
SQLITE_API int sqlite3_compileoption_used(const char *zOptName);
|
||||
SQLITE_API const char *sqlite3_compileoption_get(int N);
|
||||
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** CAPI3REF: Test To See If The Library Is Threadsafe
|
||||
@ -393,7 +393,7 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */
|
||||
#define SQLITE_FULL 13 /* Insertion failed because database is full */
|
||||
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
|
||||
#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */
|
||||
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
|
||||
#define SQLITE_EMPTY 16 /* Database is empty */
|
||||
#define SQLITE_SCHEMA 17 /* The database schema changed */
|
||||
#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
|
||||
@ -449,7 +449,12 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8))
|
||||
#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
|
||||
#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8) )
|
||||
#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
|
||||
#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
|
||||
#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flags For File Open Operations
|
||||
@ -476,11 +481,12 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Device Characteristics
|
||||
**
|
||||
** The xDeviceCapabilities method of the [sqlite3_io_methods]
|
||||
** The xDeviceCharacteristics method of the [sqlite3_io_methods]
|
||||
** object returns an integer which is a vector of the these
|
||||
** bit values expressing I/O characteristics of the mass storage
|
||||
** device that holds the file that the [sqlite3_io_methods]
|
||||
@ -497,17 +503,18 @@ SQLITE_API int sqlite3_exec(
|
||||
** information is written to disk in the same order as calls
|
||||
** to xWrite().
|
||||
*/
|
||||
#define SQLITE_IOCAP_ATOMIC 0x00000001
|
||||
#define SQLITE_IOCAP_ATOMIC512 0x00000002
|
||||
#define SQLITE_IOCAP_ATOMIC1K 0x00000004
|
||||
#define SQLITE_IOCAP_ATOMIC2K 0x00000008
|
||||
#define SQLITE_IOCAP_ATOMIC4K 0x00000010
|
||||
#define SQLITE_IOCAP_ATOMIC8K 0x00000020
|
||||
#define SQLITE_IOCAP_ATOMIC16K 0x00000040
|
||||
#define SQLITE_IOCAP_ATOMIC32K 0x00000080
|
||||
#define SQLITE_IOCAP_ATOMIC64K 0x00000100
|
||||
#define SQLITE_IOCAP_SAFE_APPEND 0x00000200
|
||||
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
|
||||
#define SQLITE_IOCAP_ATOMIC 0x00000001
|
||||
#define SQLITE_IOCAP_ATOMIC512 0x00000002
|
||||
#define SQLITE_IOCAP_ATOMIC1K 0x00000004
|
||||
#define SQLITE_IOCAP_ATOMIC2K 0x00000008
|
||||
#define SQLITE_IOCAP_ATOMIC4K 0x00000010
|
||||
#define SQLITE_IOCAP_ATOMIC8K 0x00000020
|
||||
#define SQLITE_IOCAP_ATOMIC16K 0x00000040
|
||||
#define SQLITE_IOCAP_ATOMIC32K 0x00000080
|
||||
#define SQLITE_IOCAP_ATOMIC64K 0x00000100
|
||||
#define SQLITE_IOCAP_SAFE_APPEND 0x00000200
|
||||
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
|
||||
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
|
||||
|
||||
/*
|
||||
** CAPI3REF: File Locking Levels
|
||||
@ -658,6 +665,12 @@ struct sqlite3_io_methods {
|
||||
int (*xFileControl)(sqlite3_file*, int op, void *pArg);
|
||||
int (*xSectorSize)(sqlite3_file*);
|
||||
int (*xDeviceCharacteristics)(sqlite3_file*);
|
||||
/* Methods above are valid for version 1 */
|
||||
int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
|
||||
int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
|
||||
void (*xShmBarrier)(sqlite3_file*);
|
||||
int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
|
||||
/* Methods above are valid for version 2 */
|
||||
/* Additional methods may be added in future releases */
|
||||
};
|
||||
|
||||
@ -675,11 +688,19 @@ struct sqlite3_io_methods {
|
||||
** into an integer that the pArg argument points to. This capability
|
||||
** is used during testing and only needs to be supported when SQLITE_TEST
|
||||
** is defined.
|
||||
**
|
||||
** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
|
||||
** layer a hint of how large the database file will grow to be during the
|
||||
** current transaction. This hint is not guaranteed to be accurate but it
|
||||
** is often close. The underlying VFS might choose to preallocate database
|
||||
** file space based on this hint in order to help writes to the database
|
||||
** file run faster.
|
||||
*/
|
||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||
#define SQLITE_GET_LOCKPROXYFILE 2
|
||||
#define SQLITE_SET_LOCKPROXYFILE 3
|
||||
#define SQLITE_LAST_ERRNO 4
|
||||
#define SQLITE_FCNTL_SIZE_HINT 5
|
||||
|
||||
/*
|
||||
** CAPI3REF: Mutex Handle
|
||||
@ -811,20 +832,27 @@ typedef struct sqlite3_mutex sqlite3_mutex;
|
||||
** handled as a fatal error by SQLite, vfs implementations should endeavor
|
||||
** to prevent this by setting mxPathname to a sufficiently large value.
|
||||
**
|
||||
** The xRandomness(), xSleep(), and xCurrentTime() interfaces
|
||||
** are not strictly a part of the filesystem, but they are
|
||||
** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64()
|
||||
** interfaces are not strictly a part of the filesystem, but they are
|
||||
** included in the VFS structure for completeness.
|
||||
** The xRandomness() function attempts to return nBytes bytes
|
||||
** of good-quality randomness into zOut. The return value is
|
||||
** the actual number of bytes of randomness obtained.
|
||||
** The xSleep() method causes the calling thread to sleep for at
|
||||
** least the number of microseconds given. The xCurrentTime()
|
||||
** method returns a Julian Day Number for the current date and time.
|
||||
**
|
||||
** method returns a Julian Day Number for the current date and time as
|
||||
** a floating point value.
|
||||
** The xCurrentTimeInt64() method returns, as an integer, the Julian
|
||||
** Day Number multipled by 86400000 (the number of milliseconds in
|
||||
** a 24-hour day).
|
||||
** ^SQLite will use the xCurrentTimeInt64() method to get the current
|
||||
** date and time if that method is available (if iVersion is 2 or
|
||||
** greater and the function pointer is not NULL) and will fall back
|
||||
** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
|
||||
*/
|
||||
typedef struct sqlite3_vfs sqlite3_vfs;
|
||||
struct sqlite3_vfs {
|
||||
int iVersion; /* Structure version number */
|
||||
int iVersion; /* Structure version number (currently 2) */
|
||||
int szOsFile; /* Size of subclassed sqlite3_file */
|
||||
int mxPathname; /* Maximum file pathname length */
|
||||
sqlite3_vfs *pNext; /* Next registered VFS */
|
||||
@ -843,8 +871,16 @@ struct sqlite3_vfs {
|
||||
int (*xSleep)(sqlite3_vfs*, int microseconds);
|
||||
int (*xCurrentTime)(sqlite3_vfs*, double*);
|
||||
int (*xGetLastError)(sqlite3_vfs*, int, char *);
|
||||
/* New fields may be appended in figure versions. The iVersion
|
||||
** value will increment whenever this happens. */
|
||||
/*
|
||||
** The methods above are in version 1 of the sqlite_vfs object
|
||||
** definition. Those that follow are added in version 2 or later
|
||||
*/
|
||||
int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
|
||||
/*
|
||||
** The methods above are in versions 1 and 2 of the sqlite_vfs object.
|
||||
** New fields may be appended in figure versions. The iVersion
|
||||
** value will increment whenever this happens.
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
@ -856,13 +892,58 @@ struct sqlite3_vfs {
|
||||
** With SQLITE_ACCESS_EXISTS, the xAccess method
|
||||
** simply checks whether the file exists.
|
||||
** With SQLITE_ACCESS_READWRITE, the xAccess method
|
||||
** checks whether the file is both readable and writable.
|
||||
** checks whether the named directory is both readable and writable
|
||||
** (in other words, if files can be added, removed, and renamed within
|
||||
** the directory).
|
||||
** The SQLITE_ACCESS_READWRITE constant is currently used only by the
|
||||
** [temp_store_directory pragma], though this could change in a future
|
||||
** release of SQLite.
|
||||
** With SQLITE_ACCESS_READ, the xAccess method
|
||||
** checks whether the file is readable.
|
||||
** checks whether the file is readable. The SQLITE_ACCESS_READ constant is
|
||||
** currently unused, though it might be used in a future release of
|
||||
** SQLite.
|
||||
*/
|
||||
#define SQLITE_ACCESS_EXISTS 0
|
||||
#define SQLITE_ACCESS_READWRITE 1
|
||||
#define SQLITE_ACCESS_READ 2
|
||||
#define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */
|
||||
#define SQLITE_ACCESS_READ 2 /* Unused */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flags for the xShmLock VFS method
|
||||
**
|
||||
** These integer constants define the various locking operations
|
||||
** allowed by the xShmLock method of [sqlite3_io_methods]. The
|
||||
** following are the only legal combinations of flags to the
|
||||
** xShmLock method:
|
||||
**
|
||||
** <ul>
|
||||
** <li> SQLITE_SHM_LOCK | SQLITE_SHM_SHARED
|
||||
** <li> SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE
|
||||
** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED
|
||||
** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE
|
||||
** </ul>
|
||||
**
|
||||
** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as
|
||||
** was given no the corresponding lock.
|
||||
**
|
||||
** The xShmLock method can transition between unlocked and SHARED or
|
||||
** between unlocked and EXCLUSIVE. It cannot transition between SHARED
|
||||
** and EXCLUSIVE.
|
||||
*/
|
||||
#define SQLITE_SHM_UNLOCK 1
|
||||
#define SQLITE_SHM_LOCK 2
|
||||
#define SQLITE_SHM_SHARED 4
|
||||
#define SQLITE_SHM_EXCLUSIVE 8
|
||||
|
||||
/*
|
||||
** CAPI3REF: Maximum xShmLock index
|
||||
**
|
||||
** The xShmLock method on [sqlite3_io_methods] may use values
|
||||
** between 0 and this upper bound as its "offset" argument.
|
||||
** The SQLite core will never attempt to acquire or release a
|
||||
** lock outside of this range
|
||||
*/
|
||||
#define SQLITE_SHM_NLOCK 8
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Initialize The SQLite Library
|
||||
@ -973,11 +1054,10 @@ SQLITE_API int sqlite3_os_end(void);
|
||||
** ^If the option is unknown or SQLite is unable to set the option
|
||||
** then this routine returns a non-zero [error code].
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_config(int, ...);
|
||||
SQLITE_API int sqlite3_config(int, ...);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Configure database connections
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** The sqlite3_db_config() interface is used to make configuration
|
||||
** changes to a [database connection]. The interface is similar to
|
||||
@ -997,11 +1077,10 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_config(int, ...);
|
||||
** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if
|
||||
** the call is considered successful.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_config(sqlite3*, int op, ...);
|
||||
SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Memory Allocation Routines
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** An instance of this object defines the interface between SQLite
|
||||
** and low-level memory allocation routines.
|
||||
@ -1083,7 +1162,6 @@ struct sqlite3_mem_methods {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Configuration Options
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** These constants are the available integer configuration options that
|
||||
** can be passed as the first argument to the [sqlite3_config()] interface.
|
||||
@ -1269,6 +1347,24 @@ struct sqlite3_mem_methods {
|
||||
** [sqlite3_pcache_methods] object. SQLite copies of the current
|
||||
** page cache implementation into that object.)^ </dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_LOG</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
|
||||
** function with a call signature of void(*)(void*,int,const char*),
|
||||
** and a pointer to void. ^If the function pointer is not NULL, it is
|
||||
** invoked by [sqlite3_log()] to process each logging event. ^If the
|
||||
** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
|
||||
** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is
|
||||
** passed through as the first parameter to the application-defined logger
|
||||
** function whenever that function is invoked. ^The second parameter to
|
||||
** the logger function is a copy of the first parameter to the corresponding
|
||||
** [sqlite3_log()] call and is intended to be a [result code] or an
|
||||
** [extended result code]. ^The third parameter passed to the logger is
|
||||
** log message after formatting via [sqlite3_snprintf()].
|
||||
** The SQLite logging interface is not reentrant; the logger function
|
||||
** supplied by the application must not invoke any SQLite interface.
|
||||
** In a multi-threaded application, the application-defined logger
|
||||
** function must be threadsafe. </dd>
|
||||
**
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
|
||||
@ -1289,8 +1385,7 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Configuration Options
|
||||
** EXPERIMENTAL
|
||||
** CAPI3REF: Database Connection Configuration Options
|
||||
**
|
||||
** These constants are the available integer configuration options that
|
||||
** can be passed as the second argument to the [sqlite3_db_config()] interface.
|
||||
@ -2066,7 +2161,6 @@ SQLITE_API int sqlite3_set_authorizer(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Tracing And Profiling Functions
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** These routines register callback functions that can be used for
|
||||
** tracing and profiling the execution of SQL statements.
|
||||
@ -2084,7 +2178,7 @@ SQLITE_API int sqlite3_set_authorizer(
|
||||
** the original statement text and an estimate of wall-clock time
|
||||
** of how long that statement took to run.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
|
||||
SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
|
||||
SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
|
||||
void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
|
||||
|
||||
@ -2877,6 +2971,14 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
|
||||
** be the case that the same database connection is being used by two or
|
||||
** more threads at the same moment in time.
|
||||
**
|
||||
** For all versions of SQLite up to and including 3.6.23.1, it was required
|
||||
** after sqlite3_step() returned anything other than [SQLITE_ROW] that
|
||||
** [sqlite3_reset()] be called before any subsequent invocation of
|
||||
** sqlite3_step(). Failure to invoke [sqlite3_reset()] in this way would
|
||||
** result in an [SQLITE_MISUSE] return from sqlite3_step(). But after
|
||||
** version 3.6.23.1, sqlite3_step() began calling [sqlite3_reset()]
|
||||
** automatically in this circumstance rather than returning [SQLITE_MISUSE].
|
||||
**
|
||||
** <b>Goofy Interface Alert:</b> In the legacy interface, the sqlite3_step()
|
||||
** API always returns a generic error code, [SQLITE_ERROR], following any
|
||||
** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call
|
||||
@ -3689,7 +3791,7 @@ SQLITE_API int sqlite3_collation_needed16(
|
||||
void(*)(void*,sqlite3*,int eTextRep,const void*)
|
||||
);
|
||||
|
||||
#if SQLITE_HAS_CODEC
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
/*
|
||||
** Specify the key for an encrypted database. This routine should be
|
||||
** called right after sqlite3_open().
|
||||
@ -3872,8 +3974,6 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
|
||||
** an error or constraint causes an implicit rollback to occur.
|
||||
** ^The rollback callback is not invoked if a transaction is
|
||||
** automatically rolled back because the database connection is closed.
|
||||
** ^The rollback callback is not invoked if a transaction is
|
||||
** rolled back because a commit callback returned non-zero.
|
||||
**
|
||||
** See also the [sqlite3_update_hook()] interface.
|
||||
*/
|
||||
@ -4159,8 +4259,6 @@ SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
|
||||
SQLITE_API void sqlite3_reset_auto_extension(void);
|
||||
|
||||
/*
|
||||
****** EXPERIMENTAL - subject to change without notice **************
|
||||
**
|
||||
** The interface to the virtual-table mechanism is currently considered
|
||||
** to be experimental. The interface might change in incompatible ways.
|
||||
** If this is a problem for you, do not use the interface at this time.
|
||||
@ -4180,7 +4278,6 @@ typedef struct sqlite3_module sqlite3_module;
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Object
|
||||
** KEYWORDS: sqlite3_module {virtual table module}
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** This structure, sometimes called a a "virtual table module",
|
||||
** defines the implementation of a [virtual tables].
|
||||
@ -4227,7 +4324,6 @@ struct sqlite3_module {
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Indexing Information
|
||||
** KEYWORDS: sqlite3_index_info
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** The sqlite3_index_info structure and its substructures is used to
|
||||
** pass information into and receive the reply from the [xBestIndex]
|
||||
@ -4309,7 +4405,6 @@ struct sqlite3_index_info {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Register A Virtual Table Implementation
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^These routines are used to register a new [virtual table module] name.
|
||||
** ^Module names must be registered before
|
||||
@ -4331,13 +4426,13 @@ struct sqlite3_index_info {
|
||||
** interface is equivalent to sqlite3_create_module_v2() with a NULL
|
||||
** destructor.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module(
|
||||
SQLITE_API int sqlite3_create_module(
|
||||
sqlite3 *db, /* SQLite connection to register module with */
|
||||
const char *zName, /* Name of the module */
|
||||
const sqlite3_module *p, /* Methods for the module */
|
||||
void *pClientData /* Client data for xCreate/xConnect */
|
||||
);
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
|
||||
SQLITE_API int sqlite3_create_module_v2(
|
||||
sqlite3 *db, /* SQLite connection to register module with */
|
||||
const char *zName, /* Name of the module */
|
||||
const sqlite3_module *p, /* Methods for the module */
|
||||
@ -4348,7 +4443,6 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Instance Object
|
||||
** KEYWORDS: sqlite3_vtab
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** Every [virtual table module] implementation uses a subclass
|
||||
** of this object to describe a particular instance
|
||||
@ -4374,7 +4468,6 @@ struct sqlite3_vtab {
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Cursor Object
|
||||
** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor}
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** Every [virtual table module] implementation uses a subclass of the
|
||||
** following structure to describe cursors that point into the
|
||||
@ -4396,18 +4489,16 @@ struct sqlite3_vtab_cursor {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Declare The Schema Of A Virtual Table
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^The [xCreate] and [xConnect] methods of a
|
||||
** [virtual table module] call this interface
|
||||
** to declare the format (the names and datatypes of the columns) of
|
||||
** the virtual tables they implement.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
|
||||
SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Overload A Function For A Virtual Table
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^(Virtual tables can provide alternative implementations of functions
|
||||
** using the [xFindFunction] method of the [virtual table module].
|
||||
@ -4422,7 +4513,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zS
|
||||
** purpose is to be a placeholder function that can be overloaded
|
||||
** by a [virtual table].
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
|
||||
SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
|
||||
|
||||
/*
|
||||
** The interface to the virtual-table mechanism defined above (back up
|
||||
@ -4432,8 +4523,6 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const cha
|
||||
**
|
||||
** When the virtual-table mechanism stabilizes, we will declare the
|
||||
** interface fixed, support it indefinitely, and remove this comment.
|
||||
**
|
||||
****** EXPERIMENTAL - subject to change without notice **************
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -4776,7 +4865,6 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Mutex Methods Object
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** An instance of this structure defines the low-level routines
|
||||
** used to allocate and use mutexes.
|
||||
@ -4989,11 +5077,11 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_RESERVE 14
|
||||
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
|
||||
#define SQLITE_TESTCTRL_ISKEYWORD 16
|
||||
#define SQLITE_TESTCTRL_LAST 16
|
||||
#define SQLITE_TESTCTRL_PGHDRSZ 17
|
||||
#define SQLITE_TESTCTRL_LAST 17
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQLite Runtime Status
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^This interface is used to retrieve runtime status information
|
||||
** about the preformance of SQLite, and optionally to reset various
|
||||
@ -5021,12 +5109,11 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
**
|
||||
** See also: [sqlite3_db_status()]
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
||||
SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Status Parameters
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** These integer constants designate various run-time status parameters
|
||||
** that can be returned by [sqlite3_status()].
|
||||
@ -5113,14 +5200,15 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pH
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Status
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^This interface is used to retrieve runtime status information
|
||||
** about a single [database connection]. ^The first argument is the
|
||||
** database connection object to be interrogated. ^The second argument
|
||||
** is the parameter to interrogate. ^Currently, the only allowed value
|
||||
** for the second parameter is [SQLITE_DBSTATUS_LOOKASIDE_USED].
|
||||
** Additional options will likely appear in future releases of SQLite.
|
||||
** is an integer constant, taken from the set of
|
||||
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that
|
||||
** determiness the parameter to interrogate. The set of
|
||||
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely
|
||||
** to grow in future releases of SQLite.
|
||||
**
|
||||
** ^The current value of the requested parameter is written into *pCur
|
||||
** and the highest instantaneous value is written into *pHiwtr. ^If
|
||||
@ -5129,11 +5217,10 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pH
|
||||
**
|
||||
** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Status Parameters for database connections
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** These constants are the available integer "verbs" that can be passed as
|
||||
** the second argument to the [sqlite3_db_status()] interface.
|
||||
@ -5148,14 +5235,21 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur
|
||||
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
|
||||
** <dd>This parameter returns the number of lookaside memory slots currently
|
||||
** checked out.</dd>)^
|
||||
**
|
||||
** <dt>SQLITE_DBSTATUS_CACHE_USED</dt>
|
||||
** <dd>^This parameter returns the approximate number of of bytes of heap
|
||||
** memory used by all pager caches associated with the database connection.
|
||||
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
|
||||
** </dd>
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
|
||||
#define SQLITE_DBSTATUS_CACHE_USED 1
|
||||
#define SQLITE_DBSTATUS_MAX 1 /* Largest defined DBSTATUS */
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Prepared Statement Status
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^(Each prepared statement maintains various
|
||||
** [SQLITE_STMTSTATUS_SORT | counters] that measure the number
|
||||
@ -5177,11 +5271,10 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur
|
||||
**
|
||||
** See also: [sqlite3_status()] and [sqlite3_db_status()].
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
|
||||
SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Status Parameters for prepared statements
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** These preprocessor macros define integer codes that name counter
|
||||
** values associated with the [sqlite3_stmt_status()] interface.
|
||||
@ -5199,14 +5292,21 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_status(sqlite3_stmt*, int op,int
|
||||
** A non-zero value in this counter may indicate an opportunity to
|
||||
** improvement performance through careful use of indices.</dd>
|
||||
**
|
||||
** <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
|
||||
** <dd>^This is the number of rows inserted into transient indices that
|
||||
** were created automatically in order to help joins run faster.
|
||||
** A non-zero value in this counter may indicate an opportunity to
|
||||
** improvement performance by adding permanent indices that do not
|
||||
** need to be reinitialized each time the statement is run.</dd>
|
||||
**
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
|
||||
#define SQLITE_STMTSTATUS_SORT 2
|
||||
#define SQLITE_STMTSTATUS_AUTOINDEX 3
|
||||
|
||||
/*
|
||||
** CAPI3REF: Custom Page Cache Object
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** The sqlite3_pcache type is opaque. It is implemented by
|
||||
** the pluggable module. The SQLite core has no knowledge of
|
||||
@ -5221,7 +5321,6 @@ typedef struct sqlite3_pcache sqlite3_pcache;
|
||||
/*
|
||||
** CAPI3REF: Application Defined Page Cache.
|
||||
** KEYWORDS: {page cache}
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can
|
||||
** register an alternative page cache implementation by passing in an
|
||||
@ -5363,7 +5462,6 @@ struct sqlite3_pcache_methods {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Online Backup Object
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** The sqlite3_backup object records state information about an ongoing
|
||||
** online backup operation. ^The sqlite3_backup object is created by
|
||||
@ -5376,7 +5474,6 @@ typedef struct sqlite3_backup sqlite3_backup;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Online Backup API.
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** The backup API copies the content of one database into another.
|
||||
** It is useful either for creating backups of databases or
|
||||
@ -5445,10 +5542,14 @@ typedef struct sqlite3_backup sqlite3_backup;
|
||||
** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an
|
||||
** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code.
|
||||
**
|
||||
** ^The sqlite3_backup_step() might return [SQLITE_READONLY] if the destination
|
||||
** database was opened read-only or if
|
||||
** the destination is an in-memory database with a different page size
|
||||
** from the source database.
|
||||
** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if
|
||||
** <ol>
|
||||
** <li> the destination database was opened read-only, or
|
||||
** <li> the destination database is using write-ahead-log journaling
|
||||
** and the destination and source page sizes differ, or
|
||||
** <li> The destination database is an in-memory database and the
|
||||
** destination and source page sizes differ.
|
||||
** </ol>)^
|
||||
**
|
||||
** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then
|
||||
** the [sqlite3_busy_handler | busy-handler function]
|
||||
@ -5564,7 +5665,6 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Unlock Notification
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^When running in shared-cache mode, a database operation may fail with
|
||||
** an [SQLITE_LOCKED] error if the required locks on the shared-cache or
|
||||
@ -5686,7 +5786,6 @@ SQLITE_API int sqlite3_unlock_notify(
|
||||
|
||||
/*
|
||||
** CAPI3REF: String Comparison
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^The [sqlite3_strnicmp()] API allows applications and extensions to
|
||||
** compare the contents of two buffers containing UTF-8 strings in a
|
||||
@ -5697,12 +5796,11 @@ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Error Logging Interface
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^The [sqlite3_log()] interface writes a message into the error log
|
||||
** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
|
||||
** ^If logging is enabled, the zFormat string and subsequent arguments are
|
||||
** passed through to [sqlite3_vmprintf()] to generate the final output string.
|
||||
** used with [sqlite3_snprintf()] to generate the final output string.
|
||||
**
|
||||
** The sqlite3_log() interface is intended for use by extensions such as
|
||||
** virtual tables, collating functions, and SQL functions. While there is
|
||||
@ -5719,6 +5817,89 @@ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
|
||||
*/
|
||||
SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Write-Ahead Log Commit Hook
|
||||
**
|
||||
** ^The [sqlite3_wal_hook()] function is used to register a callback that
|
||||
** will be invoked each time a database connection commits data to a
|
||||
** [write-ahead log] (i.e. whenever a transaction is committed in
|
||||
** [journal_mode | journal_mode=WAL mode]).
|
||||
**
|
||||
** ^The callback is invoked by SQLite after the commit has taken place and
|
||||
** the associated write-lock on the database released, so the implementation
|
||||
** may read, write or [checkpoint] the database as required.
|
||||
**
|
||||
** ^The first parameter passed to the callback function when it is invoked
|
||||
** is a copy of the third parameter passed to sqlite3_wal_hook() when
|
||||
** registering the callback. ^The second is a copy of the database handle.
|
||||
** ^The third parameter is the name of the database that was written to -
|
||||
** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter
|
||||
** is the number of pages currently in the write-ahead log file,
|
||||
** including those that were just committed.
|
||||
**
|
||||
** The callback function should normally return [SQLITE_OK]. ^If an error
|
||||
** code is returned, that error will propagate back up through the
|
||||
** SQLite code base to cause the statement that provoked the callback
|
||||
** to report an error, though the commit will have still occurred. If the
|
||||
** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value
|
||||
** that does not correspond to any valid SQLite error code, the results
|
||||
** are undefined.
|
||||
**
|
||||
** A single database handle may have at most a single write-ahead log callback
|
||||
** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
|
||||
** previously registered write-ahead log callback. ^Note that the
|
||||
** [sqlite3_wal_autocheckpoint()] interface and the
|
||||
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
|
||||
** those overwrite any prior [sqlite3_wal_hook()] settings.
|
||||
*/
|
||||
SQLITE_API void *sqlite3_wal_hook(
|
||||
sqlite3*,
|
||||
int(*)(void *,sqlite3*,const char*,int),
|
||||
void*
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Configure an auto-checkpoint
|
||||
**
|
||||
** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
|
||||
** [sqlite3_wal_hook()] that causes any database on [database connection] D
|
||||
** to automatically [checkpoint]
|
||||
** after committing a transaction if there are N or
|
||||
** more frames in the [write-ahead log] file. ^Passing zero or
|
||||
** a negative value as the nFrame parameter disables automatic
|
||||
** checkpoints entirely.
|
||||
**
|
||||
** ^The callback registered by this function replaces any existing callback
|
||||
** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback
|
||||
** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
|
||||
** configured by this function.
|
||||
**
|
||||
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
|
||||
** from SQL.
|
||||
**
|
||||
** ^Every new [database connection] defaults to having the auto-checkpoint
|
||||
** enabled with a threshold of 1000 pages. The use of this interface
|
||||
** is only necessary if the default setting is found to be suboptimal
|
||||
** for a particular application.
|
||||
*/
|
||||
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Checkpoint a database
|
||||
**
|
||||
** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X
|
||||
** on [database connection] D to be [checkpointed]. ^If X is NULL or an
|
||||
** empty string, then a checkpoint is run on all databases of
|
||||
** connection D. ^If the database connection D is not in
|
||||
** [WAL | write-ahead log mode] then this interface is a harmless no-op.
|
||||
**
|
||||
** ^The [wal_checkpoint pragma] can be used to invoke this interface
|
||||
** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
|
||||
** [wal_autocheckpoint pragma] can be used to cause this interface to be
|
||||
** run whenever the WAL reaches a certain size threshold.
|
||||
*/
|
||||
SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
|
||||
|
||||
/*
|
||||
** Undo the hack that converts floating point types to integer for
|
||||
** builds on processors without floating point support.
|
||||
|
@ -68,5 +68,22 @@ _TEST_FILES = \
|
||||
blank.html \
|
||||
$(NULL)
|
||||
|
||||
ifneq (mobile,$(MOZ_BUILD_APP))
|
||||
_BROWSER_TEST_FILES = \
|
||||
browser_bug343515.js \
|
||||
bug343515_pg1.html \
|
||||
bug343515_pg2.html \
|
||||
bug343515_pg3.html \
|
||||
bug343515_pg3_1.html \
|
||||
bug343515_pg3_2.html \
|
||||
bug343515_pg3_1_1.html \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
|
||||
ifneq (mobile,$(MOZ_BUILD_APP))
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
endif
|
||||
|
248
docshell/test/navigation/browser_bug343515.js
Normal file
248
docshell/test/navigation/browser_bug343515.js
Normal file
@ -0,0 +1,248 @@
|
||||
// Test for bug 343515 - Need API for tabbrowsers to tell docshells they're visible/hidden
|
||||
|
||||
// Globals
|
||||
var testPath = "http://mochi.test:8888/browser/docshell/test/navigation/";
|
||||
var Ci = Components.interfaces;
|
||||
var Cc = Components.classes;
|
||||
var ctx = {};
|
||||
|
||||
// Helper function to check if a window is active
|
||||
function isActive(aWindow) {
|
||||
var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
return docshell.isActive;
|
||||
}
|
||||
|
||||
// Returns a closure that will remove itself as a listener from
|
||||
// aElem and then call aCallback. aCallback is executed asynchronously,
|
||||
// which is handy because load events fire before mIsDocumentLoaded is actually
|
||||
// set to true. :(
|
||||
function autoRemovedListener(aElem, aType, aCallback) {
|
||||
|
||||
var elem = aElem;
|
||||
var type = aType;
|
||||
var callback = aCallback;
|
||||
|
||||
function remover() {
|
||||
elem.removeEventListener(type, remover, true);
|
||||
executeSoon(callback);
|
||||
}
|
||||
|
||||
return remover;
|
||||
}
|
||||
|
||||
// Returns a closure that iteratively (BFS) waits for all
|
||||
// of the descendant frames of aInitialWindow to finish loading,
|
||||
// then calls aFinalCallback.
|
||||
function frameLoadWaiter(aInitialWindow, aFinalCallback) {
|
||||
|
||||
// The window we're currently waiting on
|
||||
var curr = aInitialWindow;
|
||||
|
||||
// The windows we need to wait for
|
||||
var waitQueue = [];
|
||||
|
||||
// The callback to call when we're all done
|
||||
var finalCallback = aFinalCallback;
|
||||
|
||||
function frameLoadCallback() {
|
||||
|
||||
// Push any subframes of what we just got
|
||||
for (var i = 0; i < curr.frames.length; ++i)
|
||||
waitQueue.push(curr.frames[i]);
|
||||
|
||||
// Handle the next window in the queue
|
||||
if (waitQueue.length >= 1) {
|
||||
curr = waitQueue.shift();
|
||||
if (curr.document.readyState == "complete")
|
||||
frameLoadCallback();
|
||||
else
|
||||
curr.addEventListener("load", autoRemovedListener(curr, "load", frameLoadCallback), true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we're all done. Call the final callback
|
||||
finalCallback();
|
||||
}
|
||||
|
||||
return frameLoadCallback;
|
||||
}
|
||||
|
||||
// Entry point from Mochikit
|
||||
function test() {
|
||||
|
||||
// Lots of callbacks going on here
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Begin the test
|
||||
step1();
|
||||
}
|
||||
|
||||
function step1() {
|
||||
|
||||
// Get a handle on the initial tab
|
||||
ctx.tab0 = gBrowser.selectedTab;
|
||||
ctx.tab0Browser = gBrowser.getBrowserForTab(ctx.tab0);
|
||||
ctx.tab0Window = ctx.tab0Browser.contentWindow;
|
||||
|
||||
// Our current tab should be active
|
||||
ok(isActive(ctx.tab0Window), "Tab 0 should be active at test start");
|
||||
|
||||
// Open a New Tab
|
||||
ctx.tab1 = gBrowser.addTab(testPath + "bug343515_pg1.html");
|
||||
ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1);
|
||||
ctx.tab1Window = ctx.tab1Browser.contentWindow;
|
||||
ctx.tab1Browser.addEventListener("load",
|
||||
autoRemovedListener(ctx.tab1Browser, "load", step2),
|
||||
true);
|
||||
}
|
||||
|
||||
function step2() {
|
||||
|
||||
// Our current tab should still be active
|
||||
ok(isActive(ctx.tab0Window), "Tab 0 should still be active");
|
||||
ok(!isActive(ctx.tab1Window), "Tab 1 should not be active");
|
||||
|
||||
// Switch to tab 1
|
||||
gBrowser.selectedTab = ctx.tab1;
|
||||
|
||||
// Tab 1 should now be active
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
||||
|
||||
// Open another tab
|
||||
ctx.tab2 = gBrowser.addTab(testPath + "bug343515_pg2.html");
|
||||
ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2);
|
||||
ctx.tab2Window = ctx.tab2Browser.contentWindow;
|
||||
ctx.tab2Browser.addEventListener("load",
|
||||
autoRemovedListener(ctx.tab2Browser, "load",
|
||||
frameLoadWaiter(ctx.tab2Window, step3)),
|
||||
true);
|
||||
}
|
||||
|
||||
function step3() {
|
||||
|
||||
// Tab 0 should be inactive, Tab 1 should be active
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
||||
|
||||
// Tab 2's window _and_ its iframes should be inactive
|
||||
ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
|
||||
is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes");
|
||||
ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
|
||||
|
||||
// Navigate tab 2 to a different page
|
||||
ctx.tab2Window.location = testPath + "bug343515_pg3.html";
|
||||
ctx.tab2Browser.addEventListener("load",
|
||||
autoRemovedListener(ctx.tab2Browser, "load",
|
||||
frameLoadWaiter(ctx.tab2Window, step4)),
|
||||
true);
|
||||
}
|
||||
|
||||
function step4() {
|
||||
|
||||
// Tab 0 should be inactive, Tab 1 should be active
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
||||
|
||||
// Tab2 and all descendants should be inactive
|
||||
ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
|
||||
is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes");
|
||||
is(ctx.tab2Window.frames[0].frames.length, 1, "Tab 2 iframe 0 should have 1 iframes");
|
||||
ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
|
||||
|
||||
// Switch to Tab 2
|
||||
gBrowser.selectedTab = ctx.tab2;
|
||||
|
||||
// Check everything
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive");
|
||||
ok(isActive(ctx.tab2Window), "Tab 2 should be active");
|
||||
ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active");
|
||||
ok(isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be active");
|
||||
ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active");
|
||||
|
||||
// Go back
|
||||
ctx.tab2Browser.addEventListener("pageshow",
|
||||
autoRemovedListener(ctx.tab2Browser, "pageshow",
|
||||
frameLoadWaiter(ctx.tab2Window, step5)),
|
||||
true);
|
||||
ctx.tab2Browser.goBack();
|
||||
|
||||
}
|
||||
|
||||
function step5() {
|
||||
|
||||
// Check everything
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive");
|
||||
ok(isActive(ctx.tab2Window), "Tab 2 should be active");
|
||||
ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active");
|
||||
ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active");
|
||||
|
||||
// Switch to tab 1
|
||||
gBrowser.selectedTab = ctx.tab1;
|
||||
|
||||
// Navigate to page 3
|
||||
ctx.tab1Window.location = testPath + "bug343515_pg3.html";
|
||||
ctx.tab1Browser.addEventListener("load",
|
||||
autoRemovedListener(ctx.tab1Browser, "load",
|
||||
frameLoadWaiter(ctx.tab1Window, step6)),
|
||||
true);
|
||||
}
|
||||
|
||||
function step6() {
|
||||
|
||||
// Check everything
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
||||
ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active");
|
||||
ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
|
||||
ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active");
|
||||
ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
|
||||
|
||||
// Go forward on tab 2
|
||||
ctx.tab2Browser.addEventListener("pageshow",
|
||||
autoRemovedListener(ctx.tab2Browser, "pageshow",
|
||||
frameLoadWaiter(ctx.tab2Window, step7)),
|
||||
true);
|
||||
var tab2docshell = ctx.tab2Window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation);
|
||||
tab2docshell.goForward();
|
||||
}
|
||||
|
||||
function step7() {
|
||||
|
||||
ctx.tab2Window = ctx.tab2Browser.contentWindow;
|
||||
|
||||
// Check everything
|
||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
||||
ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active");
|
||||
ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
|
||||
ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active");
|
||||
ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive");
|
||||
ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
|
||||
|
||||
// That's probably enough
|
||||
allDone();
|
||||
}
|
||||
|
||||
function allDone() {
|
||||
|
||||
// Close the tabs we made
|
||||
gBrowser.removeCurrentTab();
|
||||
gBrowser.tabContainer.advanceSelectedTab(1, true);
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
// Tell the framework we're done
|
||||
finish();
|
||||
}
|
5
docshell/test/navigation/bug343515_pg1.html
Normal file
5
docshell/test/navigation/bug343515_pg1.html
Normal file
@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>Page 1
|
||||
</body>
|
||||
</html>
|
7
docshell/test/navigation/bug343515_pg2.html
Normal file
7
docshell/test/navigation/bug343515_pg2.html
Normal file
@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>Page 2
|
||||
<iframe src="data:text/html,<html><head></head><body>pg2 iframe 0</body></html>"></iframe>
|
||||
<iframe src="data:text/html,<html><head></head><body>pg2 iframe 1</body></html>"></iframe>
|
||||
</body>
|
||||
</html>
|
7
docshell/test/navigation/bug343515_pg3.html
Normal file
7
docshell/test/navigation/bug343515_pg3.html
Normal file
@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>Page 3
|
||||
<iframe src="bug343515_pg3_1.html"></iframe>
|
||||
<iframe src="bug343515_pg3_2.html"></iframe>
|
||||
</body>
|
||||
</html>
|
6
docshell/test/navigation/bug343515_pg3_1.html
Normal file
6
docshell/test/navigation/bug343515_pg3_1.html
Normal file
@ -0,0 +1,6 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>pg3 - iframe 0
|
||||
<iframe src="bug343515_pg3_1_1.html"></iframe>
|
||||
</body>
|
||||
</html>
|
1
docshell/test/navigation/bug343515_pg3_1_1.html
Normal file
1
docshell/test/navigation/bug343515_pg3_1_1.html
Normal file
@ -0,0 +1 @@
|
||||
<html><head></head><body>How far does the rabbit hole go?</body></html>
|
1
docshell/test/navigation/bug343515_pg3_2.html
Normal file
1
docshell/test/navigation/bug343515_pg3_2.html
Normal file
@ -0,0 +1 @@
|
||||
<html><head></head><body>pg3 iframe 1</body></html>
|
@ -495,19 +495,25 @@ static const char kDOMStringBundleURL[] =
|
||||
// NOTE: DEFAULT_SCRIPTABLE_FLAGS and DOM_DEFAULT_SCRIPTABLE_FLAGS
|
||||
// are defined in nsIDOMClassInfo.h.
|
||||
|
||||
#define WINDOW_SCRIPTABLE_FLAGS \
|
||||
#define COMMON_WINDOW_SCRIPTABLE_FLAGS \
|
||||
(nsIXPCScriptable::WANT_GETPROPERTY | \
|
||||
nsIXPCScriptable::WANT_SETPROPERTY | \
|
||||
nsIXPCScriptable::WANT_PRECREATE | \
|
||||
nsIXPCScriptable::WANT_ADDPROPERTY | \
|
||||
nsIXPCScriptable::WANT_DELPROPERTY | \
|
||||
nsIXPCScriptable::WANT_NEWENUMERATE | \
|
||||
nsIXPCScriptable::WANT_FINALIZE | \
|
||||
nsIXPCScriptable::WANT_EQUALITY | \
|
||||
nsIXPCScriptable::WANT_OUTER_OBJECT | \
|
||||
nsIXPCScriptable::WANT_INNER_OBJECT | \
|
||||
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE)
|
||||
|
||||
#define INNER_WINDOW_SCRIPTABLE_FLAGS \
|
||||
(COMMON_WINDOW_SCRIPTABLE_FLAGS | \
|
||||
nsIXPCScriptable::WANT_OUTER_OBJECT) \
|
||||
|
||||
#define OUTER_WINDOW_SCRIPTABLE_FLAGS \
|
||||
(COMMON_WINDOW_SCRIPTABLE_FLAGS | \
|
||||
nsIXPCScriptable::WANT_INNER_OBJECT | \
|
||||
nsIXPCScriptable::WANT_NEWENUMERATE)
|
||||
|
||||
#define NODE_SCRIPTABLE_FLAGS \
|
||||
((DOM_DEFAULT_SCRIPTABLE_FLAGS | \
|
||||
nsIXPCScriptable::WANT_GETPROPERTY | \
|
||||
@ -633,11 +639,11 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(Window, nsOuterWindowSH,
|
||||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
OUTER_WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(InnerWindow, nsInnerWindowSH,
|
||||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
INNER_WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(Location, nsLocationSH,
|
||||
(DOM_DEFAULT_SCRIPTABLE_FLAGS &
|
||||
@ -928,11 +934,11 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
// DOM Chrome Window class.
|
||||
NS_DEFINE_CLASSINFO_DATA(ChromeWindow, nsOuterWindowSH,
|
||||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
OUTER_WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(InnerChromeWindow, nsInnerWindowSH,
|
||||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
INNER_WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(CSSRGBColor, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
@ -1315,11 +1321,11 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsOuterWindowSH,
|
||||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
OUTER_WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(InnerModalContentWindow, nsInnerWindowSH,
|
||||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
WINDOW_SCRIPTABLE_FLAGS)
|
||||
INNER_WINDOW_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(DataContainerEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
@ -5379,34 +5385,15 @@ nsCommonWindowSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCommonWindowSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp,
|
||||
PRBool *_retval)
|
||||
nsOuterWindowSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp,
|
||||
PRBool *_retval)
|
||||
{
|
||||
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
|
||||
|
||||
#ifdef DEBUG_SH_FORWARDING
|
||||
{
|
||||
nsDependentJSString str(::JS_ValueToString(cx, id));
|
||||
|
||||
if (win->IsInnerWindow()) {
|
||||
#ifdef DEBUG_PRINT_INNER
|
||||
printf("Property '%s' add on inner window %p\n",
|
||||
NS_ConvertUTF16toUTF8(str).get(), (void *)win);
|
||||
#endif
|
||||
} else {
|
||||
printf("Property '%s' add on outer window %p\n",
|
||||
NS_ConvertUTF16toUTF8(str).get(), (void *)win);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
JSObject *realObj;
|
||||
wrapper->GetJSObject(&realObj);
|
||||
if (win->IsOuterWindow() && obj == realObj) {
|
||||
// XXXjst: Do security checks here when we remove the security
|
||||
// checks on the inner window.
|
||||
|
||||
if (obj == realObj) {
|
||||
nsGlobalWindow *innerWin = win->GetCurrentInnerWindowInternal();
|
||||
|
||||
JSObject *innerObj;
|
||||
@ -6523,38 +6510,22 @@ ContentWindowGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsCommonWindowSH::sResolving = PR_FALSE;
|
||||
nsOuterWindowSH::sResolving = PR_FALSE;
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCommonWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval)
|
||||
nsOuterWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval)
|
||||
{
|
||||
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
|
||||
|
||||
#ifdef DEBUG_SH_FORWARDING
|
||||
{
|
||||
nsDependentJSString str(::JS_ValueToString(cx, id));
|
||||
|
||||
if (win->IsInnerWindow()) {
|
||||
#ifdef DEBUG_PRINT_INNER
|
||||
printf("Property '%s' resolve on inner window %p\n",
|
||||
NS_ConvertUTF16toUTF8(str).get(), (void *)win);
|
||||
#endif
|
||||
} else {
|
||||
printf("Property '%s' resolve on outer window %p\n",
|
||||
NS_ConvertUTF16toUTF8(str).get(), (void *)win);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Note, we won't forward resolve of the location property to the
|
||||
// inner window, we need to deal with that one for the outer too
|
||||
// since we've got special security protection code for that
|
||||
// property. Also note that we want to enter this block even for
|
||||
// native wrappers, so that we'll ensure an inner window to wrap
|
||||
// against for the result of whatever we're getting.
|
||||
if (win->IsOuterWindow() && id != sLocation_id) {
|
||||
if (id != sLocation_id) {
|
||||
// XXXjst: Do security checks here when we remove the security
|
||||
// checks on the inner window.
|
||||
|
||||
@ -6635,6 +6606,17 @@ nsCommonWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
}
|
||||
}
|
||||
|
||||
return nsCommonWindowSH::NewResolve(wrapper, cx, obj, id, flags, objp,
|
||||
_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCommonWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval)
|
||||
{
|
||||
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
|
||||
|
||||
if (!JSID_IS_STRING(id)) {
|
||||
if (JSID_IS_INT(id) && !(flags & JSRESOLVE_ASSIGNING)) {
|
||||
// If we're resolving a numeric property, treat that as if
|
||||
@ -7159,32 +7141,30 @@ nsCommonWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCommonWindowSH::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, PRUint32 enum_op, jsval *statep,
|
||||
jsid *idp, PRBool *_retval)
|
||||
nsOuterWindowSH::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, PRUint32 enum_op, jsval *statep,
|
||||
jsid *idp, PRBool *_retval)
|
||||
{
|
||||
switch ((JSIterateOp)enum_op) {
|
||||
/* FIXME bug 576449: non-enumerable property support */
|
||||
case JSENUMERATE_INIT_ALL:
|
||||
case JSENUMERATE_INIT:
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// First, do the security check that nsDOMClassInfo does to see
|
||||
// if we need to do any work at all.
|
||||
nsDOMClassInfo::Enumerate(wrapper, cx, obj, _retval);
|
||||
if (!*_retval) {
|
||||
NS_ERROR("security wrappers failed us");
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
// The security check passed, let's see if we need to get the inner
|
||||
// window's JS object or if we can just start enumerating.
|
||||
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
|
||||
JSObject *enumobj = win->GetGlobalJSObject();
|
||||
if (win->IsOuterWindow()) {
|
||||
nsGlobalWindow *inner = win->GetCurrentInnerWindowInternal();
|
||||
if (inner) {
|
||||
enumobj = inner->GetGlobalJSObject();
|
||||
}
|
||||
}
|
||||
nsGlobalWindow *win =
|
||||
nsGlobalWindow::FromWrapper(wrapper)->GetCurrentInnerWindowInternal();
|
||||
JSObject *enumobj = win->FastGetGlobalJSObject();
|
||||
|
||||
// Great, we have the js object, now let's enumerate it.
|
||||
JSObject *iterator = JS_NewPropertyIterator(cx, enumobj);
|
||||
@ -7272,8 +7252,8 @@ nsCommonWindowSH::Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCommonWindowSH::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, JSObject * *_retval)
|
||||
nsInnerWindowSH::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, JSObject * *_retval)
|
||||
{
|
||||
nsGlobalWindow *origWin = nsGlobalWindow::FromWrapper(wrapper);
|
||||
nsGlobalWindow *win = origWin->GetOuterWindowInternal();
|
||||
@ -7300,12 +7280,12 @@ nsCommonWindowSH::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCommonWindowSH::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, JSObject * *_retval)
|
||||
nsOuterWindowSH::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, JSObject * *_retval)
|
||||
{
|
||||
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
|
||||
|
||||
if (win->IsInnerWindow() || win->IsFrozen()) {
|
||||
if (win->IsFrozen()) {
|
||||
// Return the inner window, or the outer if we're dealing with a
|
||||
// frozen outer.
|
||||
|
||||
@ -7317,7 +7297,7 @@ nsCommonWindowSH::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx
|
||||
if (!inner) {
|
||||
// Yikes! No inner window! Instead of leaking the outer window into the
|
||||
// scope chain, let's return an error.
|
||||
|
||||
NS_ERROR("using an outer that doesn't have an inner?");
|
||||
*_retval = nsnull;
|
||||
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
@ -513,8 +513,6 @@ protected:
|
||||
JSObject *obj, JSString *str,
|
||||
PRBool *did_resolve);
|
||||
|
||||
static PRBool sResolving;
|
||||
|
||||
public:
|
||||
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
JSObject *globalObj, JSObject **parentObj);
|
||||
@ -544,24 +542,15 @@ public:
|
||||
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
|
||||
NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
|
||||
NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
|
||||
NS_IMETHOD DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
|
||||
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval);
|
||||
NS_IMETHOD NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, PRUint32 enum_op, jsval *statep,
|
||||
jsid *idp, PRBool *_retval);
|
||||
NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj);
|
||||
NS_IMETHOD Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, const jsval &val, PRBool *bp);
|
||||
NS_IMETHOD OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, JSObject * *_retval);
|
||||
NS_IMETHOD InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, JSObject * *_retval);
|
||||
|
||||
static JSBool GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
|
||||
jsid id, uintN flags,
|
||||
@ -586,7 +575,20 @@ protected:
|
||||
{
|
||||
}
|
||||
|
||||
static PRBool sResolving;
|
||||
|
||||
public:
|
||||
NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
|
||||
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval);
|
||||
NS_IMETHOD NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, PRUint32 enum_op, jsval *statep,
|
||||
jsid *idp, PRBool *_retval);
|
||||
NS_IMETHOD InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, JSObject * *_retval);
|
||||
|
||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||
{
|
||||
return new nsOuterWindowSH(aData);
|
||||
@ -605,6 +607,10 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
// We WANT_ADDPROPERTY, but are content to inherit it from nsEventReceiverSH.
|
||||
NS_IMETHOD OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
JSObject * obj, JSObject * *_retval);
|
||||
|
||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||
{
|
||||
return new nsInnerWindowSH(aData);
|
||||
|
@ -157,6 +157,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
|
||||
|
||||
nsFocusManager* nsFocusManager::sInstance = nsnull;
|
||||
PRBool nsFocusManager::sMouseFocusesFormControl = PR_FALSE;
|
||||
|
||||
nsFocusManager::nsFocusManager()
|
||||
{ }
|
||||
@ -168,6 +169,7 @@ nsFocusManager::~nsFocusManager()
|
||||
if (prefBranch) {
|
||||
prefBranch->RemoveObserver("accessibility.browsewithcaret", this);
|
||||
prefBranch->RemoveObserver("accessibility.tabfocus_applies_to_xul", this);
|
||||
prefBranch->RemoveObserver("accessibility.mouse_focuses_formcontrol", this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,9 +186,13 @@ nsFocusManager::Init()
|
||||
nsContentUtils::GetBoolPref("accessibility.tabfocus_applies_to_xul",
|
||||
nsIContent::sTabFocusModelAppliesToXUL);
|
||||
|
||||
sMouseFocusesFormControl =
|
||||
nsContentUtils::GetBoolPref("accessibility.mouse_focuses_formcontrol", PR_FALSE);
|
||||
|
||||
nsIPrefBranch2* prefBranch = nsContentUtils::GetPrefBranch();
|
||||
prefBranch->AddObserver("accessibility.browsewithcaret", fm, PR_TRUE);
|
||||
prefBranch->AddObserver("accessibility.tabfocus_applies_to_xul", fm, PR_TRUE);
|
||||
prefBranch->AddObserver("accessibility.mouse_focuses_formcontrol", fm, PR_TRUE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -213,6 +219,10 @@ nsFocusManager::Observe(nsISupports *aSubject,
|
||||
nsContentUtils::GetBoolPref("accessibility.tabfocus_applies_to_xul",
|
||||
nsIContent::sTabFocusModelAppliesToXUL);
|
||||
}
|
||||
else if (data.EqualsLiteral("accessibility.mouse_focuses_formcontrol")) {
|
||||
sMouseFocusesFormControl =
|
||||
nsContentUtils::GetBoolPref("accessibility.mouse_focuses_formcontrol", PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -113,6 +113,8 @@ public:
|
||||
*/
|
||||
static nsIContent* GetRedirectedFocus(nsIContent* aContent);
|
||||
|
||||
static PRBool sMouseFocusesFormControl;
|
||||
|
||||
protected:
|
||||
|
||||
nsFocusManager();
|
||||
|
@ -926,7 +926,7 @@ nsGlobalWindow::CleanUp(PRBool aIgnoreModalDialog)
|
||||
if (mCleanedUp)
|
||||
return;
|
||||
mCleanedUp = PR_TRUE;
|
||||
|
||||
|
||||
mNavigator = nsnull;
|
||||
mScreen = nsnull;
|
||||
mHistory = nsnull;
|
||||
@ -1077,6 +1077,8 @@ nsGlobalWindow::FreeInnerObjects(PRBool aClearScope)
|
||||
mListenerManager = nsnull;
|
||||
}
|
||||
|
||||
mLocation = nsnull;
|
||||
|
||||
if (mDocument) {
|
||||
NS_ASSERTION(mDoc, "Why is mDoc null?");
|
||||
|
||||
@ -1510,7 +1512,6 @@ public:
|
||||
WindowStateHolder(nsGlobalWindow *aWindow,
|
||||
nsIXPConnectJSObjectHolder *aHolder,
|
||||
nsNavigator *aNavigator,
|
||||
nsLocation *aLocation,
|
||||
nsIXPConnectJSObjectHolder *aOuterProto);
|
||||
|
||||
nsGlobalWindow* GetInnerWindow() { return mInnerWindow; }
|
||||
@ -1518,7 +1519,6 @@ public:
|
||||
{ return mInnerWindowHolder; }
|
||||
|
||||
nsNavigator* GetNavigator() { return mNavigator; }
|
||||
nsLocation* GetLocation() { return mLocation; }
|
||||
nsIXPConnectJSObjectHolder* GetOuterProto() { return mOuterProto; }
|
||||
|
||||
void DidRestoreWindow()
|
||||
@ -1527,7 +1527,6 @@ public:
|
||||
|
||||
mInnerWindowHolder = nsnull;
|
||||
mNavigator = nsnull;
|
||||
mLocation = nsnull;
|
||||
mOuterProto = nsnull;
|
||||
}
|
||||
|
||||
@ -1539,7 +1538,6 @@ protected:
|
||||
// window ends up recalculating it anyway.
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> mInnerWindowHolder;
|
||||
nsRefPtr<nsNavigator> mNavigator;
|
||||
nsRefPtr<nsLocation> mLocation;
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> mOuterProto;
|
||||
};
|
||||
|
||||
@ -1548,11 +1546,9 @@ NS_DEFINE_STATIC_IID_ACCESSOR(WindowStateHolder, WINDOWSTATEHOLDER_IID)
|
||||
WindowStateHolder::WindowStateHolder(nsGlobalWindow *aWindow,
|
||||
nsIXPConnectJSObjectHolder *aHolder,
|
||||
nsNavigator *aNavigator,
|
||||
nsLocation *aLocation,
|
||||
nsIXPConnectJSObjectHolder *aOuterProto)
|
||||
: mInnerWindow(aWindow),
|
||||
mNavigator(aNavigator),
|
||||
mLocation(aLocation),
|
||||
mOuterProto(aOuterProto)
|
||||
{
|
||||
NS_PRECONDITION(aWindow, "null window");
|
||||
@ -1754,7 +1750,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
|
||||
// These assignments addref.
|
||||
mNavigator = wsh->GetNavigator();
|
||||
mLocation = wsh->GetLocation();
|
||||
|
||||
if (mNavigator) {
|
||||
// Update mNavigator's docshell pointer now.
|
||||
@ -1773,8 +1768,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
newInnerWindow = new nsGlobalWindow(this);
|
||||
}
|
||||
}
|
||||
|
||||
mLocation = nsnull;
|
||||
}
|
||||
|
||||
if (!newInnerWindow) {
|
||||
@ -2191,8 +2184,6 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
|
||||
|
||||
if (mNavigator)
|
||||
mNavigator->SetDocShell(aDocShell);
|
||||
if (mLocation)
|
||||
mLocation->SetDocShell(aDocShell);
|
||||
if (mHistory)
|
||||
mHistory->SetDocShell(aDocShell);
|
||||
if (mFrames)
|
||||
@ -6811,12 +6802,13 @@ nsGlobalWindow::GetPrivateRoot()
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::GetLocation(nsIDOMLocation ** aLocation)
|
||||
{
|
||||
FORWARD_TO_OUTER(GetLocation, (aLocation), NS_ERROR_NOT_INITIALIZED);
|
||||
FORWARD_TO_INNER(GetLocation, (aLocation), NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
*aLocation = nsnull;
|
||||
|
||||
if (!mLocation && mDocShell) {
|
||||
mLocation = new nsLocation(mDocShell);
|
||||
nsIDocShell *docShell = GetDocShell();
|
||||
if (!mLocation && docShell) {
|
||||
mLocation = new nsLocation(docShell);
|
||||
if (!mLocation) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -9093,7 +9085,6 @@ nsGlobalWindow::SaveWindowState(nsISupports **aState)
|
||||
nsCOMPtr<nsISupports> state = new WindowStateHolder(inner,
|
||||
mInnerWindowHolder,
|
||||
mNavigator,
|
||||
mLocation,
|
||||
proto);
|
||||
NS_ENSURE_TRUE(state, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
|
@ -786,7 +786,6 @@ protected:
|
||||
nsRefPtr<nsBarProp> mStatusbar;
|
||||
nsRefPtr<nsBarProp> mScrollbars;
|
||||
nsCOMPtr<nsIWeakReference> mWindowUtils;
|
||||
nsRefPtr<nsLocation> mLocation;
|
||||
nsString mStatus;
|
||||
nsString mDefaultStatus;
|
||||
// index 0->language_id 1, so index MAX-1 == language_id MAX
|
||||
@ -808,6 +807,7 @@ protected:
|
||||
nsTimeout* mTimeoutInsertionPoint;
|
||||
PRUint32 mTimeoutPublicIdCounter;
|
||||
PRUint32 mTimeoutFiringDepth;
|
||||
nsRefPtr<nsLocation> mLocation;
|
||||
|
||||
// Holder of the dummy java plugin, used to expose window.java and
|
||||
// window.packages.
|
||||
|
@ -48,10 +48,10 @@ class nsIControllers;
|
||||
class nsIController;
|
||||
struct JSContext;
|
||||
|
||||
// 2e26a297-6e40-41c1-81c9-7306571f955e
|
||||
// 426C1B56-E38A-435E-B291-BE1557F2A0A2
|
||||
#define NS_IWINDOWROOT_IID \
|
||||
{ 0x2e26a297, 0x6e40, 0x41c1, \
|
||||
{ 0x81, 0xc9, 0x73, 0x06, 0x57, 0x1f, 0x95, 0x5e } }
|
||||
{ 0x426c1b56, 0xe38a, 0x435e, \
|
||||
{ 0xb2, 0x91, 0xbe, 0x15, 0x57, 0xf2, 0xa0, 0xa2 } }
|
||||
|
||||
class nsPIWindowRoot : public nsPIDOMEventTarget {
|
||||
public:
|
||||
@ -59,7 +59,8 @@ public:
|
||||
|
||||
virtual nsPIDOMWindow* GetWindow()=0;
|
||||
|
||||
virtual void GetPopupNode(nsIDOMNode** aNode) = 0;
|
||||
// get and set the node that is the context of a popup menu
|
||||
virtual nsIDOMNode* GetPopupNode() = 0;
|
||||
virtual void SetPopupNode(nsIDOMNode* aNode) = 0;
|
||||
|
||||
virtual nsresult GetControllerForCommand(const char *aCommand,
|
||||
|
@ -355,10 +355,10 @@ nsWindowRoot::GetControllerForCommand(const char * aCommand,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsWindowRoot::GetPopupNode(nsIDOMNode** aNode)
|
||||
nsIDOMNode*
|
||||
nsWindowRoot::GetPopupNode()
|
||||
{
|
||||
NS_IF_ADDREF(*aNode = mPopupNode);
|
||||
return mPopupNode;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -95,7 +95,7 @@ public:
|
||||
virtual nsresult GetControllerForCommand(const char * aCommand,
|
||||
nsIController** _retval);
|
||||
|
||||
virtual void GetPopupNode(nsIDOMNode** aNode);
|
||||
virtual nsIDOMNode* GetPopupNode();
|
||||
virtual void SetPopupNode(nsIDOMNode* aNode);
|
||||
|
||||
virtual void SetParentTarget(nsPIDOMEventTarget* aTarget)
|
||||
|
@ -43,7 +43,7 @@ interface nsIDOMXULCommandDispatcher;
|
||||
interface nsIObserver;
|
||||
interface nsIBoxObject;
|
||||
|
||||
[scriptable, uuid(d55c39B4-b54a-4df5-9e68-09919e4538f9)]
|
||||
[scriptable, uuid(b16d13c3-837d-445d-8f56-05d83d9b9eae)]
|
||||
interface nsIDOMXULDocument : nsISupports
|
||||
{
|
||||
attribute nsIDOMNode popupNode;
|
||||
@ -101,16 +101,4 @@ interface nsIDOMXULDocument : nsISupports
|
||||
* - Ben Goodger (8/23/2005)
|
||||
*/
|
||||
void loadOverlay(in DOMString url, in nsIObserver aObserver);
|
||||
|
||||
/**
|
||||
* Get the popup node from this XUL document without doing a security check to
|
||||
* make sure that the caller has access to this node. This is for use from C++
|
||||
* callers that can indirectly be called from content.
|
||||
*/
|
||||
[noscript] nsIDOMNode trustedGetPopupNode();
|
||||
|
||||
/**
|
||||
* Like trustedGetPopupNode, but gets the tooltip node instead.
|
||||
*/
|
||||
[noscript] nsIDOMNode trustedGetTooltipNode();
|
||||
};
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "mozilla/plugins/BrowserStreamParent.h"
|
||||
#include "PluginIdentifierParent.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCRT.h"
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
@ -69,6 +70,7 @@ using mozilla::ipc::SyncChannel;
|
||||
using namespace mozilla::plugins;
|
||||
|
||||
static const char kTimeoutPref[] = "dom.ipc.plugins.timeoutSecs";
|
||||
static const char kLaunchTimeoutPref[] = "dom.ipc.plugins.processLaunchTimeoutSecs";
|
||||
|
||||
template<>
|
||||
struct RunnableMethodTraits<mozilla::plugins::PluginModuleParent>
|
||||
@ -84,15 +86,21 @@ PluginModuleParent::LoadModule(const char* aFilePath)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG_FUNCTION;
|
||||
|
||||
PRInt32 prefSecs = nsContentUtils::GetIntPref(kLaunchTimeoutPref, 0);
|
||||
|
||||
// Block on the child process being launched and initialized.
|
||||
PluginModuleParent* parent = new PluginModuleParent(aFilePath);
|
||||
parent->mSubprocess->Launch();
|
||||
nsAutoPtr<PluginModuleParent> parent(new PluginModuleParent(aFilePath));
|
||||
bool launched = parent->mSubprocess->Launch(prefSecs * 1000);
|
||||
if (!launched) {
|
||||
// Need to set this so the destructor doesn't complain.
|
||||
parent->mShutdown = true;
|
||||
return nsnull;
|
||||
}
|
||||
parent->Open(parent->mSubprocess->GetChannel(),
|
||||
parent->mSubprocess->GetChildProcessHandle());
|
||||
|
||||
TimeoutChanged(kTimeoutPref, parent);
|
||||
|
||||
return parent;
|
||||
return parent.forget();
|
||||
}
|
||||
|
||||
|
||||
|
@ -68,11 +68,11 @@ PluginProcessParent::~PluginProcessParent()
|
||||
}
|
||||
|
||||
bool
|
||||
PluginProcessParent::Launch()
|
||||
PluginProcessParent::Launch(PRInt32 timeoutMs)
|
||||
{
|
||||
vector<string> args;
|
||||
args.push_back(MungePluginDsoPath(mPluginFilePath));
|
||||
return SyncLaunch(args);
|
||||
return SyncLaunch(args, timeoutMs);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -61,9 +61,10 @@ public:
|
||||
~PluginProcessParent();
|
||||
|
||||
/**
|
||||
* Synchronously launch the plugin process.
|
||||
* Synchronously launch the plugin process. If the process fails to launch
|
||||
* after timeoutMs, this method will return false.
|
||||
*/
|
||||
bool Launch();
|
||||
bool Launch(PRInt32 timeoutMs);
|
||||
|
||||
void Delete();
|
||||
|
||||
|
@ -51,6 +51,8 @@ _TEST_FILES = \
|
||||
child_ip_address.html \
|
||||
test_setting_document.domain_idn.html \
|
||||
idn_child.html \
|
||||
file_location.html \
|
||||
test_location.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
10
dom/tests/mochitest/dom-level0/file_location.html
Normal file
10
dom/tests/mochitest/dom-level0/file_location.html
Normal file
@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<script>
|
||||
try {
|
||||
top.SimpleTest.ok(!("existingprop" in location), "got a new location object in the iframe");
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
location.iframeprop = 42;
|
||||
</script>
|
||||
</html>
|
65
dom/tests/mochitest/dom-level0/test_location.html
Normal file
65
dom/tests/mochitest/dom-level0/test_location.html
Normal file
@ -0,0 +1,65 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for location object behaviors</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<iframe id="ifr" onload="runTest()"></iframe>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var count = 0;
|
||||
var firstlocation;
|
||||
var lastlocation;
|
||||
|
||||
function runTest() {
|
||||
++count;
|
||||
if (count == 1) {
|
||||
firstlocation = $('ifr').contentWindow.location;
|
||||
firstlocation.existingprop = 'fail';
|
||||
firstlocation.href = 'file_location.html';
|
||||
return;
|
||||
}
|
||||
|
||||
if (count == 2) {
|
||||
lastlocation = $('ifr').contentWindow.location;
|
||||
is(lastlocation.iframeprop, 42, 'can read the new prop');
|
||||
ok(firstlocation !== lastlocation, 'got a new location object');
|
||||
// firstlocation should still work.
|
||||
firstlocation.href = 'http://example.com/tests/dom/tests/mochitest/dom-level0/file_location.html';
|
||||
return;
|
||||
}
|
||||
|
||||
if (count == 3) {
|
||||
try {
|
||||
isnot($('ifr').contentWindow.location.iframeprop, 42, "shouldn't see this");
|
||||
} catch (e) {
|
||||
ok(/Permission denied/.test(e), "correctly threw a security error");
|
||||
}
|
||||
|
||||
// XXX this doesn't work - file a bug on me!
|
||||
//firstlocation.href = 'http://mochi.test:8888/tests/dom/tests/mochitest/dom-level0/file_location.html';
|
||||
todo(false, 'can use old same-origin location object to set cross-origin frame');
|
||||
$('ifr').contentWindow.location = 'file_location.html';
|
||||
return;
|
||||
}
|
||||
|
||||
is(lastlocation.iframeprop, 42, 'can still read old values of the location object');
|
||||
ok(lastlocation !== $('ifr').contentWindow.location, 'location objects are distinct');
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -79,7 +79,19 @@ function runTest()
|
||||
// the test regardless of which user input last occurred.
|
||||
$("l1").focus();
|
||||
var expectedVisible = (!isWin || getComputedStyle($("l1"), "").outlineWidth == "2px");
|
||||
testHTMLElements(isMac, isWin && !expectedVisible);
|
||||
testHTMLElements(htmlElements, isMac, isWin && !expectedVisible);
|
||||
|
||||
if (isMac) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
|
||||
getService(Components.interfaces.nsIPrefBranch);
|
||||
prefs.setBoolPref("accessibility.mouse_focuses_formcontrol", true);
|
||||
|
||||
testHTMLElements(htmlElementsMacPrefSet, true, false);
|
||||
|
||||
prefs.setBoolPref("accessibility.mouse_focuses_formcontrol", false);
|
||||
}
|
||||
|
||||
$("l1").focus();
|
||||
checkFocus($("l1"), expectedVisible, "appearance on list after focus() with :moz-focusring");
|
||||
@ -117,6 +129,7 @@ var htmlElements = [
|
||||
"<input id='elem' class='canfocus'>",
|
||||
"<input id='elem' type='password' class='canfocus'>",
|
||||
"<input id='elem' type='button'>",
|
||||
"<input id='elem' type='checkbox'>",
|
||||
"<textarea id='elem' class='canfocus'></textarea>",
|
||||
"<select id='elem' class='canfocus'><option>One</select>",
|
||||
"<select id='elem' rows='5' class='canfocus'><option>One</select>",
|
||||
@ -124,13 +137,20 @@ var htmlElements = [
|
||||
"<a href='about:blank' class='canfocus' onclick='return false;'>about:blank</a>",
|
||||
];
|
||||
|
||||
function testHTMLElements(isMac, expectedNoRingsOnWin)
|
||||
var htmlElementsMacPrefSet = [
|
||||
"<button id='elem' class='canfocus'>Button</button>",
|
||||
"<input id='elem' class='canfocus'>",
|
||||
"<input id='elem' type='button' class='canfocus'>",
|
||||
"<input id='elem' type='checkbox' class='canfocus'>",
|
||||
];
|
||||
|
||||
function testHTMLElements(list, isMac, expectedNoRingsOnWin)
|
||||
{
|
||||
var childwin = frames[0];
|
||||
var childdoc = childwin.document;
|
||||
var container = childdoc.getElementById("container");
|
||||
for (var e = 0; e < htmlElements.length; e++) {
|
||||
container.innerHTML = htmlElements[e];
|
||||
for (var e = 0; e < list.length; e++) {
|
||||
container.innerHTML = list[e];
|
||||
|
||||
var elem = container.firstChild;
|
||||
|
||||
@ -140,8 +160,8 @@ function testHTMLElements(isMac, expectedNoRingsOnWin)
|
||||
ringSize = "0px";
|
||||
|
||||
synthesizeMouse(elem, 8, 8, { }, childwin);
|
||||
is(childdoc.activeElement, shouldFocus ? elem : childdoc.body, "mouse click on " + htmlElements[e]);
|
||||
is(childwin.getComputedStyle(elem, "").outlineWidth, ringSize, "mouse click on " + htmlElements[e] + " ring");
|
||||
is(childdoc.activeElement, shouldFocus ? elem : childdoc.body, "mouse click on " + list[e]);
|
||||
is(childwin.getComputedStyle(elem, "").outlineWidth, ringSize, "mouse click on " + list[e] + " ring");
|
||||
|
||||
if (childdoc.activeElement)
|
||||
childdoc.activeElement.blur();
|
||||
@ -149,9 +169,9 @@ function testHTMLElements(isMac, expectedNoRingsOnWin)
|
||||
ringSize = (elem.localName == "a" ? "0" : (expectedNoRingsOnWin ? 2 : 1)) + "px";
|
||||
|
||||
elem.focus();
|
||||
is(childdoc.activeElement, elem, "focus() on " + htmlElements[e]);
|
||||
is(childdoc.activeElement, elem, "focus() on " + list[e]);
|
||||
is(childwin.getComputedStyle(elem, "").outlineWidth, ringSize,
|
||||
"focus() on " + htmlElements[e] + " ring");
|
||||
"focus() on " + list[e] + " ring");
|
||||
|
||||
childdoc.activeElement.blur();
|
||||
}
|
||||
|
@ -102,6 +102,7 @@ DIST_LINK_FILES = \
|
||||
greprefs.js \
|
||||
browserconfig.properties \
|
||||
blocklist.xml \
|
||||
chrome.manifest \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_IPC
|
||||
|
@ -107,7 +107,7 @@ static JSContext *autoconfig_cx = nsnull;
|
||||
static JSObject *autoconfig_glob;
|
||||
|
||||
static JSClass global_class = {
|
||||
"autoconfig_global", 0,
|
||||
"autoconfig_global", JSCLASS_GLOBAL_FLAGS,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nsnull
|
||||
};
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "nsUnicharUtilCIID.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsTextFragment.h"
|
||||
|
||||
// IsIgnorableCharacter
|
||||
//
|
||||
@ -429,13 +430,6 @@ IsBRElement(nsIDOMNode* aNode)
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
static void
|
||||
GetNodeText(nsIDOMNode* aNode, nsAutoString& aText)
|
||||
{
|
||||
nsresult rv = aNode->GetNodeValue(aText);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to get node text");
|
||||
}
|
||||
|
||||
// Find the previous node in the DOM tree in preorder. This isn't fast because
|
||||
// one call to GetPrevSibling can be O(N) in the number of siblings...
|
||||
static nsIDOMNode*
|
||||
@ -480,10 +474,12 @@ ContainsDOMWordSeparator(nsIDOMNode* aNode, PRInt32 aBeforeOffset,
|
||||
if (!IsTextNode(aNode))
|
||||
return PR_FALSE;
|
||||
|
||||
nsAutoString str;
|
||||
GetNodeText(aNode, str);
|
||||
for (PRInt32 i = NS_MIN(aBeforeOffset, PRInt32(str.Length())) - 1; i >= 0; --i) {
|
||||
if (IsDOMWordSeparator(str.CharAt(i))) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
|
||||
NS_ASSERTION(content, "Where is our content?");
|
||||
const nsTextFragment* textFragment = content->GetText();
|
||||
NS_ASSERTION(textFragment, "Where is our text?");
|
||||
for (PRInt32 i = NS_MIN(aBeforeOffset, PRInt32(textFragment->GetLength())) - 1; i >= 0; --i) {
|
||||
if (IsDOMWordSeparator(textFragment->CharAt(i))) {
|
||||
*aSeparatorOffset = i;
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -584,7 +580,6 @@ mozInlineSpellWordUtil::BuildSoftText()
|
||||
PRBool seenSoftEnd = PR_FALSE;
|
||||
// Leave this outside the loop so large heap string allocations can be reused
|
||||
// across iterations
|
||||
nsAutoString str;
|
||||
while (node) {
|
||||
if (node == mSoftEnd.mNode) {
|
||||
seenSoftEnd = PR_TRUE;
|
||||
@ -592,14 +587,17 @@ mozInlineSpellWordUtil::BuildSoftText()
|
||||
|
||||
PRBool exit = PR_FALSE;
|
||||
if (IsTextNode(node)) {
|
||||
GetNodeText(node, str);
|
||||
PRInt32 lastOffsetInNode = str.Length();
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
|
||||
NS_ASSERTION(content, "Where is our content?");
|
||||
const nsTextFragment* textFragment = content->GetText();
|
||||
NS_ASSERTION(textFragment, "Where is our text?");
|
||||
PRInt32 lastOffsetInNode = textFragment->GetLength();
|
||||
|
||||
if (seenSoftEnd) {
|
||||
// check whether we can stop after this
|
||||
for (PRInt32 i = node == mSoftEnd.mNode ? mSoftEnd.mOffset : 0;
|
||||
i < PRInt32(str.Length()); ++i) {
|
||||
if (IsDOMWordSeparator(str.CharAt(i))) {
|
||||
i < PRInt32(textFragment->GetLength()); ++i) {
|
||||
if (IsDOMWordSeparator(textFragment->CharAt(i))) {
|
||||
exit = PR_TRUE;
|
||||
// stop at the first separator after the soft end point
|
||||
lastOffsetInNode = i;
|
||||
@ -612,7 +610,7 @@ mozInlineSpellWordUtil::BuildSoftText()
|
||||
PRInt32 len = lastOffsetInNode - firstOffsetInNode;
|
||||
mSoftTextDOMMapping.AppendElement(
|
||||
DOMTextMapping(NodeOffset(node, firstOffsetInNode), mSoftText.Length(), len));
|
||||
mSoftText.Append(Substring(str, firstOffsetInNode, len));
|
||||
textFragment->AppendTo(mSoftText, firstOffsetInNode, len);
|
||||
}
|
||||
|
||||
firstOffsetInNode = 0;
|
||||
|
@ -237,3 +237,16 @@
|
||||
|
||||
// Vista glass
|
||||
#define NS_THEME_WIN_GLASS 230
|
||||
|
||||
// Windows themed window frame elements
|
||||
#define NS_THEME_WINDOW_TITLEBAR 231
|
||||
#define NS_THEME_WINDOW_TITLEBAR_MAXIMIZED 232
|
||||
#define NS_THEME_WINDOW_FRAME_LEFT 233
|
||||
#define NS_THEME_WINDOW_FRAME_RIGHT 234
|
||||
#define NS_THEME_WINDOW_FRAME_BOTTOM 235
|
||||
#define NS_THEME_WINDOW_BUTTON_CLOSE 236
|
||||
#define NS_THEME_WINDOW_BUTTON_MINIMIZE 237
|
||||
#define NS_THEME_WINDOW_BUTTON_MAXIMIZE 238
|
||||
#define NS_THEME_WINDOW_BUTTON_RESTORE 239
|
||||
#define NS_THEME_WINDOW_BUTTON_BOX 240
|
||||
#define NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED 241
|
||||
|
@ -131,12 +131,14 @@ void GeckoChildProcessHost::InitWindowsGroupID()
|
||||
#endif
|
||||
|
||||
bool
|
||||
GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTimeoutMs)
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
InitWindowsGroupID();
|
||||
#endif
|
||||
|
||||
PRIntervalTime timeoutTicks = (aTimeoutMs > 0) ?
|
||||
PR_MillisecondsToInterval(aTimeoutMs) : PR_INTERVAL_NO_TIMEOUT;
|
||||
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
|
||||
NS_ASSERTION(MessageLoop::current() != ioLoop, "sync launch from the IO thread NYI");
|
||||
|
||||
@ -144,15 +146,29 @@ GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
NewRunnableMethod(this,
|
||||
&GeckoChildProcessHost::PerformAsyncLaunch,
|
||||
aExtraOpts));
|
||||
|
||||
// NB: this uses a different mechanism than the chromium parent
|
||||
// class.
|
||||
MonitorAutoEnter mon(mMonitor);
|
||||
PRIntervalTime waitStart = PR_IntervalNow();
|
||||
PRIntervalTime current;
|
||||
|
||||
// We'll receive several notifications, we need to exit when we
|
||||
// have either successfully launched or have timed out.
|
||||
while (!mLaunched) {
|
||||
mon.Wait();
|
||||
mon.Wait(timeoutTicks);
|
||||
|
||||
if (timeoutTicks != PR_INTERVAL_NO_TIMEOUT) {
|
||||
current = PR_IntervalNow();
|
||||
PRIntervalTime elapsed = current - waitStart;
|
||||
if (elapsed > timeoutTicks) {
|
||||
break;
|
||||
}
|
||||
timeoutTicks = timeoutTicks - elapsed;
|
||||
waitStart = current;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return mLaunched;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -64,7 +64,7 @@ public:
|
||||
|
||||
~GeckoChildProcessHost();
|
||||
|
||||
bool SyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>());
|
||||
bool SyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>(), int32 timeoutMs=0);
|
||||
bool AsyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>());
|
||||
bool PerformAsyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>());
|
||||
|
||||
|
@ -486,7 +486,6 @@ def _cxxRefType(ipdltype, side):
|
||||
def _cxxConstRefType(ipdltype, side):
|
||||
t = _cxxBareType(ipdltype, side)
|
||||
if ipdltype.isIPDL() and ipdltype.isActor():
|
||||
t.const = 1 # const Actor*
|
||||
return t
|
||||
if ipdltype.isIPDL() and ipdltype.isShmem():
|
||||
t.ref = 1
|
||||
@ -508,8 +507,7 @@ def _cxxConstPtrToType(ipdltype, side):
|
||||
t = _cxxBareType(ipdltype, side)
|
||||
if ipdltype.isIPDL() and ipdltype.isActor():
|
||||
t.ptr = 0
|
||||
t.const = 1
|
||||
t.ptrconstptr = 1 # const Actor* const*
|
||||
t.ptrconstptr = 1
|
||||
return t
|
||||
t.const = 1
|
||||
t.ptrconst = 1
|
||||
|
@ -78,6 +78,7 @@ IPDLTESTS = \
|
||||
TestShutdown \
|
||||
TestStackHooks \
|
||||
TestSyncWakeup \
|
||||
TestSyncHang \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(OS_ARCH),Linux)
|
||||
|
15
ipc/ipdl/test/cxx/PTestSyncHang.ipdl
Normal file
15
ipc/ipdl/test/cxx/PTestSyncHang.ipdl
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestSyncHang {
|
||||
|
||||
child:
|
||||
__delete__();
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
71
ipc/ipdl/test/cxx/TestSyncHang.cpp
Normal file
71
ipc/ipdl/test/cxx/TestSyncHang.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include "TestSyncHang.h"
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent
|
||||
|
||||
mozilla::ipc::GeckoChildProcessHost* gSyncHangSubprocess;
|
||||
|
||||
TestSyncHangParent::TestSyncHangParent()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestSyncHangParent);
|
||||
}
|
||||
|
||||
TestSyncHangParent::~TestSyncHangParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestSyncHangParent);
|
||||
}
|
||||
|
||||
void
|
||||
DeleteSyncHangSubprocess(MessageLoop* uiLoop)
|
||||
{
|
||||
delete gSyncHangSubprocess;
|
||||
}
|
||||
|
||||
void
|
||||
DeferredSyncHangParentShutdown()
|
||||
{
|
||||
// ping to DeleteSubprocess
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(DeleteSyncHangSubprocess, MessageLoop::current()));
|
||||
}
|
||||
|
||||
void
|
||||
TestSyncHangParent::Main()
|
||||
{
|
||||
vector<string> args;
|
||||
args.push_back("fake/path");
|
||||
gSyncHangSubprocess = new mozilla::ipc::GeckoChildProcessHost(GeckoProcessType_Plugin);
|
||||
bool launched = gSyncHangSubprocess->SyncLaunch(args, 2);
|
||||
if (launched)
|
||||
fail("Calling SyncLaunch with an invalid path should return false");
|
||||
|
||||
MessageLoop::current()->PostTask(
|
||||
FROM_HERE, NewRunnableFunction(DeferredSyncHangParentShutdown));
|
||||
Close();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
TestSyncHangChild::TestSyncHangChild()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestSyncHangChild);
|
||||
}
|
||||
|
||||
TestSyncHangChild::~TestSyncHangChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestSyncHangChild);
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
56
ipc/ipdl/test/cxx/TestSyncHang.h
Normal file
56
ipc/ipdl/test/cxx/TestSyncHang.h
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef mozilla__ipdltest_TestSyncHang_h
|
||||
#define mozilla__ipdltest_TestSyncHang_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestSyncHangParent.h"
|
||||
#include "mozilla/_ipdltest/PTestSyncHangChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
class TestSyncHangParent :
|
||||
public PTestSyncHangParent
|
||||
{
|
||||
public:
|
||||
TestSyncHangParent();
|
||||
virtual ~TestSyncHangParent();
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TestSyncHangChild :
|
||||
public PTestSyncHangChild
|
||||
{
|
||||
public:
|
||||
TestSyncHangChild();
|
||||
virtual ~TestSyncHangChild();
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
QuitChild();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestSyncHang_h
|
@ -30,5 +30,6 @@ IPDLSRCS = \
|
||||
PTestShutdownSubsub.ipdl \
|
||||
PTestStackHooks.ipdl \
|
||||
PTestSyncWakeup.ipdl \
|
||||
PTestSyncHang.ipdl \
|
||||
PTestSysVShmem.ipdl \
|
||||
$(NULL)
|
||||
|
@ -48,6 +48,8 @@
|
||||
#include "jsobj.h"
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace jetpack {
|
||||
|
||||
@ -62,7 +64,8 @@ class Handle
|
||||
Handle(Handle* parent)
|
||||
: mParent(parent)
|
||||
, mObj(NULL)
|
||||
, mRuntime(NULL)
|
||||
, mCx(NULL)
|
||||
, mRooted(false)
|
||||
{}
|
||||
|
||||
BaseType* AllocPHandle() {
|
||||
@ -79,7 +82,8 @@ public:
|
||||
Handle()
|
||||
: mParent(NULL)
|
||||
, mObj(NULL)
|
||||
, mRuntime(NULL)
|
||||
, mCx(NULL)
|
||||
, mRooted(false)
|
||||
{}
|
||||
|
||||
~Handle() { TearDown(); }
|
||||
@ -95,8 +99,28 @@ public:
|
||||
return Unwrap(cx, JSVAL_TO_OBJECT(val));
|
||||
}
|
||||
|
||||
JSObject* ToJSObject(JSContext* cx) const {
|
||||
if (!mObj && !mRuntime) {
|
||||
void Root() {
|
||||
NS_ASSERTION(mObj && mCx, "Rooting with no object unexpected.");
|
||||
if (mRooted)
|
||||
return;
|
||||
|
||||
if (!JS_AddNamedObjectRoot(mCx, &mObj, "Jetpack Handle")) {
|
||||
NS_RUNTIMEABORT("Failed to add root.");
|
||||
}
|
||||
mRooted = true;
|
||||
}
|
||||
|
||||
void Unroot() {
|
||||
NS_ASSERTION(mCx, "Unrooting with no JSContext unexpected.");
|
||||
if (!mRooted)
|
||||
return;
|
||||
|
||||
JS_RemoveObjectRoot(mCx, &mObj);
|
||||
mRooted = false;
|
||||
}
|
||||
|
||||
JSObject* ToJSObject(JSContext* cx) {
|
||||
if (!mObj && !mCx) {
|
||||
JSAutoRequest request(cx);
|
||||
|
||||
JSClass* clasp = const_cast<JSClass*>(&sHandle_JSClass);
|
||||
@ -107,16 +131,13 @@ public:
|
||||
|
||||
JSPropertySpec* ps = const_cast<JSPropertySpec*>(sHandle_Properties);
|
||||
JSFunctionSpec* fs = const_cast<JSFunctionSpec*>(sHandle_Functions);
|
||||
JSRuntime* rt;
|
||||
|
||||
if (JS_SetPrivate(cx, obj, (void*)this) &&
|
||||
JS_DefineProperties(cx, obj, ps) &&
|
||||
JS_DefineFunctions(cx, obj, fs) &&
|
||||
(rt = JS_GetRuntime(cx)) &&
|
||||
JS_AddObjectRoot(cx, &mObj))
|
||||
{
|
||||
JS_DefineFunctions(cx, obj, fs)) {
|
||||
mObj = obj;
|
||||
mRuntime = rt;
|
||||
mCx = cx;
|
||||
Root();
|
||||
}
|
||||
}
|
||||
return mObj;
|
||||
@ -134,16 +155,33 @@ private:
|
||||
static bool IsParent(const PHandleChild* handle) { return false; }
|
||||
|
||||
void TearDown() {
|
||||
if (mObj) {
|
||||
mObj->setPrivate(NULL);
|
||||
mObj = NULL;
|
||||
if (mCx) {
|
||||
JSAutoRequest ar(mCx);
|
||||
|
||||
if (mObj) {
|
||||
mObj->setPrivate(NULL);
|
||||
|
||||
js::AutoObjectRooter obj(mCx, mObj);
|
||||
mObj = NULL;
|
||||
|
||||
JSBool hasOnInvalidate;
|
||||
if (JS_HasProperty(mCx, obj.object(), "onInvalidate",
|
||||
&hasOnInvalidate) && hasOnInvalidate) {
|
||||
js::AutoValueRooter r(mCx);
|
||||
JSBool ok = JS_CallFunctionName(mCx, obj.object(), "onInvalidate", 0,
|
||||
NULL, r.jsval_addr());
|
||||
if (!ok)
|
||||
JS_ReportPendingException(mCx);
|
||||
}
|
||||
|
||||
// By not nulling out mContext, we prevent ToJSObject from
|
||||
// reviving an invalidated/destroyed handle.
|
||||
}
|
||||
|
||||
// Nulling out mObj effectively unroots the object, but we still
|
||||
// need to remove the root, else the JS engine will complain at
|
||||
// shutdown.
|
||||
NS_ASSERTION(mRuntime, "Should have a JSRuntime if we had an object");
|
||||
js_RemoveRoot(mRuntime, (void*)&mObj);
|
||||
// By not nulling out mRuntime, we prevent ToJSObject from
|
||||
// reviving an invalidated/destroyed handle.
|
||||
Unroot();
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,8 +193,9 @@ private:
|
||||
|
||||
// Used to cache the JSObject returned by ToJSObject, which is
|
||||
// otherwise a const method.
|
||||
mutable JSObject* mObj;
|
||||
mutable JSRuntime* mRuntime;
|
||||
JSObject* mObj;
|
||||
JSContext* mCx;
|
||||
bool mRooted;
|
||||
|
||||
static Handle*
|
||||
Unwrap(JSContext* cx, JSObject* obj) {
|
||||
@ -199,6 +238,38 @@ private:
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
GetIsRooted(JSContext* cx, JSObject* obj, jsid, jsval* vp) {
|
||||
Handle* self = Unwrap(cx, obj);
|
||||
bool rooted = self ? self->mRooted : false;
|
||||
JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(rooted));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
SetIsRooted(JSContext* cx, JSObject* obj, jsid, jsval* vp) {
|
||||
Handle* self = Unwrap(cx, obj);
|
||||
JSBool v;
|
||||
if (!JS_ValueToBoolean(cx, *vp, &v))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!self) {
|
||||
if (v) {
|
||||
JS_ReportError(cx, "Cannot root invalidated handle.");
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (v)
|
||||
self->Root();
|
||||
else
|
||||
self->Unroot();
|
||||
|
||||
*vp = BOOLEAN_TO_JSVAL(v);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Invalidate(JSContext* cx, uintN argc, jsval* vp) {
|
||||
if (argc > 0) {
|
||||
@ -207,15 +278,10 @@ private:
|
||||
}
|
||||
|
||||
Handle* self = Unwrap(cx, JS_THIS_OBJECT(cx, vp));
|
||||
if (self) {
|
||||
JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_TRUE));
|
||||
if (!Send__delete__(self)) {
|
||||
JS_ReportError(cx, "Failed to send __delete__ while invalidating");
|
||||
return JS_FALSE;
|
||||
}
|
||||
} else {
|
||||
JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_FALSE));
|
||||
}
|
||||
if (self)
|
||||
unused << Send__delete__(self);
|
||||
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -248,10 +314,13 @@ private:
|
||||
static void
|
||||
Finalize(JSContext* cx, JSObject* obj) {
|
||||
Handle* self = Unwrap(cx, obj);
|
||||
// Avoid warnings about unused return values:
|
||||
self && Send__delete__(self);
|
||||
if (self) {
|
||||
NS_ASSERTION(!self->mRooted, "Finalizing a rooted object?");
|
||||
self->mCx = NULL;
|
||||
self->mObj = NULL;
|
||||
unused << Send__delete__(self);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <class BaseType>
|
||||
@ -265,13 +334,14 @@ Handle<BaseType>::sHandle_JSClass = {
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
#define HANDLE_PROP_FLAGS (JSPROP_READONLY | JSPROP_PERMANENT)
|
||||
#define HANDLE_PROP_FLAGS (JSPROP_PERMANENT | JSPROP_SHARED)
|
||||
|
||||
template <class BaseType>
|
||||
const JSPropertySpec
|
||||
Handle<BaseType>::sHandle_Properties[] = {
|
||||
{ "parent", 0, HANDLE_PROP_FLAGS, GetParent, NULL },
|
||||
{ "isValid", 0, HANDLE_PROP_FLAGS, GetIsValid, NULL },
|
||||
{ "parent", 0, HANDLE_PROP_FLAGS | JSPROP_READONLY, GetParent, NULL },
|
||||
{ "isValid", 0, HANDLE_PROP_FLAGS | JSPROP_READONLY, GetIsValid, NULL },
|
||||
{ "isRooted", 0, HANDLE_PROP_FLAGS, GetIsRooted, SetIsRooted },
|
||||
{ 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -298,7 +298,7 @@ JetpackActorCommon::jsval_from_PrimVariant(JSContext* cx,
|
||||
|
||||
case PrimVariant::TPHandleParent: {
|
||||
JSObject* hobj =
|
||||
static_cast<const HandleParent*>(from.get_PHandleParent())->ToJSObject(cx);
|
||||
static_cast<HandleParent*>(from.get_PHandleParent())->ToJSObject(cx);
|
||||
if (!hobj)
|
||||
return false;
|
||||
*to = OBJECT_TO_JSVAL(hobj);
|
||||
@ -307,7 +307,7 @@ JetpackActorCommon::jsval_from_PrimVariant(JSContext* cx,
|
||||
|
||||
case PrimVariant::TPHandleChild: {
|
||||
JSObject* hobj =
|
||||
static_cast<const HandleChild*>(from.get_PHandleChild())->ToJSObject(cx);
|
||||
static_cast<HandleChild*>(from.get_PHandleChild())->ToJSObject(cx);
|
||||
if (!hobj)
|
||||
return false;
|
||||
*to = OBJECT_TO_JSVAL(hobj);
|
||||
|
@ -68,10 +68,13 @@ JetpackChild::sImplMethods[] = {
|
||||
JS_FN("registerReceiver", RegisterReceiver, 2, IMPL_METHOD_FLAGS),
|
||||
JS_FN("unregisterReceiver", UnregisterReceiver, 2, IMPL_METHOD_FLAGS),
|
||||
JS_FN("unregisterReceivers", UnregisterReceivers, 1, IMPL_METHOD_FLAGS),
|
||||
JS_FN("wrap", Wrap, 1, IMPL_METHOD_FLAGS),
|
||||
JS_FN("createHandle", CreateHandle, 0, IMPL_METHOD_FLAGS),
|
||||
JS_FN("createSandbox", CreateSandbox, 0, IMPL_METHOD_FLAGS),
|
||||
JS_FN("evalInSandbox", EvalInSandbox, 2, IMPL_METHOD_FLAGS),
|
||||
JS_FN("gc", GC, 0, IMPL_METHOD_FLAGS),
|
||||
#ifdef JS_GC_ZEAL
|
||||
JS_FN("gczeal", GCZeal, 1, IMPL_METHOD_FLAGS),
|
||||
#endif
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
@ -362,13 +365,6 @@ JetpackChild::UnregisterReceivers(JSContext* cx, uintN argc, jsval* vp)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JetpackChild::Wrap(JSContext* cx, uintN argc, jsval* vp)
|
||||
{
|
||||
NS_NOTYETIMPLEMENTED("wrap not yet implemented (depends on bug 563010)");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JetpackChild::CreateHandle(JSContext* cx, uintN argc, jsval* vp)
|
||||
{
|
||||
@ -476,5 +472,27 @@ JetpackChild::ReportError(JSContext* cx, const char* message,
|
||||
sReportingError = false;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JetpackChild::GC(JSContext* cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JS_GC(cx);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
JSBool
|
||||
JetpackChild::GCZeal(JSContext* cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval* argv = JS_ARGV(cx, vp);
|
||||
|
||||
uint32 zeal;
|
||||
if (!JS_ValueToECMAUint32(cx, argv[0], &zeal))
|
||||
return JS_FALSE;
|
||||
|
||||
JS_SetGCZeal(cx, PRUint8(zeal));
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace jetpack
|
||||
} // namespace mozilla
|
||||
|
@ -86,10 +86,13 @@ private:
|
||||
static JSBool RegisterReceiver(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool UnregisterReceiver(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool UnregisterReceivers(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool Wrap(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool CreateHandle(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool CreateSandbox(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool EvalInSandbox(JSContext* cx, uintN argc, jsval *vp);
|
||||
static JSBool GC(JSContext* cx, uintN argc, jsval *vp);
|
||||
#ifdef JS_GC_ZEAL
|
||||
static JSBool GCZeal(JSContext* cx, uintN argc, jsval *vp);
|
||||
#endif
|
||||
|
||||
static void ReportError(JSContext* cx, const char* message,
|
||||
JSErrorReport* report);
|
||||
|
@ -38,15 +38,17 @@ function test_local_invalidation() {
|
||||
var parent = createHandle(),
|
||||
child = parent.createHandle();
|
||||
|
||||
do_check_true(child.invalidate());
|
||||
dump("test_local_invalidation\n");
|
||||
|
||||
child.invalidate();
|
||||
do_check_false(child.isValid);
|
||||
do_check_true(parent.isValid);
|
||||
|
||||
child = parent.createHandle();
|
||||
do_check_true(child.isValid);
|
||||
|
||||
do_check_true(parent.invalidate());
|
||||
do_check_false(parent.invalidate());
|
||||
parent.invalidate();
|
||||
parent.invalidate();
|
||||
do_check_false(child.isValid);
|
||||
do_check_false(parent.isValid);
|
||||
|
||||
@ -60,7 +62,7 @@ function test_local_invalidation() {
|
||||
do_check_eq(child.parent.parent, parent);
|
||||
do_check_true(child.parent.isValid);
|
||||
|
||||
do_check_true(child.parent.invalidate());
|
||||
child.parent.invalidate();
|
||||
do_check_false(child.isValid);
|
||||
do_check_true(parent.isValid);
|
||||
|
||||
@ -80,7 +82,7 @@ function test_long_parent_chain(len) {
|
||||
handle = handle.parent;
|
||||
|
||||
do_check_true(child.isValid);
|
||||
do_check_true(ancestor.invalidate());
|
||||
ancestor.invalidate();
|
||||
do_check_false(child.isValid);
|
||||
}
|
||||
|
||||
|
46
js/jetpack/tests/unit/head_jetpack.js
Normal file
46
js/jetpack/tests/unit/head_jetpack.js
Normal file
@ -0,0 +1,46 @@
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
function createJetpack(args)
|
||||
{
|
||||
var jp = Components.classes["@mozilla.org/jetpack/service;1"].
|
||||
getService(Components.interfaces.nsIJetpackService).
|
||||
createJetpack();
|
||||
|
||||
if (!args.skipRegisterCleanup)
|
||||
do_register_cleanup(function() {
|
||||
jp.destroy();
|
||||
});
|
||||
|
||||
if (!args.skipRegisterError)
|
||||
jp.registerReceiver("core:exception", function(msgName, e) {
|
||||
dump("Received exception from remote code: " + e + "\n");
|
||||
do_check_true(false);
|
||||
});
|
||||
|
||||
if (args.scriptFile)
|
||||
jp.evalScript(read_file(args.scriptFile));
|
||||
|
||||
return jp;
|
||||
}
|
||||
|
||||
const PR_RDONLY = 0x1;
|
||||
|
||||
function read_file(f)
|
||||
{
|
||||
var fis = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
fis.init(f, PR_RDONLY, 0444, Ci.nsIFileInputStream.CLOSE_ON_EOF);
|
||||
|
||||
var lis = Cc["@mozilla.org/intl/converter-input-stream;1"]
|
||||
.createInstance(Ci.nsIConverterInputStream);
|
||||
lis.init(fis, "UTF-8", 1024, 0);
|
||||
|
||||
var data = "";
|
||||
|
||||
var r = {};
|
||||
while (lis.readString(0x0FFFFFFF, r))
|
||||
data += r.value;
|
||||
|
||||
return data;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user