diff options
author | newt@chromium.org <newt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-30 20:04:23 +0000 |
---|---|---|
committer | newt@chromium.org <newt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-30 20:04:23 +0000 |
commit | cf59dd169aa864e41d6fbd32384e831e4ab80fba (patch) | |
tree | 1aa4556475e9322d829a26519f7b2f4c376fae8d /components/search_provider_logos/google_logo_api.cc | |
parent | ebb3ad52433c978a914d0b387690dc98c791736a (diff) | |
download | chromium_src-cf59dd169aa864e41d6fbd32384e831e4ab80fba.zip chromium_src-cf59dd169aa864e41d6fbd32384e831e4ab80fba.tar.gz chromium_src-cf59dd169aa864e41d6fbd32384e831e4ab80fba.tar.bz2 |
Add LogoTracker to fetch search providers' logos.
The LogoTracker keeps track of the logo for a search provider. The logo
is downloaded, cached on disk, and periodically revalidated.
This code lives inside a component (search_provider_logos) so it can be
used on both Android and iOS.
BUG=178922
NOTRY=true
Review URL: https://codereview.chromium.org/162373002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267314 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components/search_provider_logos/google_logo_api.cc')
-rw-r--r-- | components/search_provider_logos/google_logo_api.cc | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/components/search_provider_logos/google_logo_api.cc b/components/search_provider_logos/google_logo_api.cc new file mode 100644 index 0000000..9a855cb --- /dev/null +++ b/components/search_provider_logos/google_logo_api.cc @@ -0,0 +1,93 @@ +// Copyright 2014 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 "components/search_provider_logos/google_logo_api.h" + +#include "base/base64.h" +#include "base/json/json_reader.h" +#include "base/memory/ref_counted_memory.h" +#include "base/strings/string_util.h" +#include "base/values.h" +#include "net/base/url_util.h" + +namespace search_provider_logos { + +namespace { +const char kResponsePreamble[] = ")]}'"; +} + +GURL GoogleAppendFingerprintToLogoURL(const GURL& logo_url, + const std::string& fingerprint) { + return net::AppendQueryParameter(logo_url, "async", "es_dfp:" + fingerprint); +} + +scoped_ptr<EncodedLogo> GoogleParseLogoResponse( + const scoped_ptr<std::string>& response, + base::Time response_time) { + // Google doodles are sent as JSON with a prefix. Example: + // )]}' {"update":{"logo":{ + // "data": "/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/...", + // "mime_type": "image/png", + // "fingerprint": "db063e32", + // "target": "http://www.google.com.au/search?q=Wilbur+Christiansen", + // "alt": "Wilbur Christiansen's Birthday" + // "time_to_live": 1389304799 + // }}} + + // The response may start with )]}'. Ignore this. + base::StringPiece response_sp(*response); + if (response_sp.starts_with(kResponsePreamble)) + response_sp.remove_prefix(strlen(kResponsePreamble)); + + scoped_ptr<base::Value> value(base::JSONReader::Read(response_sp)); + if (!value.get()) + return scoped_ptr<EncodedLogo>(); + + // The important data lives inside several nested dictionaries: + // {"update": {"logo": { "mime_type": ..., etc } } } + const base::DictionaryValue* outer_dict; + if (!value->GetAsDictionary(&outer_dict)) + return scoped_ptr<EncodedLogo>(); + const base::DictionaryValue* update_dict; + if (!outer_dict->GetDictionary("update", &update_dict)) + return scoped_ptr<EncodedLogo>(); + const base::DictionaryValue* logo_dict; + if (!update_dict->GetDictionary("logo", &logo_dict)) + return scoped_ptr<EncodedLogo>(); + + scoped_ptr<EncodedLogo> logo(new EncodedLogo()); + + std::string encoded_image_base64; + if (logo_dict->GetString("data", &encoded_image_base64)) { + // Data is optional, since we may be revalidating a cached logo. + base::RefCountedString* encoded_image_string = new base::RefCountedString(); + if (!base::Base64Decode(encoded_image_base64, + &encoded_image_string->data())) + return scoped_ptr<EncodedLogo>(); + logo->encoded_image = encoded_image_string; + if (!logo_dict->GetString("mime_type", &logo->metadata.mime_type)) + return scoped_ptr<EncodedLogo>(); + } + + // Don't check return values since these fields are optional. + logo_dict->GetString("target", &logo->metadata.on_click_url); + logo_dict->GetString("fingerprint", &logo->metadata.fingerprint); + logo_dict->GetString("alt", &logo->metadata.alt_text); + + base::TimeDelta time_to_live; + int time_to_live_ms; + if (logo_dict->GetInteger("time_to_live", &time_to_live_ms)) { + time_to_live = base::TimeDelta::FromMilliseconds( + std::min(static_cast<int64>(time_to_live_ms), kMaxTimeToLiveMS)); + logo->metadata.can_show_after_expiration = false; + } else { + time_to_live = base::TimeDelta::FromMilliseconds(kMaxTimeToLiveMS); + logo->metadata.can_show_after_expiration = true; + } + logo->metadata.expiration_time = response_time + time_to_live; + + return logo.Pass(); +} + +} // namespace search_provider_logos |