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