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