/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "base/basictypes.h" #include "BrowserChild.h" #ifdef ACCESSIBILITY # include "mozilla/a11y/DocAccessibleChild.h" #endif #include "Layers.h" #include "ContentChild.h" #include "BrowserParent.h" #include "js/JSON.h" #include "mozilla/Preferences.h" #include "mozilla/BrowserElementParent.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/EventListenerManager.h" #include "mozilla/dom/DataTransfer.h" #include "mozilla/dom/Event.h" #include "mozilla/dom/LoadURIOptionsBinding.h" #include "mozilla/dom/MessageManagerBinding.h" #include "mozilla/dom/MouseEventBinding.h" #include "mozilla/dom/Nullable.h" #include "mozilla/dom/PaymentRequestChild.h" #include "mozilla/dom/PBrowser.h" #include "mozilla/dom/WindowProxyHolder.h" #include "mozilla/dom/BrowserBridgeChild.h" #include "mozilla/dom/SessionStoreListener.h" #include "mozilla/gfx/CrossProcessPaint.h" #include "mozilla/gfx/gfxVars.h" #include "mozilla/IMEStateManager.h" #include "mozilla/ipc/BackgroundUtils.h" #include "mozilla/ipc/URIUtils.h" #include "mozilla/layers/APZChild.h" #include "mozilla/layers/APZCCallbackHelper.h" #include "mozilla/layers/APZCTreeManagerChild.h" #include "mozilla/layers/APZEventState.h" #include "mozilla/layers/ContentProcessController.h" #include "mozilla/layers/CompositorBridgeChild.h" #include "mozilla/layers/DoubleTapToZoom.h" #include "mozilla/layers/IAPZCTreeManager.h" #include "mozilla/layers/ImageBridgeChild.h" #include "mozilla/layers/InputAPZContext.h" #include "mozilla/layers/LayerTransactionChild.h" #include "mozilla/layers/ShadowLayers.h" #include "mozilla/layers/WebRenderLayerManager.h" #include "mozilla/plugins/PPluginWidgetChild.h" #include "mozilla/recordreplay/ParentIPC.h" #include "mozilla/LookAndFeel.h" #include "mozilla/MouseEvents.h" #include "mozilla/Move.h" #include "mozilla/PresShell.h" #include "mozilla/ProcessHangMonitor.h" #include "mozilla/ResultExtensions.h" #include "mozilla/ScopeExit.h" #include "mozilla/Services.h" #include "mozilla/StaticPtr.h" #include "mozilla/StaticPrefs_dom.h" #include "mozilla/StaticPrefs_layout.h" #include "mozilla/TextEvents.h" #include "mozilla/TouchEvents.h" #include "mozilla/Unused.h" #include "Units.h" #include "nsBrowserStatusFilter.h" #include "nsContentUtils.h" #include "nsDocShell.h" #include "nsEmbedCID.h" #include "nsGlobalWindow.h" #include #include "nsExceptionHandler.h" #include "nsFilePickerProxy.h" #include "mozilla/dom/Element.h" #include "nsGlobalWindow.h" #include "nsIBaseWindow.h" #include "nsIBrowserDOMWindow.h" #include "nsIClassifiedChannel.h" #include "DocumentInlines.h" #include "nsIDocShellTreeOwner.h" #include "nsIDOMChromeWindow.h" #include "nsIDOMWindow.h" #include "nsIDOMWindowUtils.h" #include "nsFocusManager.h" #include "EventStateManager.h" #include "nsIDocShell.h" #include "nsIFrame.h" #include "nsIURI.h" #include "nsIURIMutator.h" #include "nsIURIFixup.h" #include "nsIWebBrowser.h" #include "nsIWebProgress.h" #include "nsIXULRuntime.h" #include "nsPIDOMWindow.h" #include "nsPIWindowRoot.h" #include "nsPointerHashKeys.h" #include "nsLayoutUtils.h" #include "nsPrintfCString.h" #include "nsTHashtable.h" #include "nsThreadManager.h" #include "nsThreadUtils.h" #include "nsViewManager.h" #include "nsIWeakReferenceUtils.h" #include "nsWindowWatcher.h" #include "PermissionMessageUtils.h" #include "PuppetWidget.h" #include "StructuredCloneData.h" #include "nsViewportInfo.h" #include "nsILoadContext.h" #include "ipc/nsGUIEventIPC.h" #include "mozilla/gfx/Matrix.h" #include "UnitTransforms.h" #include "ClientLayerManager.h" #include "nsColorPickerProxy.h" #include "nsContentPermissionHelper.h" #include "nsNetUtil.h" #include "nsIPermissionManager.h" #include "nsIURILoader.h" #include "nsIScriptError.h" #include "mozilla/EventForwards.h" #include "nsDeviceContext.h" #include "nsSandboxFlags.h" #include "FrameLayerBuilder.h" #include "VRManagerChild.h" #include "nsCommandParams.h" #include "nsISHEntry.h" #include "nsISHistory.h" #include "nsQueryObject.h" #include "nsIHttpChannel.h" #include "mozilla/dom/DocGroup.h" #include "nsString.h" #include "nsISupportsPrimitives.h" #include "mozilla/Telemetry.h" #include "nsDocShellLoadState.h" #include "nsWebBrowser.h" #include "mozilla/dom/WindowGlobalChild.h" #include "MMPrinter.h" #include "mozilla/ResultExtensions.h" #ifdef XP_WIN # include "mozilla/plugins/PluginWidgetChild.h" #endif #ifdef NS_PRINTING # include "nsIPrintSession.h" # include "nsIPrintSettings.h" # include "nsIPrintSettingsService.h" # include "nsIWebBrowserPrint.h" #endif #define BROWSER_ELEMENT_CHILD_SCRIPT \ NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js") #define TABC_LOG(...) // #define TABC_LOG(...) printf_stderr("TABC: " __VA_ARGS__) using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::dom::ipc; using namespace mozilla::ipc; using namespace mozilla::layers; using namespace mozilla::layout; using namespace mozilla::docshell; using namespace mozilla::widget; using namespace mozilla::jsipc; using mozilla::layers::GeckoContentController; NS_IMPL_ISUPPORTS(ContentListener, nsIDOMEventListener) static const char BEFORE_FIRST_PAINT[] = "before-first-paint"; nsTHashtable>* BrowserChild::sVisibleTabs; typedef nsDataHashtable BrowserChildMap; static BrowserChildMap* sBrowserChildren; StaticMutex sBrowserChildrenMutex; already_AddRefed BrowserChild::GetTopLevelDocument() const { nsCOMPtr doc; WebNavigation()->GetDocument(getter_AddRefs(doc)); return doc.forget(); } PresShell* BrowserChild::GetTopLevelPresShell() const { if (RefPtr doc = GetTopLevelDocument()) { return doc->GetPresShell(); } return nullptr; } void BrowserChild::DispatchMessageManagerMessage(const nsAString& aMessageName, const nsAString& aJSONData) { AutoSafeJSContext cx; JS::Rooted json(cx, JS::NullValue()); dom::ipc::StructuredCloneData data; if (JS_ParseJSON(cx, static_cast(aJSONData.BeginReading()), aJSONData.Length(), &json)) { ErrorResult rv; data.Write(cx, json, rv); if (NS_WARN_IF(rv.Failed())) { rv.SuppressException(); return; } } RefPtr kungFuDeathGrip( mBrowserChildMessageManager); RefPtr mm = kungFuDeathGrip->GetMessageManager(); mm->ReceiveMessage(static_cast(kungFuDeathGrip), nullptr, aMessageName, false, &data, nullptr, nullptr, nullptr, IgnoreErrors()); } bool BrowserChild::UpdateFrame(const RepaintRequest& aRequest) { MOZ_ASSERT(aRequest.GetScrollId() != ScrollableLayerGuid::NULL_SCROLL_ID); if (aRequest.IsRootContent()) { if (PresShell* presShell = GetTopLevelPresShell()) { // Guard against stale updates (updates meant for a pres shell which // has since been torn down and destroyed). if (aRequest.GetPresShellId() == presShell->GetPresShellId()) { ProcessUpdateFrame(aRequest); return true; } } } else { // aRequest.mIsRoot is false, so we are trying to update a subframe. // This requires special handling. APZCCallbackHelper::UpdateSubFrame(aRequest); return true; } return true; } void BrowserChild::ProcessUpdateFrame(const RepaintRequest& aRequest) { if (!mBrowserChildMessageManager) { return; } APZCCallbackHelper::UpdateRootFrame(aRequest); } NS_IMETHODIMP ContentListener::HandleEvent(Event* aEvent) { RemoteDOMEvent remoteEvent; remoteEvent.mEvent = aEvent; NS_ENSURE_STATE(remoteEvent.mEvent); mBrowserChild->SendEvent(remoteEvent); return NS_OK; } class BrowserChild::DelayedDeleteRunnable final : public Runnable, public nsIRunnablePriority { RefPtr mBrowserChild; // In order to ensure that this runnable runs after everything that could // possibly touch this tab, we send it through the event queue twice. The // first time it runs at normal priority and the second time it runs at // input priority. This ensures that it runs after all events that were in // either queue at the time it was first dispatched. mReadyToDelete starts // out false (when it runs at normal priority) and is then set to true. bool mReadyToDelete = false; public: explicit DelayedDeleteRunnable(BrowserChild* aBrowserChild) : Runnable("BrowserChild::DelayedDeleteRunnable"), mBrowserChild(aBrowserChild) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aBrowserChild); } NS_DECL_ISUPPORTS_INHERITED private: ~DelayedDeleteRunnable() { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!mBrowserChild); } NS_IMETHOD GetPriority(uint32_t* aPriority) override { *aPriority = mReadyToDelete ? nsIRunnablePriority::PRIORITY_INPUT : nsIRunnablePriority::PRIORITY_NORMAL; return NS_OK; } NS_IMETHOD Run() override { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mBrowserChild); if (!mReadyToDelete) { // This time run this runnable at input priority. mReadyToDelete = true; MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(this)); return NS_OK; } // Check in case ActorDestroy was called after RecvDestroy message. // Middleman processes with their own recording child process avoid // sending a delete message, so that the parent process does not // receive two deletes for the same actor. if (mBrowserChild->IPCOpen() && !recordreplay::parent::IsMiddlemanWithRecordingChild()) { Unused << PBrowserChild::Send__delete__(mBrowserChild); } mBrowserChild = nullptr; return NS_OK; } }; NS_IMPL_ISUPPORTS_INHERITED(BrowserChild::DelayedDeleteRunnable, Runnable, nsIRunnablePriority) namespace { std::map>& NestedBrowserChildMap() { MOZ_ASSERT(NS_IsMainThread()); static std::map> sNestedBrowserChildMap; return sNestedBrowserChildMap; } } // namespace already_AddRefed BrowserChild::FindBrowserChild( const TabId& aTabId) { auto iter = NestedBrowserChildMap().find(aTabId); if (iter == NestedBrowserChildMap().end()) { return nullptr; } RefPtr browserChild = iter->second; return browserChild.forget(); } /*static*/ already_AddRefed BrowserChild::Create( ContentChild* aManager, const TabId& aTabId, const TabId& aSameTabGroupAs, const TabContext& aContext, BrowsingContext* aBrowsingContext, uint32_t aChromeFlags, bool aIsTopLevel) { RefPtr groupChild = FindBrowserChild(aSameTabGroupAs); dom::TabGroup* group = groupChild ? groupChild->TabGroup() : nullptr; RefPtr iframe = new BrowserChild(aManager, aTabId, group, aContext, aBrowsingContext, aChromeFlags, aIsTopLevel); return iframe.forget(); } BrowserChild::BrowserChild(ContentChild* aManager, const TabId& aTabId, dom::TabGroup* aTabGroup, const TabContext& aContext, BrowsingContext* aBrowsingContext, uint32_t aChromeFlags, bool aIsTopLevel) : TabContext(aContext), mBrowserChildMessageManager(nullptr), mTabGroup(aTabGroup), mManager(aManager), mBrowsingContext(aBrowsingContext), mChromeFlags(aChromeFlags), mMaxTouchPoints(0), mLayersId{0}, mEffectsInfo{EffectsInfo::FullyHidden()}, mDidFakeShow(false), mNotified(false), mTriedBrowserInit(false), mOrientation(hal::eScreenOrientation_PortraitPrimary), mIgnoreKeyPressEvent(false), mHasValidInnerSize(false), mDestroyed(false), mUniqueId(aTabId), mIsTopLevel(aIsTopLevel), mHasSiblings(false), mIsTransparent(false), mIPCOpen(false), mParentIsActive(false), mDidSetRealShowInfo(false), mDidLoadURLInit(false), mAwaitingLA(false), mSkipKeyPress(false), mLayersObserverEpoch{1}, #if defined(XP_WIN) && defined(ACCESSIBILITY) mNativeWindowHandle(0), #endif #if defined(ACCESSIBILITY) mTopLevelDocAccessibleChild(nullptr), #endif mShouldSendWebProgressEventsToParent(false), mRenderLayers(true), mPendingDocShellIsActive(false), mPendingDocShellReceivedMessage(false), mPendingRenderLayers(false), mPendingRenderLayersReceivedMessage(false), mPendingLayersObserverEpoch{0}, mPendingDocShellBlockers(0), mCancelContentJSEpoch(0), mWidgetNativeData(0) { mozilla::HoldJSObjects(this); nsWeakPtr weakPtrThis(do_GetWeakReference( static_cast(this))); // for capture by the lambda mSetAllowedTouchBehaviorCallback = [weakPtrThis](uint64_t aInputBlockId, const nsTArray& aFlags) { if (nsCOMPtr browserChild = do_QueryReferent(weakPtrThis)) { static_cast(browserChild.get()) ->SetAllowedTouchBehavior(aInputBlockId, aFlags); } }; // preloaded BrowserChild should not be added to child map if (mUniqueId) { MOZ_ASSERT(NestedBrowserChildMap().find(mUniqueId) == NestedBrowserChildMap().end()); NestedBrowserChildMap()[mUniqueId] = this; } mCoalesceMouseMoveEvents = Preferences::GetBool("dom.event.coalesce_mouse_move"); if (mCoalesceMouseMoveEvents) { mCoalescedMouseEventFlusher = new CoalescedMouseMoveFlusher(this); } } const CompositorOptions& BrowserChild::GetCompositorOptions() const { // If you're calling this before mCompositorOptions is set, well.. don't. MOZ_ASSERT(mCompositorOptions); return mCompositorOptions.ref(); } bool BrowserChild::AsyncPanZoomEnabled() const { // This might get called by the TouchEvent::PrefEnabled code before we have // mCompositorOptions populated (bug 1370089). In that case we just assume // APZ is enabled because we're in a content process (because BrowserChild) // and APZ is probably going to be enabled here since e10s is enabled. return mCompositorOptions ? mCompositorOptions->UseAPZ() : true; } NS_IMETHODIMP BrowserChild::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) { if (!strcmp(aTopic, BEFORE_FIRST_PAINT)) { if (AsyncPanZoomEnabled()) { nsCOMPtr subject(do_QueryInterface(aSubject)); nsCOMPtr doc(GetTopLevelDocument()); if (subject == doc && doc->IsTopLevelContentDocument()) { RefPtr presShell = doc->GetPresShell(); if (presShell) { presShell->SetIsFirstPaint(true); } APZCCallbackHelper::InitializeRootDisplayport(presShell); } } } return NS_OK; } void BrowserChild::ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefault) const { if (mApzcTreeManager) { mApzcTreeManager->ContentReceivedInputBlock(aInputBlockId, aPreventDefault); } } void BrowserChild::SetTargetAPZC( uint64_t aInputBlockId, const nsTArray& aTargets) const { if (mApzcTreeManager) { mApzcTreeManager->SetTargetAPZC(aInputBlockId, aTargets); } } void BrowserChild::SetAllowedTouchBehavior( uint64_t aInputBlockId, const nsTArray& aTargets) const { if (mApzcTreeManager) { mApzcTreeManager->SetAllowedTouchBehavior(aInputBlockId, aTargets); } } bool BrowserChild::DoUpdateZoomConstraints( const uint32_t& aPresShellId, const ViewID& aViewId, const Maybe& aConstraints) { if (!mApzcTreeManager || mDestroyed) { return false; } SLGuidAndRenderRoot guid = SLGuidAndRenderRoot( mLayersId, aPresShellId, aViewId, gfxUtils::GetContentRenderRoot()); mApzcTreeManager->UpdateZoomConstraints(guid, aConstraints); return true; } nsresult BrowserChild::Init(mozIDOMWindowProxy* aParent) { MOZ_DIAGNOSTIC_ASSERT(mTabGroup); nsCOMPtr widget = nsIWidget::CreatePuppetWidget(this); mPuppetWidget = static_cast(widget.get()); if (!mPuppetWidget) { NS_ERROR("couldn't create fake widget"); return NS_ERROR_FAILURE; } mPuppetWidget->InfallibleCreate(nullptr, nullptr, // no parents LayoutDeviceIntRect(0, 0, 0, 0), nullptr // HandleWidgetEvent ); mWebBrowser = nsWebBrowser::Create(this, mPuppetWidget, OriginAttributesRef(), mBrowsingContext); nsIWebBrowser* webBrowser = mWebBrowser; mWebNav = do_QueryInterface(webBrowser); NS_ASSERTION(mWebNav, "nsWebBrowser doesn't implement nsIWebNavigation?"); // Set the tab context attributes then pass to docShell NotifyTabContextUpdated(false); // IPC uses a WebBrowser object for which DNS prefetching is turned off // by default. But here we really want it, so enable it explicitly mWebBrowser->SetAllowDNSPrefetch(true); nsCOMPtr docShell = do_GetInterface(WebNavigation()); MOZ_ASSERT(docShell); const uint32_t notifyMask = nsIWebProgress::NOTIFY_STATE_ALL | nsIWebProgress::NOTIFY_PROGRESS | nsIWebProgress::NOTIFY_STATUS | nsIWebProgress::NOTIFY_LOCATION | nsIWebProgress::NOTIFY_REFRESH | nsIWebProgress::NOTIFY_CONTENT_BLOCKING; mStatusFilter = new nsBrowserStatusFilter(); RefPtr eventTarget = TabGroup()->EventTargetFor(TaskCategory::Network); mStatusFilter->SetTarget(eventTarget); nsresult rv = mStatusFilter->AddProgressListener(this, notifyMask); NS_ENSURE_SUCCESS(rv, rv); { nsCOMPtr webProgress = do_QueryInterface(docShell); rv = webProgress->AddProgressListener(mStatusFilter, notifyMask); NS_ENSURE_SUCCESS(rv, rv); } docShell->SetAffectPrivateSessionLifetime( mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME); nsCOMPtr loadContext = do_GetInterface(WebNavigation()); MOZ_ASSERT(loadContext); loadContext->SetPrivateBrowsing(OriginAttributesRef().mPrivateBrowsingId > 0); loadContext->SetRemoteTabs(mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW); loadContext->SetRemoteSubframes(mChromeFlags & nsIWebBrowserChrome::CHROME_FISSION_WINDOW); // Few lines before, baseWindow->Create() will end up creating a new // window root in nsGlobalWindow::SetDocShell. // Then this chrome event handler, will be inherited to inner windows. // We want to also set it to the docshell so that inner windows // and any code that has access to the docshell // can all listen to the same chrome event handler. // XXX: ideally, we would set a chrome event handler earlier, // and all windows, even the root one, will use the docshell one. nsCOMPtr window = do_GetInterface(WebNavigation()); NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); nsCOMPtr chromeHandler = window->GetChromeEventHandler(); docShell->SetChromeEventHandler(chromeHandler); if (window->GetCurrentInnerWindow()) { window->SetKeyboardIndicators(ShowFocusRings()); } else { // Skip ShouldShowFocusRing check if no inner window is available window->SetInitialKeyboardIndicators(ShowFocusRings()); } nsContentUtils::SetScrollbarsVisibility( window->GetDocShell(), !!(mChromeFlags & nsIWebBrowserChrome::CHROME_SCROLLBARS)); nsWeakPtr weakPtrThis = do_GetWeakReference( static_cast(this)); // for capture by the lambda ContentReceivedInputBlockCallback callback( [weakPtrThis](uint64_t aInputBlockId, bool aPreventDefault) { if (nsCOMPtr browserChild = do_QueryReferent(weakPtrThis)) { static_cast(browserChild.get()) ->ContentReceivedInputBlock(aInputBlockId, aPreventDefault); } }); mAPZEventState = new APZEventState(mPuppetWidget, std::move(callback)); mIPCOpen = true; // Recording/replaying processes use their own compositor. if (recordreplay::IsRecordingOrReplaying()) { mPuppetWidget->CreateCompositor(); } #if !defined(MOZ_WIDGET_ANDROID) mSessionStoreListener = new TabListener(docShell, nullptr); rv = mSessionStoreListener->Init(); NS_ENSURE_SUCCESS(rv, rv); #endif return NS_OK; } void BrowserChild::NotifyTabContextUpdated(bool aIsPreallocated) { nsCOMPtr docShell = do_GetInterface(WebNavigation()); MOZ_ASSERT(docShell); if (!docShell) { return; } UpdateFrameType(); if (aIsPreallocated) { nsDocShell::Cast(docShell)->SetOriginAttributes(OriginAttributesRef()); } // Set SANDBOXED_AUXILIARY_NAVIGATION flag if this is a receiver page. if (!PresentationURL().IsEmpty()) { docShell->SetSandboxFlags(SANDBOXED_AUXILIARY_NAVIGATION); } } void BrowserChild::UpdateFrameType() { nsCOMPtr docShell = do_GetInterface(WebNavigation()); MOZ_ASSERT(docShell); // TODO: Bug 1252794 - remove frameType from nsIDocShell.idl docShell->SetFrameType(IsMozBrowserElement() ? nsIDocShell::FRAME_TYPE_BROWSER : nsIDocShell::FRAME_TYPE_REGULAR); } NS_IMPL_CYCLE_COLLECTION_CLASS(BrowserChild) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowserChild) NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserChildMessageManager) tmp->nsMessageManagerScriptExecutor::Unlink(); NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebBrowserChrome) NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusFilter) NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebNav) NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowserChild) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserChildMessageManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebBrowserChrome) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusFilter) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebNav) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(BrowserChild) tmp->nsMessageManagerScriptExecutor::Trace(aCallbacks, aClosure); NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserChild) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2) NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus) NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_INTERFACE_MAP_ENTRY(nsIWindowProvider) NS_INTERFACE_MAP_ENTRY(nsIBrowserChild) NS_INTERFACE_MAP_ENTRY(nsIObserver) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_ENTRY(nsITooltipListener) NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBrowserChild) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(BrowserChild) NS_IMPL_CYCLE_COLLECTING_RELEASE(BrowserChild) NS_IMETHODIMP BrowserChild::SetStatus(uint32_t aStatusType, const char16_t* aStatus) { return SetStatusWithContext( aStatusType, aStatus ? static_cast(nsDependentString(aStatus)) : EmptyString(), nullptr); } NS_IMETHODIMP BrowserChild::GetChromeFlags(uint32_t* aChromeFlags) { *aChromeFlags = mChromeFlags; return NS_OK; } NS_IMETHODIMP BrowserChild::SetChromeFlags(uint32_t aChromeFlags) { NS_WARNING("trying to SetChromeFlags from content process?"); return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP BrowserChild::RemoteSizeShellTo(int32_t aWidth, int32_t aHeight, int32_t aShellItemWidth, int32_t aShellItemHeight) { nsCOMPtr ourDocShell = do_GetInterface(WebNavigation()); nsCOMPtr docShellAsWin(do_QueryInterface(ourDocShell)); NS_ENSURE_STATE(docShellAsWin); int32_t width, height; docShellAsWin->GetSize(&width, &height); uint32_t flags = 0; if (width == aWidth) { flags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX; } if (height == aHeight) { flags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY; } bool sent = SendSizeShellTo(flags, aWidth, aHeight, aShellItemWidth, aShellItemHeight); return sent ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP BrowserChild::RemoteDropLinks( const nsTArray>& aLinks) { nsTArray linksArray; nsresult rv = NS_OK; for (nsIDroppedLinkItem* link : aLinks) { nsString tmp; rv = link->GetUrl(tmp); if (NS_FAILED(rv)) { return rv; } linksArray.AppendElement(tmp); rv = link->GetName(tmp); if (NS_FAILED(rv)) { return rv; } linksArray.AppendElement(tmp); rv = link->GetType(tmp); if (NS_FAILED(rv)) { return rv; } linksArray.AppendElement(tmp); } bool sent = SendDropLinks(linksArray); return sent ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP BrowserChild::ShowAsModal() { NS_WARNING("BrowserChild::ShowAsModal not supported in BrowserChild"); return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP BrowserChild::IsWindowModal(bool* aRetVal) { *aRetVal = false; return NS_OK; } NS_IMETHODIMP BrowserChild::SetStatusWithContext(uint32_t aStatusType, const nsAString& aStatusText, nsISupports* aStatusContext) { // We can only send the status after the ipc machinery is set up if (IPCOpen()) { SendSetStatus(aStatusType, nsString(aStatusText)); } return NS_OK; } NS_IMETHODIMP BrowserChild::SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY, int32_t aCx, int32_t aCy) { // The parent is in charge of the dimension changes. If JS code wants to // change the dimensions (moveTo, screenX, etc.) we send a message to the // parent about the new requested dimension, the parent does the resize/move // then send a message to the child to update itself. For APIs like screenX // this function is called with the current value for the non-changed values. // In a series of calls like window.screenX = 10; window.screenY = 10; for // the second call, since screenX is not yet updated we might accidentally // reset back screenX to it's old value. To avoid this if a parameter did not // change we want the parent to ignore its value. int32_t x, y, cx, cy; GetDimensions(aFlags, &x, &y, &cx, &cy); if (x == aX) { aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_X; } if (y == aY) { aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_Y; } if (cx == aCx) { aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CX; } if (cy == aCy) { aFlags |= nsIEmbeddingSiteWindow::DIM_FLAGS_IGNORE_CY; } Unused << SendSetDimensions(aFlags, aX, aY, aCx, aCy); return NS_OK; } NS_IMETHODIMP BrowserChild::GetDimensions(uint32_t aFlags, int32_t* aX, int32_t* aY, int32_t* aCx, int32_t* aCy) { ScreenIntRect rect = GetOuterRect(); if (aX) { *aX = rect.x; } if (aY) { *aY = rect.y; } if (aCx) { *aCx = rect.width; } if (aCy) { *aCy = rect.height; } return NS_OK; } NS_IMETHODIMP BrowserChild::SetFocus() { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP BrowserChild::GetVisibility(bool* aVisibility) { *aVisibility = true; return NS_OK; } NS_IMETHODIMP BrowserChild::SetVisibility(bool aVisibility) { // should the platform support this? Bug 666365 return NS_OK; } NS_IMETHODIMP BrowserChild::GetTitle(nsAString& aTitle) { NS_WARNING("BrowserChild::GetTitle not supported in BrowserChild"); return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP BrowserChild::SetTitle(const nsAString& aTitle) { // JavaScript sends the "DOMTitleChanged" event to the parent // via the message manager. return NS_OK; } NS_IMETHODIMP BrowserChild::GetSiteWindow(void** aSiteWindow) { NS_WARNING("BrowserChild::GetSiteWindow not supported in BrowserChild"); return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP BrowserChild::Blur() { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP BrowserChild::FocusNextElement(bool aForDocumentNavigation) { SendMoveFocus(true, aForDocumentNavigation); return NS_OK; } NS_IMETHODIMP BrowserChild::FocusPrevElement(bool aForDocumentNavigation) { SendMoveFocus(false, aForDocumentNavigation); return NS_OK; } NS_IMETHODIMP BrowserChild::GetInterface(const nsIID& aIID, void** aSink) { if (aIID.Equals(NS_GET_IID(nsIWebBrowserChrome3))) { NS_IF_ADDREF(((nsISupports*)(*aSink = mWebBrowserChrome))); return NS_OK; } // XXXbz should we restrict the set of interfaces we hand out here? // See bug 537429 return QueryInterface(aIID, aSink); } NS_IMETHODIMP BrowserChild::ProvideWindow(mozIDOMWindowProxy* aParent, uint32_t aChromeFlags, bool aCalledFromJS, bool aPositionSpecified, bool aSizeSpecified, nsIURI* aURI, const nsAString& aName, const nsACString& aFeatures, bool aForceNoOpener, bool aForceNoReferrer, nsDocShellLoadState* aLoadState, bool* aWindowIsNew, BrowsingContext** aReturn) { *aReturn = nullptr; // If aParent is inside an