| Index: storage/browser/blob/blob_storage_context.h | 
| diff --git a/storage/browser/blob/blob_storage_context.h b/storage/browser/blob/blob_storage_context.h | 
| index 8553d0266d2d8b6338a176f4e9d9ce9d7675fa85..79339eec0aade31b667d7740c8ac8d4bff24b26b 100644 | 
| --- a/storage/browser/blob/blob_storage_context.h | 
| +++ b/storage/browser/blob/blob_storage_context.h | 
| @@ -18,7 +18,9 @@ | 
| #include "base/macros.h" | 
| #include "base/memory/ref_counted.h" | 
| #include "base/memory/weak_ptr.h" | 
| +#include "base/single_thread_task_runner.h" | 
| #include "storage/browser/blob/blob_data_handle.h" | 
| +#include "storage/browser/blob/blob_memory_controller.h" | 
| #include "storage/browser/blob/blob_storage_registry.h" | 
| #include "storage/browser/blob/internal_blob_data.h" | 
| #include "storage/browser/storage_browser_export.h" | 
| @@ -75,14 +77,54 @@ class STORAGE_EXPORT BlobStorageContext | 
| bool RegisterPublicBlobURL(const GURL& url, const std::string& uuid); | 
| void RevokePublicBlobURL(const GURL& url); | 
|  | 
| -  size_t memory_usage() const { return memory_usage_; } | 
| size_t blob_count() const { return registry_.blob_count(); } | 
| -  size_t memory_available() const { | 
| -    return kBlobStorageMaxMemoryUsage - memory_usage_; | 
| -  } | 
|  | 
| const BlobStorageRegistry& registry() { return registry_; } | 
|  | 
| +  void EnableDisk(const base::FilePath storage_directory, | 
| +                  scoped_refptr<base::SingleThreadTaskRunner> file_runner); | 
| + | 
| +  std::unique_ptr<BlobDataHandle> BuildBrokenBlob( | 
| +      const std::string& uuid, | 
| +      const std::string& content_type, | 
| +      const std::string& content_disposition, | 
| +      IPCBlobCreationCancelCode reason); | 
| + | 
| +  // If the handle is not broken, then we will call |can_populate_memory| when | 
| +  // we're ready for the user data to be populated. This can happen | 
| +  // synchronously | 
| +  // or asynchronously. | 
| +  // If the handle is broken, then the possible error cases are: | 
| +  // * OUT_OF_MEMORY if we don't have enough memory to store the blob, | 
| +  // * REFERENCED_BLOB_BROKEN if a referenced blob is broken or we're | 
| +  //   referencing ourself. | 
| +  std::unique_ptr<BlobDataHandle> BuildBlob( | 
| +      const BlobDataBuilder& content, | 
| +      const base::Callback<void(bool, IPCBlobCreationCancelCode)>& | 
| +          can_populate_memory); | 
| + | 
| +  void BreakAndFinishBlob(const std::string& uuid, | 
| +                          IPCBlobCreationCancelCode code); | 
| + | 
| +  // This notifies the construction system that the unpopulated data in the | 
| +  // given blob has been populated. | 
| +  void FinishedPopulatingBlob(const std::string& uuid); | 
| + | 
| + protected: | 
| +  friend struct BlobSlice; | 
| +  friend struct BlobFlattener; | 
| + | 
| +  friend class content::BlobDispatcherHostTest; | 
| + | 
| +  // Not thread safe. | 
| +  static uint64_t GetAndIncrementItemId(); | 
| + | 
| +  BlobMemoryController* mutable_memory_controller() { | 
| +    return &memory_controller_; | 
| +  } | 
| + | 
| +  const BlobMemoryController& memory_controller() { return memory_controller_; } | 
| + | 
| private: | 
| using BlobRegistryEntry = BlobStorageRegistry::Entry; | 
| using BlobConstructedCallback = BlobStorageRegistry::BlobConstructedCallback; | 
| @@ -102,18 +144,20 @@ class STORAGE_EXPORT BlobStorageContext | 
| TestUnknownBrokenAndBuildingBlobReference); | 
| friend class ViewBlobInternalsJob; | 
|  | 
| -  // CompletePendingBlob or CancelPendingBlob should be called after this. | 
| -  void CreatePendingBlob(const std::string& uuid, | 
| -                         const std::string& content_type, | 
| -                         const std::string& content_disposition); | 
| +  std::unique_ptr<BlobDataHandle> CreateHandle(const std::string& uuid, | 
| +                                               BlobRegistryEntry* entry); | 
| + | 
| +  bool CanFinishBuilding(BlobRegistryEntry* entry); | 
|  | 
| -  // This includes resolving blob references in the builder. This will run the | 
| -  // callbacks given in RunOnConstructionComplete. | 
| -  void CompletePendingBlob(const BlobDataBuilder& external_builder); | 
| +  void FinishBuilding(BlobRegistryEntry* entry); | 
|  | 
| -  // This will run the callbacks given in RunOnConstructionComplete. | 
| -  void CancelPendingBlob(const std::string& uuid, | 
| -                         IPCBlobCreationCancelCode reason); | 
| +  void OnEnoughSizeForBlobData(const std::string& uuid, bool can_fit); | 
| + | 
| +  void OnDependentBlobFinished(const std::string& owning_blob_uuid, | 
| +                               bool construction_success, | 
| +                               IPCBlobCreationCancelCode reason); | 
| + | 
| +  void ClearAndFreeMemory(const std::string& uuid, BlobRegistryEntry* entry); | 
|  | 
| void IncrementBlobRefCount(const std::string& uuid); | 
| void DecrementBlobRefCount(const std::string& uuid); | 
| @@ -123,7 +167,9 @@ class STORAGE_EXPORT BlobStorageContext | 
| // TODO(dmurph): After we make the snapshot method in BlobHandle private, then | 
| // make this DCHECK on the blob not being complete. | 
| std::unique_ptr<BlobDataSnapshot> CreateSnapshot(const std::string& uuid); | 
| +  // TODO(dmurph): Merge the next two methods. | 
| bool IsBroken(const std::string& uuid) const; | 
| +  IPCBlobCreationCancelCode GetBrokenReason(const std::string& uuid) const; | 
| bool IsBeingBuilt(const std::string& uuid) const; | 
| // Runs |done| when construction completes, with true if it was successful, | 
| // and false if there was an error, which is reported in the second argument | 
| @@ -131,37 +177,8 @@ class STORAGE_EXPORT BlobStorageContext | 
| void RunOnConstructionComplete(const std::string& uuid, | 
| const BlobConstructedCallback& done); | 
|  | 
| -  // Appends the given blob item to the blob builder.  The new blob | 
| -  // retains ownership of data_item if applicable, and returns false if there | 
| -  // was an error and pouplates the error_code.  We can either have an error of: | 
| -  // OUT_OF_MEMORY: We are out of memory to store this blob. | 
| -  // REFERENCED_BLOB_BROKEN: One of the referenced blobs is broken. | 
| -  bool AppendAllocatedBlobItem(const std::string& target_blob_uuid, | 
| -                               scoped_refptr<BlobDataItem> data_item, | 
| -                               InternalBlobData::Builder* target_blob_data, | 
| -                               IPCBlobCreationCancelCode* error_code); | 
| - | 
| -  // Allocates a shareable blob data item, with blob references resolved.  If | 
| -  // there isn't enough memory, then a nullptr is returned. | 
| -  scoped_refptr<ShareableBlobDataItem> AllocateShareableBlobDataItem( | 
| -      const std::string& target_blob_uuid, | 
| -      scoped_refptr<BlobDataItem> data_item); | 
| - | 
| -  // Deconstructs the blob and appends it's contents to the target blob.  Items | 
| -  // are shared if possible, and copied if the given offset and length | 
| -  // have to split an item. | 
| -  bool AppendBlob(const std::string& target_blob_uuid, | 
| -                  const InternalBlobData& blob, | 
| -                  uint64_t offset, | 
| -                  uint64_t length, | 
| -                  InternalBlobData::Builder* target_blob_data); | 
| - | 
| BlobStorageRegistry registry_; | 
| - | 
| -  // Used to keep track of how much memory is being utilized for blob data, | 
| -  // we count only the items of TYPE_DATA which are held in memory and not | 
| -  // items of TYPE_FILE. | 
| -  size_t memory_usage_; | 
| +  BlobMemoryController memory_controller_; | 
|  | 
| DISALLOW_COPY_AND_ASSIGN(BlobStorageContext); | 
| }; | 
|  |