Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Unified Diff: ios/chrome/browser/net/image_fetcher.mm

Issue 787903003: Upstream image_fetcher::ImageFetcher (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@436897
Patch Set: Fix compilation with Xcode 5.1 by adding ugly casts Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ios/chrome/browser/net/image_fetcher.mm
diff --git a/ios/chrome/browser/net/image_fetcher.mm b/ios/chrome/browser/net/image_fetcher.mm
new file mode 100644
index 0000000000000000000000000000000000000000..e40dcdf69e1a6a982f9197ce34b6366ccaa63d32
--- /dev/null
+++ b/ios/chrome/browser/net/image_fetcher.mm
@@ -0,0 +1,176 @@
+// Copyright 2012 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.
+
+#import "ios/chrome/browser/net/image_fetcher.h"
+
+#import <Foundation/Foundation.h>
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/mac/scoped_block.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/task_runner_util.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "ios/web/public/webp_decoder.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_fetcher.h"
+#include "url/gurl.h"
+
+namespace {
+
+class WebpDecoderDelegate : public web::WebpDecoder::Delegate {
+ public:
+ NSData* data() const { return decoded_image_; }
+
+ // WebpDecoder::Delegate methods
+ void OnFinishedDecoding(bool success) override {
+ if (!success)
+ decoded_image_.reset();
+ }
+ void SetImageFeatures(
+ size_t total_size,
+ web::WebpDecoder::DecodedImageFormat format) override {
+ decoded_image_.reset([[NSMutableData alloc] initWithCapacity:total_size]);
+ }
+ void OnDataDecoded(NSData* data) override {
+ DCHECK(decoded_image_);
+ [decoded_image_ appendData:data];
+ }
+ private:
+ ~WebpDecoderDelegate() override {}
+ base::scoped_nsobject<NSMutableData> decoded_image_;
+};
+
+// Returns a NSData object containing the decoded image.
+// Returns nil in case of failure.
+base::scoped_nsobject<NSData> DecodeWebpImage(
+ const base::scoped_nsobject<NSData>& webp_image) {
+ scoped_refptr<WebpDecoderDelegate> delegate(new WebpDecoderDelegate);
+ scoped_refptr<web::WebpDecoder> decoder(new web::WebpDecoder(delegate.get()));
+ decoder->OnDataReceived(webp_image);
+ DLOG_IF(ERROR, !delegate->data()) << "WebP image decoding failed.";
+ return base::scoped_nsobject<NSData>([delegate->data() retain]);
+}
+
+} // namespace
+
+namespace image_fetcher {
+
+ImageFetcher::ImageFetcher(
+ const scoped_refptr<base::SequencedWorkerPool> decoding_pool)
+ : request_context_getter_(nullptr),
+ weak_factory_(this),
+ decoding_pool_(decoding_pool) {
+ DCHECK(decoding_pool_.get());
+}
+
+ImageFetcher::~ImageFetcher() {
+ // Delete all the entries in the |downloads_in_progress_| map. This will in
+ // turn cancel all of the requests.
+ for (std::map<const net::URLFetcher*, Callback>::iterator it =
+ downloads_in_progress_.begin();
+ it != downloads_in_progress_.end(); ++it) {
+ [it->second release];
+ delete it->first;
+ }
+}
+
+void ImageFetcher::StartDownload(
+ const GURL& url,
+ Callback callback,
+ const std::string& referrer,
+ net::URLRequest::ReferrerPolicy referrer_policy) {
+ DCHECK(request_context_getter_.get());
+ net::URLFetcher* fetcher = net::URLFetcher::Create(url,
+ net::URLFetcher::GET,
+ this);
+ downloads_in_progress_[fetcher] = [callback copy];
+ fetcher->SetLoadFlags(
+ net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES);
Ryan Sleevi 2014/12/12 23:32:01 | net::LOAD_DO_NOT_SEND_AUTH_DATA | net::LOAD_DO_
sdefresne 2014/12/15 13:11:58 Done.
sdefresne 2014/12/15 13:11:58 Done.
+ fetcher->SetRequestContext(request_context_getter_.get());
+ fetcher->SetReferrer(referrer);
+ fetcher->SetReferrerPolicy(referrer_policy);
+ fetcher->Start();
+}
+
+void ImageFetcher::StartDownload(const GURL& url, Callback callback) {
+ ImageFetcher::StartDownload(
+ url, callback, "", net::URLRequest::NEVER_CLEAR_REFERRER);
Ryan Sleevi 2014/12/12 23:32:01 s/""/std::string()/
sdefresne 2014/12/15 13:11:58 Done.
+}
+
+// Delegate callback that is called when URLFetcher completes. If the image
+// was fetched successfully, creates a new NSData and returns it to the
+// callback, otherwise returns nil to the callback.
+void ImageFetcher::OnURLFetchComplete(const net::URLFetcher* fetcher) {
+ if (downloads_in_progress_.find(fetcher) == downloads_in_progress_.end()) {
+ LOG(ERROR) << "Received callback for unknown URLFetcher " << fetcher;
+ return;
+ }
+
+ // Ensures that |fetcher| will be deleted even if we return early.
Ryan Sleevi 2014/12/12 23:32:01 nit: Pronouns in comments considered harmful http
sdefresne 2014/12/15 13:11:58 Done.
sdefresne 2014/12/15 13:11:58 Done.
+ scoped_ptr<const net::URLFetcher> fetcher_deleter(fetcher);
+
+ // Retrieves the callback and ensures that it will be deleted even if we
+ // return early.
Ryan Sleevi 2014/12/12 23:32:00 https://groups.google.com/a/chromium.org/d/topic/c
sdefresne 2014/12/15 13:11:58 Done.
+ base::mac::ScopedBlock<Callback> callback(downloads_in_progress_[fetcher]);
+
+ // Remove |fetcher| from the map.
+ downloads_in_progress_.erase(fetcher);
+
+ // Make sure the request was successful. For "data" requests, the response
+ // code has no meaning, because there is no actual server (data is encoded
+ // directly in the URL). In that case, we set the response code to 200.
Ryan Sleevi 2014/12/12 23:32:01 https://groups.google.com/a/chromium.org/d/topic/c
sdefresne 2014/12/15 13:11:58 Done.
+ const GURL& original_url = fetcher->GetOriginalURL();
+ const int http_response_code = original_url.SchemeIs("data") ?
+ 200 : fetcher->GetResponseCode();
+ if (http_response_code != 200) {
+ (callback.get())(original_url, http_response_code, nil);
+ return;
+ }
+
+ std::string response;
+ if (!fetcher->GetResponseAsString(&response)) {
+ (callback.get())(original_url, http_response_code, nil);
+ return;
+ }
+
+ // Create a NSData from the returned data and notify the callback.
+ base::scoped_nsobject<NSData> data([[NSData alloc]
+ initWithBytes:reinterpret_cast<const unsigned char*>(response.data())
+ length:response.size()]);
+
+ if (fetcher->GetResponseHeaders()) {
+ std::string mime_type;
+ fetcher->GetResponseHeaders()->GetMimeType(&mime_type);
+ if (mime_type == "image/webp") {
Ryan Sleevi 2014/12/12 23:32:01 Should the constant be a static const char[] kCons
sdefresne 2014/12/15 13:11:58 Done.
+ base::PostTaskAndReplyWithResult(decoding_pool_.get(),
+ FROM_HERE,
+ base::Bind(&DecodeWebpImage, data),
+ base::Bind(&ImageFetcher::RunCallback,
+ weak_factory_.GetWeakPtr(),
+ callback,
+ original_url,
+ http_response_code));
+ return;
+ }
+ }
+ (callback.get())(original_url, http_response_code, data);
Ryan Sleevi 2014/12/12 23:32:01 My gut instinct is a little nervous here about avo
+}
+
+void ImageFetcher::RunCallback(const base::mac::ScopedBlock<Callback>& callback,
+ const GURL& url,
+ int http_response_code,
+ NSData* data) {
+ (callback.get())(url, http_response_code, data);
+}
+
+void ImageFetcher::SetRequestContextGetter(
+ net::URLRequestContextGetter* request_context_getter) {
+ request_context_getter_ = request_context_getter;
+}
+
+} // namespace image_fetcher

Powered by Google App Engine
This is Rietveld 408576698