This commit is contained in:
Gervase Markham 2011-05-23 21:25:55 +01:00
commit 31cbf46eed
22 changed files with 332 additions and 49 deletions

View File

@ -201,9 +201,6 @@
label="&errorConsoleCmd.label;" label="&errorConsoleCmd.label;"
key="key_errorConsole" key="key_errorConsole"
oncommand="toJavaScriptConsole();"/> oncommand="toJavaScriptConsole();"/>
<menuitem id="appmenu_getMoreDevtools"
label="&getMoreDevtoolsCmd.label;"
oncommand="Devtools.getMoreLink();"/>
<menuseparator/> <menuseparator/>
#define ID_PREFIX appmenu_developer_ #define ID_PREFIX appmenu_developer_
#define OMIT_ACCESSKEYS #define OMIT_ACCESSKEYS

View File

@ -567,9 +567,6 @@
accesskey="&errorConsoleCmd.accesskey;" accesskey="&errorConsoleCmd.accesskey;"
key="key_errorConsole" key="key_errorConsole"
oncommand="toJavaScriptConsole();"/> oncommand="toJavaScriptConsole();"/>
<menuitem id="getMoreDevtools"
label="&getMoreDevtoolsCmd.label;"
oncommand="Devtools.getMoreLink();"/>
</menupopup> </menupopup>
</menu> </menu>
<menuitem id="menu_pageInfo" <menuitem id="menu_pageInfo"

View File

@ -8678,12 +8678,6 @@ var Scratchpad = {
}, },
}; };
var Devtools = {
getMoreLink: function Devtools_getMoreLink() {
switchToTabHavingURI("https://addons.mozilla.org/en-US/firefox/collections/mozilla/webdeveloper/", true);
},
};
XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () { XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
#ifdef XP_WIN #ifdef XP_WIN

View File

@ -226,8 +226,6 @@ can reach it easily. -->
<!ENTITY inspectObjectButton.label "Object"> <!ENTITY inspectObjectButton.label "Object">
<!ENTITY inspectObjectButton.accesskey "O"> <!ENTITY inspectObjectButton.accesskey "O">
<!ENTITY getMoreDevtoolsCmd.label "Get More Tools…">
<!ENTITY fileMenu.label "File"> <!ENTITY fileMenu.label "File">
<!ENTITY fileMenu.accesskey "F"> <!ENTITY fileMenu.accesskey "F">
<!ENTITY newNavigatorCmd.label "New Window"> <!ENTITY newNavigatorCmd.label "New Window">

View File

@ -271,7 +271,7 @@ NS_IMETHODIMP
nsDOMFileReader::Abort() nsDOMFileReader::Abort()
{ {
if (mReadyState != nsIDOMFileReader::LOADING) if (mReadyState != nsIDOMFileReader::LOADING)
return NS_OK; return NS_ERROR_DOM_FILE_ABORT_ERR;
//Clear progress and file data //Clear progress and file data
mProgressEventWasDelayed = PR_FALSE; mProgressEventWasDelayed = PR_FALSE;

View File

@ -1339,10 +1339,33 @@ nsEventSource::DispatchAllMessageEvents()
return; return;
} }
// Let's play get the JSContext
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(mOwner);
NS_ENSURE_TRUE(sgo,);
nsIScriptContext* scriptContext = sgo->GetContext();
NS_ENSURE_TRUE(scriptContext,);
JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
NS_ENSURE_TRUE(cx,);
while (mMessagesToDispatch.GetSize() > 0) { while (mMessagesToDispatch.GetSize() > 0) {
nsAutoPtr<Message> nsAutoPtr<Message>
message(static_cast<Message*>(mMessagesToDispatch.PopFront())); message(static_cast<Message*>(mMessagesToDispatch.PopFront()));
// Now we can turn our string into a jsval
jsval jsData;
{
JSString* jsString;
JSAutoRequest ar(cx);
jsString = JS_NewUCStringCopyN(cx,
message->mData.get(),
message->mData.Length());
NS_ENSURE_TRUE(jsString,);
jsData = STRING_TO_JSVAL(jsString);
}
// create an event that uses the MessageEvent interface, // create an event that uses the MessageEvent interface,
// which does not bubble, is not cancelable, and has no default action // which does not bubble, is not cancelable, and has no default action
@ -1356,7 +1379,7 @@ nsEventSource::DispatchAllMessageEvents()
nsCOMPtr<nsIDOMMessageEvent> messageEvent = do_QueryInterface(event); nsCOMPtr<nsIDOMMessageEvent> messageEvent = do_QueryInterface(event);
rv = messageEvent->InitMessageEvent(message->mEventName, rv = messageEvent->InitMessageEvent(message->mEventName,
PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE,
message->mData, jsData,
NS_ConvertUTF8toUTF16(mOrigin), NS_ConvertUTF8toUTF16(mOrigin),
message->mLastEventID, nsnull); message->mLastEventID, nsnull);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {

View File

@ -819,6 +819,31 @@ nsWebSocket::CreateAndDispatchMessageEvent(const nsACString& aData)
return NS_OK; return NS_OK;
} }
// Let's play get the JSContext
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(mOwner);
NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE);
nsIScriptContext* scriptContext = sgo->GetContext();
NS_ENSURE_TRUE(scriptContext, NS_ERROR_FAILURE);
JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
// Now we can turn our string into a jsval
jsval jsData;
{
NS_ConvertUTF8toUTF16 utf16Data(aData);
JSString* jsString;
JSAutoRequest ar(cx);
jsString = JS_NewUCStringCopyN(cx,
utf16Data.get(),
utf16Data.Length());
NS_ENSURE_TRUE(jsString, NS_ERROR_FAILURE);
jsData = STRING_TO_JSVAL(jsString);
}
// create an event that uses the MessageEvent interface, // create an event that uses the MessageEvent interface,
// which does not bubble, is not cancelable, and has no default action // which does not bubble, is not cancelable, and has no default action
@ -829,7 +854,7 @@ nsWebSocket::CreateAndDispatchMessageEvent(const nsACString& aData)
nsCOMPtr<nsIDOMMessageEvent> messageEvent = do_QueryInterface(event); nsCOMPtr<nsIDOMMessageEvent> messageEvent = do_QueryInterface(event);
rv = messageEvent->InitMessageEvent(NS_LITERAL_STRING("message"), rv = messageEvent->InitMessageEvent(NS_LITERAL_STRING("message"),
PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE,
NS_ConvertUTF8toUTF16(aData), jsData,
mUTF16Origin, mUTF16Origin,
EmptyString(), nsnull); EmptyString(), nsnull);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);

