Bug 549682 - Port the message-manager API to mozilla-central, r=jst

--HG--
extra : rebase_source : 45b28a7762428193873a636fa7d5108607f9e4a3
This commit is contained in:
Olli Pettay 2010-05-18 11:52:24 +03:00
parent 45cbd7e1ed
commit af68dc73cd
29 changed files with 1649 additions and 32 deletions

View File

@ -2135,15 +2135,15 @@ nsScriptSecurityManager::GetPrincipalFromContext(JSContext *cx,
{
*result = nsnull;
nsIScriptContext *scriptContext = GetScriptContext(cx);
nsIScriptContextPrincipal* scp =
GetScriptContextPrincipalFromJSContext(cx);
if (!scriptContext)
if (!scp)
{
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIScriptObjectPrincipal> globalData =
do_QueryInterface(scriptContext->GetGlobalObject());
nsIScriptObjectPrincipal* globalData = scp->GetObjectPrincipal();
if (globalData)
NS_IF_ADDREF(*result = globalData->GetPrincipal());
@ -2328,11 +2328,11 @@ nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
return targetPrincipal;
}
nsIScriptContext *scriptContext = GetScriptContext(cx);
if (scriptContext)
nsIScriptContextPrincipal* scp =
GetScriptContextPrincipalFromJSContext(cx);
if (scp)
{
nsCOMPtr<nsIScriptObjectPrincipal> globalData =
do_QueryInterface(scriptContext->GetGlobalObject());
nsIScriptObjectPrincipal* globalData = scp->GetObjectPrincipal();
if (!globalData)
{
*rv = NS_ERROR_FAILURE;

View File

@ -122,6 +122,7 @@ XPIDLSRCS = \
nsIFrameLoader.idl \
nsIXMLHttpRequest.idl \
nsIContentSecurityPolicy.idl \
nsIFrameMessageManager.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -1721,7 +1721,7 @@ public:
PRBool RePush(nsPIDOMEventTarget *aCurrentTarget);
// If a null JSContext is passed to Push(), that will cause no
// push to happen and false to be returned.
PRBool Push(JSContext *cx);
PRBool Push(JSContext *cx, PRBool aRequiresScriptContext = PR_TRUE);
// Explicitly push a null JSContext on the the stack
PRBool PushNull();

View File

@ -41,8 +41,9 @@
interface nsIDocShell;
interface nsIURI;
interface nsIChromeFrameMessageManager;
[scriptable, uuid(d675c531-6bdc-417c-b176-635060105f07)]
[scriptable, uuid(3b256c12-20e1-4fd3-8edb-b9c793919f15)]
interface nsIFrameLoader : nsISupports
{
/**
@ -74,6 +75,9 @@ interface nsIFrameLoader : nsISupports
* or may not be allowed on the loader's docshell.
*/
readonly attribute boolean depthTooGreat;
// Note, when frameloaders are swapped, also messageManagers are swapped.
readonly attribute nsIChromeFrameMessageManager messageManager;
};
native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);

View File

@ -0,0 +1,119 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIDOMWindow;
interface nsIDocShell;
interface nsIContent;
[scriptable, function, uuid(938fcb95-3d63-46be-aa72-94d08fd3b418)]
interface nsIFrameMessageListener : nsISupports
{
/**
* This is for JS only.
* receiveMessage is called with one parameter, which has the following
* properties:
* {
* name: %message name%,
* sync: %true or false%.
* json: %json object or null%,
* objects: %array of cpow or null, always null if sync is false%
* }
* @note objects property isn't implemented yet.
*
* if the message is synchronous, possible return value is sent back
* as JSON.
*
* When the listener is called, 'this' value is the target of the message.
*/
void receiveMessage();
};
[scriptable, uuid(6b736edb-863d-40bd-bca2-62f44da803c0)]
interface nsIFrameMessageManager : nsISupports
{
void addMessageListener(in AString aMessage, in nsIFrameMessageListener aListener);
void removeMessageListener(in AString aMessage, in nsIFrameMessageListener aListener);
void sendAsyncMessage(/*in messageName, in JSON*/);
};
[scriptable, uuid(c56e85b8-6736-4ae2-ae90-66bcef952a82)]
interface nsIContentFrameMessageManager : nsIFrameMessageManager
{
/**
* @note sending JS objects isn't implemented yet.
*
* Returns an array of JSON objects.
*/
void sendSyncMessage(/*in messageName, in JSON, in an array of JS objects,*/);
/**
* The current top level window in the frame or null.
*/
readonly attribute nsIDOMWindow content;
/**
* The top level docshell or null.
*/
readonly attribute nsIDocShell docShell;
/**
* Print a string to stdout.
*/
void dump(in DOMString aStr);
};
[uuid(9c48d557-92fe-4edb-95fc-bfe97e77bdc3)]
interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager
{
[notxpcom] nsIContent getOwnerContent();
};
[scriptable, uuid(ed6522fd-ffb6-4920-b50d-cf629309616b)]
interface nsIChromeFrameMessageManager : nsIFrameMessageManager
{
/*
* Load a script in the (remote) frame. aURL must be the absolute URL.
* data: URLs are also supported. For example data:,dump("foo\n");
* If aAllowDelayedLoad is true, script will be loaded when the
* remote frame becomes available. Otherwise the script will be loaded
* only if the frame is already available.
*/
void loadFrameScript(in AString aURL, in boolean aAllowDelayedLoad);
};

View File

@ -144,6 +144,8 @@ CPPSRCS = \
nsXMLNameSpaceMap.cpp \
Link.cpp \
nsFileDataProtocolHandler.cpp \
nsFrameMessageManager.cpp \
nsInProcessTabChildGlobal.cpp \
$(NULL)
GQI_SRCS = contentbase.gqi

View File

@ -2699,6 +2699,12 @@ nsCxPusher::Push(nsPIDOMEventTarget *aCurrentTarget)
NS_ENSURE_SUCCESS(rv, PR_FALSE);
if (!scx) {
// The target may have a special JS context for event handlers.
JSContext* cx = aCurrentTarget->GetJSContextForEventHandlers();
if (cx) {
DoPush(cx);
}
// Nothing to do here, I guess. Have to return true so that event firing
// will still work correctly even if there is no associated JSContext
return PR_TRUE;
@ -2748,7 +2754,7 @@ nsCxPusher::RePush(nsPIDOMEventTarget *aCurrentTarget)
}
PRBool
nsCxPusher::Push(JSContext *cx)
nsCxPusher::Push(JSContext *cx, PRBool aRequiresScriptContext)
{
if (mPushedSomething) {
NS_ERROR("Whaaa! No double pushing with nsCxPusher::Push()!");
@ -2764,7 +2770,7 @@ nsCxPusher::Push(JSContext *cx)
// XXXbz do we really need to? If we don't get one of these in Pop(), is
// that really a problem? Or do we need to do this to effectively root |cx|?
mScx = GetScriptContextFromJSContext(cx);
if (!mScx) {
if (!mScx && aRequiresScriptContext) {
// Should probably return PR_FALSE. See bug 416916.
return PR_TRUE;
}
@ -3188,14 +3194,22 @@ nsContentUtils::DispatchChromeEvent(nsIDocument *aDoc,
NS_ASSERTION(aDoc, "GetEventAndTarget lied?");
if (!aDoc->GetWindow())
return NS_ERROR_INVALID_ARG;
if (!aDoc->GetWindow()->GetChromeEventHandler())
nsPIDOMEventTarget* piTarget = aDoc->GetWindow()->GetChromeEventHandler();
if (!target)
return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(piTarget);
if (flo) {
nsRefPtr<nsFrameLoader> fl = flo->GetFrameLoader();
if (fl) {
nsPIDOMEventTarget* t = fl->GetTabChildGlobalAsEventTarget();
piTarget = t ? t : piTarget;
}
}
nsEventStatus status = nsEventStatus_eIgnore;
rv = aDoc->GetWindow()->GetChromeEventHandler()->DispatchDOMEvent(nsnull,
event,
nsnull,
&status);
rv = piTarget->DispatchDOMEvent(nsnull, event, nsnull, &status);
if (aDefaultAction) {
*aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
}

View File

@ -87,6 +87,8 @@
#include "nsThreadUtils.h"
#include "nsIContentViewer.h"
#include "nsIDOMChromeWindow.h"
#include "nsInProcessTabChildGlobal.h"
class nsAsyncDocShellDestroyer : public nsRunnable
{
@ -124,7 +126,20 @@ public:
// we'd need to re-institute a fixed version of bug 98158.
#define MAX_DEPTH_CONTENT_FRAMES 10
NS_IMPL_CYCLE_COLLECTION_1(nsFrameLoader, mDocShell)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameLoader)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameLoader)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocShell)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mMessageManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChildMessageManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameLoader)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocShell)
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "nsFrameLoader::mMessageManager");
cb.NoteXPCOMChild(static_cast<nsIContentFrameMessageManager*>(tmp->mMessageManager.get()));
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChildMessageManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameLoader)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
@ -831,6 +846,38 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
mOwnerContent = otherContent;
aOther->mOwnerContent = ourContent;
nsRefPtr<nsFrameMessageManager> ourMessageManager = mMessageManager;
nsRefPtr<nsFrameMessageManager> otherMessageManager = aOther->mMessageManager;
// Swap pointers in child message managers.
if (mChildMessageManager) {
nsInProcessTabChildGlobal* tabChild =
static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
tabChild->SetOwner(otherContent);
tabChild->SetChromeMessageManager(otherMessageManager);
}
if (aOther->mChildMessageManager) {
nsInProcessTabChildGlobal* otherTabChild =
static_cast<nsInProcessTabChildGlobal*>(aOther->mChildMessageManager.get());
otherTabChild->SetOwner(ourContent);
otherTabChild->SetChromeMessageManager(ourMessageManager);
}
// Swap and setup things in parent message managers.
nsFrameMessageManager* ourParentManager = mMessageManager ?
mMessageManager->GetParentManager() : nsnull;
nsFrameMessageManager* otherParentManager = aOther->mMessageManager ?
aOther->mMessageManager->GetParentManager() : nsnull;
if (mMessageManager) {
mMessageManager->Disconnect();
mMessageManager->SetParentManager(otherParentManager);
mMessageManager->SetCallbackData(aOther, PR_FALSE);
}
if (aOther->mMessageManager) {
aOther->mMessageManager->Disconnect();
aOther->mMessageManager->SetParentManager(ourParentManager);
aOther->mMessageManager->SetCallbackData(this, PR_FALSE);
}
mMessageManager.swap(aOther->mMessageManager);
aFirstToSwap.swap(aSecondToSwap);
// Drop any cached content viewers in the two session histories.
@ -869,6 +916,13 @@ nsFrameLoader::Destroy()
}
mDestroyCalled = PR_TRUE;
if (mMessageManager) {
mMessageManager->Disconnect();
}
if (mChildMessageManager) {
static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->Disconnect();
}
nsCOMPtr<nsIDocument> doc;
if (mOwnerContent) {
doc = mOwnerContent->GetOwnerDoc();
@ -1019,6 +1073,8 @@ nsFrameLoader::EnsureDocShell()
mDocShell->SetChromeEventHandler(chromeEventHandler);
}
EnsureMessageManager();
// This is nasty, this code (the do_GetInterface(mDocShell) below)
// *must* come *after* the above call to
// mDocShell->SetChromeEventHandler() for the global window to get
@ -1173,3 +1229,101 @@ nsFrameLoader::CreateStaticClone(nsIFrameLoader* aDest)
viewer->SetDOMDocument(clonedDOMDoc);
return NS_OK;
}
bool LoadScript(void* aCallbackData, const nsAString& aURL)
{
nsFrameLoader* fl = static_cast<nsFrameLoader*>(aCallbackData);
nsRefPtr<nsInProcessTabChildGlobal> tabChild =
static_cast<nsInProcessTabChildGlobal*>(fl->GetTabChildGlobalAsEventTarget());
if (tabChild) {
tabChild->LoadFrameScript(aURL);
}
return true;
}
class nsAsyncMessageToChild : public nsRunnable
{
public:
nsAsyncMessageToChild(nsFrameLoader* aFrameLoader,
const nsAString& aMessage, const nsAString& aJSON)
: mFrameLoader(aFrameLoader), mMessage(aMessage), mJSON(aJSON) {}
NS_IMETHOD Run()
{
nsInProcessTabChildGlobal* tabChild =
static_cast<nsInProcessTabChildGlobal*>(mFrameLoader->mChildMessageManager.get());
if (tabChild && tabChild->GetInnerManager()) {
tabChild->GetInnerManager()->
ReceiveMessage(static_cast<nsPIDOMEventTarget*>(tabChild), mMessage,
PR_FALSE, mJSON, nsnull, nsnull);
}
return NS_OK;
}
nsRefPtr<nsFrameLoader> mFrameLoader;
nsString mMessage;
nsString mJSON;
};
bool SendAsyncMessageToChild(void* aCallbackData,
const nsAString& aMessage,
const nsAString& aJSON)
{
nsRefPtr<nsIRunnable> ev =
new nsAsyncMessageToChild(static_cast<nsFrameLoader*>(aCallbackData),
aMessage, aJSON);
NS_DispatchToCurrentThread(ev);
return true;
}
NS_IMETHODIMP
nsFrameLoader::GetMessageManager(nsIChromeFrameMessageManager** aManager)
{
NS_IF_ADDREF(*aManager = mMessageManager);
return NS_OK;
}
nsresult
nsFrameLoader::EnsureMessageManager()
{
NS_ENSURE_STATE(mOwnerContent);
//XXX Should we create message manager also for chrome iframes?
if (!mIsTopLevelContent) {
return NS_OK;
}
EnsureDocShell();
if (mMessageManager) {
return NS_OK;
}
nsresult rv = NS_OK;
nsIScriptContext* sctx = mOwnerContent->GetContextForEventHandlers(&rv);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(sctx);
JSContext* cx = static_cast<JSContext*>(sctx->GetNativeContext());
NS_ENSURE_STATE(cx);
nsCOMPtr<nsIDOMChromeWindow> chromeWindow =
do_QueryInterface(mOwnerContent->GetOwnerDoc()->GetWindow());
NS_ENSURE_STATE(chromeWindow);
nsCOMPtr<nsIChromeFrameMessageManager> parentManager;
chromeWindow->GetMessageManager(getter_AddRefs(parentManager));
mMessageManager = new nsFrameMessageManager(PR_TRUE,
nsnull,
SendAsyncMessageToChild,
LoadScript,
this,
static_cast<nsFrameMessageManager*>(parentManager.get()),
cx);
NS_ENSURE_TRUE(mMessageManager, NS_ERROR_OUT_OF_MEMORY);
mChildMessageManager =
new nsInProcessTabChildGlobal(mDocShell, mOwnerContent, mMessageManager);
return NS_OK;
}
nsPIDOMEventTarget*
nsFrameLoader::GetTabChildGlobalAsEventTarget()
{
return static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
}

