summaryrefslogtreecommitdiffstats
path: root/components/search_provider_logos/google_logo_api.cc
diff options
context:
space:
mode:
authornewt@chromium.org <newt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-30 21:55:16 +0000
committernewt@chromium.org <newt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-30 21:55:16 +0000
commit12fad44d9e65df34ef7f71f53bf16e0d429a8aff (patch)
treed2199704d6e10040a68faba57c4ee89bbf02994a /components/search_provider_logos/google_logo_api.cc
parent09bd7bc27cf7544bdfb58fe0e21465b6485d599e (diff)
downloadchromium_src-12fad44d9e65df34ef7f71f53bf16e0d429a8aff.zip
chromium_src-12fad44d9e65df34ef7f71f53bf16e0d429a8aff.tar.gz
chromium_src-12fad44d9e65df34ef7f71f53bf16e0d429a8aff.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 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=267314 Review URL: https://codereview.chromium.org/162373002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267349 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.cc93
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