blob: 52aabe11018816f081e87b4f11f83548b9f0fb37 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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"
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01009#include "base/strings/nullable_string16.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010#include "base/strings/utf_string_conversions.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000011#include "base/threading/sequenced_worker_pool.h"
Ben Murdochbb1529c2013-08-08 10:24:53 +010012#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"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010018#include "content/public/browser/user_metrics.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010019#include "url/gurl.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000020
Torne (Richard Coles)58218062012-11-14 11:43:16 +000021namespace content {
22
23DOMStorageMessageFilter::DOMStorageMessageFilter(
24 int unused,
Ben Murdochbb1529c2013-08-08 10:24:53 +010025 DOMStorageContextWrapper* context)
Torne (Richard Coles)58218062012-11-14 11:43:16 +000026 : context_(context->context()),
27 connection_dispatching_message_for_(0) {
28}
29
30DOMStorageMessageFilter::~DOMStorageMessageFilter() {
31 DCHECK(!host_.get());
32}
33
34void DOMStorageMessageFilter::InitializeInSequence() {
35 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
Ben Murdochbb1529c2013-08-08 10:24:53 +010036 host_.reset(new DOMStorageHost(context_.get()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +000037 context_->AddEventObserver(this);
38}
39
40void DOMStorageMessageFilter::UninitializeInSequence() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000041 // TODO(michaeln): Restore this DCHECK once crbug/166470 and crbug/164403
42 // are resolved.
43 // DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
Torne (Richard Coles)58218062012-11-14 11:43:16 +000044 context_->RemoveEventObserver(this);
45 host_.reset();
46}
47
48void DOMStorageMessageFilter::OnFilterAdded(IPC::Channel* channel) {
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
50 BrowserMessageFilter::OnFilterAdded(channel);
51 context_->task_runner()->PostShutdownBlockingTask(
52 FROM_HERE,
Ben Murdochbb1529c2013-08-08 10:24:53 +010053 DOMStorageTaskRunner::PRIMARY_SEQUENCE,
Torne (Richard Coles)58218062012-11-14 11:43:16 +000054 base::Bind(&DOMStorageMessageFilter::InitializeInSequence, this));
55}
56
57void DOMStorageMessageFilter::OnFilterRemoved() {
58 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
59 BrowserMessageFilter::OnFilterRemoved();
60 context_->task_runner()->PostShutdownBlockingTask(
61 FROM_HERE,
Ben Murdochbb1529c2013-08-08 10:24:53 +010062 DOMStorageTaskRunner::PRIMARY_SEQUENCE,
Torne (Richard Coles)58218062012-11-14 11:43:16 +000063 base::Bind(&DOMStorageMessageFilter::UninitializeInSequence, this));
64}
65
66base::TaskRunner* DOMStorageMessageFilter::OverrideTaskRunnerForMessage(
67 const IPC::Message& message) {
68 if (IPC_MESSAGE_CLASS(message) == DOMStorageMsgStart)
69 return context_->task_runner();
70 return NULL;
71}
72
73bool DOMStorageMessageFilter::OnMessageReceived(const IPC::Message& message,
74 bool* message_was_ok) {
75 if (IPC_MESSAGE_CLASS(message) != DOMStorageMsgStart)
76 return false;
77 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
78 DCHECK(host_.get());
79
80 bool handled = true;
81 IPC_BEGIN_MESSAGE_MAP_EX(DOMStorageMessageFilter, message, *message_was_ok)
82 IPC_MESSAGE_HANDLER(DOMStorageHostMsg_OpenStorageArea, OnOpenStorageArea)
83 IPC_MESSAGE_HANDLER(DOMStorageHostMsg_CloseStorageArea, OnCloseStorageArea)
84 IPC_MESSAGE_HANDLER(DOMStorageHostMsg_LoadStorageArea, OnLoadStorageArea)
85 IPC_MESSAGE_HANDLER(DOMStorageHostMsg_SetItem, OnSetItem)
86 IPC_MESSAGE_HANDLER(DOMStorageHostMsg_RemoveItem, OnRemoveItem)
87 IPC_MESSAGE_HANDLER(DOMStorageHostMsg_Clear, OnClear)
88 IPC_MESSAGE_HANDLER(DOMStorageHostMsg_FlushMessages, OnFlushMessages)
89 IPC_MESSAGE_UNHANDLED(handled = false)
90 IPC_END_MESSAGE_MAP()
91 return handled;
92}
93
94void DOMStorageMessageFilter::OnOpenStorageArea(int connection_id,
95 int64 namespace_id,
96 const GURL& origin) {
97 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
98 if (!host_->OpenStorageArea(connection_id, namespace_id, origin)) {
99 RecordAction(UserMetricsAction("BadMessageTerminate_DSMF_1"));
100 BadMessageReceived();
101 }
102}
103
104void DOMStorageMessageFilter::OnCloseStorageArea(int connection_id) {
105 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
106 host_->CloseStorageArea(connection_id);
107}
108
109void DOMStorageMessageFilter::OnLoadStorageArea(int connection_id,
Ben Murdochbb1529c2013-08-08 10:24:53 +0100110 DOMStorageValuesMap* map) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000111 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
112 if (!host_->ExtractAreaValues(connection_id, map)) {
113 RecordAction(UserMetricsAction("BadMessageTerminate_DSMF_2"));
114 BadMessageReceived();
115 }
116 Send(new DOMStorageMsg_AsyncOperationComplete(true));
117}
118
119void DOMStorageMessageFilter::OnSetItem(
120 int connection_id, const string16& key,
121 const string16& value, const GURL& page_url) {
122 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
123 DCHECK_EQ(0, connection_dispatching_message_for_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000124 base::AutoReset<int> auto_reset(&connection_dispatching_message_for_,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000125 connection_id);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100126 base::NullableString16 not_used;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000127 bool success = host_->SetAreaItem(connection_id, key, value,
128 page_url, &not_used);
129 Send(new DOMStorageMsg_AsyncOperationComplete(success));
130}
131
132void DOMStorageMessageFilter::OnRemoveItem(
133 int connection_id, const string16& key,
134 const GURL& page_url) {
135 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
136 DCHECK_EQ(0, connection_dispatching_message_for_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000137 base::AutoReset<int> auto_reset(&connection_dispatching_message_for_,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000138 connection_id);
139 string16 not_used;
140 host_->RemoveAreaItem(connection_id, key, page_url, &not_used);
141 Send(new DOMStorageMsg_AsyncOperationComplete(true));
142}
143
144void DOMStorageMessageFilter::OnClear(
145 int connection_id, const GURL& page_url) {
146 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
147 DCHECK_EQ(0, connection_dispatching_message_for_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000148 base::AutoReset<int> auto_reset(&connection_dispatching_message_for_,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000149 connection_id);
150 host_->ClearArea(connection_id, page_url);
151 Send(new DOMStorageMsg_AsyncOperationComplete(true));
152}
153
154void DOMStorageMessageFilter::OnFlushMessages() {
155 // Intentionally empty method body.
156}
157
Ben Murdochbb1529c2013-08-08 10:24:53 +0100158void DOMStorageMessageFilter::OnDOMStorageItemSet(
159 const DOMStorageArea* area,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000160 const string16& key,
161 const string16& new_value,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100162 const base::NullableString16& old_value,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000163 const GURL& page_url) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100164 SendDOMStorageEvent(area, page_url,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100165 base::NullableString16(key, false),
166 base::NullableString16(new_value, false),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000167 old_value);
168}
169
Ben Murdochbb1529c2013-08-08 10:24:53 +0100170void DOMStorageMessageFilter::OnDOMStorageItemRemoved(
171 const DOMStorageArea* area,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000172 const string16& key,
173 const string16& old_value,
174 const GURL& page_url) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100175 SendDOMStorageEvent(area, page_url,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100176 base::NullableString16(key, false),
177 base::NullableString16(),
178 base::NullableString16(old_value, false));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000179}
180
Ben Murdochbb1529c2013-08-08 10:24:53 +0100181void DOMStorageMessageFilter::OnDOMStorageAreaCleared(
182 const DOMStorageArea* area,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000183 const GURL& page_url) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100184 SendDOMStorageEvent(area, page_url,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100185 base::NullableString16(),
186 base::NullableString16(),
187 base::NullableString16());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000188}
189
Ben Murdochbb1529c2013-08-08 10:24:53 +0100190void DOMStorageMessageFilter::SendDOMStorageEvent(
191 const DOMStorageArea* area,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000192 const GURL& page_url,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100193 const base::NullableString16& key,
194 const base::NullableString16& new_value,
195 const base::NullableString16& old_value) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000196 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
197 // Only send mutation events to processes which have the area open.
198 bool originated_in_process = connection_dispatching_message_for_ != 0;
199 if (originated_in_process ||
200 host_->HasAreaOpen(area->namespace_id(), area->origin())) {
201 DOMStorageMsg_Event_Params params;
202 params.origin = area->origin();
203 params.page_url = page_url;
204 params.connection_id = connection_dispatching_message_for_;
205 params.key = key;
206 params.new_value = new_value;
207 params.old_value = old_value;
208 params.namespace_id = area->namespace_id();
209 Send(new DOMStorageMsg_Event(params));
210 }
211}
212
213} // namespace content