View File

@ -48,10 +48,12 @@
#include "nsStringFwd.h"
#include "nsIFrameLoader.h"
#include "nsIURI.h"
#include "nsFrameMessageManager.h"
class nsIContent;
class nsIURI;
class nsIFrameFrame;
class nsIInProcessContentFrameMessageManager;
class nsFrameLoader : public nsIFrameLoader
{
@ -80,7 +82,7 @@ public:
nsresult ReallyStartLoading();
void Finalize();
nsIDocShell* GetExistingDocShell() { return mDocShell; }
nsPIDOMEventTarget* GetTabChildGlobalAsEventTarget();
nsresult CreateStaticClone(nsIFrameLoader* aDest);
/**
@ -109,6 +111,7 @@ public:
private:
NS_HIDDEN_(nsresult) EnsureDocShell();
nsresult EnsureMessageManager();
NS_HIDDEN_(void) GetURL(nsString& aURL);
nsresult CheckURILoad(nsIURI* aURI);
void FireErrorEvent();
@ -117,6 +120,11 @@ private:
nsCOMPtr<nsIDocShell> mDocShell;
nsCOMPtr<nsIURI> mURIToLoad;
nsIContent *mOwnerContent; // WEAK
public:
// public because a callback needs these.
nsRefPtr<nsFrameMessageManager> mMessageManager;
nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager;
private:
PRPackedBool mDepthTooGreat : 1;
PRPackedBool mIsTopLevelContent : 1;
PRPackedBool mDestroyCalled : 1;

View File

@ -0,0 +1,457 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsFrameMessageManager.h"
#include "nsContentUtils.h"
#include "nsIXPConnect.h"
#include "jsapi.h"
#include "jsarray.h"
#include "jsinterp.h"
#include "nsJSUtils.h"
NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameMessageManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameMessageManager)
PRUint32 count = tmp->mListeners.Length();
for (PRUint32 i = 0; i < count; i++) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mListeners[i] mListener");
cb.NoteXPCOMChild(tmp->mListeners[i].mListener.get());
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mChildManagers)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameMessageManager)
tmp->mListeners.Clear();
for (PRInt32 i = tmp->mChildManagers.Count(); i > 0; --i) {
static_cast<nsFrameMessageManager*>(tmp->mChildManagers[i - 1])->
Disconnect(PR_FALSE);
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mChildManagers)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameMessageManager)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentFrameMessageManager)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIFrameMessageManager, nsIContentFrameMessageManager)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIContentFrameMessageManager, !mChrome)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIChromeFrameMessageManager, mChrome)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsFrameMessageManager,
nsIContentFrameMessageManager)
NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsFrameMessageManager,
nsIContentFrameMessageManager)
NS_IMETHODIMP
nsFrameMessageManager::AddMessageListener(const nsAString& aMessage,
nsIFrameMessageListener* aListener)
{
nsCOMPtr<nsIAtom> message = do_GetAtom(aMessage);
PRUint32 len = mListeners.Length();
for (PRUint32 i = 0; i < len; ++i) {
if (mListeners[i].mMessage == message &&
mListeners[i].mListener == aListener) {
return NS_OK;
}
}
nsMessageListenerInfo* entry = mListeners.AppendElement();
NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
entry->mMessage = message;
entry->mListener = aListener;
return NS_OK;
}
NS_IMETHODIMP
nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessage,
nsIFrameMessageListener* aListener)
{
nsCOMPtr<nsIAtom> message = do_GetAtom(aMessage);
PRUint32 len = mListeners.Length();
for (PRUint32 i = 0; i < len; ++i) {
if (mListeners[i].mMessage == message &&
mListeners[i].mListener == aListener) {
mListeners.RemoveElementAt(i);
return NS_OK;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsFrameMessageManager::LoadFrameScript(const nsAString& aURL,
PRBool aAllowDelayedLoad)
{
if (aAllowDelayedLoad && !mCallbackData && !mChildManagers.Count()) {
mPendingScripts.AppendElement(aURL);
return NS_OK;
}
if (mCallbackData) {
#ifdef DEBUG_smaug
printf("Will load %s \n", NS_ConvertUTF16toUTF8(aURL).get());
#endif
NS_ENSURE_TRUE(mLoadScriptCallback(mCallbackData, aURL), NS_ERROR_FAILURE);
}
PRInt32 len = mChildManagers.Count();
for (PRInt32 i = 0; i < len; ++i) {
static_cast<nsFrameMessageManager*>(mChildManagers[i])->LoadFrameScript(aURL,
PR_FALSE);
}
return NS_OK;
}
static JSBool
JSONCreator(const jschar* aBuf, uint32 aLen, void* aData)
{
nsAString* result = static_cast<nsAString*>(aData);
result->Append((PRUnichar*)aBuf, (PRUint32)aLen);
return JS_TRUE;
}
nsresult
nsFrameMessageManager::GetParamsForMessage(nsAString& aMessageName,
nsAString& aJSON)
{
aMessageName.Truncate();
aJSON.Truncate();
nsAXPCNativeCallContext* ncc = nsnull;
nsresult rv = nsContentUtils::XPConnect()->GetCurrentNativeCallContext(&ncc);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(ncc);
JSContext* ctx = nsnull;
rv = ncc->GetJSContext(&ctx);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 argc;
jsval* argv = nsnull;
ncc->GetArgc(&argc);
ncc->GetArgvPtr(&argv);
JSAutoRequest ar(ctx);
JSString* str;
if (argc && (str = JS_ValueToString(ctx, argv[0])) && str) {
aMessageName.Assign(nsDependentJSString(str));
}
if (argc >= 2) {
jsval v = argv[1];
nsAutoGCRoot root(&v, &rv);
NS_ENSURE_SUCCESS(rv, JS_FALSE);
if (JS_TryJSON(ctx, &v)) {
JS_Stringify(ctx, &v, nsnull, JSVAL_NULL, JSONCreator, &aJSON);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsFrameMessageManager::SendSyncMessage()
{
if (mSyncCallback) {
NS_ENSURE_TRUE(mCallbackData, NS_ERROR_NOT_INITIALIZED);
nsString messageName;
nsString json;
nsresult rv = GetParamsForMessage(messageName, json);
NS_ENSURE_SUCCESS(rv, rv);
nsTArray<nsString> retval;
if (mSyncCallback(mCallbackData, messageName, json, &retval)) {
nsAXPCNativeCallContext* ncc = nsnull;
rv = nsContentUtils::XPConnect()->GetCurrentNativeCallContext(&ncc);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(ncc);
JSContext* ctx = nsnull;
rv = ncc->GetJSContext(&ctx);
NS_ENSURE_SUCCESS(rv, rv);
JSAutoRequest ar(ctx);
PRUint32 len = retval.Length();
jsval* dest = nsnull;
JSObject* dataArray = js_NewArrayObjectWithCapacity(ctx, len, &dest);
NS_ENSURE_TRUE(dataArray, NS_ERROR_OUT_OF_MEMORY);
nsAutoGCRoot arrayGCRoot(&dataArray, &rv);
NS_ENSURE_SUCCESS(rv, rv);
for (PRUint32 i = 0; i < len; ++i) {
jsval ret = JSVAL_VOID;
nsAutoGCRoot root(&ret, &rv);
NS_ENSURE_SUCCESS(rv, rv);
JSONParser* parser = JS_BeginJSONParse(ctx, &ret);
JSBool ok = JS_ConsumeJSONText(ctx, parser, (jschar*)retval[i].get(),
(uint32)retval[i].Length());
ok = JS_FinishJSONParse(ctx, parser, JSVAL_NULL) && ok;
if (ok) {
dest[i] = ret;
}
}
jsval* retvalPtr;
ncc->GetRetValPtr(&retvalPtr);
*retvalPtr = OBJECT_TO_JSVAL(dataArray);
ncc->SetReturnValueWasSet(PR_TRUE);
}
}
NS_ASSERTION(!mParentManager, "Should not have parent manager in content!");
return NS_OK;
}
nsresult
nsFrameMessageManager::SendAsyncMessageInternal(const nsAString& aMessage,
const nsAString& aJSON)
{
if (mAsyncCallback) {
NS_ENSURE_TRUE(mCallbackData, NS_ERROR_NOT_INITIALIZED);
mAsyncCallback(mCallbackData, aMessage, aJSON);
}
PRInt32 len = mChildManagers.Count();
for (PRInt32 i = 0; i < len; ++i) {
static_cast<nsFrameMessageManager*>(mChildManagers[i])->
SendAsyncMessageInternal(aMessage, aJSON);
}
return NS_OK;
}
NS_IMETHODIMP
nsFrameMessageManager::SendAsyncMessage()
{
nsString messageName;
nsString json;
nsresult rv = GetParamsForMessage(messageName, json);
NS_ENSURE_SUCCESS(rv, rv);
return SendAsyncMessageInternal(messageName, json);
}
NS_IMETHODIMP
nsFrameMessageManager::Dump(const nsAString& aStr)
{
fputs(NS_ConvertUTF16toUTF8(aStr).get(), stdout);
fflush(stdout);
return NS_OK;
}
NS_IMETHODIMP
nsFrameMessageManager::GetContent(nsIDOMWindow** aContent)
{
*aContent = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsFrameMessageManager::GetDocShell(nsIDocShell** aDocShell)
{
*aDocShell = nsnull;
return NS_OK;
}
nsresult
nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
const nsAString& aMessage,
PRBool aSync, const nsAString& aJSON,
JSObject* aObjectsArray,
nsTArray<nsString>* aJSONRetVal)
{
if (mListeners.Length()) {
nsCOMPtr<nsIAtom> name = do_GetAtom(aMessage);
nsRefPtr<nsFrameMessageManager> kungfuDeathGrip(this);
for (PRUint32 i = 0; i < mListeners.Length(); ++i) {
if (mListeners[i].mMessage == name) {
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS =
do_QueryInterface(mListeners[i].mListener);
if (!wrappedJS) {
continue;
}
JSObject* object = nsnull;
wrappedJS->GetJSObject(&object);
if (!object) {
continue;
}
nsCxPusher pusher;
NS_ENSURE_STATE(pusher.Push(mContext, PR_FALSE));
JSAutoRequest ar(mContext);
// The parameter for the listener function.
JSObject* param = JS_NewObject(mContext, NULL, NULL, NULL);
NS_ENSURE_TRUE(param, NS_ERROR_OUT_OF_MEMORY);
nsresult rv;
nsAutoGCRoot resultGCRoot(&param, &rv);
NS_ENSURE_SUCCESS(rv, rv);
jsval targetv;
nsAutoGCRoot resultGCRoot2(&targetv, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsContentUtils::WrapNative(mContext,
JS_GetGlobalObject(mContext),
aTarget, &targetv);
// To keep compatibility with e10s message manager,
// define empty objects array.
if (!aObjectsArray) {
jsval* dest = nsnull;
// Because we want JS messages to have always the same properties,
// create array even if len == 0.
aObjectsArray = js_NewArrayObjectWithCapacity(mContext, 0, &dest);
if (!aObjectsArray) {
return false;
}
}
nsAutoGCRoot arrayGCRoot(&aObjectsArray, &rv);
NS_ENSURE_SUCCESS(rv, rv);
jsval json = JSVAL_NULL;
nsAutoGCRoot root(&json, &rv);
if (NS_SUCCEEDED(rv) && !aJSON.IsEmpty()) {
JSONParser* parser = JS_BeginJSONParse(mContext, &json);
if (parser) {
JSBool ok = JS_ConsumeJSONText(mContext, parser,
(jschar*)nsString(aJSON).get(),
(uint32)aJSON.Length());
ok = JS_FinishJSONParse(mContext, parser, JSVAL_NULL) && ok;
if (!ok) {
json = JSVAL_NULL;
}
}
}
JSString* jsMessage =
JS_NewUCStringCopyN(mContext,
reinterpret_cast<const jschar *>(nsString(aMessage).get()),
aMessage.Length());
NS_ENSURE_TRUE(jsMessage, NS_ERROR_OUT_OF_MEMORY);
JS_DefineProperty(mContext, param, "target", targetv, NULL, NULL, JSPROP_ENUMERATE);
JS_DefineProperty(mContext, param, "name",
STRING_TO_JSVAL(jsMessage), NULL, NULL, JSPROP_ENUMERATE);
JS_DefineProperty(mContext, param, "sync",
BOOLEAN_TO_JSVAL(aSync), NULL, NULL, JSPROP_ENUMERATE);
JS_DefineProperty(mContext, param, "json", json, NULL, NULL, JSPROP_ENUMERATE);
JS_DefineProperty(mContext, param, "objects", OBJECT_TO_JSVAL(aObjectsArray),
NULL, NULL, JSPROP_ENUMERATE);
jsval thisValue = JSVAL_VOID;
nsAutoGCRoot resultGCRoot3(&thisValue, &rv);
NS_ENSURE_SUCCESS(rv, rv);
jsval funval = JSVAL_VOID;
if (JS_ObjectIsFunction(mContext, object)) {
// If the listener is a JS function:
funval = OBJECT_TO_JSVAL(object);
nsCOMPtr<nsISupports> defaultThisValue =
do_QueryInterface(static_cast<nsIContentFrameMessageManager*>(this));
nsContentUtils::WrapNative(mContext,
JS_GetGlobalObject(mContext),
defaultThisValue, &thisValue);
} else {
// If the listener is a JS object which has receiveMessage function:
NS_ENSURE_STATE(JS_GetProperty(mContext, object, "receiveMessage",
&funval) &&
JSVAL_IS_OBJECT(funval) &&
!JSVAL_IS_NULL(funval));
JSObject* funobject = JSVAL_TO_OBJECT(funval);
NS_ENSURE_STATE(JS_ObjectIsFunction(mContext, funobject));
thisValue = OBJECT_TO_JSVAL(object);
}
jsval rval = JSVAL_VOID;
nsAutoGCRoot resultGCRoot4(&rval, &rv);
NS_ENSURE_SUCCESS(rv, rv);
void* mark = nsnull;
jsval* argv = js_AllocStack(mContext, 1, &mark);
NS_ENSURE_TRUE(argv, NS_ERROR_OUT_OF_MEMORY);
argv[0] = OBJECT_TO_JSVAL(param);
JSObject* thisObject = JSVAL_TO_OBJECT(thisValue);
JS_CallFunctionValue(mContext, thisObject,
funval, 1, argv, &rval);
if (aJSONRetVal) {
nsString json;
if (JS_TryJSON(mContext, &rval) &&
JS_Stringify(mContext, &rval, nsnull, JSVAL_NULL,
JSONCreator, &json)) {
aJSONRetVal->AppendElement(json);
}
}
js_FreeStack(mContext, mark);
}
}
}
return mParentManager ? mParentManager->ReceiveMessage(aTarget, aMessage,
aSync, aJSON, aObjectsArray,
aJSONRetVal) : NS_OK;
}
void
nsFrameMessageManager::AddChildManager(nsFrameMessageManager* aManager,
PRBool aLoadScripts)
{
mChildManagers.AppendObject(aManager);
if (aLoadScripts) {
for (PRUint32 i = 0; i < mPendingScripts.Length(); ++i) {
aManager->LoadFrameScript(mPendingScripts[i], PR_FALSE);
}
}
}
void
nsFrameMessageManager::SetCallbackData(void* aData, PRBool aLoadScripts)
{
if (aData && mCallbackData != aData) {
mCallbackData = aData;
// First load global scripts by adding this to parent manager.
if (mParentManager) {
mParentManager->AddChildManager(this, aLoadScripts);
}
if (aLoadScripts) {
for (PRUint32 i = 0; i < mPendingScripts.Length(); ++i) {
LoadFrameScript(mPendingScripts[i], PR_FALSE);
}
}
}
}
void
nsFrameMessageManager::Disconnect(PRBool aRemoveFromParent)
{
if (mParentManager && aRemoveFromParent) {
mParentManager->RemoveChildManager(this);
}
mParentManager = nsnull;
mCallbackData = nsnull;
}

View File

@ -0,0 +1,143 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 ***** */
#ifndef nsFrameMessageManager_h__
#define nsFrameMessageManager_h__
#include "nsIFrameMessageManager.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsCOMArray.h"
#include "nsTArray.h"
#include "nsIAtom.h"
#include "nsCycleCollectionParticipant.h"
#include "nsTArray.h"
class nsAXPCNativeCallContext;
struct JSContext;
struct JSObject;
struct nsMessageListenerInfo
{
nsCOMPtr<nsIFrameMessageListener> mListener;
nsCOMPtr<nsIAtom> mMessage;
};
typedef bool (*nsLoadScriptCallback)(void* aCallbackData, const nsAString& aURL);
typedef bool (*nsSyncMessageCallback)(void* aCallbackData,
const nsAString& aMessage,
const nsAString& aJSON,
nsTArray<nsString>* aJSONRetVal);
typedef bool (*nsAsyncMessageCallback)(void* aCallbackData,
const nsAString& aMessage,
const nsAString& aJSON);
class nsFrameMessageManager : public nsIContentFrameMessageManager,
public nsIChromeFrameMessageManager
{
public:
nsFrameMessageManager(PRBool aChrome,
nsSyncMessageCallback aSyncCallback,
nsAsyncMessageCallback aAsyncCallback,
nsLoadScriptCallback aLoadScriptCallback,
void* aCallbackData,
nsFrameMessageManager* aParentManager,
JSContext* aContext)
: mChrome(aChrome), mParentManager(aParentManager),
mSyncCallback(aSyncCallback), mAsyncCallback(aAsyncCallback),
mLoadScriptCallback(aLoadScriptCallback), mCallbackData(aCallbackData),
mContext(aContext)
{
NS_ASSERTION(mContext, "Should have mContext!");
NS_ASSERTION(aChrome || !aParentManager, "Should not set parent manager!");
if (mParentManager && mCallbackData) {
mParentManager->AddChildManager(this);
}
}
~nsFrameMessageManager()
{
for (PRInt32 i = mChildManagers.Count(); i > 0; --i) {
static_cast<nsFrameMessageManager*>(mChildManagers[i - 1])->
Disconnect(PR_FALSE);
}
}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameMessageManager,
nsIContentFrameMessageManager)
NS_DECL_NSIFRAMEMESSAGEMANAGER
NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
NS_DECL_NSICHROMEFRAMEMESSAGEMANAGER
nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
PRBool aSync, const nsAString& aJSON,
JSObject* aObjectsArray,
nsTArray<nsString>* aJSONRetVal);
void AddChildManager(nsFrameMessageManager* aManager,
PRBool aLoadScripts = PR_TRUE);
void RemoveChildManager(nsFrameMessageManager* aManager)
{
mChildManagers.RemoveObject(aManager);
}
void Disconnect(PRBool aRemoveFromParent = PR_TRUE);
void SetCallbackData(void* aData, PRBool aLoadScripts = PR_TRUE);
nsresult GetParamsForMessage(nsAString& aMessageName, nsAString& aJSON);
nsresult SendAsyncMessageInternal(const nsAString& aMessage,
const nsAString& aJSON);
JSContext* GetJSContext() { return mContext; }
nsFrameMessageManager* GetParentManager() { return mParentManager; }
void SetParentManager(nsFrameMessageManager* aParent)
{
NS_ASSERTION(!mParentManager, "We have parent manager already!");
NS_ASSERTION(mChrome, "Should not set parent manager!");
mParentManager = aParent;
}
protected:
nsTArray<nsMessageListenerInfo> mListeners;
nsCOMArray<nsIContentFrameMessageManager> mChildManagers;
PRBool mChrome;
nsFrameMessageManager* mParentManager;
nsSyncMessageCallback mSyncCallback;
nsAsyncMessageCallback mAsyncCallback;
nsLoadScriptCallback mLoadScriptCallback;
void* mCallbackData;
JSContext* mContext;
nsTArray<nsString> mPendingScripts;
};
#endif

