OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_UI_WEBUI_CHROME_URL_DATA_MANAGER_H_ | 5 #ifndef CHROME_BROWSER_UI_WEBUI_CHROME_URL_DATA_MANAGER_H_ |
6 #define CHROME_BROWSER_UI_WEBUI_CHROME_URL_DATA_MANAGER_H_ | 6 #define CHROME_BROWSER_UI_WEBUI_CHROME_URL_DATA_MANAGER_H_ |
7 | 7 |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/callback.h" | 11 #include "base/callback.h" |
12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
13 #include "base/sequenced_task_runner_helpers.h" | 13 #include "base/sequenced_task_runner_helpers.h" |
14 #include "base/synchronization/lock.h" | 14 #include "base/synchronization/lock.h" |
15 #include "chrome/browser/profiles/profile_keyed_service.h" | 15 #include "chrome/browser/profiles/profile_keyed_service.h" |
16 | 16 |
17 class ChromeURLDataManagerBackend; | 17 class ChromeURLDataManagerBackend; |
18 class MessageLoop; | 18 class MessageLoop; |
19 class Profile; | 19 class Profile; |
20 | 20 |
21 namespace base { | 21 namespace base { |
22 class DictionaryValue; | 22 class DictionaryValue; |
23 class RefCountedMemory; | 23 class RefCountedMemory; |
24 } | 24 } |
25 | 25 |
| 26 namespace content { |
| 27 class URLDataSourceDelegate; |
| 28 } |
| 29 |
| 30 class URLDataSource; |
| 31 |
26 // To serve dynamic data off of chrome: URLs, implement the | 32 // To serve dynamic data off of chrome: URLs, implement the |
27 // ChromeURLDataManager::DataSource interface and register your handler | 33 // ChromeURLDataManager::DataSource interface and register your handler |
28 // with AddDataSource. DataSources must be added on the UI thread (they are also | 34 // with AddDataSource. DataSources must be added on the UI thread (they are also |
29 // deleted on the UI thread). Internally the DataSources are maintained by | 35 // deleted on the UI thread). Internally the DataSources are maintained by |
30 // ChromeURLDataManagerBackend, see it for details. | 36 // ChromeURLDataManagerBackend, see it for details. |
31 class ChromeURLDataManager : public ProfileKeyedService { | 37 class ChromeURLDataManager : public ProfileKeyedService { |
32 public: | 38 public: |
33 class DataSource; | |
34 | |
35 // Trait used to handle deleting a DataSource. Deletion happens on the UI | |
36 // thread. | |
37 // | |
38 // Implementation note: the normal shutdown sequence is for the UI loop to | |
39 // stop pumping events then the IO loop and thread are stopped. When the | |
40 // DataSources are no longer referenced (which happens when IO thread stops) | |
41 // they get added to the UI message loop for deletion. But because the UI loop | |
42 // has stopped by the time this happens the DataSources would be leaked. | |
43 // | |
44 // To make sure DataSources are properly deleted ChromeURLDataManager manages | |
45 // deletion of the DataSources. When a DataSource is no longer referenced it | |
46 // is added to |data_sources_| and a task is posted to the UI thread to handle | |
47 // the actual deletion. During shutdown |DeleteDataSources| is invoked so that | |
48 // all pending DataSources are properly deleted. | |
49 struct DeleteDataSource { | |
50 static void Destruct(const DataSource* data_source) { | |
51 ChromeURLDataManager::DeleteDataSource(data_source); | |
52 } | |
53 }; | |
54 | |
55 // A DataSource is an object that can answer requests for data | |
56 // asynchronously. DataSources are collectively owned with refcounting smart | |
57 // pointers and should never be deleted on the IO thread, since their calls | |
58 // are handled almost always on the UI thread and there's a possibility of a | |
59 // data race. The |DeleteDataSource| trait above is used to enforce this. | |
60 // | |
61 // An implementation of DataSource should handle calls to | |
62 // StartDataRequest() by starting its (implementation-specific) asynchronous | |
63 // request for the data, then call SendResponse() to notify. | |
64 class DataSource : public base::RefCountedThreadSafe< | |
65 DataSource, DeleteDataSource> { | |
66 public: | |
67 // See source_name_ and message_loop_ below for docs on these parameters. | |
68 DataSource(const std::string& source_name, MessageLoop* message_loop); | |
69 | |
70 // Sent by the DataManager to request data at |path|. The source should | |
71 // call SendResponse() when the data is available or if the request could | |
72 // not be satisfied. | |
73 virtual void StartDataRequest(const std::string& path, | |
74 bool is_incognito, | |
75 int request_id) = 0; | |
76 | |
77 // Return the mimetype that should be sent with this response, or empty | |
78 // string to specify no mime type. | |
79 virtual std::string GetMimeType(const std::string& path) const = 0; | |
80 | |
81 // Report that a request has resulted in the data |bytes|. | |
82 // If the request can't be satisfied, pass NULL for |bytes| to indicate | |
83 // the request is over. | |
84 virtual void SendResponse(int request_id, base::RefCountedMemory* bytes); | |
85 | |
86 // Returns the MessageLoop on which the DataSource wishes to have | |
87 // StartDataRequest called to handle the request for |path|. If the | |
88 // DataSource does not care which thread StartDataRequest is called on, | |
89 // this should return NULL. The default implementation always returns | |
90 // message_loop_, which generally results in processing on the UI thread. | |
91 // It may be beneficial to return NULL for requests that are safe to handle | |
92 // directly on the IO thread. This can improve performance by satisfying | |
93 // such requests more rapidly when there is a large amount of UI thread | |
94 // contention. | |
95 virtual MessageLoop* MessageLoopForRequestPath(const std::string& path) | |
96 const; | |
97 | |
98 const std::string& source_name() const { return source_name_; } | |
99 | |
100 // Returns true if this DataSource should replace an existing DataSource | |
101 // with the same name that has already been registered. The default is | |
102 // true. | |
103 // | |
104 // WARNING: this is invoked on the IO thread. | |
105 // | |
106 // TODO: nuke this and convert all callers to not replace. | |
107 virtual bool ShouldReplaceExistingSource() const; | |
108 | |
109 // Returns true if responses from this DataSource can be cached. | |
110 virtual bool AllowCaching() const; | |
111 | |
112 static void SetFontAndTextDirection( | |
113 base::DictionaryValue* localized_strings); | |
114 | |
115 protected: | |
116 virtual ~DataSource(); | |
117 | |
118 private: | |
119 friend class ChromeURLDataManagerBackend; | |
120 friend class ChromeURLDataManager; | |
121 friend class base::DeleteHelper<DataSource>; | |
122 | |
123 // SendResponse invokes this on the IO thread. Notifies the backend to | |
124 // handle the actual work of sending the data. | |
125 virtual void SendResponseOnIOThread( | |
126 int request_id, | |
127 scoped_refptr<base::RefCountedMemory> bytes); | |
128 | |
129 // The name of this source. | |
130 // E.g., for favicons, this could be "favicon", which results in paths for | |
131 // specific resources like "favicon/34" getting sent to this source. | |
132 const std::string source_name_; | |
133 | |
134 // The MessageLoop for the thread where this DataSource lives. | |
135 // Used to send messages to the DataSource. | |
136 MessageLoop* message_loop_; | |
137 | |
138 // This field is set and maintained by ChromeURLDataManagerBackend. It is | |
139 // set when the DataSource is added, and unset if the DataSource is removed. | |
140 // A DataSource can be removed in two ways: the ChromeURLDataManagerBackend | |
141 // is deleted, or another DataSource is registered with the same | |
142 // name. backend_ should only be accessed on the IO thread. | |
143 // This reference can't be via a scoped_refptr else there would be a cycle | |
144 // between the backend and data source. | |
145 ChromeURLDataManagerBackend* backend_; | |
146 }; | |
147 | |
148 explicit ChromeURLDataManager( | 39 explicit ChromeURLDataManager( |
149 const base::Callback<ChromeURLDataManagerBackend*(void)>& backend); | 40 const base::Callback<ChromeURLDataManagerBackend*(void)>& backend); |
150 virtual ~ChromeURLDataManager(); | 41 virtual ~ChromeURLDataManager(); |
151 | 42 |
152 // Adds a DataSource to the collection of data sources. This *must* be invoked | 43 // Adds a DataSource to the collection of data sources. This *must* be invoked |
153 // on the UI thread. | 44 // on the UI thread. |
154 // | 45 // |
155 // If |AddDataSource| is called more than once for a particular name it will | 46 // If |AddDataSource| is called more than once for a particular name it will |
156 // release the old |DataSource|, most likely resulting in it getting deleted | 47 // release the old |DataSource|, most likely resulting in it getting deleted |
157 // as there are no other references to it. |DataSource| uses the | 48 // as there are no other references to it. |DataSource| uses the |
158 // |DeleteOnUIThread| trait to insure that the destructor is called on the UI | 49 // |DeleteOnUIThread| trait to insure that the destructor is called on the UI |
159 // thread. This is necessary as some |DataSource|s notably |FileIconSource| | 50 // thread. This is necessary as some |DataSource|s notably |FileIconSource| |
160 // and |FaviconSource|, have members that will DCHECK if they are not | 51 // and |FaviconSource|, have members that will DCHECK if they are not |
161 // destructed in the same thread as they are constructed (the UI thread). | 52 // destructed in the same thread as they are constructed (the UI thread). |
162 void AddDataSource(DataSource* source); | 53 void AddDataSource(URLDataSource* source); |
163 | 54 |
164 // Deletes any data sources no longer referenced. This is normally invoked | 55 // Deletes any data sources no longer referenced. This is normally invoked |
165 // for you, but can be invoked to force deletion (such as during shutdown). | 56 // for you, but can be invoked to force deletion (such as during shutdown). |
166 static void DeleteDataSources(); | 57 static void DeleteDataSources(); |
167 | 58 |
168 // Convenience wrapper function to add |source| to |profile|'s | 59 // Convenience wrapper function to add |source| to |profile|'s |
169 // |ChromeURLDataManager|. | 60 // |ChromeURLDataManager|. |
170 static void AddDataSource(Profile* profile, DataSource* source); | 61 static void AddDataSource(Profile* profile, |
| 62 content::URLDataSourceDelegate* delegate); |
171 | 63 |
172 private: | 64 private: |
173 typedef std::vector<const ChromeURLDataManager::DataSource*> DataSources; | 65 friend class URLDataSource; |
| 66 friend struct DeleteURLDataSource; |
| 67 typedef std::vector<const URLDataSource*> URLDataSources; |
174 | 68 |
175 // If invoked on the UI thread the DataSource is deleted immediatlye, | 69 // If invoked on the UI thread the DataSource is deleted immediatlye, |
176 // otherwise it is added to |data_sources_| and a task is scheduled to handle | 70 // otherwise it is added to |data_sources_| and a task is scheduled to handle |
177 // deletion on the UI thread. See note abouve DeleteDataSource for more info. | 71 // deletion on the UI thread. See note abouve DeleteDataSource for more info. |
178 static void DeleteDataSource(const DataSource* data_source); | 72 static void DeleteDataSource(const URLDataSource* data_source); |
179 | 73 |
180 // Returns true if |data_source| is scheduled for deletion (|DeleteDataSource| | 74 // Returns true if |data_source| is scheduled for deletion (|DeleteDataSource| |
181 // was invoked). | 75 // was invoked). |
182 static bool IsScheduledForDeletion(const DataSource* data_source); | 76 static bool IsScheduledForDeletion(const URLDataSource* data_source); |
183 | 77 |
184 // A callback that returns the ChromeURLDataManagerBackend. Only accessible on | 78 // A callback that returns the ChromeURLDataManagerBackend. Only accessible on |
185 // the IO thread. This is necessary because ChromeURLDataManager is created on | 79 // the IO thread. This is necessary because ChromeURLDataManager is created on |
186 // the UI thread, but ChromeURLDataManagerBackend lives on the IO thread. | 80 // the UI thread, but ChromeURLDataManagerBackend lives on the IO thread. |
187 const base::Callback<ChromeURLDataManagerBackend*(void)> backend_; | 81 const base::Callback<ChromeURLDataManagerBackend*(void)> backend_; |
188 | 82 |
189 // |data_sources_| that are no longer referenced and scheduled for deletion. | 83 // |data_sources_| that are no longer referenced and scheduled for deletion. |
190 // Protected by g_delete_lock in the .cc file. | 84 // Protected by g_delete_lock in the .cc file. |
191 static DataSources* data_sources_; | 85 static URLDataSources* data_sources_; |
192 | 86 |
193 DISALLOW_COPY_AND_ASSIGN(ChromeURLDataManager); | 87 DISALLOW_COPY_AND_ASSIGN(ChromeURLDataManager); |
194 }; | 88 }; |
195 | 89 |
| 90 // Trait used to handle deleting a URLDataSource. Deletion happens on the UI |
| 91 // thread. |
| 92 // |
| 93 // Implementation note: the normal shutdown sequence is for the UI loop to |
| 94 // stop pumping events then the IO loop and thread are stopped. When the |
| 95 // URLDataSources are no longer referenced (which happens when IO thread stops) |
| 96 // they get added to the UI message loop for deletion. But because the UI loop |
| 97 // has stopped by the time this happens the URLDataSources would be leaked. |
| 98 // |
| 99 // To make sure URLDataSources are properly deleted ChromeURLDataManager manages |
| 100 // deletion of the URLDataSources. When a URLDataSource is no longer referenced |
| 101 // it is added to |data_sources_| and a task is posted to the UI thread to |
| 102 // handle the actual deletion. During shutdown |DeleteDataSources| is invoked so |
| 103 // that all pending URLDataSources are properly deleted. |
| 104 struct DeleteURLDataSource { |
| 105 static void Destruct(const URLDataSource* data_source) { |
| 106 ChromeURLDataManager::DeleteDataSource(data_source); |
| 107 } |
| 108 }; |
| 109 |
| 110 // A URLDataSource is an object that can answer requests for data |
| 111 // asynchronously. URLDataSources are collectively owned with refcounting smart |
| 112 // pointers and should never be deleted on the IO thread, since their calls |
| 113 // are handled almost always on the UI thread and there's a possibility of a |
| 114 // data race. The |DeleteDataSource| trait above is used to enforce this. |
| 115 // |
| 116 // A delegate of URLDataSource should handle calls to StartDataRequest() by |
| 117 // starting its (implementation-specific) asynchronous request for the data, |
| 118 // then call SendResponse() to notify. |
| 119 class URLDataSource : public base::RefCountedThreadSafe< |
| 120 URLDataSource, DeleteURLDataSource> { |
| 121 public: |
| 122 // See source_name_ below for docs on that parameter. Takes ownership of |
| 123 // |delegate|. |
| 124 URLDataSource(const std::string& source_name, |
| 125 content::URLDataSourceDelegate* delegate); |
| 126 |
| 127 // Report that a request has resulted in the data |bytes|. |
| 128 // If the request can't be satisfied, pass NULL for |bytes| to indicate |
| 129 // the request is over. |
| 130 virtual void SendResponse(int request_id, base::RefCountedMemory* bytes); |
| 131 |
| 132 const std::string& source_name() const { return source_name_; } |
| 133 content::URLDataSourceDelegate* delegate() const { return delegate_.get(); } |
| 134 |
| 135 static void SetFontAndTextDirection( |
| 136 base::DictionaryValue* localized_strings); |
| 137 |
| 138 protected: |
| 139 virtual ~URLDataSource(); |
| 140 |
| 141 content::URLDataSourceDelegate* release_delegate() { |
| 142 return delegate_.release(); |
| 143 } |
| 144 |
| 145 private: |
| 146 friend class ChromeURLDataManagerBackend; |
| 147 friend class ChromeURLDataManager; |
| 148 friend class base::DeleteHelper<URLDataSource>; |
| 149 |
| 150 // SendResponse invokes this on the IO thread. Notifies the backend to |
| 151 // handle the actual work of sending the data. |
| 152 virtual void SendResponseOnIOThread( |
| 153 int request_id, |
| 154 scoped_refptr<base::RefCountedMemory> bytes); |
| 155 |
| 156 // The name of this source. |
| 157 // E.g., for favicons, this could be "favicon", which results in paths for |
| 158 // specific resources like "favicon/34" getting sent to this source. |
| 159 const std::string source_name_; |
| 160 |
| 161 // This field is set and maintained by ChromeURLDataManagerBackend. It is |
| 162 // set when the DataSource is added, and unset if the DataSource is removed. |
| 163 // A DataSource can be removed in two ways: the ChromeURLDataManagerBackend |
| 164 // is deleted, or another DataSource is registered with the same |
| 165 // name. backend_ should only be accessed on the IO thread. |
| 166 // This reference can't be via a scoped_refptr else there would be a cycle |
| 167 // between the backend and data source. |
| 168 ChromeURLDataManagerBackend* backend_; |
| 169 |
| 170 scoped_ptr<content::URLDataSourceDelegate> delegate_; |
| 171 }; |
| 172 |
196 #endif // CHROME_BROWSER_UI_WEBUI_CHROME_URL_DATA_MANAGER_H_ | 173 #endif // CHROME_BROWSER_UI_WEBUI_CHROME_URL_DATA_MANAGER_H_ |
OLD | NEW |