sync_setup_flow.h revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2006-2008 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_SYNC_SYNC_SETUP_FLOW_H_ 6#define CHROME_BROWSER_SYNC_SYNC_SETUP_FLOW_H_ 7#pragma once 8 9#include <string> 10#include <vector> 11 12#include "app/l10n_util.h" 13#include "base/gtest_prod_util.h" 14#include "base/time.h" 15#include "chrome/browser/dom_ui/html_dialog_ui.h" 16#include "chrome/browser/sync/profile_sync_service.h" 17#include "chrome/browser/sync/sync_setup_wizard.h" 18#include "gfx/native_widget_types.h" 19#include "grit/generated_resources.h" 20 21class FlowHandler; 22class SyncSetupFlowContainer; 23 24// The state machine used by SyncSetupWizard, exposed in its own header 25// to facilitate testing of SyncSetupWizard. This class is used to open and 26// run the html dialog and deletes itself when the dialog closes. 27class SyncSetupFlow : public HtmlDialogUIDelegate { 28 public: 29 virtual ~SyncSetupFlow(); 30 31 // Runs a flow from |start| to |end|, and does the work of actually showing 32 // the HTML dialog. |container| is kept up-to-date with the lifetime of the 33 // flow (e.g it is emptied on dialog close). 34 static SyncSetupFlow* Run(ProfileSyncService* service, 35 SyncSetupFlowContainer* container, 36 SyncSetupWizard::State start, 37 SyncSetupWizard::State end, 38 gfx::NativeWindow parent_window); 39 40 // Fills |args| with "user" and "error" arguments by querying |service|. 41 static void GetArgsForGaiaLogin( 42 const ProfileSyncService* service, 43 DictionaryValue* args); 44 45 // Fills |args| with "user" and "error" arguments by querying |service|. 46 static void GetArgsForChooseDataTypes( 47 ProfileSyncService* service, 48 DictionaryValue* args); 49 50 // Triggers a state machine transition to advance_state. 51 void Advance(SyncSetupWizard::State advance_state); 52 53 // Focuses the dialog. This is useful in cases where the dialog has been 54 // obscured by a browser window. 55 void Focus(); 56 57 // HtmlDialogUIDelegate implementation. 58 // Get the HTML file path for the content to load in the dialog. 59 virtual GURL GetDialogContentURL() const { 60 return GURL("chrome://syncresources/setup"); 61 } 62 63 // HtmlDialogUIDelegate implementation. 64 virtual void GetDOMMessageHandlers( 65 std::vector<DOMMessageHandler*>* handlers) const; 66 67 // HtmlDialogUIDelegate implementation. 68 // Get the size of the dialog. 69 virtual void GetDialogSize(gfx::Size* size) const; 70 71 // HtmlDialogUIDelegate implementation. 72 // Gets the JSON string input to use when opening the dialog. 73 virtual std::string GetDialogArgs() const { 74 return dialog_start_args_; 75 } 76 77 // HtmlDialogUIDelegate implementation. 78 // A callback to notify the delegate that the dialog closed. 79 virtual void OnDialogClosed(const std::string& json_retval); 80 81 // HtmlDialogUIDelegate implementation. 82 virtual void OnCloseContents(TabContents* source, bool* out_close_dialog) { } 83 84 // HtmlDialogUIDelegate implementation. 85 virtual std::wstring GetDialogTitle() const { 86 return l10n_util::GetString(IDS_SYNC_MY_BOOKMARKS_LABEL); 87 } 88 89 // HtmlDialogUIDelegate implementation. 90 virtual bool IsDialogModal() const { 91 return false; 92 } 93 94 void OnUserSubmittedAuth(const std::string& username, 95 const std::string& password, 96 const std::string& captcha) { 97 service_->OnUserSubmittedAuth(username, password, captcha); 98 } 99 100 void OnUserChoseDataTypes(bool sync_everything, 101 syncable::ModelTypeSet& chosen_types) { 102 service_->OnUserChoseDatatypes(sync_everything, chosen_types); 103 } 104 105 private: 106 FRIEND_TEST_ALL_PREFIXES(SyncSetupWizardTest, InitialStepLogin); 107 FRIEND_TEST_ALL_PREFIXES(SyncSetupWizardTest, ChooseDataTypesSetsPrefs); 108 FRIEND_TEST_ALL_PREFIXES(SyncSetupWizardTest, DialogCancelled); 109 FRIEND_TEST_ALL_PREFIXES(SyncSetupWizardTest, InvalidTransitions); 110 FRIEND_TEST_ALL_PREFIXES(SyncSetupWizardTest, FullSuccessfulRunSetsPref); 111 FRIEND_TEST_ALL_PREFIXES(SyncSetupWizardTest, AbortedByPendingClear); 112 FRIEND_TEST_ALL_PREFIXES(SyncSetupWizardTest, DiscreteRunGaiaLogin); 113 FRIEND_TEST_ALL_PREFIXES(SyncSetupWizardTest, DiscreteRunChooseDataTypes); 114 FRIEND_TEST_ALL_PREFIXES(SyncSetupWizardTest, 115 DiscreteRunChooseDataTypesAbortedByPendingClear); 116 117 // Use static Run method to get an instance. 118 SyncSetupFlow(SyncSetupWizard::State start_state, 119 SyncSetupWizard::State end_state, 120 const std::string& args, SyncSetupFlowContainer* container, 121 ProfileSyncService* service); 122 123 // Returns true if |this| should transition its state machine to |state| 124 // based on |current_state_|, or false if that would be nonsense or is 125 // a no-op. 126 bool ShouldAdvance(SyncSetupWizard::State state); 127 128 SyncSetupFlowContainer* container_; // Our container. Don't own this. 129 std::string dialog_start_args_; // The args to pass to the initial page. 130 131 SyncSetupWizard::State current_state_; 132 SyncSetupWizard::State end_state_; // The goal. 133 134 // Time that the GAIA_LOGIN step was received. 135 base::TimeTicks login_start_time_; 136 137 // The handler needed for the entire flow. 138 FlowHandler* flow_handler_; 139 mutable bool owns_flow_handler_; 140 141 // We need this to write the sentinel "setup completed" pref. 142 ProfileSyncService* service_; 143 144 // Currently used only on OS X 145 // TODO(akalin): Add the necessary support to the other OSes and use 146 // this for them. 147 gfx::NativeWindow html_dialog_window_; 148 149 DISALLOW_COPY_AND_ASSIGN(SyncSetupFlow); 150}; 151 152// A really simple wrapper for a SyncSetupFlow so that we don't have to 153// add any public methods to the public SyncSetupWizard interface to notify it 154// when the dialog closes. 155class SyncSetupFlowContainer { 156 public: 157 SyncSetupFlowContainer() : flow_(NULL) { } 158 void set_flow(SyncSetupFlow* flow) { 159 DCHECK(!flow_ || !flow); 160 flow_ = flow; 161 } 162 163 SyncSetupFlow* get_flow() { return flow_; } 164 private: 165 SyncSetupFlow* flow_; 166 167 DISALLOW_COPY_AND_ASSIGN(SyncSetupFlowContainer); 168}; 169 170// The FlowHandler connects the state machine to the dialog backing HTML and 171// JS namespace by implementing DOMMessageHandler and being invoked by the 172// SyncSetupFlow. Exposed here to facilitate testing. 173class FlowHandler : public DOMMessageHandler { 174 public: 175 FlowHandler() {} 176 virtual ~FlowHandler() {} 177 178 // DOMMessageHandler implementation. 179 virtual void RegisterMessages(); 180 181 // Callbacks from the page. 182 void HandleSubmitAuth(const ListValue* args); 183 void HandleChooseDataTypes(const ListValue* args); 184 185 // These functions control which part of the HTML is visible. 186 void ShowGaiaLogin(const DictionaryValue& args); 187 void ShowGaiaSuccessAndClose(); 188 void ShowGaiaSuccessAndSettingUp(); 189 void ShowChooseDataTypes(const DictionaryValue& args); 190 void ShowSetupDone(const std::wstring& user); 191 void ShowFirstTimeDone(const std::wstring& user); 192 193 void set_flow(SyncSetupFlow* flow) { 194 flow_ = flow; 195 } 196 197 private: 198 void ExecuteJavascriptInIFrame(const std::wstring& iframe_xpath, 199 const std::wstring& js); 200 SyncSetupFlow* flow_; 201 DISALLOW_COPY_AND_ASSIGN(FlowHandler); 202}; 203 204#endif // CHROME_BROWSER_SYNC_SYNC_SETUP_FLOW_H_ 205