View File

@ -23,10 +23,10 @@ var gen = runTest();
function runTest() { function runTest() {
var iframe = $('iframe'); var iframe = $('iframe');
iframe.src = "http://noxul.example.com/tests/content/base/test/file_bug590870.html"; iframe.src = "http://noxul.example.com/tests/content/base/test/file_bug590870.html";
is((yield), "true", "shouldn't be able to create XUL elements"); is((yield), true, "shouldn't be able to create XUL elements");
iframe.src = "file_bug590870.html"; iframe.src = "file_bug590870.html";
is((yield), "false", "should be able to create XUL elements"); is((yield), false, "should be able to create XUL elements");
SimpleTest.finish(); SimpleTest.finish();
yield; yield;

View File

@ -22,7 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=601803
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
window.onmessage = function (event) { window.onmessage = function (event) {
is(event.data, "false", "Shouldn't throw when adopting a node cross-compartment"); is(event.data, false, "Shouldn't throw when adopting a node cross-compartment");
SimpleTest.finish(); SimpleTest.finish();
} }

View File

@ -259,7 +259,13 @@ r.onloadend = function (event) {
r.onload = function() { ok(false, "load should not fire for aborted reads") }; r.onload = function() { ok(false, "load should not fire for aborted reads") };
r.onerror = function() { ok(false, "error should not fire for aborted reads") }; r.onerror = function() { ok(false, "error should not fire for aborted reads") };
r.onprogress = function() { ok(false, "progress should not fire for aborted reads") }; r.onprogress = function() { ok(false, "progress should not fire for aborted reads") };
r.abort(); var abortThrew = false;
try {
r.abort();
} catch(e) {
abortThrew = true;
}
is(abortThrew, true, "abort() must throw if not loading");
is(abortHasRun, false, "abort() is a no-op unless loading"); is(abortHasRun, false, "abort() is a no-op unless loading");
r.readAsText(asciiFile); r.readAsText(asciiFile);
r.abort(); r.abort();
@ -277,7 +283,13 @@ r.onabort = function (event) {
is(event.target.result, null, "file data should be null on aborted reads"); is(event.target.result, null, "file data should be null on aborted reads");
} }
r.onload = function() { ok(false, "load should not fire for aborted reads") }; r.onload = function() { ok(false, "load should not fire for aborted reads") };
r.abort(); var abortThrew = false;
try {
r.abort();
} catch(e) {
abortThrew = true;
}
is(abortThrew, true, "abort() must throw if not loading");
is(reuseAbortHasRun, false, "abort() is a no-op unless loading"); is(reuseAbortHasRun, false, "abort() is a no-op unless loading");
r.readAsText(asciiFile); r.readAsText(asciiFile);
r.readAsText(asciiFile); r.readAsText(asciiFile);

View File

@ -38,17 +38,29 @@
#include "nsDOMMessageEvent.h" #include "nsDOMMessageEvent.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "jsapi.h"
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMessageEvent) NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMessageEvent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMMessageEvent, nsDOMEvent) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMMessageEvent, nsDOMEvent)
if (tmp->mDataRooted) {
tmp->UnrootData();
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSource) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSource)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMMessageEvent, nsDOMEvent) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMMessageEvent, nsDOMEvent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSource) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSource)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMMessageEvent)
if (JSVAL_IS_GCTHING(tmp->mData)) {
void *gcThing = JSVAL_TO_GCTHING(tmp->mData);
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mData")
}
NS_IMPL_CYCLE_COLLECTION_TRACE_END
DOMCI_DATA(MessageEvent, nsDOMMessageEvent) DOMCI_DATA(MessageEvent, nsDOMMessageEvent)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMMessageEvent) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMMessageEvent)
@ -59,10 +71,41 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
NS_IMPL_ADDREF_INHERITED(nsDOMMessageEvent, nsDOMEvent) NS_IMPL_ADDREF_INHERITED(nsDOMMessageEvent, nsDOMEvent)
NS_IMPL_RELEASE_INHERITED(nsDOMMessageEvent, nsDOMEvent) NS_IMPL_RELEASE_INHERITED(nsDOMMessageEvent, nsDOMEvent)
NS_IMETHODIMP nsDOMMessageEvent::nsDOMMessageEvent(nsPresContext* aPresContext,
nsDOMMessageEvent::GetData(nsAString& aData) nsEvent* aEvent)
: nsDOMEvent(aPresContext, aEvent),
mData(JSVAL_VOID),
mDataRooted(false)
{ {
aData = mData; }
nsDOMMessageEvent::~nsDOMMessageEvent()
{
if (mDataRooted)
UnrootData();
}
void
nsDOMMessageEvent::RootData()
{
NS_ASSERTION(!mDataRooted, "...");
NS_HOLD_JS_OBJECTS(this, nsDOMMessageEvent);
mDataRooted = true;
}
void
nsDOMMessageEvent::UnrootData()
{
NS_ASSERTION(mDataRooted, "...");
NS_DROP_JS_OBJECTS(this, nsDOMMessageEvent);
mDataRooted = false;
mData = JSVAL_VOID;
}
NS_IMETHODIMP
nsDOMMessageEvent::GetData(jsval* aData)
{
*aData = mData;
return NS_OK; return NS_OK;
} }
@ -91,7 +134,7 @@ NS_IMETHODIMP
nsDOMMessageEvent::InitMessageEvent(const nsAString& aType, nsDOMMessageEvent::InitMessageEvent(const nsAString& aType,
PRBool aCanBubble, PRBool aCanBubble,
PRBool aCancelable, PRBool aCancelable,
const nsAString& aData, const jsval& aData,
const nsAString& aOrigin, const nsAString& aOrigin,
const nsAString& aLastEventId, const nsAString& aLastEventId,
nsIDOMWindow* aSource) nsIDOMWindow* aSource)
@ -99,7 +142,12 @@ nsDOMMessageEvent::InitMessageEvent(const nsAString& aType,
nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Allowing double-initialization seems a little silly, but we have a test
// for it so it might be important ...
if (mDataRooted)
UnrootData();
mData = aData; mData = aData;
RootData();
mOrigin = aOrigin; mOrigin = aOrigin;
mLastEventId = aLastEventId; mLastEventId = aLastEventId;
mSource = aSource; mSource = aSource;
@ -113,8 +161,6 @@ NS_NewDOMMessageEvent(nsIDOMEvent** aInstancePtrResult,
nsEvent* aEvent) nsEvent* aEvent)
{ {
nsDOMMessageEvent* it = new nsDOMMessageEvent(aPresContext, aEvent); nsDOMMessageEvent* it = new nsDOMMessageEvent(aPresContext, aEvent);
if (nsnull == it)
return NS_ERROR_OUT_OF_MEMORY;
return CallQueryInterface(it, aInstancePtrResult); return CallQueryInterface(it, aInstancePtrResult);
} }

