Home | History | Annotate | Download | only in dom_storage
      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                                int render_process_id)
     17     : context_(context),
     18       render_process_id_(render_process_id) {
     19 }
     20 
     21 DOMStorageHost::~DOMStorageHost() {
     22   AreaMap::const_iterator it = connections_.begin();
     23   for (; it != connections_.end(); ++it)
     24     it->second.namespace_->CloseStorageArea(it->second.area_.get());
     25   connections_.clear();  // Clear prior to releasing the context_
     26 }
     27 
     28 bool DOMStorageHost::OpenStorageArea(int connection_id, int namespace_id,
     29                                      const GURL& origin) {
     30   DCHECK(!GetOpenArea(connection_id));
     31   if (GetOpenArea(connection_id))
     32     return false;  // Indicates the renderer gave us very bad data.
     33   NamespaceAndArea references;
     34   references.namespace_ = context_->GetStorageNamespace(namespace_id);
     35   if (!references.namespace_.get())
     36     return false;
     37   references.area_ = references.namespace_->OpenStorageArea(origin);
     38   DCHECK(references.area_.get());
     39   connections_[connection_id] = references;
     40   return true;
     41 }
     42 
     43 void DOMStorageHost::CloseStorageArea(int connection_id) {
     44   AreaMap::iterator found = connections_.find(connection_id);
     45   if (found == connections_.end())
     46     return;
     47   found->second.namespace_->CloseStorageArea(found->second.area_.get());
     48   connections_.erase(found);
     49 }
     50 
     51 bool DOMStorageHost::ExtractAreaValues(
     52     int connection_id, DOMStorageValuesMap* map, bool* send_log_get_messages) {
     53   map->clear();
     54   DOMStorageArea* area = GetOpenArea(connection_id);
     55   if (!area)
     56     return false;
     57   if (!area->IsLoadedInMemory()) {
     58     DOMStorageNamespace* ns = GetNamespace(connection_id);
     59     DCHECK(ns);
     60     if (ns->CountInMemoryAreas() > kMaxInMemoryStorageAreas) {
     61       ns->PurgeMemory(DOMStorageNamespace::PURGE_UNOPENED);
     62       if (ns->CountInMemoryAreas() > kMaxInMemoryStorageAreas)
     63         ns->PurgeMemory(DOMStorageNamespace::PURGE_AGGRESSIVE);
     64     }
     65   }
     66   area->ExtractValues(map);
     67   *send_log_get_messages = false;
     68   DOMStorageNamespace* ns = GetNamespace(connection_id);
     69   DCHECK(ns);
     70   *send_log_get_messages = ns->IsLoggingRenderer(render_process_id_);
     71   return true;
     72 }
     73 
     74 unsigned DOMStorageHost::GetAreaLength(int connection_id) {
     75   DOMStorageArea* area = GetOpenArea(connection_id);
     76   if (!area)
     77     return 0;
     78   return area->Length();
     79 }
     80 
     81 base::NullableString16 DOMStorageHost::GetAreaKey(int connection_id,
     82                                                   unsigned index) {
     83   DOMStorageArea* area = GetOpenArea(connection_id);
     84   if (!area)
     85     return base::NullableString16();
     86   return area->Key(index);
     87 }
     88 
     89 base::NullableString16 DOMStorageHost::GetAreaItem(int connection_id,
     90                                                    const base::string16& key) {
     91   DOMStorageArea* area = GetOpenArea(connection_id);
     92   if (!area)
     93     return base::NullableString16();
     94   return area->GetItem(key);
     95 }
     96 
     97 bool DOMStorageHost::SetAreaItem(
     98     int connection_id, const base::string16& key,
     99     const base::string16& value, const GURL& page_url,
    100     base::NullableString16* old_value) {
    101   DOMStorageArea* area = GetOpenArea(connection_id);
    102   if (!area)
    103     return false;
    104   if (!area->SetItem(key, value, old_value))
    105     return false;
    106   if (old_value->is_null() || old_value->string() != value)
    107     context_->NotifyItemSet(area, key, value, *old_value, page_url);
    108   MaybeLogTransaction(connection_id,
    109                       DOMStorageNamespace::TRANSACTION_WRITE,
    110                       area->origin(), page_url, key,
    111                       base::NullableString16(value, false));
    112   return true;
    113 }
    114 
    115 void DOMStorageHost::LogGetAreaItem(
    116     int connection_id, const base::string16& key,
    117     const base::NullableString16& value) {
    118   DOMStorageArea* area = GetOpenArea(connection_id);
    119   if (!area)
    120     return;
    121   MaybeLogTransaction(connection_id,
    122                       DOMStorageNamespace::TRANSACTION_READ,
    123                       area->origin(), GURL(), key, value);
    124 }
    125 
    126 bool DOMStorageHost::RemoveAreaItem(
    127     int connection_id, const base::string16& key, const GURL& page_url,
    128     base::string16* old_value) {
    129   DOMStorageArea* area = GetOpenArea(connection_id);
    130   if (!area)
    131     return false;
    132   if (!area->RemoveItem(key, old_value))
    133     return false;
    134   context_->NotifyItemRemoved(area, key, *old_value, page_url);
    135   MaybeLogTransaction(connection_id,
    136                       DOMStorageNamespace::TRANSACTION_REMOVE,
    137                       area->origin(), page_url, key, base::NullableString16());
    138   return true;
    139 }
    140 
    141 bool DOMStorageHost::ClearArea(int connection_id, const GURL& page_url) {
    142   DOMStorageArea* area = GetOpenArea(connection_id);
    143   if (!area)
    144     return false;
    145   if (!area->Clear())
    146     return false;
    147   context_->NotifyAreaCleared(area, page_url);
    148   MaybeLogTransaction(connection_id,
    149                       DOMStorageNamespace::TRANSACTION_CLEAR,
    150                       area->origin(), page_url, base::string16(),
    151                       base::NullableString16());
    152   return true;
    153 }
    154 
    155 bool DOMStorageHost::HasAreaOpen(
    156     int64 namespace_id, const GURL& origin, int64* alias_namespace_id) const {
    157   AreaMap::const_iterator it = connections_.begin();
    158   for (; it != connections_.end(); ++it) {
    159     if (namespace_id == it->second.area_->namespace_id() &&
    160         origin == it->second.area_->origin()) {
    161       *alias_namespace_id = it->second.namespace_->namespace_id();
    162       return true;
    163     }
    164   }
    165   return false;
    166 }
    167 
    168 bool DOMStorageHost::ResetOpenAreasForNamespace(int64 namespace_id) {
    169   bool result = false;
    170   AreaMap::iterator it = connections_.begin();
    171   for (; it != connections_.end(); ++it) {
    172     if (namespace_id == it->second.namespace_->namespace_id()) {
    173       GURL origin = it->second.area_->origin();
    174       it->second.namespace_->CloseStorageArea(it->second.area_.get());
    175       it->second.area_ = it->second.namespace_->OpenStorageArea(origin);
    176       result = true;
    177     }
    178   }
    179   return result;
    180 }
    181 
    182 DOMStorageArea* DOMStorageHost::GetOpenArea(int connection_id) {
    183   AreaMap::iterator found = connections_.find(connection_id);
    184   if (found == connections_.end())
    185     return NULL;
    186   return found->second.area_.get();
    187 }
    188 
    189 DOMStorageNamespace* DOMStorageHost::GetNamespace(int connection_id) {
    190   AreaMap::iterator found = connections_.find(connection_id);
    191   if (found == connections_.end())
    192     return NULL;
    193   return found->second.namespace_.get();
    194 }
    195 
    196 void DOMStorageHost::MaybeLogTransaction(
    197     int connection_id,
    198     DOMStorageNamespace::LogType transaction_type,
    199     const GURL& origin,
    200     const GURL& page_url,
    201     const base::string16& key,
    202     const base::NullableString16& value) {
    203   DOMStorageNamespace* ns = GetNamespace(connection_id);
    204   DCHECK(ns);
    205   if (!ns->IsLoggingRenderer(render_process_id_))
    206     return;
    207   DOMStorageNamespace::TransactionRecord transaction;
    208   transaction.transaction_type = transaction_type;
    209   transaction.origin = origin;
    210   transaction.page_url = page_url;
    211   transaction.key = key;
    212   transaction.value = value;
    213   ns->AddTransaction(render_process_id_, transaction);
    214 }
    215 
    216 // NamespaceAndArea
    217 
    218 DOMStorageHost::NamespaceAndArea::NamespaceAndArea() {}
    219 DOMStorageHost::NamespaceAndArea::~NamespaceAndArea() {}
    220 
    221 }  // namespace content
    222