dom/ipc/TabChild.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
michael@0 2 /* vim: set sw=2 sts=2 ts=8 et tw=80 : */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "base/basictypes.h"
michael@0 8
michael@0 9 #include "TabChild.h"
michael@0 10
michael@0 11 #include "Layers.h"
michael@0 12 #include "ContentChild.h"
michael@0 13 #include "IndexedDBChild.h"
michael@0 14 #include "mozilla/Preferences.h"
michael@0 15 #include "mozilla/ClearOnShutdown.h"
michael@0 16 #include "mozilla/EventListenerManager.h"
michael@0 17 #include "mozilla/IntentionalCrash.h"
michael@0 18 #include "mozilla/docshell/OfflineCacheUpdateChild.h"
michael@0 19 #include "mozilla/ipc/DocumentRendererChild.h"
michael@0 20 #include "mozilla/ipc/FileDescriptorUtils.h"
michael@0 21 #include "mozilla/layers/ActiveElementManager.h"
michael@0 22 #include "mozilla/layers/APZCCallbackHelper.h"
michael@0 23 #include "mozilla/layers/AsyncPanZoomController.h"
michael@0 24 #include "mozilla/layers/CompositorChild.h"
michael@0 25 #include "mozilla/layers/ImageBridgeChild.h"
michael@0 26 #include "mozilla/layers/ShadowLayers.h"
michael@0 27 #include "mozilla/layout/RenderFrameChild.h"
michael@0 28 #include "mozilla/MouseEvents.h"
michael@0 29 #include "mozilla/Services.h"
michael@0 30 #include "mozilla/StaticPtr.h"
michael@0 31 #include "mozilla/TextEvents.h"
michael@0 32 #include "mozilla/TouchEvents.h"
michael@0 33 #include "mozilla/unused.h"
michael@0 34 #include "mozIApplication.h"
michael@0 35 #include "nsContentUtils.h"
michael@0 36 #include "nsCxPusher.h"
michael@0 37 #include "nsEmbedCID.h"
michael@0 38 #include <algorithm>
michael@0 39 #ifdef MOZ_CRASHREPORTER
michael@0 40 #include "nsExceptionHandler.h"
michael@0 41 #endif
michael@0 42 #include "nsFilePickerProxy.h"
michael@0 43 #include "mozilla/dom/Element.h"
michael@0 44 #include "nsIBaseWindow.h"
michael@0 45 #include "nsICachedFileDescriptorListener.h"
michael@0 46 #include "nsIDocumentInlines.h"
michael@0 47 #include "nsIDocShellTreeOwner.h"
michael@0 48 #include "nsIDOMEvent.h"
michael@0 49 #include "nsIDOMWindow.h"
michael@0 50 #include "nsIDOMWindowUtils.h"
michael@0 51 #include "nsIDocShell.h"
michael@0 52 #include "nsIURI.h"
michael@0 53 #include "nsIURIFixup.h"
michael@0 54 #include "nsCDefaultURIFixup.h"
michael@0 55 #include "nsIWebBrowser.h"
michael@0 56 #include "nsIWebBrowserFocus.h"
michael@0 57 #include "nsIWebBrowserSetup.h"
michael@0 58 #include "nsIWebProgress.h"
michael@0 59 #include "nsIXULRuntime.h"
michael@0 60 #include "nsInterfaceHashtable.h"
michael@0 61 #include "nsPIDOMWindow.h"
michael@0 62 #include "nsPIWindowRoot.h"
michael@0 63 #include "nsLayoutUtils.h"
michael@0 64 #include "nsPrintfCString.h"
michael@0 65 #include "nsThreadUtils.h"
michael@0 66 #include "nsWeakReference.h"
michael@0 67 #include "PermissionMessageUtils.h"
michael@0 68 #include "PCOMContentPermissionRequestChild.h"
michael@0 69 #include "PuppetWidget.h"
michael@0 70 #include "StructuredCloneUtils.h"
michael@0 71 #include "nsViewportInfo.h"
michael@0 72 #include "JavaScriptChild.h"
michael@0 73 #include "nsILoadContext.h"
michael@0 74 #include "ipc/nsGUIEventIPC.h"
michael@0 75 #include "mozilla/gfx/Matrix.h"
michael@0 76 #include "UnitTransforms.h"
michael@0 77 #include "ClientLayerManager.h"
michael@0 78
michael@0 79 #include "nsColorPickerProxy.h"
michael@0 80
michael@0 81 #ifdef DEBUG
michael@0 82 #include "PCOMContentPermissionRequestChild.h"
michael@0 83 #endif /* DEBUG */
michael@0 84
michael@0 85 #define BROWSER_ELEMENT_CHILD_SCRIPT \
michael@0 86 NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
michael@0 87
michael@0 88 using namespace mozilla;
michael@0 89 using namespace mozilla::dom;
michael@0 90 using namespace mozilla::dom::ipc;
michael@0 91 using namespace mozilla::ipc;
michael@0 92 using namespace mozilla::layers;
michael@0 93 using namespace mozilla::layout;
michael@0 94 using namespace mozilla::docshell;
michael@0 95 using namespace mozilla::dom::indexedDB;
michael@0 96 using namespace mozilla::widget;
michael@0 97 using namespace mozilla::jsipc;
michael@0 98
michael@0 99 NS_IMPL_ISUPPORTS(ContentListener, nsIDOMEventListener)
michael@0 100
michael@0 101 static const CSSSize kDefaultViewportSize(980, 480);
michael@0 102
michael@0 103 static const char BROWSER_ZOOM_TO_RECT[] = "browser-zoom-to-rect";
michael@0 104 static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
michael@0 105
michael@0 106 static bool sCpowsEnabled = false;
michael@0 107 static int32_t sActiveDurationMs = 10;
michael@0 108 static bool sActiveDurationMsSet = false;
michael@0 109
michael@0 110 typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
michael@0 111 static TabChildMap* sTabChildren;
michael@0 112
michael@0 113 TabChildBase::TabChildBase()
michael@0 114 : mOldViewportWidth(0.0f)
michael@0 115 , mContentDocumentIsDisplayed(false)
michael@0 116 , mTabChildGlobal(nullptr)
michael@0 117 , mInnerSize(0, 0)
michael@0 118 {
michael@0 119 }
michael@0 120
michael@0 121 NS_IMPL_CYCLE_COLLECTING_ADDREF(TabChildBase)
michael@0 122 NS_IMPL_CYCLE_COLLECTING_RELEASE(TabChildBase)
michael@0 123 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildBase)
michael@0 124 NS_INTERFACE_MAP_ENTRY(nsISupports)
michael@0 125 NS_INTERFACE_MAP_END
michael@0 126
michael@0 127 NS_IMPL_CYCLE_COLLECTION(TabChildBase, mTabChildGlobal, mGlobal)
michael@0 128
michael@0 129 void
michael@0 130 TabChildBase::InitializeRootMetrics()
michael@0 131 {
michael@0 132 // Calculate a really simple resolution that we probably won't
michael@0 133 // be keeping, as well as putting the scroll offset back to
michael@0 134 // the top-left of the page.
michael@0 135 mLastRootMetrics.mViewport = CSSRect(CSSPoint(), kDefaultViewportSize);
michael@0 136 mLastRootMetrics.mCompositionBounds = ParentLayerIntRect(
michael@0 137 ParentLayerIntPoint(),
michael@0 138 ViewAs<ParentLayerPixel>(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot));
michael@0 139 mLastRootMetrics.SetZoom(mLastRootMetrics.CalculateIntrinsicScale());
michael@0 140 mLastRootMetrics.mDevPixelsPerCSSPixel = WebWidget()->GetDefaultScale();
michael@0 141 // We use ScreenToLayerScale(1) below in order to turn the
michael@0 142 // async zoom amount into the gecko zoom amount.
michael@0 143 mLastRootMetrics.mCumulativeResolution =
michael@0 144 mLastRootMetrics.GetZoom() / mLastRootMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
michael@0 145 // This is the root layer, so the cumulative resolution is the same
michael@0 146 // as the resolution.
michael@0 147 mLastRootMetrics.mResolution = mLastRootMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1);
michael@0 148 mLastRootMetrics.SetScrollOffset(CSSPoint(0, 0));
michael@0 149 }
michael@0 150
michael@0 151 bool
michael@0 152 TabChildBase::HasValidInnerSize()
michael@0 153 {
michael@0 154 return (mInnerSize.width != 0) && (mInnerSize.height != 0);
michael@0 155 }
michael@0 156
michael@0 157 void
michael@0 158 TabChildBase::SetCSSViewport(const CSSSize& aSize)
michael@0 159 {
michael@0 160 mOldViewportWidth = aSize.width;
michael@0 161
michael@0 162 if (mContentDocumentIsDisplayed) {
michael@0 163 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
michael@0 164 utils->SetCSSViewport(aSize.width, aSize.height);
michael@0 165 }
michael@0 166 }
michael@0 167
michael@0 168 CSSSize
michael@0 169 TabChildBase::GetPageSize(nsCOMPtr<nsIDocument> aDocument, const CSSSize& aViewport)
michael@0 170 {
michael@0 171 nsCOMPtr<Element> htmlDOMElement = aDocument->GetHtmlElement();
michael@0 172 HTMLBodyElement* bodyDOMElement = aDocument->GetBodyElement();
michael@0 173
michael@0 174 if (!htmlDOMElement && !bodyDOMElement) {
michael@0 175 // For non-HTML content (e.g. SVG), just assume page size == viewport size.
michael@0 176 return aViewport;
michael@0 177 }
michael@0 178
michael@0 179 int32_t htmlWidth = 0, htmlHeight = 0;
michael@0 180 if (htmlDOMElement) {
michael@0 181 htmlWidth = htmlDOMElement->ScrollWidth();
michael@0 182 htmlHeight = htmlDOMElement->ScrollHeight();
michael@0 183 }
michael@0 184 int32_t bodyWidth = 0, bodyHeight = 0;
michael@0 185 if (bodyDOMElement) {
michael@0 186 bodyWidth = bodyDOMElement->ScrollWidth();
michael@0 187 bodyHeight = bodyDOMElement->ScrollHeight();
michael@0 188 }
michael@0 189 return CSSSize(std::max(htmlWidth, bodyWidth),
michael@0 190 std::max(htmlHeight, bodyHeight));
michael@0 191 }
michael@0 192
michael@0 193 bool
michael@0 194 TabChildBase::HandlePossibleViewportChange()
michael@0 195 {
michael@0 196 if (!IsAsyncPanZoomEnabled()) {
michael@0 197 return false;
michael@0 198 }
michael@0 199
michael@0 200 nsCOMPtr<nsIDocument> document(GetDocument());
michael@0 201 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
michael@0 202
michael@0 203 nsViewportInfo viewportInfo = nsContentUtils::GetViewportInfo(document, mInnerSize);
michael@0 204 uint32_t presShellId;
michael@0 205 mozilla::layers::FrameMetrics::ViewID viewId;
michael@0 206 bool scrollIdentifiersValid = APZCCallbackHelper::GetScrollIdentifiers(
michael@0 207 document->GetDocumentElement(), &presShellId, &viewId);
michael@0 208 if (scrollIdentifiersValid) {
michael@0 209 ZoomConstraints constraints(
michael@0 210 viewportInfo.IsZoomAllowed(),
michael@0 211 viewportInfo.IsDoubleTapZoomAllowed(),
michael@0 212 viewportInfo.GetMinZoom(),
michael@0 213 viewportInfo.GetMaxZoom());
michael@0 214 DoUpdateZoomConstraints(presShellId,
michael@0 215 viewId,
michael@0 216 /* isRoot = */ true,
michael@0 217 constraints);
michael@0 218 }
michael@0 219
michael@0 220 float screenW = mInnerSize.width;
michael@0 221 float screenH = mInnerSize.height;
michael@0 222 CSSSize viewport(viewportInfo.GetSize());
michael@0 223
michael@0 224 // We're not being displayed in any way; don't bother doing anything because
michael@0 225 // that will just confuse future adjustments.
michael@0 226 if (!screenW || !screenH) {
michael@0 227 return false;
michael@0 228 }
michael@0 229
michael@0 230 float oldBrowserWidth = mOldViewportWidth;
michael@0 231 mLastRootMetrics.mViewport.SizeTo(viewport);
michael@0 232 if (!oldBrowserWidth) {
michael@0 233 oldBrowserWidth = kDefaultViewportSize.width;
michael@0 234 }
michael@0 235 SetCSSViewport(viewport);
michael@0 236
michael@0 237 // If this page has not been painted yet, then this must be getting run
michael@0 238 // because a meta-viewport element was added (via the DOMMetaAdded handler).
michael@0 239 // in this case, we should not do anything that forces a reflow (see bug
michael@0 240 // 759678) such as requesting the page size or sending a viewport update. this
michael@0 241 // code will get run again in the before-first-paint handler and that point we
michael@0 242 // will run though all of it. the reason we even bother executing up to this
michael@0 243 // point on the DOMMetaAdded handler is so that scripts that use
michael@0 244 // window.innerWidth before they are painted have a correct value (bug
michael@0 245 // 771575).
michael@0 246 if (!mContentDocumentIsDisplayed) {
michael@0 247 return false;
michael@0 248 }
michael@0 249
michael@0 250 float oldScreenWidth = mLastRootMetrics.mCompositionBounds.width;
michael@0 251 if (!oldScreenWidth) {
michael@0 252 oldScreenWidth = mInnerSize.width;
michael@0 253 }
michael@0 254
michael@0 255 FrameMetrics metrics(mLastRootMetrics);
michael@0 256 metrics.mViewport = CSSRect(CSSPoint(), viewport);
michael@0 257 metrics.mCompositionBounds = ParentLayerIntRect(
michael@0 258 ParentLayerIntPoint(),
michael@0 259 ViewAs<ParentLayerPixel>(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot));
michael@0 260 metrics.SetRootCompositionSize(
michael@0 261 ScreenSize(mInnerSize) * ScreenToLayoutDeviceScale(1.0f) / metrics.mDevPixelsPerCSSPixel);
michael@0 262
michael@0 263 // This change to the zoom accounts for all types of changes I can conceive:
michael@0 264 // 1. screen size changes, CSS viewport does not (pages with no meta viewport
michael@0 265 // or a fixed size viewport)
michael@0 266 // 2. screen size changes, CSS viewport also does (pages with a device-width
michael@0 267 // viewport)
michael@0 268 // 3. screen size remains constant, but CSS viewport changes (meta viewport
michael@0 269 // tag is added or removed)
michael@0 270 // 4. neither screen size nor CSS viewport changes
michael@0 271 //
michael@0 272 // In all of these cases, we maintain how much actual content is visible
michael@0 273 // within the screen width. Note that "actual content" may be different with
michael@0 274 // respect to CSS pixels because of the CSS viewport size changing.
michael@0 275 float oldIntrinsicScale = oldScreenWidth / oldBrowserWidth;
michael@0 276 metrics.ZoomBy(metrics.CalculateIntrinsicScale().scale / oldIntrinsicScale);
michael@0 277
michael@0 278 // Changing the zoom when we're not doing a first paint will get ignored
michael@0 279 // by AsyncPanZoomController and causes a blurry flash.
michael@0 280 bool isFirstPaint;
michael@0 281 nsresult rv = utils->GetIsFirstPaint(&isFirstPaint);
michael@0 282 if (NS_FAILED(rv) || isFirstPaint) {
michael@0 283 // FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of
michael@0 284 // 0.0 to mean "did not calculate a zoom". In that case, we default
michael@0 285 // it to the intrinsic scale.
michael@0 286 if (viewportInfo.GetDefaultZoom().scale < 0.01f) {
michael@0 287 viewportInfo.SetDefaultZoom(metrics.CalculateIntrinsicScale());
michael@0 288 }
michael@0 289
michael@0 290 CSSToScreenScale defaultZoom = viewportInfo.GetDefaultZoom();
michael@0 291 MOZ_ASSERT(viewportInfo.GetMinZoom() <= defaultZoom &&
michael@0 292 defaultZoom <= viewportInfo.GetMaxZoom());
michael@0 293 metrics.SetZoom(defaultZoom);
michael@0 294
michael@0 295 metrics.SetScrollId(viewId);
michael@0 296 }
michael@0 297
michael@0 298 metrics.mCumulativeResolution = metrics.GetZoom() / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
michael@0 299 // This is the root layer, so the cumulative resolution is the same
michael@0 300 // as the resolution.
michael@0 301 metrics.mResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1);
michael@0 302 utils->SetResolution(metrics.mResolution.scale, metrics.mResolution.scale);
michael@0 303
michael@0 304 CSSSize scrollPort = metrics.CalculateCompositedSizeInCssPixels();
michael@0 305 utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height);
michael@0 306
michael@0 307 // The call to GetPageSize forces a resize event to content, so we need to
michael@0 308 // make sure that we have the right CSS viewport and
michael@0 309 // scrollPositionClampingScrollPortSize set up before that happens.
michael@0 310
michael@0 311 CSSSize pageSize = GetPageSize(document, viewport);
michael@0 312 if (!pageSize.width) {
michael@0 313 // Return early rather than divide by 0.
michael@0 314 return false;
michael@0 315 }
michael@0 316 metrics.mScrollableRect = CSSRect(CSSPoint(), pageSize);
michael@0 317
michael@0 318 // Calculate a display port _after_ having a scrollable rect because the
michael@0 319 // display port is clamped to the scrollable rect.
michael@0 320 metrics.SetDisplayPortMargins(AsyncPanZoomController::CalculatePendingDisplayPort(
michael@0 321 // The page must have been refreshed in some way such as a new document or
michael@0 322 // new CSS viewport, so we know that there's no velocity, acceleration, and
michael@0 323 // we have no idea how long painting will take.
michael@0 324 metrics, ScreenPoint(0.0f, 0.0f), 0.0));
michael@0 325 metrics.SetUseDisplayPortMargins();
michael@0 326
michael@0 327 // Force a repaint with these metrics. This, among other things, sets the
michael@0 328 // displayport, so we start with async painting.
michael@0 329 mLastRootMetrics = ProcessUpdateFrame(metrics);
michael@0 330
michael@0 331 if (viewportInfo.IsZoomAllowed() && scrollIdentifiersValid) {
michael@0 332 // If the CSS viewport is narrower than the screen (i.e. width <= device-width)
michael@0 333 // then we disable double-tap-to-zoom behaviour.
michael@0 334 bool allowDoubleTapZoom = (viewport.width > screenW / metrics.mDevPixelsPerCSSPixel.scale);
michael@0 335 if (allowDoubleTapZoom != viewportInfo.IsDoubleTapZoomAllowed()) {
michael@0 336 viewportInfo.SetAllowDoubleTapZoom(allowDoubleTapZoom);
michael@0 337
michael@0 338 ZoomConstraints constraints(
michael@0 339 viewportInfo.IsZoomAllowed(),
michael@0 340 viewportInfo.IsDoubleTapZoomAllowed(),
michael@0 341 viewportInfo.GetMinZoom(),
michael@0 342 viewportInfo.GetMaxZoom());
michael@0 343 DoUpdateZoomConstraints(presShellId,
michael@0 344 viewId,
michael@0 345 /* isRoot = */ true,
michael@0 346 constraints);
michael@0 347 }
michael@0 348 }
michael@0 349
michael@0 350 return true;
michael@0 351 }
michael@0 352
michael@0 353 already_AddRefed<nsIDOMWindowUtils>
michael@0 354 TabChildBase::GetDOMWindowUtils()
michael@0 355 {
michael@0 356 nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation());
michael@0 357 nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window);
michael@0 358 return utils.forget();
michael@0 359 }
michael@0 360
michael@0 361 already_AddRefed<nsIDocument>
michael@0 362 TabChildBase::GetDocument()
michael@0 363 {
michael@0 364 nsCOMPtr<nsIDOMDocument> domDoc;
michael@0 365 WebNavigation()->GetDocument(getter_AddRefs(domDoc));
michael@0 366 nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
michael@0 367 return doc.forget();
michael@0 368 }
michael@0 369
michael@0 370 void
michael@0 371 TabChildBase::DispatchMessageManagerMessage(const nsAString& aMessageName,
michael@0 372 const nsAString& aJSONData)
michael@0 373 {
michael@0 374 AutoSafeJSContext cx;
michael@0 375 JS::Rooted<JS::Value> json(cx, JSVAL_NULL);
michael@0 376 StructuredCloneData cloneData;
michael@0 377 JSAutoStructuredCloneBuffer buffer;
michael@0 378 if (JS_ParseJSON(cx,
michael@0 379 static_cast<const jschar*>(aJSONData.BeginReading()),
michael@0 380 aJSONData.Length(),
michael@0 381 &json)) {
michael@0 382 WriteStructuredClone(cx, json, buffer, cloneData.mClosure);
michael@0 383 cloneData.mData = buffer.data();
michael@0 384 cloneData.mDataLength = buffer.nbytes();
michael@0 385 }
michael@0 386
michael@0 387 nsCOMPtr<nsIXPConnectJSObjectHolder> kungFuDeathGrip(GetGlobal());
michael@0 388 // Let the BrowserElementScrolling helper (if it exists) for this
michael@0 389 // content manipulate the frame state.
michael@0 390 nsRefPtr<nsFrameMessageManager> mm =
michael@0 391 static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
michael@0 392 mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal),
michael@0 393 aMessageName, false, &cloneData, nullptr, nullptr, nullptr);
michael@0 394 }
michael@0 395
michael@0 396 bool
michael@0 397 TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics)
michael@0 398 {
michael@0 399 MOZ_ASSERT(aFrameMetrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID);
michael@0 400
michael@0 401 if (aFrameMetrics.mIsRoot) {
michael@0 402 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
michael@0 403 if (APZCCallbackHelper::HasValidPresShellId(utils, aFrameMetrics)) {
michael@0 404 mLastRootMetrics = ProcessUpdateFrame(aFrameMetrics);
michael@0 405 APZCCallbackHelper::UpdateCallbackTransform(aFrameMetrics, mLastRootMetrics);
michael@0 406 return true;
michael@0 407 }
michael@0 408 } else {
michael@0 409 // aFrameMetrics.mIsRoot is false, so we are trying to update a subframe.
michael@0 410 // This requires special handling.
michael@0 411 nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(
michael@0 412 aFrameMetrics.GetScrollId());
michael@0 413 if (content) {
michael@0 414 FrameMetrics newSubFrameMetrics(aFrameMetrics);
michael@0 415 APZCCallbackHelper::UpdateSubFrame(content, newSubFrameMetrics);
michael@0 416 APZCCallbackHelper::UpdateCallbackTransform(aFrameMetrics, newSubFrameMetrics);
michael@0 417 return true;
michael@0 418 }
michael@0 419 }
michael@0 420
michael@0 421 // We've recieved a message that is out of date and we want to ignore.
michael@0 422 // However we can't reply without painting so we reply by painting the
michael@0 423 // exact same thing as we did before.
michael@0 424 mLastRootMetrics = ProcessUpdateFrame(mLastRootMetrics);
michael@0 425 return true;
michael@0 426 }
michael@0 427
michael@0 428 FrameMetrics
michael@0 429 TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
michael@0 430 {
michael@0 431 if (!mGlobal || !mTabChildGlobal) {
michael@0 432 return aFrameMetrics;
michael@0 433 }
michael@0 434
michael@0 435 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
michael@0 436
michael@0 437 FrameMetrics newMetrics = aFrameMetrics;
michael@0 438 APZCCallbackHelper::UpdateRootFrame(utils, newMetrics);
michael@0 439
michael@0 440 CSSSize cssCompositedSize = newMetrics.CalculateCompositedSizeInCssPixels();
michael@0 441 // The BrowserElementScrolling helper must know about these updated metrics
michael@0 442 // for other functions it performs, such as double tap handling.
michael@0 443 // Note, %f must not be used because it is locale specific!
michael@0 444 nsString data;
michael@0 445 data.AppendPrintf("{ \"x\" : %d", NS_lround(newMetrics.GetScrollOffset().x));
michael@0 446 data.AppendPrintf(", \"y\" : %d", NS_lround(newMetrics.GetScrollOffset().y));
michael@0 447 data.AppendLiteral(", \"viewport\" : ");
michael@0 448 data.AppendLiteral("{ \"width\" : ");
michael@0 449 data.AppendFloat(newMetrics.mViewport.width);
michael@0 450 data.AppendLiteral(", \"height\" : ");
michael@0 451 data.AppendFloat(newMetrics.mViewport.height);
michael@0 452 data.AppendLiteral(" }");
michael@0 453 data.AppendLiteral(", \"cssPageRect\" : ");
michael@0 454 data.AppendLiteral("{ \"x\" : ");
michael@0 455 data.AppendFloat(newMetrics.mScrollableRect.x);
michael@0 456 data.AppendLiteral(", \"y\" : ");
michael@0 457 data.AppendFloat(newMetrics.mScrollableRect.y);
michael@0 458 data.AppendLiteral(", \"width\" : ");
michael@0 459 data.AppendFloat(newMetrics.mScrollableRect.width);
michael@0 460 data.AppendLiteral(", \"height\" : ");
michael@0 461 data.AppendFloat(newMetrics.mScrollableRect.height);
michael@0 462 data.AppendLiteral(" }");
michael@0 463 data.AppendPrintf(", \"resolution\" : "); // TODO: check if it's actually used?
michael@0 464 data.AppendPrintf("{ \"width\" : ");
michael@0 465 data.AppendFloat(newMetrics.CalculateIntrinsicScale().scale);
michael@0 466 data.AppendPrintf(" }");
michael@0 467 data.AppendLiteral(", \"cssCompositedRect\" : ");
michael@0 468 data.AppendLiteral("{ \"width\" : ");
michael@0 469 data.AppendFloat(cssCompositedSize.width);
michael@0 470 data.AppendLiteral(", \"height\" : ");
michael@0 471 data.AppendFloat(cssCompositedSize.height);
michael@0 472 data.AppendLiteral(" }");
michael@0 473 data.AppendLiteral(" }");
michael@0 474
michael@0 475 DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
michael@0 476 return newMetrics;
michael@0 477 }
michael@0 478
michael@0 479 nsEventStatus
michael@0 480 TabChildBase::DispatchSynthesizedMouseEvent(uint32_t aMsg, uint64_t aTime,
michael@0 481 const LayoutDevicePoint& aRefPoint,
michael@0 482 nsIWidget* aWidget)
michael@0 483 {
michael@0 484 MOZ_ASSERT(aMsg == NS_MOUSE_MOVE || aMsg == NS_MOUSE_BUTTON_DOWN ||
michael@0 485 aMsg == NS_MOUSE_BUTTON_UP);
michael@0 486
michael@0 487 WidgetMouseEvent event(true, aMsg, nullptr,
michael@0 488 WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
michael@0 489 event.refPoint = LayoutDeviceIntPoint(aRefPoint.x, aRefPoint.y);
michael@0 490 event.time = aTime;
michael@0 491 event.button = WidgetMouseEvent::eLeftButton;
michael@0 492 event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
michael@0 493 if (aMsg != NS_MOUSE_MOVE) {
michael@0 494 event.clickCount = 1;
michael@0 495 }
michael@0 496 event.widget = aWidget;
michael@0 497
michael@0 498 return DispatchWidgetEvent(event);
michael@0 499 }
michael@0 500
michael@0 501 nsEventStatus
michael@0 502 TabChildBase::DispatchWidgetEvent(WidgetGUIEvent& event)
michael@0 503 {
michael@0 504 if (!event.widget)
michael@0 505 return nsEventStatus_eConsumeNoDefault;
michael@0 506
michael@0 507 nsEventStatus status;
michael@0 508 NS_ENSURE_SUCCESS(event.widget->DispatchEvent(&event, status),
michael@0 509 nsEventStatus_eConsumeNoDefault);
michael@0 510 return status;
michael@0 511 }
michael@0 512
michael@0 513 bool
michael@0 514 TabChildBase::IsAsyncPanZoomEnabled()
michael@0 515 {
michael@0 516 return mScrolling == ASYNC_PAN_ZOOM;
michael@0 517 }
michael@0 518
michael@0 519 NS_IMETHODIMP
michael@0 520 ContentListener::HandleEvent(nsIDOMEvent* aEvent)
michael@0 521 {
michael@0 522 RemoteDOMEvent remoteEvent;
michael@0 523 remoteEvent.mEvent = do_QueryInterface(aEvent);
michael@0 524 NS_ENSURE_STATE(remoteEvent.mEvent);
michael@0 525 mTabChild->SendEvent(remoteEvent);
michael@0 526 return NS_OK;
michael@0 527 }
michael@0 528
michael@0 529 class TabChild::CachedFileDescriptorInfo
michael@0 530 {
michael@0 531 struct PathOnlyComparatorHelper
michael@0 532 {
michael@0 533 bool Equals(const nsAutoPtr<CachedFileDescriptorInfo>& a,
michael@0 534 const CachedFileDescriptorInfo& b) const
michael@0 535 {
michael@0 536 return a->mPath == b.mPath;
michael@0 537 }
michael@0 538 };
michael@0 539
michael@0 540 struct PathAndCallbackComparatorHelper
michael@0 541 {
michael@0 542 bool Equals(const nsAutoPtr<CachedFileDescriptorInfo>& a,
michael@0 543 const CachedFileDescriptorInfo& b) const
michael@0 544 {
michael@0 545 return a->mPath == b.mPath &&
michael@0 546 a->mCallback == b.mCallback;
michael@0 547 }
michael@0 548 };
michael@0 549
michael@0 550 public:
michael@0 551 nsString mPath;
michael@0 552 FileDescriptor mFileDescriptor;
michael@0 553 nsCOMPtr<nsICachedFileDescriptorListener> mCallback;
michael@0 554 bool mCanceled;
michael@0 555
michael@0 556 CachedFileDescriptorInfo(const nsAString& aPath)
michael@0 557 : mPath(aPath), mCanceled(false)
michael@0 558 { }
michael@0 559
michael@0 560 CachedFileDescriptorInfo(const nsAString& aPath,
michael@0 561 const FileDescriptor& aFileDescriptor)
michael@0 562 : mPath(aPath), mFileDescriptor(aFileDescriptor), mCanceled(false)
michael@0 563 { }
michael@0 564
michael@0 565 CachedFileDescriptorInfo(const nsAString& aPath,
michael@0 566 nsICachedFileDescriptorListener* aCallback)
michael@0 567 : mPath(aPath), mCallback(aCallback), mCanceled(false)
michael@0 568 { }
michael@0 569
michael@0 570 PathOnlyComparatorHelper PathOnlyComparator() const
michael@0 571 {
michael@0 572 return PathOnlyComparatorHelper();
michael@0 573 }
michael@0 574
michael@0 575 PathAndCallbackComparatorHelper PathAndCallbackComparator() const
michael@0 576 {
michael@0 577 return PathAndCallbackComparatorHelper();
michael@0 578 }
michael@0 579
michael@0 580 void FireCallback() const
michael@0 581 {
michael@0 582 mCallback->OnCachedFileDescriptor(mPath, mFileDescriptor);
michael@0 583 }
michael@0 584 };
michael@0 585
michael@0 586 class TabChild::CachedFileDescriptorCallbackRunnable : public nsRunnable
michael@0 587 {
michael@0 588 typedef TabChild::CachedFileDescriptorInfo CachedFileDescriptorInfo;
michael@0 589
michael@0 590 nsAutoPtr<CachedFileDescriptorInfo> mInfo;
michael@0 591
michael@0 592 public:
michael@0 593 CachedFileDescriptorCallbackRunnable(CachedFileDescriptorInfo* aInfo)
michael@0 594 : mInfo(aInfo)
michael@0 595 {
michael@0 596 MOZ_ASSERT(NS_IsMainThread());
michael@0 597 MOZ_ASSERT(aInfo);
michael@0 598 MOZ_ASSERT(!aInfo->mPath.IsEmpty());
michael@0 599 MOZ_ASSERT(aInfo->mCallback);
michael@0 600 }
michael@0 601
michael@0 602 void Dispatch()
michael@0 603 {
michael@0 604 MOZ_ASSERT(NS_IsMainThread());
michael@0 605
michael@0 606 nsresult rv = NS_DispatchToCurrentThread(this);
michael@0 607 NS_ENSURE_SUCCESS_VOID(rv);
michael@0 608 }
michael@0 609
michael@0 610 private:
michael@0 611 NS_IMETHOD Run()
michael@0 612 {
michael@0 613 MOZ_ASSERT(NS_IsMainThread());
michael@0 614 MOZ_ASSERT(mInfo);
michael@0 615
michael@0 616 mInfo->FireCallback();
michael@0 617 return NS_OK;
michael@0 618 }
michael@0 619 };
michael@0 620
michael@0 621 StaticRefPtr<TabChild> sPreallocatedTab;
michael@0 622
michael@0 623 /*static*/ void
michael@0 624 TabChild::PreloadSlowThings()
michael@0 625 {
michael@0 626 MOZ_ASSERT(!sPreallocatedTab);
michael@0 627
michael@0 628 nsRefPtr<TabChild> tab(new TabChild(ContentChild::GetSingleton(),
michael@0 629 TabContext(), /* chromeFlags */ 0));
michael@0 630 if (!NS_SUCCEEDED(tab->Init()) ||
michael@0 631 !tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) {
michael@0 632 return;
michael@0 633 }
michael@0 634 // Just load and compile these scripts, but don't run them.
michael@0 635 tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
michael@0 636 // Load, compile, and run these scripts.
michael@0 637 tab->RecvLoadRemoteScript(
michael@0 638 NS_LITERAL_STRING("chrome://global/content/preload.js"),
michael@0 639 true);
michael@0 640
michael@0 641 nsCOMPtr<nsIDocShell> docShell = do_GetInterface(tab->WebNavigation());
michael@0 642 if (nsIPresShell* presShell = docShell->GetPresShell()) {
michael@0 643 // Initialize and do an initial reflow of the about:blank
michael@0 644 // PresShell to let it preload some things for us.
michael@0 645 presShell->Initialize(0, 0);
michael@0 646 nsIDocument* doc = presShell->GetDocument();
michael@0 647 doc->FlushPendingNotifications(Flush_Layout);
michael@0 648 // ... but after it's done, make sure it doesn't do any more
michael@0 649 // work.
michael@0 650 presShell->MakeZombie();
michael@0 651 }
michael@0 652
michael@0 653 sPreallocatedTab = tab;
michael@0 654 ClearOnShutdown(&sPreallocatedTab);
michael@0 655 }
michael@0 656
michael@0 657 /*static*/ already_AddRefed<TabChild>
michael@0 658 TabChild::Create(ContentChild* aManager, const TabContext &aContext, uint32_t aChromeFlags)
michael@0 659 {
michael@0 660 if (sPreallocatedTab &&
michael@0 661 sPreallocatedTab->mChromeFlags == aChromeFlags &&
michael@0 662 aContext.IsBrowserOrApp()) {
michael@0 663
michael@0 664 nsRefPtr<TabChild> child = sPreallocatedTab.get();
michael@0 665 sPreallocatedTab = nullptr;
michael@0 666
michael@0 667 MOZ_ASSERT(!child->mTriedBrowserInit);
michael@0 668
michael@0 669 child->SetTabContext(aContext);
michael@0 670 child->NotifyTabContextUpdated();
michael@0 671 return child.forget();
michael@0 672 }
michael@0 673
michael@0 674 nsRefPtr<TabChild> iframe = new TabChild(aManager,
michael@0 675 aContext, aChromeFlags);
michael@0 676 return NS_SUCCEEDED(iframe->Init()) ? iframe.forget() : nullptr;
michael@0 677 }
michael@0 678
michael@0 679
michael@0 680 TabChild::TabChild(ContentChild* aManager, const TabContext& aContext, uint32_t aChromeFlags)
michael@0 681 : TabContext(aContext)
michael@0 682 , mRemoteFrame(nullptr)
michael@0 683 , mManager(aManager)
michael@0 684 , mChromeFlags(aChromeFlags)
michael@0 685 , mLayersId(0)
michael@0 686 , mOuterRect(0, 0, 0, 0)
michael@0 687 , mActivePointerId(-1)
michael@0 688 , mTapHoldTimer(nullptr)
michael@0 689 , mAppPackageFileDescriptorRecved(false)
michael@0 690 , mLastBackgroundColor(NS_RGB(255, 255, 255))
michael@0 691 , mDidFakeShow(false)
michael@0 692 , mNotified(false)
michael@0 693 , mTriedBrowserInit(false)
michael@0 694 , mOrientation(eScreenOrientation_PortraitPrimary)
michael@0 695 , mUpdateHitRegion(false)
michael@0 696 , mContextMenuHandled(false)
michael@0 697 , mWaitingTouchListeners(false)
michael@0 698 , mIgnoreKeyPressEvent(false)
michael@0 699 , mActiveElementManager(new ActiveElementManager())
michael@0 700 {
michael@0 701 if (!sActiveDurationMsSet) {
michael@0 702 Preferences::AddIntVarCache(&sActiveDurationMs,
michael@0 703 "ui.touch_activation.duration_ms",
michael@0 704 sActiveDurationMs);
michael@0 705 sActiveDurationMsSet = true;
michael@0 706 }
michael@0 707 }
michael@0 708
michael@0 709 NS_IMETHODIMP
michael@0 710 TabChild::HandleEvent(nsIDOMEvent* aEvent)
michael@0 711 {
michael@0 712 nsAutoString eventType;
michael@0 713 aEvent->GetType(eventType);
michael@0 714 if (eventType.EqualsLiteral("DOMMetaAdded")) {
michael@0 715 // This meta data may or may not have been a meta viewport tag. If it was,
michael@0 716 // we should handle it immediately.
michael@0 717 HandlePossibleViewportChange();
michael@0 718 }
michael@0 719
michael@0 720 return NS_OK;
michael@0 721 }
michael@0 722
michael@0 723 NS_IMETHODIMP
michael@0 724 TabChild::Observe(nsISupports *aSubject,
michael@0 725 const char *aTopic,
michael@0 726 const char16_t *aData)
michael@0 727 {
michael@0 728 if (!strcmp(aTopic, BROWSER_ZOOM_TO_RECT)) {
michael@0 729 nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
michael@0 730 nsCOMPtr<nsITabChild> tabChild(TabChild::GetFrom(docShell));
michael@0 731 if (tabChild == this) {
michael@0 732 nsCOMPtr<nsIDocument> doc(GetDocument());
michael@0 733 uint32_t presShellId;
michael@0 734 ViewID viewId;
michael@0 735 if (APZCCallbackHelper::GetScrollIdentifiers(doc->GetDocumentElement(),
michael@0 736 &presShellId, &viewId)) {
michael@0 737 CSSRect rect;
michael@0 738 sscanf(NS_ConvertUTF16toUTF8(aData).get(),
michael@0 739 "{\"x\":%f,\"y\":%f,\"w\":%f,\"h\":%f}",
michael@0 740 &rect.x, &rect.y, &rect.width, &rect.height);
michael@0 741 SendZoomToRect(presShellId, viewId, rect);
michael@0 742 }
michael@0 743 }
michael@0 744 } else if (!strcmp(aTopic, BEFORE_FIRST_PAINT)) {
michael@0 745 if (IsAsyncPanZoomEnabled()) {
michael@0 746 nsCOMPtr<nsIDocument> subject(do_QueryInterface(aSubject));
michael@0 747 nsCOMPtr<nsIDocument> doc(GetDocument());
michael@0 748
michael@0 749 if (SameCOMIdentity(subject, doc)) {
michael@0 750 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
michael@0 751 utils->SetIsFirstPaint(true);
michael@0 752
michael@0 753 mContentDocumentIsDisplayed = true;
michael@0 754
michael@0 755 // Reset CSS viewport and zoom to default on new page, then
michael@0 756 // calculate them properly using the actual metadata from the
michael@0 757 // page.
michael@0 758 SetCSSViewport(kDefaultViewportSize);
michael@0 759
michael@0 760 // In some cases before-first-paint gets called before
michael@0 761 // RecvUpdateDimensions is called and therefore before we have an
michael@0 762 // mInnerSize value set. In such cases defer initializing the viewport
michael@0 763 // until we we get an inner size.
michael@0 764 if (HasValidInnerSize()) {
michael@0 765 InitializeRootMetrics();
michael@0 766 utils->SetResolution(mLastRootMetrics.mResolution.scale,
michael@0 767 mLastRootMetrics.mResolution.scale);
michael@0 768 HandlePossibleViewportChange();
michael@0 769 }
michael@0 770 }
michael@0 771 }
michael@0 772 }
michael@0 773
michael@0 774 return NS_OK;
michael@0 775 }
michael@0 776
michael@0 777 NS_IMETHODIMP
michael@0 778 TabChild::OnStateChange(nsIWebProgress* aWebProgress,
michael@0 779 nsIRequest* aRequest,
michael@0 780 uint32_t aStateFlags,
michael@0 781 nsresult aStatus)
michael@0 782 {
michael@0 783 NS_NOTREACHED("not implemented in TabChild");
michael@0 784 return NS_OK;
michael@0 785 }
michael@0 786
michael@0 787 NS_IMETHODIMP
michael@0 788 TabChild::OnProgressChange(nsIWebProgress* aWebProgress,
michael@0 789 nsIRequest* aRequest,
michael@0 790 int32_t aCurSelfProgress,
michael@0 791 int32_t aMaxSelfProgress,
michael@0 792 int32_t aCurTotalProgress,
michael@0 793 int32_t aMaxTotalProgress)
michael@0 794 {
michael@0 795 NS_NOTREACHED("not implemented in TabChild");
michael@0 796 return NS_OK;
michael@0 797 }
michael@0 798
michael@0 799 NS_IMETHODIMP
michael@0 800 TabChild::OnLocationChange(nsIWebProgress* aWebProgress,
michael@0 801 nsIRequest* aRequest,
michael@0 802 nsIURI *aLocation,
michael@0 803 uint32_t aFlags)
michael@0 804 {
michael@0 805 if (!IsAsyncPanZoomEnabled()) {
michael@0 806 return NS_OK;
michael@0 807 }
michael@0 808
michael@0 809 nsCOMPtr<nsIDOMWindow> window;
michael@0 810 aWebProgress->GetDOMWindow(getter_AddRefs(window));
michael@0 811 if (!window) {
michael@0 812 return NS_OK;
michael@0 813 }
michael@0 814
michael@0 815 nsCOMPtr<nsIDOMDocument> progressDoc;
michael@0 816 window->GetDocument(getter_AddRefs(progressDoc));
michael@0 817 if (!progressDoc) {
michael@0 818 return NS_OK;
michael@0 819 }
michael@0 820
michael@0 821 nsCOMPtr<nsIDOMDocument> domDoc;
michael@0 822 WebNavigation()->GetDocument(getter_AddRefs(domDoc));
michael@0 823 if (!domDoc || !SameCOMIdentity(domDoc, progressDoc)) {
michael@0 824 return NS_OK;
michael@0 825 }
michael@0 826
michael@0 827 nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID));
michael@0 828 if (!urifixup) {
michael@0 829 return NS_OK;
michael@0 830 }
michael@0 831
michael@0 832 nsCOMPtr<nsIURI> exposableURI;
michael@0 833 urifixup->CreateExposableURI(aLocation, getter_AddRefs(exposableURI));
michael@0 834 if (!exposableURI) {
michael@0 835 return NS_OK;
michael@0 836 }
michael@0 837
michael@0 838 if (!(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT)) {
michael@0 839 mContentDocumentIsDisplayed = false;
michael@0 840 } else if (mLastURI != nullptr) {
michael@0 841 bool exposableEqualsLast, exposableEqualsNew;
michael@0 842 exposableURI->Equals(mLastURI.get(), &exposableEqualsLast);
michael@0 843 exposableURI->Equals(aLocation, &exposableEqualsNew);
michael@0 844 if (exposableEqualsLast && !exposableEqualsNew) {
michael@0 845 mContentDocumentIsDisplayed = false;
michael@0 846 }
michael@0 847 }
michael@0 848
michael@0 849 return NS_OK;
michael@0 850 }
michael@0 851
michael@0 852 NS_IMETHODIMP
michael@0 853 TabChild::OnStatusChange(nsIWebProgress* aWebProgress,
michael@0 854 nsIRequest* aRequest,
michael@0 855 nsresult aStatus,
michael@0 856 const char16_t* aMessage)
michael@0 857 {
michael@0 858 NS_NOTREACHED("not implemented in TabChild");
michael@0 859 return NS_OK;
michael@0 860 }
michael@0 861
michael@0 862 NS_IMETHODIMP
michael@0 863 TabChild::OnSecurityChange(nsIWebProgress* aWebProgress,
michael@0 864 nsIRequest* aRequest,
michael@0 865 uint32_t aState)
michael@0 866 {
michael@0 867 NS_NOTREACHED("not implemented in TabChild");
michael@0 868 return NS_OK;
michael@0 869 }
michael@0 870
michael@0 871 bool
michael@0 872 TabChild::DoUpdateZoomConstraints(const uint32_t& aPresShellId,
michael@0 873 const ViewID& aViewId,
michael@0 874 const bool& aIsRoot,
michael@0 875 const ZoomConstraints& aConstraints)
michael@0 876 {
michael@0 877 return SendUpdateZoomConstraints(aPresShellId,
michael@0 878 aViewId,
michael@0 879 aIsRoot,
michael@0 880 aConstraints);
michael@0 881 }
michael@0 882
michael@0 883 nsresult
michael@0 884 TabChild::Init()
michael@0 885 {
michael@0 886 nsCOMPtr<nsIWebBrowser> webBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
michael@0 887 if (!webBrowser) {
michael@0 888 NS_ERROR("Couldn't create a nsWebBrowser?");
michael@0 889 return NS_ERROR_FAILURE;
michael@0 890 }
michael@0 891
michael@0 892 webBrowser->SetContainerWindow(this);
michael@0 893 mWebNav = do_QueryInterface(webBrowser);
michael@0 894 NS_ASSERTION(mWebNav, "nsWebBrowser doesn't implement nsIWebNavigation?");
michael@0 895
michael@0 896 nsCOMPtr<nsIDocShellTreeItem> docShellItem(do_QueryInterface(WebNavigation()));
michael@0 897 docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
michael@0 898
michael@0 899 nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
michael@0 900 if (!baseWindow) {
michael@0 901 NS_ERROR("mWebNav doesn't QI to nsIBaseWindow");
michael@0 902 return NS_ERROR_FAILURE;
michael@0 903 }
michael@0 904
michael@0 905 mWidget = nsIWidget::CreatePuppetWidget(this);
michael@0 906 if (!mWidget) {
michael@0 907 NS_ERROR("couldn't create fake widget");
michael@0 908 return NS_ERROR_FAILURE;
michael@0 909 }
michael@0 910 mWidget->Create(
michael@0 911 nullptr, 0, // no parents
michael@0 912 nsIntRect(nsIntPoint(0, 0), nsIntSize(0, 0)),
michael@0 913 nullptr, // HandleWidgetEvent
michael@0 914 nullptr // nsDeviceContext
michael@0 915 );
michael@0 916
michael@0 917 baseWindow->InitWindow(0, mWidget, 0, 0, 0, 0);
michael@0 918 baseWindow->Create();
michael@0 919
michael@0 920 NotifyTabContextUpdated();
michael@0 921
michael@0 922 // IPC uses a WebBrowser object for which DNS prefetching is turned off
michael@0 923 // by default. But here we really want it, so enable it explicitly
michael@0 924 nsCOMPtr<nsIWebBrowserSetup> webBrowserSetup =
michael@0 925 do_QueryInterface(baseWindow);
michael@0 926 if (webBrowserSetup) {
michael@0 927 webBrowserSetup->SetProperty(nsIWebBrowserSetup::SETUP_ALLOW_DNS_PREFETCH,
michael@0 928 true);
michael@0 929 } else {
michael@0 930 NS_WARNING("baseWindow doesn't QI to nsIWebBrowserSetup, skipping "
michael@0 931 "DNS prefetching enable step.");
michael@0 932 }
michael@0 933
michael@0 934 nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
michael@0 935 MOZ_ASSERT(docShell);
michael@0 936
michael@0 937 docShell->SetAffectPrivateSessionLifetime(
michael@0 938 mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME);
michael@0 939 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(WebNavigation());
michael@0 940 MOZ_ASSERT(loadContext);
michael@0 941 loadContext->SetPrivateBrowsing(
michael@0 942 mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW);
michael@0 943 loadContext->SetRemoteTabs(
michael@0 944 mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW);
michael@0 945
michael@0 946 nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
michael@0 947 NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE);
michael@0 948 webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION);
michael@0 949
michael@0 950 // Few lines before, baseWindow->Create() will end up creating a new
michael@0 951 // window root in nsGlobalWindow::SetDocShell.
michael@0 952 // Then this chrome event handler, will be inherited to inner windows.
michael@0 953 // We want to also set it to the docshell so that inner windows
michael@0 954 // and any code that has access to the docshell
michael@0 955 // can all listen to the same chrome event handler.
michael@0 956 // XXX: ideally, we would set a chrome event handler earlier,
michael@0 957 // and all windows, even the root one, will use the docshell one.
michael@0 958 nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation());
michael@0 959 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
michael@0 960 nsCOMPtr<EventTarget> chromeHandler =
michael@0 961 do_QueryInterface(window->GetChromeEventHandler());
michael@0 962 docShell->SetChromeEventHandler(chromeHandler);
michael@0 963
michael@0 964 return NS_OK;
michael@0 965 }
michael@0 966
michael@0 967 void
michael@0 968 TabChild::NotifyTabContextUpdated()
michael@0 969 {
michael@0 970 nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
michael@0 971 MOZ_ASSERT(docShell);
michael@0 972
michael@0 973 if (docShell) {
michael@0 974 // nsDocShell will do the right thing if we pass NO_APP_ID or
michael@0 975 // UNKNOWN_APP_ID for aOwnOrContainingAppId.
michael@0 976 if (IsBrowserElement()) {
michael@0 977 docShell->SetIsBrowserInsideApp(BrowserOwnerAppId());
michael@0 978 } else {
michael@0 979 docShell->SetIsApp(OwnAppId());
michael@0 980 }
michael@0 981 }
michael@0 982 }
michael@0 983
michael@0 984 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChild)
michael@0 985 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
michael@0 986 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2)
michael@0 987 NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
michael@0 988 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus)
michael@0 989 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
michael@0 990 NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
michael@0 991 NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
michael@0 992 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
michael@0 993 NS_INTERFACE_MAP_ENTRY(nsITabChild)
michael@0 994 NS_INTERFACE_MAP_ENTRY(nsIObserver)
michael@0 995 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
michael@0 996 NS_INTERFACE_MAP_ENTRY(nsITooltipListener)
michael@0 997 NS_INTERFACE_MAP_END_INHERITING(TabChildBase)
michael@0 998
michael@0 999 NS_IMPL_ADDREF_INHERITED(TabChild, TabChildBase);
michael@0 1000 NS_IMPL_RELEASE_INHERITED(TabChild, TabChildBase);
michael@0 1001
michael@0 1002 NS_IMETHODIMP
michael@0 1003 TabChild::SetStatus(uint32_t aStatusType, const char16_t* aStatus)
michael@0 1004 {
michael@0 1005 return SetStatusWithContext(aStatusType,
michael@0 1006 aStatus ? static_cast<const nsString &>(nsDependentString(aStatus))
michael@0 1007 : EmptyString(),
michael@0 1008 nullptr);
michael@0 1009 }
michael@0 1010
michael@0 1011 NS_IMETHODIMP
michael@0 1012 TabChild::GetWebBrowser(nsIWebBrowser** aWebBrowser)
michael@0 1013 {
michael@0 1014 NS_NOTREACHED("TabChild::GetWebBrowser not supported in TabChild");
michael@0 1015
michael@0 1016 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1017 }
michael@0 1018
michael@0 1019 NS_IMETHODIMP
michael@0 1020 TabChild::SetWebBrowser(nsIWebBrowser* aWebBrowser)
michael@0 1021 {
michael@0 1022 NS_NOTREACHED("TabChild::SetWebBrowser not supported in TabChild");
michael@0 1023
michael@0 1024 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1025 }
michael@0 1026
michael@0 1027 NS_IMETHODIMP
michael@0 1028 TabChild::GetChromeFlags(uint32_t* aChromeFlags)
michael@0 1029 {
michael@0 1030 *aChromeFlags = mChromeFlags;
michael@0 1031 return NS_OK;
michael@0 1032 }
michael@0 1033
michael@0 1034 NS_IMETHODIMP
michael@0 1035 TabChild::SetChromeFlags(uint32_t aChromeFlags)
michael@0 1036 {
michael@0 1037 NS_NOTREACHED("trying to SetChromeFlags from content process?");
michael@0 1038
michael@0 1039 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1040 }
michael@0 1041
michael@0 1042 NS_IMETHODIMP
michael@0 1043 TabChild::DestroyBrowserWindow()
michael@0 1044 {
michael@0 1045 NS_NOTREACHED("TabChild::DestroyBrowserWindow not supported in TabChild");
michael@0 1046
michael@0 1047 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1048 }
michael@0 1049
michael@0 1050 NS_IMETHODIMP
michael@0 1051 TabChild::SizeBrowserTo(int32_t aCX, int32_t aCY)
michael@0 1052 {
michael@0 1053 NS_NOTREACHED("TabChild::SizeBrowserTo not supported in TabChild");
michael@0 1054
michael@0 1055 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1056 }
michael@0 1057
michael@0 1058 NS_IMETHODIMP
michael@0 1059 TabChild::ShowAsModal()
michael@0 1060 {
michael@0 1061 NS_NOTREACHED("TabChild::ShowAsModal not supported in TabChild");
michael@0 1062
michael@0 1063 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1064 }
michael@0 1065
michael@0 1066 NS_IMETHODIMP
michael@0 1067 TabChild::IsWindowModal(bool* aRetVal)
michael@0 1068 {
michael@0 1069 *aRetVal = false;
michael@0 1070 return NS_OK;
michael@0 1071 }
michael@0 1072
michael@0 1073 NS_IMETHODIMP
michael@0 1074 TabChild::ExitModalEventLoop(nsresult aStatus)
michael@0 1075 {
michael@0 1076 NS_NOTREACHED("TabChild::ExitModalEventLoop not supported in TabChild");
michael@0 1077
michael@0 1078 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1079 }
michael@0 1080
michael@0 1081 NS_IMETHODIMP
michael@0 1082 TabChild::SetStatusWithContext(uint32_t aStatusType,
michael@0 1083 const nsAString& aStatusText,
michael@0 1084 nsISupports* aStatusContext)
michael@0 1085 {
michael@0 1086 // We can only send the status after the ipc machinery is set up,
michael@0 1087 // mRemoteFrame is a good indicator.
michael@0 1088 if (mRemoteFrame)
michael@0 1089 SendSetStatus(aStatusType, nsString(aStatusText));
michael@0 1090 return NS_OK;
michael@0 1091 }
michael@0 1092
michael@0 1093 NS_IMETHODIMP
michael@0 1094 TabChild::SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY,
michael@0 1095 int32_t aCx, int32_t aCy)
michael@0 1096 {
michael@0 1097 NS_NOTREACHED("TabChild::SetDimensions not supported in TabChild");
michael@0 1098
michael@0 1099 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1100 }
michael@0 1101
michael@0 1102 NS_IMETHODIMP
michael@0 1103 TabChild::GetDimensions(uint32_t aFlags, int32_t* aX,
michael@0 1104 int32_t* aY, int32_t* aCx, int32_t* aCy)
michael@0 1105 {
michael@0 1106 if (aX) {
michael@0 1107 *aX = mOuterRect.x;
michael@0 1108 }
michael@0 1109 if (aY) {
michael@0 1110 *aY = mOuterRect.y;
michael@0 1111 }
michael@0 1112 if (aCx) {
michael@0 1113 *aCx = mOuterRect.width;
michael@0 1114 }
michael@0 1115 if (aCy) {
michael@0 1116 *aCy = mOuterRect.height;
michael@0 1117 }
michael@0 1118
michael@0 1119 return NS_OK;
michael@0 1120 }
michael@0 1121
michael@0 1122 NS_IMETHODIMP
michael@0 1123 TabChild::SetFocus()
michael@0 1124 {
michael@0 1125 NS_WARNING("TabChild::SetFocus not supported in TabChild");
michael@0 1126
michael@0 1127 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1128 }
michael@0 1129
michael@0 1130 NS_IMETHODIMP
michael@0 1131 TabChild::GetVisibility(bool* aVisibility)
michael@0 1132 {
michael@0 1133 *aVisibility = true;
michael@0 1134 return NS_OK;
michael@0 1135 }
michael@0 1136
michael@0 1137 NS_IMETHODIMP
michael@0 1138 TabChild::SetVisibility(bool aVisibility)
michael@0 1139 {
michael@0 1140 // should the platform support this? Bug 666365
michael@0 1141 return NS_OK;
michael@0 1142 }
michael@0 1143
michael@0 1144 NS_IMETHODIMP
michael@0 1145 TabChild::GetTitle(char16_t** aTitle)
michael@0 1146 {
michael@0 1147 NS_NOTREACHED("TabChild::GetTitle not supported in TabChild");
michael@0 1148
michael@0 1149 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1150 }
michael@0 1151
michael@0 1152 NS_IMETHODIMP
michael@0 1153 TabChild::SetTitle(const char16_t* aTitle)
michael@0 1154 {
michael@0 1155 // JavaScript sends the "DOMTitleChanged" event to the parent
michael@0 1156 // via the message manager.
michael@0 1157 return NS_OK;
michael@0 1158 }
michael@0 1159
michael@0 1160 NS_IMETHODIMP
michael@0 1161 TabChild::GetSiteWindow(void** aSiteWindow)
michael@0 1162 {
michael@0 1163 NS_NOTREACHED("TabChild::GetSiteWindow not supported in TabChild");
michael@0 1164
michael@0 1165 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1166 }
michael@0 1167
michael@0 1168 NS_IMETHODIMP
michael@0 1169 TabChild::Blur()
michael@0 1170 {
michael@0 1171 NS_WARNING("TabChild::Blur not supported in TabChild");
michael@0 1172
michael@0 1173 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1174 }
michael@0 1175
michael@0 1176 NS_IMETHODIMP
michael@0 1177 TabChild::FocusNextElement()
michael@0 1178 {
michael@0 1179 SendMoveFocus(true);
michael@0 1180 return NS_OK;
michael@0 1181 }
michael@0 1182
michael@0 1183 NS_IMETHODIMP
michael@0 1184 TabChild::FocusPrevElement()
michael@0 1185 {
michael@0 1186 SendMoveFocus(false);
michael@0 1187 return NS_OK;
michael@0 1188 }
michael@0 1189
michael@0 1190 NS_IMETHODIMP
michael@0 1191 TabChild::GetInterface(const nsIID & aIID, void **aSink)
michael@0 1192 {
michael@0 1193 // XXXbz should we restrict the set of interfaces we hand out here?
michael@0 1194 // See bug 537429
michael@0 1195 return QueryInterface(aIID, aSink);
michael@0 1196 }
michael@0 1197
michael@0 1198 NS_IMETHODIMP
michael@0 1199 TabChild::ProvideWindow(nsIDOMWindow* aParent, uint32_t aChromeFlags,
michael@0 1200 bool aCalledFromJS,
michael@0 1201 bool aPositionSpecified, bool aSizeSpecified,
michael@0 1202 nsIURI* aURI, const nsAString& aName,
michael@0 1203 const nsACString& aFeatures, bool* aWindowIsNew,
michael@0 1204 nsIDOMWindow** aReturn)
michael@0 1205 {
michael@0 1206 *aReturn = nullptr;
michael@0 1207
michael@0 1208 // If aParent is inside an <iframe mozbrowser> or <iframe mozapp> and this
michael@0 1209 // isn't a request to open a modal-type window, we're going to create a new
michael@0 1210 // <iframe mozbrowser/mozapp> and return its window here.
michael@0 1211 nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
michael@0 1212 if (docshell && docshell->GetIsInBrowserOrApp() &&
michael@0 1213 !(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL |
michael@0 1214 nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
michael@0 1215 nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) {
michael@0 1216
michael@0 1217 // Note that BrowserFrameProvideWindow may return NS_ERROR_ABORT if the
michael@0 1218 // open window call was canceled. It's important that we pass this error
michael@0 1219 // code back to our caller.
michael@0 1220 return BrowserFrameProvideWindow(aParent, aURI, aName, aFeatures,
michael@0 1221 aWindowIsNew, aReturn);
michael@0 1222 }
michael@0 1223
michael@0 1224 // Otherwise, create a new top-level window.
michael@0 1225 PBrowserChild* newChild;
michael@0 1226 if (!CallCreateWindow(&newChild)) {
michael@0 1227 return NS_ERROR_NOT_AVAILABLE;
michael@0 1228 }
michael@0 1229
michael@0 1230 *aWindowIsNew = true;
michael@0 1231 nsCOMPtr<nsIDOMWindow> win =
michael@0 1232 do_GetInterface(static_cast<TabChild*>(newChild)->WebNavigation());
michael@0 1233 win.forget(aReturn);
michael@0 1234 return NS_OK;
michael@0 1235 }
michael@0 1236
michael@0 1237 nsresult
michael@0 1238 TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
michael@0 1239 nsIURI* aURI,
michael@0 1240 const nsAString& aName,
michael@0 1241 const nsACString& aFeatures,
michael@0 1242 bool* aWindowIsNew,
michael@0 1243 nsIDOMWindow** aReturn)
michael@0 1244 {
michael@0 1245 *aReturn = nullptr;
michael@0 1246
michael@0 1247 nsRefPtr<TabChild> newChild =
michael@0 1248 new TabChild(ContentChild::GetSingleton(),
michael@0 1249 /* TabContext */ *this, /* chromeFlags */ 0);
michael@0 1250 if (!NS_SUCCEEDED(newChild->Init())) {
michael@0 1251 return NS_ERROR_ABORT;
michael@0 1252 }
michael@0 1253
michael@0 1254 // We must use PopupIPCTabContext here; ContentParent will not accept the
michael@0 1255 // result of this->AsIPCTabContext() (which will be a
michael@0 1256 // BrowserFrameIPCTabContext or an AppFrameIPCTabContext), for security
michael@0 1257 // reasons.
michael@0 1258 PopupIPCTabContext context;
michael@0 1259 context.openerChild() = this;
michael@0 1260 context.isBrowserElement() = IsBrowserElement();
michael@0 1261
michael@0 1262 unused << Manager()->SendPBrowserConstructor(
michael@0 1263 // We release this ref in DeallocPBrowserChild
michael@0 1264 nsRefPtr<TabChild>(newChild).forget().take(),
michael@0 1265 IPCTabContext(context, mScrolling), /* chromeFlags */ 0);
michael@0 1266
michael@0 1267 nsAutoCString spec;
michael@0 1268 if (aURI) {
michael@0 1269 aURI->GetSpec(spec);
michael@0 1270 }
michael@0 1271
michael@0 1272 NS_ConvertUTF8toUTF16 url(spec);
michael@0 1273 nsString name(aName);
michael@0 1274 NS_ConvertUTF8toUTF16 features(aFeatures);
michael@0 1275 newChild->SendBrowserFrameOpenWindow(this, url, name,
michael@0 1276 features, aWindowIsNew);
michael@0 1277 if (!*aWindowIsNew) {
michael@0 1278 PBrowserChild::Send__delete__(newChild);
michael@0 1279 return NS_ERROR_ABORT;
michael@0 1280 }
michael@0 1281
michael@0 1282 // Unfortunately we don't get a window unless we've shown the frame. That's
michael@0 1283 // pretty bogus; see bug 763602.
michael@0 1284 newChild->DoFakeShow();
michael@0 1285
michael@0 1286 nsCOMPtr<nsIDOMWindow> win = do_GetInterface(newChild->WebNavigation());
michael@0 1287 win.forget(aReturn);
michael@0 1288 return NS_OK;
michael@0 1289 }
michael@0 1290
michael@0 1291 #ifdef DEBUG
michael@0 1292 PContentPermissionRequestChild*
michael@0 1293 TabChild:: SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
michael@0 1294 const InfallibleTArray<PermissionRequest>& aRequests,
michael@0 1295 const IPC::Principal& aPrincipal)
michael@0 1296 {
michael@0 1297 PCOMContentPermissionRequestChild* child = static_cast<PCOMContentPermissionRequestChild*>(aActor);
michael@0 1298 PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aRequests, aPrincipal);
michael@0 1299 child->mIPCOpen = true;
michael@0 1300 return request;
michael@0 1301 }
michael@0 1302 #endif /* DEBUG */
michael@0 1303
michael@0 1304 void
michael@0 1305 TabChild::DestroyWindow()
michael@0 1306 {
michael@0 1307 nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
michael@0 1308 if (baseWindow)
michael@0 1309 baseWindow->Destroy();
michael@0 1310
michael@0 1311 // NB: the order of mWidget->Destroy() and mRemoteFrame->Destroy()
michael@0 1312 // is important: we want to kill off remote layers before their
michael@0 1313 // frames
michael@0 1314 if (mWidget) {
michael@0 1315 mWidget->Destroy();
michael@0 1316 }
michael@0 1317
michael@0 1318 if (mRemoteFrame) {
michael@0 1319 mRemoteFrame->Destroy();
michael@0 1320 mRemoteFrame = nullptr;
michael@0 1321 }
michael@0 1322
michael@0 1323
michael@0 1324 if (mLayersId != 0) {
michael@0 1325 MOZ_ASSERT(sTabChildren);
michael@0 1326 sTabChildren->Remove(mLayersId);
michael@0 1327 if (!sTabChildren->Count()) {
michael@0 1328 delete sTabChildren;
michael@0 1329 sTabChildren = nullptr;
michael@0 1330 }
michael@0 1331 mLayersId = 0;
michael@0 1332 }
michael@0 1333 }
michael@0 1334
michael@0 1335 bool
michael@0 1336 TabChild::UseDirectCompositor()
michael@0 1337 {
michael@0 1338 return !!CompositorChild::Get();
michael@0 1339 }
michael@0 1340
michael@0 1341 void
michael@0 1342 TabChild::ActorDestroy(ActorDestroyReason why)
michael@0 1343 {
michael@0 1344 if (mTabChildGlobal) {
michael@0 1345 // The messageManager relays messages via the TabChild which
michael@0 1346 // no longer exists.
michael@0 1347 static_cast<nsFrameMessageManager*>
michael@0 1348 (mTabChildGlobal->mMessageManager.get())->Disconnect();
michael@0 1349 mTabChildGlobal->mMessageManager = nullptr;
michael@0 1350 }
michael@0 1351 }
michael@0 1352
michael@0 1353 TabChild::~TabChild()
michael@0 1354 {
michael@0 1355 DestroyWindow();
michael@0 1356
michael@0 1357 nsCOMPtr<nsIWebBrowser> webBrowser = do_QueryInterface(WebNavigation());
michael@0 1358 if (webBrowser) {
michael@0 1359 webBrowser->SetContainerWindow(nullptr);
michael@0 1360 }
michael@0 1361 }
michael@0 1362
michael@0 1363 void
michael@0 1364 TabChild::SetProcessNameToAppName()
michael@0 1365 {
michael@0 1366 nsCOMPtr<mozIApplication> app = GetOwnApp();
michael@0 1367 if (!app) {
michael@0 1368 return;
michael@0 1369 }
michael@0 1370
michael@0 1371 nsAutoString appName;
michael@0 1372 nsresult rv = app->GetName(appName);
michael@0 1373 if (NS_FAILED(rv)) {
michael@0 1374 NS_WARNING("Failed to retrieve app name");
michael@0 1375 return;
michael@0 1376 }
michael@0 1377
michael@0 1378 ContentChild::GetSingleton()->SetProcessName(appName, true);
michael@0 1379 }
michael@0 1380
michael@0 1381 bool
michael@0 1382 TabChild::IsRootContentDocument()
michael@0 1383 {
michael@0 1384 // A TabChild is a "root content document" if it's
michael@0 1385 //
michael@0 1386 // - <iframe mozapp> not inside another <iframe mozapp>,
michael@0 1387 // - <iframe mozbrowser> (not mozapp), or
michael@0 1388 // - a vanilla remote frame (<html:iframe remote=true> or <xul:browser
michael@0 1389 // remote=true>).
michael@0 1390 //
michael@0 1391 // Put another way, an iframe is /not/ a "root content document" iff it's a
michael@0 1392 // mozapp inside a mozapp. (This corresponds exactly to !HasAppOwnerApp.)
michael@0 1393 //
michael@0 1394 // Note that we're lying through our teeth here (thus the scare quotes).
michael@0 1395 // <html:iframe remote=true> or <xul:browser remote=true> inside another
michael@0 1396 // content iframe is not actually a root content document, but we say it is.
michael@0 1397 //
michael@0 1398 // We do this because we make a remote frame opaque iff
michael@0 1399 // IsRootContentDocument(), and making vanilla remote frames transparent
michael@0 1400 // breaks our remote reftests.
michael@0 1401
michael@0 1402 return !HasAppOwnerApp();
michael@0 1403 }
michael@0 1404
michael@0 1405 bool
michael@0 1406 TabChild::RecvLoadURL(const nsCString& uri)
michael@0 1407 {
michael@0 1408 SetProcessNameToAppName();
michael@0 1409
michael@0 1410 nsresult rv = WebNavigation()->LoadURI(NS_ConvertUTF8toUTF16(uri).get(),
michael@0 1411 nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
michael@0 1412 nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_OWNER,
michael@0 1413 nullptr, nullptr, nullptr);
michael@0 1414 if (NS_FAILED(rv)) {
michael@0 1415 NS_WARNING("WebNavigation()->LoadURI failed. Eating exception, what else can I do?");
michael@0 1416 }
michael@0 1417
michael@0 1418 #ifdef MOZ_CRASHREPORTER
michael@0 1419 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("URL"), uri);
michael@0 1420 #endif
michael@0 1421
michael@0 1422 return true;
michael@0 1423 }
michael@0 1424
michael@0 1425 bool
michael@0 1426 TabChild::RecvCacheFileDescriptor(const nsString& aPath,
michael@0 1427 const FileDescriptor& aFileDescriptor)
michael@0 1428 {
michael@0 1429 MOZ_ASSERT(NS_IsMainThread());
michael@0 1430 MOZ_ASSERT(!aPath.IsEmpty());
michael@0 1431 MOZ_ASSERT(!mAppPackageFileDescriptorRecved);
michael@0 1432
michael@0 1433 mAppPackageFileDescriptorRecved = true;
michael@0 1434
michael@0 1435 // aFileDescriptor may be invalid here, but the callback will choose how to
michael@0 1436 // handle it.
michael@0 1437
michael@0 1438 // First see if we already have a request for this path.
michael@0 1439 const CachedFileDescriptorInfo search(aPath);
michael@0 1440 uint32_t index =
michael@0 1441 mCachedFileDescriptorInfos.IndexOf(search, 0,
michael@0 1442 search.PathOnlyComparator());
michael@0 1443 if (index == mCachedFileDescriptorInfos.NoIndex) {
michael@0 1444 // We haven't had any requests for this path yet. Assume that we will
michael@0 1445 // in a little while and save the file descriptor here.
michael@0 1446 mCachedFileDescriptorInfos.AppendElement(
michael@0 1447 new CachedFileDescriptorInfo(aPath, aFileDescriptor));
michael@0 1448 return true;
michael@0 1449 }
michael@0 1450
michael@0 1451 nsAutoPtr<CachedFileDescriptorInfo>& info =
michael@0 1452 mCachedFileDescriptorInfos[index];
michael@0 1453
michael@0 1454 MOZ_ASSERT(info);
michael@0 1455 MOZ_ASSERT(info->mPath == aPath);
michael@0 1456 MOZ_ASSERT(!info->mFileDescriptor.IsValid());
michael@0 1457 MOZ_ASSERT(info->mCallback);
michael@0 1458
michael@0 1459 // If this callback has been canceled then we can simply close the file
michael@0 1460 // descriptor and forget about the callback.
michael@0 1461 if (info->mCanceled) {
michael@0 1462 // Only close if this is a valid file descriptor.
michael@0 1463 if (aFileDescriptor.IsValid()) {
michael@0 1464 nsRefPtr<CloseFileRunnable> runnable =
michael@0 1465 new CloseFileRunnable(aFileDescriptor);
michael@0 1466 runnable->Dispatch();
michael@0 1467 }
michael@0 1468 } else {
michael@0 1469 // Not canceled so fire the callback.
michael@0 1470 info->mFileDescriptor = aFileDescriptor;
michael@0 1471
michael@0 1472 // We don't need a runnable here because we should already be at the top
michael@0 1473 // of the event loop. Just fire immediately.
michael@0 1474 info->FireCallback();
michael@0 1475 }
michael@0 1476
michael@0 1477 mCachedFileDescriptorInfos.RemoveElementAt(index);
michael@0 1478 return true;
michael@0 1479 }
michael@0 1480
michael@0 1481 bool
michael@0 1482 TabChild::GetCachedFileDescriptor(const nsAString& aPath,
michael@0 1483 nsICachedFileDescriptorListener* aCallback)
michael@0 1484 {
michael@0 1485 MOZ_ASSERT(NS_IsMainThread());
michael@0 1486 MOZ_ASSERT(!aPath.IsEmpty());
michael@0 1487 MOZ_ASSERT(aCallback);
michael@0 1488
michael@0 1489 // First see if we've already received a cached file descriptor for this
michael@0 1490 // path.
michael@0 1491 const CachedFileDescriptorInfo search(aPath);
michael@0 1492 uint32_t index =
michael@0 1493 mCachedFileDescriptorInfos.IndexOf(search, 0,
michael@0 1494 search.PathOnlyComparator());
michael@0 1495 if (index == mCachedFileDescriptorInfos.NoIndex) {
michael@0 1496 // We haven't received a file descriptor for this path yet. Assume that
michael@0 1497 // we will in a little while and save the request here.
michael@0 1498 if (!mAppPackageFileDescriptorRecved) {
michael@0 1499 mCachedFileDescriptorInfos.AppendElement(
michael@0 1500 new CachedFileDescriptorInfo(aPath, aCallback));
michael@0 1501 }
michael@0 1502 return false;
michael@0 1503 }
michael@0 1504
michael@0 1505 nsAutoPtr<CachedFileDescriptorInfo>& info =
michael@0 1506 mCachedFileDescriptorInfos[index];
michael@0 1507
michael@0 1508 MOZ_ASSERT(info);
michael@0 1509 MOZ_ASSERT(info->mPath == aPath);
michael@0 1510
michael@0 1511 // If we got a previous request for this file descriptor that was then
michael@0 1512 // canceled, insert the new request ahead of the old in the queue so that
michael@0 1513 // it will be serviced first.
michael@0 1514 if (info->mCanceled) {
michael@0 1515 // This insertion will change the array and invalidate |info|, so
michael@0 1516 // be careful not to touch |info| after this.
michael@0 1517 mCachedFileDescriptorInfos.InsertElementAt(index,
michael@0 1518 new CachedFileDescriptorInfo(aPath, aCallback));
michael@0 1519 return false;
michael@0 1520 }
michael@0 1521
michael@0 1522 MOZ_ASSERT(!info->mCallback);
michael@0 1523 info->mCallback = aCallback;
michael@0 1524
michael@0 1525 nsRefPtr<CachedFileDescriptorCallbackRunnable> runnable =
michael@0 1526 new CachedFileDescriptorCallbackRunnable(info.forget());
michael@0 1527 runnable->Dispatch();
michael@0 1528
michael@0 1529 mCachedFileDescriptorInfos.RemoveElementAt(index);
michael@0 1530 return true;
michael@0 1531 }
michael@0 1532
michael@0 1533 void
michael@0 1534 TabChild::CancelCachedFileDescriptorCallback(
michael@0 1535 const nsAString& aPath,
michael@0 1536 nsICachedFileDescriptorListener* aCallback)
michael@0 1537 {
michael@0 1538 MOZ_ASSERT(NS_IsMainThread());
michael@0 1539 MOZ_ASSERT(!aPath.IsEmpty());
michael@0 1540 MOZ_ASSERT(aCallback);
michael@0 1541
michael@0 1542 if (mAppPackageFileDescriptorRecved) {
michael@0 1543 // Already received cached file descriptor for the app package. Nothing to do here.
michael@0 1544 return;
michael@0 1545 }
michael@0 1546
michael@0 1547 const CachedFileDescriptorInfo search(aPath, aCallback);
michael@0 1548 uint32_t index =
michael@0 1549 mCachedFileDescriptorInfos.IndexOf(search, 0,
michael@0 1550 search.PathAndCallbackComparator());
michael@0 1551 if (index == mCachedFileDescriptorInfos.NoIndex) {
michael@0 1552 // Nothing to do here.
michael@0 1553 return;
michael@0 1554 }
michael@0 1555
michael@0 1556 nsAutoPtr<CachedFileDescriptorInfo>& info =
michael@0 1557 mCachedFileDescriptorInfos[index];
michael@0 1558
michael@0 1559 MOZ_ASSERT(info);
michael@0 1560 MOZ_ASSERT(info->mPath == aPath);
michael@0 1561 MOZ_ASSERT(!info->mFileDescriptor.IsValid());
michael@0 1562 MOZ_ASSERT(info->mCallback == aCallback);
michael@0 1563 MOZ_ASSERT(!info->mCanceled);
michael@0 1564
michael@0 1565 // Set this flag so that we will close the file descriptor when it arrives.
michael@0 1566 info->mCanceled = true;
michael@0 1567 }
michael@0 1568
michael@0 1569 void
michael@0 1570 TabChild::DoFakeShow()
michael@0 1571 {
michael@0 1572 RecvShow(nsIntSize(0, 0));
michael@0 1573 mDidFakeShow = true;
michael@0 1574 }
michael@0 1575
michael@0 1576 bool
michael@0 1577 TabChild::RecvShow(const nsIntSize& size)
michael@0 1578 {
michael@0 1579
michael@0 1580 if (mDidFakeShow) {
michael@0 1581 return true;
michael@0 1582 }
michael@0 1583
michael@0 1584 nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
michael@0 1585 if (!baseWindow) {
michael@0 1586 NS_ERROR("WebNavigation() doesn't QI to nsIBaseWindow");
michael@0 1587 return false;
michael@0 1588 }
michael@0 1589
michael@0 1590 if (!InitRenderingState()) {
michael@0 1591 // We can fail to initialize our widget if the <browser
michael@0 1592 // remote> has already been destroyed, and we couldn't hook
michael@0 1593 // into the parent-process's layer system. That's not a fatal
michael@0 1594 // error.
michael@0 1595 return true;
michael@0 1596 }
michael@0 1597
michael@0 1598 baseWindow->SetVisibility(true);
michael@0 1599
michael@0 1600 return InitTabChildGlobal();
michael@0 1601 }
michael@0 1602
michael@0 1603 bool
michael@0 1604 TabChild::RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size, const ScreenOrientation& orientation)
michael@0 1605 {
michael@0 1606 if (!mRemoteFrame) {
michael@0 1607 return true;
michael@0 1608 }
michael@0 1609
michael@0 1610 mOuterRect.x = rect.x;
michael@0 1611 mOuterRect.y = rect.y;
michael@0 1612 mOuterRect.width = rect.width;
michael@0 1613 mOuterRect.height = rect.height;
michael@0 1614
michael@0 1615 bool initialSizing = !HasValidInnerSize()
michael@0 1616 && (size.width != 0 && size.height != 0);
michael@0 1617
michael@0 1618 mOrientation = orientation;
michael@0 1619 mInnerSize = ScreenIntSize::FromUnknownSize(
michael@0 1620 gfx::IntSize(size.width, size.height));
michael@0 1621 mWidget->Resize(0, 0, size.width, size.height,
michael@0 1622 true);
michael@0 1623
michael@0 1624 nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
michael@0 1625 baseWin->SetPositionAndSize(0, 0, size.width, size.height,
michael@0 1626 true);
michael@0 1627
michael@0 1628 if (initialSizing && mContentDocumentIsDisplayed) {
michael@0 1629 // If this is the first time we're getting a valid mInnerSize, and the
michael@0 1630 // before-first-paint event has already been handled, then we need to set
michael@0 1631 // up our default viewport here. See the corresponding call to
michael@0 1632 // InitializeRootMetrics in the before-first-paint handler.
michael@0 1633 InitializeRootMetrics();
michael@0 1634 }
michael@0 1635
michael@0 1636 HandlePossibleViewportChange();
michael@0 1637
michael@0 1638 return true;
michael@0 1639 }
michael@0 1640
michael@0 1641 bool
michael@0 1642 TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
michael@0 1643 {
michael@0 1644 return TabChildBase::UpdateFrameHandler(aFrameMetrics);
michael@0 1645 }
michael@0 1646
michael@0 1647 bool
michael@0 1648 TabChild::RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
michael@0 1649 const uint32_t& aScrollGeneration)
michael@0 1650 {
michael@0 1651 APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
michael@0 1652 return true;
michael@0 1653 }
michael@0 1654
michael@0 1655 bool
michael@0 1656 TabChild::RecvHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
michael@0 1657 {
michael@0 1658 if (!mGlobal || !mTabChildGlobal) {
michael@0 1659 return true;
michael@0 1660 }
michael@0 1661
michael@0 1662 CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
michael@0 1663 nsString data;
michael@0 1664 data.AppendLiteral("{ \"x\" : ");
michael@0 1665 data.AppendFloat(point.x);
michael@0 1666 data.AppendLiteral(", \"y\" : ");
michael@0 1667 data.AppendFloat(point.y);
michael@0 1668 data.AppendLiteral(" }");
michael@0 1669
michael@0 1670 DispatchMessageManagerMessage(NS_LITERAL_STRING("Gesture:DoubleTap"), data);
michael@0 1671
michael@0 1672 return true;
michael@0 1673 }
michael@0 1674
michael@0 1675 bool
michael@0 1676 TabChild::RecvHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
michael@0 1677 {
michael@0 1678 if (!mGlobal || !mTabChildGlobal) {
michael@0 1679 return true;
michael@0 1680 }
michael@0 1681
michael@0 1682 LayoutDevicePoint currentPoint = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid) * mWidget->GetDefaultScale();;
michael@0 1683
michael@0 1684 MessageLoop::current()->PostDelayedTask(
michael@0 1685 FROM_HERE,
michael@0 1686 NewRunnableMethod(this, &TabChild::FireSingleTapEvent, currentPoint),
michael@0 1687 sActiveDurationMs);
michael@0 1688 return true;
michael@0 1689 }
michael@0 1690
michael@0 1691 void
michael@0 1692 TabChild::FireSingleTapEvent(LayoutDevicePoint aPoint)
michael@0 1693 {
michael@0 1694 int time = 0;
michael@0 1695 DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, aPoint, mWidget);
michael@0 1696 DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, aPoint, mWidget);
michael@0 1697 DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, aPoint, mWidget);
michael@0 1698 }
michael@0 1699
michael@0 1700 bool
michael@0 1701 TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
michael@0 1702 {
michael@0 1703 if (!mGlobal || !mTabChildGlobal) {
michael@0 1704 return true;
michael@0 1705 }
michael@0 1706
michael@0 1707 mContextMenuHandled =
michael@0 1708 DispatchMouseEvent(NS_LITERAL_STRING("contextmenu"),
michael@0 1709 APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid),
michael@0 1710 2, 1, 0, false,
michael@0 1711 nsIDOMMouseEvent::MOZ_SOURCE_TOUCH);
michael@0 1712
michael@0 1713 SendContentReceivedTouch(aGuid, mContextMenuHandled);
michael@0 1714
michael@0 1715 return true;
michael@0 1716 }
michael@0 1717
michael@0 1718 bool
michael@0 1719 TabChild::RecvHandleLongTapUp(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
michael@0 1720 {
michael@0 1721 if (mContextMenuHandled) {
michael@0 1722 mContextMenuHandled = false;
michael@0 1723 return true;
michael@0 1724 }
michael@0 1725
michael@0 1726 RecvHandleSingleTap(aPoint, aGuid);
michael@0 1727 return true;
michael@0 1728 }
michael@0 1729
michael@0 1730 bool
michael@0 1731 TabChild::RecvNotifyAPZStateChange(const ViewID& aViewId,
michael@0 1732 const APZStateChange& aChange,
michael@0 1733 const int& aArg)
michael@0 1734 {
michael@0 1735 switch (aChange)
michael@0 1736 {
michael@0 1737 case APZStateChange::TransformBegin:
michael@0 1738 {
michael@0 1739 nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
michael@0 1740 nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf);
michael@0 1741 if (scrollbarOwner) {
michael@0 1742 scrollbarOwner->ScrollbarActivityStarted();
michael@0 1743 }
michael@0 1744 break;
michael@0 1745 }
michael@0 1746 case APZStateChange::TransformEnd:
michael@0 1747 {
michael@0 1748 nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
michael@0 1749 nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf);
michael@0 1750 if (scrollbarOwner) {
michael@0 1751 scrollbarOwner->ScrollbarActivityStopped();
michael@0 1752 }
michael@0 1753 break;
michael@0 1754 }
michael@0 1755 case APZStateChange::StartTouch:
michael@0 1756 {
michael@0 1757 mActiveElementManager->HandleTouchStart(aArg);
michael@0 1758 break;
michael@0 1759 }
michael@0 1760 case APZStateChange::StartPanning:
michael@0 1761 {
michael@0 1762 mActiveElementManager->HandlePanStart();
michael@0 1763 break;
michael@0 1764 }
michael@0 1765 case APZStateChange::EndTouch:
michael@0 1766 {
michael@0 1767 mActiveElementManager->HandleTouchEnd(aArg);
michael@0 1768 break;
michael@0 1769 }
michael@0 1770 default:
michael@0 1771 // APZStateChange has a 'sentinel' value, and the compiler complains
michael@0 1772 // if an enumerator is not handled and there is no 'default' case.
michael@0 1773 break;
michael@0 1774 }
michael@0 1775 return true;
michael@0 1776 }
michael@0 1777
michael@0 1778 bool
michael@0 1779 TabChild::RecvActivate()
michael@0 1780 {
michael@0 1781 nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(WebNavigation());
michael@0 1782 browser->Activate();
michael@0 1783 return true;
michael@0 1784 }
michael@0 1785
michael@0 1786 bool TabChild::RecvDeactivate()
michael@0 1787 {
michael@0 1788 nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(WebNavigation());
michael@0 1789 browser->Deactivate();
michael@0 1790 return true;
michael@0 1791 }
michael@0 1792
michael@0 1793 bool
michael@0 1794 TabChild::RecvMouseEvent(const nsString& aType,
michael@0 1795 const float& aX,
michael@0 1796 const float& aY,
michael@0 1797 const int32_t& aButton,
michael@0 1798 const int32_t& aClickCount,
michael@0 1799 const int32_t& aModifiers,
michael@0 1800 const bool& aIgnoreRootScrollFrame)
michael@0 1801 {
michael@0 1802 DispatchMouseEvent(aType, CSSPoint(aX, aY), aButton, aClickCount, aModifiers,
michael@0 1803 aIgnoreRootScrollFrame, nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN);
michael@0 1804 return true;
michael@0 1805 }
michael@0 1806
michael@0 1807 bool
michael@0 1808 TabChild::RecvRealMouseEvent(const WidgetMouseEvent& event)
michael@0 1809 {
michael@0 1810 WidgetMouseEvent localEvent(event);
michael@0 1811 localEvent.widget = mWidget;
michael@0 1812 DispatchWidgetEvent(localEvent);
michael@0 1813 return true;
michael@0 1814 }
michael@0 1815
michael@0 1816 bool
michael@0 1817 TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& event)
michael@0 1818 {
michael@0 1819 WidgetWheelEvent localEvent(event);
michael@0 1820 localEvent.widget = mWidget;
michael@0 1821 DispatchWidgetEvent(localEvent);
michael@0 1822 return true;
michael@0 1823 }
michael@0 1824
michael@0 1825 static Touch*
michael@0 1826 GetTouchForIdentifier(const WidgetTouchEvent& aEvent, int32_t aId)
michael@0 1827 {
michael@0 1828 for (uint32_t i = 0; i < aEvent.touches.Length(); ++i) {
michael@0 1829 Touch* touch = static_cast<Touch*>(aEvent.touches[i].get());
michael@0 1830 if (touch->mIdentifier == aId) {
michael@0 1831 return touch;
michael@0 1832 }
michael@0 1833 }
michael@0 1834 return nullptr;
michael@0 1835 }
michael@0 1836
michael@0 1837 void
michael@0 1838 TabChild::UpdateTapState(const WidgetTouchEvent& aEvent, nsEventStatus aStatus)
michael@0 1839 {
michael@0 1840 static bool sHavePrefs;
michael@0 1841 static bool sClickHoldContextMenusEnabled;
michael@0 1842 static nsIntSize sDragThreshold;
michael@0 1843 static int32_t sContextMenuDelayMs;
michael@0 1844 if (!sHavePrefs) {
michael@0 1845 sHavePrefs = true;
michael@0 1846 Preferences::AddBoolVarCache(&sClickHoldContextMenusEnabled,
michael@0 1847 "ui.click_hold_context_menus", true);
michael@0 1848 Preferences::AddIntVarCache(&sDragThreshold.width,
michael@0 1849 "ui.dragThresholdX", 25);
michael@0 1850 Preferences::AddIntVarCache(&sDragThreshold.height,
michael@0 1851 "ui.dragThresholdY", 25);
michael@0 1852 Preferences::AddIntVarCache(&sContextMenuDelayMs,
michael@0 1853 "ui.click_hold_context_menus.delay", 500);
michael@0 1854 }
michael@0 1855
michael@0 1856 if (aEvent.touches.Length() == 0) {
michael@0 1857 return;
michael@0 1858 }
michael@0 1859
michael@0 1860 bool currentlyTrackingTouch = (mActivePointerId >= 0);
michael@0 1861 if (aEvent.message == NS_TOUCH_START) {
michael@0 1862 if (currentlyTrackingTouch || aEvent.touches.Length() > 1) {
michael@0 1863 // We're tracking a possible tap for another point, or we saw a
michael@0 1864 // touchstart for a later pointer after we canceled tracking of
michael@0 1865 // the first point. Ignore this one.
michael@0 1866 return;
michael@0 1867 }
michael@0 1868 if (aStatus == nsEventStatus_eConsumeNoDefault ||
michael@0 1869 nsIPresShell::gPreventMouseEvents ||
michael@0 1870 aEvent.mFlags.mMultipleActionsPrevented) {
michael@0 1871 return;
michael@0 1872 }
michael@0 1873
michael@0 1874 Touch* touch = aEvent.touches[0];
michael@0 1875 mGestureDownPoint = LayoutDevicePoint(touch->mRefPoint.x, touch->mRefPoint.y);
michael@0 1876 mActivePointerId = touch->mIdentifier;
michael@0 1877 if (sClickHoldContextMenusEnabled) {
michael@0 1878 MOZ_ASSERT(!mTapHoldTimer);
michael@0 1879 mTapHoldTimer = NewRunnableMethod(this,
michael@0 1880 &TabChild::FireContextMenuEvent);
michael@0 1881 MessageLoop::current()->PostDelayedTask(FROM_HERE, mTapHoldTimer,
michael@0 1882 sContextMenuDelayMs);
michael@0 1883 }
michael@0 1884 return;
michael@0 1885 }
michael@0 1886
michael@0 1887 // If we're not tracking a touch or this event doesn't include the
michael@0 1888 // one we care about, bail.
michael@0 1889 if (!currentlyTrackingTouch) {
michael@0 1890 return;
michael@0 1891 }
michael@0 1892 Touch* trackedTouch = GetTouchForIdentifier(aEvent, mActivePointerId);
michael@0 1893 if (!trackedTouch) {
michael@0 1894 return;
michael@0 1895 }
michael@0 1896
michael@0 1897 LayoutDevicePoint currentPoint = LayoutDevicePoint(trackedTouch->mRefPoint.x, trackedTouch->mRefPoint.y);
michael@0 1898 int64_t time = aEvent.time;
michael@0 1899 switch (aEvent.message) {
michael@0 1900 case NS_TOUCH_MOVE:
michael@0 1901 if (abs(currentPoint.x - mGestureDownPoint.x) > sDragThreshold.width ||
michael@0 1902 abs(currentPoint.y - mGestureDownPoint.y) > sDragThreshold.height) {
michael@0 1903 CancelTapTracking();
michael@0 1904 }
michael@0 1905 return;
michael@0 1906
michael@0 1907 case NS_TOUCH_END:
michael@0 1908 if (!nsIPresShell::gPreventMouseEvents) {
michael@0 1909 DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, currentPoint, mWidget);
michael@0 1910 DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, currentPoint, mWidget);
michael@0 1911 DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, currentPoint, mWidget);
michael@0 1912 }
michael@0 1913 // fall through
michael@0 1914 case NS_TOUCH_CANCEL:
michael@0 1915 CancelTapTracking();
michael@0 1916 return;
michael@0 1917
michael@0 1918 default:
michael@0 1919 NS_WARNING("Unknown touch event type");
michael@0 1920 }
michael@0 1921 }
michael@0 1922
michael@0 1923 void
michael@0 1924 TabChild::FireContextMenuEvent()
michael@0 1925 {
michael@0 1926 double scale;
michael@0 1927 GetDefaultScale(&scale);
michael@0 1928 if (scale < 0) {
michael@0 1929 scale = 1;
michael@0 1930 }
michael@0 1931
michael@0 1932 MOZ_ASSERT(mTapHoldTimer && mActivePointerId >= 0);
michael@0 1933 bool defaultPrevented = DispatchMouseEvent(NS_LITERAL_STRING("contextmenu"),
michael@0 1934 mGestureDownPoint / CSSToLayoutDeviceScale(scale),
michael@0 1935 2 /* Right button */,
michael@0 1936 1 /* Click count */,
michael@0 1937 0 /* Modifiers */,
michael@0 1938 false /* Ignore root scroll frame */,
michael@0 1939 nsIDOMMouseEvent::MOZ_SOURCE_TOUCH);
michael@0 1940
michael@0 1941 // Fire a click event if someone didn't call preventDefault() on the context
michael@0 1942 // menu event.
michael@0 1943 if (defaultPrevented) {
michael@0 1944 CancelTapTracking();
michael@0 1945 } else if (mTapHoldTimer) {
michael@0 1946 mTapHoldTimer->Cancel();
michael@0 1947 mTapHoldTimer = nullptr;
michael@0 1948 }
michael@0 1949 }
michael@0 1950
michael@0 1951 void
michael@0 1952 TabChild::CancelTapTracking()
michael@0 1953 {
michael@0 1954 mActivePointerId = -1;
michael@0 1955 if (mTapHoldTimer) {
michael@0 1956 mTapHoldTimer->Cancel();
michael@0 1957 }
michael@0 1958 mTapHoldTimer = nullptr;
michael@0 1959 }
michael@0 1960
michael@0 1961 bool
michael@0 1962 TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
michael@0 1963 const ScrollableLayerGuid& aGuid)
michael@0 1964 {
michael@0 1965 WidgetTouchEvent localEvent(aEvent);
michael@0 1966 localEvent.widget = mWidget;
michael@0 1967 for (size_t i = 0; i < localEvent.touches.Length(); i++) {
michael@0 1968 aEvent.touches[i]->mRefPoint = APZCCallbackHelper::ApplyCallbackTransform(aEvent.touches[i]->mRefPoint, aGuid, mWidget->GetDefaultScale());
michael@0 1969 }
michael@0 1970
michael@0 1971 nsEventStatus status = DispatchWidgetEvent(localEvent);
michael@0 1972
michael@0 1973 if (!IsAsyncPanZoomEnabled()) {
michael@0 1974 UpdateTapState(localEvent, status);
michael@0 1975 return true;
michael@0 1976 }
michael@0 1977
michael@0 1978 if (aEvent.message == NS_TOUCH_START && localEvent.touches.Length() > 0) {
michael@0 1979 mActiveElementManager->SetTargetElement(localEvent.touches[0]->Target());
michael@0 1980 }
michael@0 1981
michael@0 1982 nsCOMPtr<nsPIDOMWindow> outerWindow = do_GetInterface(WebNavigation());
michael@0 1983 nsCOMPtr<nsPIDOMWindow> innerWindow = outerWindow->GetCurrentInnerWindow();
michael@0 1984
michael@0 1985 if (!innerWindow || !innerWindow->HasTouchEventListeners()) {
michael@0 1986 SendContentReceivedTouch(aGuid, false);
michael@0 1987 return true;
michael@0 1988 }
michael@0 1989
michael@0 1990 bool isTouchPrevented = nsIPresShell::gPreventMouseEvents ||
michael@0 1991 localEvent.mFlags.mMultipleActionsPrevented;
michael@0 1992 switch (aEvent.message) {
michael@0 1993 case NS_TOUCH_START: {
michael@0 1994 if (isTouchPrevented) {
michael@0 1995 SendContentReceivedTouch(aGuid, isTouchPrevented);
michael@0 1996 } else {
michael@0 1997 mWaitingTouchListeners = true;
michael@0 1998 }
michael@0 1999 break;
michael@0 2000 }
michael@0 2001
michael@0 2002 case NS_TOUCH_MOVE:
michael@0 2003 case NS_TOUCH_END:
michael@0 2004 case NS_TOUCH_CANCEL: {
michael@0 2005 if (mWaitingTouchListeners) {
michael@0 2006 SendContentReceivedTouch(aGuid, isTouchPrevented);
michael@0 2007 mWaitingTouchListeners = false;
michael@0 2008 }
michael@0 2009 break;
michael@0 2010 }
michael@0 2011
michael@0 2012 default:
michael@0 2013 NS_WARNING("Unknown touch event type");
michael@0 2014 }
michael@0 2015
michael@0 2016 return true;
michael@0 2017 }
michael@0 2018
michael@0 2019 bool
michael@0 2020 TabChild::RecvRealTouchMoveEvent(const WidgetTouchEvent& aEvent,
michael@0 2021 const ScrollableLayerGuid& aGuid)
michael@0 2022 {
michael@0 2023 return RecvRealTouchEvent(aEvent, aGuid);
michael@0 2024 }
michael@0 2025
michael@0 2026 void
michael@0 2027 TabChild::RequestNativeKeyBindings(AutoCacheNativeKeyCommands* aAutoCache,
michael@0 2028 WidgetKeyboardEvent* aEvent)
michael@0 2029 {
michael@0 2030 MaybeNativeKeyBinding maybeBindings;
michael@0 2031 if (!SendRequestNativeKeyBindings(*aEvent, &maybeBindings)) {
michael@0 2032 return;
michael@0 2033 }
michael@0 2034
michael@0 2035 if (maybeBindings.type() == MaybeNativeKeyBinding::TNativeKeyBinding) {
michael@0 2036 const NativeKeyBinding& bindings = maybeBindings;
michael@0 2037 aAutoCache->Cache(bindings.singleLineCommands(),
michael@0 2038 bindings.multiLineCommands(),
michael@0 2039 bindings.richTextCommands());
michael@0 2040 } else {
michael@0 2041 aAutoCache->CacheNoCommands();
michael@0 2042 }
michael@0 2043 }
michael@0 2044
michael@0 2045 bool
michael@0 2046 TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
michael@0 2047 const MaybeNativeKeyBinding& aBindings)
michael@0 2048 {
michael@0 2049 PuppetWidget* widget = static_cast<PuppetWidget*>(mWidget.get());
michael@0 2050 AutoCacheNativeKeyCommands autoCache(widget);
michael@0 2051
michael@0 2052 if (event.message == NS_KEY_PRESS) {
michael@0 2053 if (aBindings.type() == MaybeNativeKeyBinding::TNativeKeyBinding) {
michael@0 2054 const NativeKeyBinding& bindings = aBindings;
michael@0 2055 autoCache.Cache(bindings.singleLineCommands(),
michael@0 2056 bindings.multiLineCommands(),
michael@0 2057 bindings.richTextCommands());
michael@0 2058 } else {
michael@0 2059 autoCache.CacheNoCommands();
michael@0 2060 }
michael@0 2061 }
michael@0 2062 // If content code called preventDefault() on a keydown event, then we don't
michael@0 2063 // want to process any following keypress events.
michael@0 2064 if (event.message == NS_KEY_PRESS && mIgnoreKeyPressEvent) {
michael@0 2065 return true;
michael@0 2066 }
michael@0 2067
michael@0 2068 WidgetKeyboardEvent localEvent(event);
michael@0 2069 localEvent.widget = mWidget;
michael@0 2070 nsEventStatus status = DispatchWidgetEvent(localEvent);
michael@0 2071
michael@0 2072 if (event.message == NS_KEY_DOWN) {
michael@0 2073 mIgnoreKeyPressEvent = status == nsEventStatus_eConsumeNoDefault;
michael@0 2074 }
michael@0 2075
michael@0 2076 if (localEvent.mFlags.mWantReplyFromContentProcess) {
michael@0 2077 SendReplyKeyEvent(localEvent);
michael@0 2078 }
michael@0 2079
michael@0 2080 return true;
michael@0 2081 }
michael@0 2082
michael@0 2083 bool
michael@0 2084 TabChild::RecvKeyEvent(const nsString& aType,
michael@0 2085 const int32_t& aKeyCode,
michael@0 2086 const int32_t& aCharCode,
michael@0 2087 const int32_t& aModifiers,
michael@0 2088 const bool& aPreventDefault)
michael@0 2089 {
michael@0 2090 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
michael@0 2091 NS_ENSURE_TRUE(utils, true);
michael@0 2092 bool ignored = false;
michael@0 2093 utils->SendKeyEvent(aType, aKeyCode, aCharCode,
michael@0 2094 aModifiers, aPreventDefault, &ignored);
michael@0 2095 return true;
michael@0 2096 }
michael@0 2097
michael@0 2098 bool
michael@0 2099 TabChild::RecvCompositionEvent(const WidgetCompositionEvent& event)
michael@0 2100 {
michael@0 2101 WidgetCompositionEvent localEvent(event);
michael@0 2102 localEvent.widget = mWidget;
michael@0 2103 DispatchWidgetEvent(localEvent);
michael@0 2104 return true;
michael@0 2105 }
michael@0 2106
michael@0 2107 bool
michael@0 2108 TabChild::RecvTextEvent(const WidgetTextEvent& event)
michael@0 2109 {
michael@0 2110 WidgetTextEvent localEvent(event);
michael@0 2111 localEvent.widget = mWidget;
michael@0 2112 DispatchWidgetEvent(localEvent);
michael@0 2113 return true;
michael@0 2114 }
michael@0 2115
michael@0 2116 bool
michael@0 2117 TabChild::RecvSelectionEvent(const WidgetSelectionEvent& event)
michael@0 2118 {
michael@0 2119 WidgetSelectionEvent localEvent(event);
michael@0 2120 localEvent.widget = mWidget;
michael@0 2121 DispatchWidgetEvent(localEvent);
michael@0 2122 return true;
michael@0 2123 }
michael@0 2124
michael@0 2125 PDocumentRendererChild*
michael@0 2126 TabChild::AllocPDocumentRendererChild(const nsRect& documentRect,
michael@0 2127 const mozilla::gfx::Matrix& transform,
michael@0 2128 const nsString& bgcolor,
michael@0 2129 const uint32_t& renderFlags,
michael@0 2130 const bool& flushLayout,
michael@0 2131 const nsIntSize& renderSize)
michael@0 2132 {
michael@0 2133 return new DocumentRendererChild();
michael@0 2134 }
michael@0 2135
michael@0 2136 bool
michael@0 2137 TabChild::DeallocPDocumentRendererChild(PDocumentRendererChild* actor)
michael@0 2138 {
michael@0 2139 delete actor;
michael@0 2140 return true;
michael@0 2141 }
michael@0 2142
michael@0 2143 bool
michael@0 2144 TabChild::RecvPDocumentRendererConstructor(PDocumentRendererChild* actor,
michael@0 2145 const nsRect& documentRect,
michael@0 2146 const mozilla::gfx::Matrix& transform,
michael@0 2147 const nsString& bgcolor,
michael@0 2148 const uint32_t& renderFlags,
michael@0 2149 const bool& flushLayout,
michael@0 2150 const nsIntSize& renderSize)
michael@0 2151 {
michael@0 2152 DocumentRendererChild *render = static_cast<DocumentRendererChild *>(actor);
michael@0 2153
michael@0 2154 nsCOMPtr<nsIWebBrowser> browser = do_QueryInterface(WebNavigation());
michael@0 2155 if (!browser)
michael@0 2156 return true; // silently ignore
michael@0 2157 nsCOMPtr<nsIDOMWindow> window;
michael@0 2158 if (NS_FAILED(browser->GetContentDOMWindow(getter_AddRefs(window))) ||
michael@0 2159 !window)
michael@0 2160 {
michael@0 2161 return true; // silently ignore
michael@0 2162 }
michael@0 2163
michael@0 2164 nsCString data;
michael@0 2165 bool ret = render->RenderDocument(window,
michael@0 2166 documentRect, transform,
michael@0 2167 bgcolor,
michael@0 2168 renderFlags, flushLayout,
michael@0 2169 renderSize, data);
michael@0 2170 if (!ret)
michael@0 2171 return true; // silently ignore
michael@0 2172
michael@0 2173 return PDocumentRendererChild::Send__delete__(actor, renderSize, data);
michael@0 2174 }
michael@0 2175
michael@0 2176 PColorPickerChild*
michael@0 2177 TabChild::AllocPColorPickerChild(const nsString&, const nsString&)
michael@0 2178 {
michael@0 2179 NS_RUNTIMEABORT("unused");
michael@0 2180 return nullptr;
michael@0 2181 }
michael@0 2182
michael@0 2183 bool
michael@0 2184 TabChild::DeallocPColorPickerChild(PColorPickerChild* aColorPicker)
michael@0 2185 {
michael@0 2186 nsColorPickerProxy* picker = static_cast<nsColorPickerProxy*>(aColorPicker);
michael@0 2187 NS_RELEASE(picker);
michael@0 2188 return true;
michael@0 2189 }
michael@0 2190
michael@0 2191 PContentPermissionRequestChild*
michael@0 2192 TabChild::AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
michael@0 2193 const IPC::Principal& aPrincipal)
michael@0 2194 {
michael@0 2195 NS_RUNTIMEABORT("unused");
michael@0 2196 return nullptr;
michael@0 2197 }
michael@0 2198
michael@0 2199 bool
michael@0 2200 TabChild::DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor)
michael@0 2201 {
michael@0 2202 PCOMContentPermissionRequestChild* child =
michael@0 2203 static_cast<PCOMContentPermissionRequestChild*>(actor);
michael@0 2204 #ifdef DEBUG
michael@0 2205 child->mIPCOpen = false;
michael@0 2206 #endif /* DEBUG */
michael@0 2207 child->IPDLRelease();
michael@0 2208 return true;
michael@0 2209 }
michael@0 2210
michael@0 2211 PFilePickerChild*
michael@0 2212 TabChild::AllocPFilePickerChild(const nsString&, const int16_t&)
michael@0 2213 {
michael@0 2214 NS_RUNTIMEABORT("unused");
michael@0 2215 return nullptr;
michael@0 2216 }
michael@0 2217
michael@0 2218 bool
michael@0 2219 TabChild::DeallocPFilePickerChild(PFilePickerChild* actor)
michael@0 2220 {
michael@0 2221 nsFilePickerProxy* filePicker = static_cast<nsFilePickerProxy*>(actor);
michael@0 2222 NS_RELEASE(filePicker);
michael@0 2223 return true;
michael@0 2224 }
michael@0 2225
michael@0 2226 bool
michael@0 2227 TabChild::RecvActivateFrameEvent(const nsString& aType, const bool& capture)
michael@0 2228 {
michael@0 2229 nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation());
michael@0 2230 NS_ENSURE_TRUE(window, true);
michael@0 2231 nsCOMPtr<EventTarget> chromeHandler =
michael@0 2232 do_QueryInterface(window->GetChromeEventHandler());
michael@0 2233 NS_ENSURE_TRUE(chromeHandler, true);
michael@0 2234 nsRefPtr<ContentListener> listener = new ContentListener(this);
michael@0 2235 chromeHandler->AddEventListener(aType, listener, capture);
michael@0 2236 return true;
michael@0 2237 }
michael@0 2238
michael@0 2239 POfflineCacheUpdateChild*
michael@0 2240 TabChild::AllocPOfflineCacheUpdateChild(const URIParams& manifestURI,
michael@0 2241 const URIParams& documentURI,
michael@0 2242 const bool& stickDocument)
michael@0 2243 {
michael@0 2244 NS_RUNTIMEABORT("unused");
michael@0 2245 return nullptr;
michael@0 2246 }
michael@0 2247
michael@0 2248 bool
michael@0 2249 TabChild::DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* actor)
michael@0 2250 {
michael@0 2251 OfflineCacheUpdateChild* offlineCacheUpdate = static_cast<OfflineCacheUpdateChild*>(actor);
michael@0 2252 NS_RELEASE(offlineCacheUpdate);
michael@0 2253 return true;
michael@0 2254 }
michael@0 2255
michael@0 2256 bool
michael@0 2257 TabChild::RecvLoadRemoteScript(const nsString& aURL, const bool& aRunInGlobalScope)
michael@0 2258 {
michael@0 2259 if (!mGlobal && !InitTabChildGlobal())
michael@0 2260 // This can happen if we're half-destroyed. It's not a fatal
michael@0 2261 // error.
michael@0 2262 return true;
michael@0 2263
michael@0 2264 LoadFrameScriptInternal(aURL, aRunInGlobalScope);
michael@0 2265 return true;
michael@0 2266 }
michael@0 2267
michael@0 2268 bool
michael@0 2269 TabChild::RecvAsyncMessage(const nsString& aMessage,
michael@0 2270 const ClonedMessageData& aData,
michael@0 2271 const InfallibleTArray<CpowEntry>& aCpows,
michael@0 2272 const IPC::Principal& aPrincipal)
michael@0 2273 {
michael@0 2274 if (mTabChildGlobal) {
michael@0 2275 nsCOMPtr<nsIXPConnectJSObjectHolder> kungFuDeathGrip(GetGlobal());
michael@0 2276 StructuredCloneData cloneData = UnpackClonedMessageDataForChild(aData);
michael@0 2277 nsRefPtr<nsFrameMessageManager> mm =
michael@0 2278 static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
michael@0 2279 CpowIdHolder cpows(static_cast<ContentChild*>(Manager())->GetCPOWManager(), aCpows);
michael@0 2280 mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal),
michael@0 2281 aMessage, false, &cloneData, &cpows, aPrincipal, nullptr);
michael@0 2282 }
michael@0 2283 return true;
michael@0 2284 }
michael@0 2285
michael@0 2286 class UnloadScriptEvent : public nsRunnable
michael@0 2287 {
michael@0 2288 public:
michael@0 2289 UnloadScriptEvent(TabChild* aTabChild, TabChildGlobal* aTabChildGlobal)
michael@0 2290 : mTabChild(aTabChild), mTabChildGlobal(aTabChildGlobal)
michael@0 2291 { }
michael@0 2292
michael@0 2293 NS_IMETHOD Run()
michael@0 2294 {
michael@0 2295 nsCOMPtr<nsIDOMEvent> event;
michael@0 2296 NS_NewDOMEvent(getter_AddRefs(event), mTabChildGlobal, nullptr, nullptr);
michael@0 2297 if (event) {
michael@0 2298 event->InitEvent(NS_LITERAL_STRING("unload"), false, false);
michael@0 2299 event->SetTrusted(true);
michael@0 2300
michael@0 2301 bool dummy;
michael@0 2302 mTabChildGlobal->DispatchEvent(event, &dummy);
michael@0 2303 }
michael@0 2304
michael@0 2305 return NS_OK;
michael@0 2306 }
michael@0 2307
michael@0 2308 nsRefPtr<TabChild> mTabChild;
michael@0 2309 TabChildGlobal* mTabChildGlobal;
michael@0 2310 };
michael@0 2311
michael@0 2312 bool
michael@0 2313 TabChild::RecvDestroy()
michael@0 2314 {
michael@0 2315 if (mTabChildGlobal) {
michael@0 2316 // Let the frame scripts know the child is being closed
michael@0 2317 nsContentUtils::AddScriptRunner(
michael@0 2318 new UnloadScriptEvent(this, mTabChildGlobal)
michael@0 2319 );
michael@0 2320 }
michael@0 2321
michael@0 2322 nsCOMPtr<nsIObserverService> observerService =
michael@0 2323 mozilla::services::GetObserverService();
michael@0 2324
michael@0 2325 observerService->RemoveObserver(this, BROWSER_ZOOM_TO_RECT);
michael@0 2326 observerService->RemoveObserver(this, BEFORE_FIRST_PAINT);
michael@0 2327
michael@0 2328 const InfallibleTArray<PIndexedDBChild*>& idbActors =
michael@0 2329 ManagedPIndexedDBChild();
michael@0 2330 for (uint32_t i = 0; i < idbActors.Length(); ++i) {
michael@0 2331 static_cast<IndexedDBChild*>(idbActors[i])->Disconnect();
michael@0 2332 }
michael@0 2333
michael@0 2334 // XXX what other code in ~TabChild() should we be running here?
michael@0 2335 DestroyWindow();
michael@0 2336
michael@0 2337 return Send__delete__(this);
michael@0 2338 }
michael@0 2339
michael@0 2340 bool
michael@0 2341 TabChild::RecvSetUpdateHitRegion(const bool& aEnabled)
michael@0 2342 {
michael@0 2343 mUpdateHitRegion = aEnabled;
michael@0 2344 return true;
michael@0 2345 }
michael@0 2346
michael@0 2347 bool
michael@0 2348 TabChild::RecvSetIsDocShellActive(const bool& aIsActive)
michael@0 2349 {
michael@0 2350 nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
michael@0 2351 if (docShell) {
michael@0 2352 docShell->SetIsActive(aIsActive);
michael@0 2353 }
michael@0 2354 return true;
michael@0 2355 }
michael@0 2356
michael@0 2357 PRenderFrameChild*
michael@0 2358 TabChild::AllocPRenderFrameChild()
michael@0 2359 {
michael@0 2360 return new RenderFrameChild();
michael@0 2361 }
michael@0 2362
michael@0 2363 bool
michael@0 2364 TabChild::DeallocPRenderFrameChild(PRenderFrameChild* aFrame)
michael@0 2365 {
michael@0 2366 delete aFrame;
michael@0 2367 return true;
michael@0 2368 }
michael@0 2369
michael@0 2370 bool
michael@0 2371 TabChild::InitTabChildGlobal(FrameScriptLoading aScriptLoading)
michael@0 2372 {
michael@0 2373 if (!mGlobal && !mTabChildGlobal) {
michael@0 2374 nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation());
michael@0 2375 NS_ENSURE_TRUE(window, false);
michael@0 2376 nsCOMPtr<EventTarget> chromeHandler =
michael@0 2377 do_QueryInterface(window->GetChromeEventHandler());
michael@0 2378 NS_ENSURE_TRUE(chromeHandler, false);
michael@0 2379
michael@0 2380 nsRefPtr<TabChildGlobal> scope = new TabChildGlobal(this);
michael@0 2381 mTabChildGlobal = scope;
michael@0 2382
michael@0 2383 nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, scope);
michael@0 2384
michael@0 2385 NS_NAMED_LITERAL_CSTRING(globalId, "outOfProcessTabChildGlobal");
michael@0 2386 NS_ENSURE_TRUE(InitTabChildGlobalInternal(scopeSupports, globalId), false);
michael@0 2387
michael@0 2388 scope->Init();
michael@0 2389
michael@0 2390 nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(chromeHandler);
michael@0 2391 NS_ENSURE_TRUE(root, false);
michael@0 2392 root->SetParentTarget(scope);
michael@0 2393
michael@0 2394 chromeHandler->AddEventListener(NS_LITERAL_STRING("DOMMetaAdded"), this, false);
michael@0 2395 }
michael@0 2396
michael@0 2397 if (aScriptLoading != DONT_LOAD_SCRIPTS && !mTriedBrowserInit) {
michael@0 2398 mTriedBrowserInit = true;
michael@0 2399 // Initialize the child side of the browser element machinery,
michael@0 2400 // if appropriate.
michael@0 2401 if (IsBrowserOrApp()) {
michael@0 2402 RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
michael@0 2403 }
michael@0 2404 }
michael@0 2405
michael@0 2406 return true;
michael@0 2407 }
michael@0 2408
michael@0 2409 bool
michael@0 2410 TabChild::InitRenderingState()
michael@0 2411 {
michael@0 2412 static_cast<PuppetWidget*>(mWidget.get())->InitIMEState();
michael@0 2413
michael@0 2414 uint64_t id;
michael@0 2415 bool success;
michael@0 2416 RenderFrameChild* remoteFrame =
michael@0 2417 static_cast<RenderFrameChild*>(SendPRenderFrameConstructor());
michael@0 2418 if (!remoteFrame) {
michael@0 2419 NS_WARNING("failed to construct RenderFrame");
michael@0 2420 return false;
michael@0 2421 }
michael@0 2422 SendInitRenderFrame(remoteFrame, &mScrolling, &mTextureFactoryIdentifier, &id, &success);
michael@0 2423 if (!success) {
michael@0 2424 NS_WARNING("failed to construct RenderFrame");
michael@0 2425 PRenderFrameChild::Send__delete__(remoteFrame);
michael@0 2426 return false;
michael@0 2427 }
michael@0 2428
michael@0 2429 PLayerTransactionChild* shadowManager = nullptr;
michael@0 2430 if (id != 0) {
michael@0 2431 // Pushing layers transactions directly to a separate
michael@0 2432 // compositor context.
michael@0 2433 PCompositorChild* compositorChild = CompositorChild::Get();
michael@0 2434 if (!compositorChild) {
michael@0 2435 NS_WARNING("failed to get CompositorChild instance");
michael@0 2436 return false;
michael@0 2437 }
michael@0 2438 nsTArray<LayersBackend> backends;
michael@0 2439 backends.AppendElement(mTextureFactoryIdentifier.mParentBackend);
michael@0 2440 bool success;
michael@0 2441 shadowManager =
michael@0 2442 compositorChild->SendPLayerTransactionConstructor(backends,
michael@0 2443 id, &mTextureFactoryIdentifier, &success);
michael@0 2444 if (!success) {
michael@0 2445 NS_WARNING("failed to properly allocate layer transaction");
michael@0 2446 return false;
michael@0 2447 }
michael@0 2448 } else {
michael@0 2449 // Pushing transactions to the parent content.
michael@0 2450 shadowManager = remoteFrame->SendPLayerTransactionConstructor();
michael@0 2451 }
michael@0 2452
michael@0 2453 if (!shadowManager) {
michael@0 2454 NS_WARNING("failed to construct LayersChild");
michael@0 2455 // This results in |remoteFrame| being deleted.
michael@0 2456 PRenderFrameChild::Send__delete__(remoteFrame);
michael@0 2457 return false;
michael@0 2458 }
michael@0 2459
michael@0 2460 ShadowLayerForwarder* lf =
michael@0 2461 mWidget->GetLayerManager(shadowManager, mTextureFactoryIdentifier.mParentBackend)
michael@0 2462 ->AsShadowForwarder();
michael@0 2463 NS_ABORT_IF_FALSE(lf && lf->HasShadowManager(),
michael@0 2464 "PuppetWidget should have shadow manager");
michael@0 2465 lf->IdentifyTextureHost(mTextureFactoryIdentifier);
michael@0 2466 ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
michael@0 2467
michael@0 2468 mRemoteFrame = remoteFrame;
michael@0 2469 if (id != 0) {
michael@0 2470 if (!sTabChildren) {
michael@0 2471 sTabChildren = new TabChildMap;
michael@0 2472 }
michael@0 2473 sTabChildren->Put(id, this);
michael@0 2474 mLayersId = id;
michael@0 2475 }
michael@0 2476
michael@0 2477 nsCOMPtr<nsIObserverService> observerService =
michael@0 2478 mozilla::services::GetObserverService();
michael@0 2479
michael@0 2480 if (observerService) {
michael@0 2481 observerService->AddObserver(this,
michael@0 2482 BROWSER_ZOOM_TO_RECT,
michael@0 2483 false);
michael@0 2484 observerService->AddObserver(this,
michael@0 2485 BEFORE_FIRST_PAINT,
michael@0 2486 false);
michael@0 2487 }
michael@0 2488
michael@0 2489 // This state can't change during the lifetime of the child.
michael@0 2490 sCpowsEnabled = BrowserTabsRemote();
michael@0 2491 if (Preferences::GetBool("dom.ipc.cpows.force-enabled", false))
michael@0 2492 sCpowsEnabled = true;
michael@0 2493
michael@0 2494 return true;
michael@0 2495 }
michael@0 2496
michael@0 2497 void
michael@0 2498 TabChild::SetBackgroundColor(const nscolor& aColor)
michael@0 2499 {
michael@0 2500 if (mLastBackgroundColor != aColor) {
michael@0 2501 mLastBackgroundColor = aColor;
michael@0 2502 SendSetBackgroundColor(mLastBackgroundColor);
michael@0 2503 }
michael@0 2504 }
michael@0 2505
michael@0 2506 void
michael@0 2507 TabChild::GetDPI(float* aDPI)
michael@0 2508 {
michael@0 2509 *aDPI = -1.0;
michael@0 2510 if (!mRemoteFrame) {
michael@0 2511 return;
michael@0 2512 }
michael@0 2513
michael@0 2514 SendGetDPI(aDPI);
michael@0 2515 }
michael@0 2516
michael@0 2517 void
michael@0 2518 TabChild::GetDefaultScale(double* aScale)
michael@0 2519 {
michael@0 2520 *aScale = -1.0;
michael@0 2521 if (!mRemoteFrame) {
michael@0 2522 return;
michael@0 2523 }
michael@0 2524
michael@0 2525 SendGetDefaultScale(aScale);
michael@0 2526 }
michael@0 2527
michael@0 2528 void
michael@0 2529 TabChild::NotifyPainted()
michael@0 2530 {
michael@0 2531 if (UseDirectCompositor() && !mNotified) {
michael@0 2532 mRemoteFrame->SendNotifyCompositorTransaction();
michael@0 2533 mNotified = true;
michael@0 2534 }
michael@0 2535 }
michael@0 2536
michael@0 2537 bool
michael@0 2538 TabChild::DispatchMouseEvent(const nsString& aType,
michael@0 2539 const CSSPoint& aPoint,
michael@0 2540 const int32_t& aButton,
michael@0 2541 const int32_t& aClickCount,
michael@0 2542 const int32_t& aModifiers,
michael@0 2543 const bool& aIgnoreRootScrollFrame,
michael@0 2544 const unsigned short& aInputSourceArg)
michael@0 2545 {
michael@0 2546 nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
michael@0 2547 NS_ENSURE_TRUE(utils, true);
michael@0 2548
michael@0 2549 bool defaultPrevented = false;
michael@0 2550 utils->SendMouseEvent(aType, aPoint.x, aPoint.y, aButton, aClickCount, aModifiers,
michael@0 2551 aIgnoreRootScrollFrame, 0, aInputSourceArg, false, 4, &defaultPrevented);
michael@0 2552 return defaultPrevented;
michael@0 2553 }
michael@0 2554
michael@0 2555 void
michael@0 2556 TabChild::MakeVisible()
michael@0 2557 {
michael@0 2558 if (mWidget) {
michael@0 2559 mWidget->Show(true);
michael@0 2560 }
michael@0 2561 }
michael@0 2562
michael@0 2563 void
michael@0 2564 TabChild::MakeHidden()
michael@0 2565 {
michael@0 2566 if (mWidget) {
michael@0 2567 mWidget->Show(false);
michael@0 2568 }
michael@0 2569 }
michael@0 2570
michael@0 2571 void
michael@0 2572 TabChild::UpdateHitRegion(const nsRegion& aRegion)
michael@0 2573 {
michael@0 2574 mRemoteFrame->SendUpdateHitRegion(aRegion);
michael@0 2575 }
michael@0 2576
michael@0 2577 NS_IMETHODIMP
michael@0 2578 TabChild::GetMessageManager(nsIContentFrameMessageManager** aResult)
michael@0 2579 {
michael@0 2580 if (mTabChildGlobal) {
michael@0 2581 NS_ADDREF(*aResult = mTabChildGlobal);
michael@0 2582 return NS_OK;
michael@0 2583 }
michael@0 2584 *aResult = nullptr;
michael@0 2585 return NS_ERROR_FAILURE;
michael@0 2586 }
michael@0 2587
michael@0 2588 void
michael@0 2589 TabChild::SendRequestFocus(bool aCanFocus)
michael@0 2590 {
michael@0 2591 PBrowserChild::SendRequestFocus(aCanFocus);
michael@0 2592 }
michael@0 2593
michael@0 2594 PIndexedDBChild*
michael@0 2595 TabChild::AllocPIndexedDBChild(
michael@0 2596 const nsCString& aGroup,
michael@0 2597 const nsCString& aASCIIOrigin, bool* /* aAllowed */)
michael@0 2598 {
michael@0 2599 NS_NOTREACHED("Should never get here!");
michael@0 2600 return nullptr;
michael@0 2601 }
michael@0 2602
michael@0 2603 bool
michael@0 2604 TabChild::DeallocPIndexedDBChild(PIndexedDBChild* aActor)
michael@0 2605 {
michael@0 2606 delete aActor;
michael@0 2607 return true;
michael@0 2608 }
michael@0 2609
michael@0 2610 bool
michael@0 2611 TabChild::DoSendBlockingMessage(JSContext* aCx,
michael@0 2612 const nsAString& aMessage,
michael@0 2613 const StructuredCloneData& aData,
michael@0 2614 JS::Handle<JSObject *> aCpows,
michael@0 2615 nsIPrincipal* aPrincipal,
michael@0 2616 InfallibleTArray<nsString>* aJSONRetVal,
michael@0 2617 bool aIsSync)
michael@0 2618 {
michael@0 2619 ContentChild* cc = Manager();
michael@0 2620 ClonedMessageData data;
michael@0 2621 if (!BuildClonedMessageDataForChild(cc, aData, data)) {
michael@0 2622 return false;
michael@0 2623 }
michael@0 2624 InfallibleTArray<CpowEntry> cpows;
michael@0 2625 if (sCpowsEnabled) {
michael@0 2626 if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
michael@0 2627 return false;
michael@0 2628 }
michael@0 2629 }
michael@0 2630 if (aIsSync) {
michael@0 2631 return SendSyncMessage(PromiseFlatString(aMessage), data, cpows,
michael@0 2632 aPrincipal, aJSONRetVal);
michael@0 2633 }
michael@0 2634
michael@0 2635 return CallRpcMessage(PromiseFlatString(aMessage), data, cpows,
michael@0 2636 aPrincipal, aJSONRetVal);
michael@0 2637 }
michael@0 2638
michael@0 2639 bool
michael@0 2640 TabChild::DoSendAsyncMessage(JSContext* aCx,
michael@0 2641 const nsAString& aMessage,
michael@0 2642 const StructuredCloneData& aData,
michael@0 2643 JS::Handle<JSObject *> aCpows,
michael@0 2644 nsIPrincipal* aPrincipal)
michael@0 2645 {
michael@0 2646 ContentChild* cc = Manager();
michael@0 2647 ClonedMessageData data;
michael@0 2648 if (!BuildClonedMessageDataForChild(cc, aData, data)) {
michael@0 2649 return false;
michael@0 2650 }
michael@0 2651 InfallibleTArray<CpowEntry> cpows;
michael@0 2652 if (sCpowsEnabled) {
michael@0 2653 if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
michael@0 2654 return false;
michael@0 2655 }
michael@0 2656 }
michael@0 2657 return SendAsyncMessage(PromiseFlatString(aMessage), data, cpows,
michael@0 2658 aPrincipal);
michael@0 2659 }
michael@0 2660
michael@0 2661 TabChild*
michael@0 2662 TabChild::GetFrom(nsIPresShell* aPresShell)
michael@0 2663 {
michael@0 2664 nsIDocument* doc = aPresShell->GetDocument();
michael@0 2665 if (!doc) {
michael@0 2666 return nullptr;
michael@0 2667 }
michael@0 2668 nsCOMPtr<nsIDocShell> docShell(doc->GetDocShell());
michael@0 2669 return GetFrom(docShell);
michael@0 2670 }
michael@0 2671
michael@0 2672 TabChild*
michael@0 2673 TabChild::GetFrom(uint64_t aLayersId)
michael@0 2674 {
michael@0 2675 if (!sTabChildren) {
michael@0 2676 return nullptr;
michael@0 2677 }
michael@0 2678 return sTabChildren->Get(aLayersId);
michael@0 2679 }
michael@0 2680
michael@0 2681 void
michael@0 2682 TabChild::DidComposite()
michael@0 2683 {
michael@0 2684 MOZ_ASSERT(mWidget);
michael@0 2685 MOZ_ASSERT(mWidget->GetLayerManager());
michael@0 2686 MOZ_ASSERT(mWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT);
michael@0 2687
michael@0 2688 ClientLayerManager *manager = static_cast<ClientLayerManager*>(mWidget->GetLayerManager());
michael@0 2689 manager->DidComposite();
michael@0 2690 }
michael@0 2691
michael@0 2692 NS_IMETHODIMP
michael@0 2693 TabChild::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText)
michael@0 2694 {
michael@0 2695 nsString str(aTipText);
michael@0 2696 SendShowTooltip(aXCoords, aYCoords, str);
michael@0 2697 return NS_OK;
michael@0 2698 }
michael@0 2699
michael@0 2700 NS_IMETHODIMP
michael@0 2701 TabChild::OnHideTooltip()
michael@0 2702 {
michael@0 2703 SendHideTooltip();
michael@0 2704 return NS_OK;
michael@0 2705 }
michael@0 2706
michael@0 2707 TabChildGlobal::TabChildGlobal(TabChildBase* aTabChild)
michael@0 2708 : mTabChild(aTabChild)
michael@0 2709 {
michael@0 2710 }
michael@0 2711
michael@0 2712 void
michael@0 2713 TabChildGlobal::Init()
michael@0 2714 {
michael@0 2715 NS_ASSERTION(!mMessageManager, "Re-initializing?!?");
michael@0 2716 mMessageManager = new nsFrameMessageManager(mTabChild,
michael@0 2717 nullptr,
michael@0 2718 MM_CHILD);
michael@0 2719 }
michael@0 2720
michael@0 2721 NS_IMPL_CYCLE_COLLECTION_INHERITED(TabChildGlobal, DOMEventTargetHelper,
michael@0 2722 mMessageManager, mTabChild)
michael@0 2723
michael@0 2724 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChildGlobal)
michael@0 2725 NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
michael@0 2726 NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
michael@0 2727 NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender)
michael@0 2728 NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
michael@0 2729 NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
michael@0 2730 NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
michael@0 2731 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
michael@0 2732 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
michael@0 2733
michael@0 2734 NS_IMPL_ADDREF_INHERITED(TabChildGlobal, DOMEventTargetHelper)
michael@0 2735 NS_IMPL_RELEASE_INHERITED(TabChildGlobal, DOMEventTargetHelper)
michael@0 2736
michael@0 2737 /* [notxpcom] boolean markForCC (); */
michael@0 2738 // This method isn't automatically forwarded safely because it's notxpcom, so
michael@0 2739 // the IDL binding doesn't know what value to return.
michael@0 2740 NS_IMETHODIMP_(bool)
michael@0 2741 TabChildGlobal::MarkForCC()
michael@0 2742 {
michael@0 2743 return mMessageManager ? mMessageManager->MarkForCC() : false;
michael@0 2744 }
michael@0 2745
michael@0 2746 NS_IMETHODIMP
michael@0 2747 TabChildGlobal::GetContent(nsIDOMWindow** aContent)
michael@0 2748 {
michael@0 2749 *aContent = nullptr;
michael@0 2750 if (!mTabChild)
michael@0 2751 return NS_ERROR_NULL_POINTER;
michael@0 2752 nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mTabChild->WebNavigation());
michael@0 2753 window.swap(*aContent);
michael@0 2754 return NS_OK;
michael@0 2755 }
michael@0 2756
michael@0 2757 NS_IMETHODIMP
michael@0 2758 TabChildGlobal::PrivateNoteIntentionalCrash()
michael@0 2759 {
michael@0 2760 mozilla::NoteIntentionalCrash("tab");
michael@0 2761 return NS_OK;
michael@0 2762 }
michael@0 2763
michael@0 2764 NS_IMETHODIMP
michael@0 2765 TabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
michael@0 2766 {
michael@0 2767 *aDocShell = nullptr;
michael@0 2768 if (!mTabChild)
michael@0 2769 return NS_ERROR_NULL_POINTER;
michael@0 2770 nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mTabChild->WebNavigation());
michael@0 2771 docShell.swap(*aDocShell);
michael@0 2772 return NS_OK;
michael@0 2773 }
michael@0 2774
michael@0 2775 NS_IMETHODIMP
michael@0 2776 TabChildGlobal::Btoa(const nsAString& aBinaryData,
michael@0 2777 nsAString& aAsciiBase64String)
michael@0 2778 {
michael@0 2779 return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
michael@0 2780 }
michael@0 2781
michael@0 2782 NS_IMETHODIMP
michael@0 2783 TabChildGlobal::Atob(const nsAString& aAsciiString,
michael@0 2784 nsAString& aBinaryData)
michael@0 2785 {
michael@0 2786 return nsContentUtils::Atob(aAsciiString, aBinaryData);
michael@0 2787 }
michael@0 2788
michael@0 2789 JSContext*
michael@0 2790 TabChildGlobal::GetJSContextForEventHandlers()
michael@0 2791 {
michael@0 2792 return nsContentUtils::GetSafeJSContext();
michael@0 2793 }
michael@0 2794
michael@0 2795 nsIPrincipal*
michael@0 2796 TabChildGlobal::GetPrincipal()
michael@0 2797 {
michael@0 2798 if (!mTabChild)
michael@0 2799 return nullptr;
michael@0 2800 return mTabChild->GetPrincipal();
michael@0 2801 }
michael@0 2802
michael@0 2803 JSObject*
michael@0 2804 TabChildGlobal::GetGlobalJSObject()
michael@0 2805 {
michael@0 2806 NS_ENSURE_TRUE(mTabChild, nullptr);
michael@0 2807 nsCOMPtr<nsIXPConnectJSObjectHolder> ref = mTabChild->GetGlobal();
michael@0 2808 NS_ENSURE_TRUE(ref, nullptr);
michael@0 2809 return ref->GetJSObject();
michael@0 2810 }
michael@0 2811

mercurial