dom/file/ArchiveRequest.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:fe0b29feab8a
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "ArchiveRequest.h"
8
9 #include "mozilla/EventDispatcher.h"
10 #include "mozilla/dom/ArchiveRequestBinding.h"
11 #include "nsContentUtils.h"
12 #include "nsCxPusher.h"
13
14 using namespace mozilla;
15
16 USING_FILE_NAMESPACE
17
18 /**
19 * Class used to make asynchronous the ArchiveRequest.
20 */
21 class ArchiveRequestEvent : public nsRunnable
22 {
23 public:
24 NS_DECL_NSIRUNNABLE
25
26 ArchiveRequestEvent(ArchiveRequest* request)
27 : mRequest(request)
28 {
29 MOZ_COUNT_CTOR(ArchiveRequestEvent);
30 }
31
32 ~ArchiveRequestEvent()
33 {
34 MOZ_COUNT_DTOR(ArchiveRequestEvent);
35 }
36
37 private: //data
38 nsRefPtr<ArchiveRequest> mRequest;
39 };
40
41 NS_IMETHODIMP
42 ArchiveRequestEvent::Run()
43 {
44 NS_ABORT_IF_FALSE(mRequest, "the request is not longer valid");
45 mRequest->Run();
46 return NS_OK;
47 }
48
49 // ArchiveRequest
50
51 ArchiveRequest::ArchiveRequest(nsPIDOMWindow* aWindow,
52 ArchiveReader* aReader)
53 : DOMRequest(aWindow),
54 mArchiveReader(aReader)
55 {
56 MOZ_ASSERT(aReader);
57
58 MOZ_COUNT_CTOR(ArchiveRequest);
59
60 /* An event to make this request asynchronous: */
61 nsRefPtr<ArchiveRequestEvent> event = new ArchiveRequestEvent(this);
62 NS_DispatchToCurrentThread(event);
63 }
64
65 ArchiveRequest::~ArchiveRequest()
66 {
67 MOZ_COUNT_DTOR(ArchiveRequest);
68 }
69
70 nsresult
71 ArchiveRequest::PreHandleEvent(EventChainPreVisitor& aVisitor)
72 {
73 aVisitor.mCanHandle = true;
74 aVisitor.mParentTarget = nullptr;
75 return NS_OK;
76 }
77
78 /* virtual */ JSObject*
79 ArchiveRequest::WrapObject(JSContext* aCx)
80 {
81 return ArchiveRequestBinding::Wrap(aCx, this);
82 }
83
84 ArchiveReader*
85 ArchiveRequest::Reader() const
86 {
87 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
88
89 return mArchiveReader;
90 }
91
92 // Here the request is processed:
93 void
94 ArchiveRequest::Run()
95 {
96 // Register this request to the reader.
97 // When the reader is ready to return data, a 'Ready()' will be called
98 nsresult rv = mArchiveReader->RegisterRequest(this);
99 if (NS_FAILED(rv)) {
100 FireError(rv);
101 }
102 }
103
104 void
105 ArchiveRequest::OpGetFilenames()
106 {
107 mOperation = GetFilenames;
108 }
109
110 void
111 ArchiveRequest::OpGetFile(const nsAString& aFilename)
112 {
113 mOperation = GetFile;
114 mFilename = aFilename;
115 }
116
117 void
118 ArchiveRequest::OpGetFiles()
119 {
120 mOperation = GetFiles;
121 }
122
123 nsresult
124 ArchiveRequest::ReaderReady(nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList,
125 nsresult aStatus)
126 {
127 if (NS_FAILED(aStatus)) {
128 FireError(aStatus);
129 return NS_OK;
130 }
131
132 nsresult rv;
133
134 nsIScriptContext* sc = GetContextForEventHandlers(&rv);
135 NS_ENSURE_STATE(sc);
136
137 AutoPushJSContext cx(sc->GetNativeContext());
138 NS_ASSERTION(cx, "Failed to get a context!");
139
140 JS::Rooted<JSObject*> global(cx, sc->GetWindowProxy());
141 NS_ASSERTION(global, "Failed to get global object!");
142
143 JSAutoCompartment ac(cx, global);
144
145 JS::Rooted<JS::Value> result(cx);
146 switch (mOperation) {
147 case GetFilenames:
148 rv = GetFilenamesResult(cx, result.address(), aFileList);
149 break;
150
151 case GetFile:
152 rv = GetFileResult(cx, &result, aFileList);
153 break;
154
155 case GetFiles:
156 rv = GetFilesResult(cx, &result, aFileList);
157 break;
158 }
159
160 if (NS_FAILED(rv)) {
161 NS_WARNING("Get*Result failed!");
162 }
163
164 if (NS_SUCCEEDED(rv)) {
165 FireSuccess(result);
166 }
167 else {
168 FireError(rv);
169 }
170
171 return NS_OK;
172 }
173
174 nsresult
175 ArchiveRequest::GetFilenamesResult(JSContext* aCx,
176 JS::Value* aValue,
177 nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList)
178 {
179 JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aFileList.Length()));
180 nsresult rv;
181
182 if (!array) {
183 return NS_ERROR_OUT_OF_MEMORY;
184 }
185
186 JS::Rooted<JSString*> str(aCx);
187 for (uint32_t i = 0; i < aFileList.Length(); ++i) {
188 nsCOMPtr<nsIDOMFile> file = aFileList[i];
189
190 nsString filename;
191 rv = file->GetName(filename);
192 NS_ENSURE_SUCCESS(rv, rv);
193
194 str = JS_NewUCStringCopyZ(aCx, filename.get());
195 NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
196
197 if (NS_FAILED(rv) ||
198 !JS_DefineElement(aCx, array, i, JS::StringValue(str), nullptr, nullptr,
199 JSPROP_ENUMERATE)) {
200 return NS_ERROR_FAILURE;
201 }
202 }
203
204 if (!JS_FreezeObject(aCx, array)) {
205 return NS_ERROR_FAILURE;
206 }
207
208 *aValue = OBJECT_TO_JSVAL(array);
209 return NS_OK;
210 }
211
212 nsresult
213 ArchiveRequest::GetFileResult(JSContext* aCx,
214 JS::MutableHandle<JS::Value> aValue,
215 nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList)
216 {
217 for (uint32_t i = 0; i < aFileList.Length(); ++i) {
218 nsCOMPtr<nsIDOMFile> file = aFileList[i];
219
220 nsString filename;
221 nsresult rv = file->GetName(filename);
222 NS_ENSURE_SUCCESS(rv, rv);
223
224 if (filename == mFilename) {
225 return nsContentUtils::WrapNative(aCx, file, &NS_GET_IID(nsIDOMFile),
226 aValue);
227 }
228 }
229
230 return NS_ERROR_FAILURE;
231 }
232
233 nsresult
234 ArchiveRequest::GetFilesResult(JSContext* aCx,
235 JS::MutableHandle<JS::Value> aValue,
236 nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList)
237 {
238 JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, aFileList.Length()));
239 if (!array) {
240 return NS_ERROR_OUT_OF_MEMORY;
241 }
242
243 for (uint32_t i = 0; i < aFileList.Length(); ++i) {
244 nsCOMPtr<nsIDOMFile> file = aFileList[i];
245
246 JS::Rooted<JS::Value> value(aCx);
247 nsresult rv = nsContentUtils::WrapNative(aCx, file, &NS_GET_IID(nsIDOMFile),
248 &value);
249 if (NS_FAILED(rv) ||
250 !JS_DefineElement(aCx, array, i, value, nullptr, nullptr,
251 JSPROP_ENUMERATE)) {
252 return NS_ERROR_FAILURE;
253 }
254 }
255
256 aValue.setObject(*array);
257 return NS_OK;
258 }
259
260 // static
261 already_AddRefed<ArchiveRequest>
262 ArchiveRequest::Create(nsPIDOMWindow* aOwner,
263 ArchiveReader* aReader)
264 {
265 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
266
267 nsRefPtr<ArchiveRequest> request = new ArchiveRequest(aOwner, aReader);
268
269 return request.forget();
270 }
271
272 NS_IMPL_CYCLE_COLLECTION_INHERITED(ArchiveRequest, DOMRequest,
273 mArchiveReader)
274
275 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ArchiveRequest)
276 NS_INTERFACE_MAP_END_INHERITING(DOMRequest)
277
278 NS_IMPL_ADDREF_INHERITED(ArchiveRequest, DOMRequest)
279 NS_IMPL_RELEASE_INHERITED(ArchiveRequest, DOMRequest)

mercurial