diff options
Diffstat (limited to 'chrome/browser/remoting/remoting_setup_flow.cc')
-rw-r--r-- | chrome/browser/remoting/remoting_setup_flow.cc | 243 |
1 files changed, 177 insertions, 66 deletions
diff --git a/chrome/browser/remoting/remoting_setup_flow.cc b/chrome/browser/remoting/remoting_setup_flow.cc index 9c71b9b..4a982db 100644 --- a/chrome/browser/remoting/remoting_setup_flow.cc +++ b/chrome/browser/remoting/remoting_setup_flow.cc @@ -19,8 +19,10 @@ #include "chrome/browser/profile.h" #include "chrome/browser/remoting/remoting_resources_source.h" #include "chrome/browser/remoting/remoting_setup_message_handler.h" +#include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/service/service_process_control.h" #include "chrome/browser/service/service_process_control_manager.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/net/gaia/gaia_authenticator2.h" #include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/net/gaia/google_service_auth_error.h" @@ -29,14 +31,75 @@ #include "gfx/font.h" #include "grit/locale_settings.h" -// Use static Run method to get an instance. +static const wchar_t kLoginIFrameXPath[] = L"//iframe[@id='login']"; +static const wchar_t kDoneIframeXPath[] = L"//iframe[@id='done']"; + +//////////////////////////////////////////////////////////////////////////////// +// RemotingServiceProcessHelper +// +// This is a helper class to perform actions when the service process +// is connected or launched. The events are sent back to RemotingSetupFlow +// when the dialog is still active. RemotingSetupFlow can detach from this +// helper class when the dialog is closed. +class RemotingServiceProcessHelper : + public base::RefCountedThreadSafe<RemotingServiceProcessHelper> { + public: + RemotingServiceProcessHelper(RemotingSetupFlow* flow) + : flow_(flow) { + } + + void Detach() { + flow_ = NULL; + } + + void OnProcessLaunched() { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); + // If the flow is detached then show the done page. + if (!flow_) + return; + + flow_->OnProcessLaunched(); + } + + private: + RemotingSetupFlow* flow_; + + DISALLOW_COPY_AND_ASSIGN(RemotingServiceProcessHelper); +}; + +//////////////////////////////////////////////////////////////////////////////// +// RemotingSetupFlow implementation. +// static +RemotingSetupFlow* RemotingSetupFlow::OpenDialog(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); + + if (profile->GetPrefs()->GetBoolean(prefs::kRemotingHasSetupCompleted)) { + args.SetString("iframeToShow", "done"); + } + + std::string json_args; + base::JSONWriter::Write(&args, false, &json_args); + + Browser* b = BrowserList::GetLastActive(); + if (!b) + return NULL; + + RemotingSetupFlow* flow = new RemotingSetupFlow(json_args, profile); + b->BrowserShowHtmlDialog(flow, NULL); + return flow; +} + RemotingSetupFlow::RemotingSetupFlow(const std::string& args, Profile* profile) - : message_handler_(NULL), + : dom_ui_(NULL), dialog_start_args_(args), profile_(profile), process_control_(NULL) { - // TODO(hclam): We are currently leaking this objcet. Need to fix this! - message_handler_ = new RemotingSetupMessageHandler(this); + // TODO(hclam): The data source should be added once. ChromeThread::PostTask( ChromeThread::IO, FROM_HERE, NewRunnableMethod(Singleton<ChromeURLDataManager>::get(), @@ -47,6 +110,25 @@ RemotingSetupFlow::RemotingSetupFlow(const std::string& args, Profile* profile) RemotingSetupFlow::~RemotingSetupFlow() { } +void RemotingSetupFlow::Focus() { + // TODO(pranavk): implement this method. + NOTIMPLEMENTED(); +} + +/////////////////////////////////////////////////////////////////////////////// +// HtmlDialogUIDelegate implementation. +GURL RemotingSetupFlow::GetDialogContentURL() const { + return GURL("chrome://remotingresources/setup"); +} + +void RemotingSetupFlow::GetDOMMessageHandlers( + std::vector<DOMMessageHandler*>* handlers) const { + // Create the message handler only after we are asked, the caller is + // responsible for deleting the objects. + handlers->push_back( + new RemotingSetupMessageHandler(const_cast<RemotingSetupFlow*>(this))); +} + void RemotingSetupFlow::GetDialogSize(gfx::Size* size) const { PrefService* prefs = profile_->GetPrefs(); gfx::Font approximate_web_font( @@ -65,38 +147,37 @@ void RemotingSetupFlow::OnDialogClosed(const std::string& json_retval) { // If we are fetching the token then cancel the request. if (authenticator_.get()) authenticator_->CancelRequest(); + + // If the service process helper is still active then detach outself from it. + // This is because the dialog is closing and this object is going to be + // deleted but the service process launch is still in progress so we don't + // the service process helper to call us when the process is launched. + if (service_process_helper_.get()) + service_process_helper_->Detach(); delete this; } -void RemotingSetupFlow::GetDOMMessageHandlers( - std::vector<DOMMessageHandler*>* handlers) const { - // Create the message handler only after we are asked. - handlers->push_back(message_handler_); +std::string RemotingSetupFlow::GetDialogArgs() const { + return dialog_start_args_; } -void RemotingSetupFlow::Focus() { - // TODO(pranavk): implement this method. - NOTIMPLEMENTED(); +void RemotingSetupFlow::OnCloseContents(TabContents* source, + bool* out_close_dialog) { } -void RemotingSetupFlow::OnUserSubmittedAuth(const std::string& user, - const std::string& password, - const std::string& captcha) { - // Save the login name only. - login_ = user; +std::wstring RemotingSetupFlow::GetDialogTitle() const { + return l10n_util::GetString(IDS_REMOTING_SETUP_DIALOG_TITLE); +} - // Start the authenticator. - authenticator_.reset( - new GaiaAuthenticator2(this, GaiaConstants::kChromeSource, - profile_->GetRequestContext())); - authenticator_->StartClientLogin(user, password, - GaiaConstants::kRemotingService, - "", captcha); +bool RemotingSetupFlow::IsDialogModal() const { + return true; } +/////////////////////////////////////////////////////////////////////////////// +// GaiaAuthConsumer implementation. void RemotingSetupFlow::OnClientLoginFailure( const GoogleServiceAuthError& error) { - message_handler_->ShowGaiaFailed(); + ShowGaiaFailed(error); authenticator_.reset(); } @@ -114,7 +195,7 @@ void RemotingSetupFlow::OnClientLoginSuccess( void RemotingSetupFlow::OnIssueAuthTokenSuccess(const std::string& service, const std::string& auth_token) { // Show that Gaia login has succeeded. - message_handler_->ShowGaiaSuccessAndSettingUp(); + ShowGaiaSuccessAndSettingUp(); // Save the sync token. sync_token_ = auth_token; @@ -129,75 +210,105 @@ void RemotingSetupFlow::OnIssueAuthTokenSuccess(const std::string& service, kServiceProcessRemoting); if (process_control_->is_connected()) { - OnProcessLaunched(); + // TODO(hclam): Need to figure out what to do when the service process is + // already connected. } else { - // TODO(hclam): This is really messed up because I totally ignore the - // lifetime of this object. I need a master cleanup on the lifetime of - // objects. +#if defined(OS_WIN) // TODO(hclam): This call only works on Windows. I need to make it work // on other platforms. + service_process_helper_ = new RemotingServiceProcessHelper(this); process_control_->Launch( - NewRunnableMethod(this, &RemotingSetupFlow::OnProcessLaunched)); + NewRunnableMethod(service_process_helper_.get(), + &RemotingServiceProcessHelper::OnProcessLaunched)); +#else + ShowSetupDone(); +#endif } } void RemotingSetupFlow::OnIssueAuthTokenFailure(const std::string& service, const GoogleServiceAuthError& error) { - // TODO(hclam): Do something to show the error. + ShowGaiaFailed(error); authenticator_.reset(); } -void RemotingSetupFlow::OnProcessLaunched() { - if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) { - ChromeThread::PostTask( - ChromeThread::UI, - FROM_HERE, - NewRunnableMethod(this, &RemotingSetupFlow::OnProcessLaunched)); - return; - } +/////////////////////////////////////////////////////////////////////////////// +// Methods called by RemotingSetupMessageHandler +void RemotingSetupFlow::Attach(DOMUI* dom_ui) { + dom_ui_ = dom_ui; +} +void RemotingSetupFlow::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 GaiaAuthenticator2(this, GaiaConstants::kChromeSource, + profile_->GetRequestContext())); + authenticator_->StartClientLogin(user, password, + GaiaConstants::kRemotingService, + "", captcha); +} + +/////////////////////////////////////////////////////////////////////////////// +// Method called by RemotingServicePRocessHelper +void RemotingSetupFlow::OnProcessLaunched() { DCHECK(process_control_->is_connected()); + // TODO(hclam): Need to wait for an ACK to be sure that it is actually active. process_control_->EnableRemotingWithTokens(login_, remoting_token_, sync_token_); - message_handler_->ShowSetupDone(); // Save the preference that we have completed the setup of remoting. profile_->GetPrefs()->SetBoolean(prefs::kRemotingHasSetupCompleted, true); + ShowSetupDone(); } -// static -RemotingSetupFlow* RemotingSetupFlow::Run(Profile* profile) { - // Set the arguments for showing the gaia login page. +/////////////////////////////////////////////////////////////////////////////// +// Helper methods for showing contents of the DOM UI +void RemotingSetupFlow::ShowGaiaLogin(const DictionaryValue& args) { + if (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 RemotingSetupFlow::ShowGaiaSuccessAndSettingUp() { + ExecuteJavascriptInIFrame(kLoginIFrameXPath, + L"showGaiaSuccessAndSettingUp();"); +} + +void RemotingSetupFlow::ShowGaiaFailed(const GoogleServiceAuthError& error) { DictionaryValue args; args.SetString("iframeToShow", "login"); args.SetString("user", ""); - args.SetInteger("error", 0); + args.SetInteger("error", error.state()); args.SetBoolean("editable_user", true); + args.SetString("captchaUrl", error.captcha().image_url.spec()); + ShowGaiaLogin(args); +} - if (profile->GetPrefs()->GetBoolean(prefs::kRemotingHasSetupCompleted)) { - args.SetString("iframeToShow", "done"); - } +void RemotingSetupFlow::ShowSetupDone() { + std::wstring javascript = L"setMessage('You are all set!');"; + ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript); - std::string json_args; - base::JSONWriter::Write(&args, false, &json_args); + if (dom_ui_) + dom_ui_->CallJavascriptFunction(L"showSetupDone"); - RemotingSetupFlow* flow = new RemotingSetupFlow(json_args, profile); - Browser* b = BrowserList::GetLastActive(); - if (b) { - b->BrowserShowHtmlDialog(flow, NULL); - } else { - delete flow; - return NULL; - } - return flow; + ExecuteJavascriptInIFrame(kDoneIframeXPath, L"onPageShown();"); } -// Global function to start the remoting setup dialog. -void OpenRemotingSetupDialog(Profile* profile) { - RemotingSetupFlow::Run(profile->GetOriginalProfile()); +void RemotingSetupFlow::ExecuteJavascriptInIFrame( + const std::wstring& iframe_xpath, + const std::wstring& js) { + if (dom_ui_) { + RenderViewHost* rvh = dom_ui_->tab_contents()->render_view_host(); + rvh->ExecuteJavascriptInWebFrame(iframe_xpath, js); + } } - -// TODO(hclam): Need to refcount RemotingSetupFlow. I need to fix -// lifetime of objects. -DISABLE_RUNNABLE_METHOD_REFCOUNT(RemotingSetupFlow); -DISABLE_RUNNABLE_METHOD_REFCOUNT(RemotingSetupMessageHandler); |