michael@0: /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */ michael@0: /* vim: set sw=2 sts=2 ts=8 et tw=80 : */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "base/basictypes.h" michael@0: michael@0: #include "TabChild.h" michael@0: michael@0: #include "Layers.h" michael@0: #include "ContentChild.h" michael@0: #include "IndexedDBChild.h" michael@0: #include "mozilla/Preferences.h" michael@0: #include "mozilla/ClearOnShutdown.h" michael@0: #include "mozilla/EventListenerManager.h" michael@0: #include "mozilla/IntentionalCrash.h" michael@0: #include "mozilla/docshell/OfflineCacheUpdateChild.h" michael@0: #include "mozilla/ipc/DocumentRendererChild.h" michael@0: #include "mozilla/ipc/FileDescriptorUtils.h" michael@0: #include "mozilla/layers/ActiveElementManager.h" michael@0: #include "mozilla/layers/APZCCallbackHelper.h" michael@0: #include "mozilla/layers/AsyncPanZoomController.h" michael@0: #include "mozilla/layers/CompositorChild.h" michael@0: #include "mozilla/layers/ImageBridgeChild.h" michael@0: #include "mozilla/layers/ShadowLayers.h" michael@0: #include "mozilla/layout/RenderFrameChild.h" michael@0: #include "mozilla/MouseEvents.h" michael@0: #include "mozilla/Services.h" michael@0: #include "mozilla/StaticPtr.h" michael@0: #include "mozilla/TextEvents.h" michael@0: #include "mozilla/TouchEvents.h" michael@0: #include "mozilla/unused.h" michael@0: #include "mozIApplication.h" michael@0: #include "nsContentUtils.h" michael@0: #include "nsCxPusher.h" michael@0: #include "nsEmbedCID.h" michael@0: #include michael@0: #ifdef MOZ_CRASHREPORTER michael@0: #include "nsExceptionHandler.h" michael@0: #endif michael@0: #include "nsFilePickerProxy.h" michael@0: #include "mozilla/dom/Element.h" michael@0: #include "nsIBaseWindow.h" michael@0: #include "nsICachedFileDescriptorListener.h" michael@0: #include "nsIDocumentInlines.h" michael@0: #include "nsIDocShellTreeOwner.h" michael@0: #include "nsIDOMEvent.h" michael@0: #include "nsIDOMWindow.h" michael@0: #include "nsIDOMWindowUtils.h" michael@0: #include "nsIDocShell.h" michael@0: #include "nsIURI.h" michael@0: #include "nsIURIFixup.h" michael@0: #include "nsCDefaultURIFixup.h" michael@0: #include "nsIWebBrowser.h" michael@0: #include "nsIWebBrowserFocus.h" michael@0: #include "nsIWebBrowserSetup.h" michael@0: #include "nsIWebProgress.h" michael@0: #include "nsIXULRuntime.h" michael@0: #include "nsInterfaceHashtable.h" michael@0: #include "nsPIDOMWindow.h" michael@0: #include "nsPIWindowRoot.h" michael@0: #include "nsLayoutUtils.h" michael@0: #include "nsPrintfCString.h" michael@0: #include "nsThreadUtils.h" michael@0: #include "nsWeakReference.h" michael@0: #include "PermissionMessageUtils.h" michael@0: #include "PCOMContentPermissionRequestChild.h" michael@0: #include "PuppetWidget.h" michael@0: #include "StructuredCloneUtils.h" michael@0: #include "nsViewportInfo.h" michael@0: #include "JavaScriptChild.h" michael@0: #include "nsILoadContext.h" michael@0: #include "ipc/nsGUIEventIPC.h" michael@0: #include "mozilla/gfx/Matrix.h" michael@0: #include "UnitTransforms.h" michael@0: #include "ClientLayerManager.h" michael@0: michael@0: #include "nsColorPickerProxy.h" michael@0: michael@0: #ifdef DEBUG michael@0: #include "PCOMContentPermissionRequestChild.h" michael@0: #endif /* DEBUG */ michael@0: michael@0: #define BROWSER_ELEMENT_CHILD_SCRIPT \ michael@0: NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js") michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::dom; michael@0: using namespace mozilla::dom::ipc; michael@0: using namespace mozilla::ipc; michael@0: using namespace mozilla::layers; michael@0: using namespace mozilla::layout; michael@0: using namespace mozilla::docshell; michael@0: using namespace mozilla::dom::indexedDB; michael@0: using namespace mozilla::widget; michael@0: using namespace mozilla::jsipc; michael@0: michael@0: NS_IMPL_ISUPPORTS(ContentListener, nsIDOMEventListener) michael@0: michael@0: static const CSSSize kDefaultViewportSize(980, 480); michael@0: michael@0: static const char BROWSER_ZOOM_TO_RECT[] = "browser-zoom-to-rect"; michael@0: static const char BEFORE_FIRST_PAINT[] = "before-first-paint"; michael@0: michael@0: static bool sCpowsEnabled = false; michael@0: static int32_t sActiveDurationMs = 10; michael@0: static bool sActiveDurationMsSet = false; michael@0: michael@0: typedef nsDataHashtable TabChildMap; michael@0: static TabChildMap* sTabChildren; michael@0: michael@0: TabChildBase::TabChildBase() michael@0: : mOldViewportWidth(0.0f) michael@0: , mContentDocumentIsDisplayed(false) michael@0: , mTabChildGlobal(nullptr) michael@0: , mInnerSize(0, 0) michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_CYCLE_COLLECTING_ADDREF(TabChildBase) michael@0: NS_IMPL_CYCLE_COLLECTING_RELEASE(TabChildBase) michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildBase) michael@0: NS_INTERFACE_MAP_ENTRY(nsISupports) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION(TabChildBase, mTabChildGlobal, mGlobal) michael@0: michael@0: void michael@0: TabChildBase::InitializeRootMetrics() michael@0: { michael@0: // Calculate a really simple resolution that we probably won't michael@0: // be keeping, as well as putting the scroll offset back to michael@0: // the top-left of the page. michael@0: mLastRootMetrics.mViewport = CSSRect(CSSPoint(), kDefaultViewportSize); michael@0: mLastRootMetrics.mCompositionBounds = ParentLayerIntRect( michael@0: ParentLayerIntPoint(), michael@0: ViewAs(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot)); michael@0: mLastRootMetrics.SetZoom(mLastRootMetrics.CalculateIntrinsicScale()); michael@0: mLastRootMetrics.mDevPixelsPerCSSPixel = WebWidget()->GetDefaultScale(); michael@0: // We use ScreenToLayerScale(1) below in order to turn the michael@0: // async zoom amount into the gecko zoom amount. michael@0: mLastRootMetrics.mCumulativeResolution = michael@0: mLastRootMetrics.GetZoom() / mLastRootMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); michael@0: // This is the root layer, so the cumulative resolution is the same michael@0: // as the resolution. michael@0: mLastRootMetrics.mResolution = mLastRootMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); michael@0: mLastRootMetrics.SetScrollOffset(CSSPoint(0, 0)); michael@0: } michael@0: michael@0: bool michael@0: TabChildBase::HasValidInnerSize() michael@0: { michael@0: return (mInnerSize.width != 0) && (mInnerSize.height != 0); michael@0: } michael@0: michael@0: void michael@0: TabChildBase::SetCSSViewport(const CSSSize& aSize) michael@0: { michael@0: mOldViewportWidth = aSize.width; michael@0: michael@0: if (mContentDocumentIsDisplayed) { michael@0: nsCOMPtr utils(GetDOMWindowUtils()); michael@0: utils->SetCSSViewport(aSize.width, aSize.height); michael@0: } michael@0: } michael@0: michael@0: CSSSize michael@0: TabChildBase::GetPageSize(nsCOMPtr aDocument, const CSSSize& aViewport) michael@0: { michael@0: nsCOMPtr htmlDOMElement = aDocument->GetHtmlElement(); michael@0: HTMLBodyElement* bodyDOMElement = aDocument->GetBodyElement(); michael@0: michael@0: if (!htmlDOMElement && !bodyDOMElement) { michael@0: // For non-HTML content (e.g. SVG), just assume page size == viewport size. michael@0: return aViewport; michael@0: } michael@0: michael@0: int32_t htmlWidth = 0, htmlHeight = 0; michael@0: if (htmlDOMElement) { michael@0: htmlWidth = htmlDOMElement->ScrollWidth(); michael@0: htmlHeight = htmlDOMElement->ScrollHeight(); michael@0: } michael@0: int32_t bodyWidth = 0, bodyHeight = 0; michael@0: if (bodyDOMElement) { michael@0: bodyWidth = bodyDOMElement->ScrollWidth(); michael@0: bodyHeight = bodyDOMElement->ScrollHeight(); michael@0: } michael@0: return CSSSize(std::max(htmlWidth, bodyWidth), michael@0: std::max(htmlHeight, bodyHeight)); michael@0: } michael@0: michael@0: bool michael@0: TabChildBase::HandlePossibleViewportChange() michael@0: { michael@0: if (!IsAsyncPanZoomEnabled()) { michael@0: return false; michael@0: } michael@0: michael@0: nsCOMPtr document(GetDocument()); michael@0: nsCOMPtr utils(GetDOMWindowUtils()); michael@0: michael@0: nsViewportInfo viewportInfo = nsContentUtils::GetViewportInfo(document, mInnerSize); michael@0: uint32_t presShellId; michael@0: mozilla::layers::FrameMetrics::ViewID viewId; michael@0: bool scrollIdentifiersValid = APZCCallbackHelper::GetScrollIdentifiers( michael@0: document->GetDocumentElement(), &presShellId, &viewId); michael@0: if (scrollIdentifiersValid) { michael@0: ZoomConstraints constraints( michael@0: viewportInfo.IsZoomAllowed(), michael@0: viewportInfo.IsDoubleTapZoomAllowed(), michael@0: viewportInfo.GetMinZoom(), michael@0: viewportInfo.GetMaxZoom()); michael@0: DoUpdateZoomConstraints(presShellId, michael@0: viewId, michael@0: /* isRoot = */ true, michael@0: constraints); michael@0: } michael@0: michael@0: float screenW = mInnerSize.width; michael@0: float screenH = mInnerSize.height; michael@0: CSSSize viewport(viewportInfo.GetSize()); michael@0: michael@0: // We're not being displayed in any way; don't bother doing anything because michael@0: // that will just confuse future adjustments. michael@0: if (!screenW || !screenH) { michael@0: return false; michael@0: } michael@0: michael@0: float oldBrowserWidth = mOldViewportWidth; michael@0: mLastRootMetrics.mViewport.SizeTo(viewport); michael@0: if (!oldBrowserWidth) { michael@0: oldBrowserWidth = kDefaultViewportSize.width; michael@0: } michael@0: SetCSSViewport(viewport); michael@0: michael@0: // If this page has not been painted yet, then this must be getting run michael@0: // because a meta-viewport element was added (via the DOMMetaAdded handler). michael@0: // in this case, we should not do anything that forces a reflow (see bug michael@0: // 759678) such as requesting the page size or sending a viewport update. this michael@0: // code will get run again in the before-first-paint handler and that point we michael@0: // will run though all of it. the reason we even bother executing up to this michael@0: // point on the DOMMetaAdded handler is so that scripts that use michael@0: // window.innerWidth before they are painted have a correct value (bug michael@0: // 771575). michael@0: if (!mContentDocumentIsDisplayed) { michael@0: return false; michael@0: } michael@0: michael@0: float oldScreenWidth = mLastRootMetrics.mCompositionBounds.width; michael@0: if (!oldScreenWidth) { michael@0: oldScreenWidth = mInnerSize.width; michael@0: } michael@0: michael@0: FrameMetrics metrics(mLastRootMetrics); michael@0: metrics.mViewport = CSSRect(CSSPoint(), viewport); michael@0: metrics.mCompositionBounds = ParentLayerIntRect( michael@0: ParentLayerIntPoint(), michael@0: ViewAs(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot)); michael@0: metrics.SetRootCompositionSize( michael@0: ScreenSize(mInnerSize) * ScreenToLayoutDeviceScale(1.0f) / metrics.mDevPixelsPerCSSPixel); michael@0: michael@0: // This change to the zoom accounts for all types of changes I can conceive: michael@0: // 1. screen size changes, CSS viewport does not (pages with no meta viewport michael@0: // or a fixed size viewport) michael@0: // 2. screen size changes, CSS viewport also does (pages with a device-width michael@0: // viewport) michael@0: // 3. screen size remains constant, but CSS viewport changes (meta viewport michael@0: // tag is added or removed) michael@0: // 4. neither screen size nor CSS viewport changes michael@0: // michael@0: // In all of these cases, we maintain how much actual content is visible michael@0: // within the screen width. Note that "actual content" may be different with michael@0: // respect to CSS pixels because of the CSS viewport size changing. michael@0: float oldIntrinsicScale = oldScreenWidth / oldBrowserWidth; michael@0: metrics.ZoomBy(metrics.CalculateIntrinsicScale().scale / oldIntrinsicScale); michael@0: michael@0: // Changing the zoom when we're not doing a first paint will get ignored michael@0: // by AsyncPanZoomController and causes a blurry flash. michael@0: bool isFirstPaint; michael@0: nsresult rv = utils->GetIsFirstPaint(&isFirstPaint); michael@0: if (NS_FAILED(rv) || isFirstPaint) { michael@0: // FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of michael@0: // 0.0 to mean "did not calculate a zoom". In that case, we default michael@0: // it to the intrinsic scale. michael@0: if (viewportInfo.GetDefaultZoom().scale < 0.01f) { michael@0: viewportInfo.SetDefaultZoom(metrics.CalculateIntrinsicScale()); michael@0: } michael@0: michael@0: CSSToScreenScale defaultZoom = viewportInfo.GetDefaultZoom(); michael@0: MOZ_ASSERT(viewportInfo.GetMinZoom() <= defaultZoom && michael@0: defaultZoom <= viewportInfo.GetMaxZoom()); michael@0: metrics.SetZoom(defaultZoom); michael@0: michael@0: metrics.SetScrollId(viewId); michael@0: } michael@0: michael@0: metrics.mCumulativeResolution = metrics.GetZoom() / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); michael@0: // This is the root layer, so the cumulative resolution is the same michael@0: // as the resolution. michael@0: metrics.mResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); michael@0: utils->SetResolution(metrics.mResolution.scale, metrics.mResolution.scale); michael@0: michael@0: CSSSize scrollPort = metrics.CalculateCompositedSizeInCssPixels(); michael@0: utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height); michael@0: michael@0: // The call to GetPageSize forces a resize event to content, so we need to michael@0: // make sure that we have the right CSS viewport and michael@0: // scrollPositionClampingScrollPortSize set up before that happens. michael@0: michael@0: CSSSize pageSize = GetPageSize(document, viewport); michael@0: if (!pageSize.width) { michael@0: // Return early rather than divide by 0. michael@0: return false; michael@0: } michael@0: metrics.mScrollableRect = CSSRect(CSSPoint(), pageSize); michael@0: michael@0: // Calculate a display port _after_ having a scrollable rect because the michael@0: // display port is clamped to the scrollable rect. michael@0: metrics.SetDisplayPortMargins(AsyncPanZoomController::CalculatePendingDisplayPort( michael@0: // The page must have been refreshed in some way such as a new document or michael@0: // new CSS viewport, so we know that there's no velocity, acceleration, and michael@0: // we have no idea how long painting will take. michael@0: metrics, ScreenPoint(0.0f, 0.0f), 0.0)); michael@0: metrics.SetUseDisplayPortMargins(); michael@0: michael@0: // Force a repaint with these metrics. This, among other things, sets the michael@0: // displayport, so we start with async painting. michael@0: mLastRootMetrics = ProcessUpdateFrame(metrics); michael@0: michael@0: if (viewportInfo.IsZoomAllowed() && scrollIdentifiersValid) { michael@0: // If the CSS viewport is narrower than the screen (i.e. width <= device-width) michael@0: // then we disable double-tap-to-zoom behaviour. michael@0: bool allowDoubleTapZoom = (viewport.width > screenW / metrics.mDevPixelsPerCSSPixel.scale); michael@0: if (allowDoubleTapZoom != viewportInfo.IsDoubleTapZoomAllowed()) { michael@0: viewportInfo.SetAllowDoubleTapZoom(allowDoubleTapZoom); michael@0: michael@0: ZoomConstraints constraints( michael@0: viewportInfo.IsZoomAllowed(), michael@0: viewportInfo.IsDoubleTapZoomAllowed(), michael@0: viewportInfo.GetMinZoom(), michael@0: viewportInfo.GetMaxZoom()); michael@0: DoUpdateZoomConstraints(presShellId, michael@0: viewId, michael@0: /* isRoot = */ true, michael@0: constraints); michael@0: } michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: already_AddRefed michael@0: TabChildBase::GetDOMWindowUtils() michael@0: { michael@0: nsCOMPtr window = do_GetInterface(WebNavigation()); michael@0: nsCOMPtr utils = do_GetInterface(window); michael@0: return utils.forget(); michael@0: } michael@0: michael@0: already_AddRefed michael@0: TabChildBase::GetDocument() michael@0: { michael@0: nsCOMPtr domDoc; michael@0: WebNavigation()->GetDocument(getter_AddRefs(domDoc)); michael@0: nsCOMPtr doc(do_QueryInterface(domDoc)); michael@0: return doc.forget(); michael@0: } michael@0: michael@0: void michael@0: TabChildBase::DispatchMessageManagerMessage(const nsAString& aMessageName, michael@0: const nsAString& aJSONData) michael@0: { michael@0: AutoSafeJSContext cx; michael@0: JS::Rooted json(cx, JSVAL_NULL); michael@0: StructuredCloneData cloneData; michael@0: JSAutoStructuredCloneBuffer buffer; michael@0: if (JS_ParseJSON(cx, michael@0: static_cast(aJSONData.BeginReading()), michael@0: aJSONData.Length(), michael@0: &json)) { michael@0: WriteStructuredClone(cx, json, buffer, cloneData.mClosure); michael@0: cloneData.mData = buffer.data(); michael@0: cloneData.mDataLength = buffer.nbytes(); michael@0: } michael@0: michael@0: nsCOMPtr kungFuDeathGrip(GetGlobal()); michael@0: // Let the BrowserElementScrolling helper (if it exists) for this michael@0: // content manipulate the frame state. michael@0: nsRefPtr mm = michael@0: static_cast(mTabChildGlobal->mMessageManager.get()); michael@0: mm->ReceiveMessage(static_cast(mTabChildGlobal), michael@0: aMessageName, false, &cloneData, nullptr, nullptr, nullptr); michael@0: } michael@0: michael@0: bool michael@0: TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics) michael@0: { michael@0: MOZ_ASSERT(aFrameMetrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID); michael@0: michael@0: if (aFrameMetrics.mIsRoot) { michael@0: nsCOMPtr utils(GetDOMWindowUtils()); michael@0: if (APZCCallbackHelper::HasValidPresShellId(utils, aFrameMetrics)) { michael@0: mLastRootMetrics = ProcessUpdateFrame(aFrameMetrics); michael@0: APZCCallbackHelper::UpdateCallbackTransform(aFrameMetrics, mLastRootMetrics); michael@0: return true; michael@0: } michael@0: } else { michael@0: // aFrameMetrics.mIsRoot is false, so we are trying to update a subframe. michael@0: // This requires special handling. michael@0: nsCOMPtr content = nsLayoutUtils::FindContentFor( michael@0: aFrameMetrics.GetScrollId()); michael@0: if (content) { michael@0: FrameMetrics newSubFrameMetrics(aFrameMetrics); michael@0: APZCCallbackHelper::UpdateSubFrame(content, newSubFrameMetrics); michael@0: APZCCallbackHelper::UpdateCallbackTransform(aFrameMetrics, newSubFrameMetrics); michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: // We've recieved a message that is out of date and we want to ignore. michael@0: // However we can't reply without painting so we reply by painting the michael@0: // exact same thing as we did before. michael@0: mLastRootMetrics = ProcessUpdateFrame(mLastRootMetrics); michael@0: return true; michael@0: } michael@0: michael@0: FrameMetrics michael@0: TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics) michael@0: { michael@0: if (!mGlobal || !mTabChildGlobal) { michael@0: return aFrameMetrics; michael@0: } michael@0: michael@0: nsCOMPtr utils(GetDOMWindowUtils()); michael@0: michael@0: FrameMetrics newMetrics = aFrameMetrics; michael@0: APZCCallbackHelper::UpdateRootFrame(utils, newMetrics); michael@0: michael@0: CSSSize cssCompositedSize = newMetrics.CalculateCompositedSizeInCssPixels(); michael@0: // The BrowserElementScrolling helper must know about these updated metrics michael@0: // for other functions it performs, such as double tap handling. michael@0: // Note, %f must not be used because it is locale specific! michael@0: nsString data; michael@0: data.AppendPrintf("{ \"x\" : %d", NS_lround(newMetrics.GetScrollOffset().x)); michael@0: data.AppendPrintf(", \"y\" : %d", NS_lround(newMetrics.GetScrollOffset().y)); michael@0: data.AppendLiteral(", \"viewport\" : "); michael@0: data.AppendLiteral("{ \"width\" : "); michael@0: data.AppendFloat(newMetrics.mViewport.width); michael@0: data.AppendLiteral(", \"height\" : "); michael@0: data.AppendFloat(newMetrics.mViewport.height); michael@0: data.AppendLiteral(" }"); michael@0: data.AppendLiteral(", \"cssPageRect\" : "); michael@0: data.AppendLiteral("{ \"x\" : "); michael@0: data.AppendFloat(newMetrics.mScrollableRect.x); michael@0: data.AppendLiteral(", \"y\" : "); michael@0: data.AppendFloat(newMetrics.mScrollableRect.y); michael@0: data.AppendLiteral(", \"width\" : "); michael@0: data.AppendFloat(newMetrics.mScrollableRect.width); michael@0: data.AppendLiteral(", \"height\" : "); michael@0: data.AppendFloat(newMetrics.mScrollableRect.height); michael@0: data.AppendLiteral(" }"); michael@0: data.AppendPrintf(", \"resolution\" : "); // TODO: check if it's actually used? michael@0: data.AppendPrintf("{ \"width\" : "); michael@0: data.AppendFloat(newMetrics.CalculateIntrinsicScale().scale); michael@0: data.AppendPrintf(" }"); michael@0: data.AppendLiteral(", \"cssCompositedRect\" : "); michael@0: data.AppendLiteral("{ \"width\" : "); michael@0: data.AppendFloat(cssCompositedSize.width); michael@0: data.AppendLiteral(", \"height\" : "); michael@0: data.AppendFloat(cssCompositedSize.height); michael@0: data.AppendLiteral(" }"); michael@0: data.AppendLiteral(" }"); michael@0: michael@0: DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data); michael@0: return newMetrics; michael@0: } michael@0: michael@0: nsEventStatus michael@0: TabChildBase::DispatchSynthesizedMouseEvent(uint32_t aMsg, uint64_t aTime, michael@0: const LayoutDevicePoint& aRefPoint, michael@0: nsIWidget* aWidget) michael@0: { michael@0: MOZ_ASSERT(aMsg == NS_MOUSE_MOVE || aMsg == NS_MOUSE_BUTTON_DOWN || michael@0: aMsg == NS_MOUSE_BUTTON_UP); michael@0: michael@0: WidgetMouseEvent event(true, aMsg, nullptr, michael@0: WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal); michael@0: event.refPoint = LayoutDeviceIntPoint(aRefPoint.x, aRefPoint.y); michael@0: event.time = aTime; michael@0: event.button = WidgetMouseEvent::eLeftButton; michael@0: event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH; michael@0: if (aMsg != NS_MOUSE_MOVE) { michael@0: event.clickCount = 1; michael@0: } michael@0: event.widget = aWidget; michael@0: michael@0: return DispatchWidgetEvent(event); michael@0: } michael@0: michael@0: nsEventStatus michael@0: TabChildBase::DispatchWidgetEvent(WidgetGUIEvent& event) michael@0: { michael@0: if (!event.widget) michael@0: return nsEventStatus_eConsumeNoDefault; michael@0: michael@0: nsEventStatus status; michael@0: NS_ENSURE_SUCCESS(event.widget->DispatchEvent(&event, status), michael@0: nsEventStatus_eConsumeNoDefault); michael@0: return status; michael@0: } michael@0: michael@0: bool michael@0: TabChildBase::IsAsyncPanZoomEnabled() michael@0: { michael@0: return mScrolling == ASYNC_PAN_ZOOM; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: ContentListener::HandleEvent(nsIDOMEvent* aEvent) michael@0: { michael@0: RemoteDOMEvent remoteEvent; michael@0: remoteEvent.mEvent = do_QueryInterface(aEvent); michael@0: NS_ENSURE_STATE(remoteEvent.mEvent); michael@0: mTabChild->SendEvent(remoteEvent); michael@0: return NS_OK; michael@0: } michael@0: michael@0: class TabChild::CachedFileDescriptorInfo michael@0: { michael@0: struct PathOnlyComparatorHelper michael@0: { michael@0: bool Equals(const nsAutoPtr& a, michael@0: const CachedFileDescriptorInfo& b) const michael@0: { michael@0: return a->mPath == b.mPath; michael@0: } michael@0: }; michael@0: michael@0: struct PathAndCallbackComparatorHelper michael@0: { michael@0: bool Equals(const nsAutoPtr& a, michael@0: const CachedFileDescriptorInfo& b) const michael@0: { michael@0: return a->mPath == b.mPath && michael@0: a->mCallback == b.mCallback; michael@0: } michael@0: }; michael@0: michael@0: public: michael@0: nsString mPath; michael@0: FileDescriptor mFileDescriptor; michael@0: nsCOMPtr mCallback; michael@0: bool mCanceled; michael@0: michael@0: CachedFileDescriptorInfo(const nsAString& aPath) michael@0: : mPath(aPath), mCanceled(false) michael@0: { } michael@0: michael@0: CachedFileDescriptorInfo(const nsAString& aPath, michael@0: const FileDescriptor& aFileDescriptor) michael@0: : mPath(aPath), mFileDescriptor(aFileDescriptor), mCanceled(false) michael@0: { } michael@0: michael@0: CachedFileDescriptorInfo(const nsAString& aPath, michael@0: nsICachedFileDescriptorListener* aCallback) michael@0: : mPath(aPath), mCallback(aCallback), mCanceled(false) michael@0: { } michael@0: michael@0: PathOnlyComparatorHelper PathOnlyComparator() const michael@0: { michael@0: return PathOnlyComparatorHelper(); michael@0: } michael@0: michael@0: PathAndCallbackComparatorHelper PathAndCallbackComparator() const michael@0: { michael@0: return PathAndCallbackComparatorHelper(); michael@0: } michael@0: michael@0: void FireCallback() const michael@0: { michael@0: mCallback->OnCachedFileDescriptor(mPath, mFileDescriptor); michael@0: } michael@0: }; michael@0: michael@0: class TabChild::CachedFileDescriptorCallbackRunnable : public nsRunnable michael@0: { michael@0: typedef TabChild::CachedFileDescriptorInfo CachedFileDescriptorInfo; michael@0: michael@0: nsAutoPtr mInfo; michael@0: michael@0: public: michael@0: CachedFileDescriptorCallbackRunnable(CachedFileDescriptorInfo* aInfo) michael@0: : mInfo(aInfo) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: MOZ_ASSERT(aInfo); michael@0: MOZ_ASSERT(!aInfo->mPath.IsEmpty()); michael@0: MOZ_ASSERT(aInfo->mCallback); michael@0: } michael@0: michael@0: void Dispatch() michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: michael@0: nsresult rv = NS_DispatchToCurrentThread(this); michael@0: NS_ENSURE_SUCCESS_VOID(rv); michael@0: } michael@0: michael@0: private: michael@0: NS_IMETHOD Run() michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: MOZ_ASSERT(mInfo); michael@0: michael@0: mInfo->FireCallback(); michael@0: return NS_OK; michael@0: } michael@0: }; michael@0: michael@0: StaticRefPtr sPreallocatedTab; michael@0: michael@0: /*static*/ void michael@0: TabChild::PreloadSlowThings() michael@0: { michael@0: MOZ_ASSERT(!sPreallocatedTab); michael@0: michael@0: nsRefPtr tab(new TabChild(ContentChild::GetSingleton(), michael@0: TabContext(), /* chromeFlags */ 0)); michael@0: if (!NS_SUCCEEDED(tab->Init()) || michael@0: !tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) { michael@0: return; michael@0: } michael@0: // Just load and compile these scripts, but don't run them. michael@0: tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT, true); michael@0: // Load, compile, and run these scripts. michael@0: tab->RecvLoadRemoteScript( michael@0: NS_LITERAL_STRING("chrome://global/content/preload.js"), michael@0: true); michael@0: michael@0: nsCOMPtr docShell = do_GetInterface(tab->WebNavigation()); michael@0: if (nsIPresShell* presShell = docShell->GetPresShell()) { michael@0: // Initialize and do an initial reflow of the about:blank michael@0: // PresShell to let it preload some things for us. michael@0: presShell->Initialize(0, 0); michael@0: nsIDocument* doc = presShell->GetDocument(); michael@0: doc->FlushPendingNotifications(Flush_Layout); michael@0: // ... but after it's done, make sure it doesn't do any more michael@0: // work. michael@0: presShell->MakeZombie(); michael@0: } michael@0: michael@0: sPreallocatedTab = tab; michael@0: ClearOnShutdown(&sPreallocatedTab); michael@0: } michael@0: michael@0: /*static*/ already_AddRefed michael@0: TabChild::Create(ContentChild* aManager, const TabContext &aContext, uint32_t aChromeFlags) michael@0: { michael@0: if (sPreallocatedTab && michael@0: sPreallocatedTab->mChromeFlags == aChromeFlags && michael@0: aContext.IsBrowserOrApp()) { michael@0: michael@0: nsRefPtr child = sPreallocatedTab.get(); michael@0: sPreallocatedTab = nullptr; michael@0: michael@0: MOZ_ASSERT(!child->mTriedBrowserInit); michael@0: michael@0: child->SetTabContext(aContext); michael@0: child->NotifyTabContextUpdated(); michael@0: return child.forget(); michael@0: } michael@0: michael@0: nsRefPtr iframe = new TabChild(aManager, michael@0: aContext, aChromeFlags); michael@0: return NS_SUCCEEDED(iframe->Init()) ? iframe.forget() : nullptr; michael@0: } michael@0: michael@0: michael@0: TabChild::TabChild(ContentChild* aManager, const TabContext& aContext, uint32_t aChromeFlags) michael@0: : TabContext(aContext) michael@0: , mRemoteFrame(nullptr) michael@0: , mManager(aManager) michael@0: , mChromeFlags(aChromeFlags) michael@0: , mLayersId(0) michael@0: , mOuterRect(0, 0, 0, 0) michael@0: , mActivePointerId(-1) michael@0: , mTapHoldTimer(nullptr) michael@0: , mAppPackageFileDescriptorRecved(false) michael@0: , mLastBackgroundColor(NS_RGB(255, 255, 255)) michael@0: , mDidFakeShow(false) michael@0: , mNotified(false) michael@0: , mTriedBrowserInit(false) michael@0: , mOrientation(eScreenOrientation_PortraitPrimary) michael@0: , mUpdateHitRegion(false) michael@0: , mContextMenuHandled(false) michael@0: , mWaitingTouchListeners(false) michael@0: , mIgnoreKeyPressEvent(false) michael@0: , mActiveElementManager(new ActiveElementManager()) michael@0: { michael@0: if (!sActiveDurationMsSet) { michael@0: Preferences::AddIntVarCache(&sActiveDurationMs, michael@0: "ui.touch_activation.duration_ms", michael@0: sActiveDurationMs); michael@0: sActiveDurationMsSet = true; michael@0: } michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::HandleEvent(nsIDOMEvent* aEvent) michael@0: { michael@0: nsAutoString eventType; michael@0: aEvent->GetType(eventType); michael@0: if (eventType.EqualsLiteral("DOMMetaAdded")) { michael@0: // This meta data may or may not have been a meta viewport tag. If it was, michael@0: // we should handle it immediately. michael@0: HandlePossibleViewportChange(); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::Observe(nsISupports *aSubject, michael@0: const char *aTopic, michael@0: const char16_t *aData) michael@0: { michael@0: if (!strcmp(aTopic, BROWSER_ZOOM_TO_RECT)) { michael@0: nsCOMPtr docShell(do_QueryInterface(aSubject)); michael@0: nsCOMPtr tabChild(TabChild::GetFrom(docShell)); michael@0: if (tabChild == this) { michael@0: nsCOMPtr doc(GetDocument()); michael@0: uint32_t presShellId; michael@0: ViewID viewId; michael@0: if (APZCCallbackHelper::GetScrollIdentifiers(doc->GetDocumentElement(), michael@0: &presShellId, &viewId)) { michael@0: CSSRect rect; michael@0: sscanf(NS_ConvertUTF16toUTF8(aData).get(), michael@0: "{\"x\":%f,\"y\":%f,\"w\":%f,\"h\":%f}", michael@0: &rect.x, &rect.y, &rect.width, &rect.height); michael@0: SendZoomToRect(presShellId, viewId, rect); michael@0: } michael@0: } michael@0: } else if (!strcmp(aTopic, BEFORE_FIRST_PAINT)) { michael@0: if (IsAsyncPanZoomEnabled()) { michael@0: nsCOMPtr subject(do_QueryInterface(aSubject)); michael@0: nsCOMPtr doc(GetDocument()); michael@0: michael@0: if (SameCOMIdentity(subject, doc)) { michael@0: nsCOMPtr utils(GetDOMWindowUtils()); michael@0: utils->SetIsFirstPaint(true); michael@0: michael@0: mContentDocumentIsDisplayed = true; michael@0: michael@0: // Reset CSS viewport and zoom to default on new page, then michael@0: // calculate them properly using the actual metadata from the michael@0: // page. michael@0: SetCSSViewport(kDefaultViewportSize); michael@0: michael@0: // In some cases before-first-paint gets called before michael@0: // RecvUpdateDimensions is called and therefore before we have an michael@0: // mInnerSize value set. In such cases defer initializing the viewport michael@0: // until we we get an inner size. michael@0: if (HasValidInnerSize()) { michael@0: InitializeRootMetrics(); michael@0: utils->SetResolution(mLastRootMetrics.mResolution.scale, michael@0: mLastRootMetrics.mResolution.scale); michael@0: HandlePossibleViewportChange(); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::OnStateChange(nsIWebProgress* aWebProgress, michael@0: nsIRequest* aRequest, michael@0: uint32_t aStateFlags, michael@0: nsresult aStatus) michael@0: { michael@0: NS_NOTREACHED("not implemented in TabChild"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::OnProgressChange(nsIWebProgress* aWebProgress, michael@0: nsIRequest* aRequest, michael@0: int32_t aCurSelfProgress, michael@0: int32_t aMaxSelfProgress, michael@0: int32_t aCurTotalProgress, michael@0: int32_t aMaxTotalProgress) michael@0: { michael@0: NS_NOTREACHED("not implemented in TabChild"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::OnLocationChange(nsIWebProgress* aWebProgress, michael@0: nsIRequest* aRequest, michael@0: nsIURI *aLocation, michael@0: uint32_t aFlags) michael@0: { michael@0: if (!IsAsyncPanZoomEnabled()) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsCOMPtr window; michael@0: aWebProgress->GetDOMWindow(getter_AddRefs(window)); michael@0: if (!window) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsCOMPtr progressDoc; michael@0: window->GetDocument(getter_AddRefs(progressDoc)); michael@0: if (!progressDoc) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsCOMPtr domDoc; michael@0: WebNavigation()->GetDocument(getter_AddRefs(domDoc)); michael@0: if (!domDoc || !SameCOMIdentity(domDoc, progressDoc)) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsCOMPtr urifixup(do_GetService(NS_URIFIXUP_CONTRACTID)); michael@0: if (!urifixup) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsCOMPtr exposableURI; michael@0: urifixup->CreateExposableURI(aLocation, getter_AddRefs(exposableURI)); michael@0: if (!exposableURI) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (!(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT)) { michael@0: mContentDocumentIsDisplayed = false; michael@0: } else if (mLastURI != nullptr) { michael@0: bool exposableEqualsLast, exposableEqualsNew; michael@0: exposableURI->Equals(mLastURI.get(), &exposableEqualsLast); michael@0: exposableURI->Equals(aLocation, &exposableEqualsNew); michael@0: if (exposableEqualsLast && !exposableEqualsNew) { michael@0: mContentDocumentIsDisplayed = false; michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::OnStatusChange(nsIWebProgress* aWebProgress, michael@0: nsIRequest* aRequest, michael@0: nsresult aStatus, michael@0: const char16_t* aMessage) michael@0: { michael@0: NS_NOTREACHED("not implemented in TabChild"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::OnSecurityChange(nsIWebProgress* aWebProgress, michael@0: nsIRequest* aRequest, michael@0: uint32_t aState) michael@0: { michael@0: NS_NOTREACHED("not implemented in TabChild"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: bool michael@0: TabChild::DoUpdateZoomConstraints(const uint32_t& aPresShellId, michael@0: const ViewID& aViewId, michael@0: const bool& aIsRoot, michael@0: const ZoomConstraints& aConstraints) michael@0: { michael@0: return SendUpdateZoomConstraints(aPresShellId, michael@0: aViewId, michael@0: aIsRoot, michael@0: aConstraints); michael@0: } michael@0: michael@0: nsresult michael@0: TabChild::Init() michael@0: { michael@0: nsCOMPtr webBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID); michael@0: if (!webBrowser) { michael@0: NS_ERROR("Couldn't create a nsWebBrowser?"); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: webBrowser->SetContainerWindow(this); michael@0: mWebNav = do_QueryInterface(webBrowser); michael@0: NS_ASSERTION(mWebNav, "nsWebBrowser doesn't implement nsIWebNavigation?"); michael@0: michael@0: nsCOMPtr docShellItem(do_QueryInterface(WebNavigation())); michael@0: docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper); michael@0: michael@0: nsCOMPtr baseWindow = do_QueryInterface(WebNavigation()); michael@0: if (!baseWindow) { michael@0: NS_ERROR("mWebNav doesn't QI to nsIBaseWindow"); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: mWidget = nsIWidget::CreatePuppetWidget(this); michael@0: if (!mWidget) { michael@0: NS_ERROR("couldn't create fake widget"); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: mWidget->Create( michael@0: nullptr, 0, // no parents michael@0: nsIntRect(nsIntPoint(0, 0), nsIntSize(0, 0)), michael@0: nullptr, // HandleWidgetEvent michael@0: nullptr // nsDeviceContext michael@0: ); michael@0: michael@0: baseWindow->InitWindow(0, mWidget, 0, 0, 0, 0); michael@0: baseWindow->Create(); michael@0: michael@0: NotifyTabContextUpdated(); michael@0: michael@0: // IPC uses a WebBrowser object for which DNS prefetching is turned off michael@0: // by default. But here we really want it, so enable it explicitly michael@0: nsCOMPtr webBrowserSetup = michael@0: do_QueryInterface(baseWindow); michael@0: if (webBrowserSetup) { michael@0: webBrowserSetup->SetProperty(nsIWebBrowserSetup::SETUP_ALLOW_DNS_PREFETCH, michael@0: true); michael@0: } else { michael@0: NS_WARNING("baseWindow doesn't QI to nsIWebBrowserSetup, skipping " michael@0: "DNS prefetching enable step."); michael@0: } michael@0: michael@0: nsCOMPtr docShell = do_GetInterface(WebNavigation()); michael@0: MOZ_ASSERT(docShell); michael@0: michael@0: docShell->SetAffectPrivateSessionLifetime( michael@0: mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME); michael@0: nsCOMPtr loadContext = do_GetInterface(WebNavigation()); michael@0: MOZ_ASSERT(loadContext); michael@0: loadContext->SetPrivateBrowsing( michael@0: mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW); michael@0: loadContext->SetRemoteTabs( michael@0: mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW); michael@0: michael@0: nsCOMPtr webProgress = do_GetInterface(docShell); michael@0: NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE); michael@0: webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION); michael@0: michael@0: // Few lines before, baseWindow->Create() will end up creating a new michael@0: // window root in nsGlobalWindow::SetDocShell. michael@0: // Then this chrome event handler, will be inherited to inner windows. michael@0: // We want to also set it to the docshell so that inner windows michael@0: // and any code that has access to the docshell michael@0: // can all listen to the same chrome event handler. michael@0: // XXX: ideally, we would set a chrome event handler earlier, michael@0: // and all windows, even the root one, will use the docshell one. michael@0: nsCOMPtr window = do_GetInterface(WebNavigation()); michael@0: NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); michael@0: nsCOMPtr chromeHandler = michael@0: do_QueryInterface(window->GetChromeEventHandler()); michael@0: docShell->SetChromeEventHandler(chromeHandler); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: TabChild::NotifyTabContextUpdated() michael@0: { michael@0: nsCOMPtr docShell = do_GetInterface(WebNavigation()); michael@0: MOZ_ASSERT(docShell); michael@0: michael@0: if (docShell) { michael@0: // nsDocShell will do the right thing if we pass NO_APP_ID or michael@0: // UNKNOWN_APP_ID for aOwnOrContainingAppId. michael@0: if (IsBrowserElement()) { michael@0: docShell->SetIsBrowserInsideApp(BrowserOwnerAppId()); michael@0: } else { michael@0: docShell->SetIsApp(OwnAppId()); michael@0: } michael@0: } michael@0: } michael@0: michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChild) michael@0: NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) michael@0: NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2) michael@0: NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow) michael@0: NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus) michael@0: NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) michael@0: NS_INTERFACE_MAP_ENTRY(nsIWindowProvider) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) michael@0: NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener) michael@0: NS_INTERFACE_MAP_ENTRY(nsITabChild) michael@0: NS_INTERFACE_MAP_ENTRY(nsIObserver) michael@0: NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) michael@0: NS_INTERFACE_MAP_ENTRY(nsITooltipListener) michael@0: NS_INTERFACE_MAP_END_INHERITING(TabChildBase) michael@0: michael@0: NS_IMPL_ADDREF_INHERITED(TabChild, TabChildBase); michael@0: NS_IMPL_RELEASE_INHERITED(TabChild, TabChildBase); michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::SetStatus(uint32_t aStatusType, const char16_t* aStatus) michael@0: { michael@0: return SetStatusWithContext(aStatusType, michael@0: aStatus ? static_cast(nsDependentString(aStatus)) michael@0: : EmptyString(), michael@0: nullptr); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::GetWebBrowser(nsIWebBrowser** aWebBrowser) michael@0: { michael@0: NS_NOTREACHED("TabChild::GetWebBrowser not supported in TabChild"); michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::SetWebBrowser(nsIWebBrowser* aWebBrowser) michael@0: { michael@0: NS_NOTREACHED("TabChild::SetWebBrowser not supported in TabChild"); michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::GetChromeFlags(uint32_t* aChromeFlags) michael@0: { michael@0: *aChromeFlags = mChromeFlags; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::SetChromeFlags(uint32_t aChromeFlags) michael@0: { michael@0: NS_NOTREACHED("trying to SetChromeFlags from content process?"); michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::DestroyBrowserWindow() michael@0: { michael@0: NS_NOTREACHED("TabChild::DestroyBrowserWindow not supported in TabChild"); michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::SizeBrowserTo(int32_t aCX, int32_t aCY) michael@0: { michael@0: NS_NOTREACHED("TabChild::SizeBrowserTo not supported in TabChild"); michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::ShowAsModal() michael@0: { michael@0: NS_NOTREACHED("TabChild::ShowAsModal not supported in TabChild"); michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::IsWindowModal(bool* aRetVal) michael@0: { michael@0: *aRetVal = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::ExitModalEventLoop(nsresult aStatus) michael@0: { michael@0: NS_NOTREACHED("TabChild::ExitModalEventLoop not supported in TabChild"); michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::SetStatusWithContext(uint32_t aStatusType, michael@0: const nsAString& aStatusText, michael@0: nsISupports* aStatusContext) michael@0: { michael@0: // We can only send the status after the ipc machinery is set up, michael@0: // mRemoteFrame is a good indicator. michael@0: if (mRemoteFrame) michael@0: SendSetStatus(aStatusType, nsString(aStatusText)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY, michael@0: int32_t aCx, int32_t aCy) michael@0: { michael@0: NS_NOTREACHED("TabChild::SetDimensions not supported in TabChild"); michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::GetDimensions(uint32_t aFlags, int32_t* aX, michael@0: int32_t* aY, int32_t* aCx, int32_t* aCy) michael@0: { michael@0: if (aX) { michael@0: *aX = mOuterRect.x; michael@0: } michael@0: if (aY) { michael@0: *aY = mOuterRect.y; michael@0: } michael@0: if (aCx) { michael@0: *aCx = mOuterRect.width; michael@0: } michael@0: if (aCy) { michael@0: *aCy = mOuterRect.height; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::SetFocus() michael@0: { michael@0: NS_WARNING("TabChild::SetFocus not supported in TabChild"); michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::GetVisibility(bool* aVisibility) michael@0: { michael@0: *aVisibility = true; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::SetVisibility(bool aVisibility) michael@0: { michael@0: // should the platform support this? Bug 666365 michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::GetTitle(char16_t** aTitle) michael@0: { michael@0: NS_NOTREACHED("TabChild::GetTitle not supported in TabChild"); michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::SetTitle(const char16_t* aTitle) michael@0: { michael@0: // JavaScript sends the "DOMTitleChanged" event to the parent michael@0: // via the message manager. michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::GetSiteWindow(void** aSiteWindow) michael@0: { michael@0: NS_NOTREACHED("TabChild::GetSiteWindow not supported in TabChild"); michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::Blur() michael@0: { michael@0: NS_WARNING("TabChild::Blur not supported in TabChild"); michael@0: michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::FocusNextElement() michael@0: { michael@0: SendMoveFocus(true); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::FocusPrevElement() michael@0: { michael@0: SendMoveFocus(false); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::GetInterface(const nsIID & aIID, void **aSink) michael@0: { michael@0: // XXXbz should we restrict the set of interfaces we hand out here? michael@0: // See bug 537429 michael@0: return QueryInterface(aIID, aSink); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TabChild::ProvideWindow(nsIDOMWindow* aParent, uint32_t aChromeFlags, michael@0: bool aCalledFromJS, michael@0: bool aPositionSpecified, bool aSizeSpecified, michael@0: nsIURI* aURI, const nsAString& aName, michael@0: const nsACString& aFeatures, bool* aWindowIsNew, michael@0: nsIDOMWindow** aReturn) michael@0: { michael@0: *aReturn = nullptr; michael@0: michael@0: // If aParent is inside an