// Copyright 2013 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 "extensions/browser/blob_reader.h" #include #include #include "base/format_macros.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" BlobReader::BlobReader(content::BrowserContext* browser_context, const std::string& blob_uuid, BlobReadCallback callback) : callback_(callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); GURL blob_url = GURL(std::string("blob:uuid/") + blob_uuid); DCHECK(blob_url.is_valid()); net::NetworkTrafficAnnotationTag traffic_annotation = net::DefineNetworkTrafficAnnotation("blob_reader", R"( semantics { sender: "BlobReader" description: "Blobs are used for a variety of use cases, and are basically " "immutable blocks of data. See https://chromium.googlesource.com/" "chromium/src/+/master/storage/browser/blob/README.md for an " "explanation of blobs and their implementation in Chrome. These " "can be created by scripts in a website, web platform features, or " "internally in the browser." trigger: "Request for reading the contents of a blob." data: "A reference to a Blob, File, or CacheStorage entry created from " "script, a web platform feature, or browser internals." destination: LOCAL } policy { cookies_allowed: NO setting: "This feature cannot be disabled by settings." policy_exception_justification: "Not implemented. This is a local data fetch request and has no " "network activity." })"); fetcher_ = net::URLFetcher::Create(blob_url, net::URLFetcher::GET, this, traffic_annotation); fetcher_->SetRequestContext( content::BrowserContext::GetDefaultStoragePartition(browser_context) ->GetURLRequestContext()); } BlobReader::~BlobReader() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } void BlobReader::SetByteRange(int64_t offset, int64_t length) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); CHECK_GE(offset, 0); CHECK_GT(length, 0); CHECK_LE(offset, std::numeric_limits::max() - length); net::HttpRequestHeaders headers; headers.SetHeader( net::HttpRequestHeaders::kRange, base::StringPrintf("bytes=%" PRId64 "-%" PRId64, offset, offset + length - 1)); fetcher_->SetExtraRequestHeaders(headers.ToString()); } void BlobReader::Start() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); fetcher_->Start(); } // Overridden from net::URLFetcherDelegate. void BlobReader::OnURLFetchComplete(const net::URLFetcher* source) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); std::unique_ptr response(new std::string); int64_t first = 0, last = 0, length = 0; source->GetResponseAsString(response.get()); if (source->GetResponseHeaders()) source->GetResponseHeaders()->GetContentRangeFor206(&first, &last, &length); callback_.Run(std::move(response), length); delete this; }