Upstream version 10.38.220.0
[platform/framework/web/crosswalk.git] / src / components / search_provider_logos / google_logo_api.cc
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.
4
5 #include "components/search_provider_logos/google_logo_api.h"
6
7 #include "base/base64.h"
8 #include "base/json/json_reader.h"
9 #include "base/memory/ref_counted_memory.h"
10 #include "base/strings/string_util.h"
11 #include "base/values.h"
12
13 namespace search_provider_logos {
14
15 namespace {
16 const char kResponsePreamble[] = ")]}'";
17 }
18
19 GURL GoogleAppendFingerprintToLogoURL(const GURL& logo_url,
20                                       const std::string& fingerprint) {
21   // Note: we can't just use net::AppendQueryParameter() because it escapes
22   // ":" to "%3A", but the server requires the colon not to be escaped.
23   // See: http://crbug.com/413845
24
25   // TODO(newt): Switch to using net::AppendQueryParameter once it no longer
26   // escapes ":"
27
28   std::string query(logo_url.query());
29   if (!query.empty())
30     query += "&";
31
32   query += "async=es_dfp:";
33   query += fingerprint;
34   GURL::Replacements replacements;
35   replacements.SetQueryStr(query);
36   return logo_url.ReplaceComponents(replacements);
37 }
38
39 scoped_ptr<EncodedLogo> GoogleParseLogoResponse(
40     const scoped_ptr<std::string>& response,
41     base::Time response_time) {
42   // Google doodles are sent as JSON with a prefix. Example:
43   //   )]}' {"update":{"logo":{
44   //     "data": "/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/...",
45   //     "mime_type": "image/png",
46   //     "fingerprint": "db063e32",
47   //     "target": "http://www.google.com.au/search?q=Wilbur+Christiansen",
48   //     "alt": "Wilbur Christiansen's Birthday"
49   //     "time_to_live": 1389304799
50   //   }}}
51
52   // The response may start with )]}'. Ignore this.
53   base::StringPiece response_sp(*response);
54   if (response_sp.starts_with(kResponsePreamble))
55     response_sp.remove_prefix(strlen(kResponsePreamble));
56
57   scoped_ptr<base::Value> value(base::JSONReader::Read(response_sp));
58   if (!value.get())
59     return scoped_ptr<EncodedLogo>();
60
61   // The important data lives inside several nested dictionaries:
62   // {"update": {"logo": { "mime_type": ..., etc } } }
63   const base::DictionaryValue* outer_dict;
64   if (!value->GetAsDictionary(&outer_dict))
65     return scoped_ptr<EncodedLogo>();
66   const base::DictionaryValue* update_dict;
67   if (!outer_dict->GetDictionary("update", &update_dict))
68     return scoped_ptr<EncodedLogo>();
69   const base::DictionaryValue* logo_dict;
70   if (!update_dict->GetDictionary("logo", &logo_dict))
71     return scoped_ptr<EncodedLogo>();
72
73   scoped_ptr<EncodedLogo> logo(new EncodedLogo());
74
75   std::string encoded_image_base64;
76   if (logo_dict->GetString("data", &encoded_image_base64)) {
77     // Data is optional, since we may be revalidating a cached logo.
78     base::RefCountedString* encoded_image_string = new base::RefCountedString();
79     if (!base::Base64Decode(encoded_image_base64,
80                             &encoded_image_string->data()))
81       return scoped_ptr<EncodedLogo>();
82     logo->encoded_image = encoded_image_string;
83     if (!logo_dict->GetString("mime_type", &logo->metadata.mime_type))
84       return scoped_ptr<EncodedLogo>();
85   }
86
87   // Don't check return values since these fields are optional.
88   logo_dict->GetString("target", &logo->metadata.on_click_url);
89   logo_dict->GetString("fingerprint", &logo->metadata.fingerprint);
90   logo_dict->GetString("alt", &logo->metadata.alt_text);
91
92   base::TimeDelta time_to_live;
93   int time_to_live_ms;
94   if (logo_dict->GetInteger("time_to_live", &time_to_live_ms)) {
95     time_to_live = base::TimeDelta::FromMilliseconds(
96         std::min(static_cast<int64>(time_to_live_ms), kMaxTimeToLiveMS));
97     logo->metadata.can_show_after_expiration = false;
98   } else {
99     time_to_live = base::TimeDelta::FromMilliseconds(kMaxTimeToLiveMS);
100     logo->metadata.can_show_after_expiration = true;
101   }
102   logo->metadata.expiration_time = response_time + time_to_live;
103
104   return logo.Pass();
105 }
106
107 }  // namespace search_provider_logos