Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "nsStructuredCloneContainer.h"
8 :
9 : #include "nsCOMPtr.h"
10 : #include "nsIGlobalObject.h"
11 : #include "nsIVariant.h"
12 : #include "nsIXPConnect.h"
13 : #include "nsServiceManagerUtils.h"
14 : #include "nsContentUtils.h"
15 : #include "jsapi.h"
16 : #include "xpcpublic.h"
17 :
18 : #include "mozilla/Base64.h"
19 : #include "mozilla/dom/ScriptSettings.h"
20 :
21 : using namespace mozilla;
22 : using namespace mozilla::dom;
23 :
24 0 : NS_IMPL_ADDREF(nsStructuredCloneContainer)
25 0 : NS_IMPL_RELEASE(nsStructuredCloneContainer)
26 :
27 0 : NS_INTERFACE_MAP_BEGIN(nsStructuredCloneContainer)
28 0 : NS_INTERFACE_MAP_ENTRY(nsIStructuredCloneContainer)
29 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
30 0 : NS_INTERFACE_MAP_END
31 :
32 0 : nsStructuredCloneContainer::nsStructuredCloneContainer()
33 0 : : mVersion(0)
34 : {
35 0 : }
36 :
37 0 : nsStructuredCloneContainer::~nsStructuredCloneContainer()
38 : {
39 0 : }
40 :
41 : NS_IMETHODIMP
42 0 : nsStructuredCloneContainer::InitFromJSVal(JS::Handle<JS::Value> aData,
43 : JSContext* aCx)
44 : {
45 0 : if (DataLength()) {
46 0 : return NS_ERROR_FAILURE;
47 : }
48 :
49 0 : ErrorResult rv;
50 0 : Write(aCx, aData, rv);
51 0 : if (NS_WARN_IF(rv.Failed())) {
52 0 : return rv.StealNSResult();
53 : }
54 :
55 0 : mVersion = JS_STRUCTURED_CLONE_VERSION;
56 0 : return NS_OK;
57 : }
58 :
59 : NS_IMETHODIMP
60 0 : nsStructuredCloneContainer::InitFromBase64(const nsAString &aData,
61 : uint32_t aFormatVersion)
62 : {
63 0 : if (DataLength()) {
64 0 : return NS_ERROR_FAILURE;
65 : }
66 :
67 0 : NS_ConvertUTF16toUTF8 data(aData);
68 :
69 0 : nsAutoCString binaryData;
70 0 : nsresult rv = Base64Decode(data, binaryData);
71 0 : NS_ENSURE_SUCCESS(rv, rv);
72 :
73 0 : if (!CopyExternalData(binaryData.get(), binaryData.Length())) {
74 0 : return NS_ERROR_OUT_OF_MEMORY;
75 : }
76 :
77 0 : mVersion = aFormatVersion;
78 0 : return NS_OK;
79 : }
80 :
81 : nsresult
82 0 : nsStructuredCloneContainer::DeserializeToJsval(JSContext* aCx,
83 : JS::MutableHandle<JS::Value> aValue)
84 : {
85 0 : aValue.setNull();
86 0 : JS::Rooted<JS::Value> jsStateObj(aCx);
87 :
88 0 : ErrorResult rv;
89 0 : Read(aCx, &jsStateObj, rv);
90 0 : if (NS_WARN_IF(rv.Failed())) {
91 0 : return rv.StealNSResult();
92 : }
93 :
94 0 : aValue.set(jsStateObj);
95 0 : return NS_OK;
96 : }
97 :
98 : NS_IMETHODIMP
99 0 : nsStructuredCloneContainer::DeserializeToVariant(JSContext* aCx,
100 : nsIVariant** aData)
101 : {
102 0 : NS_ENSURE_ARG_POINTER(aData);
103 0 : *aData = nullptr;
104 :
105 0 : if (!DataLength()) {
106 0 : return NS_ERROR_FAILURE;
107 : }
108 :
109 : // Deserialize to a JS::Value.
110 0 : JS::Rooted<JS::Value> jsStateObj(aCx);
111 0 : nsresult rv = DeserializeToJsval(aCx, &jsStateObj);
112 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
113 0 : return rv;
114 : }
115 :
116 : // Now wrap the JS::Value as an nsIVariant.
117 0 : nsCOMPtr<nsIVariant> varStateObj;
118 0 : nsCOMPtr<nsIXPConnect> xpconnect = do_GetService(nsIXPConnect::GetCID());
119 0 : NS_ENSURE_STATE(xpconnect);
120 0 : xpconnect->JSValToVariant(aCx, jsStateObj, getter_AddRefs(varStateObj));
121 0 : NS_ENSURE_STATE(varStateObj);
122 :
123 0 : varStateObj.forget(aData);
124 0 : return NS_OK;
125 : }
126 :
127 : NS_IMETHODIMP
128 0 : nsStructuredCloneContainer::GetDataAsBase64(nsAString &aOut)
129 : {
130 0 : aOut.Truncate();
131 :
132 0 : if (!DataLength()) {
133 0 : return NS_ERROR_FAILURE;
134 : }
135 :
136 0 : if (HasClonedDOMObjects()) {
137 0 : return NS_ERROR_FAILURE;
138 : }
139 :
140 0 : auto iter = Data().Iter();
141 0 : size_t size = Data().Size();
142 0 : nsAutoCString binaryData;
143 0 : binaryData.SetLength(size);
144 0 : Data().ReadBytes(iter, binaryData.BeginWriting(), size);
145 0 : nsAutoCString base64Data;
146 0 : nsresult rv = Base64Encode(binaryData, base64Data);
147 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
148 0 : return rv;
149 : }
150 :
151 0 : CopyASCIItoUTF16(base64Data, aOut);
152 0 : return NS_OK;
153 : }
154 :
155 : NS_IMETHODIMP
156 0 : nsStructuredCloneContainer::GetSerializedNBytes(uint64_t* aSize)
157 : {
158 0 : NS_ENSURE_ARG_POINTER(aSize);
159 :
160 0 : if (!DataLength()) {
161 0 : return NS_ERROR_FAILURE;
162 : }
163 :
164 0 : *aSize = DataLength();
165 0 : return NS_OK;
166 : }
167 :
168 : NS_IMETHODIMP
169 0 : nsStructuredCloneContainer::GetFormatVersion(uint32_t* aFormatVersion)
170 : {
171 0 : NS_ENSURE_ARG_POINTER(aFormatVersion);
172 :
173 0 : if (!DataLength()) {
174 0 : return NS_ERROR_FAILURE;
175 : }
176 :
177 0 : *aFormatVersion = mVersion;
178 0 : return NS_OK;
179 : }
|