// Copyright 2014 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 "third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.h"

#include <algorithm>
#include <memory>
#include <utility>
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader_client.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/inspected_frames.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/network/http_header_map.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"

using blink::protocol::Array;
// Renaming Cache since there is another blink::Cache.
using ProtocolCache = blink::protocol::CacheStorage::Cache;
using blink::protocol::CacheStorage::Cache;
using blink::protocol::CacheStorage::CachedResponse;
using blink::protocol::CacheStorage::CachedResponseType;
using blink::protocol::CacheStorage::DataEntry;
using blink::protocol::CacheStorage::Header;
// Renaming Response since there is another blink::Response.
using ProtocolResponse = blink::protocol::Response;

using DeleteCacheCallback =
    blink::protocol::CacheStorage::Backend::DeleteCacheCallback;
using DeleteEntryCallback =
    blink::protocol::CacheStorage::Backend::DeleteEntryCallback;
using RequestCacheNamesCallback =
    blink::protocol::CacheStorage::Backend::RequestCacheNamesCallback;
using RequestEntriesCallback =
    blink::protocol::CacheStorage::Backend::RequestEntriesCallback;
using RequestCachedResponseCallback =
    blink::protocol::CacheStorage::Backend::RequestCachedResponseCallback;

namespace blink {

namespace {

String BuildCacheId(const String& security_origin, const String& cache_name) {
  String id(security_origin);
  id.append('|');
  id.append(cache_name);
  return id;
}

ProtocolResponse ParseCacheId(const String& id,
                              String* security_origin,
                              String* cache_name) {
  wtf_size_t pipe = id.find('|');
  if (pipe == WTF::kNotFound)
    return ProtocolResponse::Error("Invalid cache id.");
  *security_origin = id.Substring(0, pipe);
  *cache_name = id.Substring(pipe + 1);
  return ProtocolResponse::OK();
}

ProtocolResponse GetExecutionContext(InspectedFrames* frames,
                                     const String& security_origin,
                                     ExecutionContext** context) {
  LocalFrame* frame = frames->FrameWithSecurityOrigin(security_origin);
  if (!frame)
    return ProtocolResponse::Error("No frame with origin " + security_origin);

  blink::Document* document = frame->GetDocument();
  if (!document)
    return ProtocolResponse::Error("No execution context found");

  *context = document;

  return ProtocolResponse::OK();
}

ProtocolResponse AssertCacheStorage(
    const String& security_origin,
    InspectedFrames* frames,
    InspectorCacheStorageAgent::CachesMap* caches,
    mojom::blink::CacheStorage** result) {
  scoped_refptr<const SecurityOrigin> sec_origin =
      SecurityOrigin::CreateFromString(security_origin);

  // Cache Storage API is restricted to trustworthy origins.
  if (!sec_origin->IsPotentiallyTrustworthy()) {
    return ProtocolResponse::Error(
        sec_origin->IsPotentiallyTrustworthyErrorMessage());
  }

  ExecutionContext* context = nullptr;
  ProtocolResponse response =
      GetExecutionContext(frames, security_origin, &context);
  if (!response.isSuccess())
    return response;

  auto it = caches->find(security_origin);

  if (it == caches->end()) {
    mojom::blink::CacheStoragePtr cache_storage_ptr;
    context->GetInterfaceProvider()->GetInterface(
        mojo::MakeRequest(&cache_storage_ptr));
    *result = cache_storage_ptr.get();
    caches->Set(security_origin, std::move(cache_storage_ptr));
  } else {
    *result = it->value.get();
  }

  return ProtocolResponse::OK();
}

ProtocolResponse AssertCacheStorageAndNameForId(
    const String& cache_id,
    InspectedFrames* frames,
    String* cache_name,
    InspectorCacheStorageAgent::CachesMap* caches,
    mojom::blink::CacheStorage** result) {
  String security_origin;
  ProtocolResponse response =
      ParseCacheId(cache_id, &security_origin, cache_name);
  if (!response.isSuccess())
    return response;
  return AssertCacheStorage(security_origin, frames, caches, result);
}

CString CacheStorageErrorString(mojom::blink::CacheStorageError error) {
  switch (error) {
    case mojom::blink::CacheStorageError::kErrorNotImplemented:
      return CString("not implemented.");
    case mojom::blink::CacheStorageError::kErrorNotFound:
      return CString("not found.");
    case mojom::blink::CacheStorageError::kErrorExists:
      return CString("cache already exists.");
    case mojom::blink::CacheStorageError::kErrorQuotaExceeded:
      return CString("quota exceeded.");
    case mojom::blink::CacheStorageError::kErrorCacheNameNotFound:
      return CString("cache not found.");
    case mojom::blink::CacheStorageError::kErrorQueryTooLarge:
      return CString("operation too large.");
    case mojom::blink::CacheStorageError::kErrorStorage:
      return CString("storage failure.");
    case mojom::blink::CacheStorageError::kErrorDuplicateOperation:
      return CString("duplicate operation.");
    case mojom::blink::CacheStorageError::kSuccess:
      // This function should only be called upon error.
      break;
  }
  NOTREACHED();
  return "";
}

CachedResponseType ResponseTypeToString(
    network::mojom::FetchResponseType type) {
  switch (type) {
    case network::mojom::FetchResponseType::kBasic:
      return protocol::CacheStorage::CachedResponseTypeEnum::Basic;
    case network::mojom::FetchResponseType::kCors:
      return protocol::CacheStorage::CachedResponseTypeEnum::Cors;
    case network::mojom::FetchResponseType::kDefault:
      return protocol::CacheStorage::CachedResponseTypeEnum::Default;
    case network::mojom::FetchResponseType::kError:
      return protocol::CacheStorage::CachedResponseTypeEnum::Error;
    case network::mojom::FetchResponseType::kOpaque:
      return protocol::CacheStorage::CachedResponseTypeEnum::OpaqueResponse;
    case network::mojom::FetchResponseType::kOpaqueRedirect:
      return protocol::CacheStorage::CachedResponseTypeEnum::OpaqueRedirect;
  }
  NOTREACHED();
  return "";
}

struct DataRequestParams {
  String cache_name;
  int skip_count;
  int page_size;
  String path_filter;
};

struct RequestResponse {
  String request_url;
  String request_method;
  HTTPHeaderMap request_headers;
  int response_status;
  String response_status_text;
  double response_time;
  network::mojom::FetchResponseType response_type;
  HTTPHeaderMap response_headers;
};

class ResponsesAccumulator : public RefCounted<ResponsesAccumulator> {
 public:
  ResponsesAccumulator(wtf_size_t num_responses,
                       const DataRequestParams& params,
                       mojom::blink::CacheStorageCacheAssociatedPtr cache_ptr,
                       std::unique_ptr<RequestEntriesCallback> callback)
      : params_(params),
        num_responses_left_(num_responses),
        cache_ptr_(std::move(cache_ptr)),
        callback_(std::move(callback)) {}

