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_BROWSER_TRANSLATE_TRANSLATE_MANAGER_H_
6#define CHROME_BROWSER_TRANSLATE_TRANSLATE_MANAGER_H_
7#pragma once
8
9#include <map>
10#include <set>
11#include <string>
12#include <vector>
13
14#include "base/lazy_instance.h"
15#include "base/task.h"
16#include "chrome/browser/prefs/pref_change_registrar.h"
17#include "chrome/common/net/url_fetcher.h"
18#include "chrome/common/translate_errors.h"
19#include "content/common/notification_observer.h"
20#include "content/common/notification_registrar.h"
21
22template <typename T> struct DefaultSingletonTraits;
23class GURL;
24struct PageTranslatedDetails;
25class PrefService;
26class TabContents;
27class TranslateInfoBarDelegate;
28
29// The TranslateManager class is responsible for showing an info-bar when a page
30// in a language different than the user language is loaded.  It triggers the
31// page translation the user requests.
32// It is a singleton.
33
34class TranslateManager : public NotificationObserver,
35                         public URLFetcher::Delegate {
36 public:
37  // Returns the singleton instance.
38  static TranslateManager* GetInstance();
39
40  virtual ~TranslateManager();
41
42  // Translates the page contents from |source_lang| to |target_lang|.
43  // The actual translation might be performed asynchronously if the translate
44  // script is not yet available.
45  void TranslatePage(TabContents* tab_contents,
46                     const std::string& source_lang,
47                     const std::string& target_lang);
48
49  // Reverts the contents of the page in |tab_contents| to its original
50  // language.
51  void RevertTranslation(TabContents* tab_contents);
52
53  // Reports to the Google translate server that a page language was incorrectly
54  // detected.  This call is initiated by the user selecting the "report" menu
55  // under options in the translate infobar.
56  void ReportLanguageDetectionError(TabContents* tab_contents);
57
58  // Clears the translate script, so it will be fetched next time we translate.
59  void ClearTranslateScript() { translate_script_.clear(); }
60
61  // NotificationObserver implementation:
62  virtual void Observe(NotificationType type,
63                       const NotificationSource& source,
64                       const NotificationDetails& details);
65
66  // URLFetcher::Delegate implementation:
67  virtual void OnURLFetchComplete(const URLFetcher* source,
68                                  const GURL& url,
69                                  const net::URLRequestStatus& status,
70                                  int response_code,
71                                  const ResponseCookies& cookies,
72                                  const std::string& data);
73
74  // Used by unit-tests to override the default delay after which the translate
75  // script is fetched again from the translation server.
76  void set_translate_script_expiration_delay(int delay_ms) {
77    translate_script_expiration_delay_ = delay_ms;
78  }
79
80  // Convenience method to know if a tab is showing a translate infobar.
81  static bool IsShowingTranslateInfobar(TabContents* tab);
82
83  // Returns true if the URL can be translated.
84  static bool IsTranslatableURL(const GURL& url);
85
86  // Fills |languages| with the list of languages that the translate server can
87  // translate to and from.
88  static void GetSupportedLanguages(std::vector<std::string>* languages);
89
90  // Returns the language code that can be used with the Translate method for a
91  // specified |chrome_locale|.
92  static std::string GetLanguageCode(const std::string& chrome_locale);
93
94  // Returns true if |language| is supported by the translation server.
95  static bool IsSupportedLanguage(const std::string& language);
96
97 protected:
98  TranslateManager();
99
100 private:
101  friend struct DefaultSingletonTraits<TranslateManager>;
102
103  // Structure that describes a translate request.
104  // Translation may be deferred while the translate script is being retrieved
105  // from the translate server.
106  struct PendingRequest {
107    int render_process_id;
108    int render_view_id;
109    int page_id;
110    std::string source_lang;
111    std::string target_lang;
112  };
113
114  // Starts the translation process on |tab| containing the page in the
115  // |page_lang| language.
116  void InitiateTranslation(TabContents* tab, const std::string& page_lang);
117
118  // If the tab identified by |process_id| and |render_id| has been closed, this
119  // does nothing, otherwise it calls InitiateTranslation.
120  void InitiateTranslationPosted(int process_id,
121                                 int render_id,
122                                 const std::string& page_lang);
123
124  // Sends a translation request to the RenderView of |tab_contents|.
125  void DoTranslatePage(TabContents* tab_contents,
126                       const std::string& translate_script,
127                       const std::string& source_lang,
128                       const std::string& target_lang);
129
130   // Shows the after translate or error infobar depending on the details.
131   void PageTranslated(TabContents* tab, PageTranslatedDetails* details);
132
133  // Returns true if the passed language has been configured by the user as an
134  // accept language.
135  bool IsAcceptLanguage(TabContents* tab, const std::string& language);
136
137  // Initializes the |accept_languages_| language table based on the associated
138  // preference in |prefs|.
139  void InitAcceptLanguages(PrefService* prefs);
140
141  // Fetches the JS translate script (the script that is injected in the page
142  // to translate it).
143  void RequestTranslateScript();
144
145  // Shows the specified translate |infobar| in the given |tab|.  If a current
146  // translate infobar is showing, it just replaces it with the new one.
147  void ShowInfoBar(TabContents* tab, TranslateInfoBarDelegate* infobar);
148
149  // Returns the language to translate to, which is the language the UI is
150  // configured in.  Returns an empty string if that language is not supported
151  // by the translation service.
152  static std::string GetTargetLanguage();
153
154  // Returns the translate info bar showing in |tab| or NULL if none is showing.
155  static TranslateInfoBarDelegate* GetTranslateInfoBarDelegate(
156      TabContents* tab);
157
158  NotificationRegistrar notification_registrar_;
159  PrefChangeRegistrar pref_change_registrar_;
160
161  // A map that associates a profile with its parsed "accept languages".
162  typedef std::set<std::string> LanguageSet;
163  typedef std::map<PrefService*, LanguageSet> PrefServiceLanguagesMap;
164  PrefServiceLanguagesMap accept_languages_;
165
166  ScopedRunnableMethodFactory<TranslateManager> method_factory_;
167
168  // The JS injected in the page to do the translation.
169  std::string translate_script_;
170
171  // Delay in milli-seconds after which the translate script is fetched again
172  // from the translate server.
173  int translate_script_expiration_delay_;
174
175  // Whether the translate JS is currently being retrieved.
176  bool translate_script_request_pending_;
177
178  // The list of pending translate requests.  Translate requests are queued when
179  // the translate script is not ready and has to be fetched from the translate
180  // server.
181  std::vector<PendingRequest> pending_requests_;
182
183  // The languages supported by the translation server.
184  static base::LazyInstance<std::set<std::string> > supported_languages_;
185
186  DISALLOW_COPY_AND_ASSIGN(TranslateManager);
187};
188
189#endif  // CHROME_BROWSER_TRANSLATE_TRANSLATE_MANAGER_H_
190