- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / dom_storage / dom_storage_message_filter.cc
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
3 // found in the LICENSE file.
4
5 #include "content/browser/dom_storage/dom_storage_message_filter.h"
6
7 #include "base/auto_reset.h"
8 #include "base/bind.h"
9 #include "base/strings/nullable_string16.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "content/browser/dom_storage/dom_storage_area.h"
13 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
14 #include "content/browser/dom_storage/dom_storage_host.h"
15 #include "content/browser/dom_storage/dom_storage_namespace.h"
16 #include "content/browser/dom_storage/dom_storage_task_runner.h"
17 #include "content/common/dom_storage/dom_storage_messages.h"
18 #include "content/public/browser/user_metrics.h"
19 #include "url/gurl.h"
20
21 namespace content {
22
23 DOMStorageMessageFilter::DOMStorageMessageFilter(
24     int render_process_id,
25     DOMStorageContextWrapper* context)
26     : render_process_id_(render_process_id),
27       context_(context->context()),
28       connection_dispatching_message_for_(0) {
29 }
30
31 DOMStorageMessageFilter::~DOMStorageMessageFilter() {
32   DCHECK(!host_.get());
33 }
34
35 void DOMStorageMessageFilter::InitializeInSequence() {
36   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
37   host_.reset(new DOMStorageHost(context_.get(), render_process_id_));
38   context_->AddEventObserver(this);
39 }
40
41 void DOMStorageMessageFilter::UninitializeInSequence() {
42   // TODO(michaeln): Restore this DCHECK once crbug/166470 and crbug/164403
43   // are resolved.
44   // DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
45   context_->RemoveEventObserver(this);
46   host_.reset();
47 }
48
49 void DOMStorageMessageFilter::OnFilterAdded(IPC::Channel* channel) {
50   context_->task_runner()->PostShutdownBlockingTask(
51       FROM_HERE,
52       DOMStorageTaskRunner::PRIMARY_SEQUENCE,
53       base::Bind(&DOMStorageMessageFilter::InitializeInSequence, this));
54 }
55
56 void DOMStorageMessageFilter::OnFilterRemoved() {
57   context_->task_runner()->PostShutdownBlockingTask(
58       FROM_HERE,
59       DOMStorageTaskRunner::PRIMARY_SEQUENCE,
60       base::Bind(&DOMStorageMessageFilter::UninitializeInSequence, this));
61 }
62
63 base::TaskRunner* DOMStorageMessageFilter::OverrideTaskRunnerForMessage(
64     const IPC::Message& message) {
65   if (IPC_MESSAGE_CLASS(message) == DOMStorageMsgStart)
66     return context_->task_runner();
67   return NULL;
68 }
69
70 bool DOMStorageMessageFilter::OnMessageReceived(const IPC::Message& message,
71                                                 bool* message_was_ok) {
72   if (IPC_MESSAGE_CLASS(message) != DOMStorageMsgStart)
73     return false;
74   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
75   DCHECK(host_.get());
76
77   bool handled = true;
78   IPC_BEGIN_MESSAGE_MAP_EX(DOMStorageMessageFilter, message, *message_was_ok)
79     IPC_MESSAGE_HANDLER(DOMStorageHostMsg_OpenStorageArea, OnOpenStorageArea)
80     IPC_MESSAGE_HANDLER(DOMStorageHostMsg_CloseStorageArea, OnCloseStorageArea)
81     IPC_MESSAGE_HANDLER(DOMStorageHostMsg_LoadStorageArea, OnLoadStorageArea)
82     IPC_MESSAGE_HANDLER(DOMStorageHostMsg_SetItem, OnSetItem)
83     IPC_MESSAGE_HANDLER(DOMStorageHostMsg_LogGetItem, OnLogGetItem)
84     IPC_MESSAGE_HANDLER(DOMStorageHostMsg_RemoveItem, OnRemoveItem)
85     IPC_MESSAGE_HANDLER(DOMStorageHostMsg_Clear, OnClear)
86     IPC_MESSAGE_HANDLER(DOMStorageHostMsg_FlushMessages, OnFlushMessages)
87     IPC_MESSAGE_UNHANDLED(handled = false)
88   IPC_END_MESSAGE_MAP()
89   return handled;
90 }
91
92 void DOMStorageMessageFilter::OnOpenStorageArea(int connection_id,
93                                                 int64 namespace_id,
94                                                 const GURL& origin) {
95   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
96   if (!host_->OpenStorageArea(connection_id, namespace_id, origin)) {
97     RecordAction(UserMetricsAction("BadMessageTerminate_DSMF_1"));
98     BadMessageReceived();
99   }
100 }
101
102 void DOMStorageMessageFilter::OnCloseStorageArea(int connection_id) {
103   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
104   host_->CloseStorageArea(connection_id);
105 }
106
107 void DOMStorageMessageFilter::OnLoadStorageArea(int connection_id,
108                                                 DOMStorageValuesMap* map,
109                                                 bool* send_log_get_messages) {
110   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
111   if (!host_->ExtractAreaValues(connection_id, map, send_log_get_messages)) {
112     RecordAction(UserMetricsAction("BadMessageTerminate_DSMF_2"));
113     BadMessageReceived();
114   }
115   Send(new DOMStorageMsg_AsyncOperationComplete(true));
116 }
117
118 void DOMStorageMessageFilter::OnSetItem(
119     int connection_id, const string16& key,
120     const string16& value, const GURL& page_url) {
121   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
122   DCHECK_EQ(0, connection_dispatching_message_for_);
123   base::AutoReset<int> auto_reset(&connection_dispatching_message_for_,
124                             connection_id);
125   base::NullableString16 not_used;
126   bool success = host_->SetAreaItem(connection_id, key, value,
127                                     page_url, &not_used);
128   Send(new DOMStorageMsg_AsyncOperationComplete(success));
129 }
130
131 void DOMStorageMessageFilter::OnLogGetItem(
132     int connection_id, const string16& key,
133     const base::NullableString16& value) {
134   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
135   host_->LogGetAreaItem(connection_id, key, value);
136 }
137
138 void DOMStorageMessageFilter::OnRemoveItem(
139     int connection_id, const string16& key,
140     const GURL& page_url) {
141   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
142   DCHECK_EQ(0, connection_dispatching_message_for_);
143   base::AutoReset<int> auto_reset(&connection_dispatching_message_for_,
144                             connection_id);
145   string16 not_used;
146   host_->RemoveAreaItem(connection_id, key, page_url, &not_used);
147   Send(new DOMStorageMsg_AsyncOperationComplete(true));
148 }
149
150 void DOMStorageMessageFilter::OnClear(
151     int connection_id, const GURL& page_url) {
152   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
153   DCHECK_EQ(0, connection_dispatching_message_for_);
154   base::AutoReset<int> auto_reset(&connection_dispatching_message_for_,
155                             connection_id);
156   host_->ClearArea(connection_id, page_url);
157   Send(new DOMStorageMsg_AsyncOperationComplete(true));
158 }
159
160 void DOMStorageMessageFilter::OnFlushMessages() {
161   // Intentionally empty method body.
162 }
163
164 void DOMStorageMessageFilter::OnDOMStorageItemSet(
165     const DOMStorageArea* area,
166     const string16& key,
167     const string16& new_value,
168     const base::NullableString16& old_value,
169     const GURL& page_url) {
170   SendDOMStorageEvent(area, page_url,
171                       base::NullableString16(key, false),
172                       base::NullableString16(new_value, false),
173                       old_value);
174 }
175
176 void DOMStorageMessageFilter::OnDOMStorageItemRemoved(
177     const DOMStorageArea* area,
178     const string16& key,
179     const string16& old_value,
180     const GURL& page_url) {
181   SendDOMStorageEvent(area, page_url,
182                       base::NullableString16(key, false),
183                       base::NullableString16(),
184                       base::NullableString16(old_value, false));
185 }
186
187 void DOMStorageMessageFilter::OnDOMStorageAreaCleared(
188     const DOMStorageArea* area,
189     const GURL& page_url) {
190   SendDOMStorageEvent(area, page_url,
191                       base::NullableString16(),
192                       base::NullableString16(),
193                       base::NullableString16());
194 }
195
196 void DOMStorageMessageFilter::SendDOMStorageEvent(
197     const DOMStorageArea* area,
198     const GURL& page_url,
199     const base::NullableString16& key,
200     const base::NullableString16& new_value,
201     const base::NullableString16& old_value) {
202   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
203   // Only send mutation events to processes which have the area open.
204   bool originated_in_process = connection_dispatching_message_for_ != 0;
205   if (originated_in_process ||
206       host_->HasAreaOpen(area->namespace_id(), area->origin())) {
207     DOMStorageMsg_Event_Params params;
208     params.origin = area->origin();
209     params.page_url = page_url;
210     params.connection_id = connection_dispatching_message_for_;
211     params.key = key;
212     params.new_value = new_value;
213     params.old_value = old_value;
214     params.namespace_id = area->namespace_id();
215     Send(new DOMStorageMsg_Event(params));
216   }
217 }
218
219 }  // namespace content