зеркало из https://github.com/mozilla/gecko-dev.git
Merge MC -> JM
This commit is contained in:
Коммит
2c18d8ec04
|
@ -540,6 +540,7 @@ var InspectorUI = {
|
|||
inspecting: false,
|
||||
treeLoaded: false,
|
||||
prefEnabledName: "devtools.inspector.enabled",
|
||||
isDirty: false,
|
||||
|
||||
/**
|
||||
* Toggle the inspector interface elements on or off.
|
||||
|
@ -585,7 +586,7 @@ var InspectorUI = {
|
|||
get defaultSelection()
|
||||
{
|
||||
let doc = this.win.document;
|
||||
return doc.documentElement.lastElementChild;
|
||||
return doc.documentElement ? doc.documentElement.lastElementChild : null;
|
||||
},
|
||||
|
||||
initializeTreePanel: function IUI_initializeTreePanel()
|
||||
|
@ -779,6 +780,8 @@ var InspectorUI = {
|
|||
|
||||
this.toolbar.hidden = false;
|
||||
this.inspectCmd.setAttribute("checked", true);
|
||||
|
||||
gBrowser.addProgressListener(InspectorProgressListener);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -838,6 +841,8 @@ var InspectorUI = {
|
|||
this.closing = true;
|
||||
this.toolbar.hidden = true;
|
||||
|
||||
gBrowser.removeProgressListener(InspectorProgressListener);
|
||||
|
||||
if (!aKeepStore) {
|
||||
InspectorStore.deleteStore(this.winID);
|
||||
this.win.removeEventListener("pagehide", this, true);
|
||||
|
@ -1315,6 +1320,8 @@ var InspectorUI = {
|
|||
// update the HTML tree attribute value
|
||||
this.editingContext.attrObj.innerHTML = editorInput.value;
|
||||
|
||||
this.isDirty = true;
|
||||
|
||||
// event notification
|
||||
Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.EDITOR_SAVED,
|
||||
null);
|
||||
|
@ -1741,9 +1748,122 @@ var InspectorStore = {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The InspectorProgressListener object is an nsIWebProgressListener which
|
||||
* handles onStateChange events for the inspected browser. If the user makes
|
||||
* changes to the web page and he tries to navigate away, he is prompted to
|
||||
* confirm page navigation, such that he's given the chance to prevent the loss
|
||||
* of edits.
|
||||
*/
|
||||
var InspectorProgressListener = {
|
||||
onStateChange:
|
||||
function IPL_onStateChange(aProgress, aRequest, aFlag, aStatus)
|
||||
{
|
||||
// Remove myself if the Inspector is no longer open.
|
||||
if (!InspectorUI.isTreePanelOpen) {
|
||||
gBrowser.removeProgressListener(InspectorProgressListener);
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip non-start states.
|
||||
if (!(aFlag & Ci.nsIWebProgressListener.STATE_START)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the request is about to happen in a new window, we are not concerned
|
||||
// about the request.
|
||||
if (aProgress.DOMWindow != InspectorUI.win) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (InspectorUI.isDirty) {
|
||||
this.showNotification(aRequest);
|
||||
} else {
|
||||
InspectorUI.closeInspectorUI();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Show an asynchronous notification which asks the user to confirm or cancel
|
||||
* the page navigation request.
|
||||
*
|
||||
* @param nsIRequest aRequest
|
||||
* The request initiated by the user or by the page itself.
|
||||
* @returns void
|
||||
*/
|
||||
showNotification: function IPL_showNotification(aRequest)
|
||||
{
|
||||
aRequest.suspend();
|
||||
|
||||
let notificationBox = gBrowser.getNotificationBox(InspectorUI.browser);
|
||||
let notification = notificationBox.
|
||||
getNotificationWithValue("inspector-page-navigation");
|
||||
|
||||
if (notification) {
|
||||
notificationBox.removeNotification(notification, true);
|
||||
}
|
||||
|
||||
let cancelRequest = function onCancelRequest() {
|
||||
if (aRequest) {
|
||||
aRequest.cancel(Cr.NS_BINDING_ABORTED);
|
||||
aRequest.resume(); // needed to allow the connection to be cancelled.
|
||||
aRequest = null;
|
||||
}
|
||||
};
|
||||
|
||||
let eventCallback = function onNotificationCallback(aEvent) {
|
||||
if (aEvent == "removed") {
|
||||
cancelRequest();
|
||||
}
|
||||
};
|
||||
|
||||
let buttons = [
|
||||
{
|
||||
id: "inspector.confirmNavigationAway.buttonLeave",
|
||||
label: InspectorUI.strings.
|
||||
GetStringFromName("confirmNavigationAway.buttonLeave"),
|
||||
accessKey: InspectorUI.strings.
|
||||
GetStringFromName("confirmNavigationAway.buttonLeaveAccesskey"),
|
||||
callback: function onButtonLeave() {
|
||||
if (aRequest) {
|
||||
aRequest.resume();
|
||||
aRequest = null;
|
||||
InspectorUI.closeInspectorUI();
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "inspector.confirmNavigationAway.buttonStay",
|
||||
label: InspectorUI.strings.
|
||||
GetStringFromName("confirmNavigationAway.buttonStay"),
|
||||
accessKey: InspectorUI.strings.
|
||||
GetStringFromName("confirmNavigationAway.buttonStayAccesskey"),
|
||||
callback: cancelRequest
|
||||
},
|
||||
];
|
||||
|
||||
let message = InspectorUI.strings.
|
||||
GetStringFromName("confirmNavigationAway.message");
|
||||
|
||||
notification = notificationBox.appendNotification(message,
|
||||
"inspector-page-navigation", "chrome://browser/skin/Info.png",
|
||||
notificationBox.PRIORITY_WARNING_HIGH, buttons, eventCallback);
|
||||
|
||||
// Make sure this not a transient notification, to avoid the automatic
|
||||
// transient notification removal.
|
||||
notification.persistence = -1;
|
||||
},
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//// Initializors
|
||||
//// Initializers
|
||||
|
||||
XPCOMUtils.defineLazyGetter(InspectorUI, "inspectCmd", function () {
|
||||
return document.getElementById("Tools:Inspect");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(InspectorUI, "strings", function () {
|
||||
return Services.strings.
|
||||
createBundle("chrome://browser/locale/inspector.properties");
|
||||
});
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ _BROWSER_FILES = \
|
|||
browser_inspector_registertools.js \
|
||||
browser_inspector_bug_665880.js \
|
||||
browser_inspector_editor.js \
|
||||
browser_inspector_bug_566084_location_changed.js \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let notificationBox = null;
|
||||
|
||||
function startLocationTests() {
|
||||
ok(window.InspectorUI, "InspectorUI variable exists");
|
||||
Services.obs.addObserver(runInspectorTests, INSPECTOR_NOTIFICATIONS.OPENED, null);
|
||||
InspectorUI.toggleInspectorUI();
|
||||
}
|
||||
|
||||
function runInspectorTests() {
|
||||
Services.obs.removeObserver(runInspectorTests, INSPECTOR_NOTIFICATIONS.OPENED, null);
|
||||
|
||||
let para = content.document.querySelector("p");
|
||||
ok(para, "found the paragraph element");
|
||||
is(para.textContent, "init", "paragraph content is correct");
|
||||
|
||||
ok(InspectorUI.inspecting, "Inspector is highlighting");
|
||||
ok(InspectorUI.isTreePanelOpen, "Inspector Panel is open");
|
||||
|
||||
InspectorUI.isDirty = true;
|
||||
|
||||
notificationBox = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
|
||||
notificationBox.addEventListener("AlertActive", alertActive1, false);
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", onPageLoad, true);
|
||||
|
||||
content.location = "data:text/html,<div>location change test 1 for " +
|
||||
"inspector</div><p>test1</p>";
|
||||
}
|
||||
|
||||
function alertActive1() {
|
||||
notificationBox.removeEventListener("AlertActive", alertActive1, false);
|
||||
|
||||
let notification = notificationBox.
|
||||
getNotificationWithValue("inspector-page-navigation");
|
||||
ok(notification, "found the inspector-page-navigation notification");
|
||||
|
||||
// By closing the notification it is expected that page navigation is
|
||||
// canceled.
|
||||
executeSoon(function() {
|
||||
notification.close();
|
||||
locationTest2();
|
||||
});
|
||||
}
|
||||
|
||||
function onPageLoad() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onPageLoad, true);
|
||||
|
||||
isnot(content.location.href.indexOf("test2"), -1,
|
||||
"page navigated to the correct location");
|
||||
|
||||
let para = content.document.querySelector("p");
|
||||
ok(para, "found the paragraph element, third time");
|
||||
is(para.textContent, "test2", "paragraph content is correct");
|
||||
|
||||
ok(!InspectorUI.inspecting, "Inspector is not highlighting");
|
||||
ok(!InspectorUI.isTreePanelOpen, "Inspector Panel is not open");
|
||||
|
||||
testEnd();
|
||||
}
|
||||
|
||||
function locationTest2() {
|
||||
// Location did not change.
|
||||
let para = content.document.querySelector("p");
|
||||
ok(para, "found the paragraph element, second time");
|
||||
is(para.textContent, "init", "paragraph content is correct");
|
||||
|
||||
ok(InspectorUI.inspecting, "Inspector is highlighting");
|
||||
ok(InspectorUI.isTreePanelOpen, "Inspector Panel is open");
|
||||
|
||||
notificationBox.addEventListener("AlertActive", alertActive2, false);
|
||||
|
||||
content.location = "data:text/html,<div>location change test 2 for " +
|
||||
"inspector</div><p>test2</p>";
|
||||
}
|
||||
|
||||
function alertActive2() {
|
||||
notificationBox.removeEventListener("AlertActive", alertActive2, false);
|
||||
|
||||
let notification = notificationBox.
|
||||
getNotificationWithValue("inspector-page-navigation");
|
||||
ok(notification, "found the inspector-page-navigation notification");
|
||||
|
||||
let buttons = notification.querySelectorAll("button");
|
||||
let buttonLeave = null;
|
||||
for (let i = 0; i < buttons.length; i++) {
|
||||
if (buttons[i].buttonInfo.id == "inspector.confirmNavigationAway.buttonLeave") {
|
||||
buttonLeave = buttons[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ok(buttonLeave, "the Leave page button was found");
|
||||
|
||||
// Accept page navigation.
|
||||
executeSoon(function(){
|
||||
buttonLeave.doCommand();
|
||||
});
|
||||
}
|
||||
|
||||
function testEnd() {
|
||||
notificationBox = null;
|
||||
InspectorUI.isDirty = false;
|
||||
gBrowser.removeCurrentTab();
|
||||
executeSoon(finish);
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onBrowserLoad() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onBrowserLoad, true);
|
||||
waitForFocus(startLocationTests, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,<div>location change tests for " +
|
||||
"inspector.</div><p>init</p>";
|
||||
}
|
|
@ -280,7 +280,7 @@ var Scratchpad = {
|
|||
scriptError.initWithWindowID(ex.message + "\n" + ex.stack, ex.fileName,
|
||||
"", ex.lineNumber, 0, scriptError.errorFlag,
|
||||
"content javascript",
|
||||
this.getWindowId(contentWindow));
|
||||
this.getInnerWindowId(contentWindow));
|
||||
|
||||
Services.console.logMessage(scriptError);
|
||||
}
|
||||
|
@ -633,16 +633,16 @@ var Scratchpad = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Gets the ID of the outer window of the given DOM window object.
|
||||
* Gets the ID of the inner window of the given DOM window object.
|
||||
*
|
||||
* @param nsIDOMWindow aWindow
|
||||
* @return integer
|
||||
* the outer window ID
|
||||
* the inner window ID
|
||||
*/
|
||||
getWindowId: function SP_getWindowId(aWindow)
|
||||
getInnerWindowId: function SP_getInnerWindowId(aWindow)
|
||||
{
|
||||
return aWindow.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
|
||||
getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -90,7 +90,7 @@ XPCOMUtils.defineLazyGetter(this, "PropertyPanel", function () {
|
|||
XPCOMUtils.defineLazyGetter(this, "AutocompletePopup", function () {
|
||||
var obj = {};
|
||||
try {
|
||||
Cu.import("resource://gre/modules/AutocompletePopup.jsm", obj);
|
||||
Cu.import("resource:///modules/AutocompletePopup.jsm", obj);
|
||||
}
|
||||
catch (err) {
|
||||
Cu.reportError(err);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
// Tests that document.body autocompletes in the web console.
|
||||
|
||||
Cu.import("resource://gre/modules/PropertyPanel.jsm");
|
||||
Cu.import("resource:///modules/PropertyPanel.jsm");
|
||||
|
||||
function test() {
|
||||
addTab("data:text/html,Web Console autocompletion bug in document.body");
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
Cu.import("resource://gre/modules/HUDService.jsm");
|
||||
Cu.import("resource:///modules/HUDService.jsm");
|
||||
|
||||
function log(aMsg)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# LOCALIZATION NOTE (confirmNavigationAway): Used in the Inspector tool, when
|
||||
# the user tries to navigate away from a web page, to confirm the change of
|
||||
# page.
|
||||
confirmNavigationAway.message=Leaving this page will close the Inspector and the changes you have made will be lost.
|
||||
confirmNavigationAway.buttonLeave=Leave Page
|
||||
confirmNavigationAway.buttonLeaveAccesskey=L
|
||||
confirmNavigationAway.buttonStay=Stay on Page
|
||||
confirmNavigationAway.buttonStayAccesskey=S
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
locale/browser/browser.properties (%chrome/browser/browser.properties)
|
||||
locale/browser/scratchpad.properties (%chrome/browser/scratchpad.properties)
|
||||
locale/browser/scratchpad.dtd (%chrome/browser/scratchpad.dtd)
|
||||
locale/browser/inspector.properties (%chrome/browser/inspector.properties)
|
||||
locale/browser/openLocation.dtd (%chrome/browser/openLocation.dtd)
|
||||
locale/browser/openLocation.properties (%chrome/browser/openLocation.properties)
|
||||
* locale/browser/pageInfo.dtd (%chrome/browser/pageInfo.dtd)
|
||||
|
|
|
@ -743,8 +743,8 @@ public:
|
|||
* @param aColumnNumber Column number within resource containing error.
|
||||
* @param aErrorFlags See nsIScriptError.
|
||||
* @param aCategory Name of module reporting error.
|
||||
* @param [aWindowId=0] (Optional) The window ID of the outer window the
|
||||
* message originates from.
|
||||
* @param [aInnerWindowId=0] (Optional) The window ID of the inner window
|
||||
* the message originates from.
|
||||
*/
|
||||
enum PropertiesFile {
|
||||
eCSS_PROPERTIES,
|
||||
|
@ -769,7 +769,7 @@ public:
|
|||
PRUint32 aColumnNumber,
|
||||
PRUint32 aErrorFlags,
|
||||
const char *aCategory,
|
||||
PRUint64 aWindowId = 0);
|
||||
PRUint64 aInnerWindowId = 0);
|
||||
|
||||
/**
|
||||
* Report a localized error message to the error console.
|
||||
|
|
|
@ -720,6 +720,15 @@ public:
|
|||
return window ? window->WindowID() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the inner window ID.
|
||||
*/
|
||||
PRUint64 InnerWindowID()
|
||||
{
|
||||
nsPIDOMWindow *window = GetInnerWindow();
|
||||
return window ? window->WindowID() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the script loader for this document
|
||||
*/
|
||||
|
|
|
@ -2733,7 +2733,7 @@ nsContentUtils::ReportToConsole(PropertiesFile aFile,
|
|||
PRUint32 aColumnNumber,
|
||||
PRUint32 aErrorFlags,
|
||||
const char *aCategory,
|
||||
PRUint64 aWindowId)
|
||||
PRUint64 aInnerWindowId)
|
||||
{
|
||||
NS_ASSERTION((aParams && aParamsLength) || (!aParams && !aParamsLength),
|
||||
"Supply either both parameters and their number or no"
|
||||
|
@ -2767,7 +2767,8 @@ nsContentUtils::ReportToConsole(PropertiesFile aFile,
|
|||
NS_ConvertUTF8toUTF16(spec).get(), // file name
|
||||
aSourceLine.get(),
|
||||
aLineNumber, aColumnNumber,
|
||||
aErrorFlags, aCategory, aWindowId);
|
||||
aErrorFlags, aCategory,
|
||||
aInnerWindowId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIScriptError> logError = do_QueryInterface(errorObject);
|
||||
|
@ -2788,17 +2789,17 @@ nsContentUtils::ReportToConsole(PropertiesFile aFile,
|
|||
nsIDocument* aDocument)
|
||||
{
|
||||
nsIURI* uri = aURI;
|
||||
PRUint64 windowID = 0;
|
||||
PRUint64 innerWindowID = 0;
|
||||
if (aDocument) {
|
||||
if (!uri) {
|
||||
uri = aDocument->GetDocumentURI();
|
||||
}
|
||||
windowID = aDocument->OuterWindowID();
|
||||
innerWindowID = aDocument->InnerWindowID();
|
||||
}
|
||||
|
||||
return ReportToConsole(aFile, aMessageName, aParams, aParamsLength, uri,
|
||||
aSourceLine, aLineNumber, aColumnNumber, aErrorFlags,
|
||||
aCategory, windowID);
|
||||
aCategory, innerWindowID);
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
|
|
@ -85,7 +85,7 @@ nsEventSource::nsEventSource() :
|
|||
mLastConvertionResult(NS_OK),
|
||||
mReadyState(nsIEventSource::CONNECTING),
|
||||
mScriptLine(0),
|
||||
mWindowID(0)
|
||||
mInnerWindowID(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -253,7 +253,7 @@ nsEventSource::Init(nsIPrincipal* aPrincipal,
|
|||
mScriptFile.AssignASCII(filename);
|
||||
}
|
||||
|
||||
mWindowID = nsJSUtils::GetCurrentlyRunningCodeWindowID(cx);
|
||||
mInnerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
|
||||
}
|
||||
|
||||
// Get the load group for the page. When requesting we'll add ourselves to it.
|
||||
|
@ -1072,7 +1072,7 @@ nsEventSource::PrintErrorOnConsole(const char *aBundleURI,
|
|||
nsnull,
|
||||
mScriptLine, 0,
|
||||
nsIScriptError::errorFlag,
|
||||
"Event Source", mWindowID);
|
||||
"Event Source", mInnerWindowID);
|
||||
|
||||
// print the error message directly to the JS console
|
||||
nsCOMPtr<nsIScriptError> logError = do_QueryInterface(errObj);
|
||||
|
|
|
@ -252,12 +252,12 @@ protected:
|
|||
// Event Source owner information:
|
||||
// - the script file name
|
||||
// - source code line number where the Event Source object was constructed.
|
||||
// - the window ID of the outer window where the script lives. Note that this
|
||||
// may not be the same as the Event Source owner window.
|
||||
// - the ID of the inner window where the script lives. Note that this may not
|
||||
// be the same as the Event Source owner window.
|
||||
// These attributes are used for error reporting.
|
||||
nsString mScriptFile;
|
||||
PRUint32 mScriptLine;
|
||||
PRUint64 mWindowID;
|
||||
PRUint64 mInnerWindowID;
|
||||
|
||||
private:
|
||||
nsEventSource(const nsEventSource& x); // prevent bad usage
|
||||
|
|
|
@ -357,7 +357,7 @@ nsWebSocketEstablishedConnection::PrintErrorOnConsole(const char *aBundleURI,
|
|||
NS_ConvertUTF8toUTF16(mOwner->GetScriptFile()).get(),
|
||||
nsnull,
|
||||
mOwner->GetScriptLine(), 0, nsIScriptError::errorFlag,
|
||||
"Web Socket", mOwner->WindowID()
|
||||
"Web Socket", mOwner->InnerWindowID()
|
||||
);
|
||||
|
||||
// print the error message directly to the JS console
|
||||
|
@ -631,7 +631,7 @@ nsWebSocket::nsWebSocket() : mKeepingAlive(PR_FALSE),
|
|||
mReadyState(nsIMozWebSocket::CONNECTING),
|
||||
mOutgoingBufferedAmount(0),
|
||||
mScriptLine(0),
|
||||
mWindowID(0)
|
||||
mInnerWindowID(0)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
|
||||
}
|
||||
|
@ -1428,7 +1428,7 @@ nsWebSocket::Init(nsIPrincipal* aPrincipal,
|
|||
}
|
||||
}
|
||||
|
||||
mWindowID = nsJSUtils::GetCurrentlyRunningCodeWindowID(cx);
|
||||
mInnerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
|
||||
}
|
||||
|
||||
// parses the url
|
||||
|
|
|
@ -99,7 +99,7 @@ public:
|
|||
// Determine if preferences allow WebSocket
|
||||
static PRBool PrefEnabled();
|
||||
|
||||
const PRUint64 WindowID() const { return mWindowID; }
|
||||
const PRUint64 InnerWindowID() const { return mInnerWindowID; }
|
||||
const nsCString& GetScriptFile() const { return mScriptFile; }
|
||||
const PRUint32 GetScriptLine() const { return mScriptLine; }
|
||||
|
||||
|
@ -164,12 +164,12 @@ protected:
|
|||
// Web Socket owner information:
|
||||
// - the script file name, UTF8 encoded.
|
||||
// - source code line number where the Web Socket object was constructed.
|
||||
// - the window ID of the outer window where the script lives. Note that this
|
||||
// may not be the same as the Web Socket owner window.
|
||||
// - the ID of the inner window where the script lives. Note that this may not
|
||||
// be the same as the Web Socket owner window.
|
||||
// These attributes are used for error reporting.
|
||||
nsCString mScriptFile;
|
||||
PRUint32 mScriptLine;
|
||||
PRUint64 mWindowID;
|
||||
PRUint64 mInnerWindowID;
|
||||
|
||||
private:
|
||||
nsWebSocket(const nsWebSocket& x); // prevent bad usage
|
||||
|
|
|
@ -382,8 +382,8 @@ nsXMLDocument::Load(const nsAString& aUrl, PRBool *aReturn)
|
|||
nsnull, 0, 0, nsIScriptError::warningFlag,
|
||||
"DOM",
|
||||
callingDoc ?
|
||||
callingDoc->OuterWindowID() :
|
||||
this->OuterWindowID());
|
||||
callingDoc->InnerWindowID() :
|
||||
this->InnerWindowID());
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ let Cc = Components.classes;
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm");
|
||||
|
||||
function ConsoleAPI() {}
|
||||
ConsoleAPI.prototype = {
|
||||
|
@ -53,12 +54,16 @@ ConsoleAPI.prototype = {
|
|||
|
||||
// nsIDOMGlobalPropertyInitializer
|
||||
init: function CA_init(aWindow) {
|
||||
let id;
|
||||
let outerID;
|
||||
let innerID;
|
||||
try {
|
||||
id = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.outerWindowID;
|
||||
} catch (ex) {
|
||||
let windowUtils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
outerID = windowUtils.outerWindowID;
|
||||
innerID = windowUtils.currentInnerWindowID;
|
||||
}
|
||||
catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
|
||||
|
@ -66,26 +71,26 @@ ConsoleAPI.prototype = {
|
|||
let chromeObject = {
|
||||
// window.console API
|
||||
log: function CA_log() {
|
||||
self.notifyObservers(id, "log", arguments);
|
||||
self.notifyObservers(outerID, innerID, "log", arguments);
|
||||
},
|
||||
info: function CA_info() {
|
||||
self.notifyObservers(id, "info", arguments);
|
||||
self.notifyObservers(outerID, innerID, "info", arguments);
|
||||
},
|
||||
warn: function CA_warn() {
|
||||
self.notifyObservers(id, "warn", arguments);
|
||||
self.notifyObservers(outerID, innerID, "warn", arguments);
|
||||
},
|
||||
error: function CA_error() {
|
||||
self.notifyObservers(id, "error", arguments);
|
||||
self.notifyObservers(outerID, innerID, "error", arguments);
|
||||
},
|
||||
debug: function CA_debug() {
|
||||
self.notifyObservers(id, "log", arguments);
|
||||
self.notifyObservers(outerID, innerID, "log", arguments);
|
||||
},
|
||||
trace: function CA_trace() {
|
||||
self.notifyObservers(id, "trace", self.getStackTrace());
|
||||
self.notifyObservers(outerID, innerID, "trace", self.getStackTrace());
|
||||
},
|
||||
// Displays an interactive listing of all the properties of an object.
|
||||
dir: function CA_dir() {
|
||||
self.notifyObservers(id, "dir", arguments);
|
||||
self.notifyObservers(outerID, innerID, "dir", arguments);
|
||||
},
|
||||
__exposedProps__: {
|
||||
log: "r",
|
||||
|
@ -125,17 +130,29 @@ ConsoleAPI.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Notify all observers of any console API call
|
||||
* Notify all observers of any console API call.
|
||||
*
|
||||
* @param number aOuterWindowID
|
||||
* The outer window ID from where the message came from.
|
||||
* @param number aInnerWindowID
|
||||
* The inner window ID from where the message came from.
|
||||
* @param string aLevel
|
||||
* The message level.
|
||||
* @param mixed aArguments
|
||||
* The arguments given to the console API call.
|
||||
**/
|
||||
notifyObservers: function CA_notifyObservers(aID, aLevel, aArguments) {
|
||||
if (!aID)
|
||||
notifyObservers:
|
||||
function CA_notifyObservers(aOuterWindowID, aInnerWindowID, aLevel, aArguments) {
|
||||
if (!aOuterWindowID) {
|
||||
return;
|
||||
}
|
||||
|
||||
let stack = this.getStackTrace();
|
||||
// Skip the first frame since it contains an internal call.
|
||||
let frame = stack[1];
|
||||
let consoleEvent = {
|
||||
ID: aID,
|
||||
ID: aOuterWindowID,
|
||||
innerID: aInnerWindowID,
|
||||
level: aLevel,
|
||||
filename: frame.filename,
|
||||
lineNumber: frame.lineNumber,
|
||||
|
@ -145,8 +162,10 @@ ConsoleAPI.prototype = {
|
|||
|
||||
consoleEvent.wrappedJSObject = consoleEvent;
|
||||
|
||||
ConsoleAPIStorage.recordEvent(aInnerWindowID, consoleEvent);
|
||||
|
||||
Services.obs.notifyObservers(consoleEvent,
|
||||
"console-api-log-event", aID);
|
||||
"console-api-log-event", aOuterWindowID);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
/* ***** 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 ConsoleStorageService code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* David Dahl <ddahl@mozilla.com> (Original Author)
|
||||
*
|
||||
* 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 Cu = Components.utils;
|
||||
let Ci = Components.interfaces;
|
||||
let Cc = Components.classes;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const STORAGE_MAX_EVENTS = 200;
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gPrivBrowsing", function () {
|
||||
// private browsing may not be available in some Gecko Apps
|
||||
try {
|
||||
return Cc["@mozilla.org/privatebrowsing;1"].getService(Ci.nsIPrivateBrowsingService);
|
||||
}
|
||||
catch (ex) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
var EXPORTED_SYMBOLS = ["ConsoleAPIStorage"];
|
||||
|
||||
var _consoleStorage = {};
|
||||
|
||||
/**
|
||||
* The ConsoleAPIStorage is meant to cache window.console API calls for later
|
||||
* reuse by other components when needed. For example, the Web Console code can
|
||||
* display the cached messages when it opens for the active tab.
|
||||
*
|
||||
* ConsoleAPI messages are stored as they come from the ConsoleAPI code, with
|
||||
* all their properties. They are kept around until the inner window object that
|
||||
* created the messages is destroyed. Messages are indexed by the inner window
|
||||
* ID.
|
||||
*
|
||||
* Usage:
|
||||
* Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm");
|
||||
*
|
||||
* // Get the cached events array for the window you want (use the inner
|
||||
* // window ID).
|
||||
* let events = ConsoleAPIStorage.getEvents(innerWindowID);
|
||||
* events.forEach(function(event) { ... });
|
||||
*
|
||||
* // Clear the events for the given inner window ID.
|
||||
* ConsoleAPIStorage.clearEvents(innerWindowID);
|
||||
*/
|
||||
var ConsoleAPIStorage = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
|
||||
|
||||
/** @private */
|
||||
observe: function CS_observe(aSubject, aTopic, aData)
|
||||
{
|
||||
if (aTopic == "xpcom-shutdown") {
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
Services.obs.removeObserver(this, "memory-pressure");
|
||||
delete _consoleStorage;
|
||||
}
|
||||
else if (aTopic == "inner-window-destroyed") {
|
||||
let innerWindowID = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
this.clearEvents(innerWindowID);
|
||||
}
|
||||
else if (aTopic == "memory-pressure") {
|
||||
if (aData == "low-memory") {
|
||||
this.clearEvents();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** @private */
|
||||
init: function CS_init()
|
||||
{
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
Services.obs.addObserver(this, "memory-pressure", false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the events array by inner window ID.
|
||||
*
|
||||
* @param string aId
|
||||
* The inner window ID for which you want to get the array of cached
|
||||
* events.
|
||||
* @returns array
|
||||
* The array of cached events for the given window.
|
||||
*/
|
||||
getEvents: function CS_getEvents(aId)
|
||||
{
|
||||
return _consoleStorage[aId] || [];
|
||||
},
|
||||
|
||||
/**
|
||||
* Record an event associated with the given window ID.
|
||||
*
|
||||
* @param string aWindowID
|
||||
* The ID of the inner window for which the event occurred.
|
||||
* @param object aEvent
|
||||
* A JavaScript object you want to store.
|
||||
*/
|
||||
recordEvent: function CS_recordEvent(aWindowID, aEvent)
|
||||
{
|
||||
let ID = parseInt(aWindowID);
|
||||
if (isNaN(ID)) {
|
||||
throw new Error("Invalid window ID argument");
|
||||
}
|
||||
|
||||
if (gPrivBrowsing && gPrivBrowsing.privateBrowsingEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_consoleStorage[ID]) {
|
||||
_consoleStorage[ID] = [];
|
||||
}
|
||||
let storage = _consoleStorage[ID];
|
||||
storage.push(aEvent);
|
||||
|
||||
// truncate
|
||||
if (storage.length > STORAGE_MAX_EVENTS) {
|
||||
storage.shift();
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(aEvent, "console-storage-cache-event", ID);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear storage data for the given window.
|
||||
*
|
||||
* @param string [aId]
|
||||
* Optional, the inner window ID for which you want to clear the
|
||||
* messages. If this is not specified all of the cached messages are
|
||||
* cleared, from all window objects.
|
||||
*/
|
||||
clearEvents: function CS_clearEvents(aId)
|
||||
{
|
||||
if (aId != null) {
|
||||
delete _consoleStorage[aId];
|
||||
}
|
||||
else {
|
||||
_consoleStorage = {};
|
||||
Services.obs.notifyObservers(null, "console-storage-reset", null);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
ConsoleAPIStorage.init();
|
|
@ -52,6 +52,9 @@ EXTRA_PP_COMPONENTS = \
|
|||
ConsoleAPI.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = ConsoleAPIStorage.jsm \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIEntropyCollector.idl \
|
||||
nsIScriptChannel.idl \
|
||||
|
|
|
@ -1702,7 +1702,7 @@ PrintWarningOnConsole(JSContext *cx, const char *stringBundleProperty)
|
|||
0, // column for error is not available
|
||||
nsIScriptError::warningFlag,
|
||||
"DOM:HTML",
|
||||
nsJSUtils::GetCurrentlyRunningCodeWindowID(cx));
|
||||
nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx));
|
||||
|
||||
if (NS_SUCCEEDED(rv)){
|
||||
nsCOMPtr<nsIScriptError> logError = do_QueryInterface(scriptError);
|
||||
|
|
|
@ -540,6 +540,11 @@ public:
|
|||
return outerWindow && !outerWindow->IsInnerWindow() ? outerWindow : nsnull;
|
||||
}
|
||||
|
||||
static nsGlobalWindow* GetInnerWindowWithId(PRUint64 aInnerWindowID) {
|
||||
nsGlobalWindow* innerWindow = sWindowsById->Get(aInnerWindowID);
|
||||
return innerWindow && innerWindow->IsInnerWindow() ? innerWindow : nsnull;
|
||||
}
|
||||
|
||||
static bool HasIndexedDBSupport();
|
||||
|
||||
static bool HasPerformanceSupport();
|
||||
|
|
|
@ -267,11 +267,11 @@ public:
|
|||
const nsAString& aFileName,
|
||||
const nsAString& aSourceLine,
|
||||
PRBool aDispatchEvent,
|
||||
PRUint64 aWindowID)
|
||||
PRUint64 aInnerWindowID)
|
||||
: mScriptGlobal(aScriptGlobal), mLineNr(aLineNr), mColumn(aColumn),
|
||||
mFlags(aFlags), mErrorMsg(aErrorMsg), mFileName(aFileName),
|
||||
mSourceLine(aSourceLine), mDispatchEvent(aDispatchEvent),
|
||||
mWindowID(aWindowID)
|
||||
mInnerWindowID(aInnerWindowID)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
|
@ -364,7 +364,7 @@ public:
|
|||
rv = error2->InitWithWindowID(mErrorMsg.get(), mFileName.get(),
|
||||
mSourceLine.get(),
|
||||
mLineNr, mColumn, mFlags,
|
||||
category, mWindowID);
|
||||
category, mInnerWindowID);
|
||||
} else {
|
||||
rv = errorObject->Init(mErrorMsg.get(), mFileName.get(),
|
||||
mSourceLine.get(),
|
||||
|
@ -393,7 +393,7 @@ public:
|
|||
nsString mFileName;
|
||||
nsString mSourceLine;
|
||||
PRBool mDispatchEvent;
|
||||
PRUint64 mWindowID;
|
||||
PRUint64 mInnerWindowID;
|
||||
|
||||
static PRBool sHandlingScriptError;
|
||||
};
|
||||
|
@ -474,13 +474,19 @@ NS_ScriptErrorReporter(JSContext *cx,
|
|||
nsAutoString sourceLine;
|
||||
sourceLine.Assign(reinterpret_cast<const PRUnichar*>(report->uclinebuf));
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(globalObject);
|
||||
PRUint64 windowID = win ? win->WindowID() : 0;
|
||||
PRUint64 innerWindowID = 0;
|
||||
if (win) {
|
||||
nsCOMPtr<nsPIDOMWindow> innerWin = win->GetCurrentInnerWindow();
|
||||
if (innerWin) {
|
||||
innerWindowID = innerWin->WindowID();
|
||||
}
|
||||
}
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new ScriptErrorEvent(globalObject, report->lineno,
|
||||
report->uctokenptr - report->uclinebuf,
|
||||
report->flags, msg, fileName, sourceLine,
|
||||
report->errorNumber != JSMSG_OUT_OF_MEMORY,
|
||||
windowID));
|
||||
innerWindowID));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -163,12 +163,12 @@ nsJSUtils::GetDynamicScriptContext(JSContext *aContext)
|
|||
}
|
||||
|
||||
PRUint64
|
||||
nsJSUtils::GetCurrentlyRunningCodeWindowID(JSContext *aContext)
|
||||
nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(JSContext *aContext)
|
||||
{
|
||||
if (!aContext)
|
||||
return 0;
|
||||
|
||||
PRUint64 windowID = 0;
|
||||
PRUint64 innerWindowID = 0;
|
||||
|
||||
JSObject *jsGlobal = JS_GetGlobalForScopeChain(aContext);
|
||||
if (jsGlobal) {
|
||||
|
@ -177,10 +177,10 @@ nsJSUtils::GetCurrentlyRunningCodeWindowID(JSContext *aContext)
|
|||
if (scriptGlobal) {
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(scriptGlobal);
|
||||
if (win)
|
||||
windowID = win->GetOuterWindow()->WindowID();
|
||||
innerWindowID = win->WindowID();
|
||||
}
|
||||
}
|
||||
|
||||
return windowID;
|
||||
return innerWindowID;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,14 +71,14 @@ public:
|
|||
static nsIScriptContext *GetDynamicScriptContext(JSContext *aContext);
|
||||
|
||||
/**
|
||||
* Retrieve the outer window ID based on the given JSContext.
|
||||
* Retrieve the inner window ID based on the given JSContext.
|
||||
*
|
||||
* @param JSContext aContext
|
||||
* The JSContext from which you want to find the outer window ID.
|
||||
* The JSContext from which you want to find the inner window ID.
|
||||
*
|
||||
* @returns PRUint64 the outer window ID.
|
||||
* @returns PRUint64 the inner window ID.
|
||||
*/
|
||||
static PRUint64 GetCurrentlyRunningCodeWindowID(JSContext *aContext);
|
||||
static PRUint64 GetCurrentlyRunningCodeInnerWindowID(JSContext *aContext);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -50,6 +50,8 @@ _BROWSER_FILES = \
|
|||
browser_autofocus_background.js \
|
||||
browser_ConsoleAPITests.js \
|
||||
test-console-api.html \
|
||||
browser_ConsoleStorageAPITests.js \
|
||||
browser_ConsoleStoragePBTest.js \
|
||||
browser_autofocus_preference.js \
|
||||
browser_popup_blocker_save_open_panel.js \
|
||||
$(NULL)
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const TEST_URI = "http://example.com/browser/dom/tests/browser/test-console-api.html";
|
||||
const TEST_URI_NAV = "http://example.com/browser/dom/tests/browser/";
|
||||
|
||||
Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm");
|
||||
|
||||
var apiCallCount;
|
||||
|
||||
var ConsoleObserver = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
|
||||
|
||||
init: function CO_init()
|
||||
{
|
||||
Services.obs.addObserver(this, "console-storage-cache-event", false);
|
||||
apiCallCount = 0;
|
||||
},
|
||||
|
||||
observe: function CO_observe(aSubject, aTopic, aData)
|
||||
{
|
||||
if (aTopic == "console-storage-cache-event") {
|
||||
apiCallCount ++;
|
||||
if (apiCallCount == 4) {
|
||||
try {
|
||||
var tab = gBrowser.selectedTab;
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
let win = XPCNativeWrapper.unwrap(browser.contentWindow);
|
||||
let windowID = getWindowId(win);
|
||||
let messages = ConsoleAPIStorage.getEvents(windowID);
|
||||
|
||||
ok(messages.length >= 4, "Some messages found in the storage service");
|
||||
|
||||
ConsoleAPIStorage.clearEvents();
|
||||
messages = ConsoleAPIStorage.getEvents(windowID);
|
||||
ok(messages.length == 0, "Cleared Storage, no events found");
|
||||
|
||||
// remove the observer so we don't trigger this test again
|
||||
Services.obs.removeObserver(this, "console-storage-cache-event");
|
||||
|
||||
// make sure a closed window's events are in fact removed from the
|
||||
// storage cache
|
||||
win.console.log("adding a new event");
|
||||
|
||||
// close the window - the storage cache should now be empty
|
||||
gBrowser.removeTab(tab, {animate: false});
|
||||
|
||||
window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils).garbageCollect();
|
||||
executeSoon(function (){
|
||||
// use the old windowID again to see if we have any stray cached messages
|
||||
messages = ConsoleAPIStorage.getEvents(windowID);
|
||||
ok(messages.length == 0, "0 events found, tab close is clearing the cache");
|
||||
finish();
|
||||
});
|
||||
} catch (ex) {
|
||||
dump(ex + "\n\n\n");
|
||||
dump(ex.stack + "\n\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function tearDown()
|
||||
{
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
}
|
||||
|
||||
function test()
|
||||
{
|
||||
registerCleanupFunction(tearDown);
|
||||
|
||||
ConsoleObserver.init();
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
var tab = gBrowser.addTab(TEST_URI);
|
||||
gBrowser.selectedTab = tab;
|
||||
var browser = gBrowser.selectedBrowser;
|
||||
browser.addEventListener("DOMContentLoaded", function onLoad(event) {
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
executeSoon(function test_executeSoon() {
|
||||
var contentWin = browser.contentWindow;
|
||||
|
||||
let win = XPCNativeWrapper.unwrap(contentWin);
|
||||
|
||||
win.console.log("this", "is", "a", "log message");
|
||||
win.console.info("this", "is", "a", "info message");
|
||||
win.console.warn("this", "is", "a", "warn message");
|
||||
win.console.error("this", "is", "a", "error message");
|
||||
});
|
||||
}, false);
|
||||
}
|
||||
|
||||
function getWindowId(aWindow)
|
||||
{
|
||||
return aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.currentInnerWindowID;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
try {
|
||||
var pb = Cc["@mozilla.org/privatebrowsing;1"].getService(Ci.nsIPrivateBrowsingService);
|
||||
} catch (ex) {
|
||||
ok(true, "nothing to do here, PB service doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
var CSS = {};
|
||||
Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm", CSS);
|
||||
|
||||
function checkStorageOccurs(shouldOccur) {
|
||||
let win = XPCNativeWrapper.unwrap(browser.contentWindow);
|
||||
let innerID = getInnerWindowId(win);
|
||||
|
||||
let beforeEvents = CSS.ConsoleAPIStorage.getEvents(innerID);
|
||||
win.console.log("foo bar baz (private: " + !shouldOccur + ")");
|
||||
|
||||
let afterEvents = CSS.ConsoleAPIStorage.getEvents(innerID);
|
||||
|
||||
is(beforeEvents.length == afterEvents.length - 1,
|
||||
shouldOccur, "storage should" + (shouldOccur ? "" : "n't") + " occur");
|
||||
}
|
||||
|
||||
function pbObserver(aSubject, aTopic, aData) {
|
||||
if (aData == "enter") {
|
||||
checkStorageOccurs(false);
|
||||
|
||||
executeSoon(function () { pb.privateBrowsingEnabled = false; });
|
||||
} else if (aData == "exit") {
|
||||
executeSoon(finish);
|
||||
}
|
||||
}
|
||||
|
||||
const TEST_URI = "http://example.com/browser/dom/tests/browser/test-console-api.html";
|
||||
var tab = gBrowser.selectedTab = gBrowser.addTab(TEST_URI);
|
||||
var browser = gBrowser.selectedBrowser;
|
||||
|
||||
Services.obs.addObserver(pbObserver, "private-browsing", false);
|
||||
|
||||
const PB_KEEP_SESSION_PREF = "browser.privatebrowsing.keep_current_session";
|
||||
Services.prefs.setBoolPref(PB_KEEP_SESSION_PREF, true);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
Services.obs.removeObserver(pbObserver, "private-browsing");
|
||||
|
||||
if (Services.prefs.prefHasUserValue(PB_KEEP_SESSION_PREF))
|
||||
Services.prefs.clearUserPref(PB_KEEP_SESSION_PREF);
|
||||
});
|
||||
|
||||
browser.addEventListener("DOMContentLoaded", function onLoad(event) {
|
||||
if (browser.currentURI.spec != TEST_URI)
|
||||
return;
|
||||
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
|
||||
checkStorageOccurs(true);
|
||||
|
||||
pb.privateBrowsingEnabled = true;
|
||||
}, false);
|
||||
}
|
||||
|
||||
function getInnerWindowId(aWindow) {
|
||||
return aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.currentInnerWindowID;
|
||||
}
|
|
@ -895,11 +895,11 @@ public:
|
|||
aWorkerPrivate->AssertInnerWindowIsCorrect();
|
||||
}
|
||||
|
||||
PRUint64 windowId;
|
||||
PRUint64 innerWindowId;
|
||||
|
||||
WorkerPrivate* parent = aWorkerPrivate->GetParent();
|
||||
if (parent) {
|
||||
windowId = 0;
|
||||
innerWindowId = 0;
|
||||
}
|
||||
else {
|
||||
AssertIsOnMainThread();
|
||||
|
@ -909,13 +909,13 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
windowId = aWorkerPrivate->GetOuterWindowId();
|
||||
innerWindowId = aWorkerPrivate->GetInnerWindowId();
|
||||
}
|
||||
|
||||
return ReportErrorRunnable::ReportError(aCx, parent, true, target, mMessage,
|
||||
mFilename, mLine, mLineNumber,
|
||||
mColumnNumber, mFlags,
|
||||
mErrorNumber, windowId);
|
||||
mErrorNumber, innerWindowId);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -923,7 +923,7 @@ public:
|
|||
bool aFireAtScope, JSObject* aTarget, const nsString& aMessage,
|
||||
const nsString& aFilename, const nsString& aLine,
|
||||
PRUint32 aLineNumber, PRUint32 aColumnNumber, PRUint32 aFlags,
|
||||
PRUint32 aErrorNumber, PRUint64 aWindowId)
|
||||
PRUint32 aErrorNumber, PRUint64 aInnerWindowId)
|
||||
{
|
||||
if (aWorkerPrivate) {
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
@ -1030,7 +1030,7 @@ public:
|
|||
aLine.get(), aLineNumber,
|
||||
aColumnNumber, aFlags,
|
||||
"Web Worker",
|
||||
aWindowId))) {
|
||||
aInnerWindowId))) {
|
||||
consoleMessage = do_QueryInterface(scriptError);
|
||||
NS_ASSERTION(consoleMessage, "This should never fail!");
|
||||
}
|
||||
|
@ -1932,10 +1932,10 @@ WorkerPrivateParent<Derived>::PostMessage(JSContext* aCx, jsval aMessage)
|
|||
|
||||
template <class Derived>
|
||||
PRUint64
|
||||
WorkerPrivateParent<Derived>::GetOuterWindowId()
|
||||
WorkerPrivateParent<Derived>::GetInnerWindowId()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
return mDocument->OuterWindowID();
|
||||
return mDocument->InnerWindowID();
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
|
|
|
@ -299,7 +299,7 @@ public:
|
|||
PostMessage(JSContext* aCx, jsval aMessage);
|
||||
|
||||
PRUint64
|
||||
GetOuterWindowId();
|
||||
GetInnerWindowId();
|
||||
|
||||
void
|
||||
UpdateJSContextOptions(JSContext* aCx, PRUint32 aOptions);
|
||||
|
|
|
@ -96,15 +96,23 @@ interface nsIScriptError : nsIConsoleMessage
|
|||
* An interface that nsIScriptError objects can implement to allow
|
||||
* them to be initialized with a window id.
|
||||
*/
|
||||
[scriptable, uuid(35cd0f6a-f5bb-497a-ba83-9c8d089b52cd)]
|
||||
[scriptable, uuid(4472646b-c928-4d76-9e7c-6b91da7f24cc)]
|
||||
interface nsIScriptError2 : nsISupports {
|
||||
/* Get the window id this was initialized with. Zero will be
|
||||
returned if init() was used instead of initWithWindowId(). */
|
||||
returned if init() was used instead of initWithWindowID(). */
|
||||
readonly attribute unsigned long long outerWindowID;
|
||||
|
||||
/* Get the inner window id this was initialized with. Zero will be
|
||||
returned if init() was used instead of initWithWindowID(). */
|
||||
readonly attribute unsigned long long innerWindowID;
|
||||
|
||||
/* Elapsed time, in milliseconds, from a platform-specific zero time to the
|
||||
time the message was created. */
|
||||
readonly attribute long long timeStamp;
|
||||
|
||||
/* This should be called instead of nsIScriptError.init to
|
||||
initialize with a window id. The window id should be for the
|
||||
outer window associated with this error. */
|
||||
inner window associated with this error. */
|
||||
void initWithWindowID(in wstring message,
|
||||
in wstring sourceName,
|
||||
in wstring sourceLine,
|
||||
|
@ -112,7 +120,7 @@ interface nsIScriptError2 : nsISupports {
|
|||
in PRUint32 columnNumber,
|
||||
in PRUint32 flags,
|
||||
in string category,
|
||||
in unsigned long long windowID);
|
||||
in unsigned long long innerWindowID);
|
||||
};
|
||||
|
||||
%{ C++
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
*/
|
||||
|
||||
#include "xpcprivate.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(nsScriptError, nsIConsoleMessage, nsIScriptError,
|
||||
nsIScriptError2)
|
||||
|
@ -55,7 +57,9 @@ nsScriptError::nsScriptError()
|
|||
mColumnNumber(0),
|
||||
mFlags(0),
|
||||
mCategory(),
|
||||
mWindowID(0)
|
||||
mOuterWindowID(0),
|
||||
mInnerWindowID(0),
|
||||
mTimeStamp(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -142,7 +146,7 @@ nsScriptError::InitWithWindowID(const PRUnichar *message,
|
|||
PRUint32 columnNumber,
|
||||
PRUint32 flags,
|
||||
const char *category,
|
||||
PRUint64 aWindowID)
|
||||
PRUint64 aInnerWindowID)
|
||||
{
|
||||
mMessage.Assign(message);
|
||||
mSourceName.Assign(sourceName);
|
||||
|
@ -151,7 +155,18 @@ nsScriptError::InitWithWindowID(const PRUnichar *message,
|
|||
mColumnNumber = columnNumber;
|
||||
mFlags = flags;
|
||||
mCategory.Assign(category);
|
||||
mWindowID = aWindowID;
|
||||
mTimeStamp = PR_Now() / 1000;
|
||||
mInnerWindowID = aInnerWindowID;
|
||||
|
||||
if(aInnerWindowID) {
|
||||
nsGlobalWindow* window =
|
||||
nsGlobalWindow::GetInnerWindowWithId(aInnerWindowID);
|
||||
if(window) {
|
||||
nsPIDOMWindow* outer = window->GetOuterWindow();
|
||||
if(outer)
|
||||
mOuterWindowID = outer->WindowID();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -218,8 +233,22 @@ nsScriptError::ToString(nsACString& /*UTF8*/ aResult)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptError::GetOuterWindowID(PRUint64 *aWindowID)
|
||||
nsScriptError::GetOuterWindowID(PRUint64 *aOuterWindowID)
|
||||
{
|
||||
*aWindowID = mWindowID;
|
||||
*aOuterWindowID = mOuterWindowID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptError::GetInnerWindowID(PRUint64 *aInnerWindowID)
|
||||
{
|
||||
*aInnerWindowID = mInnerWindowID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptError::GetTimeStamp(PRInt64 *aTimeStamp)
|
||||
{
|
||||
*aTimeStamp = mTimeStamp;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -2880,7 +2880,7 @@ nsXPCComponents_Utils::ReportError()
|
|||
if(NS_FAILED(rv) || !argv)
|
||||
return NS_OK;
|
||||
|
||||
const PRUint64 windowID = nsJSUtils::GetCurrentlyRunningCodeWindowID(cx);
|
||||
const PRUint64 innerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
|
||||
|
||||
JSErrorReport* err = JS_ErrorFromException(cx, argv[0]);
|
||||
if(err)
|
||||
|
@ -2899,7 +2899,7 @@ nsXPCComponents_Utils::ReportError()
|
|||
err->lineno,
|
||||
column,
|
||||
err->flags,
|
||||
"XPConnect JavaScript", windowID);
|
||||
"XPConnect JavaScript", innerWindowID);
|
||||
if(NS_FAILED(rv))
|
||||
return NS_OK;
|
||||
|
||||
|
@ -2935,8 +2935,8 @@ nsXPCComponents_Utils::ReportError()
|
|||
rv = scripterr->InitWithWindowID(reinterpret_cast<const PRUnichar *>(msgchars),
|
||||
NS_ConvertUTF8toUTF16(fileName).get(),
|
||||
nsnull,
|
||||
lineNo, 0,
|
||||
0, "XPConnect JavaScript", windowID);
|
||||
lineNo, 0, 0,
|
||||
"XPConnect JavaScript", innerWindowID);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsIScriptError> logError = do_QueryInterface(scripterr);
|
||||
|
|
|
@ -1827,7 +1827,7 @@ XPCConvert::JSErrorToXPCException(XPCCallContext& ccx,
|
|||
(const PRUnichar *)report->uclinebuf, report->lineno,
|
||||
report->uctokenptr - report->uclinebuf, report->flags,
|
||||
"XPConnect JavaScript",
|
||||
nsJSUtils::GetCurrentlyRunningCodeWindowID(ccx.GetJSContext()));
|
||||
nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(ccx.GetJSContext()));
|
||||
}
|
||||
|
||||
if(data)
|
||||
|
|
|
@ -3885,7 +3885,9 @@ private:
|
|||
PRUint32 mColumnNumber;
|
||||
PRUint32 mFlags;
|
||||
nsCString mCategory;
|
||||
PRUint64 mWindowID;
|
||||
PRUint64 mOuterWindowID;
|
||||
PRUint64 mInnerWindowID;
|
||||
PRUint64 mTimeStamp;
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
|
|
@ -1218,7 +1218,7 @@ nsXPCWrappedJSClass::CheckForException(XPCCallContext & ccx,
|
|||
nsnull,
|
||||
lineNumber, 0, 0,
|
||||
"XPConnect JavaScript",
|
||||
nsJSUtils::GetCurrentlyRunningCodeWindowID(cx));
|
||||
nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx));
|
||||
if(NS_FAILED(rv))
|
||||
scriptError = nsnull;
|
||||
}
|
||||
|
|
|
@ -285,7 +285,7 @@ nsCSSScanner::nsCSSScanner()
|
|||
, mSVGMode(PR_FALSE)
|
||||
#ifdef CSS_REPORT_PARSE_ERRORS
|
||||
, mError(mErrorBuf, NS_ARRAY_LENGTH(mErrorBuf), 0)
|
||||
, mWindowID(0)
|
||||
, mInnerWindowID(0)
|
||||
, mWindowIDCached(PR_FALSE)
|
||||
, mSheet(nsnull)
|
||||
, mLoader(nsnull)
|
||||
|
@ -449,12 +449,12 @@ nsCSSScanner::OutputError()
|
|||
if (InitGlobals() && gReportErrors) {
|
||||
if (!mWindowIDCached) {
|
||||
if (mSheet) {
|
||||
mWindowID = mSheet->FindOwningWindowID();
|
||||
mInnerWindowID = mSheet->FindOwningWindowInnerID();
|
||||
}
|
||||
if (mWindowID == 0 && mLoader) {
|
||||
if (mInnerWindowID == 0 && mLoader) {
|
||||
nsIDocument* doc = mLoader->GetDocument();
|
||||
if (doc) {
|
||||
mWindowID = doc->OuterWindowID();
|
||||
mInnerWindowID = doc->InnerWindowID();
|
||||
}
|
||||
}
|
||||
mWindowIDCached = PR_TRUE;
|
||||
|
@ -471,7 +471,8 @@ nsCSSScanner::OutputError()
|
|||
mErrorLineNumber,
|
||||
mErrorColNumber,
|
||||
nsIScriptError::warningFlag,
|
||||
"CSS Parser", mWindowID);
|
||||
"CSS Parser",
|
||||
mInnerWindowID);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIScriptError> logError = do_QueryInterface(errorObject);
|
||||
gConsoleService->LogMessage(logError);
|
||||
|
@ -622,7 +623,7 @@ nsCSSScanner::Close()
|
|||
mFileName.Truncate();
|
||||
mURI = nsnull;
|
||||
mError.Truncate();
|
||||
mWindowID = 0;
|
||||
mInnerWindowID = 0;
|
||||
mWindowIDCached = PR_FALSE;
|
||||
mSheet = nsnull;
|
||||
mLoader = nsnull;
|
||||
|
|
|
@ -248,7 +248,7 @@ protected:
|
|||
PRUint32 mErrorLineNumber, mColNumber, mErrorColNumber;
|
||||
nsFixedString mError;
|
||||
PRUnichar mErrorBuf[200];
|
||||
PRUint64 mWindowID;
|
||||
PRUint64 mInnerWindowID;
|
||||
PRBool mWindowIDCached;
|
||||
nsCSSStyleSheet* mSheet;
|
||||
mozilla::css::Loader* mLoader;
|
||||
|
|
|
@ -1252,12 +1252,12 @@ nsCSSStyleSheet::SetOwningDocument(nsIDocument* aDocument)
|
|||
}
|
||||
}
|
||||
|
||||
/* virtual */ PRUint64
|
||||
nsCSSStyleSheet::FindOwningWindowID() const
|
||||
PRUint64
|
||||
nsCSSStyleSheet::FindOwningWindowInnerID() const
|
||||
{
|
||||
PRUint64 windowID = 0;
|
||||
if (mDocument) {
|
||||
windowID = mDocument->OuterWindowID();
|
||||
windowID = mDocument->InnerWindowID();
|
||||
}
|
||||
|
||||
if (windowID == 0 && mOwningNode) {
|
||||
|
@ -1265,7 +1265,7 @@ nsCSSStyleSheet::FindOwningWindowID() const
|
|||
if (node) {
|
||||
nsIDocument* doc = node->GetOwnerDoc();
|
||||
if (doc) {
|
||||
windowID = doc->OuterWindowID();
|
||||
windowID = doc->InnerWindowID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1275,13 +1275,13 @@ nsCSSStyleSheet::FindOwningWindowID() const
|
|||
if (sheet) {
|
||||
nsRefPtr<nsCSSStyleSheet> cssSheet = do_QueryObject(sheet);
|
||||
if (cssSheet) {
|
||||
windowID = cssSheet->FindOwningWindowID();
|
||||
windowID = cssSheet->FindOwningWindowInnerID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (windowID == 0 && mParent) {
|
||||
windowID = mParent->FindOwningWindowID();
|
||||
windowID = mParent->FindOwningWindowInnerID();
|
||||
}
|
||||
|
||||
return windowID;
|
||||
|
|
|
@ -155,8 +155,8 @@ public:
|
|||
virtual nsIDocument* GetOwningDocument() const; // may be null
|
||||
virtual void SetOwningDocument(nsIDocument* aDocument);
|
||||
|
||||
// Find the ID of the owner outer window.
|
||||
virtual PRUint64 FindOwningWindowID() const;
|
||||
// Find the ID of the owner inner window.
|
||||
PRUint64 FindOwningWindowInnerID() const;
|
||||
#ifdef DEBUG
|
||||
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
||||
#endif
|
||||
|
|
|
@ -798,14 +798,14 @@ nsUserFontSet::LogMessage(gfxProxyFontEntry *aProxy,
|
|||
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint64 windowID = GetPresContext()->Document()->OuterWindowID();
|
||||
PRUint64 innerWindowID = GetPresContext()->Document()->InnerWindowID();
|
||||
rv = scriptError->InitWithWindowID(NS_ConvertUTF8toUTF16(msg).get(),
|
||||
href.get(), // file
|
||||
text.get(), // src line
|
||||
0, 0, // line & column number
|
||||
aFlags, // flags
|
||||
"CSS Loader", // category (make separate?)
|
||||
windowID);
|
||||
innerWindowID);
|
||||
if (NS_SUCCEEDED(rv)){
|
||||
nsCOMPtr<nsIScriptError> logError = do_QueryInterface(scriptError);
|
||||
if (logError) {
|
||||
|
|
|
@ -153,7 +153,7 @@ Decoder::Finish()
|
|||
NS_ConvertUTF8toUTF16(mImage->GetURIString()).get(),
|
||||
nsnull,
|
||||
0, 0, nsIScriptError::errorFlag,
|
||||
"Image", mImage->WindowID()
|
||||
"Image", mImage->InnerWindowID()
|
||||
);
|
||||
|
||||
nsCOMPtr<nsIScriptError> error = do_QueryInterface(errorObject);
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace imagelib {
|
|||
|
||||
// Constructor
|
||||
Image::Image(imgStatusTracker* aStatusTracker) :
|
||||
mWindowId(0),
|
||||
mInnerWindowId(0),
|
||||
mAnimationConsumers(0),
|
||||
mAnimationMode(kNormalAnimMode),
|
||||
mInitialized(PR_FALSE),
|
||||
|
|
|
@ -125,10 +125,10 @@ public:
|
|||
PRUint32 GetAnimationConsumers() { return mAnimationConsumers; }
|
||||
#endif
|
||||
|
||||
void SetWindowID(PRUint64 aWindowId) {
|
||||
mWindowId = aWindowId;
|
||||
void SetInnerWindowID(PRUint64 aInnerWindowId) {
|
||||
mInnerWindowId = aInnerWindowId;
|
||||
}
|
||||
PRUint64 WindowID() const { return mWindowId; }
|
||||
PRUint64 InnerWindowID() const { return mInnerWindowId; }
|
||||
|
||||
PRBool HasError() { return mError; }
|
||||
|
||||
|
@ -144,7 +144,7 @@ protected:
|
|||
virtual nsresult StartAnimation() = 0;
|
||||
virtual nsresult StopAnimation() = 0;
|
||||
|
||||
PRUint64 mWindowId;
|
||||
PRUint64 mInnerWindowId;
|
||||
|
||||
// Member data shared by all implementations of this abstract class
|
||||
nsAutoPtr<imgStatusTracker> mStatusTracker;
|
||||
|
|
|
@ -1709,10 +1709,10 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
|
|||
request->Init(aURI, aURI, loadGroup, newChannel, entry, cacheId, aCX,
|
||||
aLoadingPrincipal, corsmode);
|
||||
|
||||
// Pass the windowID of the loading document, if possible.
|
||||
// Pass the inner window ID of the loading document, if possible.
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aCX);
|
||||
if (doc) {
|
||||
request->SetWindowID(doc->OuterWindowID());
|
||||
request->SetInnerWindowID(doc->InnerWindowID());
|
||||
}
|
||||
|
||||
// create the proxy listener
|
||||
|
|
|
@ -184,8 +184,9 @@ NS_IMPL_ISUPPORTS8(imgRequest,
|
|||
|
||||
imgRequest::imgRequest() :
|
||||
mCacheId(0), mValidator(nsnull), mImageSniffers("image-sniffing-services"),
|
||||
mWindowId(0), mCORSMode(imgIRequest::CORS_NONE), mDecodeRequested(PR_FALSE),
|
||||
mIsMultiPartChannel(PR_FALSE), mGotData(PR_FALSE), mIsInCache(PR_FALSE)
|
||||
mInnerWindowId(0), mCORSMode(imgIRequest::CORS_NONE),
|
||||
mDecodeRequested(PR_FALSE), mIsMultiPartChannel(PR_FALSE), mGotData(PR_FALSE),
|
||||
mIsInCache(PR_FALSE)
|
||||
{}
|
||||
|
||||
imgRequest::~imgRequest()
|
||||
|
@ -1035,7 +1036,7 @@ NS_IMETHODIMP imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctx
|
|||
} else {
|
||||
mImage = new RasterImage(mStatusTracker.forget());
|
||||
}
|
||||
mImage->SetWindowID(mWindowId);
|
||||
mImage->SetInnerWindowID(mInnerWindowId);
|
||||
imageType = mImage->GetType();
|
||||
|
||||
// Notify any imgRequestProxys that are observing us that we have an Image.
|
||||
|
|
|
@ -123,12 +123,12 @@ public:
|
|||
nsresult UnlockImage();
|
||||
nsresult RequestDecode();
|
||||
|
||||
inline void SetWindowID(PRUint64 aWindowId) {
|
||||
mWindowId = aWindowId;
|
||||
inline void SetInnerWindowID(PRUint64 aInnerWindowId) {
|
||||
mInnerWindowId = aInnerWindowId;
|
||||
}
|
||||
|
||||
inline PRUint64 WindowID() const {
|
||||
return mWindowId;
|
||||
inline PRUint64 InnerWindowID() const {
|
||||
return mInnerWindowId;
|
||||
}
|
||||
|
||||
// Set the cache validation information (expiry time, whether we must
|
||||
|
@ -257,8 +257,8 @@ private:
|
|||
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
|
||||
nsCOMPtr<nsIChannel> mNewRedirectChannel;
|
||||
|
||||
// Originating outer window ID. Used for error reporting.
|
||||
PRUint64 mWindowId;
|
||||
// The ID of the inner window origin, used for error reporting.
|
||||
PRUint64 mInnerWindowId;
|
||||
|
||||
// The CORS mode (defined in imgIRequest) this image was loaded with. By
|
||||
// default, imgIRequest::CORS_NONE.
|
||||
|
|
|
@ -376,7 +376,7 @@ nsExpatDriver::nsExpatDriver()
|
|||
mInternalState(NS_OK),
|
||||
mExpatBuffered(0),
|
||||
mCatalogData(nsnull),
|
||||
mWindowID(0)
|
||||
mInnerWindowID(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -953,7 +953,7 @@ nsExpatDriver::HandleError()
|
|||
mLastLine.get(),
|
||||
lineNumber, colNumber,
|
||||
nsIScriptError::errorFlag, "malformed-xml",
|
||||
mWindowID);
|
||||
mInnerWindowID);
|
||||
}
|
||||
|
||||
// If it didn't initialize, we can't do any logging.
|
||||
|
@ -1250,8 +1250,11 @@ nsExpatDriver::WillBuildModel(const CParserContext& aParserContext,
|
|||
win = do_QueryInterface(global);
|
||||
}
|
||||
}
|
||||
if (win && !win->IsInnerWindow()) {
|
||||
win = win->GetCurrentInnerWindow();
|
||||
}
|
||||
if (win) {
|
||||
mWindowID = win->GetOuterWindow()->WindowID();
|
||||
mInnerWindowID = win->WindowID();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -169,7 +169,7 @@ private:
|
|||
nsString mURISpec;
|
||||
|
||||
// Used for error reporting.
|
||||
PRUint64 mWindowID;
|
||||
PRUint64 mInnerWindowID;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -49,6 +49,24 @@ function testtag_notificationbox(nb)
|
|||
runTimedTests(tests, -1, nb, null);
|
||||
}
|
||||
|
||||
var notification_last_event, notification_last_event_item;
|
||||
function notification_eventCallback(event)
|
||||
{
|
||||
notification_last_event = event;
|
||||
notification_last_event_item = this;
|
||||
}
|
||||
|
||||
function testtag_notification_eventCallback(expectedEvent, ntf, testName)
|
||||
{
|
||||
SimpleTest.is(notification_last_event, expectedEvent,
|
||||
testName + ": event name");
|
||||
SimpleTest.is(notification_last_event_item, ntf,
|
||||
testName + ": event item");
|
||||
|
||||
notification_last_event = null;
|
||||
notification_last_event_item = null;
|
||||
}
|
||||
|
||||
var tests =
|
||||
[
|
||||
{
|
||||
|
@ -90,6 +108,33 @@ var tests =
|
|||
ise(exh, true, "removeNotification again");
|
||||
testtag_notificationbox_State(nb, "removeNotification again", null, 0);
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
test: function(nb, ntf) {
|
||||
// append a new notification, but now with an event callback
|
||||
var ntf = nb.appendNotification("Notification", "note", "happy.png",
|
||||
nb.PRIORITY_INFO_LOW,
|
||||
testtag_notificationbox_buttons,
|
||||
notification_eventCallback);
|
||||
ise(ntf && ntf.localName == "notification", true, "append notification with callback");
|
||||
return ntf;
|
||||
},
|
||||
result: function(nb, ntf) {
|
||||
testtag_notificationbox_State(nb, "append with callback", ntf, 1);
|
||||
return ntf;
|
||||
}
|
||||
},
|
||||
{
|
||||
test: function(nb, ntf) {
|
||||
nb.removeNotification(ntf);
|
||||
return ntf;
|
||||
},
|
||||
result: function(nb, ntf) {
|
||||
testtag_notificationbox_State(nb, "removeNotification with callback",
|
||||
null, 0);
|
||||
|
||||
testtag_notification_eventCallback("removed", ntf, "removeNotification()");
|
||||
return [1, null];
|
||||
}
|
||||
},
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
<parameter name="aImage"/>
|
||||
<parameter name="aPriority"/>
|
||||
<parameter name="aButtons"/>
|
||||
<parameter name="aEventCallback"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (aPriority < this.PRIORITY_INFO_LOW ||
|
||||
|
@ -99,6 +100,7 @@
|
|||
newitem.setAttribute("value", aValue);
|
||||
if (aImage)
|
||||
newitem.setAttribute("image", aImage);
|
||||
newitem.eventCallback = aEventCallback;
|
||||
|
||||
if (aButtons) {
|
||||
for (var b = 0; b < aButtons.length; b++) {
|
||||
|
@ -148,12 +150,23 @@
|
|||
if (aItem == this.currentNotification)
|
||||
this.removeCurrentNotification(aSkipAnimation);
|
||||
else if (aItem != this._closedNotification)
|
||||
this.removeChild(aItem);
|
||||
this._removeNotificationElement(aItem);
|
||||
return aItem;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_removeNotificationElement">
|
||||
<parameter name="aChild"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (aChild.eventCallback)
|
||||
aChild.eventCallback("removed");
|
||||
this.removeChild(aChild);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="removeCurrentNotification">
|
||||
<parameter name="aSkipAnimation"/>
|
||||
<body>
|
||||
|
@ -170,7 +183,7 @@
|
|||
var notifications = this.allNotifications;
|
||||
for (var n = notifications.length - 1; n >= 0; n--) {
|
||||
if (aImmediate)
|
||||
this.removeChild(notifications[n]);
|
||||
this._removeNotificationElement(notifications[n]);
|
||||
else
|
||||
this.removeNotification(notifications[n]);
|
||||
}
|
||||
|
@ -228,7 +241,7 @@
|
|||
this.currentNotification = (idx >= 0) ? notifications[idx] : null;
|
||||
|
||||
if (skipAnimation) {
|
||||
this.removeChild(this._closedNotification);
|
||||
this._removeNotificationElement(this._closedNotification);
|
||||
this._closedNotification = null;
|
||||
this._setBlockingState(this.currentNotification);
|
||||
return;
|
||||
|
@ -248,7 +261,7 @@
|
|||
if (this._animating) {
|
||||
this._animating = false;
|
||||
if (this._closedNotification) {
|
||||
this.removeChild(this._closedNotification);
|
||||
this._removeNotificationElement(this._closedNotification);
|
||||
this._closedNotification = null;
|
||||
}
|
||||
this._setBlockingState(this.currentNotification);
|
||||
|
|
Загрузка…
Ссылка в новой задаче