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