tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

InProcessBrowserChildMessageManager.cpp (9237B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "InProcessBrowserChildMessageManager.h"
      8 
      9 #include "mozilla/EventDispatcher.h"
     10 #include "mozilla/HoldDropJSObjects.h"
     11 #include "mozilla/dom/ChromeMessageSender.h"
     12 #include "mozilla/dom/Document.h"
     13 #include "mozilla/dom/JSActorService.h"
     14 #include "mozilla/dom/MessageManagerBinding.h"
     15 #include "mozilla/dom/SameProcessMessageQueue.h"
     16 #include "mozilla/dom/ScriptLoader.h"
     17 #include "mozilla/dom/WindowProxyHolder.h"
     18 #include "nsComponentManagerUtils.h"
     19 #include "nsContentUtils.h"
     20 #include "nsDocShell.h"
     21 #include "nsFrameLoader.h"
     22 #include "nsFrameLoaderOwner.h"
     23 #include "nsIInterfaceRequestorUtils.h"
     24 #include "nsQueryObject.h"
     25 #include "xpcpublic.h"
     26 
     27 using namespace mozilla;
     28 using namespace mozilla::dom;
     29 using namespace mozilla::dom::ipc;
     30 
     31 /* static */
     32 already_AddRefed<InProcessBrowserChildMessageManager>
     33 InProcessBrowserChildMessageManager::Create(nsDocShell* aShell,
     34                                            nsIContent* aOwner,
     35                                            nsFrameMessageManager* aChrome) {
     36  RefPtr<InProcessBrowserChildMessageManager> mm =
     37      new InProcessBrowserChildMessageManager(aShell, aOwner, aChrome);
     38 
     39  NS_ENSURE_TRUE(mm->Init(), nullptr);
     40 
     41  if (XRE_IsParentProcess()) {
     42    RefPtr<JSActorService> wasvc = JSActorService::GetSingleton();
     43    wasvc->RegisterChromeEventTarget(mm);
     44  }
     45 
     46  return mm.forget();
     47 }
     48 
     49 bool InProcessBrowserChildMessageManager::DoSendBlockingMessage(
     50    const nsAString& aMessage, StructuredCloneData& aData,
     51    nsTArray<UniquePtr<StructuredCloneData>>* aRetVal) {
     52  SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
     53  queue->Flush();
     54 
     55  if (mChromeMessageManager) {
     56    RefPtr<nsFrameMessageManager> mm = mChromeMessageManager;
     57    RefPtr<nsFrameLoader> fl = GetFrameLoader();
     58    mm->ReceiveMessage(mOwner, fl, aMessage, true, &aData, aRetVal,
     59                       IgnoreErrors());
     60  }
     61  return true;
     62 }
     63 
     64 class nsAsyncMessageToParent : public nsSameProcessAsyncMessageBase,
     65                               public SameProcessMessageQueue::Runnable {
     66 public:
     67  explicit nsAsyncMessageToParent(
     68      InProcessBrowserChildMessageManager* aBrowserChild)
     69      : mBrowserChild(aBrowserChild) {}
     70 
     71  virtual nsresult HandleMessage() override {
     72    RefPtr<nsFrameLoader> fl = mBrowserChild->GetFrameLoader();
     73    ReceiveMessage(mBrowserChild->mOwner, fl,
     74                   mBrowserChild->mChromeMessageManager);
     75    return NS_OK;
     76  }
     77  RefPtr<InProcessBrowserChildMessageManager> mBrowserChild;
     78 };
     79 
     80 nsresult InProcessBrowserChildMessageManager::DoSendAsyncMessage(
     81    const nsAString& aMessage, StructuredCloneData& aData) {
     82  SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
     83  RefPtr<nsAsyncMessageToParent> ev = new nsAsyncMessageToParent(this);
     84 
     85  nsresult rv = ev->Init(aMessage, aData);
     86  if (NS_FAILED(rv)) {
     87    return rv;
     88  }
     89 
     90  queue->Push(ev);
     91  return NS_OK;
     92 }
     93 
     94 InProcessBrowserChildMessageManager::InProcessBrowserChildMessageManager(
     95    nsDocShell* aShell, nsIContent* aOwner, nsFrameMessageManager* aChrome)
     96    : ContentFrameMessageManager(new nsFrameMessageManager(this)),
     97      mDocShell(aShell),
     98      mLoadingScript(false),
     99      mPreventEventsEscaping(false),
    100      mOwner(aOwner),
    101      mChromeMessageManager(aChrome) {
    102  mozilla::HoldJSObjects(this);
    103 }
    104 
    105 InProcessBrowserChildMessageManager::~InProcessBrowserChildMessageManager() {
    106  if (XRE_IsParentProcess()) {
    107    JSActorService::UnregisterChromeEventTarget(this);
    108  }
    109 
    110  mozilla::DropJSObjects(this);
    111 }
    112 
    113 // This method isn't automatically forwarded safely because it's notxpcom, so
    114 // the IDL binding doesn't know what value to return.
    115 void InProcessBrowserChildMessageManager::MarkForCC() {
    116  MarkScopesForCC();
    117  MessageManagerGlobal::MarkForCC();
    118 }
    119 
    120 NS_IMPL_CYCLE_COLLECTION_CLASS(InProcessBrowserChildMessageManager)
    121 
    122 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(
    123    InProcessBrowserChildMessageManager, DOMEventTargetHelper)
    124  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
    125  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)
    126 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    127 
    128 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(
    129    InProcessBrowserChildMessageManager, DOMEventTargetHelper)
    130  tmp->nsMessageManagerScriptExecutor::Trace(aCallbacks, aClosure);
    131 NS_IMPL_CYCLE_COLLECTION_TRACE_END
    132 
    133 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(
    134    InProcessBrowserChildMessageManager, DOMEventTargetHelper)
    135  if (XRE_IsParentProcess()) {
    136    JSActorService::UnregisterChromeEventTarget(tmp);
    137  }
    138 
    139  NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
    140  NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)
    141  tmp->nsMessageManagerScriptExecutor::Unlink();
    142  NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
    143 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    144 
    145 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InProcessBrowserChildMessageManager)
    146  NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
    147  NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
    148  NS_INTERFACE_MAP_ENTRY_CONCRETE(ContentFrameMessageManager)
    149  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
    150 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
    151 
    152 NS_IMPL_ADDREF_INHERITED(InProcessBrowserChildMessageManager,
    153                         DOMEventTargetHelper)
    154 NS_IMPL_RELEASE_INHERITED(InProcessBrowserChildMessageManager,
    155                          DOMEventTargetHelper)
    156 
    157 JSObject* InProcessBrowserChildMessageManager::WrapObject(
    158    JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
    159  return ContentFrameMessageManager_Binding::Wrap(aCx, this, aGivenProto);
    160 }
    161 
    162 void InProcessBrowserChildMessageManager::CacheFrameLoader(
    163    nsFrameLoader* aFrameLoader) {
    164  mFrameLoader = aFrameLoader;
    165 }
    166 
    167 Nullable<WindowProxyHolder> InProcessBrowserChildMessageManager::GetContent(
    168    ErrorResult& aError) {
    169  if (!mDocShell) {
    170    return nullptr;
    171  }
    172  return WindowProxyHolder(mDocShell->GetBrowsingContext());
    173 }
    174 
    175 already_AddRefed<nsIEventTarget>
    176 InProcessBrowserChildMessageManager::GetTabEventTarget() {
    177  nsCOMPtr<nsIEventTarget> target = GetMainThreadSerialEventTarget();
    178  return target.forget();
    179 }
    180 
    181 void InProcessBrowserChildMessageManager::FireUnloadEvent() {
    182  // We're called from Document::MaybeInitializeFinalizeFrameLoaders, so it
    183  // should be safe to run script.
    184  MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
    185 
    186  // Don't let the unload event propagate to chrome event handlers.
    187  mPreventEventsEscaping = true;
    188  DOMEventTargetHelper::DispatchTrustedEvent(u"unload"_ns);
    189 
    190  // Allow events fired during docshell destruction (pagehide, unload) to
    191  // propagate to the <browser> element since chrome code depends on this.
    192  mPreventEventsEscaping = false;
    193 }
    194 
    195 void InProcessBrowserChildMessageManager::DisconnectEventListeners() {
    196  if (mDocShell) {
    197    if (nsCOMPtr<nsPIDOMWindowOuter> win = mDocShell->GetWindow()) {
    198      win->SetChromeEventHandler(win->GetChromeEventHandler());
    199    }
    200  }
    201  if (mListenerManager) {
    202    mListenerManager->Disconnect();
    203  }
    204 
    205  mDocShell = nullptr;
    206 }
    207 
    208 void InProcessBrowserChildMessageManager::Disconnect() {
    209  mChromeMessageManager = nullptr;
    210  mOwner = nullptr;
    211  if (mMessageManager) {
    212    static_cast<nsFrameMessageManager*>(mMessageManager.get())->Disconnect();
    213    mMessageManager = nullptr;
    214  }
    215 }
    216 
    217 NS_IMETHODIMP_(nsIContent*)
    218 InProcessBrowserChildMessageManager::GetOwnerContent() { return mOwner; }
    219 
    220 void InProcessBrowserChildMessageManager::GetEventTargetParent(
    221    EventChainPreVisitor& aVisitor) {
    222  aVisitor.mForceContentDispatch = true;
    223  aVisitor.mCanHandle = true;
    224 
    225  if (mPreventEventsEscaping) {
    226    aVisitor.SetParentTarget(nullptr, false);
    227    return;
    228  }
    229 
    230  aVisitor.SetParentTarget(mOwner, false);
    231 }
    232 
    233 class nsAsyncScriptLoad : public Runnable {
    234 public:
    235  nsAsyncScriptLoad(InProcessBrowserChildMessageManager* aBrowserChild,
    236                    const nsAString& aURL, bool aRunInGlobalScope)
    237      : mozilla::Runnable("nsAsyncScriptLoad"),
    238        mBrowserChild(aBrowserChild),
    239        mURL(aURL),
    240        mRunInGlobalScope(aRunInGlobalScope) {}
    241 
    242  NS_IMETHOD Run() override {
    243    mBrowserChild->LoadFrameScript(mURL, mRunInGlobalScope);
    244    return NS_OK;
    245  }
    246  RefPtr<InProcessBrowserChildMessageManager> mBrowserChild;
    247  nsString mURL;
    248  bool mRunInGlobalScope;
    249 };
    250 
    251 void InProcessBrowserChildMessageManager::LoadFrameScript(
    252    const nsAString& aURL, bool aRunInGlobalScope) {
    253  if (!nsContentUtils::IsSafeToRunScript()) {
    254    nsContentUtils::AddScriptRunner(
    255        new nsAsyncScriptLoad(this, aURL, aRunInGlobalScope));
    256    return;
    257  }
    258  bool tmp = mLoadingScript;
    259  mLoadingScript = true;
    260  JS::Rooted<JSObject*> mm(mozilla::dom::RootingCx(), GetOrCreateWrapper());
    261  LoadScriptInternal(mm, aURL, !aRunInGlobalScope);
    262  mLoadingScript = tmp;
    263 }
    264 
    265 already_AddRefed<nsFrameLoader>
    266 InProcessBrowserChildMessageManager::GetFrameLoader() {
    267  RefPtr<nsFrameLoaderOwner> owner = do_QueryObject(mOwner);
    268  RefPtr<nsFrameLoader> fl = owner ? owner->GetFrameLoader() : nullptr;
    269  if (!fl) {
    270    fl = mFrameLoader;
    271  }
    272  return fl.forget();
    273 }