Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / translate / chrome_translate_client.cc
blobc16a64a5578f9539b7cc97755ee625820c9770d7
1 // Copyright 2014 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.
5 #include "chrome/browser/translate/chrome_translate_client.h"
7 #include <vector>
9 #include "base/logging.h"
10 #include "base/path_service.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/string_split.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/infobars/infobar_service.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/translate/translate_accept_languages_factory.h"
17 #include "chrome/browser/translate/translate_service.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_finder.h"
20 #include "chrome/browser/ui/browser_tabstrip.h"
21 #include "chrome/browser/ui/browser_window.h"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h"
23 #include "chrome/browser/ui/translate/translate_bubble_factory.h"
24 #include "chrome/common/chrome_paths.h"
25 #include "chrome/common/pref_names.h"
26 #include "components/translate/content/browser/browser_cld_data_provider_factory.h"
27 #include "components/translate/content/common/cld_data_source.h"
28 #include "components/translate/content/common/translate_messages.h"
29 #include "components/translate/core/browser/language_state.h"
30 #include "components/translate/core/browser/page_translated_details.h"
31 #include "components/translate/core/browser/translate_accept_languages.h"
32 #include "components/translate/core/browser/translate_download_manager.h"
33 #include "components/translate/core/browser/translate_infobar_delegate.h"
34 #include "components/translate/core/browser/translate_manager.h"
35 #include "components/translate/core/browser/translate_prefs.h"
36 #include "components/translate/core/common/language_detection_details.h"
37 #include "content/public/browser/notification_service.h"
38 #include "content/public/browser/render_view_host.h"
39 #include "content/public/browser/web_contents.h"
40 #include "grit/theme_resources.h"
41 #include "url/gurl.h"
43 namespace {
45 // TODO(andrewhayden): Make the data file path into a gyp/gn define
46 // If you change this, also update standalone_cld_data_harness.cc
47 // accordingly!
48 const base::FilePath::CharType kCldDataFileName[] =
49 FILE_PATH_LITERAL("cld2_data.bin");
51 bool g_cld_file_path_initialized_ = false;
53 } // namespace
55 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ChromeTranslateClient);
57 ChromeTranslateClient::ChromeTranslateClient(content::WebContents* web_contents)
58 : content::WebContentsObserver(web_contents),
59 translate_driver_(&web_contents->GetController()),
60 translate_manager_(
61 new translate::TranslateManager(this, prefs::kAcceptLanguages)),
62 cld_data_provider_(
63 translate::BrowserCldDataProviderFactory::Get()->
64 CreateBrowserCldDataProvider(web_contents)) {
65 translate_driver_.AddObserver(this);
66 translate_driver_.set_translate_manager(translate_manager_.get());
67 // Customization: for the standalone data source, we configure the path to
68 // CLD data immediately on startup.
69 if (translate::CldDataSource::IsUsingStandaloneDataSource() &&
70 !g_cld_file_path_initialized_) {
71 DVLOG(1) << "Initializing CLD file path for the first time.";
72 base::FilePath path;
73 if (!PathService::Get(chrome::DIR_USER_DATA, &path)) {
74 // Chrome isn't properly installed
75 LOG(WARNING) << "Unable to locate user data directory";
76 } else {
77 g_cld_file_path_initialized_ = true;
78 path = path.Append(kCldDataFileName);
79 DVLOG(1) << "Setting CLD data file path: " << path.value();
80 translate::CldDataSource::Get()->SetCldDataFilePath(path);
85 ChromeTranslateClient::~ChromeTranslateClient() {
86 translate_driver_.RemoveObserver(this);
89 translate::LanguageState& ChromeTranslateClient::GetLanguageState() {
90 return translate_manager_->GetLanguageState();
93 // static
94 scoped_ptr<translate::TranslatePrefs>
95 ChromeTranslateClient::CreateTranslatePrefs(PrefService* prefs) {
96 #if defined(OS_CHROMEOS)
97 const char* preferred_languages_prefs = prefs::kLanguagePreferredLanguages;
98 #else
99 const char* preferred_languages_prefs = NULL;
100 #endif
101 return scoped_ptr<translate::TranslatePrefs>(new translate::TranslatePrefs(
102 prefs, prefs::kAcceptLanguages, preferred_languages_prefs));
105 // static
106 translate::TranslateAcceptLanguages*
107 ChromeTranslateClient::GetTranslateAcceptLanguages(
108 content::BrowserContext* browser_context) {
109 return TranslateAcceptLanguagesFactory::GetForBrowserContext(browser_context);
112 // static
113 translate::TranslateManager* ChromeTranslateClient::GetManagerFromWebContents(
114 content::WebContents* web_contents) {
115 ChromeTranslateClient* chrome_translate_client =
116 FromWebContents(web_contents);
117 if (!chrome_translate_client)
118 return NULL;
119 return chrome_translate_client->GetTranslateManager();
122 // static
123 void ChromeTranslateClient::GetTranslateLanguages(
124 content::WebContents* web_contents,
125 std::string* source,
126 std::string* target) {
127 DCHECK(source != NULL);
128 DCHECK(target != NULL);
130 ChromeTranslateClient* chrome_translate_client =
131 FromWebContents(web_contents);
132 if (!chrome_translate_client)
133 return;
135 *source = translate::TranslateDownloadManager::GetLanguageCode(
136 chrome_translate_client->GetLanguageState().original_language());
138 Profile* profile =
139 Profile::FromBrowserContext(web_contents->GetBrowserContext());
140 Profile* original_profile = profile->GetOriginalProfile();
141 PrefService* prefs = original_profile->GetPrefs();
142 scoped_ptr<translate::TranslatePrefs> translate_prefs =
143 CreateTranslatePrefs(prefs);
144 if (!web_contents->GetBrowserContext()->IsOffTheRecord()) {
145 std::string auto_translate_language =
146 translate::TranslateManager::GetAutoTargetLanguage(
147 *source, translate_prefs.get());
148 if (!auto_translate_language.empty()) {
149 *target = auto_translate_language;
150 return;
154 std::string accept_languages_str = prefs->GetString(prefs::kAcceptLanguages);
155 std::vector<std::string> accept_languages_list = base::SplitString(
156 accept_languages_str, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
157 *target =
158 translate::TranslateManager::GetTargetLanguage(accept_languages_list);
161 translate::TranslateManager* ChromeTranslateClient::GetTranslateManager() {
162 return translate_manager_.get();
165 void ChromeTranslateClient::ShowTranslateUI(
166 translate::TranslateStep step,
167 const std::string source_language,
168 const std::string target_language,
169 translate::TranslateErrors::Type error_type,
170 bool triggered_from_menu) {
171 DCHECK(web_contents());
172 if (error_type != translate::TranslateErrors::NONE)
173 step = translate::TRANSLATE_STEP_TRANSLATE_ERROR;
175 if (TranslateService::IsTranslateBubbleEnabled()) {
176 // Bubble UI.
177 if (step == translate::TRANSLATE_STEP_BEFORE_TRANSLATE) {
178 // TODO(droger): Move this logic out of UI code.
179 GetLanguageState().SetTranslateEnabled(true);
180 if (!GetLanguageState().HasLanguageChanged())
181 return;
183 if (!triggered_from_menu) {
184 if (web_contents()->GetBrowserContext()->IsOffTheRecord())
185 return;
186 if (GetTranslatePrefs()->IsTooOftenDenied(source_language))
187 return;
190 ShowBubble(step, error_type);
191 return;
194 // Infobar UI.
195 translate::TranslateInfoBarDelegate::Create(
196 step != translate::TRANSLATE_STEP_BEFORE_TRANSLATE,
197 translate_manager_->GetWeakPtr(),
198 InfoBarService::FromWebContents(web_contents()),
199 web_contents()->GetBrowserContext()->IsOffTheRecord(),
200 step,
201 source_language,
202 target_language,
203 error_type,
204 triggered_from_menu);
207 translate::TranslateDriver* ChromeTranslateClient::GetTranslateDriver() {
208 return &translate_driver_;
211 PrefService* ChromeTranslateClient::GetPrefs() {
212 DCHECK(web_contents());
213 Profile* profile =
214 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
215 return profile->GetOriginalProfile()->GetPrefs();
218 scoped_ptr<translate::TranslatePrefs>
219 ChromeTranslateClient::GetTranslatePrefs() {
220 DCHECK(web_contents());
221 Profile* profile =
222 Profile::FromBrowserContext(web_contents()->GetBrowserContext());
223 return CreateTranslatePrefs(profile->GetPrefs());
226 translate::TranslateAcceptLanguages*
227 ChromeTranslateClient::GetTranslateAcceptLanguages() {
228 DCHECK(web_contents());
229 return GetTranslateAcceptLanguages(web_contents()->GetBrowserContext());
232 int ChromeTranslateClient::GetInfobarIconID() const {
233 return IDR_INFOBAR_TRANSLATE;
236 bool ChromeTranslateClient::IsTranslatableURL(const GURL& url) {
237 return TranslateService::IsTranslatableURL(url);
240 void ChromeTranslateClient::ShowReportLanguageDetectionErrorUI(
241 const GURL& report_url) {
242 #if defined(OS_ANDROID)
243 // Android does not support reporting language detection errors.
244 NOTREACHED();
245 #else
246 // We'll open the URL in a new tab so that the user can tell us more.
247 Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
248 if (!browser) {
249 NOTREACHED();
250 return;
253 chrome::AddSelectedTabWithURL(
254 browser, report_url, ui::PAGE_TRANSITION_AUTO_BOOKMARK);
255 #endif // defined(OS_ANDROID)
258 bool ChromeTranslateClient::OnMessageReceived(const IPC::Message& message) {
259 return cld_data_provider_->OnMessageReceived(message);
262 void ChromeTranslateClient::WebContentsDestroyed() {
263 // Translation process can be interrupted.
264 // Destroying the TranslateManager now guarantees that it never has to deal
265 // with NULL WebContents.
266 translate_manager_.reset();
269 // ContentTranslateDriver::Observer implementation.
271 void ChromeTranslateClient::OnLanguageDetermined(
272 const translate::LanguageDetectionDetails& details) {
273 // TODO: Remove translate notifications and have the clients be
274 // ContentTranslateDriver::Observer directly instead.
275 content::NotificationService::current()->Notify(
276 chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED,
277 content::Source<content::WebContents>(web_contents()),
278 content::Details<const translate::LanguageDetectionDetails>(&details));
281 void ChromeTranslateClient::OnPageTranslated(
282 const std::string& original_lang,
283 const std::string& translated_lang,
284 translate::TranslateErrors::Type error_type) {
285 // TODO: Remove translate notifications and have the clients be
286 // ContentTranslateDriver::Observer directly instead.
287 DCHECK(web_contents());
288 translate::PageTranslatedDetails details;
289 details.source_language = original_lang;
290 details.target_language = translated_lang;
291 details.error_type = error_type;
292 content::NotificationService::current()->Notify(
293 chrome::NOTIFICATION_PAGE_TRANSLATED,
294 content::Source<content::WebContents>(web_contents()),
295 content::Details<translate::PageTranslatedDetails>(&details));
298 void ChromeTranslateClient::ShowBubble(
299 translate::TranslateStep step,
300 translate::TranslateErrors::Type error_type) {
301 // The bubble is implemented only on the desktop platforms.
302 #if !defined(OS_ANDROID) && !defined(OS_IOS)
303 Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
305 // |browser| might be NULL when testing. In this case, Show(...) should be
306 // called because the implementation for testing is used.
307 if (!browser) {
308 TranslateBubbleFactory::Show(NULL, web_contents(), step, error_type);
309 return;
312 if (web_contents() != browser->tab_strip_model()->GetActiveWebContents())
313 return;
315 // This ShowBubble function is also used for upating the existing bubble.
316 // However, with the bubble shown, any browser windows are NOT activated
317 // because the bubble takes the focus from the other widgets including the
318 // browser windows. So it is checked that |browser| is the last activated
319 // browser, not is now activated.
320 if (browser !=
321 chrome::FindLastActiveWithHostDesktopType(browser->host_desktop_type())) {
322 return;
325 // During auto-translating, the bubble should not be shown.
326 if (step == translate::TRANSLATE_STEP_TRANSLATING ||
327 step == translate::TRANSLATE_STEP_AFTER_TRANSLATE) {
328 if (GetLanguageState().InTranslateNavigation())
329 return;
332 TranslateBubbleFactory::Show(
333 browser->window(), web_contents(), step, error_type);
334 #else
335 NOTREACHED();
336 #endif