Bumping manifests a=b2g-bump
[gecko.git] / dom / ipc / TabParent.cpp
bloba311f9a080f753f9e0acd2c8a64fa97d38703edb
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/net/NeckoChild.h"
26 #include "mozilla/Preferences.h"
27 #include "mozilla/TextEvents.h"
28 #include "mozilla/TouchEvents.h"
29 #include "mozilla/unused.h"
30 #include "nsCOMPtr.h"
31 #include "nsContentPermissionHelper.h"
32 #include "nsContentUtils.h"
33 #include "nsDebug.h"
34 #include "nsFocusManager.h"
35 #include "nsFrameLoader.h"
36 #include "nsIContent.h"
37 #include "nsIDocShell.h"
38 #include "nsIDocShellTreeOwner.h"
39 #include "nsIDOMElement.h"
40 #include "nsIDOMEvent.h"
41 #include "nsIDOMWindow.h"
42 #include "nsIDOMWindowUtils.h"
43 #include "nsIInterfaceRequestorUtils.h"
44 #include "nsILoadInfo.h"
45 #include "nsIPromptFactory.h"
46 #include "nsIURI.h"
47 #include "nsIWebBrowserChrome.h"
48 #include "nsIWindowCreator2.h"
49 #include "nsIXULBrowserWindow.h"
50 #include "nsIXULWindow.h"
51 #include "nsViewManager.h"
52 #include "nsIWidget.h"
53 #include "nsIWindowWatcher.h"
54 #include "nsPIDOMWindow.h"
55 #include "nsPIWindowWatcher.h"
56 #include "nsPrintfCString.h"
57 #include "nsServiceManagerUtils.h"
58 #include "nsThreadUtils.h"
59 #include "nsWindowWatcher.h"
60 #include "private/pprio.h"
61 #include "PermissionMessageUtils.h"
62 #include "StructuredCloneUtils.h"
63 #include "ColorPickerParent.h"
64 #include "JavaScriptParent.h"
65 #include "FilePickerParent.h"
66 #include "TabChild.h"
67 #include "LoadContext.h"
68 #include "nsNetCID.h"
69 #include "nsIAuthInformation.h"
70 #include "nsIAuthPromptCallback.h"
71 #include "nsAuthInformationHolder.h"
72 #include "nsICancelable.h"
73 #include "gfxPrefs.h"
74 #include <algorithm>
76 using namespace mozilla::dom;
77 using namespace mozilla::ipc;
78 using namespace mozilla::layers;
79 using namespace mozilla::layout;
80 using namespace mozilla::services;
81 using namespace mozilla::widget;
82 using namespace mozilla::dom::indexedDB;
83 using namespace mozilla::jsipc;
85 // The flags passed by the webProgress notifications are 16 bits shifted
86 // from the ones registered by webProgressListeners.
87 #define NOTIFY_FLAG_SHIFT 16
89 class OpenFileAndSendFDRunnable : public nsRunnable
91 const nsString mPath;
92 nsRefPtr<TabParent> mTabParent;
93 nsCOMPtr<nsIEventTarget> mEventTarget;
94 PRFileDesc* mFD;
96 public:
97 OpenFileAndSendFDRunnable(const nsAString& aPath, TabParent* aTabParent)
98 : mPath(aPath), mTabParent(aTabParent), mFD(nullptr)
100 MOZ_ASSERT(NS_IsMainThread());
101 MOZ_ASSERT(!aPath.IsEmpty());
102 MOZ_ASSERT(aTabParent);
105 void Dispatch()
107 MOZ_ASSERT(NS_IsMainThread());
109 mEventTarget = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
110 NS_ENSURE_TRUE_VOID(mEventTarget);
112 nsresult rv = mEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
113 NS_ENSURE_SUCCESS_VOID(rv);
116 private:
117 ~OpenFileAndSendFDRunnable()
119 MOZ_ASSERT(!mFD);
122 // This shouldn't be called directly except by the event loop. Use Dispatch
123 // to start the sequence.
124 NS_IMETHOD Run()
126 if (NS_IsMainThread()) {
127 SendResponse();
128 } else if (mFD) {
129 CloseFile();
130 } else {
131 OpenFile();
134 return NS_OK;
137 void SendResponse()
139 MOZ_ASSERT(NS_IsMainThread());
140 MOZ_ASSERT(mTabParent);
141 MOZ_ASSERT(mEventTarget);
142 MOZ_ASSERT(mFD);
144 nsRefPtr<TabParent> tabParent;
145 mTabParent.swap(tabParent);
147 using mozilla::ipc::FileDescriptor;
149 FileDescriptor::PlatformHandleType handle =
150 FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(mFD));
152 // Our TabParent may have been destroyed already. If so, don't send any
153 // fds over, just go back to the IO thread and close them.
154 if (!tabParent->IsDestroyed()) {
155 mozilla::unused << tabParent->SendCacheFileDescriptor(mPath,
156 FileDescriptor(handle));
159 nsCOMPtr<nsIEventTarget> eventTarget;
160 mEventTarget.swap(eventTarget);
162 if (NS_FAILED(eventTarget->Dispatch(this, NS_DISPATCH_NORMAL))) {
163 NS_WARNING("Failed to dispatch to stream transport service!");
165 // It's probably safer to take the main thread IO hit here rather
166 // than leak a file descriptor.
167 CloseFile();
171 void OpenFile()
173 MOZ_ASSERT(!NS_IsMainThread());
174 MOZ_ASSERT(!mFD);
176 nsCOMPtr<nsIFile> file;
177 nsresult rv = NS_NewLocalFile(mPath, false, getter_AddRefs(file));
178 NS_ENSURE_SUCCESS_VOID(rv);
180 PRFileDesc* fd;
181 rv = file->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
182 NS_ENSURE_SUCCESS_VOID(rv);
184 mFD = fd;
186 if (NS_FAILED(NS_DispatchToMainThread(this))) {
187 NS_WARNING("Failed to dispatch to main thread!");
189 CloseFile();
193 void CloseFile()
195 // It's possible for this to happen on the main thread if the dispatch
196 // to the stream service fails after we've already opened the file so
197 // we can't assert the thread we're running on.
199 MOZ_ASSERT(mFD);
201 PRStatus prrc;
202 prrc = PR_Close(mFD);
203 if (prrc != PR_SUCCESS) {
204 NS_ERROR("PR_Close() failed.");
206 mFD = nullptr;
210 namespace mozilla {
211 namespace dom {
213 TabParent* sEventCapturer;
215 TabParent *TabParent::mIMETabParent = nullptr;
217 NS_IMPL_ISUPPORTS(TabParent,
218 nsITabParent,
219 nsIAuthPromptProvider,
220 nsISecureBrowserUI,
221 nsISupportsWeakReference)
223 TabParent::TabParent(nsIContentParent* aManager, const TabContext& aContext, uint32_t aChromeFlags)
224 : TabContext(aContext)
225 , mFrameElement(nullptr)
226 , mIMESelectionAnchor(0)
227 , mIMESelectionFocus(0)
228 , mIMEComposing(false)
229 , mIMECompositionEnding(false)
230 , mIMECompositionStart(0)
231 , mIMESeqno(0)
232 , mIMECompositionRectOffset(0)
233 , mEventCaptureDepth(0)
234 , mRect(0, 0, 0, 0)
235 , mDimensions(0, 0)
236 , mOrientation(0)
237 , mDPI(0)
238 , mDefaultScale(0)
239 , mShown(false)
240 , mUpdatedDimensions(false)
241 , mManager(aManager)
242 , mMarkedDestroying(false)
243 , mIsDestroyed(false)
244 , mAppPackageFileDescriptorSent(false)
245 , mChromeFlags(aChromeFlags)
247 MOZ_ASSERT(aManager);
250 TabParent::~TabParent()
254 void
255 TabParent::SetOwnerElement(Element* aElement)
257 mFrameElement = aElement;
258 TryCacheDPIAndScale();
261 void
262 TabParent::GetAppType(nsAString& aOut)
264 aOut.Truncate();
265 nsCOMPtr<Element> elem = do_QueryInterface(mFrameElement);
266 if (!elem) {
267 return;
270 elem->GetAttr(kNameSpaceID_None, nsGkAtoms::mozapptype, aOut);
273 bool
274 TabParent::IsVisible()
276 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
277 if (!frameLoader) {
278 return false;
281 bool visible = false;
282 frameLoader->GetVisible(&visible);
283 return visible;
286 void
287 TabParent::Destroy()
289 if (mIsDestroyed) {
290 return;
293 // If this fails, it's most likely due to a content-process crash,
294 // and auto-cleanup will kick in. Otherwise, the child side will
295 // destroy itself and send back __delete__().
296 unused << SendDestroy();
298 const InfallibleTArray<PIndexedDBParent*>& idbParents =
299 ManagedPIndexedDBParent();
300 for (uint32_t i = 0; i < idbParents.Length(); ++i) {
301 static_cast<IndexedDBParent*>(idbParents[i])->Disconnect();
304 const InfallibleTArray<POfflineCacheUpdateParent*>& ocuParents =
305 ManagedPOfflineCacheUpdateParent();
306 for (uint32_t i = 0; i < ocuParents.Length(); ++i) {
307 nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> ocuParent =
308 static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(ocuParents[i]);
309 ocuParent->StopSendingMessagesToChild();
312 if (RenderFrameParent* frame = GetRenderFrame()) {
313 frame->Destroy();
315 mIsDestroyed = true;
317 if (XRE_GetProcessType() == GeckoProcessType_Default) {
318 Manager()->AsContentParent()->NotifyTabDestroying(this);
320 mMarkedDestroying = true;
323 bool
324 TabParent::Recv__delete__()
326 if (XRE_GetProcessType() == GeckoProcessType_Default) {
327 Manager()->AsContentParent()->NotifyTabDestroyed(this, mMarkedDestroying);
329 return true;
332 void
333 TabParent::ActorDestroy(ActorDestroyReason why)
335 if (sEventCapturer == this) {
336 sEventCapturer = nullptr;
338 if (mIMETabParent == this) {
339 mIMETabParent = nullptr;
341 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
342 nsCOMPtr<nsIObserverService> os = services::GetObserverService();
343 nsRefPtr<nsFrameMessageManager> fmm;
344 if (frameLoader) {
345 fmm = frameLoader->GetFrameMessageManager();
346 nsCOMPtr<Element> frameElement(mFrameElement);
347 ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr,
348 nullptr);
349 frameLoader->DestroyChild();
351 if (why == AbnormalShutdown && os) {
352 os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, frameLoader),
353 "oop-frameloader-crashed", nullptr);
354 nsContentUtils::DispatchTrustedEvent(frameElement->OwnerDoc(), frameElement,
355 NS_LITERAL_STRING("oop-browser-crashed"),
356 true, true);
360 if (os) {
361 os->NotifyObservers(NS_ISUPPORTS_CAST(nsITabParent*, this), "ipc:browser-destroyed", nullptr);
363 if (fmm) {
364 fmm->Disconnect();
368 bool
369 TabParent::RecvMoveFocus(const bool& aForward)
371 nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
372 if (fm) {
373 nsCOMPtr<nsIDOMElement> dummy;
374 uint32_t type = aForward ? uint32_t(nsIFocusManager::MOVEFOCUS_FORWARD)
375 : uint32_t(nsIFocusManager::MOVEFOCUS_BACKWARD);
376 nsCOMPtr<nsIDOMElement> frame = do_QueryInterface(mFrameElement);
377 fm->MoveFocus(nullptr, frame, type, nsIFocusManager::FLAG_BYKEY,
378 getter_AddRefs(dummy));
380 return true;
383 bool
384 TabParent::RecvEvent(const RemoteDOMEvent& aEvent)
386 nsCOMPtr<nsIDOMEvent> event = do_QueryInterface(aEvent.mEvent);
387 NS_ENSURE_TRUE(event, true);
389 nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryInterface(mFrameElement);
390 NS_ENSURE_TRUE(target, true);
392 event->SetOwner(target);
394 bool dummy;
395 target->DispatchEvent(event, &dummy);
396 return true;
399 bool
400 TabParent::AnswerCreateWindow(const uint32_t& aChromeFlags,
401 const bool& aCalledFromJS,
402 const bool& aPositionSpecified,
403 const bool& aSizeSpecified,
404 const nsString& aURI,
405 const nsString& aName,
406 const nsString& aFeatures,
407 const nsString& aBaseURI,
408 bool* aWindowIsNew,
409 PBrowserParent** aRetVal)
411 if (IsBrowserOrApp()) {
412 return false;
415 nsresult rv;
416 nsCOMPtr<nsPIWindowWatcher> pwwatch =
417 do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
418 NS_ENSURE_SUCCESS(rv, false);
420 nsCOMPtr<nsIContent> frame(do_QueryInterface(mFrameElement));
421 NS_ENSURE_TRUE(frame, false);
423 nsCOMPtr<nsIDOMWindow> parent = do_QueryInterface(frame->OwnerDoc()->GetWindow());
424 NS_ENSURE_TRUE(parent, false);
426 int32_t openLocation =
427 nsWindowWatcher::GetWindowOpenLocation(parent, aChromeFlags, aCalledFromJS,
428 aPositionSpecified, aSizeSpecified);
430 MOZ_ASSERT(openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB ||
431 openLocation == nsIBrowserDOMWindow::OPEN_NEWWINDOW);
433 *aWindowIsNew = true;
435 // Opening new tabs is the easy case...
436 if (openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB) {
437 NS_ENSURE_TRUE(mBrowserDOMWindow, false);
439 nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
440 mBrowserDOMWindow->OpenURIInFrame(nullptr, nullptr,
441 nsIBrowserDOMWindow::OPEN_NEWTAB,
442 nsIBrowserDOMWindow::OPEN_NEW,
443 getter_AddRefs(frameLoaderOwner));
444 NS_ENSURE_TRUE(frameLoaderOwner, false);
446 nsRefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
447 NS_ENSURE_TRUE(frameLoader, false);
449 *aRetVal = frameLoader->GetRemoteBrowser();
450 return true;
453 // WindowWatcher is going to expect a valid URI to open a window
454 // to. If it can't find one, it's going to attempt to figure one
455 // out on its own, which is problematic because it can't access
456 // the document for the remote browser we're opening. Luckily,
457 // TabChild has sent us a baseURI with which we can ensure that
458 // the URI we pass to WindowWatcher is valid.
459 nsCOMPtr<nsIURI> baseURI;
460 rv = NS_NewURI(getter_AddRefs(baseURI), aBaseURI);
461 NS_ENSURE_SUCCESS(rv, false);
463 nsCOMPtr<nsIURI> finalURI;
464 rv = NS_NewURI(getter_AddRefs(finalURI), NS_ConvertUTF16toUTF8(aURI).get(), baseURI);
465 NS_ENSURE_SUCCESS(rv, false);
467 nsAutoCString finalURIString;
468 finalURI->GetSpec(finalURIString);
470 nsCOMPtr<nsIDOMWindow> window;
472 rv = pwwatch->OpenWindow2(parent, finalURIString.get(),
473 NS_ConvertUTF16toUTF8(aName).get(),
474 NS_ConvertUTF16toUTF8(aFeatures).get(), aCalledFromJS,
475 false, false, this, nullptr, getter_AddRefs(window));
476 NS_ENSURE_SUCCESS(rv, false);
478 nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(window);
479 NS_ENSURE_TRUE(pwindow, false);
481 nsRefPtr<nsIDocShell> newDocShell = pwindow->GetDocShell();
482 NS_ENSURE_TRUE(newDocShell, false);
484 nsCOMPtr<nsITabParent> newRemoteTab = newDocShell->GetOpenedRemote();
485 NS_ENSURE_TRUE(newRemoteTab, false);
487 *aRetVal = static_cast<TabParent*>(newRemoteTab.get());
488 return true;
491 void
492 TabParent::LoadURL(nsIURI* aURI)
494 MOZ_ASSERT(aURI);
496 if (mIsDestroyed) {
497 return;
500 nsCString spec;
501 aURI->GetSpec(spec);
503 if (!mShown) {
504 NS_WARNING(nsPrintfCString("TabParent::LoadURL(%s) called before "
505 "Show(). Ignoring LoadURL.\n",
506 spec.get()).get());
507 return;
510 unused << SendLoadURL(spec);
512 // If this app is a packaged app then we can speed startup by sending over
513 // the file descriptor for the "application.zip" file that it will
514 // invariably request. Only do this once.
515 if (!mAppPackageFileDescriptorSent) {
516 mAppPackageFileDescriptorSent = true;
518 nsCOMPtr<mozIApplication> app = GetOwnOrContainingApp();
519 if (app) {
520 nsString manifestURL;
521 nsresult rv = app->GetManifestURL(manifestURL);
522 NS_ENSURE_SUCCESS_VOID(rv);
524 if (StringBeginsWith(manifestURL, NS_LITERAL_STRING("app:"))) {
525 nsString basePath;
526 rv = app->GetBasePath(basePath);
527 NS_ENSURE_SUCCESS_VOID(rv);
529 nsString appId;
530 rv = app->GetId(appId);
531 NS_ENSURE_SUCCESS_VOID(rv);
533 nsCOMPtr<nsIFile> packageFile;
534 rv = NS_NewLocalFile(basePath, false,
535 getter_AddRefs(packageFile));
536 NS_ENSURE_SUCCESS_VOID(rv);
538 rv = packageFile->Append(appId);
539 NS_ENSURE_SUCCESS_VOID(rv);
541 rv = packageFile->Append(NS_LITERAL_STRING("application.zip"));
542 NS_ENSURE_SUCCESS_VOID(rv);
544 nsString path;
545 rv = packageFile->GetPath(path);
546 NS_ENSURE_SUCCESS_VOID(rv);
548 nsRefPtr<OpenFileAndSendFDRunnable> openFileRunnable =
549 new OpenFileAndSendFDRunnable(path, this);
550 openFileRunnable->Dispatch();
556 void
557 TabParent::Show(const nsIntSize& size)
559 // sigh
560 mShown = true;
561 mDimensions = size;
562 if (!mIsDestroyed) {
563 unused << SendShow(size);
567 void
568 TabParent::UpdateDimensions(const nsIntRect& rect, const nsIntSize& size)
570 if (mIsDestroyed) {
571 return;
573 hal::ScreenConfiguration config;
574 hal::GetCurrentScreenConfiguration(&config);
575 ScreenOrientation orientation = config.orientation();
577 if (!mUpdatedDimensions || mOrientation != orientation ||
578 mDimensions != size || !mRect.IsEqualEdges(rect)) {
579 mUpdatedDimensions = true;
580 mRect = rect;
581 mDimensions = size;
582 mOrientation = orientation;
584 unused << SendUpdateDimensions(mRect, mDimensions, mOrientation);
588 void
589 TabParent::UpdateFrame(const FrameMetrics& aFrameMetrics)
591 if (!mIsDestroyed) {
592 unused << SendUpdateFrame(aFrameMetrics);
596 void
597 TabParent::UIResolutionChanged()
599 if (!mIsDestroyed) {
600 // TryCacheDPIAndScale()'s cache is keyed off of
601 // mDPI being greater than 0, so this invalidates it.
602 mDPI = -1;
603 unused << SendUIResolutionChanged();
607 void
608 TabParent::AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration)
610 if (!mIsDestroyed) {
611 unused << SendAcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
615 void TabParent::HandleDoubleTap(const CSSPoint& aPoint,
616 int32_t aModifiers,
617 const ScrollableLayerGuid &aGuid)
619 if (!mIsDestroyed) {
620 unused << SendHandleDoubleTap(aPoint, aGuid);
624 void TabParent::HandleSingleTap(const CSSPoint& aPoint,
625 int32_t aModifiers,
626 const ScrollableLayerGuid &aGuid)
628 // TODO Send the modifier data to TabChild for use in mouse events.
629 if (!mIsDestroyed) {
630 unused << SendHandleSingleTap(aPoint, aGuid);
634 void TabParent::HandleLongTap(const CSSPoint& aPoint,
635 int32_t aModifiers,
636 const ScrollableLayerGuid &aGuid)
638 if (!mIsDestroyed) {
639 unused << SendHandleLongTap(aPoint, aGuid);
643 void TabParent::HandleLongTapUp(const CSSPoint& aPoint,
644 int32_t aModifiers,
645 const ScrollableLayerGuid &aGuid)
647 if (!mIsDestroyed) {
648 unused << SendHandleLongTapUp(aPoint, aGuid);
652 void TabParent::NotifyAPZStateChange(ViewID aViewId,
653 APZStateChange aChange,
654 int aArg)
656 if (!mIsDestroyed) {
657 unused << SendNotifyAPZStateChange(aViewId, aChange, aArg);
661 void
662 TabParent::Activate()
664 if (!mIsDestroyed) {
665 unused << SendActivate();
669 void
670 TabParent::Deactivate()
672 if (!mIsDestroyed) {
673 unused << SendDeactivate();
677 NS_IMETHODIMP
678 TabParent::Init(nsIDOMWindow *window)
680 return NS_OK;
683 NS_IMETHODIMP
684 TabParent::GetState(uint32_t *aState)
686 NS_ENSURE_ARG(aState);
687 NS_WARNING("SecurityState not valid here");
688 *aState = 0;
689 return NS_OK;
692 NS_IMETHODIMP
693 TabParent::SetDocShell(nsIDocShell *aDocShell)
695 NS_ENSURE_ARG(aDocShell);
696 NS_WARNING("No mDocShell member in TabParent so there is no docShell to set");
697 return NS_OK;
700 PDocumentRendererParent*
701 TabParent::AllocPDocumentRendererParent(const nsRect& documentRect,
702 const gfx::Matrix& transform,
703 const nsString& bgcolor,
704 const uint32_t& renderFlags,
705 const bool& flushLayout,
706 const nsIntSize& renderSize)
708 return new DocumentRendererParent();
711 bool
712 TabParent::DeallocPDocumentRendererParent(PDocumentRendererParent* actor)
714 delete actor;
715 return true;
718 PContentPermissionRequestParent*
719 TabParent::AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
720 const IPC::Principal& aPrincipal)
722 return nsContentPermissionUtils::CreateContentPermissionRequestParent(aRequests, mFrameElement, aPrincipal);
725 bool
726 TabParent::DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor)
728 delete actor;
729 return true;
732 PFilePickerParent*
733 TabParent::AllocPFilePickerParent(const nsString& aTitle, const int16_t& aMode)
735 return new FilePickerParent(aTitle, aMode);
738 bool
739 TabParent::DeallocPFilePickerParent(PFilePickerParent* actor)
741 delete actor;
742 return true;
745 void
746 TabParent::SendMouseEvent(const nsAString& aType, float aX, float aY,
747 int32_t aButton, int32_t aClickCount,
748 int32_t aModifiers, bool aIgnoreRootScrollFrame)
750 if (!mIsDestroyed) {
751 unused << PBrowserParent::SendMouseEvent(nsString(aType), aX, aY,
752 aButton, aClickCount,
753 aModifiers, aIgnoreRootScrollFrame);
757 void
758 TabParent::SendKeyEvent(const nsAString& aType,
759 int32_t aKeyCode,
760 int32_t aCharCode,
761 int32_t aModifiers,
762 bool aPreventDefault)
764 if (!mIsDestroyed) {
765 unused << PBrowserParent::SendKeyEvent(nsString(aType), aKeyCode, aCharCode,
766 aModifiers, aPreventDefault);
770 bool
771 TabParent::MapEventCoordinatesForChildProcess(WidgetEvent* aEvent)
773 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
774 if (!frameLoader) {
775 return false;
777 LayoutDeviceIntPoint offset =
778 EventStateManager::GetChildProcessOffset(frameLoader, *aEvent);
779 MapEventCoordinatesForChildProcess(offset, aEvent);
780 return true;
783 void
784 TabParent::MapEventCoordinatesForChildProcess(
785 const LayoutDeviceIntPoint& aOffset, WidgetEvent* aEvent)
787 if (aEvent->mClass != eTouchEventClass) {
788 aEvent->refPoint = aOffset;
789 } else {
790 aEvent->refPoint = LayoutDeviceIntPoint();
791 // Then offset all the touch points by that distance, to put them
792 // in the space where top-left is 0,0.
793 const WidgetTouchEvent::TouchArray& touches =
794 aEvent->AsTouchEvent()->touches;
795 for (uint32_t i = 0; i < touches.Length(); ++i) {
796 Touch* touch = touches[i];
797 if (touch) {
798 touch->mRefPoint += LayoutDeviceIntPoint::ToUntyped(aOffset);
804 bool TabParent::SendRealMouseEvent(WidgetMouseEvent& event)
806 if (mIsDestroyed) {
807 return false;
809 nsEventStatus status = MaybeForwardEventToRenderFrame(event, nullptr);
810 if (status == nsEventStatus_eConsumeNoDefault ||
811 !MapEventCoordinatesForChildProcess(&event)) {
812 return false;
814 return PBrowserParent::SendRealMouseEvent(event);
817 CSSPoint TabParent::AdjustTapToChildWidget(const CSSPoint& aPoint)
819 nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
821 if (!content || !content->OwnerDoc()) {
822 return aPoint;
825 nsIDocument* doc = content->OwnerDoc();
826 if (!doc || !doc->GetShell()) {
827 return aPoint;
829 nsPresContext* presContext = doc->GetShell()->GetPresContext();
831 return aPoint + CSSPoint(
832 presContext->DevPixelsToFloatCSSPixels(mChildProcessOffsetAtTouchStart.x),
833 presContext->DevPixelsToFloatCSSPixels(mChildProcessOffsetAtTouchStart.y));
836 bool TabParent::SendHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
838 if (mIsDestroyed) {
839 return false;
842 return PBrowserParent::SendHandleSingleTap(AdjustTapToChildWidget(aPoint), aGuid);
845 bool TabParent::SendHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
847 if (mIsDestroyed) {
848 return false;
851 return PBrowserParent::SendHandleLongTap(AdjustTapToChildWidget(aPoint), aGuid);
854 bool TabParent::SendHandleLongTapUp(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
856 if (mIsDestroyed) {
857 return false;
860 return PBrowserParent::SendHandleLongTapUp(AdjustTapToChildWidget(aPoint), aGuid);
863 bool TabParent::SendHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
865 if (mIsDestroyed) {
866 return false;
869 return PBrowserParent::SendHandleDoubleTap(AdjustTapToChildWidget(aPoint), aGuid);
872 bool TabParent::SendMouseWheelEvent(WidgetWheelEvent& event)
874 if (mIsDestroyed) {
875 return false;
877 nsEventStatus status = MaybeForwardEventToRenderFrame(event, nullptr);
878 if (status == nsEventStatus_eConsumeNoDefault ||
879 !MapEventCoordinatesForChildProcess(&event)) {
880 return false;
882 return PBrowserParent::SendMouseWheelEvent(event);
885 static void
886 DoCommandCallback(mozilla::Command aCommand, void* aData)
888 static_cast<InfallibleTArray<mozilla::CommandInt>*>(aData)->AppendElement(aCommand);
891 bool
892 TabParent::RecvRequestNativeKeyBindings(const WidgetKeyboardEvent& aEvent,
893 MaybeNativeKeyBinding* aBindings)
895 AutoInfallibleTArray<mozilla::CommandInt, 4> singleLine;
896 AutoInfallibleTArray<mozilla::CommandInt, 4> multiLine;
897 AutoInfallibleTArray<mozilla::CommandInt, 4> richText;
899 *aBindings = mozilla::void_t();
901 nsCOMPtr<nsIWidget> widget = GetWidget();
902 if (!widget) {
903 return true;
906 WidgetKeyboardEvent localEvent(aEvent);
908 if (NS_FAILED(widget->AttachNativeKeyEvent(localEvent))) {
909 return true;
912 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForSingleLineEditor,
913 localEvent, DoCommandCallback, &singleLine);
914 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForMultiLineEditor,
915 localEvent, DoCommandCallback, &multiLine);
916 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForRichTextEditor,
917 localEvent, DoCommandCallback, &richText);
919 if (!singleLine.IsEmpty() || !multiLine.IsEmpty() || !richText.IsEmpty()) {
920 *aBindings = NativeKeyBinding(singleLine, multiLine, richText);
923 return true;
926 bool TabParent::SendRealKeyEvent(WidgetKeyboardEvent& event)
928 if (mIsDestroyed) {
929 return false;
931 MaybeForwardEventToRenderFrame(event, nullptr);
932 if (!MapEventCoordinatesForChildProcess(&event)) {
933 return false;
937 MaybeNativeKeyBinding bindings;
938 bindings = void_t();
939 if (event.message == NS_KEY_PRESS) {
940 nsCOMPtr<nsIWidget> widget = GetWidget();
942 AutoInfallibleTArray<mozilla::CommandInt, 4> singleLine;
943 AutoInfallibleTArray<mozilla::CommandInt, 4> multiLine;
944 AutoInfallibleTArray<mozilla::CommandInt, 4> richText;
946 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForSingleLineEditor,
947 event, DoCommandCallback, &singleLine);
948 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForMultiLineEditor,
949 event, DoCommandCallback, &multiLine);
950 widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForRichTextEditor,
951 event, DoCommandCallback, &richText);
953 if (!singleLine.IsEmpty() || !multiLine.IsEmpty() || !richText.IsEmpty()) {
954 bindings = NativeKeyBinding(singleLine, multiLine, richText);
958 return PBrowserParent::SendRealKeyEvent(event, bindings);
961 bool TabParent::SendRealTouchEvent(WidgetTouchEvent& event)
963 if (mIsDestroyed) {
964 return false;
966 if (event.message == NS_TOUCH_START) {
967 // Adjust the widget coordinates to be relative to our frame.
968 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
969 if (!frameLoader) {
970 // No frame anymore?
971 sEventCapturer = nullptr;
972 return false;
975 mChildProcessOffsetAtTouchStart =
976 EventStateManager::GetChildProcessOffset(frameLoader, event);
978 MOZ_ASSERT((!sEventCapturer && mEventCaptureDepth == 0) ||
979 (sEventCapturer == this && mEventCaptureDepth > 0));
980 // We want to capture all remaining touch events in this series
981 // for fast-path dispatch.
982 sEventCapturer = this;
983 ++mEventCaptureDepth;
986 // PresShell::HandleEventInternal adds touches on touch end/cancel. This
987 // confuses remote content and the panning and zooming logic into thinking
988 // that the added touches are part of the touchend/cancel, when actually
989 // they're not.
990 if (event.message == NS_TOUCH_END || event.message == NS_TOUCH_CANCEL) {
991 for (int i = event.touches.Length() - 1; i >= 0; i--) {
992 if (!event.touches[i]->mChanged) {
993 event.touches.RemoveElementAt(i);
998 ScrollableLayerGuid guid;
999 nsEventStatus status = MaybeForwardEventToRenderFrame(event, &guid);
1001 if (status == nsEventStatus_eConsumeNoDefault || mIsDestroyed) {
1002 return false;
1005 MapEventCoordinatesForChildProcess(mChildProcessOffsetAtTouchStart, &event);
1007 return (event.message == NS_TOUCH_MOVE) ?
1008 PBrowserParent::SendRealTouchMoveEvent(event, guid) :
1009 PBrowserParent::SendRealTouchEvent(event, guid);
1012 /*static*/ TabParent*
1013 TabParent::GetEventCapturer()
1015 return sEventCapturer;
1018 bool
1019 TabParent::TryCapture(const WidgetGUIEvent& aEvent)
1021 MOZ_ASSERT(sEventCapturer == this && mEventCaptureDepth > 0);
1023 if (aEvent.mClass != eTouchEventClass) {
1024 // Only capture of touch events is implemented, for now.
1025 return false;
1028 WidgetTouchEvent event(*aEvent.AsTouchEvent());
1030 bool isTouchPointUp = (event.message == NS_TOUCH_END ||
1031 event.message == NS_TOUCH_CANCEL);
1032 if (event.message == NS_TOUCH_START || isTouchPointUp) {
1033 // Let the DOM see touch start/end events so that its touch-point
1034 // state stays consistent.
1035 if (isTouchPointUp && 0 == --mEventCaptureDepth) {
1036 // All event series are un-captured, don't try to catch any
1037 // more.
1038 sEventCapturer = nullptr;
1040 return false;
1043 SendRealTouchEvent(event);
1044 return true;
1047 bool
1048 TabParent::RecvSyncMessage(const nsString& aMessage,
1049 const ClonedMessageData& aData,
1050 const InfallibleTArray<CpowEntry>& aCpows,
1051 const IPC::Principal& aPrincipal,
1052 InfallibleTArray<nsString>* aJSONRetVal)
1054 // FIXME Permission check for TabParent in Content process
1055 nsIPrincipal* principal = aPrincipal;
1056 if (Manager()->IsContentParent()) {
1057 ContentParent* parent = Manager()->AsContentParent();
1058 if (!ContentParent::IgnoreIPCPrincipal() &&
1059 parent && principal && !AssertAppPrincipal(parent, principal)) {
1060 return false;
1064 StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
1065 CpowIdHolder cpows(Manager()->GetCPOWManager(), aCpows);
1066 return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal);
1069 bool
1070 TabParent::AnswerRpcMessage(const nsString& aMessage,
1071 const ClonedMessageData& aData,
1072 const InfallibleTArray<CpowEntry>& aCpows,
1073 const IPC::Principal& aPrincipal,
1074 InfallibleTArray<nsString>* aJSONRetVal)
1076 // FIXME Permission check for TabParent in Content process
1077 nsIPrincipal* principal = aPrincipal;
1078 if (Manager()->IsContentParent()) {
1079 ContentParent* parent = Manager()->AsContentParent();
1080 if (!ContentParent::IgnoreIPCPrincipal() &&
1081 parent && principal && !AssertAppPrincipal(parent, principal)) {
1082 return false;
1086 StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
1087 CpowIdHolder cpows(Manager()->GetCPOWManager(), aCpows);
1088 return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal);
1091 bool
1092 TabParent::RecvAsyncMessage(const nsString& aMessage,
1093 const ClonedMessageData& aData,
1094 const InfallibleTArray<CpowEntry>& aCpows,
1095 const IPC::Principal& aPrincipal)
1097 // FIXME Permission check for TabParent in Content process
1098 nsIPrincipal* principal = aPrincipal;
1099 if (Manager()->IsContentParent()) {
1100 ContentParent* parent = Manager()->AsContentParent();
1101 if (!ContentParent::IgnoreIPCPrincipal() &&
1102 parent && principal && !AssertAppPrincipal(parent, principal)) {
1103 return false;
1107 StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
1108 CpowIdHolder cpows(Manager()->GetCPOWManager(), aCpows);
1109 return ReceiveMessage(aMessage, false, &cloneData, &cpows, aPrincipal, nullptr);
1112 bool
1113 TabParent::RecvSetCursor(const uint32_t& aCursor, const bool& aForce)
1115 nsCOMPtr<nsIWidget> widget = GetWidget();
1116 if (widget) {
1117 if (aForce) {
1118 widget->ClearCachedCursor();
1120 widget->SetCursor((nsCursor) aCursor);
1122 return true;
1125 bool
1126 TabParent::RecvSetBackgroundColor(const nscolor& aColor)
1128 if (RenderFrameParent* frame = GetRenderFrame()) {
1129 frame->SetBackgroundColor(aColor);
1131 return true;
1134 nsIXULBrowserWindow*
1135 TabParent::GetXULBrowserWindow()
1137 nsCOMPtr<nsIContent> frame = do_QueryInterface(mFrameElement);
1138 if (!frame) {
1139 return nullptr;
1142 nsCOMPtr<nsIDocShell> docShell = frame->OwnerDoc()->GetDocShell();
1143 if (!docShell) {
1144 return nullptr;
1147 nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
1148 docShell->GetTreeOwner(getter_AddRefs(treeOwner));
1149 if (!treeOwner) {
1150 return nullptr;
1153 nsCOMPtr<nsIXULWindow> window = do_GetInterface(treeOwner);
1154 if (!window) {
1155 return nullptr;
1158 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow;
1159 window->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow));
1160 return xulBrowserWindow;
1163 bool
1164 TabParent::RecvSetStatus(const uint32_t& aType, const nsString& aStatus)
1166 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow();
1167 if (!xulBrowserWindow) {
1168 return true;
1171 switch (aType) {
1172 case nsIWebBrowserChrome::STATUS_SCRIPT:
1173 xulBrowserWindow->SetJSStatus(aStatus);
1174 break;
1175 case nsIWebBrowserChrome::STATUS_LINK:
1176 xulBrowserWindow->SetOverLink(aStatus, nullptr);
1177 break;
1179 return true;
1182 bool
1183 TabParent::RecvShowTooltip(const uint32_t& aX, const uint32_t& aY, const nsString& aTooltip)
1185 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow();
1186 if (!xulBrowserWindow) {
1187 return true;
1190 xulBrowserWindow->ShowTooltip(aX, aY, aTooltip);
1191 return true;
1194 bool
1195 TabParent::RecvHideTooltip()
1197 nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow();
1198 if (!xulBrowserWindow) {
1199 return true;
1202 xulBrowserWindow->HideTooltip();
1203 return true;
1206 bool
1207 TabParent::RecvNotifyIMEFocus(const bool& aFocus,
1208 nsIMEUpdatePreference* aPreference,
1209 uint32_t* aSeqno)
1211 nsCOMPtr<nsIWidget> widget = GetWidget();
1212 if (!widget) {
1213 *aPreference = nsIMEUpdatePreference();
1214 return true;
1217 *aSeqno = mIMESeqno;
1218 mIMETabParent = aFocus ? this : nullptr;
1219 mIMESelectionAnchor = 0;
1220 mIMESelectionFocus = 0;
1221 widget->NotifyIME(IMENotification(aFocus ? NOTIFY_IME_OF_FOCUS :
1222 NOTIFY_IME_OF_BLUR));
1224 if (aFocus) {
1225 *aPreference = widget->GetIMEUpdatePreference();
1226 } else {
1227 mIMECacheText.Truncate(0);
1229 return true;
1232 bool
1233 TabParent::RecvNotifyIMETextChange(const uint32_t& aStart,
1234 const uint32_t& aEnd,
1235 const uint32_t& aNewEnd,
1236 const bool& aCausedByComposition)
1238 nsCOMPtr<nsIWidget> widget = GetWidget();
1239 if (!widget)
1240 return true;
1242 #ifdef DEBUG
1243 nsIMEUpdatePreference updatePreference = widget->GetIMEUpdatePreference();
1244 NS_ASSERTION(updatePreference.WantTextChange(),
1245 "Don't call Send/RecvNotifyIMETextChange without NOTIFY_TEXT_CHANGE");
1246 MOZ_ASSERT(!aCausedByComposition ||
1247 updatePreference.WantChangesCausedByComposition(),
1248 "The widget doesn't want text change notification caused by composition");
1249 #endif
1251 IMENotification notification(NOTIFY_IME_OF_TEXT_CHANGE);
1252 notification.mTextChangeData.mStartOffset = aStart;
1253 notification.mTextChangeData.mOldEndOffset = aEnd;
1254 notification.mTextChangeData.mNewEndOffset = aNewEnd;
1255 notification.mTextChangeData.mCausedByComposition = aCausedByComposition;
1256 widget->NotifyIME(notification);
1257 return true;
1260 bool
1261 TabParent::RecvNotifyIMESelectedCompositionRect(const uint32_t& aOffset,
1262 const nsIntRect& aRect,
1263 const nsIntRect& aCaretRect)
1265 // add rect to cache for another query
1266 mIMECompositionRectOffset = aOffset;
1267 mIMECompositionRect = aRect;
1268 mIMECaretRect = aCaretRect;
1270 nsCOMPtr<nsIWidget> widget = GetWidget();
1271 if (!widget) {
1272 return true;
1274 widget->NotifyIME(IMENotification(NOTIFY_IME_OF_COMPOSITION_UPDATE));
1275 return true;
1278 bool
1279 TabParent::RecvNotifyIMESelection(const uint32_t& aSeqno,
1280 const uint32_t& aAnchor,
1281 const uint32_t& aFocus,
1282 const bool& aCausedByComposition)
1284 nsCOMPtr<nsIWidget> widget = GetWidget();
1285 if (!widget)
1286 return true;
1288 if (aSeqno == mIMESeqno) {
1289 mIMESelectionAnchor = aAnchor;
1290 mIMESelectionFocus = aFocus;
1291 const nsIMEUpdatePreference updatePreference =
1292 widget->GetIMEUpdatePreference();
1293 if (updatePreference.WantSelectionChange() &&
1294 (updatePreference.WantChangesCausedByComposition() ||
1295 !aCausedByComposition)) {
1296 IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
1297 notification.mSelectionChangeData.mCausedByComposition =
1298 aCausedByComposition;
1299 widget->NotifyIME(notification);
1302 return true;
1305 bool
1306 TabParent::RecvNotifyIMETextHint(const nsString& aText)
1308 // Replace our cache with new text
1309 mIMECacheText = aText;
1310 return true;
1313 bool
1314 TabParent::RecvRequestFocus(const bool& aCanRaise)
1316 nsCOMPtr<nsIFocusManager> fm = nsFocusManager::GetFocusManager();
1317 if (!fm) {
1318 return true;
1321 nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
1322 if (!content || !content->OwnerDoc()) {
1323 return true;
1326 uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
1327 if (aCanRaise)
1328 flags |= nsIFocusManager::FLAG_RAISE;
1330 nsCOMPtr<nsIDOMElement> node = do_QueryInterface(mFrameElement);
1331 fm->SetFocus(node, flags);
1332 return true;
1335 nsIntPoint
1336 TabParent::GetChildProcessOffset()
1338 // The "toplevel widget" in child processes is always at position
1339 // 0,0. Map the event coordinates to match that.
1341 nsIntPoint offset(0, 0);
1342 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
1343 if (!frameLoader) {
1344 return offset;
1346 nsIFrame* targetFrame = frameLoader->GetPrimaryFrameOfOwningContent();
1347 if (!targetFrame) {
1348 return offset;
1351 // Find out how far we're offset from the nearest widget.
1352 nsCOMPtr<nsIWidget> widget = GetWidget();
1353 if (!widget) {
1354 return offset;
1356 nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(widget,
1357 nsIntPoint(0, 0),
1358 targetFrame);
1360 return LayoutDeviceIntPoint::ToUntyped(LayoutDeviceIntPoint::FromAppUnitsToNearest(
1361 pt, targetFrame->PresContext()->AppUnitsPerDevPixel()));
1364 bool
1365 TabParent::RecvReplyKeyEvent(const WidgetKeyboardEvent& event)
1367 NS_ENSURE_TRUE(mFrameElement, true);
1369 WidgetKeyboardEvent localEvent(event);
1370 // Set mNoCrossProcessBoundaryForwarding to avoid this event from
1371 // being infinitely redispatched and forwarded to the child again.
1372 localEvent.mFlags.mNoCrossProcessBoundaryForwarding = true;
1374 // Here we convert the WidgetEvent that we received to an nsIDOMEvent
1375 // to be able to dispatch it to the <browser> element as the target element.
1376 nsIDocument* doc = mFrameElement->OwnerDoc();
1377 nsIPresShell* presShell = doc->GetShell();
1378 NS_ENSURE_TRUE(presShell, true);
1379 nsPresContext* presContext = presShell->GetPresContext();
1380 NS_ENSURE_TRUE(presContext, true);
1382 EventDispatcher::Dispatch(mFrameElement, presContext, &localEvent);
1383 return true;
1387 * Try to answer query event using cached text.
1389 * For NS_QUERY_SELECTED_TEXT, fail if the cache doesn't contain the whole
1390 * selected range. (This shouldn't happen because PuppetWidget should have
1391 * already sent the whole selection.)
1393 * For NS_QUERY_TEXT_CONTENT, fail only if the cache doesn't overlap with
1394 * the queried range. Note the difference from above. We use
1395 * this behavior because a normal NS_QUERY_TEXT_CONTENT event is allowed to
1396 * have out-of-bounds offsets, so that widget can request content without
1397 * knowing the exact length of text. It's up to widget to handle cases when
1398 * the returned offset/length are different from the queried offset/length.
1400 * For NS_QUERY_TEXT_RECT, fail if cached offset/length aren't equals to input.
1401 * Cocoa widget always queries selected offset, so it works on it.
1403 * For NS_QUERY_CARET_RECT, fail if cached offset isn't equals to input
1405 bool
1406 TabParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent)
1408 aEvent.mSucceeded = false;
1409 aEvent.mWasAsync = false;
1410 aEvent.mReply.mFocusedWidget = nsCOMPtr<nsIWidget>(GetWidget()).get();
1412 switch (aEvent.message)
1414 case NS_QUERY_SELECTED_TEXT:
1416 aEvent.mReply.mOffset = std::min(mIMESelectionAnchor, mIMESelectionFocus);
1417 if (mIMESelectionAnchor == mIMESelectionFocus) {
1418 aEvent.mReply.mString.Truncate(0);
1419 } else {
1420 if (mIMESelectionAnchor > mIMECacheText.Length() ||
1421 mIMESelectionFocus > mIMECacheText.Length()) {
1422 break;
1424 uint32_t selLen = mIMESelectionAnchor > mIMESelectionFocus ?
1425 mIMESelectionAnchor - mIMESelectionFocus :
1426 mIMESelectionFocus - mIMESelectionAnchor;
1427 aEvent.mReply.mString = Substring(mIMECacheText,
1428 aEvent.mReply.mOffset,
1429 selLen);
1431 aEvent.mReply.mReversed = mIMESelectionFocus < mIMESelectionAnchor;
1432 aEvent.mReply.mHasSelection = true;
1433 aEvent.mSucceeded = true;
1435 break;
1436 case NS_QUERY_TEXT_CONTENT:
1438 uint32_t inputOffset = aEvent.mInput.mOffset,
1439 inputEnd = inputOffset + aEvent.mInput.mLength;
1441 if (inputEnd > mIMECacheText.Length()) {
1442 inputEnd = mIMECacheText.Length();
1444 if (inputEnd < inputOffset) {
1445 break;
1447 aEvent.mReply.mOffset = inputOffset;
1448 aEvent.mReply.mString = Substring(mIMECacheText,
1449 inputOffset,
1450 inputEnd - inputOffset);
1451 aEvent.mSucceeded = true;
1453 break;
1454 case NS_QUERY_TEXT_RECT:
1456 if (aEvent.mInput.mOffset != mIMECompositionRectOffset ||
1457 aEvent.mInput.mLength != 1) {
1458 break;
1461 aEvent.mReply.mOffset = mIMECompositionRectOffset;
1462 aEvent.mReply.mRect = mIMECompositionRect - GetChildProcessOffset();
1463 aEvent.mSucceeded = true;
1465 break;
1466 case NS_QUERY_CARET_RECT:
1468 if (aEvent.mInput.mOffset != mIMECompositionRectOffset) {
1469 break;
1472 aEvent.mReply.mOffset = mIMECompositionRectOffset;
1473 aEvent.mReply.mRect = mIMECaretRect - GetChildProcessOffset();
1474 aEvent.mSucceeded = true;
1476 break;
1478 return true;
1481 bool
1482 TabParent::SendCompositionEvent(WidgetCompositionEvent& event)
1484 if (mIsDestroyed) {
1485 return false;
1487 mIMEComposing = event.message != NS_COMPOSITION_END;
1488 mIMECompositionStart = std::min(mIMESelectionAnchor, mIMESelectionFocus);
1489 if (mIMECompositionEnding)
1490 return true;
1491 event.mSeqno = ++mIMESeqno;
1492 return PBrowserParent::SendCompositionEvent(event);
1496 * During REQUEST_TO_COMMIT_COMPOSITION or REQUEST_TO_CANCEL_COMPOSITION,
1497 * widget usually sends a NS_TEXT_TEXT event to finalize or clear the
1498 * composition, respectively
1500 * Because the event will not reach content in time, we intercept it
1501 * here and pass the text as the EndIMEComposition return value
1503 bool
1504 TabParent::SendTextEvent(WidgetTextEvent& event)
1506 if (mIsDestroyed) {
1507 return false;
1509 if (mIMECompositionEnding) {
1510 mIMECompositionText = event.theText;
1511 return true;
1514 // We must be able to simulate the selection because
1515 // we might not receive selection updates in time
1516 if (!mIMEComposing) {
1517 mIMECompositionStart = std::min(mIMESelectionAnchor, mIMESelectionFocus);
1519 mIMESelectionAnchor = mIMESelectionFocus =
1520 mIMECompositionStart + event.theText.Length();
1522 event.mSeqno = ++mIMESeqno;
1523 return PBrowserParent::SendTextEvent(event);
1526 bool
1527 TabParent::SendSelectionEvent(WidgetSelectionEvent& event)
1529 if (mIsDestroyed) {
1530 return false;
1532 mIMESelectionAnchor = event.mOffset + (event.mReversed ? event.mLength : 0);
1533 mIMESelectionFocus = event.mOffset + (!event.mReversed ? event.mLength : 0);
1534 event.mSeqno = ++mIMESeqno;
1535 return PBrowserParent::SendSelectionEvent(event);
1538 /*static*/ TabParent*
1539 TabParent::GetFrom(nsFrameLoader* aFrameLoader)
1541 if (!aFrameLoader) {
1542 return nullptr;
1544 PBrowserParent* remoteBrowser = aFrameLoader->GetRemoteBrowser();
1545 return static_cast<TabParent*>(remoteBrowser);
1548 /*static*/ TabParent*
1549 TabParent::GetFrom(nsIContent* aContent)
1551 nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(aContent);
1552 if (!loaderOwner) {
1553 return nullptr;
1555 nsRefPtr<nsFrameLoader> frameLoader = loaderOwner->GetFrameLoader();
1556 return GetFrom(frameLoader);
1559 RenderFrameParent*
1560 TabParent::GetRenderFrame()
1562 if (ManagedPRenderFrameParent().IsEmpty()) {
1563 return nullptr;
1565 return static_cast<RenderFrameParent*>(ManagedPRenderFrameParent()[0]);
1568 bool
1569 TabParent::RecvEndIMEComposition(const bool& aCancel,
1570 nsString* aComposition)
1572 nsCOMPtr<nsIWidget> widget = GetWidget();
1573 if (!widget)
1574 return true;
1576 mIMECompositionEnding = true;
1578 widget->NotifyIME(IMENotification(aCancel ? REQUEST_TO_CANCEL_COMPOSITION :
1579 REQUEST_TO_COMMIT_COMPOSITION));
1581 mIMECompositionEnding = false;
1582 *aComposition = mIMECompositionText;
1583 mIMECompositionText.Truncate(0);
1584 return true;
1587 bool
1588 TabParent::RecvGetInputContext(int32_t* aIMEEnabled,
1589 int32_t* aIMEOpen,
1590 intptr_t* aNativeIMEContext)
1592 nsCOMPtr<nsIWidget> widget = GetWidget();
1593 if (!widget) {
1594 *aIMEEnabled = IMEState::DISABLED;
1595 *aIMEOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
1596 *aNativeIMEContext = 0;
1597 return true;
1600 InputContext context = widget->GetInputContext();
1601 *aIMEEnabled = static_cast<int32_t>(context.mIMEState.mEnabled);
1602 *aIMEOpen = static_cast<int32_t>(context.mIMEState.mOpen);
1603 *aNativeIMEContext = reinterpret_cast<intptr_t>(context.mNativeIMEContext);
1604 return true;
1607 bool
1608 TabParent::RecvSetInputContext(const int32_t& aIMEEnabled,
1609 const int32_t& aIMEOpen,
1610 const nsString& aType,
1611 const nsString& aInputmode,
1612 const nsString& aActionHint,
1613 const int32_t& aCause,
1614 const int32_t& aFocusChange)
1616 // mIMETabParent (which is actually static) tracks which if any TabParent has IMEFocus
1617 // When the input mode is set to anything but IMEState::DISABLED,
1618 // mIMETabParent should be set to this
1619 mIMETabParent =
1620 aIMEEnabled != static_cast<int32_t>(IMEState::DISABLED) ? this : nullptr;
1621 nsCOMPtr<nsIWidget> widget = GetWidget();
1622 if (!widget || !AllowContentIME())
1623 return true;
1625 InputContext context;
1626 context.mIMEState.mEnabled = static_cast<IMEState::Enabled>(aIMEEnabled);
1627 context.mIMEState.mOpen = static_cast<IMEState::Open>(aIMEOpen);
1628 context.mHTMLInputType.Assign(aType);
1629 context.mHTMLInputInputmode.Assign(aInputmode);
1630 context.mActionHint.Assign(aActionHint);
1631 InputContextAction action(
1632 static_cast<InputContextAction::Cause>(aCause),
1633 static_cast<InputContextAction::FocusChange>(aFocusChange));
1634 widget->SetInputContext(context, action);
1636 nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
1637 if (!observerService)
1638 return true;
1640 nsAutoString state;
1641 state.AppendInt(aIMEEnabled);
1642 observerService->NotifyObservers(nullptr, "ime-enabled-state-changed", state.get());
1644 return true;
1647 bool
1648 TabParent::RecvIsParentWindowMainWidgetVisible(bool* aIsVisible)
1650 nsCOMPtr<nsIContent> frame = do_QueryInterface(mFrameElement);
1651 if (!frame)
1652 return true;
1653 nsCOMPtr<nsIDOMWindowUtils> windowUtils =
1654 do_QueryInterface(frame->OwnerDoc()->GetWindow());
1655 nsresult rv = windowUtils->GetIsParentWindowMainWidgetVisible(aIsVisible);
1656 return NS_SUCCEEDED(rv);
1659 bool
1660 TabParent::RecvGetDPI(float* aValue)
1662 TryCacheDPIAndScale();
1664 NS_ABORT_IF_FALSE(mDPI > 0,
1665 "Must not ask for DPI before OwnerElement is received!");
1666 *aValue = mDPI;
1667 return true;
1670 bool
1671 TabParent::RecvGetDefaultScale(double* aValue)
1673 TryCacheDPIAndScale();
1675 NS_ABORT_IF_FALSE(mDefaultScale.scale > 0,
1676 "Must not ask for scale before OwnerElement is received!");
1677 *aValue = mDefaultScale.scale;
1678 return true;
1681 bool
1682 TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue)
1684 nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
1685 if (content) {
1686 nsIPresShell* shell = content->OwnerDoc()->GetShell();
1687 if (shell) {
1688 nsViewManager* vm = shell->GetViewManager();
1689 nsCOMPtr<nsIWidget> widget;
1690 vm->GetRootWidget(getter_AddRefs(widget));
1691 if (widget) {
1692 *aValue = reinterpret_cast<WindowsHandle>(
1693 widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW));
1694 return true;
1698 return false;
1701 bool
1702 TabParent::ReceiveMessage(const nsString& aMessage,
1703 bool aSync,
1704 const StructuredCloneData* aCloneData,
1705 CpowHolder* aCpows,
1706 nsIPrincipal* aPrincipal,
1707 InfallibleTArray<nsString>* aJSONRetVal)
1709 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
1710 if (frameLoader && frameLoader->GetFrameMessageManager()) {
1711 nsRefPtr<nsFrameMessageManager> manager =
1712 frameLoader->GetFrameMessageManager();
1714 manager->ReceiveMessage(mFrameElement,
1715 aMessage,
1716 aSync,
1717 aCloneData,
1718 aCpows,
1719 aPrincipal,
1720 aJSONRetVal);
1722 return true;
1725 PIndexedDBParent*
1726 TabParent::AllocPIndexedDBParent(
1727 const nsCString& aGroup,
1728 const nsCString& aASCIIOrigin, bool* /* aAllowed */)
1730 return new IndexedDBParent(this);
1733 bool
1734 TabParent::DeallocPIndexedDBParent(PIndexedDBParent* aActor)
1736 delete aActor;
1737 return true;
1740 bool
1741 TabParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
1742 const nsCString& aGroup,
1743 const nsCString& aASCIIOrigin,
1744 bool* aAllowed)
1746 nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::GetOrCreate();
1747 NS_ENSURE_TRUE(mgr, false);
1749 if (!IndexedDatabaseManager::IsMainProcess()) {
1750 NS_RUNTIMEABORT("Not supported yet!");
1753 nsresult rv;
1755 // XXXbent Need to make sure we have a whitelist for chrome databases!
1757 // Verify that the child is requesting to access a database it's allowed to
1758 // see. (aASCIIOrigin here specifies a TabContext + a website origin, and
1759 // we're checking that the TabContext may access it.)
1761 // We have to check IsBrowserOrApp() because TabContextMayAccessOrigin will
1762 // fail if we're not a browser-or-app, since aASCIIOrigin will be a plain URI,
1763 // but TabContextMayAccessOrigin will construct an extended origin using
1764 // app-id 0. Note that as written below, we allow a non browser-or-app child
1765 // to read any database. That's a security hole, but we don't ship a
1766 // configuration which creates non browser-or-app children, so it's not a big
1767 // deal.
1768 if (!aASCIIOrigin.EqualsLiteral("chrome") && IsBrowserOrApp() &&
1769 !IndexedDatabaseManager::TabContextMayAccessOrigin(*this, aASCIIOrigin)) {
1771 NS_WARNING("App attempted to open databases that it does not have "
1772 "permission to access!");
1773 return false;
1776 nsCOMPtr<nsINode> node = do_QueryInterface(GetOwnerElement());
1777 NS_ENSURE_TRUE(node, false);
1779 nsIDocument* doc = node->GetOwnerDocument();
1780 NS_ENSURE_TRUE(doc, false);
1782 nsCOMPtr<nsPIDOMWindow> window = doc->GetInnerWindow();
1783 NS_ENSURE_TRUE(window, false);
1785 // Let's do a current inner check to see if the inner is active or is in
1786 // bf cache, and bail out if it's not active.
1787 nsCOMPtr<nsPIDOMWindow> outer = doc->GetWindow();
1788 if (!outer || outer->GetCurrentInnerWindow() != window) {
1789 *aAllowed = false;
1790 return true;
1793 NS_ASSERTION(Manager(), "Null manager?!");
1795 nsRefPtr<IDBFactory> factory;
1796 rv = IDBFactory::Create(window, aGroup, aASCIIOrigin, Manager(),
1797 getter_AddRefs(factory));
1798 NS_ENSURE_SUCCESS(rv, false);
1800 if (!factory) {
1801 *aAllowed = false;
1802 return true;
1805 IndexedDBParent* actor = static_cast<IndexedDBParent*>(aActor);
1806 actor->mFactory = factory;
1807 actor->mASCIIOrigin = aASCIIOrigin;
1809 *aAllowed = true;
1810 return true;
1813 // nsIAuthPromptProvider
1815 // This method is largely copied from nsDocShell::GetAuthPrompt
1816 NS_IMETHODIMP
1817 TabParent::GetAuthPrompt(uint32_t aPromptReason, const nsIID& iid,
1818 void** aResult)
1820 // we're either allowing auth, or it's a proxy request
1821 nsresult rv;
1822 nsCOMPtr<nsIPromptFactory> wwatch =
1823 do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
1824 NS_ENSURE_SUCCESS(rv, rv);
1826 nsCOMPtr<nsIDOMWindow> window;
1827 nsCOMPtr<nsIContent> frame = do_QueryInterface(mFrameElement);
1828 if (frame)
1829 window = do_QueryInterface(frame->OwnerDoc()->GetWindow());
1831 // Get an auth prompter for our window so that the parenting
1832 // of the dialogs works as it should when using tabs.
1833 return wwatch->GetPrompt(window, iid,
1834 reinterpret_cast<void**>(aResult));
1837 PColorPickerParent*
1838 TabParent::AllocPColorPickerParent(const nsString& aTitle,
1839 const nsString& aInitialColor)
1841 return new ColorPickerParent(aTitle, aInitialColor);
1844 bool
1845 TabParent::DeallocPColorPickerParent(PColorPickerParent* actor)
1847 delete actor;
1848 return true;
1851 PRenderFrameParent*
1852 TabParent::AllocPRenderFrameParent(ScrollingBehavior* aScrolling,
1853 TextureFactoryIdentifier* aTextureFactoryIdentifier,
1854 uint64_t* aLayersId, bool* aSuccess)
1856 MOZ_ASSERT(ManagedPRenderFrameParent().IsEmpty());
1858 nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
1859 *aScrolling = UseAsyncPanZoom() ? ASYNC_PAN_ZOOM : DEFAULT_SCROLLING;
1860 return new RenderFrameParent(frameLoader,
1861 *aScrolling,
1862 aTextureFactoryIdentifier, aLayersId,
1863 aSuccess);
1866 bool
1867 TabParent::DeallocPRenderFrameParent(PRenderFrameParent* aFrame)
1869 delete aFrame;
1870 return true;
1873 mozilla::docshell::POfflineCacheUpdateParent*
1874 TabParent::AllocPOfflineCacheUpdateParent(const URIParams& aManifestURI,
1875 const URIParams& aDocumentURI,
1876 const bool& aStickDocument)
1878 nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
1879 new mozilla::docshell::OfflineCacheUpdateParent(OwnOrContainingAppId(),
1880 IsBrowserElement());
1881 // Use this reference as the IPDL reference.
1882 return update.forget().take();
1885 bool
1886 TabParent::RecvPOfflineCacheUpdateConstructor(POfflineCacheUpdateParent* aActor,
1887 const URIParams& aManifestURI,
1888 const URIParams& aDocumentURI,
1889 const bool& aStickDocument)
1891 MOZ_ASSERT(aActor);
1893 nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
1894 static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(aActor);
1896 nsresult rv = update->Schedule(aManifestURI, aDocumentURI, aStickDocument);
1897 if (NS_FAILED(rv) && !IsDestroyed()) {
1898 // Inform the child of failure.
1899 unused << update->SendFinish(false, false);
1902 return true;
1905 bool
1906 TabParent::DeallocPOfflineCacheUpdateParent(POfflineCacheUpdateParent* aActor)
1908 // Reclaim the IPDL reference.
1909 nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
1910 dont_AddRef(
1911 static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(aActor));
1912 return true;
1915 bool
1916 TabParent::RecvSetOfflinePermission(const IPC::Principal& aPrincipal)
1918 nsIPrincipal* principal = aPrincipal;
1919 nsContentUtils::MaybeAllowOfflineAppByDefault(principal, nullptr);
1920 return true;
1923 bool
1924 TabParent::AllowContentIME()
1926 nsFocusManager* fm = nsFocusManager::GetFocusManager();
1927 NS_ENSURE_TRUE(fm, false);
1929 nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedContent();
1930 if (focusedContent && focusedContent->IsEditable())
1931 return false;
1933 return true;
1936 already_AddRefed<nsFrameLoader>
1937 TabParent::GetFrameLoader() const
1939 nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner = do_QueryInterface(mFrameElement);
1940 return frameLoaderOwner ? frameLoaderOwner->GetFrameLoader() : nullptr;
1943 void
1944 TabParent::TryCacheDPIAndScale()
1946 if (mDPI > 0) {
1947 return;
1950 nsCOMPtr<nsIWidget> widget = GetWidget();
1952 if (!widget && mFrameElement) {
1953 // Even if we don't have a widget (e.g. because we're display:none), there's
1954 // probably a widget somewhere in the hierarchy our frame element lives in.
1955 widget = nsContentUtils::WidgetForDocument(mFrameElement->OwnerDoc());
1958 if (widget) {
1959 mDPI = widget->GetDPI();
1960 mDefaultScale = widget->GetDefaultScale();
1964 already_AddRefed<nsIWidget>
1965 TabParent::GetWidget() const
1967 nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
1968 if (!content)
1969 return nullptr;
1971 nsIFrame *frame = content->GetPrimaryFrame();
1972 if (!frame)
1973 return nullptr;
1975 nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget();
1976 return widget.forget();
1979 bool
1980 TabParent::UseAsyncPanZoom()
1982 bool usingOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
1983 return (usingOffMainThreadCompositing && gfxPrefs::AsyncPanZoomEnabled() &&
1984 GetScrollingBehavior() == ASYNC_PAN_ZOOM);
1987 nsEventStatus
1988 TabParent::MaybeForwardEventToRenderFrame(WidgetInputEvent& aEvent,
1989 ScrollableLayerGuid* aOutTargetGuid)
1991 if (RenderFrameParent* rfp = GetRenderFrame()) {
1992 return rfp->NotifyInputEvent(aEvent, aOutTargetGuid);
1994 return nsEventStatus_eIgnore;
1997 bool
1998 TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
1999 const nsString& aURL,
2000 const nsString& aName,
2001 const nsString& aFeatures,
2002 bool* aOutWindowOpened)
2004 BrowserElementParent::OpenWindowResult opened =
2005 BrowserElementParent::OpenWindowOOP(static_cast<TabParent*>(aOpener),
2006 this, aURL, aName, aFeatures);
2007 *aOutWindowOpened = (opened != BrowserElementParent::OPEN_WINDOW_CANCELLED);
2008 return true;
2011 bool
2012 TabParent::RecvPRenderFrameConstructor(PRenderFrameParent* aActor,
2013 ScrollingBehavior* aScrolling,
2014 TextureFactoryIdentifier* aFactoryIdentifier,
2015 uint64_t* aLayersId,
2016 bool* aSuccess)
2018 return true;
2021 bool
2022 TabParent::RecvZoomToRect(const uint32_t& aPresShellId,
2023 const ViewID& aViewId,
2024 const CSSRect& aRect)
2026 if (RenderFrameParent* rfp = GetRenderFrame()) {
2027 rfp->ZoomToRect(aPresShellId, aViewId, aRect);
2029 return true;
2032 bool
2033 TabParent::RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
2034 const ViewID& aViewId,
2035 const bool& aIsRoot,
2036 const ZoomConstraints& aConstraints)
2038 if (RenderFrameParent* rfp = GetRenderFrame()) {
2039 rfp->UpdateZoomConstraints(aPresShellId, aViewId, aIsRoot, aConstraints);
2041 return true;
2044 bool
2045 TabParent::RecvContentReceivedTouch(const ScrollableLayerGuid& aGuid,
2046 const bool& aPreventDefault)
2048 if (RenderFrameParent* rfp = GetRenderFrame()) {
2049 rfp->ContentReceivedTouch(aGuid, aPreventDefault);
2051 return true;
2054 already_AddRefed<nsILoadContext>
2055 TabParent::GetLoadContext()
2057 nsCOMPtr<nsILoadContext> loadContext;
2058 if (mLoadContext) {
2059 loadContext = mLoadContext;
2060 } else {
2061 loadContext = new LoadContext(GetOwnerElement(),
2062 OwnOrContainingAppId(),
2063 true /* aIsContent */,
2064 mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW,
2065 mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW,
2066 IsBrowserElement());
2067 mLoadContext = loadContext;
2069 return loadContext.forget();
2072 /* Be careful if you call this method while proceding a real touch event. For
2073 * example sending a touchstart during a real touchend may results into
2074 * a busted mEventCaptureDepth and following touch events may not do what you
2075 * expect.
2077 NS_IMETHODIMP
2078 TabParent::InjectTouchEvent(const nsAString& aType,
2079 uint32_t* aIdentifiers,
2080 int32_t* aXs,
2081 int32_t* aYs,
2082 uint32_t* aRxs,
2083 uint32_t* aRys,
2084 float* aRotationAngles,
2085 float* aForces,
2086 uint32_t aCount,
2087 int32_t aModifiers)
2089 uint32_t msg;
2090 nsContentUtils::GetEventIdAndAtom(aType, eTouchEventClass, &msg);
2091 if (msg != NS_TOUCH_START && msg != NS_TOUCH_MOVE &&
2092 msg != NS_TOUCH_END && msg != NS_TOUCH_CANCEL) {
2093 return NS_ERROR_FAILURE;
2096 nsCOMPtr<nsIWidget> widget = GetWidget();
2097 if (!widget) {
2098 return NS_ERROR_FAILURE;
2101 WidgetTouchEvent event(true, msg, widget);
2102 event.modifiers = aModifiers;
2103 event.time = PR_IntervalNow();
2105 nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
2106 if (!content || !content->OwnerDoc()) {
2107 return NS_ERROR_FAILURE;
2110 nsIDocument* doc = content->OwnerDoc();
2111 if (!doc || !doc->GetShell()) {
2112 return NS_ERROR_FAILURE;
2114 nsPresContext* presContext = doc->GetShell()->GetPresContext();
2116 event.touches.SetCapacity(aCount);
2117 for (uint32_t i = 0; i < aCount; ++i) {
2118 LayoutDeviceIntPoint pt =
2119 LayoutDeviceIntPoint::FromAppUnitsRounded(
2120 CSSPoint::ToAppUnits(CSSPoint(aXs[i], aYs[i])),
2121 presContext->AppUnitsPerDevPixel());
2123 nsRefPtr<Touch> t = new Touch(aIdentifiers[i],
2124 LayoutDeviceIntPoint::ToUntyped(pt),
2125 nsIntPoint(aRxs[i], aRys[i]),
2126 aRotationAngles[i],
2127 aForces[i]);
2129 // Consider all injected touch events as changedTouches. For more details
2130 // about the meaning of changedTouches for each event, see
2131 // https://developer.mozilla.org/docs/Web/API/TouchEvent.changedTouches
2132 t->mChanged = true;
2133 event.touches.AppendElement(t);
2136 if ((msg == NS_TOUCH_END || msg == NS_TOUCH_CANCEL) && sEventCapturer) {
2137 WidgetGUIEvent* guiEvent = event.AsGUIEvent();
2138 TryCapture(*guiEvent);
2141 SendRealTouchEvent(event);
2142 return NS_OK;
2145 NS_IMETHODIMP
2146 TabParent::GetUseAsyncPanZoom(bool* useAsyncPanZoom)
2148 *useAsyncPanZoom = UseAsyncPanZoom();
2149 return NS_OK;
2152 NS_IMETHODIMP
2153 TabParent::SetIsDocShellActive(bool isActive)
2155 unused << SendSetIsDocShellActive(isActive);
2156 return NS_OK;
2159 bool
2160 TabParent::RecvRemotePaintIsReady()
2162 nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryInterface(mFrameElement);
2163 if (!target) {
2164 NS_WARNING("Could not locate target for MozAfterRemotePaint message.");
2165 return true;
2168 nsCOMPtr<nsIDOMEvent> event;
2169 NS_NewDOMEvent(getter_AddRefs(event), mFrameElement, nullptr, nullptr);
2170 event->InitEvent(NS_LITERAL_STRING("MozAfterRemotePaint"), false, false);
2171 event->SetTrusted(true);
2172 event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
2173 bool dummy;
2174 mFrameElement->DispatchEvent(event, &dummy);
2175 return true;
2178 class FakeChannel MOZ_FINAL : public nsIChannel,
2179 public nsIAuthPromptCallback,
2180 public nsIInterfaceRequestor,
2181 public nsILoadContext
2183 public:
2184 FakeChannel(const nsCString& aUri, uint64_t aCallbackId, Element* aElement)
2185 : mCallbackId(aCallbackId)
2186 , mElement(aElement)
2188 NS_NewURI(getter_AddRefs(mUri), aUri);
2191 NS_DECL_ISUPPORTS
2192 #define NO_IMPL { return NS_ERROR_NOT_IMPLEMENTED; }
2193 NS_IMETHOD GetName(nsACString&) NO_IMPL
2194 NS_IMETHOD IsPending(bool*) NO_IMPL
2195 NS_IMETHOD GetStatus(nsresult*) NO_IMPL
2196 NS_IMETHOD Cancel(nsresult) NO_IMPL
2197 NS_IMETHOD Suspend() NO_IMPL
2198 NS_IMETHOD Resume() NO_IMPL
2199 NS_IMETHOD GetLoadGroup(nsILoadGroup**) NO_IMPL
2200 NS_IMETHOD SetLoadGroup(nsILoadGroup*) NO_IMPL
2201 NS_IMETHOD SetLoadFlags(nsLoadFlags) NO_IMPL
2202 NS_IMETHOD GetLoadFlags(nsLoadFlags*) NO_IMPL
2203 NS_IMETHOD GetOriginalURI(nsIURI**) NO_IMPL
2204 NS_IMETHOD SetOriginalURI(nsIURI*) NO_IMPL
2205 NS_IMETHOD GetURI(nsIURI** aUri)
2207 NS_IF_ADDREF(mUri);
2208 *aUri = mUri;
2209 return NS_OK;
2211 NS_IMETHOD GetOwner(nsISupports**) NO_IMPL
2212 NS_IMETHOD SetOwner(nsISupports*) NO_IMPL
2213 NS_IMETHOD GetLoadInfo(nsILoadInfo** aLoadInfo)
2215 NS_IF_ADDREF(*aLoadInfo = mLoadInfo);
2216 return NS_OK;
2218 NS_IMETHOD SetLoadInfo(nsILoadInfo* aLoadInfo)
2220 mLoadInfo = aLoadInfo;
2221 return NS_OK;
2223 NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor** aRequestor)
2225 NS_ADDREF(*aRequestor = this);
2226 return NS_OK;
2228 NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor*) NO_IMPL
2229 NS_IMETHOD GetSecurityInfo(nsISupports**) NO_IMPL
2230 NS_IMETHOD GetContentType(nsACString&) NO_IMPL
2231 NS_IMETHOD SetContentType(const nsACString&) NO_IMPL
2232 NS_IMETHOD GetContentCharset(nsACString&) NO_IMPL
2233 NS_IMETHOD SetContentCharset(const nsACString&) NO_IMPL
2234 NS_IMETHOD GetContentLength(int64_t*) NO_IMPL
2235 NS_IMETHOD SetContentLength(int64_t) NO_IMPL
2236 NS_IMETHOD Open(nsIInputStream**) NO_IMPL
2237 NS_IMETHOD AsyncOpen(nsIStreamListener*, nsISupports*) NO_IMPL
2238 NS_IMETHOD GetContentDisposition(uint32_t*) NO_IMPL
2239 NS_IMETHOD SetContentDisposition(uint32_t) NO_IMPL
2240 NS_IMETHOD GetContentDispositionFilename(nsAString&) NO_IMPL
2241 NS_IMETHOD SetContentDispositionFilename(const nsAString&) NO_IMPL
2242 NS_IMETHOD GetContentDispositionHeader(nsACString&) NO_IMPL
2243 NS_IMETHOD OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo);
2244 NS_IMETHOD OnAuthCancelled(nsISupports *aContext, bool userCancel);
2245 NS_IMETHOD GetInterface(const nsIID & uuid, void **result)
2247 return QueryInterface(uuid, result);
2249 NS_IMETHOD GetAssociatedWindow(nsIDOMWindow**) NO_IMPL
2250 NS_IMETHOD GetTopWindow(nsIDOMWindow**) NO_IMPL
2251 NS_IMETHOD GetTopFrameElement(nsIDOMElement** aElement)
2253 nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(mElement);
2254 elem.forget(aElement);
2255 return NS_OK;
2257 NS_IMETHOD GetNestedFrameId(uint64_t*) NO_IMPL
2258 NS_IMETHOD IsAppOfType(uint32_t, bool*) NO_IMPL
2259 NS_IMETHOD GetIsContent(bool*) NO_IMPL
2260 NS_IMETHOD GetUsePrivateBrowsing(bool*) NO_IMPL
2261 NS_IMETHOD SetUsePrivateBrowsing(bool) NO_IMPL
2262 NS_IMETHOD SetPrivateBrowsing(bool) NO_IMPL
2263 NS_IMETHOD GetIsInBrowserElement(bool*) NO_IMPL
2264 NS_IMETHOD GetAppId(uint32_t*) NO_IMPL
2265 NS_IMETHOD GetUseRemoteTabs(bool*) NO_IMPL
2266 NS_IMETHOD SetRemoteTabs(bool) NO_IMPL
2267 #undef NO_IMPL
2269 protected:
2270 ~FakeChannel() {}
2272 nsCOMPtr<nsIURI> mUri;
2273 uint64_t mCallbackId;
2274 nsCOMPtr<Element> mElement;
2275 nsCOMPtr<nsILoadInfo> mLoadInfo;
2278 NS_IMPL_ISUPPORTS(FakeChannel, nsIChannel, nsIAuthPromptCallback,
2279 nsIRequest, nsIInterfaceRequestor, nsILoadContext);
2281 bool
2282 TabParent::RecvAsyncAuthPrompt(const nsCString& aUri,
2283 const nsString& aRealm,
2284 const uint64_t& aCallbackId)
2286 nsCOMPtr<nsIAuthPrompt2> authPrompt;
2287 GetAuthPrompt(nsIAuthPromptProvider::PROMPT_NORMAL,
2288 NS_GET_IID(nsIAuthPrompt2),
2289 getter_AddRefs(authPrompt));
2290 nsRefPtr<FakeChannel> channel = new FakeChannel(aUri, aCallbackId, mFrameElement);
2291 uint32_t promptFlags = nsIAuthInformation::AUTH_HOST;
2293 nsRefPtr<nsAuthInformationHolder> holder =
2294 new nsAuthInformationHolder(promptFlags, aRealm,
2295 EmptyCString());
2297 uint32_t level = nsIAuthPrompt2::LEVEL_NONE;
2298 nsCOMPtr<nsICancelable> dummy;
2299 nsresult rv =
2300 authPrompt->AsyncPromptAuth(channel, channel, nullptr,
2301 level, holder, getter_AddRefs(dummy));
2303 return rv == NS_OK;
2306 NS_IMETHODIMP
2307 FakeChannel::OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo)
2309 nsAuthInformationHolder* holder =
2310 static_cast<nsAuthInformationHolder*>(aAuthInfo);
2312 if (!net::gNeckoChild->SendOnAuthAvailable(mCallbackId,
2313 holder->User(),
2314 holder->Password(),
2315 holder->Domain())) {
2316 return NS_ERROR_FAILURE;
2318 return NS_OK;
2321 NS_IMETHODIMP
2322 FakeChannel::OnAuthCancelled(nsISupports *aContext, bool userCancel)
2324 if (!net::gNeckoChild->SendOnAuthCancelled(mCallbackId, userCancel)) {
2325 return NS_ERROR_FAILURE;
2327 return NS_OK;
2331 } // namespace tabs
2332 } // namespace mozilla