summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorrafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-07 04:43:45 +0000
committerrafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-07 04:43:45 +0000
commit5cbb809a7203d91c05021aae74e16fdcefff9352 (patch)
tree0627479ed7960568638b118d8e01c0aac41d5a25 /chrome
parentb00e86cf9afb44beb3f8fd51e85318505cabaa89 (diff)
downloadchromium_src-5cbb809a7203d91c05021aae74e16fdcefff9352.zip
chromium_src-5cbb809a7203d91c05021aae74e16fdcefff9352.tar.gz
chromium_src-5cbb809a7203d91c05021aae74e16fdcefff9352.tar.bz2
This reverts: HTML Pack Extension Dialog / Linux & Mac Packaging Support.
original issue: http://codereview.chromium.org/207062/ TBR=sky Review URL: http://codereview.chromium.org/270001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28234 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/browser_init.cc27
-rw-r--r--chrome/browser/extensions/extensions_service_unittest.cc2
-rw-r--r--chrome/browser/extensions/extensions_ui.cc138
-rw-r--r--chrome/browser/extensions/extensions_ui.h23
-rw-r--r--chrome/browser/extensions/pack_extension_job.h8
-rw-r--r--chrome/browser/net/chrome_url_request_context.cc3
-rw-r--r--chrome/browser/resources/extensions_ui.html188
-rw-r--r--chrome/browser/views/extensions/extension_pack_dialog.cc233
-rwxr-xr-xchrome/chrome.gyp8
9 files changed, 275 insertions, 355 deletions
diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc
index ce0c7f4..b551bcf 100644
--- a/chrome/browser/browser_init.cc
+++ b/chrome/browser/browser_init.cc
@@ -28,7 +28,9 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/defaults.h"
+#if defined(OS_WIN) // TODO(port)
#include "chrome/browser/extensions/extension_creator.h"
+#endif
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/user_script_master.h"
#include "chrome/browser/first_run.h"
@@ -365,20 +367,6 @@ GURL GetWelcomePageURL() {
return GURL(welcome_url);
}
-void ShowPackExtensionMessage(const std::wstring caption,
- const std::wstring message) {
-#if defined(OS_WIN)
- win_util::MessageBox(NULL, message, caption, MB_OK | MB_SETFOREGROUND);
-#else
- // Just send caption & text to stdout on mac & linux.
- std::string out_text = WideToASCII(caption);
- out_text.append("\n\n");
- out_text.append(WideToASCII(message));
- out_text.append("\n");
- printf(out_text.c_str());
-#endif
-}
-
} // namespace
// static
@@ -763,6 +751,7 @@ bool BrowserInit::ProcessCmdLineImpl(const CommandLine& command_line,
// ExtensionCreator depends on base/crypto/rsa_private_key and
// base/crypto/signature_creator, both of which only have windows
// implementations.
+#if defined(OS_WIN)
scoped_ptr<ExtensionCreator> creator(new ExtensionCreator());
if (creator->Run(src_dir, crx_path, private_key_path,
output_private_key_path)) {
@@ -780,12 +769,16 @@ bool BrowserInit::ProcessCmdLineImpl(const CommandLine& command_line,
message = StringPrintf(L"Created the extension:\n\n%ls",
crx_path.ToWStringHack().c_str());
}
- ShowPackExtensionMessage(L"Extension Packaging Success", message);
+ win_util::MessageBox(NULL, message, L"Extension Packaging Success",
+ MB_OK | MB_SETFOREGROUND);
} else {
- ShowPackExtensionMessage(L"Extension Packaging Error",
- UTF8ToWide(creator->error_message()));
+ win_util::MessageBox(NULL, UTF8ToWide(creator->error_message()),
+ L"Extension Packaging Error", MB_OK | MB_SETFOREGROUND);
return false;
}
+#else
+ NOTIMPLEMENTED() << " extension creation not implemented on POSIX.";
+#endif // defined(OS_WIN)
return false;
}
}
diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc
index 57ae6f6..fa257e0 100644
--- a/chrome/browser/extensions/extensions_service_unittest.cc
+++ b/chrome/browser/extensions/extensions_service_unittest.cc
@@ -727,6 +727,7 @@ TEST_F(ExtensionsServiceTest, InstallExtension) {
// TODO(erikkay): add tests for upgrade cases.
}
+#if defined(OS_WIN) // TODO(port)
// Test Packaging and installing an extension.
// TODO(rafaelw): add more tests for failure cases.
TEST_F(ExtensionsServiceTest, PackExtension) {
@@ -790,6 +791,7 @@ TEST_F(ExtensionsServiceTest, PackExtensionOpenSSLKey) {
file_util::Delete(crx_path, false);
}
+#endif // defined(OS_WIN)
TEST_F(ExtensionsServiceTest, InstallTheme) {
InitializeEmptyExtensionsService();
diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc
index 96de8e3..db10a9a 100644
--- a/chrome/browser/extensions/extensions_ui.cc
+++ b/chrome/browser/extensions/extensions_ui.cc
@@ -9,7 +9,6 @@
#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/debugger/devtools_manager.h"
#include "chrome/browser/extensions/extension_message_service.h"
#include "chrome/browser/extensions/extensions_service.h"
@@ -48,14 +47,6 @@ void ExtensionsUIHTMLSource::StartDataRequest(const std::string& path,
DictionaryValue localized_strings;
localized_strings.SetString(L"title",
l10n_util::GetString(IDS_EXTENSIONS_TITLE));
- localized_strings.SetString(L"packDialogHeading",
- l10n_util::GetString(IDS_EXTENSION_PACK_DIALOG_HEADING));
- localized_strings.SetString(L"rootDirectoryLabel",
- l10n_util::GetString(IDS_EXTENSION_PACK_DIALOG_ROOT_DIRECTORY_LABEL));
- localized_strings.SetString(L"packDialogBrowse",
- l10n_util::GetString(IDS_EXTENSION_PACK_DIALOG_BROWSE));
- localized_strings.SetString(L"privateKeyLabel",
- l10n_util::GetString(IDS_EXTENSION_PACK_DIALOG_PRIVATE_KEY_LABEL));
static const base::StringPiece extensions_html(
ResourceBundle::GetSharedInstance().GetRawDataResource(
@@ -100,8 +91,6 @@ void ExtensionsDOMHandler::RegisterMessages() {
NewCallback(this, &ExtensionsDOMHandler::HandlePackMessage));
dom_ui_->RegisterMessageCallback("autoupdate",
NewCallback(this, &ExtensionsDOMHandler::HandleAutoUpdateMessage));
- dom_ui_->RegisterMessageCallback("selectFilePath",
- NewCallback(this, &ExtensionsDOMHandler::HandleSelectFilePathMessage));
}
void ExtensionsDOMHandler::HandleRequestExtensionsData(const Value* value) {
@@ -198,77 +187,18 @@ void ExtensionsDOMHandler::HandleUninstallMessage(const Value* value) {
}
void ExtensionsDOMHandler::HandleLoadMessage(const Value* value) {
- std::string string_path;
- CHECK(value->IsType(Value::TYPE_LIST));
- const ListValue* list = static_cast<const ListValue*>(value);
- CHECK(list->GetSize() == 1) << list->GetSize();
- CHECK(list->GetString(0, &string_path));
- FilePath file_path = FilePath::FromWStringHack(ASCIIToWide(string_path));
- extensions_service_->LoadExtension(file_path);
-}
-
-void ExtensionsDOMHandler::ShowAlert(const std::string& message) {
- ListValue arguments;
- arguments.Append(Value::CreateStringValue(message));
- dom_ui_->CallJavascriptFunction(L"alert", arguments);
+ load_extension_dialog_ = SelectFileDialog::Create(this);
+ load_extension_dialog_->SelectFile(
+ SelectFileDialog::SELECT_FOLDER,
+ l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY),
+ FilePath(), NULL, 0, FILE_PATH_LITERAL(""),
+ dom_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
}
void ExtensionsDOMHandler::HandlePackMessage(const Value* value) {
- std::string extension_path;
- std::string private_key_path;
- CHECK(value->IsType(Value::TYPE_LIST));
- const ListValue* list = static_cast<const ListValue*>(value);
- CHECK(list->GetSize() == 2);
- CHECK(list->GetString(0, &extension_path));
- CHECK(list->GetString(1, &private_key_path));
-
- FilePath root_directory = FilePath::FromWStringHack(ASCIIToWide(
- extension_path));
- FilePath key_file = FilePath::FromWStringHack(ASCIIToWide(private_key_path));
-
- if (root_directory.empty()) {
- if (extension_path.empty()) {
- ShowAlert(l10n_util::GetStringUTF8(
- IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_REQUIRED));
- } else {
- ShowAlert(l10n_util::GetStringUTF8(
- IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_INVALID));
- }
-
- return;
- }
-
- if (!private_key_path.empty() && key_file.empty()) {
- ShowAlert(l10n_util::GetStringUTF8(
- IDS_EXTENSION_PACK_DIALOG_ERROR_KEY_INVALID));
- return;
- }
-
- pack_job_ = new PackExtensionJob(this, root_directory, key_file,
- ChromeThread::GetMessageLoop(ChromeThread::FILE));
-}
-
-void ExtensionsDOMHandler::OnPackSuccess(const FilePath& crx_file,
- const FilePath& pem_file) {
- std::string message;
- if (!pem_file.empty()) {
- message = WideToASCII(l10n_util::GetStringF(
- IDS_EXTENSION_PACK_DIALOG_SUCCESS_BODY_NEW,
- crx_file.ToWStringHack(),
- pem_file.ToWStringHack()));
- } else {
- message = WideToASCII(l10n_util::GetStringF(
- IDS_EXTENSION_PACK_DIALOG_SUCCESS_BODY_UPDATE,
- crx_file.ToWStringHack()));
- }
- ShowAlert(message);
-
- ListValue results;
- dom_ui_->CallJavascriptFunction(L"hidePackDialog", results);
-}
-
-void ExtensionsDOMHandler::OnPackFailure(const std::wstring& error) {
- ShowAlert(WideToASCII(error));
+#if defined(OS_WIN)
+ ShowPackDialog();
+#endif
}
void ExtensionsDOMHandler::HandleAutoUpdateMessage(const Value* value) {
@@ -278,55 +208,9 @@ void ExtensionsDOMHandler::HandleAutoUpdateMessage(const Value* value) {
}
}
-void ExtensionsDOMHandler::HandleSelectFilePathMessage(const Value* value) {
- std::string select_type;
- std::string operation;
- CHECK(value->IsType(Value::TYPE_LIST));
- const ListValue* list = static_cast<const ListValue*>(value);
- CHECK(list->GetSize() == 2);
- CHECK(list->GetString(0, &select_type));
- CHECK(list->GetString(1, &operation));
-
- SelectFileDialog::Type type = SelectFileDialog::SELECT_FOLDER;
- static SelectFileDialog::FileTypeInfo info;
- int file_type_index = 0;
- if (select_type == "file")
- type = SelectFileDialog::SELECT_OPEN_FILE;
-
- string16 select_title;
- if (operation == "load")
- select_title = l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY);
- else if (operation == "packRoot")
- select_title = l10n_util::GetStringUTF16(
- IDS_EXTENSION_PACK_DIALOG_SELECT_ROOT);
- else if (operation == "pem") {
- select_title = l10n_util::GetStringUTF16(
- IDS_EXTENSION_PACK_DIALOG_SELECT_KEY);
- info.extensions.push_back(std::vector<FilePath::StringType>());
- info.extensions.front().push_back(FILE_PATH_LITERAL("pem"));
- info.extension_description_overrides.push_back(WideToUTF16(
- l10n_util::GetString(
- IDS_EXTENSION_PACK_DIALOG_KEY_FILE_TYPE_DESCRIPTION)));
- info.include_all_files = true;
- file_type_index = 1;
- } else {
- NOTREACHED();
- return;
- }
-
- load_extension_dialog_ = SelectFileDialog::Create(this);
- load_extension_dialog_->SelectFile(type, select_title, FilePath(), &info,
- file_type_index, FILE_PATH_LITERAL(""),
- dom_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
-}
-
-
void ExtensionsDOMHandler::FileSelected(const FilePath& path, int index,
void* params) {
- // Add the extensions to the results structure.
- ListValue results;
- results.Append(Value::CreateStringValue(path.value()));
- dom_ui_->CallJavascriptFunction(L"window.handleFilePathSelected", results);
+ extensions_service_->LoadExtension(path);
}
void ExtensionsDOMHandler::Observe(NotificationType type,
@@ -459,8 +343,6 @@ std::vector<ExtensionPage> ExtensionsDOMHandler::GetActivePagesForExtension(
}
ExtensionsDOMHandler::~ExtensionsDOMHandler() {
- if (pack_job_.get())
- pack_job_->ClearClient();
}
// ExtensionsDOMHandler, public: -----------------------------------------------
diff --git a/chrome/browser/extensions/extensions_ui.h b/chrome/browser/extensions/extensions_ui.h
index 908c9f3..80ddf4d 100644
--- a/chrome/browser/extensions/extensions_ui.h
+++ b/chrome/browser/extensions/extensions_ui.h
@@ -10,7 +10,6 @@
#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
#include "chrome/browser/dom_ui/dom_ui.h"
-#include "chrome/browser/extensions/pack_extension_job.h"
#include "chrome/browser/shell_dialogs.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
@@ -53,7 +52,6 @@ class ExtensionsUIHTMLSource : public ChromeURLDataManager::DataSource {
class ExtensionsDOMHandler
: public DOMMessageHandler,
public NotificationObserver,
- public PackExtensionJob::Client,
public SelectFileDialog::Listener {
public:
explicit ExtensionsDOMHandler(ExtensionsService* extension_service);
@@ -73,13 +71,13 @@ class ExtensionsDOMHandler
const UserScript& script,
const FilePath& extension_path);
- // ExtensionPackJob::Client
- virtual void OnPackSuccess(const FilePath& crx_file,
- const FilePath& key_file);
-
- virtual void OnPackFailure(const std::wstring& message);
-
private:
+#if defined(OS_WIN)
+ // The implementation of this method is platform-specific and defined
+ // elsewhere.
+ static void ShowPackDialog();
+#endif
+
// Callback for "requestExtensionsData" message.
void HandleRequestExtensionsData(const Value* value);
@@ -104,12 +102,6 @@ class ExtensionsDOMHandler
// Callback for "autoupdate" message.
void HandleAutoUpdateMessage(const Value* value);
- // Utility for calling javascript window.alert in the page.
- void ShowAlert(const std::string& message);
-
- // Callback for "selectFilePath" message.
- void HandleSelectFilePathMessage(const Value* value);
-
// SelectFileDialog::Listener
virtual void FileSelected(const FilePath& path,
int index, void* params);
@@ -134,9 +126,6 @@ class ExtensionsDOMHandler
// Used to pick the directory when loading an extension.
scoped_refptr<SelectFileDialog> load_extension_dialog_;
- // Used to package the extension.
- scoped_refptr<PackExtensionJob> pack_job_;
-
// We monitor changes to the extension system so that we can reload when
// necessary.
NotificationRegistrar registrar_;
diff --git a/chrome/browser/extensions/pack_extension_job.h b/chrome/browser/extensions/pack_extension_job.h
index 8c3cf26..ec00f21 100644
--- a/chrome/browser/extensions/pack_extension_job.h
+++ b/chrome/browser/extensions/pack_extension_job.h
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_EXTENSIONS_PACK_EXTENSION_JOB_UI_H_
-#define CHROME_BROWSER_EXTENSIONS_PACK_EXTENSION_JOB_UI_H_
-
#include <string>
#include "base/file_path.h"
@@ -14,7 +11,7 @@ class MessageLoop;
// Manages packing an extension on the file thread and reporting the result
// back to the UI.
-class PackExtensionJob : public base::RefCountedThreadSafe<PackExtensionJob> {
+class PackExtensionJob : public base::RefCounted<PackExtensionJob> {
public:
// Interface for people who want to use PackExtensionJob to implement.
@@ -49,6 +46,3 @@ class PackExtensionJob : public base::RefCountedThreadSafe<PackExtensionJob> {
DISALLOW_COPY_AND_ASSIGN(PackExtensionJob);
};
-
-#endif // CHROME_BROWSER_EXTENSIONS_PACK_EXTENSION_JOB_UI_H_
-
diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc
index 2918b1f..2c68419 100644
--- a/chrome/browser/net/chrome_url_request_context.cc
+++ b/chrome/browser/net/chrome_url_request_context.cc
@@ -520,8 +520,9 @@ void ChromeURLRequestContext::OnDefaultCharsetChange(
void ChromeURLRequestContext::OnNewExtensions(const std::string& id,
const FilePath& path) {
- if (!is_off_the_record_)
+ if (!is_off_the_record_) {
extension_paths_[id] = path;
+ }
}
void ChromeURLRequestContext::OnUnloadedExtension(const std::string& id) {
diff --git a/chrome/browser/resources/extensions_ui.html b/chrome/browser/resources/extensions_ui.html
index 99076f8..0c9273b 100644
--- a/chrome/browser/resources/extensions_ui.html
+++ b/chrome/browser/resources/extensions_ui.html
@@ -111,87 +111,6 @@ button {
font-size:100%;
}
-#dialogBackground, #dialogBackground div {
- display: -webkit-box;
- -webkit-box-align: center;
-}
-
-#dialog input[type="button"] {
- font-size: 12px;
- height: 25px;
- width: 100px;
-}
-
-#dialog input[type="text"] {
- width: 220px;
- font-size: 12px;
- font-family: Arial, Helvetica, sans-serif;
-}
-
-#dialogBackground {
- background-color: rgba(0, 0, 0, .2);
- display: none;
- height: 100%;
- left: 0;
- position: fixed;
- top: 0;
- width: 100%;
- z-index: 1;
- -webkit-box-orient: vertical;
- -webkit-user-select:none;
-}
-
-#dialogHBackground {
- height: 100%;
- -webkit-box-orient: horizontal;
-}
-
-#dialog {
- background-color: #5296DE;
- border: 1px solid #3A75BD;
- border-radius: 6px 6px;
- font-size: 12px;
- width: 500px;
- -webkit-box-orient: vertical;
-}
-
-#dialogHeader {
- background-color: rgba(0,0,0,0);
- color: white;
- margin: 4px;
- width: 100%;
-}
-
-#dialogBody {
- background-color: rgb(240, 240, 240);
- border: 1px solid #3A75BD;
- border-bottom-left-radius: 4px 4px;
- border-bottom-right-radius: 4px 4px;
- margin: 0px 2px 2px 2px;
- -webkit-box-orient: vertical;
-}
-
-#dialogContentHeader {
- margin: 16px;
-}
-
-.dialogBrowseRow {
- margin-left: -24px;
- width: 100%;
- -webkit-box-orient: horizontal;
- -webkit-box-pack: end;
-}
-
-.dialogBrowseRow>* {
- margin: 2px
-}
-
-#dialogContentFooter {
- margin-bottom: 6px;
- margin-left: -12px;
- margin-top: 20px;
-}
-
</style>
<script>
/**
@@ -345,69 +264,17 @@ function handleUninstallExtension(node) {
}
/**
- * Utility function which asks the C++ to show a platform-specific file select
- * dialog, and fire |callback| with the |filePath| that resulted. |selectType|
- * can be either 'file' or 'folder'. |operation| can be 'load', 'packRoot',
- * or 'pem' which are signals to the C++ to do some operation-specific
- * configuration.
- */
-function showFileDialog(selectType, operation, callback) {
- handleFilePathSelected = function(filePath) {
- callback(filePath);
- handleFilePathSelected = function() {};
- };
-
- chrome.send('selectFilePath', [selectType, operation]);
-}
-
-/**
* Handles the "Load extension..." button being pressed.
*/
function loadExtension() {
- showFileDialog('folder', 'load', function(filePath) {
- chrome.send('load', [String(filePath)]);
- });
+ chrome.send('load', []);
}
/**
* Handles the "Pack extension..." button being pressed.
*/
function packExtension() {
- var extensionPath = document.getElementById('extensionPathText').value;
- var privateKeyPath = document.getElementById('privateKeyPath').value;
- chrome.send('pack', [extensionPath, privateKeyPath]);
-}
-
-/**
- * Shows to modal HTML pack dialog.
- */
-function showPackDialog() {
- document.getElementById('dialogBackground').style.display="-webkit-box";
-}
-
-/**
- * Hides the pack dialog.
- */
-function hidePackDialog() {
- document.getElementById('dialogBackground').style.display="none"
-}
-
-/**
- * Pop up a select dialog to capture the extension path.
- */
-function selectExtensionPath() {
- showFileDialog('folder', 'packRoot', function(filePath) {
- document.getElementById('extensionPathText').value = filePath;
- });
-}
-
-/**
- * Pop up a select dialog to capture the private key path.
- */
-function selectPrivateKeyPath() {
- showFileDialog('file', 'pem', function(filePath) {
- document.getElementById('privateKeyPath').value = filePath;
- });
+ chrome.send('pack', []);
}
/**
@@ -420,55 +287,6 @@ function autoUpdate() {
</script>
</head>
<body onload="requestExtensionsData();">
- <div id="dialogBackground">
- <div id="dialogHBackground">
- <div id="dialog">
- <div id="dialogHeader">
- Pack Extension
- </div>
- <div id="dialogBody">
- <div id="dialogContentHeader" i18n-content="packDialogHeading">
- HEADING
- </div>
- <div class="dialogBrowseRow">
- <div i18n-content="rootDirectoryLabel">
- ROOT_DIR
- </div>
- <div>
- <input type="text" id="extensionPathText">
- </div>
- <div>
- <input type="button" value="BROWSE"
- i18n-values="value:packDialogBrowse"
- onclick="selectExtensionPath();">
- </div>
- </div>
- <div class="dialogBrowseRow">
- <div i18n-content="privateKeyLabel">
- PRIVATE_KEY
- </div>
- <div>
- <input type="text" id="privateKeyPath">
- </div>
- <div>
- <input type="button" value="BROWSE"
- i18n-values="value:packDialogBrowse"
- onclick="selectPrivateKeyPath();">
- </div>
- </div>
- <div class="dialogBrowseRow" id="dialogContentFooter">
- <div>
- <input type="button" value="OK" onclick="packExtension();">
- </div>
- <div>
- <input type="button" value="Cancel" onclick="hidePackDialog();">
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
-
<div id="body-container" style="display:none;">
<div id="header"><h1>About extensions</h1></div>
@@ -538,7 +356,7 @@ function autoUpdate() {
<div class="sidebar-content">
<button onclick="loadExtension()">Load unpacked extension...</button><br />
- <button onclick="showPackDialog()">Pack extension...</button><br />
+ <button onclick="packExtension()">Pack extension...</button><br />
<button onclick="autoUpdate()">Update extensions now</button>
</div>
</td>
diff --git a/chrome/browser/views/extensions/extension_pack_dialog.cc b/chrome/browser/views/extensions/extension_pack_dialog.cc
new file mode 100644
index 0000000..3b66cc7
--- /dev/null
+++ b/chrome/browser/views/extensions/extension_pack_dialog.cc
@@ -0,0 +1,233 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "app/gfx/font.h"
+#include "app/l10n_util.h"
+#include "app/win_util.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/extensions/extensions_ui.h"
+#include "chrome/browser/extensions/pack_extension_job.h"
+#include "chrome/browser/shell_dialogs.h"
+#include "grit/generated_resources.h"
+#include "views/controls/label.h"
+#include "views/controls/button/native_button.h"
+#include "views/controls/textfield/textfield.h"
+#include "views/standard_layout.h"
+#include "views/view.h"
+#include "views/window/dialog_client_view.h"
+#include "views/window/dialog_delegate.h"
+#include "views/window/window.h"
+
+namespace {
+
+// Puts up the the pack dialog, which has this basic layout:
+//
+// Select the extension to pack.
+//
+// Extension root: [ ] [browse]
+// Extension key file: [ ] [browse]
+//
+// [ok] [cancel]
+class PackDialogContent
+ : public views::View,
+ public PackExtensionJob::Client,
+ public SelectFileDialog::Listener,
+ public views::ButtonListener,
+ public views::DialogDelegate {
+ public:
+ PackDialogContent() : ok_button_(NULL) {
+ using views::GridLayout;
+
+ // Setup the layout.
+ views::GridLayout* layout = CreatePanelGridLayout(this);
+ SetLayoutManager(layout);
+
+ views::ColumnSet* columns = layout->AddColumnSet(0);
+ columns->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
+ GridLayout::USE_PREF, 0, 0);
+ columns->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+ columns->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
+ GridLayout::USE_PREF, 0, 0);
+ columns->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+ columns->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
+ GridLayout::USE_PREF, 0, 0);
+
+ layout->StartRow(0, 0);
+ views::Label* heading = new views::Label(
+ l10n_util::GetString(IDS_EXTENSION_PACK_DIALOG_HEADING));
+ heading->SetMultiLine(true);
+ heading->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ layout->AddView(heading, 5, 1, GridLayout::FILL, GridLayout::LEADING);
+
+ layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+
+ layout->StartRow(0, 0);
+ layout->AddView(new views::Label(l10n_util::GetString(
+ IDS_EXTENSION_PACK_DIALOG_ROOT_DIRECTORY_LABEL)));
+ extension_root_textbox_ = new views::Textfield();
+ extension_root_textbox_->set_default_width_in_chars(32);
+ layout->AddView(extension_root_textbox_);
+ extension_root_button_ = new views::NativeButton(this, l10n_util::GetString(
+ IDS_EXTENSION_PACK_DIALOG_BROWSE));
+ layout->AddView(extension_root_button_);
+
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+
+ layout->StartRow(0, 0);
+ layout->AddView(new views::Label(l10n_util::GetString(
+ IDS_EXTENSION_PACK_DIALOG_PRIVATE_KEY_LABEL)));
+ private_key_textbox_ = new views::Textfield();
+ private_key_textbox_->set_default_width_in_chars(32);
+ layout->AddView(private_key_textbox_);
+ private_key_button_ = new views::NativeButton(this, l10n_util::GetString(
+ IDS_EXTENSION_PACK_DIALOG_BROWSE));
+ layout->AddView(private_key_button_);
+ }
+
+ // PackExtensionJob::Client
+ virtual void OnPackSuccess(const FilePath& crx_file,
+ const FilePath& pem_file) {
+ ok_button_->SetEnabled(true);
+ std::wstring message;
+ if (!pem_file.empty()) {
+ message = l10n_util::GetStringF(
+ IDS_EXTENSION_PACK_DIALOG_SUCCESS_BODY_NEW,
+ crx_file.ToWStringHack(),
+ pem_file.ToWStringHack());
+ } else {
+ message = l10n_util::GetStringF(
+ IDS_EXTENSION_PACK_DIALOG_SUCCESS_BODY_UPDATE,
+ crx_file.ToWStringHack());
+ }
+ win_util::MessageBox(GetWindow()->GetNativeWindow(), message,
+ l10n_util::GetString(IDS_EXTENSION_PACK_DIALOG_SUCCESS_TITLE),
+ MB_OK | MB_SETFOREGROUND);
+ GetWindow()->Close();
+ }
+
+ void OnPackFailure(const std::wstring& error) {
+ ok_button_->SetEnabled(true);
+ win_util::MessageBox(GetWindow()->GetNativeWindow(), error,
+ l10n_util::GetString(IDS_EXTENSION_PACK_DIALOG_FAILURE_TITLE),
+ MB_OK | MB_SETFOREGROUND);
+ }
+
+ private:
+ // DialogDelegate
+ virtual bool Accept() {
+ FilePath root_directory = FilePath::FromWStringHack(
+ extension_root_textbox_->text());
+ FilePath key_file = FilePath::FromWStringHack(private_key_textbox_->text());
+
+ if (root_directory.empty()) {
+ if (extension_root_textbox_->text().empty()) {
+ OnPackFailure(l10n_util::GetString(
+ IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_REQUIRED));
+ } else {
+ OnPackFailure(l10n_util::GetString(
+ IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_INVALID));
+ }
+
+ return false;
+ }
+
+ if (!private_key_textbox_->text().empty() && key_file.empty()) {
+ OnPackFailure(l10n_util::GetString(
+ IDS_EXTENSION_PACK_DIALOG_ERROR_KEY_INVALID));
+ return false;
+ }
+
+ pack_job_ = new PackExtensionJob(this, root_directory, key_file,
+ ChromeThread::GetMessageLoop(ChromeThread::FILE));
+
+ // Prevent the dialog from closing because PackExtensionJob is asynchronous.
+ // We need to wait to find out if it succeeded before closing the window.
+ //
+ // Also disable the OK button while this is going so the user understands
+ // that something is happening.
+ views::DialogClientView* dialog = static_cast<views::DialogClientView*>(
+ GetWindow()->GetClientView());
+ ok_button_ = dialog->ok_button();
+ ok_button_->SetEnabled(false);
+ return false;
+ }
+
+ virtual void OnClose() {
+ if (pack_job_)
+ pack_job_->ClearClient();
+ }
+
+ // WindowDelegate
+ virtual std::wstring GetWindowTitle() const {
+ return l10n_util::GetString(IDS_EXTENSION_PACK_DIALOG_TITLE);
+ }
+ virtual views::View* GetContentsView() {
+ return this;
+ }
+
+ // ButtonListener
+ virtual void ButtonPressed(views::Button* sender, const views::Event& event) {
+ file_dialog_ = SelectFileDialog::Create(this);
+
+ if (sender == extension_root_button_) {
+ file_dialog_->SelectFile(SelectFileDialog::SELECT_FOLDER,
+ l10n_util::GetString(IDS_EXTENSION_PACK_DIALOG_SELECT_ROOT),
+ FilePath::FromWStringHack(extension_root_textbox_->text()),
+ NULL, 0, FILE_PATH_LITERAL(""),
+ GetWindow()->GetNativeWindow(),
+ extension_root_textbox_);
+ } else {
+ static SelectFileDialog::FileTypeInfo info;
+ info.extensions.push_back(std::vector<FilePath::StringType>());
+ info.extensions.front().push_back(FILE_PATH_LITERAL("pem"));
+ info.extension_description_overrides.push_back(l10n_util::GetString(
+ IDS_EXTENSION_PACK_DIALOG_KEY_FILE_TYPE_DESCRIPTION));
+ info.include_all_files = true;
+
+ file_dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE,
+ l10n_util::GetString(IDS_EXTENSION_PACK_DIALOG_SELECT_KEY),
+ FilePath::FromWStringHack(private_key_textbox_->text()),
+ &info, 1, FILE_PATH_LITERAL(""),
+ GetWindow()->GetNativeWindow(),
+ private_key_textbox_);
+ }
+ }
+
+ // SelectFileDialog::Listener
+ virtual void MultiFilesSelected(
+ const std::vector<FilePath>& files, void* params) {};
+ virtual void FileSelectionCanceled(void* params) {};
+ virtual void FileSelected(const FilePath& path, int index, void* params) {
+ static_cast<views::Textfield*>(params)->SetText(path.ToWStringHack());
+ }
+
+ views::Textfield* extension_root_textbox_;
+ views::Textfield* private_key_textbox_;
+ views::NativeButton* extension_root_button_;
+ views::NativeButton* private_key_button_;
+ views::NativeButton* ok_button_;
+
+ scoped_refptr<SelectFileDialog> file_dialog_;
+ scoped_refptr<PackExtensionJob> pack_job_;
+
+ DISALLOW_COPY_AND_ASSIGN(PackDialogContent);
+};
+
+} // namespace
+
+// static
+void ExtensionsDOMHandler::ShowPackDialog() {
+ Browser* browser = BrowserList::GetLastActive();
+ if (!browser)
+ return;
+
+ BrowserWindow* window = browser->window();
+ if (!window)
+ return;
+
+ views::Window::CreateChromeWindow(window->GetNativeHandle(),
+ gfx::Rect(400, 0), new PackDialogContent())->Show();
+}
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index e4addf0..5e97e00 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -2098,6 +2098,7 @@
'browser/views/event_utils.cc',
'browser/views/event_utils.h',
'browser/views/extensions/extension_install_prompt.cc',
+ 'browser/views/extensions/extension_pack_dialog.cc',
'browser/views/extensions/extension_popup.cc',
'browser/views/extensions/extension_popup.h',
'browser/views/extensions/extension_shelf.cc',
@@ -2751,6 +2752,11 @@
['exclude', '^browser/tab_contents/tab_contents_view_gtk.h'],
['exclude', '^browser/tab_contents/render_view_context_menu_gtk.cc'],
['exclude', '^browser/tab_contents/render_view_context_menu_gtk.h'],
+ # This compiles but has Linux shared build linking issues due to
+ # missing rsa_private_key functions.
+ ['exclude', '^browser/extensions/extension_creator.cc'],
+ # This compiles but it needs extension_creator.
+ ['exclude', '^browser/extensions/pack_extension_job.cc'],
],
}],
['OS=="linux" and toolkit_views==0', {
@@ -2836,6 +2842,8 @@
'browser/bookmarks/bookmark_menu_controller.h',
'browser/browser_accessibility.cc',
'browser/browser_accessibility_manager.cc',
+ 'browser/extensions/extension_creator.cc',
+ 'browser/extensions/pack_extension_job.cc',
'browser/dom_ui/html_dialog_contents.cc',
'browser/external_tab_container.cc',
'browser/google_update.cc',