View File

@ -54,21 +54,23 @@ class nsDOMMessageEvent : public nsDOMEvent,
public nsIDOMMessageEvent public nsIDOMMessageEvent
{ {
public: public:
nsDOMMessageEvent(nsPresContext* aPresContext, nsEvent* aEvent) nsDOMMessageEvent(nsPresContext* aPresContext, nsEvent* aEvent);
: nsDOMEvent(aPresContext, aEvent) ~nsDOMMessageEvent();
{
}
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMMessageEvent, nsDOMEvent) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsDOMMessageEvent,
nsDOMEvent)
NS_DECL_NSIDOMMESSAGEEVENT NS_DECL_NSIDOMMESSAGEEVENT
// Forward to base class // Forward to base class
NS_FORWARD_TO_NSDOMEVENT NS_FORWARD_TO_NSDOMEVENT
void RootData();
void UnrootData();
private: private:
nsString mData; jsval mData;
bool mDataRooted;
nsString mOrigin; nsString mOrigin;
nsString mLastEventId; nsString mLastEventId;
nsCOMPtr<nsIDOMWindow> mSource; nsCOMPtr<nsIDOMWindow> mSource;

View File

@ -127,6 +127,7 @@
#define NS_ERROR_DOM_FILE_NOT_FOUND_ERR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_FILE, 0) #define NS_ERROR_DOM_FILE_NOT_FOUND_ERR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_FILE, 0)
#define NS_ERROR_DOM_FILE_NOT_READABLE_ERR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_FILE, 1) #define NS_ERROR_DOM_FILE_NOT_READABLE_ERR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_FILE, 1)
#define NS_ERROR_DOM_FILE_ABORT_ERR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_FILE, 2)
#define NS_ERROR_DOM_UNSPECIFIED_EVENT_TYPE_ERR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_EVENTS, 0) #define NS_ERROR_DOM_UNSPECIFIED_EVENT_TYPE_ERR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_EVENTS, 0)

