Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Side by Side Diff: chrome/renderer/translate/translate_helper.cc

Issue 333603002: Modularize Compact Language Detector 2 (CLD2) data sources (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use base/memory/scoped_ptr.h, not base/scoped_ptr.h Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/renderer/translate/translate_helper.h" 5 #include "chrome/renderer/translate/translate_helper.h"
6 6
7 #if defined(CLD2_DYNAMIC_MODE)
8 #include <stdint.h>
9 #endif
10
11 #include "base/bind.h" 7 #include "base/bind.h"
12 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
13 #if defined(CLD2_DYNAMIC_MODE)
14 #include "base/files/memory_mapped_file.h"
15 #endif
16 #include "base/logging.h" 9 #include "base/logging.h"
17 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop.h"
18 #include "base/strings/string16.h" 11 #include "base/strings/string16.h"
19 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
21 #include "chrome/renderer/isolated_world_ids.h" 14 #include "chrome/renderer/isolated_world_ids.h"
22 #include "components/translate/content/common/translate_messages.h" 15 #include "components/translate/content/common/translate_messages.h"
23 #include "components/translate/core/common/translate_constants.h" 16 #include "components/translate/core/common/translate_constants.h"
24 #include "components/translate/core/common/translate_metrics.h" 17 #include "components/translate/core/common/translate_metrics.h"
25 #include "components/translate/core/common/translate_util.h" 18 #include "components/translate/core/common/translate_util.h"
26 #include "components/translate/core/language_detection/language_detection_util.h " 19 #include "components/translate/core/language_detection/language_detection_util.h "
27 #include "content/public/renderer/render_view.h" 20 #include "content/public/renderer/render_view.h"
28 #include "extensions/common/constants.h" 21 #include "extensions/common/constants.h"
29 #include "extensions/renderer/extension_groups.h" 22 #include "extensions/renderer/extension_groups.h"
30 #include "ipc/ipc_platform_file.h" 23 #include "ipc/ipc_platform_file.h"
31 #if defined(CLD2_DYNAMIC_MODE)
32 #include "content/public/common/url_constants.h" 24 #include "content/public/common/url_constants.h"
33 #include "third_party/cld_2/src/public/compact_lang_det.h"
34 #endif
35 #include "third_party/WebKit/public/web/WebDocument.h" 25 #include "third_party/WebKit/public/web/WebDocument.h"
36 #include "third_party/WebKit/public/web/WebElement.h" 26 #include "third_party/WebKit/public/web/WebElement.h"
37 #include "third_party/WebKit/public/web/WebFrame.h" 27 #include "third_party/WebKit/public/web/WebFrame.h"
38 #include "third_party/WebKit/public/web/WebNode.h" 28 #include "third_party/WebKit/public/web/WebNode.h"
39 #include "third_party/WebKit/public/web/WebNodeList.h" 29 #include "third_party/WebKit/public/web/WebNodeList.h"
40 #include "third_party/WebKit/public/web/WebScriptSource.h" 30 #include "third_party/WebKit/public/web/WebScriptSource.h"
41 #include "third_party/WebKit/public/web/WebView.h" 31 #include "third_party/WebKit/public/web/WebView.h"
42 #include "third_party/WebKit/public/web/WebWidget.h" 32 #include "third_party/WebKit/public/web/WebWidget.h"
43 #include "url/gurl.h" 33 #include "url/gurl.h"
44 #include "v8/include/v8.h" 34 #include "v8/include/v8.h"
(...skipping 23 matching lines...) Expand all
68 // The delay we wait in milliseconds before checking whether the translation has 58 // The delay we wait in milliseconds before checking whether the translation has
69 // finished. 59 // finished.
70 const int kTranslateStatusCheckDelayMs = 400; 60 const int kTranslateStatusCheckDelayMs = 400;
71 61
72 // Language name passed to the Translate element for it to detect the language. 62 // Language name passed to the Translate element for it to detect the language.
73 const char kAutoDetectionLanguage[] = "auto"; 63 const char kAutoDetectionLanguage[] = "auto";
74 64
75 // Isolated world sets following content-security-policy. 65 // Isolated world sets following content-security-policy.
76 const char kContentSecurityPolicy[] = "script-src 'self' 'unsafe-eval'"; 66 const char kContentSecurityPolicy[] = "script-src 'self' 'unsafe-eval'";
77 67
68 // Whether or not we have set the CLD callback yet.
69 bool cld_callback_set = false;
Takashi Toyoshima 2014/06/23 08:50:01 g_cld_callback_set
Andrew Hayden (chromium.org) 2014/06/23 13:20:36 Done.
70
78 } // namespace 71 } // namespace
79 72
80 #if defined(CLD2_DYNAMIC_MODE)
81 // The mmap for the CLD2 data must be held forever once it is available in the
82 // process. This is declared static in the translate_helper.h.
83 base::LazyInstance<TranslateHelper::CLDMmapWrapper>::Leaky
84 TranslateHelper::s_cld_mmap_ = LAZY_INSTANCE_INITIALIZER;
85 #endif
86 73
87 //////////////////////////////////////////////////////////////////////////////// 74 ////////////////////////////////////////////////////////////////////////////////
88 // TranslateHelper, public: 75 // TranslateHelper, public:
89 // 76 //
90 TranslateHelper::TranslateHelper(content::RenderView* render_view) 77 TranslateHelper::TranslateHelper(content::RenderView* render_view)
91 : content::RenderViewObserver(render_view), 78 : content::RenderViewObserver(render_view),
92 page_id_(-1), 79 page_id_(-1),
93 translation_pending_(false), 80 translation_pending_(false),
94 weak_method_factory_(this) 81 weak_method_factory_(this),
95 #if defined(CLD2_DYNAMIC_MODE) 82 cld_data_provider_(translate::CreateRendererCldDataProviderFor(this)),
96 ,cld2_data_file_polling_started_(false), 83 cld_data_polling_started_(false),
97 cld2_data_file_polling_canceled_(false), 84 cld_data_polling_canceled_(false),
98 deferred_page_capture_(false), 85 deferred_page_capture_(false),
99 deferred_page_id_(-1), 86 deferred_page_id_(-1),
100 deferred_contents_(ASCIIToUTF16("")) 87 deferred_contents_(ASCIIToUTF16("")) {
101 #endif
102 {
103 } 88 }
104 89
105 TranslateHelper::~TranslateHelper() { 90 TranslateHelper::~TranslateHelper() {
106 CancelPendingTranslation(); 91 CancelPendingTranslation();
107 #if defined(CLD2_DYNAMIC_MODE) 92 CancelCldDataPolling();
108 CancelCLD2DataFilePolling();
109 #endif
110 } 93 }
111 94
112 void TranslateHelper::PrepareForUrl(const GURL& url) { 95 void TranslateHelper::PrepareForUrl(const GURL& url) {
113 #if defined(CLD2_DYNAMIC_MODE)
114 deferred_page_capture_ = false; 96 deferred_page_capture_ = false;
115 deferred_contents_.clear(); 97 deferred_contents_.clear();
116 if (cld2_data_file_polling_started_) 98 if (cld_data_polling_started_)
117 return; 99 return;
118 100
119 // TODO(andrewhayden): Refactor translate_manager.cc's IsTranslatableURL to 101 // TODO(andrewhayden): Refactor translate_manager.cc's IsTranslatableURL to
Andrew Hayden (chromium.org) 2014/06/21 07:40:28 This is biting us: the chromeos bots are failing w
droger 2014/06/23 08:31:31 I don't think this can go in components/translate/
Andrew Hayden (chromium.org) 2014/06/23 13:20:36 Talked with Takashi about this, see below.
120 // components/translate/core/common/translate_util.cc, and ignore any URL 102 // components/translate/core/common/translate_util.cc, and ignore any URL
121 // that fails that check. This will require moving unit tests and rewiring 103 // that fails that check. This will require moving unit tests and rewiring
122 // other function calls as well, so for now replicate the logic here. 104 // other function calls as well, so for now replicate the logic here.
123 if (url.is_empty()) 105 if (url.is_empty())
124 return; 106 return;
125 if (url.SchemeIs(content::kChromeUIScheme)) 107 if (url.SchemeIs(content::kChromeUIScheme))
126 return; 108 return;
127 if (url.SchemeIs(content::kChromeDevToolsScheme)) 109 if (url.SchemeIs(content::kChromeDevToolsScheme))
128 return; 110 return;
129 if (url.SchemeIs(url::kFtpScheme)) 111 if (url.SchemeIs(url::kFtpScheme))
130 return; 112 return;
131 #if defined(OS_CHROMEOS) 113 #if defined(OS_CHROMEOS)
132 if (url.SchemeIs(extensions::kExtensionScheme) && 114 if (url.SchemeIs(extensions::kExtensionScheme) &&
Takashi Toyoshima 2014/06/23 08:50:01 I guess other native extensions should not be tran
Andrew Hayden (chromium.org) 2014/06/23 13:20:36 Agreed after offline discussion, I've removed the
133 url.DomainIs(file_manager::kFileManagerAppId)) 115 url.DomainIs(file_manager::kFileManagerAppId))
134 return; 116 return;
135 #endif 117 #endif
136 118
137 // Start polling for CLD data. 119 // Start polling for CLD data.
138 cld2_data_file_polling_started_ = true; 120 cld_data_polling_started_ = true;
139 TranslateHelper::SendCLD2DataFileRequest(0, 1000); 121 TranslateHelper::SendCldDataRequest(0, 1000);
140 #endif
141 } 122 }
142 123
143 #if defined(CLD2_DYNAMIC_MODE)
144 void TranslateHelper::DeferPageCaptured(const int page_id, 124 void TranslateHelper::DeferPageCaptured(const int page_id,
145 const base::string16& contents) { 125 const base::string16& contents) {
146 deferred_page_capture_ = true; 126 deferred_page_capture_ = true;
147 deferred_page_id_ = page_id; 127 deferred_page_id_ = page_id;
148 deferred_contents_ = contents; 128 deferred_contents_ = contents;
149 } 129 }
150 #endif
151 130
152 void TranslateHelper::PageCaptured(int page_id, 131 void TranslateHelper::PageCaptured(int page_id,
153 const base::string16& contents) { 132 const base::string16& contents) {
154 // Get the document language as set by WebKit from the http-equiv 133 // Get the document language as set by WebKit from the http-equiv
155 // meta tag for "content-language". This may or may not also 134 // meta tag for "content-language". This may or may not also
156 // have a value derived from the actual Content-Language HTTP 135 // have a value derived from the actual Content-Language HTTP
157 // header. The two actually have different meanings (despite the 136 // header. The two actually have different meanings (despite the
158 // original intent of http-equiv to be an equivalent) with the former 137 // original intent of http-equiv to be an equivalent) with the former
159 // being the language of the document and the latter being the 138 // being the language of the document and the latter being the
160 // language of the intended audience (a distinction really only 139 // language of the intended audience (a distinction really only
161 // relevant for things like langauge textbooks). This distinction 140 // relevant for things like langauge textbooks). This distinction
162 // shouldn't affect translation. 141 // shouldn't affect translation.
163 WebFrame* main_frame = GetMainFrame(); 142 WebFrame* main_frame = GetMainFrame();
164 if (!main_frame || render_view()->GetPageId() != page_id) 143 if (!main_frame || render_view()->GetPageId() != page_id)
165 return; 144 return;
166 145
167 // TODO(andrewhayden): UMA insertion point here: Track if data is available. 146 // TODO(andrewhayden): UMA insertion point here: Track if data is available.
168 // TODO(andrewhayden): Retry insertion point here, retry till data available. 147 // TODO(andrewhayden): Retry insertion point here, retry till data available.
169 #if defined(CLD2_DYNAMIC_MODE) 148 if (!cld_data_provider_->IsCldDataAvailable()) {
170 if (!CLD2::isDataLoaded()) {
171 // We're in dynamic mode and CLD data isn't loaded. Retry when CLD data 149 // We're in dynamic mode and CLD data isn't loaded. Retry when CLD data
172 // is loaded, if ever. 150 // is loaded, if ever.
173 TranslateHelper::DeferPageCaptured(page_id, contents); 151 TranslateHelper::DeferPageCaptured(page_id, contents);
174 return; 152 return;
175 } 153 }
176 #endif 154
177 page_id_ = page_id; 155 page_id_ = page_id;
178 WebDocument document = main_frame->document(); 156 WebDocument document = main_frame->document();
179 std::string content_language = document.contentLanguage().utf8(); 157 std::string content_language = document.contentLanguage().utf8();
180 WebElement html_element = document.documentElement(); 158 WebElement html_element = document.documentElement();
181 std::string html_lang; 159 std::string html_lang;
182 // |html_element| can be null element, e.g. in 160 // |html_element| can be null element, e.g. in
183 // BrowserTest.WindowOpenClose. 161 // BrowserTest.WindowOpenClose.
184 if (!html_element.isNull()) 162 if (!html_element.isNull())
185 html_lang = html_element.getAttribute("lang").utf8(); 163 html_lang = html_element.getAttribute("lang").utf8();
186 std::string cld_language; 164 std::string cld_language;
(...skipping 24 matching lines...) Expand all
211 routing_id(), 189 routing_id(),
212 details, 190 details,
213 IsTranslationAllowed(&document) && !language.empty())); 191 IsTranslationAllowed(&document) && !language.empty()));
214 } 192 }
215 193
216 void TranslateHelper::CancelPendingTranslation() { 194 void TranslateHelper::CancelPendingTranslation() {
217 weak_method_factory_.InvalidateWeakPtrs(); 195 weak_method_factory_.InvalidateWeakPtrs();
218 translation_pending_ = false; 196 translation_pending_ = false;
219 source_lang_.clear(); 197 source_lang_.clear();
220 target_lang_.clear(); 198 target_lang_.clear();
221 #if defined(CLD2_DYNAMIC_MODE) 199 CancelCldDataPolling();
222 CancelCLD2DataFilePolling();
223 #endif
224 } 200 }
225 201
226 //////////////////////////////////////////////////////////////////////////////// 202 ////////////////////////////////////////////////////////////////////////////////
227 // TranslateHelper, protected: 203 // TranslateHelper, protected:
228 // 204 //
229 bool TranslateHelper::IsTranslateLibAvailable() { 205 bool TranslateHelper::IsTranslateLibAvailable() {
230 return ExecuteScriptAndGetBoolResult( 206 return ExecuteScriptAndGetBoolResult(
231 "typeof cr != 'undefined' && typeof cr.googleTranslate != 'undefined' && " 207 "typeof cr != 'undefined' && typeof cr.googleTranslate != 'undefined' && "
232 "typeof cr.googleTranslate.translate == 'function'", false); 208 "typeof cr.googleTranslate.translate == 'function'", false);
233 } 209 }
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 return false; 364 return false;
389 } 365 }
390 return true; 366 return true;
391 } 367 }
392 368
393 bool TranslateHelper::OnMessageReceived(const IPC::Message& message) { 369 bool TranslateHelper::OnMessageReceived(const IPC::Message& message) {
394 bool handled = true; 370 bool handled = true;
395 IPC_BEGIN_MESSAGE_MAP(TranslateHelper, message) 371 IPC_BEGIN_MESSAGE_MAP(TranslateHelper, message)
396 IPC_MESSAGE_HANDLER(ChromeViewMsg_TranslatePage, OnTranslatePage) 372 IPC_MESSAGE_HANDLER(ChromeViewMsg_TranslatePage, OnTranslatePage)
397 IPC_MESSAGE_HANDLER(ChromeViewMsg_RevertTranslation, OnRevertTranslation) 373 IPC_MESSAGE_HANDLER(ChromeViewMsg_RevertTranslation, OnRevertTranslation)
398 #if defined(CLD2_DYNAMIC_MODE)
399 IPC_MESSAGE_HANDLER(ChromeViewMsg_CLDDataAvailable, OnCLDDataAvailable);
400 #endif
401 IPC_MESSAGE_UNHANDLED(handled = false) 374 IPC_MESSAGE_UNHANDLED(handled = false)
402 IPC_END_MESSAGE_MAP() 375 IPC_END_MESSAGE_MAP()
376 if (!handled) {
377 if (!cld_callback_set) {
Takashi Toyoshima 2014/06/23 08:50:01 Hum.... setting a callback inside this message han
Andrew Hayden (chromium.org) 2014/06/23 13:20:36 Done.
378 cld_callback_set = true;
379 cld_data_provider_->SetCldAvailableCallback(
380 base::Bind(&TranslateHelper::OnCldDataAvailable,
381 weak_method_factory_.GetWeakPtr()));
382 }
383 handled = cld_data_provider_->OnMessageReceived(message);
384 }
403 return handled; 385 return handled;
404 } 386 }
405 387
406 void TranslateHelper::OnTranslatePage(int page_id, 388 void TranslateHelper::OnTranslatePage(int page_id,
407 const std::string& translate_script, 389 const std::string& translate_script,
408 const std::string& source_lang, 390 const std::string& source_lang,
409 const std::string& target_lang) { 391 const std::string& target_lang) {
410 WebFrame* main_frame = GetMainFrame(); 392 WebFrame* main_frame = GetMainFrame();
411 if (!main_frame || 393 if (!main_frame ||
412 page_id_ != page_id || 394 page_id_ != page_id ||
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 WebFrame* TranslateHelper::GetMainFrame() { 563 WebFrame* TranslateHelper::GetMainFrame() {
582 WebView* web_view = render_view()->GetWebView(); 564 WebView* web_view = render_view()->GetWebView();
583 565
584 // When the tab is going to be closed, the web_view can be NULL. 566 // When the tab is going to be closed, the web_view can be NULL.
585 if (!web_view) 567 if (!web_view)
586 return NULL; 568 return NULL;
587 569
588 return web_view->mainFrame(); 570 return web_view->mainFrame();
589 } 571 }
590 572
591 #if defined(CLD2_DYNAMIC_MODE) 573 void TranslateHelper::CancelCldDataPolling() {
592 void TranslateHelper::CancelCLD2DataFilePolling() { 574 cld_data_polling_canceled_ = true;
593 cld2_data_file_polling_canceled_ = true;
594 } 575 }
595 576
596 void TranslateHelper::SendCLD2DataFileRequest(const int delay_millis, 577 void TranslateHelper::SendCldDataRequest(const int delay_millis,
597 const int next_delay_millis) { 578 const int next_delay_millis) {
598 // Terminate immediately if told to stop polling. 579 // Terminate immediately if told to stop polling.
599 if (cld2_data_file_polling_canceled_) 580 if (cld_data_polling_canceled_)
600 return; 581 return;
601 582
602 // Terminate immediately if data is already loaded. 583 // Terminate immediately if data is already loaded.
603 if (CLD2::isDataLoaded()) 584 if (cld_data_provider_->IsCldDataAvailable())
604 return; 585 return;
605 586
606 // Else, send the IPC message to the browser process requesting the data... 587 // Else, make an asynchronous request to get the data we need.
Takashi Toyoshima 2014/06/23 08:50:01 As a commented above, you may be able to set the c
Andrew Hayden (chromium.org) 2014/06/23 13:20:36 Done.
607 Send(new ChromeViewHostMsg_NeedCLDData(routing_id())); 588 cld_data_provider_->SendCldDataRequest();
608 589
609 // ... and enqueue another delayed task to call again. This will start a 590 // ... and enqueue another delayed task to call again. This will start a
610 // chain of polling that will last until the pointer stops being NULL, 591 // chain of polling that will last until the pointer stops being NULL,
611 // which is the right thing to do. 592 // which is the right thing to do.
612 // NB: In the great majority of cases, the data file will be available and 593 // NB: In the great majority of cases, the data file will be available and
613 // the very first delayed task will be a no-op that terminates the chain. 594 // the very first delayed task will be a no-op that terminates the chain.
614 // It's only while downloading the file that this will chain for a 595 // It's only while downloading the file that this will chain for a
615 // nontrivial amount of time. 596 // nontrivial amount of time.
616 // Use a weak pointer to avoid keeping this helper object around forever. 597 // Use a weak pointer to avoid keeping this helper object around forever.
617 base::MessageLoop::current()->PostDelayedTask( 598 base::MessageLoop::current()->PostDelayedTask(
618 FROM_HERE, 599 FROM_HERE,
619 base::Bind(&TranslateHelper::SendCLD2DataFileRequest, 600 base::Bind(&TranslateHelper::SendCldDataRequest,
620 weak_method_factory_.GetWeakPtr(), 601 weak_method_factory_.GetWeakPtr(),
621 next_delay_millis, next_delay_millis), 602 next_delay_millis, next_delay_millis),
622 base::TimeDelta::FromMilliseconds(delay_millis)); 603 base::TimeDelta::FromMilliseconds(delay_millis));
623 } 604 }
624 605
625 void TranslateHelper::OnCLDDataAvailable( 606 void TranslateHelper::OnCldDataAvailable() {
626 const IPC::PlatformFileForTransit ipc_file_handle, 607 if (deferred_page_capture_) {
627 const uint64 data_offset,
628 const uint64 data_length) {
629 LoadCLDDData(IPC::PlatformFileForTransitToFile(ipc_file_handle), data_offset,
630 data_length);
631 if (deferred_page_capture_ && CLD2::isDataLoaded()) {
632 deferred_page_capture_ = false; // Don't do this a second time. 608 deferred_page_capture_ = false; // Don't do this a second time.
633 PageCaptured(deferred_page_id_, deferred_contents_); 609 PageCaptured(deferred_page_id_, deferred_contents_);
634 deferred_page_id_ = -1; // Clean up for sanity 610 deferred_page_id_ = -1; // Clean up for sanity
635 deferred_contents_.clear(); // Clean up for sanity 611 deferred_contents_.clear(); // Clean up for sanity
636 } 612 }
637 } 613 }
638
639 void TranslateHelper::LoadCLDDData(
640 base::File file,
641 const uint64 data_offset,
642 const uint64 data_length) {
643 // Terminate immediately if told to stop polling.
644 if (cld2_data_file_polling_canceled_)
645 return;
646
647 // Terminate immediately if data is already loaded.
648 if (CLD2::isDataLoaded())
649 return;
650
651 if (!file.IsValid()) {
652 LOG(ERROR) << "Can't find the CLD data file.";
653 return;
654 }
655
656 // mmap the file
657 s_cld_mmap_.Get().value = new base::MemoryMappedFile();
658 bool initialized = s_cld_mmap_.Get().value->Initialize(file.Pass());
659 if (!initialized) {
660 LOG(ERROR) << "mmap initialization failed";
661 delete s_cld_mmap_.Get().value;
662 s_cld_mmap_.Get().value = NULL;
663 return;
664 }
665
666 // Sanity checks
667 uint64 max_int32 = std::numeric_limits<int32>::max();
668 if (data_length + data_offset > s_cld_mmap_.Get().value->length()
669 || data_length > max_int32) { // max signed 32 bit integer
670 LOG(ERROR) << "Illegal mmap config: data_offset="
671 << data_offset << ", data_length=" << data_length
672 << ", mmap->length()=" << s_cld_mmap_.Get().value->length();
673 delete s_cld_mmap_.Get().value;
674 s_cld_mmap_.Get().value = NULL;
675 return;
676 }
677
678 // Initialize the CLD subsystem... and it's all done!
679 const uint8* data_ptr = s_cld_mmap_.Get().value->data() + data_offset;
680 CLD2::loadDataFromRawAddress(data_ptr, data_length);
681 DCHECK(CLD2::isDataLoaded()) << "Failed to load CLD data from mmap";
682 }
683 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698