Fix UnlockEndpointIsDelayed again.
[chromium-blink-merge.git] / chrome / browser / android / logo_service.cc
blobf9d32524a15ac574d8c3a0b526e7ac965ff97c89
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/android/logo_service.h"
7 #include "base/memory/weak_ptr.h"
8 #include "chrome/browser/google/google_profile_helper.h"
9 #include "chrome/browser/image_decoder.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/search_engines/template_url_service_factory.h"
12 #include "components/google/core/browser/google_util.h"
13 #include "components/keyed_service/content/browser_context_dependency_manager.h"
14 #include "components/search_engines/template_url_service.h"
15 #include "components/search_provider_logos/google_logo_api.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "net/url_request/url_request_context_getter.h"
19 using content::BrowserThread;
20 using search_provider_logos::Logo;
21 using search_provider_logos::LogoDelegate;
22 using search_provider_logos::LogoTracker;
24 namespace {
26 const char kGoogleDoodleURLPath[] = "async/newtab_mobile";
27 const char kCachedLogoDirectory[] = "Search Logo";
28 const int kDecodeLogoTimeoutSeconds = 30;
30 // Returns the URL where the doodle can be downloaded, e.g.
31 // https://www.google.com/async/newtab_mobile. This depends on the user's
32 // Google domain.
33 GURL GetGoogleDoodleURL(Profile* profile) {
34 // SetPathStr() requires its argument to stay in scope as long as
35 // |replacements| is, so a std::string is needed, instead of a char*.
36 std::string path = kGoogleDoodleURLPath;
37 GURL::Replacements replacements;
38 replacements.SetPathStr(path);
40 GURL base_url(google_util::CommandLineGoogleBaseURL());
41 if (!base_url.is_valid())
42 base_url = google_profile_helper::GetGoogleHomePageURL(profile);
43 return base_url.ReplaceComponents(replacements);
46 class LogoDecoderDelegate : public ImageDecoder::Delegate {
47 public:
48 LogoDecoderDelegate(
49 const scoped_refptr<ImageDecoder>& image_decoder,
50 const base::Callback<void(const SkBitmap&)>& image_decoded_callback)
51 : image_decoder_(image_decoder),
52 image_decoded_callback_(image_decoded_callback),
53 weak_ptr_factory_(this) {
54 // If the ImageDecoder crashes or otherwise never completes, call
55 // OnImageDecodeTimedOut() eventually to ensure that image_decoded_callback_
56 // is run.
57 base::MessageLoopProxy::current()->PostDelayedTask(
58 FROM_HERE,
59 base::Bind(&LogoDecoderDelegate::OnDecodeImageFailed,
60 weak_ptr_factory_.GetWeakPtr(),
61 (const ImageDecoder*) NULL),
62 base::TimeDelta::FromSeconds(kDecodeLogoTimeoutSeconds));
65 virtual ~LogoDecoderDelegate() {
66 image_decoder_->set_delegate(NULL);
69 // ImageDecoder::Delegate:
70 virtual void OnImageDecoded(const ImageDecoder* decoder,
71 const SkBitmap& decoded_image) override {
72 image_decoded_callback_.Run(decoded_image);
73 delete this;
76 virtual void OnDecodeImageFailed(const ImageDecoder* decoder) override {
77 image_decoded_callback_.Run(SkBitmap());
78 delete this;
81 private:
82 scoped_refptr<ImageDecoder> image_decoder_;
83 base::Callback<void(const SkBitmap&)> image_decoded_callback_;
84 base::WeakPtrFactory<LogoDecoderDelegate> weak_ptr_factory_;
86 DISALLOW_COPY_AND_ASSIGN(LogoDecoderDelegate);
89 class ChromeLogoDelegate : public search_provider_logos::LogoDelegate {
90 public:
91 ChromeLogoDelegate() {}
92 virtual ~ChromeLogoDelegate() {}
94 // search_provider_logos::LogoDelegate:
95 virtual void DecodeUntrustedImage(
96 const scoped_refptr<base::RefCountedString>& encoded_image,
97 base::Callback<void(const SkBitmap&)> image_decoded_callback) override {
98 scoped_refptr<ImageDecoder> image_decoder = new ImageDecoder(
99 NULL,
100 encoded_image->data(),
101 ImageDecoder::DEFAULT_CODEC);
102 LogoDecoderDelegate* delegate =
103 new LogoDecoderDelegate(image_decoder, image_decoded_callback);
104 image_decoder->set_delegate(delegate);
105 image_decoder->Start(base::MessageLoopProxy::current());
108 private:
109 DISALLOW_COPY_AND_ASSIGN(ChromeLogoDelegate);
112 } // namespace
114 // LogoService ----------------------------------------------------------------
116 LogoService::LogoService(Profile* profile) : profile_(profile) {
119 LogoService::~LogoService() {
122 void LogoService::GetLogo(search_provider_logos::LogoObserver* observer) {
123 TemplateURLService* template_url_service =
124 TemplateURLServiceFactory::GetForProfile(profile_);
125 if (!template_url_service)
126 return;
128 TemplateURL* template_url = template_url_service->GetDefaultSearchProvider();
129 if (!template_url || !template_url->url_ref().HasGoogleBaseURLs(
130 template_url_service->search_terms_data()))
131 return;
133 if (!logo_tracker_) {
134 logo_tracker_.reset(new LogoTracker(
135 profile_->GetPath().Append(kCachedLogoDirectory),
136 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
137 BrowserThread::GetBlockingPool(),
138 profile_->GetRequestContext(),
139 scoped_ptr<search_provider_logos::LogoDelegate>(
140 new ChromeLogoDelegate())));
143 logo_tracker_->SetServerAPI(
144 GetGoogleDoodleURL(profile_),
145 base::Bind(&search_provider_logos::GoogleParseLogoResponse),
146 base::Bind(&search_provider_logos::GoogleAppendFingerprintToLogoURL));
147 logo_tracker_->GetLogo(observer);
150 // LogoServiceFactory ---------------------------------------------------------
152 // static
153 LogoService* LogoServiceFactory::GetForProfile(Profile* profile) {
154 return static_cast<LogoService*>(
155 GetInstance()->GetServiceForBrowserContext(profile, true));
158 // static
159 LogoServiceFactory* LogoServiceFactory::GetInstance() {
160 return Singleton<LogoServiceFactory>::get();
163 LogoServiceFactory::LogoServiceFactory()
164 : BrowserContextKeyedServiceFactory(
165 "LogoService",
166 BrowserContextDependencyManager::GetInstance()) {
169 LogoServiceFactory::~LogoServiceFactory() {}
171 KeyedService* LogoServiceFactory::BuildServiceInstanceFor(
172 content::BrowserContext* context) const {
173 Profile* profile = static_cast<Profile*>(context);
174 DCHECK(!profile->IsOffTheRecord());
175 return new LogoService(profile);