View File

@ -0,0 +1,366 @@
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */
/* vim: set sw=4 ts=8 et 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 Mozilla Content App.
*
* 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):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsInProcessTabChildGlobal.h"
#include "nsContentUtils.h"
#include "nsIScriptSecurityManager.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsEventDispatcher.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIJSRuntimeService.h"
#include "nsComponentManagerUtils.h"
#include "nsNetUtil.h"
#include "nsScriptLoader.h"
#include "nsIJSContextStack.h"
#include "nsFrameLoader.h"
bool SendSyncMessageToParent(void* aCallbackData,
const nsAString& aMessage,
const nsAString& aJSON,
nsTArray<nsString>* aJSONRetVal)
{
nsInProcessTabChildGlobal* tabChild =
static_cast<nsInProcessTabChildGlobal*>(aCallbackData);
PRInt32 count = tabChild->mASyncMessages.Count();
for (PRInt32 i = 0; i < count; ++i) {
nsCOMPtr<nsIRunnable> async = tabChild->mASyncMessages.SafeObjectAt(i);
async->Run();
}
if (tabChild->mChromeMessageManager) {
tabChild->mChromeMessageManager->ReceiveMessage(tabChild->mOwner, aMessage, PR_TRUE,
aJSON, nsnull, aJSONRetVal);
}
return true;
}
class nsAsyncMessageToParent : public nsRunnable
{
public:
nsAsyncMessageToParent(nsInProcessTabChildGlobal* aTabChild,
const nsAString& aMessage, const nsAString& aJSON)
: mTabChild(aTabChild), mMessage(aMessage), mJSON(aJSON) {}
NS_IMETHOD Run()
{
mTabChild->mASyncMessages.RemoveObject(this);
if (mTabChild->mChromeMessageManager) {
mTabChild->mChromeMessageManager->ReceiveMessage(mTabChild->mOwner, mMessage,
PR_FALSE,
mJSON, nsnull, nsnull);
}
return NS_OK;
}
nsRefPtr<nsInProcessTabChildGlobal> mTabChild;
nsString mMessage;
nsString mJSON;
};
bool SendAsyncMessageToParent(void* aCallbackData,
const nsAString& aMessage,
const nsAString& aJSON)
{
nsInProcessTabChildGlobal* tabChild =
static_cast<nsInProcessTabChildGlobal*>(aCallbackData);
nsRefPtr<nsIRunnable> ev = new nsAsyncMessageToParent(tabChild, aMessage, aJSON);
tabChild->mASyncMessages.AppendObject(ev);
NS_DispatchToCurrentThread(ev);
return true;
}
static int tabChildC = 0;
nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
nsIContent* aOwner,
nsFrameMessageManager* aChrome)
: mCx(nsnull), mDocShell(aShell), mInitialized(PR_FALSE), mLoadingScript(PR_FALSE),
mDelayedDisconnect(PR_FALSE), mOwner(aOwner), mChromeMessageManager(aChrome)
{
}
nsInProcessTabChildGlobal::~nsInProcessTabChildGlobal()
{
Disconnect();
NS_ASSERTION(!mCx, "Couldn't release JSContext?!?");
}
nsresult
nsInProcessTabChildGlobal::Init()
{
nsresult rv = InitTabChildGlobal();
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"Couldn't initialize nsInProcessTabChildGlobal");
mMessageManager = new nsFrameMessageManager(PR_FALSE,
SendSyncMessageToParent,
SendAsyncMessageToParent,
nsnull,
this,
nsnull,
mCx);
return NS_OK;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsInProcessTabChildGlobal)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsInProcessTabChildGlobal,
nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mMessageManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGlobal)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsInProcessTabChildGlobal,
nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGlobal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal)
NS_INTERFACE_MAP_ENTRY(nsIFrameMessageManager)
NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
NS_INTERFACE_MAP_ENTRY(nsIScriptContextPrincipal)
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(nsInProcessTabChildGlobal, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(nsInProcessTabChildGlobal, nsDOMEventTargetHelper)
NS_IMETHODIMP
nsInProcessTabChildGlobal::GetContent(nsIDOMWindow** aContent)
{
*aContent = nsnull;
nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mDocShell);
window.swap(*aContent);
return NS_OK;
}
NS_IMETHODIMP
nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
{
NS_IF_ADDREF(*aDocShell = mDocShell);
return NS_OK;
}
void
nsInProcessTabChildGlobal::Disconnect()
{
mDocShell = nsnull;
mOwner = nsnull;
mChromeMessageManager = nsnull;
if (mMessageManager) {
static_cast<nsFrameMessageManager*>(mMessageManager.get())->Disconnect();
mMessageManager = nsnull;
}
if (!mLoadingScript) {
if (mCx) {
JS_DestroyContext(mCx);
mCx = nsnull;
}
} else {
mDelayedDisconnect = PR_TRUE;
}
}
NS_IMETHODIMP_(nsIContent *)
nsInProcessTabChildGlobal::GetOwnerContent()
{
return mOwner;
}
nsresult
nsInProcessTabChildGlobal::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
aVisitor.mCanHandle = PR_TRUE;
aVisitor.mParentTarget = mOwner;
#ifdef DEBUG
if (mOwner) {
nsCOMPtr<nsIFrameLoaderOwner> owner = do_QueryInterface(mOwner);
nsRefPtr<nsFrameLoader> fl = owner->GetFrameLoader();
if (fl) {
NS_ASSERTION(this == fl->GetTabChildGlobalAsEventTarget(),
"Wrong event target!");
NS_ASSERTION(fl->mMessageManager == mChromeMessageManager,
"Wrong message manager!");
}
}
#endif
return NS_OK;
}
nsresult
nsInProcessTabChildGlobal::InitTabChildGlobal()
{
nsCOMPtr<nsIJSRuntimeService> runtimeSvc =
do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
NS_ENSURE_STATE(runtimeSvc);
JSRuntime* rt = nsnull;
runtimeSvc->GetRuntime(&rt);
NS_ENSURE_STATE(rt);
JSContext* cx = JS_NewContext(rt, 8192);
NS_ENSURE_STATE(cx);
mCx = cx;
nsContentUtils::XPConnect()->SetSecurityManagerForJSContext(cx, nsContentUtils::GetSecurityManager(), 0);
nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
PRUint32 stackDummy;
jsuword stackLimit, currentStackAddr = (jsuword)&stackDummy;
// 256k stack space.
const jsuword kStackSize = 0x40000;
#if JS_STACK_GROWTH_DIRECTION < 0
stackLimit = (currentStackAddr > kStackSize) ?
currentStackAddr - kStackSize :
0;
#else
stackLimit = (currentStackAddr + kStackSize > currentStackAddr) ?
currentStackAddr + kStackSize :
(jsuword) -1;
#endif
JS_SetThreadStackLimit(cx, stackLimit);
JS_SetScriptStackQuota(cx, 100*1024*1024);
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_JIT | JSOPTION_ANONFUNFIX | JSOPTION_PRIVATE_IS_NSISUPPORTS);
JS_SetVersion(cx, JSVERSION_LATEST);
JS_SetGCParameterForThread(cx, JSGC_MAX_CODE_CACHE_BYTES, 1 * 1024 * 1024);
JSAutoRequest ar(cx);
nsIXPConnect* xpc = nsContentUtils::XPConnect();
const PRUint32 flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES |
/*nsIXPConnect::OMIT_COMPONENTS_OBJECT ? |*/
nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT;
nsISupports* scopeSupports =
NS_ISUPPORTS_CAST(nsPIDOMEventTarget*, this);
JS_SetContextPrivate(cx, scopeSupports);
nsresult rv =
xpc->InitClassesWithNewWrappedGlobal(cx, scopeSupports,
NS_GET_IID(nsISupports), flags,
getter_AddRefs(mGlobal));
NS_ENSURE_SUCCESS(rv, false);
JSObject* global = nsnull;
rv = mGlobal->GetJSObject(&global);
NS_ENSURE_SUCCESS(rv, false);
JS_SetGlobalObject(cx, global);
return NS_OK;
}
void
nsInProcessTabChildGlobal::LoadFrameScript(const nsAString& aURL)
{
if (!mInitialized) {
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()) {
JSAutoRequest ar(mCx);
jsval retval;
JSObject* global = nsnull;
mGlobal->GetJSObject(&global);
if (!global) {
return;
}
JSPrincipals* jsprin = nsnull;
mPrincipal->GetJSPrincipals(mCx, &jsprin);
nsContentUtils::XPConnect()->FlagSystemFilenamePrefix(url.get(), PR_TRUE);
nsContentUtils::ThreadJSContextStack()->Push(mCx);
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);
}
if (!mLoadingScript && mDelayedDisconnect) {
mDelayedDisconnect = PR_FALSE;
Disconnect();
}
}

