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