blob: 5211094b61a2bba35c6085525f865e4c2c27d96d [file] [log] [blame]
// 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 <stddef.h>
#include <map>
#include <memory>
#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"
#include "storage/common/blob_storage/blob_storage_constants.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 {
// True means the blob was constructed successfully, and false means that
// there was an error, which is reported in the second argument.
using BlobConstructedCallback =
base::Callback<void(bool, IPCBlobCreationCancelCode)>;
enum class BlobState {
// The blob is pending transportation from the renderer. This is the default
// state on entry construction.
// The blob is complete and can be read from.
// The blob is broken and no longer holds data. This happens when there was
// a problem constructing the blob, or we've run out of memory.
struct STORAGE_EXPORT Entry {
size_t refcount;
BlobState state;
std::vector<BlobConstructedCallback> build_completion_callbacks;
// Only applicable if the state == BROKEN.
IPCBlobCreationCancelCode broken_reason =
// data and data_builder are mutually exclusive.
std::unique_ptr<InternalBlobData> data;
std::unique_ptr<InternalBlobData::Builder> data_builder;
std::string content_type;
std::string content_disposition;
Entry() = delete;
Entry(int refcount, BlobState state);
// 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);
// Creates the blob entry with a refcount of 1 and a state of PENDING. If
// the blob is already in use, we return null.
Entry* CreateEntry(const std::string& uuid,
const std::string& content_type,
const std::string& content_disposition);
// 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);
bool HasEntry(const std::string& uuid) const;
// Gets the blob entry for the given uuid. Returns nullptr if the entry
// does not exist.
Entry* GetEntry(const std::string& uuid);
const Entry* GetEntry(const std::string& uuid) const;
// 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(); }
friend class ViewBlobInternalsJob;
using BlobMap = base::ScopedPtrHashMap<std::string, std::unique_ptr<Entry>>;
using URLMap = std::map<GURL, std::string>;
BlobMap blob_map_;
URLMap url_to_uuid_;
} // namespace storage