LCOV - code coverage report
Current view: top level - toolkit/mozapps/extensions - AddonManagerStartup.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 192 288 66.7 %
Date: 2017-07-14 16:53:18 Functions: 39 49 79.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "AddonManagerStartup.h"
       7             : #include "AddonManagerStartup-inlines.h"
       8             : 
       9             : #include "jsapi.h"
      10             : #include "jsfriendapi.h"
      11             : #include "js/TracingAPI.h"
      12             : #include "xpcpublic.h"
      13             : 
      14             : #include "mozilla/ClearOnShutdown.h"
      15             : #include "mozilla/EndianUtils.h"
      16             : #include "mozilla/Compression.h"
      17             : #include "mozilla/Preferences.h"
      18             : #include "mozilla/ScopeExit.h"
      19             : #include "mozilla/Services.h"
      20             : #include "mozilla/Unused.h"
      21             : #include "mozilla/ErrorResult.h"
      22             : #include "mozilla/dom/ipc/StructuredCloneData.h"
      23             : 
      24             : #include "nsAppDirectoryServiceDefs.h"
      25             : #include "nsAppRunner.h"
      26             : #include "nsContentUtils.h"
      27             : #include "nsIAddonInterposition.h"
      28             : #include "nsXULAppAPI.h"
      29             : 
      30             : #include <stdlib.h>
      31             : 
      32             : namespace mozilla {
      33             : 
      34             : template <>
      35             : class MOZ_MUST_USE_TYPE GenericErrorResult<nsresult>
      36             : {
      37             :   nsresult mErrorValue;
      38             : 
      39             :   template<typename V, typename E2> friend class Result;
      40             : 
      41             : public:
      42           0 :   explicit GenericErrorResult(nsresult aErrorValue) : mErrorValue(aErrorValue) {}
      43             : 
      44           0 :   operator nsresult() { return mErrorValue; }
      45             : };
      46             : 
      47             : static inline Result<Ok, nsresult>
      48             : WrapNSResult(PRStatus aRv)
      49             : {
      50             :     if (aRv != PR_SUCCESS) {
      51             :         return Err(NS_ERROR_FAILURE);
      52             :     }
      53             :     return Ok();
      54             : }
      55             : 
      56             : static inline Result<Ok, nsresult>
      57          12 : WrapNSResult(nsresult aRv)
      58             : {
      59          12 :     if (NS_FAILED(aRv)) {
      60           0 :         return Err(aRv);
      61             :     }
      62          12 :     return Ok();
      63             : }
      64             : 
      65             : #define NS_TRY(expr) MOZ_TRY(WrapNSResult(expr))
      66             : 
      67             : 
      68             : using Compression::LZ4;
      69             : using dom::ipc::StructuredCloneData;
      70             : 
      71             : #ifdef XP_WIN
      72             : #  define READ_BINARYMODE "rb"
      73             : #else
      74             : #  define READ_BINARYMODE "r"
      75             : #endif
      76             : 
      77             : AddonManagerStartup&
      78          17 : AddonManagerStartup::GetSingleton()
      79             : {
      80          17 :   static RefPtr<AddonManagerStartup> singleton;
      81          17 :   if (!singleton) {
      82           3 :     singleton = new AddonManagerStartup();
      83           3 :     ClearOnShutdown(&singleton);
      84             :   }
      85          17 :   return *singleton;
      86             : }
      87             : 
      88           3 : AddonManagerStartup::AddonManagerStartup()
      89           3 :   : mInitialized(false)
      90           3 : {}
      91             : 
      92             : 
      93             : nsIFile*
      94           1 : AddonManagerStartup::ProfileDir()
      95             : {
      96           1 :   if (!mProfileDir) {
      97             :     nsresult rv;
      98             : 
      99           1 :     rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mProfileDir));
     100           1 :     MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
     101             :   }
     102             : 
     103           1 :   return mProfileDir;
     104             : }
     105             : 
     106          51 : NS_IMPL_ISUPPORTS(AddonManagerStartup, amIAddonManagerStartup)
     107             : 
     108             : 
     109             : /*****************************************************************************
     110             :  * File utils
     111             :  *****************************************************************************/
     112             : 
     113             : static already_AddRefed<nsIFile>
     114           5 : CloneAndAppend(nsIFile* aFile, const char* name)
     115             : {
     116          10 :   nsCOMPtr<nsIFile> file;
     117           5 :   aFile->Clone(getter_AddRefs(file));
     118           5 :   file->AppendNative(nsDependentCString(name));
     119          10 :   return file.forget();
     120             : }
     121             : 
     122             : static bool
     123           2 : IsNormalFile(nsIFile* file)
     124             : {
     125             :   bool result;
     126           2 :   return NS_SUCCEEDED(file->IsFile(&result)) && result;
     127             : }
     128             : 
     129             : static nsCString
     130           1 : ReadFile(const char* path)
     131             : {
     132           1 :   nsCString result;
     133             : 
     134           1 :   FILE* fd = fopen(path, READ_BINARYMODE);
     135           1 :   if (!fd) {
     136           0 :     return result;
     137             :   }
     138           1 :   auto cleanup = MakeScopeExit([&] () {
     139           1 :     fclose(fd);
     140           3 :   });
     141             : 
     142           1 :   if (fseek(fd, 0, SEEK_END) != 0) {
     143           0 :     return result;
     144             :   }
     145           1 :   size_t len = ftell(fd);
     146           1 :   if (len <= 0 || fseek(fd, 0, SEEK_SET) != 0) {
     147           0 :     return result;
     148             :   }
     149             : 
     150           1 :   result.SetLength(len);
     151           1 :   size_t rd = fread(result.BeginWriting(), sizeof(char), len, fd);
     152           1 :   if (rd != len) {
     153           0 :     result.Truncate();
     154             :   }
     155             : 
     156           1 :   return result;
     157             : }
     158             : 
     159             : static const char STRUCTURED_CLONE_MAGIC[] = "mozJSSCLz40v001";
     160             : 
     161             : template <typename T>
     162             : static Result<nsCString, nsresult>
     163           1 : DecodeLZ4(const nsACString& lz4, const T& magicNumber)
     164             : {
     165           1 :   constexpr auto HEADER_SIZE = sizeof(magicNumber) + 4;
     166             : 
     167             :   // Note: We want to include the null terminator here.
     168           2 :   nsDependentCSubstring magic(magicNumber, sizeof(magicNumber));
     169             : 
     170           1 :   if (lz4.Length() < HEADER_SIZE || StringHead(lz4, magic.Length()) != magic) {
     171           0 :     return Err(NS_ERROR_UNEXPECTED);
     172             :   }
     173             : 
     174           1 :   auto data = lz4.BeginReading() + magic.Length();
     175           1 :   auto size = LittleEndian::readUint32(data);
     176           1 :   data += 4;
     177             : 
     178           2 :   nsCString result;
     179           2 :   if (!result.SetLength(size, fallible) ||
     180           1 :       !LZ4::decompress(data, result.BeginWriting(), size)) {
     181           0 :     return Err(NS_ERROR_UNEXPECTED);
     182             :   }
     183             : 
     184           1 :   return result;
     185             : }
     186             : 
     187             : // Our zlib headers redefine this to MOZ_Z_compress, which breaks LZ4::compress
     188             : #undef compress
     189             : 
     190             : template <typename T>
     191             : static Result<nsCString, nsresult>
     192           0 : EncodeLZ4(const nsACString& data, const T& magicNumber)
     193             : {
     194             :   // Note: We want to include the null terminator here.
     195           0 :   nsDependentCSubstring magic(magicNumber, sizeof(magicNumber));
     196             : 
     197           0 :   nsAutoCString result;
     198           0 :   result.Append(magic);
     199             : 
     200           0 :   auto off = result.Length();
     201           0 :   result.SetLength(off + 4);
     202             : 
     203           0 :   LittleEndian::writeUint32(result.BeginWriting() + off, data.Length());
     204           0 :   off += 4;
     205             : 
     206           0 :   auto size = LZ4::maxCompressedSize(data.Length());
     207           0 :   result.SetLength(off + size);
     208             : 
     209           0 :   size = LZ4::compress(data.BeginReading(), data.Length(),
     210           0 :                        result.BeginWriting() + off);
     211             : 
     212           0 :   result.SetLength(off + size);
     213           0 :   return result;
     214             : }
     215             : 
     216             : static_assert(sizeof STRUCTURED_CLONE_MAGIC % 8 == 0,
     217             :               "Magic number should be an array of uint64_t");
     218             : 
     219             : /**
     220             :  * Reads the contents of a LZ4-compressed file, as stored by the OS.File
     221             :  * module, and returns the decompressed contents on success.
     222             :  *
     223             :  * A nonexistent or empty file is treated as success. A corrupt or non-LZ4
     224             :  * file is treated as failure.
     225             :  */
     226             : static Result<nsCString, nsresult>
     227           1 : ReadFileLZ4(const char* path)
     228             : {
     229             :   static const char MAGIC_NUMBER[] = "mozLz40";
     230             : 
     231           2 :   nsCString result;
     232             : 
     233           2 :   nsCString lz4 = ReadFile(path);
     234           1 :   if (lz4.IsEmpty()) {
     235           0 :     return result;
     236             :   }
     237             : 
     238           1 :   return DecodeLZ4(lz4, MAGIC_NUMBER);
     239             : }
     240             : 
     241             : static bool
     242           1 : ParseJSON(JSContext* cx, nsACString& jsonData, JS::MutableHandleValue result)
     243             : {
     244           2 :   NS_ConvertUTF8toUTF16 str(jsonData);
     245           1 :   jsonData.Truncate();
     246             : 
     247           2 :   return JS_ParseJSON(cx, str.Data(), str.Length(), result);
     248             : }
     249             : 
     250             : 
     251             : /*****************************************************************************
     252             :  * JSON data handling
     253             :  *****************************************************************************/
     254             : 
     255          24 : class MOZ_STACK_CLASS WrapperBase {
     256             : protected:
     257             :   WrapperBase(JSContext* cx, JSObject* object)
     258             :     : mCx(cx)
     259             :     , mObject(cx, object)
     260             :   {}
     261             : 
     262          24 :   WrapperBase(JSContext* cx, const JS::Value& value)
     263          24 :     : mCx(cx)
     264          24 :     , mObject(cx)
     265             :   {
     266          24 :     if (value.isObject()) {
     267          24 :       mObject = &value.toObject();
     268             :     } else {
     269           0 :       mObject = JS_NewPlainObject(cx);
     270             :     }
     271          24 :   }
     272             : 
     273             : protected:
     274             :   JSContext* mCx;
     275             :   JS::RootedObject mObject;
     276             : 
     277             :   bool GetBool(const char* name, bool defVal = false);
     278             : 
     279             :   double GetNumber(const char* name, double defVal = 0);
     280             : 
     281             :   nsString GetString(const char* name, const char* defVal = "");
     282             : 
     283             :   JSObject* GetObject(const char* name);
     284             : };
     285             : 
     286             : bool
     287          41 : WrapperBase::GetBool(const char* name, bool defVal)
     288             : {
     289          82 :   JS::RootedObject obj(mCx, mObject);
     290             : 
     291          82 :   JS::RootedValue val(mCx, JS::UndefinedValue());
     292          41 :   if (!JS_GetProperty(mCx, obj, name, &val)) {
     293           0 :     JS_ClearPendingException(mCx);
     294             :   }
     295             : 
     296          41 :   if (val.isBoolean()) {
     297          33 :     return val.toBoolean();
     298             :   }
     299           8 :   return defVal;
     300             : }
     301             : 
     302             : double
     303           1 : WrapperBase::GetNumber(const char* name, double defVal)
     304             : {
     305           2 :   JS::RootedObject obj(mCx, mObject);
     306             : 
     307           2 :   JS::RootedValue val(mCx, JS::UndefinedValue());
     308           1 :   if (!JS_GetProperty(mCx, obj, name, &val)) {
     309           0 :     JS_ClearPendingException(mCx);
     310             :   }
     311             : 
     312           1 :   if (val.isNumber()) {
     313           1 :     return val.toNumber();
     314             :   }
     315           0 :   return defVal;
     316             : }
     317             : 
     318             : nsString
     319          11 : WrapperBase::GetString(const char* name, const char* defVal)
     320             : {
     321          22 :   JS::RootedObject obj(mCx, mObject);
     322             : 
     323          22 :   JS::RootedValue val(mCx, JS::UndefinedValue());
     324          11 :   if (!JS_GetProperty(mCx, obj, name, &val)) {
     325           0 :     JS_ClearPendingException(mCx);
     326             :   }
     327             : 
     328          11 :   nsString res;
     329          11 :   if (val.isString()) {
     330           9 :     AssignJSString(mCx, res, val.toString());
     331             :   } else {
     332           2 :     res.AppendASCII(defVal);
     333             :   }
     334          22 :   return res;
     335             : }
     336             : 
     337             : JSObject*
     338           6 : WrapperBase::GetObject(const char* name)
     339             : {
     340          12 :   JS::RootedObject obj(mCx, mObject);
     341             : 
     342          12 :   JS::RootedValue val(mCx, JS::UndefinedValue());
     343           6 :   if (!JS_GetProperty(mCx, obj, name, &val)) {
     344           0 :     JS_ClearPendingException(mCx);
     345             :   }
     346             : 
     347           6 :   if (val.isObject()) {
     348           6 :     return &val.toObject();
     349             :   }
     350           0 :   return nullptr;
     351             : }
     352             : 
     353             : 
     354           6 : class MOZ_STACK_CLASS InstallLocation : public WrapperBase {
     355             : public:
     356             :   InstallLocation(JSContext* cx, const JS::Value& value);
     357             : 
     358           6 :   MOZ_IMPLICIT InstallLocation(PropertyIterElem& iter)
     359           6 :     : InstallLocation(iter.Cx(), iter.Value())
     360           6 :   {}
     361             : 
     362             :   InstallLocation(const InstallLocation& other)
     363             :     : InstallLocation(other.mCx, JS::ObjectValue(*other.mObject))
     364             :   {}
     365             : 
     366           0 :   void SetChanged(bool changed)
     367             :   {
     368           0 :     JS::RootedObject obj(mCx, mObject);
     369             : 
     370           0 :     JS::RootedValue val(mCx, JS::BooleanValue(changed));
     371           0 :     if (!JS_SetProperty(mCx, obj, "changed", val)) {
     372           0 :       JS_ClearPendingException(mCx);
     373             :     }
     374           0 :   }
     375             : 
     376           4 :   PropertyIter& Addons() { return mAddonsIter.ref(); }
     377             : 
     378           4 :   nsString Path() { return GetString("path"); }
     379             : 
     380           3 :   bool ShouldCheckStartupModifications() { return GetBool("checkStartupModifications"); }
     381             : 
     382             : 
     383             : private:
     384             :   JS::RootedObject mAddonsObj;
     385             :   Maybe<PropertyIter> mAddonsIter;
     386             : };
     387             : 
     388             : 
     389          18 : class MOZ_STACK_CLASS Addon : public WrapperBase {
     390             : public:
     391             :   Addon(JSContext* cx, InstallLocation& location, const nsAString& id, JSObject* object)
     392             :     : WrapperBase(cx, object)
     393             :     , mId(id)
     394             :     , mLocation(location)
     395             :   {}
     396             : 
     397          18 :   MOZ_IMPLICIT Addon(PropertyIterElem& iter)
     398          36 :     : WrapperBase(iter.Cx(), iter.Value())
     399          18 :     , mId(iter.Name())
     400          36 :     , mLocation(*static_cast<InstallLocation*>(iter.Context()))
     401          18 :   {}
     402             : 
     403             :   Addon(const Addon& other)
     404             :     : WrapperBase(other.mCx, other.mObject)
     405             :     , mId(other.mId)
     406             :     , mLocation(other.mLocation)
     407             :   {}
     408             : 
     409           0 :   const nsString& Id() { return mId; }
     410             : 
     411           4 :   nsString Path() { return GetString("path"); }
     412             : 
     413          17 :   bool Bootstrapped() { return GetBool("bootstrapped"); }
     414             : 
     415          18 :   bool Enabled() { return GetBool("enabled"); }
     416             : 
     417           3 :   bool ShimsEnabled() { return GetBool("enableShims"); }
     418             : 
     419           1 :   double LastModifiedTime() { return GetNumber("lastModifiedTime"); }
     420             : 
     421             : 
     422             :   Result<nsCOMPtr<nsIFile>, nsresult> FullPath();
     423             : 
     424             :   NSLocationType LocationType();
     425             : 
     426             :   Result<bool, nsresult> UpdateLastModifiedTime();
     427             : 
     428             : 
     429             : private:
     430             :   nsString mId;
     431             :   InstallLocation& mLocation;
     432             : };
     433             : 
     434             : Result<nsCOMPtr<nsIFile>, nsresult>
     435           4 : Addon::FullPath()
     436             : {
     437           8 :   nsString path = Path();
     438             : 
     439             :   // First check for an absolute path, in case we have a proxy file.
     440           8 :   nsCOMPtr<nsIFile> file;
     441           4 :   if (NS_SUCCEEDED(NS_NewLocalFile(path, false, getter_AddRefs(file)))) {
     442           0 :     return Move(file);
     443             :   }
     444             : 
     445             :   // If not an absolute path, fall back to a relative path from the location.
     446           4 :   NS_TRY(NS_NewLocalFile(mLocation.Path(), false, getter_AddRefs(file)));
     447             : 
     448           4 :   NS_TRY(file->AppendRelativePath(path));
     449           4 :   return Move(file);
     450             : }
     451             : 
     452             : NSLocationType
     453           3 : Addon::LocationType()
     454             : {
     455           6 :   nsString type = GetString("type", "extension");
     456           3 :   if (type.LowerCaseEqualsLiteral("theme")) {
     457           1 :     return NS_SKIN_LOCATION;
     458             :   }
     459           2 :   return NS_EXTENSION_LOCATION;
     460             : }
     461             : 
     462             : Result<bool, nsresult>
     463           1 : Addon::UpdateLastModifiedTime()
     464             : {
     465           2 :   nsCOMPtr<nsIFile> file;
     466           1 :   MOZ_TRY_VAR(file, FullPath());
     467             : 
     468             :   bool result;
     469           1 :   if (NS_FAILED(file->Exists(&result)) || !result) {
     470           0 :     return true;
     471             :   }
     472             : 
     473             :   PRTime time;
     474             : 
     475           2 :   nsCOMPtr<nsIFile> manifest = file;
     476           1 :   if (!IsNormalFile(manifest)) {
     477           1 :     manifest = CloneAndAppend(file, "install.rdf");
     478           1 :     if (!IsNormalFile(manifest)) {
     479           0 :       manifest = CloneAndAppend(file, "manifest.json");
     480           0 :       if (!IsNormalFile(manifest)) {
     481           0 :         return true;
     482             :       }
     483             :     }
     484             :   }
     485             : 
     486           1 :   if (NS_FAILED(manifest->GetLastModifiedTime(&time))) {
     487           0 :     return true;
     488             :   }
     489             : 
     490           2 :   JS::RootedObject obj(mCx, mObject);
     491             : 
     492           1 :   double lastModified = time;
     493           2 :   JS::RootedValue value(mCx, JS::NumberValue(lastModified));
     494           1 :   if (!JS_SetProperty(mCx, obj, "currentModifiedTime", value)) {
     495           0 :     JS_ClearPendingException(mCx);
     496             :   }
     497             : 
     498           1 :   return lastModified != LastModifiedTime();;
     499             : }
     500             : 
     501             : 
     502           6 : InstallLocation::InstallLocation(JSContext* cx, const JS::Value& value)
     503             :   : WrapperBase(cx, value)
     504             :   , mAddonsObj(cx)
     505           6 :   , mAddonsIter()
     506             : {
     507           6 :   mAddonsObj = GetObject("addons");
     508           6 :   if (!mAddonsObj) {
     509           0 :     mAddonsObj = JS_NewPlainObject(cx);
     510             :   }
     511           6 :   mAddonsIter.emplace(cx, mAddonsObj, this);
     512           6 : }
     513             : 
     514             : 
     515             : /*****************************************************************************
     516             :  * XPC interfacing
     517             :  *****************************************************************************/
     518             : 
     519             : static void
     520           0 : EnableShims(const nsAString& addonId)
     521             : {
     522           0 :   NS_ConvertUTF16toUTF8 id(addonId);
     523             : 
     524             :   nsCOMPtr<nsIAddonInterposition> interposition =
     525           0 :      do_GetService("@mozilla.org/addons/multiprocess-shims;1");
     526             : 
     527           0 :   if (!interposition || !xpc::SetAddonInterposition(id, interposition)) {
     528           0 :     return;
     529             :   }
     530             : 
     531           0 :   Unused << xpc::AllowCPOWsInAddon(id, true);
     532             : }
     533             : 
     534             : Result<Ok, nsresult>
     535           3 : AddonManagerStartup::AddInstallLocation(Addon& addon)
     536             : {
     537           6 :   nsCOMPtr<nsIFile> file;
     538           3 :   MOZ_TRY_VAR(file, addon.FullPath());
     539             : 
     540           6 :   nsString path;
     541           3 :   NS_TRY(file->GetPath(path));
     542             : 
     543           3 :   auto type = addon.LocationType();
     544             : 
     545           3 :   if (type == NS_SKIN_LOCATION) {
     546           1 :     mThemePaths.AppendElement(file);
     547             :   } else {
     548           2 :     mExtensionPaths.AppendElement(file);
     549             :   }
     550             : 
     551           3 :   if (StringTail(path, 4).LowerCaseEqualsLiteral(".xpi")) {
     552           0 :     XRE_AddJarManifestLocation(type, file);
     553             :   } else {
     554           6 :     nsCOMPtr<nsIFile> manifest = CloneAndAppend(file, "chrome.manifest");
     555           3 :     XRE_AddManifestLocation(type, manifest);
     556             :   }
     557           3 :   return Ok();
     558             : }
     559             : 
     560             : nsresult
     561           1 : AddonManagerStartup::ReadStartupData(JSContext* cx, JS::MutableHandleValue locations)
     562             : {
     563           1 :   locations.set(JS::UndefinedValue());
     564             : 
     565           2 :   nsCOMPtr<nsIFile> file = CloneAndAppend(ProfileDir(), "addonStartup.json.lz4");
     566             : 
     567           2 :   nsCString path;
     568           1 :   NS_TRY(file->GetNativePath(path));
     569             : 
     570           2 :   nsCString data;
     571           1 :   MOZ_TRY_VAR(data, ReadFileLZ4(path.get()));
     572             : 
     573           1 :   if (data.IsEmpty() || !ParseJSON(cx, data, locations)) {
     574           0 :     return NS_OK;
     575             :   }
     576             : 
     577           1 :   if (!locations.isObject()) {
     578           0 :     return NS_ERROR_UNEXPECTED;
     579             :   }
     580             : 
     581           2 :   JS::RootedObject locs(cx, &locations.toObject());
     582           2 :   for (auto e1 : PropertyIter(cx, locs)) {
     583           4 :     InstallLocation loc(e1);
     584             : 
     585           3 :     if (!loc.ShouldCheckStartupModifications()) {
     586           2 :       continue;
     587             :     }
     588             : 
     589           2 :     for (auto e2 : loc.Addons()) {
     590           2 :       Addon addon(e2);
     591             : 
     592           1 :       if (addon.Enabled()) {
     593             :         bool changed;
     594           1 :         MOZ_TRY_VAR(changed, addon.UpdateLastModifiedTime());
     595           1 :         if (changed) {
     596           0 :           loc.SetChanged(true);
     597             :         }
     598             :       }
     599             :     }
     600             :   }
     601             : 
     602           1 :   return NS_OK;
     603             : }
     604             : 
     605             : nsresult
     606           1 : AddonManagerStartup::InitializeExtensions(JS::HandleValue locations, JSContext* cx)
     607             : {
     608           1 :   NS_ENSURE_FALSE(mInitialized, NS_ERROR_UNEXPECTED);
     609           1 :   NS_ENSURE_TRUE(locations.isObject(), NS_ERROR_INVALID_ARG);
     610             : 
     611           1 :   mInitialized = true;
     612             : 
     613           1 :   if (!Preferences::GetBool("extensions.defaultProviders.enabled", true)) {
     614           0 :     return NS_OK;
     615             :   }
     616             : 
     617           1 :   bool enableInterpositions = Preferences::GetBool("extensions.interposition.enabled", false);
     618             : 
     619           2 :   JS::RootedObject locs(cx, &locations.toObject());
     620           4 :   for (auto e1 : PropertyIter(cx, locs)) {
     621           6 :     InstallLocation loc(e1);
     622             : 
     623          20 :     for (auto e2 : loc.Addons()) {
     624          34 :       Addon addon(e2);
     625             : 
     626          17 :       if (addon.Enabled() && !addon.Bootstrapped()) {
     627           3 :         Unused << AddInstallLocation(addon);
     628             : 
     629           3 :         if (enableInterpositions && addon.ShimsEnabled()) {
     630           0 :           EnableShims(addon.Id());
     631             :         }
     632             :       }
     633             :     }
     634             :   }
     635             : 
     636           1 :   return NS_OK;
     637             : }
     638             : 
     639             : nsresult
     640           0 : AddonManagerStartup::EncodeBlob(JS::HandleValue value, JSContext* cx, JS::MutableHandleValue result)
     641             : {
     642           0 :   StructuredCloneData holder;
     643             : 
     644           0 :   ErrorResult rv;
     645           0 :   holder.Write(cx, value, rv);
     646           0 :   if (rv.Failed()) {
     647           0 :     return rv.StealNSResult();
     648             :   }
     649             : 
     650           0 :   nsAutoCString scData;
     651             : 
     652           0 :   auto& data = holder.Data();
     653           0 :   auto iter = data.Iter();
     654           0 :   while (!iter.Done()) {
     655           0 :     scData.Append(nsDependentCSubstring(iter.Data(), iter.RemainingInSegment()));
     656           0 :     iter.Advance(data, iter.RemainingInSegment());
     657             :   }
     658             : 
     659           0 :   nsCString lz4;
     660           0 :   MOZ_TRY_VAR(lz4, EncodeLZ4(scData, STRUCTURED_CLONE_MAGIC));
     661             : 
     662           0 :   JS::RootedObject obj(cx);
     663           0 :   NS_TRY(nsContentUtils::CreateArrayBuffer(cx, lz4, &obj.get()));
     664             : 
     665           0 :   result.set(JS::ObjectValue(*obj));
     666           0 :   return NS_OK;
     667             : }
     668             : 
     669             : nsresult
     670           0 : AddonManagerStartup::DecodeBlob(JS::HandleValue value, JSContext* cx, JS::MutableHandleValue result)
     671             : {
     672           0 :   NS_ENSURE_TRUE(value.isObject() &&
     673             :                  JS_IsArrayBufferObject(&value.toObject()) &&
     674             :                  JS_ArrayBufferHasData(&value.toObject()),
     675             :                  NS_ERROR_INVALID_ARG);
     676             : 
     677           0 :   StructuredCloneData holder;
     678             : 
     679           0 :   nsCString data;
     680             :   {
     681           0 :     JS::AutoCheckCannotGC nogc;
     682             : 
     683           0 :     auto obj = &value.toObject();
     684             :     bool isShared;
     685             : 
     686             :     nsDependentCSubstring lz4(
     687           0 :       reinterpret_cast<char*>(JS_GetArrayBufferData(obj, &isShared, nogc)),
     688           0 :       JS_GetArrayBufferByteLength(obj));
     689             : 
     690           0 :     MOZ_TRY_VAR(data, DecodeLZ4(lz4, STRUCTURED_CLONE_MAGIC));
     691             :   }
     692             : 
     693           0 :   bool ok = holder.CopyExternalData(data.get(), data.Length());
     694           0 :   NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
     695             : 
     696           0 :   ErrorResult rv;
     697           0 :   holder.Read(cx, result, rv);
     698           0 :   return rv.StealNSResult();;
     699             : }
     700             : 
     701             : nsresult
     702           0 : AddonManagerStartup::Reset()
     703             : {
     704           0 :   MOZ_RELEASE_ASSERT(xpc::IsInAutomation());
     705             : 
     706           0 :   mInitialized = false;
     707             : 
     708           0 :   mExtensionPaths.Clear();
     709           0 :   mThemePaths.Clear();
     710             : 
     711           0 :   return NS_OK;
     712             : }
     713             : 
     714             : } // namespace mozilla

Generated by: LCOV version 1.13