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/webui/chrome_web_ui_controller_factory.h"
6
7 #include <vector>
8
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/location.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "base/prefs/pref_service.h"
14 #include "chrome/browser/about_flags.h"
15 #include "chrome/browser/bookmarks/enhanced_bookmarks_features.h"
16 #include "chrome/browser/dom_distiller/dom_distiller_service_factory.h"
17 #include "chrome/browser/favicon/favicon_service.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/profiles/profile_manager.h"
20 #include "chrome/browser/ui/webui/about_ui.h"
21 #include "chrome/browser/ui/webui/app_launcher_page_ui.h"
22 #include "chrome/browser/ui/webui/bookmarks_ui.h"
23 #include "chrome/browser/ui/webui/components_ui.h"
24 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"
25 #include "chrome/browser/ui/webui/crashes_ui.h"
26 #include "chrome/browser/ui/webui/devtools_ui.h"
27 #include "chrome/browser/ui/webui/domain_reliability_internals_ui.h"
28 #include "chrome/browser/ui/webui/downloads_ui.h"
29 #include "chrome/browser/ui/webui/flags_ui.h"
30 #include "chrome/browser/ui/webui/flash_ui.h"
31 #include "chrome/browser/ui/webui/gcm_internals_ui.h"
32 #include "chrome/browser/ui/webui/help/help_ui.h"
33 #include "chrome/browser/ui/webui/history_ui.h"
34 #include "chrome/browser/ui/webui/identity_internals_ui.h"
35 #include "chrome/browser/ui/webui/inspect_ui.h"
36 #include "chrome/browser/ui/webui/instant_ui.h"
37 #include "chrome/browser/ui/webui/interstitials/interstitial_ui.h"
38 #include "chrome/browser/ui/webui/invalidations_ui.h"
39 #include "chrome/browser/ui/webui/memory_internals/memory_internals_ui.h"
40 #include "chrome/browser/ui/webui/net_internals/net_internals_ui.h"
41 #include "chrome/browser/ui/webui/omnibox/omnibox_ui.h"
42 #include "chrome/browser/ui/webui/options/options_ui.h"
43 #include "chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui.h"
44 #include "chrome/browser/ui/webui/plugins_ui.h"
45 #include "chrome/browser/ui/webui/predictors/predictors_ui.h"
46 #include "chrome/browser/ui/webui/profiler_ui.h"
47 #include "chrome/browser/ui/webui/signin/inline_login_ui.h"
48 #include "chrome/browser/ui/webui/signin/profile_signin_confirmation_ui.h"
49 #include "chrome/browser/ui/webui/signin/user_manager_ui.h"
50 #include "chrome/browser/ui/webui/signin_internals_ui.h"
51 #include "chrome/browser/ui/webui/sync_internals_ui.h"
52 #include "chrome/browser/ui/webui/translate_internals/translate_internals_ui.h"
53 #include "chrome/browser/ui/webui/user_actions/user_actions_ui.h"
54 #include "chrome/browser/ui/webui/version_ui.h"
55 #include "chrome/common/chrome_switches.h"
56 #include "chrome/common/pref_names.h"
57 #include "chrome/common/url_constants.h"
58 #include "components/dom_distiller/core/dom_distiller_constants.h"
59 #include "components/dom_distiller/core/dom_distiller_service.h"
60 #include "components/dom_distiller/core/url_constants.h"
61 #include "components/dom_distiller/webui/dom_distiller_ui.h"
62 #include "components/favicon_base/favicon_util.h"
63 #include "components/favicon_base/select_favicon_frames.h"
64 #include "components/history/core/browser/history_types.h"
65 #include "components/password_manager/core/common/password_manager_switches.h"
66 #include "components/signin/core/common/profile_management_switches.h"
67 #include "content/public/browser/web_contents.h"
68 #include "content/public/browser/web_ui.h"
69 #include "content/public/common/content_client.h"
70 #include "content/public/common/url_utils.h"
71 #include "ui/gfx/favicon_size.h"
72 #include "ui/web_dialogs/web_dialog_ui.h"
73 #include "url/gurl.h"
74
75 #if !defined(DISABLE_NACL)
76 #include "chrome/browser/ui/webui/nacl_ui.h"
77 #endif
78
79 #if defined(ENABLE_CONFIGURATION_POLICY)
80 #include "chrome/browser/ui/webui/policy_ui.h"
81 #endif
82
83 #if defined(ENABLE_WEBRTC)
84 #include "chrome/browser/ui/webui/media/webrtc_logs_ui.h"
85 #endif
86
87 #if defined(ENABLE_FULL_PRINTING)
88 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
89 #endif
90
91 #if defined(OS_ANDROID)
92 #include "chrome/browser/ui/webui/welcome_ui_android.h"
93 #else
94 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
95 #include "chrome/browser/ui/webui/quota_internals/quota_internals_ui.h"
96 #include "chrome/browser/ui/webui/suggestions_internals/suggestions_internals_ui.h"
97 #include "chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_ui.h"
98 #include "chrome/browser/ui/webui/system_info_ui.h"
99 #include "chrome/browser/ui/webui/uber/uber_ui.h"
100 #endif
101
102 #if defined(OS_ANDROID) || defined(OS_IOS)
103 #include "chrome/browser/ui/webui/net_export_ui.h"
104 #endif
105
106 #if defined(OS_CHROMEOS)
107 #include "chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui.h"
108 #include "chrome/browser/ui/webui/chromeos/certificate_manager_dialog_ui.h"
109 #include "chrome/browser/ui/webui/chromeos/charger_replacement_ui.h"
110 #include "chrome/browser/ui/webui/chromeos/choose_mobile_network_ui.h"
111 #include "chrome/browser/ui/webui/chromeos/cryptohome_ui.h"
112 #include "chrome/browser/ui/webui/chromeos/drive_internals_ui.h"
113 #include "chrome/browser/ui/webui/chromeos/first_run/first_run_ui.h"
114 #include "chrome/browser/ui/webui/chromeos/imageburner/imageburner_ui.h"
115 #include "chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.h"
116 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
117 #include "chrome/browser/ui/webui/chromeos/mobile_setup_ui.h"
118 #include "chrome/browser/ui/webui/chromeos/network_ui.h"
119 #include "chrome/browser/ui/webui/chromeos/nfc_debug_ui.h"
120 #include "chrome/browser/ui/webui/chromeos/power_ui.h"
121 #include "chrome/browser/ui/webui/chromeos/provided_file_systems_ui.h"
122 #include "chrome/browser/ui/webui/chromeos/proxy_settings_ui.h"
123 #include "chrome/browser/ui/webui/chromeos/salsa_ui.h"
124 #include "chrome/browser/ui/webui/chromeos/set_time_ui.h"
125 #include "chrome/browser/ui/webui/chromeos/sim_unlock_ui.h"
126 #include "chrome/browser/ui/webui/chromeos/slow_trace_ui.h"
127 #include "chrome/browser/ui/webui/chromeos/slow_ui.h"
128 #endif
129
130 #if defined(USE_AURA)
131 #include "chrome/browser/ui/webui/gesture_config_ui.h"
132 #endif
133
134 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
135 #include "chrome/browser/ui/sync/sync_promo_ui.h"
136 #endif
137
138 #if defined(OS_WIN)
139 #include "chrome/browser/ui/webui/conflicts_ui.h"
140 #include "chrome/browser/ui/webui/set_as_default_browser_ui.h"
141 #endif
142
143 #if (defined(USE_NSS) || defined(USE_OPENSSL)) && defined(USE_AURA)
144 #include "chrome/browser/ui/webui/certificate_viewer_ui.h"
145 #endif
146
147 #if defined(ENABLE_SERVICE_DISCOVERY)
148 #include "chrome/browser/ui/webui/local_discovery/local_discovery_ui.h"
149 #endif
150
151 #if defined(ENABLE_APP_LIST)
152 #include "chrome/browser/ui/webui/app_list/start_page_ui.h"
153 #endif
154
155 #if defined(ENABLE_EXTENSIONS)
156 #include "chrome/browser/extensions/extension_web_ui.h"
157 #include "chrome/browser/ui/webui/extensions/extension_info_ui.h"
158 #include "chrome/browser/ui/webui/extensions/extensions_ui.h"
159 #include "chrome/browser/ui/webui/voicesearch_ui.h"
160 #include "chrome/common/extensions/extension_constants.h"
161 #include "extensions/browser/extension_registry.h"
162 #include "extensions/browser/extension_system.h"
163 #include "extensions/common/constants.h"
164 #include "extensions/common/extension.h"
165 #include "extensions/common/feature_switch.h"
166 #include "extensions/common/manifest.h"
167 #endif
168
169 using content::WebUI;
170 using content::WebUIController;
171 using ui::ExternalWebDialogUI;
172 using ui::WebDialogUI;
173
174 namespace {
175
176 // A function for creating a new WebUI. The caller owns the return value, which
177 // may be NULL (for example, if the URL refers to an non-existent extension).
178 typedef WebUIController* (*WebUIFactoryFunction)(WebUI* web_ui,
179 const GURL& url);
180
181 // Template for defining WebUIFactoryFunction.
182 template<class T>
NewWebUI(WebUI * web_ui,const GURL & url)183 WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) {
184 return new T(web_ui);
185 }
186
187 #if defined(ENABLE_EXTENSIONS)
188 // Special cases for extensions.
189 template<>
NewWebUI(WebUI * web_ui,const GURL & url)190 WebUIController* NewWebUI<ExtensionWebUI>(WebUI* web_ui,
191 const GURL& url) {
192 return new ExtensionWebUI(web_ui, url);
193 }
194 #endif // defined(ENABLE_EXTENSIONS)
195
196 // Special case for older about: handlers.
197 template<>
NewWebUI(WebUI * web_ui,const GURL & url)198 WebUIController* NewWebUI<AboutUI>(WebUI* web_ui, const GURL& url) {
199 return new AboutUI(web_ui, url.host());
200 }
201
202 #if defined(OS_CHROMEOS)
203 template<>
NewWebUI(WebUI * web_ui,const GURL & url)204 WebUIController* NewWebUI<chromeos::OobeUI>(WebUI* web_ui, const GURL& url) {
205 return new chromeos::OobeUI(web_ui, url);
206 }
207 #endif
208
209 // Special cases for DOM distiller.
210 template<>
NewWebUI(WebUI * web_ui,const GURL & url)211 WebUIController* NewWebUI<dom_distiller::DomDistillerUi>(WebUI* web_ui,
212 const GURL& url) {
213 // The DomDistillerUi can not depend on components/dom_distiller/content,
214 // so inject the correct DomDistillerService from chrome/.
215 content::BrowserContext* browser_context =
216 web_ui->GetWebContents()->GetBrowserContext();
217 dom_distiller::DomDistillerService* service =
218 dom_distiller::DomDistillerServiceFactory::GetForBrowserContext(
219 browser_context);
220 return new dom_distiller::DomDistillerUi(
221 web_ui, service, dom_distiller::kDomDistillerScheme);
222 }
223
224 #if defined(ENABLE_EXTENSIONS)
225 // Only create ExtensionWebUI for URLs that are allowed extension bindings,
226 // hosted by actual tabs.
NeedsExtensionWebUI(Profile * profile,const GURL & url)227 bool NeedsExtensionWebUI(Profile* profile, const GURL& url) {
228 if (!profile)
229 return false;
230
231 const extensions::Extension* extension =
232 extensions::ExtensionRegistry::Get(profile)->enabled_extensions().
233 GetExtensionOrAppByURL(url);
234 // Allow bindings for all packaged extensions and component hosted apps.
235 return extension &&
236 (!extension->is_hosted_app() ||
237 extension->location() == extensions::Manifest::COMPONENT);
238 }
239 #endif
240
241 // Returns a function that can be used to create the right type of WebUI for a
242 // tab, based on its URL. Returns NULL if the URL doesn't have WebUI associated
243 // with it.
GetWebUIFactoryFunction(WebUI * web_ui,Profile * profile,const GURL & url)244 WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
245 Profile* profile,
246 const GURL& url) {
247 #if defined(ENABLE_EXTENSIONS)
248 if (NeedsExtensionWebUI(profile, url))
249 return &NewWebUI<ExtensionWebUI>;
250 #endif
251
252 // This will get called a lot to check all URLs, so do a quick check of other
253 // schemes to filter out most URLs.
254 if (!url.SchemeIs(content::kChromeDevToolsScheme) &&
255 !url.SchemeIs(content::kChromeUIScheme)) {
256 return NULL;
257 }
258
259 /****************************************************************************
260 * Please keep this in alphabetical order. If #ifs or special logics are
261 * required, add it below in the appropriate section.
262 ***************************************************************************/
263 // We must compare hosts only since some of the Web UIs append extra stuff
264 // after the host name.
265 // All platform builds of Chrome will need to have a cloud printing
266 // dialog as backup. It's just that on Chrome OS, it's the only
267 // print dialog.
268 if (url.host() == chrome::kChromeUICloudPrintResourcesHost)
269 return &NewWebUI<ExternalWebDialogUI>;
270 if (url.host() == chrome::kChromeUICloudPrintSetupHost)
271 return &NewWebUI<WebDialogUI>;
272 if (url.host() == chrome::kChromeUIComponentsHost)
273 return &NewWebUI<ComponentsUI>;
274 if (url.spec() == chrome::kChromeUIConstrainedHTMLTestURL)
275 return &NewWebUI<ConstrainedWebDialogUI>;
276 if (url.host() == chrome::kChromeUICrashesHost)
277 return &NewWebUI<CrashesUI>;
278 #if defined(ENABLE_SERVICE_DISCOVERY)
279 if (url.host() == chrome::kChromeUIDevicesHost) {
280 return &NewWebUI<LocalDiscoveryUI>;
281 }
282 #endif
283 if (url.host() == chrome::kChromeUIDomainReliabilityInternalsHost)
284 return &NewWebUI<DomainReliabilityInternalsUI>;
285 if (url.host() == chrome::kChromeUIFlagsHost)
286 return &NewWebUI<FlagsUI>;
287 if (url.host() == chrome::kChromeUIHistoryFrameHost)
288 return &NewWebUI<HistoryUI>;
289 if (url.host() == chrome::kChromeUIInstantHost)
290 return &NewWebUI<InstantUI>;
291 if (url.host() == chrome::kChromeUIInterstitialHost)
292 return &NewWebUI<InterstitialUI>;
293 if (url.host() == chrome::kChromeUIInvalidationsHost)
294 return &NewWebUI<InvalidationsUI>;
295 if (url.host() == chrome::kChromeUISupervisedUserPassphrasePageHost)
296 return &NewWebUI<ConstrainedWebDialogUI>;
297 if (url.host() == chrome::kChromeUIMemoryInternalsHost)
298 return &NewWebUI<MemoryInternalsUI>;
299 #if !defined(DISABLE_NACL)
300 if (url.host() == chrome::kChromeUINaClHost)
301 return &NewWebUI<NaClUI>;
302 #endif
303 #if defined(OS_ANDROID) || defined(OS_IOS)
304 if (url.host() == chrome::kChromeUINetExportHost)
305 return &NewWebUI<NetExportUI>;
306 #endif
307 if (url.host() == chrome::kChromeUINetInternalsHost)
308 return &NewWebUI<NetInternalsUI>;
309 #if !defined(OS_ANDROID)
310 if (url.host() == chrome::kChromeUINewTabHost)
311 return &NewWebUI<NewTabUI>;
312 #endif
313 if (url.host() == chrome::kChromeUIOmniboxHost)
314 return &NewWebUI<OmniboxUI>;
315 if (url.host() == chrome::kChromeUIPasswordManagerInternalsHost)
316 return &NewWebUI<PasswordManagerInternalsUI>;
317 if (url.host() == chrome::kChromeUIPredictorsHost)
318 return &NewWebUI<PredictorsUI>;
319 if (url.host() == chrome::kChromeUIProfilerHost)
320 return &NewWebUI<ProfilerUI>;
321 if (url.host() == chrome::kChromeUISignInInternalsHost)
322 return &NewWebUI<SignInInternalsUI>;
323 if (url.host() == chrome::kChromeUISyncInternalsHost)
324 return &NewWebUI<SyncInternalsUI>;
325 if (url.host() == chrome::kChromeUISyncResourcesHost)
326 return &NewWebUI<WebDialogUI>;
327 if (url.host() == chrome::kChromeUITranslateInternalsHost)
328 return &NewWebUI<TranslateInternalsUI>;
329 if (url.host() == chrome::kChromeUIUserActionsHost)
330 return &NewWebUI<UserActionsUI>;
331 if (url.host() == chrome::kChromeUIVersionHost)
332 return &NewWebUI<VersionUI>;
333 #if defined(ENABLE_EXTENSIONS)
334 if (url.host() == chrome::kChromeUIVoiceSearchHost)
335 return &NewWebUI<VoiceSearchUI>;
336 #endif
337 #if defined(ENABLE_WEBRTC)
338 if (url.host() == chrome::kChromeUIWebRtcLogsHost)
339 return &NewWebUI<WebRtcLogsUI>;
340 #endif
341 #if defined(ENABLE_APP_LIST)
342 if (url.host() == chrome::kChromeUIAppListStartPageHost)
343 return &NewWebUI<app_list::StartPageUI>;
344 #endif
345
346 /****************************************************************************
347 * OS Specific #defines
348 ***************************************************************************/
349 #if defined(OS_ANDROID)
350 if (url.host() == chrome::kChromeUIWelcomeHost)
351 return &NewWebUI<WelcomeUI>;
352 #else
353 // AppLauncherPage is not needed on Android.
354 if (url.host() == chrome::kChromeUIAppLauncherPageHost &&
355 profile && extensions::ExtensionSystem::Get(profile)->
356 extension_service()) {
357 return &NewWebUI<AppLauncherPageUI>;
358 }
359 // Bookmarks are part of NTP on Android.
360 if (url.host() == chrome::kChromeUIBookmarksHost)
361 return &NewWebUI<BookmarksUI>;
362 if (url.SchemeIs(content::kChromeDevToolsScheme))
363 return &NewWebUI<DevToolsUI>;
364 // Downloads list on Android uses the built-in download manager.
365 if (url.host() == chrome::kChromeUIDownloadsHost)
366 return &NewWebUI<DownloadsUI>;
367 // Flash is not available on android.
368 if (url.host() == chrome::kChromeUIFlashHost)
369 return &NewWebUI<FlashUI>;
370 if (url.host() == chrome::kChromeUIGCMInternalsHost)
371 return &NewWebUI<GCMInternalsUI>;
372 // Help is implemented with native UI elements on Android.
373 if (url.host() == chrome::kChromeUIHelpFrameHost)
374 return &NewWebUI<HelpUI>;
375 // Identity API is not available on Android.
376 if (url.host() == chrome::kChromeUIIdentityInternalsHost)
377 return &NewWebUI<IdentityInternalsUI>;
378 // chrome://inspect isn't supported on Android. Page debugging is handled by a
379 // remote devtools on the host machine, and other elements (Shared Workers,
380 // extensions, etc) aren't supported.
381 if (url.host() == chrome::kChromeUIInspectHost)
382 return &NewWebUI<InspectUI>;
383 // Android does not support plugins for now.
384 if (url.host() == chrome::kChromeUIPluginsHost)
385 return &NewWebUI<PluginsUI>;
386 if (url.host() == chrome::kChromeUIQuotaInternalsHost)
387 return &NewWebUI<QuotaInternalsUI>;
388 // Settings are implemented with native UI elements on Android.
389 // Handle chrome://settings if settings in a window and about in settings
390 // are enabled.
391 if (url.host() == chrome::kChromeUISettingsFrameHost ||
392 (url.host() == chrome::kChromeUISettingsHost &&
393 ::switches::AboutInSettingsEnabled())) {
394 return &NewWebUI<options::OptionsUI>;
395 }
396 if (url.host() == chrome::kChromeUISuggestionsInternalsHost)
397 return &NewWebUI<SuggestionsInternalsUI>;
398 if (url.host() == chrome::kChromeUISyncFileSystemInternalsHost)
399 return &NewWebUI<SyncFileSystemInternalsUI>;
400 if (url.host() == chrome::kChromeUISystemInfoHost)
401 return &NewWebUI<SystemInfoUI>;
402 // Uber frame is not used on Android.
403 if (url.host() == chrome::kChromeUIUberFrameHost)
404 return &NewWebUI<UberFrameUI>;
405 // Uber page is not used on Android.
406 if (url.host() == chrome::kChromeUIUberHost)
407 return &NewWebUI<UberUI>;
408 #endif
409 #if defined(OS_WIN)
410 if (url.host() == chrome::kChromeUIConflictsHost)
411 return &NewWebUI<ConflictsUI>;
412 if (url.host() == chrome::kChromeUIMetroFlowHost)
413 return &NewWebUI<SetAsDefaultBrowserUI>;
414 #endif
415 #if (defined(USE_NSS) || defined(USE_OPENSSL)) && defined(USE_AURA)
416 if (url.host() == chrome::kChromeUICertificateViewerHost)
417 return &NewWebUI<CertificateViewerUI>;
418 #if defined(OS_CHROMEOS)
419 if (url.host() == chrome::kChromeUICertificateViewerDialogHost)
420 return &NewWebUI<CertificateViewerModalDialogUI>;
421 #endif
422 #endif
423 #if defined(OS_CHROMEOS)
424 if (url.host() == chrome::kChromeUIBluetoothPairingHost)
425 return &NewWebUI<chromeos::BluetoothPairingUI>;
426 if (url.host() == chrome::kChromeUICertificateManagerHost)
427 return &NewWebUI<chromeos::CertificateManagerDialogUI>;
428 if (url.host() == chrome::kChromeUIChargerReplacementHost)
429 return &NewWebUI<chromeos::ChargerReplacementUI>;
430 if (url.host() == chrome::kChromeUIChooseMobileNetworkHost)
431 return &NewWebUI<chromeos::ChooseMobileNetworkUI>;
432 if (url.host() == chrome::kChromeUICryptohomeHost)
433 return &NewWebUI<chromeos::CryptohomeUI>;
434 if (url.host() == chrome::kChromeUIDriveInternalsHost)
435 return &NewWebUI<chromeos::DriveInternalsUI>;
436 if (url.host() == chrome::kChromeUIFirstRunHost)
437 return &NewWebUI<chromeos::FirstRunUI>;
438 if (url.host() == chrome::kChromeUIImageBurnerHost)
439 return &NewWebUI<ImageBurnUI>;
440 if (url.host() == chrome::kChromeUIKeyboardOverlayHost)
441 return &NewWebUI<KeyboardOverlayUI>;
442 if (url.host() == chrome::kChromeUIMobileSetupHost)
443 return &NewWebUI<MobileSetupUI>;
444 if (url.host() == chrome::kChromeUINfcDebugHost)
445 return &NewWebUI<chromeos::NfcDebugUI>;
446 if (url.host() == chrome::kChromeUIOobeHost)
447 return &NewWebUI<chromeos::OobeUI>;
448 if (url.host() == chrome::kChromeUIProvidedFileSystemsHost)
449 return &NewWebUI<chromeos::ProvidedFileSystemsUI>;
450 if (url.host() == chrome::kChromeUIProxySettingsHost)
451 return &NewWebUI<chromeos::ProxySettingsUI>;
452 if (url.host() == chrome::kChromeUISalsaHost)
453 return &NewWebUI<SalsaUI>;
454 if (url.host() == chrome::kChromeUISetTimeHost)
455 return &NewWebUI<chromeos::SetTimeUI>;
456 if (url.host() == chrome::kChromeUISimUnlockHost)
457 return &NewWebUI<chromeos::SimUnlockUI>;
458 if (url.host() == chrome::kChromeUISlowHost)
459 return &NewWebUI<chromeos::SlowUI>;
460 if (url.host() == chrome::kChromeUISlowTraceHost)
461 return &NewWebUI<chromeos::SlowTraceController>;
462 if (url.host() == chrome::kChromeUINetworkHost)
463 return &NewWebUI<chromeos::NetworkUI>;
464 if (url.host() == chrome::kChromeUIPowerHost)
465 return &NewWebUI<chromeos::PowerUI>;
466 #endif // defined(OS_CHROMEOS)
467 #if !defined(OS_ANDROID) && !defined(OS_IOS)
468 if (url.host() == chrome::kChromeUIChromeSigninHost)
469 return &NewWebUI<InlineLoginUI>;
470 #endif
471
472 /****************************************************************************
473 * Other #defines and special logics.
474 ***************************************************************************/
475 #if defined(ENABLE_CONFIGURATION_POLICY)
476 if (url.host() == chrome::kChromeUIPolicyHost)
477 return &NewWebUI<PolicyUI>;
478
479 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
480 if (url.host() == chrome::kChromeUIProfileSigninConfirmationHost)
481 return &NewWebUI<ProfileSigninConfirmationUI>;
482 #endif
483
484 #endif // defined(ENABLE_CONFIGURATION_POLICY)
485
486 #if (defined(OS_LINUX) && defined(TOOLKIT_VIEWS)) || defined(USE_AURA)
487 if (url.host() == chrome::kChromeUITabModalConfirmDialogHost) {
488 return &NewWebUI<ConstrainedWebDialogUI>;
489 }
490 #endif
491
492 #if defined(USE_AURA)
493 if (url.host() == chrome::kChromeUIGestureConfigHost)
494 return &NewWebUI<GestureConfigUI>;
495 #endif
496
497 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_IOS)
498 if (url.host() == chrome::kChromeUIUserManagerHost &&
499 switches::IsNewAvatarMenu()) {
500 return &NewWebUI<UserManagerUI>;
501 }
502 #endif
503
504 if (url.host() == chrome::kChromeUIChromeURLsHost ||
505 url.host() == chrome::kChromeUICreditsHost ||
506 url.host() == chrome::kChromeUIDNSHost ||
507 url.host() == chrome::kChromeUIMemoryHost ||
508 url.host() == chrome::kChromeUIMemoryRedirectHost ||
509 url.host() == chrome::kChromeUIStatsHost ||
510 url.host() == chrome::kChromeUITermsHost
511 #if defined(OS_LINUX) || defined(OS_OPENBSD)
512 || url.host() == chrome::kChromeUILinuxProxyConfigHost
513 || url.host() == chrome::kChromeUISandboxHost
514 #endif
515 #if defined(OS_CHROMEOS)
516 || url.host() == chrome::kChromeUIDiscardsHost
517 || url.host() == chrome::kChromeUIOSCreditsHost
518 #endif
519 #if defined(WEBUI_TASK_MANAGER)
520 || url.host() == chrome::kChromeUITaskManagerHost
521 #endif
522 ) {
523 return &NewWebUI<AboutUI>;
524 }
525
526 #if defined(ENABLE_EXTENSIONS)
527 if (url.host() == chrome::kChromeUIExtensionsFrameHost)
528 return &NewWebUI<extensions::ExtensionsUI>;
529 #endif
530 #if defined(ENABLE_FULL_PRINTING)
531 if (url.host() == chrome::kChromeUIPrintHost &&
532 !profile->GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled)) {
533 return &NewWebUI<PrintPreviewUI>;
534 }
535 #endif
536
537 if (IsEnableDomDistillerSet() &&
538 url.host() == dom_distiller::kChromeUIDomDistillerHost) {
539 return &NewWebUI<dom_distiller::DomDistillerUi>;
540 }
541
542 return NULL;
543 }
544
RunFaviconCallbackAsync(const favicon_base::FaviconResultsCallback & callback,const std::vector<favicon_base::FaviconRawBitmapResult> * results)545 void RunFaviconCallbackAsync(
546 const favicon_base::FaviconResultsCallback& callback,
547 const std::vector<favicon_base::FaviconRawBitmapResult>* results) {
548 base::MessageLoopProxy::current()->PostTask(
549 FROM_HERE,
550 base::Bind(&FaviconService::FaviconResultsCallbackRunner,
551 callback, base::Owned(results)));
552 }
553
554 } // namespace
555
GetWebUIType(content::BrowserContext * browser_context,const GURL & url) const556 WebUI::TypeID ChromeWebUIControllerFactory::GetWebUIType(
557 content::BrowserContext* browser_context, const GURL& url) const {
558 Profile* profile = Profile::FromBrowserContext(browser_context);
559 WebUIFactoryFunction function = GetWebUIFactoryFunction(NULL, profile, url);
560 return function ? reinterpret_cast<WebUI::TypeID>(function) : WebUI::kNoWebUI;
561 }
562
UseWebUIForURL(content::BrowserContext * browser_context,const GURL & url) const563 bool ChromeWebUIControllerFactory::UseWebUIForURL(
564 content::BrowserContext* browser_context, const GURL& url) const {
565 return GetWebUIType(browser_context, url) != WebUI::kNoWebUI;
566 }
567
UseWebUIBindingsForURL(content::BrowserContext * browser_context,const GURL & url) const568 bool ChromeWebUIControllerFactory::UseWebUIBindingsForURL(
569 content::BrowserContext* browser_context, const GURL& url) const {
570 bool needs_extensions_web_ui = false;
571 #if defined(ENABLE_EXTENSIONS)
572 // Extensions are rendered via WebUI in tabs, but don't actually need WebUI
573 // bindings (see the ExtensionWebUI constructor).
574 needs_extensions_web_ui =
575 NeedsExtensionWebUI(Profile::FromBrowserContext(browser_context), url);
576 #endif
577 return !needs_extensions_web_ui && UseWebUIForURL(browser_context, url);
578 }
579
CreateWebUIControllerForURL(WebUI * web_ui,const GURL & url) const580 WebUIController* ChromeWebUIControllerFactory::CreateWebUIControllerForURL(
581 WebUI* web_ui,
582 const GURL& url) const {
583 Profile* profile = Profile::FromWebUI(web_ui);
584 WebUIFactoryFunction function = GetWebUIFactoryFunction(web_ui, profile, url);
585 if (!function)
586 return NULL;
587
588 return (*function)(web_ui, url);
589 }
590
GetFaviconForURL(Profile * profile,const GURL & page_url,const std::vector<int> & desired_sizes_in_pixel,const favicon_base::FaviconResultsCallback & callback) const591 void ChromeWebUIControllerFactory::GetFaviconForURL(
592 Profile* profile,
593 const GURL& page_url,
594 const std::vector<int>& desired_sizes_in_pixel,
595 const favicon_base::FaviconResultsCallback& callback) const {
596 // Before determining whether page_url is an extension url, we must handle
597 // overrides. This changes urls in |kChromeUIScheme| to extension urls, and
598 // allows to use ExtensionWebUI::GetFaviconForURL.
599 GURL url(page_url);
600 #if defined(ENABLE_EXTENSIONS)
601 ExtensionWebUI::HandleChromeURLOverride(&url, profile);
602
603 // All extensions but the bookmark manager get their favicon from the icons
604 // part of the manifest.
605 if (url.SchemeIs(extensions::kExtensionScheme) &&
606 url.host() != extension_misc::kBookmarkManagerId) {
607 ExtensionWebUI::GetFaviconForURL(profile, url, callback);
608 return;
609 }
610 #endif
611
612 std::vector<favicon_base::FaviconRawBitmapResult>* favicon_bitmap_results =
613 new std::vector<favicon_base::FaviconRawBitmapResult>();
614
615 // Use ui::GetSupportedScaleFactors instead of
616 // favicon_base::GetFaviconScales() because chrome favicons comes from
617 // resources.
618 std::vector<ui::ScaleFactor> resource_scale_factors =
619 ui::GetSupportedScaleFactors();
620
621 std::vector<gfx::Size> candidate_sizes;
622 for (size_t i = 0; i < resource_scale_factors.size(); ++i) {
623 float scale = ui::GetScaleForScaleFactor(resource_scale_factors[i]);
624 // Assume that GetFaviconResourceBytes() returns favicons which are
625 // |gfx::kFaviconSize| x |gfx::kFaviconSize| DIP.
626 int candidate_edge_size =
627 static_cast<int>(gfx::kFaviconSize * scale + 0.5f);
628 candidate_sizes.push_back(
629 gfx::Size(candidate_edge_size, candidate_edge_size));
630 }
631 std::vector<size_t> selected_indices;
632 SelectFaviconFrameIndices(
633 candidate_sizes, desired_sizes_in_pixel, &selected_indices, NULL);
634 for (size_t i = 0; i < selected_indices.size(); ++i) {
635 size_t selected_index = selected_indices[i];
636 ui::ScaleFactor selected_resource_scale =
637 resource_scale_factors[selected_index];
638
639 scoped_refptr<base::RefCountedMemory> bitmap(
640 GetFaviconResourceBytes(url, selected_resource_scale));
641 if (bitmap.get() && bitmap->size()) {
642 favicon_base::FaviconRawBitmapResult bitmap_result;
643 bitmap_result.bitmap_data = bitmap;
644 // Leave |bitmap_result|'s icon URL as the default of GURL().
645 bitmap_result.icon_type = favicon_base::FAVICON;
646 favicon_bitmap_results->push_back(bitmap_result);
647
648 bitmap_result.pixel_size = candidate_sizes[selected_index];
649 }
650 }
651
652 RunFaviconCallbackAsync(callback, favicon_bitmap_results);
653 }
654
655 // static
GetInstance()656 ChromeWebUIControllerFactory* ChromeWebUIControllerFactory::GetInstance() {
657 return Singleton<ChromeWebUIControllerFactory>::get();
658 }
659
ChromeWebUIControllerFactory()660 ChromeWebUIControllerFactory::ChromeWebUIControllerFactory() {
661 }
662
~ChromeWebUIControllerFactory()663 ChromeWebUIControllerFactory::~ChromeWebUIControllerFactory() {
664 }
665
GetFaviconResourceBytes(const GURL & page_url,ui::ScaleFactor scale_factor) const666 base::RefCountedMemory* ChromeWebUIControllerFactory::GetFaviconResourceBytes(
667 const GURL& page_url, ui::ScaleFactor scale_factor) const {
668 #if !defined(OS_ANDROID) // Bookmarks are part of NTP on Android.
669 // The bookmark manager is a chrome extension, so we have to check for it
670 // before we check for extension scheme.
671 if (page_url.host() == extension_misc::kBookmarkManagerId)
672 return BookmarksUI::GetFaviconResourceBytes(scale_factor);
673
674 // The extension scheme is handled in GetFaviconForURL.
675 if (page_url.SchemeIs(extensions::kExtensionScheme)) {
676 NOTREACHED();
677 return NULL;
678 }
679 #endif
680
681 if (!content::HasWebUIScheme(page_url))
682 return NULL;
683
684 if (page_url.host() == chrome::kChromeUIComponentsHost)
685 return ComponentsUI::GetFaviconResourceBytes(scale_factor);
686
687 #if defined(OS_WIN)
688 if (page_url.host() == chrome::kChromeUIConflictsHost)
689 return ConflictsUI::GetFaviconResourceBytes(scale_factor);
690 #endif
691
692 if (page_url.host() == chrome::kChromeUICrashesHost)
693 return CrashesUI::GetFaviconResourceBytes(scale_factor);
694
695 if (page_url.host() == chrome::kChromeUIFlagsHost)
696 return FlagsUI::GetFaviconResourceBytes(scale_factor);
697
698 if (page_url.host() == chrome::kChromeUIHistoryHost)
699 return HistoryUI::GetFaviconResourceBytes(scale_factor);
700
701 #if !defined(OS_ANDROID)
702 // The Apps launcher page is not available on android.
703 if (page_url.host() == chrome::kChromeUIAppLauncherPageHost)
704 return AppLauncherPageUI::GetFaviconResourceBytes(scale_factor);
705
706 // Flash is not available on android.
707 if (page_url.host() == chrome::kChromeUIFlashHost)
708 return FlashUI::GetFaviconResourceBytes(scale_factor);
709
710 // Android uses the native download manager.
711 if (page_url.host() == chrome::kChromeUIDownloadsHost)
712 return DownloadsUI::GetFaviconResourceBytes(scale_factor);
713
714 // Android doesn't use the Options pages.
715 if (page_url.host() == chrome::kChromeUISettingsHost ||
716 page_url.host() == chrome::kChromeUISettingsFrameHost)
717 return options::OptionsUI::GetFaviconResourceBytes(scale_factor);
718
719 #if defined(ENABLE_EXTENSIONS)
720 if (page_url.host() == chrome::kChromeUIExtensionsHost ||
721 page_url.host() == chrome::kChromeUIExtensionsFrameHost)
722 return extensions::ExtensionsUI::GetFaviconResourceBytes(scale_factor);
723 #endif
724
725 // Android doesn't use the plugins pages.
726 if (page_url.host() == chrome::kChromeUIPluginsHost)
727 return PluginsUI::GetFaviconResourceBytes(scale_factor);
728
729 #endif
730
731 return NULL;
732 }
733