summaryrefslogtreecommitdiffstats
path: root/chrome/browser/remoting
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-28 20:41:35 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-28 20:41:35 +0000
commit90fe28b929482fb3b492691305f7d7fefe452fc2 (patch)
treed230d9bd9e35077517038988d2a10c1f4c41c874 /chrome/browser/remoting
parentfcdceecb9a2888e31186a986caafba37e89e3f74 (diff)
downloadchromium_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.cc194
-rw-r--r--chrome/browser/remoting/setup_flow.h155
-rw-r--r--chrome/browser/remoting/setup_flow_login_step.cc137
-rw-r--r--chrome/browser/remoting/setup_flow_login_step.h58
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_