Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 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" |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 9 | #include "base/strings/nullable_string16.h" |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 10 | #include "base/strings/utf_string_conversions.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 11 | #include "base/threading/sequenced_worker_pool.h" |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 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" |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 18 | #include "content/public/browser/user_metrics.h" |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 19 | #include "url/gurl.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 20 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 21 | namespace content { |
| 22 | |
| 23 | DOMStorageMessageFilter::DOMStorageMessageFilter( |
| 24 | int unused, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 25 | DOMStorageContextWrapper* context) |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 26 | : context_(context->context()), |
| 27 | connection_dispatching_message_for_(0) { |
| 28 | } |
| 29 | |
| 30 | DOMStorageMessageFilter::~DOMStorageMessageFilter() { |
| 31 | DCHECK(!host_.get()); |
| 32 | } |
| 33 | |
| 34 | void DOMStorageMessageFilter::InitializeInSequence() { |
| 35 | DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 36 | host_.reset(new DOMStorageHost(context_.get())); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 37 | context_->AddEventObserver(this); |
| 38 | } |
| 39 | |
| 40 | void DOMStorageMessageFilter::UninitializeInSequence() { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 41 | // TODO(michaeln): Restore this DCHECK once crbug/166470 and crbug/164403 |
| 42 | // are resolved. |
| 43 | // DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 44 | context_->RemoveEventObserver(this); |
| 45 | host_.reset(); |
| 46 | } |
| 47 | |
| 48 | void DOMStorageMessageFilter::OnFilterAdded(IPC::Channel* channel) { |
| 49 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 50 | BrowserMessageFilter::OnFilterAdded(channel); |
| 51 | context_->task_runner()->PostShutdownBlockingTask( |
| 52 | FROM_HERE, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 53 | DOMStorageTaskRunner::PRIMARY_SEQUENCE, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 54 | base::Bind(&DOMStorageMessageFilter::InitializeInSequence, this)); |
| 55 | } |
| 56 | |
| 57 | void DOMStorageMessageFilter::OnFilterRemoved() { |
| 58 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 59 | BrowserMessageFilter::OnFilterRemoved(); |
| 60 | context_->task_runner()->PostShutdownBlockingTask( |
| 61 | FROM_HERE, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 62 | DOMStorageTaskRunner::PRIMARY_SEQUENCE, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 63 | base::Bind(&DOMStorageMessageFilter::UninitializeInSequence, this)); |
| 64 | } |
| 65 | |
| 66 | base::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 | |
| 73 | bool 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 | |
| 94 | void 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 | |
| 104 | void DOMStorageMessageFilter::OnCloseStorageArea(int connection_id) { |
| 105 | DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 106 | host_->CloseStorageArea(connection_id); |
| 107 | } |
| 108 | |
| 109 | void DOMStorageMessageFilter::OnLoadStorageArea(int connection_id, |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 110 | DOMStorageValuesMap* map) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 111 | 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 | |
| 119 | void 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) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 124 | base::AutoReset<int> auto_reset(&connection_dispatching_message_for_, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 125 | connection_id); |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 126 | base::NullableString16 not_used; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 127 | bool success = host_->SetAreaItem(connection_id, key, value, |
| 128 | page_url, ¬_used); |
| 129 | Send(new DOMStorageMsg_AsyncOperationComplete(success)); |
| 130 | } |
| 131 | |
| 132 | void 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) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 137 | base::AutoReset<int> auto_reset(&connection_dispatching_message_for_, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 138 | connection_id); |
| 139 | string16 not_used; |
| 140 | host_->RemoveAreaItem(connection_id, key, page_url, ¬_used); |
| 141 | Send(new DOMStorageMsg_AsyncOperationComplete(true)); |
| 142 | } |
| 143 | |
| 144 | void 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) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 148 | base::AutoReset<int> auto_reset(&connection_dispatching_message_for_, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 149 | connection_id); |
| 150 | host_->ClearArea(connection_id, page_url); |
| 151 | Send(new DOMStorageMsg_AsyncOperationComplete(true)); |
| 152 | } |
| 153 | |
| 154 | void DOMStorageMessageFilter::OnFlushMessages() { |
| 155 | // Intentionally empty method body. |
| 156 | } |
| 157 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 158 | void DOMStorageMessageFilter::OnDOMStorageItemSet( |
| 159 | const DOMStorageArea* area, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 160 | const string16& key, |
| 161 | const string16& new_value, |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 162 | const base::NullableString16& old_value, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 163 | const GURL& page_url) { |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 164 | SendDOMStorageEvent(area, page_url, |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 165 | base::NullableString16(key, false), |
| 166 | base::NullableString16(new_value, false), |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 167 | old_value); |
| 168 | } |
| 169 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 170 | void DOMStorageMessageFilter::OnDOMStorageItemRemoved( |
| 171 | const DOMStorageArea* area, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 172 | const string16& key, |
| 173 | const string16& old_value, |
| 174 | const GURL& page_url) { |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 175 | SendDOMStorageEvent(area, page_url, |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 176 | base::NullableString16(key, false), |
| 177 | base::NullableString16(), |
| 178 | base::NullableString16(old_value, false)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 179 | } |
| 180 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 181 | void DOMStorageMessageFilter::OnDOMStorageAreaCleared( |
| 182 | const DOMStorageArea* area, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 183 | const GURL& page_url) { |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 184 | SendDOMStorageEvent(area, page_url, |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 185 | base::NullableString16(), |
| 186 | base::NullableString16(), |
| 187 | base::NullableString16()); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 188 | } |
| 189 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 190 | void DOMStorageMessageFilter::SendDOMStorageEvent( |
| 191 | const DOMStorageArea* area, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 192 | const GURL& page_url, |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 193 | const base::NullableString16& key, |
| 194 | const base::NullableString16& new_value, |
| 195 | const base::NullableString16& old_value) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 196 | 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 |