• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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