Commit 7abb9382 authored by yilkal's avatar yilkal Committed by Commit Bot

Show error page when oauth2 access token fetch fails.

If access token fetch fails, this cl logs the error and shows
the error screen.

Bug: 1144327
Change-Id: Ib8c4fbd3226cc05910eb209ba5ead1f47fd097b0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2511909Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarAga Wronska <agawronska@chromium.org>
Commit-Queue: Yilkal Abe <yilkal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#823832}
parent 621663f8
......@@ -84,6 +84,10 @@ Polymer({
/** @override */
ready() {
this.addWebUIListener('show-error-screen', () => {
this.onError_();
});
window.addEventListener('online', () => {
if (this.currentScreen_ !== Screens.ERROR) {
this.switchToScreen_(Screens.ONLINE_FLOW);
......
......@@ -6,6 +6,7 @@ import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js
import {AuthCompletedCredentials} from '../../gaia_auth_host/authenticator.m.js';
/** TODO(yilkal): Improve the naming of methods in the proxy. */
/** @interface */
export class EduCoexistenceBrowserProxy {
......@@ -48,15 +49,20 @@ export class EduCoexistenceBrowserProxy {
* the parental consent is valid.
* @param {string} account Added account email.
* @param {string} eduCoexistenceToSVersion The terms of service version.
* @return {!Promise<boolean>}
* @return {!Promise<boolean>} Returns a promise which will resolve to true
* when the account has successfully been added. The promise will be used
* by the server flow to show "Account added" page.
*/
consentLogged(account, eduCoexistenceToSVersion) {}
/** Sends 'dialogClose' message to close the login dialog. */
dialogClose() {}
/** Sends 'error' message to handler. */
error() {}
/**
* Sends 'error' message to handler.
* @param {Array<string>} msg Error messages.
*/
onError(msg) {}
}
/**
......@@ -106,8 +112,8 @@ export class EduCoexistenceBrowserProxyImpl {
}
/** @override */
error() {
chrome.send('error');
onError(msg) {
chrome.send('error', msg);
}
}
......
......@@ -63,16 +63,18 @@ function constructEduCoexistenceUrl(params) {
*/
export class EduCoexistenceController extends PostMessageAPIServer {
/**
* @param {!Element} ui Polymer object edu-coexistence-ui
* @param {!Element} webview The <webview> element to listen to as a
* client.
* @param {!EduCoexistenceParams} params The params for the flow.
*/
constructor(webview, params) {
constructor(ui, webview, params) {
const flowURL = constructEduCoexistenceUrl(params);
const protocol = flowURL.hostname === 'localhost' ? 'http://' : 'https://';
const originURLPrefix = protocol + flowURL.host;
super(webview, METHOD_LIST, originURLPrefix, originURLPrefix);
this.ui = ui;
this.flowURL_ = flowURL;
this.originURLPrefix_ = originURLPrefix;
this.webview_ = webview;
......@@ -264,8 +266,10 @@ export class EduCoexistenceController extends PostMessageAPIServer {
* index 0.
*/
reportError_(error) {
// TODO(yilkal): Pass the error to the browser proxy.
// TODO(danan): Show the error ui (possibly using the error message).
this.browserProxy_.error();
// Notify the app to switch to error screen.
this.ui.fire('go-error');
// Send the error strings to C++ handler so they are logged.
this.browserProxy_.onError(error);
}
}
......@@ -134,12 +134,15 @@ Polymer({
(data) => {
this.webview_ =
/** @type {!WebView} */ (this.$.signinFrame);
this.controller_ = new EduCoexistenceController(this.webview_, data);
this.controller_ =
new EduCoexistenceController(this, this.webview_, data);
EduCoexistenceBrowserProxyImpl.getInstance().initializeLogin();
},
(err) => {
console.error('There was an error getting edu coexistence data');
this.fire('go-error');
EduCoexistenceBrowserProxyImpl.getInstance().onError(
['There was an error getting edu coexistence data']);
});
},
});
......@@ -136,7 +136,41 @@ IN_PROC_BROWSER_TEST_F(EduCoexistenceLoginHandlerBrowserTest,
VerifyJavascriptCallResolved(second_call, callback_id, kResponseCallback);
}
// TODO(yilkal): Add test to cover for when OauthAccessTokenFetchFails.
IN_PROC_BROWSER_TEST_F(EduCoexistenceLoginHandlerBrowserTest,
ErrorCallsFromWebUI) {
std::unique_ptr<EduCoexistenceLoginHandler> handler = SetUpHandler();
base::ListValue call_args;
call_args.Append("error message 1");
call_args.Append("error message 2");
web_ui()->HandleReceivedMessage("error", &call_args);
EXPECT_TRUE(handler->in_error_state());
}
IN_PROC_BROWSER_TEST_F(EduCoexistenceLoginHandlerBrowserTest,
OAuth2AccessTokensFetchFailed) {
std::unique_ptr<EduCoexistenceLoginHandler> handler = SetUpHandler();
SimulateAccessTokenFetched(handler.get(), /* success */ false);
// Error messages are not sent until initialize message is sent from js to
// C++ handler.
EXPECT_EQ(web_ui()->call_data().size(), 0u);
base::ListValue call_args;
call_args.Append("coexistence-data-init");
web_ui()->HandleReceivedMessage("initializeEduArgs", &call_args);
EXPECT_EQ(web_ui()->call_data().size(), 1u);
EXPECT_EQ(web_ui()->call_data()[0]->function_name(),
"cr.webUIListenerCallback");
const base::Value* arg1 = web_ui()->call_data()[0]->arg1();
std::string method_call = arg1 ? arg1->GetString() : std::string();
constexpr char kWebUICallErrorCallback[] = "show-error-screen";
EXPECT_EQ(method_call, kWebUICallErrorCallback);
}
IN_PROC_BROWSER_TEST_F(EduCoexistenceLoginHandlerBrowserTest,
HandleConsentLogged) {
......
......@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/check.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/guid.h"
......@@ -53,6 +54,7 @@ constexpr char kEduCoexistenceLoginDefaultURL[] =
"https://families.google.com/supervision/coexistence";
constexpr char kOobe[] = "oobe";
constexpr char kInSession[] = "in_session";
constexpr char kOnErrorWebUIListener[] = "show-error-screen";
constexpr char kFetchAccessTokenResultHistogram[] =
"AccountManager.EduCoexistence.FetchAccessTokenResult";
......@@ -219,7 +221,10 @@ void EduCoexistenceLoginHandler::OnOAuthAccessTokensFetched(
GoogleServiceAuthError::NUM_STATES);
if (error.state() != GoogleServiceAuthError::State::NONE) {
// TODO(yilkal) call on to the ui to show error screen.
if (initialize_edu_args_callback_.has_value()) {
FireWebUIListener(kOnErrorWebUIListener);
}
in_error_state_ = true;
return;
}
......@@ -235,6 +240,11 @@ void EduCoexistenceLoginHandler::InitializeEduArgs(
initialize_edu_args_callback_ = args->GetList()[0].GetString();
if (in_error_state_) {
FireWebUIListener(kOnErrorWebUIListener);
return;
}
// If the access token is not fetched yet, wait for access token.
if (!oauth_access_token_.has_value()) {
return;
......@@ -290,6 +300,7 @@ void EduCoexistenceLoginHandler::SendInitializeEduArgs() {
void EduCoexistenceLoginHandler::ConsentValid(const base::ListValue* args) {
AllowJavascript();
DCHECK(!in_error_state_);
// TODO(yilkal): Have a state enum to record the progress.
}
......@@ -297,6 +308,8 @@ void EduCoexistenceLoginHandler::ConsentLogged(const base::ListValue* args) {
if (!args || args->GetList().size() == 0)
return;
DCHECK(!in_error_state_);
account_added_callback_ = args->GetList()[0].GetString();
const base::Value::ConstListView& arguments = args->GetList()[1].GetList();
......@@ -309,7 +322,15 @@ void EduCoexistenceLoginHandler::ConsentLogged(const base::ListValue* args) {
}
void EduCoexistenceLoginHandler::OnError(const base::ListValue* args) {
// TODO(yilkal): Handle error appropriately.
AllowJavascript();
if (!args || args->GetList().size() == 0)
return;
in_error_state_ = true;
const base::Value::ConstListView& arguments = args->GetList();
for (const base::Value& message : arguments) {
DCHECK(message.is_string());
LOG(ERROR) << message.GetString();
}
}
} // namespace chromeos
......@@ -48,6 +48,8 @@ class EduCoexistenceLoginHandler : public content::WebUIMessageHandler,
void set_web_ui_for_test(content::WebUI* web_ui) { set_web_ui(web_ui); }
bool in_error_state() const { return in_error_state_; }
private:
// Registered WebUi Message handlers.
void InitializeEduArgs(const base::ListValue* args);
......@@ -75,6 +77,16 @@ class EduCoexistenceLoginHandler : public content::WebUIMessageHandler,
std::string terms_of_service_version_number_;
signin::IdentityManager* const identity_manager_;
// |in_error_state_| boolean tracks whether an error has occurred.
// The error could happen when trying to access OAuth tokens.
// The error could be reported from the online flow through the
// |EduCoexistenceLoginHandler::OnError| call.
// If the object is in error state and |InitializeEduArgs| is called, this
// class will notify the ui to show the error screen through calling the
// "on-error" webui javascript listener.
// The other message callbacks can't be called from js in error state.
bool in_error_state_ = false;
};
} // namespace chromeos
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment