From 628fb5f5e97cb262a1f9916f4e5a357a805428ed Mon Sep 17 00:00:00 2001 From: Robo Date: Thu, 2 Jul 2015 19:42:18 +0530 Subject: [PATCH] app: api to clear data from different storage types --- atom/browser/api/atom_api_session.cc | 96 +++++++++++++++++++ atom/browser/api/atom_api_session.h | 6 ++ docs/api/browser-window.md | 26 ++++- ...es-spec.coffee => api-session-spec.coffee} | 17 +++- spec/fixtures/api/localstorage.html | 11 +++ 5 files changed, 150 insertions(+), 6 deletions(-) rename spec/{api-cookies-spec.coffee => api-session-spec.coffee} (80%) create mode 100644 spec/fixtures/api/localstorage.html diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index d1eaca7994ab..4236fddc136c 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -10,17 +10,67 @@ #include "atom/browser/atom_browser_context.h" #include "atom/common/native_mate_converters/gurl_converter.h" #include "base/thread_task_runner_handle.h" +#include "base/strings/string_util.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" #include "native_mate/callback.h" #include "native_mate/object_template_builder.h" #include "net/base/load_flags.h" +#include "net/disk_cache/disk_cache.h" #include "net/proxy/proxy_service.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" #include "atom/common/node_includes.h" +using content::BrowserThread; +using content::StoragePartition; + +namespace { + +int GetStorageMask(const std::vector& storage_types) { + int storage_mask = 0; + + for (auto &it : storage_types) { + auto type = base::StringToLowerASCII(it); + if (type == "appcache") { + storage_mask |= StoragePartition::REMOVE_DATA_MASK_APPCACHE; + } else if (type == "cookies") { + storage_mask |= StoragePartition::REMOVE_DATA_MASK_COOKIES; + } else if (type == "filesystem") { + storage_mask |= StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS; + } else if (type == "indexdb") { + storage_mask |= StoragePartition::REMOVE_DATA_MASK_INDEXEDDB; + } else if (type == "localstorage") { + storage_mask |= StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE; + } else if (type == "shadercache") { + storage_mask |= StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE; + } else if (type == "websql") { + storage_mask |= StoragePartition::REMOVE_DATA_MASK_WEBSQL; + } else if (type == "serviceworkers") { + storage_mask |= StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS; + } + } + + return storage_mask; +} + +int GetQuotaMask(const std::vector& quota_types) { + int quota_mask = 0; + + for (auto &type : quota_types) { + if (type == "temporary") { + quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY; + } else if (type == "persistent") { + quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT; + } + } + + return quota_mask; +} + +} // namespace + namespace atom { namespace api { @@ -80,6 +130,30 @@ class ResolveProxyHelper { DISALLOW_COPY_AND_ASSIGN(ResolveProxyHelper); }; +void Noop(int result) { + DCHECK(result == net::OK); +} + +void DoClearCache(disk_cache::Backend** cache_ptr, + int result) { + DCHECK(result == net::OK); + if (cache_ptr && *cache_ptr) + (*cache_ptr)->DoomAllEntries(base::Bind(&Noop)); +} + +void ClearHttpCacheOnIO(net::URLRequestContextGetter* getter) { + typedef disk_cache::Backend* Backendptr; + Backendptr* cache_ptr = new Backendptr(nullptr); + auto request_context = getter->GetURLRequestContext(); + net::CompletionCallback callback(base::Bind(&DoClearCache, + base::Owned(cache_ptr))); + auto http_cache = request_context->http_transaction_factory()->GetCache(); + int rv = http_cache->GetBackend(cache_ptr, callback); + + if (rv != net::ERR_IO_PENDING) + callback.Run(net::OK); +} + } // namespace Session::Session(AtomBrowserContext* browser_context) @@ -94,6 +168,26 @@ void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) { new ResolveProxyHelper(browser_context_, url, callback); } +void Session::ClearCache(const base::Closure& callback) { + auto getter = browser_context_->GetRequestContext(); + BrowserThread::PostTaskAndReply(BrowserThread::IO, FROM_HERE, + base::Bind(&ClearHttpCacheOnIO, + base::Unretained(getter)), + callback); +} + +void Session::ClearStorageData(const GURL& origin, + const std::vector& storage_types, + const std::vector& quota_types, + const base::Closure& callback) { + auto storage_partition = + content::BrowserContext::GetStoragePartition(browser_context_, nullptr); + storage_partition->ClearData( + GetStorageMask(storage_types), GetQuotaMask(quota_types), origin, + content::StoragePartition::OriginMatcherFunction(), + base::Time(), base::Time::Max(), callback); +} + v8::Local Session::Cookies(v8::Isolate* isolate) { if (cookies_.IsEmpty()) { auto handle = atom::api::Cookies::Create(isolate, browser_context_); @@ -106,6 +200,8 @@ mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( v8::Isolate* isolate) { return mate::ObjectTemplateBuilder(isolate) .SetMethod("resolveProxy", &Session::ResolveProxy) + .SetMethod("clearCache", &Session::ClearCache) + .SetMethod("clearStorageData", &Session::ClearStorageData) .SetProperty("cookies", &Session::Cookies); } diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index cd9f0a59a872..ec9083d3054a 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -6,6 +6,7 @@ #define ATOM_BROWSER_API_ATOM_API_SESSION_H_ #include +#include #include "atom/browser/api/trackable_object.h" #include "base/callback.h" @@ -37,6 +38,11 @@ class Session: public mate::TrackableObject { private: void ResolveProxy(const GURL& url, ResolveProxyCallback callback); + void ClearCache(const base::Closure& callback); + void ClearStorageData(const GURL& origin, + const std::vector& storage_types, + const std::vector& quota_types, + const base::Closure& callback); v8::Local Cookies(v8::Isolate* isolate); v8::Global cookies_; diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index a339b855bb71..7850fcabbdc8 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -1055,7 +1055,9 @@ app.on('ready', function() { 2. There is no way to send synchronous messages from the main process to a renderer process, because it would be very easy to cause dead locks. -## Class: WebContents.session.cookies +## Class: Session + +### Session.cookies The `cookies` gives you ability to query and modify cookies, an example is: @@ -1091,7 +1093,7 @@ win.webContents.on('did-finish-load', function() { }); ``` -### WebContents.session.cookies.get(details, callback) +### Session.cookies.get(details, callback) * `details` Object * `url` String - Retrieves cookies which are associated with `url`. @@ -1118,7 +1120,7 @@ win.webContents.on('did-finish-load', function() { the number of seconds since the UNIX epoch. Not provided for session cookies. -### WebContents.session.cookies.set(details, callback) +### Session.cookies.set(details, callback) * `details` Object * `url` String - Retrieves cookies which are associated with `url` @@ -1134,10 +1136,26 @@ win.webContents.on('did-finish-load', function() { * `callback` Function - function(error) * `error` Error -### WebContents.session.cookies.remove(details, callback) +### Session.cookies.remove(details, callback) * `details` Object * `url` String - The URL associated with the cookie * `name` String - The name of cookie to remove * `callback` Function - function(error) * `error` Error + +### Session.clearCache() + +Clears the session's http cache. + +### Session.clearStorageData(origin, storageType, quotaType, callback) + +* `origin` String - should follow `window.location.origin` representation `scheme`://`host`:`port` +* `storageType` Array - specifies the type of storage, can contain - + `appcache`, `cookies`, `filesystem`, `indexdb`, `localstorage`, `shadercache`, `websql`, + `serviceworkers` +* `quotaType` Array - specifies the storage quota type, can contain - + `temporary`, `persistent` +* `callback` Function + +`callback` is invoked when the deletion process is scheduled. diff --git a/spec/api-cookies-spec.coffee b/spec/api-session-spec.coffee similarity index 80% rename from spec/api-cookies-spec.coffee rename to spec/api-session-spec.coffee index de934234c140..d439b6373cda 100644 --- a/spec/api-cookies-spec.coffee +++ b/spec/api-session-spec.coffee @@ -4,12 +4,12 @@ http = require 'http' path = require 'path' BrowserWindow = remote.require 'browser-window' -describe 'cookies module', -> +describe 'session module', -> fixtures = path.resolve __dirname, 'fixtures' w = null url = "http://127.0.0.1" - beforeEach -> w = new BrowserWindow(show: true) + beforeEach -> w = new BrowserWindow(show: false, width: 400, height: 400) afterEach -> w.destroy() it 'should get cookies', (done) -> @@ -69,3 +69,16 @@ describe 'cookies module', -> throw error if error assert.equal 0, cookies_list.length done() + + describe 'session.clearStorageData(options)', -> + fixtures = path.resolve __dirname, 'fixtures' + it 'clears localstorage data', (done) -> + ipc = remote.require('ipc') + ipc.on 'count', (event, count) -> + ipc.removeAllListeners 'count' + assert not count + done() + w.loadUrl 'file://' + path.join(fixtures, 'api', 'localstorage.html') + w.webContents.on 'did-finish-load', -> + w.webContents.session.clearStorageData "file://", ['localstorage'], ['persistent'], -> + w.webContents.send 'getcount' diff --git a/spec/fixtures/api/localstorage.html b/spec/fixtures/api/localstorage.html new file mode 100644 index 000000000000..8110a0b4be6a --- /dev/null +++ b/spec/fixtures/api/localstorage.html @@ -0,0 +1,11 @@ + + + + +