View File

@ -5843,13 +5843,13 @@ class PostMessageEvent : public nsRunnable
PostMessageEvent(nsGlobalWindow* aSource, PostMessageEvent(nsGlobalWindow* aSource,
const nsAString& aCallerOrigin, const nsAString& aCallerOrigin,
const nsAString& aMessage,
nsGlobalWindow* aTargetWindow, nsGlobalWindow* aTargetWindow,
nsIURI* aProvidedOrigin, nsIURI* aProvidedOrigin,
PRBool aTrustedCaller) PRBool aTrustedCaller)
: mSource(aSource), : mSource(aSource),
mCallerOrigin(aCallerOrigin), mCallerOrigin(aCallerOrigin),
mMessage(aMessage), mMessage(nsnull),
mMessageLen(0),
mTargetWindow(aTargetWindow), mTargetWindow(aTargetWindow),
mProvidedOrigin(aProvidedOrigin), mProvidedOrigin(aProvidedOrigin),
mTrustedCaller(aTrustedCaller) mTrustedCaller(aTrustedCaller)
@ -5859,13 +5859,21 @@ class PostMessageEvent : public nsRunnable
~PostMessageEvent() ~PostMessageEvent()
{ {
NS_ASSERTION(!mMessage, "Message should have been deserialized!");
MOZ_COUNT_DTOR(PostMessageEvent); MOZ_COUNT_DTOR(PostMessageEvent);
} }
void SetJSData(JSAutoStructuredCloneBuffer& aBuffer)
{
NS_ASSERTION(!mMessage && mMessageLen == 0, "Don't call twice!");
aBuffer.steal(&mMessage, &mMessageLen);
}
private: private:
nsRefPtr<nsGlobalWindow> mSource; nsRefPtr<nsGlobalWindow> mSource;
nsString mCallerOrigin; nsString mCallerOrigin;
nsString mMessage; uint64* mMessage;
size_t mMessageLen;
nsRefPtr<nsGlobalWindow> mTargetWindow; nsRefPtr<nsGlobalWindow> mTargetWindow;
nsCOMPtr<nsIURI> mProvidedOrigin; nsCOMPtr<nsIURI> mProvidedOrigin;
PRBool mTrustedCaller; PRBool mTrustedCaller;
@ -5879,6 +5887,22 @@ PostMessageEvent::Run()
NS_ABORT_IF_FALSE(!mSource || mSource->IsOuterWindow(), NS_ABORT_IF_FALSE(!mSource || mSource->IsOuterWindow(),
"should have been passed an outer window!"); "should have been passed an outer window!");
// Get the JSContext for the target window
nsIScriptContext* scriptContext = mTargetWindow->GetContext();
NS_ENSURE_TRUE(scriptContext, NS_ERROR_FAILURE);
JSContext* cx = (JSContext*)scriptContext->GetNativeContext();
NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
// If we bailed before this point we're going to leak mMessage, but
// that's probably better than crashing.
// Ensure that the buffer is freed even if we fail to post the message
JSAutoStructuredCloneBuffer buffer;
buffer.adopt(cx, mMessage, mMessageLen);
mMessage = nsnull;
mMessageLen = 0;
nsRefPtr<nsGlobalWindow> targetWindow; nsRefPtr<nsGlobalWindow> targetWindow;
if (mTargetWindow->IsClosedOrClosing() || if (mTargetWindow->IsClosedOrClosing() ||
!(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) || !(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) ||
@ -5924,6 +5948,14 @@ PostMessageEvent::Run()
return NS_OK; return NS_OK;
} }
// Deserialize the structured clone data
jsval messageData;
{
JSAutoRequest ar(cx);
if (!buffer.read(&messageData, cx, nsnull))
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
// Create the event // Create the event
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(targetWindow->mDocument); nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(targetWindow->mDocument);
@ -5939,7 +5971,7 @@ PostMessageEvent::Run()
nsresult rv = message->InitMessageEvent(NS_LITERAL_STRING("message"), nsresult rv = message->InitMessageEvent(NS_LITERAL_STRING("message"),
PR_FALSE /* non-bubbling */, PR_FALSE /* non-bubbling */,
PR_TRUE /* cancelable */, PR_TRUE /* cancelable */,
mMessage, messageData,
mCallerOrigin, mCallerOrigin,
EmptyString(), EmptyString(),
mSource); mSource);
@ -5971,9 +6003,12 @@ PostMessageEvent::Run()
} }
NS_IMETHODIMP NS_IMETHODIMP
nsGlobalWindow::PostMessageMoz(const nsAString& aMessage, const nsAString& aOrigin) nsGlobalWindow::PostMessageMoz(const jsval& aMessage,
const nsAString& aOrigin,
JSContext* aCx)
{ {
FORWARD_TO_OUTER(PostMessageMoz, (aMessage, aOrigin), NS_ERROR_NOT_INITIALIZED); FORWARD_TO_OUTER(PostMessageMoz, (aMessage, aOrigin, aCx),
NS_ERROR_NOT_INITIALIZED);
// //
// Window.postMessage is an intentional subversion of the same-origin policy. // Window.postMessage is an intentional subversion of the same-origin policy.
@ -6037,10 +6072,19 @@ nsGlobalWindow::PostMessageMoz(const nsAString& aMessage, const nsAString& aOrig
? nsnull ? nsnull
: callerInnerWin->GetOuterWindowInternal(), : callerInnerWin->GetOuterWindowInternal(),
origin, origin,
aMessage,
this, this,
providedOrigin, providedOrigin,
nsContentUtils::IsCallerTrustedForWrite()); nsContentUtils::IsCallerTrustedForWrite());
// We *must* clone the data here, or the jsval could be modified
// by script
JSAutoStructuredCloneBuffer buffer;
if (!buffer.write(aCx, aMessage, nsnull, nsnull))
return NS_ERROR_DOM_DATA_CLONE_ERR;
event->SetJSData(buffer);
return NS_DispatchToCurrentThread(event); return NS_DispatchToCurrentThread(event);
} }

