Home | History | Annotate | Download | only in translate
      1 // Copyright 2013 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 "chrome/browser/translate/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/strings/string_util.h"
     12 #include "chrome/browser/translate/translate_url_fetcher.h"
     13 #include "chrome/browser/translate/translate_url_util.h"
     14 #include "chrome/common/chrome_switches.h"
     15 #include "google_apis/google_api_keys.h"
     16 #include "grit/browser_resources.h"
     17 #include "net/base/escape.h"
     18 #include "net/base/url_util.h"
     19 #include "ui/base/resource/resource_bundle.h"
     20 
     21 namespace {
     22 
     23 const int kExpirationDelayDays = 1;
     24 
     25 const char kScriptURL[] =
     26     "https://translate.google.com/translate_a/element.js";
     27 const char kRequestHeader[] = "Google-Translate-Element-Mode: library";
     28 
     29 // Used in kTranslateScriptURL to specify a callback function name.
     30 const char kCallbackQueryName[] = "cb";
     31 const char kCallbackQueryValue[] =
     32     "cr.googleTranslate.onTranslateElementLoad";
     33 
     34 }  // namespace
     35 
     36 TranslateScript::TranslateScript()
     37     : weak_method_factory_(this),
     38       expiration_delay_(base::TimeDelta::FromDays(kExpirationDelayDays)) {
     39 }
     40 
     41 TranslateScript::~TranslateScript() {
     42   weak_method_factory_.InvalidateWeakPtrs();
     43 }
     44 
     45 void TranslateScript::Request(const Callback& callback) {
     46   if (fetcher_.get() != NULL) {
     47     NOTREACHED();
     48     return;
     49   }
     50 
     51   callback_ = callback;
     52 
     53   GURL translate_script_url;
     54   // Check if command-line contains an alternative URL for translate service.
     55   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
     56   if (command_line.HasSwitch(switches::kTranslateScriptURL)) {
     57     translate_script_url = GURL(
     58         command_line.GetSwitchValueASCII(switches::kTranslateScriptURL));
     59     if (!translate_script_url.is_valid() ||
     60         !translate_script_url.query().empty()) {
     61       LOG(WARNING) << "The following translate URL specified at the "
     62                    << "command-line is invalid: "
     63                    << translate_script_url.spec();
     64       translate_script_url = GURL();
     65     }
     66   }
     67 
     68   // Use default URL when command-line argument is not specified, or specified
     69   // URL is invalid.
     70   if (translate_script_url.is_empty())
     71     translate_script_url = GURL(kScriptURL);
     72 
     73   translate_script_url = net::AppendQueryParameter(
     74       translate_script_url,
     75       kCallbackQueryName,
     76       kCallbackQueryValue);
     77 
     78   translate_script_url =
     79       TranslateURLUtil::AddHostLocaleToUrl(translate_script_url);
     80   translate_script_url =
     81       TranslateURLUtil::AddApiKeyToUrl(translate_script_url);
     82 
     83   fetcher_.reset(new TranslateURLFetcher(kFetcherId));
     84   fetcher_->set_extra_request_header(kRequestHeader);
     85   fetcher_->Request(
     86       translate_script_url,
     87       base::Bind(&TranslateScript::OnScriptFetchComplete,
     88                  base::Unretained(this)));
     89 }
     90 
     91 
     92 void TranslateScript::OnScriptFetchComplete(
     93     int id, bool success, const std::string& data) {
     94   DCHECK_EQ(kFetcherId, id);
     95 
     96   scoped_ptr<const TranslateURLFetcher> delete_ptr(fetcher_.release());
     97 
     98   if (success) {
     99     base::StringPiece str = ResourceBundle::GetSharedInstance().
    100         GetRawDataResource(IDR_TRANSLATE_JS);
    101     DCHECK(data_.empty());
    102     str.CopyToString(&data_);
    103     std::string argument = "('";
    104     std::string api_key = google_apis::GetAPIKey();
    105     argument += net::EscapeQueryParamValue(api_key, true);
    106     argument += "');\n";
    107     data_ += argument + data;
    108 
    109     // We'll expire the cached script after some time, to make sure long
    110     // running browsers still get fixes that might get pushed with newer
    111     // scripts.
    112     base::MessageLoop::current()->PostDelayedTask(
    113         FROM_HERE,
    114         base::Bind(&TranslateScript::Clear,
    115                    weak_method_factory_.GetWeakPtr()),
    116         expiration_delay_);
    117   }
    118 
    119   callback_.Run(success, data);
    120 }
    121