15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/translate/content/renderer/translate_helper.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/metrics/histogram.h" 127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string16.h" 137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "components/translate/content/common/translate_messages.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/translate/core/common/translate_constants.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/translate/core/common/translate_metrics.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/translate/core/common/translate_util.h" 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/translate/core/language_detection/language_detection_util.h" 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/common/content_constants.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/common/url_constants.h" 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/renderer/render_thread.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/renderer/render_view.h" 24effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ipc/ipc_platform_file.h" 257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebDocument.h" 267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebElement.h" 277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrame.h" 287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebNode.h" 297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebNodeList.h" 307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebScriptSource.h" 317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebView.h" 32558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "third_party/WebKit/public/web/WebWidget.h" 33558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "url/gurl.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "v8/include/v8.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::ASCIIToUTF16; 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebDocument; 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebElement; 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebFrame; 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebNode; 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebNodeList; 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebScriptSource; 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebSecurityOrigin; 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebString; 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebVector; 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebView; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The delay in milliseconds that we'll wait before checking to see if the 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// translate library injected in the page is ready. 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kTranslateInitCheckDelayMs = 150; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The maximum number of times we'll check to see if the translate library 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// injected in the page is ready. 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kMaxTranslateInitCheckAttempts = 5; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The delay we wait in milliseconds before checking whether the translation has 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// finished. 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kTranslateStatusCheckDelayMs = 400; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Language name passed to the Translate element for it to detect the language. 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kAutoDetectionLanguage[] = "auto"; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 65558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Isolated world sets following content-security-policy. 66558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochconst char kContentSecurityPolicy[] = "script-src 'self' 'unsafe-eval'"; 67558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Whether or not we have set the CLD callback yet. 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool g_cld_callback_set = false; 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace translate { 74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TranslateHelper, public: 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTranslateHelper::TranslateHelper(content::RenderView* render_view, 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int world_id, 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int extension_group, 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& extension_scheme) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : content::RenderViewObserver(render_view), 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch page_seq_no_(0), 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) translation_pending_(false), 85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cld_data_provider_(translate::CreateRendererCldDataProviderFor(this)), 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cld_data_polling_started_(false), 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cld_data_polling_canceled_(false), 88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch deferred_page_capture_(false), 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci deferred_page_seq_no_(-1), 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci world_id_(world_id), 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_group_(extension_group), 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_scheme_(extension_scheme), 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_method_factory_(this) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TranslateHelper::~TranslateHelper() { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingTranslation(); 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CancelCldDataPolling(); 99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 100effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid TranslateHelper::PrepareForUrl(const GURL& url) { 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++page_seq_no_; 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Send(new ChromeViewHostMsg_TranslateAssignedSequenceNumber( 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch routing_id(), page_seq_no_)); 105effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch deferred_page_capture_ = false; 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch deferred_page_seq_no_ = -1; 107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch deferred_contents_.clear(); 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (cld_data_polling_started_) 109effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // TODO(andrewhayden): Refactor translate_manager.cc's IsTranslatableURL to 112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // components/translate/core/common/translate_util.cc, and ignore any URL 113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // that fails that check. This will require moving unit tests and rewiring 114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // other function calls as well, so for now replicate the logic here. 115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (url.is_empty()) 116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (url.SchemeIs(content::kChromeUIScheme)) 118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (url.SchemeIs(content::kChromeDevToolsScheme)) 120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (url.SchemeIs(url::kFtpScheme)) 122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (url.SchemeIs(extension_scheme_.c_str())) 124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Start polling for CLD data. 127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cld_data_polling_started_ = true; 128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TranslateHelper::SendCldDataRequest(0, 1000); 129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 131116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TranslateHelper::PageCaptured(const base::string16& contents) { 132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PageCapturedImpl(page_seq_no_, contents); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TranslateHelper::PageCapturedImpl(int page_seq_no, 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::string16& contents) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the document language as set by WebKit from the http-equiv 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // meta tag for "content-language". This may or may not also 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have a value derived from the actual Content-Language HTTP 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // header. The two actually have different meanings (despite the 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // original intent of http-equiv to be an equivalent) with the former 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // being the language of the document and the latter being the 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // language of the intended audience (a distinction really only 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // relevant for things like langauge textbooks). This distinction 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shouldn't affect translation. 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WebFrame* main_frame = GetMainFrame(); 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!main_frame || page_seq_no_ != page_seq_no) 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!cld_data_provider_->IsCldDataAvailable()) { 151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // We're in dynamic mode and CLD data isn't loaded. Retry when CLD data 152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // is loaded, if ever. 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch deferred_page_capture_ = true; 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch deferred_page_seq_no_ = page_seq_no; 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch deferred_contents_ = contents; 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch RecordLanguageDetectionTiming(DEFERRED); 157effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (deferred_page_seq_no_ == -1) { 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // CLD data was available before language detection was requested. 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch RecordLanguageDetectionTiming(ON_TIME); 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // This is a request that was triggered because CLD data is now available 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // and was previously deferred. 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch RecordLanguageDetectionTiming(RESUMED); 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WebDocument document = main_frame->document(); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string content_language = document.contentLanguage().utf8(); 17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WebElement html_element = document.documentElement(); 17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string html_lang; 17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // |html_element| can be null element, e.g. in 17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // BrowserTest.WindowOpenClose. 17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!html_element.isNull()) 17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) html_lang = html_element.getAttribute("lang").utf8(); 17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string cld_language; 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool is_cld_reliable; 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string language = DeterminePageLanguage( 18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content_language, html_lang, contents, &cld_language, &is_cld_reliable); 18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (language.empty()) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) language_determined_time_ = base::TimeTicks::Now(); 18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GURL url(document.url()); 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LanguageDetectionDetails details; 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) details.time = base::Time::Now(); 19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) details.url = url; 19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) details.content_language = content_language; 19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) details.cld_language = cld_language; 19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) details.is_cld_reliable = is_cld_reliable; 194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) details.html_root_language = html_lang; 19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) details.adopted_language = language; 19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(hajimehoshi): If this affects performance, it should be set only if 198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // translate-internals tab exists. 199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) details.contents = contents; 200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Send(new ChromeViewHostMsg_TranslateLanguageDetermined( 20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) routing_id(), 20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) details, 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) IsTranslationAllowed(&document) && !language.empty())); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TranslateHelper::CancelPendingTranslation() { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_method_factory_.InvalidateWeakPtrs(); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) translation_pending_ = false; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_lang_.clear(); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_lang_.clear(); 212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CancelCldDataPolling(); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TranslateHelper, protected: 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TranslateHelper::IsTranslateLibAvailable() { 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ExecuteScriptAndGetBoolResult( 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "typeof cr != 'undefined' && typeof cr.googleTranslate != 'undefined' && " 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "typeof cr.googleTranslate.translate == 'function'", false); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TranslateHelper::IsTranslateLibReady() { 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ExecuteScriptAndGetBoolResult("cr.googleTranslate.libReady", false); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TranslateHelper::HasTranslationFinished() { 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ExecuteScriptAndGetBoolResult("cr.googleTranslate.finished", true); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TranslateHelper::HasTranslationFailed() { 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ExecuteScriptAndGetBoolResult("cr.googleTranslate.error", true); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TranslateHelper::StartTranslation() { 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string script = "cr.googleTranslate.translate('" + 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) source_lang_ + 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "','" + 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) target_lang_ + 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "')"; 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ExecuteScriptAndGetBoolResult(script, false); 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string TranslateHelper::GetOriginalPageLanguage() { 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ExecuteScriptAndGetStringResult("cr.googleTranslate.sourceLang"); 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::TimeDelta TranslateHelper::AdjustDelay(int delayInMs) { 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Just converts |delayInMs| without any modification in practical cases. 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Tests will override this function to return modified value. 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return base::TimeDelta::FromMilliseconds(delayInMs); 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void TranslateHelper::ExecuteScript(const std::string& script) { 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebFrame* main_frame = GetMainFrame(); 257558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (!main_frame) 258558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return; 259558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 260558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebScriptSource source = WebScriptSource(ASCIIToUTF16(script)); 261558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch main_frame->executeScriptInIsolatedWorld( 2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci world_id_, &source, 1, extension_group_); 263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool TranslateHelper::ExecuteScriptAndGetBoolResult(const std::string& script, 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool fallback) { 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebFrame* main_frame = GetMainFrame(); 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!main_frame) 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return fallback; 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 27158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); 272558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebVector<v8::Local<v8::Value> > results; 273558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebScriptSource source = WebScriptSource(ASCIIToUTF16(script)); 274558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch main_frame->executeScriptInIsolatedWorld( 2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci world_id_, &source, 1, extension_group_, &results); 276558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (results.size() != 1 || results[0].IsEmpty() || !results[0]->IsBoolean()) { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return fallback; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 281558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return results[0]->BooleanValue(); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string TranslateHelper::ExecuteScriptAndGetStringResult( 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& script) { 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebFrame* main_frame = GetMainFrame(); 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!main_frame) 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); 291558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebVector<v8::Local<v8::Value> > results; 292558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebScriptSource source = WebScriptSource(ASCIIToUTF16(script)); 293558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch main_frame->executeScriptInIsolatedWorld( 2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci world_id_, &source, 1, extension_group_, &results); 295558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (results.size() != 1 || results[0].IsEmpty() || !results[0]->IsString()) { 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED(); 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 300558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch v8::Local<v8::String> v8_str = results[0]->ToString(); 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int length = v8_str->Utf8Length() + 1; 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<char[]> str(new char[length]); 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) v8_str->WriteUtf8(str.get(), length); 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(str.get()); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)double TranslateHelper::ExecuteScriptAndGetDoubleResult( 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& script) { 309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebFrame* main_frame = GetMainFrame(); 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!main_frame) 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return 0.0; 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); 314558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebVector<v8::Local<v8::Value> > results; 315558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebScriptSource source = WebScriptSource(ASCIIToUTF16(script)); 316558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch main_frame->executeScriptInIsolatedWorld( 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci world_id_, &source, 1, extension_group_, &results); 318558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (results.size() != 1 || results[0].IsEmpty() || !results[0]->IsNumber()) { 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED(); 320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return 0.0; 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 323558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return results[0]->NumberValue(); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TranslateHelper, private: 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool TranslateHelper::IsTranslationAllowed(WebDocument* document) { 33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WebElement head = document->head(); 33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (head.isNull() || !head.hasChildNodes()) 33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return true; 33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const WebString meta(ASCIIToUTF16("meta")); 33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const WebString name(ASCIIToUTF16("name")); 33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const WebString google(ASCIIToUTF16("google")); 33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const WebString value(ASCIIToUTF16("value")); 34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const WebString content(ASCIIToUTF16("content")); 34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WebNodeList children = head.childNodes(); 34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t i = 0; i < children.length(); ++i) { 34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WebNode node = children.item(i); 34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!node.isElementNode()) 34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WebElement element = node.to<WebElement>(); 34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Check if a tag is <meta>. 349116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!element.hasHTMLTagName(meta)) 35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Check if the tag contains name="google". 35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WebString attribute = element.getAttribute(name); 35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (attribute.isNull() || attribute != google) 35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Check if the tag contains value="notranslate", or content="notranslate". 35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) attribute = element.getAttribute(value); 35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (attribute.isNull()) 35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) attribute = element.getAttribute(content); 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (attribute.isNull()) 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (LowerCaseEqualsASCII(attribute, "notranslate")) 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TranslateHelper::OnMessageReceived(const IPC::Message& message) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool handled = true; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_BEGIN_MESSAGE_MAP(TranslateHelper, message) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(ChromeViewMsg_TranslatePage, OnTranslatePage) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_HANDLER(ChromeViewMsg_RevertTranslation, OnRevertTranslation) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_UNHANDLED(handled = false) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_END_MESSAGE_MAP() 374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!handled) { 375116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch handled = cld_data_provider_->OnMessageReceived(message); 376116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return handled; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 380116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TranslateHelper::OnTranslatePage(int page_seq_no, 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& translate_script, 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source_lang, 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& target_lang) { 38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WebFrame* main_frame = GetMainFrame(); 385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!main_frame || page_seq_no_ != page_seq_no) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // We navigated away, nothing to do. 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // A similar translation is already under way, nothing to do. 389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (translation_pending_ && target_lang_ == target_lang) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Any pending translation is now irrelevant. 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingTranslation(); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set our states. 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) translation_pending_ = true; 397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the source language is undetermined, we'll let the translate element 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // detect it. 4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci source_lang_ = (source_lang != kUnknownLanguageCode) ? source_lang 4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : kAutoDetectionLanguage; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_lang_ = target_lang; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReportUserActionDuration(language_determined_time_, base::TimeTicks::Now()); 40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GURL url(main_frame->document().url()); 4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReportPageScheme(url.scheme()); 40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 409558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Set up v8 isolated world with proper content-security-policy and 410558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // security-origin. 411558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebFrame* frame = GetMainFrame(); 412558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (frame) { 413558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch frame->setIsolatedWorldContentSecurityPolicy( 4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci world_id_, WebString::fromUTF8(kContentSecurityPolicy)); 415558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GURL security_origin = GetTranslateSecurityOrigin(); 417558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch frame->setIsolatedWorldSecurityOrigin( 4181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci world_id_, WebSecurityOrigin::create(security_origin)); 419558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 420558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsTranslateLibAvailable()) { 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Evaluate the script to add the translation related method to the global 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // context of the page. 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExecuteScript(translate_script); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsTranslateLibAvailable()); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TranslatePageImpl(page_seq_no, 0); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 431116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TranslateHelper::OnRevertTranslation(int page_seq_no) { 432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (page_seq_no_ != page_seq_no) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // We navigated away, nothing to do. 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsTranslateLibAvailable()) { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingTranslation(); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExecuteScript("cr.googleTranslate.revert()"); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TranslateHelper::CheckTranslateStatus(int page_seq_no) { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is not the same page, the translation has been canceled. If the 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // view is gone, the page is closing. 448116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (page_seq_no_ != page_seq_no || !render_view()->GetWebView()) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First check if there was an error. 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HasTranslationFailed()) { 45358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // TODO(toyoshim): Check |errorCode| of translate.js and notify it here. 4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NotifyBrowserTranslationFailed(TranslateErrors::TRANSLATION_ERROR); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // There was an error. 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HasTranslationFinished()) { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string actual_source_lang; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Translation was successfull, if it was auto, retrieve the source 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // language the Translate Element detected. 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source_lang_ == kAutoDetectionLanguage) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) actual_source_lang = GetOriginalPageLanguage(); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (actual_source_lang.empty()) { 4651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NotifyBrowserTranslationFailed(TranslateErrors::UNKNOWN_LANGUAGE); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (actual_source_lang == target_lang_) { 4681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NotifyBrowserTranslationFailed(TranslateErrors::IDENTICAL_LANGUAGES); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) actual_source_lang = source_lang_; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!translation_pending_) { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) translation_pending_ = false; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check JavaScript performance counters for UMA reports. 4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReportTimeToTranslate( 484a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ExecuteScriptAndGetDoubleResult("cr.googleTranslate.translationTime")); 485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify the browser we are done. 4875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) render_view()->Send( 4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new ChromeViewHostMsg_PageTranslated(render_view()->GetRoutingID(), 4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) actual_source_lang, 4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_lang_, 4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TranslateErrors::NONE)); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The translation is still pending, check again later. 496a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TranslateHelper::CheckTranslateStatus, 499116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch weak_method_factory_.GetWeakPtr(), page_seq_no), 500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AdjustDelay(kTranslateStatusCheckDelayMs)); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 503116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TranslateHelper::TranslatePageImpl(int page_seq_no, int count) { 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(count, kMaxTranslateInitCheckAttempts); 505116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (page_seq_no_ != page_seq_no || !render_view()->GetWebView()) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsTranslateLibReady()) { 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The library is not ready, try again later, unless we have tried several 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // times unsucessfully already. 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (++count >= kMaxTranslateInitCheckAttempts) { 5121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NotifyBrowserTranslationFailed(TranslateErrors::INITIALIZATION_ERROR); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TranslateHelper::TranslatePageImpl, 518a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) weak_method_factory_.GetWeakPtr(), 519116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch page_seq_no, count), 520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AdjustDelay(count * kTranslateInitCheckDelayMs)); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The library is loaded, and ready for translation now. 525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check JavaScript performance counters for UMA reports. 5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReportTimeToBeReady( 527a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ExecuteScriptAndGetDoubleResult("cr.googleTranslate.readyTime")); 5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReportTimeToLoad( 529a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ExecuteScriptAndGetDoubleResult("cr.googleTranslate.loadTime")); 530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!StartTranslation()) { 5321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NotifyBrowserTranslationFailed(TranslateErrors::TRANSLATION_ERROR); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the status of the translation. 536a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TranslateHelper::CheckTranslateStatus, 539116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch weak_method_factory_.GetWeakPtr(), page_seq_no), 540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AdjustDelay(kTranslateStatusCheckDelayMs)); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TranslateHelper::NotifyBrowserTranslationFailed( 5441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TranslateErrors::Type error) { 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) translation_pending_ = false; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify the browser there was an error. 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view()->Send(new ChromeViewHostMsg_PageTranslated( 548116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch render_view()->GetRoutingID(), source_lang_, target_lang_, error)); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebFrame* TranslateHelper::GetMainFrame() { 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebView* web_view = render_view()->GetWebView(); 55390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 55490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // When the tab is going to be closed, the web_view can be NULL. 55590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!web_view) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 55790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return web_view->mainFrame(); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 560effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 561116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TranslateHelper::CancelCldDataPolling() { 562116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cld_data_polling_canceled_ = true; 563effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 564effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 565116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TranslateHelper::SendCldDataRequest(const int delay_millis, 566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const int next_delay_millis) { 567effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Terminate immediately if told to stop polling. 568116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (cld_data_polling_canceled_) 569effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 570effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 571effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Terminate immediately if data is already loaded. 572116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (cld_data_provider_->IsCldDataAvailable()) 573effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 574effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!g_cld_callback_set) { 576116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch g_cld_callback_set = true; 577116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cld_data_provider_->SetCldAvailableCallback( 578116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&TranslateHelper::OnCldDataAvailable, 579116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch weak_method_factory_.GetWeakPtr())); 580116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 581116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 582116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Else, make an asynchronous request to get the data we need. 583116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cld_data_provider_->SendCldDataRequest(); 584effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 585effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // ... and enqueue another delayed task to call again. This will start a 586effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // chain of polling that will last until the pointer stops being NULL, 587effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // which is the right thing to do. 588effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // NB: In the great majority of cases, the data file will be available and 589effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // the very first delayed task will be a no-op that terminates the chain. 590effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // It's only while downloading the file that this will chain for a 591effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // nontrivial amount of time. 592effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Use a weak pointer to avoid keeping this helper object around forever. 593effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::MessageLoop::current()->PostDelayedTask( 594effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 595116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&TranslateHelper::SendCldDataRequest, 596effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch weak_method_factory_.GetWeakPtr(), 597116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch next_delay_millis, 598116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch next_delay_millis), 599effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::TimeDelta::FromMilliseconds(delay_millis)); 600effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 601effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 602116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TranslateHelper::OnCldDataAvailable() { 603116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (deferred_page_capture_) { 604effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch deferred_page_capture_ = false; // Don't do this a second time. 605116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PageCapturedImpl(deferred_page_seq_no_, deferred_contents_); 606116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch deferred_page_seq_no_ = -1; // Clean up for sanity 607effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch deferred_contents_.clear(); // Clean up for sanity 608effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 609effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 610effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 611116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TranslateHelper::RecordLanguageDetectionTiming( 612116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LanguageDetectionTiming timing) { 613116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // The following comment is copied from page_load_histograms.cc, and applies 614116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // just as equally here: 615116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // 616116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Since there are currently no guarantees that renderer histograms will be 617116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // sent to the browser, we initiate a PostTask here to be sure that we send 618116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // the histograms we generated. Without this call, pages that don't have an 619116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // on-close-handler might generate data that is lost when the renderer is 620116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // shutdown abruptly (perchance because the user closed the tab). 621116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DVLOG(1) << "Language detection timing: " << timing; 622116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch UMA_HISTOGRAM_ENUMERATION("Translate.LanguageDetectionTiming", timing, 623116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LANGUAGE_DETECTION_TIMING_MAX_VALUE); 624116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 625116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Note on performance: Under normal circumstances, this should get called 626116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // once per page load. The code will either manage to do it ON_TIME or will 627116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // be DEFERRED until CLD is ready. In the latter case, CLD is in dynamic mode 628116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // and may eventually become available, triggering the RESUMED event; after 629116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // this, everything should start being ON_TIME. This should never run more 630116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // than twice in a page load, under any conditions. 631116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Also note that language detection is triggered off of a delay AFTER the 632116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // page load completed event has fired, making this very much off the critical 633116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // path. 634116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch content::RenderThread::Get()->UpdateHistograms( 635116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch content::kHistogramSynchronizerReservedSequenceNumber); 636effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 6371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace translate 639