// 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/ui/webui/chromeos/enterprise_enrollment_ui.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/lazy_instance.h" #include "base/memory/ref_counted_memory.h" #include "base/message_loop.h" #include "base/stringprintf.h" #include "base/values.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/chrome_url_data_manager.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/url_constants.h" #include "content/browser/renderer_host/render_view_host.h" #include "content/browser/tab_contents/tab_contents.h" #include "content/common/bindings_policy.h" #include "content/common/property_bag.h" #include "grit/browser_resources.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" namespace chromeos { static base::LazyInstance< PropertyAccessor<EnterpriseEnrollmentUI::Controller*> > g_enrollment_ui_controller_property(base::LINKER_INITIALIZED); static const char kEnterpriseEnrollmentGaiaLoginPath[] = "gaialogin"; // WebUIMessageHandler implementation which handles events occuring on the page, // such as the user pressing the signin button. class EnterpriseEnrollmentMessageHandler : public WebUIMessageHandler { public: EnterpriseEnrollmentMessageHandler(); virtual ~EnterpriseEnrollmentMessageHandler(); // WebUIMessageHandler implementation. virtual void RegisterMessages() OVERRIDE; private: // Handlers for WebUI messages. void HandleSubmitAuth(const ListValue* args); void HandleCancelAuth(const ListValue* args); void HandleConfirmationClose(const ListValue* args); // Gets the currently installed enrollment controller (if any). EnterpriseEnrollmentUI::Controller* GetController(); DISALLOW_COPY_AND_ASSIGN(EnterpriseEnrollmentMessageHandler); }; // A data source that provides the resources for the enterprise enrollment page. // The enterprise enrollment page requests the HTML and other resources from // this source. class EnterpriseEnrollmentDataSource : public ChromeURLDataManager::DataSource { public: EnterpriseEnrollmentDataSource(); // DataSource implementation. virtual void StartDataRequest(const std::string& path, bool is_off_the_record, int request_id) OVERRIDE; virtual std::string GetMimeType(const std::string& path) const OVERRIDE; private: virtual ~EnterpriseEnrollmentDataSource(); // Saves i18n string for |resource_id| to the |key| property of |dictionary|. static void AddString(DictionaryValue* dictionary, const std::string& key, int resource_id); static void AddString(DictionaryValue* dictionary, const std::string& key, int resource_id, const string16& arg1); DISALLOW_COPY_AND_ASSIGN(EnterpriseEnrollmentDataSource); }; EnterpriseEnrollmentMessageHandler::EnterpriseEnrollmentMessageHandler() {} EnterpriseEnrollmentMessageHandler::~EnterpriseEnrollmentMessageHandler() {} void EnterpriseEnrollmentMessageHandler::RegisterMessages() { web_ui_->RegisterMessageCallback( "SubmitAuth", NewCallback( this, &EnterpriseEnrollmentMessageHandler::HandleSubmitAuth)); web_ui_->RegisterMessageCallback( "DialogClose", NewCallback( this, &EnterpriseEnrollmentMessageHandler::HandleCancelAuth)); web_ui_->RegisterMessageCallback( "confirmationClose", NewCallback( this, &EnterpriseEnrollmentMessageHandler::HandleConfirmationClose)); } void EnterpriseEnrollmentMessageHandler::HandleSubmitAuth( const ListValue* value) { EnterpriseEnrollmentUI::Controller* controller = GetController(); if (!controller) { NOTREACHED(); return; } // Value carries single list entry, which is a json-encoded string that // contains the auth parameters (see gaia_login.js). std::string json_params; if (!value->GetString(0, &json_params)) { NOTREACHED(); return; } // Check the value type. scoped_ptr<Value> params(base::JSONReader::Read(json_params, false)); if (!params.get() || !params->IsType(Value::TYPE_DICTIONARY)) { NOTREACHED(); return; } // Read the parameters. DictionaryValue* params_dict = static_cast<DictionaryValue*>(params.get()); std::string user; std::string pass; std::string captcha; std::string access_code; if (!params_dict->GetString("user", &user) || !params_dict->GetString("pass", &pass) || !params_dict->GetString("captcha", &captcha) || !params_dict->GetString("access_code", &access_code)) { NOTREACHED(); return; } controller->OnAuthSubmitted(user, pass, captcha, access_code); } void EnterpriseEnrollmentMessageHandler::HandleCancelAuth( const ListValue* value) { EnterpriseEnrollmentUI::Controller* controller = GetController(); if (!controller) { NOTREACHED(); return; } controller->OnAuthCancelled(); } void EnterpriseEnrollmentMessageHandler::HandleConfirmationClose( const ListValue* value) { EnterpriseEnrollmentUI::Controller* controller = GetController(); if (!controller) { NOTREACHED(); return; } controller->OnConfirmationClosed(); } EnterpriseEnrollmentUI::Controller* EnterpriseEnrollmentMessageHandler::GetController() { return EnterpriseEnrollmentUI::GetController(web_ui_); } EnterpriseEnrollmentDataSource::EnterpriseEnrollmentDataSource() : DataSource(chrome::kChromeUIEnterpriseEnrollmentHost, MessageLoop::current()) {} void EnterpriseEnrollmentDataSource::StartDataRequest(const std::string& path, bool is_off_the_record, int request_id) { ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance(); DictionaryValue strings; std::string response; if (path.empty()) { AddString(&strings, "loginHeader", IDS_ENTERPRISE_ENROLLMENT_LOGIN_HEADER), AddString(&strings, "loginExplain", IDS_ENTERPRISE_ENROLLMENT_LOGIN_EXPLAIN, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); AddString(&strings, "cloudHeader", IDS_ENTERPRISE_ENROLLMENT_CLOUD_HEADER), AddString(&strings, "cloudExplain", IDS_ENTERPRISE_ENROLLMENT_CLOUD_EXPLAIN); AddString(&strings, "accesscontrolHeader", IDS_ENTERPRISE_ENROLLMENT_ACCESSCONTROL_HEADER), AddString(&strings, "accesscontrolExplain", IDS_ENTERPRISE_ENROLLMENT_ACCESSCONTROL_EXPLAIN); AddString(&strings, "confirmationHeader", IDS_ENTERPRISE_ENROLLMENT_CONFIRMATION_HEADER); AddString(&strings, "confirmationMessage", IDS_ENTERPRISE_ENROLLMENT_CONFIRMATION_MESSAGE); AddString(&strings, "confirmationClose", IDS_ENTERPRISE_ENROLLMENT_CONFIRMATION_CLOSE); static const base::StringPiece html( resource_bundle.GetRawDataResource(IDR_ENTERPRISE_ENROLLMENT_HTML)); SetFontAndTextDirection(&strings); response = jstemplate_builder::GetI18nTemplateHtml(html, &strings); } else if (path == kEnterpriseEnrollmentGaiaLoginPath) { strings.SetString("invalidpasswordhelpurl", ""); strings.SetString("invalidaccessaccounturl", ""); strings.SetString("cannotaccessaccount", ""); strings.SetString("cannotaccessaccounturl", ""); strings.SetString("createaccount", ""); strings.SetString("createnewaccounturl", ""); strings.SetString("getaccesscodehelp", ""); strings.SetString("getaccesscodeurl", ""); // None of the strings used here currently have sync-specific wording in // them. We have a unit test to catch if that happens. strings.SetString("introduction", ""); AddString(&strings, "signinprefix", IDS_SYNC_LOGIN_SIGNIN_PREFIX); AddString(&strings, "signinsuffix", IDS_SYNC_LOGIN_SIGNIN_SUFFIX); AddString(&strings, "cannotbeblank", IDS_SYNC_CANNOT_BE_BLANK); AddString(&strings, "emaillabel", IDS_SYNC_LOGIN_EMAIL); AddString(&strings, "passwordlabel", IDS_SYNC_LOGIN_PASSWORD); AddString(&strings, "invalidcredentials", IDS_SYNC_INVALID_USER_CREDENTIALS); AddString(&strings, "signin", IDS_SYNC_SIGNIN); AddString(&strings, "couldnotconnect", IDS_SYNC_LOGIN_COULD_NOT_CONNECT); AddString(&strings, "cancel", IDS_CANCEL); AddString(&strings, "settingup", IDS_SYNC_LOGIN_SETTING_UP); AddString(&strings, "success", IDS_SYNC_SUCCESS); AddString(&strings, "errorsigningin", IDS_SYNC_ERROR_SIGNING_IN); AddString(&strings, "captchainstructions", IDS_SYNC_GAIA_CAPTCHA_INSTRUCTIONS); AddString(&strings, "invalidaccesscode", IDS_SYNC_INVALID_ACCESS_CODE_LABEL); AddString(&strings, "enteraccesscode", IDS_SYNC_ENTER_ACCESS_CODE_LABEL); static const base::StringPiece html(resource_bundle.GetRawDataResource( IDR_GAIA_LOGIN_HTML)); SetFontAndTextDirection(&strings); response = jstemplate_builder::GetI18nTemplateHtml(html, &strings); } // Send the response. scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes()); html_bytes->data.resize(response.size()); std::copy(response.begin(), response.end(), html_bytes->data.begin()); SendResponse(request_id, html_bytes); } std::string EnterpriseEnrollmentDataSource::GetMimeType( const std::string& path) const { return "text/html"; } EnterpriseEnrollmentDataSource::~EnterpriseEnrollmentDataSource() {} void EnterpriseEnrollmentDataSource::AddString(DictionaryValue* dictionary, const std::string& key, int resource_id) { dictionary->SetString(key, l10n_util::GetStringUTF16(resource_id)); } void EnterpriseEnrollmentDataSource::AddString(DictionaryValue* dictionary, const std::string& key, int resource_id, const string16& arg1) { dictionary->SetString(key, l10n_util::GetStringFUTF16(resource_id, arg1)); } EnterpriseEnrollmentUI::EnterpriseEnrollmentUI(TabContents* contents) : WebUI(contents) {} EnterpriseEnrollmentUI::~EnterpriseEnrollmentUI() {} void EnterpriseEnrollmentUI::RenderViewCreated( RenderViewHost* render_view_host) { // Bail out early if the controller doesn't exist or web ui is disabled. if (!GetController(this) || !(bindings_ & BindingsPolicy::WEB_UI)) return; WebUIMessageHandler* handler = new EnterpriseEnrollmentMessageHandler(); AddMessageHandler(handler->Attach(this)); // Set up the data source, so the enrollment page can be loaded. tab_contents()->profile()->GetChromeURLDataManager()->AddDataSource( new EnterpriseEnrollmentDataSource()); std::string user; bool has_init_user = GetController(this)->GetInitialUser(&user); if (!has_init_user) user = ""; // Set the arguments for showing the gaia login page. DictionaryValue args; args.SetString("user", user); args.SetInteger("error", 0); args.SetBoolean("editable_user", !has_init_user); args.SetString("initialScreen", "login-screen"); std::string json_args; base::JSONWriter::Write(&args, false, &json_args); render_view_host->SetWebUIProperty("dialogArguments", json_args); } // static EnterpriseEnrollmentUI::Controller* EnterpriseEnrollmentUI::GetController( WebUI* ui) { Controller** controller = g_enrollment_ui_controller_property.Get().GetProperty( ui->tab_contents()->property_bag()); return controller ? *controller : NULL; } // static void EnterpriseEnrollmentUI::SetController( TabContents* contents, EnterpriseEnrollmentUI::Controller* controller) { g_enrollment_ui_controller_property.Get().SetProperty( contents->property_bag(), controller); } } // namespace chromeos