  void Dispatch(Vector<mojom::blink::FetchAPIRequestPtr> old_requests) {
    Vector<mojom::blink::FetchAPIRequestPtr> requests;
    if (params_.path_filter.IsEmpty()) {
      requests = std::move(old_requests);
    } else {
      for (auto& request : old_requests) {
        String urlPath(request->url.GetPath());
        if (!urlPath.Contains(params_.path_filter,
                              WTF::kTextCaseUnicodeInsensitive))
          continue;
        requests.push_back(std::move(request));
      }
    }
    wtf_size_t requestSize = requests.size();
    if (!requestSize) {
      callback_->sendSuccess(Array<DataEntry>::create(), false);
      return;
    }

    responses_ = Vector<RequestResponse>(requestSize);
    num_responses_left_ = requestSize;
    for (auto& request : requests) {
      // All FetchAPIRequests in cache_storage code are supposed to not contain
      // a body.
      DCHECK(!request->blob && !request->body);
      auto request_clone_without_body = mojom::blink::FetchAPIRequest::New(
          request->mode, request->is_main_resource_load,
          request->request_context_type, request->frame_type, request->url,
          request->method, request->headers, nullptr /* blob */,
          nullptr /* body */, request->referrer.Clone(),
          request->credentials_mode, request->cache_mode,
          request->redirect_mode, request->integrity, request->priority,
          request->fetch_window_id, request->keepalive, request->client_id,
          request->is_reload, request->is_history_navigation);
      cache_ptr_->Match(std::move(request), mojom::blink::QueryParams::New(),
                        WTF::Bind(
                            [](scoped_refptr<ResponsesAccumulator> accumulator,
                               mojom::blink::FetchAPIRequestPtr request,
                               mojom::blink::MatchResultPtr result) {
                              if (result->is_status()) {
                                accumulator->SendFailure(result->get_status());
                              } else {
                                accumulator->AddRequestResponsePair(
                                    request, result->get_response());
                              }
                            },
                            scoped_refptr<ResponsesAccumulator>(this),
                            std::move(request_clone_without_body)));
    }
  }

