Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / ui / webui / devtools_ui.cc
blob4360cf1af4506832dfb4102b1a8819cc754ed4c6
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.
5 #include "chrome/browser/ui/webui/devtools_ui.h"
7 #include "base/memory/ref_counted_memory.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/common/url_constants.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/devtools_frontend_host.h"
14 #include "content/public/browser/url_data_source.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/browser/web_ui.h"
17 #include "content/public/common/user_agent.h"
18 #include "net/url_request/url_fetcher.h"
19 #include "net/url_request/url_fetcher_delegate.h"
20 #include "net/url_request/url_request_context_getter.h"
22 using content::BrowserThread;
23 using content::WebContents;
25 namespace {
27 std::string PathWithoutParams(const std::string& path) {
28 return GURL(std::string("chrome-devtools://devtools/") + path)
29 .path().substr(1);
32 const char kRemoteFrontendDomain[] = "chrome-devtools-frontend.appspot.com";
33 const char kRemoteFrontendBase[] =
34 "https://chrome-devtools-frontend.appspot.com/";
35 const char kRemoteFrontendPath[] = "serve_file";
36 const char kHttpNotFound[] = "HTTP/1.1 404 Not Found\n\n";
38 #if defined(DEBUG_DEVTOOLS)
39 // Local frontend url provided by InspectUI.
40 const char kFallbackFrontendURL[] =
41 "chrome-devtools://devtools/bundled/inspector.html";
42 #else
43 // URL causing the DevTools window to display a plain text warning.
44 const char kFallbackFrontendURL[] =
45 "data:text/plain,Cannot load DevTools frontend from an untrusted origin";
46 #endif // defined(DEBUG_DEVTOOLS)
48 // DevToolsDataSource ---------------------------------------------------------
50 std::string GetMimeTypeForPath(const std::string& path) {
51 std::string filename = PathWithoutParams(path);
52 if (EndsWith(filename, ".html", false)) {
53 return "text/html";
54 } else if (EndsWith(filename, ".css", false)) {
55 return "text/css";
56 } else if (EndsWith(filename, ".js", false)) {
57 return "application/javascript";
58 } else if (EndsWith(filename, ".png", false)) {
59 return "image/png";
60 } else if (EndsWith(filename, ".gif", false)) {
61 return "image/gif";
62 } else if (EndsWith(filename, ".svg", false)) {
63 return "image/svg+xml";
64 } else if (EndsWith(filename, ".manifest", false)) {
65 return "text/cache-manifest";
67 return "text/html";
70 // An URLDataSource implementation that handles chrome-devtools://devtools/
71 // requests. Three types of requests could be handled based on the URL path:
72 // 1. /bundled/: bundled DevTools frontend is served.
73 // 2. /remote/: remote DevTools frontend is served from App Engine.
74 class DevToolsDataSource : public content::URLDataSource,
75 public net::URLFetcherDelegate {
76 public:
77 using GotDataCallback = content::URLDataSource::GotDataCallback;
79 explicit DevToolsDataSource(net::URLRequestContextGetter* request_context);
81 // content::URLDataSource implementation.
82 std::string GetSource() const override;
84 void StartDataRequest(const std::string& path,
85 int render_process_id,
86 int render_frame_id,
87 const GotDataCallback& callback) override;
89 private:
90 // content::URLDataSource overrides.
91 std::string GetMimeType(const std::string& path) const override;
92 bool ShouldAddContentSecurityPolicy() const override;
93 bool ShouldDenyXFrameOptions() const override;
94 bool ShouldServeMimeTypeAsContentTypeHeader() const override;
96 // net::URLFetcherDelegate overrides.
97 void OnURLFetchComplete(const net::URLFetcher* source) override;
99 // Serves bundled DevTools frontend from ResourceBundle.
100 void StartBundledDataRequest(const std::string& path,
101 int render_process_id,
102 int render_frame_id,
103 const GotDataCallback& callback);
105 // Serves remote DevTools frontend from hard-coded App Engine domain.
106 void StartRemoteDataRequest(const std::string& path,
107 int render_process_id,
108 int render_frame_id,
109 const GotDataCallback& callback);
111 ~DevToolsDataSource() override;
113 scoped_refptr<net::URLRequestContextGetter> request_context_;
115 using PendingRequestsMap = std::map<const net::URLFetcher*, GotDataCallback>;
116 PendingRequestsMap pending_;
118 DISALLOW_COPY_AND_ASSIGN(DevToolsDataSource);
121 DevToolsDataSource::DevToolsDataSource(
122 net::URLRequestContextGetter* request_context)
123 : request_context_(request_context) {
126 DevToolsDataSource::~DevToolsDataSource() {
127 for (const auto& pair : pending_) {
128 delete pair.first;
129 pair.second.Run(
130 new base::RefCountedStaticMemory(kHttpNotFound, strlen(kHttpNotFound)));
134 std::string DevToolsDataSource::GetSource() const {
135 return chrome::kChromeUIDevToolsHost;
138 void DevToolsDataSource::StartDataRequest(
139 const std::string& path,
140 int render_process_id,
141 int render_frame_id,
142 const content::URLDataSource::GotDataCallback& callback) {
143 // Serve request from local bundle.
144 std::string bundled_path_prefix(chrome::kChromeUIDevToolsBundledPath);
145 bundled_path_prefix += "/";
146 if (StartsWithASCII(path, bundled_path_prefix, false)) {
147 StartBundledDataRequest(path.substr(bundled_path_prefix.length()),
148 render_process_id, render_frame_id, callback);
149 return;
152 // Serve request from remote location.
153 std::string remote_path_prefix(chrome::kChromeUIDevToolsRemotePath);
154 remote_path_prefix += "/";
155 if (StartsWithASCII(path, remote_path_prefix, false)) {
156 StartRemoteDataRequest(path.substr(remote_path_prefix.length()),
157 render_process_id, render_frame_id, callback);
158 return;
161 callback.Run(NULL);
164 std::string DevToolsDataSource::GetMimeType(const std::string& path) const {
165 return GetMimeTypeForPath(path);
168 bool DevToolsDataSource::ShouldAddContentSecurityPolicy() const {
169 return false;
172 bool DevToolsDataSource::ShouldDenyXFrameOptions() const {
173 return false;
176 bool DevToolsDataSource::ShouldServeMimeTypeAsContentTypeHeader() const {
177 return true;
180 void DevToolsDataSource::StartBundledDataRequest(
181 const std::string& path,
182 int render_process_id,
183 int render_frame_id,
184 const content::URLDataSource::GotDataCallback& callback) {
185 std::string filename = PathWithoutParams(path);
186 base::StringPiece resource =
187 content::DevToolsFrontendHost::GetFrontendResource(filename);
189 DLOG_IF(WARNING, resource.empty())
190 << "Unable to find dev tool resource: " << filename
191 << ". If you compiled with debug_devtools=1, try running with "
192 "--debug-devtools.";
193 scoped_refptr<base::RefCountedStaticMemory> bytes(
194 new base::RefCountedStaticMemory(resource.data(), resource.length()));
195 callback.Run(bytes.get());
198 void DevToolsDataSource::StartRemoteDataRequest(
199 const std::string& path,
200 int render_process_id,
201 int render_frame_id,
202 const content::URLDataSource::GotDataCallback& callback) {
203 GURL url = GURL(kRemoteFrontendBase + path);
204 CHECK_EQ(url.host(), kRemoteFrontendDomain);
205 if (!url.is_valid()) {
206 callback.Run(
207 new base::RefCountedStaticMemory(kHttpNotFound, strlen(kHttpNotFound)));
208 return;
210 net::URLFetcher* fetcher =
211 net::URLFetcher::Create(url, net::URLFetcher::GET, this).release();
212 pending_[fetcher] = callback;
213 fetcher->SetRequestContext(request_context_.get());
214 fetcher->Start();
217 void DevToolsDataSource::OnURLFetchComplete(const net::URLFetcher* source) {
218 DCHECK(source);
219 PendingRequestsMap::iterator it = pending_.find(source);
220 DCHECK(it != pending_.end());
221 std::string response;
222 source->GetResponseAsString(&response);
223 delete source;
224 it->second.Run(base::RefCountedString::TakeString(&response));
225 pending_.erase(it);
228 } // namespace
230 // DevToolsUI -----------------------------------------------------------------
232 // static
233 GURL DevToolsUI::GetProxyURL(const std::string& frontend_url) {
234 GURL url(frontend_url);
235 if (!url.is_valid() || url.host() != kRemoteFrontendDomain)
236 return GURL(kFallbackFrontendURL);
237 return GURL(base::StringPrintf("%s://%s/%s/%s",
238 content::kChromeDevToolsScheme,
239 chrome::kChromeUIDevToolsHost,
240 chrome::kChromeUIDevToolsRemotePath,
241 url.path().substr(1).c_str()));
244 // static
245 GURL DevToolsUI::GetRemoteBaseURL() {
246 return GURL(base::StringPrintf(
247 "%s%s/%s/",
248 kRemoteFrontendBase,
249 kRemoteFrontendPath,
250 content::GetWebKitRevision().c_str()));
253 DevToolsUI::DevToolsUI(content::WebUI* web_ui)
254 : WebUIController(web_ui),
255 bindings_(web_ui->GetWebContents()) {
256 web_ui->SetBindings(0);
257 Profile* profile = Profile::FromWebUI(web_ui);
258 content::URLDataSource::Add(
259 profile,
260 new DevToolsDataSource(profile->GetRequestContext()));
263 DevToolsUI::~DevToolsUI() {