| 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 |