| 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 |