1 // Copyright (c) 2011 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_factory.h" 6 7 #include "base/command_line.h" 8 #include "chrome/browser/about_flags.h" 9 #include "chrome/browser/extensions/extension_service.h" 10 #include "chrome/browser/extensions/extension_web_ui.h" 11 #include "chrome/browser/extensions/extensions_ui.h" 12 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/ui/webui/bookmarks_ui.h" 14 #include "chrome/browser/ui/webui/bug_report_ui.h" 15 #include "chrome/browser/ui/webui/constrained_html_ui.h" 16 #include "chrome/browser/ui/webui/crashes_ui.h" 17 #include "chrome/browser/ui/webui/devtools_ui.h" 18 #include "chrome/browser/ui/webui/downloads_ui.h" 19 #include "chrome/browser/ui/webui/flags_ui.h" 20 #include "chrome/browser/ui/webui/gpu_internals_ui.h" 21 #include "chrome/browser/ui/webui/history2_ui.h" 22 #include "chrome/browser/ui/webui/history_ui.h" 23 #include "chrome/browser/ui/webui/html_dialog_ui.h" 24 #include "chrome/browser/ui/webui/net_internals_ui.h" 25 #include "chrome/browser/ui/webui/new_tab_ui.h" 26 #include "chrome/browser/ui/webui/options/options_ui.h" 27 #include "chrome/browser/ui/webui/plugins_ui.h" 28 #include "chrome/browser/ui/webui/print_preview_ui.h" 29 #include "chrome/browser/ui/webui/remoting_ui.h" 30 #include "chrome/browser/ui/webui/sync_internals_ui.h" 31 #include "chrome/browser/ui/webui/textfields_ui.h" 32 #include "chrome/common/chrome_switches.h" 33 #include "chrome/common/extensions/extension_constants.h" 34 #include "chrome/common/url_constants.h" 35 #include "content/browser/tab_contents/tab_contents.h" 36 #include "content/browser/webui/web_ui.h" 37 #include "googleurl/src/gurl.h" 38 39 #if defined(OS_CHROMEOS) 40 #include "chrome/browser/ui/webui/chromeos/choose_mobile_network_ui.h" 41 #include "chrome/browser/ui/webui/chromeos/enterprise_enrollment_ui.h" 42 #include "chrome/browser/ui/webui/chromeos/imageburner_ui.h" 43 #include "chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.h" 44 #include "chrome/browser/ui/webui/chromeos/mobile_setup_ui.h" 45 #include "chrome/browser/ui/webui/chromeos/proxy_settings_ui.h" 46 #include "chrome/browser/ui/webui/chromeos/register_page_ui.h" 47 #include "chrome/browser/ui/webui/chromeos/sim_unlock_ui.h" 48 #include "chrome/browser/ui/webui/chromeos/system_info_ui.h" 49 #include "chrome/browser/ui/webui/active_downloads_ui.h" 50 #include "chrome/browser/ui/webui/mediaplayer_ui.h" 51 #endif 52 53 #if defined(TOUCH_UI) 54 #include "chrome/browser/ui/webui/keyboard_ui.h" 55 #endif 56 57 #if defined(TOUCH_UI) && defined(OS_CHROMEOS) 58 #include "chrome/browser/ui/webui/chromeos/login/login_ui.h" 59 #endif 60 61 #if defined(OS_WIN) 62 #include "chrome/browser/ui/webui/conflicts_ui.h" 63 #endif 64 65 namespace { 66 67 // A function for creating a new WebUI. The caller owns the return value, which 68 // may be NULL (for example, if the URL refers to an non-existent extension). 69 typedef WebUI* (*WebUIFactoryFunction)(TabContents* tab_contents, 70 const GURL& url); 71 72 // Template for defining WebUIFactoryFunction. 73 template<class T> 74 WebUI* NewWebUI(TabContents* contents, const GURL& url) { 75 return new T(contents); 76 } 77 78 // Special case for extensions. 79 template<> 80 WebUI* NewWebUI<ExtensionWebUI>(TabContents* contents, const GURL& url) { 81 // Don't use a WebUI for incognito tabs because we require extensions to run 82 // within a single process. 83 ExtensionService* service = contents->profile()->GetExtensionService(); 84 if (service && 85 service->ExtensionBindingsAllowed(url)) { 86 return new ExtensionWebUI(contents, url); 87 } 88 return NULL; 89 } 90 91 // Returns a function that can be used to create the right type of WebUI for a 92 // tab, based on its URL. Returns NULL if the URL doesn't have WebUI associated 93 // with it. Even if the factory function is valid, it may yield a NULL WebUI 94 // when invoked for a particular tab - see NewWebUI<ExtensionWebUI>. 95 static WebUIFactoryFunction GetWebUIFactoryFunction(Profile* profile, 96 const GURL& url) { 97 if (url.host() == chrome::kChromeUIDialogHost) 98 return &NewWebUI<ConstrainedHtmlUI>; 99 100 ExtensionService* service = profile ? profile->GetExtensionService() : NULL; 101 if (service && service->ExtensionBindingsAllowed(url)) 102 return &NewWebUI<ExtensionWebUI>; 103 104 // All platform builds of Chrome will need to have a cloud printing 105 // dialog as backup. It's just that on Chrome OS, it's the only 106 // print dialog. 107 if (url.host() == chrome::kCloudPrintResourcesHost) 108 return &NewWebUI<ExternalHtmlDialogUI>; 109 110 // This will get called a lot to check all URLs, so do a quick check of other 111 // schemes to filter out most URLs. 112 if (!url.SchemeIs(chrome::kChromeDevToolsScheme) && 113 !url.SchemeIs(chrome::kChromeInternalScheme) && 114 !url.SchemeIs(chrome::kChromeUIScheme)) 115 return NULL; 116 117 if (url.host() == chrome::kChromeUISyncResourcesHost || 118 url.host() == chrome::kChromeUIRemotingResourcesHost || 119 url.host() == chrome::kCloudPrintSetupHost) 120 return &NewWebUI<HtmlDialogUI>; 121 122 // Special case the new tab page. In older versions of Chrome, the new tab 123 // page was hosted at chrome-internal:<blah>. This might be in people's saved 124 // sessions or bookmarks, so we say any URL with that scheme triggers the new 125 // tab page. 126 if (url.host() == chrome::kChromeUINewTabHost || 127 url.SchemeIs(chrome::kChromeInternalScheme)) 128 return &NewWebUI<NewTabUI>; 129 130 // Give about:about a generic Web UI so it can navigate to pages with Web UIs. 131 if (url.spec() == chrome::kChromeUIAboutAboutURL) 132 return &NewWebUI<WebUI>; 133 134 // We must compare hosts only since some of the Web UIs append extra stuff 135 // after the host name. 136 if (url.host() == chrome::kChromeUIBookmarksHost) 137 return &NewWebUI<BookmarksUI>; 138 if (url.host() == chrome::kChromeUIBugReportHost) 139 return &NewWebUI<BugReportUI>; 140 if (url.host() == chrome::kChromeUICrashesHost) 141 return &NewWebUI<CrashesUI>; 142 if (url.host() == chrome::kChromeUIDevToolsHost) 143 return &NewWebUI<DevToolsUI>; 144 #if defined(OS_WIN) 145 if (url.host() == chrome::kChromeUIConflictsHost) 146 return &NewWebUI<ConflictsUI>; 147 #endif 148 if (url.host() == chrome::kChromeUIDownloadsHost) 149 return &NewWebUI<DownloadsUI>; 150 if (url.host() == chrome::kChromeUITextfieldsHost) 151 return &NewWebUI<TextfieldsUI>; 152 if (url.host() == chrome::kChromeUIExtensionsHost) 153 return &NewWebUI<ExtensionsUI>; 154 if (url.host() == chrome::kChromeUIHistoryHost) 155 return &NewWebUI<HistoryUI>; 156 if (url.host() == chrome::kChromeUIHistory2Host) 157 return &NewWebUI<HistoryUI2>; 158 if (url.host() == chrome::kChromeUIFlagsHost) 159 return &NewWebUI<FlagsUI>; 160 #if defined(TOUCH_UI) 161 if (url.host() == chrome::kChromeUIKeyboardHost) 162 return &NewWebUI<KeyboardUI>; 163 #endif 164 if (url.host() == chrome::kChromeUIGpuInternalsHost) 165 return &NewWebUI<GpuInternalsUI>; 166 if (url.host() == chrome::kChromeUINetInternalsHost) 167 return &NewWebUI<NetInternalsUI>; 168 if (url.host() == chrome::kChromeUIPluginsHost) 169 return &NewWebUI<PluginsUI>; 170 if (url.host() == chrome::kChromeUISyncInternalsHost) 171 return &NewWebUI<SyncInternalsUI>; 172 #if defined(ENABLE_REMOTING) 173 if (url.host() == chrome::kChromeUIRemotingHost) { 174 if (CommandLine::ForCurrentProcess()->HasSwitch( 175 switches::kEnableRemoting)) { 176 return &NewWebUI<RemotingUI>; 177 } 178 } 179 #endif 180 181 #if defined(OS_CHROMEOS) 182 if (url.host() == chrome::kChromeUIChooseMobileNetworkHost) 183 return &NewWebUI<chromeos::ChooseMobileNetworkUI>; 184 if (url.host() == chrome::kChromeUICollectedCookiesHost || 185 url.host() == chrome::kChromeUIHttpAuthHost) { 186 return &NewWebUI<ConstrainedHtmlUI>; 187 } 188 if (url.host() == chrome::kChromeUIActiveDownloadsHost) 189 return &NewWebUI<ActiveDownloadsUI>; 190 if (url.host() == chrome::kChromeUIImageBurnerHost) 191 return &NewWebUI<ImageBurnUI>; 192 if (url.host() == chrome::kChromeUIKeyboardOverlayHost) 193 return &NewWebUI<KeyboardOverlayUI>; 194 if (url.host() == chrome::kChromeUIMediaplayerHost) 195 return &NewWebUI<MediaplayerUI>; 196 if (url.host() == chrome::kChromeUIMobileSetupHost) 197 return &NewWebUI<MobileSetupUI>; 198 if (url.host() == chrome::kChromeUIProxySettingsHost) 199 return &NewWebUI<chromeos::ProxySettingsUI>; 200 if (url.host() == chrome::kChromeUIRegisterPageHost) 201 return &NewWebUI<RegisterPageUI>; 202 if (url.host() == chrome::kChromeUISettingsHost) 203 return &NewWebUI<OptionsUI>; 204 if (url.host() == chrome::kChromeUISimUnlockHost) 205 return &NewWebUI<chromeos::SimUnlockUI>; 206 if (url.host() == chrome::kChromeUISystemInfoHost) 207 return &NewWebUI<SystemInfoUI>; 208 if (url.host() == chrome::kChromeUIEnterpriseEnrollmentHost) 209 return &NewWebUI<chromeos::EnterpriseEnrollmentUI>; 210 #else 211 if (url.host() == chrome::kChromeUISettingsHost) 212 return &NewWebUI<OptionsUI>; 213 if (url.host() == chrome::kChromeUIPrintHost) { 214 if (CommandLine::ForCurrentProcess()->HasSwitch( 215 switches::kEnablePrintPreview)) { 216 return &NewWebUI<PrintPreviewUI>; 217 } 218 } 219 #endif // defined(OS_CHROMEOS) 220 221 #if defined(TOUCH_UI) && defined(OS_CHROMEOS) 222 if (url.host() == chrome::kChromeUILoginHost) 223 return &NewWebUI<chromeos::LoginUI>; 224 #endif 225 226 if (url.spec() == chrome::kChromeUIConstrainedHTMLTestURL) 227 return &NewWebUI<ConstrainedHtmlUI>; 228 229 return NULL; 230 } 231 232 } // namespace 233 234 WebUI::TypeID ChromeWebUIFactory::GetWebUIType(Profile* profile, 235 const GURL& url) const { 236 WebUIFactoryFunction function = GetWebUIFactoryFunction(profile, url); 237 return function ? reinterpret_cast<WebUI::TypeID>(function) : WebUI::kNoWebUI; 238 } 239 240 bool ChromeWebUIFactory::UseWebUIForURL(Profile* profile, 241 const GURL& url) const { 242 return GetWebUIType(profile, url) != WebUI::kNoWebUI; 243 } 244 245 bool ChromeWebUIFactory::HasWebUIScheme(const GURL& url) const { 246 return url.SchemeIs(chrome::kChromeDevToolsScheme) || 247 url.SchemeIs(chrome::kChromeInternalScheme) || 248 url.SchemeIs(chrome::kChromeUIScheme) || 249 url.SchemeIs(chrome::kExtensionScheme); 250 } 251 252 bool ChromeWebUIFactory::IsURLAcceptableForWebUI( 253 Profile* profile, 254 const GURL& url) const { 255 return UseWebUIForURL(profile, url) || 256 // javacsript: URLs are allowed to run in Web UI pages 257 url.SchemeIs(chrome::kJavaScriptScheme) || 258 // It's possible to load about:blank in a Web UI renderer. 259 // See http://crbug.com/42547 260 url.spec() == chrome::kAboutBlankURL || 261 // about:crash, about:kill, about:hang, and about:shorthang are allowed. 262 url.spec() == chrome::kAboutCrashURL || 263 url.spec() == chrome::kAboutKillURL || 264 url.spec() == chrome::kAboutHangURL || 265 url.spec() == chrome::kAboutShorthangURL; 266 } 267 268 WebUI* ChromeWebUIFactory::CreateWebUIForURL( 269 TabContents* tab_contents, 270 const GURL& url) const { 271 WebUIFactoryFunction function = GetWebUIFactoryFunction( 272 tab_contents->profile(), url); 273 if (!function) 274 return NULL; 275 return (*function)(tab_contents, url); 276 } 277 278 void ChromeWebUIFactory::GetFaviconForURL( 279 Profile* profile, 280 FaviconService::GetFaviconRequest* request, 281 const GURL& page_url) const { 282 // All extensions but the bookmark manager get their favicon from the icons 283 // part of the manifest. 284 if (page_url.SchemeIs(chrome::kExtensionScheme) && 285 page_url.host() != extension_misc::kBookmarkManagerId) { 286 ExtensionWebUI::GetFaviconForURL(profile, request, page_url); 287 } else { 288 history::FaviconData favicon; 289 favicon.image_data = scoped_refptr<RefCountedMemory>( 290 GetFaviconResourceBytes(page_url)); 291 favicon.known_icon = favicon.image_data.get() != NULL && 292 favicon.image_data->size() > 0; 293 request->ForwardResultAsync( 294 FaviconService::FaviconDataCallback::TupleType(request->handle(), 295 favicon)); 296 } 297 } 298 299 // static 300 ChromeWebUIFactory* ChromeWebUIFactory::GetInstance() { 301 return Singleton<ChromeWebUIFactory>::get(); 302 } 303 304 ChromeWebUIFactory::ChromeWebUIFactory() { 305 } 306 307 ChromeWebUIFactory::~ChromeWebUIFactory() { 308 } 309 310 RefCountedMemory* ChromeWebUIFactory::GetFaviconResourceBytes( 311 const GURL& page_url) const { 312 // The bookmark manager is a chrome extension, so we have to check for it 313 // before we check for extension scheme. 314 if (page_url.host() == extension_misc::kBookmarkManagerId) 315 return BookmarksUI::GetFaviconResourceBytes(); 316 317 // The extension scheme is handled in GetFaviconForURL. 318 if (page_url.SchemeIs(chrome::kExtensionScheme)) { 319 NOTREACHED(); 320 return NULL; 321 } 322 323 if (!HasWebUIScheme(page_url)) 324 return NULL; 325 326 #if defined(OS_WIN) 327 if (page_url.host() == chrome::kChromeUIConflictsHost) 328 return ConflictsUI::GetFaviconResourceBytes(); 329 #endif 330 331 if (page_url.host() == chrome::kChromeUICrashesHost) 332 return CrashesUI::GetFaviconResourceBytes(); 333 334 if (page_url.host() == chrome::kChromeUIDownloadsHost) 335 return DownloadsUI::GetFaviconResourceBytes(); 336 337 if (page_url.host() == chrome::kChromeUIExtensionsHost) 338 return ExtensionsUI::GetFaviconResourceBytes(); 339 340 if (page_url.host() == chrome::kChromeUIHistoryHost) 341 return HistoryUI::GetFaviconResourceBytes(); 342 343 if (page_url.host() == chrome::kChromeUIHistory2Host) 344 return HistoryUI2::GetFaviconResourceBytes(); 345 346 if (page_url.host() == chrome::kChromeUIFlagsHost) 347 return FlagsUI::GetFaviconResourceBytes(); 348 349 if (page_url.host() == chrome::kChromeUISettingsHost) 350 return OptionsUI::GetFaviconResourceBytes(); 351 352 if (page_url.host() == chrome::kChromeUIPluginsHost) 353 return PluginsUI::GetFaviconResourceBytes(); 354 355 #if defined(ENABLE_REMOTING) 356 if (page_url.host() == chrome::kChromeUIRemotingHost) 357 return RemotingUI::GetFaviconResourceBytes(); 358 #endif 359 360 return NULL; 361 } 362