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/pack_extension_handler.h"
6
7 #include "base/bind.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/extensions/extension_creator.h"
10 #include "chrome/browser/ui/chrome_select_file_policy.h"
11 #include "content/public/browser/web_contents.h"
12 #include "content/public/browser/web_ui.h"
13 #include "content/public/browser/web_ui_data_source.h"
14 #include "grit/generated_resources.h"
15 #include "ui/base/l10n/l10n_util.h"
16
17 namespace extensions {
18
PackExtensionHandler()19 PackExtensionHandler::PackExtensionHandler() {
20 }
21
~PackExtensionHandler()22 PackExtensionHandler::~PackExtensionHandler() {
23 // There may be pending file dialogs, we need to tell them that we've gone
24 // away so they don't try and call back to us.
25 if (load_extension_dialog_.get())
26 load_extension_dialog_->ListenerDestroyed();
27
28 if (pack_job_.get())
29 pack_job_->ClearClient();
30 }
31
GetLocalizedValues(content::WebUIDataSource * source)32 void PackExtensionHandler::GetLocalizedValues(
33 content::WebUIDataSource* source) {
34 source->AddString("packExtensionOverlay",
35 l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_TITLE));
36 source->AddString("packExtensionHeading",
37 l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_HEADING));
38 source->AddString("packExtensionCommit",
39 l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_BUTTON));
40 source->AddString("ok", l10n_util::GetStringUTF16(IDS_OK));
41 source->AddString("cancel", l10n_util::GetStringUTF16(IDS_CANCEL));
42 source->AddString("packExtensionRootDir",
43 l10n_util::GetStringUTF16(
44 IDS_EXTENSION_PACK_DIALOG_ROOT_DIRECTORY_LABEL));
45 source->AddString("packExtensionPrivateKey",
46 l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_PRIVATE_KEY_LABEL));
47 source->AddString("packExtensionBrowseButton",
48 l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_BROWSE));
49 source->AddString("packExtensionProceedAnyway",
50 l10n_util::GetStringUTF16(IDS_EXTENSION_PROCEED_ANYWAY));
51 source->AddString("packExtensionWarningTitle",
52 l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_WARNING_TITLE));
53 source->AddString("packExtensionErrorTitle",
54 l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_ERROR_TITLE));
55 }
56
RegisterMessages()57 void PackExtensionHandler::RegisterMessages() {
58 web_ui()->RegisterMessageCallback(
59 "pack",
60 base::Bind(&PackExtensionHandler::HandlePackMessage,
61 base::Unretained(this)));
62 web_ui()->RegisterMessageCallback(
63 "packExtensionSelectFilePath",
64 base::Bind(&PackExtensionHandler::HandleSelectFilePathMessage,
65 base::Unretained(this)));
66 }
67
OnPackSuccess(const base::FilePath & crx_file,const base::FilePath & pem_file)68 void PackExtensionHandler::OnPackSuccess(const base::FilePath& crx_file,
69 const base::FilePath& pem_file) {
70 base::ListValue arguments;
71 arguments.Append(base::Value::CreateStringValue(
72 base::UTF16ToUTF8(PackExtensionJob::StandardSuccessMessage(
73 crx_file, pem_file))));
74 web_ui()->CallJavascriptFunction(
75 "extensions.PackExtensionOverlay.showSuccessMessage", arguments);
76 }
77
OnPackFailure(const std::string & error,ExtensionCreator::ErrorType type)78 void PackExtensionHandler::OnPackFailure(const std::string& error,
79 ExtensionCreator::ErrorType type) {
80 if (type == ExtensionCreator::kCRXExists) {
81 base::StringValue error_str(error);
82 base::StringValue extension_path_str(extension_path_.value());
83 base::StringValue key_path_str(private_key_path_.value());
84 base::FundamentalValue overwrite_flag(ExtensionCreator::kOverwriteCRX);
85
86 web_ui()->CallJavascriptFunction(
87 "extensions.ExtensionSettings.askToOverrideWarning",
88 error_str, extension_path_str, key_path_str, overwrite_flag);
89 } else {
90 ShowAlert(error);
91 }
92 }
93
FileSelected(const base::FilePath & path,int index,void * params)94 void PackExtensionHandler::FileSelected(const base::FilePath& path, int index,
95 void* params) {
96 base::ListValue results;
97 results.Append(base::Value::CreateStringValue(path.value()));
98 web_ui()->CallJavascriptFunction("window.handleFilePathSelected", results);
99 }
100
MultiFilesSelected(const std::vector<base::FilePath> & files,void * params)101 void PackExtensionHandler::MultiFilesSelected(
102 const std::vector<base::FilePath>& files, void* params) {
103 NOTREACHED();
104 }
105
HandlePackMessage(const base::ListValue * args)106 void PackExtensionHandler::HandlePackMessage(const base::ListValue* args) {
107 DCHECK_EQ(3U, args->GetSize());
108
109 double flags_double = 0.0;
110 base::FilePath::StringType extension_path_str;
111 base::FilePath::StringType private_key_path_str;
112 if (!args->GetString(0, &extension_path_str) ||
113 !args->GetString(1, &private_key_path_str) ||
114 !args->GetDouble(2, &flags_double)) {
115 NOTREACHED();
116 return;
117 }
118
119 extension_path_ = base::FilePath(extension_path_str);
120 private_key_path_ = base::FilePath(private_key_path_str);
121
122 int run_flags = static_cast<int>(flags_double);
123
124 base::FilePath root_directory = extension_path_;
125 base::FilePath key_file = private_key_path_;
126 last_used_path_ = extension_path_;
127
128 if (root_directory.empty()) {
129 if (extension_path_.empty()) {
130 ShowAlert(l10n_util::GetStringUTF8(
131 IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_REQUIRED));
132 } else {
133 ShowAlert(l10n_util::GetStringUTF8(
134 IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_INVALID));
135 }
136
137 return;
138 }
139
140 if (!private_key_path_.empty() && key_file.empty()) {
141 ShowAlert(l10n_util::GetStringUTF8(
142 IDS_EXTENSION_PACK_DIALOG_ERROR_KEY_INVALID));
143 return;
144 }
145
146 pack_job_ = new PackExtensionJob(this, root_directory, key_file, run_flags);
147 pack_job_->Start();
148 }
149
HandleSelectFilePathMessage(const base::ListValue * args)150 void PackExtensionHandler::HandleSelectFilePathMessage(
151 const base::ListValue* args) {
152 DCHECK_EQ(2U, args->GetSize());
153
154 std::string select_type;
155 if (!args->GetString(0, &select_type))
156 NOTREACHED();
157
158 std::string operation;
159 if (!args->GetString(1, &operation))
160 NOTREACHED();
161
162 ui::SelectFileDialog::Type type = ui::SelectFileDialog::SELECT_FOLDER;
163 ui::SelectFileDialog::FileTypeInfo info;
164 int file_type_index = 0;
165 base::FilePath path_to_use = last_used_path_;
166 if (select_type == "file") {
167 type = ui::SelectFileDialog::SELECT_OPEN_FILE;
168 path_to_use = base::FilePath();
169 }
170
171 base::string16 select_title;
172 if (operation == "load") {
173 select_title = l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY);
174 } else if (operation == "pem") {
175 select_title = l10n_util::GetStringUTF16(
176 IDS_EXTENSION_PACK_DIALOG_SELECT_KEY);
177 info.extensions.push_back(std::vector<base::FilePath::StringType>());
178 info.extensions.front().push_back(FILE_PATH_LITERAL("pem"));
179 info.extension_description_overrides.push_back(
180 l10n_util::GetStringUTF16(
181 IDS_EXTENSION_PACK_DIALOG_KEY_FILE_TYPE_DESCRIPTION));
182 info.include_all_files = true;
183 file_type_index = 1;
184 } else {
185 NOTREACHED();
186 }
187
188 load_extension_dialog_ = ui::SelectFileDialog::Create(
189 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
190 load_extension_dialog_->SelectFile(
191 type,
192 select_title,
193 path_to_use,
194 &info,
195 file_type_index,
196 base::FilePath::StringType(),
197 web_ui()->GetWebContents()->GetTopLevelNativeWindow(),
198 NULL);
199 }
200
ShowAlert(const std::string & message)201 void PackExtensionHandler::ShowAlert(const std::string& message) {
202 base::ListValue arguments;
203 arguments.Append(base::Value::CreateStringValue(message));
204 web_ui()->CallJavascriptFunction(
205 "extensions.PackExtensionOverlay.showError", arguments);
206 }
207
208 } // namespace extensions
209