- Persist localStorage data across sessions when a cache path is specified (issue #139).
- Add a localStorage test to cefclient. git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@140 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
6ad535823a
commit
3dd54c536c
11
cef.gyp
11
cef.gyp
|
@ -493,6 +493,10 @@
|
||||||
'libcef/browser_webcookiejar_impl.h',
|
'libcef/browser_webcookiejar_impl.h',
|
||||||
'libcef/browser_webblobregistry_impl.cc',
|
'libcef/browser_webblobregistry_impl.cc',
|
||||||
'libcef/browser_webblobregistry_impl.h',
|
'libcef/browser_webblobregistry_impl.h',
|
||||||
|
'libcef/browser_webstoragearea_impl.cc',
|
||||||
|
'libcef/browser_webstoragearea_impl.h',
|
||||||
|
'libcef/browser_webstoragenamespace_impl.cc',
|
||||||
|
'libcef/browser_webstoragenamespace_impl.h',
|
||||||
'libcef/browser_webkit_glue.cc',
|
'libcef/browser_webkit_glue.cc',
|
||||||
'libcef/browser_webkit_glue.h',
|
'libcef/browser_webkit_glue.h',
|
||||||
'libcef/browser_webkit_init.h',
|
'libcef/browser_webkit_init.h',
|
||||||
|
@ -513,6 +517,13 @@
|
||||||
'libcef/cef_string_map.cc',
|
'libcef/cef_string_map.cc',
|
||||||
'libcef/cef_thread.cc',
|
'libcef/cef_thread.cc',
|
||||||
'libcef/cef_thread.h',
|
'libcef/cef_thread.h',
|
||||||
|
'libcef/dom_storage_area.cc',
|
||||||
|
'libcef/dom_storage_area.h',
|
||||||
|
'libcef/dom_storage_common.h',
|
||||||
|
'libcef/dom_storage_context.cc',
|
||||||
|
'libcef/dom_storage_context.h',
|
||||||
|
'libcef/dom_storage_namespace.cc',
|
||||||
|
'libcef/dom_storage_namespace.h',
|
||||||
'libcef/request_impl.cc',
|
'libcef/request_impl.cc',
|
||||||
'libcef/request_impl.h',
|
'libcef/request_impl.h',
|
||||||
'libcef/scheme_impl.cc',
|
'libcef/scheme_impl.cc',
|
||||||
|
|
|
@ -187,6 +187,10 @@ FilePath BrowserDatabaseSystem::GetFullFilePathForVfsFile(
|
||||||
return FilePath();
|
return FilePath();
|
||||||
|
|
||||||
AutoLock file_names_auto_lock(file_names_lock_);
|
AutoLock file_names_auto_lock(file_names_lock_);
|
||||||
DCHECK(file_names_.find(vfs_file_name) != file_names_.end());
|
if(file_names_.find(vfs_file_name) != file_names_.end())
|
||||||
return file_names_[vfs_file_name];
|
return file_names_[vfs_file_name];
|
||||||
|
|
||||||
|
// This method is getting called when an empty localStorage database is
|
||||||
|
// deleted. In that case, just return the path.
|
||||||
|
return FilePath(vfs_file_name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,14 @@
|
||||||
#ifndef _BROWSER_WEBKIT_INIT_H
|
#ifndef _BROWSER_WEBKIT_INIT_H
|
||||||
#define _BROWSER_WEBKIT_INIT_H
|
#define _BROWSER_WEBKIT_INIT_H
|
||||||
|
|
||||||
|
#include "browser_appcache_system.h"
|
||||||
|
#include "browser_database_system.h"
|
||||||
|
#include "browser_file_system.h"
|
||||||
|
#include "browser_resource_loader_bridge.h"
|
||||||
|
#include "browser_webblobregistry_impl.h"
|
||||||
|
#include "browser_webcookiejar_impl.h"
|
||||||
|
#include "browser_webstoragenamespace_impl.h"
|
||||||
|
|
||||||
#include "base/file_util.h"
|
#include "base/file_util.h"
|
||||||
#include "base/metrics/stats_counters.h"
|
#include "base/metrics/stats_counters.h"
|
||||||
#include "base/path_service.h"
|
#include "base/path_service.h"
|
||||||
|
@ -35,12 +43,6 @@
|
||||||
#include "webkit/glue/webfileutilities_impl.h"
|
#include "webkit/glue/webfileutilities_impl.h"
|
||||||
#include "webkit/glue/webkit_glue.h"
|
#include "webkit/glue/webkit_glue.h"
|
||||||
#include "webkit/glue/webkitclient_impl.h"
|
#include "webkit/glue/webkitclient_impl.h"
|
||||||
#include "browser_appcache_system.h"
|
|
||||||
#include "browser_database_system.h"
|
|
||||||
#include "browser_file_system.h"
|
|
||||||
#include "browser_resource_loader_bridge.h"
|
|
||||||
#include "browser_webblobregistry_impl.h"
|
|
||||||
#include "browser_webcookiejar_impl.h"
|
|
||||||
|
|
||||||
|
|
||||||
class BrowserWebKitInit : public webkit_glue::WebKitClientImpl {
|
class BrowserWebKitInit : public webkit_glue::WebKitClientImpl {
|
||||||
|
@ -193,6 +195,12 @@ class BrowserWebKitInit : public webkit_glue::WebKitClientImpl {
|
||||||
|
|
||||||
virtual WebKit::WebStorageNamespace* createLocalStorageNamespace(
|
virtual WebKit::WebStorageNamespace* createLocalStorageNamespace(
|
||||||
const WebKit::WebString& path, unsigned quota) {
|
const WebKit::WebString& path, unsigned quota) {
|
||||||
|
if (BrowserWebStorageNamespaceImpl::IsStorageActive()) {
|
||||||
|
// Use the localStorage implementation that writes data to disk.
|
||||||
|
return new BrowserWebStorageNamespaceImpl(DOM_STORAGE_LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the default localStorage implementation.
|
||||||
return WebKit::WebStorageNamespace::createLocalStorageNamespace(path,
|
return WebKit::WebStorageNamespace::createLocalStorageNamespace(path,
|
||||||
WebKit::WebStorageNamespace::m_localStorageQuota);
|
WebKit::WebStorageNamespace::m_localStorageQuota);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
|
||||||
|
// reserved. Use of this source code is governed by a BSD-style license that can
|
||||||
|
// be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "browser_webstoragearea_impl.h"
|
||||||
|
#include "cef_context.h"
|
||||||
|
#include "dom_storage_area.h"
|
||||||
|
#include "dom_storage_namespace.h"
|
||||||
|
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
|
||||||
|
|
||||||
|
using WebKit::WebFrame;
|
||||||
|
using WebKit::WebString;
|
||||||
|
using WebKit::WebURL;
|
||||||
|
using WebKit::WebView;
|
||||||
|
|
||||||
|
BrowserWebStorageAreaImpl::BrowserWebStorageAreaImpl(
|
||||||
|
int64 namespace_id, const WebString& origin) {
|
||||||
|
area_ = _Context->storage_context()->GetStorageNamespace(namespace_id, true)->
|
||||||
|
GetStorageArea(origin);
|
||||||
|
DCHECK(area_ != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
BrowserWebStorageAreaImpl::~BrowserWebStorageAreaImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned BrowserWebStorageAreaImpl::length() {
|
||||||
|
return area_->Length();
|
||||||
|
}
|
||||||
|
|
||||||
|
WebString BrowserWebStorageAreaImpl::key(unsigned index) {
|
||||||
|
return area_->Key(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebString BrowserWebStorageAreaImpl::getItem(const WebString& key) {
|
||||||
|
return area_->GetItem(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BrowserWebStorageAreaImpl::setItem(
|
||||||
|
const WebString& key, const WebString& value, const WebURL& url,
|
||||||
|
WebStorageArea::Result& result, WebString& old_value_webkit,
|
||||||
|
WebFrame* web_frame) {
|
||||||
|
old_value_webkit = area_->SetItem(key, value, &result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BrowserWebStorageAreaImpl::removeItem(
|
||||||
|
const WebString& key, const WebURL& url, WebString& old_value_webkit) {
|
||||||
|
old_value_webkit = area_->RemoveItem(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BrowserWebStorageAreaImpl::clear(
|
||||||
|
const WebURL& url, bool& cleared_something) {
|
||||||
|
cleared_something = area_->Clear();
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
|
||||||
|
// reserved. Use of this source code is governed by a BSD-style license that can
|
||||||
|
// be found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef _BROWSER_WEBSTORAGEAREA_IMPL_H
|
||||||
|
#define _BROWSER_WEBSTORAGEAREA_IMPL_H
|
||||||
|
|
||||||
|
#include "base/basictypes.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebStorageArea.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
|
||||||
|
|
||||||
|
class DOMStorageArea;
|
||||||
|
|
||||||
|
class BrowserWebStorageAreaImpl : public WebKit::WebStorageArea {
|
||||||
|
public:
|
||||||
|
BrowserWebStorageAreaImpl(int64 namespace_id, const WebKit::WebString& origin);
|
||||||
|
virtual ~BrowserWebStorageAreaImpl();
|
||||||
|
|
||||||
|
// See WebStorageArea.h for documentation on these functions.
|
||||||
|
virtual unsigned length();
|
||||||
|
virtual WebKit::WebString key(unsigned index);
|
||||||
|
virtual WebKit::WebString getItem(const WebKit::WebString& key);
|
||||||
|
virtual void setItem(
|
||||||
|
const WebKit::WebString& key, const WebKit::WebString& value,
|
||||||
|
const WebKit::WebURL& url, WebStorageArea::Result& result,
|
||||||
|
WebKit::WebString& old_value, WebKit::WebFrame* web_view);
|
||||||
|
virtual void removeItem(
|
||||||
|
const WebKit::WebString& key, const WebKit::WebURL& url,
|
||||||
|
WebKit::WebString& old_value);
|
||||||
|
virtual void clear(const WebKit::WebURL& url, bool& cleared_something);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The object is owned by DOMStorageNamespace.
|
||||||
|
DOMStorageArea* area_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _BROWSER_WEBSTORAGEAREA_IMPL_H
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "browser_webstoragenamespace_impl.h"
|
||||||
|
#include "browser_webstoragearea_impl.h"
|
||||||
|
#include "cef_context.h"
|
||||||
|
|
||||||
|
#include "base/logging.h"
|
||||||
|
|
||||||
|
using WebKit::WebStorageArea;
|
||||||
|
using WebKit::WebStorageNamespace;
|
||||||
|
using WebKit::WebString;
|
||||||
|
|
||||||
|
BrowserWebStorageNamespaceImpl::BrowserWebStorageNamespaceImpl(
|
||||||
|
DOMStorageType storage_type)
|
||||||
|
: storage_type_(storage_type),
|
||||||
|
namespace_id_(kLocalStorageNamespaceId) {
|
||||||
|
DCHECK(storage_type == DOM_STORAGE_LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
BrowserWebStorageNamespaceImpl::BrowserWebStorageNamespaceImpl(
|
||||||
|
DOMStorageType storage_type, int64 namespace_id)
|
||||||
|
: storage_type_(storage_type),
|
||||||
|
namespace_id_(namespace_id) {
|
||||||
|
DCHECK(storage_type == DOM_STORAGE_SESSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
BrowserWebStorageNamespaceImpl::~BrowserWebStorageNamespaceImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
WebStorageArea* BrowserWebStorageNamespaceImpl::createStorageArea(
|
||||||
|
const WebString& origin) {
|
||||||
|
// Ideally, we'd keep a hash map of origin to these objects. Unfortunately
|
||||||
|
// this doesn't seem practical because there's no good way to ref-count these
|
||||||
|
// objects, and it'd be unclear who owned them. So, instead, we'll pay the
|
||||||
|
// price in terms of wasted memory.
|
||||||
|
return new BrowserWebStorageAreaImpl(namespace_id_, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebStorageNamespace* BrowserWebStorageNamespaceImpl::copy() {
|
||||||
|
// By returning NULL, we're telling WebKit to lazily fetch it the next time
|
||||||
|
// session storage is used. In the WebViewClient::createView, we do the
|
||||||
|
// book-keeping necessary to make it a true copy-on-write despite not doing
|
||||||
|
// anything here, now.
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BrowserWebStorageNamespaceImpl::close() {
|
||||||
|
// This is called only on LocalStorage namespaces when WebKit thinks its
|
||||||
|
// shutting down. This has no impact on Chromium.
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
bool BrowserWebStorageNamespaceImpl::IsStorageActive() {
|
||||||
|
return (_Context->storage_context() != NULL);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef _BROWSER_WEBSTORAGENAMESPACE_IMPL_H
|
||||||
|
#define _BROWSER_WEBSTORAGENAMESPACE_IMPL_H
|
||||||
|
|
||||||
|
#include "dom_storage_common.h"
|
||||||
|
|
||||||
|
#include "base/basictypes.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebStorageNamespace.h"
|
||||||
|
|
||||||
|
class BrowserWebStorageNamespaceImpl : public WebKit::WebStorageNamespace {
|
||||||
|
public:
|
||||||
|
explicit BrowserWebStorageNamespaceImpl(DOMStorageType storage_type);
|
||||||
|
BrowserWebStorageNamespaceImpl(DOMStorageType storage_type,
|
||||||
|
int64 namespace_id);
|
||||||
|
|
||||||
|
// See WebStorageNamespace.h for documentation on these functions.
|
||||||
|
virtual ~BrowserWebStorageNamespaceImpl();
|
||||||
|
virtual WebKit::WebStorageArea* createStorageArea(
|
||||||
|
const WebKit::WebString& origin);
|
||||||
|
virtual WebKit::WebStorageNamespace* copy();
|
||||||
|
virtual void close();
|
||||||
|
|
||||||
|
// Returns true if storage data is being cached to disk.
|
||||||
|
static bool IsStorageActive();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Used during lazy initialization of namespace_id_.
|
||||||
|
const DOMStorageType storage_type_;
|
||||||
|
|
||||||
|
// Our namespace ID.
|
||||||
|
int64 namespace_id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _BROWSER_WEBSTORAGENAMESPACE_IMPL_H
|
|
@ -198,7 +198,9 @@ WebWidget* BrowserWebViewDelegate::createPopupMenu(WebPopupType popup_type) {
|
||||||
|
|
||||||
WebStorageNamespace* BrowserWebViewDelegate::createSessionStorageNamespace(
|
WebStorageNamespace* BrowserWebViewDelegate::createSessionStorageNamespace(
|
||||||
unsigned quota) {
|
unsigned quota) {
|
||||||
// Enforce quota, ignoring the parameter from WebCore as in Chrome.
|
// Enforce quota, ignoring the parameter from WebCore as in Chrome. We could
|
||||||
|
// potentially use DOMStorageContext to manage session storage but there's
|
||||||
|
// currently no need since session storage data is not written to disk.
|
||||||
return WebKit::WebStorageNamespace::createSessionStorageNamespace(
|
return WebKit::WebStorageNamespace::createSessionStorageNamespace(
|
||||||
WebStorageNamespace::m_sessionStorageQuota);
|
WebStorageNamespace::m_sessionStorageQuota);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "browser_request_context.h"
|
#include "browser_request_context.h"
|
||||||
#include "cef_process.h"
|
#include "cef_process.h"
|
||||||
#include "cef_thread.h"
|
#include "cef_thread.h"
|
||||||
|
#include "dom_storage_context.h"
|
||||||
|
|
||||||
#include "base/at_exit.h"
|
#include "base/at_exit.h"
|
||||||
#include "base/file_path.h"
|
#include "base/file_path.h"
|
||||||
|
@ -56,6 +57,11 @@ public:
|
||||||
scoped_refptr<BrowserRequestContext> request_context()
|
scoped_refptr<BrowserRequestContext> request_context()
|
||||||
{ return request_context_; }
|
{ return request_context_; }
|
||||||
|
|
||||||
|
// The DOMStorageContext object is managed by CefProcessUIThread.
|
||||||
|
void set_storage_context(DOMStorageContext* storage_context)
|
||||||
|
{ storage_context_.reset(storage_context); }
|
||||||
|
DOMStorageContext* storage_context() { return storage_context_.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Manages the various process threads.
|
// Manages the various process threads.
|
||||||
scoped_refptr<CefProcess> process_;
|
scoped_refptr<CefProcess> process_;
|
||||||
|
@ -67,6 +73,7 @@ private:
|
||||||
std::wstring cache_path_;
|
std::wstring cache_path_;
|
||||||
WebPreferences* webprefs_;
|
WebPreferences* webprefs_;
|
||||||
scoped_refptr<BrowserRequestContext> request_context_;
|
scoped_refptr<BrowserRequestContext> request_context_;
|
||||||
|
scoped_ptr<DOMStorageContext> storage_context_;
|
||||||
|
|
||||||
// Map of browsers that currently exist.
|
// Map of browsers that currently exist.
|
||||||
BrowserList browserlist_;
|
BrowserList browserlist_;
|
||||||
|
|
|
@ -116,6 +116,11 @@ void CefProcessUIThread::Init() {
|
||||||
gfx::InitializeGLBindings(gfx::kGLImplementationDesktopGL);
|
gfx::InitializeGLBindings(gfx::kGLImplementationDesktopGL);
|
||||||
|
|
||||||
URLRequest::RegisterProtocolFactory("blob", &BlobURLRequestJobFactory);
|
URLRequest::RegisterProtocolFactory("blob", &BlobURLRequestJobFactory);
|
||||||
|
|
||||||
|
if(!_Context->cache_path().empty()) {
|
||||||
|
// Create the storage context object.
|
||||||
|
_Context->set_storage_context(new DOMStorageContext());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefProcessUIThread::CleanUp() {
|
void CefProcessUIThread::CleanUp() {
|
||||||
|
@ -124,6 +129,9 @@ void CefProcessUIThread::CleanUp() {
|
||||||
// purify leak-test results.
|
// purify leak-test results.
|
||||||
MessageLoop::current()->RunAllPending();
|
MessageLoop::current()->RunAllPending();
|
||||||
|
|
||||||
|
// Destroy the storage context object.
|
||||||
|
_Context->set_storage_context(NULL);
|
||||||
|
|
||||||
// Tear down the shared StatsTable.
|
// Tear down the shared StatsTable.
|
||||||
base::StatsTable::set_current(NULL);
|
base::StatsTable::set_current(NULL);
|
||||||
delete statstable_;
|
delete statstable_;
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "dom_storage_area.h"
|
||||||
|
#include "dom_storage_context.h"
|
||||||
|
#include "dom_storage_namespace.h"
|
||||||
|
|
||||||
|
#include "base/task.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebStorageArea.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
|
||||||
|
#include "webkit/glue/webkit_glue.h"
|
||||||
|
|
||||||
|
using WebKit::WebSecurityOrigin;
|
||||||
|
using WebKit::WebStorageArea;
|
||||||
|
using WebKit::WebString;
|
||||||
|
using WebKit::WebURL;
|
||||||
|
|
||||||
|
DOMStorageArea::DOMStorageArea(
|
||||||
|
const string16& origin,
|
||||||
|
int64 id,
|
||||||
|
DOMStorageNamespace* owner)
|
||||||
|
: origin_(origin),
|
||||||
|
origin_url_(origin),
|
||||||
|
id_(id),
|
||||||
|
owner_(owner) {
|
||||||
|
DCHECK(owner_);
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMStorageArea::~DOMStorageArea() {
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned DOMStorageArea::Length() {
|
||||||
|
CreateWebStorageAreaIfNecessary();
|
||||||
|
return storage_area_->length();
|
||||||
|
}
|
||||||
|
|
||||||
|
NullableString16 DOMStorageArea::Key(unsigned index) {
|
||||||
|
CreateWebStorageAreaIfNecessary();
|
||||||
|
return storage_area_->key(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
NullableString16 DOMStorageArea::GetItem(const string16& key) {
|
||||||
|
CreateWebStorageAreaIfNecessary();
|
||||||
|
return storage_area_->getItem(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
NullableString16 DOMStorageArea::SetItem(
|
||||||
|
const string16& key, const string16& value,
|
||||||
|
WebStorageArea::Result* result) {
|
||||||
|
if (!CheckContentSetting(key, value)) {
|
||||||
|
*result = WebStorageArea::ResultBlockedByPolicy;
|
||||||
|
return NullableString16(true); // Ignored if the content was blocked.
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateWebStorageAreaIfNecessary();
|
||||||
|
WebString old_value;
|
||||||
|
storage_area_->setItem(key, value, WebURL(), *result, old_value);
|
||||||
|
return old_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
NullableString16 DOMStorageArea::RemoveItem(const string16& key) {
|
||||||
|
CreateWebStorageAreaIfNecessary();
|
||||||
|
WebString old_value;
|
||||||
|
storage_area_->removeItem(key, WebURL(), old_value);
|
||||||
|
return old_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DOMStorageArea::Clear() {
|
||||||
|
CreateWebStorageAreaIfNecessary();
|
||||||
|
bool somethingCleared;
|
||||||
|
storage_area_->clear(WebURL(), somethingCleared);
|
||||||
|
return somethingCleared;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DOMStorageArea::PurgeMemory() {
|
||||||
|
storage_area_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DOMStorageArea::CreateWebStorageAreaIfNecessary() {
|
||||||
|
if (!storage_area_.get())
|
||||||
|
storage_area_.reset(owner_->CreateWebStorageArea(origin_));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DOMStorageArea::CheckContentSetting(
|
||||||
|
const string16& key, const string16& value) {
|
||||||
|
// TODO(cef): Potentially give the host an option to deny write access.
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef _DOM_STORAGE_AREA_H
|
||||||
|
#define _DOM_STORAGE_AREA_H
|
||||||
|
|
||||||
|
#include "base/hash_tables.h"
|
||||||
|
#include "base/nullable_string16.h"
|
||||||
|
#include "base/ref_counted.h"
|
||||||
|
#include "base/scoped_ptr.h"
|
||||||
|
#include "base/string16.h"
|
||||||
|
#include "googleurl/src/gurl.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebStorageArea.h"
|
||||||
|
|
||||||
|
class DOMStorageNamespace;
|
||||||
|
|
||||||
|
// Only use on the WebKit thread. DOMStorageNamespace manages our registration
|
||||||
|
// with DOMStorageContext.
|
||||||
|
class DOMStorageArea {
|
||||||
|
public:
|
||||||
|
DOMStorageArea(const string16& origin,
|
||||||
|
int64 id,
|
||||||
|
DOMStorageNamespace* owner);
|
||||||
|
~DOMStorageArea();
|
||||||
|
|
||||||
|
unsigned Length();
|
||||||
|
NullableString16 Key(unsigned index);
|
||||||
|
NullableString16 GetItem(const string16& key);
|
||||||
|
NullableString16 SetItem(
|
||||||
|
const string16& key, const string16& value,
|
||||||
|
WebKit::WebStorageArea::Result* result);
|
||||||
|
NullableString16 RemoveItem(const string16& key);
|
||||||
|
bool Clear();
|
||||||
|
void PurgeMemory();
|
||||||
|
|
||||||
|
int64 id() const { return id_; }
|
||||||
|
|
||||||
|
DOMStorageNamespace* owner() const { return owner_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Creates the underlying WebStorageArea on demand.
|
||||||
|
void CreateWebStorageAreaIfNecessary();
|
||||||
|
|
||||||
|
// Used to see if setItem has permission to do its thing.
|
||||||
|
bool CheckContentSetting(const string16& key, const string16& value);
|
||||||
|
|
||||||
|
// The origin this storage area represents.
|
||||||
|
string16 origin_;
|
||||||
|
GURL origin_url_;
|
||||||
|
|
||||||
|
// The storage area we wrap.
|
||||||
|
scoped_ptr<WebKit::WebStorageArea> storage_area_;
|
||||||
|
|
||||||
|
// Our storage area id. Unique to our parent context.
|
||||||
|
int64 id_;
|
||||||
|
|
||||||
|
// The DOMStorageNamespace that owns us.
|
||||||
|
DOMStorageNamespace* owner_;
|
||||||
|
|
||||||
|
DISALLOW_IMPLICIT_CONSTRUCTORS(DOMStorageArea);
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(COMPILER_GCC)
|
||||||
|
namespace __gnu_cxx {
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct hash<DOMStorageArea*> {
|
||||||
|
std::size_t operator()(DOMStorageArea* const& p) const {
|
||||||
|
return reinterpret_cast<std::size_t>(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace __gnu_cxx
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _DOM_STORAGE_AREA_H
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef _DOM_STORAGE_COMMON_H
|
||||||
|
#define _DOM_STORAGE_COMMON_H
|
||||||
|
|
||||||
|
#include "base/basictypes.h"
|
||||||
|
|
||||||
|
const int64 kLocalStorageNamespaceId = 0;
|
||||||
|
const int64 kInvalidSessionStorageNamespaceId = kLocalStorageNamespaceId;
|
||||||
|
|
||||||
|
enum DOMStorageType {
|
||||||
|
DOM_STORAGE_LOCAL = 0,
|
||||||
|
DOM_STORAGE_SESSION
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _DOM_STORAGE_COMMON_H
|
|
@ -0,0 +1,250 @@
|
||||||
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "dom_storage_context.h"
|
||||||
|
#include "cef_context.h"
|
||||||
|
#include "cef_thread.h"
|
||||||
|
#include "dom_storage_namespace.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "base/file_path.h"
|
||||||
|
#include "base/file_util.h"
|
||||||
|
#include "base/string_util.h"
|
||||||
|
#include "dom_storage_area.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
|
||||||
|
#include "webkit/glue/webkit_glue.h"
|
||||||
|
|
||||||
|
const FilePath::CharType DOMStorageContext::kLocalStorageDirectory[] =
|
||||||
|
FILE_PATH_LITERAL("Local Storage");
|
||||||
|
|
||||||
|
const FilePath::CharType DOMStorageContext::kLocalStorageExtension[] =
|
||||||
|
FILE_PATH_LITERAL(".localstorage");
|
||||||
|
|
||||||
|
DOMStorageContext::DOMStorageContext()
|
||||||
|
: last_storage_area_id_(0),
|
||||||
|
last_session_storage_namespace_id_on_ui_thread_(kLocalStorageNamespaceId),
|
||||||
|
last_session_storage_namespace_id_on_io_thread_(kLocalStorageNamespaceId){
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMStorageContext::~DOMStorageContext() {
|
||||||
|
for (StorageNamespaceMap::iterator iter(storage_namespace_map_.begin());
|
||||||
|
iter != storage_namespace_map_.end(); ++iter) {
|
||||||
|
delete iter->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 DOMStorageContext::AllocateStorageAreaId() {
|
||||||
|
DCHECK(CefThread::CurrentlyOn(CefThread::UI));
|
||||||
|
return ++last_storage_area_id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 DOMStorageContext::AllocateSessionStorageNamespaceId() {
|
||||||
|
if (CefThread::CurrentlyOn(CefThread::UI))
|
||||||
|
return ++last_session_storage_namespace_id_on_ui_thread_;
|
||||||
|
return --last_session_storage_namespace_id_on_io_thread_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 DOMStorageContext::CloneSessionStorage(int64 original_id) {
|
||||||
|
DCHECK(!CefThread::CurrentlyOn(CefThread::UI));
|
||||||
|
int64 clone_id = AllocateSessionStorageNamespaceId();
|
||||||
|
CefThread::PostTask(
|
||||||
|
CefThread::UI, FROM_HERE, NewRunnableFunction(
|
||||||
|
&DOMStorageContext::CompleteCloningSessionStorage,
|
||||||
|
this, original_id, clone_id));
|
||||||
|
return clone_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DOMStorageContext::RegisterStorageArea(DOMStorageArea* storage_area) {
|
||||||
|
DCHECK(CefThread::CurrentlyOn(CefThread::UI));
|
||||||
|
int64 id = storage_area->id();
|
||||||
|
DCHECK(!GetStorageArea(id));
|
||||||
|
storage_area_map_[id] = storage_area;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DOMStorageContext::UnregisterStorageArea(DOMStorageArea* storage_area) {
|
||||||
|
DCHECK(CefThread::CurrentlyOn(CefThread::UI));
|
||||||
|
int64 id = storage_area->id();
|
||||||
|
DCHECK(GetStorageArea(id));
|
||||||
|
storage_area_map_.erase(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMStorageArea* DOMStorageContext::GetStorageArea(int64 id) {
|
||||||
|
DCHECK(CefThread::CurrentlyOn(CefThread::UI));
|
||||||
|
StorageAreaMap::iterator iter = storage_area_map_.find(id);
|
||||||
|
if (iter == storage_area_map_.end())
|
||||||
|
return NULL;
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DOMStorageContext::DeleteSessionStorageNamespace(int64 namespace_id) {
|
||||||
|
DCHECK(CefThread::CurrentlyOn(CefThread::UI));
|
||||||
|
StorageNamespaceMap::iterator iter =
|
||||||
|
storage_namespace_map_.find(namespace_id);
|
||||||
|
if (iter == storage_namespace_map_.end())
|
||||||
|
return;
|
||||||
|
DCHECK(iter->second->dom_storage_type() == DOM_STORAGE_SESSION);
|
||||||
|
delete iter->second;
|
||||||
|
storage_namespace_map_.erase(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMStorageNamespace* DOMStorageContext::GetStorageNamespace(
|
||||||
|
int64 id, bool allocation_allowed) {
|
||||||
|
DCHECK(CefThread::CurrentlyOn(CefThread::UI));
|
||||||
|
StorageNamespaceMap::iterator iter = storage_namespace_map_.find(id);
|
||||||
|
if (iter != storage_namespace_map_.end())
|
||||||
|
return iter->second;
|
||||||
|
if (!allocation_allowed)
|
||||||
|
return NULL;
|
||||||
|
if (id == kLocalStorageNamespaceId)
|
||||||
|
return CreateLocalStorage();
|
||||||
|
return CreateSessionStorage(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DOMStorageContext::PurgeMemory() {
|
||||||
|
// It is only safe to purge the memory from the LocalStorage namespace,
|
||||||
|
// because it is backed by disk and can be reloaded later. If we purge a
|
||||||
|
// SessionStorage namespace, its data will be gone forever, because it isn't
|
||||||
|
// currently backed by disk.
|
||||||
|
DOMStorageNamespace* local_storage =
|
||||||
|
GetStorageNamespace(kLocalStorageNamespaceId, false);
|
||||||
|
if (local_storage)
|
||||||
|
local_storage->PurgeMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DOMStorageContext::DeleteDataModifiedSince(
|
||||||
|
const base::Time& cutoff,
|
||||||
|
const char* url_scheme_to_be_skipped,
|
||||||
|
const std::vector<string16>& protected_origins) {
|
||||||
|
// Make sure that we don't delete a database that's currently being accessed
|
||||||
|
// by unloading all of the databases temporarily.
|
||||||
|
PurgeMemory();
|
||||||
|
|
||||||
|
FilePath data_path(_Context->cache_path());
|
||||||
|
file_util::FileEnumerator file_enumerator(
|
||||||
|
data_path.Append(kLocalStorageDirectory), false,
|
||||||
|
file_util::FileEnumerator::FILES);
|
||||||
|
for (FilePath path = file_enumerator.Next(); !path.value().empty();
|
||||||
|
path = file_enumerator.Next()) {
|
||||||
|
WebKit::WebSecurityOrigin web_security_origin =
|
||||||
|
WebKit::WebSecurityOrigin::createFromDatabaseIdentifier(
|
||||||
|
webkit_glue::FilePathToWebString(path.BaseName()));
|
||||||
|
if (EqualsASCII(web_security_origin.protocol(), url_scheme_to_be_skipped))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::vector<string16>::const_iterator find_iter =
|
||||||
|
std::find(protected_origins.begin(), protected_origins.end(),
|
||||||
|
web_security_origin.databaseIdentifier());
|
||||||
|
if (find_iter != protected_origins.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
file_util::FileEnumerator::FindInfo find_info;
|
||||||
|
file_enumerator.GetFindInfo(&find_info);
|
||||||
|
if (file_util::HasFileBeenModifiedSince(find_info, cutoff))
|
||||||
|
file_util::Delete(path, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DOMStorageContext::DeleteLocalStorageFile(const FilePath& file_path) {
|
||||||
|
DCHECK(CefThread::CurrentlyOn(CefThread::UI));
|
||||||
|
|
||||||
|
// Make sure that we don't delete a database that's currently being accessed
|
||||||
|
// by unloading all of the databases temporarily.
|
||||||
|
// TODO(bulach): both this method and DeleteDataModifiedSince could purge
|
||||||
|
// only the memory used by the specific file instead of all memory at once.
|
||||||
|
// See http://crbug.com/32000
|
||||||
|
PurgeMemory();
|
||||||
|
file_util::Delete(file_path, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DOMStorageContext::DeleteLocalStorageForOrigin(const string16& origin_id) {
|
||||||
|
DCHECK(CefThread::CurrentlyOn(CefThread::UI));
|
||||||
|
DeleteLocalStorageFile(GetLocalStorageFilePath(origin_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DOMStorageContext::DeleteAllLocalStorageFiles() {
|
||||||
|
DCHECK(CefThread::CurrentlyOn(CefThread::UI));
|
||||||
|
|
||||||
|
// Make sure that we don't delete a database that's currently being accessed
|
||||||
|
// by unloading all of the databases temporarily.
|
||||||
|
PurgeMemory();
|
||||||
|
|
||||||
|
FilePath data_path(_Context->cache_path());
|
||||||
|
file_util::FileEnumerator file_enumerator(
|
||||||
|
data_path.Append(kLocalStorageDirectory), false,
|
||||||
|
file_util::FileEnumerator::FILES);
|
||||||
|
for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
|
||||||
|
file_path = file_enumerator.Next()) {
|
||||||
|
if (file_path.Extension() == kLocalStorageExtension)
|
||||||
|
file_util::Delete(file_path, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMStorageNamespace* DOMStorageContext::CreateLocalStorage() {
|
||||||
|
FilePath data_path(_Context->cache_path());
|
||||||
|
FilePath dir_path;
|
||||||
|
if (!data_path.empty())
|
||||||
|
dir_path = data_path.Append(kLocalStorageDirectory);
|
||||||
|
|
||||||
|
DOMStorageNamespace* new_namespace =
|
||||||
|
DOMStorageNamespace::CreateLocalStorageNamespace(this, dir_path);
|
||||||
|
RegisterStorageNamespace(new_namespace);
|
||||||
|
return new_namespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMStorageNamespace* DOMStorageContext::CreateSessionStorage(
|
||||||
|
int64 namespace_id) {
|
||||||
|
DOMStorageNamespace* new_namespace =
|
||||||
|
DOMStorageNamespace::CreateSessionStorageNamespace(this, namespace_id);
|
||||||
|
RegisterStorageNamespace(new_namespace);
|
||||||
|
return new_namespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DOMStorageContext::RegisterStorageNamespace(
|
||||||
|
DOMStorageNamespace* storage_namespace) {
|
||||||
|
DCHECK(CefThread::CurrentlyOn(CefThread::UI));
|
||||||
|
int64 id = storage_namespace->id();
|
||||||
|
DCHECK(!GetStorageNamespace(id, false));
|
||||||
|
storage_namespace_map_[id] = storage_namespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void DOMStorageContext::CompleteCloningSessionStorage(
|
||||||
|
DOMStorageContext* context, int64 existing_id, int64 clone_id) {
|
||||||
|
DCHECK(CefThread::CurrentlyOn(CefThread::UI));
|
||||||
|
DOMStorageNamespace* existing_namespace =
|
||||||
|
context->GetStorageNamespace(existing_id, false);
|
||||||
|
// If nothing exists, then there's nothing to clone.
|
||||||
|
if (existing_namespace)
|
||||||
|
context->RegisterStorageNamespace(existing_namespace->Copy(clone_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void DOMStorageContext::ClearLocalState(const FilePath& profile_path,
|
||||||
|
const char* url_scheme_to_be_skipped) {
|
||||||
|
file_util::FileEnumerator file_enumerator(profile_path.Append(
|
||||||
|
kLocalStorageDirectory), false, file_util::FileEnumerator::FILES);
|
||||||
|
for (FilePath file_path = file_enumerator.Next(); !file_path.empty();
|
||||||
|
file_path = file_enumerator.Next()) {
|
||||||
|
if (file_path.Extension() == kLocalStorageExtension) {
|
||||||
|
WebKit::WebSecurityOrigin web_security_origin =
|
||||||
|
WebKit::WebSecurityOrigin::createFromDatabaseIdentifier(
|
||||||
|
webkit_glue::FilePathToWebString(file_path.BaseName()));
|
||||||
|
if (!EqualsASCII(web_security_origin.protocol(),
|
||||||
|
url_scheme_to_be_skipped))
|
||||||
|
file_util::Delete(file_path, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePath DOMStorageContext::GetLocalStorageFilePath(
|
||||||
|
const string16& origin_id) const {
|
||||||
|
FilePath data_path(_Context->cache_path());
|
||||||
|
FilePath storageDir = data_path.Append(
|
||||||
|
DOMStorageContext::kLocalStorageDirectory);
|
||||||
|
FilePath::StringType id =
|
||||||
|
webkit_glue::WebStringToFilePathString(origin_id);
|
||||||
|
return storageDir.Append(id.append(kLocalStorageExtension));
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef _DOM_STORAGE_CONTEXT_H
|
||||||
|
#define _DOM_STORAGE_CONTEXT_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "base/file_path.h"
|
||||||
|
#include "base/string16.h"
|
||||||
|
#include "base/time.h"
|
||||||
|
|
||||||
|
class DOMStorageArea;
|
||||||
|
class DOMStorageNamespace;
|
||||||
|
|
||||||
|
// This is owned by CefContext and is all the dom storage information that's
|
||||||
|
// shared by all of the browser windows. The specifics of responsibilities are
|
||||||
|
// fairly well documented here and in StorageNamespace and StorageArea.
|
||||||
|
// Everything is only to be accessed on the WebKit thread unless noted
|
||||||
|
// otherwise.
|
||||||
|
//
|
||||||
|
// NOTE: Virtual methods facilitate mocking functions for testing.
|
||||||
|
class DOMStorageContext {
|
||||||
|
public:
|
||||||
|
DOMStorageContext();
|
||||||
|
virtual ~DOMStorageContext();
|
||||||
|
|
||||||
|
// Allocate a new storage area id. Only call on the WebKit thread.
|
||||||
|
int64 AllocateStorageAreaId();
|
||||||
|
|
||||||
|
// Allocate a new session storage id. Only call on the UI or IO thread.
|
||||||
|
int64 AllocateSessionStorageNamespaceId();
|
||||||
|
|
||||||
|
// Clones a session storage namespace and returns the cloned namespaces' id.
|
||||||
|
// Only call on the IO thread.
|
||||||
|
int64 CloneSessionStorage(int64 original_id);
|
||||||
|
|
||||||
|
// Various storage area methods. The storage area is owned by one of the
|
||||||
|
// namespaces that's owned by this class.
|
||||||
|
void RegisterStorageArea(DOMStorageArea* storage_area);
|
||||||
|
void UnregisterStorageArea(DOMStorageArea* storage_area);
|
||||||
|
DOMStorageArea* GetStorageArea(int64 id);
|
||||||
|
|
||||||
|
// Called on WebKit thread when a session storage namespace can be deleted.
|
||||||
|
void DeleteSessionStorageNamespace(int64 namespace_id);
|
||||||
|
|
||||||
|
// Get a namespace from an id. What's returned is owned by this class. If
|
||||||
|
// allocation_allowed is true, then this function will create the storage
|
||||||
|
// namespace if it hasn't been already.
|
||||||
|
DOMStorageNamespace* GetStorageNamespace(int64 id, bool allocation_allowed);
|
||||||
|
|
||||||
|
// Tells storage namespaces to purge any memory they do not need.
|
||||||
|
virtual void PurgeMemory();
|
||||||
|
|
||||||
|
// Delete any local storage files that have been touched since the cutoff
|
||||||
|
// date that's supplied.
|
||||||
|
void DeleteDataModifiedSince(const base::Time& cutoff,
|
||||||
|
const char* url_scheme_to_be_skipped,
|
||||||
|
const std::vector<string16>& protected_origins);
|
||||||
|
|
||||||
|
// Deletes a single local storage file.
|
||||||
|
void DeleteLocalStorageFile(const FilePath& file_path);
|
||||||
|
|
||||||
|
// Deletes the local storage file for the given origin.
|
||||||
|
void DeleteLocalStorageForOrigin(const string16& origin_id);
|
||||||
|
|
||||||
|
// Deletes all local storage files.
|
||||||
|
void DeleteAllLocalStorageFiles();
|
||||||
|
|
||||||
|
// The local storage directory.
|
||||||
|
static const FilePath::CharType kLocalStorageDirectory[];
|
||||||
|
|
||||||
|
// The local storage file extension.
|
||||||
|
static const FilePath::CharType kLocalStorageExtension[];
|
||||||
|
|
||||||
|
// Delete all non-extension local storage files.
|
||||||
|
static void ClearLocalState(const FilePath& profile_path,
|
||||||
|
const char* url_scheme_to_be_skipped);
|
||||||
|
|
||||||
|
// Get the file name of the local storage file for the given origin.
|
||||||
|
FilePath GetLocalStorageFilePath(const string16& origin_id) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Get the local storage instance. The object is owned by this class.
|
||||||
|
DOMStorageNamespace* CreateLocalStorage();
|
||||||
|
|
||||||
|
// Get a new session storage namespace. The object is owned by this class.
|
||||||
|
DOMStorageNamespace* CreateSessionStorage(int64 namespace_id);
|
||||||
|
|
||||||
|
// Used internally to register storage namespaces we create.
|
||||||
|
void RegisterStorageNamespace(DOMStorageNamespace* storage_namespace);
|
||||||
|
|
||||||
|
// The WebKit thread half of CloneSessionStorage above. Static because
|
||||||
|
// DOMStorageContext isn't ref counted thus we can't use a runnable method.
|
||||||
|
// That said, we know this is safe because this class is destroyed on the
|
||||||
|
// WebKit thread, so there's no way it could be destroyed before this is run.
|
||||||
|
static void CompleteCloningSessionStorage(DOMStorageContext* context,
|
||||||
|
int64 existing_id, int64 clone_id);
|
||||||
|
|
||||||
|
// The last used storage_area_id and storage_namespace_id's. For the storage
|
||||||
|
// namespaces, IDs allocated on the UI thread are positive and count up while
|
||||||
|
// IDs allocated on the IO thread are negative and count down. This allows us
|
||||||
|
// to allocate unique IDs on both without any locking. All storage area ids
|
||||||
|
// are allocated on the WebKit thread.
|
||||||
|
int64 last_storage_area_id_;
|
||||||
|
int64 last_session_storage_namespace_id_on_ui_thread_;
|
||||||
|
int64 last_session_storage_namespace_id_on_io_thread_;
|
||||||
|
|
||||||
|
// Maps ids to StorageAreas. We do NOT own these objects. StorageNamespace
|
||||||
|
// (which does own them) will notify us when we should remove the entries.
|
||||||
|
typedef std::map<int64, DOMStorageArea*> StorageAreaMap;
|
||||||
|
StorageAreaMap storage_area_map_;
|
||||||
|
|
||||||
|
// Maps ids to StorageNamespaces. We own these objects.
|
||||||
|
typedef std::map<int64, DOMStorageNamespace*> StorageNamespaceMap;
|
||||||
|
StorageNamespaceMap storage_namespace_map_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _DOM_STORAGE_CONTEXT_H
|
|
@ -0,0 +1,110 @@
|
||||||
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this
|
||||||
|
// source code is governed by a BSD-style license that can be found in the
|
||||||
|
// LICENSE file.
|
||||||
|
|
||||||
|
#include "dom_storage_namespace.h"
|
||||||
|
#include "dom_storage_area.h"
|
||||||
|
#include "dom_storage_context.h"
|
||||||
|
|
||||||
|
#include "base/file_path.h"
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebStorageArea.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebStorageNamespace.h"
|
||||||
|
#include "webkit/glue/webkit_glue.h"
|
||||||
|
|
||||||
|
using WebKit::WebStorageArea;
|
||||||
|
using WebKit::WebStorageNamespace;
|
||||||
|
using WebKit::WebString;
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
DOMStorageNamespace* DOMStorageNamespace::CreateLocalStorageNamespace(
|
||||||
|
DOMStorageContext* dom_storage_context, const FilePath& data_dir_path) {
|
||||||
|
int64 id = kLocalStorageNamespaceId;
|
||||||
|
DCHECK(!dom_storage_context->GetStorageNamespace(id, false));
|
||||||
|
return new DOMStorageNamespace(dom_storage_context, id,
|
||||||
|
webkit_glue::FilePathToWebString(data_dir_path), DOM_STORAGE_LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
DOMStorageNamespace* DOMStorageNamespace::CreateSessionStorageNamespace(
|
||||||
|
DOMStorageContext* dom_storage_context, int64 id) {
|
||||||
|
DCHECK(!dom_storage_context->GetStorageNamespace(id, false));
|
||||||
|
return new DOMStorageNamespace(dom_storage_context, id, WebString(),
|
||||||
|
DOM_STORAGE_SESSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMStorageNamespace::DOMStorageNamespace(DOMStorageContext* dom_storage_context,
|
||||||
|
int64 id,
|
||||||
|
const WebString& data_dir_path,
|
||||||
|
DOMStorageType dom_storage_type)
|
||||||
|
: dom_storage_context_(dom_storage_context),
|
||||||
|
id_(id),
|
||||||
|
data_dir_path_(data_dir_path),
|
||||||
|
dom_storage_type_(dom_storage_type) {
|
||||||
|
DCHECK(dom_storage_context_);
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMStorageNamespace::~DOMStorageNamespace() {
|
||||||
|
// TODO(jorlow): If the DOMStorageContext is being destructed, there's no need
|
||||||
|
// to do these calls. Maybe we should add a fast path?
|
||||||
|
for (OriginToStorageAreaMap::iterator iter(origin_to_storage_area_.begin());
|
||||||
|
iter != origin_to_storage_area_.end(); ++iter) {
|
||||||
|
dom_storage_context_->UnregisterStorageArea(iter->second);
|
||||||
|
delete iter->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMStorageArea* DOMStorageNamespace::GetStorageArea(
|
||||||
|
const string16& origin) {
|
||||||
|
// We may have already created it for another dispatcher host.
|
||||||
|
OriginToStorageAreaMap::iterator iter = origin_to_storage_area_.find(origin);
|
||||||
|
if (iter != origin_to_storage_area_.end())
|
||||||
|
return iter->second;
|
||||||
|
|
||||||
|
// We need to create a new one.
|
||||||
|
int64 id = dom_storage_context_->AllocateStorageAreaId();
|
||||||
|
DCHECK(!dom_storage_context_->GetStorageArea(id));
|
||||||
|
DOMStorageArea* storage_area = new DOMStorageArea(origin, id, this);
|
||||||
|
origin_to_storage_area_[origin] = storage_area;
|
||||||
|
dom_storage_context_->RegisterStorageArea(storage_area);
|
||||||
|
return storage_area;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMStorageNamespace* DOMStorageNamespace::Copy(int64 id) {
|
||||||
|
DCHECK(dom_storage_type_ == DOM_STORAGE_SESSION);
|
||||||
|
DCHECK(!dom_storage_context_->GetStorageNamespace(id, false));
|
||||||
|
DOMStorageNamespace* new_storage_namespace = new DOMStorageNamespace(
|
||||||
|
dom_storage_context_, id, data_dir_path_, dom_storage_type_);
|
||||||
|
// If we haven't used the namespace yet, there's nothing to copy.
|
||||||
|
if (storage_namespace_.get())
|
||||||
|
new_storage_namespace->storage_namespace_.reset(storage_namespace_->copy());
|
||||||
|
return new_storage_namespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DOMStorageNamespace::PurgeMemory() {
|
||||||
|
DCHECK(dom_storage_type_ == DOM_STORAGE_LOCAL);
|
||||||
|
for (OriginToStorageAreaMap::iterator iter(origin_to_storage_area_.begin());
|
||||||
|
iter != origin_to_storage_area_.end(); ++iter)
|
||||||
|
iter->second->PurgeMemory();
|
||||||
|
storage_namespace_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
WebStorageArea* DOMStorageNamespace::CreateWebStorageArea(
|
||||||
|
const string16& origin) {
|
||||||
|
CreateWebStorageNamespaceIfNecessary();
|
||||||
|
return storage_namespace_->createStorageArea(origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DOMStorageNamespace::CreateWebStorageNamespaceIfNecessary() {
|
||||||
|
if (storage_namespace_.get())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dom_storage_type_ == DOM_STORAGE_LOCAL) {
|
||||||
|
storage_namespace_.reset(
|
||||||
|
WebStorageNamespace::createLocalStorageNamespace(data_dir_path_,
|
||||||
|
WebStorageNamespace::m_localStorageQuota));
|
||||||
|
} else {
|
||||||
|
storage_namespace_.reset(WebStorageNamespace::createSessionStorageNamespace(
|
||||||
|
WebStorageNamespace::m_sessionStorageQuota));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef _DOM_STORAGE_NAMESPACE_H
|
||||||
|
#define _DOM_STORAGE_NAMESPACE_H
|
||||||
|
|
||||||
|
#include "dom_storage_common.h"
|
||||||
|
|
||||||
|
#include "base/hash_tables.h"
|
||||||
|
#include "base/scoped_ptr.h"
|
||||||
|
#include "base/string16.h"
|
||||||
|
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
|
||||||
|
|
||||||
|
class DOMStorageArea;
|
||||||
|
class DOMStorageContext;
|
||||||
|
class FilePath;
|
||||||
|
|
||||||
|
namespace WebKit {
|
||||||
|
class WebStorageArea;
|
||||||
|
class WebStorageNamespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only to be used on the WebKit thread.
|
||||||
|
class DOMStorageNamespace {
|
||||||
|
public:
|
||||||
|
static DOMStorageNamespace* CreateLocalStorageNamespace(
|
||||||
|
DOMStorageContext* dom_storage_context, const FilePath& data_dir_path);
|
||||||
|
static DOMStorageNamespace* CreateSessionStorageNamespace(
|
||||||
|
DOMStorageContext* dom_storage_context, int64 namespace_id);
|
||||||
|
|
||||||
|
~DOMStorageNamespace();
|
||||||
|
|
||||||
|
DOMStorageArea* GetStorageArea(const string16& origin);
|
||||||
|
DOMStorageNamespace* Copy(int64 clone_namespace_id);
|
||||||
|
|
||||||
|
void PurgeMemory();
|
||||||
|
|
||||||
|
const DOMStorageContext* dom_storage_context() const {
|
||||||
|
return dom_storage_context_;
|
||||||
|
}
|
||||||
|
int64 id() const { return id_; }
|
||||||
|
const WebKit::WebString& data_dir_path() const { return data_dir_path_; }
|
||||||
|
DOMStorageType dom_storage_type() const { return dom_storage_type_; }
|
||||||
|
|
||||||
|
// Creates a WebStorageArea for the given origin. This should only be called
|
||||||
|
// by an owned DOMStorageArea.
|
||||||
|
WebKit::WebStorageArea* CreateWebStorageArea(const string16& origin);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Called by the static factory methods above.
|
||||||
|
DOMStorageNamespace(DOMStorageContext* dom_storage_context,
|
||||||
|
int64 id,
|
||||||
|
const WebKit::WebString& data_dir_path,
|
||||||
|
DOMStorageType storage_type);
|
||||||
|
|
||||||
|
// Creates the underlying WebStorageNamespace on demand.
|
||||||
|
void CreateWebStorageNamespaceIfNecessary();
|
||||||
|
|
||||||
|
// All the storage areas we own.
|
||||||
|
typedef base::hash_map<string16, DOMStorageArea*> OriginToStorageAreaMap;
|
||||||
|
OriginToStorageAreaMap origin_to_storage_area_;
|
||||||
|
|
||||||
|
// The DOMStorageContext that owns us.
|
||||||
|
DOMStorageContext* dom_storage_context_;
|
||||||
|
|
||||||
|
// The WebKit storage namespace we manage.
|
||||||
|
scoped_ptr<WebKit::WebStorageNamespace> storage_namespace_;
|
||||||
|
|
||||||
|
// Our id. Unique to our parent context class.
|
||||||
|
int64 id_;
|
||||||
|
|
||||||
|
// The path used to create us, so we can recreate our WebStorageNamespace on
|
||||||
|
// demand.
|
||||||
|
WebKit::WebString data_dir_path_;
|
||||||
|
|
||||||
|
// SessionStorage vs. LocalStorage.
|
||||||
|
const DOMStorageType dom_storage_type_;
|
||||||
|
|
||||||
|
DISALLOW_IMPLICIT_CONSTRUCTORS(DOMStorageNamespace);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _DOM_STORAGE_NAMESPACE_H
|
|
@ -338,3 +338,8 @@ void RunPopupTest(CefRefPtr<CefBrowser> browser)
|
||||||
browser->GetMainFrame()->ExecuteJavaScript(
|
browser->GetMainFrame()->ExecuteJavaScript(
|
||||||
L"window.open('http://www.google.com');", L"about:blank", 0);
|
L"window.open('http://www.google.com');", L"about:blank", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RunLocalStorageTest(CefRefPtr<CefBrowser> browser)
|
||||||
|
{
|
||||||
|
browser->GetMainFrame()->LoadURL(L"http://tests/localstorage");
|
||||||
|
}
|
||||||
|
|
|
@ -361,5 +361,6 @@ void RunGetTextTest(CefRefPtr<CefFrame> frame);
|
||||||
void RunRequestTest(CefRefPtr<CefBrowser> browser);
|
void RunRequestTest(CefRefPtr<CefBrowser> browser);
|
||||||
void RunJavaScriptExecuteTest(CefRefPtr<CefBrowser> browser);
|
void RunJavaScriptExecuteTest(CefRefPtr<CefBrowser> browser);
|
||||||
void RunPopupTest(CefRefPtr<CefBrowser> browser);
|
void RunPopupTest(CefRefPtr<CefBrowser> browser);
|
||||||
|
void RunLocalStorageTest(CefRefPtr<CefBrowser> browser);
|
||||||
|
|
||||||
#endif // _CEFCLIENT_H
|
#endif // _CEFCLIENT_H
|
||||||
|
|
|
@ -31,6 +31,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
IDS_LOGO BINARY "res\logo.png"
|
IDS_LOGO BINARY "res\logo.png"
|
||||||
IDS_UIPLUGIN BINARY "res\uiplugin.html"
|
IDS_UIPLUGIN BINARY "res\uiplugin.html"
|
||||||
IDS_LOGOBALL BINARY "res\logoball.png"
|
IDS_LOGOBALL BINARY "res\logoball.png"
|
||||||
|
IDS_LOCALSTORAGE BINARY "res\localstorage.html"
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -73,7 +74,8 @@ BEGIN
|
||||||
MENUITEM "Request", ID_TESTS_REQUEST
|
MENUITEM "Request", ID_TESTS_REQUEST
|
||||||
MENUITEM "Scheme Handler", ID_TESTS_SCHEME_HANDLER
|
MENUITEM "Scheme Handler", ID_TESTS_SCHEME_HANDLER
|
||||||
MENUITEM "UI App Example", ID_TESTS_UIAPP
|
MENUITEM "UI App Example", ID_TESTS_UIAPP
|
||||||
END
|
MENUITEM "Local Storage", ID_TESTS_LOCALSTORAGE
|
||||||
|
END
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -533,6 +533,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
if(browser.get())
|
if(browser.get())
|
||||||
RunUIPluginTest(browser);
|
RunUIPluginTest(browser);
|
||||||
return 0;
|
return 0;
|
||||||
|
case ID_TESTS_LOCALSTORAGE: // Test localStorage
|
||||||
|
if(browser.get())
|
||||||
|
RunLocalStorageTest(browser);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -656,14 +660,20 @@ CefHandler::RetVal ClientHandler::HandleBeforeResourceLoad(
|
||||||
resourceStream = CefStreamReader::CreateForData(
|
resourceStream = CefStreamReader::CreateForData(
|
||||||
(void*)dump.c_str(), dump.size() * sizeof(wchar_t));
|
(void*)dump.c_str(), dump.size() * sizeof(wchar_t));
|
||||||
mimeType = L"text/plain";
|
mimeType = L"text/plain";
|
||||||
}
|
} else if(url == L"http://tests/uiapp") {
|
||||||
else if(url == L"http://tests/uiapp") {
|
|
||||||
// Show the uiapp contents
|
// Show the uiapp contents
|
||||||
if(LoadBinaryResource(IDS_UIPLUGIN, dwSize, pBytes)) {
|
if(LoadBinaryResource(IDS_UIPLUGIN, dwSize, pBytes)) {
|
||||||
resourceStream = CefStreamReader::CreateForHandler(
|
resourceStream = CefStreamReader::CreateForHandler(
|
||||||
new CefByteReadHandler(pBytes, dwSize, NULL));
|
new CefByteReadHandler(pBytes, dwSize, NULL));
|
||||||
mimeType = L"text/html";
|
mimeType = L"text/html";
|
||||||
}
|
}
|
||||||
|
} else if(url == L"http://tests/localstorage") {
|
||||||
|
// Show the localstorage contents
|
||||||
|
if(LoadBinaryResource(IDS_LOCALSTORAGE, dwSize, pBytes)) {
|
||||||
|
resourceStream = CefStreamReader::CreateForHandler(
|
||||||
|
new CefByteReadHandler(pBytes, dwSize, NULL));
|
||||||
|
mimeType = L"text/html";
|
||||||
|
}
|
||||||
} else if(wcsstr(url.c_str(), L"/ps_logo2.png") != NULL) {
|
} else if(wcsstr(url.c_str(), L"/ps_logo2.png") != NULL) {
|
||||||
// Any time we find "ps_logo2.png" in the URL substitute in our own image
|
// Any time we find "ps_logo2.png" in the URL substitute in our own image
|
||||||
if(LoadBinaryResource(IDS_LOGO, dwSize, pBytes)) {
|
if(LoadBinaryResource(IDS_LOGO, dwSize, pBytes)) {
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script language="JavaScript">
|
||||||
|
var val = window.localStorage.getItem('val');
|
||||||
|
function addLine() {
|
||||||
|
if(val == null)
|
||||||
|
val = '<br/>One Line.';
|
||||||
|
else
|
||||||
|
val += '<br/>Another Line.';
|
||||||
|
window.localStorage.setItem('val', val);
|
||||||
|
document.getElementById('out').innerHTML = val;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
Click the "Add Line" button to add a line or the "Clear" button to clear.<br/>
|
||||||
|
This data will persist across sessions if a cache path was specified.<br/>
|
||||||
|
<input type="button" value="Add Line" onClick="addLine();"/>
|
||||||
|
<input type="button" value="Clear" onClick="window.localStorage.removeItem('val'); window.location.reload();"/>
|
||||||
|
<div id="out"></div>
|
||||||
|
<script language="JavaScript">
|
||||||
|
if(val != null)
|
||||||
|
document.getElementById('out').innerHTML = val;
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -36,10 +36,12 @@
|
||||||
#define ID_TESTS_REQUEST 32776
|
#define ID_TESTS_REQUEST 32776
|
||||||
#define ID_TESTS_SCHEME_HANDLER 32777
|
#define ID_TESTS_SCHEME_HANDLER 32777
|
||||||
#define ID_TESTS_UIAPP 32778
|
#define ID_TESTS_UIAPP 32778
|
||||||
|
#define ID_TESTS_LOCALSTORAGE 32779
|
||||||
#define IDC_STATIC -1
|
#define IDC_STATIC -1
|
||||||
#define IDS_LOGO 1000
|
#define IDS_LOGO 1000
|
||||||
#define IDS_UIPLUGIN 1001
|
#define IDS_UIPLUGIN 1001
|
||||||
#define IDS_LOGOBALL 1002
|
#define IDS_LOGOBALL 1002
|
||||||
|
#define IDS_LOCALSTORAGE 1003
|
||||||
|
|
||||||
// Avoid files associated with MacOS
|
// Avoid files associated with MacOS
|
||||||
#define _X86_
|
#define _X86_
|
||||||
|
|
Loading…
Reference in New Issue