1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file.
4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extensions_ui.h"
6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <algorithm>
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/base64.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/callback.h"
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/file_util.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/singleton.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_number_conversions.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_util.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/threading/thread.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/utf_string_conversions.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/version.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/debugger/devtools_manager.h"
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/debugger/devtools_toggle_action.h"
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/crx_installer.h"
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_disabled_infobar_delegate.h"
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_error_reporter.h"
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_function_dispatcher.h"
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_host.h"
25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_message_service.h"
26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_service.h"
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_updater.h"
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/google/google_util.h"
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/prefs/pref_service.h"
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/profiles/profile.h"
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/tab_contents/background_contents.h"
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h"
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/extension.h"
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/extension_icon_set.h"
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/url_pattern.h"
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/user_script.h"
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/jstemplate_builder.h"
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/pref_names.h"
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/url_constants.h"
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/renderer_host/render_process_host.h"
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/renderer_host/render_view_host.h"
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/renderer_host/render_widget_host.h"
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/tab_contents/tab_contents.h"
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/tab_contents/tab_contents_view.h"
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h"
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_type.h"
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "grit/browser_resources.h"
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "grit/chromium_strings.h"
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "grit/generated_resources.h"
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "grit/theme_resources.h"
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/net_util.h"
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/base/l10n/l10n_util.h"
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/base/resource/resource_bundle.h"
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/gfx/codec/png_codec.h"
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/gfx/color_utils.h"
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/gfx/skbitmap_operations.h"
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "webkit/glue/image_decoder.h"
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace {
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ShouldShowExtension(const Extension* extension) {
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Don't show themes since this page's UI isn't really useful for themes.
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (extension->is_theme())
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Don't show component extensions because they are only extensions as an
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // implementation detail of Chrome.
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (extension->location() == Extension::COMPONENT)
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Always show unpacked extensions and apps.
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (extension->location() == Extension::LOAD)
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return true;
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Unless they are unpacked, never show hosted apps.
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (extension->is_hosted_app())
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}  // namespace
83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen////////////////////////////////////////////////////////////////////////////////
85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen//
86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// ExtensionsHTMLSource
87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen//
88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen////////////////////////////////////////////////////////////////////////////////
89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionsUIHTMLSource::ExtensionsUIHTMLSource()
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : DataSource(chrome::kChromeUIExtensionsHost, MessageLoop::current()) {
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsUIHTMLSource::StartDataRequest(const std::string& path,
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                              bool is_incognito,
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                              int request_id) {
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryValue localized_strings;
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("title",
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_TITLE));
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("devModeLink",
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_DEVELOPER_MODE_LINK));
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("devModePrefix",
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_DEVELOPER_MODE_PREFIX));
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("loadUnpackedButton",
105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_UNPACKED_BUTTON));
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("packButton",
107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_PACK_BUTTON));
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("updateButton",
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_UPDATE_BUTTON));
110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("noExtensions",
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_NONE_INSTALLED));
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("suggestGallery",
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringFUTF16(IDS_EXTENSIONS_NONE_INSTALLED_SUGGEST_GALLERY,
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          ASCIIToUTF16("<a href='") +
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              ASCIIToUTF16(google_util::AppendGoogleLocaleParam(
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                  GURL(Extension::ChromeStoreLaunchURL())).spec()) +
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              ASCIIToUTF16("'>"),
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          ASCIIToUTF16("</a>")));
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("getMoreExtensions",
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ASCIIToUTF16("<a href='") +
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ASCIIToUTF16(google_util::AppendGoogleLocaleParam(
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          GURL(Extension::ChromeStoreLaunchURL())).spec()) +
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ASCIIToUTF16("'>") +
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_GET_MORE_EXTENSIONS) +
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ASCIIToUTF16("</a>"));
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("extensionCrashed",
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_CRASHED_EXTENSION));
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("extensionDisabled",
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_DISABLED_EXTENSION));
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("inDevelopment",
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_IN_DEVELOPMENT));
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("viewIncognito",
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_VIEW_INCOGNITO));
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("extensionId",
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_ID));
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("extensionVersion",
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_VERSION));
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("inspectViews",
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_INSPECT_VIEWS));
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("inspectPopupsInstructions",
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_INSPECT_POPUPS_INSTRUCTIONS));
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("disable",
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_DISABLE));
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("enable",
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLE));
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("enableIncognito",
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLE_INCOGNITO));
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("allowFileAccess",
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_ALLOW_FILE_ACCESS));
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("incognitoWarning",
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringFUTF16(IDS_EXTENSIONS_INCOGNITO_WARNING,
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("reload",
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_RELOAD));
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("uninstall",
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_UNINSTALL));
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("options",
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_OPTIONS));
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("packDialogTitle",
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_TITLE));
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("packDialogHeading",
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_HEADING));
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("rootDirectoryLabel",
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          IDS_EXTENSION_PACK_DIALOG_ROOT_DIRECTORY_LABEL));
166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("packDialogBrowse",
167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_BROWSE));
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("privateKeyLabel",
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_PRIVATE_KEY_LABEL));
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("okButton",
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_OK));
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("cancelButton",
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_CANCEL));
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  localized_strings.SetString("showButton",
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_BUTTON));
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SetFontAndTextDirection(&localized_strings);
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static const base::StringPiece extensions_html(
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ResourceBundle::GetSharedInstance().GetRawDataResource(
181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          IDR_EXTENSIONS_UI_HTML));
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string full_html(extensions_html.data(), extensions_html.size());
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  jstemplate_builder::AppendJsonHtml(&localized_strings, &full_html);
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  jstemplate_builder::AppendI18nTemplateSourceHtml(&full_html);
185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  jstemplate_builder::AppendI18nTemplateProcessHtml(&full_html);
186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  jstemplate_builder::AppendJsTemplateSourceHtml(&full_html);
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  html_bytes->data.resize(full_html.size());
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin());
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SendResponse(request_id, html_bytes);
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::string ExtensionsUIHTMLSource::GetMimeType(const std::string&) const {
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return "text/html";
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen////////////////////////////////////////////////////////////////////////////////
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen//
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// ExtensionsDOMHandler::IconLoader
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen//
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen////////////////////////////////////////////////////////////////////////////////
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionsDOMHandler::IconLoader::IconLoader(ExtensionsDOMHandler* handler)
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : handler_(handler) {
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::IconLoader::LoadIcons(
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::vector<ExtensionResource>* icons, DictionaryValue* json) {
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BrowserThread::PostTask(
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      BrowserThread::FILE, FROM_HERE,
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewRunnableMethod(this,
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          &IconLoader::LoadIconsOnFileThread, icons, json));
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::IconLoader::Cancel() {
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  handler_ = NULL;
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::IconLoader::LoadIconsOnFileThread(
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::vector<ExtensionResource>* icons, DictionaryValue* json) {
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<std::vector<ExtensionResource> > icons_deleter(icons);
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<DictionaryValue> json_deleter(json);
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue* extensions = NULL;
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(json->GetList("extensions", &extensions));
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t i = 0; i < icons->size(); ++i) {
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* extension = NULL;
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CHECK(extensions->GetDictionary(static_cast<int>(i), &extension));
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Read the file.
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string file_contents;
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (icons->at(i).relative_path().empty() ||
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        !file_util::ReadFileToString(icons->at(i).GetFilePath(),
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     &file_contents)) {
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // If there's no icon, use the default icon. This is safe to do from
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // the file thread.
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // TODO(erikkay) Assuming we're going to keep showing apps in this list,
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // then we need to figure out when we should use the app default icon.
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      file_contents = ResourceBundle::GetSharedInstance().GetRawDataResource(
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          IDR_EXTENSION_DEFAULT_ICON).as_string();
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // If the extension is disabled, we desaturate the icon to add to the
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // disabledness effect.
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    bool enabled = false;
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CHECK(extension->GetBoolean("enabled", &enabled));
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!enabled) {
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const unsigned char* data =
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          reinterpret_cast<const unsigned char*>(file_contents.data());
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      webkit_glue::ImageDecoder decoder;
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      scoped_ptr<SkBitmap> decoded(new SkBitmap());
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *decoded = decoder.Decode(data, file_contents.length());
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Desaturate the icon and lighten it a bit.
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      color_utils::HSL shift = {-1, 0, 0.6};
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *decoded = SkBitmapOperations::CreateHSLShiftedBitmap(*decoded, shift);
260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      std::vector<unsigned char> output;
262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      gfx::PNGCodec::EncodeBGRASkBitmap(*decoded, false, &output);
263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Lame, but we must make a copy of this now, because base64 doesn't take
265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // the same input type.
266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      file_contents.assign(reinterpret_cast<char*>(&output.front()),
267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           output.size());
268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Create a data URL (all icons are converted to PNGs during unpacking).
271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string base64_encoded;
272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::Base64Encode(file_contents, &base64_encoded);
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    GURL icon_url("data:image/png;base64," + base64_encoded);
274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extension->SetString("icon", icon_url.spec());
276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BrowserThread::PostTask(
279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      BrowserThread::UI, FROM_HERE,
280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewRunnableMethod(this, &IconLoader::ReportResultOnUIThread,
281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                        json_deleter.release()));
282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::IconLoader::ReportResultOnUIThread(
285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* json) {
286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (handler_)
287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    handler_->OnIconsLoaded(json);
288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen///////////////////////////////////////////////////////////////////////////////
292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen//
293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// ExtensionsDOMHandler
294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen//
295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen///////////////////////////////////////////////////////////////////////////////
296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionsDOMHandler::ExtensionsDOMHandler(ExtensionService* extension_service)
298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : extensions_service_(extension_service),
299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ignore_notifications_(false),
300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      deleting_rvh_(NULL) {
301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::RegisterMessages() {
304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("requestExtensionsData",
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandleRequestExtensionsData));
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("toggleDeveloperMode",
307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandleToggleDeveloperMode));
308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("inspect",
309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandleInspectMessage));
310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("reload",
311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandleReloadMessage));
312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("enable",
313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandleEnableMessage));
314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("enableIncognito",
315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandleEnableIncognitoMessage));
316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("allowFileAccess",
317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandleAllowFileAccessMessage));
318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("uninstall",
319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandleUninstallMessage));
320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("options",
321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandleOptionsMessage));
322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("showButton",
323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandleShowButtonMessage));
324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("load",
325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandleLoadMessage));
326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("pack",
327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandlePackMessage));
328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("autoupdate",
329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandleAutoUpdateMessage));
330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->RegisterMessageCallback("selectFilePath",
331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewCallback(this, &ExtensionsDOMHandler::HandleSelectFilePathMessage));
332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandleRequestExtensionsData(const ListValue* args) {
335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryValue* results = new DictionaryValue();
336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Add the extensions to the results structure.
338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue *extensions_list = new ListValue();
339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Stores the icon resource for each of the extensions in extensions_list. We
341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // build up a list of them here, then load them on the file thread in
342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // ::LoadIcons().
343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::vector<ExtensionResource>* extension_icons =
344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      new std::vector<ExtensionResource>();
345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const ExtensionList* extensions = extensions_service_->extensions();
347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (ExtensionList::const_iterator extension = extensions->begin();
348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       extension != extensions->end(); ++extension) {
349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (ShouldShowExtension(*extension)) {
350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extensions_list->Append(CreateExtensionDetailValue(
351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          extensions_service_.get(),
352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          *extension,
353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          GetActivePagesForExtension(*extension),
354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          true, false));  // enabled, terminated
355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extension_icons->push_back(PickExtensionIcon(*extension));
356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extensions = extensions_service_->disabled_extensions();
359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (ExtensionList::const_iterator extension = extensions->begin();
360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       extension != extensions->end(); ++extension) {
361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (ShouldShowExtension(*extension)) {
362ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extensions_list->Append(CreateExtensionDetailValue(
363ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          extensions_service_.get(),
364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          *extension,
365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          GetActivePagesForExtension(*extension),
366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          false, false));  // enabled, terminated
367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extension_icons->push_back(PickExtensionIcon(*extension));
368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extensions = extensions_service_->terminated_extensions();
371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::vector<ExtensionPage> empty_pages;
372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (ExtensionList::const_iterator extension = extensions->begin();
373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       extension != extensions->end(); ++extension) {
374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (ShouldShowExtension(*extension)) {
375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extensions_list->Append(CreateExtensionDetailValue(
376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          extensions_service_.get(),
377ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          *extension,
378ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          empty_pages,  // Terminated process has no active pages.
379ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          false, true));  // enabled, terminated
380ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extension_icons->push_back(PickExtensionIcon(*extension));
381ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
382ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
383ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  results->Set("extensions", extensions_list);
384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
385ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool developer_mode = web_ui_->GetProfile()->GetPrefs()
386ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ->GetBoolean(prefs::kExtensionsUIDeveloperMode);
387ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  results->SetBoolean("developerMode", developer_mode);
388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (icon_loader_.get())
390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    icon_loader_->Cancel();
391ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
392ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  icon_loader_ = new IconLoader(this);
393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  icon_loader_->LoadIcons(extension_icons, results);
394ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
396ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::OnIconsLoaded(DictionaryValue* json) {
397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->CallJavascriptFunction(L"returnExtensionsData", *json);
398ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  delete json;
399ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
400ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Register for notifications that we need to reload the page.
401ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  registrar_.RemoveAll();
402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  registrar_.Add(this, NotificationType::EXTENSION_LOADED,
403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationService::AllSources());
404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  registrar_.Add(this, NotificationType::EXTENSION_PROCESS_CREATED,
405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationService::AllSources());
406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationService::AllSources());
408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  registrar_.Add(this, NotificationType::EXTENSION_UPDATE_DISABLED,
409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationService::AllSources());
410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  registrar_.Add(this, NotificationType::EXTENSION_FUNCTION_DISPATCHER_CREATED,
411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationService::AllSources());
412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  registrar_.Add(this,
413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationType::EXTENSION_FUNCTION_DISPATCHER_DESTROYED,
414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationService::AllSources());
415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  registrar_.Add(this,
416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationType::NAV_ENTRY_COMMITTED,
417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationService::AllSources());
418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  registrar_.Add(this,
419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationType::RENDER_VIEW_HOST_DELETED,
420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationService::AllSources());
421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  registrar_.Add(this,
422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationType::BACKGROUND_CONTENTS_NAVIGATED,
423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationService::AllSources());
424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  registrar_.Add(this,
425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationType::BACKGROUND_CONTENTS_DELETED,
426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationService::AllSources());
427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  registrar_.Add(this,
428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationType::EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED,
429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NotificationService::AllSources());
430ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionResource ExtensionsDOMHandler::PickExtensionIcon(
433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const Extension* extension) {
434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return extension->GetIconResource(Extension::EXTENSION_ICON_MEDIUM,
435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                    ExtensionIconSet::MATCH_BIGGER);
436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionUninstallDialog* ExtensionsDOMHandler::GetExtensionUninstallDialog() {
439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!extension_uninstall_dialog_.get()) {
440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extension_uninstall_dialog_.reset(
441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        new ExtensionUninstallDialog(web_ui_->GetProfile()));
442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
443ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return extension_uninstall_dialog_.get();
444ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
446ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandleToggleDeveloperMode(const ListValue* args) {
447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool developer_mode = web_ui_->GetProfile()->GetPrefs()
448ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ->GetBoolean(prefs::kExtensionsUIDeveloperMode);
449ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->GetProfile()->GetPrefs()->SetBoolean(
450ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      prefs::kExtensionsUIDeveloperMode, !developer_mode);
451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
452ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
453ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandleInspectMessage(const ListValue* args) {
454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string render_process_id_str;
455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string render_view_id_str;
456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int render_process_id;
457ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int render_view_id;
458ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetSize() == 2);
459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetString(0, &render_process_id_str));
460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetString(1, &render_view_id_str));
461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(base::StringToInt(render_process_id_str, &render_process_id));
462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(base::StringToInt(render_view_id_str, &render_view_id));
463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  RenderViewHost* host = RenderViewHost::FromID(render_process_id,
464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                render_view_id);
465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!host) {
466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // This can happen if the host has gone away since the page was displayed.
467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
468ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
469ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
470ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DevToolsManager::GetInstance()->OpenDevToolsWindow(host);
471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
473ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandleReloadMessage(const ListValue* args) {
474ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string extension_id = WideToASCII(ExtractStringValue(args));
475ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(!extension_id.empty());
476ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extensions_service_->ReloadExtension(extension_id);
477ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
478ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandleEnableMessage(const ListValue* args) {
480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetSize() == 2);
481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string extension_id, enable_str;
482ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetString(0, &extension_id));
483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetString(1, &enable_str));
484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (enable_str == "true") {
485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ExtensionPrefs* prefs = extensions_service_->extension_prefs();
486ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (prefs->DidExtensionEscalatePermissions(extension_id)) {
487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const Extension* extension =
488ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          extensions_service_->GetExtensionById(extension_id, true);
489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ShowExtensionDisabledDialog(extensions_service_,
490ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  web_ui_->GetProfile(), extension);
491ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else {
492ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extensions_service_->EnableExtension(extension_id);
493ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
494ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
495ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extensions_service_->DisableExtension(extension_id);
496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandleEnableIncognitoMessage(const ListValue* args) {
500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetSize() == 2);
501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string extension_id, enable_str;
502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetString(0, &extension_id));
503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetString(1, &enable_str));
504ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const Extension* extension =
505ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extensions_service_->GetExtensionById(extension_id, true);
506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(extension);
507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Flipping the incognito bit will generate unload/load notifications for the
509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // extension, but we don't want to reload the page, because a) we've already
510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // updated the UI to reflect the change, and b) we want the yellow warning
511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // text to stay until the user has left the page.
512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  //
513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(aa): This creates crapiness in some cases. For example, in a main
514ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // window, when toggling this, the browser action will flicker because it gets
515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // unloaded, then reloaded. It would be better to have a dedicated
516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // notification for this case.
517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  //
518ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Bug: http://crbug.com/41384
519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ignore_notifications_ = true;
520ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extensions_service_->SetIsIncognitoEnabled(extension, enable_str == "true");
521ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ignore_notifications_ = false;
522ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
523ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandleAllowFileAccessMessage(const ListValue* args) {
525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetSize() == 2);
526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string extension_id, allow_str;
527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetString(0, &extension_id));
528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetString(1, &allow_str));
529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const Extension* extension =
530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extensions_service_->GetExtensionById(extension_id, true);
531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(extension);
532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extensions_service_->SetAllowFileAccess(extension, allow_str == "true");
534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandleUninstallMessage(const ListValue* args) {
537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string extension_id = WideToASCII(ExtractStringValue(args));
538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(!extension_id.empty());
539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const Extension* extension =
540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extensions_service_->GetExtensionById(extension_id, true);
541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!extension)
542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extension = extensions_service_->GetTerminatedExtension(extension_id);
543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!extension)
544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!extension_id_prompting_.empty())
547ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;  // Only one prompt at a time.
548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_id_prompting_ = extension_id;
550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GetExtensionUninstallDialog()->ConfirmUninstall(this, extension);
552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::ExtensionDialogAccepted() {
555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!extension_id_prompting_.empty());
556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
557ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool was_terminated = false;
558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // The extension can be uninstalled in another window while the UI was
560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // showing. Do nothing in that case.
561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const Extension* extension =
562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extensions_service_->GetExtensionById(extension_id_prompting_, true);
563ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!extension) {
564ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extension = extensions_service_->GetTerminatedExtension(
565ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        extension_id_prompting_);
566ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    was_terminated = true;
567ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
568ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!extension)
569ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
571ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extensions_service_->UninstallExtension(extension_id_prompting_,
572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                          false /* external_uninstall */, NULL);
573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_id_prompting_ = "";
574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // There will be no EXTENSION_UNLOADED notification for terminated
576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // extensions as they were already unloaded.
577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (was_terminated)
578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    HandleRequestExtensionsData(NULL);
579ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
580ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::ExtensionDialogCanceled() {
582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_id_prompting_ = "";
583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
585ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandleOptionsMessage(const ListValue* args) {
586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const Extension* extension = GetExtension(args);
587ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!extension || extension->options_url().is_empty())
588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->GetProfile()->GetExtensionProcessManager()->OpenOptionsPage(
590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extension, NULL);
591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandleShowButtonMessage(const ListValue* args) {
594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const Extension* extension = GetExtension(args);
595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extensions_service_->SetBrowserActionVisibility(extension, true);
596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandleLoadMessage(const ListValue* args) {
599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FilePath::StringType string_path;
600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetSize() == 1) << args->GetSize();
601ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetString(0, &string_path));
602ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extensions_service_->LoadExtension(FilePath(string_path));
603ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
604ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
605ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::ShowAlert(const std::string& message) {
606ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue arguments;
607ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  arguments.Append(Value::CreateStringValue(message));
608ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->CallJavascriptFunction(L"alert", arguments);
609ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
610ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
611ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandlePackMessage(const ListValue* args) {
612ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string extension_path;
613ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string private_key_path;
614ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetSize() == 2);
615ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetString(0, &extension_path));
616ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetString(1, &private_key_path));
617ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
618ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FilePath root_directory =
619ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      FilePath::FromWStringHack(UTF8ToWide(extension_path));
620ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FilePath key_file = FilePath::FromWStringHack(UTF8ToWide(private_key_path));
621ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
622ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (root_directory.empty()) {
623ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (extension_path.empty()) {
624ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ShowAlert(l10n_util::GetStringUTF8(
625ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_REQUIRED));
626ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else {
627ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ShowAlert(l10n_util::GetStringUTF8(
628ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_INVALID));
629ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
630ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
631ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
632ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
633ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
634ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!private_key_path.empty() && key_file.empty()) {
635ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ShowAlert(l10n_util::GetStringUTF8(
636ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        IDS_EXTENSION_PACK_DIALOG_ERROR_KEY_INVALID));
637ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
638ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
639ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
640ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  pack_job_ = new PackExtensionJob(this, root_directory, key_file);
641ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  pack_job_->Start();
642ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
643ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
644ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::OnPackSuccess(const FilePath& crx_file,
645ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                         const FilePath& pem_file) {
646ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ShowAlert(UTF16ToUTF8(PackExtensionJob::StandardSuccessMessage(crx_file,
647ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                                 pem_file)));
648ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
649ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue results;
650ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->CallJavascriptFunction(L"hidePackDialog", results);
651ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
652ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
653ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::OnPackFailure(const std::string& error) {
654ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ShowAlert(error);
655ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
656ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
657ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandleAutoUpdateMessage(const ListValue* args) {
658ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExtensionUpdater* updater = extensions_service_->updater();
659ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (updater)
660ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    updater->CheckNow();
661ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
662ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
663ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::HandleSelectFilePathMessage(const ListValue* args) {
664ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string select_type;
665ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string operation;
666ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetSize() == 2);
667ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetString(0, &select_type));
668ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(args->GetString(1, &operation));
669ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
670ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SelectFileDialog::Type type = SelectFileDialog::SELECT_FOLDER;
671ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static SelectFileDialog::FileTypeInfo info;
672ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int file_type_index = 0;
673ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (select_type == "file")
674ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    type = SelectFileDialog::SELECT_OPEN_FILE;
675ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
676ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  string16 select_title;
677ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (operation == "load") {
678ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    select_title = l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY);
679ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (operation == "packRoot") {
680ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    select_title = l10n_util::GetStringUTF16(
681ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        IDS_EXTENSION_PACK_DIALOG_SELECT_ROOT);
682ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (operation == "pem") {
683ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    select_title = l10n_util::GetStringUTF16(
684ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        IDS_EXTENSION_PACK_DIALOG_SELECT_KEY);
685ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    info.extensions.push_back(std::vector<FilePath::StringType>());
686ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        info.extensions.front().push_back(FILE_PATH_LITERAL("pem"));
687ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        info.extension_description_overrides.push_back(
688ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            l10n_util::GetStringUTF16(
689ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                IDS_EXTENSION_PACK_DIALOG_KEY_FILE_TYPE_DESCRIPTION));
690ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        info.include_all_files = true;
691ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    file_type_index = 1;
692ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
693ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
694ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
695ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
696ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
697ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  load_extension_dialog_ = SelectFileDialog::Create(this);
698ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  load_extension_dialog_->SelectFile(type, select_title, FilePath(), &info,
699ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      file_type_index, FILE_PATH_LITERAL(""), web_ui_->tab_contents(),
700ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
701ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
702ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
703ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
704ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::FileSelected(const FilePath& path, int index,
705ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                        void* params) {
706ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Add the extensions to the results structure.
707ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue results;
708ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  results.Append(Value::CreateStringValue(path.value()));
709ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->CallJavascriptFunction(L"window.handleFilePathSelected", results);
710ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
711ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
712ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::MultiFilesSelected(
713ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::vector<FilePath>& files, void* params) {
714ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  NOTREACHED();
715ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
716ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
717ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::Observe(NotificationType type,
718ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   const NotificationSource& source,
719ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   const NotificationDetails& details) {
720ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  switch (type.value) {
721ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // We listen for notifications that will result in the page being
722ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // repopulated with data twice for the same event in certain cases.
723ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // For instance, EXTENSION_LOADED & EXTENSION_PROCESS_CREATED because
724ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // we don't know about the views for an extension at EXTENSION_LOADED, but
725ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // if we only listen to EXTENSION_PROCESS_CREATED, we'll miss extensions
726ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // that don't have a process at startup. Similarly, NAV_ENTRY_COMMITTED &
727ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // EXTENSION_FUNCTION_DISPATCHER_CREATED because we want to handle both
728ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // the case of live app pages (which don't have an EFD) and
729ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // chrome-extension:// urls which are served in a TabContents.
730ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    //
731ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Doing it this way gets everything but causes the page to be rendered
732ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // more than we need. It doesn't seem to result in any noticeable flicker.
733ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case NotificationType::RENDER_VIEW_HOST_DELETED:
734ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      deleting_rvh_ = Details<RenderViewHost>(details).ptr();
735ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      MaybeUpdateAfterNotification();
736ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
737ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case NotificationType::BACKGROUND_CONTENTS_DELETED:
738ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      deleting_rvh_ = Details<BackgroundContents>(details)->render_view_host();
739ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      MaybeUpdateAfterNotification();
740ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
741ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case NotificationType::EXTENSION_LOADED:
742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case NotificationType::EXTENSION_PROCESS_CREATED:
743ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case NotificationType::EXTENSION_UNLOADED:
744ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case NotificationType::EXTENSION_UPDATE_DISABLED:
745ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case NotificationType::EXTENSION_FUNCTION_DISPATCHER_CREATED:
746ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case NotificationType::EXTENSION_FUNCTION_DISPATCHER_DESTROYED:
747ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case NotificationType::NAV_ENTRY_COMMITTED:
748ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case NotificationType::BACKGROUND_CONTENTS_NAVIGATED:
749ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case NotificationType::EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED:
750ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      MaybeUpdateAfterNotification();
751ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
752ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    default:
753ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NOTREACHED();
754ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
755ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
756ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
757ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst Extension* ExtensionsDOMHandler::GetExtension(const ListValue* args) {
758ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string extension_id = WideToASCII(ExtractStringValue(args));
759ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CHECK(!extension_id.empty());
760ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return extensions_service_->GetExtensionById(extension_id, true);
761ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
762ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
763ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::MaybeUpdateAfterNotification() {
764ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!ignore_notifications_ && web_ui_->tab_contents())
765ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    HandleRequestExtensionsData(NULL);
766ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  deleting_rvh_ = NULL;
767ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
768ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
769ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Static
770ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDictionaryValue* ExtensionsDOMHandler::CreateExtensionDetailValue(
771ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ExtensionService* service, const Extension* extension,
772ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::vector<ExtensionPage>& pages, bool enabled, bool terminated) {
773ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryValue* extension_data = new DictionaryValue();
774ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
775ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->SetString("id", extension->id());
776ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->SetString("name", extension->name());
777ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->SetString("description", extension->description());
778ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->SetString("version", extension->version()->GetString());
779ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->SetBoolean("enabled", enabled);
780ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->SetBoolean("terminated", terminated);
781ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->SetBoolean("enabledIncognito",
782ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      service ? service->IsIncognitoEnabled(extension) : false);
783ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->SetBoolean("wantsFileAccess", extension->wants_file_access());
784ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->SetBoolean("allowFileAccess",
785ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      service ? service->AllowFileAccess(extension) : false);
786ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->SetBoolean("allow_reload",
787ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             extension->location() == Extension::LOAD);
788ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->SetBoolean("is_hosted_app", extension->is_hosted_app());
789ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
790ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Determine the sort order: Extensions loaded through --load-extensions show
791ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // up at the top. Disabled extensions show up at the bottom.
792ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (extension->location() == Extension::LOAD)
793ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extension_data->SetInteger("order", 1);
794ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  else
795ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extension_data->SetInteger("order", 2);
796ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
797ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!extension->options_url().is_empty())
798ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extension_data->SetString("options_url", extension->options_url().spec());
799ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
800ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (service && !service->GetBrowserActionVisibility(extension))
801ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extension_data->SetBoolean("enable_show_button", true);
802ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
803ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Add views
804ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ListValue* views = new ListValue;
805ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (std::vector<ExtensionPage>::const_iterator iter = pages.begin();
806ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       iter != pages.end(); ++iter) {
807ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* view_value = new DictionaryValue;
808ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (iter->url.scheme() == chrome::kExtensionScheme) {
809ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // No leading slash.
810ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      view_value->SetString("path", iter->url.path().substr(1));
811ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else {
812ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // For live pages, use the full URL.
813ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      view_value->SetString("path", iter->url.spec());
814ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
815ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    view_value->SetInteger("renderViewId", iter->render_view_id);
816ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    view_value->SetInteger("renderProcessId", iter->render_process_id);
817ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    view_value->SetBoolean("incognito", iter->incognito);
818ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    views->Append(view_value);
819ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
820ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->Set("views", views);
821ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->SetBoolean("hasPopupAction",
822ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extension->browser_action() || extension->page_action());
823ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extension_data->SetString("homepageUrl", extension->GetHomepageURL().spec());
824ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
825ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return extension_data;
826ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
827ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
828ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::vector<ExtensionPage> ExtensionsDOMHandler::GetActivePagesForExtension(
829ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const Extension* extension) {
830ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::vector<ExtensionPage> result;
831ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
832ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Get the extension process's active views.
833ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExtensionProcessManager* process_manager =
834ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extensions_service_->profile()->GetExtensionProcessManager();
835ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GetActivePagesForExtensionProcess(
836ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      process_manager->GetExtensionProcess(extension->url()),
837ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extension, &result);
838ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
839ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Repeat for the incognito process, if applicable.
840ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (extensions_service_->profile()->HasOffTheRecordProfile() &&
841ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extension->incognito_split_mode()) {
842ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ExtensionProcessManager* process_manager =
843ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        extensions_service_->profile()->GetOffTheRecordProfile()->
844ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            GetExtensionProcessManager();
845ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    GetActivePagesForExtensionProcess(
846ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        process_manager->GetExtensionProcess(extension->url()),
847ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        extension, &result);
848ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
849ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
850ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return result;
851ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
852ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
853ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsDOMHandler::GetActivePagesForExtensionProcess(
854ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    RenderProcessHost* process,
855ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const Extension* extension,
856ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::vector<ExtensionPage> *result) {
857ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!process)
858ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
859ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
860ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  RenderProcessHost::listeners_iterator iter = process->ListenersIterator();
861ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (; !iter.IsAtEnd(); iter.Advance()) {
862ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const RenderWidgetHost* widget =
863ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        static_cast<const RenderWidgetHost*>(iter.GetCurrentValue());
864ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK(widget);
865ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!widget || !widget->IsRenderView())
866ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      continue;
867ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const RenderViewHost* host = static_cast<const RenderViewHost*>(widget);
868ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (host == deleting_rvh_ ||
869ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ViewType::EXTENSION_POPUP == host->delegate()->GetRenderViewType())
870ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      continue;
871ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
872ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    GURL url = host->delegate()->GetURL();
873ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (url.SchemeIs(chrome::kExtensionScheme)) {
874ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (url.host() != extension->id())
875ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        continue;
876ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else if (!extension->web_extent().ContainsURL(url)) {
877ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      continue;
878ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
879ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
880ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result->push_back(ExtensionPage(url, process->id(), host->routing_id(),
881ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                    process->profile()->IsOffTheRecord()));
882ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
883ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
884ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
885ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionsDOMHandler::~ExtensionsDOMHandler() {
886ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // There may be pending file dialogs, we need to tell them that we've gone
887ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // away so they don't try and call back to us.
888ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (load_extension_dialog_.get())
889ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    load_extension_dialog_->ListenerDestroyed();
890ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
891ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (pack_job_.get())
892ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    pack_job_->ClearClient();
893ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
894ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (icon_loader_.get())
895ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    icon_loader_->Cancel();
896ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
897ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
898ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// ExtensionsDOMHandler, public: -----------------------------------------------
899ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
900ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionsUI::ExtensionsUI(TabContents* contents) : WebUI(contents) {
901ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExtensionService *exstension_service =
902ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      GetProfile()->GetOriginalProfile()->GetExtensionService();
903ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
904ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExtensionsDOMHandler* handler = new ExtensionsDOMHandler(exstension_service);
905ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  AddMessageHandler(handler);
906ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  handler->Attach(this);
907ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
908ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExtensionsUIHTMLSource* html_source = new ExtensionsUIHTMLSource();
909ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
910ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Set up the chrome://extensions/ source.
911ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
912ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
913ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
914ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
915ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenRefCountedMemory* ExtensionsUI::GetFaviconResourceBytes() {
916ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return ResourceBundle::GetSharedInstance().
917ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      LoadDataResourceBytes(IDR_PLUGIN);
918ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
919ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
920ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
921ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionsUI::RegisterUserPrefs(PrefService* prefs) {
922ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  prefs->RegisterBooleanPref(prefs::kExtensionsUIDeveloperMode, false);
923ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
924