  void AddRequestResponsePair(
      const mojom::blink::FetchAPIRequestPtr& request,
      const mojom::blink::FetchAPIResponsePtr& response) {
    DCHECK_GT(num_responses_left_, 0);
    RequestResponse& request_response =
        responses_.at(responses_.size() - num_responses_left_);

    request_response.request_url = request->url.GetString();
    request_response.request_method = request->method;
    for (const auto& header : request->headers) {
      request_response.request_headers.Set(AtomicString(header.key),
                                           AtomicString(header.value));
    }

    request_response.response_status = response->status_code;
    request_response.response_status_text = response->status_text;
    request_response.response_time = response->response_time.ToDoubleT();
    request_response.response_type = response->response_type;
    for (const auto& header : response->headers) {
      request_response.response_headers.Set(AtomicString(header.key),
                                            AtomicString(header.value));
    }

    if (--num_responses_left_ != 0)
      return;

    std::sort(responses_.begin(), responses_.end(),
              [](const RequestResponse& a, const RequestResponse& b) {
                return WTF::CodePointCompareLessThan(a.request_url,
                                                     b.request_url);
              });
    if (params_.skip_count > 0)
      responses_.EraseAt(0, params_.skip_count);
    bool has_more = false;
    if (static_cast<size_t>(params_.page_size) < responses_.size()) {
      responses_.EraseAt(params_.page_size,
                         responses_.size() - params_.page_size);
      has_more = true;
    }
    std::unique_ptr<Array<DataEntry>> array = Array<DataEntry>::create();
    for (const auto& request_response : responses_) {
      std::unique_ptr<DataEntry> entry =
          DataEntry::create()
              .setRequestURL(request_response.request_url)
              .setRequestMethod(request_response.request_method)
              .setRequestHeaders(
                  SerializeHeaders(request_response.request_headers))
              .setResponseStatus(request_response.response_status)
              .setResponseStatusText(request_response.response_status_text)
              .setResponseTime(request_response.response_time)
              .setResponseType(
                  ResponseTypeToString(request_response.response_type))
              .setResponseHeaders(
                  SerializeHeaders(request_response.response_headers))
              .build();
      array->addItem(std::move(entry));
    }
    callback_->sendSuccess(std::move(array), has_more);
  }

  void SendFailure(const mojom::blink::CacheStorageError& error) {
    callback_->sendFailure(ProtocolResponse::Error(
        String::Format("Error requesting responses for cache %s : %s",
                       params_.cache_name.Utf8().data(),
                       CacheStorageErrorString(error).data())));
  }

  std::unique_ptr<Array<Header>> SerializeHeaders(
      const HTTPHeaderMap& headers) {
    std::unique_ptr<Array<Header>> result = Array<Header>::create();
    for (HTTPHeaderMap::const_iterator it = headers.begin(),
                                       end = headers.end();
         it != end; ++it) {
      result->addItem(
          Header::create().setName(it->key).setValue(it->value).build());
    }
    return result;
  }

