LCOV - code coverage report
Current view: top level - dom/media - EncodedBufferCache.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 1 61 1.6 %
Date: 2017-07-14 16:53:18 Functions: 2 5 40.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       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 "EncodedBufferCache.h"
       8             : #include "prio.h"
       9             : #include "nsAnonymousTemporaryFile.h"
      10             : #include "mozilla/Monitor.h"
      11             : #include "mozilla/dom/ContentChild.h"
      12             : #include "mozilla/dom/File.h"
      13             : #include "nsThreadUtils.h"
      14             : #include "nsXULAppAPI.h"
      15             : 
      16             : namespace mozilla {
      17             : 
      18             : void
      19           0 : EncodedBufferCache::AppendBuffer(nsTArray<uint8_t> & aBuf)
      20             : {
      21           0 :   MOZ_ASSERT(!NS_IsMainThread());
      22             : 
      23           0 :   MutexAutoLock lock(mMutex);
      24           0 :   mDataSize += aBuf.Length();
      25             : 
      26           0 :   mEncodedBuffers.AppendElement()->SwapElements(aBuf);
      27             : 
      28           0 :   if (!mTempFileEnabled && mDataSize > mMaxMemoryStorage) {
      29             :     nsresult rv;
      30           0 :     PRFileDesc* tempFD = nullptr;
      31             :     {
      32             :       // Release the mMutex because of the sync dispatch to the main thread.
      33           0 :       MutexAutoUnlock unlock(mMutex);
      34           0 :       if (XRE_IsParentProcess()) {
      35             :         // In case we are in the parent process, do a synchronous I/O here to open a
      36             :         // temporary file.
      37           0 :         rv = NS_OpenAnonymousTemporaryFile(&tempFD);
      38             :       } else {
      39             :         // In case we are in the child process, we don't have access to open a file
      40             :         // directly due to sandbox restrictions, so we need to ask the parent process
      41             :         // to do that for us.  In order to initiate the IPC, we need to first go to
      42             :         // the main thread.  This is done by dispatching a runnable to the main thread.
      43             :         // From there, we start an asynchronous IPC, and we block the current thread
      44             :         // using a monitor while this async work is in progress.  When we receive the
      45             :         // resulting file descriptor from the parent process, we notify the monitor
      46             :         // and unblock the current thread and continue.
      47             :         typedef dom::ContentChild::AnonymousTemporaryFileCallback
      48             :           AnonymousTemporaryFileCallback;
      49           0 :         bool done = false;
      50           0 :         Monitor monitor("EncodeBufferCache::AppendBuffer");
      51           0 :         RefPtr<dom::ContentChild> cc = dom::ContentChild::GetSingleton();
      52             :         nsCOMPtr<nsIRunnable> runnable =
      53           0 :           NewRunnableMethod<AnonymousTemporaryFileCallback>(
      54             :             "dom::ContentChild::AsyncOpenAnonymousTemporaryFile",
      55             :             cc,
      56             :             &dom::ContentChild::AsyncOpenAnonymousTemporaryFile,
      57           0 :             [&](PRFileDesc* aFile) {
      58           0 :               rv = aFile ? NS_OK : NS_ERROR_FAILURE;
      59           0 :               tempFD = aFile;
      60           0 :               MonitorAutoLock lock(monitor);
      61           0 :               done = true;
      62           0 :               lock.Notify();
      63           0 :             });
      64           0 :         MonitorAutoLock lock(monitor);
      65           0 :         rv = NS_DispatchToMainThread(runnable);
      66           0 :         if (NS_SUCCEEDED(rv)) {
      67           0 :           while (!done) {
      68           0 :             lock.Wait();
      69             :           }
      70             :         }
      71             :       }
      72             :     }
      73           0 :     if (!NS_FAILED(rv)) {
      74             :       // Check the mDataSize again since we release the mMutex before.
      75           0 :       if (mDataSize > mMaxMemoryStorage) {
      76           0 :         mFD = tempFD;
      77           0 :         mTempFileEnabled = true;
      78             :       } else {
      79             :         // Close the tempFD because the data had been taken during the
      80             :         // MutexAutoUnlock.
      81           0 :         PR_Close(tempFD);
      82             :       }
      83             :     }
      84             :   }
      85             : 
      86           0 :   if (mTempFileEnabled) {
      87             :     // has created temporary file, write buffer in it
      88           0 :     for (uint32_t i = 0; i < mEncodedBuffers.Length(); i++) {
      89           0 :       int32_t amount = PR_Write(mFD, mEncodedBuffers.ElementAt(i).Elements(), mEncodedBuffers.ElementAt(i).Length());
      90           0 :       if (amount < 0 || size_t(amount) < mEncodedBuffers.ElementAt(i).Length()) {
      91           0 :         NS_WARNING("Failed to write media cache block!");
      92             :       }
      93             :     }
      94           0 :     mEncodedBuffers.Clear();
      95             :   }
      96             : 
      97           0 : }
      98             : 
      99             : already_AddRefed<dom::Blob>
     100           0 : EncodedBufferCache::ExtractBlob(nsISupports* aParent,
     101             :                                 const nsAString &aContentType)
     102             : {
     103           0 :   MutexAutoLock lock(mMutex);
     104           0 :   RefPtr<dom::Blob> blob;
     105           0 :   if (mTempFileEnabled) {
     106             :     // generate new temporary file to write
     107           0 :     blob = dom::Blob::CreateTemporaryBlob(aParent, mFD, 0, mDataSize,
     108           0 :                                           aContentType);
     109             :     // fallback to memory blob
     110           0 :     mTempFileEnabled = false;
     111           0 :     mDataSize = 0;
     112           0 :     mFD = nullptr;
     113             :   } else {
     114           0 :     void* blobData = malloc(mDataSize);
     115           0 :     NS_ASSERTION(blobData, "out of memory!!");
     116             : 
     117           0 :     if (blobData) {
     118           0 :       for (uint32_t i = 0, offset = 0; i < mEncodedBuffers.Length(); i++) {
     119           0 :         memcpy((uint8_t*)blobData + offset, mEncodedBuffers.ElementAt(i).Elements(),
     120           0 :                mEncodedBuffers.ElementAt(i).Length());
     121           0 :         offset += mEncodedBuffers.ElementAt(i).Length();
     122             :       }
     123           0 :       blob = dom::Blob::CreateMemoryBlob(aParent, blobData, mDataSize,
     124           0 :                                          aContentType);
     125           0 :       mEncodedBuffers.Clear();
     126             :     } else
     127           0 :       return nullptr;
     128             :   }
     129           0 :   mDataSize = 0;
     130           0 :   return blob.forget();
     131             : }
     132             : 
     133           9 : } // namespace mozilla

Generated by: LCOV version 1.13