1 // Copyright (c) 2014 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/settings_api_bubble_helpers.h"
6 
7 #include <utility>
8 
9 #include "build/build_config.h"
10 #include "chrome/browser/extensions/ntp_overridden_bubble_delegate.h"
11 #include "chrome/browser/extensions/settings_api_bubble_delegate.h"
12 #include "chrome/browser/extensions/settings_api_helpers.h"
13 #include "chrome/browser/ui/browser_dialogs.h"
14 #include "chrome/browser/ui/browser_finder.h"
15 #include "chrome/browser/ui/browser_window.h"
16 #include "chrome/browser/ui/extensions/extension_message_bubble_bridge.h"
17 #include "chrome/browser/ui/extensions/extension_settings_overridden_dialog.h"
18 #include "chrome/browser/ui/extensions/settings_overridden_params_providers.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
21 #include "chrome/browser/ui/ui_features.h"
22 #include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
23 #include "chrome/common/url_constants.h"
24 #include "content/public/browser/browser_url_handler.h"
25 #include "content/public/browser/navigation_entry.h"
26 #include "extensions/common/constants.h"
27 
28 namespace extensions {
29 
30 namespace {
31 
32 // Whether the NTP post-install UI is enabled. By default, this is limited to
33 // Windows, Mac, and ChromeOS, but can be overridden for testing.
34 #if defined(OS_WIN) || defined(OS_MAC) || defined(OS_CHROMEOS)
35 bool g_ntp_post_install_ui_enabled = true;
36 #else
37 bool g_ntp_post_install_ui_enabled = false;
38 #endif
39 
40 #if defined(OS_WIN) || defined(OS_MAC)
ShowSettingsApiBubble(SettingsApiOverrideType type,Browser * browser)41 void ShowSettingsApiBubble(SettingsApiOverrideType type,
42                            Browser* browser) {
43   ToolbarActionsModel* model = ToolbarActionsModel::Get(browser->profile());
44   if (model->has_active_bubble())
45     return;
46 
47   std::unique_ptr<ExtensionMessageBubbleController> settings_api_bubble(
48       new ExtensionMessageBubbleController(
49           new SettingsApiBubbleDelegate(browser->profile(), type), browser));
50   if (!settings_api_bubble->ShouldShow())
51     return;
52 
53   settings_api_bubble->SetIsActiveBubble();
54   std::unique_ptr<ToolbarActionsBarBubbleDelegate> bridge(
55       new ExtensionMessageBubbleBridge(std::move(settings_api_bubble)));
56   browser->window()->GetExtensionsContainer()->ShowToolbarActionBubbleAsync(
57       std::move(bridge));
58 }
59 #endif
60 
61 }  // namespace
62 
SetNtpPostInstallUiEnabledForTesting(bool enabled)63 void SetNtpPostInstallUiEnabledForTesting(bool enabled) {
64   g_ntp_post_install_ui_enabled = enabled;
65 }
66 
MaybeShowExtensionControlledHomeNotification(Browser * browser)67 void MaybeShowExtensionControlledHomeNotification(Browser* browser) {
68 #if defined(OS_WIN) || defined(OS_MAC)
69   ShowSettingsApiBubble(BUBBLE_TYPE_HOME_PAGE, browser);
70 #endif
71 }
72 
MaybeShowExtensionControlledSearchNotification(content::WebContents * web_contents,AutocompleteMatch::Type match_type)73 void MaybeShowExtensionControlledSearchNotification(
74     content::WebContents* web_contents,
75     AutocompleteMatch::Type match_type) {
76 #if defined(OS_WIN) || defined(OS_MAC)
77   if (!AutocompleteMatch::IsSearchType(match_type) ||
78       match_type == AutocompleteMatchType::SEARCH_OTHER_ENGINE) {
79     return;
80   }
81 
82   Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
83   if (!browser)
84     return;
85 
86   if (base::FeatureList::IsEnabled(
87           features::kExtensionSettingsOverriddenDialogs)) {
88     base::Optional<ExtensionSettingsOverriddenDialog::Params> params =
89         settings_overridden_params::GetSearchOverriddenParams(
90             browser->profile());
91     if (!params)
92       return;
93 
94     auto dialog = std::make_unique<ExtensionSettingsOverriddenDialog>(
95         std::move(*params), browser->profile());
96     if (!dialog->ShouldShow())
97       return;
98 
99     chrome::ShowExtensionSettingsOverriddenDialog(std::move(dialog), browser);
100   } else {
101     ShowSettingsApiBubble(BUBBLE_TYPE_SEARCH_ENGINE, browser);
102   }
103 #endif
104 }
105 
MaybeShowExtensionControlledNewTabPage(Browser * browser,content::WebContents * web_contents)106 void MaybeShowExtensionControlledNewTabPage(
107     Browser* browser, content::WebContents* web_contents) {
108   if (!g_ntp_post_install_ui_enabled)
109     return;
110 
111   // Acknowledge existing extensions if necessary.
112   NtpOverriddenBubbleDelegate::MaybeAcknowledgeExistingNtpExtensions(
113       browser->profile());
114 
115   // Jump through a series of hoops to see if the web contents is pointing to
116   // an extension-controlled NTP.
117   // TODO(devlin): Some of this is redundant with the checks in the bubble/
118   // dialog. We should consolidate, but that'll be simpler once we only have
119   // one UI option. In the meantime, extra checks don't hurt.
120   content::NavigationEntry* entry =
121       web_contents->GetController().GetVisibleEntry();
122   if (!entry)
123     return;
124   GURL active_url = entry->GetURL();
125   if (!active_url.SchemeIs(extensions::kExtensionScheme))
126     return;  // Not a URL that we care about.
127 
128   // See if the current active URL matches a transformed NewTab URL.
129   GURL ntp_url(chrome::kChromeUINewTabURL);
130   content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
131       &ntp_url, web_contents->GetBrowserContext());
132   if (ntp_url != active_url)
133     return;  // Not being overridden by an extension.
134 
135   Profile* const profile = browser->profile();
136   ToolbarActionsModel* model = ToolbarActionsModel::Get(profile);
137   if (model->has_active_bubble())
138     return;
139 
140   if (base::FeatureList::IsEnabled(
141           features::kExtensionSettingsOverriddenDialogs)) {
142     base::Optional<ExtensionSettingsOverriddenDialog::Params> params =
143         settings_overridden_params::GetNtpOverriddenParams(profile);
144     if (!params)
145       return;
146 
147     auto dialog = std::make_unique<ExtensionSettingsOverriddenDialog>(
148         std::move(*params), profile);
149     if (!dialog->ShouldShow())
150       return;
151 
152     chrome::ShowExtensionSettingsOverriddenDialog(std::move(dialog), browser);
153     return;
154   }
155 
156   std::unique_ptr<ExtensionMessageBubbleController> ntp_overridden_bubble(
157       new ExtensionMessageBubbleController(
158           new NtpOverriddenBubbleDelegate(profile), browser));
159   if (!ntp_overridden_bubble->ShouldShow())
160     return;
161 
162   ntp_overridden_bubble->SetIsActiveBubble();
163   std::unique_ptr<ToolbarActionsBarBubbleDelegate> bridge(
164       new ExtensionMessageBubbleBridge(std::move(ntp_overridden_bubble)));
165   browser->window()->GetExtensionsContainer()->ShowToolbarActionBubbleAsync(
166       std::move(bridge));
167 }
168 
169 }  // namespace extensions
170