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/extension_system.h"
     14 #include "chrome/browser/extensions/unpacked_installer.h"
     15 #include "chrome/browser/profiles/profile.h"
     16 #include "chrome/common/extensions/feature_switch.h"
     17 #include "content/public/browser/web_contents.h"
     18 #include "content/public/browser/web_contents_view.h"
     19 #include "content/public/browser/web_ui.h"
     20 #include "content/public/browser/web_ui_data_source.h"
     21 #include "content/public/common/drop_data.h"
     22 #include "grit/generated_resources.h"
     23 #include "net/base/net_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(const ListValue* args) {
     64   content::DropData* drop_data =
     65       web_ui()->GetWebContents()->GetView()->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 content::DropData::FileInfo& file_info = drop_data->filenames.front();
     77 
     78   file_to_install_ = base::FilePath::FromWStringHack(
     79       UTF16ToWide(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   file_display_name_ =
     83       file_info.display_name.empty() ? file_info.path : file_info.display_name;
     84 }
     85 
     86 void InstallExtensionHandler::HandleStopDragMessage(const ListValue* args) {
     87   file_to_install_.clear();
     88   file_display_name_.clear();
     89 }
     90 
     91 void InstallExtensionHandler::HandleInstallMessage(const ListValue* args) {
     92   if (file_to_install_.empty()) {
     93     LOG(ERROR) << "No file captured to install.";
     94     return;
     95   }
     96 
     97   Profile* profile = Profile::FromBrowserContext(
     98       web_ui()->GetWebContents()->GetBrowserContext());
     99   scoped_ptr<ExtensionInstallPrompt> prompt(
    100       new ExtensionInstallPrompt(web_ui()->GetWebContents()));
    101   scoped_refptr<CrxInstaller> crx_installer(CrxInstaller::Create(
    102       ExtensionSystem::Get(profile)->extension_service(),
    103       prompt.Pass()));
    104   crx_installer->set_error_on_unsupported_requirements(true);
    105   crx_installer->set_off_store_install_allow_reason(
    106       CrxInstaller::OffStoreInstallAllowedFromSettingsPage);
    107   crx_installer->set_install_wait_for_idle(false);
    108 
    109   const bool kCaseSensitive = false;
    110 
    111   if (EndsWith(file_display_name_, ASCIIToUTF16(".user.js"), kCaseSensitive)) {
    112     crx_installer->InstallUserScript(
    113         file_to_install_,
    114         net::FilePathToFileURL(file_to_install_));
    115   } else if (EndsWith(file_display_name_,
    116                       ASCIIToUTF16(".crx"),
    117                       kCaseSensitive)) {
    118     crx_installer->InstallCrx(file_to_install_);
    119   } else {
    120     CHECK(false);
    121   }
    122 
    123   file_to_install_.clear();
    124   file_display_name_.clear();
    125 }
    126 
    127 void InstallExtensionHandler::HandleInstallDirectoryMessage(
    128     const ListValue* args) {
    129   Profile* profile = Profile::FromBrowserContext(
    130       web_ui()->GetWebContents()->GetBrowserContext());
    131   UnpackedInstaller::Create(
    132       ExtensionSystem::Get(profile)->
    133           extension_service())->Load(file_to_install_);
    134 }
    135 
    136 }  // namespace extensions
    137