View File

@ -0,0 +1,142 @@
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */
/* vim: set sw=4 ts=8 et 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 Mozilla Content App.
*
* 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):
*
* 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 ***** */
#ifndef nsInProcessTabChildGlobal_h
#define nsInProcessTabChildGlobal_h
#include "nsCOMPtr.h"
#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 nsIInProcessContentFrameMessageManager,
public nsIScriptObjectPrincipal,
public nsIScriptContextPrincipal
{
public:
nsInProcessTabChildGlobal(nsIDocShell* aShell, nsIContent* aOwner,
nsFrameMessageManager* aChrome);
virtual ~nsInProcessTabChildGlobal();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsInProcessTabChildGlobal,
nsDOMEventTargetHelper)
NS_FORWARD_SAFE_NSIFRAMEMESSAGEMANAGER(mMessageManager)
NS_IMETHOD SendSyncMessage()
{
return mMessageManager ? mMessageManager->SendSyncMessage()
: NS_ERROR_NULL_POINTER;
}
NS_IMETHOD GetContent(nsIDOMWindow** aContent);
NS_IMETHOD GetDocShell(nsIDocShell** aDocShell);
NS_IMETHOD Dump(const nsAString& aStr)
{
return mMessageManager ? mMessageManager->Dump(aStr) : NS_OK;
}
NS_DECL_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
NS_IMETHOD AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
PRBool aUseCapture)
{
// By default add listeners only for trusted events!
return nsDOMEventTargetHelper::AddEventListener(aType, aListener,
aUseCapture, PR_FALSE, 1);
}
NS_IMETHOD AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
PRBool aUseCapture, PRBool aWantsUntrusted,
PRUint8 optional_argc)
{
return nsDOMEventTargetHelper::AddEventListener(aType, aListener,
aUseCapture,
aWantsUntrusted,
optional_argc);
}
virtual nsIScriptObjectPrincipal* GetObjectPrincipal() { return this; }
virtual JSContext* GetJSContextForEventHandlers() { return mCx; }
virtual nsIPrincipal* GetPrincipal() { return mPrincipal; }
void LoadFrameScript(const nsAString& aURL);
void Disconnect();
void SendMessageToParent(const nsString& aMessage, PRBool aSync,
const nsString& aJSON,
nsTArray<nsString>* aJSONRetVal);
nsFrameMessageManager* GetInnerManager()
{
return static_cast<nsFrameMessageManager*>(mMessageManager.get());
}
void SetOwner(nsIContent* aOwner) { mOwner = aOwner; }
nsFrameMessageManager* GetChromeMessageManager()
{
return mChromeMessageManager;
}
void SetChromeMessageManager(nsFrameMessageManager* aParent)
{
mChromeMessageManager = aParent;
}
protected:
nsresult Init();
nsresult InitTabChildGlobal();
nsCOMPtr<nsIContentFrameMessageManager> mMessageManager;
JSContext* mCx;
nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIDocShell> mDocShell;
PRPackedBool mInitialized;
PRPackedBool mLoadingScript;
PRPackedBool mDelayedDisconnect;
public:
nsIContent* mOwner;
nsFrameMessageManager* mChromeMessageManager;
nsCOMArray<nsIRunnable> mASyncMessages;
};
#endif

