Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / android / logo_service.cc
blob35e3ce0cad734da65fb2e51dad4c300e7c34b096
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 "base/thread_task_runner_handle.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 "chrome/browser/search_engines/ui_thread_search_terms_data.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 kCachedLogoDirectory[] = "Search Logo";
27 const int kDecodeLogoTimeoutSeconds = 30;
29 // Returns the URL where the doodle can be downloaded, e.g.
30 // https://www.google.com/async/newtab_mobile. This depends on the user's
31 // Google domain.
32 GURL GetGoogleDoodleURL(Profile* profile) {
33 GURL google_base_url(UIThreadSearchTermsData(profile).GoogleBaseURLValue());
34 const char kGoogleDoodleURLPath[] = "async/newtab_mobile";
35 GURL::Replacements replacements;
36 replacements.SetPathStr(kGoogleDoodleURLPath);
37 return google_base_url.ReplaceComponents(replacements);
40 class LogoDecoderDelegate : public ImageDecoder::ImageRequest {
41 public:
42 LogoDecoderDelegate(
43 const base::Callback<void(const SkBitmap&)>& image_decoded_callback)
44 : image_decoded_callback_(image_decoded_callback),
45 weak_ptr_factory_(this) {
46 // If the ImageDecoder crashes or otherwise never completes, call
47 // OnImageDecodeTimedOut() eventually to ensure that image_decoded_callback_
48 // is run.
49 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
50 FROM_HERE, base::Bind(&LogoDecoderDelegate::OnDecodeImageFailed,
51 weak_ptr_factory_.GetWeakPtr()),
52 base::TimeDelta::FromSeconds(kDecodeLogoTimeoutSeconds));
55 ~LogoDecoderDelegate() override {}
57 // ImageDecoder::ImageRequest:
58 void OnImageDecoded(const SkBitmap& decoded_image) override {
59 image_decoded_callback_.Run(decoded_image);
60 delete this;
63 void OnDecodeImageFailed() override {
64 image_decoded_callback_.Run(SkBitmap());
65 delete this;
68 private:
69 base::Callback<void(const SkBitmap&)> image_decoded_callback_;
70 base::WeakPtrFactory<LogoDecoderDelegate> weak_ptr_factory_;
72 DISALLOW_COPY_AND_ASSIGN(LogoDecoderDelegate);
75 class ChromeLogoDelegate : public search_provider_logos::LogoDelegate {
76 public:
77 ChromeLogoDelegate() {}
78 ~ChromeLogoDelegate() override {}
80 // search_provider_logos::LogoDelegate:
81 void DecodeUntrustedImage(
82 const scoped_refptr<base::RefCountedString>& encoded_image,
83 base::Callback<void(const SkBitmap&)> image_decoded_callback) override {
84 LogoDecoderDelegate* delegate =
85 new LogoDecoderDelegate(image_decoded_callback);
86 ImageDecoder::Start(delegate, encoded_image->data());
89 private:
90 DISALLOW_COPY_AND_ASSIGN(ChromeLogoDelegate);
93 } // namespace
95 // LogoService ----------------------------------------------------------------
97 LogoService::LogoService(Profile* profile) : profile_(profile) {
100 LogoService::~LogoService() {
103 void LogoService::GetLogo(search_provider_logos::LogoObserver* observer) {
104 TemplateURLService* template_url_service =
105 TemplateURLServiceFactory::GetForProfile(profile_);
106 if (!template_url_service)
107 return;
109 TemplateURL* template_url = template_url_service->GetDefaultSearchProvider();
110 if (!template_url || !template_url->url_ref().HasGoogleBaseURLs(
111 template_url_service->search_terms_data()))
112 return;
114 if (!logo_tracker_) {
115 logo_tracker_.reset(new LogoTracker(
116 profile_->GetPath().Append(kCachedLogoDirectory),
117 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
118 BrowserThread::GetBlockingPool(),
119 profile_->GetRequestContext(),
120 scoped_ptr<search_provider_logos::LogoDelegate>(
121 new ChromeLogoDelegate())));
124 logo_tracker_->SetServerAPI(
125 GetGoogleDoodleURL(profile_),
126 base::Bind(&search_provider_logos::GoogleParseLogoResponse),
127 base::Bind(&search_provider_logos::GoogleAppendQueryparamsToLogoURL),
128 false);
129 logo_tracker_->GetLogo(observer);
132 // LogoServiceFactory ---------------------------------------------------------
134 // static
135 LogoService* LogoServiceFactory::GetForProfile(Profile* profile) {
136 return static_cast<LogoService*>(
137 GetInstance()->GetServiceForBrowserContext(profile, true));
140 // static
141 LogoServiceFactory* LogoServiceFactory::GetInstance() {
142 return Singleton<LogoServiceFactory>::get();
145 LogoServiceFactory::LogoServiceFactory()
146 : BrowserContextKeyedServiceFactory(
147 "LogoService",
148 BrowserContextDependencyManager::GetInstance()) {
151 LogoServiceFactory::~LogoServiceFactory() {}
153 KeyedService* LogoServiceFactory::BuildServiceInstanceFor(
154 content::BrowserContext* context) const {
155 Profile* profile = static_cast<Profile*>(context);
156 DCHECK(!profile->IsOffTheRecord());
157 return new LogoService(profile);