LCOV - code coverage report
Current view: top level - dom/media/systemservices - MediaParent.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 292 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 64 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 sw=2 ts=8 et ft=cpp : */
       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             : #include "MediaParent.h"
       8             : 
       9             : #include "mozilla/Base64.h"
      10             : #include <mozilla/StaticMutex.h>
      11             : 
      12             : #include "MediaUtils.h"
      13             : #include "MediaEngine.h"
      14             : #include "VideoUtils.h"
      15             : #include "nsAutoPtr.h"
      16             : #include "nsThreadUtils.h"
      17             : #include "nsNetCID.h"
      18             : #include "nsNetUtil.h"
      19             : #include "nsIInputStream.h"
      20             : #include "nsILineInputStream.h"
      21             : #include "nsIOutputStream.h"
      22             : #include "nsISafeOutputStream.h"
      23             : #include "nsAppDirectoryServiceDefs.h"
      24             : #include "nsISupportsImpl.h"
      25             : #include "mozilla/Logging.h"
      26             : 
      27             : #undef LOG
      28             : mozilla::LazyLogModule gMediaParentLog("MediaParent");
      29             : #define LOG(args) MOZ_LOG(gMediaParentLog, mozilla::LogLevel::Debug, args)
      30             : 
      31             : // A file in the profile dir is used to persist mOriginKeys used to anonymize
      32             : // deviceIds to be unique per origin, to avoid them being supercookies.
      33             : 
      34             : #define ORIGINKEYS_FILE "enumerate_devices.txt"
      35             : #define ORIGINKEYS_VERSION "1"
      36             : 
      37             : namespace mozilla {
      38             : namespace media {
      39             : 
      40             : static OriginKeyStore* sOriginKeyStore = nullptr;
      41             : 
      42           0 : class OriginKeyStore : public nsISupports
      43             : {
      44             :   NS_DECL_THREADSAFE_ISUPPORTS
      45           0 :   class OriginKey
      46             :   {
      47             :   public:
      48             :     static const size_t DecodedLength = 18;
      49             :     static const size_t EncodedLength = DecodedLength * 4 / 3;
      50             : 
      51           0 :     explicit OriginKey(const nsACString& aKey, int64_t aSecondsStamp = 0) // 0 = temporal
      52           0 :     : mKey(aKey)
      53           0 :     , mSecondsStamp(aSecondsStamp) {}
      54             : 
      55             :     nsCString mKey; // Base64 encoded.
      56             :     int64_t mSecondsStamp;
      57             :   };
      58             : 
      59           0 :   class OriginKeysTable
      60             :   {
      61             :   public:
      62           0 :     OriginKeysTable() : mPersistCount(0) {}
      63             : 
      64             :     nsresult
      65           0 :     GetPrincipalKey(const ipc::PrincipalInfo& aPrincipalInfo,
      66             :                     nsCString& aResult, bool aPersist = false)
      67             :     {
      68           0 :       nsAutoCString principalString;
      69           0 :       PrincipalInfoToString(aPrincipalInfo, principalString);
      70             : 
      71             :       OriginKey* key;
      72           0 :       if (!mKeys.Get(principalString, &key)) {
      73           0 :         nsCString salt; // Make a new one
      74           0 :         nsresult rv = GenerateRandomName(salt, key->EncodedLength);
      75           0 :         if (NS_WARN_IF(NS_FAILED(rv))) {
      76           0 :           return rv;
      77             :         }
      78           0 :         key = new OriginKey(salt);
      79           0 :         mKeys.Put(principalString, key);
      80             :       }
      81           0 :       if (aPersist && !key->mSecondsStamp) {
      82           0 :         key->mSecondsStamp = PR_Now() / PR_USEC_PER_SEC;
      83           0 :         mPersistCount++;
      84             :       }
      85           0 :       aResult = key->mKey;
      86           0 :       return NS_OK;
      87             :     }
      88             : 
      89           0 :     void Clear(int64_t aSinceWhen)
      90             :     {
      91             :       // Avoid int64_t* <-> void* casting offset
      92           0 :       OriginKey since(nsCString(), aSinceWhen  / PR_USEC_PER_SEC);
      93           0 :       for (auto iter = mKeys.Iter(); !iter.Done(); iter.Next()) {
      94           0 :         nsAutoPtr<OriginKey>& originKey = iter.Data();
      95           0 :         LOG((((originKey->mSecondsStamp >= since.mSecondsStamp)?
      96             :               "%s: REMOVE %" PRId64 " >= %" PRId64 :
      97             :               "%s: KEEP   %" PRId64 " < %" PRId64),
      98             :               __FUNCTION__, originKey->mSecondsStamp, since.mSecondsStamp));
      99             : 
     100           0 :         if (originKey->mSecondsStamp >= since.mSecondsStamp) {
     101           0 :           iter.Remove();
     102             :         }
     103             :       }
     104           0 :       mPersistCount = 0;
     105           0 :     }
     106             : 
     107             :   private:
     108             :     void
     109           0 :     PrincipalInfoToString(const ipc::PrincipalInfo& aPrincipalInfo,
     110             :                           nsACString& aString)
     111             :     {
     112           0 :       switch (aPrincipalInfo.type()) {
     113             :         case ipc::PrincipalInfo::TSystemPrincipalInfo:
     114           0 :           aString.Assign("[System Principal]");
     115           0 :           return;
     116             : 
     117             :         case ipc::PrincipalInfo::TNullPrincipalInfo: {
     118             :           const ipc::NullPrincipalInfo& info =
     119           0 :             aPrincipalInfo.get_NullPrincipalInfo();
     120           0 :           aString.Assign(info.spec());
     121           0 :           return;
     122             :         }
     123             : 
     124             :         case ipc::PrincipalInfo::TContentPrincipalInfo: {
     125             :           const ipc::ContentPrincipalInfo& info =
     126           0 :             aPrincipalInfo.get_ContentPrincipalInfo();
     127           0 :           aString.Assign(info.originNoSuffix());
     128             : 
     129           0 :           nsAutoCString suffix;
     130           0 :           info.attrs().CreateSuffix(suffix);
     131           0 :           aString.Append(suffix);
     132           0 :           return;
     133             :         }
     134             : 
     135             :         case ipc::PrincipalInfo::TExpandedPrincipalInfo: {
     136             :           const ipc::ExpandedPrincipalInfo& info =
     137           0 :             aPrincipalInfo.get_ExpandedPrincipalInfo();
     138             : 
     139           0 :           aString.Assign("[Expanded Principal [");
     140             : 
     141           0 :           for (uint32_t i = 0; i < info.whitelist().Length(); i++) {
     142           0 :             nsAutoCString str;
     143           0 :             PrincipalInfoToString(info.whitelist()[i], str);
     144             : 
     145           0 :             if (i != 0) {
     146           0 :               aString.Append(", ");
     147             :             }
     148             : 
     149           0 :             aString.Append(str);
     150             :           }
     151             : 
     152           0 :           aString.Append("]]");
     153           0 :           return;
     154             :         }
     155             : 
     156             :         default:
     157           0 :           MOZ_CRASH("Unknown PrincipalInfo type!");
     158             :       }
     159             :     }
     160             : 
     161             :   protected:
     162             :     nsClassHashtable<nsCStringHashKey, OriginKey> mKeys;
     163             :     size_t mPersistCount;
     164             :   };
     165             : 
     166           0 :   class OriginKeysLoader : public OriginKeysTable
     167             :   {
     168             :   public:
     169           0 :     OriginKeysLoader() {}
     170             : 
     171             :     nsresult
     172           0 :     GetPrincipalKey(const ipc::PrincipalInfo& aPrincipalInfo,
     173             :                     nsCString& aResult, bool aPersist = false)
     174             :     {
     175           0 :       auto before = mPersistCount;
     176           0 :       nsresult rv = OriginKeysTable::GetPrincipalKey(aPrincipalInfo, aResult,
     177           0 :                                                      aPersist);
     178           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
     179           0 :         return rv;
     180             :       }
     181             : 
     182           0 :       if (mPersistCount != before) {
     183           0 :         Save();
     184             :       }
     185           0 :       return NS_OK;
     186             :     }
     187             : 
     188             :     already_AddRefed<nsIFile>
     189           0 :     GetFile()
     190             :     {
     191           0 :       MOZ_ASSERT(mProfileDir);
     192           0 :       nsCOMPtr<nsIFile> file;
     193           0 :       nsresult rv = mProfileDir->Clone(getter_AddRefs(file));
     194           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
     195           0 :         return nullptr;
     196             :       }
     197           0 :       file->Append(NS_LITERAL_STRING(ORIGINKEYS_FILE));
     198           0 :       return file.forget();
     199             :     }
     200             : 
     201             :     // Format of file is key secondsstamp origin (first line is version #):
     202             :     //
     203             :     // 1
     204             :     // rOMAAbFujNwKyIpj4RJ3Wt5Q 1424733961 http://fiddle.jshell.net
     205             :     // rOMAAbFujNwKyIpj4RJ3Wt5Q 1424734841 http://mozilla.github.io
     206             :     // etc.
     207             : 
     208           0 :     nsresult Read()
     209             :     {
     210           0 :       nsCOMPtr<nsIFile> file = GetFile();
     211           0 :       if (NS_WARN_IF(!file)) {
     212           0 :         return NS_ERROR_UNEXPECTED;
     213             :       }
     214             :       bool exists;
     215           0 :       nsresult rv = file->Exists(&exists);
     216           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
     217           0 :         return rv;
     218             :       }
     219           0 :       if (!exists) {
     220           0 :         return NS_OK;
     221             :       }
     222             : 
     223           0 :       nsCOMPtr<nsIInputStream> stream;
     224           0 :       rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file);
     225           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
     226           0 :         return rv;
     227             :       }
     228           0 :       nsCOMPtr<nsILineInputStream> i = do_QueryInterface(stream);
     229           0 :       MOZ_ASSERT(i);
     230           0 :       MOZ_ASSERT(!mPersistCount);
     231             : 
     232           0 :       nsCString line;
     233             :       bool hasMoreLines;
     234           0 :       rv = i->ReadLine(line, &hasMoreLines);
     235           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
     236           0 :         return rv;
     237             :       }
     238           0 :       if (!line.EqualsLiteral(ORIGINKEYS_VERSION)) {
     239             :         // If version on disk is newer than we can understand then ignore it.
     240           0 :         return NS_OK;
     241             :       }
     242             : 
     243           0 :       while (hasMoreLines) {
     244           0 :         rv = i->ReadLine(line, &hasMoreLines);
     245           0 :         if (NS_WARN_IF(NS_FAILED(rv))) {
     246           0 :           return rv;
     247             :         }
     248             :         // Read key secondsstamp origin.
     249             :         // Ignore any lines that don't fit format in the comment above exactly.
     250           0 :         int32_t f = line.FindChar(' ');
     251           0 :         if (f < 0) {
     252           0 :           continue;
     253             :         }
     254           0 :         const nsACString& key = Substring(line, 0, f);
     255           0 :         const nsACString& s = Substring(line, f+1);
     256           0 :         f = s.FindChar(' ');
     257           0 :         if (f < 0) {
     258           0 :           continue;
     259             :         }
     260           0 :         int64_t secondsstamp = nsCString(Substring(s, 0, f)).ToInteger64(&rv);
     261           0 :         if (NS_FAILED(rv)) {
     262           0 :           continue;
     263             :         }
     264           0 :         const nsACString& origin = Substring(s, f+1);
     265             : 
     266             :         // Validate key
     267           0 :         if (key.Length() != OriginKey::EncodedLength) {
     268           0 :           continue;
     269             :         }
     270           0 :         nsCString dummy;
     271           0 :         rv = Base64Decode(key, dummy);
     272           0 :         if (NS_FAILED(rv)) {
     273           0 :           continue;
     274             :         }
     275           0 :         mKeys.Put(origin, new OriginKey(key, secondsstamp));
     276             :       }
     277           0 :       mPersistCount = mKeys.Count();
     278           0 :       return NS_OK;
     279             :     }
     280             : 
     281             :     nsresult
     282           0 :     Write()
     283             :     {
     284           0 :       nsCOMPtr<nsIFile> file = GetFile();
     285           0 :       if (NS_WARN_IF(!file)) {
     286           0 :         return NS_ERROR_UNEXPECTED;
     287             :       }
     288             : 
     289           0 :       nsCOMPtr<nsIOutputStream> stream;
     290           0 :       nsresult rv = NS_NewSafeLocalFileOutputStream(getter_AddRefs(stream), file);
     291           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
     292           0 :         return rv;
     293             :       }
     294             : 
     295           0 :       nsAutoCString versionBuffer;
     296           0 :       versionBuffer.AppendLiteral(ORIGINKEYS_VERSION);
     297           0 :       versionBuffer.Append('\n');
     298             : 
     299             :       uint32_t count;
     300           0 :       rv = stream->Write(versionBuffer.Data(), versionBuffer.Length(), &count);
     301           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
     302           0 :         return rv;
     303             :       }
     304           0 :       if (count != versionBuffer.Length()) {
     305           0 :         return NS_ERROR_UNEXPECTED;
     306             :       }
     307           0 :       for (auto iter = mKeys.Iter(); !iter.Done(); iter.Next()) {
     308           0 :         const nsACString& origin = iter.Key();
     309           0 :         OriginKey* originKey = iter.UserData();
     310             : 
     311           0 :         if (!originKey->mSecondsStamp) {
     312           0 :           continue; // don't write temporal ones
     313             :         }
     314             : 
     315           0 :         nsCString originBuffer;
     316           0 :         originBuffer.Append(originKey->mKey);
     317           0 :         originBuffer.Append(' ');
     318           0 :         originBuffer.AppendInt(originKey->mSecondsStamp);
     319           0 :         originBuffer.Append(' ');
     320           0 :         originBuffer.Append(origin);
     321           0 :         originBuffer.Append('\n');
     322             : 
     323           0 :         rv = stream->Write(originBuffer.Data(), originBuffer.Length(), &count);
     324           0 :         if (NS_WARN_IF(NS_FAILED(rv)) || count != originBuffer.Length()) {
     325           0 :           break;
     326             :         }
     327             :       }
     328             : 
     329           0 :       nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(stream);
     330           0 :       MOZ_ASSERT(safeStream);
     331             : 
     332           0 :       rv = safeStream->Finish();
     333           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
     334           0 :         return rv;
     335             :       }
     336           0 :       return NS_OK;
     337             :     }
     338             : 
     339           0 :     nsresult Load()
     340             :     {
     341           0 :       nsresult rv = Read();
     342           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
     343           0 :         Delete();
     344             :       }
     345           0 :       return rv;
     346             :     }
     347             : 
     348           0 :     nsresult Save()
     349             :     {
     350           0 :       nsresult rv = Write();
     351           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
     352           0 :         NS_WARNING("Failed to write data for EnumerateDevices id-persistence.");
     353           0 :         Delete();
     354             :       }
     355           0 :       return rv;
     356             :     }
     357             : 
     358           0 :     void Clear(int64_t aSinceWhen)
     359             :     {
     360           0 :       OriginKeysTable::Clear(aSinceWhen);
     361           0 :       Delete();
     362           0 :       Save();
     363           0 :     }
     364             : 
     365           0 :     nsresult Delete()
     366             :     {
     367           0 :       nsCOMPtr<nsIFile> file = GetFile();
     368           0 :       if (NS_WARN_IF(!file)) {
     369           0 :         return NS_ERROR_UNEXPECTED;
     370             :       }
     371           0 :       nsresult rv = file->Remove(false);
     372           0 :       if (rv == NS_ERROR_FILE_NOT_FOUND) {
     373           0 :         return NS_OK;
     374             :       }
     375           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
     376           0 :         return rv;
     377             :       }
     378           0 :       return NS_OK;
     379             :     }
     380             : 
     381             :     void
     382           0 :     SetProfileDir(nsIFile* aProfileDir)
     383             :     {
     384           0 :       MOZ_ASSERT(!NS_IsMainThread());
     385           0 :       bool first = !mProfileDir;
     386           0 :       mProfileDir = aProfileDir;
     387             :       // Load from disk when we first get a profileDir, but not subsequently.
     388           0 :       if (first) {
     389           0 :         Load();
     390             :       }
     391           0 :     }
     392             :   private:
     393             :     nsCOMPtr<nsIFile> mProfileDir;
     394             :   };
     395             : 
     396             : private:
     397           0 :   virtual ~OriginKeyStore()
     398           0 :   {
     399           0 :     sOriginKeyStore = nullptr;
     400           0 :     LOG((__FUNCTION__));
     401           0 :   }
     402             : 
     403             : public:
     404           0 :   static OriginKeyStore* Get()
     405             :   {
     406           0 :     MOZ_ASSERT(NS_IsMainThread());
     407           0 :     if (!sOriginKeyStore) {
     408           0 :       sOriginKeyStore = new OriginKeyStore();
     409             :     }
     410           0 :     return sOriginKeyStore;
     411             :   }
     412             : 
     413             :   // Only accessed on StreamTS thread
     414             :   OriginKeysLoader mOriginKeys;
     415             :   OriginKeysTable mPrivateBrowsingOriginKeys;
     416             : };
     417             : 
     418           0 : NS_IMPL_ISUPPORTS0(OriginKeyStore)
     419             : 
     420           0 : bool NonE10s::SendGetPrincipalKeyResponse(const uint32_t& aRequestId,
     421             :                                           nsCString aKey) {
     422           0 :   MediaManager* mgr = MediaManager::GetIfExists();
     423           0 :   if (!mgr) {
     424           0 :     return false;
     425             :   }
     426           0 :   RefPtr<Pledge<nsCString>> pledge = mgr->mGetPrincipalKeyPledges.Remove(aRequestId);
     427           0 :   if (pledge) {
     428           0 :     pledge->Resolve(aKey);
     429             :   }
     430           0 :   return true;
     431             : }
     432             : 
     433             : template<class Super> mozilla::ipc::IPCResult
     434           0 : Parent<Super>::RecvGetPrincipalKey(const uint32_t& aRequestId,
     435             :                                    const ipc::PrincipalInfo& aPrincipalInfo,
     436             :                                    const bool& aPersist)
     437             : {
     438           0 :   MOZ_ASSERT(NS_IsMainThread());
     439             : 
     440             :   // First, get profile dir.
     441             : 
     442           0 :   MOZ_ASSERT(NS_IsMainThread());
     443           0 :   nsCOMPtr<nsIFile> profileDir;
     444           0 :   nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
     445           0 :                                        getter_AddRefs(profileDir));
     446           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     447           0 :     return IPCResult(this, false);
     448             :   }
     449             : 
     450             :   // Then over to stream-transport thread to do the actual file io.
     451             :   // Stash a pledge to hold the answer and get an id for this request.
     452             : 
     453           0 :   RefPtr<Pledge<nsCString>> p = new Pledge<nsCString>();
     454           0 :   uint32_t id = mOutstandingPledges.Append(*p);
     455             : 
     456           0 :   nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
     457           0 :   MOZ_ASSERT(sts);
     458           0 :   RefPtr<Parent<Super>> that(this);
     459             : 
     460           0 :   rv = sts->Dispatch(NewRunnableFrom([this, that, id, profileDir,
     461           0 :                                       aPrincipalInfo, aPersist]() -> nsresult {
     462           0 :     MOZ_ASSERT(!NS_IsMainThread());
     463           0 :     mOriginKeyStore->mOriginKeys.SetProfileDir(profileDir);
     464             : 
     465             :     nsresult rv;
     466           0 :     nsAutoCString result;
     467           0 :     if (IsPincipalInfoPrivate(aPrincipalInfo)) {
     468           0 :       rv = mOriginKeyStore->mPrivateBrowsingOriginKeys.GetPrincipalKey(aPrincipalInfo, result);
     469             :     } else {
     470           0 :       rv = mOriginKeyStore->mOriginKeys.GetPrincipalKey(aPrincipalInfo, result, aPersist);
     471             :     }
     472             : 
     473           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     474           0 :       return rv;
     475             :     }
     476             : 
     477             :     // Pass result back to main thread.
     478           0 :     rv = NS_DispatchToMainThread(NewRunnableFrom([this, that, id,
     479           0 :                                                   result]() -> nsresult {
     480           0 :       if (mDestroyed) {
     481           0 :         return NS_OK;
     482             :       }
     483           0 :       RefPtr<Pledge<nsCString>> p = mOutstandingPledges.Remove(id);
     484           0 :       if (!p) {
     485           0 :         return NS_ERROR_UNEXPECTED;
     486             :       }
     487           0 :       p->Resolve(result);
     488           0 :       return NS_OK;
     489             :     }), NS_DISPATCH_NORMAL);
     490             : 
     491           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     492           0 :       return rv;
     493             :     }
     494           0 :     return NS_OK;
     495             :   }), NS_DISPATCH_NORMAL);
     496             : 
     497           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     498           0 :     return IPCResult(this, false);
     499             :   }
     500           0 :   p->Then([this, that, aRequestId](const nsCString& aKey) mutable {
     501           0 :     if (mDestroyed) {
     502           0 :       return NS_OK;
     503             :     }
     504           0 :     Unused << this->SendGetPrincipalKeyResponse(aRequestId, aKey);
     505           0 :     return NS_OK;
     506             :   });
     507           0 :   return IPC_OK();
     508             : }
     509             : 
     510             : template<class Super> mozilla::ipc::IPCResult
     511           0 : Parent<Super>::RecvSanitizeOriginKeys(const uint64_t& aSinceWhen,
     512             :                                       const bool& aOnlyPrivateBrowsing)
     513             : {
     514           0 :   MOZ_ASSERT(NS_IsMainThread());
     515           0 :   nsCOMPtr<nsIFile> profileDir;
     516           0 :   nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
     517           0 :                                          getter_AddRefs(profileDir));
     518           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     519           0 :     return IPCResult(this, false);
     520             :   }
     521             :   // Over to stream-transport thread to do the file io.
     522             : 
     523           0 :   nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
     524           0 :   MOZ_ASSERT(sts);
     525           0 :   RefPtr<OriginKeyStore> store(mOriginKeyStore);
     526             : 
     527           0 :   rv = sts->Dispatch(NewRunnableFrom([profileDir, store, aSinceWhen,
     528           0 :                                       aOnlyPrivateBrowsing]() -> nsresult {
     529           0 :     MOZ_ASSERT(!NS_IsMainThread());
     530           0 :     store->mPrivateBrowsingOriginKeys.Clear(aSinceWhen);
     531           0 :     if (!aOnlyPrivateBrowsing) {
     532           0 :       store->mOriginKeys.SetProfileDir(profileDir);
     533           0 :       store->mOriginKeys.Clear(aSinceWhen);
     534             :     }
     535           0 :     return NS_OK;
     536             :   }), NS_DISPATCH_NORMAL);
     537           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     538           0 :     return IPCResult(this, false);
     539             :   }
     540           0 :   return IPC_OK();
     541             : }
     542             : 
     543             : template<class Super> void
     544           0 : Parent<Super>::ActorDestroy(ActorDestroyReason aWhy)
     545             : {
     546             :   // No more IPC from here
     547           0 :   mDestroyed = true;
     548           0 :   LOG((__FUNCTION__));
     549           0 : }
     550             : 
     551             : template<class Super>
     552           0 : Parent<Super>::Parent()
     553             :   : mOriginKeyStore(OriginKeyStore::Get())
     554           0 :   , mDestroyed(false)
     555             : {
     556           0 :   LOG(("media::Parent: %p", this));
     557           0 : }
     558             : 
     559             : template<class Super>
     560           0 : Parent<Super>::~Parent()
     561             : {
     562           0 :   LOG(("~media::Parent: %p", this));
     563           0 : }
     564             : 
     565             : PMediaParent*
     566           0 : AllocPMediaParent()
     567             : {
     568           0 :   Parent<PMediaParent>* obj = new Parent<PMediaParent>();
     569           0 :   obj->AddRef();
     570           0 :   return obj;
     571             : }
     572             : 
     573             : bool
     574           0 : DeallocPMediaParent(media::PMediaParent *aActor)
     575             : {
     576           0 :   static_cast<Parent<PMediaParent>*>(aActor)->Release();
     577           0 :   return true;
     578             : }
     579             : 
     580             : } // namespace media
     581             : } // namespace mozilla
     582             : 
     583             : // Instantiate templates to satisfy linker
     584             : template class mozilla::media::Parent<mozilla::media::NonE10s>;

Generated by: LCOV version 1.13