dom/ipc/TabParent.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

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

mercurial