• 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 
42 #include "include/base/cef_macros.h"
43 #include "include/base/cef_ref_counted.h"
44 #include "include/base/cef_scoped_ptr.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   typedef base::Callback<std::string(const std::string& /*url*/)> UrlFilter;
69 
70   ///
71   // Used to resolve mime types for URLs, usually based on the file extension.
72   // |url| will be fully qualified and may contain query or fragment components.
73   ///
74   typedef base::Callback<std::string(const std::string& /*url*/)>
75       MimeTypeResolver;
76 
77  private:
78   // Values that stay with a request as it moves between providers.
79   struct RequestParams {
80     std::string url_;
81     CefRefPtr<CefBrowser> browser_;
82     CefRefPtr<CefFrame> frame_;
83     CefRefPtr<CefRequest> request_;
84     UrlFilter url_filter_;
85     MimeTypeResolver mime_type_resolver_;
86   };
87 
88   // Values that are associated with the pending request only.
89   struct RequestState;
90 
91  public:
92   ///
93   // Object representing a request. Each request object is used for a single
94   // call to Provider::OnRequest and will become detached (meaning the callbacks
95   // will no longer trigger) after Request::Continue or Request::Stop is called.
96   // A request passed to Provider::OnRequestCanceled will already have been
97   // detached. The methods of this class may be called on any browser process
98   // thread.
99   ///
100   class Request : public base::RefCountedThreadSafe<Request> {
101    public:
102     ///
103     // Returns the URL associated with this request. The returned value will be
104     // fully qualified but will not contain query or fragment components. It
105     // will already have been passed through the URL filter.
106     ///
url()107     std::string url() const { return params_.url_; }
108 
109     ///
110     // Returns the CefBrowser associated with this request.
111     ///
browser()112     CefRefPtr<CefBrowser> browser() const { return params_.browser_; }
113 
114     ///
115     // Returns the CefFrame associated with this request.
116     ///
frame()117     CefRefPtr<CefFrame> frame() const { return params_.frame_; }
118 
119     ///
120     // Returns the CefRequest associated with this request.
121     ///
request()122     CefRefPtr<CefRequest> request() const { return params_.request_; }
123 
124     ///
125     // Returns the current URL filter.
126     ///
url_filter()127     const CefResourceManager::UrlFilter& url_filter() const {
128       return params_.url_filter_;
129     }
130 
131     ///
132     // Returns the current mime type resolver.
133     ///
mime_type_resolver()134     const CefResourceManager::MimeTypeResolver& mime_type_resolver() const {
135       return params_.mime_type_resolver_;
136     }
137 
138     ///
139     // Continue handling the request. If |handler| is non-NULL then no
140     // additional providers will be called and the |handler| value will be
141     // returned via CefResourceManager::GetResourceHandler. If |handler| is NULL
142     // then the next provider in order, if any, will be called. If there are no
143     // additional providers then NULL will be returned via CefResourceManager::
144     // GetResourceHandler.
145     ///
146     void Continue(CefRefPtr<CefResourceHandler> handler);
147 
148     ///
149     // Stop handling the request. No additional providers will be called and
150     // NULL will be returned via CefResourceManager::GetResourceHandler.
151     ///
152     void Stop();
153 
154    private:
155     // Only allow deletion via scoped_refptr.
156     friend class base::RefCountedThreadSafe<Request>;
157 
158     friend class CefResourceManager;
159 
160     // The below methods are called on the browser process IO thread.
161 
162     explicit Request(scoped_ptr<RequestState> state);
163 
164     scoped_ptr<RequestState> SendRequest();
165     bool HasState();
166 
167     static void ContinueOnIOThread(scoped_ptr<RequestState> state,
168                                    CefRefPtr<CefResourceHandler> handler);
169     static void StopOnIOThread(scoped_ptr<RequestState> state);
170 
171     // Will be non-NULL while the request is pending. Only accessed on the
172     // browser process IO thread.
173     scoped_ptr<RequestState> state_;
174 
175     // Params that stay with this request object. Safe to access on any thread.
176     RequestParams params_;
177 
178     DISALLOW_COPY_AND_ASSIGN(Request);
179   };
180 
181   typedef std::list<scoped_refptr<Request>> RequestList;
182 
183   ///
184   // Interface implemented by resource providers. A provider may be created on
185   // any thread but the methods will be called on, and the object will be
186   // destroyed on, the browser process IO thread.
187   ///
188   class Provider {
189    public:
190     ///
191     // Called to handle a request. If the provider knows immediately that it
192     // will not handle the request return false. Otherwise, return true and call
193     // Request::Continue or Request::Stop either in this method or
194     // asynchronously to indicate completion. See comments on Request for
195     // additional usage information.
196     ///
197     virtual bool OnRequest(scoped_refptr<Request> request) = 0;
198 
199     ///
200     // Called when a request has been canceled. It is still safe to dereference
201     // |request| but any calls to Request::Continue or Request::Stop will be
202     // ignored.
203     ///
OnRequestCanceled(scoped_refptr<Request> request)204     virtual void OnRequestCanceled(scoped_refptr<Request> request) {}
205 
~Provider()206     virtual ~Provider() {}
207   };
208 
209   CefResourceManager();
210 
211   ///
212   // Add a provider that maps requests for |url| to |content|. |url| should be
213   // fully qualified but not include a query or fragment component. If
214   // |mime_type| is empty the MimeTypeResolver will be used. See comments on
215   // AddProvider for usage of the |order| and |identifier| parameters.
216   ///
217   void AddContentProvider(const std::string& url,
218                           const std::string& content,
219                           const std::string& mime_type,
220                           int order,
221                           const std::string& identifier);
222 
223   ///
224   // Add a provider that maps requests that start with |url_path| to files under
225   // |directory_path|. |url_path| should include an origin and optional path
226   // component only. Files will be loaded when a matching URL is requested.
227   // See comments on AddProvider for usage of the |order| and |identifier|
228   // parameters.
229   ///
230   void AddDirectoryProvider(const std::string& url_path,
231                             const std::string& directory_path,
232                             int order,
233                             const std::string& identifier);
234 
235   ///
236   // Add a provider that maps requests that start with |url_path| to files
237   // stored in the archive file at |archive_path|. |url_path| should include an
238   // origin and optional path component only. The archive file will be loaded
239   // when a matching URL is requested for the first time. See comments on
240   // AddProvider for usage of the |order| and |identifier| parameters.
241   ///
242   void AddArchiveProvider(const std::string& url_path,
243                           const std::string& archive_path,
244                           const std::string& password,
245                           int order,
246                           const std::string& identifier);
247 
248   ///
249   // Add a provider. This object takes ownership of |provider|. Providers will
250   // be called in ascending order based on the |order| value. Multiple providers
251   // sharing the same |order| value will be called in the order that they were
252   // added. The |identifier| value, which does not need to be unique, can be
253   // used to remove the provider at a later time.
254   ///
255   void AddProvider(Provider* provider,
256                    int order,
257                    const std::string& identifier);
258 
259   ///
260   // Remove all providers with the specified |identifier| value. If any removed
261   // providers have pending requests the Provider::OnRequestCancel method will
262   // be called. The removed providers may be deleted immediately or at a later
263   // time.
264   ///
265   void RemoveProviders(const std::string& identifier);
266 
267   ///
268   // Remove all providers. If any removed providers have pending requests the
269   // Provider::OnRequestCancel method will be called. The removed providers may
270   // be deleted immediately or at a later time.
271   ///
272   void RemoveAllProviders();
273 
274   ///
275   // Set the url filter. If not set the default no-op filter will be used.
276   // Changes to this value will not affect currently pending requests.
277   ///
278   void SetUrlFilter(const UrlFilter& filter);
279 
280   ///
281   // Set the mime type resolver. If not set the default resolver will be used.
282   // Changes to this value will not affect currently pending requests.
283   ///
284   void SetMimeTypeResolver(const MimeTypeResolver& resolver);
285 
286   // The below methods should be called from other CEF handlers. They must be
287   // called exactly as documented for the manager to function correctly.
288 
289   ///
290   // Called from CefRequestHandler::OnBeforeResourceLoad on the browser process
291   // IO thread.
292   ///
293   cef_return_value_t OnBeforeResourceLoad(
294       CefRefPtr<CefBrowser> browser,
295       CefRefPtr<CefFrame> frame,
296       CefRefPtr<CefRequest> request,
297       CefRefPtr<CefRequestCallback> callback);
298 
299   ///
300   // Called from CefRequestHandler::GetResourceHandler on the browser process
301   // IO thread.
302   ///
303   CefRefPtr<CefResourceHandler> GetResourceHandler(
304       CefRefPtr<CefBrowser> browser,
305       CefRefPtr<CefFrame> frame,
306       CefRefPtr<CefRequest> request);
307 
308  private:
309   // Only allow deletion via scoped_refptr.
310   friend struct CefDeleteOnThread<TID_IO>;
311   friend class base::RefCountedThreadSafe<CefResourceManager,
312                                           CefDeleteOnIOThread>;
313 
314   ~CefResourceManager();
315 
316   // Provider and associated information.
317   struct ProviderEntry;
318   typedef std::list<ProviderEntry*> ProviderEntryList;
319 
320   // Values associated with the pending request only. Ownership will be passed
321   // between requests and the resource manager as request handling proceeds.
322   struct RequestState {
323     ~RequestState();
324 
325     base::WeakPtr<CefResourceManager> manager_;
326 
327     // Callback to execute once request handling is complete.
328     CefRefPtr<CefRequestCallback> callback_;
329 
330     // Position of the currently associated ProviderEntry in the |providers_|
331     // list.
332     ProviderEntryList::iterator current_entry_pos_;
333 
334     // Position of this request object in the currently associated
335     // ProviderEntry's |pending_requests_| list.
336     RequestList::iterator current_request_pos_;
337 
338     // Params that will be copied to each request object.
339     RequestParams params_;
340   };
341 
342   // Methods that manage request state between requests. Called on the browser
343   // process IO thread.
344   bool SendRequest(scoped_ptr<RequestState> state);
345   void ContinueRequest(scoped_ptr<RequestState> state,
346                        CefRefPtr<CefResourceHandler> handler);
347   void StopRequest(scoped_ptr<RequestState> state);
348   bool IncrementProvider(RequestState* state);
349   void DetachRequestFromProvider(RequestState* state);
350   void GetNextValidProvider(ProviderEntryList::iterator& iterator);
351   void DeleteProvider(ProviderEntryList::iterator& iterator, bool stop);
352 
353   // The below members are only accessed on the browser process IO thread.
354 
355   // List of providers including additional associated information.
356   ProviderEntryList providers_;
357 
358   // Map of response ID to pending CefResourceHandler object.
359   typedef std::map<uint64, CefRefPtr<CefResourceHandler>> PendingHandlersMap;
360   PendingHandlersMap pending_handlers_;
361 
362   UrlFilter url_filter_;
363   MimeTypeResolver mime_type_resolver_;
364 
365   // Must be the last member. Created and accessed on the IO thread.
366   scoped_ptr<base::WeakPtrFactory<CefResourceManager>> weak_ptr_factory_;
367 
368   DISALLOW_COPY_AND_ASSIGN(CefResourceManager);
369 };
370 
371 #endif  // CEF_INCLUDE_WRAPPER_CEF_RESOURCE_MANAGER_H_
372