diff --git a/dom/base/Makefile.in b/dom/base/Makefile.in index d2d81f42744..c492f3ec512 100644 --- a/dom/base/Makefile.in +++ b/dom/base/Makefile.in @@ -88,6 +88,11 @@ EXPORTS = \ nsDOMMemoryReporter.h \ $(NULL) +EXPORTS_NAMESPACES = mozilla/dom +EXPORTS_mozilla/dom = \ + StructuredCloneTags.h \ + $(NULL) + CPPSRCS = \ nsBarProps.cpp \ nsDOMException.cpp \ diff --git a/dom/base/StructuredCloneTags.h b/dom/base/StructuredCloneTags.h new file mode 100644 index 00000000000..d866c75f86e --- /dev/null +++ b/dom/base/StructuredCloneTags.h @@ -0,0 +1,55 @@ +/* ***** 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 Structured Clone Code. + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Kyle Huey + * + * 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 StructuredCloneTags_h__ +#define StructuredCloneTags_h__ + +#include "jsapi.h" + +namespace mozilla { +namespace dom { + +enum StructuredCloneTags { + SCTAG_BASE = JS_SCTAG_USER_MIN, + SCTAG_DOM_BLOB, + SCTAG_DOM_FILELIST, + SCTAG_DOM_MAX +}; + +} // namespace dom +} // namespace mozilla + +#endif // StructuredCloneTags_h__ diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index adbd43debb1..2fcfb5631d7 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -179,6 +179,7 @@ #include "nsCSSProps.h" #include "nsFileDataProtocolHandler.h" #include "nsIDOMFile.h" +#include "nsIDOMFileList.h" #include "nsIURIFixup.h" #include "mozilla/FunctionTimer.h" #include "nsCDefaultURIFixup.h" @@ -240,6 +241,8 @@ #include "mozilla/dom/indexedDB/IDBFactory.h" #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h" +#include "mozilla/dom/StructuredCloneTags.h" + #include "nsRefreshDriver.h" #include "mozAutoDocUpdate.h" @@ -5911,7 +5914,6 @@ nsGlobalWindow::CallerInnerWindow() return static_cast(win.get()); } - /** * Class used to represent events generated by calls to Window.postMessage, * which asynchronously creates and dispatches events. @@ -5949,6 +5951,12 @@ class PostMessageEvent : public nsRunnable aBuffer.steal(&mMessage, &mMessageLen); } + bool StoreISupports(nsISupports* aSupports) + { + mSupportsArray.AppendElement(aSupports); + return true; + } + private: nsRefPtr mSource; nsString mCallerOrigin; @@ -5957,8 +5965,102 @@ class PostMessageEvent : public nsRunnable nsRefPtr mTargetWindow; nsCOMPtr mProvidedOrigin; PRBool mTrustedCaller; + nsTArray > mSupportsArray; }; +namespace { + +struct StructuredCloneInfo { + PostMessageEvent* event; + PRBool subsumes; +}; + +static JSObject* +PostMessageReadStructuredClone(JSContext* cx, + JSStructuredCloneReader* reader, + uint32 tag, + uint32 data, + void* closure) +{ + StructuredCloneInfo* scInfo = static_cast(closure); + NS_ASSERTION(scInfo, "Must have scInfo!"); + + if (tag == SCTAG_DOM_BLOB || tag == SCTAG_DOM_FILELIST) { + NS_ASSERTION(!data, "Data should be empty"); + + nsISupports* supports; + if (JS_ReadBytes(reader, &supports, sizeof(supports))) { + JSObject* global = JS_GetGlobalForObject(cx, JS_GetScopeChain(cx)); + if (global) { + jsval val; + nsCOMPtr wrapper; + if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, global, supports, + &val, + getter_AddRefs(wrapper)))) { + return JSVAL_TO_OBJECT(val); + } + } + } + } + + const JSStructuredCloneCallbacks* runtimeCallbacks = + cx->runtime->structuredCloneCallbacks; + + if (runtimeCallbacks) { + return runtimeCallbacks->read(cx, reader, tag, data, nsnull); + } + + return JS_FALSE; +} + +static JSBool +PostMessageWriteStructuredClone(JSContext* cx, + JSStructuredCloneWriter* writer, + JSObject* obj, + void *closure) +{ + StructuredCloneInfo* scInfo = static_cast(closure); + NS_ASSERTION(scInfo, "Must have scInfo!"); + + nsCOMPtr wrappedNative; + nsContentUtils::XPConnect()-> + GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative)); + if (wrappedNative) { + PRUint32 scTag = 0; + nsISupports* supports = wrappedNative->Native(); + + nsCOMPtr blob = do_QueryInterface(supports); + if (blob && scInfo->subsumes) + scTag = SCTAG_DOM_BLOB; + + nsCOMPtr list = do_QueryInterface(supports); + if (list && scInfo->subsumes) + scTag = SCTAG_DOM_FILELIST; + + if (scTag) + return JS_WriteUint32Pair(writer, scTag, 0) && + JS_WriteBytes(writer, &supports, sizeof(supports)) && + scInfo->event->StoreISupports(supports); + } + + const JSStructuredCloneCallbacks* runtimeCallbacks = + cx->runtime->structuredCloneCallbacks; + + if (runtimeCallbacks) { + return runtimeCallbacks->write(cx, writer, obj, nsnull); + } + + return JS_FALSE; +} + +JSStructuredCloneCallbacks kPostMessageCallbacks = { + PostMessageReadStructuredClone, + PostMessageWriteStructuredClone, + nsnull +}; + +} // anonymous namespace + NS_IMETHODIMP PostMessageEvent::Run() { @@ -6046,8 +6148,10 @@ PostMessageEvent::Run() jsval messageData; { JSAutoRequest ar(cx); + StructuredCloneInfo scInfo; + scInfo.event = this; - if (!buffer.read(cx, &messageData, nsnull)) + if (!buffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo)) return NS_ERROR_DOM_DATA_CLONE_ERR; } @@ -6173,8 +6277,14 @@ nsGlobalWindow::PostMessageMoz(const jsval& aMessage, // We *must* clone the data here, or the jsval could be modified // by script JSAutoStructuredCloneBuffer buffer; + StructuredCloneInfo scInfo; + scInfo.event = event; - if (!buffer.write(aCx, aMessage, nsnull, nsnull)) + nsIPrincipal* principal = GetPrincipal(); + if (NS_FAILED(callerPrin->Subsumes(principal, &scInfo.subsumes))) + return NS_ERROR_DOM_DATA_CLONE_ERR; + + if (!buffer.write(aCx, aMessage, &kPostMessageCallbacks, &scInfo)) return NS_ERROR_DOM_DATA_CLONE_ERR; event->SetJSData(buffer); diff --git a/xpcom/Makefile.in b/xpcom/Makefile.in index 8af06ee85bd..ac811ddf906 100644 --- a/xpcom/Makefile.in +++ b/xpcom/Makefile.in @@ -90,3 +90,9 @@ endif include $(topsrcdir)/config/rules.mk +regenerate-idl-parser: + $(PYTHON_PATH) \ + -I$(topsrcdir)/other-licenses/ply \ + -I$(topsrcdir)/xpcom/idl-parser \ + $(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(topsrcdir)/xpcom/idl-parser --regen + diff --git a/xpcom/idl-parser/header.py b/xpcom/idl-parser/header.py index 7ecfa30e424..8d43013134d 100644 --- a/xpcom/idl-parser/header.py +++ b/xpcom/idl-parser/header.py @@ -483,6 +483,8 @@ if __name__ == '__main__': help="Output file (default is stdout)") o.add_option('-d', dest='depfile', default=None, help="Generate a make dependency file") + o.add_option('--regen', action='store_true', dest='regen', default=False, + help="Regenerate IDL Parser cache") options, args = o.parse_args() file, = args @@ -491,6 +493,14 @@ if __name__ == '__main__': os.mkdir(options.cachedir) sys.path.append(options.cachedir) + if options.regen: + if options.cachedir is None: + print >>sys.stderr, "--regen requires --cachedir" + sys.exit(1) + + p = xpidl.IDLParser(outputdir=options.cachedir, regen=True) + sys.exit(0) + if options.depfile is not None and options.outfile is None: print >>sys.stderr, "-d requires -o" sys.exit(1) diff --git a/xpcom/idl-parser/typelib.py b/xpcom/idl-parser/typelib.py index 2b55673f1e7..0c6bc386dfd 100644 --- a/xpcom/idl-parser/typelib.py +++ b/xpcom/idl-parser/typelib.py @@ -281,6 +281,8 @@ if __name__ == '__main__': help="Output file") o.add_option('-d', dest='depfile', default=None, help="Generate a make dependency file") + o.add_option('--regen', action='store_true', dest='regen', default=False, + help="Regenerate IDL Parser cache") options, args = o.parse_args() file, = args @@ -289,6 +291,14 @@ if __name__ == '__main__': os.mkdir(options.cachedir) sys.path.append(options.cachedir) + if options.regen: + if options.cachedir is None: + print >>sys.stderr, "--regen requires --cachedir" + sys.exit(1) + + p = xpidl.IDLParser(outputdir=options.cachedir, regen=True) + sys.exit(0) + if options.depfile is not None and options.outfile is None: print >>sys.stderr, "-d requires -o" sys.exit(1) diff --git a/xpcom/idl-parser/xpidl.py b/xpcom/idl-parser/xpidl.py index d3cbff743fe..f568befc5c8 100644 --- a/xpcom/idl-parser/xpidl.py +++ b/xpcom/idl-parser/xpidl.py @@ -1336,17 +1336,17 @@ class IDLParser(object): location = Location(self.lexer, t.lineno, t.lexpos) raise IDLError("invalid syntax", location) - def __init__(self, outputdir=''): + def __init__(self, outputdir='', regen=False): self._doccomments = [] self.lexer = lex.lex(object=self, outputdir=outputdir, lextab='xpidllex', - optimize=1) + optimize=0 if regen else 1) self.parser = yacc.yacc(module=self, outputdir=outputdir, debugfile='xpidl_debug', tabmodule='xpidlyacc', - optimize=1) + optimize=0 if regen else 1) def clearComments(self): self._doccomments = []