OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_protocols.h" | 5 #include "chrome/browser/extensions/extension_protocols.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/file_path.h" | 9 #include "base/file_path.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 virtual ~URLRequestResourceBundleJob() { } | 60 virtual ~URLRequestResourceBundleJob() { } |
61 | 61 |
62 // We need the filename of the resource to determine the mime type. | 62 // We need the filename of the resource to determine the mime type. |
63 FilePath filename_; | 63 FilePath filename_; |
64 | 64 |
65 // The resource bundle id to load. | 65 // The resource bundle id to load. |
66 int resource_id_; | 66 int resource_id_; |
67 }; | 67 }; |
68 | 68 |
69 // Returns true if an chrome-extension:// resource should be allowed to load. | 69 // Returns true if an chrome-extension:// resource should be allowed to load. |
| 70 // TODO(aa): This should be moved into ExtensionResourceRequestPolicy, but we |
| 71 // first need to find a way to get CanLoadInIncognito state into the renderers. |
70 bool AllowExtensionResourceLoad(net::URLRequest* request, | 72 bool AllowExtensionResourceLoad(net::URLRequest* request, |
71 ChromeURLRequestContext* context, | 73 ChromeURLRequestContext* context, |
72 const std::string& scheme) { | 74 const std::string& scheme) { |
73 const ResourceDispatcherHostRequestInfo* info = | 75 const ResourceDispatcherHostRequestInfo* info = |
74 ResourceDispatcherHost::InfoForRequest(request); | 76 ResourceDispatcherHost::InfoForRequest(request); |
75 | 77 |
76 // We have seen crashes where info is NULL: crbug.com/52374. | 78 // We have seen crashes where info is NULL: crbug.com/52374. |
77 if (!info) { | 79 if (!info) { |
78 LOG(ERROR) << "Allowing load of " << request->url().spec() | 80 LOG(ERROR) << "Allowing load of " << request->url().spec() |
79 << "from unknown origin. Could not find user data for " | 81 << "from unknown origin. Could not find user data for " |
80 << "request."; | 82 << "request."; |
81 return true; | 83 return true; |
82 } | 84 } |
83 | 85 |
84 GURL origin_url(info->frame_origin()); | |
85 | |
86 // chrome:// URLs are always allowed to load chrome-extension:// resources. | |
87 // The app launcher in the NTP uses this feature, as does dev tools. | |
88 if (origin_url.SchemeIs(chrome::kChromeDevToolsScheme) || | |
89 origin_url.SchemeIs(chrome::kChromeUIScheme)) | |
90 return true; | |
91 | |
92 // Disallow loading of packaged resources for hosted apps. We don't allow | |
93 // hybrid hosted/packaged apps. The one exception is access to icons, since | |
94 // some extensions want to be able to do things like create their own | |
95 // launchers. | |
96 if (context->extension_info_map()-> | |
97 ExtensionHasWebExtent(request->url().host())) { | |
98 if (!context->extension_info_map()->URLIsForExtensionIcon(request->url())) { | |
99 LOG(ERROR) << "Denying load of " << request->url().spec() << " from " | |
100 << "hosted app."; | |
101 return false; | |
102 } | |
103 } | |
104 | |
105 // Don't allow toplevel navigations to extension resources in incognito mode. | 86 // Don't allow toplevel navigations to extension resources in incognito mode. |
106 // This is because an extension must run in a single process, and an | 87 // This is because an extension must run in a single process, and an |
107 // incognito tab prevents that. | 88 // incognito tab prevents that. |
108 if (context->is_off_the_record() && | 89 if (context->is_off_the_record() && |
109 info->resource_type() == ResourceType::MAIN_FRAME && | 90 info->resource_type() == ResourceType::MAIN_FRAME && |
110 !context->extension_info_map()-> | 91 !context->extension_info_map()-> |
111 ExtensionCanLoadInIncognito(request->url().host())) { | 92 ExtensionCanLoadInIncognito(request->url().host())) { |
112 LOG(ERROR) << "Denying load of " << request->url().spec() << " from " | 93 LOG(ERROR) << "Denying load of " << request->url().spec() << " from " |
113 << "incognito tab."; | 94 << "incognito tab."; |
114 return false; | 95 return false; |
115 } | 96 } |
116 | 97 |
117 // Otherwise, pages are allowed to load resources from extensions if the | 98 return true; |
118 // extension has host permissions to (and therefore could be running script | |
119 // in, which might need access to the extension resources). | |
120 // | |
121 // Exceptions are: | |
122 // - empty origin (needed for some edge cases when we have empty origins) | |
123 // - chrome-extension:// (for legacy reasons -- some extensions interop) | |
124 // - data: (basic HTML notifications use data URLs internally) | |
125 if (origin_url.is_empty() || | |
126 origin_url.SchemeIs(chrome::kExtensionScheme) | | |
127 origin_url.SchemeIs(chrome::kDataScheme)) { | |
128 return true; | |
129 } else { | |
130 ExtensionExtent host_permissions = context->extension_info_map()-> | |
131 GetEffectiveHostPermissionsForExtension(request->url().host()); | |
132 if (host_permissions.ContainsURL(origin_url)) { | |
133 return true; | |
134 } else { | |
135 LOG(ERROR) << "Denying load of " << request->url().spec() << " from " | |
136 << origin_url.spec() << " because the extension does not have " | |
137 << "access to the requesting page."; | |
138 return false; | |
139 } | |
140 } | |
141 } | 99 } |
142 | 100 |
143 } // namespace | 101 } // namespace |
144 | 102 |
145 // Factory registered with net::URLRequest to create URLRequestJobs for | 103 // Factory registered with net::URLRequest to create URLRequestJobs for |
146 // extension:// URLs. | 104 // extension:// URLs. |
147 static net::URLRequestJob* CreateExtensionURLRequestJob( | 105 static net::URLRequestJob* CreateExtensionURLRequestJob( |
148 net::URLRequest* request, | 106 net::URLRequest* request, |
149 const std::string& scheme) { | 107 const std::string& scheme) { |
150 ChromeURLRequestContext* context = | 108 ChromeURLRequestContext* context = |
151 static_cast<ChromeURLRequestContext*>(request->context()); | 109 static_cast<ChromeURLRequestContext*>(request->context()); |
152 | 110 |
153 // TODO(mpcomplete): better error code. | 111 // TODO(mpcomplete): better error code. |
154 if (!AllowExtensionResourceLoad(request, context, scheme)) | 112 if (!AllowExtensionResourceLoad(request, context, scheme)) { |
| 113 LOG(ERROR) << "disallowed in extension protocols"; |
155 return new net::URLRequestErrorJob(request, net::ERR_ADDRESS_UNREACHABLE); | 114 return new net::URLRequestErrorJob(request, net::ERR_ADDRESS_UNREACHABLE); |
| 115 } |
156 | 116 |
157 // chrome-extension://extension-id/resource/path.js | 117 // chrome-extension://extension-id/resource/path.js |
158 const std::string& extension_id = request->url().host(); | 118 const std::string& extension_id = request->url().host(); |
159 FilePath directory_path = context->extension_info_map()-> | 119 FilePath directory_path = context->extension_info_map()-> |
160 GetPathForExtension(extension_id); | 120 GetPathForExtension(extension_id); |
161 if (directory_path.value().empty()) { | 121 if (directory_path.value().empty()) { |
162 LOG(WARNING) << "Failed to GetPathForExtension: " << extension_id; | 122 LOG(WARNING) << "Failed to GetPathForExtension: " << extension_id; |
163 return NULL; | 123 return NULL; |
164 } | 124 } |
165 | 125 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 | 178 |
219 return new net::URLRequestFileJob(request, resource.GetFilePath()); | 179 return new net::URLRequestFileJob(request, resource.GetFilePath()); |
220 } | 180 } |
221 | 181 |
222 void RegisterExtensionProtocols() { | 182 void RegisterExtensionProtocols() { |
223 net::URLRequest::RegisterProtocolFactory(chrome::kExtensionScheme, | 183 net::URLRequest::RegisterProtocolFactory(chrome::kExtensionScheme, |
224 &CreateExtensionURLRequestJob); | 184 &CreateExtensionURLRequestJob); |
225 net::URLRequest::RegisterProtocolFactory(chrome::kUserScriptScheme, | 185 net::URLRequest::RegisterProtocolFactory(chrome::kUserScriptScheme, |
226 &CreateUserScriptURLRequestJob); | 186 &CreateUserScriptURLRequestJob); |
227 } | 187 } |
OLD | NEW |