Bug 1299061 - Expose the browser that the request was originated in; r=smaug draft
authorChun-Min Chang <chun.m.chang@gmail.com>
Wed, 31 Aug 2016 20:56:17 +0800
changeset 410067 a0602ea2b079500ffd4e420f7edb8b097ed2fa0d
parent 410066 8c9c4e816e86f903c1d820f3f29715dc070a5a4a
child 530482 7a76c55d76acc690bf3b168794b11ef4ba78f244
push id28627
push userbmo:cchang@mozilla.com
push dateTue, 06 Sep 2016 03:06:42 +0000
reviewerssmaug
bugs1299061
milestone51.0a1
Bug 1299061 - Expose the browser that the request was originated in; r=smaug MozReview-Commit-ID: 2iFQiYeoxBh
dom/ipc/ContentParent.cpp
dom/presentation/PresentationRequest.cpp
dom/presentation/PresentationService.cpp
dom/presentation/interfaces/nsIPresentationDevicePrompt.idl
dom/presentation/interfaces/nsIPresentationService.idl
dom/presentation/ipc/PPresentation.ipdl
dom/presentation/ipc/PresentationIPCService.cpp
dom/presentation/ipc/PresentationParent.cpp
dom/presentation/ipc/PresentationParent.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -3638,17 +3638,17 @@ ContentParent::DeallocPPresentationParen
   RefPtr<PresentationParent> actor =
   dont_AddRef(static_cast<PresentationParent*>(aActor));
   return true;
 }
 
 bool
 ContentParent::RecvPPresentationConstructor(PPresentationParent* aActor)
 {
-  return static_cast<PresentationParent*>(aActor)->Init();
+  return static_cast<PresentationParent*>(aActor)->Init(mChildID);
 }
 
 PFlyWebPublishedServerParent*
 ContentParent::AllocPFlyWebPublishedServerParent(const nsString& name,
                                                  const FlyWebPublishOptions& params)
 {
   RefPtr<FlyWebPublishedServerParent> actor =
     new FlyWebPublishedServerParent(name, params);
--- a/dom/presentation/PresentationRequest.cpp
+++ b/dom/presentation/PresentationRequest.cpp
@@ -194,19 +194,25 @@ PresentationRequest::StartWithDevice(con
 
   nsCOMPtr<nsIPresentationService> service =
     do_GetService(PRESENTATION_SERVICE_CONTRACTID);
   if(NS_WARN_IF(!service)) {
     promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
     return promise.forget();
   }
 
+  // Get xul:browser element in parent process or nsWindowRoot object in child
+  // process. If it's in child process, the corresponding xul:browser element
+  // will be obtained at PresentationRequestParent::DoRequest in its parent
+  // process.
+  nsCOMPtr<nsIDOMEventTarget> handler =
+    do_QueryInterface(GetOwner()->GetChromeEventHandler());
   nsCOMPtr<nsIPresentationServiceCallback> callback =
     new PresentationRequesterCallback(this, id, promise);
-  rv = service->StartSession(mUrls, id, origin, aDeviceId, GetOwner()->WindowID(), callback);
+  rv = service->StartSession(mUrls, id, origin, aDeviceId, GetOwner()->WindowID(), handler, callback);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
   }
 
   return promise.forget();
 }
 
 already_AddRefed<Promise>
--- a/dom/presentation/PresentationService.cpp
+++ b/dom/presentation/PresentationService.cpp
@@ -106,47 +106,51 @@ class PresentationDeviceRequest final : 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPRESENTATIONDEVICEREQUEST
 
   PresentationDeviceRequest(const nsTArray<nsString>& aUrls,
                             const nsAString& aId,
                             const nsAString& aOrigin,
                             uint64_t aWindowId,
+                            nsIDOMEventTarget* aEventTarget,
                             nsIPresentationServiceCallback* aCallback);
 
 private:
   virtual ~PresentationDeviceRequest() = default;
   nsresult CreateSessionInfo(nsIPresentationDevice* aDevice,
                              const nsAString& aSelectedRequestUrl);
 
   nsTArray<nsString> mRequestUrls;
   nsString mId;
   nsString mOrigin;
   uint64_t mWindowId;