 private:
  DataRequestParams params_;
  int num_responses_left_;
  Vector<RequestResponse> responses_;
  mojom::blink::CacheStorageCacheAssociatedPtr cache_ptr_;
  std::unique_ptr<RequestEntriesCallback> callback_;

  DISALLOW_COPY_AND_ASSIGN(ResponsesAccumulator);
};

class GetCacheKeysForRequestData {
 public:
  GetCacheKeysForRequestData(
      const DataRequestParams& params,
      mojom::blink::CacheStorageCacheAssociatedPtrInfo cache_ptr_info,
      std::unique_ptr<RequestEntriesCallback> callback)
      : params_(params), callback_(std::move(callback)) {
    cache_ptr_.Bind(std::move(cache_ptr_info));
  }

  void Dispatch(std::unique_ptr<GetCacheKeysForRequestData> self) {
    cache_ptr_->Keys(
        nullptr /* request */, mojom::blink::QueryParams::New(),
        WTF::Bind(
            [](DataRequestParams params,
               std::unique_ptr<GetCacheKeysForRequestData> self,
               mojom::blink::CacheKeysResultPtr result) {
              if (result->is_status()) {
                self->callback_->sendFailure(
                    ProtocolResponse::Error(String::Format(
                        "Error requesting requests for cache %s: %s",
                        params.cache_name.Utf8().data(),
                        CacheStorageErrorString(result->get_status()).data())));
              } else {
                if (result->get_keys().IsEmpty()) {
                  std::unique_ptr<Array<DataEntry>> array =
                      Array<DataEntry>::create();
                  self->callback_->sendSuccess(std::move(array), false);
                  return;
                }
                scoped_refptr<ResponsesAccumulator> accumulator =
                    base::AdoptRef(new ResponsesAccumulator(
                        result->get_keys().size(), params,
                        std::move(self->cache_ptr_),
                        std::move(self->callback_)));
                accumulator->Dispatch(std::move(result->get_keys()));
              }
            },
            params_, std::move(self)));
  }

 private:
  DataRequestParams params_;
  mojom::blink::CacheStorageCacheAssociatedPtr cache_ptr_;
  std::unique_ptr<RequestEntriesCallback> callback_;

