• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DOMStorageMessageFilter(int render_process_id,DOMStorageContextWrapper * context)23 DOMStorageMessageFilter::DOMStorageMessageFilter(
24     int render_process_id,
25     DOMStorageContextWrapper* context)
26     : BrowserMessageFilter(DOMStorageMsgStart),
27       render_process_id_(render_process_id),
28       context_(context->context()),
29       connection_dispatching_message_for_(0) {
30 }
31 
~DOMStorageMessageFilter()32 DOMStorageMessageFilter::~DOMStorageMessageFilter() {
33   DCHECK(!host_.get());
34 }
35 
InitializeInSequence()36 void DOMStorageMessageFilter::InitializeInSequence() {
37   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
38   host_.reset(new DOMStorageHost(context_.get(), render_process_id_));
39   context_->AddEventObserver(this);
40 }
41 
UninitializeInSequence()42 void DOMStorageMessageFilter::UninitializeInSequence() {
43   // TODO(michaeln): Restore this DCHECK once crbug/166470 and crbug/164403
44   // are resolved.
45   // DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
46   context_->RemoveEventObserver(this);
47   host_.reset();
48 }
49 
OnFilterAdded(IPC::Sender * sender)50 void DOMStorageMessageFilter::OnFilterAdded(IPC::Sender* sender) {
51   context_->task_runner()->PostShutdownBlockingTask(
52       FROM_HERE,
53       DOMStorageTaskRunner::PRIMARY_SEQUENCE,
54       base::Bind(&DOMStorageMessageFilter::InitializeInSequence, this));
55 }
56 
OnFilterRemoved()57 void DOMStorageMessageFilter::OnFilterRemoved() {
58   context_->task_runner()->PostShutdownBlockingTask(
59       FROM_HERE,
60       DOMStorageTaskRunner::PRIMARY_SEQUENCE,
61       base::Bind(&DOMStorageMessageFilter::UninitializeInSequence, this));
62 }
63 
OverrideTaskRunnerForMessage(const IPC::Message & message)64 base::TaskRunner* DOMStorageMessageFilter::OverrideTaskRunnerForMessage(
65     const IPC::Message& message) {
66   if (IPC_MESSAGE_CLASS(message) == DOMStorageMsgStart)
67     return context_->task_runner();
68   return NULL;
69 }
70 
OnMessageReceived(const IPC::Message & message)71 bool DOMStorageMessageFilter::OnMessageReceived(const IPC::Message& message) {
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(DOMStorageMessageFilter, message)
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 
OnOpenStorageArea(int connection_id,int64 namespace_id,const GURL & origin)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(base::UserMetricsAction("BadMessageTerminate_DSMF_1"));
98     BadMessageReceived();
99   }
100 }
101 
OnCloseStorageArea(int connection_id)102 void DOMStorageMessageFilter::OnCloseStorageArea(int connection_id) {
103   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
104   host_->CloseStorageArea(connection_id);
105 }
106 
OnLoadStorageArea(int connection_id,DOMStorageValuesMap * map,bool * send_log_get_messages)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(base::UserMetricsAction("BadMessageTerminate_DSMF_2"));
113     BadMessageReceived();
114   }
115   Send(new DOMStorageMsg_AsyncOperationComplete(true));
116 }
117 
OnSetItem(int connection_id,const base::string16 & key,const base::string16 & value,const GURL & page_url)118 void DOMStorageMessageFilter::OnSetItem(
119     int connection_id, const base::string16& key,
120     const base::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 
OnLogGetItem(int connection_id,const base::string16 & key,const base::NullableString16 & value)131 void DOMStorageMessageFilter::OnLogGetItem(
132     int connection_id, const base::string16& key,
133     const base::NullableString16& value) {
134   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
135   host_->LogGetAreaItem(connection_id, key, value);
136 }
137 
OnRemoveItem(int connection_id,const base::string16 & key,const GURL & page_url)138 void DOMStorageMessageFilter::OnRemoveItem(
139     int connection_id, const base::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   base::string16 not_used;
146   host_->RemoveAreaItem(connection_id, key, page_url, &not_used);
147   Send(new DOMStorageMsg_AsyncOperationComplete(true));
148 }
149 
OnClear(int connection_id,const GURL & page_url)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 
OnFlushMessages()160 void DOMStorageMessageFilter::OnFlushMessages() {
161   // Intentionally empty method body.
162 }
163 
OnDOMStorageItemSet(const DOMStorageArea * area,const base::string16 & key,const base::string16 & new_value,const base::NullableString16 & old_value,const GURL & page_url)164 void DOMStorageMessageFilter::OnDOMStorageItemSet(
165     const DOMStorageArea* area,
166     const base::string16& key,
167     const base::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 
OnDOMStorageItemRemoved(const DOMStorageArea * area,const base::string16 & key,const base::string16 & old_value,const GURL & page_url)176 void DOMStorageMessageFilter::OnDOMStorageItemRemoved(
177     const DOMStorageArea* area,
178     const base::string16& key,
179     const base::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 
OnDOMStorageAreaCleared(const DOMStorageArea * area,const GURL & page_url)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 
OnDOMSessionStorageReset(int64 namespace_id)196 void DOMStorageMessageFilter::OnDOMSessionStorageReset(int64 namespace_id) {
197   if (host_->ResetOpenAreasForNamespace(namespace_id))
198     Send(new DOMStorageMsg_ResetCachedValues(namespace_id));
199 }
200 
SendDOMStorageEvent(const DOMStorageArea * area,const GURL & page_url,const base::NullableString16 & key,const base::NullableString16 & new_value,const base::NullableString16 & old_value)201 void DOMStorageMessageFilter::SendDOMStorageEvent(
202     const DOMStorageArea* area,
203     const GURL& page_url,
204     const base::NullableString16& key,
205     const base::NullableString16& new_value,
206     const base::NullableString16& old_value) {
207   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
208   // Only send mutation events to processes which have the area open.
209   bool originated_in_process = connection_dispatching_message_for_ != 0;
210   int64 alias_namespace_id = area->namespace_id();
211   if (host_->HasAreaOpen(area->namespace_id(), area->origin(),
212                          &alias_namespace_id) ||
213       originated_in_process) {
214     DOMStorageMsg_Event_Params params;
215     params.origin = area->origin();
216     params.page_url = page_url;
217     params.connection_id = connection_dispatching_message_for_;
218     params.key = key;
219     params.new_value = new_value;
220     params.old_value = old_value;
221     params.namespace_id = alias_namespace_id;
222     Send(new DOMStorageMsg_Event(params));
223   }
224 }
225 
226 }  // namespace content
227