+  nsWeakPtr mChromeEventHandler;
   nsCOMPtr<nsIPresentationServiceCallback> mCallback;
 };
 
 LazyLogModule gPresentationLog("Presentation");
 
 } // namespace dom
 } // namespace mozilla
 
 NS_IMPL_ISUPPORTS(PresentationDeviceRequest, nsIPresentationDeviceRequest)
 
 PresentationDeviceRequest::PresentationDeviceRequest(
                                       const nsTArray<nsString>& aUrls,
                                       const nsAString& aId,
                                       const nsAString& aOrigin,
                                       uint64_t aWindowId,
+                                      nsIDOMEventTarget* aEventTarget,
                                       nsIPresentationServiceCallback* aCallback)
   : mRequestUrls(aUrls)
   , mId(aId)
   , mOrigin(aOrigin)
   , mWindowId(aWindowId)
+  , mChromeEventHandler(do_GetWeakReference(aEventTarget))
   , mCallback(aCallback)
 {
   MOZ_ASSERT(!mRequestUrls.IsEmpty());
   MOZ_ASSERT(!mId.IsEmpty());
   MOZ_ASSERT(!mOrigin.IsEmpty());
   MOZ_ASSERT(mCallback);
 }
 
@@ -159,16 +163,24 @@ PresentationDeviceRequest::GetOrigin(nsA
 
 NS_IMETHODIMP
 PresentationDeviceRequest::GetRequestURLs(nsIArray** aUrls)
 {
   return ConvertURLArrayHelper(mRequestUrls, aUrls);
 }
 
 NS_IMETHODIMP
+PresentationDeviceRequest::GetChromeEventHandler(nsIDOMEventTarget** aChromeEventHandler)
+{
+  nsCOMPtr<nsIDOMEventTarget> handler(do_QueryReferent(mChromeEventHandler));
+  handler.forget(aChromeEventHandler);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 PresentationDeviceRequest::Select(nsIPresentationDevice* aDevice)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (NS_WARN_IF(!aDevice)) {
     MOZ_ASSERT(false, "|aDevice| should noe be null.");
     mCallback->NotifyError(NS_ERROR_DOM_OPERATION_ERR);
     return NS_ERROR_INVALID_ARG;
   }
@@ -629,30 +641,32 @@ PresentationService::IsAppInstalled(nsIU
 }
 
 NS_IMETHODIMP
 PresentationService::StartSession(const nsTArray<nsString>& aUrls,
                                   const nsAString& aSessionId,
                                   const nsAString& aOrigin,
                                   const nsAString& aDeviceId,
                                   uint64_t aWindowId,
+                                  nsIDOMEventTarget* aEventTarget,
                                   nsIPresentationServiceCallback* aCallback)
 {
   PRES_DEBUG("%s:id[%s]\n", __func__, NS_ConvertUTF16toUTF8(aSessionId).get());
 
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aCallback);
   MOZ_ASSERT(!aSessionId.IsEmpty());
   MOZ_ASSERT(!aUrls.IsEmpty());
 
   nsCOMPtr<nsIPresentationDeviceRequest> request =
     new PresentationDeviceRequest(aUrls,
                                   aSessionId,
                                   aOrigin,
                                   aWindowId,
+                                  aEventTarget,
                                   aCallback);
 
   if (aDeviceId.IsVoid()) {
     // Pop up a prompt and ask user to select a device.
     nsCOMPtr<nsIPresentationDevicePrompt> prompt =
       do_GetService(PRESENTATION_DEVICE_PROMPT_CONTRACTID);
     if (NS_WARN_IF(!prompt)) {
       return aCallback->NotifyError(NS_ERROR_DOM_OPERATION_ERR);
--- a/dom/presentation/interfaces/nsIPresentationDevicePrompt.idl
+++ b/dom/presentation/interfaces/nsIPresentationDevicePrompt.idl
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIArray;
+interface nsIDOMEventTarget;
 interface nsIPresentationDevice;
 
 %{C++
 #define PRESENTATION_DEVICE_PROMPT_CONTRACTID "@mozilla.org/presentation-device/prompt;1"
 %}
 
 /*
  * The information and callbacks for device selection
@@ -18,16 +19,19 @@ interface nsIPresentationDevice;
 interface nsIPresentationDeviceRequest : nsISupports
 {
   // The origin which initiate the request.
   readonly attribute DOMString origin;
 
   // The array of candidate URLs.
   readonly attribute nsIArray requestURLs;
 
+  // The XUL browser element that the request was originated in.
+  readonly attribute nsIDOMEventTarget chromeEventHandler;
+
   /*
    * Callback after selecting a device
    * @param device The selected device.
    */
   void select(in nsIPresentationDevice device);
 
   /*
    * Callback after selection failed or canceled by user.
--- a/dom/presentation/interfaces/nsIPresentationService.idl
+++ b/dom/presentation/interfaces/nsIPresentationService.idl
@@ -1,14 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
+interface nsIDOMEventTarget;
 interface nsIInputStream;
 interface nsIPresentationAvailabilityListener;
 interface nsIPresentationRespondingListener;
 interface nsIPresentationSessionListener;
 
 %{C++
 #define PRESENTATION_SERVICE_CID \
   { 0x1d9bb10c, 0xc0ab, 0x4fe8, \
@@ -54,31 +55,35 @@ interface nsIPresentationService : nsISu
   /*
    * Start a new presentation session and display a prompt box which asks users
    * to select a device.
    *
    * @param urls: The candidate Urls of presenting page. Only one url would be used.
    * @param sessionId: An ID to identify presentation session.
    * @param origin: The url of requesting page.
    * @param deviceId: The specified device of handling this request, null string
-                      for prompt device selection dialog.
+   *                  for prompt device selection dialog.
    * @param windowId: The inner window ID associated with the presentation
    *                  session. (0 implies no window ID since no actual window
    *                  uses 0 as its ID. Generally it's the case the window is
    *                  located in different process from this service)
+   * @param eventTarget: The chrome event handler, in particular XUL browser
+   *                     element in parent process, that the request was
+   *                     originated in.
    * @param callback: Invoke the callback when the operation is completed.
    *                  NotifySuccess() is called with |id| if a session is
    *                  established successfully with the selected device.
    *                  Otherwise, NotifyError() is called with a error message.
    */
   [noscript] void startSession(in URLArrayRef urls,
                                in DOMString sessionId,
                                in DOMString origin,
                                in DOMString deviceId,
                                in unsigned long long windowId,
+                               in nsIDOMEventTarget eventTarget,
                                in nsIPresentationServiceCallback callback);
 
   /*
    * Send the message to the session.
    *
    * @param sessionId: An ID to identify presentation session.
    * @param role: Identify the function called by controller or receiver.
    * @param data: the message being sent out.
--- a/dom/presentation/ipc/PPresentation.ipdl
+++ b/dom/presentation/ipc/PPresentation.ipdl
@@ -5,26 +5,29 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PContent;
 include protocol PPresentationRequest;
 include protocol PPresentationBuilder;
 
 include InputStreamParams;
 
+using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
+
 namespace mozilla {
 namespace dom {
 
 struct StartSessionRequest
 {
   nsString[] urls;
   nsString sessionId;
   nsString origin;
   nsString deviceId;
   uint64_t windowId;
+  TabId tabId;
 };
 
 struct SendSessionMessageRequest
 {
   nsString sessionId;
   uint8_t role;
   nsString data;
 };
--- a/dom/presentation/ipc/PresentationIPCService.cpp
+++ b/dom/presentation/ipc/PresentationIPCService.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et ft=cpp : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/PPresentation.h"
+#include "mozilla/dom/TabParent.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsIPresentationListener.h"
 #include "PresentationCallbacks.h"
 #include "PresentationChild.h"
 #include "PresentationContentSessionInfo.h"
 #include "PresentationIPCService.h"
@@ -52,29 +53,35 @@ PresentationIPCService::~PresentationIPC
 }
 
 NS_IMETHODIMP
 PresentationIPCService::StartSession(const nsTArray<nsString>& aUrls,
                                      const nsAString& aSessionId,
                                      const nsAString& aOrigin,
                                      const nsAString& aDeviceId,
                                      uint64_t aWindowId,
+                                     nsIDOMEventTarget* aEventTarget,
                                      nsIPresentationServiceCallback* aCallback)
 {
   if (aWindowId != 0) {
     AddRespondingSessionId(aWindowId,
                            aSessionId,
                            nsIPresentationService::ROLE_CONTROLLER);
   }
 
+  nsPIDOMWindowInner* window =
+    nsGlobalWindow::GetInnerWindowWithId(aWindowId)->AsInner();
+  TabId tabId = TabParent::GetTabIdFrom(window->GetDocShell());
+
   return SendRequest(aCallback, StartSessionRequest(aUrls,
                                                     nsString(aSessionId),
                                                     nsString(aOrigin),
                                                     nsString(aDeviceId),
-                                                    aWindowId));
+                                                    aWindowId,
+                                                    tabId));
 }
 
 NS_IMETHODIMP
 PresentationIPCService::SendSessionMessage(const nsAString& aSessionId,
                                            uint8_t aRole,
                                            const nsAString& aData)
 {
   MOZ_ASSERT(!aSessionId.IsEmpty());
--- a/dom/presentation/ipc/PresentationParent.cpp
+++ b/dom/presentation/ipc/PresentationParent.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DCPresentationChannelDescription.h"
+#include "mozilla/dom/ContentProcessManager.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/Unused.h"
 #include "nsIPresentationDeviceManager.h"
 #include "nsServiceManagerUtils.h"
 #include "PresentationBuilderParent.h"
 #include "PresentationParent.h"
 #include "PresentationService.h"
 #include "PresentationSessionInfo.h"
@@ -31,20 +32,21 @@ PresentationParent::PresentationParent()
 }
 
 /* virtual */ PresentationParent::~PresentationParent()
 {
   MOZ_COUNT_DTOR(PresentationParent);
 }
 
 bool
-PresentationParent::Init()
+PresentationParent::Init(ContentParentId aContentParentId)
 {
   MOZ_ASSERT(!mService);
   mService = do_GetService(PRESENTATION_SERVICE_CONTRACTID);
+  mChildId = aContentParentId;
   return NS_WARN_IF(!mService) ? false : true;
 }
 
 void
 PresentationParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   mActorDestroyed = true;
 
@@ -103,17 +105,17 @@ PresentationParent::RecvPPresentationReq
   return NS_WARN_IF(NS_FAILED(rv)) ? false : true;
 }
 
 PPresentationRequestParent*
 PresentationParent::AllocPPresentationRequestParent(
   const PresentationIPCRequest& aRequest)
 {
   MOZ_ASSERT(mService);
-  RefPtr<PresentationRequestParent> actor = new PresentationRequestParent(mService);
+  RefPtr<PresentationRequestParent> actor = new PresentationRequestParent(mService, mChildId);
   return actor.forget().take();
 }
 
 bool
 PresentationParent::DeallocPPresentationRequestParent(
   PPresentationRequestParent* aActor)
 {
   RefPtr<PresentationRequestParent> actor =
@@ -305,18 +307,20 @@ PresentationParent::RecvNotifyTransportC
 }
 
 /*
  * Implementation of PresentationRequestParent
  */
 
 NS_IMPL_ISUPPORTS(PresentationRequestParent, nsIPresentationServiceCallback)
 
-PresentationRequestParent::PresentationRequestParent(nsIPresentationService* aService)
+PresentationRequestParent::PresentationRequestParent(nsIPresentationService* aService,
+                                                     ContentParentId aContentParentId)
   : mService(aService)
+  , mChildId(aContentParentId)
 {
   MOZ_COUNT_CTOR(PresentationRequestParent);
 }
 
 PresentationRequestParent::~PresentationRequestParent()
 {
   MOZ_COUNT_DTOR(PresentationRequestParent);
 }
@@ -329,19 +333,28 @@ PresentationRequestParent::ActorDestroy(
 }
 
 nsresult
 PresentationRequestParent::DoRequest(const StartSessionRequest& aRequest)
 {
   MOZ_ASSERT(mService);
   mNeedRegisterBuilder = true;
   mSessionId = aRequest.sessionId();
+
+  nsCOMPtr<nsIDOMEventTarget> eventTarget;
+  ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
+  RefPtr<TabParent> tp =
+    cpm->GetTopLevelTabParentByProcessAndTabId(mChildId, aRequest.tabId());
+  if (tp) {
+    eventTarget = do_QueryInterface(tp->GetOwnerElement());
+  }
+  
   return mService->StartSession(aRequest.urls(), aRequest.sessionId(),
                                 aRequest.origin(), aRequest.deviceId(),
-                                aRequest.windowId(), this);
+                                aRequest.windowId(), eventTarget, this);
 }
 
 nsresult
 PresentationRequestParent::DoRequest(const SendSessionMessageRequest& aRequest)
 {
   MOZ_ASSERT(mService);
 
   // Validate the accessibility (primarily for receiver side) so that a
--- a/dom/presentation/ipc/PresentationParent.h
+++ b/dom/presentation/ipc/PresentationParent.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_PresentationParent_h__
 #define mozilla_dom_PresentationParent_h__
 
+#include "mozilla/dom/ipc/IdType.h"
 #include "mozilla/dom/PPresentationBuilderParent.h"
 #include "mozilla/dom/PPresentationParent.h"
 #include "mozilla/dom/PPresentationRequestParent.h"
 #include "nsIPresentationListener.h"
 #include "nsIPresentationService.h"
 #include "nsIPresentationSessionTransportBuilder.h"
 
 namespace mozilla {
@@ -25,17 +26,17 @@ class PresentationParent final : public 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPRESENTATIONAVAILABILITYLISTENER
   NS_DECL_NSIPRESENTATIONSESSIONLISTENER
   NS_DECL_NSIPRESENTATIONRESPONDINGLISTENER
 
   PresentationParent();
 
-  bool Init();
+  bool Init(ContentParentId aContentParentId);
 
   bool RegisterTransportBuilder(const nsString& aSessionId, const uint8_t& aRole);
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   virtual bool
   RecvPPresentationRequestConstructor(PPresentationRequestParent* aActor,
                                       const PresentationIPCRequest& aRequest) override;
@@ -81,28 +82,30 @@ public:
 private:
   virtual ~PresentationParent();
 
   bool mActorDestroyed = false;
   nsCOMPtr<nsIPresentationService> mService;
   nsTArray<nsString> mSessionIdsAtController;
   nsTArray<nsString> mSessionIdsAtReceiver;
   nsTArray<uint64_t> mWindowIds;
+  ContentParentId mChildId;
 };
 
 class PresentationRequestParent final : public PPresentationRequestParent
                                       , public nsIPresentationServiceCallback
 {
   friend class PresentationParent;
 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPRESENTATIONSERVICECALLBACK
 
-  explicit PresentationRequestParent(nsIPresentationService* aService);
+  explicit PresentationRequestParent(nsIPresentationService* aService,
+                                     ContentParentId aContentParentId);
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
 private:
   virtual ~PresentationRequestParent();
 
   nsresult SendResponse(nsresult aResult);
 
@@ -117,14 +120,15 @@ private:
   nsresult DoRequest(const ReconnectSessionRequest& aRequest);
 
   nsresult DoRequest(const BuildTransportRequest& aRequest);
 
   bool mActorDestroyed = false;
   bool mNeedRegisterBuilder = false;
   nsString mSessionId;
   nsCOMPtr<nsIPresentationService> mService;
+  ContentParentId mChildId;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_PresentationParent_h__