OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_install_ui.h" | 5 #include "chrome/browser/extensions/extension_install_ui.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "app/l10n_util.h" | 9 #include "app/l10n_util.h" |
10 #include "app/resource_bundle.h" | 10 #include "app/resource_bundle.h" |
11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
12 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
| 13 #include "base/utf_string_conversions.h" |
13 #include "chrome/browser/browser_list.h" | 14 #include "chrome/browser/browser_list.h" |
14 #include "chrome/browser/browser_window.h" | 15 #include "chrome/browser/browser_window.h" |
15 #include "chrome/browser/extensions/theme_installed_infobar_delegate.h" | 16 #include "chrome/browser/extensions/theme_installed_infobar_delegate.h" |
16 #include "chrome/browser/profile.h" | 17 #include "chrome/browser/profile.h" |
17 #include "chrome/browser/tab_contents/tab_contents.h" | 18 #include "chrome/browser/tab_contents/tab_contents.h" |
18 #include "chrome/common/extensions/extension.h" | 19 #include "chrome/common/extensions/extension.h" |
19 #include "grit/browser_resources.h" | 20 #include "grit/browser_resources.h" |
20 #include "grit/chromium_strings.h" | 21 #include "grit/chromium_strings.h" |
21 #include "grit/generated_resources.h" | 22 #include "grit/generated_resources.h" |
22 | 23 |
23 #if defined(OS_WIN) | 24 #if defined(TOOLKIT_GTK) |
24 #include "app/win_util.h" | |
25 #elif defined(OS_MACOSX) | |
26 #include "base/scoped_cftyperef.h" | |
27 #include "base/sys_string_conversions.h" | |
28 #include <CoreFoundation/CFUserNotification.h> | |
29 #elif defined(TOOLKIT_GTK) | |
30 #include "chrome/browser/extensions/gtk_theme_installed_infobar_delegate.h" | 25 #include "chrome/browser/extensions/gtk_theme_installed_infobar_delegate.h" |
31 #include "chrome/browser/gtk/gtk_theme_provider.h" | 26 #include "chrome/browser/gtk/gtk_theme_provider.h" |
32 #endif | 27 #endif |
33 | 28 |
34 namespace { | 29 namespace { |
35 | 30 |
36 #if defined(OS_WIN) || defined(TOOLKIT_GTK) | |
37 | |
38 static std::wstring GetInstallWarning(Extension* extension) { | 31 static std::wstring GetInstallWarning(Extension* extension) { |
39 // If the extension has a plugin, it's easy: the plugin has the most severe | 32 // If the extension has a plugin, it's easy: the plugin has the most severe |
40 // warning. | 33 // warning. |
41 if (!extension->plugins().empty()) | 34 if (!extension->plugins().empty()) |
42 return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_NEW_FULL_ACCESS); | 35 return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_NEW_FULL_ACCESS); |
43 | 36 |
44 // Otherwise, we go in descending order of severity: all hosts, several hosts, | 37 // Otherwise, we go in descending order of severity: all hosts, several hosts, |
45 // a single host, no hosts. For each of these, we also have a variation of the | 38 // a single host, no hosts. For each of these, we also have a variation of the |
46 // message for when api permissions are also requested. | 39 // message for when api permissions are also requested. |
47 if (extension->HasAccessToAllHosts()) { | 40 if (extension->HasAccessToAllHosts()) { |
(...skipping 25 matching lines...) Expand all Loading... |
73 UTF8ToWide(*hosts.begin())); | 66 UTF8ToWide(*hosts.begin())); |
74 } | 67 } |
75 | 68 |
76 DCHECK(hosts.size() == 0); | 69 DCHECK(hosts.size() == 0); |
77 if (extension->api_permissions().empty()) | 70 if (extension->api_permissions().empty()) |
78 return L""; | 71 return L""; |
79 else | 72 else |
80 return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_NEW_BROWSER); | 73 return l10n_util::GetString(IDS_EXTENSION_PROMPT_WARNING_NEW_BROWSER); |
81 } | 74 } |
82 | 75 |
83 #endif | |
84 | |
85 } // namespace | 76 } // namespace |
86 | 77 |
87 ExtensionInstallUI::ExtensionInstallUI(Profile* profile) | 78 ExtensionInstallUI::ExtensionInstallUI(Profile* profile) |
88 : profile_(profile), ui_loop_(MessageLoop::current()) | 79 : profile_(profile), ui_loop_(MessageLoop::current()) |
89 #if defined(TOOLKIT_GTK) | 80 #if defined(TOOLKIT_GTK) |
90 ,previous_use_gtk_theme_(false) | 81 ,previous_use_gtk_theme_(false) |
91 #endif | 82 #endif |
92 { | 83 {} |
93 } | |
94 | 84 |
95 void ExtensionInstallUI::ConfirmInstall(Delegate* delegate, | 85 void ExtensionInstallUI::ConfirmInstall(Delegate* delegate, |
96 Extension* extension, | 86 Extension* extension, |
97 SkBitmap* install_icon) { | 87 SkBitmap* install_icon) { |
98 DCHECK(ui_loop_ == MessageLoop::current()); | 88 DCHECK(ui_loop_ == MessageLoop::current()); |
99 | 89 |
100 // We special-case themes to not show any confirm UI. Instead they are | 90 // We special-case themes to not show any confirm UI. Instead they are |
101 // immediately installed, and then we show an infobar (see OnInstallSuccess) | 91 // immediately installed, and then we show an infobar (see OnInstallSuccess) |
102 // to allow the user to revert if they don't like it. | 92 // to allow the user to revert if they don't like it. |
103 if (extension->IsTheme()) { | 93 if (extension->IsTheme()) { |
104 // Remember the current theme in case the user pressed undo. | 94 // Remember the current theme in case the user pressed undo. |
105 Extension* previous_theme = profile_->GetTheme(); | 95 Extension* previous_theme = profile_->GetTheme(); |
106 if (previous_theme) | 96 if (previous_theme) |
107 previous_theme_id_ = previous_theme->id(); | 97 previous_theme_id_ = previous_theme->id(); |
108 | 98 |
109 #if defined(TOOLKIT_GTK) | 99 #if defined(TOOLKIT_GTK) |
110 // On linux, we also need to take the user's system settings into account | 100 // On linux, we also need to take the user's system settings into account |
111 // to undo theme installation. | 101 // to undo theme installation. |
112 previous_use_gtk_theme_ = | 102 previous_use_gtk_theme_ = |
113 GtkThemeProvider::GetFrom(profile_)->UseGtkTheme(); | 103 GtkThemeProvider::GetFrom(profile_)->UseGtkTheme(); |
114 #endif | 104 #endif |
115 | 105 |
116 delegate->ContinueInstall(); | 106 delegate->ContinueInstall(); |
117 return; | 107 return; |
118 } | 108 } |
119 | 109 |
120 #if defined(OS_WIN) || defined(TOOLKIT_GTK) | |
121 if (!install_icon) { | 110 if (!install_icon) { |
122 install_icon = ResourceBundle::GetSharedInstance().GetBitmapNamed( | 111 install_icon = ResourceBundle::GetSharedInstance().GetBitmapNamed( |
123 IDR_DEFAULT_EXTENSION_ICON_128); | 112 IDR_DEFAULT_EXTENSION_ICON_128); |
124 } | 113 } |
125 | 114 |
126 ShowExtensionInstallPrompt(profile_, delegate, extension, install_icon, | 115 ShowExtensionInstallPrompt(profile_, delegate, extension, install_icon, |
127 GetInstallWarning(extension)); | 116 GetInstallWarning(extension)); |
128 | 117 |
129 #elif defined(OS_MACOSX) | |
130 // TODO(port): Implement nicer UI. | |
131 // Using CoreFoundation to do this dialog is unimaginably lame but will do | |
132 // until the UI is redone. | |
133 scoped_cftyperef<CFStringRef> confirm_title(base::SysWideToCFStringRef( | |
134 l10n_util::GetString(IDS_EXTENSION_PROMPT_TITLE))); | |
135 | |
136 // Build the confirmation prompt, including a heading, a random humorous | |
137 // warning, and a severe warning. | |
138 const string16& confirm_format(ASCIIToUTF16("$1\n\n$2\n\n$3")); | |
139 std::vector<string16> subst; | |
140 subst.push_back(l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_HEADING, | |
141 UTF8ToUTF16(extension->name()))); | |
142 string16 warnings[] = { | |
143 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_1), | |
144 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_2), | |
145 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_3) | |
146 }; | |
147 subst.push_back(warnings[base::RandInt(0, arraysize(warnings) - 1)]); | |
148 subst.push_back(l10n_util::GetStringUTF16( | |
149 IDS_EXTENSION_PROMPT_WARNING_SEVERE)); | |
150 scoped_cftyperef<CFStringRef> confirm_prompt(base::SysUTF16ToCFStringRef( | |
151 ReplaceStringPlaceholders(confirm_format, subst, NULL))); | |
152 | |
153 scoped_cftyperef<CFStringRef> confirm_cancel(base::SysWideToCFStringRef( | |
154 l10n_util::GetString(IDS_EXTENSION_PROMPT_CANCEL_BUTTON))); | |
155 | |
156 CFOptionFlags response; | |
157 CFUserNotificationDisplayAlert( | |
158 0, kCFUserNotificationCautionAlertLevel, | |
159 NULL, // TODO(port): show the install_icon instead of a default. | |
160 NULL, NULL, // Sound URL, localization URL. | |
161 confirm_title, | |
162 confirm_prompt, | |
163 NULL, // Default button. | |
164 confirm_cancel, | |
165 NULL, // Other button. | |
166 &response); | |
167 if (response == kCFUserNotificationAlternateResponse) { | |
168 delegate->AbortInstall(); | |
169 } else { | |
170 delegate->ContinueInstall(); | |
171 } | |
172 #else | |
173 // TODO(port): Implement some UI. | |
174 NOTREACHED(); | |
175 delegate->ContinueInstall(); | |
176 #endif // OS_* | |
177 } | 118 } |
178 | 119 |
179 void ExtensionInstallUI::OnInstallSuccess(Extension* extension) { | 120 void ExtensionInstallUI::OnInstallSuccess(Extension* extension) { |
180 ShowThemeInfoBar(extension); | 121 ShowThemeInfoBar(extension); |
181 } | 122 } |
182 | 123 |
183 void ExtensionInstallUI::OnInstallFailure(const std::string& error) { | 124 void ExtensionInstallUI::OnInstallFailure(const std::string& error) { |
184 DCHECK(ui_loop_ == MessageLoop::current()); | 125 DCHECK(ui_loop_ == MessageLoop::current()); |
185 | 126 |
186 #if defined(OS_WIN) | 127 ShowExtensionInstallError(error); |
187 win_util::MessageBox(NULL, UTF8ToWide(error), L"Extension Install Error", | |
188 MB_OK | MB_SETFOREGROUND); | |
189 #elif defined(OS_MACOSX) | |
190 // There must be a better way to do this, for all platforms. | |
191 scoped_cftyperef<CFStringRef> message_cf( | |
192 base::SysUTF8ToCFStringRef(error)); | |
193 CFOptionFlags response; | |
194 CFUserNotificationDisplayAlert( | |
195 0, kCFUserNotificationNoteAlertLevel, NULL, NULL, NULL, | |
196 CFSTR("Extension Install Error"), message_cf, | |
197 NULL, NULL, NULL, &response); | |
198 #else | |
199 GtkWidget* dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, | |
200 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", error.c_str()); | |
201 g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL); | |
202 gtk_widget_show_all(dialog); | |
203 #endif | |
204 } | 128 } |
205 | 129 |
206 void ExtensionInstallUI::OnOverinstallAttempted(Extension* extension) { | 130 void ExtensionInstallUI::OnOverinstallAttempted(Extension* extension) { |
207 ShowThemeInfoBar(extension); | 131 ShowThemeInfoBar(extension); |
208 } | 132 } |
209 | 133 |
210 void ExtensionInstallUI::ShowThemeInfoBar(Extension* new_theme) { | 134 void ExtensionInstallUI::ShowThemeInfoBar(Extension* new_theme) { |
211 if (!new_theme->IsTheme()) | 135 if (!new_theme->IsTheme()) |
212 return; | 136 return; |
213 | 137 |
214 Browser* browser = BrowserList::GetLastActiveWithProfile(profile_); | 138 Browser* browser = BrowserList::GetLastActiveWithProfile(profile_); |
215 if (!browser) | 139 if (!browser) |
216 return; | 140 return; |
217 | 141 |
218 TabContents* tab_contents = browser->GetSelectedTabContents(); | 142 TabContents* tab_contents = browser->GetSelectedTabContents(); |
219 if (!tab_contents) | 143 if (!tab_contents) |
220 return; | 144 return; |
221 | 145 |
222 // First find any previous theme preview infobars. | 146 // First find any previous theme preview infobars. |
223 InfoBarDelegate* old_delegate = NULL; | 147 InfoBarDelegate* old_delegate = NULL; |
224 for (int i = 0; i < tab_contents->infobar_delegate_count(); ++i) { | 148 for (int i = 0; i < tab_contents->infobar_delegate_count(); ++i) { |
225 InfoBarDelegate* delegate = tab_contents->GetInfoBarDelegateAt(i); | 149 InfoBarDelegate* delegate = tab_contents->GetInfoBarDelegateAt(i); |
226 if (delegate->AsThemePreviewInfobarDelegate()) { | 150 if (delegate->AsThemePreviewInfobarDelegate()) { |
227 old_delegate = delegate; | 151 old_delegate = delegate; |
228 break; | 152 break; |
229 } | 153 } |
230 } | 154 } |
231 | 155 |
232 // Then either replace that old one or add a new one. | 156 // Then either replace that old one or add a new one. |
233 InfoBarDelegate* new_delegate = | 157 InfoBarDelegate* new_delegate = GetNewInfoBarDelegate(new_theme, |
234 #if defined(TOOLKIT_GTK) | 158 tab_contents); |
235 new GtkThemeInstalledInfoBarDelegate( | |
236 tab_contents, | |
237 new_theme->name(), previous_theme_id_, previous_use_gtk_theme_); | |
238 #else | |
239 new ThemeInstalledInfoBarDelegate(tab_contents, | |
240 new_theme->name(), previous_theme_id_); | |
241 #endif | |
242 | 159 |
243 if (old_delegate) | 160 if (old_delegate) |
244 tab_contents->ReplaceInfoBar(old_delegate, new_delegate); | 161 tab_contents->ReplaceInfoBar(old_delegate, new_delegate); |
245 else | 162 else |
246 tab_contents->AddInfoBar(new_delegate); | 163 tab_contents->AddInfoBar(new_delegate); |
247 } | 164 } |
| 165 |
| 166 InfoBarDelegate* ExtensionInstallUI::GetNewInfoBarDelegate( |
| 167 Extension* new_theme, TabContents* tab_contents) { |
| 168 #if defined(TOOLKIT_GTK) |
| 169 return new GtkThemeInstalledInfoBarDelegate(tab_contents, new_theme->name(), |
| 170 previous_theme_id_, previous_use_gtk_theme_); |
| 171 #else |
| 172 return new ThemeInstalledInfoBarDelegate(tab_contents, new_theme->name(), |
| 173 previous_theme_id_); |
| 174 #endif |
| 175 } |
OLD | NEW |