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