View File

@ -80,8 +80,8 @@ class nsIArray;
class nsPIWindowRoot; class nsPIWindowRoot;
#define NS_PIDOMWINDOW_IID \ #define NS_PIDOMWINDOW_IID \
{ 0xafc4849b, 0x21d3, 0x45ea, \ { 0x176e69ce, 0x25d3, 0x4f2a, \
{ 0x8b, 0xfd, 0x61, 0xec, 0x12, 0x5d, 0x38, 0x64 } } { 0x9d, 0x99, 0x81, 0xa3, 0x9a, 0xfd, 0xe2, 0xf0 } }
class nsPIDOMWindow : public nsIDOMWindowInternal class nsPIDOMWindow : public nsIDOMWindowInternal
{ {

View File

@ -39,6 +39,10 @@
#include "nsIDOMWindow2.idl" #include "nsIDOMWindow2.idl"
%{ C++
#include "jspubtd.h"
%}
interface nsIPrompt; interface nsIPrompt;
interface nsIControllers; interface nsIControllers;
interface nsIDOMLocation; interface nsIDOMLocation;
@ -46,7 +50,7 @@ interface nsIVariant;
interface nsIAnimationFrameListener; interface nsIAnimationFrameListener;
interface nsIDOMMediaQueryList; interface nsIDOMMediaQueryList;
[scriptable, uuid(4d95736f-8130-43cb-a276-5bc554eca80a)] [scriptable, uuid(3a7b0839-b9d6-42ff-8ba6-910aba60a966)]
interface nsIDOMWindowInternal : nsIDOMWindow2 interface nsIDOMWindowInternal : nsIDOMWindow2
{ {
readonly attribute nsIDOMWindowInternal window; readonly attribute nsIDOMWindowInternal window;
@ -214,8 +218,8 @@ interface nsIDOMWindowInternal : nsIDOMWindow2
* *
* See the WHATWG HTML5 specification, section 6.4, for more details. * See the WHATWG HTML5 specification, section 6.4, for more details.
*/ */
[binaryname(PostMessageMoz)] void postMessage(in DOMString message, [implicit_jscontext, binaryname(PostMessageMoz)]
in DOMString targetOrigin); void postMessage(in jsval message, in DOMString targetOrigin);
/** /**
* Returns the number of times this document for this window has * Returns the number of times this document for this window has

View File

@ -38,6 +38,10 @@
#include "nsIDOMEvent.idl" #include "nsIDOMEvent.idl"
%{ C++
#include "jspubtd.h"
%}
/** /**
* The nsIDOMMessageEvent interface is used for server-sent events and for * The nsIDOMMessageEvent interface is used for server-sent events and for
* cross-domain messaging. * cross-domain messaging.
@ -45,13 +49,13 @@
* For more information on this interface, please see * For more information on this interface, please see
* http://www.whatwg.org/specs/web-apps/current-work/#messageevent * http://www.whatwg.org/specs/web-apps/current-work/#messageevent
*/ */
[scriptable, uuid(d02e9a24-e5b2-47e4-bd80-7e980bf56b45)] [scriptable, uuid(dc8ec5c6-ebf2-4f95-be99-cd13e3c0d0c6)]
interface nsIDOMMessageEvent : nsIDOMEvent interface nsIDOMMessageEvent : nsIDOMEvent
{ {
/** /**
* Custom string data associated with this event. * Custom string data associated with this event.
*/ */
readonly attribute DOMString data; readonly attribute jsval data;
/** /**
* The origin of the site from which this event originated, which is the * The origin of the site from which this event originated, which is the
@ -80,7 +84,7 @@ interface nsIDOMMessageEvent : nsIDOMEvent
void initMessageEvent(in DOMString aType, void initMessageEvent(in DOMString aType,
in boolean aCanBubble, in boolean aCanBubble,
in boolean aCancelable, in boolean aCancelable,
in DOMString aData, in jsval aData,
in DOMString aOrigin, in DOMString aOrigin,
in DOMString aLastEventId, in DOMString aLastEventId,
in nsIDOMWindow aSource); in nsIDOMWindow aSource);

View File

@ -49,6 +49,9 @@ function onMessageReceived(event)
// Any other message indicates error, succes or todo message of a test // Any other message indicates error, succes or todo message of a test
default: default:
if (typeof event.data == "undefined")
break; // XXXkhuey this receives undefined values
// (which used to become empty strings) on occasion ...
if (event.data.match(todoRegExp)) if (event.data.match(todoRegExp))
SimpleTest.todo(false, event.data); SimpleTest.todo(false, event.data);
else else

View File

@ -80,6 +80,9 @@ _TEST_FILES = \
test_bug500328.html \ test_bug500328.html \
file_bug500328_1.html \ file_bug500328_1.html \
file_bug500328_2.html \ file_bug500328_2.html \
test_postMessage_structured_clone.html \
postMessage_structured_clone_helper.js \
postMessage_structured_clone_helper.html \
$(NULL) $(NULL)
_CHROME_FILES = \ _CHROME_FILES = \

View File

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<head>
<title>postMessage structured clone page</title>
<script type="application/javascript;version=1.7"
src="postMessage_structured_clone_helper.js"></script>
<script type="application/javascript">
var generator = new getTestContent()
function eq(lhs, rhs)
{
for(p in lhs)
{
switch(typeof(lhs[p]))
{
case 'object':
if (!eq(lhs[p], rhs[p])) { return false }; break;
case 'function':
if (typeof(rhs[p])=='undefined' || (p != 'equals' && lhs[p].toString() != rhs[p].toString())) { return false; }; break;
default:
if (lhs[p] != rhs[p]) { return false; }
}
}
for(p in rhs)
{
if(typeof(lhs[p])=='undefined') {return false;}
}
return true;
}
function receiveMessage(evt)
{
if (eq(evt.data,generator.next()))
window.parent.postMessage("TEST-PASS", "*");
else
window.parent.postMessage("TEST-FAIL", "*");
}
window.addEventListener("message", receiveMessage, false);
</script>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,16 @@
function getTestContent()
{
yield "hello";
yield 2+3;
yield 12;
yield null;
yield "complex" + "string";
yield new Object();
yield new Date(1306113544);
yield [1, 2, 3, 4, 5];
let obj = new Object();
obj.foo = 3;
obj.bar = "hi";
obj.baz = new Date(1306113544);
yield obj;
}

View File

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=553125
-->
<head>
<title>postMessage uses structured clone</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript;version=1.7"
src="postMessage_structured_clone_helper.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=553125">Mozilla Bug 553125</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<iframe src="http://mochi.test:8888/tests/dom/tests/mochitest/whatwg/postMessage_structured_clone_helper.html"
name="sameDomain"></iframe>
<iframe src="http://example.org:8000/tests/dom/tests/mochitest/whatwg/postMessage_structured_clone_helper.html"
name="crossDomain"></iframe>
<pre id="test">
<script class="testbody" type="application/javascript">
/** Test for Bug 553125 **/
SimpleTest.waitForExplicitFinish();
var lastMessage = null;
var crossOrigin = false;
var generator = new getTestContent();
function runNextSameOrigin() {
try {
lastMessage = generator.next();
} catch (e) {
generator = new getTestContent();
crossOrigin = true;
runNextCrossOrigin();
}
window.frames.sameDomain.postMessage(lastMessage, "http://mochi.test:8888");
}
function runNextCrossOrigin() {
try {
lastMessage = generator.next();
} catch (e) {
SimpleTest.finish();
}
window.frames.crossDomain.postMessage(lastMessage, "http://example.org:8000");
}
function receiveMessage(evt) {
if (evt.data == "TEST-PASS")
SimpleTest.ok(true, "structured clone of | " + lastMessage + " | succeeded");
else
SimpleTest.ok(false, "structured clone of | " + lastMessage + " | failed");
setTimeout(crossOrigin ? runNextCrossOrigin : runNextSameOrigin, 0);
}
window.addEventListener("message", receiveMessage, false);
window.addEventListener("load", runNextSameOrigin, false);
</script>
</pre>
</body>
</html>