View File

@ -930,7 +930,7 @@ nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const PRUint8* aData,
DetectByteOrderMark(aData, aLength, characterSet);
}
if (characterSet.IsEmpty()) {
if (characterSet.IsEmpty() && aDocument) {
// charset from document default
characterSet = aDocument->GetDocumentCharacterSet();
}

View File

@ -55,6 +55,8 @@ _CHROME_FILES = \
test_bug467123.xul \
test_title.xul \
title_window.xul \
test_bug549682.xul \
file_bug549682.xul \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,45 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=549682
-->
<window title="Mozilla Bug 549682"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="run()">
<label value="Mozilla Bug 549682"/>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
var didRunAsync = false;
function asyncL(m) {
didRunAsync = true;
opener.wrappedJSObject.is(m.name, "async", "Wrong message!");
opener.wrappedJSObject.is(m.json.data, 1234, "Wrong data!");
}
function syncL(m) {
opener.wrappedJSObject.is(m.name, "sync", "Wrong message!");
opener.wrappedJSObject.is(m.json.data, 1234, "Wrong data!");
opener.wrappedJSObject.ok(didRunAsync, "Should have run async!");
opener.setTimeout("done()", 0);
var i = document.getElementById("ifr");
i.parentNode.removeChild(i); // This is a crash test!
window.close();
}
function loadScript() {
// Async should be prosessed first!
messageManager.loadFrameScript("data:,sendAsyncMessage('async', { data: 1234 }); sendSyncMessage('sync', { data: 1234 });", true);
}
function run() {
messageManager.addMessageListener("async", asyncL);
messageManager.addMessageListener("sync", syncL);
setTimeout(loadScript, 0);
}
]]></script>
<browser type="content" src="about:blank" id="ifr"/>
</window>

