diff options
Diffstat (limited to 'storage')
-rw-r--r-- | storage/browser/BUILD.gn | 2 | ||||
-rw-r--r-- | storage/browser/blob/blob_storage_registry.cc | 116 | ||||
-rw-r--r-- | storage/browser/blob/blob_storage_registry.h | 108 | ||||
-rw-r--r-- | storage/browser/blob/internal_blob_data.h | 1 | ||||
-rw-r--r-- | storage/storage_browser.gyp | 2 |
5 files changed, 229 insertions, 0 deletions
diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn index 6206f37..e3bfa81 100644 --- a/storage/browser/BUILD.gn +++ b/storage/browser/BUILD.gn @@ -18,6 +18,8 @@ component("browser") { "blob/blob_reader.h", "blob/blob_storage_context.cc", "blob/blob_storage_context.h", + "blob/blob_storage_registry.cc", + "blob/blob_storage_registry.h", "blob/blob_url_request_job.cc", "blob/blob_url_request_job.h", "blob/blob_url_request_job_factory.cc", diff --git a/storage/browser/blob/blob_storage_registry.cc b/storage/browser/blob/blob_storage_registry.cc new file mode 100644 index 0000000..805a677d --- /dev/null +++ b/storage/browser/blob/blob_storage_registry.cc @@ -0,0 +1,116 @@ +// Copyright 2015 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 "storage/browser/blob/blob_storage_registry.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "base/stl_util.h" +#include "url/gurl.h" + +namespace storage { +using BlobState = BlobStorageRegistry::BlobState; + +namespace { +// We can't use GURL directly for these hash fragment manipulations +// since it doesn't have specific knowlege of the BlobURL format. GURL +// treats BlobURLs as if they were PathURLs which don't support hash +// fragments. + +bool BlobUrlHasRef(const GURL& url) { + return url.spec().find('#') != std::string::npos; +} + +GURL ClearBlobUrlRef(const GURL& url) { + size_t hash_pos = url.spec().find('#'); + if (hash_pos == std::string::npos) + return url; + return GURL(url.spec().substr(0, hash_pos)); +} + +} // namespace + +BlobStorageRegistry::Entry::Entry(int refcount, BlobState state) + : refcount(refcount), state(state), exceeded_memory(false) {} + +BlobStorageRegistry::Entry::~Entry() {} + +bool BlobStorageRegistry::Entry::TestAndSetState(BlobState expected, + BlobState set) { + if (state != expected) + return false; + state = set; + return true; +} + +BlobStorageRegistry::BlobStorageRegistry() {} + +BlobStorageRegistry::~BlobStorageRegistry() { + // Note: We don't bother calling the construction complete callbacks, as we + // are only being destructed at the end of the life of the browser process. + // So it shouldn't matter. +} + +BlobStorageRegistry::Entry* BlobStorageRegistry::CreateEntry( + const std::string& uuid) { + DCHECK(!ContainsKey(blob_map_, uuid)); + Entry* entry = new Entry(1, BlobState::RESERVED); + blob_map_.add(uuid, make_scoped_ptr(entry)); + return entry; +} + +bool BlobStorageRegistry::DeleteEntry(const std::string& uuid) { + return blob_map_.erase(uuid) == 1; +} + +BlobStorageRegistry::Entry* BlobStorageRegistry::GetEntry( + const std::string& uuid) { + BlobMap::iterator found = blob_map_.find(uuid); + if (found == blob_map_.end()) + return nullptr; + return found->second; +} + +bool BlobStorageRegistry::CreateUrlMapping(const GURL& blob_url, + const std::string& uuid) { + DCHECK(!BlobUrlHasRef(blob_url)); + if (blob_map_.find(uuid) == blob_map_.end() || IsURLMapped(blob_url)) + return false; + url_to_uuid_[blob_url] = uuid; + return true; +} + +bool BlobStorageRegistry::DeleteURLMapping(const GURL& blob_url, + std::string* uuid) { + DCHECK(!BlobUrlHasRef(blob_url)); + URLMap::iterator found = url_to_uuid_.find(blob_url); + if (found == url_to_uuid_.end()) + return false; + if (uuid) + uuid->assign(found->second); + url_to_uuid_.erase(found); + return true; +} + +bool BlobStorageRegistry::IsURLMapped(const GURL& blob_url) const { + return ContainsKey(url_to_uuid_, blob_url); +} + +BlobStorageRegistry::Entry* BlobStorageRegistry::GetEntryFromURL( + const GURL& url, + std::string* uuid) { + URLMap::iterator found = + url_to_uuid_.find(BlobUrlHasRef(url) ? ClearBlobUrlRef(url) : url); + if (found == url_to_uuid_.end()) + return nullptr; + Entry* entry = GetEntry(found->second); + if (entry && uuid) + uuid->assign(found->second); + return entry; +} + +} // namespace storage diff --git a/storage/browser/blob/blob_storage_registry.h b/storage/browser/blob/blob_storage_registry.h new file mode 100644 index 0000000..8a79493 --- /dev/null +++ b/storage/browser/blob/blob_storage_registry.h @@ -0,0 +1,108 @@ +// Copyright 2015 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 STORAGE_BROWSER_BLOB_BLOB_STORAGE_REGISTRY_H_ +#define STORAGE_BROWSER_BLOB_BLOB_STORAGE_REGISTRY_H_ + +#include <map> +#include <string> +#include <vector> + +#include "base/callback_forward.h" +#include "base/containers/scoped_ptr_hash_map.h" +#include "base/macros.h" +#include "storage/browser/blob/internal_blob_data.h" +#include "storage/browser/storage_browser_export.h" + +class GURL; + +namespace storage { + +// This class stores the blob data in the various states of construction, as +// well as URL mappings to blob uuids. +// Implementation notes: +// * There is no implicit refcounting in this class, except for setting the +// refcount to 1 on registration. +// * When removing a uuid registration, we do not check for URL mappings to that +// uuid. The user must keep track of these. +class STORAGE_EXPORT BlobStorageRegistry { + public: + enum class BlobState { + // First the renderer reserves the uuid. + RESERVED = 1, + // Second, we are asynchronously transporting data to the browser. + ASYNC_TRANSPORTATION, + // Third, we construct the blob when we have all of the data. + CONSTRUCTION, + // Finally, the blob is built. + ACTIVE + }; + + struct STORAGE_EXPORT Entry { + size_t refcount; + BlobState state; + std::vector<base::Callback<void(bool)>> construction_complete_callbacks; + + // Flags + bool exceeded_memory; + + // data and data_builder are mutually exclusive. + scoped_ptr<InternalBlobData> data; + scoped_ptr<InternalBlobData::Builder> data_builder; + + Entry() = delete; + Entry(int refcount, BlobState state); + ~Entry(); + + // Performs a test-and-set on the state of the given blob. If the state + // isn't as expected, we return false. Otherwise we set the new state and + // return true. + bool TestAndSetState(BlobState expected, BlobState set); + }; + + BlobStorageRegistry(); + ~BlobStorageRegistry(); + + // Creates the blob entry with a refcount of 1 and a state of RESERVED. If + // the blob is already in use, we return null. + Entry* CreateEntry(const std::string& uuid); + + // Removes the blob entry with the given uuid. This does not unmap any + // URLs that are pointing to this uuid. Returns if the entry existed. + bool DeleteEntry(const std::string& uuid); + + // Gets the blob entry for the given uuid. Returns nullptr if the entry + // does not exist. + Entry* GetEntry(const std::string& uuid); + + // Creates a url mapping from blob uuid to the given url. Returns false if + // the uuid isn't mapped to an entry or if there already is a map for the URL. + bool CreateUrlMapping(const GURL& url, const std::string& uuid); + + // Removes the given URL mapping. Optionally populates a uuid string of the + // removed entry uuid. Returns false if the url isn't mapped. + bool DeleteURLMapping(const GURL& url, std::string* uuid); + + // Returns if the url is mapped to a blob uuid. + bool IsURLMapped(const GURL& blob_url) const; + + // Returns the entry from the given url, and optionally populates the uuid for + // that entry. Returns a nullptr if the mapping or entry doesn't exist. + Entry* GetEntryFromURL(const GURL& url, std::string* uuid); + + size_t blob_count() const { return blob_map_.size(); } + size_t url_count() const { return url_to_uuid_.size(); } + + private: + using BlobMap = base::ScopedPtrHashMap<std::string, scoped_ptr<Entry>>; + using URLMap = std::map<GURL, std::string>; + + BlobMap blob_map_; + URLMap url_to_uuid_; + + DISALLOW_COPY_AND_ASSIGN(BlobStorageRegistry); +}; + +} // namespace storage +#endif // STORAGE_BROWSER_BLOB_BLOB_STORAGE_REGISTRY_H_ diff --git a/storage/browser/blob/internal_blob_data.h b/storage/browser/blob/internal_blob_data.h index aa47101..7ec2bf8 100644 --- a/storage/browser/blob/internal_blob_data.h +++ b/storage/browser/blob/internal_blob_data.h @@ -23,6 +23,7 @@ class InternalBlobData { protected: friend class BlobStorageContext; + friend class BlobStorageRegistry; friend class ViewBlobInternalsJob; // Removes the given blob uuid from the internal ShareableBlobDataItems. diff --git a/storage/storage_browser.gyp b/storage/storage_browser.gyp index de1d166..3f4b7ea 100644 --- a/storage/storage_browser.gyp +++ b/storage/storage_browser.gyp @@ -37,6 +37,8 @@ 'browser/blob/blob_reader.h', 'browser/blob/blob_storage_context.cc', 'browser/blob/blob_storage_context.h', + 'browser/blob/blob_storage_registry.cc', + 'browser/blob/blob_storage_registry.h', 'browser/blob/blob_url_request_job.cc', 'browser/blob/blob_url_request_job.h', 'browser/blob/blob_url_request_job_factory.cc', |