• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 #include "chrome/browser/remoting/setup_flow.h"
6 
7 #include "base/json/json_reader.h"
8 #include "base/json/json_writer.h"
9 #include "base/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "chrome/browser/prefs/pref_service.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/remoting/remoting_resources_source.h"
14 #include "chrome/browser/remoting/setup_flow_login_step.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_list.h"
17 #include "chrome/common/pref_names.h"
18 #include "content/browser/browser_thread.h"
19 #include "content/browser/renderer_host/render_view_host.h"
20 #include "content/browser/tab_contents/tab_contents.h"
21 #include "grit/generated_resources.h"
22 #include "grit/locale_settings.h"
23 #include "ui/base/l10n/l10n_font_util.h"
24 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/gfx/font.h"
26 
27 namespace remoting {
28 
29 static const wchar_t kDoneIframeXPath[] = L"//iframe[@id='done']";
30 static const wchar_t kErrorIframeXPath[] = L"//iframe[@id='error']";
31 
SetupFlowStep()32 SetupFlowStep::SetupFlowStep() { }
~SetupFlowStep()33 SetupFlowStep::~SetupFlowStep() { }
34 
SetupFlowStepBase()35 SetupFlowStepBase::SetupFlowStepBase()
36     : flow_(NULL),
37       done_(false),
38       next_step_(NULL) {
39 }
40 
~SetupFlowStepBase()41 SetupFlowStepBase::~SetupFlowStepBase() { }
42 
Start(SetupFlow * flow,DoneCallback * done_callback)43 void SetupFlowStepBase::Start(SetupFlow* flow, DoneCallback* done_callback) {
44   done_callback_.reset(done_callback);
45   flow_ = flow;
46   DoStart();
47 }
48 
GetNextStep()49 SetupFlowStep* SetupFlowStepBase::GetNextStep() {
50   DCHECK(done_);
51   return next_step_;
52 }
53 
ExecuteJavascriptInIFrame(const std::wstring & iframe_xpath,const std::wstring & js)54 void SetupFlowStepBase::ExecuteJavascriptInIFrame(
55     const std::wstring& iframe_xpath, const std::wstring& js) {
56   WebUI* web_ui = flow()->web_ui();
57   DCHECK(web_ui);
58 
59   RenderViewHost* rvh = web_ui->tab_contents()->render_view_host();
60   rvh->ExecuteJavascriptInWebFrame(WideToUTF16Hack(iframe_xpath),
61                                    WideToUTF16Hack(js));
62 }
63 
FinishStep(SetupFlowStep * next_step)64 void SetupFlowStepBase::FinishStep(SetupFlowStep* next_step) {
65   next_step_ = next_step;
66   done_ = true;
67   done_callback_->Run();
68 }
69 
SetupFlowErrorStepBase()70 SetupFlowErrorStepBase::SetupFlowErrorStepBase() { }
~SetupFlowErrorStepBase()71 SetupFlowErrorStepBase::~SetupFlowErrorStepBase() { }
72 
HandleMessage(const std::string & message,const Value * arg)73 void SetupFlowErrorStepBase::HandleMessage(const std::string& message,
74                                            const Value* arg) {
75   if (message == "Retry") {
76     Retry();
77   }
78 }
79 
Cancel()80 void SetupFlowErrorStepBase::Cancel() { }
81 
DoStart()82 void SetupFlowErrorStepBase::DoStart() {
83   std::wstring javascript =
84       L"setMessage('" + UTF16ToWide(GetErrorMessage()) + L"');";
85   ExecuteJavascriptInIFrame(kErrorIframeXPath, javascript);
86 
87   flow()->web_ui()->CallJavascriptFunction("showError");
88 
89   ExecuteJavascriptInIFrame(kErrorIframeXPath, L"onPageShown();");
90 }
91 
SetupFlowDoneStep()92 SetupFlowDoneStep::SetupFlowDoneStep() {
93   message_ = l10n_util::GetStringUTF16(IDS_REMOTING_SUCCESS_MESSAGE);
94 }
95 
SetupFlowDoneStep(const string16 & message)96 SetupFlowDoneStep::SetupFlowDoneStep(const string16& message)
97     : message_(message) {
98 }
99 
~SetupFlowDoneStep()100 SetupFlowDoneStep::~SetupFlowDoneStep() { }
101 
HandleMessage(const std::string & message,const Value * arg)102 void SetupFlowDoneStep::HandleMessage(const std::string& message,
103                                       const Value* arg) {
104 }
105 
Cancel()106 void SetupFlowDoneStep::Cancel() { }
107 
DoStart()108 void SetupFlowDoneStep::DoStart() {
109   std::wstring javascript =
110       L"setMessage('" + UTF16ToWide(message_) + L"');";
111   ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript);
112 
113   flow()->web_ui()->CallJavascriptFunction("showSetupDone");
114 
115   ExecuteJavascriptInIFrame(kDoneIframeXPath, L"onPageShown();");
116 }
117 
SetupFlowContext()118 SetupFlowContext::SetupFlowContext() { }
~SetupFlowContext()119 SetupFlowContext::~SetupFlowContext() { }
120 
SetupFlow(const std::string & args,Profile * profile,SetupFlowStep * first_step)121 SetupFlow::SetupFlow(const std::string& args,
122                      Profile* profile,
123                      SetupFlowStep* first_step)
124     : web_ui_(NULL),
125       dialog_start_args_(args),
126       profile_(profile),
127       current_step_(first_step) {
128   // TODO(hclam): The data source should be added once.
129   profile->GetChromeURLDataManager()->AddDataSource(
130       new RemotingResourcesSource());
131 }
132 
~SetupFlow()133 SetupFlow::~SetupFlow() { }
134 
135 // static
OpenSetupDialog(Profile * profile)136 SetupFlow* SetupFlow::OpenSetupDialog(Profile* profile) {
137   // Set the arguments for showing the gaia login page.
138   DictionaryValue args;
139   args.SetString("iframeToShow", "login");
140   args.SetString("user", "");
141   args.SetInteger("error", 0);
142   args.SetBoolean("editable_user", true);
143 
144   std::string json_args;
145   base::JSONWriter::Write(&args, false, &json_args);
146 
147   Browser* b = BrowserList::GetLastActive();
148   if (!b)
149     return NULL;
150 
151   SetupFlow *flow = new SetupFlow(json_args, profile, new SetupFlowLoginStep());
152   b->BrowserShowHtmlDialog(flow, NULL);
153   return flow;
154 }
155 
GetDialogContentURL() const156 GURL SetupFlow::GetDialogContentURL() const {
157   return GURL("chrome://remotingresources/setup");
158 }
159 
GetWebUIMessageHandlers(std::vector<WebUIMessageHandler * > * handlers) const160 void SetupFlow::GetWebUIMessageHandlers(
161     std::vector<WebUIMessageHandler*>* handlers) const {
162   // The called will be responsible for deleting this object.
163   handlers->push_back(const_cast<SetupFlow*>(this));
164 }
165 
GetDialogSize(gfx::Size * size) const166 void SetupFlow::GetDialogSize(gfx::Size* size) const {
167   PrefService* prefs = profile_->GetPrefs();
168   gfx::Font approximate_web_font(
169       UTF8ToUTF16(prefs->GetString(prefs::kWebKitSansSerifFontFamily)),
170       prefs->GetInteger(prefs::kWebKitDefaultFontSize));
171 
172   // TODO(pranavk) Replace the following SYNC resources with REMOTING Resources.
173   *size = ui::GetLocalizedContentsSizeForFont(
174       IDS_REMOTING_SETUP_WIZARD_WIDTH_CHARS,
175       IDS_REMOTING_SETUP_WIZARD_HEIGHT_LINES,
176       approximate_web_font);
177 }
178 
179 // A callback to notify the delegate that the dialog closed.
OnDialogClosed(const std::string & json_retval)180 void SetupFlow::OnDialogClosed(const std::string& json_retval) {
181   if (current_step_ != NULL)
182     current_step_->Cancel();
183 }
184 
GetDialogArgs() const185 std::string SetupFlow::GetDialogArgs() const {
186     return dialog_start_args_;
187 }
188 
OnCloseContents(TabContents * source,bool * out_close_dialog)189 void SetupFlow::OnCloseContents(TabContents* source,
190                                 bool* out_close_dialog) {
191 }
192 
GetDialogTitle() const193 std::wstring SetupFlow::GetDialogTitle() const {
194   return UTF16ToWideHack(
195       l10n_util::GetStringUTF16(IDS_REMOTING_SETUP_DIALOG_TITLE));
196 }
197 
IsDialogModal() const198 bool SetupFlow::IsDialogModal() const {
199   return false;
200 }
201 
ShouldShowDialogTitle() const202 bool SetupFlow::ShouldShowDialogTitle() const {
203   return true;
204 }
205 
Attach(WebUI * web_ui)206 WebUIMessageHandler* SetupFlow::Attach(WebUI* web_ui) {
207   web_ui_ = web_ui;
208   StartCurrentStep();
209   return WebUIMessageHandler::Attach(web_ui);
210 }
211 
RegisterMessages()212 void SetupFlow::RegisterMessages() {
213   web_ui_->RegisterMessageCallback(
214       "SubmitAuth", NewCallback(this, &SetupFlow::HandleSubmitAuth));
215   web_ui_->RegisterMessageCallback(
216       "RemotingSetup", NewCallback(this, &SetupFlow::HandleUIMessage));
217 }
218 
HandleSubmitAuth(const ListValue * args)219 void SetupFlow::HandleSubmitAuth(const ListValue* args) {
220   Value* first_arg = NULL;
221   if (!args->Get(0, &first_arg)) {
222     NOTREACHED();
223     return;
224   }
225 
226   current_step_->HandleMessage("SubmitAuth", first_arg);
227 }
228 
HandleUIMessage(const ListValue * args)229 void SetupFlow::HandleUIMessage(const ListValue* args) {
230   std::string message;
231   Value* message_value;
232   if (!args->Get(0, &message_value) ||
233       !message_value->GetAsString(&message)) {
234     NOTREACHED();
235     return;
236   }
237 
238   // Message argument is optional and set to NULL if it is not
239   // provided by the sending page.
240   Value* arg_value = NULL;
241   if (args->GetSize() >= 2) {
242     if (!args->Get(1, &arg_value)) {
243       NOTREACHED();
244       return;
245     }
246   }
247 
248   current_step_->HandleMessage(message, arg_value);
249 }
250 
StartCurrentStep()251 void SetupFlow::StartCurrentStep() {
252   current_step_->Start(this, NewCallback(this, &SetupFlow::OnStepDone));
253 }
254 
OnStepDone()255 void SetupFlow::OnStepDone() {
256   SetupFlowStep* next_step = current_step_->GetNextStep();
257 
258   if (current_step_.get()) {
259     // Can't destroy current step here. Schedule it to be destroyed later.
260     BrowserThread::PostTask(
261         BrowserThread::UI, FROM_HERE,
262         new DeleteTask<SetupFlowStep>(current_step_.release()));
263   }
264 
265   current_step_.reset(next_step);
266   StartCurrentStep();
267 }
268 
269 }  // namespace remoting
270