View File

@ -0,0 +1,35 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=549682
-->
<window title="Mozilla Bug 549682"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=549682"
target="_blank">Mozilla Bug 549682</a>
</body>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
/** Test for Bug 549682 **/
SimpleTest.waitForExplicitFinish();
function done() {
SimpleTest.finish();
}
addLoadEvent(function() {
window.open("file_bug549682.xul", "", "chrome");
});
]]></script>
</window>

View File

@ -49,11 +49,12 @@ class nsIEventListenerManager;
class nsIDOMEventListener;
class nsIDOMEventGroup;
class nsIScriptContext;
struct JSContext;
// e6579895-a23c-4afc-872a-d53da71def5d
// 89292f3a-535d-4ba0-882a-10cff9e21bcc
#define NS_PIDOMEVENTTARGET_IID \
{ 0xe6579895, 0xa23c, 0x4afc, \
{ 0x87, 0x2a, 0xd5, 0x3d, 0xa7, 0x1d, 0xef, 0x5d } }
{ 0x89292f3a, 0x535d, 0x4ba0, \
{ 0x88, 0x2a, 0x10, 0xcf, 0xf9, 0xe2, 0x1b, 0xcc } }
class nsPIDOMEventTarget : public nsISupports
{
@ -164,6 +165,12 @@ public:
* @note Caller *must* check the value of aRv.
*/
virtual nsIScriptContext* GetContextForEventHandlers(nsresult* aRv) = 0;
/**
* If the method above returns null, but a success code, this method
* is called.
*/
virtual JSContext* GetJSContextForEventHandlers() { return nsnull; }
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMEventTarget, NS_PIDOMEVENTTARGET_IID)

