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