1 // Copyright (c) 2015 Marshall A. Greenblatt. All rights reserved. 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google Inc. nor the name Chromium Embedded 14 // Framework nor the names of its contributors may be used to endorse 15 // or promote products derived from this software without specific prior 16 // written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 // 30 // --------------------------------------------------------------------------- 31 // 32 // The contents of this file are only available to applications that link 33 // against the libcef_dll_wrapper target. 34 // 35 36 #ifndef CEF_INCLUDE_WRAPPER_CEF_RESOURCE_MANAGER_H_ 37 #define CEF_INCLUDE_WRAPPER_CEF_RESOURCE_MANAGER_H_ 38 #pragma once 39 40 #include <list> 41 #include <memory> 42 43 #include "include/base/cef_callback.h" 44 #include "include/base/cef_ref_counted.h" 45 #include "include/base/cef_weak_ptr.h" 46 #include "include/cef_request_handler.h" 47 #include "include/wrapper/cef_closure_task.h" 48 #include "include/wrapper/cef_helpers.h" 49 50 /// 51 // Class for managing multiple resource providers. For each resource request 52 // providers will be called in order and have the option to (a) handle the 53 // request by returning a CefResourceHandler, (b) pass the request to the next 54 // provider in order, or (c) stop handling the request. See comments on the 55 // Request object for additional usage information. The methods of this class 56 // may be called on any browser process thread unless otherwise indicated. 57 /// 58 class CefResourceManager 59 : public base::RefCountedThreadSafe<CefResourceManager, 60 CefDeleteOnIOThread> { 61 public: 62 /// 63 // Provides an opportunity to modify |url| before it is passed to a provider. 64 // For example, the implementation could rewrite |url| to include a default 65 // file extension. |url| will be fully qualified and may contain query or 66 // fragment components. 67 /// 68 using UrlFilter = 69 base::RepeatingCallback<std::string(const std::string& /*url*/)>; 70 71 /// 72 // Used to resolve mime types for URLs, usually based on the file extension. 73 // |url| will be fully qualified and may contain query or fragment components. 74 /// 75 using MimeTypeResolver = 76 base::RepeatingCallback<std::string(const std::string& /*url*/)>; 77 78 private: 79 // Values that stay with a request as it moves between providers. 80 struct RequestParams { 81 std::string url_; 82 CefRefPtr<CefBrowser> browser_; 83 CefRefPtr<CefFrame> frame_; 84 CefRefPtr<CefRequest> request_; 85 UrlFilter url_filter_; 86 MimeTypeResolver mime_type_resolver_; 87 }; 88 89 // Values that are associated with the pending request only. 90 struct RequestState; 91 92 public: 93 /// 94 // Object representing a request. Each request object is used for a single 95 // call to Provider::OnRequest and will become detached (meaning the callbacks 96 // will no longer trigger) after Request::Continue or Request::Stop is called. 97 // A request passed to Provider::OnRequestCanceled will already have been 98 // detached. The methods of this class may be called on any browser process 99 // thread. 100 /// 101 class Request : public base::RefCountedThreadSafe<Request> { 102 public: 103 Request(const Request&) = delete; 104 Request& operator=(const Request&) = delete; 105 106 /// 107 // Returns the URL associated with this request. The returned value will be 108 // fully qualified but will not contain query or fragment components. It 109 // will already have been passed through the URL filter. 110 /// url()111 std::string url() const { return params_.url_; } 112 113 /// 114 // Returns the CefBrowser associated with this request. 115 /// browser()116 CefRefPtr<CefBrowser> browser() const { return params_.browser_; } 117 118 /// 119 // Returns the CefFrame associated with this request. 120 /// frame()121 CefRefPtr<CefFrame> frame() const { return params_.frame_; } 122 123 /// 124 // Returns the CefRequest associated with this request. 125 /// request()126 CefRefPtr<CefRequest> request() const { return params_.request_; } 127 128 /// 129 // Returns the current URL filter. 130 /// url_filter()131 const CefResourceManager::UrlFilter& url_filter() const { 132 return params_.url_filter_; 133 } 134 135 /// 136 // Returns the current mime type resolver. 137 /// mime_type_resolver()138 const CefResourceManager::MimeTypeResolver& mime_type_resolver() const { 139 return params_.mime_type_resolver_; 140 } 141 142 /// 143 // Continue handling the request. If |handler| is non-NULL then no 144 // additional providers will be called and the |handler| value will be 145 // returned via CefResourceManager::GetResourceHandler. If |handler| is NULL 146 // then the next provider in order, if any, will be called. If there are no 147 // additional providers then NULL will be returned via CefResourceManager:: 148 // GetResourceHandler. 149 /// 150 void Continue(CefRefPtr<CefResourceHandler> handler); 151 152 /// 153 // Stop handling the request. No additional providers will be called and 154 // NULL will be returned via CefResourceManager::GetResourceHandler. 155 /// 156 void Stop(); 157 158 private: 159 // Only allow deletion via scoped_refptr. 160 friend class base::RefCountedThreadSafe<Request>; 161 162 friend class CefResourceManager; 163 164 // The below methods are called on the browser process IO thread. 165 166 explicit Request(std::unique_ptr<RequestState> state); 167 168 std::unique_ptr<RequestState> SendRequest(); 169 bool HasState(); 170 171 static void ContinueOnIOThread(std::unique_ptr<RequestState> state, 172 CefRefPtr<CefResourceHandler> handler); 173 static void StopOnIOThread(std::unique_ptr<RequestState> state); 174 175 // Will be non-NULL while the request is pending. Only accessed on the 176 // browser process IO thread. 177 std::unique_ptr<RequestState> state_; 178 179 // Params that stay with this request object. Safe to access on any thread. 180 RequestParams params_; 181 }; 182 183 using RequestList = std::list<scoped_refptr<Request>>; 184 185 /// 186 // Interface implemented by resource providers. A provider may be created on 187 // any thread but the methods will be called on, and the object will be 188 // destroyed on, the browser process IO thread. 189 /// 190 class Provider { 191 public: 192 /// 193 // Called to handle a request. If the provider knows immediately that it 194 // will not handle the request return false. Otherwise, return true and call 195 // Request::Continue or Request::Stop either in this method or 196 // asynchronously to indicate completion. See comments on Request for 197 // additional usage information. 198 /// 199 virtual bool OnRequest(scoped_refptr<Request> request) = 0; 200 201 /// 202 // Called when a request has been canceled. It is still safe to dereference 203 // |request| but any calls to Request::Continue or Request::Stop will be 204 // ignored. 205 /// OnRequestCanceled(scoped_refptr<Request> request)206 virtual void OnRequestCanceled(scoped_refptr<Request> request) {} 207 ~Provider()208 virtual ~Provider() {} 209 }; 210 211 CefResourceManager(); 212 213 CefResourceManager(const CefResourceManager&) = delete; 214 CefResourceManager& operator=(const CefResourceManager&) = delete; 215 216 /// 217 // Add a provider that maps requests for |url| to |content|. |url| should be 218 // fully qualified but not include a query or fragment component. If 219 // |mime_type| is empty the MimeTypeResolver will be used. See comments on 220 // AddProvider for usage of the |order| and |identifier| parameters. 221 /// 222 void AddContentProvider(const std::string& url, 223 const std::string& content, 224 const std::string& mime_type, 225 int order, 226 const std::string& identifier); 227 228 /// 229 // Add a provider that maps requests that start with |url_path| to files under 230 // |directory_path|. |url_path| should include an origin and optional path 231 // component only. Files will be loaded when a matching URL is requested. 232 // See comments on AddProvider for usage of the |order| and |identifier| 233 // parameters. 234 /// 235 void AddDirectoryProvider(const std::string& url_path, 236 const std::string& directory_path, 237 int order, 238 const std::string& identifier); 239 240 /// 241 // Add a provider that maps requests that start with |url_path| to files 242 // stored in the archive file at |archive_path|. |url_path| should include an 243 // origin and optional path component only. The archive file will be loaded 244 // when a matching URL is requested for the first time. See comments on 245 // AddProvider for usage of the |order| and |identifier| parameters. 246 /// 247 void AddArchiveProvider(const std::string& url_path, 248 const std::string& archive_path, 249 const std::string& password, 250 int order, 251 const std::string& identifier); 252 253 /// 254 // Add a provider. This object takes ownership of |provider|. Providers will 255 // be called in ascending order based on the |order| value. Multiple providers 256 // sharing the same |order| value will be called in the order that they were 257 // added. The |identifier| value, which does not need to be unique, can be 258 // used to remove the provider at a later time. 259 /// 260 void AddProvider(Provider* provider, 261 int order, 262 const std::string& identifier); 263 264 /// 265 // Remove all providers with the specified |identifier| value. If any removed 266 // providers have pending requests the Provider::OnRequestCancel method will 267 // be called. The removed providers may be deleted immediately or at a later 268 // time. 269 /// 270 void RemoveProviders(const std::string& identifier); 271 272 /// 273 // Remove all providers. If any removed providers have pending requests the 274 // Provider::OnRequestCancel method will be called. The removed providers may 275 // be deleted immediately or at a later time. 276 /// 277 void RemoveAllProviders(); 278 279 /// 280 // Set the url filter. If not set the default no-op filter will be used. 281 // Changes to this value will not affect currently pending requests. 282 /// 283 void SetUrlFilter(const UrlFilter& filter); 284 285 /// 286 // Set the mime type resolver. If not set the default resolver will be used. 287 // Changes to this value will not affect currently pending requests. 288 /// 289 void SetMimeTypeResolver(const MimeTypeResolver& resolver); 290 291 // The below methods should be called from other CEF handlers. They must be 292 // called exactly as documented for the manager to function correctly. 293 294 /// 295 // Called from CefRequestHandler::OnBeforeResourceLoad on the browser process 296 // IO thread. 297 /// 298 cef_return_value_t OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser, 299 CefRefPtr<CefFrame> frame, 300 CefRefPtr<CefRequest> request, 301 CefRefPtr<CefCallback> callback); 302 303 /// 304 // Called from CefRequestHandler::GetResourceHandler on the browser process 305 // IO thread. 306 /// 307 CefRefPtr<CefResourceHandler> GetResourceHandler( 308 CefRefPtr<CefBrowser> browser, 309 CefRefPtr<CefFrame> frame, 310 CefRefPtr<CefRequest> request); 311 312 private: 313 // Only allow deletion via scoped_refptr. 314 friend struct CefDeleteOnThread<TID_IO>; 315 friend class base::RefCountedThreadSafe<CefResourceManager, 316 CefDeleteOnIOThread>; 317 318 ~CefResourceManager(); 319 320 // Provider and associated information. 321 struct ProviderEntry; 322 using ProviderEntryList = std::list<ProviderEntry*>; 323 324 // Values associated with the pending request only. Ownership will be passed 325 // between requests and the resource manager as request handling proceeds. 326 struct RequestState { 327 ~RequestState(); 328 329 base::WeakPtr<CefResourceManager> manager_; 330 331 // Callback to execute once request handling is complete. 332 CefRefPtr<CefCallback> callback_; 333 334 // Position of the currently associated ProviderEntry in the |providers_| 335 // list. 336 ProviderEntryList::iterator current_entry_pos_; 337 338 // Position of this request object in the currently associated 339 // ProviderEntry's |pending_requests_| list. 340 RequestList::iterator current_request_pos_; 341 342 // Params that will be copied to each request object. 343 RequestParams params_; 344 }; 345 346 // Methods that manage request state between requests. Called on the browser 347 // process IO thread. 348 bool SendRequest(std::unique_ptr<RequestState> state); 349 void ContinueRequest(std::unique_ptr<RequestState> state, 350 CefRefPtr<CefResourceHandler> handler); 351 void StopRequest(std::unique_ptr<RequestState> state); 352 bool IncrementProvider(RequestState* state); 353 void DetachRequestFromProvider(RequestState* state); 354 void GetNextValidProvider(ProviderEntryList::iterator& iterator); 355 void DeleteProvider(ProviderEntryList::iterator& iterator, bool stop); 356 357 // The below members are only accessed on the browser process IO thread. 358 359 // List of providers including additional associated information. 360 ProviderEntryList providers_; 361 362 // Map of response ID to pending CefResourceHandler object. 363 using PendingHandlersMap = std::map<uint64, CefRefPtr<CefResourceHandler>>; 364 PendingHandlersMap pending_handlers_; 365 366 UrlFilter url_filter_; 367 MimeTypeResolver mime_type_resolver_; 368 369 // Must be the last member. Created and accessed on the IO thread. 370 std::unique_ptr<base::WeakPtrFactory<CefResourceManager>> weak_ptr_factory_; 371 }; 372 373 #endif // CEF_INCLUDE_WRAPPER_CEF_RESOURCE_MANAGER_H_ 374