View File

@ -469,6 +469,7 @@
#include "nsIDOMNSMouseEvent.h"
#include "nsIEventListenerService.h"
#include "nsIFrameMessageManager.h"
#include "mozilla/dom/Element.h"
using namespace mozilla::dom;
@ -550,6 +551,7 @@ static const char kDOMStringBundleURL[] =
DOMCI_DATA(Crypto, void)
DOMCI_DATA(CRMFObject, void)
DOMCI_DATA(SmartCardEvent, void)
DOMCI_DATA(ContentFrameMessageManager, void)
DOMCI_DATA(DOMPrototype, void)
DOMCI_DATA(DOMConstructor, void)
@ -1383,6 +1385,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(TransitionEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(ContentFrameMessageManager, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(FormData, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -3834,6 +3838,13 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_EVENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentFrameMessageManager, nsIContentFrameMessageManager)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEventTarget)
DOM_CLASSINFO_MAP_ENTRY(nsIFrameMessageManager)
DOM_CLASSINFO_MAP_ENTRY(nsIContentFrameMessageManager)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(FormData, nsIDOMFormData)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFormData)
DOM_CLASSINFO_MAP_END

View File

@ -468,5 +468,6 @@ DOMCI_CLASS(PopStateEvent)
DOMCI_CLASS(EventListenerInfo)
DOMCI_CLASS(TransitionEvent)
DOMCI_CLASS(ContentFrameMessageManager)
DOMCI_CLASS(FormData)

View File

@ -23,6 +23,22 @@ GetScriptContextFromJSContext(JSContext *cx)
return scx;
}
inline nsIScriptContextPrincipal*
GetScriptContextPrincipalFromJSContext(JSContext *cx)
{
if (!(::JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)) {
return nsnull;
}
nsCOMPtr<nsIScriptContextPrincipal> scx =
do_QueryInterface(static_cast<nsISupports *>
(::JS_GetContextPrivate(cx)));
// This will return a pointer to something that's about to be
// released, but that's ok here.
return scx;
}
// A factory function for turning a jsval argv into an nsIArray
// but also supports an effecient way of extracting the original argv.
// Bug 312003 describes why this must be "void *", but argv will be cast to

View File

