1 // Copyright 2020 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 "chromecast/browser/webui/cast_resource_data_source.h"
6
7 #include "base/bind.h"
8 #include "base/files/file_path.h"
9 #include "base/memory/ref_counted_memory.h"
10 #include "chromecast/base/cast_constants.h"
11 #include "net/base/mime_util.h"
12 #include "net/url_request/url_request.h"
13 #include "services/network/public/mojom/content_security_policy.mojom.h"
14
15 namespace chromecast {
16
17 namespace {
18
GotData(base::OnceCallback<void (scoped_refptr<base::RefCountedMemory>)> cb,scoped_refptr<base::RefCountedMemory> memory)19 void GotData(base::OnceCallback<void(scoped_refptr<base::RefCountedMemory>)> cb,
20 scoped_refptr<base::RefCountedMemory> memory) {
21 std::move(cb).Run(std::move(memory));
22 }
23
24 } // namespace
25
CastResourceDataSource(const std::string & host,bool for_webui)26 CastResourceDataSource::CastResourceDataSource(const std::string& host,
27 bool for_webui)
28 : host_(host), for_webui_(for_webui) {}
29
30 CastResourceDataSource::~CastResourceDataSource() = default;
31
GetSource()32 std::string CastResourceDataSource::GetSource() {
33 return host_;
34 }
35
StartDataRequest(const GURL & url,const content::WebContents::Getter & wc_getter,content::URLDataSource::GotDataCallback callback)36 void CastResourceDataSource::StartDataRequest(
37 const GURL& url,
38 const content::WebContents::Getter& wc_getter,
39 content::URLDataSource::GotDataCallback callback) {
40 std::string path = content::URLDataSource::URLToRequestPath(url);
41 remote_->RequestResourceBytes(path,
42 base::BindOnce(&GotData, std::move(callback)));
43 }
44
GetMimeType(const std::string & path)45 std::string CastResourceDataSource::GetMimeType(const std::string& path) {
46 if (!for_webui_) {
47 std::string mime_type;
48 base::FilePath::StringType file_ext =
49 base::FilePath().AppendASCII(path).Extension();
50 // net::GetMimeTypeFromFile() will crash at base::nix::GetFileMimeType()
51 // because IO is not allowed.
52 if (!file_ext.empty())
53 net::GetWellKnownMimeTypeFromExtension(file_ext.substr(1), &mime_type);
54 return mime_type;
55 }
56
57 // Remove the query string for to determine the mime type.
58 std::string file_path = path.substr(0, path.find_first_of('?'));
59
60 if (base::EndsWith(file_path, ".css", base::CompareCase::INSENSITIVE_ASCII))
61 return "text/css";
62
63 if (base::EndsWith(file_path, ".js", base::CompareCase::INSENSITIVE_ASCII))
64 return "application/javascript";
65
66 if (base::EndsWith(file_path, ".json", base::CompareCase::INSENSITIVE_ASCII))
67 return "application/json";
68
69 if (base::EndsWith(file_path, ".pdf", base::CompareCase::INSENSITIVE_ASCII))
70 return "application/pdf";
71
72 if (base::EndsWith(file_path, ".svg", base::CompareCase::INSENSITIVE_ASCII))
73 return "image/svg+xml";
74
75 if (base::EndsWith(file_path, ".jpg", base::CompareCase::INSENSITIVE_ASCII))
76 return "image/jpeg";
77
78 if (base::EndsWith(file_path, ".png", base::CompareCase::INSENSITIVE_ASCII))
79 return "image/png";
80
81 return "text/html";
82 }
83
ShouldServiceRequest(const GURL & url,content::BrowserContext * browser_context,int render_process_id)84 bool CastResourceDataSource::ShouldServiceRequest(
85 const GURL& url,
86 content::BrowserContext* browser_context,
87 int render_process_id) {
88 if (url.SchemeIs(kChromeResourceScheme))
89 return true;
90 return URLDataSource::ShouldServiceRequest(url, browser_context,
91 render_process_id);
92 }
93
GetAccessControlAllowOriginForOrigin(const std::string & origin)94 std::string CastResourceDataSource::GetAccessControlAllowOriginForOrigin(
95 const std::string& origin) {
96 // For now we give access for all "chrome://*" origins.
97 std::string allowed_origin_prefix = "chrome://";
98 if (!base::StartsWith(origin, allowed_origin_prefix,
99 base::CompareCase::SENSITIVE)) {
100 return "";
101 }
102 return origin;
103 }
104
105 mojo::PendingReceiver<mojom::Resources>
BindNewPipeAndPassReceiver()106 CastResourceDataSource::BindNewPipeAndPassReceiver() {
107 return remote_.BindNewPipeAndPassReceiver();
108 }
109
OverrideContentSecurityPolicyChildSrc(const std::string & data)110 void CastResourceDataSource::OverrideContentSecurityPolicyChildSrc(
111 const std::string& data) {
112 frame_src_ = data;
113 }
114
DisableDenyXFrameOptions()115 void CastResourceDataSource::DisableDenyXFrameOptions() {
116 deny_xframe_options_ = false;
117 }
118
GetContentSecurityPolicy(network::mojom::CSPDirectiveName directive)119 std::string CastResourceDataSource::GetContentSecurityPolicy(
120 network::mojom::CSPDirectiveName directive) {
121 if (directive == network::mojom::CSPDirectiveName::ChildSrc && frame_src_) {
122 return *frame_src_;
123 }
124 return URLDataSource::GetContentSecurityPolicy(directive);
125 }
126
ShouldDenyXFrameOptions()127 bool CastResourceDataSource::ShouldDenyXFrameOptions() {
128 return deny_xframe_options_;
129 }
130
131 } // namespace chromecast
132