electron_extension_loader.cc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "shell/browser/extensions/electron_extension_loader.h"
  5. #include <utility>
  6. #include "base/auto_reset.h"
  7. #include "base/files/file_path.h"
  8. #include "base/files/file_util.h"
  9. #include "base/functional/bind.h"
  10. #include "base/logging.h"
  11. #include "base/strings/utf_string_conversions.h"
  12. #include "base/task/sequenced_task_runner.h"
  13. #include "base/threading/thread_restrictions.h"
  14. #include "base/time/time.h"
  15. #include "content/public/browser/browser_context.h"
  16. #include "extensions/browser/extension_file_task_runner.h"
  17. #include "extensions/browser/extension_prefs.h"
  18. #include "extensions/browser/extension_registry.h"
  19. #include "extensions/browser/pref_names.h"
  20. #include "extensions/common/constants.h"
  21. #include "extensions/common/error_utils.h"
  22. #include "extensions/common/file_util.h"
  23. #include "extensions/common/manifest_constants.h"
  24. namespace extensions {
  25. using LoadErrorBehavior = ExtensionRegistrar::LoadErrorBehavior;
  26. namespace {
  27. std::pair<scoped_refptr<const Extension>, std::string> LoadUnpacked(
  28. const base::FilePath& extension_dir,
  29. int load_flags) {
  30. // app_shell only supports unpacked extensions.
  31. // NOTE: If you add packed extension support consider removing the flag
  32. // FOLLOW_SYMLINKS_ANYWHERE below. Packed extensions should not have symlinks.
  33. if (!base::DirectoryExists(extension_dir)) {
  34. std::string err = "Extension directory not found: " +
  35. base::UTF16ToUTF8(extension_dir.LossyDisplayName());
  36. return std::make_pair(nullptr, err);
  37. }
  38. // remove _metadata folder. Otherwise, the following warning will be thrown
  39. // Cannot load extension with file or directory name _metadata.
  40. // Filenames starting with "_" are reserved for use by the system.
  41. // see: https://bugs.chromium.org/p/chromium/issues/detail?id=377278
  42. base::FilePath metadata_dir = extension_dir.Append(kMetadataFolder);
  43. if (base::DirectoryExists(metadata_dir)) {
  44. base::DeletePathRecursively(metadata_dir);
  45. }
  46. std::string load_error;
  47. scoped_refptr<Extension> extension = file_util::LoadExtension(
  48. extension_dir, extensions::mojom::ManifestLocation::kCommandLine,
  49. load_flags, &load_error);
  50. if (!extension.get()) {
  51. std::string err = "Loading extension at " +
  52. base::UTF16ToUTF8(extension_dir.LossyDisplayName()) +
  53. " failed with: " + load_error;
  54. return std::make_pair(nullptr, err);
  55. }
  56. std::string warnings;
  57. // Log warnings.
  58. if (!extension->install_warnings().empty()) {
  59. std::string warning_prefix =
  60. "Warnings loading extension at " +
  61. base::UTF16ToUTF8(extension_dir.LossyDisplayName());
  62. for (const auto& warning : extension->install_warnings()) {
  63. std::string unrecognized_manifest_error = ErrorUtils::FormatErrorMessage(
  64. manifest_errors::kUnrecognizedManifestKey, warning.key);
  65. if (warning.message == unrecognized_manifest_error) {
  66. // filter kUnrecognizedManifestKey error. This error does not have any
  67. // impact e.g: Unrecognized manifest key 'minimum_chrome_version' etc.
  68. LOG(WARNING) << warning_prefix << ": " << warning.message;
  69. } else {
  70. warnings += " " + warning.message + "\n";
  71. }
  72. }
  73. if (warnings != "") {
  74. warnings = warning_prefix + ":\n" + warnings;
  75. }
  76. }
  77. return std::make_pair(extension, warnings);
  78. }
  79. } // namespace
  80. ElectronExtensionLoader::ElectronExtensionLoader(
  81. content::BrowserContext* browser_context)
  82. : browser_context_(browser_context),
  83. extension_registrar_(ExtensionRegistrar::Get(browser_context)) {
  84. extension_registrar_->Init(
  85. this, /*extensions_enabled=*/true,
  86. browser_context_->GetPath().AppendASCII(kInstallDirectoryName),
  87. browser_context_->GetPath().AppendASCII(kUnpackedInstallDirectoryName));
  88. }
  89. ElectronExtensionLoader::~ElectronExtensionLoader() = default;
  90. void ElectronExtensionLoader::LoadExtension(
  91. const base::FilePath& extension_dir,
  92. int load_flags,
  93. base::OnceCallback<void(const Extension*, const std::string&)> cb) {
  94. GetExtensionFileTaskRunner()->PostTaskAndReplyWithResult(
  95. FROM_HERE, base::BindOnce(&LoadUnpacked, extension_dir, load_flags),
  96. base::BindOnce(&ElectronExtensionLoader::FinishExtensionLoad,
  97. weak_factory_.GetWeakPtr(), std::move(cb)));
  98. }
  99. void ElectronExtensionLoader::ReloadExtension(const ExtensionId& extension_id) {
  100. const Extension* extension = ExtensionRegistry::Get(browser_context_)
  101. ->GetInstalledExtension(extension_id);
  102. // We shouldn't be trying to reload extensions that haven't been added.
  103. DCHECK(extension);
  104. // This should always start false since it's only set here, or in
  105. // LoadExtensionForReload() as a result of the call below.
  106. DCHECK_EQ(false, did_schedule_reload_);
  107. base::AutoReset<bool> reset_did_schedule_reload(&did_schedule_reload_, false);
  108. extension_registrar_->ReloadExtension(extension_id,
  109. LoadErrorBehavior::kQuiet);
  110. if (did_schedule_reload_)
  111. return;
  112. }
  113. void ElectronExtensionLoader::UnloadExtension(
  114. const ExtensionId& extension_id,
  115. extensions::UnloadedExtensionReason reason) {
  116. extension_registrar_->RemoveExtension(extension_id, reason);
  117. }
  118. void ElectronExtensionLoader::FinishExtensionLoad(
  119. base::OnceCallback<void(const Extension*, const std::string&)> cb,
  120. std::pair<scoped_refptr<const Extension>, std::string> result) {
  121. scoped_refptr<const Extension> extension = result.first;
  122. if (extension) {
  123. extension_registrar_->AddExtension(extension);
  124. // Write extension install time to ExtensionPrefs. This is required by
  125. // WebRequestAPI which calls extensions::ExtensionPrefs::GetInstallTime.
  126. //
  127. // Implementation for writing the pref was based on
  128. // PreferenceAPIBase::SetExtensionControlledPref.
  129. {
  130. ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser_context_);
  131. ExtensionPrefs::ScopedDictionaryUpdate update(
  132. extension_prefs, extension.get()->id(),
  133. extensions::pref_names::kPrefPreferences);
  134. auto preference = update.Create();
  135. const int64_t now_usec =
  136. base::Time::Now().since_origin().InMicroseconds();
  137. preference->SetString("install_time", base::NumberToString(now_usec));
  138. }
  139. }
  140. std::move(cb).Run(extension.get(), result.second);
  141. }
  142. void ElectronExtensionLoader::FinishExtensionReload(
  143. const ExtensionId& old_extension_id,
  144. std::pair<scoped_refptr<const Extension>, std::string> result) {
  145. scoped_refptr<const Extension> extension = result.first;
  146. if (extension) {
  147. extension_registrar_->AddExtension(extension);
  148. }
  149. }
  150. void ElectronExtensionLoader::PreAddExtension(const Extension* extension,
  151. const Extension* old_extension) {
  152. if (old_extension)
  153. return;
  154. // The extension might be disabled if a previous reload attempt failed. In
  155. // that case, we want to remove that disable reason.
  156. ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser_context_);
  157. extension_prefs->RemoveDisableReason(extension->id(),
  158. disable_reason::DISABLE_RELOAD);
  159. }
  160. void ElectronExtensionLoader::PostActivateExtension(
  161. scoped_refptr<const Extension> extension) {}
  162. void ElectronExtensionLoader::PostDeactivateExtension(
  163. scoped_refptr<const Extension> extension) {}
  164. void ElectronExtensionLoader::PreUninstallExtension(
  165. scoped_refptr<const Extension> extension) {}
  166. void ElectronExtensionLoader::PostUninstallExtension(
  167. scoped_refptr<const Extension> extension,
  168. base::OnceClosure done_callback) {}
  169. void ElectronExtensionLoader::PostNotifyUninstallExtension(
  170. scoped_refptr<const Extension> extension) {}
  171. void ElectronExtensionLoader::LoadExtensionForReload(
  172. const ExtensionId& extension_id,
  173. const base::FilePath& path,
  174. LoadErrorBehavior load_error_behavior) {
  175. CHECK(!path.empty());
  176. // TODO(nornagon): we should save whether file access was granted
  177. // when loading this extension and retain it here. As is, reloading an
  178. // extension will cause the file access permission to be dropped.
  179. int load_flags = Extension::FOLLOW_SYMLINKS_ANYWHERE;
  180. GetExtensionFileTaskRunner()->PostTaskAndReplyWithResult(
  181. FROM_HERE, base::BindOnce(&LoadUnpacked, path, load_flags),
  182. base::BindOnce(&ElectronExtensionLoader::FinishExtensionReload,
  183. weak_factory_.GetWeakPtr(), extension_id));
  184. did_schedule_reload_ = true;
  185. }
  186. void ElectronExtensionLoader::ShowExtensionDisabledError(
  187. const Extension* extension,
  188. bool is_remote_install) {}
  189. void ElectronExtensionLoader::FinishDelayedInstallationsIfAny() {}
  190. bool ElectronExtensionLoader::CanAddExtension(const Extension* extension) {
  191. return true;
  192. }
  193. bool ElectronExtensionLoader::CanEnableExtension(const Extension* extension) {
  194. return true;
  195. }
  196. bool ElectronExtensionLoader::CanDisableExtension(const Extension* extension) {
  197. // Extensions cannot be disabled by the user.
  198. return false;
  199. }
  200. bool ElectronExtensionLoader::ShouldBlockExtension(const Extension* extension) {
  201. return false;
  202. }
  203. void ElectronExtensionLoader::GrantActivePermissions(
  204. const Extension* extension) {
  205. NOTIMPLEMENTED();
  206. }
  207. } // namespace extensions