mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 551225 - Make pushState use structured clone. r=zpao, sicking
This commit is contained in:
parent
4e3e422fee
commit
a8ba1048dc
@ -1781,8 +1781,9 @@ SessionStoreService.prototype = {
|
||||
entry.docIdentifier = aEntry.docIdentifier;
|
||||
}
|
||||
|
||||
if (aEntry.stateData) {
|
||||
entry.stateData = aEntry.stateData;
|
||||
if (aEntry.stateData != null) {
|
||||
entry.structuredCloneState = aEntry.stateData.getDataAsBase64();
|
||||
entry.structuredCloneVersion = aEntry.stateData.formatVersion;
|
||||
}
|
||||
|
||||
if (!(aEntry instanceof Ci.nsISHContainer)) {
|
||||
@ -2998,8 +2999,13 @@ SessionStoreService.prototype = {
|
||||
if (aEntry.docshellID)
|
||||
shEntry.docshellID = aEntry.docshellID;
|
||||
|
||||
if (aEntry.stateData) {
|
||||
shEntry.stateData = aEntry.stateData;
|
||||
if (aEntry.structuredCloneState && aEntry.structuredCloneVersion) {
|
||||
shEntry.stateData =
|
||||
Cc["@mozilla.org/docshell/structured-clone-container;1"].
|
||||
createInstance(Ci.nsIStructuredCloneContainer);
|
||||
|
||||
shEntry.stateData.initFromBase64(aEntry.structuredCloneState,
|
||||
aEntry.structuredCloneVersion);
|
||||
}
|
||||
|
||||
if (aEntry.scroll) {
|
||||
|
@ -68,8 +68,7 @@ function checkState(tab) {
|
||||
}
|
||||
else if (popStateCount == 1) {
|
||||
popStateCount++;
|
||||
is(JSON.stringify(aEvent.state), JSON.stringify({obj3:3}),
|
||||
"second popstate object.");
|
||||
is(aEvent.state.obj3.toString(), '/^a$/', "second popstate object.");
|
||||
|
||||
// Make sure that the new-elem node is present in the document. If it's
|
||||
// not, then this history entry has a different doc identifier than the
|
||||
@ -120,12 +119,12 @@ function test() {
|
||||
// history entries:
|
||||
// testURL (state object: null) <-- oldest
|
||||
// testURL (state object: {obj1:1})
|
||||
// page2 (state object: {obj3:3}) <-- newest
|
||||
// page2 (state object: {obj3:/^a$/}) <-- newest
|
||||
let contentWindow = tab.linkedBrowser.contentWindow;
|
||||
let history = contentWindow.history;
|
||||
history.pushState({obj1:1}, "title-obj1");
|
||||
history.pushState({obj2:2}, "title-obj2", "page2");
|
||||
history.replaceState({obj3:3}, "title-obj3");
|
||||
history.replaceState({obj3:/^a$/}, "title-obj3");
|
||||
|
||||
let state = ss.getTabState(tab);
|
||||
gBrowser.removeTab(tab);
|
||||
|
@ -189,6 +189,11 @@ class nsContentUtils
|
||||
public:
|
||||
static nsresult Init();
|
||||
|
||||
/**
|
||||
* Get a JSContext from the document's scope object.
|
||||
*/
|
||||
static JSContext* GetContextFromDocument(nsIDocument *aDocument);
|
||||
|
||||
/**
|
||||
* Get a scope from aNewDocument. Also get a context through the scope of one
|
||||
* of the documents, from the stack or the safe context.
|
||||
|
@ -67,6 +67,7 @@
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsIAnimationFrameListener.h"
|
||||
#include "nsEventStates.h"
|
||||
#include "nsIStructuredCloneContainer.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsPresContext;
|
||||
@ -123,8 +124,8 @@ class Element;
|
||||
|
||||
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0x2c6ad63f, 0xb7b9, 0x42f8, \
|
||||
{ 0xbd, 0xde, 0x76, 0x0a, 0x83, 0xe3, 0xb0, 0x49 } }
|
||||
{ 0x26ef6218, 0xcd5e, 0x4953, \
|
||||
{ 0xbb, 0x57, 0xb8, 0x50, 0x29, 0xa1, 0xae, 0x40 } }
|
||||
|
||||
// Flag for AddStyleSheet().
|
||||
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
|
||||
@ -1422,12 +1423,13 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the document's pending state object (as serialized to JSON).
|
||||
* Set the document's pending state object (as serialized using structured
|
||||
* clone).
|
||||
*/
|
||||
void SetCurrentStateObject(nsAString &obj)
|
||||
void SetStateObject(nsIStructuredCloneContainer *scContainer)
|
||||
{
|
||||
mCurrentStateObject.Assign(obj);
|
||||
mCurrentStateObjectCached = nsnull;
|
||||
mStateObjectContainer = scContainer;
|
||||
mStateObjectCached = nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1515,7 +1517,7 @@ public:
|
||||
// state is unlocked/false.
|
||||
virtual nsresult SetImageLockingState(PRBool aLocked) = 0;
|
||||
|
||||
virtual nsresult GetMozCurrentStateObject(nsIVariant** aResult) = 0;
|
||||
virtual nsresult GetStateObject(nsIVariant** aResult) = 0;
|
||||
|
||||
protected:
|
||||
~nsIDocument()
|
||||
@ -1724,8 +1726,6 @@ protected:
|
||||
*/
|
||||
PRUint32 mExternalScriptsBeingEvaluated;
|
||||
|
||||
nsString mCurrentStateObject;
|
||||
|
||||
// Weak reference to mScriptGlobalObject QI:d to nsPIDOMWindow,
|
||||
// updated on every set of mSecriptGlobalObject.
|
||||
nsPIDOMWindow *mWindow;
|
||||
@ -1741,7 +1741,8 @@ protected:
|
||||
// Our base target.
|
||||
nsString mBaseTarget;
|
||||
|
||||
nsCOMPtr<nsIVariant> mCurrentStateObjectCached;
|
||||
nsCOMPtr<nsIStructuredCloneContainer> mStateObjectContainer;
|
||||
nsCOMPtr<nsIVariant> mStateObjectCached;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
|
||||
|
@ -1391,8 +1391,8 @@ nsContentUtils::InProlog(nsINode *aNode)
|
||||
return !root || doc->IndexOf(aNode) < doc->IndexOf(root);
|
||||
}
|
||||
|
||||
static JSContext *
|
||||
GetContextFromDocument(nsIDocument *aDocument)
|
||||
JSContext *
|
||||
nsContentUtils::GetContextFromDocument(nsIDocument *aDocument)
|
||||
{
|
||||
nsIScriptGlobalObject *sgo = aDocument->GetScopeObject();
|
||||
if (!sgo) {
|
||||
|
@ -1881,7 +1881,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDOMImplementation)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOriginalDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCachedEncoder)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCurrentStateObjectCached)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mStateObjectCached)
|
||||
|
||||
// Traverse all our nsCOMArrays.
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mStyleSheets)
|
||||
@ -8153,47 +8153,22 @@ nsIDocument::ScheduleBeforePaintEvent(nsIAnimationFrameListener* aListener)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::GetMozCurrentStateObject(nsIVariant** aState)
|
||||
nsDocument::GetStateObject(nsIVariant** aState)
|
||||
{
|
||||
// Get the document's current state object. This is the object returned form
|
||||
// both document.mozCurrentStateObject as well as popStateEvent.state
|
||||
// Get the document's current state object. This is the object backing both
|
||||
// history.state and popStateEvent.state.
|
||||
//
|
||||
// mStateObjectContainer may be null; this just means that there's no
|
||||
// current state object.
|
||||
|
||||
nsCOMPtr<nsIVariant> stateObj;
|
||||
// Parse the JSON, if there's any to parse.
|
||||
if (!mCurrentStateObjectCached && !mCurrentStateObject.IsEmpty()) {
|
||||
// Get the JSContext associated with this document. We need this for
|
||||
// deserialization.
|
||||
nsIScriptGlobalObject *sgo = GetScopeObject();
|
||||
NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE);
|
||||
|
||||
nsIScriptContext *scx = sgo->GetContext();
|
||||
NS_ENSURE_TRUE(scx, NS_ERROR_FAILURE);
|
||||
|
||||
JSContext *cx = (JSContext*) scx->GetNativeContext();
|
||||
|
||||
// Make sure we in the request while we have jsval on the native stack.
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
// If our json call triggers a JS-to-C++ call, we want that call to use cx
|
||||
// as the context. So we push cx onto the context stack.
|
||||
nsCxPusher cxPusher;
|
||||
|
||||
jsval jsStateObj = JSVAL_NULL;
|
||||
|
||||
// Deserialize the state object into an nsIVariant.
|
||||
nsCOMPtr<nsIJSON> json = do_GetService("@mozilla.org/dom/json;1");
|
||||
NS_ENSURE_TRUE(cxPusher.Push(cx), NS_ERROR_FAILURE);
|
||||
nsresult rv = json->DecodeToJSVal(mCurrentStateObject, cx, &jsStateObj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
cxPusher.Pop();
|
||||
|
||||
nsCOMPtr<nsIXPConnect> xpconnect = do_GetService(nsIXPConnect::GetCID());
|
||||
NS_ENSURE_TRUE(xpconnect, NS_ERROR_FAILURE);
|
||||
rv = xpconnect->JSValToVariant(cx, &jsStateObj, getter_AddRefs(mCurrentStateObjectCached));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!mStateObjectCached && mStateObjectContainer) {
|
||||
JSContext *cx = nsContentUtils::GetContextFromDocument(this);
|
||||
mStateObjectContainer->
|
||||
DeserializeToVariant(cx, getter_AddRefs(mStateObjectCached));
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*aState = mCurrentStateObjectCached);
|
||||
NS_IF_ADDREF(*aState = mStateObjectCached);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -979,7 +979,7 @@ public:
|
||||
virtual NS_HIDDEN_(nsresult) RemoveImage(imgIRequest* aImage);
|
||||
virtual NS_HIDDEN_(nsresult) SetImageLockingState(PRBool aLocked);
|
||||
|
||||
virtual nsresult GetMozCurrentStateObject(nsIVariant** aResult);
|
||||
virtual nsresult GetStateObject(nsIVariant** aResult);
|
||||
|
||||
protected:
|
||||
friend class nsNodeUtils;
|
||||
|
@ -119,4 +119,5 @@ include $(topsrcdir)/config/rules.mk
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(srcdir)/../shistory/src \
|
||||
-I$(topsrcdir)/layout/base \
|
||||
-I$(topsrcdir)/js/src/xpconnect/src \
|
||||
$(NULL)
|
||||
|
@ -160,6 +160,8 @@
|
||||
#include "nsIWebBrowserChrome3.h"
|
||||
#include "nsITabChild.h"
|
||||
#include "nsIStrictTransportSecurityService.h"
|
||||
#include "nsStructuredCloneContainer.h"
|
||||
#include "nsIStructuredCloneContainer.h"
|
||||
|
||||
// Editor-related
|
||||
#include "nsIEditingSession.h"
|
||||
@ -7741,21 +7743,17 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer)
|
||||
nsresult
|
||||
nsDocShell::SetDocCurrentStateObj(nsISHEntry *shEntry)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIDocument> document = do_GetInterface(GetAsSupports(this));
|
||||
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoString stateData;
|
||||
if (shEntry) {
|
||||
rv = shEntry->GetStateData(stateData);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIStructuredCloneContainer> scContainer;
|
||||
nsresult rv = shEntry->GetStateData(getter_AddRefs(scContainer));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// if shEntry is null, we just set the pending state object to the
|
||||
// empty string.
|
||||
}
|
||||
// It's OK for scContainer too be null here; that just means there's no
|
||||
// state data associated with this history entry.
|
||||
document->SetStateObject(scContainer);
|
||||
|
||||
document->SetCurrentStateObject(stateData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -9413,66 +9411,6 @@ nsDocShell::SetReferrerURI(nsIURI * aURI)
|
||||
// nsDocShell: Session History
|
||||
//*****************************************************************************
|
||||
|
||||
nsresult
|
||||
nsDocShell::StringifyJSValVariant(JSContext *aCx, nsIVariant *aData,
|
||||
nsAString &aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
aResult.Truncate();
|
||||
|
||||
// First, try to extract a jsval from the variant |aData|. This works only
|
||||
// if the variant implements GetAsJSVal.
|
||||
jsval jsData;
|
||||
rv = aData->GetAsJSVal(&jsData);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsIJSContextStack> contextStack;
|
||||
JSContext *cx = aCx;
|
||||
if (!cx) {
|
||||
// Now get the JSContext associated with the current document.
|
||||
// First get the current document.
|
||||
nsCOMPtr<nsIDocument> document = do_GetInterface(GetAsSupports(this));
|
||||
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
|
||||
|
||||
// Get the JSContext from the document, like we do in
|
||||
// nsContentUtils::GetContextFromDocument().
|
||||
nsIScriptGlobalObject *sgo = document->GetScopeObject();
|
||||
NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE);
|
||||
|
||||
nsIScriptContext *scx = sgo->GetContext();
|
||||
NS_ENSURE_TRUE(scx, NS_ERROR_FAILURE);
|
||||
|
||||
cx = (JSContext *)scx->GetNativeContext();
|
||||
|
||||
// If our json call triggers a JS-to-C++ call, we want that call to use
|
||||
// aCx as the context. So we push aCx onto the context stack.
|
||||
contextStack =
|
||||
do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
contextStack->Push(cx);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIJSON> json = do_GetService("@mozilla.org/dom/json;1");
|
||||
if(json) {
|
||||
// Do the encoding
|
||||
rv = json->EncodeFromJSVal(&jsData, cx, aResult);
|
||||
}
|
||||
else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (contextStack) {
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
|
||||
contextStack->Pop(&cx);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
|
||||
const nsAString& aURL, PRBool aReplace, JSContext* aCx)
|
||||
@ -9480,7 +9418,7 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
|
||||
// Implements History.pushState and History.replaceState
|
||||
|
||||
// Here's what we do, roughly in the order specified by HTML5:
|
||||
// 1. Serialize aData to JSON.
|
||||
// 1. Serialize aData using structured clone.
|
||||
// 2. If the third argument is present,
|
||||
// a. Resolve the url, relative to the first script's base URL
|
||||
// b. If (a) fails, raise a SECURITY_ERR
|
||||
@ -9514,13 +9452,16 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Step 1: Clone aData by getting its JSON representation.
|
||||
//
|
||||
// StringifyJSValVariant might cause arbitrary JS to run, and this code
|
||||
// might navigate the page we're on, potentially to a different origin! (bug
|
||||
nsCOMPtr<nsIDocument> document = do_GetInterface(GetAsSupports(this));
|
||||
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
|
||||
|
||||
// Step 1: Serialize aData using structured clone.
|
||||
nsCOMPtr<nsIStructuredCloneContainer> scContainer;
|
||||
|
||||
// scContainer->Init might cause arbitrary JS to run, and this code might
|
||||
// navigate the page we're on, potentially to a different origin! (bug
|
||||
// 634834) To protect against this, we abort if our principal changes due
|
||||
// to the stringify call.
|
||||
nsString dataStr;
|
||||
// to the InitFromVariant() call.
|
||||
{
|
||||
nsCOMPtr<nsIDocument> origDocument =
|
||||
do_GetInterface(GetAsSupports(this));
|
||||
@ -9528,7 +9469,18 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal();
|
||||
|
||||
rv = StringifyJSValVariant(aCx, aData, dataStr);
|
||||
scContainer = new nsStructuredCloneContainer();
|
||||
JSContext *cx = aCx;
|
||||
if (!cx) {
|
||||
cx = nsContentUtils::GetContextFromDocument(document);
|
||||
}
|
||||
rv = scContainer->InitFromVariant(aData, cx);
|
||||
|
||||
// If we're running in the document's context and the structured clone
|
||||
// failed, clear the context's pending exception. See bug 637116.
|
||||
if (NS_FAILED(rv) && !aCx) {
|
||||
JS_ClearPendingException(aCx);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocument> newDocument =
|
||||
@ -9543,7 +9495,7 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
|
||||
}
|
||||
|
||||
// Check that the state object isn't too long.
|
||||
// Default max length: 640k chars.
|
||||
// Default max length: 640k bytes.
|
||||
PRInt32 maxStateObjSize = 0xA0000;
|
||||
if (mPrefs) {
|
||||
mPrefs->GetIntPref("browser.history.maxStateObjectSize",
|
||||
@ -9552,11 +9504,13 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
|
||||
if (maxStateObjSize < 0) {
|
||||
maxStateObjSize = 0;
|
||||
}
|
||||
NS_ENSURE_TRUE(dataStr.Length() <= (PRUint32)maxStateObjSize,
|
||||
NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
nsCOMPtr<nsIDocument> document = do_GetInterface(GetAsSupports(this));
|
||||
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
|
||||
PRUint64 scSize;
|
||||
rv = scContainer->GetSerializedNBytes(&scSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ENSURE_TRUE(scSize <= (PRUint32)maxStateObjSize,
|
||||
NS_ERROR_ILLEGAL_VALUE);
|
||||
|
||||
// Step 2: Resolve aURL
|
||||
PRBool equalURIs = PR_TRUE;
|
||||
@ -9693,7 +9647,7 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
|
||||
|
||||
// Step 4: Modify new/original session history entry and clear its POST
|
||||
// data, if there is any.
|
||||
newSHEntry->SetStateData(dataStr);
|
||||
newSHEntry->SetStateData(scContainer);
|
||||
newSHEntry->SetPostData(nsnull);
|
||||
|
||||
// Step 5: If aReplace is false, indicating that we're doing a pushState
|
||||
@ -9731,7 +9685,7 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
|
||||
else {
|
||||
FireDummyOnLocationChange();
|
||||
}
|
||||
document->SetCurrentStateObject(dataStr);
|
||||
document->SetStateObject(scContainer);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -335,9 +335,9 @@ protected:
|
||||
nsresult ScrollToAnchor(nsACString & curHash, nsACString & newHash,
|
||||
PRUint32 aLoadType);
|
||||
|
||||
// Tries to stringify a given variant by converting it to JSON. This only
|
||||
// Tries to serialize a given variant using structured clone. This only
|
||||
// works if the variant is backed by a JSVal.
|
||||
nsresult StringifyJSValVariant(JSContext *aCx, nsIVariant *aData,
|
||||
nsresult SerializeJSValVariant(JSContext *aCx, nsIVariant *aData,
|
||||
nsAString &aResult);
|
||||
|
||||
// Returns PR_TRUE if would have called FireOnLocationChange,
|
||||
|
@ -72,6 +72,8 @@
|
||||
// download history
|
||||
#include "nsDownloadHistory.h"
|
||||
|
||||
#include "nsStructuredCloneContainer.h"
|
||||
|
||||
static PRBool gInitialized = PR_FALSE;
|
||||
|
||||
// The one time initialization for this module
|
||||
@ -131,6 +133,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsSHistory)
|
||||
// download history
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloadHistory)
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsStructuredCloneContainer)
|
||||
|
||||
NS_DEFINE_NAMED_CID(NS_DOCSHELL_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_DEFAULTURIFIXUP_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_WEBNAVIGATION_INFO_CID);
|
||||
@ -158,6 +162,7 @@ NS_DEFINE_NAMED_CID(NS_SHTRANSACTION_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SHISTORY_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SHISTORY_INTERNAL_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_DOWNLOADHISTORY_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_STRUCTUREDCLONECONTAINER_CID);
|
||||
|
||||
|
||||
const mozilla::Module::CIDEntry kDocShellCIDs[] = {
|
||||
@ -188,6 +193,7 @@ const mozilla::Module::CIDEntry kDocShellCIDs[] = {
|
||||
{ &kNS_SHISTORY_CID, false, NULL, nsSHistoryConstructor },
|
||||
{ &kNS_SHISTORY_INTERNAL_CID, false, NULL, nsSHistoryConstructor },
|
||||
{ &kNS_DOWNLOADHISTORY_CID, false, NULL, nsDownloadHistoryConstructor },
|
||||
{ &kNS_STRUCTUREDCLONECONTAINER_CID, false, NULL, nsStructuredCloneContainerConstructor },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@ -236,6 +242,7 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
|
||||
{ NS_SHISTORY_CONTRACTID, &kNS_SHISTORY_CID },
|
||||
{ NS_SHISTORY_INTERNAL_CONTRACTID, &kNS_SHISTORY_INTERNAL_CID },
|
||||
{ NS_DOWNLOADHISTORY_CONTRACTID, &kNS_DOWNLOADHISTORY_CID },
|
||||
{ NS_STRUCTUREDCLONECONTAINER_CONTRACTID, &kNS_STRUCTUREDCLONECONTAINER_CID },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -50,6 +50,7 @@ interface nsIURI;
|
||||
interface nsIInputStream;
|
||||
interface nsIDocShellTreeItem;
|
||||
interface nsISupportsArray;
|
||||
interface nsIStructuredCloneContainer;
|
||||
%{C++
|
||||
struct nsIntRect;
|
||||
class nsDocShellEditorData;
|
||||
@ -201,9 +202,9 @@ interface nsISHEntry : nsIHistoryEntry
|
||||
|
||||
/**
|
||||
* Get/set data associated with this history state via a pushState() call,
|
||||
* encoded as JSON.
|
||||
* serialized using structured clone.
|
||||
**/
|
||||
attribute AString stateData;
|
||||
attribute nsIStructuredCloneContainer stateData;
|
||||
|
||||
/**
|
||||
* Gets the owning pointer to the editor data assosicated with
|
||||
|
@ -142,8 +142,8 @@ nsSHEntry::nsSHEntry(const nsSHEntry &other)
|
||||
, mParent(other.mParent)
|
||||
, mViewerBounds(0, 0, 0, 0)
|
||||
, mOwner(other.mOwner)
|
||||
, mStateData(other.mStateData)
|
||||
, mDocShellID(other.mDocShellID)
|
||||
, mStateData(other.mStateData)
|
||||
{
|
||||
}
|
||||
|
||||
@ -992,16 +992,17 @@ nsSHEntry::HasDetachedEditor()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::GetStateData(nsAString &aStateData)
|
||||
nsSHEntry::GetStateData(nsIStructuredCloneContainer **aContainer)
|
||||
{
|
||||
aStateData.Assign(mStateData);
|
||||
NS_ENSURE_ARG_POINTER(aContainer);
|
||||
NS_IF_ADDREF(*aContainer = mStateData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::SetStateData(const nsAString &aDataStr)
|
||||
nsSHEntry::SetStateData(nsIStructuredCloneContainer *aContainer)
|
||||
{
|
||||
mStateData.Assign(aDataStr);
|
||||
mStateData = aContainer;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -117,9 +117,9 @@ private:
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
nsExpirationState mExpirationState;
|
||||
nsAutoPtr<nsDocShellEditorData> mEditorData;
|
||||
nsString mStateData;
|
||||
PRUint64 mDocShellID;
|
||||
PRUint32 mLastTouched;
|
||||
nsCOMPtr<nsIStructuredCloneContainer> mStateData;
|
||||
};
|
||||
|
||||
#endif /* nsSHEntry_h */
|
||||
|
@ -87,6 +87,7 @@ _TEST_FILES = \
|
||||
bug529119-window.html \
|
||||
test_bug540462.html \
|
||||
file_bug540462.html \
|
||||
test_bug551225.html \
|
||||
test_bug580069.html \
|
||||
file_bug580069_1.html \
|
||||
file_bug580069_2.sjs \
|
||||
|
33
docshell/test/test_bug551225.html
Normal file
33
docshell/test/test_bug551225.html
Normal file
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=551225
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 551225</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.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=551225">Mozilla Bug 551225</a>
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
/** Test for Bug 551225 **/
|
||||
|
||||
obj = {
|
||||
a: new Date('1/1/2000'),
|
||||
b: /^foo$/,
|
||||
c: 'bar'
|
||||
};
|
||||
|
||||
history.replaceState(obj, '', '');
|
||||
is(history.state.a.toString(), new Date('1/1/2000').toString(), 'Date object.');
|
||||
is(history.state.b.toString(), '/^foo$/', 'Regex');
|
||||
is(history.state.c, 'bar', 'Other state');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -84,6 +84,7 @@ EXPORTS = \
|
||||
nsFocusManager.h \
|
||||
nsWrapperCache.h \
|
||||
nsContentPermissionHelper.h \
|
||||
nsStructuredCloneContainer.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
@ -108,6 +109,7 @@ CPPSRCS = \
|
||||
nsDOMScriptObjectFactory.cpp \
|
||||
nsQueryContentEventResult.cpp \
|
||||
nsContentPermissionHelper.cpp \
|
||||
nsStructuredCloneContainer.cpp \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/dom/dom-config.mk
|
||||
|
@ -7772,10 +7772,10 @@ nsGlobalWindow::DispatchSyncPopState()
|
||||
}
|
||||
|
||||
// Get the document's pending state object -- it contains the data we're
|
||||
// going to send along with the popstate event. The object is serialized as
|
||||
// JSON.
|
||||
// going to send along with the popstate event. The object is serialized
|
||||
// using structured clone.
|
||||
nsCOMPtr<nsIVariant> stateObj;
|
||||
rv = mDoc->GetMozCurrentStateObject(getter_AddRefs(stateObj));
|
||||
rv = mDoc->GetStateObject(getter_AddRefs(stateObj));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Obtain a presentation shell for use in creating a popstate event.
|
||||
|
@ -354,7 +354,7 @@ nsHistory::GetState(nsIVariant **aState)
|
||||
if (!doc)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
return doc->GetMozCurrentStateObject(aState);
|
||||
return doc->GetStateObject(aState);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
195
dom/base/nsStructuredCloneContainer.cpp
Normal file
195
dom/base/nsStructuredCloneContainer.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sw=2 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 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):
|
||||
* Justin Lebar <justin.lebar@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 "nsStructuredCloneContainer.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "xpcprivate.h"
|
||||
|
||||
NS_IMPL_ADDREF(nsStructuredCloneContainer)
|
||||
NS_IMPL_RELEASE(nsStructuredCloneContainer)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsStructuredCloneContainer)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIStructuredCloneContainer)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
nsStructuredCloneContainer::nsStructuredCloneContainer()
|
||||
: mData(nsnull), mSize(0), mVersion(0)
|
||||
{
|
||||
}
|
||||
|
||||
nsStructuredCloneContainer::~nsStructuredCloneContainer()
|
||||
{
|
||||
free(mData);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStructuredCloneContainer::InitFromVariant(nsIVariant *aData, JSContext *aCx)
|
||||
{
|
||||
NS_ENSURE_STATE(!mData);
|
||||
NS_ENSURE_ARG_POINTER(aData);
|
||||
NS_ENSURE_ARG_POINTER(aCx);
|
||||
|
||||
// First, try to extract a jsval from the variant |aData|. This works only
|
||||
// if the variant implements GetAsJSVal.
|
||||
jsval jsData;
|
||||
nsresult rv = aData->GetAsJSVal(&jsData);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// Make sure that we serialize in the right context.
|
||||
JSAutoRequest ar(aCx);
|
||||
JSAutoEnterCompartment ac;
|
||||
NS_ENSURE_STATE(ac.enter(aCx, JS_GetGlobalObject(aCx)));
|
||||
|
||||
nsCxPusher cxPusher;
|
||||
cxPusher.Push(aCx);
|
||||
|
||||
PRUint64* jsBytes = nsnull;
|
||||
PRBool success = JS_WriteStructuredClone(aCx, jsData, &jsBytes, &mSize,
|
||||
nsnull, nsnull);
|
||||
NS_ENSURE_STATE(success);
|
||||
NS_ENSURE_STATE(jsBytes);
|
||||
|
||||
// Copy jsBytes into our own buffer.
|
||||
mData = (PRUint64*) malloc(mSize);
|
||||
if (!mData) {
|
||||
mSize = 0;
|
||||
mVersion = 0;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else {
|
||||
mVersion = JS_STRUCTURED_CLONE_VERSION;
|
||||
}
|
||||
|
||||
memcpy(mData, jsBytes, mSize);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStructuredCloneContainer::InitFromBase64(const nsAString &aData,
|
||||
PRUint32 aFormatVersion,
|
||||
JSContext *aCx)
|
||||
{
|
||||
NS_ENSURE_STATE(!mData);
|
||||
|
||||
NS_ConvertUTF16toUTF8 data(aData);
|
||||
|
||||
nsCAutoString binaryData;
|
||||
nsresult rv = nsXPConnect::Base64Decode(data, binaryData);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Copy the string's data into our own buffer.
|
||||
mData = (PRUint64*) malloc(binaryData.Length());
|
||||
NS_ENSURE_STATE(mData);
|
||||
memcpy(mData, binaryData.get(), binaryData.Length());
|
||||
|
||||
mSize = binaryData.Length();
|
||||
mVersion = aFormatVersion;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsStructuredCloneContainer::DeserializeToVariant(JSContext *aCx,
|
||||
nsIVariant **aData)
|
||||
{
|
||||
NS_ENSURE_STATE(mData);
|
||||
NS_ENSURE_ARG_POINTER(aData);
|
||||
*aData = nsnull;
|
||||
|
||||
// Deserialize to a jsval.
|
||||
jsval jsStateObj;
|
||||
PRBool success = JS_ReadStructuredClone(aCx, mData, mSize, mVersion,
|
||||
&jsStateObj, nsnull, nsnull);
|
||||
NS_ENSURE_STATE(success);
|
||||
|
||||
// Now wrap the jsval as an nsIVariant.
|
||||
nsCOMPtr<nsIVariant> varStateObj;
|
||||
nsCOMPtr<nsIXPConnect> xpconnect = do_GetService(nsIXPConnect::GetCID());
|
||||
NS_ENSURE_STATE(xpconnect);
|
||||
xpconnect->JSValToVariant(aCx, &jsStateObj, getter_AddRefs(varStateObj));
|
||||
NS_ENSURE_STATE(varStateObj);
|
||||
|
||||
NS_IF_ADDREF(*aData = varStateObj);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStructuredCloneContainer::GetDataAsBase64(nsAString &aOut)
|
||||
{
|
||||
NS_ENSURE_STATE(mData);
|
||||
aOut.Truncate();
|
||||
|
||||
nsCAutoString binaryData(reinterpret_cast<char*>(mData), mSize);
|
||||
nsCAutoString base64Data;
|
||||
nsresult rv = nsXPConnect::Base64Encode(binaryData, base64Data);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aOut.Assign(NS_ConvertASCIItoUTF16(base64Data));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStructuredCloneContainer::GetSerializedNBytes(PRUint64 *aSize)
|
||||
{
|
||||
NS_ENSURE_STATE(mData);
|
||||
NS_ENSURE_ARG_POINTER(aSize);
|
||||
|
||||
// mSize is a size_t, while aSize is a PRUint64. We rely on an implicit cast
|
||||
// here so that we'll get a compile error if a size_t-to-uint64 cast is
|
||||
// narrowing.
|
||||
*aSize = mSize;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStructuredCloneContainer::GetFormatVersion(PRUint32 *aFormatVersion)
|
||||
{
|
||||
NS_ENSURE_STATE(mData);
|
||||
NS_ENSURE_ARG_POINTER(aFormatVersion);
|
||||
*aFormatVersion = mVersion;
|
||||
return NS_OK;
|
||||
}
|
73
dom/base/nsStructuredCloneContainer.h
Normal file
73
dom/base/nsStructuredCloneContainer.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sw=2 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 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):
|
||||
* Justin Lebar <justin.lebar@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 nsStructuredCloneContainer_h__
|
||||
#define nsStructuredCloneContainer_h__
|
||||
|
||||
#include "nsIStructuredCloneContainer.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
#define NS_STRUCTUREDCLONECONTAINER_CLASSNAME "nsStructuredCloneContainer"
|
||||
#define NS_STRUCTUREDCLONECONTAINER_CONTRACTID \
|
||||
"@mozilla.org/docshell/structured-clone-container;1"
|
||||
#define NS_STRUCTUREDCLONECONTAINER_CID \
|
||||
{ /* 38bd0634-0fd4-46f0-b85f-13ced889eeec */ \
|
||||
0x38bd0634, \
|
||||
0x0fd4, \
|
||||
0x46f0, \
|
||||
{0xb8, 0x5f, 0x13, 0xce, 0xd8, 0x89, 0xee, 0xec} \
|
||||
}
|
||||
|
||||
class nsStructuredCloneContainer : public nsIStructuredCloneContainer
|
||||
{
|
||||
public:
|
||||
nsStructuredCloneContainer();
|
||||
~nsStructuredCloneContainer();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTRUCTUREDCLONECONTAINER
|
||||
|
||||
private:
|
||||
PRUint64* mData;
|
||||
|
||||
// This needs to be size_t rather than a PR-type so it matches the JS API.
|
||||
size_t mSize;
|
||||
PRUint32 mVersion;
|
||||
};
|
||||
|
||||
#endif
|
@ -87,6 +87,7 @@ XPIDLSRCS = \
|
||||
nsITabChild.idl \
|
||||
nsITabParent.idl \
|
||||
nsIDOMGlobalPropertyInitializer.idl \
|
||||
nsIStructuredCloneContainer.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
101
dom/interfaces/base/nsIStructuredCloneContainer.idl
Normal file
101
dom/interfaces/base/nsIStructuredCloneContainer.idl
Normal file
@ -0,0 +1,101 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sw=2 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 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):
|
||||
* Justin Lebar <justin.lebar@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 nsIVariant;
|
||||
interface nsIDocument;
|
||||
|
||||
%{C++
|
||||
struct JSContext;
|
||||
%}
|
||||
|
||||
/**
|
||||
* This interface acts as a container for an object serialized using the
|
||||
* structured clone algorithm.
|
||||
*
|
||||
* You can copy an object into an nsIStructuredCloneContainer using
|
||||
* initFromVariant or initFromBase64. It's an error to initialize an
|
||||
* nsIStructuredCloneContainer more than once.
|
||||
*
|
||||
* Once you've initialized the container, you can get a copy of the object it
|
||||
* stores by calling deserializeToVariant. You can also get a base-64-encoded
|
||||
* string containing a copy of the container's serialized data, using
|
||||
* getDataAsBase64.
|
||||
*/
|
||||
[scriptable, uuid(400a282d-7157-4ed0-85b4-8bdc2fa634cd)]
|
||||
interface nsIStructuredCloneContainer : nsISupports
|
||||
{
|
||||
/**
|
||||
* Initialize this structured clone container so it contains a clone of the
|
||||
* given variant. aData must be backed by a jsval.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
void initFromVariant(in nsIVariant aData);
|
||||
|
||||
/**
|
||||
* Initialize this structured clone container from a base-64-encoded byte
|
||||
* stream, stored in aData. aFormatVersion should be the version of the
|
||||
* structured clone algorithm which was used to generate aData.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
void initFromBase64(in AString aData,in unsigned long aFormatVersion);
|
||||
|
||||
/**
|
||||
* Deserialize the object this conatiner holds, returning it wrapped as
|
||||
* an nsIVariant.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
nsIVariant deserializeToVariant();
|
||||
|
||||
/**
|
||||
* Get this structured clone container's data as a base-64-encoded string.
|
||||
*/
|
||||
AString getDataAsBase64();
|
||||
|
||||
/**
|
||||
* Get the size in bytes of this container's serialized data.
|
||||
*/
|
||||
readonly attribute unsigned long long serializedNBytes;
|
||||
|
||||
/**
|
||||
* Get the version of the structured clone algorithm which was used to
|
||||
* generate this container's serialized buffer.
|
||||
*/
|
||||
readonly attribute unsigned long formatVersion;
|
||||
};
|
Loading…
Reference in New Issue
Block a user