LCOV - code coverage report
Current view: top level - dom/workers - ServiceWorkerClient.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 136 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 18 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/.
       6             :  */
       7             : 
       8             : #include "ServiceWorkerClient.h"
       9             : #include "ServiceWorkerContainer.h"
      10             : 
      11             : #include "mozilla/dom/MessageEvent.h"
      12             : #include "mozilla/dom/Navigator.h"
      13             : #include "nsGlobalWindow.h"
      14             : #include "nsIBrowserDOMWindow.h"
      15             : #include "nsIDocument.h"
      16             : #include "ServiceWorker.h"
      17             : #include "ServiceWorkerPrivate.h"
      18             : #include "WorkerPrivate.h"
      19             : 
      20             : using namespace mozilla;
      21             : using namespace mozilla::dom;
      22             : using namespace mozilla::dom::workers;
      23             : 
      24           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ServiceWorkerClient, mOwner)
      25             : 
      26           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(ServiceWorkerClient)
      27           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(ServiceWorkerClient)
      28             : 
      29           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerClient)
      30           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      31           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      32           0 : NS_INTERFACE_MAP_END
      33             : 
      34           0 : ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc, uint32_t aOrdinal)
      35             :   : mType(ClientType::Window)
      36             :   , mOrdinal(aOrdinal)
      37             :   , mWindowId(0)
      38           0 :   , mFrameType(FrameType::None)
      39             : {
      40           0 :   MOZ_ASSERT(aDoc);
      41           0 :   nsresult rv = aDoc->GetOrCreateId(mClientId);
      42           0 :   if (NS_FAILED(rv)) {
      43           0 :     NS_WARNING("Failed to get the UUID of the document.");
      44             :   }
      45             : 
      46           0 :   RefPtr<nsGlobalWindow> innerWindow = nsGlobalWindow::Cast(aDoc->GetInnerWindow());
      47           0 :   if (innerWindow) {
      48             :     // XXXcatalinb: The inner window can be null if the document is navigating
      49             :     // and was detached.
      50           0 :     mWindowId = innerWindow->WindowID();
      51             :   }
      52             : 
      53           0 :   nsCOMPtr<nsIURI> originalURI = aDoc->GetOriginalURI();
      54           0 :   if (originalURI) {
      55           0 :     nsAutoCString spec;
      56           0 :     originalURI->GetSpec(spec);
      57           0 :     CopyUTF8toUTF16(spec, mUrl);
      58             :   }
      59           0 :   mVisibilityState = aDoc->VisibilityState();
      60             : 
      61           0 :   mLastFocusTime = aDoc->LastFocusTime();
      62             : 
      63           0 :   ErrorResult result;
      64           0 :   mFocused = aDoc->HasFocus(result);
      65           0 :   if (result.Failed()) {
      66           0 :     NS_WARNING("Failed to get focus information.");
      67             :   }
      68             : 
      69           0 :   MOZ_ASSERT_IF(mLastFocusTime.IsNull(), !mFocused);
      70           0 :   MOZ_ASSERT_IF(mFocused, !mLastFocusTime.IsNull());
      71             : 
      72           0 :   RefPtr<nsGlobalWindow> outerWindow = nsGlobalWindow::Cast(aDoc->GetWindow());
      73           0 :   if (!outerWindow) {
      74           0 :     MOZ_ASSERT(mFrameType == FrameType::None);
      75           0 :   } else if (!outerWindow->IsTopLevelWindow()) {
      76           0 :     mFrameType = FrameType::Nested;
      77           0 :   } else if (outerWindow->HadOriginalOpener()) {
      78           0 :     mFrameType = FrameType::Auxiliary;
      79             :   } else {
      80           0 :     mFrameType = FrameType::Top_level;
      81             :   }
      82           0 : }
      83             : 
      84             : bool
      85           0 : ServiceWorkerClientInfo::operator<(const ServiceWorkerClientInfo& aRight) const
      86             : {
      87             :   // Note: the mLastFocusTime comparisons are reversed because we need to
      88             :   // put most recently focused values first.  The mOrdinal comparison is
      89             :   // normal, though, because otherwise we want normal creation order.
      90             : 
      91           0 :   if (mLastFocusTime == aRight.mLastFocusTime) {
      92           0 :     return mOrdinal < aRight.mOrdinal;
      93             :   }
      94             : 
      95           0 :   if (mLastFocusTime.IsNull()) {
      96           0 :     return false;
      97             :   }
      98             : 
      99           0 :   if (aRight.mLastFocusTime.IsNull()) {
     100           0 :     return true;
     101             :   }
     102             : 
     103           0 :   return mLastFocusTime > aRight.mLastFocusTime;
     104             : }
     105             : 
     106             : bool
     107           0 : ServiceWorkerClientInfo::operator==(const ServiceWorkerClientInfo& aRight) const
     108             : {
     109           0 :   return mLastFocusTime == aRight.mLastFocusTime &&
     110           0 :          mOrdinal == aRight.mOrdinal &&
     111           0 :          mClientId == aRight.mClientId;
     112             : }
     113             : 
     114             : JSObject*
     115           0 : ServiceWorkerClient::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     116             : {
     117           0 :   return ClientBinding::Wrap(aCx, this, aGivenProto);
     118             : }
     119             : 
     120             : ClientType
     121           0 : ServiceWorkerClient::Type() const
     122             : {
     123           0 :   return mType;
     124             : }
     125             : 
     126             : namespace {
     127             : 
     128           0 : class ServiceWorkerClientPostMessageRunnable final
     129             :   : public Runnable
     130             :   , public StructuredCloneHolder
     131             : {
     132             :   const uint64_t mSourceID;
     133             :   const nsCString mSourceScope;
     134             :   const uint64_t mWindowId;
     135             : 
     136             : public:
     137           0 :   ServiceWorkerClientPostMessageRunnable(uint64_t aSourceID,
     138             :                                          const nsACString& aSourceScope,
     139             :                                          uint64_t aWindowId)
     140           0 :     : mozilla::Runnable("ServiceWorkerClientPostMessageRunnable")
     141             :     , StructuredCloneHolder(CloningSupported,
     142             :                             TransferringSupported,
     143             :                             StructuredCloneScope::SameProcessDifferentThread)
     144             :     , mSourceID(aSourceID)
     145             :     , mSourceScope(aSourceScope)
     146           0 :     , mWindowId(aWindowId)
     147           0 :   {}
     148             : 
     149             :   NS_IMETHOD
     150           0 :   Run() override
     151             :   {
     152           0 :     AssertIsOnMainThread();
     153           0 :     nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowId);
     154           0 :     if (!window) {
     155           0 :       return NS_ERROR_FAILURE;
     156             :     }
     157             : 
     158           0 :     dom::Navigator* navigator = window->Navigator();
     159           0 :     if (!navigator) {
     160           0 :       return NS_ERROR_FAILURE;
     161             :     }
     162             : 
     163           0 :     RefPtr<ServiceWorkerContainer> container = navigator->ServiceWorker();
     164           0 :     AutoJSAPI jsapi;
     165           0 :     if (NS_WARN_IF(!jsapi.Init(window))) {
     166           0 :       return NS_ERROR_FAILURE;
     167             :     }
     168           0 :     JSContext* cx = jsapi.cx();
     169             : 
     170           0 :     return DispatchDOMEvent(cx, window->AsInner(), container);
     171             :   }
     172             : 
     173             : private:
     174             :   NS_IMETHOD
     175           0 :   DispatchDOMEvent(JSContext* aCx, nsPIDOMWindowInner* aWindow,
     176             :                    ServiceWorkerContainer* aTargetContainer)
     177             :   {
     178           0 :     AssertIsOnMainThread();
     179             : 
     180           0 :     MOZ_ASSERT(aTargetContainer->GetParentObject(),
     181             :                "How come we don't have a window here?!");
     182             : 
     183           0 :     JS::Rooted<JS::Value> messageData(aCx);
     184           0 :     ErrorResult rv;
     185           0 :     Read(aTargetContainer->GetParentObject(), aCx, &messageData, rv);
     186           0 :     if (NS_WARN_IF(rv.Failed())) {
     187           0 :       xpc::Throw(aCx, rv.StealNSResult());
     188           0 :       return NS_ERROR_FAILURE;
     189             :     }
     190             : 
     191           0 :     RootedDictionary<MessageEventInit> init(aCx);
     192             : 
     193           0 :     nsCOMPtr<nsIPrincipal> principal = aTargetContainer->GetParentObject()->PrincipalOrNull();
     194           0 :     NS_WARNING_ASSERTION(principal, "Why is the principal null here?");
     195             : 
     196           0 :     bool isNullPrincipal = false;
     197           0 :     bool isSystemPrincipal = false;
     198           0 :     if (principal) {
     199           0 :       isNullPrincipal = principal->GetIsNullPrincipal();
     200           0 :       MOZ_ASSERT(!isNullPrincipal);
     201           0 :       isSystemPrincipal = principal->GetIsSystemPrincipal();
     202           0 :       MOZ_ASSERT(!isSystemPrincipal);
     203             :     }
     204             : 
     205           0 :     init.mData = messageData;
     206           0 :     nsAutoCString origin;
     207           0 :     if (principal && !isNullPrincipal && !isSystemPrincipal) {
     208           0 :       principal->GetOrigin(origin);
     209             :     }
     210           0 :     init.mOrigin = NS_ConvertUTF8toUTF16(origin);
     211             : 
     212             : 
     213           0 :     RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
     214           0 :     if (swm) {
     215             :       RefPtr<ServiceWorkerRegistrationInfo> reg =
     216           0 :         swm->GetRegistration(principal, mSourceScope);
     217           0 :       if (reg) {
     218           0 :         RefPtr<ServiceWorkerInfo> serviceWorker = reg->GetByID(mSourceID);
     219           0 :         if (serviceWorker) {
     220           0 :           init.mSource.SetValue().SetAsServiceWorker() =
     221           0 :             serviceWorker->GetOrCreateInstance(aWindow);
     222             :         }
     223             :       }
     224             :     }
     225             : 
     226           0 :     if (!TakeTransferredPortsAsSequence(init.mPorts)) {
     227           0 :       return NS_ERROR_OUT_OF_MEMORY;
     228             :     }
     229             : 
     230             :     RefPtr<MessageEvent> event =
     231           0 :       MessageEvent::Constructor(aTargetContainer, NS_LITERAL_STRING("message"),
     232           0 :                                 init);
     233             : 
     234           0 :     event->SetTrusted(true);
     235           0 :     bool status = false;
     236           0 :     aTargetContainer->DispatchEvent(static_cast<dom::Event*>(event.get()),
     237           0 :                                     &status);
     238             : 
     239           0 :     if (!status) {
     240           0 :       return NS_ERROR_FAILURE;
     241             :     }
     242             : 
     243           0 :     return NS_OK;
     244             :   }
     245             : };
     246             : 
     247             : } // namespace
     248             : 
     249             : void
     250           0 : ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
     251             :                                  const Sequence<JSObject*>& aTransferable,
     252             :                                  ErrorResult& aRv)
     253             : {
     254           0 :   WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
     255           0 :   MOZ_ASSERT(workerPrivate);
     256           0 :   workerPrivate->AssertIsOnWorkerThread();
     257             : 
     258           0 :   JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
     259             : 
     260           0 :   aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable,
     261           0 :                                                           &transferable);
     262           0 :   if (NS_WARN_IF(aRv.Failed())) {
     263           0 :     return;
     264             :   }
     265             : 
     266             :   // At the moment we only expose Client on ServiceWorker globals.
     267           0 :   MOZ_ASSERT(workerPrivate->IsServiceWorker());
     268           0 :   uint32_t serviceWorkerID = workerPrivate->ServiceWorkerID();
     269           0 :   nsCString scope = workerPrivate->ServiceWorkerScope();
     270             : 
     271             :   RefPtr<ServiceWorkerClientPostMessageRunnable> runnable =
     272             :     new ServiceWorkerClientPostMessageRunnable(serviceWorkerID, scope,
     273           0 :                                                mWindowId);
     274             : 
     275           0 :   runnable->Write(aCx, aMessage, transferable, JS::CloneDataPolicy().denySharedArrayBuffer(),
     276           0 :                   aRv);
     277           0 :   if (NS_WARN_IF(aRv.Failed())) {
     278           0 :     return;
     279             :   }
     280             : 
     281           0 :   aRv = workerPrivate->DispatchToMainThread(runnable.forget());
     282           0 :   if (NS_WARN_IF(aRv.Failed())) {
     283           0 :     return;
     284             :   }
     285             : }
     286             : 

Generated by: LCOV version 1.13