chrome_web_ui_controller_factory.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
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 "base/bind.h"
8#include "base/command_line.h"
9#include "base/location.h"
10#include "base/message_loop/message_loop_proxy.h"
11#include "base/prefs/pref_service.h"
12#include "chrome/browser/about_flags.h"
13#include "chrome/browser/extensions/extension_service.h"
14#include "chrome/browser/extensions/extension_web_ui.h"
15#include "chrome/browser/history/history_types.h"
16#include "chrome/browser/profiles/profile.h"
17#include "chrome/browser/profiles/profile_manager.h"
18#include "chrome/browser/ui/webui/about_ui.h"
19#include "chrome/browser/ui/webui/app_launcher_page_ui.h"
20#include "chrome/browser/ui/webui/bookmarks_ui.h"
21#include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"
22#include "chrome/browser/ui/webui/crashes_ui.h"
23#include "chrome/browser/ui/webui/devtools_ui.h"
24#include "chrome/browser/ui/webui/downloads_ui.h"
25#include "chrome/browser/ui/webui/extensions/extension_info_ui.h"
26#include "chrome/browser/ui/webui/extensions/extensions_ui.h"
27#include "chrome/browser/ui/webui/feedback_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/help/help_ui.h"
31#include "chrome/browser/ui/webui/history_ui.h"
32#include "chrome/browser/ui/webui/identity_internals_ui.h"
33#include "chrome/browser/ui/webui/inline_login_ui.h"
34#include "chrome/browser/ui/webui/inspect_ui.h"
35#include "chrome/browser/ui/webui/instant_ui.h"
36#include "chrome/browser/ui/webui/local_discovery/local_discovery_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/ntp/new_tab_ui.h"
40#include "chrome/browser/ui/webui/omnibox/omnibox_ui.h"
41#include "chrome/browser/ui/webui/options/options_ui.h"
42#include "chrome/browser/ui/webui/performance_monitor/performance_monitor_ui.h"
43#include "chrome/browser/ui/webui/plugins_ui.h"
44#include "chrome/browser/ui/webui/predictors/predictors_ui.h"
45#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
46#include "chrome/browser/ui/webui/profiler_ui.h"
47#include "chrome/browser/ui/webui/quota_internals/quota_internals_ui.h"
48#include "chrome/browser/ui/webui/signin/profile_signin_confirmation_ui.h"
49#include "chrome/browser/ui/webui/signin/user_chooser_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/extensions/extension_constants.h"
57#include "chrome/common/extensions/feature_switch.h"
58#include "chrome/common/pref_names.h"
59#include "chrome/common/url_constants.h"
60#include "content/public/browser/web_contents.h"
61#include "content/public/browser/web_ui.h"
62#include "content/public/common/content_client.h"
63#include "content/public/common/url_utils.h"
64#include "extensions/common/constants.h"
65#include "ui/gfx/favicon_size.h"
66#include "ui/web_dialogs/web_dialog_ui.h"
67#include "url/gurl.h"
68
69#if !defined(DISABLE_NACL)
70#include "chrome/browser/ui/webui/nacl_ui.h"
71#endif
72
73#if defined(ENABLE_CONFIGURATION_POLICY)
74#include "chrome/browser/ui/webui/policy_ui.h"
75#endif
76
77#if defined(ENABLE_WEBRTC)
78#include "chrome/browser/ui/webui/media/webrtc_logs_ui.h"
79#endif
80
81#if defined(OS_ANDROID)
82#include "chrome/browser/ui/webui/welcome_ui_android.h"
83#else
84#include "chrome/browser/ui/webui/suggestions_internals/suggestions_internals_ui.h"
85#include "chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_ui.h"
86#include "chrome/browser/ui/webui/uber/uber_ui.h"
87#endif
88
89#if defined(OS_ANDROID) || defined(OS_IOS)
90#include "chrome/browser/ui/webui/net_export_ui.h"
91#endif
92
93#if defined(OS_CHROMEOS)
94#include "chrome/browser/ui/webui/chromeos/app_launch_ui.h"
95#include "chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui.h"
96#include "chrome/browser/ui/webui/chromeos/choose_mobile_network_ui.h"
97#include "chrome/browser/ui/webui/chromeos/cryptohome_ui.h"
98#include "chrome/browser/ui/webui/chromeos/diagnostics/diagnostics_ui.h"
99#include "chrome/browser/ui/webui/chromeos/drive_internals_ui.h"
100#include "chrome/browser/ui/webui/chromeos/imageburner/imageburner_ui.h"
101#include "chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.h"
102#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
103#include "chrome/browser/ui/webui/chromeos/mobile_setup_ui.h"
104#include "chrome/browser/ui/webui/chromeos/proxy_settings_ui.h"
105#include "chrome/browser/ui/webui/chromeos/salsa_ui.h"
106#include "chrome/browser/ui/webui/chromeos/sim_unlock_ui.h"
107#include "chrome/browser/ui/webui/chromeos/system_info_ui.h"
108#endif
109
110#if defined(USE_AURA)
111#include "chrome/browser/ui/webui/gesture_config_ui.h"
112#include "ui/keyboard/keyboard_constants.h"
113#include "ui/keyboard/keyboard_ui_controller.h"
114#endif
115
116#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
117#include "chrome/browser/ui/sync/sync_promo_ui.h"
118#endif
119
120#if defined(OS_WIN)
121#include "chrome/browser/ui/webui/conflicts_ui.h"
122#include "chrome/browser/ui/webui/set_as_default_browser_ui.h"
123#endif
124
125#if (defined(USE_NSS) || defined(USE_OPENSSL)) && defined(USE_AURA)
126#include "chrome/browser/ui/webui/certificate_viewer_ui.h"
127#endif
128
129using content::WebUI;
130using content::WebUIController;
131using ui::ExternalWebDialogUI;
132using ui::WebDialogUI;
133
134namespace {
135
136// A function for creating a new WebUI. The caller owns the return value, which
137// may be NULL (for example, if the URL refers to an non-existent extension).
138typedef WebUIController* (*WebUIFactoryFunction)(WebUI* web_ui,
139                                                 const GURL& url);
140
141// Template for defining WebUIFactoryFunction.
142template<class T>
143WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) {
144  return new T(web_ui);
145}
146
147// Special cases for extensions.
148template<>
149WebUIController* NewWebUI<ExtensionWebUI>(WebUI* web_ui,
150                                          const GURL& url) {
151  return new ExtensionWebUI(web_ui, url);
152}
153
154template<>
155WebUIController* NewWebUI<ExtensionInfoUI>(WebUI* web_ui,
156                                           const GURL& url) {
157  return new ExtensionInfoUI(web_ui, url);
158}
159
160// Special case for older about: handlers.
161template<>
162WebUIController* NewWebUI<AboutUI>(WebUI* web_ui, const GURL& url) {
163  return new AboutUI(web_ui, url.host());
164}
165
166// Only create ExtensionWebUI for URLs that are allowed extension bindings,
167// hosted by actual tabs.
168bool NeedsExtensionWebUI(Profile* profile, const GURL& url) {
169  ExtensionService* service = profile ? profile->GetExtensionService() : NULL;
170  return service && service->ExtensionBindingsAllowed(url);
171}
172
173// Returns a function that can be used to create the right type of WebUI for a
174// tab, based on its URL. Returns NULL if the URL doesn't have WebUI associated
175// with it.
176WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
177                                             Profile* profile,
178                                             const GURL& url) {
179#if defined(ENABLE_EXTENSIONS)
180  if (NeedsExtensionWebUI(profile, url))
181    return &NewWebUI<ExtensionWebUI>;
182#endif
183
184  // This will get called a lot to check all URLs, so do a quick check of other
185  // schemes to filter out most URLs.
186  if (!url.SchemeIs(chrome::kChromeDevToolsScheme) &&
187      !url.SchemeIs(chrome::kChromeInternalScheme) &&
188      !url.SchemeIs(chrome::kChromeUIScheme)) {
189    return NULL;
190  }
191
192  // Special case the new tab page. In older versions of Chrome, the new tab
193  // page was hosted at chrome-internal:<blah>. This might be in people's saved
194  // sessions or bookmarks, so we say any URL with that scheme triggers the new
195  // tab page.
196  if (url.host() == chrome::kChromeUINewTabHost ||
197      url.SchemeIs(chrome::kChromeInternalScheme)) {
198    return &NewWebUI<NewTabUI>;
199  }
200
201  /****************************************************************************
202   * Please keep this in alphabetical order. If #ifs or special logics are
203   * required, add it below in the appropriate section.
204   ***************************************************************************/
205  // We must compare hosts only since some of the Web UIs append extra stuff
206  // after the host name.
207  // All platform builds of Chrome will need to have a cloud printing
208  // dialog as backup.  It's just that on Chrome OS, it's the only
209  // print dialog.
210  if (url.host() == chrome::kChromeUICloudPrintResourcesHost)
211    return &NewWebUI<ExternalWebDialogUI>;
212  if (url.host() == chrome::kChromeUICloudPrintSetupHost)
213    return &NewWebUI<WebDialogUI>;
214  if (url.spec() == chrome::kChromeUIConstrainedHTMLTestURL)
215    return &NewWebUI<ConstrainedWebDialogUI>;
216  if (url.host() == chrome::kChromeUICrashesHost)
217    return &NewWebUI<CrashesUI>;
218  if (url.host() == chrome::kChromeUIDevicesHost &&
219      CommandLine::ForCurrentProcess()->HasSwitch(
220            switches::kEnableDeviceDiscovery)) {
221    return &NewWebUI<LocalDiscoveryUI>;
222  }
223  if (url.host() == chrome::kChromeUIFlagsHost)
224    return &NewWebUI<FlagsUI>;
225  if (url.host() == chrome::kChromeUIHistoryFrameHost)
226    return &NewWebUI<HistoryUI>;
227  if (url.host() == chrome::kChromeUIInlineLoginHost)
228    return &NewWebUI<InlineLoginUI>;
229  if (url.host() == chrome::kChromeUIInstantHost)
230    return &NewWebUI<InstantUI>;
231  if (url.host() == chrome::kChromeUIManagedUserPassphrasePageHost)
232    return &NewWebUI<ConstrainedWebDialogUI>;
233  if (url.host() == chrome::kChromeUIMemoryInternalsHost)
234    return &NewWebUI<MemoryInternalsUI>;
235#if !defined(DISABLE_NACL)
236  if (url.host() == chrome::kChromeUINaClHost)
237    return &NewWebUI<NaClUI>;
238#endif
239#if defined(OS_ANDROID) || defined(OS_IOS)
240  if (url.host() == chrome::kChromeUINetExportHost)
241    return &NewWebUI<NetExportUI>;
242#endif
243  if (url.host() == chrome::kChromeUINetInternalsHost)
244    return &NewWebUI<NetInternalsUI>;
245  if (url.host() == chrome::kChromeUIOmniboxHost)
246    return &NewWebUI<OmniboxUI>;
247  if (url.host() == chrome::kChromeUIPredictorsHost)
248    return &NewWebUI<PredictorsUI>;
249  if (url.host() == chrome::kChromeUIProfilerHost)
250    return &NewWebUI<ProfilerUI>;
251  if (url.host() == chrome::kChromeUIQuotaInternalsHost)
252    return &NewWebUI<QuotaInternalsUI>;
253  if (url.host() == chrome::kChromeUISignInInternalsHost)
254    return &NewWebUI<SignInInternalsUI>;
255  if (url.host() == chrome::kChromeUISyncInternalsHost)
256    return &NewWebUI<SyncInternalsUI>;
257  if (url.host() == chrome::kChromeUISyncResourcesHost)
258    return &NewWebUI<WebDialogUI>;
259  if (url.host() == chrome::kChromeUITranslateInternalsHost)
260    return &NewWebUI<TranslateInternalsUI>;
261  if (url.host() == chrome::kChromeUIUserActionsHost)
262    return &NewWebUI<UserActionsUI>;
263  if (url.host() == chrome::kChromeUIVersionHost)
264    return &NewWebUI<VersionUI>;
265#if defined(ENABLE_WEBRTC)
266  if (url.host() == chrome::kChromeUIWebRtcLogsHost)
267    return &NewWebUI<WebRtcLogsUI>;
268#endif
269
270  /****************************************************************************
271   * OS Specific #defines
272   ***************************************************************************/
273#if defined(OS_ANDROID)
274  if (url.host() == chrome::kChromeUIWelcomeHost)
275    return &NewWebUI<WelcomeUI>;
276#else
277  // AppLauncherPage is not needed on Android.
278  if (url.host() == chrome::kChromeUIAppLauncherPageHost &&
279      profile && profile->GetExtensionService()) {
280    return &NewWebUI<AppLauncherPageUI>;
281  }
282  // Bookmarks are part of NTP on Android.
283  if (url.host() == chrome::kChromeUIBookmarksHost)
284    return &NewWebUI<BookmarksUI>;
285  if (url.SchemeIs(chrome::kChromeDevToolsScheme))
286    return &NewWebUI<DevToolsUI>;
287  // Downloads list on Android uses the built-in download manager.
288  if (url.host() == chrome::kChromeUIDownloadsHost)
289    return &NewWebUI<DownloadsUI>;
290  // Feedback on Android uses the built-in feedback app.
291  if (url.host() == chrome::kChromeUIFeedbackHost)
292    return &NewWebUI<FeedbackUI>;
293  // Flash is not available on android.
294  if (url.host() == chrome::kChromeUIFlashHost)
295    return &NewWebUI<FlashUI>;
296  // Help is implemented with native UI elements on Android.
297  if (url.host() == chrome::kChromeUIHelpFrameHost)
298    return &NewWebUI<HelpUI>;
299  // Identity API is not available on Android.
300  if (url.host() == chrome::kChromeUIIdentityInternalsHost)
301    return &NewWebUI<IdentityInternalsUI>;
302  // chrome://inspect isn't supported on Android. Page debugging is handled by a
303  // remote devtools on the host machine, and other elements (Shared Workers,
304  // extensions, etc) aren't supported.
305  if (url.host() == chrome::kChromeUIInspectHost)
306    return &NewWebUI<InspectUI>;
307  // Performance monitoring page is not on Android for now.
308  if (url.host() == chrome::kChromeUIPerformanceMonitorHost)
309    return &NewWebUI<performance_monitor::PerformanceMonitorUI>;
310  // Android does not support plugins for now.
311  if (url.host() == chrome::kChromeUIPluginsHost)
312    return &NewWebUI<PluginsUI>;
313  // Settings are implemented with native UI elements on Android.
314  if (url.host() == chrome::kChromeUISettingsFrameHost)
315    return &NewWebUI<options::OptionsUI>;
316  if (url.host() == chrome::kChromeUISuggestionsInternalsHost)
317    return &NewWebUI<SuggestionsInternalsUI>;
318  if (url.host() == chrome::kChromeUISyncFileSystemInternalsHost)
319    return &NewWebUI<SyncFileSystemInternalsUI>;
320  // Uber frame is not used on Android.
321  if (url.host() == chrome::kChromeUIUberFrameHost)
322    return &NewWebUI<UberFrameUI>;
323  // Uber page is not used on Android.
324  if (url.host() == chrome::kChromeUIUberHost)
325    return &NewWebUI<UberUI>;
326#endif
327#if defined(OS_WIN)
328  if (url.host() == chrome::kChromeUIConflictsHost)
329    return &NewWebUI<ConflictsUI>;
330  if (url.host() == chrome::kChromeUIMetroFlowHost)
331    return &NewWebUI<SetAsDefaultBrowserUI>;
332#endif
333#if (defined(USE_NSS) || defined(USE_OPENSSL)) && defined(USE_AURA)
334  if (url.host() == chrome::kChromeUICertificateViewerHost)
335    return &NewWebUI<CertificateViewerUI>;
336#endif
337#if defined(OS_CHROMEOS)
338  if (url.host() == chrome::kChromeUIAppLaunchHost)
339    return &NewWebUI<chromeos::AppLaunchUI>;
340  if (url.host() == chrome::kChromeUIBluetoothPairingHost)
341    return &NewWebUI<chromeos::BluetoothPairingUI>;
342  if (url.host() == chrome::kChromeUIChooseMobileNetworkHost)
343    return &NewWebUI<chromeos::ChooseMobileNetworkUI>;
344  if (url.host() == chrome::kChromeUICryptohomeHost)
345    return &NewWebUI<chromeos::CryptohomeUI>;
346  if (url.host() == chrome::kChromeUIDriveInternalsHost)
347    return &NewWebUI<chromeos::DriveInternalsUI>;
348  if (url.host() == chrome::kChromeUIDiagnosticsHost)
349    return &NewWebUI<chromeos::DiagnosticsUI>;
350  if (url.host() == chrome::kChromeUIImageBurnerHost)
351    return &NewWebUI<ImageBurnUI>;
352  if (url.host() == chrome::kChromeUIKeyboardOverlayHost)
353    return &NewWebUI<KeyboardOverlayUI>;
354  if (url.host() == chrome::kChromeUIMobileSetupHost)
355    return &NewWebUI<MobileSetupUI>;
356  if (url.host() == chrome::kChromeUIOobeHost)
357    return &NewWebUI<chromeos::OobeUI>;
358  if (url.host() == chrome::kChromeUIProxySettingsHost)
359    return &NewWebUI<chromeos::ProxySettingsUI>;
360  if (url.host() == chrome::kChromeUISalsaHost)
361    return &NewWebUI<SalsaUI>;
362  if (url.host() == chrome::kChromeUISimUnlockHost)
363    return &NewWebUI<chromeos::SimUnlockUI>;
364  if (url.host() == chrome::kChromeUISystemInfoHost)
365    return &NewWebUI<chromeos::SystemInfoUI>;
366#endif  // defined(OS_CHROMEOS)
367
368  /****************************************************************************
369   * Other #defines and special logics.
370   ***************************************************************************/
371#if defined(ENABLE_CONFIGURATION_POLICY)
372  if (url.host() == chrome::kChromeUIPolicyHost)
373    return &NewWebUI<PolicyUI>;
374
375#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
376  if (url.host() == chrome::kChromeUIProfileSigninConfirmationHost)
377    return &NewWebUI<ProfileSigninConfirmationUI>;
378#endif
379
380#endif  // defined(ENABLE_CONFIGURATION_POLICY)
381
382#if (defined(OS_LINUX) && defined(TOOLKIT_VIEWS)) || defined(USE_AURA)
383  if (url.host() == chrome::kChromeUITabModalConfirmDialogHost) {
384    return &NewWebUI<ConstrainedWebDialogUI>;
385  }
386#endif
387
388#if defined(USE_AURA)
389  if (url.host() == chrome::kChromeUIGestureConfigHost)
390    return &NewWebUI<GestureConfigUI>;
391  if (url.host() == keyboard::kKeyboardWebUIHost)
392    return &NewWebUI<keyboard::KeyboardUIController>;
393#endif
394
395#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_IOS)
396  if (url.host() == chrome::kChromeUIUserChooserHost &&
397      CommandLine::ForCurrentProcess()->HasSwitch(
398          switches::kNewProfileManagement))
399    return &NewWebUI<UserChooserUI>;
400#endif
401
402  if (url.host() == chrome::kChromeUIChromeURLsHost ||
403      url.host() == chrome::kChromeUICreditsHost ||
404      url.host() == chrome::kChromeUIDNSHost ||
405      url.host() == chrome::kChromeUIMemoryHost ||
406      url.host() == chrome::kChromeUIMemoryRedirectHost ||
407      url.host() == chrome::kChromeUIStatsHost ||
408      url.host() == chrome::kChromeUITermsHost
409#if defined(OS_LINUX) || defined(OS_OPENBSD)
410      || url.host() == chrome::kChromeUILinuxProxyConfigHost
411      || url.host() == chrome::kChromeUISandboxHost
412#endif
413#if defined(OS_CHROMEOS)
414      || url.host() == chrome::kChromeUIDiscardsHost
415      || url.host() == chrome::kChromeUINetworkHost
416      || url.host() == chrome::kChromeUIOSCreditsHost
417      || url.host() == chrome::kChromeUITransparencyHost
418#endif
419#if defined(WEBUI_TASK_MANAGER)
420      || url.host() == chrome::kChromeUITaskManagerHost
421#endif
422      ) {
423    return &NewWebUI<AboutUI>;
424  }
425
426#if defined(ENABLE_EXTENSIONS)
427  if (url.host() == chrome::kChromeUIExtensionInfoHost &&
428      extensions::FeatureSwitch::script_badges()->IsEnabled()) {
429    return &NewWebUI<ExtensionInfoUI>;
430  }
431  if (url.host() == chrome::kChromeUIExtensionsFrameHost)
432    return &NewWebUI<ExtensionsUI>;
433#endif
434#if defined(ENABLE_PRINTING)
435  if (url.host() == chrome::kChromeUIPrintHost &&
436      !profile->GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled))
437    return &NewWebUI<PrintPreviewUI>;
438#endif
439
440  return NULL;
441}
442
443void RunFaviconCallbackAsync(
444    const FaviconService::FaviconResultsCallback& callback,
445    const std::vector<chrome::FaviconBitmapResult>* results) {
446  base::MessageLoopProxy::current()->PostTask(
447      FROM_HERE,
448      base::Bind(&FaviconService::FaviconResultsCallbackRunner,
449                 callback, base::Owned(results)));
450}
451
452}  // namespace
453
454WebUI::TypeID ChromeWebUIControllerFactory::GetWebUIType(
455      content::BrowserContext* browser_context, const GURL& url) const {
456  Profile* profile = Profile::FromBrowserContext(browser_context);
457  WebUIFactoryFunction function = GetWebUIFactoryFunction(NULL, profile, url);
458  return function ? reinterpret_cast<WebUI::TypeID>(function) : WebUI::kNoWebUI;
459}
460
461bool ChromeWebUIControllerFactory::UseWebUIForURL(
462    content::BrowserContext* browser_context, const GURL& url) const {
463  return GetWebUIType(browser_context, url) != WebUI::kNoWebUI;
464}
465
466bool ChromeWebUIControllerFactory::UseWebUIBindingsForURL(
467    content::BrowserContext* browser_context, const GURL& url) const {
468  // Extensions are rendered via WebUI in tabs, but don't actually need WebUI
469  // bindings (see the ExtensionWebUI constructor).
470  return
471      !NeedsExtensionWebUI(Profile::FromBrowserContext(browser_context), url) &&
472      UseWebUIForURL(browser_context, url);
473}
474
475WebUIController* ChromeWebUIControllerFactory::CreateWebUIControllerForURL(
476    WebUI* web_ui,
477    const GURL& url) const {
478  Profile* profile = Profile::FromWebUI(web_ui);
479  WebUIFactoryFunction function = GetWebUIFactoryFunction(web_ui, profile, url);
480  if (!function)
481    return NULL;
482
483  return (*function)(web_ui, url);
484}
485
486void ChromeWebUIControllerFactory::GetFaviconForURL(
487    Profile* profile,
488    const GURL& page_url,
489    const std::vector<ui::ScaleFactor>& scale_factors,
490    const FaviconService::FaviconResultsCallback& callback) const {
491  // Before determining whether page_url is an extension url, we must handle
492  // overrides. This changes urls in |kChromeUIScheme| to extension urls, and
493  // allows to use ExtensionWebUI::GetFaviconForURL.
494  GURL url(page_url);
495  ExtensionWebUI::HandleChromeURLOverride(&url, profile);
496
497  // All extensions but the bookmark manager get their favicon from the icons
498  // part of the manifest.
499  if (url.SchemeIs(extensions::kExtensionScheme) &&
500      url.host() != extension_misc::kBookmarkManagerId) {
501#if defined(ENABLE_EXTENSIONS)
502    ExtensionWebUI::GetFaviconForURL(profile, url, callback);
503#else
504    RunFaviconCallbackAsync(callback,
505                            new std::vector<chrome::FaviconBitmapResult>());
506#endif
507    return;
508  }
509
510  std::vector<chrome::FaviconBitmapResult>* favicon_bitmap_results =
511      new std::vector<chrome::FaviconBitmapResult>();
512
513  for (size_t i = 0; i < scale_factors.size(); ++i) {
514    scoped_refptr<base::RefCountedMemory> bitmap(GetFaviconResourceBytes(
515          url, scale_factors[i]));
516    if (bitmap.get() && bitmap->size()) {
517      chrome::FaviconBitmapResult bitmap_result;
518      bitmap_result.bitmap_data = bitmap;
519      // Leave |bitmap_result|'s icon URL as the default of GURL().
520      bitmap_result.icon_type = chrome::FAVICON;
521      favicon_bitmap_results->push_back(bitmap_result);
522
523      // Assume that |bitmap| is |gfx::kFaviconSize| x |gfx::kFaviconSize|
524      // DIP.
525      float scale = ui::GetScaleFactorScale(scale_factors[i]);
526      int edge_pixel_size =
527          static_cast<int>(gfx::kFaviconSize * scale + 0.5f);
528      bitmap_result.pixel_size = gfx::Size(edge_pixel_size, edge_pixel_size);
529    }
530  }
531
532  RunFaviconCallbackAsync(callback, favicon_bitmap_results);
533}
534
535// static
536ChromeWebUIControllerFactory* ChromeWebUIControllerFactory::GetInstance() {
537  return Singleton<ChromeWebUIControllerFactory>::get();
538}
539
540ChromeWebUIControllerFactory::ChromeWebUIControllerFactory() {
541}
542
543ChromeWebUIControllerFactory::~ChromeWebUIControllerFactory() {
544}
545
546base::RefCountedMemory* ChromeWebUIControllerFactory::GetFaviconResourceBytes(
547    const GURL& page_url, ui::ScaleFactor scale_factor) const {
548#if !defined(OS_ANDROID)  // Bookmarks are part of NTP on Android.
549  // The bookmark manager is a chrome extension, so we have to check for it
550  // before we check for extension scheme.
551  if (page_url.host() == extension_misc::kBookmarkManagerId)
552    return BookmarksUI::GetFaviconResourceBytes(scale_factor);
553
554  // The extension scheme is handled in GetFaviconForURL.
555  if (page_url.SchemeIs(extensions::kExtensionScheme)) {
556    NOTREACHED();
557    return NULL;
558  }
559#endif
560
561  if (!content::HasWebUIScheme(page_url))
562    return NULL;
563
564#if defined(OS_WIN)
565  if (page_url.host() == chrome::kChromeUIConflictsHost)
566    return ConflictsUI::GetFaviconResourceBytes(scale_factor);
567#endif
568
569  if (page_url.host() == chrome::kChromeUICrashesHost)
570    return CrashesUI::GetFaviconResourceBytes(scale_factor);
571
572  if (page_url.host() == chrome::kChromeUIFlagsHost)
573    return FlagsUI::GetFaviconResourceBytes(scale_factor);
574
575  if (page_url.host() == chrome::kChromeUIHistoryHost)
576    return HistoryUI::GetFaviconResourceBytes(scale_factor);
577
578#if !defined(OS_ANDROID)
579  // The Apps launcher page is not available on android.
580  if (page_url.host() == chrome::kChromeUIAppLauncherPageHost)
581    return AppLauncherPageUI::GetFaviconResourceBytes(scale_factor);
582
583  // Flash is not available on android.
584  if (page_url.host() == chrome::kChromeUIFlashHost)
585    return FlashUI::GetFaviconResourceBytes(scale_factor);
586
587  // Android uses the native download manager.
588  if (page_url.host() == chrome::kChromeUIDownloadsHost)
589    return DownloadsUI::GetFaviconResourceBytes(scale_factor);
590
591  // Android doesn't use the Options pages.
592  if (page_url.host() == chrome::kChromeUISettingsFrameHost)
593    return options::OptionsUI::GetFaviconResourceBytes(scale_factor);
594
595  // Android doesn't use the plugins pages.
596  if (page_url.host() == chrome::kChromeUIPluginsHost)
597    return PluginsUI::GetFaviconResourceBytes(scale_factor);
598#endif
599
600  return NULL;
601}
602