Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / unpacked_installer.cc
index ac4d1d7..11a5487 100644 (file)
@@ -6,45 +6,57 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
 #include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
+#include "chrome/browser/extensions/extension_error_reporter.h"
 #include "chrome/browser/extensions/extension_install_prompt.h"
-#include "chrome/browser/extensions/extension_install_ui.h"
+#include "chrome/browser/extensions/extension_management.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/permissions_updater.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/extensions/extension_install_ui_factory.h"
 #include "chrome/common/extensions/api/plugins/plugins_handler.h"
-#include "chrome/common/extensions/extension_file_util.h"
-#include "chrome/common/extensions/extension_l10n_util.h"
+#include "components/crx_file/id_util.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/install/extension_install_ui.h"
+#include "extensions/browser/install_flag.h"
 #include "extensions/common/extension.h"
-#include "extensions/common/id_util.h"
+#include "extensions/common/extension_l10n_util.h"
+#include "extensions/common/file_util.h"
 #include "extensions/common/manifest.h"
+#include "extensions/common/manifest_handlers/shared_module_info.h"
 #include "sync/api/string_ordinal.h"
 
 using content::BrowserThread;
 using extensions::Extension;
+using extensions::SharedModuleInfo;
 
 namespace {
 
 const char kUnpackedExtensionsBlacklistedError[] =
     "Loading of unpacked extensions is disabled by the administrator.";
 
+const char kImportMinVersionNewer[] =
+    "'import' version requested is newer than what is installed.";
+const char kImportMissing[] = "'import' extension is not installed.";
+const char kImportNotSharedModule[] = "'import' is not a shared module.";
+
 // Manages an ExtensionInstallPrompt for a particular extension.
 class SimpleExtensionLoadPrompt : public ExtensionInstallPrompt::Delegate {
  public:
   SimpleExtensionLoadPrompt(const Extension* extension,
                             Profile* profile,
                             const base::Closure& callback);
-  virtual ~SimpleExtensionLoadPrompt();
+  ~SimpleExtensionLoadPrompt() override;
 
   void ShowPrompt();
 
   // ExtensionInstallUI::Delegate
-  virtual void InstallUIProceed() OVERRIDE;
-  virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
+  void InstallUIProceed() override;
+  void InstallUIAbort(bool user_initiated) override;
 
  private:
   scoped_ptr<ExtensionInstallPrompt> install_ui_;
@@ -56,20 +68,30 @@ SimpleExtensionLoadPrompt::SimpleExtensionLoadPrompt(
     const Extension* extension,
     Profile* profile,
     const base::Closure& callback)
-    : install_ui_(ExtensionInstallUI::CreateInstallPromptWithProfile(
-          profile)),
-      extension_(extension),
-      callback_(callback) {
+    : extension_(extension), callback_(callback) {
+  scoped_ptr<extensions::ExtensionInstallUI> ui(
+      extensions::CreateExtensionInstallUI(profile));
+  install_ui_.reset(new ExtensionInstallPrompt(
+      profile, ui->GetDefaultInstallDialogParent()));
 }
 
 SimpleExtensionLoadPrompt::~SimpleExtensionLoadPrompt() {
 }
 
 void SimpleExtensionLoadPrompt::ShowPrompt() {
-  install_ui_->ConfirmInstall(
-      this,
-      extension_.get(),
-      ExtensionInstallPrompt::GetDefaultShowDialogCallback());
+  switch (ExtensionInstallPrompt::g_auto_confirm_for_tests) {
+    case ExtensionInstallPrompt::NONE:
+      install_ui_->ConfirmInstall(
+          this,
+          extension_.get(),
+          ExtensionInstallPrompt::GetDefaultShowDialogCallback());
+      break;
+    case ExtensionInstallPrompt::ACCEPT:
+      InstallUIProceed();
+      break;
+    case ExtensionInstallPrompt::CANCEL:
+      InstallUIAbort(false);
+  }
 }
 
 void SimpleExtensionLoadPrompt::InstallUIProceed() {
@@ -97,7 +119,8 @@ UnpackedInstaller::UnpackedInstaller(ExtensionService* extension_service)
     : service_weak_(extension_service->AsWeakPtr()),
       prompt_for_plugins_(true),
       require_modern_manifest_version_(true),
-      installer_(extension_service->profile()) {
+      be_noisy_on_failure_(true),
+      install_checker_(extension_service->profile()) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
 
@@ -134,21 +157,23 @@ bool UnpackedInstaller::LoadFromCommandLine(const base::FilePath& path_in,
   }
 
   std::string error;
-  installer_.set_extension(extension_file_util::LoadExtension(
-      extension_path_, Manifest::COMMAND_LINE, GetFlags(), &error).get());
+  install_checker_.set_extension(
+      file_util::LoadExtension(
+          extension_path_, Manifest::COMMAND_LINE, GetFlags(), &error).get());
 
-  if (!installer_.extension().get() ||
+  if (!extension() ||
       !extension_l10n_util::ValidateExtensionLocales(
-          extension_path_,
-          installer_.extension()->manifest()->value(),
-          &error)) {
+          extension_path_, extension()->manifest()->value(), &error)) {
     ReportExtensionLoadError(error);
     return false;
   }
 
+  PermissionsUpdater(
+      service_weak_->profile(), PermissionsUpdater::INIT_FLAG_TRANSIENT)
+      .InitializePermissions(extension());
   ShowInstallPrompt();
 
-  *extension_id = installer_.extension()->id();
+  *extension_id = extension()->id();
   return true;
 }
 
@@ -157,43 +182,87 @@ void UnpackedInstaller::ShowInstallPrompt() {
   if (!service_weak_.get())
     return;
 
-  const ExtensionSet* disabled_extensions =
-      service_weak_->disabled_extensions();
+  const ExtensionSet& disabled_extensions =
+      ExtensionRegistry::Get(service_weak_->profile())->disabled_extensions();
   if (service_weak_->show_extensions_prompts() && prompt_for_plugins_ &&
-      PluginInfo::HasPlugins(installer_.extension().get()) &&
-      !disabled_extensions->Contains(installer_.extension()->id())) {
+      PluginInfo::HasPlugins(extension()) &&
+      !disabled_extensions.Contains(extension()->id())) {
     SimpleExtensionLoadPrompt* prompt = new SimpleExtensionLoadPrompt(
-        installer_.extension().get(),
-        installer_.profile(),
-        base::Bind(&UnpackedInstaller::CallCheckRequirements, this));
+        extension(),
+        install_checker_.profile(),
+        base::Bind(&UnpackedInstaller::StartInstallChecks, this));
     prompt->ShowPrompt();
     return;
   }
-  CallCheckRequirements();
+  StartInstallChecks();
 }
 
-void UnpackedInstaller::CallCheckRequirements() {
-  installer_.CheckRequirements(
-      base::Bind(&UnpackedInstaller::OnRequirementsChecked, this));
+void UnpackedInstaller::StartInstallChecks() {
+  // TODO(crbug.com/421128): Enable these checks all the time.  The reason
+  // they are disabled for extensions loaded from the command-line is that
+  // installing unpacked extensions is asynchronous, but there can be
+  // dependencies between the extensions loaded by the command line.
+  if (extension()->manifest()->location() != Manifest::COMMAND_LINE) {
+    ExtensionService* service = service_weak_.get();
+    if (!service || service->browser_terminating())
+      return;
+
+    // TODO(crbug.com/420147): Move this code to a utility class to avoid
+    // duplication of SharedModuleService::CheckImports code.
+    if (SharedModuleInfo::ImportsModules(extension())) {
+      const std::vector<SharedModuleInfo::ImportInfo>& imports =
+          SharedModuleInfo::GetImports(extension());
+      std::vector<SharedModuleInfo::ImportInfo>::const_iterator i;
+      for (i = imports.begin(); i != imports.end(); ++i) {
+        Version version_required(i->minimum_version);
+        const Extension* imported_module =
+            service->GetExtensionById(i->extension_id, true);
+        if (!imported_module) {
+          ReportExtensionLoadError(kImportMissing);
+          return;
+        } else if (imported_module &&
+                   !SharedModuleInfo::IsSharedModule(imported_module)) {
+          ReportExtensionLoadError(kImportNotSharedModule);
+          return;
+        } else if (imported_module && (version_required.IsValid() &&
+                                       imported_module->version()->CompareTo(
+                                           version_required) < 0)) {
+          ReportExtensionLoadError(kImportMinVersionNewer);
+          return;
+        }
+      }
+    }
+  }
+
+  install_checker_.Start(
+      ExtensionInstallChecker::CHECK_REQUIREMENTS |
+          ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY,
+      true /* fail fast */,
+      base::Bind(&UnpackedInstaller::OnInstallChecksComplete, this));
 }
 
-void UnpackedInstaller::OnRequirementsChecked(
-    std::vector<std::string> requirement_errors) {
+void UnpackedInstaller::OnInstallChecksComplete(int failed_checks) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  if (!requirement_errors.empty()) {
-    ReportExtensionLoadError(JoinString(requirement_errors, ' '));
+  if (!install_checker_.policy_error().empty()) {
+    ReportExtensionLoadError(install_checker_.policy_error());
+    return;
+  }
+
+  if (!install_checker_.requirement_errors().empty()) {
+    ReportExtensionLoadError(
+        JoinString(install_checker_.requirement_errors(), ' '));
     return;
   }
 
-  ConfirmInstall();
+  InstallExtension();
 }
 
 int UnpackedInstaller::GetFlags() {
-  std::string id = id_util::GenerateIdForPath(extension_path_);
+  std::string id = crx_file::id_util::GenerateIdForPath(extension_path_);
   bool allow_file_access =
       Manifest::ShouldAlwaysAllowFileAccess(Manifest::UNPACKED);
-  ExtensionPrefs* prefs = service_weak_->extension_prefs();
+  ExtensionPrefs* prefs = ExtensionPrefs::Get(service_weak_->profile());
   if (prefs->HasAllowFileAccessSetting(id))
     allow_file_access = prefs->AllowFileAccess(id);
 
@@ -211,8 +280,8 @@ bool UnpackedInstaller::IsLoadingUnpackedAllowed() const {
     return true;
   // If there is a "*" in the extension blacklist, then no extensions should be
   // allowed at all (except explicitly whitelisted extensions).
-  ExtensionPrefs* prefs = service_weak_->extension_prefs();
-  return !prefs->ExtensionsBlacklistedByDefault();
+  return !ExtensionManagementFactory::GetForBrowserContext(
+              service_weak_->profile())->BlacklistedByDefault();
 }
 
 void UnpackedInstaller::GetAbsolutePath() {
@@ -221,8 +290,7 @@ void UnpackedInstaller::GetAbsolutePath() {
   extension_path_ = base::MakeAbsoluteFilePath(extension_path_);
 
   std::string error;
-  if (!extension_file_util::CheckForIllegalFilenames(extension_path_,
-                                                     &error)) {
+  if (!file_util::CheckForIllegalFilenames(extension_path_, &error)) {
     BrowserThread::PostTask(
         BrowserThread::UI,
         FROM_HERE,
@@ -254,14 +322,13 @@ void UnpackedInstaller::LoadWithFileAccess(int flags) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
   std::string error;
-  installer_.set_extension(extension_file_util::LoadExtension(
-      extension_path_, Manifest::UNPACKED, flags, &error).get());
+  install_checker_.set_extension(
+      file_util::LoadExtension(
+          extension_path_, Manifest::UNPACKED, flags, &error).get());
 
-  if (!installer_.extension().get() ||
+  if (!extension() ||
       !extension_l10n_util::ValidateExtensionLocales(
-          extension_path_,
-          installer_.extension()->manifest()->value(),
-          &error)) {
+          extension_path_, extension()->manifest()->value(), &error)) {
     BrowserThread::PostTask(
         BrowserThread::UI,
         FROM_HERE,
@@ -277,28 +344,25 @@ void UnpackedInstaller::LoadWithFileAccess(int flags) {
 
 void UnpackedInstaller::ReportExtensionLoadError(const std::string &error) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (!service_weak_.get())
-    return;
-  service_weak_->ReportExtensionLoadError(extension_path_, error, true);
-}
 
-void UnpackedInstaller::ConfirmInstall() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  base::string16 error = installer_.CheckManagementPolicy();
-  if (!error.empty()) {
-    ReportExtensionLoadError(base::UTF16ToUTF8(error));
-    return;
+  if (service_weak_.get()) {
+    ExtensionErrorReporter::GetInstance()->ReportLoadError(
+        extension_path_,
+        error,
+        service_weak_->profile(),
+        be_noisy_on_failure_);
   }
+}
+
+void UnpackedInstaller::InstallExtension() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   PermissionsUpdater perms_updater(service_weak_->profile());
-  perms_updater.GrantActivePermissions(installer_.extension().get());
+  perms_updater.InitializePermissions(extension());
+  perms_updater.GrantActivePermissions(extension());
 
   service_weak_->OnExtensionInstalled(
-      installer_.extension().get(),
-      syncer::StringOrdinal(),
-      false /* no requirement errors */,
-      NOT_BLACKLISTED,
-      false /* don't wait for idle */);
+      extension(), syncer::StringOrdinal(), kInstallFlagInstallImmediately);
 }
 
 }  // namespace extensions