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 file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "IDBFileRequest.h"
8 
9 #include "IDBFileHandle.h"
10 #include "js/RootingAPI.h"
11 #include "jsapi.h"
12 #include "mozilla/Assertions.h"
13 #include "mozilla/dom/IDBFileRequestBinding.h"
14 #include "mozilla/dom/ProgressEvent.h"
15 #include "mozilla/dom/ScriptSettings.h"
16 #include "mozilla/EventDispatcher.h"
17 #include "nsCOMPtr.h"
18 #include "nsDebug.h"
19 #include "nsError.h"
20 #include "nsLiteralString.h"
21 
22 namespace mozilla {
23 namespace dom {
24 
25 using namespace mozilla::dom::indexedDB;
26 
IDBFileRequest(nsPIDOMWindowInner * aWindow,IDBFileHandle * aFileHandle,bool aWrapAsDOMRequest)27 IDBFileRequest::IDBFileRequest(nsPIDOMWindowInner* aWindow,
28                                IDBFileHandle* aFileHandle,
29                                bool aWrapAsDOMRequest)
30   : DOMRequest(aWindow)
31   , FileRequestBase(DEBUGONLY(aFileHandle->OwningThread()))
32   , mFileHandle(aFileHandle)
33   , mWrapAsDOMRequest(aWrapAsDOMRequest)
34 {
35   AssertIsOnOwningThread();
36 }
37 
~IDBFileRequest()38 IDBFileRequest::~IDBFileRequest()
39 {
40   AssertIsOnOwningThread();
41 }
42 
43 // static
44 already_AddRefed<IDBFileRequest>
Create(nsPIDOMWindowInner * aOwner,IDBFileHandle * aFileHandle,bool aWrapAsDOMRequest)45 IDBFileRequest::Create(nsPIDOMWindowInner* aOwner, IDBFileHandle* aFileHandle,
46                        bool aWrapAsDOMRequest)
47 {
48   MOZ_ASSERT(aFileHandle);
49   aFileHandle->AssertIsOnOwningThread();
50 
51   RefPtr<IDBFileRequest> request =
52     new IDBFileRequest(aOwner, aFileHandle, aWrapAsDOMRequest);
53 
54   return request.forget();
55 }
56 
NS_IMPL_ADDREF_INHERITED(IDBFileRequest,DOMRequest)57 NS_IMPL_ADDREF_INHERITED(IDBFileRequest, DOMRequest)
58 NS_IMPL_RELEASE_INHERITED(IDBFileRequest, DOMRequest)
59 
60 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBFileRequest)
61 NS_INTERFACE_MAP_END_INHERITING(DOMRequest)
62 
63 NS_IMPL_CYCLE_COLLECTION_INHERITED(IDBFileRequest, DOMRequest,
64                                    mFileHandle)
65 
66 nsresult
67 IDBFileRequest::PreHandleEvent(EventChainPreVisitor& aVisitor)
68 {
69   AssertIsOnOwningThread();
70 
71   aVisitor.mCanHandle = true;
72   aVisitor.mParentTarget = mFileHandle;
73   return NS_OK;
74 }
75 
76 // virtual
77 JSObject*
WrapObject(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)78 IDBFileRequest::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
79 {
80   AssertIsOnOwningThread();
81 
82   if (mWrapAsDOMRequest) {
83     return DOMRequest::WrapObject(aCx, aGivenProto);
84   }
85   return IDBFileRequestBinding::Wrap(aCx, this, aGivenProto);
86 }
87 
88 mozilla::dom::FileHandleBase*
FileHandle() const89 IDBFileRequest::FileHandle() const
90 {
91   AssertIsOnOwningThread();
92 
93   return mFileHandle;
94 }
95 
96 void
OnProgress(uint64_t aProgress,uint64_t aProgressMax)97 IDBFileRequest::OnProgress(uint64_t aProgress, uint64_t aProgressMax)
98 {
99   AssertIsOnOwningThread();
100 
101   FireProgressEvent(aProgress, aProgressMax);
102 }
103 
104 void
SetResultCallback(ResultCallback * aCallback)105 IDBFileRequest::SetResultCallback(ResultCallback* aCallback)
106 {
107   AssertIsOnOwningThread();
108   MOZ_ASSERT(aCallback);
109 
110   AutoJSAPI autoJS;
111   if (NS_WARN_IF(!autoJS.Init(GetOwner()))) {
112     FireError(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR);
113     return;
114   }
115 
116   JSContext* cx = autoJS.cx();
117 
118   JS::Rooted<JS::Value> result(cx);
119   nsresult rv = aCallback->GetResult(cx, &result);
120   if (NS_WARN_IF(NS_FAILED(rv))) {
121     FireError(rv);
122   } else {
123     FireSuccess(result);
124   }
125 }
126 
127 void
SetError(nsresult aError)128 IDBFileRequest::SetError(nsresult aError)
129 {
130   AssertIsOnOwningThread();
131 
132   FireError(aError);
133 }
134 
135 void
FireProgressEvent(uint64_t aLoaded,uint64_t aTotal)136 IDBFileRequest::FireProgressEvent(uint64_t aLoaded, uint64_t aTotal)
137 {
138   AssertIsOnOwningThread();
139 
140   if (NS_FAILED(CheckInnerWindowCorrectness())) {
141     return;
142   }
143 
144   ProgressEventInit init;
145   init.mBubbles = false;
146   init.mCancelable = false;
147   init.mLengthComputable = false;
148   init.mLoaded = aLoaded;
149   init.mTotal = aTotal;
150 
151   RefPtr<ProgressEvent> event =
152     ProgressEvent::Constructor(this, NS_LITERAL_STRING("progress"), init);
153   DispatchTrustedEvent(event);
154 }
155 
156 } // namespace dom
157 } // namespace mozilla
158