OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #ifndef CHROME_BROWSER_DOM_UI_CHROME_URL_DATA_MANAGER_H_ | 5 #ifndef CHROME_BROWSER_DOM_UI_CHROME_URL_DATA_MANAGER_H_ |
6 #define CHROME_BROWSER_DOM_UI_CHROME_URL_DATA_MANAGER_H_ | 6 #define CHROME_BROWSER_DOM_UI_CHROME_URL_DATA_MANAGER_H_ |
7 #pragma once | 7 #pragma once |
8 | 8 |
9 #include <map> | 9 #include <map> |
10 #include <string> | 10 #include <string> |
11 | 11 |
12 #include "base/singleton.h" | |
13 #include "base/task.h" | 12 #include "base/task.h" |
14 #include "base/ref_counted.h" | 13 #include "base/ref_counted.h" |
15 #include "chrome/browser/browser_thread.h" | 14 #include "chrome/browser/browser_thread.h" |
16 | 15 |
16 class ChromeURLDataManagerBackend; | |
17 class DictionaryValue; | 17 class DictionaryValue; |
18 class FilePath; | 18 class FilePath; |
19 class GURL; | |
20 class MessageLoop; | 19 class MessageLoop; |
20 class Profile; | |
21 class RefCountedMemory; | 21 class RefCountedMemory; |
22 class URLRequestChromeJob; | |
23 | |
24 namespace net { | |
25 class URLRequest; | |
26 class URLRequestJob; | |
27 } // namespace net | |
28 | 22 |
29 // To serve dynamic data off of chrome: URLs, implement the | 23 // To serve dynamic data off of chrome: URLs, implement the |
30 // ChromeURLDataManager::DataSource interface and register your handler | 24 // ChromeURLDataManager::DataSource interface and register your handler |
31 // with AddDataSource. | 25 // with AddDataSource. DataSources must be added on the UI thread (they are also |
32 | 26 // deleted on the UI thread). Internally the DataSources are maintained by |
33 // ChromeURLDataManager lives on the IO thread, so any interfacing with | 27 // ChromeURLDataManagerBackend, see it for details. |
34 // it from the UI thread needs to go through an InvokeLater. | |
35 class ChromeURLDataManager { | 28 class ChromeURLDataManager { |
36 public: | 29 public: |
37 // Returns the singleton instance. | 30 class DataSource; |
38 static ChromeURLDataManager* GetInstance(); | |
39 | 31 |
40 typedef int RequestID; | 32 // Trait used to handle deleting a DataSource. Deletion happens on the UI |
33 // thread. | |
34 // | |
35 // Implementation note: the normal shutdown sequence is for the UI loop to | |
36 // stop pumping events then the IO loop and thread are stopped. When the | |
37 // DataSources are no longer referenced (which happens when IO thread stops) | |
38 // they get added to the UI message loop for deletion. But because the UI loop | |
39 // has stopped by the time this happens the DataSources would be leaked. | |
40 // | |
41 // To make sure DataSources are properly deleted ChromeURLDataManager manages | |
42 // deletion of the DataSources. When a DataSource is no longer referenced it | |
43 // is added to |data_sources_| and a task is posted to the UI thread to handle | |
44 // the actual deletion. During shutdown |DeleteDataSources| is invoked so that | |
45 // all pending DataSources are properly deleted. | |
46 struct DeleteDataSource { | |
47 static void Destruct(const DataSource* data_source) { | |
48 ChromeURLDataManager::DeleteDataSource(data_source); | |
49 } | |
50 }; | |
41 | 51 |
42 // A DataSource is an object that can answer requests for data | 52 // A DataSource is an object that can answer requests for data |
43 // asynchronously. DataSources are collectively owned with refcounting smart | 53 // asynchronously. DataSources are collectively owned with refcounting smart |
44 // pointers and should never be deleted on the IO thread, since their calls | 54 // pointers and should never be deleted on the IO thread, since their calls |
45 // are handled almost always on the UI thread and there's a possibility of a | 55 // are handled almost always on the UI thread and there's a possibility of a |
46 // data race. The |DeleteOnUIThread| trait is used to enforce this. | 56 // data race. The |DeleteOnUIThread| trait is used to enforce this. |
Lei Zhang
2011/03/04 12:30:55
This comment is out of date. Can you fix?
| |
47 // | 57 // |
48 // An implementation of DataSource should handle calls to | 58 // An implementation of DataSource should handle calls to |
49 // StartDataRequest() by starting its (implementation-specific) asynchronous | 59 // StartDataRequest() by starting its (implementation-specific) asynchronous |
50 // request for the data, then call SendResponse() to notify. | 60 // request for the data, then call SendResponse() to notify. |
51 class DataSource : public base::RefCountedThreadSafe< | 61 class DataSource : public base::RefCountedThreadSafe< |
52 DataSource, BrowserThread::DeleteOnUIThread> { | 62 DataSource, DeleteDataSource> { |
53 public: | 63 public: |
54 // See source_name_ and message_loop_ below for docs on these parameters. | 64 // See source_name_ and message_loop_ below for docs on these parameters. |
55 DataSource(const std::string& source_name, | 65 DataSource(const std::string& source_name, MessageLoop* message_loop); |
56 MessageLoop* message_loop); | |
57 | 66 |
58 // Sent by the DataManager to request data at |path|. The source should | 67 // Sent by the DataManager to request data at |path|. The source should |
59 // call SendResponse() when the data is available or if the request could | 68 // call SendResponse() when the data is available or if the request could |
60 // not be satisfied. | 69 // not be satisfied. |
61 virtual void StartDataRequest(const std::string& path, | 70 virtual void StartDataRequest(const std::string& path, |
62 bool is_off_the_record, | 71 bool is_off_the_record, |
63 int request_id) = 0; | 72 int request_id) = 0; |
64 | 73 |
65 // Return the mimetype that should be sent with this response, or empty | 74 // Return the mimetype that should be sent with this response, or empty |
66 // string to specify no mime type. | 75 // string to specify no mime type. |
(...skipping 14 matching lines...) Expand all Loading... | |
81 // such requests more rapidly when there is a large amount of UI thread | 90 // such requests more rapidly when there is a large amount of UI thread |
82 // contention. | 91 // contention. |
83 virtual MessageLoop* MessageLoopForRequestPath(const std::string& path) | 92 virtual MessageLoop* MessageLoopForRequestPath(const std::string& path) |
84 const; | 93 const; |
85 | 94 |
86 const std::string& source_name() const { return source_name_; } | 95 const std::string& source_name() const { return source_name_; } |
87 | 96 |
88 static void SetFontAndTextDirection(DictionaryValue* localized_strings); | 97 static void SetFontAndTextDirection(DictionaryValue* localized_strings); |
89 | 98 |
90 protected: | 99 protected: |
91 friend class base::RefCountedThreadSafe<DataSource>; | |
92 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; | |
93 friend class DeleteTask<DataSource>; | |
94 | |
95 virtual ~DataSource(); | 100 virtual ~DataSource(); |
96 | 101 |
97 private: | 102 private: |
103 friend class ChromeURLDataManagerBackend; | |
104 friend class ChromeURLDataManager; | |
105 friend class DeleteTask<DataSource>; | |
106 | |
107 // SendResponse invokes this on the IO thread. Notifies the backend to | |
108 // handle the actual work of sending the data. | |
109 virtual void SendResponseOnIOThread(int request_id, | |
110 scoped_refptr<RefCountedMemory> bytes); | |
111 | |
98 // The name of this source. | 112 // The name of this source. |
99 // E.g., for favicons, this could be "favicon", which results in paths for | 113 // E.g., for favicons, this could be "favicon", which results in paths for |
100 // specific resources like "favicon/34" getting sent to this source. | 114 // specific resources like "favicon/34" getting sent to this source. |
101 const std::string source_name_; | 115 const std::string source_name_; |
102 | 116 |
103 // The MessageLoop for the thread where this DataSource lives. | 117 // The MessageLoop for the thread where this DataSource lives. |
104 // Used to send messages to the DataSource. | 118 // Used to send messages to the DataSource. |
105 MessageLoop* message_loop_; | 119 MessageLoop* message_loop_; |
120 | |
121 // This field is set and maintained by ChromeURLDataManagerBackend. It is | |
122 // set when the DataSource is added, and unset if the DataSource is removed. | |
123 // A DataSource can be removed in two ways: the ChromeURLDataManagerBackend | |
124 // is deleted, or another DataSource is registered with the same | |
125 // name. backend_ should only be accessed on the IO thread. | |
126 // This reference can't be via a scoped_refptr else there would be a cycle | |
127 // between the backend and data source. | |
128 ChromeURLDataManagerBackend* backend_; | |
106 }; | 129 }; |
107 | 130 |
108 // Add a DataSource to the collection of data sources. | 131 explicit ChromeURLDataManager(Profile* profile); |
109 // Because we don't track users of a given path, we can't know when it's | 132 ~ChromeURLDataManager(); |
110 // safe to remove them, so the added source effectively leaks. | |
111 // This could be improved in the future but currently the users of this | |
112 // interface are conceptually permanent registration anyway. | |
113 // Adding a second DataSource with the same name clobbers the first. | |
114 // NOTE: Calling this from threads other the IO thread must be done via | |
115 // InvokeLater. | |
116 void AddDataSource(scoped_refptr<DataSource> source); | |
117 // Called during shutdown, before destruction of |BrowserThread|. | |
118 void RemoveDataSourceForTest(const char* source_name); // For unit tests. | |
119 void RemoveAllDataSources(); // For the browser. | |
120 | 133 |
121 // Add/remove a path from the collection of file sources. | 134 // Adds a DataSource to the collection of data sources. This *must* be invoked |
122 // A file source acts like a file:// URL to the specified path. | 135 // on the UI thread. |
123 // Calling this from threads other the IO thread must be done via | 136 // |
124 // InvokeLater. | 137 // If |AddDataSource| is called more than once for a particular name it will |
125 void AddFileSource(const std::string& source_name, const FilePath& path); | 138 // release the old |DataSource|, most likely resulting in it getting deleted |
126 void RemoveFileSource(const std::string& source_name); | 139 // as there are no other references to it. |DataSource| uses the |
140 // |DeleteOnUIThread| trait to insure that the destructor is called on the UI | |
141 // thread. This is necessary as some |DataSource|s notably |FileIconSource| | |
142 // and |WebUIFavIconSource|, have members that will DCHECK if they are not | |
143 // destructed in the same thread as they are constructed (the UI thread). | |
144 void AddDataSource(DataSource* source); | |
127 | 145 |
128 static net::URLRequestJob* Factory(net::URLRequest* request, | 146 // Deletes any data sources no longer referenced. This is normally invoked |
129 const std::string& scheme); | 147 // for you, but can be invoked to force deletion (such as during shutdown). |
148 static void DeleteDataSources(); | |
130 | 149 |
131 private: | 150 private: |
132 friend class URLRequestChromeJob; | 151 typedef std::vector<const ChromeURLDataManager::DataSource*> DataSources; |
133 friend struct DefaultSingletonTraits<ChromeURLDataManager>; | |
134 | 152 |
135 ChromeURLDataManager(); | 153 // If invoked on the UI thread the DataSource is deleted immediatlye, |
136 ~ChromeURLDataManager(); | 154 // otherwise it is added to |data_sources_| and a task is scheduled to handle |
155 // deletion on the UI thread. See note abouve DeleteDataSource for more info. | |
156 static void DeleteDataSource(const DataSource* data_source); | |
137 | 157 |
138 // Parse a URL into the components used to resolve its request. | 158 // Returns true if |data_source| is scheduled for deletion (|DeleteDataSource| |
139 static void URLToRequest(const GURL& url, | 159 // was invoked). |
140 std::string* source, | 160 static bool IsScheduledForDeletion(const DataSource* data_source); |
141 std::string* path); | |
142 | 161 |
143 // Translate a chrome resource URL into a local file path if there is one. | 162 Profile* profile_; |
144 // Returns false if there is no file handler for this URL | |
145 static bool URLToFilePath(const GURL& url, FilePath* file_path); | |
146 | 163 |
147 // Called by the job when it's starting up. | 164 // Lock used when accessing |data_sources_|. |
148 // Returns false if |url| is not a URL managed by this object. | 165 static base::Lock delete_lock_; |
149 bool StartRequest(const GURL& url, URLRequestChromeJob* job); | |
150 // Remove a request from the list of pending requests. | |
151 void RemoveRequest(URLRequestChromeJob* job); | |
152 | 166 |
153 // Returns true if the job exists in |pending_requests_|. False otherwise. | 167 // |data_sources_| that are no longer referenced and scheduled for deletion. |
154 // Called by ~URLRequestChromeJob to verify that |pending_requests_| is kept | 168 static DataSources* data_sources_; |
155 // up to date. | |
156 bool HasPendingJob(URLRequestChromeJob* job) const; | |
157 | 169 |
158 // Sent by Request::SendResponse. | 170 DISALLOW_COPY_AND_ASSIGN(ChromeURLDataManager); |
159 void DataAvailable(RequestID request_id, | |
160 scoped_refptr<RefCountedMemory> bytes); | |
161 | |
162 // File sources of data, keyed by source name (e.g. "inspector"). | |
163 typedef std::map<std::string, FilePath> FileSourceMap; | |
164 FileSourceMap file_sources_; | |
165 | |
166 // Custom sources of data, keyed by source path (e.g. "favicon"). | |
167 typedef std::map<std::string, scoped_refptr<DataSource> > DataSourceMap; | |
168 DataSourceMap data_sources_; | |
169 | |
170 // All pending URLRequestChromeJobs, keyed by ID of the request. | |
171 // URLRequestChromeJob calls into this object when it's constructed and | |
172 // destructed to ensure that the pointers in this map remain valid. | |
173 typedef std::map<RequestID, URLRequestChromeJob*> PendingRequestMap; | |
174 PendingRequestMap pending_requests_; | |
175 | |
176 // The ID we'll use for the next request we receive. | |
177 RequestID next_request_id_; | |
178 }; | 171 }; |
179 | 172 |
180 // Since we have a single global ChromeURLDataManager, we don't need to | |
181 // grab a reference to it when creating Tasks involving it. | |
182 DISABLE_RUNNABLE_METHOD_REFCOUNT(ChromeURLDataManager); | |
183 | |
184 // Register our special URL handler under our special URL scheme. | |
185 // Must be done once at startup. | |
186 void RegisterURLRequestChromeJob(); | |
187 | |
188 // Undoes the registration done by RegisterURLRequestChromeJob. | |
189 void UnregisterURLRequestChromeJob(); | |
190 | |
191 #endif // CHROME_BROWSER_DOM_UI_CHROME_URL_DATA_MANAGER_H_ | 173 #endif // CHROME_BROWSER_DOM_UI_CHROME_URL_DATA_MANAGER_H_ |
OLD | NEW |