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     : 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