Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
2 /* vim: set sw=2 ts=8 et 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/. */
7 #include "base/basictypes.h"
9 #include "TabParent.h"
11 #include "AppProcessChecker.h"
12 #include "IDBFactory.h"
13 #include "IndexedDBParent.h"
14 #include "mozIApplication.h"
15 #include "mozilla/BrowserElementParent.h"
16 #include "mozilla/docshell/OfflineCacheUpdateParent.h"
17 #include "mozilla/dom/ContentParent.h"
18 #include "mozilla/dom/PContentPermissionRequestParent.h"
19 #include "mozilla/EventStateManager.h"
20 #include "mozilla/Hal.h"
21 #include "mozilla/ipc/DocumentRendererParent.h"
22 #include "mozilla/layers/CompositorParent.h"
23 #include "mozilla/layout/RenderFrameParent.h"
24 #include "mozilla/MouseEvents.h"
25 #include "mozilla/Preferences.h"
26 #include "mozilla/TextEvents.h"
27 #include "mozilla/TouchEvents.h"
28 #include "mozilla/unused.h"
29 #include "nsCOMPtr.h"
30 #include "nsContentPermissionHelper.h"
31 #include "nsContentUtils.h"
32 #include "nsDebug.h"
33 #include "nsFocusManager.h"
34 #include "nsFrameLoader.h"
35 #include "nsIContent.h"
36 #include "nsIDocShell.h"
37 #include "nsIDocShellTreeOwner.h"
38 #include "nsIDOMElement.h"
39 #include "nsIDOMEvent.h"
40 #include "nsIDOMWindow.h"
41 #include "nsIDOMWindowUtils.h"
42 #include "nsIInterfaceRequestorUtils.h"
43 #include "nsIPromptFactory.h"
44 #include "nsIURI.h"
45 #include "nsIWebBrowserChrome.h"
46 #include "nsIXULBrowserWindow.h"
47 #include "nsIXULWindow.h"
48 #include "nsViewManager.h"
49 #include "nsIWidget.h"
50 #include "nsIWindowWatcher.h"
51 #include "nsPIDOMWindow.h"
52 #include "nsPrintfCString.h"
53 #include "nsServiceManagerUtils.h"
54 #include "nsThreadUtils.h"
55 #include "private/pprio.h"
56 #include "PermissionMessageUtils.h"
57 #include "StructuredCloneUtils.h"
58 #include "ColorPickerParent.h"
59 #include "JavaScriptParent.h"
60 #include "FilePickerParent.h"
61 #include "TabChild.h"
62 #include "LoadContext.h"
63 #include "nsNetCID.h"
64 #include <algorithm>
66 using namespace mozilla::dom;
67 using namespace mozilla::ipc;
68 using namespace mozilla::layers;
69 using namespace mozilla::layout;
70 using namespace mozilla::services;
71 using namespace mozilla::widget;
72 using namespace mozilla::dom::indexedDB;
73 using namespace mozilla::jsipc;
75 // The flags passed by the webProgress notifications are 16 bits shifted
76 // from the ones registered by webProgressListeners.
77 #define NOTIFY_FLAG_SHIFT 16
79 class OpenFileAndSendFDRunnable : public nsRunnable
80 {
81 const nsString mPath;
82 nsRefPtr<TabParent> mTabParent;
83 nsCOMPtr<nsIEventTarget> mEventTarget;
84 PRFileDesc* mFD;
86 public:
87 OpenFileAndSendFDRunnable(const nsAString& aPath, TabParent* aTabParent)
88 : mPath(aPath), mTabParent(aTabParent), mFD(nullptr)
89 {
90 MOZ_ASSERT(NS_IsMainThread());
91 MOZ_ASSERT(!aPath.IsEmpty());
92 MOZ_ASSERT(aTabParent);
93 }
95 void Dispatch()
96 {
97 MOZ_ASSERT(NS_IsMainThread());
99 mEventTarget = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
100 NS_ENSURE_TRUE_VOID(mEventTarget);
102 nsresult rv = mEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
103 NS_ENSURE_SUCCESS_VOID(rv);
104 }
106 private:
107 ~OpenFileAndSendFDRunnable()
108 {
109 MOZ_ASSERT(!mFD);
110 }
112 // This shouldn't be called directly except by the event loop. Use Dispatch
113 // to start the sequence.
114 NS_IMETHOD Run()
115 {
116 if (NS_IsMainThread()) {
117 SendResponse();
118 } else if (mFD) {
119 CloseFile();
120 } else {
121 OpenFile();
122 }
124 return NS_OK;
125 }
127 void SendResponse()
128 {
129 MOZ_ASSERT(NS_IsMainThread());
130 MOZ_ASSERT(mTabParent);
131 MOZ_ASSERT(mEventTarget);
132 MOZ_ASSERT(mFD);
134 nsRefPtr<TabParent> tabParent;
135 mTabParent.swap(tabParent);
137 using mozilla::ipc::FileDescriptor;
139 FileDescriptor::PlatformHandleType handle =
140 FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(mFD));
142 mozilla::unused << tabParent->SendCacheFileDescriptor(mPath, handle);
144 nsCOMPtr<nsIEventTarget> eventTarget;
145 mEventTarget.swap(eventTarget);
147 if (NS_FAILED(eventTarget->Dispatch(this, NS_DISPATCH_NORMAL))) {
148 NS_WARNING("Failed to dispatch to stream transport service!");
150 // It's probably safer to take the main thread IO hit here rather
151 // than leak a file descriptor.
152 CloseFile();
153 }
154 }
156 void OpenFile()
157 {
158 MOZ_ASSERT(!NS_IsMainThread());
159 MOZ_ASSERT(!mFD);
161 nsCOMPtr<nsIFile> file;
162 nsresult rv = NS_NewLocalFile(mPath, false, getter_AddRefs(file));
163 NS_ENSURE_SUCCESS_VOID(rv);
165 PRFileDesc* fd;
166 rv = file->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
167 NS_ENSURE_SUCCESS_VOID(rv);
169 mFD = fd;
171 if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
172 NS_WARNING("Failed to dispatch to main thread!");
174 CloseFile();
175 }
176 }
178 void CloseFile()
179 {
180 // It's possible for this to happen on the main thread if the dispatch
181 // to the stream service fails after we've already opened the file so
182 // we can't assert the thread we're running on.
184 MOZ_ASSERT(mFD);
186 PRStatus prrc;
187 prrc = PR_Close(mFD);
188 if (prrc != PR_SUCCESS) {
189 NS_ERROR("PR_Close() failed.");
190 }
191 mFD = nullptr;
192 }
193 };
195 namespace mozilla {
196 namespace dom {
198 TabParent* sEventCapturer;
200 TabParent *TabParent::mIMETabParent = nullptr;
202 NS_IMPL_ISUPPORTS(TabParent, nsITabParent, nsIAuthPromptProvider, nsISecureBrowserUI)
204 TabParent::TabParent(ContentParent* aManager, const TabContext& aContext, uint32_t aChromeFlags)
205 : TabContext(aContext)
206 , mFrameElement(nullptr)
207 , mIMESelectionAnchor(0)
208 , mIMESelectionFocus(0)
209 , mIMEComposing(false)
210 , mIMECompositionEnding(false)
211 , mIMECompositionStart(0)
212 , mIMESeqno(0)
213 , mIMECompositionRectOffset(0)
214 , mEventCaptureDepth(0)
215 , mRect(0, 0, 0, 0)
216 , mDimensions(0, 0)
217 , mOrientation(0)
218 , mDPI(0)
219 , mDefaultScale(0)
220 , mShown(false)
221 , mUpdatedDimensions(false)
222 , mManager(aManager)
223 , mMarkedDestroying(false)
224 , mIsDestroyed(false)
225 , mAppPackageFileDescriptorSent(false)
226 , mChromeFlags(aChromeFlags)
227 {
228 }
230 TabParent::~TabParent()
231 {
232 }
234 void
235 TabParent::SetOwnerElement(Element* aElement)
236 {
237 mFrameElement = aElement;
238 TryCacheDPIAndScale();
239 }
241 void
242 TabParent::GetAppType(nsAString& aOut)
243 {
244 aOut.Truncate();
245 nsCOMPtr<Element> elem = do_QueryInterface(mFrameElement);
246 if (!elem) {
247 return;
248 }
250 elem->GetAttr(kNameSpaceID_None, nsGkAtoms::mozapptype, aOut);
251 }
253 bool
254 TabParent::IsVisible()
255 {
256 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
257 if (!frameLoader) {
258 return false;
259 }
261 bool visible = false;
262 frameLoader->GetVisible(&visible);
263 return visible;
264 }
266 void
267 TabParent::Destroy()
268 {
269 if (mIsDestroyed) {
270 return;
271 }
273 // If this fails, it's most likely due to a content-process crash,
274 // and auto-cleanup will kick in. Otherwise, the child side will
275 // destroy itself and send back __delete__().
276 unused << SendDestroy();
278 const InfallibleTArray<PIndexedDBParent*>& idbParents =
279 ManagedPIndexedDBParent();
280 for (uint32_t i = 0; i < idbParents.Length(); ++i) {
281 static_cast<IndexedDBParent*>(idbParents[i])->Disconnect();
282 }
284 const InfallibleTArray<POfflineCacheUpdateParent*>& ocuParents =
285 ManagedPOfflineCacheUpdateParent();
286 for (uint32_t i = 0; i < ocuParents.Length(); ++i) {
287 nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> ocuParent =
288 static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(ocuParents[i]);
289 ocuParent->StopSendingMessagesToChild();
290 }
292 if (RenderFrameParent* frame = GetRenderFrame()) {
293 frame->Destroy();
294 }
295 mIsDestroyed = true;
297 Manager()->NotifyTabDestroying(this);
298 mMarkedDestroying = true;
299 }
301 bool
302 TabParent::Recv__delete__()
303 {
304 Manager()->NotifyTabDestroyed(this, mMarkedDestroying);
305 return true;
306 }
308 void
309 TabParent::ActorDestroy(ActorDestroyReason why)
310 {
311 if (sEventCapturer == this) {
312 sEventCapturer = nullptr;
313 }
314 if (mIMETabParent == this) {
315 mIMETabParent = nullptr;
316 }
317 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
318 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
319 nsRefPtr<nsFrameMessageManager> fmm;
320 if (frameLoader) {
321 fmm = frameLoader->GetFrameMessageManager();
322 nsCOMPtr<Element> frameElement(mFrameElement);
323 ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr,
324 nullptr);
325 frameLoader->DestroyChild();
327 if (why == AbnormalShutdown && os) {
328 os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, frameLoader),
329 "oop-frameloader-crashed", nullptr);
330 nsContentUtils::DispatchTrustedEvent(frameElement->OwnerDoc(), frameElement,
331 NS_LITERAL_STRING("oop-browser-crashed"),
332 true, true);
333 }
334 }
336 if (os) {
337 os->NotifyObservers(NS_ISUPPORTS_CAST(nsITabParent*, this), "ipc:browser-destroyed", nullptr);
338 }
339 if (fmm) {
340 fmm->Disconnect();
341 }
342 }
344 bool
345 TabParent::RecvMoveFocus(const bool& aForward)
346 {
347 nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
348 if (fm) {
349 nsCOMPtr<nsIDOMElement> dummy;
350 uint32_t type = aForward ? uint32_t(nsIFocusManager::MOVEFOCUS_FORWARD)
351 : uint32_t(nsIFocusManager::MOVEFOCUS_BACKWARD);
352 nsCOMPtr<nsIDOMElement> frame = do_QueryInterface(mFrameElement);
353 fm->MoveFocus(nullptr, frame, type, nsIFocusManager::FLAG_BYKEY,
354 getter_AddRefs(dummy));
355 }
356 return true;
357 }
359 bool
360 TabParent::RecvEvent(const RemoteDOMEvent& aEvent)
361 {
362 nsCOMPtr<nsIDOMEvent> event = do_QueryInterface(aEvent.mEvent);
363 NS_ENSURE_TRUE(event, true);
365 nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryInterface(mFrameElement);
366 NS_ENSURE_TRUE(target, true);
368 event->SetOwner(target);
370 bool dummy;
371 target->DispatchEvent(event, &dummy);
372 return true;
373 }
375 bool
376 TabParent::AnswerCreateWindow(PBrowserParent** retval)
377 {
378 if (!mBrowserDOMWindow) {
379 return false;
380 }
382 // Only non-app, non-browser processes may call CreateWindow.
383 if (IsBrowserOrApp()) {
384 return false;
385 }
387 // Get a new rendering area from the browserDOMWin. We don't want
388 // to be starting any loads here, so get it with a null URI.
389 nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
390 mBrowserDOMWindow->OpenURIInFrame(nullptr, nullptr,
391 nsIBrowserDOMWindow::OPEN_NEWTAB,
392 nsIBrowserDOMWindow::OPEN_NEW,
393 getter_AddRefs(frameLoaderOwner));
394 if (!frameLoaderOwner) {
395 return false;
396 }
398 nsRefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
399 if (!frameLoader) {
400 return false;
401 }
403 *retval = frameLoader->GetRemoteBrowser();
404 return true;
405 }
407 void
408 TabParent::LoadURL(nsIURI* aURI)
409 {
410 MOZ_ASSERT(aURI);
412 if (mIsDestroyed) {
413 return;
414 }
416 nsCString spec;
417 aURI->GetSpec(spec);
419 if (!mShown) {
420 NS_WARNING(nsPrintfCString("TabParent::LoadURL(%s) called before "
421 "Show(). Ignoring LoadURL.\n",
422 spec.get()).get());
423 return;
424 }
426 unused << SendLoadURL(spec);
428 // If this app is a packaged app then we can speed startup by sending over
429 // the file descriptor for the "application.zip" file that it will
430 // invariably request. Only do this once.
431 if (!mAppPackageFileDescriptorSent) {
432 mAppPackageFileDescriptorSent = true;
434 nsCOMPtr<mozIApplication> app = GetOwnOrContainingApp();
435 if (app) {
436 nsString manifestURL;
437 nsresult rv = app->GetManifestURL(manifestURL);
438 NS_ENSURE_SUCCESS_VOID(rv);
440 if (StringBeginsWith(manifestURL, NS_LITERAL_STRING("app:"))) {
441 nsString basePath;
442 rv = app->GetBasePath(basePath);
443 NS_ENSURE_SUCCESS_VOID(rv);
445 nsString appId;
446 rv = app->GetId(appId);
447 NS_ENSURE_SUCCESS_VOID(rv);
449 nsCOMPtr<nsIFile> packageFile;
450 rv = NS_NewLocalFile(basePath, false,
451 getter_AddRefs(packageFile));
452 NS_ENSURE_SUCCESS_VOID(rv);
454 rv = packageFile->Append(appId);
455 NS_ENSURE_SUCCESS_VOID(rv);
457 rv = packageFile->Append(NS_LITERAL_STRING("application.zip"));
458 NS_ENSURE_SUCCESS_VOID(rv);
460 nsString path;
461 rv = packageFile->GetPath(path);
462 NS_ENSURE_SUCCESS_VOID(rv);
464 nsRefPtr<OpenFileAndSendFDRunnable> openFileRunnable =
465 new OpenFileAndSendFDRunnable(path, this);
466 openFileRunnable->Dispatch();
467 }
468 }
469 }
470 }
472 void
473 TabParent::Show(const nsIntSize& size)
474 {
475 // sigh
476 mShown = true;
477 mDimensions = size;
478 if (!mIsDestroyed) {
479 unused << SendShow(size);
480 }
481 }
483 void
484 TabParent::UpdateDimensions(const nsRect& rect, const nsIntSize& size)
485 {
486 if (mIsDestroyed) {
487 return;
488 }
489 hal::ScreenConfiguration config;
490 hal::GetCurrentScreenConfiguration(&config);
491 ScreenOrientation orientation = config.orientation();
493 if (!mUpdatedDimensions || mOrientation != orientation ||
494 mDimensions != size || !mRect.IsEqualEdges(rect)) {
495 mUpdatedDimensions = true;
496 mRect = rect;
497 mDimensions = size;
498 mOrientation = orientation;
500 unused << SendUpdateDimensions(mRect, mDimensions, mOrientation);
501 }
502 }
504 void
505 TabParent::UpdateFrame(const FrameMetrics& aFrameMetrics)
506 {
507 if (!mIsDestroyed) {
508 unused << SendUpdateFrame(aFrameMetrics);
509 }
510 }
512 void
513 TabParent::AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration)
514 {
515 if (!mIsDestroyed) {
516 unused << SendAcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
517 }
518 }
520 void TabParent::HandleDoubleTap(const CSSPoint& aPoint,
521 int32_t aModifiers,
522 const ScrollableLayerGuid &aGuid)
523 {
524 if (!mIsDestroyed) {
525 unused << SendHandleDoubleTap(aPoint, aGuid);
526 }
527 }
529 void TabParent::HandleSingleTap(const CSSPoint& aPoint,
530 int32_t aModifiers,
531 const ScrollableLayerGuid &aGuid)
532 {
533 // TODO Send the modifier data to TabChild for use in mouse events.
534 if (!mIsDestroyed) {
535 unused << SendHandleSingleTap(aPoint, aGuid);
536 }
537 }
539 void TabParent::HandleLongTap(const CSSPoint& aPoint,
540 int32_t aModifiers,
541 const ScrollableLayerGuid &aGuid)
542 {
543 if (!mIsDestroyed) {
544 unused << SendHandleLongTap(aPoint, aGuid);
545 }
546 }
548 void TabParent::HandleLongTapUp(const CSSPoint& aPoint,
549 int32_t aModifiers,
550 const ScrollableLayerGuid &aGuid)
551 {
552 if (!mIsDestroyed) {
553 unused << SendHandleLongTapUp(aPoint, aGuid);
554 }
555 }
557 void TabParent::NotifyAPZStateChange(ViewID aViewId,
558 APZStateChange aChange,
559 int aArg)
560 {
561 if (!mIsDestroyed) {
562 unused << SendNotifyAPZStateChange(aViewId, aChange, aArg);
563 }
564 }
566 void
567 TabParent::Activate()
568 {
569 if (!mIsDestroyed) {
570 unused << SendActivate();
571 }
572 }
574 void
575 TabParent::Deactivate()
576 {
577 if (!mIsDestroyed) {
578 unused << SendDeactivate();
579 }
580 }
582 NS_IMETHODIMP
583 TabParent::Init(nsIDOMWindow *window)
584 {
585 return NS_OK;
586 }
588 NS_IMETHODIMP
589 TabParent::GetState(uint32_t *aState)
590 {
591 NS_ENSURE_ARG(aState);
592 NS_WARNING("SecurityState not valid here");
593 *aState = 0;
594 return NS_OK;
595 }
597 NS_IMETHODIMP
598 TabParent::SetDocShell(nsIDocShell *aDocShell)
599 {
600 NS_ENSURE_ARG(aDocShell);
601 NS_WARNING("No mDocShell member in TabParent so there is no docShell to set");
602 return NS_OK;
603 }
605 PDocumentRendererParent*
606 TabParent::AllocPDocumentRendererParent(const nsRect& documentRect,
607 const gfx::Matrix& transform,
608 const nsString& bgcolor,
609 const uint32_t& renderFlags,
610 const bool& flushLayout,
611 const nsIntSize& renderSize)
612 {
613 return new DocumentRendererParent();
614 }
616 bool
617 TabParent::DeallocPDocumentRendererParent(PDocumentRendererParent* actor)
618 {
619 delete actor;
620 return true;
621 }
623 PContentPermissionRequestParent*
624 TabParent::AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
625 const IPC::Principal& aPrincipal)
626 {
627 return CreateContentPermissionRequestParent(aRequests, mFrameElement, aPrincipal);
628 }
630 bool
631 TabParent::DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor)
632 {
633 delete actor;
634 return true;
635 }
637 PFilePickerParent*
638 TabParent::AllocPFilePickerParent(const nsString& aTitle, const int16_t& aMode)
639 {
640 return new FilePickerParent(aTitle, aMode);
641 }
643 bool
644 TabParent::DeallocPFilePickerParent(PFilePickerParent* actor)
645 {
646 delete actor;
647 return true;
648 }
650 void
651 TabParent::SendMouseEvent(const nsAString& aType, float aX, float aY,
652 int32_t aButton, int32_t aClickCount,
653 int32_t aModifiers, bool aIgnoreRootScrollFrame)
654 {
655 if (!mIsDestroyed) {
656 unused << PBrowserParent::SendMouseEvent(nsString(aType), aX, aY,
657 aButton, aClickCount,
658 aModifiers, aIgnoreRootScrollFrame);
659 }
660 }
662 void
663 TabParent::SendKeyEvent(const nsAString& aType,
664 int32_t aKeyCode,
665 int32_t aCharCode,
666 int32_t aModifiers,
667 bool aPreventDefault)
668 {
669 if (!mIsDestroyed) {
670 unused << PBrowserParent::SendKeyEvent(nsString(aType), aKeyCode, aCharCode,
671 aModifiers, aPreventDefault);
672 }
673 }
675 bool
676 TabParent::MapEventCoordinatesForChildProcess(WidgetEvent* aEvent)
677 {
678 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
679 if (!frameLoader) {
680 return false;
681 }
682 LayoutDeviceIntPoint offset =
683 EventStateManager::GetChildProcessOffset(frameLoader, *aEvent);
684 MapEventCoordinatesForChildProcess(offset, aEvent);
685 return true;
686 }
688 void
689 TabParent::MapEventCoordinatesForChildProcess(
690 const LayoutDeviceIntPoint& aOffset, WidgetEvent* aEvent)
691 {
692 if (aEvent->eventStructType != NS_TOUCH_EVENT) {
693 aEvent->refPoint = aOffset;
694 } else {
695 aEvent->refPoint = LayoutDeviceIntPoint();
696 // Then offset all the touch points by that distance, to put them
697 // in the space where top-left is 0,0.
698 const nsTArray< nsRefPtr<Touch> >& touches =
699 aEvent->AsTouchEvent()->touches;
700 for (uint32_t i = 0; i < touches.Length(); ++i) {
701 Touch* touch = touches[i];
702 if (touch) {
703 touch->mRefPoint += LayoutDeviceIntPoint::ToUntyped(aOffset);
704 }
705 }
706 }
707 }
709 bool TabParent::SendRealMouseEvent(WidgetMouseEvent& event)
710 {
711 if (mIsDestroyed) {
712 return false;
713 }
714 MaybeForwardEventToRenderFrame(event, nullptr);
715 if (!MapEventCoordinatesForChildProcess(&event)) {
716 return false;
717 }
718 return PBrowserParent::SendRealMouseEvent(event);
719 }
721 CSSPoint TabParent::AdjustTapToChildWidget(const CSSPoint& aPoint)
722 {
723 nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
725 if (!content || !content->OwnerDoc()) {
726 return aPoint;
727 }
729 nsIDocument* doc = content->OwnerDoc();
730 if (!doc || !doc->GetShell()) {
731 return aPoint;
732 }
733 nsPresContext* presContext = doc->GetShell()->GetPresContext();
735 return aPoint + CSSPoint(
736 presContext->DevPixelsToFloatCSSPixels(mChildProcessOffsetAtTouchStart.x),
737 presContext->DevPixelsToFloatCSSPixels(mChildProcessOffsetAtTouchStart.y));
738 }
740 bool TabParent::SendHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
741 {
742 if (mIsDestroyed) {
743 return false;
744 }
746 return PBrowserParent::SendHandleSingleTap(AdjustTapToChildWidget(aPoint), aGuid);
747 }
749 bool TabParent::SendHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
750 {
751 if (mIsDestroyed) {
752 return false;
753 }
755 return PBrowserParent::SendHandleLongTap(AdjustTapToChildWidget(aPoint), aGuid);
756 }
758 bool TabParent::SendHandleLongTapUp(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
759 {
760 if (mIsDestroyed) {
761 return false;
762 }
764 return PBrowserParent::SendHandleLongTapUp(AdjustTapToChildWidget(aPoint), aGuid);
765 }
767 bool TabParent::SendHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
768 {
769 if (mIsDestroyed) {
770 return false;
771 }
773 return PBrowserParent::SendHandleDoubleTap(AdjustTapToChildWidget(aPoint), aGuid);
774 }
776 bool TabParent::SendMouseWheelEvent(WidgetWheelEvent& event)
777 {
778 if (mIsDestroyed) {
779 return false;
780 }
781 MaybeForwardEventToRenderFrame(event, nullptr);
782 if (!MapEventCoordinatesForChildProcess(&event)) {
783 return false;
784 }
785 return PBrowserParent::SendMouseWheelEvent(event);
786 }
788 static void
789 DoCommandCallback(mozilla::Command aCommand, void* aData)
790 {
791 static_cast<InfallibleTArray<mozilla::CommandInt>*>(aData)->AppendElement(aCommand);
792 }
794 bool
795 TabParent::RecvRequestNativeKeyBindings(const WidgetKeyboardEvent& aEvent,
796 MaybeNativeKeyBinding* aBindings)
797 {
798 AutoInfallibleTArray<mozilla::CommandInt, 4> singleLine;
799 AutoInfallibleTArray<mozilla::CommandInt, 4> multiLine;
800 AutoInfallibleTArray<mozilla::CommandInt, 4> richText;
802 *aBindings = mozilla::void_t();
804 nsCOMPtr<nsIWidget> widget = GetWidget();
805 if (!widget) {
806 return true;
807 }
809 WidgetKeyboardEvent localEvent(aEvent);
811 if (NS_FAILED(widget->AttachNativeKeyEvent(localEvent))) {
812 return true;
813 }
815 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForSingleLineEditor,
816 localEvent, DoCommandCallback, &singleLine);
817 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForMultiLineEditor,
818 localEvent, DoCommandCallback, &multiLine);
819 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForRichTextEditor,
820 localEvent, DoCommandCallback, &richText);
822 if (!singleLine.IsEmpty() || !multiLine.IsEmpty() || !richText.IsEmpty()) {
823 *aBindings = NativeKeyBinding(singleLine, multiLine, richText);
824 }
826 return true;
827 }
829 bool TabParent::SendRealKeyEvent(WidgetKeyboardEvent& event)
830 {
831 if (mIsDestroyed) {
832 return false;
833 }
834 MaybeForwardEventToRenderFrame(event, nullptr);
835 if (!MapEventCoordinatesForChildProcess(&event)) {
836 return false;
837 }
840 MaybeNativeKeyBinding bindings;
841 bindings = void_t();
842 if (event.message == NS_KEY_PRESS) {
843 nsCOMPtr<nsIWidget> widget = GetWidget();
845 AutoInfallibleTArray<mozilla::CommandInt, 4> singleLine;
846 AutoInfallibleTArray<mozilla::CommandInt, 4> multiLine;
847 AutoInfallibleTArray<mozilla::CommandInt, 4> richText;
849 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForSingleLineEditor,
850 event, DoCommandCallback, &singleLine);
851 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForMultiLineEditor,
852 event, DoCommandCallback, &multiLine);
853 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForRichTextEditor,
854 event, DoCommandCallback, &richText);
856 if (!singleLine.IsEmpty() || !multiLine.IsEmpty() || !richText.IsEmpty()) {
857 bindings = NativeKeyBinding(singleLine, multiLine, richText);
858 }
859 }
861 return PBrowserParent::SendRealKeyEvent(event, bindings);
862 }
864 bool TabParent::SendRealTouchEvent(WidgetTouchEvent& event)
865 {
866 if (mIsDestroyed) {
867 return false;
868 }
869 if (event.message == NS_TOUCH_START) {
870 // Adjust the widget coordinates to be relative to our frame.
871 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
872 if (!frameLoader) {
873 // No frame anymore?
874 sEventCapturer = nullptr;
875 return false;
876 }
878 mChildProcessOffsetAtTouchStart =
879 EventStateManager::GetChildProcessOffset(frameLoader, event);
881 MOZ_ASSERT((!sEventCapturer && mEventCaptureDepth == 0) ||
882 (sEventCapturer == this && mEventCaptureDepth > 0));
883 // We want to capture all remaining touch events in this series
884 // for fast-path dispatch.
885 sEventCapturer = this;
886 ++mEventCaptureDepth;
887 }
889 // PresShell::HandleEventInternal adds touches on touch end/cancel. This
890 // confuses remote content and the panning and zooming logic into thinking
891 // that the added touches are part of the touchend/cancel, when actually
892 // they're not.
893 if (event.message == NS_TOUCH_END || event.message == NS_TOUCH_CANCEL) {
894 for (int i = event.touches.Length() - 1; i >= 0; i--) {
895 if (!event.touches[i]->mChanged) {
896 event.touches.RemoveElementAt(i);
897 }
898 }
899 }
901 ScrollableLayerGuid guid;
902 MaybeForwardEventToRenderFrame(event, &guid);
904 if (mIsDestroyed) {
905 return false;
906 }
908 MapEventCoordinatesForChildProcess(mChildProcessOffsetAtTouchStart, &event);
910 return (event.message == NS_TOUCH_MOVE) ?
911 PBrowserParent::SendRealTouchMoveEvent(event, guid) :
912 PBrowserParent::SendRealTouchEvent(event, guid);
913 }
915 /*static*/ TabParent*
916 TabParent::GetEventCapturer()
917 {
918 return sEventCapturer;
919 }
921 bool
922 TabParent::TryCapture(const WidgetGUIEvent& aEvent)
923 {
924 MOZ_ASSERT(sEventCapturer == this && mEventCaptureDepth > 0);
926 if (aEvent.eventStructType != NS_TOUCH_EVENT) {
927 // Only capture of touch events is implemented, for now.
928 return false;
929 }
931 WidgetTouchEvent event(*aEvent.AsTouchEvent());
933 bool isTouchPointUp = (event.message == NS_TOUCH_END ||
934 event.message == NS_TOUCH_CANCEL);
935 if (event.message == NS_TOUCH_START || isTouchPointUp) {
936 // Let the DOM see touch start/end events so that its touch-point
937 // state stays consistent.
938 if (isTouchPointUp && 0 == --mEventCaptureDepth) {
939 // All event series are un-captured, don't try to catch any
940 // more.
941 sEventCapturer = nullptr;
942 }
943 return false;
944 }
946 SendRealTouchEvent(event);
947 return true;
948 }
950 bool
951 TabParent::RecvSyncMessage(const nsString& aMessage,
952 const ClonedMessageData& aData,
953 const InfallibleTArray<CpowEntry>& aCpows,
954 const IPC::Principal& aPrincipal,
955 InfallibleTArray<nsString>* aJSONRetVal)
956 {
957 nsIPrincipal* principal = aPrincipal;
958 ContentParent* parent = static_cast<ContentParent*>(Manager());
959 if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false) &&
960 principal && !AssertAppPrincipal(parent, principal)) {
961 return false;
962 }
964 StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
965 CpowIdHolder cpows(parent->GetCPOWManager(), aCpows);
966 return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal);
967 }
969 bool
970 TabParent::AnswerRpcMessage(const nsString& aMessage,
971 const ClonedMessageData& aData,
972 const InfallibleTArray<CpowEntry>& aCpows,
973 const IPC::Principal& aPrincipal,
974 InfallibleTArray<nsString>* aJSONRetVal)
975 {
976 nsIPrincipal* principal = aPrincipal;
977 ContentParent* parent = static_cast<ContentParent*>(Manager());
978 if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false) &&
979 principal && !AssertAppPrincipal(parent, principal)) {
980 return false;
981 }
983 StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
984 CpowIdHolder cpows(parent->GetCPOWManager(), aCpows);
985 return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal);
986 }
988 bool
989 TabParent::RecvAsyncMessage(const nsString& aMessage,
990 const ClonedMessageData& aData,
991 const InfallibleTArray<CpowEntry>& aCpows,
992 const IPC::Principal& aPrincipal)
993 {
994 nsIPrincipal* principal = aPrincipal;
995 ContentParent* parent = static_cast<ContentParent*>(Manager());
996 if (!Preferences::GetBool("dom.testing.ignore_ipc_principal", false) &&
997 principal && !AssertAppPrincipal(parent, principal)) {
998 return false;
999 }
1001 StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
1002 CpowIdHolder cpows(parent->GetCPOWManager(), aCpows);
1003 return ReceiveMessage(aMessage, false, &cloneData, &cpows, aPrincipal, nullptr);
1004 }
1006 bool
1007 TabParent::RecvSetCursor(const uint32_t& aCursor)
1008 {
1009 nsCOMPtr<nsIWidget> widget = GetWidget();
1010 if (widget) {
1011 widget->SetCursor((nsCursor) aCursor);
1012 }
1013 return true;
1014 }
1016 bool
1017 TabParent::RecvSetBackgroundColor(const nscolor& aColor)
1018 {
1019 if (RenderFrameParent* frame = GetRenderFrame()) {
1020 frame->SetBackgroundColor(aColor);
1021 }
1022 return true;
1023 }
1025 nsIXULBrowserWindow*
1026 TabParent::GetXULBrowserWindow()
1027 {
1028 nsCOMPtr<nsIContent> frame = do_QueryInterface(mFrameElement);
1029 if (!frame) {
1030 return nullptr;
1031 }
1033 nsCOMPtr<nsIDocShell> docShell = frame->OwnerDoc()->GetDocShell();
1034 if (!docShell) {
1035 return nullptr;
1036 }
1038 nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
1039 docShell->GetTreeOwner(getter_AddRefs(treeOwner));
1040 if (!treeOwner) {
1041 return nullptr;
1042 }
1044 nsCOMPtr<nsIXULWindow> window = do_GetInterface(treeOwner);
1045 if (!window) {
1046 return nullptr;
1047 }
1049 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow;
1050 window->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow));
1051 return xulBrowserWindow;
1052 }
1054 bool
1055 TabParent::RecvSetStatus(const uint32_t& aType, const nsString& aStatus)
1056 {
1057 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow();
1058 if (!xulBrowserWindow) {
1059 return true;
1060 }
1062 switch (aType) {
1063 case nsIWebBrowserChrome::STATUS_SCRIPT:
1064 xulBrowserWindow->SetJSStatus(aStatus);
1065 break;
1066 case nsIWebBrowserChrome::STATUS_LINK:
1067 xulBrowserWindow->SetOverLink(aStatus, nullptr);
1068 break;
1069 }
1070 return true;
1071 }
1073 bool
1074 TabParent::RecvShowTooltip(const uint32_t& aX, const uint32_t& aY, const nsString& aTooltip)
1075 {
1076 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow();
1077 if (!xulBrowserWindow) {
1078 return true;
1079 }
1081 xulBrowserWindow->ShowTooltip(aX, aY, aTooltip);
1082 return true;
1083 }
1085 bool
1086 TabParent::RecvHideTooltip()
1087 {
1088 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow();
1089 if (!xulBrowserWindow) {
1090 return true;
1091 }
1093 xulBrowserWindow->HideTooltip();
1094 return true;
1095 }
1097 bool
1098 TabParent::RecvNotifyIMEFocus(const bool& aFocus,
1099 nsIMEUpdatePreference* aPreference,
1100 uint32_t* aSeqno)
1101 {
1102 nsCOMPtr<nsIWidget> widget = GetWidget();
1103 if (!widget) {
1104 *aPreference = nsIMEUpdatePreference();
1105 return true;
1106 }
1108 *aSeqno = mIMESeqno;
1109 mIMETabParent = aFocus ? this : nullptr;
1110 mIMESelectionAnchor = 0;
1111 mIMESelectionFocus = 0;
1112 widget->NotifyIME(IMENotification(aFocus ? NOTIFY_IME_OF_FOCUS :
1113 NOTIFY_IME_OF_BLUR));
1115 if (aFocus) {
1116 *aPreference = widget->GetIMEUpdatePreference();
1117 } else {
1118 mIMECacheText.Truncate(0);
1119 }
1120 return true;
1121 }
1123 bool
1124 TabParent::RecvNotifyIMETextChange(const uint32_t& aStart,
1125 const uint32_t& aEnd,
1126 const uint32_t& aNewEnd,
1127 const bool& aCausedByComposition)
1128 {
1129 nsCOMPtr<nsIWidget> widget = GetWidget();
1130 if (!widget)
1131 return true;
1133 #ifdef DEBUG
1134 nsIMEUpdatePreference updatePreference = widget->GetIMEUpdatePreference();
1135 NS_ASSERTION(updatePreference.WantTextChange(),
1136 "Don't call Send/RecvNotifyIMETextChange without NOTIFY_TEXT_CHANGE");
1137 MOZ_ASSERT(!aCausedByComposition ||
1138 updatePreference.WantChangesCausedByComposition(),
1139 "The widget doesn't want text change notification caused by composition");
1140 #endif
1142 IMENotification notification(NOTIFY_IME_OF_TEXT_CHANGE);
1143 notification.mTextChangeData.mStartOffset = aStart;
1144 notification.mTextChangeData.mOldEndOffset = aEnd;
1145 notification.mTextChangeData.mNewEndOffset = aNewEnd;
1146 notification.mTextChangeData.mCausedByComposition = aCausedByComposition;
1147 widget->NotifyIME(notification);
1148 return true;
1149 }
1151 bool
1152 TabParent::RecvNotifyIMESelectedCompositionRect(const uint32_t& aOffset,
1153 const nsIntRect& aRect,
1154 const nsIntRect& aCaretRect)
1155 {
1156 // add rect to cache for another query
1157 mIMECompositionRectOffset = aOffset;
1158 mIMECompositionRect = aRect;
1159 mIMECaretRect = aCaretRect;
1161 nsCOMPtr<nsIWidget> widget = GetWidget();
1162 if (!widget) {
1163 return true;
1164 }
1165 widget->NotifyIME(IMENotification(NOTIFY_IME_OF_COMPOSITION_UPDATE));
1166 return true;
1167 }
1169 bool
1170 TabParent::RecvNotifyIMESelection(const uint32_t& aSeqno,
1171 const uint32_t& aAnchor,
1172 const uint32_t& aFocus,
1173 const bool& aCausedByComposition)
1174 {
1175 nsCOMPtr<nsIWidget> widget = GetWidget();
1176 if (!widget)
1177 return true;
1179 if (aSeqno == mIMESeqno) {
1180 mIMESelectionAnchor = aAnchor;
1181 mIMESelectionFocus = aFocus;
1182 const nsIMEUpdatePreference updatePreference =
1183 widget->GetIMEUpdatePreference();
1184 if (updatePreference.WantSelectionChange() &&
1185 (updatePreference.WantChangesCausedByComposition() ||
1186 !aCausedByComposition)) {
1187 IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
1188 notification.mSelectionChangeData.mCausedByComposition =
1189 aCausedByComposition;
1190 widget->NotifyIME(notification);
1191 }
1192 }
1193 return true;
1194 }
1196 bool
1197 TabParent::RecvNotifyIMETextHint(const nsString& aText)
1198 {
1199 // Replace our cache with new text
1200 mIMECacheText = aText;
1201 return true;
1202 }
1204 bool
1205 TabParent::RecvRequestFocus(const bool& aCanRaise)
1206 {
1207 nsCOMPtr<nsIFocusManager> fm = nsFocusManager::GetFocusManager();
1208 if (!fm) {
1209 return true;
1210 }
1212 nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
1213 if (!content || !content->OwnerDoc()) {
1214 return true;
1215 }
1217 uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
1218 if (aCanRaise)
1219 flags |= nsIFocusManager::FLAG_RAISE;
1221 nsCOMPtr<nsIDOMElement> node = do_QueryInterface(mFrameElement);
1222 fm->SetFocus(node, flags);
1223 return true;
1224 }
1226 nsIntPoint
1227 TabParent::GetChildProcessOffset()
1228 {
1229 // The "toplevel widget" in child processes is always at position
1230 // 0,0. Map the event coordinates to match that.
1232 nsIntPoint offset(0, 0);
1233 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
1234 if (!frameLoader) {
1235 return offset;
1236 }
1237 nsIFrame* targetFrame = frameLoader->GetPrimaryFrameOfOwningContent();
1238 if (!targetFrame) {
1239 return offset;
1240 }
1242 // Find out how far we're offset from the nearest widget.
1243 nsCOMPtr<nsIWidget> widget = GetWidget();
1244 if (!widget) {
1245 return offset;
1246 }
1247 nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(widget,
1248 nsIntPoint(0, 0),
1249 targetFrame);
1251 return LayoutDeviceIntPoint::ToUntyped(LayoutDeviceIntPoint::FromAppUnitsToNearest(
1252 pt, targetFrame->PresContext()->AppUnitsPerDevPixel()));
1253 }
1255 bool
1256 TabParent::RecvReplyKeyEvent(const WidgetKeyboardEvent& event)
1257 {
1258 NS_ENSURE_TRUE(mFrameElement, true);
1260 WidgetKeyboardEvent localEvent(event);
1261 // Set mNoCrossProcessBoundaryForwarding to avoid this event from
1262 // being infinitely redispatched and forwarded to the child again.
1263 localEvent.mFlags.mNoCrossProcessBoundaryForwarding = true;
1265 // Here we convert the WidgetEvent that we received to an nsIDOMEvent
1266 // to be able to dispatch it to the <browser> element as the target element.
1267 nsIDocument* doc = mFrameElement->OwnerDoc();
1268 nsIPresShell* presShell = doc->GetShell();
1269 NS_ENSURE_TRUE(presShell, true);
1270 nsPresContext* presContext = presShell->GetPresContext();
1271 NS_ENSURE_TRUE(presContext, true);
1273 EventDispatcher::Dispatch(mFrameElement, presContext, &localEvent);
1274 return true;
1275 }
1277 /**
1278 * Try to answer query event using cached text.
1279 *
1280 * For NS_QUERY_SELECTED_TEXT, fail if the cache doesn't contain the whole
1281 * selected range. (This shouldn't happen because PuppetWidget should have
1282 * already sent the whole selection.)
1283 *
1284 * For NS_QUERY_TEXT_CONTENT, fail only if the cache doesn't overlap with
1285 * the queried range. Note the difference from above. We use
1286 * this behavior because a normal NS_QUERY_TEXT_CONTENT event is allowed to
1287 * have out-of-bounds offsets, so that widget can request content without
1288 * knowing the exact length of text. It's up to widget to handle cases when
1289 * the returned offset/length are different from the queried offset/length.
1290 *
1291 * For NS_QUERY_TEXT_RECT, fail if cached offset/length aren't equals to input.
1292 * Cocoa widget always queries selected offset, so it works on it.
1293 *
1294 * For NS_QUERY_CARET_RECT, fail if cached offset isn't equals to input
1295 */
1296 bool
1297 TabParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent)
1298 {
1299 aEvent.mSucceeded = false;
1300 aEvent.mWasAsync = false;
1301 aEvent.mReply.mFocusedWidget = nsCOMPtr<nsIWidget>(GetWidget()).get();
1303 switch (aEvent.message)
1304 {
1305 case NS_QUERY_SELECTED_TEXT:
1306 {
1307 aEvent.mReply.mOffset = std::min(mIMESelectionAnchor, mIMESelectionFocus);
1308 if (mIMESelectionAnchor == mIMESelectionFocus) {
1309 aEvent.mReply.mString.Truncate(0);
1310 } else {
1311 if (mIMESelectionAnchor > mIMECacheText.Length() ||
1312 mIMESelectionFocus > mIMECacheText.Length()) {
1313 break;
1314 }
1315 uint32_t selLen = mIMESelectionAnchor > mIMESelectionFocus ?
1316 mIMESelectionAnchor - mIMESelectionFocus :
1317 mIMESelectionFocus - mIMESelectionAnchor;
1318 aEvent.mReply.mString = Substring(mIMECacheText,
1319 aEvent.mReply.mOffset,
1320 selLen);
1321 }
1322 aEvent.mReply.mReversed = mIMESelectionFocus < mIMESelectionAnchor;
1323 aEvent.mReply.mHasSelection = true;
1324 aEvent.mSucceeded = true;
1325 }
1326 break;
1327 case NS_QUERY_TEXT_CONTENT:
1328 {
1329 uint32_t inputOffset = aEvent.mInput.mOffset,
1330 inputEnd = inputOffset + aEvent.mInput.mLength;
1332 if (inputEnd > mIMECacheText.Length()) {
1333 inputEnd = mIMECacheText.Length();
1334 }
1335 if (inputEnd < inputOffset) {
1336 break;
1337 }
1338 aEvent.mReply.mOffset = inputOffset;
1339 aEvent.mReply.mString = Substring(mIMECacheText,
1340 inputOffset,
1341 inputEnd - inputOffset);
1342 aEvent.mSucceeded = true;
1343 }
1344 break;
1345 case NS_QUERY_TEXT_RECT:
1346 {
1347 if (aEvent.mInput.mOffset != mIMECompositionRectOffset ||
1348 aEvent.mInput.mLength != 1) {
1349 break;
1350 }
1352 aEvent.mReply.mOffset = mIMECompositionRectOffset;
1353 aEvent.mReply.mRect = mIMECompositionRect - GetChildProcessOffset();
1354 aEvent.mSucceeded = true;
1355 }
1356 break;
1357 case NS_QUERY_CARET_RECT:
1358 {
1359 if (aEvent.mInput.mOffset != mIMECompositionRectOffset) {
1360 break;
1361 }
1363 aEvent.mReply.mOffset = mIMECompositionRectOffset;
1364 aEvent.mReply.mRect = mIMECaretRect - GetChildProcessOffset();
1365 aEvent.mSucceeded = true;
1366 }
1367 break;
1368 }
1369 return true;
1370 }
1372 bool
1373 TabParent::SendCompositionEvent(WidgetCompositionEvent& event)
1374 {
1375 if (mIsDestroyed) {
1376 return false;
1377 }
1378 mIMEComposing = event.message != NS_COMPOSITION_END;
1379 mIMECompositionStart = std::min(mIMESelectionAnchor, mIMESelectionFocus);
1380 if (mIMECompositionEnding)
1381 return true;
1382 event.mSeqno = ++mIMESeqno;
1383 return PBrowserParent::SendCompositionEvent(event);
1384 }
1386 /**
1387 * During REQUEST_TO_COMMIT_COMPOSITION or REQUEST_TO_CANCEL_COMPOSITION,
1388 * widget usually sends a NS_TEXT_TEXT event to finalize or clear the
1389 * composition, respectively
1390 *
1391 * Because the event will not reach content in time, we intercept it
1392 * here and pass the text as the EndIMEComposition return value
1393 */
1394 bool
1395 TabParent::SendTextEvent(WidgetTextEvent& event)
1396 {
1397 if (mIsDestroyed) {
1398 return false;
1399 }
1400 if (mIMECompositionEnding) {
1401 mIMECompositionText = event.theText;
1402 return true;
1403 }
1405 // We must be able to simulate the selection because
1406 // we might not receive selection updates in time
1407 if (!mIMEComposing) {
1408 mIMECompositionStart = std::min(mIMESelectionAnchor, mIMESelectionFocus);
1409 }
1410 mIMESelectionAnchor = mIMESelectionFocus =
1411 mIMECompositionStart + event.theText.Length();
1413 event.mSeqno = ++mIMESeqno;
1414 return PBrowserParent::SendTextEvent(event);
1415 }
1417 bool
1418 TabParent::SendSelectionEvent(WidgetSelectionEvent& event)
1419 {
1420 if (mIsDestroyed) {
1421 return false;
1422 }
1423 mIMESelectionAnchor = event.mOffset + (event.mReversed ? event.mLength : 0);
1424 mIMESelectionFocus = event.mOffset + (!event.mReversed ? event.mLength : 0);
1425 event.mSeqno = ++mIMESeqno;
1426 return PBrowserParent::SendSelectionEvent(event);
1427 }
1429 /*static*/ TabParent*
1430 TabParent::GetFrom(nsFrameLoader* aFrameLoader)
1431 {
1432 if (!aFrameLoader) {
1433 return nullptr;
1434 }
1435 PBrowserParent* remoteBrowser = aFrameLoader->GetRemoteBrowser();
1436 return static_cast<TabParent*>(remoteBrowser);
1437 }
1439 /*static*/ TabParent*
1440 TabParent::GetFrom(nsIContent* aContent)
1441 {
1442 nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(aContent);
1443 if (!loaderOwner) {
1444 return nullptr;
1445 }
1446 nsRefPtr<nsFrameLoader> frameLoader = loaderOwner->GetFrameLoader();
1447 return GetFrom(frameLoader);
1448 }
1450 RenderFrameParent*
1451 TabParent::GetRenderFrame()
1452 {
1453 if (ManagedPRenderFrameParent().IsEmpty()) {
1454 return nullptr;
1455 }
1456 return static_cast<RenderFrameParent*>(ManagedPRenderFrameParent()[0]);
1457 }
1459 bool
1460 TabParent::RecvEndIMEComposition(const bool& aCancel,
1461 nsString* aComposition)
1462 {
1463 nsCOMPtr<nsIWidget> widget = GetWidget();
1464 if (!widget)
1465 return true;
1467 mIMECompositionEnding = true;
1469 widget->NotifyIME(IMENotification(aCancel ? REQUEST_TO_CANCEL_COMPOSITION :
1470 REQUEST_TO_COMMIT_COMPOSITION));
1472 mIMECompositionEnding = false;
1473 *aComposition = mIMECompositionText;
1474 mIMECompositionText.Truncate(0);
1475 return true;
1476 }
1478 bool
1479 TabParent::RecvGetInputContext(int32_t* aIMEEnabled,
1480 int32_t* aIMEOpen,
1481 intptr_t* aNativeIMEContext)
1482 {
1483 nsCOMPtr<nsIWidget> widget = GetWidget();
1484 if (!widget) {
1485 *aIMEEnabled = IMEState::DISABLED;
1486 *aIMEOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
1487 *aNativeIMEContext = 0;
1488 return true;
1489 }
1491 InputContext context = widget->GetInputContext();
1492 *aIMEEnabled = static_cast<int32_t>(context.mIMEState.mEnabled);
1493 *aIMEOpen = static_cast<int32_t>(context.mIMEState.mOpen);
1494 *aNativeIMEContext = reinterpret_cast<intptr_t>(context.mNativeIMEContext);
1495 return true;
1496 }
1498 bool
1499 TabParent::RecvSetInputContext(const int32_t& aIMEEnabled,
1500 const int32_t& aIMEOpen,
1501 const nsString& aType,
1502 const nsString& aInputmode,
1503 const nsString& aActionHint,
1504 const int32_t& aCause,
1505 const int32_t& aFocusChange)
1506 {
1507 // mIMETabParent (which is actually static) tracks which if any TabParent has IMEFocus
1508 // When the input mode is set to anything but IMEState::DISABLED,
1509 // mIMETabParent should be set to this
1510 mIMETabParent =
1511 aIMEEnabled != static_cast<int32_t>(IMEState::DISABLED) ? this : nullptr;
1512 nsCOMPtr<nsIWidget> widget = GetWidget();
1513 if (!widget || !AllowContentIME())
1514 return true;
1516 InputContext context;
1517 context.mIMEState.mEnabled = static_cast<IMEState::Enabled>(aIMEEnabled);
1518 context.mIMEState.mOpen = static_cast<IMEState::Open>(aIMEOpen);
1519 context.mHTMLInputType.Assign(aType);
1520 context.mHTMLInputInputmode.Assign(aInputmode);
1521 context.mActionHint.Assign(aActionHint);
1522 InputContextAction action(
1523 static_cast<InputContextAction::Cause>(aCause),
1524 static_cast<InputContextAction::FocusChange>(aFocusChange));
1525 widget->SetInputContext(context, action);
1527 nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
1528 if (!observerService)
1529 return true;
1531 nsAutoString state;
1532 state.AppendInt(aIMEEnabled);
1533 observerService->NotifyObservers(nullptr, "ime-enabled-state-changed", state.get());
1535 return true;
1536 }
1538 bool
1539 TabParent::RecvIsParentWindowMainWidgetVisible(bool* aIsVisible)
1540 {
1541 nsCOMPtr<nsIContent> frame = do_QueryInterface(mFrameElement);
1542 if (!frame)
1543 return true;
1544 nsCOMPtr<nsIDOMWindowUtils> windowUtils =
1545 do_QueryInterface(frame->OwnerDoc()->GetWindow());
1546 nsresult rv = windowUtils->GetIsParentWindowMainWidgetVisible(aIsVisible);
1547 return NS_SUCCEEDED(rv);
1548 }
1550 bool
1551 TabParent::RecvGetDPI(float* aValue)
1552 {
1553 TryCacheDPIAndScale();
1555 NS_ABORT_IF_FALSE(mDPI > 0,
1556 "Must not ask for DPI before OwnerElement is received!");
1557 *aValue = mDPI;
1558 return true;
1559 }
1561 bool
1562 TabParent::RecvGetDefaultScale(double* aValue)
1563 {
1564 TryCacheDPIAndScale();
1566 NS_ABORT_IF_FALSE(mDefaultScale.scale > 0,
1567 "Must not ask for scale before OwnerElement is received!");
1568 *aValue = mDefaultScale.scale;
1569 return true;
1570 }
1572 bool
1573 TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue)
1574 {
1575 nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
1576 if (content) {
1577 nsIPresShell* shell = content->OwnerDoc()->GetShell();
1578 if (shell) {
1579 nsViewManager* vm = shell->GetViewManager();
1580 nsCOMPtr<nsIWidget> widget;
1581 vm->GetRootWidget(getter_AddRefs(widget));
1582 if (widget) {
1583 *aValue = reinterpret_cast<WindowsHandle>(
1584 widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW));
1585 return true;
1586 }
1587 }
1588 }
1589 return false;
1590 }
1592 bool
1593 TabParent::ReceiveMessage(const nsString& aMessage,
1594 bool aSync,
1595 const StructuredCloneData* aCloneData,
1596 CpowHolder* aCpows,
1597 nsIPrincipal* aPrincipal,
1598 InfallibleTArray<nsString>* aJSONRetVal)
1599 {
1600 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
1601 if (frameLoader && frameLoader->GetFrameMessageManager()) {
1602 nsRefPtr<nsFrameMessageManager> manager =
1603 frameLoader->GetFrameMessageManager();
1605 manager->ReceiveMessage(mFrameElement,
1606 aMessage,
1607 aSync,
1608 aCloneData,
1609 aCpows,
1610 aPrincipal,
1611 aJSONRetVal);
1612 }
1613 return true;
1614 }
1616 PIndexedDBParent*
1617 TabParent::AllocPIndexedDBParent(
1618 const nsCString& aGroup,
1619 const nsCString& aASCIIOrigin, bool* /* aAllowed */)
1620 {
1621 return new IndexedDBParent(this);
1622 }
1624 bool
1625 TabParent::DeallocPIndexedDBParent(PIndexedDBParent* aActor)
1626 {
1627 delete aActor;
1628 return true;
1629 }
1631 bool
1632 TabParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
1633 const nsCString& aGroup,
1634 const nsCString& aASCIIOrigin,
1635 bool* aAllowed)
1636 {
1637 nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::GetOrCreate();
1638 NS_ENSURE_TRUE(mgr, false);
1640 if (!IndexedDatabaseManager::IsMainProcess()) {
1641 NS_RUNTIMEABORT("Not supported yet!");
1642 }
1644 nsresult rv;
1646 // XXXbent Need to make sure we have a whitelist for chrome databases!
1648 // Verify that the child is requesting to access a database it's allowed to
1649 // see. (aASCIIOrigin here specifies a TabContext + a website origin, and
1650 // we're checking that the TabContext may access it.)
1651 //
1652 // We have to check IsBrowserOrApp() because TabContextMayAccessOrigin will
1653 // fail if we're not a browser-or-app, since aASCIIOrigin will be a plain URI,
1654 // but TabContextMayAccessOrigin will construct an extended origin using
1655 // app-id 0. Note that as written below, we allow a non browser-or-app child
1656 // to read any database. That's a security hole, but we don't ship a
1657 // configuration which creates non browser-or-app children, so it's not a big
1658 // deal.
1659 if (!aASCIIOrigin.EqualsLiteral("chrome") && IsBrowserOrApp() &&
1660 !IndexedDatabaseManager::TabContextMayAccessOrigin(*this, aASCIIOrigin)) {
1662 NS_WARNING("App attempted to open databases that it does not have "
1663 "permission to access!");
1664 return false;
1665 }
1667 nsCOMPtr<nsINode> node = do_QueryInterface(GetOwnerElement());
1668 NS_ENSURE_TRUE(node, false);
1670 nsIDocument* doc = node->GetOwnerDocument();
1671 NS_ENSURE_TRUE(doc, false);
1673 nsCOMPtr<nsPIDOMWindow> window = doc->GetInnerWindow();
1674 NS_ENSURE_TRUE(window, false);
1676 // Let's do a current inner check to see if the inner is active or is in
1677 // bf cache, and bail out if it's not active.
1678 nsCOMPtr<nsPIDOMWindow> outer = doc->GetWindow();
1679 if (!outer || outer->GetCurrentInnerWindow() != window) {
1680 *aAllowed = false;
1681 return true;
1682 }
1684 ContentParent* contentParent = Manager();
1685 NS_ASSERTION(contentParent, "Null manager?!");
1687 nsRefPtr<IDBFactory> factory;
1688 rv = IDBFactory::Create(window, aGroup, aASCIIOrigin, contentParent,
1689 getter_AddRefs(factory));
1690 NS_ENSURE_SUCCESS(rv, false);
1692 if (!factory) {
1693 *aAllowed = false;
1694 return true;
1695 }
1697 IndexedDBParent* actor = static_cast<IndexedDBParent*>(aActor);
1698 actor->mFactory = factory;
1699 actor->mASCIIOrigin = aASCIIOrigin;
1701 *aAllowed = true;
1702 return true;
1703 }
1705 // nsIAuthPromptProvider
1707 // This method is largely copied from nsDocShell::GetAuthPrompt
1708 NS_IMETHODIMP
1709 TabParent::GetAuthPrompt(uint32_t aPromptReason, const nsIID& iid,
1710 void** aResult)
1711 {
1712 // we're either allowing auth, or it's a proxy request
1713 nsresult rv;
1714 nsCOMPtr<nsIPromptFactory> wwatch =
1715 do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
1716 NS_ENSURE_SUCCESS(rv, rv);
1718 nsCOMPtr<nsIDOMWindow> window;
1719 nsCOMPtr<nsIContent> frame = do_QueryInterface(mFrameElement);
1720 if (frame)
1721 window = do_QueryInterface(frame->OwnerDoc()->GetWindow());
1723 // Get an auth prompter for our window so that the parenting
1724 // of the dialogs works as it should when using tabs.
1725 return wwatch->GetPrompt(window, iid,
1726 reinterpret_cast<void**>(aResult));
1727 }
1729 PColorPickerParent*
1730 TabParent::AllocPColorPickerParent(const nsString& aTitle,
1731 const nsString& aInitialColor)
1732 {
1733 return new ColorPickerParent(aTitle, aInitialColor);
1734 }
1736 bool
1737 TabParent::DeallocPColorPickerParent(PColorPickerParent* actor)
1738 {
1739 delete actor;
1740 return true;
1741 }
1743 bool
1744 TabParent::RecvInitRenderFrame(PRenderFrameParent* aFrame,
1745 ScrollingBehavior* aScrolling,
1746 TextureFactoryIdentifier* aTextureFactoryIdentifier,
1747 uint64_t* aLayersId,
1748 bool *aSuccess)
1749 {
1750 *aScrolling = UseAsyncPanZoom() ? ASYNC_PAN_ZOOM : DEFAULT_SCROLLING;
1751 *aTextureFactoryIdentifier = TextureFactoryIdentifier();
1752 *aLayersId = 0;
1754 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
1755 if (!frameLoader) {
1756 NS_WARNING("Can't allocate graphics resources. May already be shutting down.");
1757 *aSuccess = false;
1758 return true;
1759 }
1761 static_cast<RenderFrameParent*>(aFrame)->Init(frameLoader, *aScrolling,
1762 aTextureFactoryIdentifier, aLayersId);
1764 *aSuccess = true;
1765 return true;
1766 }
1768 PRenderFrameParent*
1769 TabParent::AllocPRenderFrameParent()
1770 {
1771 MOZ_ASSERT(ManagedPRenderFrameParent().IsEmpty());
1772 return new RenderFrameParent();
1773 }
1775 bool
1776 TabParent::DeallocPRenderFrameParent(PRenderFrameParent* aFrame)
1777 {
1778 delete aFrame;
1779 return true;
1780 }
1782 mozilla::docshell::POfflineCacheUpdateParent*
1783 TabParent::AllocPOfflineCacheUpdateParent(const URIParams& aManifestURI,
1784 const URIParams& aDocumentURI,
1785 const bool& aStickDocument)
1786 {
1787 nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
1788 new mozilla::docshell::OfflineCacheUpdateParent(OwnOrContainingAppId(),
1789 IsBrowserElement());
1790 // Use this reference as the IPDL reference.
1791 return update.forget().take();
1792 }
1794 bool
1795 TabParent::RecvPOfflineCacheUpdateConstructor(POfflineCacheUpdateParent* aActor,
1796 const URIParams& aManifestURI,
1797 const URIParams& aDocumentURI,
1798 const bool& aStickDocument)
1799 {
1800 MOZ_ASSERT(aActor);
1802 nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
1803 static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(aActor);
1805 nsresult rv = update->Schedule(aManifestURI, aDocumentURI, aStickDocument);
1806 if (NS_FAILED(rv) && !IsDestroyed()) {
1807 // Inform the child of failure.
1808 unused << update->SendFinish(false, false);
1809 }
1811 return true;
1812 }
1814 bool
1815 TabParent::DeallocPOfflineCacheUpdateParent(POfflineCacheUpdateParent* aActor)
1816 {
1817 // Reclaim the IPDL reference.
1818 nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
1819 dont_AddRef(
1820 static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(aActor));
1821 return true;
1822 }
1824 bool
1825 TabParent::RecvSetOfflinePermission(const IPC::Principal& aPrincipal)
1826 {
1827 nsIPrincipal* principal = aPrincipal;
1828 nsContentUtils::MaybeAllowOfflineAppByDefault(principal, nullptr);
1829 return true;
1830 }
1832 bool
1833 TabParent::AllowContentIME()
1834 {
1835 nsFocusManager* fm = nsFocusManager::GetFocusManager();
1836 NS_ENSURE_TRUE(fm, false);
1838 nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedContent();
1839 if (focusedContent && focusedContent->IsEditable())
1840 return false;
1842 return true;
1843 }
1845 already_AddRefed<nsFrameLoader>
1846 TabParent::GetFrameLoader() const
1847 {
1848 nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner = do_QueryInterface(mFrameElement);
1849 return frameLoaderOwner ? frameLoaderOwner->GetFrameLoader() : nullptr;
1850 }
1852 void
1853 TabParent::TryCacheDPIAndScale()
1854 {
1855 if (mDPI > 0) {
1856 return;
1857 }
1859 nsCOMPtr<nsIWidget> widget = GetWidget();
1861 if (!widget && mFrameElement) {
1862 // Even if we don't have a widget (e.g. because we're display:none), there's
1863 // probably a widget somewhere in the hierarchy our frame element lives in.
1864 widget = nsContentUtils::WidgetForDocument(mFrameElement->OwnerDoc());
1865 }
1867 if (widget) {
1868 mDPI = widget->GetDPI();
1869 mDefaultScale = widget->GetDefaultScale();
1870 }
1871 }
1873 already_AddRefed<nsIWidget>
1874 TabParent::GetWidget() const
1875 {
1876 nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
1877 if (!content)
1878 return nullptr;
1880 nsIFrame *frame = content->GetPrimaryFrame();
1881 if (!frame)
1882 return nullptr;
1884 nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget();
1885 return widget.forget();
1886 }
1888 bool
1889 TabParent::UseAsyncPanZoom()
1890 {
1891 bool usingOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
1892 bool asyncPanZoomEnabled =
1893 Preferences::GetBool("layers.async-pan-zoom.enabled", false);
1894 return (usingOffMainThreadCompositing && asyncPanZoomEnabled &&
1895 GetScrollingBehavior() == ASYNC_PAN_ZOOM);
1896 }
1898 void
1899 TabParent::MaybeForwardEventToRenderFrame(WidgetInputEvent& aEvent,
1900 ScrollableLayerGuid* aOutTargetGuid)
1901 {
1902 if (RenderFrameParent* rfp = GetRenderFrame()) {
1903 rfp->NotifyInputEvent(aEvent, aOutTargetGuid);
1904 }
1905 }
1907 bool
1908 TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
1909 const nsString& aURL,
1910 const nsString& aName,
1911 const nsString& aFeatures,
1912 bool* aOutWindowOpened)
1913 {
1914 BrowserElementParent::OpenWindowResult opened =
1915 BrowserElementParent::OpenWindowOOP(static_cast<TabParent*>(aOpener),
1916 this, aURL, aName, aFeatures);
1917 *aOutWindowOpened = (opened != BrowserElementParent::OPEN_WINDOW_CANCELLED);
1918 return true;
1919 }
1921 bool
1922 TabParent::RecvPRenderFrameConstructor(PRenderFrameParent* actor)
1923 {
1924 return true;
1925 }
1927 bool
1928 TabParent::RecvZoomToRect(const uint32_t& aPresShellId,
1929 const ViewID& aViewId,
1930 const CSSRect& aRect)
1931 {
1932 if (RenderFrameParent* rfp = GetRenderFrame()) {
1933 rfp->ZoomToRect(aPresShellId, aViewId, aRect);
1934 }
1935 return true;
1936 }
1938 bool
1939 TabParent::RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
1940 const ViewID& aViewId,
1941 const bool& aIsRoot,
1942 const ZoomConstraints& aConstraints)
1943 {
1944 if (RenderFrameParent* rfp = GetRenderFrame()) {
1945 rfp->UpdateZoomConstraints(aPresShellId, aViewId, aIsRoot, aConstraints);
1946 }
1947 return true;
1948 }
1950 bool
1951 TabParent::RecvContentReceivedTouch(const ScrollableLayerGuid& aGuid,
1952 const bool& aPreventDefault)
1953 {
1954 if (RenderFrameParent* rfp = GetRenderFrame()) {
1955 rfp->ContentReceivedTouch(aGuid, aPreventDefault);
1956 }
1957 return true;
1958 }
1960 already_AddRefed<nsILoadContext>
1961 TabParent::GetLoadContext()
1962 {
1963 nsCOMPtr<nsILoadContext> loadContext;
1964 if (mLoadContext) {
1965 loadContext = mLoadContext;
1966 } else {
1967 loadContext = new LoadContext(GetOwnerElement(),
1968 OwnOrContainingAppId(),
1969 true /* aIsContent */,
1970 mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW,
1971 mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW,
1972 IsBrowserElement());
1973 mLoadContext = loadContext;
1974 }
1975 return loadContext.forget();
1976 }
1978 /* Be careful if you call this method while proceding a real touch event. For
1979 * example sending a touchstart during a real touchend may results into
1980 * a busted mEventCaptureDepth and following touch events may not do what you
1981 * expect.
1982 */
1983 NS_IMETHODIMP
1984 TabParent::InjectTouchEvent(const nsAString& aType,
1985 uint32_t* aIdentifiers,
1986 int32_t* aXs,
1987 int32_t* aYs,
1988 uint32_t* aRxs,
1989 uint32_t* aRys,
1990 float* aRotationAngles,
1991 float* aForces,
1992 uint32_t aCount,
1993 int32_t aModifiers)
1994 {
1995 uint32_t msg;
1996 nsContentUtils::GetEventIdAndAtom(aType, NS_TOUCH_EVENT, &msg);
1997 if (msg != NS_TOUCH_START && msg != NS_TOUCH_MOVE &&
1998 msg != NS_TOUCH_END && msg != NS_TOUCH_CANCEL) {
1999 return NS_ERROR_FAILURE;
2000 }
2002 nsCOMPtr<nsIWidget> widget = GetWidget();
2003 if (!widget) {
2004 return NS_ERROR_FAILURE;
2005 }
2007 WidgetTouchEvent event(true, msg, widget);
2008 event.modifiers = aModifiers;
2009 event.time = PR_IntervalNow();
2011 event.touches.SetCapacity(aCount);
2012 for (uint32_t i = 0; i < aCount; ++i) {
2013 nsRefPtr<Touch> t = new Touch(aIdentifiers[i],
2014 nsIntPoint(aXs[i], aYs[i]),
2015 nsIntPoint(aRxs[i], aRys[i]),
2016 aRotationAngles[i],
2017 aForces[i]);
2019 // Consider all injected touch events as changedTouches. For more details
2020 // about the meaning of changedTouches for each event, see
2021 // https://developer.mozilla.org/docs/Web/API/TouchEvent.changedTouches
2022 t->mChanged = true;
2023 event.touches.AppendElement(t);
2024 }
2026 if ((msg == NS_TOUCH_END || msg == NS_TOUCH_CANCEL) && sEventCapturer) {
2027 WidgetGUIEvent* guiEvent = event.AsGUIEvent();
2028 TryCapture(*guiEvent);
2029 }
2031 SendRealTouchEvent(event);
2032 return NS_OK;
2033 }
2035 NS_IMETHODIMP
2036 TabParent::GetUseAsyncPanZoom(bool* useAsyncPanZoom)
2037 {
2038 *useAsyncPanZoom = UseAsyncPanZoom();
2039 return NS_OK;
2040 }
2042 NS_IMETHODIMP
2043 TabParent::SetIsDocShellActive(bool isActive)
2044 {
2045 unused << SendSetIsDocShellActive(isActive);
2046 return NS_OK;
2047 }
2049 } // namespace tabs
2050 } // namespace mozilla