Commit 83fcfd3f authored by sdefresne's avatar sdefresne Committed by Commit bot

Cleanup image_fetcher::ImageFetcher

Follow-up CL to address comments on https://codereview.chromium.org/787903003
after the CL landed:
- cleanup #includes in image_fetcher.{h,mm}
- use const ref to scoped_refptr to avoid inc/dec ref churn
- prefer base::ThreadTaskRunnerHandle::Get() to MessageLoopProxy::current()
- remove std::string concatenation

BUG=None

Review URL: https://codereview.chromium.org/805713004

Cr-Commit-Position: refs/heads/master@{#308347}
parent f86c0adf
...@@ -7,35 +7,42 @@ ...@@ -7,35 +7,42 @@
#include <map> #include <map>
#include "base/compiler_specific.h" #include "base/mac/scoped_block.h"
#include "base/mac/bind_objc_block.h" #include "base/memory/ref_counted.h"
#include "base/mac/scoped_nsobject.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "net/url_request/url_fetcher_delegate.h" #include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request.h" #include "net/url_request/url_request.h"
#include "net/url_request/url_request_context_getter.h"
#include "url/gurl.h"
class GURL;
@class NSData; @class NSData;
namespace base {
class SequencedWorkerPool;
}
namespace net {
class URLRequestContextGetter;
}
namespace image_fetcher { namespace image_fetcher {
// Callback that informs of the download of an image encoded in |data|, // Callback that informs of the download of an image encoded in |data|,
// downloaded from |url|, and with the http status |http_response_code|. If the // downloaded from |url|, and with the http status |http_response_code|. If the
// url is a data URL, |http_response_code| is always 200. // url is a data URL, |http_response_code| is always 200.
typedef void (^Callback)(const GURL& url, int http_response_code, NSData* data); using ImageFetchedCallback =
void (^)(const GURL& url, int http_response_code, NSData* data);
// Utility class that will retrieve an image from an URL. The image is returned // Utility class that will retrieve an image from an URL. The image is returned
// as NSData which can be used with +[UIImage imageWithData:]. This class // as NSData which can be used with +[UIImage imageWithData:]. This class
// usually returns the raw bytes retrieved from the network without any // usually returns the raw bytes retrieved from the network without any
// processing with the exception of WebP encoded images. Those are decoded and // processing, with the exception of WebP encoded images. Those are decoded and
// then reencoded in a format suitable for UIImage. // then reencoded in a format suitable for UIImage.
// An instance of this class can download a number of images at the same time. // An instance of this class can download a number of images at the same time.
class ImageFetcher : public net::URLFetcherDelegate { class ImageFetcher : public net::URLFetcherDelegate {
public: public:
// The WorkerPool is used to eventually decode the image. // The WorkerPool is used to eventually decode the image.
explicit ImageFetcher( explicit ImageFetcher(
const scoped_refptr<base::SequencedWorkerPool> decoding_pool); const scoped_refptr<base::SequencedWorkerPool>& decoding_pool);
~ImageFetcher() override; ~ImageFetcher() override;
// Start downloading the image at the given |url|. The |callback| will be // Start downloading the image at the given |url|. The |callback| will be
...@@ -45,25 +52,25 @@ class ImageFetcher : public net::URLFetcherDelegate { ...@@ -45,25 +52,25 @@ class ImageFetcher : public net::URLFetcherDelegate {
// This method assumes the request context getter has been set. // This method assumes the request context getter has been set.
// (virtual for testing) // (virtual for testing)
virtual void StartDownload(const GURL& url, virtual void StartDownload(const GURL& url,
Callback callback, ImageFetchedCallback callback,
const std::string& referrer, const std::string& referrer,
net::URLRequest::ReferrerPolicy referrer_policy); net::URLRequest::ReferrerPolicy referrer_policy);
// Helper method to call StartDownload without a referrer. // Helper method to call StartDownload without a referrer.
// (virtual for testing) // (virtual for testing)
virtual void StartDownload(const GURL& url, Callback callback); virtual void StartDownload(const GURL& url, ImageFetchedCallback callback);
// A valid request context getter is required before starting the download. // A valid request context getter is required before starting the download.
// (virtual for testing) // (virtual for testing)
virtual void SetRequestContextGetter( virtual void SetRequestContextGetter(const scoped_refptr<
net::URLRequestContextGetter* request_context_getter); net::URLRequestContextGetter>& request_context_getter);
// content::URLFetcherDelegate methods. // net::URLFetcherDelegate:
void OnURLFetchComplete(const net::URLFetcher* source) override; void OnURLFetchComplete(const net::URLFetcher* source) override;
private: private:
// Runs the callback with the given arguments. // Runs the callback with the given arguments.
void RunCallback(const base::mac::ScopedBlock<Callback>& callback, void RunCallback(const base::mac::ScopedBlock<ImageFetchedCallback>& callback,
const GURL& url, const GURL& url,
const int http_response_code, const int http_response_code,
NSData* data); NSData* data);
...@@ -72,7 +79,7 @@ class ImageFetcher : public net::URLFetcherDelegate { ...@@ -72,7 +79,7 @@ class ImageFetcher : public net::URLFetcherDelegate {
// fetch; the value is the callback to use when the download request // fetch; the value is the callback to use when the download request
// completes. When a download request completes, the URLFetcher must be // completes. When a download request completes, the URLFetcher must be
// deleted and the callback called and released. // deleted and the callback called and released.
std::map<const net::URLFetcher*, Callback> downloads_in_progress_; std::map<const net::URLFetcher*, ImageFetchedCallback> downloads_in_progress_;
scoped_refptr<net::URLRequestContextGetter> request_context_getter_; scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
// The WeakPtrFactory is used to cancel callbacks if ImageFetcher is destroyed // The WeakPtrFactory is used to cancel callbacks if ImageFetcher is destroyed
......
...@@ -7,18 +7,15 @@ ...@@ -7,18 +7,15 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#include "base/bind.h" #include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/location.h" #include "base/location.h"
#include "base/logging.h" #include "base/mac/scoped_nsobject.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 "base/threading/sequenced_worker_pool.h"
#include "ios/web/public/web_thread.h"
#include "ios/web/public/webp_decoder.h" #include "ios/web/public/webp_decoder.h"
#include "net/base/load_flags.h" #include "net/base/load_flags.h"
#include "net/http/http_response_headers.h" #include "net/http/http_response_headers.h"
#include "net/url_request/url_fetcher.h" #include "net/url_request/url_fetcher.h"
#include "url/gurl.h" #include "net/url_request/url_request_context_getter.h"
namespace { namespace {
...@@ -45,6 +42,9 @@ class WebpDecoderDelegate : public web::WebpDecoder::Delegate { ...@@ -45,6 +42,9 @@ class WebpDecoderDelegate : public web::WebpDecoder::Delegate {
base::scoped_nsobject<NSMutableData> decoded_image_; base::scoped_nsobject<NSMutableData> decoded_image_;
}; };
// Content-type header for WebP images.
static const char kWEBPMimeType[] = "image/webp";
// Returns a NSData object containing the decoded image. // Returns a NSData object containing the decoded image.
// Returns nil in case of failure. // Returns nil in case of failure.
base::scoped_nsobject<NSData> DecodeWebpImage( base::scoped_nsobject<NSData> DecodeWebpImage(
...@@ -61,7 +61,7 @@ base::scoped_nsobject<NSData> DecodeWebpImage( ...@@ -61,7 +61,7 @@ base::scoped_nsobject<NSData> DecodeWebpImage(
namespace image_fetcher { namespace image_fetcher {
ImageFetcher::ImageFetcher( ImageFetcher::ImageFetcher(
const scoped_refptr<base::SequencedWorkerPool> decoding_pool) const scoped_refptr<base::SequencedWorkerPool>& decoding_pool)
: request_context_getter_(nullptr), : request_context_getter_(nullptr),
weak_factory_(this), weak_factory_(this),
decoding_pool_(decoding_pool) { decoding_pool_(decoding_pool) {
...@@ -71,17 +71,15 @@ ImageFetcher::ImageFetcher( ...@@ -71,17 +71,15 @@ ImageFetcher::ImageFetcher(
ImageFetcher::~ImageFetcher() { ImageFetcher::~ImageFetcher() {
// Delete all the entries in the |downloads_in_progress_| map. This will in // Delete all the entries in the |downloads_in_progress_| map. This will in
// turn cancel all of the requests. // turn cancel all of the requests.
for (std::map<const net::URLFetcher*, Callback>::iterator it = for (const auto& pair : downloads_in_progress_) {
downloads_in_progress_.begin(); [pair.second release];
it != downloads_in_progress_.end(); ++it) { delete pair.first;
[it->second release];
delete it->first;
} }
} }
void ImageFetcher::StartDownload( void ImageFetcher::StartDownload(
const GURL& url, const GURL& url,
Callback callback, ImageFetchedCallback callback,
const std::string& referrer, const std::string& referrer,
net::URLRequest::ReferrerPolicy referrer_policy) { net::URLRequest::ReferrerPolicy referrer_policy) {
DCHECK(request_context_getter_.get()); DCHECK(request_context_getter_.get());
...@@ -90,16 +88,18 @@ void ImageFetcher::StartDownload( ...@@ -90,16 +88,18 @@ void ImageFetcher::StartDownload(
this); this);
downloads_in_progress_[fetcher] = [callback copy]; downloads_in_progress_[fetcher] = [callback copy];
fetcher->SetLoadFlags( fetcher->SetLoadFlags(
net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_DO_NOT_SEND_AUTH_DATA | net::LOAD_DO_NOT_PROMPT_FOR_LOGIN);
fetcher->SetRequestContext(request_context_getter_.get()); fetcher->SetRequestContext(request_context_getter_.get());
fetcher->SetReferrer(referrer); fetcher->SetReferrer(referrer);
fetcher->SetReferrerPolicy(referrer_policy); fetcher->SetReferrerPolicy(referrer_policy);
fetcher->Start(); fetcher->Start();
} }
void ImageFetcher::StartDownload(const GURL& url, Callback callback) { void ImageFetcher::StartDownload(
const GURL& url, ImageFetchedCallback callback) {
ImageFetcher::StartDownload( ImageFetcher::StartDownload(
url, callback, "", net::URLRequest::NEVER_CLEAR_REFERRER); url, callback, std::string(), net::URLRequest::NEVER_CLEAR_REFERRER);
} }
// Delegate callback that is called when URLFetcher completes. If the image // Delegate callback that is called when URLFetcher completes. If the image
...@@ -111,19 +111,20 @@ void ImageFetcher::OnURLFetchComplete(const net::URLFetcher* fetcher) { ...@@ -111,19 +111,20 @@ void ImageFetcher::OnURLFetchComplete(const net::URLFetcher* fetcher) {
return; return;
} }
// Ensures that |fetcher| will be deleted even if we return early. // Ensures that |fetcher| will be deleted in the event of early return.
scoped_ptr<const net::URLFetcher> fetcher_deleter(fetcher); scoped_ptr<const net::URLFetcher> fetcher_deleter(fetcher);
// Retrieves the callback and ensures that it will be deleted even if we // Retrieves the callback and ensures that it will be deleted in the event
// return early. // of early return.
base::mac::ScopedBlock<Callback> callback(downloads_in_progress_[fetcher]); base::mac::ScopedBlock<ImageFetchedCallback> callback(
downloads_in_progress_[fetcher]);
// Remove |fetcher| from the map. // Remove |fetcher| from the map.
downloads_in_progress_.erase(fetcher); downloads_in_progress_.erase(fetcher);
// Make sure the request was successful. For "data" requests, the response // Make sure the request was successful. For "data" requests, the response
// code has no meaning, because there is no actual server (data is encoded // 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. // directly in the URL). In that case, set the response code to 200 (OK).
const GURL& original_url = fetcher->GetOriginalURL(); const GURL& original_url = fetcher->GetOriginalURL();
const int http_response_code = original_url.SchemeIs("data") ? const int http_response_code = original_url.SchemeIs("data") ?
200 : fetcher->GetResponseCode(); 200 : fetcher->GetResponseCode();
...@@ -146,7 +147,7 @@ void ImageFetcher::OnURLFetchComplete(const net::URLFetcher* fetcher) { ...@@ -146,7 +147,7 @@ void ImageFetcher::OnURLFetchComplete(const net::URLFetcher* fetcher) {
if (fetcher->GetResponseHeaders()) { if (fetcher->GetResponseHeaders()) {
std::string mime_type; std::string mime_type;
fetcher->GetResponseHeaders()->GetMimeType(&mime_type); fetcher->GetResponseHeaders()->GetMimeType(&mime_type);
if (mime_type == "image/webp") { if (mime_type == kWEBPMimeType) {
base::PostTaskAndReplyWithResult(decoding_pool_.get(), base::PostTaskAndReplyWithResult(decoding_pool_.get(),
FROM_HERE, FROM_HERE,
base::Bind(&DecodeWebpImage, data), base::Bind(&DecodeWebpImage, data),
...@@ -161,15 +162,16 @@ void ImageFetcher::OnURLFetchComplete(const net::URLFetcher* fetcher) { ...@@ -161,15 +162,16 @@ void ImageFetcher::OnURLFetchComplete(const net::URLFetcher* fetcher) {
(callback.get())(original_url, http_response_code, data); (callback.get())(original_url, http_response_code, data);
} }
void ImageFetcher::RunCallback(const base::mac::ScopedBlock<Callback>& callback, void ImageFetcher::RunCallback(
const GURL& url, const base::mac::ScopedBlock<ImageFetchedCallback>& callback,
int http_response_code, const GURL& url,
NSData* data) { int http_response_code,
NSData* data) {
(callback.get())(url, http_response_code, data); (callback.get())(url, http_response_code, data);
} }
void ImageFetcher::SetRequestContextGetter( void ImageFetcher::SetRequestContextGetter(
net::URLRequestContextGetter* request_context_getter) { const scoped_refptr<net::URLRequestContextGetter>& request_context_getter) {
request_context_getter_ = request_context_getter; request_context_getter_ = request_context_getter;
} }
......
...@@ -6,14 +6,12 @@ ...@@ -6,14 +6,12 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#include "base/mac/bind_objc_block.h" #include "base/mac/scoped_block.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/threading/sequenced_worker_pool.h" #include "base/thread_task_runner_handle.h"
#include "net/http/http_response_headers.h" #include "net/http/http_response_headers.h"
#include "net/url_request/test_url_fetcher_factory.h" #include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request_test_util.h" #include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h" #include "testing/platform_test.h"
...@@ -59,10 +57,16 @@ static unsigned char kWEBPImage[] = { ...@@ -59,10 +57,16 @@ static unsigned char kWEBPImage[] = {
48,1,0,157,1,42,1,0,1,0,3,0,52,37,164,0,3,112,0,254,251,253,80,0 48,1,0,157,1,42,1,0,1,0,3,0,52,37,164,0,3,112,0,254,251,253,80,0
}; };
static char kTestUrl[] = "http://www.img.com"; static const char kTestUrl[] = "http://www.img.com";
static const char kWEBPHeaderResponse[] =
"HTTP/1.1 200 OK\0Content-type: image/webp\0\0";
} // namespace } // namespace
// TODO(ios): remove the static_cast<UIImage*>(nil) once all the bots have
// Xcode 6.0 or later installed, http://crbug.com/440857
class ImageFetcherTest : public PlatformTest { class ImageFetcherTest : public PlatformTest {
protected: protected:
ImageFetcherTest() ImageFetcherTest()
...@@ -77,7 +81,7 @@ class ImageFetcherTest : public PlatformTest { ...@@ -77,7 +81,7 @@ class ImageFetcherTest : public PlatformTest {
} copy]); } copy]);
image_fetcher_->SetRequestContextGetter( image_fetcher_->SetRequestContextGetter(
new net::TestURLRequestContextGetter( new net::TestURLRequestContextGetter(
base::MessageLoopProxy::current())); base::ThreadTaskRunnerHandle::Get()));
} }
~ImageFetcherTest() override { pool_->Shutdown(); } ~ImageFetcherTest() override { pool_->Shutdown(); }
...@@ -93,7 +97,7 @@ class ImageFetcherTest : public PlatformTest { ...@@ -93,7 +97,7 @@ class ImageFetcherTest : public PlatformTest {
} }
base::MessageLoop loop_; base::MessageLoop loop_;
base::mac::ScopedBlock<image_fetcher::Callback> callback_; base::mac::ScopedBlock<image_fetcher::ImageFetchedCallback> callback_;
net::TestURLFetcherFactory factory_; net::TestURLFetcherFactory factory_;
scoped_refptr<base::SequencedWorkerPool> pool_; scoped_refptr<base::SequencedWorkerPool> pool_;
scoped_ptr<image_fetcher::ImageFetcher> image_fetcher_; scoped_ptr<image_fetcher::ImageFetcher> image_fetcher_;
...@@ -132,11 +136,8 @@ TEST_F(ImageFetcherTest, TestGoodWebP) { ...@@ -132,11 +136,8 @@ TEST_F(ImageFetcherTest, TestGoodWebP) {
fetcher->set_response_code(200); fetcher->set_response_code(200);
fetcher->SetResponseString( fetcher->SetResponseString(
std::string((char*)kWEBPImage, sizeof(kWEBPImage))); std::string((char*)kWEBPImage, sizeof(kWEBPImage)));
std::string kZero = std::string("\0", 1);
std::string header_string = std::string("HTTP/1.1 200 OK") + kZero +
"Content-type: image/webp" + kZero + kZero;
scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders( scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders(
header_string)); std::string(kWEBPHeaderResponse, arraysize(kWEBPHeaderResponse))));
fetcher->set_response_headers(headers); fetcher->set_response_headers(headers);
fetcher->delegate()->OnURLFetchComplete(fetcher); fetcher->delegate()->OnURLFetchComplete(fetcher);
pool_->FlushForTesting(); pool_->FlushForTesting();
...@@ -149,11 +150,8 @@ TEST_F(ImageFetcherTest, TestBadWebP) { ...@@ -149,11 +150,8 @@ TEST_F(ImageFetcherTest, TestBadWebP) {
net::TestURLFetcher* fetcher = SetupFetcher(); net::TestURLFetcher* fetcher = SetupFetcher();
fetcher->set_response_code(200); fetcher->set_response_code(200);
fetcher->SetResponseString("This is not a valid WebP image"); fetcher->SetResponseString("This is not a valid WebP image");
std::string kZero = std::string("\0", 1);
std::string header_string = std::string("HTTP/1.1 200 OK") + kZero +
"Content-type: image/webp" + kZero + kZero;
scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders( scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders(
header_string)); std::string(kWEBPHeaderResponse, arraysize(kWEBPHeaderResponse))));
fetcher->set_response_headers(headers); fetcher->set_response_headers(headers);
fetcher->delegate()->OnURLFetchComplete(fetcher); fetcher->delegate()->OnURLFetchComplete(fetcher);
pool_->FlushForTesting(); pool_->FlushForTesting();
...@@ -167,11 +165,8 @@ TEST_F(ImageFetcherTest, DeleteDuringWebPDecoding) { ...@@ -167,11 +165,8 @@ TEST_F(ImageFetcherTest, DeleteDuringWebPDecoding) {
fetcher->set_response_code(200); fetcher->set_response_code(200);
fetcher->SetResponseString( fetcher->SetResponseString(
std::string((char*)kWEBPImage, sizeof(kWEBPImage))); std::string((char*)kWEBPImage, sizeof(kWEBPImage)));
std::string kZero = std::string("\0", 1);
std::string header_string = std::string("HTTP/1.1 200 OK") + kZero +
"Content-type: image/webp" + kZero + kZero;
scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders( scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders(
header_string)); std::string(kWEBPHeaderResponse, arraysize(kWEBPHeaderResponse))));
fetcher->set_response_headers(headers); fetcher->set_response_headers(headers);
fetcher->delegate()->OnURLFetchComplete(fetcher); fetcher->delegate()->OnURLFetchComplete(fetcher);
// Delete the image fetcher, and check that the callback is not called. // Delete the image fetcher, and check that the callback is not called.
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/threading/sequenced_worker_pool.h" #include "base/threading/sequenced_worker_pool.h"
#include "ios/chrome/browser/net/image_fetcher.h" #include "ios/chrome/browser/net/image_fetcher.h"
#include "net/url_request/url_request_context_getter.h"
#include "skia/ext/skia_utils_ios.h" #include "skia/ext/skia_utils_ios.h"
namespace suggestions { namespace suggestions {
...@@ -40,7 +41,7 @@ void ImageFetcherImpl::StartOrQueueNetworkRequest( ...@@ -40,7 +41,7 @@ void ImageFetcherImpl::StartOrQueueNetworkRequest(
} }
// Copy url reference so it's retained. // Copy url reference so it's retained.
const GURL page_url(url); const GURL page_url(url);
image_fetcher::Callback fetcher_callback = image_fetcher::ImageFetchedCallback fetcher_callback =
^(const GURL& original_url, int response_code, NSData* data) { ^(const GURL& original_url, int response_code, NSData* data) {
if (data) { if (data) {
// Most likely always returns 1x images. // Most likely always returns 1x images.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment