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 25namespace extensions { 26 27InstallExtensionHandler::InstallExtensionHandler() { 28} 29 30InstallExtensionHandler::~InstallExtensionHandler() { 31} 32 33void 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 43void 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 62void 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 87void InstallExtensionHandler::HandleStopDragMessage( 88 const base::ListValue* args) { 89 file_to_install_.clear(); 90 file_display_name_.clear(); 91} 92 93void 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 132void 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