@ -204,6 +204,7 @@
#include "nsIDragService.h"
#include "mozilla/dom/Element.h"
#include "nsFrameLoader.h"
#include "nsISupportsPrimitives.h"
#include "nsXPCOMCID.h"
@ -296,6 +297,17 @@ static PRBool gDOMWindowDumpEnabled = PR_FALSE;
} \
PR_END_MACRO
#define FORWARD_TO_INNER_CHROME(method, args, err_rval) \
PR_BEGIN_MACRO \
if (IsOuterWindow()) { \
if (!mInnerWindow) { \
NS_WARNING("No inner window available!"); \
return err_rval; \
} \
return ((nsGlobalChromeWindow *)mInnerWindow)->method args; \
} \
PR_END_MACRO
#define FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(method, args, err_rval) \
PR_BEGIN_MACRO \
if (IsInnerWindow()) { \
@ -2373,7 +2385,16 @@ nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
}
}
aVisitor.mParentTarget = mChromeEventHandler;
nsPIDOMEventTarget* chromeTarget = mChromeEventHandler;
nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(mChromeEventHandler);
if (flo) {
nsRefPtr<nsFrameLoader> fl = flo->GetFrameLoader();
if (fl) {
nsPIDOMEventTarget* t = fl->GetTabChildGlobalAsEventTarget();
chromeTarget = t ? t : chromeTarget;
}
}
aVisitor.mParentTarget = chromeTarget;
return NS_OK;
}
@ -9376,6 +9397,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow,
nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mBrowserDOMWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
DOMCI_DATA(ChromeWindow, nsGlobalChromeWindow)
@ -9608,6 +9630,28 @@ nsGlobalChromeWindow::NotifyDefaultButtonLoaded(nsIDOMElement* aDefaultButton)
#endif
}
NS_IMETHODIMP
nsGlobalChromeWindow::GetMessageManager(nsIChromeFrameMessageManager** aManager)
{
FORWARD_TO_INNER_CHROME(GetMessageManager, (aManager), NS_ERROR_FAILURE);
if (!mMessageManager) {
nsIScriptContext* scx = GetContextInternal();
NS_ENSURE_STATE(scx);
JSContext* cx = (JSContext *)scx->GetNativeContext();
NS_ENSURE_STATE(cx);
mMessageManager = new nsFrameMessageManager(PR_TRUE,
nsnull,
nsnull,
nsnull,
nsnull,
nsnull,
cx);
NS_ENSURE_TRUE(mMessageManager, NS_ERROR_OUT_OF_MEMORY);
}
NS_ADDREF(*aManager = mMessageManager);
return NS_OK;
}
// nsGlobalModalWindow implementation
// QueryInterface implementation for nsGlobalModalWindow

View File

@ -101,6 +101,7 @@
#include "nsPIDOMEventTarget.h"
#include "nsIArray.h"
#include "nsIContent.h"
#include "nsFrameMessageManager.h"
#define DEFAULT_HOME_PAGE "www.mozilla.org"
#define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
@ -858,6 +859,7 @@ public:
protected:
nsCOMPtr<nsIBrowserDOMWindow> mBrowserDOMWindow;
nsCOMPtr<nsIChromeFrameMessageManager> mMessageManager;
};
/*

View File

@ -53,9 +53,25 @@ class nsIVariant;
class nsIObjectInputStream;
class nsIObjectOutputStream;
class nsScriptObjectHolder;
class nsIScriptObjectPrincipal;
typedef void (*nsScriptTerminationFunc)(nsISupports* aRef);
#define NS_ISCRIPTCONTEXTPRINCIPAL_IID \
{ 0xd012cdb3, 0x8f1e, 0x4440, \
{ 0x8c, 0xbd, 0x32, 0x7f, 0x98, 0x1d, 0x37, 0xb4 } }
class nsIScriptContextPrincipal : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTCONTEXTPRINCIPAL_IID)
virtual nsIScriptObjectPrincipal* GetObjectPrincipal() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
NS_ISCRIPTCONTEXTPRINCIPAL_IID)
// A4FE2B52-62B5-40C3-BF9C-5E0A27B10F90
#define NS_ISCRIPTCONTEXT_IID \
{ 0xA4FE2B52, 0x62B5, 0x40C3, \
@ -72,7 +88,7 @@ typedef void (*nsScriptTerminationFunc)(nsISupports* aRef);
* should be removed in a short time. Ideally this interface will be
* language neutral</I>
*/
class nsIScriptContext : public nsISupports
class nsIScriptContext : public nsIScriptContextPrincipal
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTCONTEXT_IID)

View File

@ -1480,6 +1480,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSContext)
NS_INTERFACE_MAP_ENTRY(nsIScriptContext)
NS_INTERFACE_MAP_ENTRY(nsIScriptContextPrincipal)
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptNotify)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptContext)
NS_INTERFACE_MAP_END
@ -1668,6 +1669,13 @@ JSValueToAString(JSContext *cx, jsval val, nsAString *result,
return NS_OK;
}
nsIScriptObjectPrincipal*
nsJSContext::GetObjectPrincipal()
{
nsCOMPtr<nsIScriptObjectPrincipal> prin = do_QueryInterface(GetGlobalObject());
return prin;
}
nsresult
nsJSContext::EvaluateString(const nsAString& aScript,
void *aScopeObject,

View File

@ -65,6 +65,8 @@ public:
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSContext,
nsIScriptContext)
virtual nsIScriptObjectPrincipal* GetObjectPrincipal();
virtual PRUint32 GetScriptTypeID()
{ return nsIProgrammingLanguage::JAVASCRIPT; }

View File

@ -40,8 +40,9 @@
interface nsIBrowserDOMWindow;
interface nsIDOMElement;
interface nsIChromeFrameMessageManager;
[scriptable, uuid(09b86cbd-9784-4fe4-9be6-70b9bbca3a9c)]
[scriptable, uuid(adf6b19f-459f-4892-93eb-71c527bae2af)]
interface nsIDOMChromeWindow : nsISupports
{
const unsigned short STATE_MAXIMIZED = 1;
@ -73,4 +74,6 @@ interface nsIDOMChromeWindow : nsISupports
* defaultButton is the default button.
*/
void notifyDefaultButtonLoaded(in nsIDOMElement defaultButton);
readonly attribute nsIChromeFrameMessageManager messageManager;
};

View File

@ -123,11 +123,10 @@ XPCJSContextStack::Pop(JSContext * *_retval)
static nsIPrincipal*
GetPrincipalFromCx(JSContext *cx)
{
nsIScriptContext* scriptContext = GetScriptContextFromJSContext(cx);
if(scriptContext)
nsIScriptContextPrincipal* scp = GetScriptContextPrincipalFromJSContext(cx);
if(scp)
{
nsCOMPtr<nsIScriptObjectPrincipal> globalData =
do_QueryInterface(scriptContext->GetGlobalObject());
nsIScriptObjectPrincipal* globalData = scp->GetObjectPrincipal();
if(globalData)
return globalData->GetPrincipal();
}

View File

@ -96,6 +96,7 @@
#include "nsObjectFrame.h"
#include "nsTransitionManager.h"
#include "mozilla/dom/Element.h"
#include "nsIFrameMessageManager.h"
#ifdef MOZ_SMIL
#include "nsSMILAnimationController.h"
@ -2052,7 +2053,22 @@ MayHavePaintEventListener(nsPIDOMWindow* aInnerWindow)
if (!chromeEventHandler)
return PR_FALSE;
nsCOMPtr<nsINode> node = do_QueryInterface(chromeEventHandler);
nsIEventListenerManager* manager = nsnull;
nsCOMPtr<nsINode> node;
nsCOMPtr<nsIInProcessContentFrameMessageManager> mm =
do_QueryInterface(chromeEventHandler);
if (mm) {
nsCOMPtr<nsPIDOMEventTarget> target = do_QueryInterface(mm);
if (target && (manager = target->GetListenerManager(PR_FALSE)) &&
manager->MayHavePaintEventListener()) {
return PR_TRUE;
}
node = mm->GetOwnerContent();
}
if (!node) {
node = do_QueryInterface(chromeEventHandler);
}
if (node)
return MayHavePaintEventListener(node->GetOwnerDoc()->GetInnerWindow());
@ -2060,7 +2076,7 @@ MayHavePaintEventListener(nsPIDOMWindow* aInnerWindow)
if (window)
return MayHavePaintEventListener(window);
nsIEventListenerManager* manager =
manager =
chromeEventHandler->GetListenerManager(PR_FALSE);
if (manager && manager->MayHavePaintEventListener())
return PR_TRUE;