Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2012 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 
      5 #include "chrome/browser/ui/webui/extensions/install_extension_handler.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/strings/utf_string_conversions.h"
     10 #include "chrome/browser/extensions/crx_installer.h"
     11 #include "chrome/browser/extensions/extension_install_prompt.h"
     12 #include "chrome/browser/extensions/extension_service.h"
     13 #include "chrome/browser/extensions/unpacked_installer.h"
     14 #include "chrome/browser/extensions/zipfile_installer.h"
     15 #include "chrome/browser/profiles/profile.h"
     16 #include "chrome/grit/generated_resources.h"
     17 #include "content/public/browser/web_contents.h"
     18 #include "content/public/browser/web_ui.h"
     19 #include "content/public/browser/web_ui_data_source.h"
     20 #include "content/public/common/drop_data.h"
     21 #include "extensions/browser/extension_system.h"
     22 #include "extensions/common/feature_switch.h"
     23 #include "net/base/filename_util.h"
     24 #include "ui/base/l10n/l10n_util.h"
     25 
     26 namespace extensions {
     27 
     28 InstallExtensionHandler::InstallExtensionHandler() {
     29 }
     30 
     31 InstallExtensionHandler::~InstallExtensionHandler() {
     32 }
     33 
     34 void InstallExtensionHandler::GetLocalizedValues(
     35     content::WebUIDataSource* source) {
     36   source->AddString(
     37       "extensionSettingsInstallDropTarget",
     38       l10n_util::GetStringUTF16(IDS_EXTENSIONS_INSTALL_DROP_TARGET));
     39   source->AddBoolean(
     40       "offStoreInstallEnabled",
     41       FeatureSwitch::easy_off_store_install()->IsEnabled());
     42 }
     43 
     44 void InstallExtensionHandler::RegisterMessages() {
     45   web_ui()->RegisterMessageCallback(
     46       "startDrag",
     47       base::Bind(&InstallExtensionHandler::HandleStartDragMessage,
     48                  base::Unretained(this)));
     49   web_ui()->RegisterMessageCallback(
     50       "stopDrag",
     51       base::Bind(&InstallExtensionHandler::HandleStopDragMessage,
     52                  base::Unretained(this)));
     53   web_ui()->RegisterMessageCallback(
     54       "installDroppedFile",
     55       base::Bind(&InstallExtensionHandler::HandleInstallMessage,
     56                  base::Unretained(this)));
     57   web_ui()->RegisterMessageCallback(
     58       "installDroppedDirectory",
     59       base::Bind(&InstallExtensionHandler::HandleInstallDirectoryMessage,
     60                  base::Unretained(this)));
     61 }
     62 
     63 void InstallExtensionHandler::HandleStartDragMessage(
     64     const base::ListValue* args) {
     65   content::DropData* drop_data =
     66       web_ui()->GetWebContents()->GetDropData();
     67   if (!drop_data) {
     68     DLOG(ERROR) << "No current drop data.";
     69     return;
     70   }
     71 
     72   if (drop_data->filenames.empty()) {
     73     DLOG(ERROR) << "Current drop data contains no files.";
     74     return;
     75   }
     76 
     77   const ui::FileInfo& file_info = drop_data->filenames.front();
     78 
     79   file_to_install_ = file_info.path;
     80   // Use the display name if provided, for checking file names
     81   // (.path is likely a random hash value in that case).
     82   // TODO(dcheng): It would be nice to make this a FilePath too.
     83   file_display_name_ = file_info.display_name.empty()
     84                            ? file_info.path.AsUTF16Unsafe()
     85                            : file_info.display_name.AsUTF16Unsafe();
     86 }
     87 
     88 void InstallExtensionHandler::HandleStopDragMessage(
     89     const base::ListValue* args) {
     90   file_to_install_.clear();
     91   file_display_name_.clear();
     92 }
     93 
     94 void InstallExtensionHandler::HandleInstallMessage(
     95     const base::ListValue* args) {
     96   if (file_to_install_.empty()) {
     97     LOG(ERROR) << "No file captured to install.";
     98     return;
     99   }
    100 
    101   Profile* profile = Profile::FromBrowserContext(
    102       web_ui()->GetWebContents()->GetBrowserContext());
    103 
    104   const bool kCaseSensitive = false;
    105 
    106   if (EndsWith(
    107           file_display_name_, base::ASCIIToUTF16(".zip"), kCaseSensitive)) {
    108     ZipFileInstaller::Create(ExtensionSystem::Get(profile)->extension_service())
    109         ->LoadFromZipFile(file_to_install_);
    110   } else {
    111     scoped_ptr<ExtensionInstallPrompt> prompt(
    112         new ExtensionInstallPrompt(web_ui()->GetWebContents()));
    113     scoped_refptr<CrxInstaller> crx_installer(CrxInstaller::Create(
    114         ExtensionSystem::Get(profile)->extension_service(), prompt.Pass()));
    115     crx_installer->set_error_on_unsupported_requirements(true);
    116     crx_installer->set_off_store_install_allow_reason(
    117         CrxInstaller::OffStoreInstallAllowedFromSettingsPage);
    118     crx_installer->set_install_immediately(true);
    119 
    120     if (EndsWith(file_display_name_,
    121                  base::ASCIIToUTF16(".user.js"),
    122                  kCaseSensitive)) {
    123       crx_installer->InstallUserScript(
    124           file_to_install_, net::FilePathToFileURL(file_to_install_));
    125     } else if (EndsWith(file_display_name_,
    126                         base::ASCIIToUTF16(".crx"),
    127                         kCaseSensitive)) {
    128       crx_installer->InstallCrx(file_to_install_);
    129     } else {
    130       CHECK(false);
    131     }
    132   }
    133 
    134   file_to_install_.clear();
    135   file_display_name_.clear();
    136 }
    137 
    138 void InstallExtensionHandler::HandleInstallDirectoryMessage(
    139     const base::ListValue* args) {
    140   Profile* profile = Profile::FromBrowserContext(
    141       web_ui()->GetWebContents()->GetBrowserContext());
    142   UnpackedInstaller::Create(
    143       ExtensionSystem::Get(profile)->
    144           extension_service())->Load(file_to_install_);
    145 }
    146 
    147 }  // namespace extensions
    148