// Copyright (c) 2011 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 "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/utf_string_conversions.h" #include "base/values.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/ui/browser.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/common/pref_names.h" #include "content/browser/browser_thread.h" #include "content/browser/renderer_host/render_view_host.h" #include "content/browser/tab_contents/tab_contents.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "ui/base/l10n/l10n_font_util.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/font.h" namespace remoting { static const wchar_t kDoneIframeXPath[] = L"//iframe[@id='done']"; static const wchar_t kErrorIframeXPath[] = L"//iframe[@id='error']"; SetupFlowStep::SetupFlowStep() { } SetupFlowStep::~SetupFlowStep() { } SetupFlowStepBase::SetupFlowStepBase() : flow_(NULL), done_(false), next_step_(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) { WebUI* web_ui = flow()->web_ui(); DCHECK(web_ui); RenderViewHost* rvh = web_ui->tab_contents()->render_view_host(); rvh->ExecuteJavascriptInWebFrame(WideToUTF16Hack(iframe_xpath), WideToUTF16Hack(js)); } void SetupFlowStepBase::FinishStep(SetupFlowStep* next_step) { next_step_ = next_step; done_ = true; done_callback_->Run(); } SetupFlowErrorStepBase::SetupFlowErrorStepBase() { } SetupFlowErrorStepBase::~SetupFlowErrorStepBase() { } void SetupFlowErrorStepBase::HandleMessage(const std::string& message, const Value* arg) { if (message == "Retry") { Retry(); } } void SetupFlowErrorStepBase::Cancel() { } void SetupFlowErrorStepBase::DoStart() { std::wstring javascript = L"setMessage('" + UTF16ToWide(GetErrorMessage()) + L"');"; ExecuteJavascriptInIFrame(kErrorIframeXPath, javascript); flow()->web_ui()->CallJavascriptFunction("showError"); ExecuteJavascriptInIFrame(kErrorIframeXPath, L"onPageShown();"); } SetupFlowDoneStep::SetupFlowDoneStep() { message_ = l10n_util::GetStringUTF16(IDS_REMOTING_SUCCESS_MESSAGE); } SetupFlowDoneStep::SetupFlowDoneStep(const string16& message) : message_(message) { } SetupFlowDoneStep::~SetupFlowDoneStep() { } void SetupFlowDoneStep::HandleMessage(const std::string& message, const Value* arg) { } void SetupFlowDoneStep::Cancel() { } void SetupFlowDoneStep::DoStart() { std::wstring javascript = L"setMessage('" + UTF16ToWide(message_) + L"');"; ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript); flow()->web_ui()->CallJavascriptFunction("showSetupDone"); ExecuteJavascriptInIFrame(kDoneIframeXPath, L"onPageShown();"); } SetupFlowContext::SetupFlowContext() { } SetupFlowContext::~SetupFlowContext() { } SetupFlow::SetupFlow(const std::string& args, Profile* profile, SetupFlowStep* first_step) : web_ui_(NULL), dialog_start_args_(args), profile_(profile), current_step_(first_step) { // TODO(hclam): The data source should be added once. profile->GetChromeURLDataManager()->AddDataSource( 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::GetWebUIMessageHandlers( std::vector<WebUIMessageHandler*>* 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( UTF8ToUTF16(prefs->GetString(prefs::kWebKitSansSerifFontFamily)), prefs->GetInteger(prefs::kWebKitDefaultFontSize)); // TODO(pranavk) Replace the following SYNC resources with REMOTING Resources. *size = ui::GetLocalizedContentsSizeForFont( IDS_REMOTING_SETUP_WIZARD_WIDTH_CHARS, IDS_REMOTING_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 UTF16ToWideHack( l10n_util::GetStringUTF16(IDS_REMOTING_SETUP_DIALOG_TITLE)); } bool SetupFlow::IsDialogModal() const { return false; } bool SetupFlow::ShouldShowDialogTitle() const { return true; } WebUIMessageHandler* SetupFlow::Attach(WebUI* web_ui) { web_ui_ = web_ui; StartCurrentStep(); return WebUIMessageHandler::Attach(web_ui); } void SetupFlow::RegisterMessages() { web_ui_->RegisterMessageCallback( "SubmitAuth", NewCallback(this, &SetupFlow::HandleSubmitAuth)); web_ui_->RegisterMessageCallback( "RemotingSetup", NewCallback(this, &SetupFlow::HandleUIMessage)); } void SetupFlow::HandleSubmitAuth(const ListValue* args) { Value* first_arg = NULL; if (!args->Get(0, &first_arg)) { NOTREACHED(); return; } current_step_->HandleMessage("SubmitAuth", first_arg); } void SetupFlow::HandleUIMessage(const ListValue* args) { std::string message; Value* message_value; if (!args->Get(0, &message_value) || !message_value->GetAsString(&message)) { NOTREACHED(); return; } // Message argument is optional and set to NULL if it is not // provided by the sending page. Value* arg_value = NULL; if (args->GetSize() >= 2) { if (!args->Get(1, &arg_value)) { NOTREACHED(); return; } } current_step_->HandleMessage(message, arg_value); } void SetupFlow::StartCurrentStep() { current_step_->Start(this, NewCallback(this, &SetupFlow::OnStepDone)); } void SetupFlow::OnStepDone() { SetupFlowStep* next_step = current_step_->GetNextStep(); if (current_step_.get()) { // Can't destroy current step here. Schedule it to be destroyed later. BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, new DeleteTask<SetupFlowStep>(current_step_.release())); } current_step_.reset(next_step); StartCurrentStep(); } } // namespace remoting