electron_api_extensions.cc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright (c) 2019 Slack Technologies, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/browser/api/electron_api_extensions.h"
  5. #include "chrome/browser/browser_process.h"
  6. #include "extensions/browser/extension_registry.h"
  7. #include "gin/data_object_builder.h"
  8. #include "gin/handle.h"
  9. #include "gin/object_template_builder.h"
  10. #include "shell/browser/api/electron_api_extensions.h"
  11. #include "shell/browser/electron_browser_context.h"
  12. #include "shell/browser/extensions/electron_extension_system.h"
  13. #include "shell/browser/javascript_environment.h"
  14. #include "shell/common/gin_converters/extension_converter.h"
  15. #include "shell/common/gin_converters/file_path_converter.h"
  16. #include "shell/common/gin_converters/gurl_converter.h"
  17. #include "shell/common/gin_converters/value_converter.h"
  18. #include "shell/common/gin_helper/dictionary.h"
  19. #include "shell/common/gin_helper/promise.h"
  20. #include "shell/common/node_util.h"
  21. namespace electron::api {
  22. gin::WrapperInfo Extensions::kWrapperInfo = {gin::kEmbedderNativeGin};
  23. Extensions::Extensions(v8::Isolate* isolate,
  24. ElectronBrowserContext* browser_context)
  25. : browser_context_(browser_context) {
  26. extensions::ExtensionRegistry::Get(browser_context)->AddObserver(this);
  27. }
  28. Extensions::~Extensions() {
  29. extensions::ExtensionRegistry::Get(browser_context())->RemoveObserver(this);
  30. }
  31. // static
  32. gin::Handle<Extensions> Extensions::Create(
  33. v8::Isolate* isolate,
  34. ElectronBrowserContext* browser_context) {
  35. return gin::CreateHandle(isolate, new Extensions(isolate, browser_context));
  36. }
  37. v8::Local<v8::Promise> Extensions::LoadExtension(
  38. v8::Isolate* isolate,
  39. const base::FilePath& extension_path,
  40. gin::Arguments* args) {
  41. gin_helper::Promise<const extensions::Extension*> promise(isolate);
  42. v8::Local<v8::Promise> handle = promise.GetHandle();
  43. if (!extension_path.IsAbsolute()) {
  44. promise.RejectWithErrorMessage(
  45. "The path to the extension in 'loadExtension' must be absolute");
  46. return handle;
  47. }
  48. if (browser_context()->IsOffTheRecord()) {
  49. promise.RejectWithErrorMessage(
  50. "Extensions cannot be loaded in a temporary session");
  51. return handle;
  52. }
  53. int load_flags = extensions::Extension::FOLLOW_SYMLINKS_ANYWHERE;
  54. gin_helper::Dictionary options;
  55. if (args->GetNext(&options)) {
  56. bool allowFileAccess = false;
  57. options.Get("allowFileAccess", &allowFileAccess);
  58. if (allowFileAccess)
  59. load_flags |= extensions::Extension::ALLOW_FILE_ACCESS;
  60. }
  61. auto* extension_system = static_cast<extensions::ElectronExtensionSystem*>(
  62. extensions::ExtensionSystem::Get(browser_context()));
  63. extension_system->LoadExtension(
  64. extension_path, load_flags,
  65. base::BindOnce(
  66. [](gin_helper::Promise<const extensions::Extension*> promise,
  67. const extensions::Extension* extension,
  68. const std::string& error_msg) {
  69. if (extension) {
  70. if (!error_msg.empty())
  71. util::EmitWarning(promise.isolate(), error_msg,
  72. "ExtensionLoadWarning");
  73. promise.Resolve(extension);
  74. } else {
  75. promise.RejectWithErrorMessage(error_msg);
  76. }
  77. },
  78. std::move(promise)));
  79. return handle;
  80. }
  81. void Extensions::RemoveExtension(const std::string& extension_id) {
  82. auto* extension_system = static_cast<extensions::ElectronExtensionSystem*>(
  83. extensions::ExtensionSystem::Get(browser_context()));
  84. extension_system->RemoveExtension(extension_id);
  85. }
  86. v8::Local<v8::Value> Extensions::GetExtension(v8::Isolate* isolate,
  87. const std::string& extension_id) {
  88. auto* registry = extensions::ExtensionRegistry::Get(browser_context());
  89. const extensions::Extension* extension =
  90. registry->GetInstalledExtension(extension_id);
  91. if (extension) {
  92. return gin::ConvertToV8(isolate, extension);
  93. } else {
  94. return v8::Null(isolate);
  95. }
  96. }
  97. v8::Local<v8::Value> Extensions::GetAllExtensions(v8::Isolate* isolate) {
  98. auto* registry = extensions::ExtensionRegistry::Get(browser_context());
  99. const extensions::ExtensionSet extensions =
  100. registry->GenerateInstalledExtensionsSet();
  101. std::vector<const extensions::Extension*> extensions_vector;
  102. for (const auto& extension : extensions) {
  103. if (extension->location() !=
  104. extensions::mojom::ManifestLocation::kComponent)
  105. extensions_vector.emplace_back(extension.get());
  106. }
  107. return gin::ConvertToV8(isolate, extensions_vector);
  108. }
  109. void Extensions::OnExtensionLoaded(content::BrowserContext* browser_context,
  110. const extensions::Extension* extension) {
  111. Emit("extension-loaded", extension);
  112. }
  113. void Extensions::OnExtensionUnloaded(
  114. content::BrowserContext* browser_context,
  115. const extensions::Extension* extension,
  116. extensions::UnloadedExtensionReason reason) {
  117. Emit("extension-unloaded", extension);
  118. }
  119. void Extensions::OnExtensionReady(content::BrowserContext* browser_context,
  120. const extensions::Extension* extension) {
  121. Emit("extension-ready", extension);
  122. }
  123. // static
  124. gin::ObjectTemplateBuilder Extensions::GetObjectTemplateBuilder(
  125. v8::Isolate* isolate) {
  126. return gin_helper::EventEmitterMixin<Extensions>::GetObjectTemplateBuilder(
  127. isolate)
  128. .SetMethod("loadExtension", &Extensions::LoadExtension)
  129. .SetMethod("removeExtension", &Extensions::RemoveExtension)
  130. .SetMethod("getExtension", &Extensions::GetExtension)
  131. .SetMethod("getAllExtensions", &Extensions::GetAllExtensions);
  132. }
  133. const char* Extensions::GetTypeName() {
  134. return "Extensions";
  135. }
  136. } // namespace electron::api