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/ui/webui/chromeos/enterprise_enrollment_ui.h" 6 7 #include "base/json/json_reader.h" 8 #include "base/json/json_writer.h" 9 #include "base/lazy_instance.h" 10 #include "base/memory/ref_counted_memory.h" 11 #include "base/message_loop.h" 12 #include "base/stringprintf.h" 13 #include "base/values.h" 14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/ui/webui/chrome_url_data_manager.h" 16 #include "chrome/common/jstemplate_builder.h" 17 #include "chrome/common/url_constants.h" 18 #include "content/browser/renderer_host/render_view_host.h" 19 #include "content/browser/tab_contents/tab_contents.h" 20 #include "content/common/bindings_policy.h" 21 #include "content/common/property_bag.h" 22 #include "grit/browser_resources.h" 23 #include "grit/chromium_strings.h" 24 #include "grit/generated_resources.h" 25 #include "ui/base/l10n/l10n_util.h" 26 #include "ui/base/resource/resource_bundle.h" 27 28 namespace chromeos { 29 30 static base::LazyInstance< 31 PropertyAccessor<EnterpriseEnrollmentUI::Controller*> > 32 g_enrollment_ui_controller_property(base::LINKER_INITIALIZED); 33 34 static const char kEnterpriseEnrollmentGaiaLoginPath[] = "gaialogin"; 35 36 // WebUIMessageHandler implementation which handles events occuring on the page, 37 // such as the user pressing the signin button. 38 class EnterpriseEnrollmentMessageHandler : public WebUIMessageHandler { 39 public: 40 EnterpriseEnrollmentMessageHandler(); 41 virtual ~EnterpriseEnrollmentMessageHandler(); 42 43 // WebUIMessageHandler implementation. 44 virtual void RegisterMessages() OVERRIDE; 45 46 private: 47 // Handlers for WebUI messages. 48 void HandleSubmitAuth(const ListValue* args); 49 void HandleCancelAuth(const ListValue* args); 50 void HandleConfirmationClose(const ListValue* args); 51 52 // Gets the currently installed enrollment controller (if any). 53 EnterpriseEnrollmentUI::Controller* GetController(); 54 55 DISALLOW_COPY_AND_ASSIGN(EnterpriseEnrollmentMessageHandler); 56 }; 57 58 // A data source that provides the resources for the enterprise enrollment page. 59 // The enterprise enrollment page requests the HTML and other resources from 60 // this source. 61 class EnterpriseEnrollmentDataSource : public ChromeURLDataManager::DataSource { 62 public: 63 EnterpriseEnrollmentDataSource(); 64 65 // DataSource implementation. 66 virtual void StartDataRequest(const std::string& path, 67 bool is_off_the_record, 68 int request_id) OVERRIDE; 69 virtual std::string GetMimeType(const std::string& path) const OVERRIDE; 70 71 private: 72 virtual ~EnterpriseEnrollmentDataSource(); 73 74 // Saves i18n string for |resource_id| to the |key| property of |dictionary|. 75 static void AddString(DictionaryValue* dictionary, 76 const std::string& key, 77 int resource_id); 78 static void AddString(DictionaryValue* dictionary, 79 const std::string& key, 80 int resource_id, 81 const string16& arg1); 82 83 DISALLOW_COPY_AND_ASSIGN(EnterpriseEnrollmentDataSource); 84 }; 85 86 EnterpriseEnrollmentMessageHandler::EnterpriseEnrollmentMessageHandler() {} 87 88 EnterpriseEnrollmentMessageHandler::~EnterpriseEnrollmentMessageHandler() {} 89 90 void EnterpriseEnrollmentMessageHandler::RegisterMessages() { 91 web_ui_->RegisterMessageCallback( 92 "SubmitAuth", 93 NewCallback( 94 this, &EnterpriseEnrollmentMessageHandler::HandleSubmitAuth)); 95 web_ui_->RegisterMessageCallback( 96 "DialogClose", 97 NewCallback( 98 this, &EnterpriseEnrollmentMessageHandler::HandleCancelAuth)); 99 web_ui_->RegisterMessageCallback( 100 "confirmationClose", 101 NewCallback( 102 this, &EnterpriseEnrollmentMessageHandler::HandleConfirmationClose)); 103 } 104 105 void EnterpriseEnrollmentMessageHandler::HandleSubmitAuth( 106 const ListValue* value) { 107 EnterpriseEnrollmentUI::Controller* controller = GetController(); 108 if (!controller) { 109 NOTREACHED(); 110 return; 111 } 112 113 // Value carries single list entry, which is a json-encoded string that 114 // contains the auth parameters (see gaia_login.js). 115 std::string json_params; 116 if (!value->GetString(0, &json_params)) { 117 NOTREACHED(); 118 return; 119 } 120 121 // Check the value type. 122 scoped_ptr<Value> params(base::JSONReader::Read(json_params, false)); 123 if (!params.get() || !params->IsType(Value::TYPE_DICTIONARY)) { 124 NOTREACHED(); 125 return; 126 } 127 128 // Read the parameters. 129 DictionaryValue* params_dict = static_cast<DictionaryValue*>(params.get()); 130 std::string user; 131 std::string pass; 132 std::string captcha; 133 std::string access_code; 134 if (!params_dict->GetString("user", &user) || 135 !params_dict->GetString("pass", &pass) || 136 !params_dict->GetString("captcha", &captcha) || 137 !params_dict->GetString("access_code", &access_code)) { 138 NOTREACHED(); 139 return; 140 } 141 142 controller->OnAuthSubmitted(user, pass, captcha, access_code); 143 } 144 145 void EnterpriseEnrollmentMessageHandler::HandleCancelAuth( 146 const ListValue* value) { 147 EnterpriseEnrollmentUI::Controller* controller = GetController(); 148 if (!controller) { 149 NOTREACHED(); 150 return; 151 } 152 153 controller->OnAuthCancelled(); 154 } 155 156 void EnterpriseEnrollmentMessageHandler::HandleConfirmationClose( 157 const ListValue* value) { 158 EnterpriseEnrollmentUI::Controller* controller = GetController(); 159 if (!controller) { 160 NOTREACHED(); 161 return; 162 } 163 164 controller->OnConfirmationClosed(); 165 } 166 167 EnterpriseEnrollmentUI::Controller* 168 EnterpriseEnrollmentMessageHandler::GetController() { 169 return EnterpriseEnrollmentUI::GetController(web_ui_); 170 } 171 172 EnterpriseEnrollmentDataSource::EnterpriseEnrollmentDataSource() 173 : DataSource(chrome::kChromeUIEnterpriseEnrollmentHost, 174 MessageLoop::current()) {} 175 176 void EnterpriseEnrollmentDataSource::StartDataRequest(const std::string& path, 177 bool is_off_the_record, 178 int request_id) { 179 ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance(); 180 181 DictionaryValue strings; 182 std::string response; 183 if (path.empty()) { 184 AddString(&strings, "loginHeader", 185 IDS_ENTERPRISE_ENROLLMENT_LOGIN_HEADER), 186 AddString(&strings, "loginExplain", 187 IDS_ENTERPRISE_ENROLLMENT_LOGIN_EXPLAIN, 188 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 189 AddString(&strings, "cloudHeader", 190 IDS_ENTERPRISE_ENROLLMENT_CLOUD_HEADER), 191 AddString(&strings, "cloudExplain", 192 IDS_ENTERPRISE_ENROLLMENT_CLOUD_EXPLAIN); 193 AddString(&strings, "accesscontrolHeader", 194 IDS_ENTERPRISE_ENROLLMENT_ACCESSCONTROL_HEADER), 195 AddString(&strings, "accesscontrolExplain", 196 IDS_ENTERPRISE_ENROLLMENT_ACCESSCONTROL_EXPLAIN); 197 AddString(&strings, "confirmationHeader", 198 IDS_ENTERPRISE_ENROLLMENT_CONFIRMATION_HEADER); 199 AddString(&strings, "confirmationMessage", 200 IDS_ENTERPRISE_ENROLLMENT_CONFIRMATION_MESSAGE); 201 AddString(&strings, "confirmationClose", 202 IDS_ENTERPRISE_ENROLLMENT_CONFIRMATION_CLOSE); 203 204 static const base::StringPiece html( 205 resource_bundle.GetRawDataResource(IDR_ENTERPRISE_ENROLLMENT_HTML)); 206 SetFontAndTextDirection(&strings); 207 response = jstemplate_builder::GetI18nTemplateHtml(html, &strings); 208 } else if (path == kEnterpriseEnrollmentGaiaLoginPath) { 209 strings.SetString("invalidpasswordhelpurl", ""); 210 strings.SetString("invalidaccessaccounturl", ""); 211 strings.SetString("cannotaccessaccount", ""); 212 strings.SetString("cannotaccessaccounturl", ""); 213 strings.SetString("createaccount", ""); 214 strings.SetString("createnewaccounturl", ""); 215 strings.SetString("getaccesscodehelp", ""); 216 strings.SetString("getaccesscodeurl", ""); 217 218 // None of the strings used here currently have sync-specific wording in 219 // them. We have a unit test to catch if that happens. 220 strings.SetString("introduction", ""); 221 AddString(&strings, "signinprefix", IDS_SYNC_LOGIN_SIGNIN_PREFIX); 222 AddString(&strings, "signinsuffix", IDS_SYNC_LOGIN_SIGNIN_SUFFIX); 223 AddString(&strings, "cannotbeblank", IDS_SYNC_CANNOT_BE_BLANK); 224 AddString(&strings, "emaillabel", IDS_SYNC_LOGIN_EMAIL); 225 AddString(&strings, "passwordlabel", IDS_SYNC_LOGIN_PASSWORD); 226 AddString(&strings, "invalidcredentials", 227 IDS_SYNC_INVALID_USER_CREDENTIALS); 228 AddString(&strings, "signin", IDS_SYNC_SIGNIN); 229 AddString(&strings, "couldnotconnect", IDS_SYNC_LOGIN_COULD_NOT_CONNECT); 230 AddString(&strings, "cancel", IDS_CANCEL); 231 AddString(&strings, "settingup", IDS_SYNC_LOGIN_SETTING_UP); 232 AddString(&strings, "success", IDS_SYNC_SUCCESS); 233 AddString(&strings, "errorsigningin", IDS_SYNC_ERROR_SIGNING_IN); 234 AddString(&strings, "captchainstructions", 235 IDS_SYNC_GAIA_CAPTCHA_INSTRUCTIONS); 236 AddString(&strings, "invalidaccesscode", 237 IDS_SYNC_INVALID_ACCESS_CODE_LABEL); 238 AddString(&strings, "enteraccesscode", IDS_SYNC_ENTER_ACCESS_CODE_LABEL); 239 240 static const base::StringPiece html(resource_bundle.GetRawDataResource( 241 IDR_GAIA_LOGIN_HTML)); 242 SetFontAndTextDirection(&strings); 243 response = jstemplate_builder::GetI18nTemplateHtml(html, &strings); 244 } 245 246 // Send the response. 247 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes()); 248 html_bytes->data.resize(response.size()); 249 std::copy(response.begin(), response.end(), html_bytes->data.begin()); 250 SendResponse(request_id, html_bytes); 251 } 252 253 std::string EnterpriseEnrollmentDataSource::GetMimeType( 254 const std::string& path) const { 255 return "text/html"; 256 } 257 258 EnterpriseEnrollmentDataSource::~EnterpriseEnrollmentDataSource() {} 259 260 void EnterpriseEnrollmentDataSource::AddString(DictionaryValue* dictionary, 261 const std::string& key, 262 int resource_id) { 263 dictionary->SetString(key, l10n_util::GetStringUTF16(resource_id)); 264 } 265 266 void EnterpriseEnrollmentDataSource::AddString(DictionaryValue* dictionary, 267 const std::string& key, 268 int resource_id, 269 const string16& arg1) { 270 dictionary->SetString(key, l10n_util::GetStringFUTF16(resource_id, arg1)); 271 } 272 273 EnterpriseEnrollmentUI::EnterpriseEnrollmentUI(TabContents* contents) 274 : WebUI(contents) {} 275 276 EnterpriseEnrollmentUI::~EnterpriseEnrollmentUI() {} 277 278 void EnterpriseEnrollmentUI::RenderViewCreated( 279 RenderViewHost* render_view_host) { 280 // Bail out early if the controller doesn't exist or web ui is disabled. 281 if (!GetController(this) || !(bindings_ & BindingsPolicy::WEB_UI)) 282 return; 283 284 WebUIMessageHandler* handler = new EnterpriseEnrollmentMessageHandler(); 285 AddMessageHandler(handler->Attach(this)); 286 287 // Set up the data source, so the enrollment page can be loaded. 288 tab_contents()->profile()->GetChromeURLDataManager()->AddDataSource( 289 new EnterpriseEnrollmentDataSource()); 290 291 std::string user; 292 bool has_init_user = GetController(this)->GetInitialUser(&user); 293 if (!has_init_user) 294 user = ""; 295 // Set the arguments for showing the gaia login page. 296 DictionaryValue args; 297 args.SetString("user", user); 298 args.SetInteger("error", 0); 299 args.SetBoolean("editable_user", !has_init_user); 300 args.SetString("initialScreen", "login-screen"); 301 std::string json_args; 302 base::JSONWriter::Write(&args, false, &json_args); 303 render_view_host->SetWebUIProperty("dialogArguments", json_args); 304 } 305 306 // static 307 EnterpriseEnrollmentUI::Controller* EnterpriseEnrollmentUI::GetController( 308 WebUI* ui) { 309 Controller** controller = 310 g_enrollment_ui_controller_property.Get().GetProperty( 311 ui->tab_contents()->property_bag()); 312 313 return controller ? *controller : NULL; 314 } 315 316 // static 317 void EnterpriseEnrollmentUI::SetController( 318 TabContents* contents, 319 EnterpriseEnrollmentUI::Controller* controller) { 320 g_enrollment_ui_controller_property.Get().SetProperty( 321 contents->property_bag(), 322 controller); 323 } 324 325 } // namespace chromeos 326