sync_setup_flow.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/sync_setup_flow.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/gfx/font_util.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/histogram.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/json/json_reader.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/json/json_writer.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_list.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX)
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/cocoa/html_dialog_window_controller_cppsafe.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/dom_ui/dom_ui_util.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/platform_util.h"
223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/profile.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_view_host.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/profile_sync_service.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/model_type.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_contents.h"
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/net/gaia/google_service_auth_error.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "gfx/font.h"
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/locale_settings.h"
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// XPath expression for finding specific iframes.
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const wchar_t* kLoginIFrameXPath = L"//iframe[@id='login']";
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const wchar_t* kChooseDataTypesIFrameXPath =
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    L"//iframe[@id='choose_data_types']";
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const wchar_t* kDoneIframeXPath = L"//iframe[@id='done']";
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FlowHandler::RegisterMessages() {
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  dom_ui_->RegisterMessageCallback("SubmitAuth",
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &FlowHandler::HandleSubmitAuth));
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  dom_ui_->RegisterMessageCallback("ChooseDataTypes",
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &FlowHandler::HandleChooseDataTypes));
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool GetAuthData(const std::string& json,
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string* username, std::string* password, std::string* captcha) {
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY))
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get());
533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!result->GetString("user", username) ||
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      !result->GetString("pass", password) ||
553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      !result->GetString("captcha", captcha)) {
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool GetDataTypeChoiceData(const std::string& json,
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool* sync_everything, syncable::ModelTypeSet* data_types) {
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY))
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get());
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!result->GetBoolean("keepEverythingSynced", sync_everything))
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // These values need to be kept in sync with where they are written in
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // choose_datatypes.html.
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool sync_bookmarks;
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!result->GetBoolean("syncBookmarks", &sync_bookmarks))
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sync_bookmarks)
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_types->insert(syncable::BOOKMARKS);
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool sync_preferences;
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!result->GetBoolean("syncPreferences", &sync_preferences))
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sync_preferences)
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_types->insert(syncable::PREFERENCES);
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool sync_themes;
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!result->GetBoolean("syncThemes", &sync_themes))
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sync_themes)
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_types->insert(syncable::THEMES);
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool sync_passwords;
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!result->GetBoolean("syncPasswords", &sync_passwords))
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sync_passwords)
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_types->insert(syncable::PASSWORDS);
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool sync_autofill;
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!result->GetBoolean("syncAutofill", &sync_autofill))
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sync_autofill)
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_types->insert(syncable::AUTOFILL);
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool sync_extensions;
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!result->GetBoolean("syncExtensions", &sync_extensions))
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sync_extensions)
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_types->insert(syncable::EXTENSIONS);
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool sync_typed_urls;
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!result->GetBoolean("syncTypedUrls", &sync_typed_urls))
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sync_typed_urls)
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_types->insert(syncable::TYPED_URLS);
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool sync_apps;
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!result->GetBoolean("syncApps", &sync_apps))
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (sync_apps)
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    data_types->insert(syncable::APPS);
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FlowHandler::HandleSubmitAuth(const ListValue* args) {
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string json(dom_ui_util::GetJsonResponseFromFirstArgumentInList(args));
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string username, password, captcha;
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (json.empty())
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!GetAuthData(json, &username, &password, &captcha)) {
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The page sent us something that we didn't understand.
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This probably indicates a programming error.
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (flow_)
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    flow_->OnUserSubmittedAuth(username, password, captcha);
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid FlowHandler::HandleChooseDataTypes(const ListValue* args) {
1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string json(dom_ui_util::GetJsonResponseFromFirstArgumentInList(args));
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool sync_everything;
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  syncable::ModelTypeSet chosen_types;
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (json.empty())
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!GetDataTypeChoiceData(json, &sync_everything, &chosen_types)) {
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The page sent us something that we didn't understand.
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This probably indicates a programming error.
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(flow_);
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  flow_->OnUserChoseDataTypes(sync_everything, chosen_types);
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return;
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Called by SyncSetupFlow::Advance.
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FlowHandler::ShowGaiaLogin(const DictionaryValue& args) {
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Whenever you start a wizard, you pass in an arg so it starts on the right
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // iframe (see setup_flow.html's showTheRightIframe() method).  But when you
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // transition from one flow to another, you have to explicitly call the JS
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // function to show the next iframe.
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // So if you ever made a wizard that involved a gaia login as not the first
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // frame, this call would be necessary to ensure that this method actually
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // shows the gaia login.
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (dom_ui_)
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    dom_ui_->CallJavascriptFunction(L"showGaiaLoginIframe");
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string json;
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::JSONWriter::Write(&args, false, &json);
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::wstring javascript = std::wstring(L"showGaiaLogin") +
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      L"(" + UTF8ToWide(json) + L");";
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ExecuteJavascriptInIFrame(kLoginIFrameXPath, javascript);
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FlowHandler::ShowGaiaSuccessAndClose() {
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ExecuteJavascriptInIFrame(kLoginIFrameXPath, L"showGaiaSuccessAndClose();");
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FlowHandler::ShowGaiaSuccessAndSettingUp() {
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ExecuteJavascriptInIFrame(kLoginIFrameXPath,
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            L"showGaiaSuccessAndSettingUp();");
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Called by SyncSetupFlow::Advance.
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FlowHandler::ShowChooseDataTypes(const DictionaryValue& args) {
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If you're starting the wizard at the Choose Data Types screen (i.e. from
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // "Customize Sync"), this will be redundant.  However, if you're coming from
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // another wizard state, this will make sure Choose Data Types is on top.
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (dom_ui_)
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    dom_ui_->CallJavascriptFunction(L"showChooseDataTypes");
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string json;
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::JSONWriter::Write(&args, false, &json);
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::wstring javascript = std::wstring(L"setCheckboxesAndErrors") +
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      L"(" + UTF8ToWide(json) + L");";
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ExecuteJavascriptInIFrame(kChooseDataTypesIFrameXPath, javascript);
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FlowHandler::ShowSetupDone(const std::wstring& user) {
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  StringValue synced_to_string(l10n_util::GetStringFUTF8(
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      IDS_SYNC_NTP_SYNCED_TO, WideToUTF16Hack(user)));
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string json;
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::JSONWriter::Write(&synced_to_string, false, &json);
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::wstring javascript = std::wstring(L"setSyncedToUser") +
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      L"(" + UTF8ToWide(json) + L");";
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript);
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (dom_ui_)
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    dom_ui_->CallJavascriptFunction(L"showSetupDone", synced_to_string);
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ExecuteJavascriptInIFrame(kDoneIframeXPath,
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            L"onPageShown();");
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FlowHandler::ShowFirstTimeDone(const std::wstring& user) {
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ExecuteJavascriptInIFrame(kDoneIframeXPath,
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            L"setShowFirstTimeSetupSummary();");
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ShowSetupDone(user);
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FlowHandler::ExecuteJavascriptInIFrame(const std::wstring& iframe_xpath,
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            const std::wstring& js) {
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (dom_ui_) {
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    RenderViewHost* rvh = dom_ui_->tab_contents()->render_view_host();
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rvh->ExecuteJavascriptInWebFrame(iframe_xpath, js);
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use static Run method to get an instance.
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSyncSetupFlow::SyncSetupFlow(SyncSetupWizard::State start_state,
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             SyncSetupWizard::State end_state,
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             const std::string& args,
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             SyncSetupFlowContainer* container,
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             ProfileSyncService* service)
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : container_(container),
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      dialog_start_args_(args),
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      current_state_(start_state),
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      end_state_(end_state),
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      login_start_time_(base::TimeTicks::Now()),
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      flow_handler_(new FlowHandler()),
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      owns_flow_handler_(true),
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      service_(service),
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      html_dialog_window_(NULL) {
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  flow_handler_->set_flow(this);
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSyncSetupFlow::~SyncSetupFlow() {
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  flow_handler_->set_flow(NULL);
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (owns_flow_handler_) {
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete flow_handler_;
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncSetupFlow::GetDialogSize(gfx::Size* size) const {
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PrefService* prefs = service_->profile()->GetPrefs();
2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gfx::Font approximate_web_font = gfx::Font(
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      UTF8ToWide(prefs->GetString(prefs::kWebKitSansSerifFontFamily)),
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      prefs->GetInteger(prefs::kWebKitDefaultFontSize));
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *size = gfx::GetLocalizedContentsSizeForFont(
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDS_SYNC_SETUP_WIZARD_WIDTH_CHARS,
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDS_SYNC_SETUP_WIZARD_HEIGHT_LINES,
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      approximate_web_font);
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX)
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // NOTE(akalin): This is a hack to work around a problem with font height on
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // windows.  Basically font metrics are incorrectly returned in logical units
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // instead of pixels on Windows.  Logical units are very commonly 96 DPI
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // so our localized char/line counts are too small by a factor of 96/72.
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // So we compensate for this on non-windows platform.
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(akalin): Remove this hack once we fix the windows font problem (or at
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // least work around it in some other place).
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  float scale_hack = 96.f/72.f;
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size->set_width(size->width() * scale_hack);
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size->set_height(size->height() * scale_hack);
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A callback to notify the delegate that the dialog closed.
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncSetupFlow::OnDialogClosed(const std::string& json_retval) {
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(json_retval.empty());
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  container_->set_flow(NULL);  // Sever ties from the wizard.
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (current_state_ == SyncSetupWizard::DONE ||
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      current_state_ == SyncSetupWizard::DONE_FIRST_TIME) {
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    service_->SetSyncSetupCompleted();
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Record the state at which the user cancelled the signon dialog.
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (current_state_) {
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::GAIA_LOGIN:
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ProfileSyncService::SyncEvent(
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          ProfileSyncService::CANCEL_FROM_SIGNON_WITHOUT_AUTH);
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::GAIA_SUCCESS:
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ProfileSyncService::SyncEvent(
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          ProfileSyncService::CANCEL_DURING_SIGNON);
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::CHOOSE_DATA_TYPES:
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ProfileSyncService::SyncEvent(
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          ProfileSyncService::CANCEL_FROM_CHOOSE_DATA_TYPES);
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::DONE_FIRST_TIME:
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::DONE:
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // TODO(sync): rename this histogram; it's tracking authorization AND
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // initial sync download time.
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      UMA_HISTOGRAM_MEDIUM_TIMES("Sync.UserPerceivedAuthorizationTime",
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 base::TimeTicks::Now() - login_start_time_);
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  service_->OnUserCancelledDialog();
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete this;
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncSetupFlow::GetArgsForGaiaLogin(const ProfileSyncService* service,
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        DictionaryValue* args) {
3263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetString("iframeToShow", "login");
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const GoogleServiceAuthError& error = service->GetAuthError();
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!service->last_attempted_user_email().empty()) {
3293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    args->SetString("user", service->last_attempted_user_email());
3303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    args->SetInteger("error", error.state());
3313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    args->SetBoolean("editable_user", true);
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
3333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    string16 user(service->GetAuthenticatedUsername());
3343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    args->SetString("user", user);
3353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    args->SetInteger("error", 0);
3363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    args->SetBoolean("editable_user", user.empty());
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetString("captchaUrl", error.captcha().image_url.spec());
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncSetupFlow::GetArgsForChooseDataTypes(ProfileSyncService* service,
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                              DictionaryValue* args) {
3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetString("iframeToShow", "choose_data_types");
3463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("keepEverythingSynced",
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      service->profile()->GetPrefs()->GetBoolean(prefs::kKeepEverythingSynced));
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Bookmarks, Preferences, and Themes are launched for good, there's no
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // going back now.  Check if the other data types are registered though.
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  syncable::ModelTypeSet registered_types;
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  service->GetRegisteredDataTypes(&registered_types);
3533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("passwordsRegistered",
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      registered_types.count(syncable::PASSWORDS) > 0);
3553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("autofillRegistered",
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      registered_types.count(syncable::AUTOFILL) > 0);
3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("extensionsRegistered",
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      registered_types.count(syncable::EXTENSIONS) > 0);
3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("typedUrlsRegistered",
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      registered_types.count(syncable::TYPED_URLS) > 0);
3613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("appsRegistered",
3623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      registered_types.count(syncable::APPS) > 0);
3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("sessionsRegistered",
3643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      registered_types.count(syncable::SESSIONS) > 0);
3653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("syncBookmarks",
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      service->profile()->GetPrefs()->GetBoolean(prefs::kSyncBookmarks));
3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("syncPreferences",
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      service->profile()->GetPrefs()->GetBoolean(prefs::kSyncPreferences));
3693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("syncThemes",
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      service->profile()->GetPrefs()->GetBoolean(prefs::kSyncThemes));
3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("syncPasswords",
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      service->profile()->GetPrefs()->GetBoolean(prefs::kSyncPasswords));
3733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("syncAutofill",
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      service->profile()->GetPrefs()->GetBoolean(prefs::kSyncAutofill));
3753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("syncExtensions",
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      service->profile()->GetPrefs()->GetBoolean(prefs::kSyncExtensions));
3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("syncSessions",
3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      service->profile()->GetPrefs()->GetBoolean(prefs::kSyncSessions));
3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("syncTypedUrls",
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      service->profile()->GetPrefs()->GetBoolean(prefs::kSyncTypedUrls));
3813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  args->SetBoolean("syncApps",
3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      service->profile()->GetPrefs()->GetBoolean(prefs::kSyncApps));
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncSetupFlow::GetDOMMessageHandlers(
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<DOMMessageHandler*>* handlers) const {
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  handlers->push_back(flow_handler_);
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't own flow_handler_ anymore, but it sticks around until at least
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // right after OnDialogClosed() is called (and this object is destroyed).
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  owns_flow_handler_ = false;
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SyncSetupFlow::ShouldAdvance(SyncSetupWizard::State state) {
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (state) {
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::GAIA_LOGIN:
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return current_state_ == SyncSetupWizard::FATAL_ERROR ||
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             current_state_ == SyncSetupWizard::GAIA_LOGIN;
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::GAIA_SUCCESS:
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return current_state_ == SyncSetupWizard::GAIA_LOGIN;
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::CHOOSE_DATA_TYPES:
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return current_state_ == SyncSetupWizard::GAIA_SUCCESS;
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::SETUP_ABORTED_BY_PENDING_CLEAR:
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return current_state_ == SyncSetupWizard::CHOOSE_DATA_TYPES;
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::FATAL_ERROR:
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;  // You can always hit the panic button.
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::DONE_FIRST_TIME:
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::DONE:
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return current_state_ == SyncSetupWizard::CHOOSE_DATA_TYPES;
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED() << "Unhandled State: " << state;
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncSetupFlow::Advance(SyncSetupWizard::State advance_state) {
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ShouldAdvance(advance_state))
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (advance_state) {
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::GAIA_LOGIN: {
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DictionaryValue args;
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SyncSetupFlow::GetArgsForGaiaLogin(service_, &args);
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      flow_handler_->ShowGaiaLogin(args);
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::GAIA_SUCCESS:
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (end_state_ == SyncSetupWizard::GAIA_SUCCESS) {
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        flow_handler_->ShowGaiaSuccessAndClose();
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      advance_state = SyncSetupWizard::CHOOSE_DATA_TYPES;
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      //  Fall through.
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::CHOOSE_DATA_TYPES: {
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DictionaryValue args;
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SyncSetupFlow::GetArgsForChooseDataTypes(service_, &args);
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      flow_handler_->ShowChooseDataTypes(args);
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::SETUP_ABORTED_BY_PENDING_CLEAR: {
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DictionaryValue args;
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SyncSetupFlow::GetArgsForChooseDataTypes(service_, &args);
4423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      args.SetBoolean("was_aborted", true);
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      flow_handler_->ShowChooseDataTypes(args);
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::FATAL_ERROR: {
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // This shows the user the "Could not connect to server" error.
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // TODO(sync): Update this error messaging.
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DictionaryValue args;
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SyncSetupFlow::GetArgsForGaiaLogin(service_, &args);
4513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      args.SetInteger("error", GoogleServiceAuthError::CONNECTION_FAILED);
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      flow_handler_->ShowGaiaLogin(args);
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::DONE_FIRST_TIME:
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      flow_handler_->ShowFirstTimeDone(
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          UTF16ToWide(service_->GetAuthenticatedUsername()));
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SyncSetupWizard::DONE:
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      flow_handler_->ShowSetupDone(
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          UTF16ToWide(service_->GetAuthenticatedUsername()));
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED() << "Invalid advance state: " << advance_state;
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  current_state_ = advance_state;
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncSetupFlow::Focus() {
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX)
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (html_dialog_window_) {
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    platform_util::ActivateWindow(html_dialog_window_);
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(csilv): We don't currently have a way to get the reference to the
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // dialog on windows/linux.  This can be resolved by a cross platform
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // implementation of HTML dialogs as described by akalin below.
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTIMPLEMENTED();
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif  // defined(OS_MACOSX)
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSyncSetupFlow* SyncSetupFlow::Run(ProfileSyncService* service,
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  SyncSetupFlowContainer* container,
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  SyncSetupWizard::State start,
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  SyncSetupWizard::State end,
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  gfx::NativeWindow parent_window) {
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue args;
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (start == SyncSetupWizard::GAIA_LOGIN)
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SyncSetupFlow::GetArgsForGaiaLogin(service, &args);
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else if (start == SyncSetupWizard::CHOOSE_DATA_TYPES)
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SyncSetupFlow::GetArgsForChooseDataTypes(service, &args);
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string json_args;
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::JSONWriter::Write(&args, false, &json_args);
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SyncSetupFlow* flow = new SyncSetupFlow(start, end, json_args,
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      container, service);
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX)
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(akalin): Figure out a cleaner way to do this than to have this
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // gross per-OS behavior, i.e. have a cross-platform ShowHtmlDialog()
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // function that is not tied to a browser instance.  Note that if we do
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // that, we'll have to fix sync_setup_wizard_unittest.cc as it relies on
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // being able to intercept ShowHtmlDialog() calls.
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  flow->html_dialog_window_ =
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      html_dialog_window_controller::ShowHtmlDialog(
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          flow, service->profile());
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Browser* b = BrowserList::GetLastActive();
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (b) {
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    b->BrowserShowHtmlDialog(flow, parent_window);
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete flow;
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif  // defined(OS_MACOSX)
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return flow;
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
518