1 // Copyright (c) 2013 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 "content/browser/webui/web_ui_controller_factory_registry.h"
6 
7 #include <stddef.h>
8 
9 #include "base/lazy_instance.h"
10 #include "content/browser/renderer_host/debug_urls.h"
11 #include "content/public/browser/content_browser_client.h"
12 #include "content/public/browser/web_ui_controller.h"
13 #include "content/public/common/content_client.h"
14 #include "content/public/common/url_constants.h"
15 #include "content/public/common/url_utils.h"
16 #include "url/gurl.h"
17 
18 namespace content {
19 
20 base::LazyInstance<std::vector<WebUIControllerFactory*>>::DestructorAtExit
21     g_web_ui_controller_factories = LAZY_INSTANCE_INITIALIZER;
22 
RegisterFactory(WebUIControllerFactory * factory)23 void WebUIControllerFactory::RegisterFactory(WebUIControllerFactory* factory) {
24   g_web_ui_controller_factories.Pointer()->push_back(factory);
25 }
26 
UnregisterFactoryForTesting(WebUIControllerFactory * factory)27 void WebUIControllerFactory::UnregisterFactoryForTesting(
28     WebUIControllerFactory* factory) {
29   std::vector<WebUIControllerFactory*>* factories =
30       g_web_ui_controller_factories.Pointer();
31   for (size_t i = 0; i < factories->size(); ++i) {
32     if ((*factories)[i] == factory) {
33       factories->erase(factories->begin() + i);
34       return;
35     }
36   }
37   NOTREACHED() << "Tried to unregister a factory but it wasn't found";
38 }
39 
GetInstance()40 WebUIControllerFactoryRegistry* WebUIControllerFactoryRegistry::GetInstance() {
41   return base::Singleton<WebUIControllerFactoryRegistry>::get();
42 }
43 
44 std::unique_ptr<WebUIController>
CreateWebUIControllerForURL(WebUI * web_ui,const GURL & url)45 WebUIControllerFactoryRegistry::CreateWebUIControllerForURL(WebUI* web_ui,
46                                                             const GURL& url) {
47   std::vector<WebUIControllerFactory*>& factories =
48       g_web_ui_controller_factories.Get();
49   for (WebUIControllerFactory* factory : factories) {
50     auto controller = factory->CreateWebUIControllerForURL(web_ui, url);
51     if (controller)
52       return controller;
53   }
54   return nullptr;
55 }
56 
GetWebUIType(BrowserContext * browser_context,const GURL & url)57 WebUI::TypeID WebUIControllerFactoryRegistry::GetWebUIType(
58     BrowserContext* browser_context,
59     const GURL& url) {
60   std::vector<WebUIControllerFactory*>* factories =
61       g_web_ui_controller_factories.Pointer();
62   for (size_t i = 0; i < factories->size(); ++i) {
63     WebUI::TypeID type = (*factories)[i]->GetWebUIType(browser_context, url);
64     if (type != WebUI::kNoWebUI)
65       return type;
66   }
67   return WebUI::kNoWebUI;
68 }
69 
UseWebUIForURL(BrowserContext * browser_context,const GURL & url)70 bool WebUIControllerFactoryRegistry::UseWebUIForURL(
71     BrowserContext* browser_context,
72     const GURL& url) {
73   std::vector<WebUIControllerFactory*>* factories =
74       g_web_ui_controller_factories.Pointer();
75   for (size_t i = 0; i < factories->size(); ++i) {
76     if ((*factories)[i]->UseWebUIForURL(browser_context, url))
77       return true;
78   }
79   return false;
80 }
81 
UseWebUIBindingsForURL(BrowserContext * browser_context,const GURL & url)82 bool WebUIControllerFactoryRegistry::UseWebUIBindingsForURL(
83     BrowserContext* browser_context,
84     const GURL& url) {
85   std::vector<WebUIControllerFactory*>* factories =
86       g_web_ui_controller_factories.Pointer();
87   for (size_t i = 0; i < factories->size(); ++i) {
88     if ((*factories)[i]->UseWebUIBindingsForURL(browser_context, url))
89       return true;
90   }
91   return false;
92 }
93 
IsURLAcceptableForWebUI(BrowserContext * browser_context,const GURL & url)94 bool WebUIControllerFactoryRegistry::IsURLAcceptableForWebUI(
95     BrowserContext* browser_context,
96     const GURL& url) {
97   return UseWebUIForURL(browser_context, url) ||
98          // It's possible to load about:blank in a Web UI renderer.
99          // See http://crbug.com/42547
100          url.spec() == url::kAboutBlankURL ||
101          // javascript: and debug URLs like chrome://kill are allowed.
102          IsRendererDebugURL(url);
103 }
104 
105 WebUIControllerFactoryRegistry::WebUIControllerFactoryRegistry() = default;
106 
107 WebUIControllerFactoryRegistry::~WebUIControllerFactoryRegistry() = default;
108 
109 }  // namespace content
110