sync_setup_wizard.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 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#include "chrome/browser/sync/sync_setup_wizard.h"
6
7#include "app/resource_bundle.h"
8#include "base/message_loop.h"
9#include "base/singleton.h"
10#include "chrome/browser/chrome_thread.h"
11#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
12#include "chrome/browser/google/google_util.h"
13#include "chrome/browser/prefs/pref_service.h"
14#include "chrome/browser/profile.h"
15#include "chrome/browser/sync/profile_sync_service.h"
16#include "chrome/browser/sync/sync_setup_flow.h"
17#include "chrome/common/jstemplate_builder.h"
18#include "chrome/common/pref_names.h"
19#include "chrome/common/url_constants.h"
20#include "googleurl/src/gurl.h"
21#include "grit/app_resources.h"
22#include "grit/browser_resources.h"
23#include "grit/chromium_strings.h"
24
25class SyncResourcesSource : public ChromeURLDataManager::DataSource {
26 public:
27  SyncResourcesSource()
28      : DataSource(chrome::kChromeUISyncResourcesHost, MessageLoop::current()) {
29  }
30
31  virtual void StartDataRequest(const std::string& path,
32                                bool is_off_the_record,
33                                int request_id);
34
35  virtual std::string GetMimeType(const std::string& path) const {
36    return "text/html";
37  }
38
39  static const char* kInvalidPasswordHelpUrl;
40  static const char* kCanNotAccessAccountUrl;
41  static const char* kCreateNewAccountUrl;
42
43 private:
44  virtual ~SyncResourcesSource() {}
45
46  // Takes a string containing an URL and returns an URL containing a CGI
47  // parameter of the form "&hl=xy" where 'xy' is the language code of the
48  // current locale.
49  std::string GetLocalizedUrl(const std::string& url) const;
50
51  DISALLOW_COPY_AND_ASSIGN(SyncResourcesSource);
52};
53
54const char* SyncResourcesSource::kInvalidPasswordHelpUrl =
55  "http://www.google.com/support/accounts/bin/answer.py?ctx=ch&answer=27444";
56const char* SyncResourcesSource::kCanNotAccessAccountUrl =
57  "http://www.google.com/support/accounts/bin/answer.py?answer=48598";
58const char* SyncResourcesSource::kCreateNewAccountUrl =
59  "https://www.google.com/accounts/NewAccount?service=chromiumsync";
60
61void SyncResourcesSource::StartDataRequest(const std::string& path_raw,
62    bool is_off_the_record, int request_id) {
63  const char kSyncGaiaLoginPath[] = "gaialogin";
64  const char kSyncChooseDataTypesPath[] = "choosedatatypes";
65  const char kSyncSetupFlowPath[] = "setup";
66  const char kSyncSetupDonePath[] = "setupdone";
67
68  std::string response;
69  if (path_raw == kSyncGaiaLoginPath) {
70    DictionaryValue localized_strings;
71
72    // Start by setting the per-locale URLs we show on the setup wizard.
73    localized_strings.SetString("invalidpasswordhelpurl",
74        GetLocalizedUrl(kInvalidPasswordHelpUrl));
75    localized_strings.SetString("cannotaccessaccounturl",
76        GetLocalizedUrl(kCanNotAccessAccountUrl));
77    localized_strings.SetString("createnewaccounturl",
78        GetLocalizedUrl(kCreateNewAccountUrl));
79
80    localized_strings.SetString("settingupsync",
81        l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_SETTING_UP_SYNC));
82    localized_strings.SetString("introduction",
83        l10n_util::GetStringFUTF16(IDS_SYNC_LOGIN_INTRODUCTION,
84        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
85    localized_strings.SetString("signinprefix",
86        l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_SIGNIN_PREFIX));
87    localized_strings.SetString("signinsuffix",
88        l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_SIGNIN_SUFFIX));
89    localized_strings.SetString("cannotbeblank",
90        l10n_util::GetStringUTF16(IDS_SYNC_CANNOT_BE_BLANK));
91    localized_strings.SetString("emaillabel",
92        l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_EMAIL));
93    localized_strings.SetString("passwordlabel",
94        l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_PASSWORD));
95    localized_strings.SetString("invalidcredentials",
96        l10n_util::GetStringUTF16(IDS_SYNC_INVALID_USER_CREDENTIALS));
97    localized_strings.SetString("signin",
98        l10n_util::GetStringUTF16(IDS_SYNC_SIGNIN));
99    localized_strings.SetString("couldnotconnect",
100        l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_COULD_NOT_CONNECT));
101    localized_strings.SetString("cannotaccessaccount",
102        l10n_util::GetStringUTF16(IDS_SYNC_CANNOT_ACCESS_ACCOUNT));
103    localized_strings.SetString("createaccount",
104        l10n_util::GetStringUTF16(IDS_SYNC_CREATE_ACCOUNT));
105    localized_strings.SetString("cancel",
106        l10n_util::GetStringUTF16(IDS_CANCEL));
107    localized_strings.SetString("settingup",
108        l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_SETTING_UP));
109    localized_strings.SetString("success",
110        l10n_util::GetStringUTF16(IDS_SYNC_SUCCESS));
111    localized_strings.SetString("errorsigningin",
112        l10n_util::GetStringUTF16(IDS_SYNC_ERROR_SIGNING_IN));
113    localized_strings.SetString("captchainstructions",
114        l10n_util::GetStringUTF16(IDS_SYNC_GAIA_CAPTCHA_INSTRUCTIONS));
115    static const base::StringPiece html(ResourceBundle::GetSharedInstance()
116        .GetRawDataResource(IDR_GAIA_LOGIN_HTML));
117    SetFontAndTextDirection(&localized_strings);
118    response = jstemplate_builder::GetI18nTemplateHtml(
119        html, &localized_strings);
120  } else if (path_raw == kSyncChooseDataTypesPath) {
121    DictionaryValue localized_strings;
122    localized_strings.SetString("choosedatatypesheader",
123        l10n_util::GetStringUTF16(IDS_SYNC_CHOOSE_DATATYPES_HEADER));
124    localized_strings.SetString("choosedatatypesinstructions",
125        l10n_util::GetStringFUTF16(IDS_SYNC_CHOOSE_DATATYPES_INSTRUCTIONS,
126        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
127    localized_strings.SetString("keepeverythingsynced",
128        l10n_util::GetStringUTF16(IDS_SYNC_EVERYTHING));
129    localized_strings.SetString("choosedatatypes",
130        l10n_util::GetStringUTF16(IDS_SYNC_CHOOSE_DATATYPES));
131    localized_strings.SetString("bookmarks",
132        l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_BOOKMARKS));
133    localized_strings.SetString("preferences",
134        l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PREFERENCES));
135    localized_strings.SetString("autofill",
136        l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_AUTOFILL));
137    localized_strings.SetString("themes",
138        l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_THEMES));
139    localized_strings.SetString("passwords",
140        l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_PASSWORDS));
141    localized_strings.SetString("extensions",
142        l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_EXTENSIONS));
143    localized_strings.SetString("typedurls",
144        l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_TYPED_URLS));
145    localized_strings.SetString("apps",
146        l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_APPS));
147    localized_strings.SetString("synczerodatatypeserror",
148        l10n_util::GetStringUTF16(IDS_SYNC_ZERO_DATA_TYPES_ERROR));
149    localized_strings.SetString("setupabortederror",
150        l10n_util::GetStringUTF16(IDS_SYNC_SETUP_ABORTED_BY_PENDING_CLEAR));
151    localized_strings.SetString("ok",
152        l10n_util::GetStringUTF16(IDS_OK));
153    localized_strings.SetString("cancel",
154        l10n_util::GetStringUTF16(IDS_CANCEL));
155    localized_strings.SetString("settingup",
156        l10n_util::GetStringUTF16(IDS_SYNC_LOGIN_SETTING_UP));
157    static const base::StringPiece html(ResourceBundle::GetSharedInstance()
158      .GetRawDataResource(IDR_SYNC_CHOOSE_DATATYPES_HTML));
159    SetFontAndTextDirection(&localized_strings);
160    response = jstemplate_builder::GetI18nTemplateHtml(
161      html, &localized_strings);
162  } else if (path_raw == kSyncSetupDonePath) {
163    DictionaryValue localized_strings;
164    localized_strings.SetString("success",
165        l10n_util::GetStringUTF16(IDS_SYNC_SUCCESS));
166    localized_strings.SetString("setupsummary",
167        l10n_util::GetStringFUTF16(IDS_SYNC_SETUP_ALL_DONE,
168        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
169    localized_strings.SetString("firsttimesetupsummary",
170        l10n_util::GetStringUTF16(IDS_SYNC_SETUP_FIRST_TIME_ALL_DONE));
171    localized_strings.SetString("okay",
172        l10n_util::GetStringUTF16(IDS_SYNC_SETUP_OK_BUTTON_LABEL));
173    static const base::StringPiece html(ResourceBundle::GetSharedInstance()
174        .GetRawDataResource(IDR_SYNC_SETUP_DONE_HTML));
175    SetFontAndTextDirection(&localized_strings);
176    response = jstemplate_builder::GetI18nTemplateHtml(
177        html, &localized_strings);
178  } else if (path_raw == kSyncSetupFlowPath) {
179    static const base::StringPiece html(ResourceBundle::GetSharedInstance()
180        .GetRawDataResource(IDR_SYNC_SETUP_FLOW_HTML));
181    response = html.as_string();
182  }
183  // Send the response.
184  scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
185  html_bytes->data.resize(response.size());
186  std::copy(response.begin(), response.end(), html_bytes->data.begin());
187  SendResponse(request_id, html_bytes);
188}
189
190std::string SyncResourcesSource::GetLocalizedUrl(
191    const std::string& url) const {
192  GURL original_url(url);
193  DCHECK(original_url.is_valid());
194  GURL localized_url = google_util::AppendGoogleLocaleParam(original_url);
195  return localized_url.spec();
196}
197
198SyncSetupWizard::SyncSetupWizard(ProfileSyncService* service)
199    : service_(service),
200      flow_container_(new SyncSetupFlowContainer()),
201      parent_window_(NULL) {
202  // Add our network layer data source for 'cloudy' URLs.
203  SyncResourcesSource* sync_source = new SyncResourcesSource();
204  ChromeThread::PostTask(
205      ChromeThread::IO, FROM_HERE,
206      NewRunnableMethod(Singleton<ChromeURLDataManager>::get(),
207                        &ChromeURLDataManager::AddDataSource,
208                        make_scoped_refptr(sync_source)));
209}
210
211SyncSetupWizard::~SyncSetupWizard() {
212  delete flow_container_;
213}
214
215void SyncSetupWizard::Step(State advance_state) {
216  SyncSetupFlow* flow = flow_container_->get_flow();
217  if (flow) {
218    // A setup flow is in progress and dialog is currently showing.
219    flow->Advance(advance_state);
220  } else if (!service_->profile()->GetPrefs()->GetBoolean(
221             prefs::kSyncHasSetupCompleted)) {
222    if (IsTerminalState(advance_state))
223      return;
224    // No flow is in progress, and we have never escorted the user all the
225    // way through the wizard flow.
226    flow_container_->set_flow(
227        SyncSetupFlow::Run(service_, flow_container_, advance_state, DONE,
228                           parent_window_));
229  } else {
230    // No flow in in progress, but we've finished the wizard flow once before.
231    // This is just a discrete run.
232    if (IsTerminalState(advance_state))
233      return;  // Nothing to do.
234    flow_container_->set_flow(SyncSetupFlow::Run(service_, flow_container_,
235        advance_state, GetEndStateForDiscreteRun(advance_state),
236        parent_window_));
237  }
238}
239
240// static
241bool SyncSetupWizard::IsTerminalState(State advance_state) {
242  return advance_state == GAIA_SUCCESS ||
243         advance_state == DONE ||
244         advance_state == DONE_FIRST_TIME ||
245         advance_state == FATAL_ERROR ||
246         advance_state == SETUP_ABORTED_BY_PENDING_CLEAR;
247}
248
249bool SyncSetupWizard::IsVisible() const {
250  return flow_container_->get_flow() != NULL;
251}
252
253void SyncSetupWizard::Focus() {
254  SyncSetupFlow* flow = flow_container_->get_flow();
255  if (flow) {
256    flow->Focus();
257  }
258}
259
260void SyncSetupWizard::SetParent(gfx::NativeWindow parent_window) {
261  parent_window_ = parent_window;
262}
263
264// static
265SyncSetupWizard::State SyncSetupWizard::GetEndStateForDiscreteRun(
266    State start_state) {
267  State result = FATAL_ERROR;
268  if (start_state == GAIA_LOGIN) {
269    result = GAIA_SUCCESS;
270  } else if (start_state == CHOOSE_DATA_TYPES) {
271    result = DONE;
272  }
273  DCHECK_NE(FATAL_ERROR, result) <<
274      "Invalid start state for discrete run: " << start_state;
275  return result;
276}
277