  DISALLOW_COPY_AND_ASSIGN(GetCacheKeysForRequestData);
};

class CachedResponseFileReaderLoaderClient final
    : private FileReaderLoaderClient {
 public:
  static void Load(scoped_refptr<BlobDataHandle> blob,
                   std::unique_ptr<RequestCachedResponseCallback> callback) {
    new CachedResponseFileReaderLoaderClient(std::move(blob),
                                             std::move(callback));
  }

  void DidStartLoading() override {}

  void DidFinishLoading() override {
    std::unique_ptr<CachedResponse> response =
        CachedResponse::create()
            .setBody(protocol::Binary::fromSharedBuffer(data_))
            .build();
    callback_->sendSuccess(std::move(response));
    dispose();
  }

  void DidFail(FileErrorCode error) override {
    callback_->sendFailure(ProtocolResponse::Error(String::Format(
        "Unable to read the cached response, error code: %d", error)));
    dispose();
  }

  void DidReceiveDataForClient(const char* data,
                               unsigned data_length) override {
    data_->Append(data, data_length);
  }

 private:
  CachedResponseFileReaderLoaderClient(
      scoped_refptr<BlobDataHandle>&& blob,
      std::unique_ptr<RequestCachedResponseCallback>&& callback)
      : loader_(
            FileReaderLoader::Create(FileReaderLoader::kReadByClient, this)),
        callback_(std::move(callback)),
        data_(SharedBuffer::Create()) {
    loader_->Start(std::move(blob));
  }

  ~CachedResponseFileReaderLoaderClient() override = default;

  void dispose() { delete this; }

  std::unique_ptr<FileReaderLoader> loader_;
  std::unique_ptr<RequestCachedResponseCallback> callback_;
  scoped_refptr<SharedBuffer> data_;

  DISALLOW_COPY_AND_ASSIGN(CachedResponseFileReaderLoaderClient);
};

}  // namespace

InspectorCacheStorageAgent::InspectorCacheStorageAgent(InspectedFrames* frames)
    : frames_(frames) {}

InspectorCacheStorageAgent::~InspectorCacheStorageAgent() = default;

void InspectorCacheStorageAgent::Trace(blink::Visitor* visitor) {
  visitor->Trace(frames_);
  InspectorBaseAgent::Trace(visitor);
}

void InspectorCacheStorageAgent::requestCacheNames(
    const String& security_origin,
    std::unique_ptr<RequestCacheNamesCallback> callback) {
  scoped_refptr<const SecurityOrigin> sec_origin =
      SecurityOrigin::CreateFromString(security_origin);

  // Cache Storage API is restricted to trustworthy origins.
  if (!sec_origin->IsPotentiallyTrustworthy()) {
    // Don't treat this as an error, just don't attempt to open and enumerate
    // the caches.
    callback->sendSuccess(Array<ProtocolCache>::create());
    return;
  }

  mojom::blink::CacheStorage* cache_storage = nullptr;

  ProtocolResponse response =
      AssertCacheStorage(security_origin, frames_, &caches_, &cache_storage);
  if (!response.isSuccess()) {
    callback->sendFailure(response);
    return;
  }

  cache_storage->Keys(WTF::Bind(
      [](String security_origin,
         std::unique_ptr<RequestCacheNamesCallback> callback,
         const Vector<String>& caches) {
        std::unique_ptr<Array<ProtocolCache>> array =
            Array<ProtocolCache>::create();
        for (auto& cache : caches) {
          array->addItem(ProtocolCache::create()
                             .setSecurityOrigin(security_origin)
                             .setCacheName(cache)
                             .setCacheId(BuildCacheId(security_origin, cache))
                             .build());
        }
        callback->sendSuccess(std::move(array));
      },
      security_origin, std::move(callback)));
}

void InspectorCacheStorageAgent::requestEntries(
    const String& cache_id,
    int skip_count,
    int page_size,
    protocol::Maybe<String> path_filter,
    std::unique_ptr<RequestEntriesCallback> callback) {
  String cache_name;
  mojom::blink::CacheStorage* cache_storage = nullptr;
  ProtocolResponse response = AssertCacheStorageAndNameForId(
      cache_id, frames_, &cache_name, &caches_, &cache_storage);
  if (!response.isSuccess()) {
    callback->sendFailure(response);
    return;
  }
  DataRequestParams params;
  params.cache_name = cache_name;
  params.page_size = page_size;
  params.skip_count = skip_count;
  params.path_filter = path_filter.fromMaybe("");

  cache_storage->Open(
      cache_name,
      WTF::Bind(
          [](DataRequestParams params,
             std::unique_ptr<RequestEntriesCallback> callback,
             mojom::blink::OpenResultPtr result) {
            if (result->is_status()) {
              callback->sendFailure(ProtocolResponse::Error(String::Format(
                  "Error requesting cache %s: %s",
                  params.cache_name.Utf8().data(),
                  CacheStorageErrorString(result->get_status()).data())));
            } else {
              auto request = std::make_unique<GetCacheKeysForRequestData>(
                  params, std::move(result->get_cache()), std::move(callback));
              auto* request_ptr = request.get();
              request_ptr->Dispatch(std::move(request));
            }
          },
          params, std::move(callback)));
}

void InspectorCacheStorageAgent::deleteCache(
    const String& cache_id,
    std::unique_ptr<DeleteCacheCallback> callback) {
  String cache_name;
  mojom::blink::CacheStorage* cache_storage = nullptr;
  ProtocolResponse response = AssertCacheStorageAndNameForId(
      cache_id, frames_, &cache_name, &caches_, &cache_storage);
  if (!response.isSuccess()) {
    callback->sendFailure(response);
    return;
  }
  cache_storage->Delete(
      cache_name,
      WTF::Bind(
          [](std::unique_ptr<DeleteCacheCallback> callback,
             mojom::blink::CacheStorageError error) {
            if (error == mojom::blink::CacheStorageError::kSuccess) {
              callback->sendSuccess();
            } else {
              callback->sendFailure(ProtocolResponse::Error(
                  String::Format("Error requesting cache names: %s",
                                 CacheStorageErrorString(error).data())));
            }
          },
          std::move(callback)));
}

void InspectorCacheStorageAgent::deleteEntry(
    const String& cache_id,
    const String& request,
    std::unique_ptr<DeleteEntryCallback> callback) {
  String cache_name;
  mojom::blink::CacheStorage* cache_storage = nullptr;
  ProtocolResponse response = AssertCacheStorageAndNameForId(
      cache_id, frames_, &cache_name, &caches_, &cache_storage);
  if (!response.isSuccess()) {
    callback->sendFailure(response);
    return;
  }
  cache_storage->Open(
      cache_name,
      WTF::Bind(
          [](String cache_name, String request,
             std::unique_ptr<DeleteEntryCallback> callback,
             mojom::blink::OpenResultPtr result) {
            if (result->is_status()) {
              callback->sendFailure(ProtocolResponse::Error(String::Format(
                  "Error requesting cache %s: %s", cache_name.Utf8().data(),
                  CacheStorageErrorString(result->get_status()).data())));
            } else {
              Vector<mojom::blink::BatchOperationPtr> batch_operations;
              batch_operations.push_back(mojom::blink::BatchOperation::New());
              auto& operation = batch_operations.back();
              operation->operation_type = mojom::blink::OperationType::kDelete;
              operation->request = mojom::blink::FetchAPIRequest::New();
              operation->request->url = KURL(request);
              operation->request->method = String("GET");

              mojom::blink::CacheStorageCacheAssociatedPtr cache_ptr;
              cache_ptr.Bind(std::move(result->get_cache()));
              auto* cache = cache_ptr.get();
              cache->Batch(
                  std::move(batch_operations), true /* fail_on_duplicates */,
                  WTF::Bind(
                      [](mojom::blink::CacheStorageCacheAssociatedPtr cache_ptr,
                         std::unique_ptr<DeleteEntryCallback> callback,
                         mojom::blink::CacheStorageVerboseErrorPtr error) {
                        if (error->value !=
                            mojom::blink::CacheStorageError::kSuccess) {
                          callback->sendFailure(
                              ProtocolResponse::Error(String::Format(
                                  "Error deleting cache entry: %s",
                                  CacheStorageErrorString(error->value)
                                      .data())));
                        } else {
                          callback->sendSuccess();
                        }
                      },
                      std::move(cache_ptr), std::move(callback)));
            }
          },
          cache_name, request, std::move(callback)));
}

void InspectorCacheStorageAgent::requestCachedResponse(
    const String& cache_id,
    const String& request_url,
    std::unique_ptr<RequestCachedResponseCallback> callback) {
  String cache_name;
  mojom::blink::CacheStorage* cache_storage = nullptr;
  ProtocolResponse response = AssertCacheStorageAndNameForId(
      cache_id, frames_, &cache_name, &caches_, &cache_storage);
  if (!response.isSuccess()) {
    callback->sendFailure(response);
    return;
  }
  auto request = mojom::blink::FetchAPIRequest::New();
  request->url = KURL(request_url);
  request->method = String("GET");
  cache_storage->Match(
      std::move(request), mojom::blink::QueryParams::New(),
      WTF::Bind(
          [](std::unique_ptr<RequestCachedResponseCallback> callback,
             mojom::blink::MatchResultPtr result) {
            if (result->is_status()) {
              callback->sendFailure(ProtocolResponse::Error(String::Format(
                  "Unable to read cached response: %s",
                  CacheStorageErrorString(result->get_status()).data())));
            } else {
              std::unique_ptr<protocol::DictionaryValue> headers =
                  protocol::DictionaryValue::create();
              if (!result->get_response()->blob) {
                callback->sendSuccess(CachedResponse::create()
                                          .setBody(protocol::Binary())
                                          .build());
                return;
              }
              CachedResponseFileReaderLoaderClient::Load(
                  std::move(result->get_response()->blob), std::move(callback));
            }
          },
          std::move(callback)));
}
}  // namespace blink
