1 // Copyright 2013 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_host.h" 6 7 #include "content/browser/dom_storage/dom_storage_area.h" 8 #include "content/browser/dom_storage/dom_storage_context_impl.h" 9 #include "content/browser/dom_storage/dom_storage_namespace.h" 10 #include "content/common/dom_storage/dom_storage_types.h" 11 #include "url/gurl.h" 12 13 namespace content { 14 15 DOMStorageHost::DOMStorageHost(DOMStorageContextImpl* context) 16 : context_(context) { 17 } 18 19 DOMStorageHost::~DOMStorageHost() { 20 AreaMap::const_iterator it = connections_.begin(); 21 for (; it != connections_.end(); ++it) 22 it->second.namespace_->CloseStorageArea(it->second.area_.get()); 23 connections_.clear(); // Clear prior to releasing the context_ 24 } 25 26 bool DOMStorageHost::OpenStorageArea(int connection_id, int namespace_id, 27 const GURL& origin) { 28 DCHECK(!GetOpenArea(connection_id)); 29 if (GetOpenArea(connection_id)) 30 return false; // Indicates the renderer gave us very bad data. 31 NamespaceAndArea references; 32 references.namespace_ = context_->GetStorageNamespace(namespace_id); 33 if (!references.namespace_.get()) { 34 // TODO(michaeln): Fix crbug/134003 and return false here. 35 // Until then return true to avoid crashing the renderer for 36 // sending a bad message. 37 return true; 38 } 39 references.area_ = references.namespace_->OpenStorageArea(origin); 40 DCHECK(references.area_.get()); 41 connections_[connection_id] = references; 42 return true; 43 } 44 45 void DOMStorageHost::CloseStorageArea(int connection_id) { 46 AreaMap::iterator found = connections_.find(connection_id); 47 if (found == connections_.end()) 48 return; 49 found->second.namespace_->CloseStorageArea(found->second.area_.get()); 50 connections_.erase(found); 51 } 52 53 bool DOMStorageHost::ExtractAreaValues( 54 int connection_id, DOMStorageValuesMap* map) { 55 map->clear(); 56 DOMStorageArea* area = GetOpenArea(connection_id); 57 if (!area) { 58 // TODO(michaeln): Fix crbug/134003 and return false here. 59 // Until then return true to avoid crashing the renderer 60 // for sending a bad message. 61 return true; 62 } 63 if (!area->IsLoadedInMemory()) { 64 DOMStorageNamespace* ns = GetNamespace(connection_id); 65 DCHECK(ns); 66 if (ns->CountInMemoryAreas() > kMaxInMemoryStorageAreas) { 67 ns->PurgeMemory(DOMStorageNamespace::PURGE_UNOPENED); 68 if (ns->CountInMemoryAreas() > kMaxInMemoryStorageAreas) 69 ns->PurgeMemory(DOMStorageNamespace::PURGE_AGGRESSIVE); 70 } 71 } 72 area->ExtractValues(map); 73 return true; 74 } 75 76 unsigned DOMStorageHost::GetAreaLength(int connection_id) { 77 DOMStorageArea* area = GetOpenArea(connection_id); 78 if (!area) 79 return 0; 80 return area->Length(); 81 } 82 83 base::NullableString16 DOMStorageHost::GetAreaKey(int connection_id, 84 unsigned index) { 85 DOMStorageArea* area = GetOpenArea(connection_id); 86 if (!area) 87 return base::NullableString16(); 88 return area->Key(index); 89 } 90 91 base::NullableString16 DOMStorageHost::GetAreaItem(int connection_id, 92 const base::string16& key) { 93 DOMStorageArea* area = GetOpenArea(connection_id); 94 if (!area) 95 return base::NullableString16(); 96 return area->GetItem(key); 97 } 98 99 bool DOMStorageHost::SetAreaItem( 100 int connection_id, const base::string16& key, 101 const base::string16& value, const GURL& page_url, 102 base::NullableString16* old_value) { 103 DOMStorageArea* area = GetOpenArea(connection_id); 104 if (!area) { 105 // TODO(michaeln): Fix crbug/134003 and return false here. 106 // Until then return true to allow the renderer to operate 107 // to a limited degree out of its cache. 108 return true; 109 } 110 if (!area->SetItem(key, value, old_value)) 111 return false; 112 if (old_value->is_null() || old_value->string() != value) 113 context_->NotifyItemSet(area, key, value, *old_value, page_url); 114 return true; 115 } 116 117 bool DOMStorageHost::RemoveAreaItem( 118 int connection_id, const base::string16& key, const GURL& page_url, 119 base::string16* old_value) { 120 DOMStorageArea* area = GetOpenArea(connection_id); 121 if (!area) 122 return false; 123 if (!area->RemoveItem(key, old_value)) 124 return false; 125 context_->NotifyItemRemoved(area, key, *old_value, page_url); 126 return true; 127 } 128 129 bool DOMStorageHost::ClearArea(int connection_id, const GURL& page_url) { 130 DOMStorageArea* area = GetOpenArea(connection_id); 131 if (!area) 132 return false; 133 if (!area->Clear()) 134 return false; 135 context_->NotifyAreaCleared(area, page_url); 136 return true; 137 } 138 139 bool DOMStorageHost::HasAreaOpen( 140 int namespace_id, const GURL& origin) const { 141 AreaMap::const_iterator it = connections_.begin(); 142 for (; it != connections_.end(); ++it) { 143 if (namespace_id == it->second.namespace_->namespace_id() && 144 origin == it->second.area_->origin()) { 145 return true; 146 } 147 } 148 return false; 149 } 150 151 DOMStorageArea* DOMStorageHost::GetOpenArea(int connection_id) { 152 AreaMap::iterator found = connections_.find(connection_id); 153 if (found == connections_.end()) 154 return NULL; 155 return found->second.area_.get(); 156 } 157 158 DOMStorageNamespace* DOMStorageHost::GetNamespace(int connection_id) { 159 AreaMap::iterator found = connections_.find(connection_id); 160 if (found == connections_.end()) 161 return NULL; 162 return found->second.namespace_.get(); 163 } 164 165 // NamespaceAndArea 166 167 DOMStorageHost::NamespaceAndArea::NamespaceAndArea() {} 168 DOMStorageHost::NamespaceAndArea::~NamespaceAndArea() {} 169 170 } // namespace content 171