Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / extensions / extension_install_ui_default.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/extensions/extension_install_ui_default.h"
6
7 #include "base/bind.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
11 #include "chrome/browser/infobars/infobar_service.h"
12 #include "chrome/browser/prefs/incognito_mode_prefs.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/themes/theme_service.h"
15 #include "chrome/browser/themes/theme_service_factory.h"
16 #include "chrome/browser/ui/app_list/app_list_service.h"
17 #include "chrome/browser/ui/app_list/app_list_util.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_dialogs.h"
20 #include "chrome/browser/ui/browser_finder.h"
21 #include "chrome/browser/ui/browser_navigator.h"
22 #include "chrome/browser/ui/browser_tabstrip.h"
23 #include "chrome/browser/ui/browser_window.h"
24 #include "chrome/browser/ui/host_desktop.h"
25 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
26 #include "chrome/browser/ui/simple_message_box.h"
27 #include "chrome/browser/ui/singleton_tabs.h"
28 #include "chrome/browser/ui/tabs/tab_strip_model.h"
29 #include "chrome/common/url_constants.h"
30 #include "chrome/grit/generated_resources.h"
31 #include "components/infobars/core/confirm_infobar_delegate.h"
32 #include "components/infobars/core/infobar.h"
33 #include "components/search/search.h"
34 #include "content/public/browser/browser_thread.h"
35 #include "content/public/browser/notification_service.h"
36 #include "content/public/browser/web_contents.h"
37 #include "extensions/browser/install/crx_installer_error.h"
38 #include "extensions/common/extension.h"
39 #include "grit/components_strings.h"
40 #include "ui/base/l10n/l10n_util.h"
41
42 #if defined(USE_ASH)
43 #include "ash/shell.h"
44 #endif
45
46 using content::BrowserThread;
47 using content::WebContents;
48 using extensions::Extension;
49
50 namespace {
51
52 Browser* FindOrCreateVisibleBrowser(Profile* profile) {
53   // TODO(mpcomplete): remove this workaround for http://crbug.com/244246
54   // after fixing http://crbug.com/38676.
55   if (!IncognitoModePrefs::CanOpenBrowser(profile))
56     return NULL;
57   chrome::ScopedTabbedBrowserDisplayer displayer(
58       profile, chrome::GetActiveDesktop());
59   Browser* browser = displayer.browser();
60   if (browser->tab_strip_model()->count() == 0)
61     chrome::AddTabAt(browser, GURL(), -1, true);
62   return browser;
63 }
64
65 void ShowExtensionInstalledBubble(const extensions::Extension* extension,
66                                   Profile* profile,
67                                   const SkBitmap& icon) {
68   Browser* browser = FindOrCreateVisibleBrowser(profile);
69   if (browser)
70     chrome::ShowExtensionInstalledBubble(extension, browser, icon);
71 }
72
73 // Helper class to put up an infobar when installation fails.
74 class ErrorInfoBarDelegate : public ConfirmInfoBarDelegate {
75  public:
76   // Creates an error infobar and delegate and adds the infobar to
77   // |infobar_service|.
78   static void Create(InfoBarService* infobar_service,
79                      const extensions::CrxInstallerError& error);
80
81  private:
82   explicit ErrorInfoBarDelegate(const extensions::CrxInstallerError& error);
83   ~ErrorInfoBarDelegate() override;
84
85   // ConfirmInfoBarDelegate:
86   base::string16 GetMessageText() const override;
87   int GetButtons() const override;
88   base::string16 GetLinkText() const override;
89   bool LinkClicked(WindowOpenDisposition disposition) override;
90
91   extensions::CrxInstallerError error_;
92
93   DISALLOW_COPY_AND_ASSIGN(ErrorInfoBarDelegate);
94 };
95
96 // static
97 void ErrorInfoBarDelegate::Create(InfoBarService* infobar_service,
98                                   const extensions::CrxInstallerError& error) {
99   infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
100       scoped_ptr<ConfirmInfoBarDelegate>(new ErrorInfoBarDelegate(error))));
101 }
102
103 ErrorInfoBarDelegate::ErrorInfoBarDelegate(
104     const extensions::CrxInstallerError& error)
105     : ConfirmInfoBarDelegate(),
106       error_(error) {
107 }
108
109 ErrorInfoBarDelegate::~ErrorInfoBarDelegate() {
110 }
111
112 base::string16 ErrorInfoBarDelegate::GetMessageText() const {
113   return error_.message();
114 }
115
116 int ErrorInfoBarDelegate::GetButtons() const {
117   return BUTTON_OK;
118 }
119
120 base::string16 ErrorInfoBarDelegate::GetLinkText() const {
121   return (error_.type() == extensions::CrxInstallerError::ERROR_OFF_STORE) ?
122       l10n_util::GetStringUTF16(IDS_LEARN_MORE) : base::string16();
123 }
124
125 bool ErrorInfoBarDelegate::LinkClicked(WindowOpenDisposition disposition) {
126   InfoBarService::WebContentsFromInfoBar(infobar())->OpenURL(
127       content::OpenURLParams(
128           GURL("http://support.google.com/chrome_webstore/?p=crx_warning"),
129           content::Referrer(),
130           (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
131           ui::PAGE_TRANSITION_LINK, false));
132   return false;
133 }
134
135 }  // namespace
136
137 ExtensionInstallUIDefault::ExtensionInstallUIDefault(
138     content::BrowserContext* context)
139     : profile_(Profile::FromBrowserContext(context)),
140       skip_post_install_ui_(false),
141       previous_using_system_theme_(false),
142       use_app_installed_bubble_(false) {
143   // |profile| can be NULL during tests.
144   if (profile_) {
145     // Remember the current theme in case the user presses undo.
146     const Extension* previous_theme =
147         ThemeServiceFactory::GetThemeForProfile(profile_);
148     if (previous_theme)
149       previous_theme_id_ = previous_theme->id();
150     previous_using_system_theme_ =
151         ThemeServiceFactory::GetForProfile(profile_)->UsingSystemTheme();
152   }
153 }
154
155 ExtensionInstallUIDefault::~ExtensionInstallUIDefault() {}
156
157 void ExtensionInstallUIDefault::OnInstallSuccess(const Extension* extension,
158                                                  const SkBitmap* icon) {
159   if (skip_post_install_ui_)
160     return;
161
162   if (!profile_) {
163     // TODO(zelidrag): Figure out what exact conditions cause crash
164     // http://crbug.com/159437 and write browser test to cover it.
165     NOTREACHED();
166     return;
167   }
168
169   if (extension->is_theme()) {
170     ThemeInstalledInfoBarDelegate::Create(
171         extension, profile_, previous_theme_id_, previous_using_system_theme_);
172     return;
173   }
174
175   // Extensions aren't enabled by default in incognito so we confirm
176   // the install in a normal window.
177   Profile* current_profile = profile_->GetOriginalProfile();
178   if (extension->is_app()) {
179     bool use_bubble = false;
180
181 #if defined(TOOLKIT_VIEWS)  || defined(OS_MACOSX)
182     use_bubble = use_app_installed_bubble_;
183 #endif
184
185     if (IsAppLauncherEnabled()) {
186       // TODO(tapted): ExtensionInstallUI should retain the desktop type from
187       // the browser used to initiate the flow. http://crbug.com/308360.
188       AppListService::Get(chrome::GetActiveDesktop())
189           ->ShowForAppInstall(current_profile, extension->id(), false);
190       return;
191     }
192
193     if (use_bubble) {
194       ShowExtensionInstalledBubble(extension, current_profile, *icon);
195       return;
196     }
197
198     OpenAppInstalledUI(extension->id());
199     return;
200   }
201
202   ShowExtensionInstalledBubble(extension, current_profile, *icon);
203 }
204
205 void ExtensionInstallUIDefault::OnInstallFailure(
206     const extensions::CrxInstallerError& error) {
207   DCHECK_CURRENTLY_ON(BrowserThread::UI);
208   if (disable_failure_ui_for_tests() || skip_post_install_ui_)
209     return;
210
211   Browser* browser =
212       chrome::FindLastActiveWithProfile(profile_, chrome::GetActiveDesktop());
213   if (!browser)  // Can be NULL in unittests.
214     return;
215   WebContents* web_contents =
216       browser->tab_strip_model()->GetActiveWebContents();
217   if (!web_contents)
218     return;
219   ErrorInfoBarDelegate::Create(InfoBarService::FromWebContents(web_contents),
220                                error);
221 }
222
223 void ExtensionInstallUIDefault::OpenAppInstalledUI(const std::string& app_id) {
224 #if defined(OS_CHROMEOS)
225   // App Launcher always enabled on ChromeOS, so always handled in
226   // OnInstallSuccess.
227   NOTREACHED();
228 #else
229   Profile* current_profile = profile_->GetOriginalProfile();
230   Browser* browser = FindOrCreateVisibleBrowser(current_profile);
231   if (browser) {
232     GURL url(chrome::IsInstantExtendedAPIEnabled()
233                  ? chrome::kChromeUIAppsURL
234                  : chrome::kChromeUINewTabURL);
235     chrome::NavigateParams params(
236         chrome::GetSingletonTabNavigateParams(browser, url));
237     chrome::Navigate(&params);
238
239     content::NotificationService::current()->Notify(
240         chrome::NOTIFICATION_APP_INSTALLED_TO_NTP,
241         content::Source<WebContents>(params.target_contents),
242         content::Details<const std::string>(&app_id));
243   }
244 #endif
245 }
246
247 void ExtensionInstallUIDefault::SetUseAppInstalledBubble(bool use_bubble) {
248   use_app_installed_bubble_ = use_bubble;
249 }
250
251 void ExtensionInstallUIDefault::SetSkipPostInstallUI(bool skip_ui) {
252   skip_post_install_ui_ = skip_ui;
253 }
254
255 gfx::NativeWindow ExtensionInstallUIDefault::GetDefaultInstallDialogParent() {
256   Browser* browser =
257       chrome::FindLastActiveWithProfile(profile_, chrome::GetActiveDesktop());
258   if (browser) {
259     content::WebContents* contents =
260         browser->tab_strip_model()->GetActiveWebContents();
261     return contents->GetTopLevelNativeWindow();
262   }
263   return NULL;
264 }