diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-28 20:41:35 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-28 20:41:35 +0000 |
commit | 90fe28b929482fb3b492691305f7d7fefe452fc2 (patch) | |
tree | d230d9bd9e35077517038988d2a10c1f4c41c874 /chrome/browser/remoting | |
parent | fcdceecb9a2888e31186a986caafba37e89e3f74 (diff) | |
download | chromium_src-90fe28b929482fb3b492691305f7d7fefe452fc2.zip chromium_src-90fe28b929482fb3b492691305f7d7fefe452fc2.tar.gz chromium_src-90fe28b929482fb3b492691305f7d7fefe452fc2.tar.bz2 |
New remoting setup flow.
BUG=67218
TEST=None
Review URL: http://codereview.chromium.org/5985003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70238 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/remoting')
-rw-r--r-- | chrome/browser/remoting/setup_flow.cc | 194 | ||||
-rw-r--r-- | chrome/browser/remoting/setup_flow.h | 155 | ||||
-rw-r--r-- | chrome/browser/remoting/setup_flow_login_step.cc | 137 | ||||
-rw-r--r-- | chrome/browser/remoting/setup_flow_login_step.h | 58 |
4 files changed, 544 insertions, 0 deletions
diff --git a/chrome/browser/remoting/setup_flow.cc b/chrome/browser/remoting/setup_flow.cc new file mode 100644 index 0000000..fe20b8d --- /dev/null +++ b/chrome/browser/remoting/setup_flow.cc @@ -0,0 +1,194 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/remoting/setup_flow.h" + +#include "app/gfx/font_util.h" +#include "app/l10n_util.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/browser_thread.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/remoting/remoting_resources_source.h" +#include "chrome/browser/remoting/setup_flow_login_step.h" +#include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/common/pref_names.h" +#include "gfx/font.h" +#include "grit/generated_resources.h" +#include "grit/locale_settings.h" + +namespace remoting { + +static const wchar_t kDoneIframeXPath[] = L"//iframe[@id='done']"; + +SetupFlowStep::SetupFlowStep() { } +SetupFlowStep::~SetupFlowStep() { } + +SetupFlowStepBase::SetupFlowStepBase() + : flow_(NULL) { +} + +SetupFlowStepBase::~SetupFlowStepBase() { } + +void SetupFlowStepBase::Start(SetupFlow* flow, DoneCallback* done_callback) { + done_callback_.reset(done_callback); + flow_ = flow; + DoStart(); +} + +SetupFlowStep* SetupFlowStepBase::GetNextStep() { + DCHECK(done_); + return next_step_; +} + +void SetupFlowStepBase::ExecuteJavascriptInIFrame( + const std::wstring& iframe_xpath, const std::wstring& js) { + DOMUI* dom_ui = flow()->dom_ui(); + DCHECK(dom_ui); + + RenderViewHost* rvh = dom_ui->tab_contents()->render_view_host(); + rvh->ExecuteJavascriptInWebFrame(iframe_xpath, js); +} + +void SetupFlowStepBase::FinishStep(SetupFlowStep* next_step) { + next_step_ = next_step; + done_ = true; + done_callback_->Run(); +} + +SetupFlowDoneStep::SetupFlowDoneStep() { } +SetupFlowDoneStep::~SetupFlowDoneStep() { } + +void SetupFlowDoneStep::HandleMessage(const std::string& message, + const ListValue* args) { +} + +void SetupFlowDoneStep::Cancel() { } + +void SetupFlowDoneStep::DoStart() { + std::wstring javascript = L"setMessage('You are all set!');"; + ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript); + + flow()->dom_ui()->CallJavascriptFunction(L"showSetupDone"); + + ExecuteJavascriptInIFrame(kDoneIframeXPath, L"onPageShown();"); +} + +SetupFlow::SetupFlow(const std::string& args, Profile* profile, + SetupFlowStep* first_step) + : dom_ui_(NULL), + dialog_start_args_(args), + profile_(profile), + current_step_(first_step) { + // TODO(hclam): The data source should be added once. + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + NewRunnableMethod(ChromeURLDataManager::GetInstance(), + &ChromeURLDataManager::AddDataSource, + make_scoped_refptr(new RemotingResourcesSource()))); +} + +SetupFlow::~SetupFlow() { } + +// static +SetupFlow* SetupFlow::OpenSetupDialog(Profile* profile) { + // Set the arguments for showing the gaia login page. + DictionaryValue args; + args.SetString("iframeToShow", "login"); + args.SetString("user", ""); + args.SetInteger("error", 0); + args.SetBoolean("editable_user", true); + + std::string json_args; + base::JSONWriter::Write(&args, false, &json_args); + + Browser* b = BrowserList::GetLastActive(); + if (!b) + return NULL; + + SetupFlow *flow = new SetupFlow(json_args, profile, new SetupFlowLoginStep()); + b->BrowserShowHtmlDialog(flow, NULL); + return flow; +} + +GURL SetupFlow::GetDialogContentURL() const { + return GURL("chrome://remotingresources/setup"); +} + +void SetupFlow::GetDOMMessageHandlers( + std::vector<DOMMessageHandler*>* handlers) const { + // The called will be responsible for deleting this object. + handlers->push_back(const_cast<SetupFlow*>(this)); +} + +void SetupFlow::GetDialogSize(gfx::Size* size) const { + PrefService* prefs = profile_->GetPrefs(); + gfx::Font approximate_web_font( + UTF8ToWide(prefs->GetString(prefs::kWebKitSansSerifFontFamily)), + prefs->GetInteger(prefs::kWebKitDefaultFontSize)); + + // TODO(pranavk) Replace the following SYNC resources with REMOTING Resources. + *size = gfx::GetLocalizedContentsSizeForFont( + IDS_SYNC_SETUP_WIZARD_WIDTH_CHARS, + IDS_SYNC_SETUP_WIZARD_HEIGHT_LINES, + approximate_web_font); +} + +// A callback to notify the delegate that the dialog closed. +void SetupFlow::OnDialogClosed(const std::string& json_retval) { + if (current_step_ != NULL) + current_step_->Cancel(); +} + +std::string SetupFlow::GetDialogArgs() const { + return dialog_start_args_; +} + +void SetupFlow::OnCloseContents(TabContents* source, + bool* out_close_dialog) { +} + +std::wstring SetupFlow::GetDialogTitle() const { + return l10n_util::GetString(IDS_REMOTING_SETUP_DIALOG_TITLE); +} + +bool SetupFlow::IsDialogModal() const { + return false; +} + +bool SetupFlow::ShouldShowDialogTitle() const { + return true; +} + +DOMMessageHandler* SetupFlow::Attach(DOMUI* dom_ui) { + dom_ui_ = dom_ui; + StartCurrentStep(); + return DOMMessageHandler::Attach(dom_ui); +} + +void SetupFlow::RegisterMessages() { + dom_ui_->RegisterMessageCallback("SubmitAuth", + NewCallback(this, &SetupFlow::HandleSubmitAuth)); +} + +void SetupFlow::HandleSubmitAuth(const ListValue* args) { + current_step_->HandleMessage("SubmitAuth", args); +} + +void SetupFlow::StartCurrentStep() { + current_step_->Start(this, NewCallback(this, &SetupFlow::OnStepDone)); +} + +void SetupFlow::OnStepDone() { + current_step_.reset(current_step_->GetNextStep()); + StartCurrentStep(); +} + +} // namespace remoting diff --git a/chrome/browser/remoting/setup_flow.h b/chrome/browser/remoting/setup_flow.h new file mode 100644 index 0000000..f5dee29 --- /dev/null +++ b/chrome/browser/remoting/setup_flow.h @@ -0,0 +1,155 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_REMOTING_SETUP_FLOW_H_ +#define CHROME_BROWSER_REMOTING_SETUP_FLOW_H_ + +#include "base/callback.h" +#include "base/scoped_ptr.h" +#include "chrome/browser/dom_ui/html_dialog_ui.h" + +class ListValue; + +namespace remoting { + +class SetupFlow; + +// SetupFlowStep represents a single step for SetupFlow, e.g. login or +// host registration. When a step is finished, GetNextStep() is called +// to get the step that must follow. +class SetupFlowStep { + public: + typedef Callback0::Type DoneCallback; + + SetupFlowStep(); + virtual ~SetupFlowStep(); + + // Start the step. Ownership of |done_callback| is given to the + // function. |done_callback| is called when the step is finished, + // The callback must be called on the same thread as Start(). + virtual void Start(SetupFlow* flow, DoneCallback* done_callback) = 0; + + // Called to handle |message| received from UI. + virtual void HandleMessage(const std::string& message, + const ListValue* args) = 0; + + // Called if user closes the dialog. + virtual void Cancel() = 0; + + // Returns SetupFlowStep object that corresponds to the next + // step. Must never return NULL. + virtual SetupFlowStep* GetNextStep() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(SetupFlowStep); +}; + +// SetupFlowStepBase implements base functions common for all +// SetupFlowStep implementations. +class SetupFlowStepBase : public SetupFlowStep { + public: + SetupFlowStepBase(); + ~SetupFlowStepBase(); + + // SetupFlowStep implementation. + virtual void Start(SetupFlow* flow, DoneCallback* done_callback); + virtual SetupFlowStep* GetNextStep(); + + protected: + SetupFlow* flow() { return flow_; } + + void ExecuteJavascriptInIFrame(const std::wstring& iframe_xpath, + const std::wstring& js); + + // Finish current step. Calls |done_callback| specified in Start(). + // GetNextStep() will return the specified |next_step|. + void FinishStep(SetupFlowStep* next_step); + + // Called from Start(). Child classes must override this method + // instead of Start(). + virtual void DoStart() = 0; + + private: + SetupFlow* flow_; + scoped_ptr<DoneCallback> done_callback_; + bool done_; + + // Next step stored between Done() and GetNextStep(); + SetupFlowStep* next_step_; + + DISALLOW_COPY_AND_ASSIGN(SetupFlowStepBase); +}; + +// The last step in the setup flow. This step never finishes, user is +// expected to close dialog after that. +class SetupFlowDoneStep : public SetupFlowStepBase { + public: + SetupFlowDoneStep(); + virtual ~SetupFlowDoneStep(); + + // SetupFlowStep implementation. + virtual void HandleMessage(const std::string& message, const ListValue* args); + virtual void Cancel(); + + protected: + void DoStart(); + + private: + DISALLOW_COPY_AND_ASSIGN(SetupFlowDoneStep); +}; + +// This class is responsible for showing a remoting setup dialog and +// perform operations to fill the content of the dialog and handle +// user actions in the dialog. +class SetupFlow : public DOMMessageHandler, + public HtmlDialogUIDelegate { + public: + virtual ~SetupFlow(); + + static SetupFlow* OpenSetupDialog(Profile* profile); + + DOMUI* dom_ui() { return dom_ui_; } + Profile* profile() { return profile_; } + + private: + explicit SetupFlow(const std::string& args, Profile* profile, + SetupFlowStep* first_step); + + // HtmlDialogUIDelegate implementation. + virtual GURL GetDialogContentURL() const; + virtual void GetDOMMessageHandlers( + std::vector<DOMMessageHandler*>* handlers) const; + virtual void GetDialogSize(gfx::Size* size) const; + virtual std::string GetDialogArgs() const; + virtual void OnDialogClosed(const std::string& json_retval); + virtual void OnCloseContents(TabContents* source, bool* out_close_dialog); + virtual std::wstring GetDialogTitle() const; + virtual bool IsDialogModal() const; + virtual bool ShouldShowDialogTitle() const; + + // DOMMessageHandler implementation. + virtual DOMMessageHandler* Attach(DOMUI* dom_ui); + virtual void RegisterMessages(); + + void HandleSubmitAuth(const ListValue* args); + + void StartCurrentStep(); + void OnStepDone(); + + // Pointer to the DOM UI. This is provided by RemotingSetupMessageHandler + // when attached. + DOMUI* dom_ui_; + + // The args to pass to the initial page. + std::string dialog_start_args_; + Profile* profile_; + + scoped_ptr<SetupFlowStep> current_step_; + + DISALLOW_COPY_AND_ASSIGN(SetupFlow); +}; + +} // namespace remoting + +#endif // CHROME_BROWSER_REMOTING_SETUP_FLOW_H_ diff --git a/chrome/browser/remoting/setup_flow_login_step.cc b/chrome/browser/remoting/setup_flow_login_step.cc new file mode 100644 index 0000000..a485a07 --- /dev/null +++ b/chrome/browser/remoting/setup_flow_login_step.cc @@ -0,0 +1,137 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/remoting/setup_flow_login_step.h" + +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/dom_ui/dom_ui_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/net/gaia/gaia_constants.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" + +namespace remoting { + +static const wchar_t kLoginIFrameXPath[] = L"//iframe[@id='login']"; + +SetupFlowLoginStep::SetupFlowLoginStep() { } +SetupFlowLoginStep::~SetupFlowLoginStep() { } + +void SetupFlowLoginStep::HandleMessage(const std::string& message, + const ListValue* args) { + if (message == "SubmitAuth") { + std::string json(dom_ui_util::GetJsonResponseFromFirstArgumentInList(args)); + if (json.empty()) + return; + + scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false)); + if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY)) { + NOTREACHED() << "Unable to parse auth data"; + return; + } + + CHECK(parsed_value->IsType(Value::TYPE_DICTIONARY)); + + std::string username, password, captcha; + DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get()); + if (!result->GetString("user", &username) || + !result->GetString("pass", &password) || + !result->GetString("captcha", &captcha)) { + NOTREACHED() << "Unable to parse auth data"; + return; + } + + OnUserSubmittedAuth(username, password, captcha); + } +} + +void SetupFlowLoginStep::Cancel() { + if (authenticator_.get()) + authenticator_->CancelRequest(); +} + +void SetupFlowLoginStep::OnUserSubmittedAuth(const std::string& user, + const std::string& password, + const std::string& captcha) { + // Save the login name only. + login_ = user; + + // Start the authenticator. + authenticator_.reset( + new GaiaAuthFetcher(this, GaiaConstants::kChromeSource, + flow()->profile()->GetRequestContext())); + authenticator_->StartClientLogin(user, password, + GaiaConstants::kRemotingService, + "", captcha, + GaiaAuthFetcher::HostedAccountsAllowed); +} + +void SetupFlowLoginStep::OnClientLoginSuccess( + const GaiaAuthConsumer::ClientLoginResult& credentials) { + // Save the token for remoting. + remoting_token_ = credentials.token; + + // After login has succeeded try to fetch the token for sync. + // We need the token for sync to connect to the talk network. + authenticator_->StartIssueAuthToken(credentials.sid, credentials.lsid, + GaiaConstants::kSyncService); +} + +void SetupFlowLoginStep::OnClientLoginFailure( + const GoogleServiceAuthError& error) { + ShowGaiaFailed(error); + authenticator_.reset(); +} + +void SetupFlowLoginStep::OnIssueAuthTokenSuccess( + const std::string& service, const std::string& auth_token) { + // Save the sync token. + talk_token_ = auth_token; + authenticator_.reset(); + + FinishStep(new SetupFlowDoneStep()); +} + +void SetupFlowLoginStep::OnIssueAuthTokenFailure(const std::string& service, + const GoogleServiceAuthError& error) { + ShowGaiaFailed(error); + authenticator_.reset(); +} + +void SetupFlowLoginStep::DoStart() { + DictionaryValue args; + args.SetString("iframeToShow", "login"); + // TODO(sergeyu): Supply current login name if the service was started before. + args.SetString("user", ""); + args.SetBoolean("editable_user", true); + ShowGaiaLogin(args); +} + +void SetupFlowLoginStep::ShowGaiaLogin(const DictionaryValue& args) { + DOMUI* dom_ui = flow()->dom_ui(); + DCHECK(dom_ui); + + dom_ui->CallJavascriptFunction(L"showGaiaLoginIframe"); + + std::string json; + base::JSONWriter::Write(&args, false, &json); + std::wstring javascript = std::wstring(L"showGaiaLogin") + + L"(" + UTF8ToWide(json) + L");"; + ExecuteJavascriptInIFrame(kLoginIFrameXPath, javascript); +} + +void SetupFlowLoginStep::ShowGaiaFailed(const GoogleServiceAuthError& error) { + DictionaryValue args; + args.SetString("iframeToShow", "login"); + args.SetString("user", ""); + args.SetInteger("error", error.state()); + args.SetBoolean("editable_user", true); + args.SetString("captchaUrl", error.captcha().image_url.spec()); + ShowGaiaLogin(args); +} + +} // namespace remoting diff --git a/chrome/browser/remoting/setup_flow_login_step.h b/chrome/browser/remoting/setup_flow_login_step.h new file mode 100644 index 0000000..7c48df7 --- /dev/null +++ b/chrome/browser/remoting/setup_flow_login_step.h @@ -0,0 +1,58 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_REMOTING_SETUP_FLOW_LOGIN_STEP_H_ +#define CHROME_BROWSER_REMOTING_SETUP_FLOW_LOGIN_STEP_H_ + +#include "chrome/browser/remoting/setup_flow.h" +#include "chrome/common/net/gaia/gaia_auth_consumer.h" +#include "chrome/common/net/gaia/gaia_auth_fetcher.h" + +namespace remoting { + +// Implementation of login step for remoting setup flow. +class SetupFlowLoginStep : public SetupFlowStepBase, public GaiaAuthConsumer { + public: + SetupFlowLoginStep(); + virtual ~SetupFlowLoginStep(); + + // SetupFlowStep implementation. + virtual void HandleMessage(const std::string& message, + const ListValue* args); + virtual void Cancel(); + + // GaiaAuthConsumer implementation. + virtual void OnClientLoginSuccess( + const GaiaAuthConsumer::ClientLoginResult& credentials); + virtual void OnClientLoginFailure( + const GoogleServiceAuthError& error); + virtual void OnIssueAuthTokenSuccess(const std::string& service, + const std::string& auth_token); + virtual void OnIssueAuthTokenFailure(const std::string& service, + const GoogleServiceAuthError& error); + + protected: + virtual void DoStart(); + + private: + void OnUserSubmittedAuth(const std::string& user, + const std::string& password, + const std::string& captcha); + + void ShowGaiaLogin(const DictionaryValue& args); + void ShowGaiaSuccessAndSettingUp(); + void ShowGaiaFailed(const GoogleServiceAuthError& error); + + // Fetcher to obtain the Chromoting Directory token. + scoped_ptr<GaiaAuthFetcher> authenticator_; + std::string login_; + std::string remoting_token_; + std::string talk_token_; + + DISALLOW_COPY_AND_ASSIGN(SetupFlowLoginStep); +}; + +} // namespace remoting + +#endif // CHROME_BROWSER_REMOTING_SETUP_FLOW_LOGIN_STEP_H_ |