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
169using content::WebUI;
170using content::WebUIController;
171using ui::ExternalWebDialogUI;
172using ui::WebDialogUI;
173
174namespace {
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).
178typedef WebUIController* (*WebUIFactoryFunction)(WebUI* web_ui,
179                                                 const GURL& url);
180
181// Template for defining WebUIFactoryFunction.
182template<class T>
183WebUIController* 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.
189template<>
190WebUIController* 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.
197template<>
198WebUIController* NewWebUI<AboutUI>(WebUI* web_ui, const GURL& url) {
199  return new AboutUI(web_ui, url.host());
200}
201
202#if defined(OS_CHROMEOS)
203template<>
204WebUIController* 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.
210template<>
211WebUIController* 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.
227bool 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.
244WebUIFactoryFunction 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
545void 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
556WebUI::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
563bool ChromeWebUIControllerFactory::UseWebUIForURL(
564    content::BrowserContext* browser_context, const GURL& url) const {
565  return GetWebUIType(browser_context, url) != WebUI::kNoWebUI;
566}
567
568bool 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
580WebUIController* 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
591void 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
656ChromeWebUIControllerFactory* ChromeWebUIControllerFactory::GetInstance() {
657  return Singleton<ChromeWebUIControllerFactory>::get();
658}
659
660ChromeWebUIControllerFactory::ChromeWebUIControllerFactory() {
661}
662
663ChromeWebUIControllerFactory::~ChromeWebUIControllerFactory() {
664}
665
666base::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