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/weak_ptr.h" 12 #include "base/strings/string16.h" 13 #include "base/time/time.h" 14 #include "components/translate/core/common/translate_errors.h" 15 #include "content/public/renderer/render_view_observer.h" 16 17 #if defined(CLD2_DYNAMIC_MODE) 18 #include "base/files/file.h" 19 #include "base/files/memory_mapped_file.h" 20 #include "base/lazy_instance.h" 21 #include "ipc/ipc_platform_file.h" 22 #include "url/gurl.h" 23 #endif 24 25 namespace blink { 26 class WebDocument; 27 class WebFrame; 28 } 29 30 // This class deals with page translation. 31 // There is one TranslateHelper per RenderView. 32 33 class TranslateHelper : public content::RenderViewObserver { 34 public: 35 explicit TranslateHelper(content::RenderView* render_view); 36 virtual ~TranslateHelper(); 37 38 // Informs us that the page's text has been extracted. 39 void PageCaptured(int page_id, const base::string16& contents); 40 41 // Lets the translation system know that we are preparing to navigate to 42 // the specified URL. If there is anything that can or should be done before 43 // this URL loads, this is the time to prepare for it. 44 void PrepareForUrl(const GURL& url); 45 46 protected: 47 // The following methods are protected so they can be overridden in 48 // unit-tests. 49 void OnTranslatePage(int page_id, 50 const std::string& translate_script, 51 const std::string& source_lang, 52 const std::string& target_lang); 53 void OnRevertTranslation(int page_id); 54 55 // Returns true if the translate library is available, meaning the JavaScript 56 // has already been injected in that page. 57 virtual bool IsTranslateLibAvailable(); 58 59 // Returns true if the translate library has been initialized successfully. 60 virtual bool IsTranslateLibReady(); 61 62 // Returns true if the translation script has finished translating the page. 63 virtual bool HasTranslationFinished(); 64 65 // Returns true if the translation script has reported an error performing the 66 // translation. 67 virtual bool HasTranslationFailed(); 68 69 // Starts the translation by calling the translate library. This method 70 // should only be called when the translate script has been injected in the 71 // page. Returns false if the call failed immediately. 72 virtual bool StartTranslation(); 73 74 // Asks the Translate element in the page what the language of the page is. 75 // Can only be called if a translation has happened and was successful. 76 // Returns the language code on success, an empty string on failure. 77 virtual std::string GetOriginalPageLanguage(); 78 79 // Adjusts a delay time for a posted task. This is used in tests to do tasks 80 // immediately by returning 0. 81 virtual base::TimeDelta AdjustDelay(int delayInMs); 82 83 // Executes the JavaScript code in |script| in the main frame of RenderView. 84 virtual void ExecuteScript(const std::string& script); 85 86 // Executes the JavaScript code in |script| in the main frame of RenderView, 87 // and returns the boolean returned by the script evaluation if the script was 88 // run successfully. Otherwise, returns |fallback| value. 89 virtual bool ExecuteScriptAndGetBoolResult(const std::string& script, 90 bool fallback); 91 92 // Executes the JavaScript code in |script| in the main frame of RenderView, 93 // and returns the string returned by the script evaluation if the script was 94 // run successfully. Otherwise, returns empty string. 95 virtual std::string ExecuteScriptAndGetStringResult( 96 const std::string& script); 97 98 // Executes the JavaScript code in |script| in the main frame of RenderView. 99 // and returns the number returned by the script evaluation if the script was 100 // run successfully. Otherwise, returns 0.0. 101 virtual double ExecuteScriptAndGetDoubleResult(const std::string& script); 102 103 private: 104 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, AdoptHtmlLang); 105 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, 106 CLDAgreeWithLanguageCodeHavingCountryCode); 107 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, 108 CLDDisagreeWithWrongLanguageCode); 109 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, 110 InvalidLanguageMetaTagProviding); 111 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, LanguageCodeTypoCorrection); 112 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, LanguageCodeSynonyms); 113 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, ResetInvalidLanguageCode); 114 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, SimilarLanguageCode); 115 FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, WellKnownWrongConfiguration); 116 117 // Converts language code to the one used in server supporting list. 118 static void ConvertLanguageCodeSynonym(std::string* code); 119 120 // Returns whether the page associated with |document| is a candidate for 121 // translation. Some pages can explictly specify (via a meta-tag) that they 122 // should not be translated. 123 static bool IsTranslationAllowed(blink::WebDocument* document); 124 125 // RenderViewObserver implementation. 126 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 127 128 // Cancels any translation that is currently being performed. This does not 129 // revert existing translations. 130 void CancelPendingTranslation(); 131 132 // Checks if the current running page translation is finished or errored and 133 // notifies the browser accordingly. If the translation has not terminated, 134 // posts a task to check again later. 135 void CheckTranslateStatus(); 136 137 // Called by TranslatePage to do the actual translation. |count| is used to 138 // limit the number of retries. 139 void TranslatePageImpl(int count); 140 141 // Sends a message to the browser to notify it that the translation failed 142 // with |error|. 143 void NotifyBrowserTranslationFailed(TranslateErrors::Type error); 144 145 // Convenience method to access the main frame. Can return NULL, typically 146 // if the page is being closed. 147 blink::WebFrame* GetMainFrame(); 148 149 // ID to represent a page which TranslateHelper captured and determined a 150 // content language. 151 int page_id_; 152 153 // The states associated with the current translation. 154 bool translation_pending_; 155 std::string source_lang_; 156 std::string target_lang_; 157 158 // Time when a page langauge is determined. This is used to know a duration 159 // time from showing infobar to requesting translation. 160 base::TimeTicks language_determined_time_; 161 162 // Method factory used to make calls to TranslatePageImpl. 163 base::WeakPtrFactory<TranslateHelper> weak_method_factory_; 164 165 #if defined(CLD2_DYNAMIC_MODE) 166 // Do not ask for CLD data any more. 167 void CancelCLD2DataFilePolling(); 168 169 // Invoked when PageCaptured is called prior to obtaining CLD data. This 170 // method stores the page ID into deferred_page_id_ and COPIES the contents 171 // of the page, then sets deferred_page_capture_ to true. When CLD data is 172 // eventually received (in OnCLDDataAvailable), any deferred request will be 173 // "resurrected" and allowed to proceed automatically, assuming that the 174 // page ID has not changed. 175 void DeferPageCaptured(const int page_id, const base::string16& contents); 176 177 // Immediately send an IPC request to the browser process to get the CLD 178 // data file. In most cases, the file will already exist and we will only 179 // poll once; but since the file might need to be downloaded first, poll 180 // indefinitely until a ChromeViewMsg_CLDDataAvailable message is received 181 // from the browser process. 182 // Polling will automatically halt as soon as the renderer obtains a 183 // reference to the data file. 184 void SendCLD2DataFileRequest(const int delay_millis, 185 const int next_delay_millis); 186 187 // Invoked when a ChromeViewMsg_CLDDataAvailable message is received from 188 // the browser process, providing a file handle for the CLD data file. If a 189 // PageCaptured request was previously deferred with DeferPageCaptured and 190 // the page ID has not yet changed, the PageCaptured is reinvoked to 191 // "resurrect" the language detection pathway. 192 void OnCLDDataAvailable(const IPC::PlatformFileForTransit ipc_file_handle, 193 const uint64 data_offset, 194 const uint64 data_length); 195 196 // After receiving data in OnCLDDataAvailable, loads the data into CLD2. 197 void LoadCLDDData(base::File file, 198 const uint64 data_offset, 199 const uint64 data_length); 200 201 // A struct that contains the pointer to the CLD mmap. Used so that we can 202 // leverage LazyInstance:Leaky to properly scope the lifetime of the mmap. 203 struct CLDMmapWrapper { 204 CLDMmapWrapper() { 205 value = NULL; 206 } 207 base::MemoryMappedFile* value; 208 }; 209 static base::LazyInstance<CLDMmapWrapper>::Leaky s_cld_mmap_; 210 211 // Whether or not polling for CLD2 data has started. 212 bool cld2_data_file_polling_started_; 213 214 // Whether or not CancelCLD2DataFilePolling has been called. 215 bool cld2_data_file_polling_canceled_; 216 217 // Whether or not a PageCaptured event arrived prior to CLD data becoming 218 // available. If true, deferred_page_id_ contains the most recent page ID 219 // and deferred_contents_ contains the most recent contents. 220 bool deferred_page_capture_; 221 222 // The ID of the page most recently reported to PageCaptured if 223 // deferred_page_capture_ is true. 224 int deferred_page_id_; 225 226 // The contents of the page most recently reported to PageCaptured if 227 // deferred_page_capture_ is true. 228 base::string16 deferred_contents_; 229 230 #endif 231 232 DISALLOW_COPY_AND_ASSIGN(TranslateHelper); 233 }; 234 235 #endif // CHROME_RENDERER_TRANSLATE_TRANSLATE_HELPER_H_ 236