1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_WEBUI_URL_DATA_MANAGER_H_
#define CONTENT_BROWSER_WEBUI_URL_DATA_MANAGER_H_
#include <string>
#include <vector>
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/sequenced_task_runner_helpers.h"
#include "base/supports_user_data.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
class ChromeURLDataManagerBackend;
class MessageLoop;
namespace base {
class RefCountedMemory;
}
namespace content {
class BrowserContext;
class URLDataSource;
class WebUIDataSource;
}
class URLDataSourceImpl;
// To serve dynamic data off of chrome: URLs, implement the
// ChromeURLDataManager::DataSource interface and register your handler
// with AddDataSource. DataSources must be added on the UI thread (they are also
// deleted on the UI thread). Internally the DataSources are maintained by
// ChromeURLDataManagerBackend, see it for details.
class CONTENT_EXPORT ChromeURLDataManager
: public base::SupportsUserData::Data {
public:
explicit ChromeURLDataManager(content::BrowserContext* browser_context);
virtual ~ChromeURLDataManager();
// Adds a DataSource to the collection of data sources. This *must* be invoked
// on the UI thread.
//
// If |AddDataSource| is called more than once for a particular name it will
// release the old |DataSource|, most likely resulting in it getting deleted
// as there are no other references to it. |DataSource| uses the
// |DeleteOnUIThread| trait to insure that the destructor is called on the UI
// thread. This is necessary as some |DataSource|s notably |FileIconSource|
// and |FaviconSource|, have members that will DCHECK if they are not
// destructed in the same thread as they are constructed (the UI thread).
void AddDataSource(URLDataSourceImpl* source);
// Deletes any data sources no longer referenced. This is normally invoked
// for you, but can be invoked to force deletion (such as during shutdown).
static void DeleteDataSources();
// Convenience wrapper function to add |source| to |browser_context|'s
// |ChromeURLDataManager|. Creates a URLDataSourceImpl to wrap the given
// source.
static void AddDataSource(
content::BrowserContext* browser_context,
content::URLDataSource* source);
// Adds a WebUI data source to |browser_context|'s |ChromeURLDataManager|.
static void AddWebUIDataSource(
content::BrowserContext* browser_context,
content::WebUIDataSource* source);
private:
friend class URLDataSourceImpl;
friend struct DeleteURLDataSource;
typedef std::vector<const URLDataSourceImpl*> URLDataSources;
// If invoked on the UI thread the DataSource is deleted immediatlye,
// otherwise it is added to |data_sources_| and a task is scheduled to handle
// deletion on the UI thread. See note abouve DeleteDataSource for more info.
static void DeleteDataSource(const URLDataSourceImpl* data_source);
// Returns true if |data_source| is scheduled for deletion (|DeleteDataSource|
// was invoked).
static bool IsScheduledForDeletion(const URLDataSourceImpl* data_source);
content::BrowserContext* browser_context_;
// |data_sources_| that are no longer referenced and scheduled for deletion.
// Protected by g_delete_lock in the .cc file.
static URLDataSources* data_sources_;
DISALLOW_COPY_AND_ASSIGN(ChromeURLDataManager);
};
// Trait used to handle deleting a URLDataSource. Deletion happens on the UI
// thread.
//
// Implementation note: the normal shutdown sequence is for the UI loop to
// stop pumping events then the IO loop and thread are stopped. When the
// URLDataSources are no longer referenced (which happens when IO thread stops)
// they get added to the UI message loop for deletion. But because the UI loop
// has stopped by the time this happens the URLDataSources would be leaked.
//
// To make sure URLDataSources are properly deleted ChromeURLDataManager manages
// deletion of the URLDataSources. When a URLDataSource is no longer referenced
// it is added to |data_sources_| and a task is posted to the UI thread to
// handle the actual deletion. During shutdown |DeleteDataSources| is invoked so
// that all pending URLDataSources are properly deleted.
struct DeleteURLDataSource {
static void Destruct(const URLDataSourceImpl* data_source) {
ChromeURLDataManager::DeleteDataSource(data_source);
}
};
// A URLDataSource is an object that can answer requests for data
// asynchronously. URLDataSources are collectively owned with refcounting smart
// pointers and should never be deleted on the IO thread, since their calls
// are handled almost always on the UI thread and there's a possibility of a
// data race. The |DeleteDataSource| trait above is used to enforce this.
class URLDataSourceImpl : public base::RefCountedThreadSafe<
URLDataSourceImpl, DeleteURLDataSource> {
public:
// See source_name_ below for docs on that parameter. Takes ownership of
// |source|.
URLDataSourceImpl(const std::string& source_name,
content::URLDataSource* source);
// Report that a request has resulted in the data |bytes|.
// If the request can't be satisfied, pass NULL for |bytes| to indicate
// the request is over.
virtual void SendResponse(int request_id, base::RefCountedMemory* bytes);
const std::string& source_name() const { return source_name_; }
content::URLDataSource* source() const { return source_.get(); }
protected:
virtual ~URLDataSourceImpl();
private:
friend class ChromeURLDataManagerBackend;
friend class ChromeURLDataManager;
friend class base::DeleteHelper<URLDataSourceImpl>;
// SendResponse invokes this on the IO thread. Notifies the backend to
// handle the actual work of sending the data.
virtual void SendResponseOnIOThread(
int request_id,
scoped_refptr<base::RefCountedMemory> bytes);
// The name of this source.
// E.g., for favicons, this could be "favicon", which results in paths for
// specific resources like "favicon/34" getting sent to this source.
const std::string source_name_;
// This field is set and maintained by ChromeURLDataManagerBackend. It is
// set when the DataSource is added, and unset if the DataSource is removed.
// A DataSource can be removed in two ways: the ChromeURLDataManagerBackend
// is deleted, or another DataSource is registered with the same
// name. backend_ should only be accessed on the IO thread.
// This reference can't be via a scoped_refptr else there would be a cycle
// between the backend and data source.
ChromeURLDataManagerBackend* backend_;
scoped_ptr<content::URLDataSource> source_;
};
#endif // CONTENT_BROWSER_WEBUI_URL_DATA_MANAGER_H_
|