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 file,
5 : * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "nsBrowserElement.h"
8 :
9 : #include "mozilla/Preferences.h"
10 : #include "mozilla/Services.h"
11 : #include "mozilla/dom/BrowserElementBinding.h"
12 : #include "mozilla/dom/DOMRequest.h"
13 : #include "mozilla/dom/ScriptSettings.h"
14 : #include "mozilla/dom/ToJSValue.h"
15 :
16 : #include "nsComponentManagerUtils.h"
17 : #include "nsFrameLoader.h"
18 : #include "nsIDOMDOMRequest.h"
19 : #include "nsIDOMElement.h"
20 : #include "nsIMozBrowserFrame.h"
21 : #include "nsINode.h"
22 : #include "nsIPrincipal.h"
23 :
24 : using namespace mozilla::dom;
25 :
26 : namespace mozilla {
27 :
28 : bool
29 0 : nsBrowserElement::IsBrowserElementOrThrow(ErrorResult& aRv)
30 : {
31 0 : if (mBrowserElementAPI) {
32 0 : return true;
33 : }
34 0 : aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
35 0 : return false;
36 : }
37 :
38 : void
39 0 : nsBrowserElement::InitBrowserElementAPI()
40 : {
41 : bool isMozBrowser;
42 0 : nsCOMPtr<nsIFrameLoader> frameLoader = GetFrameLoader();
43 0 : NS_ENSURE_TRUE_VOID(frameLoader);
44 0 : nsresult rv = frameLoader->GetOwnerIsMozBrowserFrame(&isMozBrowser);
45 0 : NS_ENSURE_SUCCESS_VOID(rv);
46 :
47 0 : if (!isMozBrowser) {
48 0 : return;
49 : }
50 :
51 0 : if (!mBrowserElementAPI) {
52 0 : mBrowserElementAPI = do_CreateInstance("@mozilla.org/dom/browser-element-api;1");
53 0 : if (NS_WARN_IF(!mBrowserElementAPI)) {
54 0 : return;
55 : }
56 : }
57 0 : mBrowserElementAPI->SetFrameLoader(frameLoader);
58 : }
59 :
60 : void
61 0 : nsBrowserElement::DestroyBrowserElementFrameScripts()
62 : {
63 0 : if (!mBrowserElementAPI) {
64 0 : return;
65 : }
66 0 : mBrowserElementAPI->DestroyFrameScripts();
67 : }
68 :
69 : void
70 0 : nsBrowserElement::SendMouseEvent(const nsAString& aType,
71 : uint32_t aX,
72 : uint32_t aY,
73 : uint32_t aButton,
74 : uint32_t aClickCount,
75 : uint32_t aModifiers,
76 : ErrorResult& aRv)
77 : {
78 0 : NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
79 :
80 0 : nsresult rv = mBrowserElementAPI->SendMouseEvent(aType,
81 : aX,
82 : aY,
83 : aButton,
84 : aClickCount,
85 0 : aModifiers);
86 :
87 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
88 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
89 : }
90 : }
91 :
92 : void
93 0 : nsBrowserElement::SendTouchEvent(const nsAString& aType,
94 : const Sequence<uint32_t>& aIdentifiers,
95 : const Sequence<int32_t>& aXs,
96 : const Sequence<int32_t>& aYs,
97 : const Sequence<uint32_t>& aRxs,
98 : const Sequence<uint32_t>& aRys,
99 : const Sequence<float>& aRotationAngles,
100 : const Sequence<float>& aForces,
101 : uint32_t aCount,
102 : uint32_t aModifiers,
103 : ErrorResult& aRv)
104 : {
105 0 : NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
106 :
107 0 : if (aIdentifiers.Length() != aCount ||
108 0 : aXs.Length() != aCount ||
109 0 : aYs.Length() != aCount ||
110 0 : aRxs.Length() != aCount ||
111 0 : aRys.Length() != aCount ||
112 0 : aRotationAngles.Length() != aCount ||
113 0 : aForces.Length() != aCount) {
114 0 : aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
115 0 : return;
116 : }
117 :
118 0 : nsresult rv = mBrowserElementAPI->SendTouchEvent(aType,
119 : aIdentifiers.Elements(),
120 : aXs.Elements(),
121 : aYs.Elements(),
122 : aRxs.Elements(),
123 : aRys.Elements(),
124 : aRotationAngles.Elements(),
125 : aForces.Elements(),
126 : aCount,
127 0 : aModifiers);
128 :
129 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
130 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
131 : }
132 : }
133 :
134 : void
135 0 : nsBrowserElement::GoBack(ErrorResult& aRv)
136 : {
137 0 : NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
138 :
139 0 : nsresult rv = mBrowserElementAPI->GoBack();
140 :
141 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
142 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
143 : }
144 : }
145 :
146 : void
147 0 : nsBrowserElement::GoForward(ErrorResult& aRv)
148 : {
149 0 : NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
150 :
151 0 : nsresult rv = mBrowserElementAPI->GoForward();
152 :
153 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
154 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
155 : }
156 : }
157 :
158 : void
159 0 : nsBrowserElement::Reload(bool aHardReload, ErrorResult& aRv)
160 : {
161 0 : NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
162 :
163 0 : nsresult rv = mBrowserElementAPI->Reload(aHardReload);
164 :
165 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
166 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
167 : }
168 : }
169 :
170 : void
171 0 : nsBrowserElement::Stop(ErrorResult& aRv)
172 : {
173 0 : NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
174 :
175 0 : nsresult rv = mBrowserElementAPI->Stop();
176 :
177 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
178 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
179 : }
180 : }
181 :
182 : already_AddRefed<DOMRequest>
183 0 : nsBrowserElement::Download(const nsAString& aUrl,
184 : const BrowserElementDownloadOptions& aOptions,
185 : ErrorResult& aRv)
186 : {
187 0 : NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
188 :
189 0 : nsCOMPtr<nsIDOMDOMRequest> req;
190 0 : nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(mBrowserElementAPI);
191 0 : MOZ_ASSERT(wrappedObj, "Failed to get wrapped JS from XPCOM component.");
192 0 : AutoJSAPI jsapi;
193 0 : if (!jsapi.Init(wrappedObj->GetJSObject())) {
194 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
195 0 : return nullptr;
196 : }
197 0 : JSContext* cx = jsapi.cx();
198 0 : JS::Rooted<JS::Value> options(cx);
199 0 : aRv.MightThrowJSException();
200 0 : if (!ToJSValue(cx, aOptions, &options)) {
201 0 : aRv.StealExceptionFromJSContext(cx);
202 0 : return nullptr;
203 : }
204 0 : nsresult rv = mBrowserElementAPI->Download(aUrl, options, getter_AddRefs(req));
205 :
206 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
207 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
208 0 : return nullptr;
209 : }
210 :
211 0 : return req.forget().downcast<DOMRequest>();
212 : }
213 :
214 : already_AddRefed<DOMRequest>
215 0 : nsBrowserElement::PurgeHistory(ErrorResult& aRv)
216 : {
217 0 : NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
218 :
219 0 : nsCOMPtr<nsIDOMDOMRequest> req;
220 0 : nsresult rv = mBrowserElementAPI->PurgeHistory(getter_AddRefs(req));
221 :
222 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
223 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
224 0 : return nullptr;
225 : }
226 :
227 0 : return req.forget().downcast<DOMRequest>();
228 : }
229 :
230 : already_AddRefed<DOMRequest>
231 0 : nsBrowserElement::GetScreenshot(uint32_t aWidth,
232 : uint32_t aHeight,
233 : const nsAString& aMimeType,
234 : ErrorResult& aRv)
235 : {
236 0 : NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
237 :
238 0 : nsCOMPtr<nsIDOMDOMRequest> req;
239 0 : nsresult rv = mBrowserElementAPI->GetScreenshot(aWidth, aHeight, aMimeType,
240 0 : getter_AddRefs(req));
241 :
242 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
243 0 : if (rv == NS_ERROR_INVALID_ARG) {
244 0 : aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
245 : } else {
246 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
247 : }
248 0 : return nullptr;
249 : }
250 :
251 0 : return req.forget().downcast<DOMRequest>();
252 : }
253 :
254 : void
255 0 : nsBrowserElement::Zoom(float aZoom, ErrorResult& aRv)
256 : {
257 0 : NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
258 :
259 0 : nsresult rv = mBrowserElementAPI->Zoom(aZoom);
260 :
261 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
262 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
263 : }
264 : }
265 :
266 : already_AddRefed<DOMRequest>
267 0 : nsBrowserElement::GetCanGoBack(ErrorResult& aRv)
268 : {
269 0 : NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
270 :
271 0 : nsCOMPtr<nsIDOMDOMRequest> req;
272 0 : nsresult rv = mBrowserElementAPI->GetCanGoBack(getter_AddRefs(req));
273 :
274 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
275 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
276 0 : return nullptr;
277 : }
278 :
279 0 : return req.forget().downcast<DOMRequest>();
280 : }
281 :
282 : already_AddRefed<DOMRequest>
283 0 : nsBrowserElement::GetCanGoForward(ErrorResult& aRv)
284 : {
285 0 : NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
286 :
287 0 : nsCOMPtr<nsIDOMDOMRequest> req;
288 0 : nsresult rv = mBrowserElementAPI->GetCanGoForward(getter_AddRefs(req));
289 :
290 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
291 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
292 0 : return nullptr;
293 : }
294 :
295 0 : return req.forget().downcast<DOMRequest>();
296 : }
297 :
298 : already_AddRefed<DOMRequest>
299 0 : nsBrowserElement::GetContentDimensions(ErrorResult& aRv)
300 : {
301 0 : NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
302 :
303 0 : nsCOMPtr<nsIDOMDOMRequest> req;
304 0 : nsresult rv = mBrowserElementAPI->GetContentDimensions(getter_AddRefs(req));
305 :
306 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
307 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
308 0 : return nullptr;
309 : }
310 :
311 0 : return req.forget().downcast<DOMRequest>();
312 : }
313 :
314 : void
315 0 : nsBrowserElement::FindAll(const nsAString& aSearchString,
316 : BrowserFindCaseSensitivity aCaseSensitivity,
317 : ErrorResult& aRv)
318 : {
319 0 : NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
320 :
321 : uint32_t caseSensitivity;
322 0 : if (aCaseSensitivity == BrowserFindCaseSensitivity::Case_insensitive) {
323 0 : caseSensitivity = nsIBrowserElementAPI::FIND_CASE_INSENSITIVE;
324 : } else {
325 0 : caseSensitivity = nsIBrowserElementAPI::FIND_CASE_SENSITIVE;
326 : }
327 :
328 0 : nsresult rv = mBrowserElementAPI->FindAll(aSearchString, caseSensitivity);
329 :
330 0 : if (NS_FAILED(rv)) {
331 0 : aRv.Throw(rv);
332 : }
333 : }
334 :
335 : void
336 0 : nsBrowserElement::FindNext(BrowserFindDirection aDirection,
337 : ErrorResult& aRv)
338 : {
339 0 : NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
340 :
341 : uint32_t direction;
342 0 : if (aDirection == BrowserFindDirection::Backward) {
343 0 : direction = nsIBrowserElementAPI::FIND_BACKWARD;
344 : } else {
345 0 : direction = nsIBrowserElementAPI::FIND_FORWARD;
346 : }
347 :
348 0 : nsresult rv = mBrowserElementAPI->FindNext(direction);
349 :
350 0 : if (NS_FAILED(rv)) {
351 0 : aRv.Throw(rv);
352 : }
353 : }
354 :
355 : void
356 0 : nsBrowserElement::ClearMatch(ErrorResult& aRv)
357 : {
358 0 : NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
359 :
360 0 : nsresult rv = mBrowserElementAPI->ClearMatch();
361 :
362 0 : if (NS_FAILED(rv)) {
363 0 : aRv.Throw(rv);
364 : }
365 : }
366 :
367 : void
368 0 : nsBrowserElement::AddNextPaintListener(BrowserElementNextPaintEventCallback& aListener,
369 : ErrorResult& aRv)
370 : {
371 0 : NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
372 :
373 : CallbackObjectHolder<BrowserElementNextPaintEventCallback,
374 0 : nsIBrowserElementNextPaintListener> holder(&aListener);
375 0 : nsCOMPtr<nsIBrowserElementNextPaintListener> listener = holder.ToXPCOMCallback();
376 :
377 0 : nsresult rv = mBrowserElementAPI->AddNextPaintListener(listener);
378 :
379 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
380 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
381 : }
382 : }
383 :
384 : void
385 0 : nsBrowserElement::RemoveNextPaintListener(BrowserElementNextPaintEventCallback& aListener,
386 : ErrorResult& aRv)
387 : {
388 0 : NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
389 :
390 : CallbackObjectHolder<BrowserElementNextPaintEventCallback,
391 0 : nsIBrowserElementNextPaintListener> holder(&aListener);
392 0 : nsCOMPtr<nsIBrowserElementNextPaintListener> listener = holder.ToXPCOMCallback();
393 :
394 0 : nsresult rv = mBrowserElementAPI->RemoveNextPaintListener(listener);
395 :
396 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
397 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
398 : }
399 : }
400 :
401 : already_AddRefed<DOMRequest>
402 0 : nsBrowserElement::ExecuteScript(const nsAString& aScript,
403 : const BrowserElementExecuteScriptOptions& aOptions,
404 : ErrorResult& aRv)
405 : {
406 0 : NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
407 :
408 0 : nsCOMPtr<nsIDOMDOMRequest> req;
409 0 : nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(mBrowserElementAPI);
410 0 : MOZ_ASSERT(wrappedObj, "Failed to get wrapped JS from XPCOM component.");
411 0 : AutoJSAPI jsapi;
412 0 : if (!jsapi.Init(wrappedObj->GetJSObject())) {
413 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
414 0 : return nullptr;
415 : }
416 0 : JSContext* cx = jsapi.cx();
417 0 : JS::Rooted<JS::Value> options(cx);
418 0 : aRv.MightThrowJSException();
419 0 : if (!ToJSValue(cx, aOptions, &options)) {
420 0 : aRv.StealExceptionFromJSContext(cx);
421 0 : return nullptr;
422 : }
423 :
424 0 : nsresult rv = mBrowserElementAPI->ExecuteScript(aScript, options, getter_AddRefs(req));
425 :
426 0 : if (NS_FAILED(rv)) {
427 0 : if (rv == NS_ERROR_INVALID_ARG) {
428 0 : aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
429 : } else {
430 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
431 : }
432 0 : return nullptr;
433 : }
434 :
435 0 : return req.forget().downcast<DOMRequest>();
436 : }
437 :
438 : already_AddRefed<DOMRequest>
439 0 : nsBrowserElement::GetWebManifest(ErrorResult& aRv)
440 : {
441 0 : NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
442 :
443 0 : nsCOMPtr<nsIDOMDOMRequest> req;
444 0 : nsresult rv = mBrowserElementAPI->GetWebManifest(getter_AddRefs(req));
445 :
446 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
447 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
448 0 : return nullptr;
449 : }
450 :
451 0 : return req.forget().downcast<DOMRequest>();
452 : }
453 :
454 :
455 :
456 : } // namespace mozilla
|