OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 #ifndef CHROME_RENDERER_TRANSLATE_TRANSLATE_HELPER_H_ | |
6 #define CHROME_RENDERER_TRANSLATE_TRANSLATE_HELPER_H_ | |
7 | |
8 #include <string> | |
9 | |
10 #include "base/gtest_prod_util.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/memory/weak_ptr.h" | |
13 #include "base/strings/string16.h" | |
14 #include "base/time/time.h" | |
15 #include "components/translate/content/renderer/renderer_cld_data_provider.h" | |
16 #include "components/translate/core/common/translate_errors.h" | |
17 #include "content/public/renderer/render_view_observer.h" | |
18 #include "url/gurl.h" | |
19 | |
20 namespace blink { | |
21 class WebDocument; | |
22 class WebFrame; | |
23 } | |
24 | |
25 namespace content { | |
26 class RendererCldDataProvider; | |
27 } | |
28 | |
29 // This class deals with page translation. | |
30 // There is one TranslateHelper per RenderView. | |
31 // | |
32 // This class provides metrics that allow tracking the user experience impact | |
33 // of non-static CldDataProvider implementations. For background on the data | |
34 // providers, please refer to the following documentation: | |
35 // http://www.chromium.org/developers/how-tos/compact-language-detector-cld-data
-source-configuration | |
36 // | |
37 // Available metrics (from the LanguageDetectionTiming enum): | |
38 // 1. ON_TIME | |
39 // Recorded if PageCaptured(...) is invoked after CLD is available. This is | |
40 // the ideal case, indicating that CLD is available before it is needed. | |
41 // 2. DEFERRED | |
42 // Recorded if PageCaptured(...) is invoked before CLD is available. | |
43 // Sub-optimal case indicating that CLD wasn't available when it was needed, | |
44 // so the request for detection has been deferred until CLD is available or | |
45 // until the user navigates to a different page. | |
46 // 3. RESUMED | |
47 // Recorded if CLD becomes available after a language detection request was | |
48 // deferred, but before the user navigated to a different page. Language | |
49 // detection is ultimately completed, it just didn't happen on time. | |
50 // | |
51 // Note that there is NOT a metric that records the number of times that | |
52 // language detection had to be aborted because CLD never became available in | |
53 // time. This is because there is no reasonable way to cover all the cases | |
54 // under which this could occur, particularly the destruction of the renderer | |
55 // for which this object was created. However, this value can be synthetically | |
56 // derived, using the logic below. | |
57 // | |
58 // Every page load that triggers language detection will result in the | |
59 // recording of exactly one of the first two events: ON_TIME or DEFERRED. If | |
60 // CLD is available in time to satisfy the request, the third event (RESUMED) | |
61 // will be recorded; thus, the number of times when language detection | |
62 // ultimately fails because CLD isn't ever available is implied as the number of | |
63 // times that detection is deferred minus the number of times that language | |
64 // detection is late: | |
65 // | |
66 // count(FAILED) ~= count(DEFERRED) - count(RESUMED) | |
67 // | |
68 // Note that this is not 100% accurate: some renderer process are so short-lived | |
69 // that language detection wouldn't have been relevant anyway, and so a failure | |
70 // to detect the language in a timely manner might be completely innocuous. The | |
71 // overall problem with language detection is that it isn't possible to know | |
72 // whether it was required or not until after it has been performed! | |
73 // | |
74 // We use histograms for recording these metrics. On Android, the renderer can | |
75 // be killed without the chance to clean up or transmit these histograms, | |
76 // leading to dropped metrics. To work around this, this method forces an IPC | |
77 // message to be sent to the browser process immediately. | |
78 class TranslateHelper : public content::RenderViewObserver { | |
79 public: | |
80 explicit TranslateHelper(content::RenderView* render_view); | |
81 virtual ~TranslateHelper(); | |
82 | |
83 // Informs us that the page's text has been extracted. | |
84 void PageCaptured(const base::string16& contents); | |
85 | |
86 // Lets the translation system know that we are preparing to navigate to | |
87 // the specified URL. If there is anything that can or should be done before | |
88 // this URL loads, this is the time to prepare for it. | |
89 void PrepareForUrl(const GURL& url); | |
90 | |
91 protected: | |
92 // The following methods are protected so they can be overridden in | |
93 // unit-tests. | |
94 void OnTranslatePage(int page_seq_no, | |
95 const std::string& translate_script, | |
96 const std::string& source_lang, | |
97 const std::string& target_lang); | |
98 void OnRevertTranslation(int page_seq_no); | |
99 | |
100 // Returns true if the translate library is available, meaning the JavaScript | |
101 // has already been injected in that page. | |
102 virtual bool IsTranslateLibAvailable(); | |
103 | |
104 // Returns true if the translate library has been initialized successfully. | |
105 virtual bool IsTranslateLibReady(); | |
106 | |
107 // Returns true if the translation script has finished translating the page. | |
108 virtual bool HasTranslationFinished(); | |
109 | |
110 // Returns true if the translation script has reported an error performing the | |
111 // translation. | |
112 virtual bool HasTranslationFailed(); | |
113 | |
114 // Starts the translation by calling the translate library. This method | |
115 // should only be called when the translate script has been injected in the | |
116 // page. Returns false if the call failed immediately. | |
117 virtual bool StartTranslation(); | |
118 | |
119 // Asks the Translate element in the page what the language of the page is. | |
120 // Can only be called if a translation has happened and was successful. | |
121 // Returns the language code on success, an empty string on failure. | |
122 virtual std::string GetOriginalPageLanguage(); | |
123 | |
124 // Adjusts a delay time for a posted task. This is used in tests to do tasks | |
125 // immediately by returning 0. | |
126 virtual base::TimeDelta AdjustDelay(int delayInMs); | |
127 | |
128 // Executes the JavaScript code in |script| in the main frame of RenderView. | |
129 virtual void ExecuteScript(const std::string& script); | |
130 | |
131 // Executes the JavaScript code in |script| in the main frame of RenderView, | |
132 // and returns the boolean returned by the script evaluation if the script was | |
133 // run successfully. Otherwise, returns |fallback| value. | |
134 virtual bool ExecuteScriptAndGetBoolResult(const std::string& script, | |
135 bool fallback); | |
136 | |
137 // Executes the JavaScript code in |script| in the main frame of RenderView, | |
138 // and returns the string returned by the script evaluation if the script was | |
139 // run successfully. Otherwise, returns empty string. | |
140 virtual std::string ExecuteScriptAndGetStringResult( | |
141 const std::string& script); | |
142 | |
143 // Executes the JavaScript code in |script| in the main frame of RenderView. | |
144 // and returns the number returned by the script evaluation if the script was | |
145 // run successfully. Otherwise, returns 0.0. | |
146 virtual double ExecuteScriptAndGetDoubleResult(const std::string& script); | |
147 | |
148 private: | |
149 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, AdoptHtmlLang); | |
150 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, | |
151 CLDAgreeWithLanguageCodeHavingCountryCode); | |
152 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, | |
153 CLDDisagreeWithWrongLanguageCode); | |
154 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, | |
155 InvalidLanguageMetaTagProviding); | |
156 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, LanguageCodeTypoCorrection); | |
157 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, LanguageCodeSynonyms); | |
158 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, ResetInvalidLanguageCode); | |
159 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, SimilarLanguageCode); | |
160 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, WellKnownWrongConfiguration); | |
161 | |
162 enum LanguageDetectionTiming { | |
163 ON_TIME, // Language detection was performed as soon as it was requested | |
164 DEFERRED, // Language detection couldn't be performed when it was requested | |
165 RESUMED, // A deferred language detection attempt was completed later | |
166 LANGUAGE_DETECTION_TIMING_MAX_VALUE // The bounding value for this enum | |
167 }; | |
168 | |
169 // Converts language code to the one used in server supporting list. | |
170 static void ConvertLanguageCodeSynonym(std::string* code); | |
171 | |
172 // Returns whether the page associated with |document| is a candidate for | |
173 // translation. Some pages can explictly specify (via a meta-tag) that they | |
174 // should not be translated. | |
175 static bool IsTranslationAllowed(blink::WebDocument* document); | |
176 | |
177 // RenderViewObserver implementation. | |
178 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; | |
179 | |
180 // Informs us that the page's text has been extracted. | |
181 void PageCapturedImpl(int page_seq_no, const base::string16& contents); | |
182 | |
183 // Cancels any translation that is currently being performed. This does not | |
184 // revert existing translations. | |
185 void CancelPendingTranslation(); | |
186 | |
187 // Checks if the current running page translation is finished or errored and | |
188 // notifies the browser accordingly. If the translation has not terminated, | |
189 // posts a task to check again later. | |
190 void CheckTranslateStatus(int page_seq_no); | |
191 | |
192 // Called by TranslatePage to do the actual translation. |count| is used to | |
193 // limit the number of retries. | |
194 void TranslatePageImpl(int page_seq_no, int count); | |
195 | |
196 // Sends a message to the browser to notify it that the translation failed | |
197 // with |error|. | |
198 void NotifyBrowserTranslationFailed(translate::TranslateErrors::Type error); | |
199 | |
200 // Convenience method to access the main frame. Can return NULL, typically | |
201 // if the page is being closed. | |
202 blink::WebFrame* GetMainFrame(); | |
203 | |
204 // Do not ask for CLD data any more. | |
205 void CancelCldDataPolling(); | |
206 | |
207 // Invoked when PageCaptured is called prior to obtaining CLD data. This | |
208 // method stores the page ID into deferred_page_id_ and COPIES the contents | |
209 // of the page, then sets deferred_page_capture_ to true. When CLD data is | |
210 // eventually received (in OnCldDataAvailable), any deferred request will be | |
211 // "resurrected" and allowed to proceed automatically, assuming that the | |
212 // page ID has not changed. | |
213 void DeferPageCaptured(const int page_id, const base::string16& contents); | |
214 | |
215 // Start polling for CLD data. | |
216 // Polling will automatically halt as soon as the renderer obtains a | |
217 // reference to the data file. | |
218 void SendCldDataRequest(const int delay_millis, const int next_delay_millis); | |
219 | |
220 // Callback triggered when CLD data becomes available. | |
221 void OnCldDataAvailable(); | |
222 | |
223 // Record the timing of language detection, immediately sending an IPC-based | |
224 // histogram delta update to the browser process in case the hosting renderer | |
225 // process terminates before the metrics would otherwise be transferred. | |
226 void RecordLanguageDetectionTiming(LanguageDetectionTiming timing); | |
227 | |
228 // An ever-increasing sequence number of the current page, used to match up | |
229 // translation requests with responses. | |
230 int page_seq_no_; | |
231 | |
232 // The states associated with the current translation. | |
233 bool translation_pending_; | |
234 std::string source_lang_; | |
235 std::string target_lang_; | |
236 | |
237 // Time when a page langauge is determined. This is used to know a duration | |
238 // time from showing infobar to requesting translation. | |
239 base::TimeTicks language_determined_time_; | |
240 | |
241 // Provides CLD data for this process. | |
242 scoped_ptr<translate::RendererCldDataProvider> cld_data_provider_; | |
243 | |
244 // Whether or not polling for CLD2 data has started. | |
245 bool cld_data_polling_started_; | |
246 | |
247 // Whether or not CancelCldDataPolling has been called. | |
248 bool cld_data_polling_canceled_; | |
249 | |
250 // Whether or not a PageCaptured event arrived prior to CLD data becoming | |
251 // available. If true, deferred_contents_ contains the most recent contents. | |
252 bool deferred_page_capture_; | |
253 | |
254 // The ID of the page most recently reported to PageCaptured if | |
255 // deferred_page_capture_ is true. | |
256 int deferred_page_seq_no_; | |
257 | |
258 // The contents of the page most recently reported to PageCaptured if | |
259 // deferred_page_capture_ is true. | |
260 base::string16 deferred_contents_; | |
261 | |
262 // Method factory used to make calls to TranslatePageImpl. | |
263 base::WeakPtrFactory<TranslateHelper> weak_method_factory_; | |
264 | |
265 DISALLOW_COPY_AND_ASSIGN(TranslateHelper); | |
266 }; | |
267 | |
268 #endif // CHROME_RENDERER_TRANSLATE_TRANSLATE_HELPER_H_ | |
OLD | NEW |