LCOV - code coverage report
Current view: top level - dom/file/ipc - IPCBlobInputStreamStorage.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 13 93 14.0 %
Date: 2017-07-14 16:53:18 Functions: 3 13 23.1 %
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
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "IPCBlobInputStreamStorage.h"
       8             : 
       9             : #include "mozilla/dom/ContentParent.h"
      10             : #include "mozilla/StaticMutex.h"
      11             : #include "mozilla/StaticPtr.h"
      12             : #include "nsIPropertyBag2.h"
      13             : #include "nsStreamUtils.h"
      14             : 
      15             : namespace mozilla {
      16             : 
      17             : using namespace hal;
      18             : 
      19             : namespace dom {
      20             : 
      21             : namespace {
      22           3 : StaticMutex gMutex;
      23           3 : StaticRefPtr<IPCBlobInputStreamStorage> gStorage;
      24             : }
      25             : 
      26           0 : NS_INTERFACE_MAP_BEGIN(IPCBlobInputStreamStorage)
      27           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
      28           0 :   NS_INTERFACE_MAP_ENTRY(nsIObserver)
      29           0 : NS_INTERFACE_MAP_END
      30             : 
      31           9 : NS_IMPL_ADDREF(IPCBlobInputStreamStorage)
      32           0 : NS_IMPL_RELEASE(IPCBlobInputStreamStorage)
      33             : 
      34           3 : IPCBlobInputStreamStorage::IPCBlobInputStreamStorage()
      35           3 : {}
      36             : 
      37           0 : IPCBlobInputStreamStorage::~IPCBlobInputStreamStorage()
      38           0 : {}
      39             : 
      40             : /* static */ IPCBlobInputStreamStorage*
      41           0 : IPCBlobInputStreamStorage::Get()
      42             : {
      43           0 :   return gStorage;
      44             : }
      45             : 
      46             : /* static */ void
      47           3 : IPCBlobInputStreamStorage::Initialize()
      48             : {
      49           3 :   MOZ_ASSERT(!gStorage);
      50             : 
      51           3 :   gStorage = new IPCBlobInputStreamStorage();
      52             : 
      53           6 :   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
      54           3 :   if (obs) {
      55           3 :     obs->AddObserver(gStorage, "xpcom-shutdown", false);
      56           3 :     obs->AddObserver(gStorage, "ipc:content-shutdown", false);
      57             :   }
      58           3 : }
      59             : 
      60             : NS_IMETHODIMP
      61           0 : IPCBlobInputStreamStorage::Observe(nsISupports* aSubject, const char* aTopic,
      62             :                                    const char16_t* aData)
      63             : {
      64           0 :   if (!strcmp(aTopic, "xpcom-shutdown")) {
      65           0 :     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
      66           0 :     if (obs) {
      67           0 :       obs->RemoveObserver(this, "xpcom-shutdown");
      68           0 :       obs->RemoveObserver(this, "ipc:content-shutdown");
      69             :     }
      70             : 
      71           0 :     gStorage = nullptr;
      72           0 :     return NS_OK;
      73             :   }
      74             : 
      75           0 :   MOZ_ASSERT(!strcmp(aTopic, "ipc:content-shutdown"));
      76             : 
      77           0 :   nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
      78           0 :   if (NS_WARN_IF(!props)) {
      79           0 :     return NS_ERROR_FAILURE;
      80             :   }
      81             : 
      82           0 :   uint64_t childID = CONTENT_PROCESS_ID_UNKNOWN;
      83           0 :   props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), &childID);
      84           0 :   if (NS_WARN_IF(childID == CONTENT_PROCESS_ID_UNKNOWN)) {
      85           0 :     return NS_ERROR_FAILURE;
      86             :   }
      87             : 
      88           0 :   mozilla::StaticMutexAutoLock lock(gMutex);
      89             : 
      90           0 :   for (auto iter = mStorage.Iter(); !iter.Done(); iter.Next()) {
      91           0 :     if (iter.Data()->mChildID == childID) {
      92           0 :       iter.Remove();
      93             :     }
      94             :   }
      95             : 
      96           0 :   return NS_OK;
      97             : }
      98             : 
      99             : void
     100           0 : IPCBlobInputStreamStorage::AddStream(nsIInputStream* aInputStream,
     101             :                                      const nsID& aID,
     102             :                                      uint64_t aChildID)
     103             : {
     104           0 :   MOZ_ASSERT(aInputStream);
     105             : 
     106           0 :   StreamData* data = new StreamData();
     107           0 :   data->mInputStream = aInputStream;
     108           0 :   data->mChildID = aChildID;
     109             : 
     110           0 :   mozilla::StaticMutexAutoLock lock(gMutex);
     111           0 :   mStorage.Put(aID, data);
     112           0 : }
     113             : 
     114             : void
     115           0 : IPCBlobInputStreamStorage::ForgetStream(const nsID& aID)
     116             : {
     117           0 :   mozilla::StaticMutexAutoLock lock(gMutex);
     118           0 :   mStorage.Remove(aID);
     119           0 : }
     120             : 
     121             : void
     122           0 : IPCBlobInputStreamStorage::GetStream(const nsID& aID,
     123             :                                      nsIInputStream** aInputStream)
     124             : {
     125           0 :   *aInputStream = nullptr;
     126             : 
     127           0 :   nsCOMPtr<nsIInputStream> inputStream;
     128             : 
     129             :   // NS_CloneInputStream cannot be called when the mutex is locked because it
     130             :   // can, recursively call GetStream() in case the child actor lives on the
     131             :   // parent process.
     132             :   {
     133           0 :     mozilla::StaticMutexAutoLock lock(gMutex);
     134           0 :     StreamData* data = mStorage.Get(aID);
     135           0 :     if (!data) {
     136           0 :       return;
     137             :     }
     138             : 
     139           0 :     inputStream = data->mInputStream;
     140             :   }
     141             : 
     142           0 :   MOZ_ASSERT(inputStream);
     143             : 
     144             :   // We cannot return always the same inputStream because not all of them are
     145             :   // able to be reused. Better to clone them.
     146             : 
     147           0 :   nsCOMPtr<nsIInputStream> clonedStream;
     148           0 :   nsCOMPtr<nsIInputStream> replacementStream;
     149             : 
     150             :   nsresult rv =
     151           0 :     NS_CloneInputStream(inputStream, getter_AddRefs(clonedStream),
     152           0 :                         getter_AddRefs(replacementStream));
     153           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     154           0 :     return;
     155             :   }
     156             : 
     157           0 :   if (replacementStream) {
     158           0 :     mozilla::StaticMutexAutoLock lock(gMutex);
     159           0 :     StreamData* data = mStorage.Get(aID);
     160             :     // data can be gone in the meantime.
     161           0 :     if (!data) {
     162           0 :       return;
     163             :     }
     164             : 
     165           0 :     data->mInputStream = replacementStream;
     166             :   }
     167             : 
     168           0 :   clonedStream.forget(aInputStream);
     169             : }
     170             : 
     171             : void
     172           0 : IPCBlobInputStreamStorage::StoreCallback(const nsID& aID,
     173             :                                          IPCBlobInputStreamParentCallback* aCallback)
     174             : {
     175           0 :   MOZ_ASSERT(aCallback);
     176             : 
     177           0 :   mozilla::StaticMutexAutoLock lock(gMutex);
     178           0 :   StreamData* data = mStorage.Get(aID);
     179           0 :   if (data) {
     180           0 :     MOZ_ASSERT(!data->mCallback);
     181           0 :     data->mCallback = aCallback;
     182             :   }
     183           0 : }
     184             : 
     185             : already_AddRefed<IPCBlobInputStreamParentCallback>
     186           0 : IPCBlobInputStreamStorage::TakeCallback(const nsID& aID)
     187             : {
     188           0 :   mozilla::StaticMutexAutoLock lock(gMutex);
     189           0 :   StreamData* data = mStorage.Get(aID);
     190           0 :   if (!data) {
     191           0 :     return nullptr;
     192             :   }
     193             : 
     194           0 :   RefPtr<IPCBlobInputStreamParentCallback> callback;
     195           0 :   data->mCallback.swap(callback);
     196           0 :   return callback.forget();
     197             : }
     198             : 
     199             : } // namespace dom
     200             : } // namespace mozilla

Generated by: LCOV version 1.13