Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / components / translate / core / browser / translate_script.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/translate/core/browser/translate_script.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/profiler/scoped_tracker.h"
12 #include "base/strings/string_piece.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/stringprintf.h"
15 #include "components/translate/core/browser/translate_url_fetcher.h"
16 #include "components/translate/core/browser/translate_url_util.h"
17 #include "components/translate/core/common/translate_switches.h"
18 #include "components/translate/core/common/translate_util.h"
19 #include "google_apis/google_api_keys.h"
20 #include "grit/components_resources.h"
21 #include "net/base/escape.h"
22 #include "net/base/url_util.h"
23 #include "ui/base/resource/resource_bundle.h"
24
25 namespace translate {
26
27 namespace {
28
29 const int kExpirationDelayDays = 1;
30
31 }  // namespace
32
33 const char TranslateScript::kScriptURL[] =
34     "https://translate.google.com/translate_a/element.js";
35 const char TranslateScript::kRequestHeader[] =
36     "Google-Translate-Element-Mode: library";
37 const char TranslateScript::kAlwaysUseSslQueryName[] = "aus";
38 const char TranslateScript::kAlwaysUseSslQueryValue[] = "true";
39 const char TranslateScript::kCallbackQueryName[] = "cb";
40 const char TranslateScript::kCallbackQueryValue[] =
41     "cr.googleTranslate.onTranslateElementLoad";
42 const char TranslateScript::kCssLoaderCallbackQueryName[] = "clc";
43 const char TranslateScript::kCssLoaderCallbackQueryValue[] =
44     "cr.googleTranslate.onLoadCSS";
45 const char TranslateScript::kJavascriptLoaderCallbackQueryName[] = "jlc";
46 const char TranslateScript::kJavascriptLoaderCallbackQueryValue[] =
47     "cr.googleTranslate.onLoadJavascript";
48
49 TranslateScript::TranslateScript()
50     : expiration_delay_(base::TimeDelta::FromDays(kExpirationDelayDays)),
51       weak_method_factory_(this) {
52 }
53
54 TranslateScript::~TranslateScript() {
55 }
56
57 void TranslateScript::Request(const RequestCallback& callback) {
58   DCHECK(data_.empty()) << "Do not fetch the script if it is already fetched";
59   callback_list_.push_back(callback);
60
61   if (fetcher_.get() != NULL) {
62     // If there is already a request in progress, do nothing. |callback| will be
63     // run on completion.
64     return;
65   }
66
67   GURL translate_script_url;
68   // Check if command-line contains an alternative URL for translate service.
69   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
70   if (command_line.HasSwitch(translate::switches::kTranslateScriptURL)) {
71     translate_script_url = GURL(command_line.GetSwitchValueASCII(
72         translate::switches::kTranslateScriptURL));
73     if (!translate_script_url.is_valid() ||
74         !translate_script_url.query().empty()) {
75       LOG(WARNING) << "The following translate URL specified at the "
76                    << "command-line is invalid: "
77                    << translate_script_url.spec();
78       translate_script_url = GURL();
79     }
80   }
81
82   // Use default URL when command-line argument is not specified, or specified
83   // URL is invalid.
84   if (translate_script_url.is_empty())
85     translate_script_url = GURL(kScriptURL);
86
87   translate_script_url = net::AppendQueryParameter(
88       translate_script_url,
89       kCallbackQueryName,
90       kCallbackQueryValue);
91   translate_script_url = net::AppendQueryParameter(
92       translate_script_url,
93       kAlwaysUseSslQueryName,
94       kAlwaysUseSslQueryValue);
95 #if !defined(OS_IOS)
96   // iOS doesn't need to use specific loaders for the isolated world.
97   translate_script_url = net::AppendQueryParameter(
98       translate_script_url,
99       kCssLoaderCallbackQueryName,
100       kCssLoaderCallbackQueryValue);
101   translate_script_url = net::AppendQueryParameter(
102       translate_script_url,
103       kJavascriptLoaderCallbackQueryName,
104       kJavascriptLoaderCallbackQueryValue);
105 #endif  // !defined(OS_IOS)
106
107   translate_script_url = AddHostLocaleToUrl(translate_script_url);
108   translate_script_url = AddApiKeyToUrl(translate_script_url);
109
110   fetcher_.reset(new TranslateURLFetcher(kFetcherId));
111   fetcher_->set_extra_request_header(kRequestHeader);
112   fetcher_->Request(
113       translate_script_url,
114       base::Bind(&TranslateScript::OnScriptFetchComplete,
115                  base::Unretained(this)));
116 }
117
118
119 void TranslateScript::OnScriptFetchComplete(
120     int id, bool success, const std::string& data) {
121   DCHECK_EQ(kFetcherId, id);
122
123   scoped_ptr<const TranslateURLFetcher> delete_ptr(fetcher_.release());
124
125   if (success) {
126     DCHECK(data_.empty());
127     // Insert variable definitions on API Key and security origin.
128     data_ = base::StringPrintf("var translateApiKey = '%s';\n",
129                                google_apis::GetAPIKey().c_str());
130
131     GURL security_origin = translate::GetTranslateSecurityOrigin();
132     base::StringAppendF(
133         &data_, "var securityOrigin = '%s';", security_origin.spec().c_str());
134
135     // Append embedded translate.js and a remote element library.
136     base::StringPiece str = ResourceBundle::GetSharedInstance().
137         GetRawDataResource(IDR_TRANSLATE_JS);
138     str.AppendToString(&data_);
139     data_ += data;
140
141     // We'll expire the cached script after some time, to make sure long
142     // running browsers still get fixes that might get pushed with newer
143     // scripts.
144     base::MessageLoop::current()->PostDelayedTask(
145         FROM_HERE,
146         base::Bind(&TranslateScript::Clear,
147                    weak_method_factory_.GetWeakPtr()),
148         expiration_delay_);
149   }
150
151   for (RequestCallbackList::iterator it = callback_list_.begin();
152        it != callback_list_.end();
153        ++it) {
154     it->Run(success, data);
155   }
156   callback_list_.clear();
157 }
158
159 }  // namespace translate