OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_COMMON_DB_MESSAGE_FILTER_H_ | 5 #ifndef CHROME_COMMON_DB_MESSAGE_FILTER_H_ |
6 #define CHROME_COMMON_DB_MESSAGE_FILTER_H_ | 6 #define CHROME_COMMON_DB_MESSAGE_FILTER_H_ |
7 | 7 |
8 #include "base/atomic_sequence_num.h" | |
9 #include "base/id_map.h" | |
10 #include "base/lock.h" | |
11 #include "base/scoped_ptr.h" | |
12 #include "base/waitable_event.h" | |
13 #include "ipc/ipc_channel_proxy.h" | 8 #include "ipc/ipc_channel_proxy.h" |
14 | 9 |
15 class Lock; | 10 // Receives database messages from the browser process and processes them on the |
16 class MessageLoop; | 11 // IO thread. |
17 | |
18 namespace IPC { | |
19 class Channel; | |
20 } | |
21 | |
22 // A thread-safe message filter used to send IPCs from DB threads and process | |
23 // replies from the browser process. | |
24 // | |
25 // This class should not be instantianted anywhere but RenderThread::Init(). It | |
26 // is meant to be a singleton in each renderer process. To access the singleton, | |
27 // use GetInstance(). | |
28 class DBMessageFilter : public IPC::ChannelProxy::MessageFilter { | 12 class DBMessageFilter : public IPC::ChannelProxy::MessageFilter { |
29 public: | 13 public: |
30 // Returns the DBMessageFilter singleton created in this renderer process. | |
31 static DBMessageFilter* GetInstance() { return instance_; } | |
32 | |
33 // Creates a new DBMessageFilter instance. | |
34 DBMessageFilter(); | 14 DBMessageFilter(); |
35 | 15 |
36 // Returns a unique ID for use when calling the SendAndWait() method. | 16 private: |
37 virtual int GetUniqueID(); | |
38 | |
39 // Posts a task to the IO thread to send |message| to the browser. | |
40 virtual void Send(IPC::Message* message); | |
41 | |
42 // Sends |message| and blocks the current thread. Returns the result from the | |
43 // reply message, or |default_result| if the renderer process is being | |
44 // destroyed or the message could not be sent. | |
45 template<class ResultType> | |
46 ResultType SendAndWait(IPC::Message* message, | |
47 int message_id, | |
48 ResultType default_result) { | |
49 ResultType result = default_result; | |
50 base::WaitableEvent waitable_event(false, false); | |
51 DBMessageState state = | |
52 { reinterpret_cast<intptr_t>(&result), &waitable_event }; | |
53 { | |
54 AutoLock msgs_awaiting_replies_autolock(messages_awaiting_replies_lock_); | |
55 messages_awaiting_replies_->AddWithID(&state, message_id); | |
56 } | |
57 | |
58 Send(message); | |
59 | |
60 base::WaitableEvent* events[2] = { shutdown_event_, &waitable_event }; | |
61 base::WaitableEvent::WaitMany(events, 2); | |
62 | |
63 // Locking on messages_awaiting_replies_ guarantees that either the IO | |
64 // thread won't enter OnResponse(), or if it's already in OnResponse(), | |
65 // then WaitableEvent::Signal() will get a chance to do all its work | |
66 // before waitable_event is deleted. | |
67 AutoLock msgs_awaiting_replies_autolock(messages_awaiting_replies_lock_); | |
68 messages_awaiting_replies_->Remove(message_id); | |
69 return result; | |
70 } | |
71 | |
72 // Processes incoming message |message| from the browser process. | |
73 virtual bool OnMessageReceived(const IPC::Message& message); | 17 virtual bool OnMessageReceived(const IPC::Message& message); |
74 | 18 |
75 private: | |
76 // The state we store for each message we send. | |
77 struct DBMessageState { | |
78 intptr_t result_address_; | |
79 base::WaitableEvent* waitable_event_; | |
80 }; | |
81 | |
82 // This is a RefCounted class, do not allow anybody to destroy it directly. | |
83 virtual ~DBMessageFilter() { instance_ = NULL; } | |
84 | |
85 // Invoked when this filter is added to |channel|. | |
86 virtual void OnFilterAdded(IPC::Channel* channel); | |
87 | |
88 // Called when the channel encounters a problem. The filter should clean up | |
89 // its internal data and not accept any more messages. | |
90 virtual void OnChannelError(); | |
91 | |
92 // Called when the channel is closing. The filter should clean up its internal | |
93 // and not accept any more messages. | |
94 virtual void OnChannelClosing(); | |
95 | |
96 // Processes the reply to a sync DB request. | |
97 template<class ResultType> | |
98 void OnResponse(int32 message_id, ResultType result) { | |
99 AutoLock msgs_awaiting_replies_autolock(messages_awaiting_replies_lock_); | |
100 DBMessageState *state = messages_awaiting_replies_->Lookup(message_id); | |
101 if (state) { | |
102 *reinterpret_cast<ResultType*>(state->result_address_) = result; | |
103 state->waitable_event_->Signal(); | |
104 } | |
105 } | |
106 | |
107 // Processes IPCs that indicate a change in the size of a DB file. | |
108 void OnDatabaseUpdateSize(const string16& origin_identifier, | 19 void OnDatabaseUpdateSize(const string16& origin_identifier, |
109 const string16& database_name, | 20 const string16& database_name, |
110 int64 database_size, | 21 int64 database_size, |
111 int64 space_available); | 22 int64 space_available); |
112 | |
113 // Processes IPCs that ask for a DB to be closed immediately. | |
114 void OnDatabaseCloseImmediately(const string16& origin_identifier, | 23 void OnDatabaseCloseImmediately(const string16& origin_identifier, |
115 const string16& database_name); | 24 const string16& database_name); |
116 | |
117 // The message loop for the IO thread. | |
118 MessageLoop* io_thread_message_loop_; | |
119 | |
120 // The channel to which this filter was added. | |
121 IPC::Channel* channel_; | |
122 | |
123 // A lock around the channel. | |
124 Lock channel_lock_; | |
125 | |
126 // The shutdown event. | |
127 base::WaitableEvent* shutdown_event_; | |
128 | |
129 // The list of messages awaiting replies. For each such message we store a | |
130 // DBMessageState instance. | |
131 scoped_ptr<IDMap<DBMessageState> > messages_awaiting_replies_; | |
132 | |
133 // The lock for 'messages_awaiting_replies_'. | |
134 Lock messages_awaiting_replies_lock_; | |
135 | |
136 // A thread-safe unique number generator. | |
137 scoped_ptr<base::AtomicSequenceNumber> unique_id_generator_; | |
138 | |
139 // The singleton. | |
140 static DBMessageFilter* instance_; | |
141 }; | 25 }; |
142 | 26 |
143 #endif // CHROME_COMMON_DB_MESSAGE_FILTER_H_ | 27 #endif // CHROME_COMMON_DB_MESSAGE_FILTER_H_ |
OLD | NEW |