Commit e78513d7 authored by Anastasiia Nikolaienko's avatar Anastasiia Nikolaienko Committed by Commit Bot

Migrate authenticator.js and it's dependencies to JS modules

Bug: 1054394
Change-Id: I106bd0edc547dc6eb2d680b409d1348d5b964079
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2066548
Commit-Queue: Anastasiia Nikolaienko <anastasiian@chromium.org>
Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Reviewed-by: default avatardpapad <dpapad@chromium.org>
Cr-Commit-Position: refs/heads/master@{#745762}
parent 64aa728b
......@@ -1393,6 +1393,7 @@ group("extra_resources") {
"//chrome/browser/resources:component_extension_resources",
"//chrome/browser/resources:dev_ui_paks",
"//chrome/browser/resources:downloads_resources",
"//chrome/browser/resources:gaia_auth_host_resources",
"//chrome/browser/resources:history_resources",
"//chrome/browser/resources:local_ntp_resources",
"//chrome/browser/resources:new_tab_page_resources",
......
......@@ -5557,6 +5557,7 @@ grit("resources") {
if (is_win || is_mac || is_desktop_linux || is_chromeos) {
deps += [
"//chrome/browser/resources/discards:discards_resources_gen",
"//chrome/browser/resources/gaia_auth_host:modulize",
"//chrome/browser/resources/management:polymer3_elements",
"//chrome/browser/resources/signin:polymer3_elements",
"//chrome/browser/ui/webui/discards:mojo_bindings_js",
......
......@@ -26,6 +26,7 @@ if (closure_compile) {
"discards:closure_compile",
"download_internals:closure_compile",
"downloads:closure_compile",
"gaia_auth_host:closure_compile",
"history:closure_compile",
"local_ntp:closure_compile",
"local_state:closure_compile",
......@@ -138,6 +139,27 @@ if (!is_android) {
output_dir = "$root_gen_dir/chrome"
}
grit("gaia_auth_host_resources") {
# The .grd contains references to generated files.
source_is_generated = true
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
]
source = "gaia_auth_host/gaia_auth_host_resources.grd"
deps = [ "//chrome/browser/resources/gaia_auth_host:closure_compile" ]
defines = chrome_grit_defines
outputs = [
"grit/gaia_auth_host_resources.h",
"grit/gaia_auth_host_resources_map.cc",
"grit/gaia_auth_host_resources_map.h",
"gaia_auth_host_resources.pak",
]
output_dir = "$root_gen_dir/chrome"
}
grit("history_resources") {
# The .grd contains references to generated files.
source_is_generated = true
......
......@@ -3,6 +3,8 @@
# found in the LICENSE file.
import("//chrome/test/base/js2gtest.gni")
import("//third_party/closure_compiler/compile_js.gni")
import("//ui/webui/resources/tools/js_modulizer.gni")
js2gtest("login_unitjs_tests") {
# These could be unit tests, except they need a browser context in order
......@@ -24,3 +26,95 @@ source_set("browser_tests") {
testonly = true
deps = [ ":login_unitjs_tests" ]
}
js_type_check("closure_compile") {
uses_js_modules = true
deps = [
":authenticator.m",
":channel.m",
":post_message_channel.m",
":saml_handler.m",
":saml_password_attributes.m",
":saml_timestamps.m",
":webview_event_manager.m",
]
}
js_library("channel.m") {
sources =
[ "$root_gen_dir/chrome/browser/resources/gaia_auth_host/channel.m.js" ]
extra_deps = [ ":modulize" ]
}
js_library("webview_event_manager.m") {
sources = [ "$root_gen_dir/chrome/browser/resources/gaia_auth_host/webview_event_manager.m.js" ]
extra_deps = [ ":modulize" ]
}
js_library("post_message_channel.m") {
sources = [ "$root_gen_dir/chrome/browser/resources/gaia_auth_host/post_message_channel.m.js" ]
deps = [ ":channel.m" ]
extra_deps = [ ":modulize" ]
}
js_library("saml_password_attributes.m") {
sources = [ "$root_gen_dir/chrome/browser/resources/gaia_auth_host/saml_password_attributes.m.js" ]
deps = [ ":saml_timestamps.m" ]
extra_deps = [ ":modulize" ]
}
js_library("saml_timestamps.m") {
sources = [ "$root_gen_dir/chrome/browser/resources/gaia_auth_host/saml_timestamps.m.js" ]
extra_deps = [ ":modulize" ]
}
js_library("saml_handler.m") {
sources = [
"$root_gen_dir/chrome/browser/resources/gaia_auth_host/saml_handler.m.js",
]
deps = [
":channel.m",
":post_message_channel.m",
":webview_event_manager.m",
]
extra_deps = [ ":modulize" ]
}
js_library("authenticator.m") {
sources = [
"$root_gen_dir/chrome/browser/resources/gaia_auth_host/authenticator.m.js",
]
deps = [
":saml_handler.m",
"//ui/webui/resources/js:assert.m",
"//ui/webui/resources/js:cr.m",
"//ui/webui/resources/js:util.m",
"//ui/webui/resources/js/cr:event_target.m",
]
externs_list = [
"$externs_path/chrome_extensions.js",
"$externs_path/webview_tag.js",
]
extra_deps = [ ":modulize" ]
}
js_modulizer("modulize") {
input_files = [
"authenticator.js",
"channel.js",
"post_message_channel.js",
"saml_handler.js",
"saml_password_attributes.js",
"saml_timestamps.js",
"webview_event_manager.js",
]
namespace_rewrites = [
"DOMWindow|Object",
"cr.EventTarget|EventTarget",
"cr.login.SamlHandler|SamlHandler",
"samlPasswordAttributes.PasswordAttributes|PasswordAttributes",
"samlPasswordAttributes.readPasswordAttributes|readPasswordAttributes",
"samlTimestamps.decodeTimestamp|decodeTimestamp",
"XMLDocument|Object",
]
}
......@@ -5,6 +5,16 @@
// <include src="saml_handler.js">
// Note: webview_event_manager.js is already included by saml_handler.js.
// clang-format off
// #import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js'
// #import {assert} from 'chrome://resources/js/assert.m.js';
// #import {$, appendParam} from 'chrome://resources/js/util.m.js';
// #import {sendWithPromise} from 'chrome://resources/js/cr.m.js';
// #import {SamlHandler, OnHeadersReceivedDetails} from './saml_handler.m.js';
// #import {WebviewEventManager} from './webview_event_manager.m.js';
// clang-format on
/**
* @fileoverview An UI component to authenticate to Chrome. The component hosts
* IdP web pages in a webview. A client who is interested in monitoring
......@@ -15,7 +25,33 @@
*/
cr.define('cr.login', function() {
'use strict';
/* #ignore */ 'use strict';
/**
* Parameters for the authorization flow.
* @typedef {{
* hl: string,
* gaiaUrl: string,
* authMode: Number,
* isLoginPrimaryAccount: boolean,
* email: string,
* constrained: string,
* readOnlyEmail: boolean,
* service: string,
* dontResizeNonEmbeddedPages: boolean,
* clientId: string,
* gaiaPath: string,
* emailDomain: string,
* showTos: string,
* extractSamlPasswordAttributes: boolean,
* flow: string,
* ignoreCrOSIdpSetting: boolean,
* enableGaiaActionButtons: boolean,
* enterpriseEnrollmentDomain: string,
* samlAclUrl: string
* }}
*/
/* #export */ let AuthParams;
// TODO(rogerta): should use gaia URL from GaiaUrls::gaia_url() instead
// of hardcoding the prod URL here. As is, this does not work with staging
......@@ -32,20 +68,20 @@ cr.define('cr.login', function() {
/**
* The source URL parameter for the constrained signin flow.
*/
const CONSTRAINED_FLOW_SOURCE = 'chrome';
/* #export */ const CONSTRAINED_FLOW_SOURCE = 'chrome';
/**
* Enum for the authorization mode, must match AuthMode defined in
* chrome/browser/ui/webui/inline_login_ui.cc.
* @enum {number}
*/
const AuthMode = {DEFAULT: 0, OFFLINE: 1, DESKTOP: 2};
/* #export */ const AuthMode = {DEFAULT: 0, OFFLINE: 1, DESKTOP: 2};
/**
* Enum for the authorization type.
* @enum {number}
*/
const AuthFlow = {DEFAULT: 0, SAML: 1};
/* #export */ const AuthFlow = {DEFAULT: 0, SAML: 1};
/**
* Supported Authenticator params.
......@@ -215,7 +251,7 @@ cr.define('cr.login', function() {
/**
* Initializes the authenticator component.
*/
class Authenticator extends cr.EventTarget {
/* #export */ class Authenticator extends cr.EventTarget {
/**
* @param {!WebView|string} webview The webview element or its ID to host
* IdP web pages.
......@@ -230,6 +266,10 @@ cr.define('cr.login', function() {
this.chooseWhatToSync_ = false;
this.skipForNow_ = false;
this.authFlow = AuthFlow.DEFAULT;
/** @type {AuthMode} */
this.authMode = AuthMode.DEFAULT;
this.dontResizeNonEmbeddedPages = false;
this.authDomain = '';
/**
* @type {!cr.login.SamlHandler|undefined}
......@@ -243,7 +283,12 @@ cr.define('cr.login', function() {
this.trusted_ = true;
this.readyFired_ = false;
this.authCompletedFired_ = false;
this.webview_ = typeof webview == 'string' ? $(webview) : webview;
/**
* @private {WebView|undefined}
*/
this.webview_ = typeof webview == 'string' ?
/** @type {WebView} */ ($(webview)) :
webview;
assert(this.webview_);
this.enableGaiaActionButtons_ = false;
this.webviewEventManager_ = WebviewEventManager.create();
......@@ -260,7 +305,7 @@ cr.define('cr.login', function() {
* Callback allowing to request whether the specified user which
* authenticates via SAML is a user without a password (neither a manually
* entered one nor one provided via Credentials Passing API).
* @type {function(string, string, function(boolean))} Arguments are the
* @type {?function(string, string, function(boolean))} Arguments are the
* e-mail, the GAIA ID, and the response callback.
*/
this.getIsSamlUserPasswordlessCallback = null;
......@@ -273,6 +318,8 @@ cr.define('cr.login', function() {
* @private
*/
this.isSamlUserPasswordless_ = null;
/** @private {boolean} */
this.isConstrainedWindow_ = false;
this.samlAclUrl_ = null;
window.addEventListener(
......@@ -398,7 +445,8 @@ cr.define('cr.login', function() {
/**
* Re-binds to another webview.
* @param {Object} webview the new webview to be used by this Authenticator.
* @param {WebView} webview the new webview to be used by this
* Authenticator.
* @private
*/
rebindWebview_(webview) {
......@@ -455,14 +503,14 @@ cr.define('cr.login', function() {
webivewParent.replaceChild(newWebview, this.webview_);
this.rebindWebview_(newWebview);
this.rebindWebview_(/** @type {WebView} */ (newWebview));
}
}
/**
* Loads the authenticator component with the given parameters.
* @param {AuthMode} authMode Authorization mode.
* @param {Object} data Parameters for the authorization flow.
* @param {AuthParams} data Parameters for the authorization flow.
*/
load(authMode, data) {
this.authMode = authMode;
......@@ -576,7 +624,7 @@ cr.define('cr.login', function() {
}
if (data.isFirstUser) {
url = appendParam(url, 'is_first_user', true);
url = appendParam(url, 'is_first_user', 'true');
if (data.lsbReleaseBoard) {
url = appendParam(url, 'chromeos_board', data.lsbReleaseBoard);
......@@ -615,7 +663,7 @@ cr.define('cr.login', function() {
url = appendParam(url, 'ignoreCrOSIdpSetting', 'true');
}
if (data.enableGaiaActionButtons) {
url = appendParam(url, 'use_native_navigation', 1);
url = appendParam(url, 'use_native_navigation', '1');
}
return url;
}
......@@ -684,10 +732,9 @@ cr.define('cr.login', function() {
/**
* Invoked when the sign-in page takes focus.
* @param {object} e The focus event being triggered.
* @private
*/
onFocus_(e) {
onFocus_() {
if (this.authMode == AuthMode.DESKTOP &&
document.activeElement == document.body) {
this.webview_.focus();
......@@ -696,7 +743,7 @@ cr.define('cr.login', function() {
/**
* Invoked when the history state is changed.
* @param {object} e The popstate event being triggered.
* @param {!Event} e The popstate event being triggered.
* @private
*/
onPopState_(e) {
......@@ -710,7 +757,7 @@ cr.define('cr.login', function() {
* Invoked when headers are received in the main frame of the webview. It
* 1) reads the authenticated user info from a signin header,
* 2) signals the start of a saml flow upon receiving a saml header.
* @return {!Object} Modified request headers.
* @param {OnHeadersReceivedDetails} details
* @private
*/
onHeadersReceived_(details) {
......@@ -745,6 +792,7 @@ cr.define('cr.login', function() {
} else if (headerName == LOCATION_HEADER) {
// If the "choose what to sync" checkbox was clicked, then the
// continue URL will contain a source=3 field.
assert(header.value);
const location = decodeURIComponent(header.value);
this.chooseWhatToSync_ = !!location.match(/(\?|&)source=3($|&)/);
}
......@@ -753,7 +801,7 @@ cr.define('cr.login', function() {
/**
* Returns true if given HTML5 message is received from the webview element.
* @param {object} e Payload of the received HTML5 message.
* @param {Object} e Payload of the received HTML5 message.
*/
isGaiaMessage(e) {
if (!this.isWebviewEvent_(e)) {
......@@ -775,7 +823,7 @@ cr.define('cr.login', function() {
/**
* Invoked when an HTML5 message is received from the webview element.
* @param {object} e Payload of the received HTML5 message.
* @param {Object} e Payload of the received HTML5 message.
* @private
*/
onMessageFromWebview_(e) {
......@@ -796,7 +844,7 @@ cr.define('cr.login', function() {
/**
* Invoked to send a HTML5 message to the webview element.
* @param {object} e Payload of the HTML5 message.
* @param {Object} payload Payload of the HTML5 message.
*/
sendMessageToWebview(payload) {
const currentUrl = this.webview_.src;
......@@ -1196,6 +1244,7 @@ cr.define('cr.login', function() {
}
}
// #cr_define_end
/**
* The current auth flow of the hosted auth page.
* @type {AuthFlow}
......
......@@ -4,8 +4,9 @@
/**
* Channel to the background script.
* @constructor
*/
function Channel() {
/* #export */ function Channel() {
this.messageCallbacks_ = {};
this.internalRequestCallbacks_ = {};
}
......
<?xml version="1.0" encoding="UTF-8"?>
<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
<outputs>
<output filename="grit/gaia_auth_host_resources.h" type="rc_header">
<emit emit_type='prepend'></emit>
</output>
<output filename="grit/gaia_auth_host_resources_map.cc"
type="resource_file_map_source" />
<output filename="grit/gaia_auth_host_resources_map.h"
type="resource_map_header" />
<output filename="gaia_auth_host_resources.pak" type="data_package" />
</outputs>
<release seq="1">
<includes>
<include name="IDR_GAIA_AUTH_AUTHENTICATOR_M_JS"
file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/authenticator.m.js"
use_base_dir="false"
type ="BINDATA"
compress="gzip" />
<include name="IDR_GAIA_AUTH_SAML_HANDLER_M_JS"
file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/saml_handler.m.js"
use_base_dir="false"
type ="BINDATA"
compress="gzip" />
<include name="IDR_GAIA_AUTH_CHANNEL_M_JS"
file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/channel.m.js"
use_base_dir="false"
type ="BINDATA"
compress="gzip" />
<include name="IDR_GAIA_AUTH_POST_MESSAGE_CHANNEL_M_JS"
file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/post_message_channel.m.js"
use_base_dir="false"
type ="BINDATA"
compress="gzip" />
<include name="IDR_GAIA_AUTH_WEBVIEW_EVENT_MANAGER_M_JS"
file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/webview_event_manager.m.js"
use_base_dir="false"
type ="BINDATA"
compress="gzip" />
<include name="IDR_GAIA_AUTH_SAML_PASSWORD_ATTRIBUTES_M_JS"
file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/saml_password_attributes.m.js"
use_base_dir="false"
type ="BINDATA"
compress="gzip" />
<include name="IDR_GAIA_AUTH_SAML_TIMESTAMPS_M_JS"
file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/saml_timestamps.m.js"
use_base_dir="false"
type ="BINDATA"
compress="gzip" />
</includes>
</release>
</grit>
......@@ -11,7 +11,11 @@
// <include src="channel.js">
const PostMessageChannel = (function() {
// clang-format off
// #import {Channel} from './channel.m.js';
// clang-format on
/* #export */ const PostMessageChannel = (function() {
/**
* Allowed origins of the hosting page.
* @type {Array<string>}
......@@ -37,6 +41,7 @@ const PostMessageChannel = (function() {
/**
* A simple event target.
* @constructor
*/
function EventTarget() {
this.listeners_ = [];
......@@ -136,7 +141,8 @@ const PostMessageChannel = (function() {
createPort(channelId, channelName, opt_targetWindow, opt_targetOrigin) {
const port = new PostMessagePort(channelId, channelName);
if (opt_targetWindow) {
port.setTarget(opt_targetWindow, opt_targetOrigin);
port.setTarget(
opt_targetWindow, /** @type {string} */ (opt_targetOrigin));
}
this.channels_[channelId] = port;
return port;
......@@ -169,13 +175,13 @@ const PostMessageChannel = (function() {
/**
* Creates a connecting port to the daemon and request connection.
* @param {string} name
* @return {PostMessagePort}
* @return {?PostMessagePort}
*/
connectToDaemon(name) {
if (this.isDaemon) {
console.error(
'Error: Connecting from the daemon page is not supported.');
return;
return null;
}
const port = this.createPort(this.createChannelId_(), name);
......@@ -270,6 +276,7 @@ const PostMessageChannel = (function() {
/**
* A HTML5 postMessage based port that provides the same port interface
* as the messaging API port.
* @constructor
* @param {number} channelId
* @param {string} name
*/
......@@ -362,7 +369,6 @@ const PostMessageChannel = (function() {
return PostMessageChannel;
})();
/** @override */
Channel.create = function() {
return new PostMessageChannel();
};
......@@ -6,12 +6,20 @@
// <include src="webview_event_manager.js">
// <include src="saml_password_attributes.js">
// clang-format off
// #import {Channel} from './channel.m.js';
// #import {PostMessageChannel} from './post_message_channel.m.js';
// #import {WebviewEventManager} from './webview_event_manager.m.js';
// #import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js'
// #import {PasswordAttributes, readPasswordAttributes} from './saml_password_attributes.m.js';
// clang-format on
/**
* @fileoverview Saml support for webview based auth.
*/
cr.define('cr.login', function() {
'use strict';
/* #ignore */ 'use strict';
/**
* The lowest version of the credentials passing API supported.
......@@ -53,6 +61,47 @@ cr.define('cr.login', function() {
// <include src="webview_saml_injected.js">
`;
/**
* @typedef {{
* method: string,
* requestedVersion: number,
* keyType: string,
* token: string,
* passwordBytes: string
* }}
*/
let ApiCallMessageCall;
/**
* @typedef {{
* name: string,
* call: ApiCallMessageCall
* }}
*/
let ApiCallMessage;
/**
* Details about the request.
* @typedef {{
* method: string,
* requestBody: Object,
* url: string
* }}
* @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onBeforeRequest#details
*/
/* #export */ let OnBeforeRequestDetails;
/**
* Details of the request.
* @typedef {{
* responseHeaders: Array<HttpHeader>,
* statusCode: number,
* url: string,
* }}
* @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onHeadersReceived#details
*/
/* #export */ let OnHeadersReceivedDetails;
/**
* Creates a new URL by striping all query parameters.
* @param {string} url The original URL.
......@@ -77,9 +126,9 @@ cr.define('cr.login', function() {
* A handler to provide saml support for the given webview that hosts the
* auth IdP pages.
*/
class SamlHandler extends cr.EventTarget {
/* #export */ class SamlHandler extends cr.EventTarget {
/**
* @param {webview} webview
* @param {!WebView} webview
* @param {boolean} startsOnSamlPage - whether initial URL is already SAML
* page
* */
......@@ -108,25 +157,26 @@ cr.define('cr.login', function() {
/**
* The webview that serves IdP pages.
* @type {webview}
* @private {!WebView}
*/
this.webview_ = webview;
/**
* Whether a Saml page is in the webview from the start.
* @private {boolean}
*/
this.startsOnSamlPage_ = startsOnSamlPage;
/**
* Whether a Saml IdP page is display in the webview.
* @type {boolean}
* @private {boolean}
*/
this.isSamlPage_ = this.startsOnSamlPage_;
/**
* Pending Saml IdP page flag that is set when a SAML_HEADER is received
* and is copied to |isSamlPage_| in loadcommit.
* @type {boolean}
* @private {boolean}
*/
this.pendingIsSamlPage_ = this.startsOnSamlPage_;
......@@ -134,7 +184,7 @@ cr.define('cr.login', function() {
* The last aborted top level url. It is recorded in loadabort event and
* used to skip injection into Chrome's error page in the following
* loadcommit event.
* @type {string}
* @private {?string}
*/
this.abortedTopLevelUrl_ = null;
......@@ -146,38 +196,38 @@ cr.define('cr.login', function() {
/**
* Scraped password stored in an id to password field value map.
* @type {Object<string, string>}
* @private
* @private {!Object<string, string>}
*/
this.passwordStore_ = {};
/**
* Whether Saml API is initialized.
* @type {boolean}
* @private {boolean}
*/
this.apiInitialized_ = false;
/**
* Saml API version to use.
* @type {number}
* @private {number}
*/
this.apiVersion_ = 0;
/**
* Saml API tokens received.
* @type {Object}
* @private {!Object}
*/
this.apiTokenStore_ = {};
/**
* Saml API confirmation token. Set by last 'confirm' call.
* @private {?string}
*/
this.confirmToken_ = null;
/**
* Saml API password bytes set by last 'add' call. Needed to not break
* existing behavior.
* @type {string}
* @private {?string}
*/
this.lastApiPasswordBytes_ = null;
......@@ -197,29 +247,26 @@ cr.define('cr.login', function() {
/**
* Current stage of device attestation flow.
* @type {DeviceAttestationStage}
* @private
* @private {!SamlHandler.DeviceAttestationStage}
*/
this.deviceAttestationStage_ = SamlHandler.DeviceAttestationStage.NONE;
/**
* Challenge from IdP to perform device attestation.
* @type {?string}
* @private
* @private {?string}
*/
this.verifiedAccessChallenge_ = null;
/**
* Response for a device attestation challenge.
* @type {?string}
* @private
* @private {?string}
*/
this.verifiedAccessChallengeResponse_ = null;
/**
* The password-attributes that were extracted from the SAMLResponse, if
* any. (Doesn't contain the password itself).
* @type {PasswordAttributes}
* @private {!PasswordAttributes}
*/
this.passwordAttributes_ =
samlPasswordAttributes.PasswordAttributes.EMPTY;
......@@ -289,7 +336,7 @@ cr.define('cr.login', function() {
/**
* Returns the Saml API password bytes.
* @return {string}
* @return {?string}
*/
get apiPasswordBytes() {
if (this.confirmToken_ != null &&
......@@ -350,7 +397,7 @@ cr.define('cr.login', function() {
/**
* Gets the password attributes extracted from SAML Response.
* @return {PasswordAttributes}
* @return {Object}
*/
get passwordAttributes() {
return this.passwordAttributes_;
......@@ -483,18 +530,24 @@ cr.define('cr.login', function() {
* Handler for webRequest.onBeforeRequest that looks for the Base64
* encoded SAMLResponse in the POST-ed formdata sent from the SAML page.
* Non-blocking.
* @param {Object} details The web-request details.
* @param {OnBeforeRequestDetails} details The web-request details.
*/
onMainFrameWebRequest(details) {
if (!this.extractSamlPasswordAttributes) return;
if (!this.isSamlPage_ || details.method != 'POST') return;
if (!this.extractSamlPasswordAttributes) {
return;
}
if (!this.isSamlPage_ || details.method != 'POST') {
return;
}
const formData = details.requestBody.formData;
let samlResponse = (formData && formData.SAMLResponse);
if (!samlResponse) {
samlResponse = new URL(details.url).searchParams.get('SAMLResponse');
}
if (!samlResponse) return;
if (!samlResponse) {
return;
}
try {
// atob means asciiToBinary, which actually means base64Decode:
......@@ -705,7 +758,7 @@ cr.define('cr.login', function() {
/**
* Handlers for channel messages.
* @param {Channel} channel A channel to send back response.
* @param {Object} msg Received message.
* @param {ApiCallMessage} msg Received message.
* @private
*/
onAPICall_(channel, msg) {
......@@ -736,7 +789,7 @@ cr.define('cr.login', function() {
this.dispatchEvent(new CustomEvent('apiPasswordAdded'));
} else if (call.method == 'confirm') {
if (!call.token in this.apiTokenStore_) {
if (!(call.token in this.apiTokenStore_)) {
console.error('SamlHandler.onAPICall_: token mismatch');
} else {
this.confirmToken_ = call.token;
......@@ -777,5 +830,6 @@ cr.define('cr.login', function() {
}
}
// #cr_define_end
return {SamlHandler: SamlHandler};
});
......@@ -4,6 +4,10 @@
// <include src="saml_timestamps.js">
// clang-format off;
// #import {decodeTimestamp} from './saml_timestamps.m.js';
// clang-format on
/**
* @fileoverview A utility for extracting password information from SAML
* authorization response. This requires that the SAML IDP administrator
......@@ -11,7 +15,7 @@
*/
cr.define('samlPasswordAttributes', function() {
'use strict';
/* #ignore */ 'use strict';
/** @const @private {number} The shortest XML string that could be useful. */
const MIN_SANE_XML_LENGTH = 100;
......@@ -63,7 +67,7 @@ cr.define('samlPasswordAttributes', function() {
* could be extracted, formatted as strings. Some or all of the strings can
* be empty if some or all of the attributes could not be extracted.
*/
function readPasswordAttributes(xmlStr) {
/* #export */ function readPasswordAttributes(xmlStr) {
// Don't throw any exception that could cause login to fail - extracting
// these attributes can fail, but login should not be interrupted.
try {
......@@ -135,7 +139,7 @@ cr.define('samlPasswordAttributes', function() {
* saml_password_attributes.cc must also be changed.
* @export @final
*/
class PasswordAttributes {
/* #export */ class PasswordAttributes {
constructor(modifiedTime, expirationTime, passwordChangeUrl) {
/** @type {string} Password last-modified timestamp. */
this.modifiedTime = modifiedTime;
......@@ -153,7 +157,7 @@ cr.define('samlPasswordAttributes', function() {
/** An immutable and empty PasswordAttributes struct. */
PasswordAttributes.EMPTY = new PasswordAttributes('', '', '');
// Public functions:
// #cr_define_end
return {
readPasswordAttributes: readPasswordAttributes,
PasswordAttributes: PasswordAttributes,
......
......@@ -44,14 +44,14 @@ cr.define('samlTimestamps', function() {
* @param {string} str A timestamp formatted as a string.
* @return {?Date} A valid decoded timestamp, or null.
*/
function decodeTimestamp(str) {
/* #export */ function decodeTimestamp(str) {
str = str.trim();
if (str.length == 0 || str.length > MAX_SANE_LENGTH) {
return null;
}
if (INTEGER_PATTERN.test(str)) {
return decodeIntegerTimestamp(parseInt(str));
return decodeIntegerTimestamp(parseInt(str, 10));
} else if (ISO_8601_PATTERN.test(str)) {
return decodeIso8601(str);
}
......@@ -134,6 +134,7 @@ cr.define('samlTimestamps', function() {
return isNaN(date) ? null : date;
}
// #cr_define_end
// Public functions:
return {decodeTimestamp: decodeTimestamp};
});
......@@ -11,8 +11,9 @@
/**
* Creates a new WebviewEventManager.
* @constructor
*/
function WebviewEventManager() {
/* #export */ function WebviewEventManager() {
this.unbindWebviewCleanupFunctions_ = [];
}
......@@ -20,10 +21,9 @@ WebviewEventManager.prototype = {
/**
* Adds a EventListener to |eventTarget| and adds a clean-up function so we
* can remove the listener in unbindFromWebview.
* @param {Object} webview the object to add the listener to
* @param {Object} eventTarget the object to add the listener to
* @param {string} type the event type
* @param {Function} listener the event listener
* @private
*/
addEventListener(eventTarget, type, listener) {
eventTarget.addEventListener(type, listener);
......@@ -34,10 +34,12 @@ WebviewEventManager.prototype = {
/**
* Adds a listener to |webRequestEvent| and adds a clean-up function so we can
* remove the listener in unbindFromWebview.
* @param {Object} webRequestEvent the object to add the listener to
* @param {string} type the event type
* @param {Object} webRequestEvent the object to add the listener to.
* @param {Function} listener the event listener
* @private
* @param {RequestFilter} filter the object describing filters to apply to
* webRequest events.
* @param {?Object} extraInfoSpec the object to pass additional event-specific
* instructions.
*/
addWebRequestEventListener(webRequestEvent, listener, filter, extraInfoSpec) {
webRequestEvent.addListener(listener, filter, extraInfoSpec);
......@@ -47,7 +49,6 @@ WebviewEventManager.prototype = {
/**
* Unbinds this Authenticator from the currently bound webview.
* @private
*/
removeAllListeners() {
for (let i = 0; i < this.unbindWebviewCleanupFunctions_.length; i++) {
......
......@@ -128,6 +128,7 @@ template("chrome_extra_paks") {
"$root_gen_dir/chrome/component_extension_resources.pak",
"$root_gen_dir/chrome/dev_ui_resources.pak",
"$root_gen_dir/chrome/downloads_resources.pak",
"$root_gen_dir/chrome/gaia_auth_host_resources.pak",
"$root_gen_dir/chrome/history_resources.pak",
"$root_gen_dir/chrome/local_ntp_resources.pak",
"$root_gen_dir/chrome/new_tab_page_resources.pak",
......@@ -140,6 +141,7 @@ template("chrome_extra_paks") {
"//chrome/browser/resources:component_extension_resources",
"//chrome/browser/resources:dev_ui_paks",
"//chrome/browser/resources:downloads_resources",
"//chrome/browser/resources:gaia_auth_host_resources",
"//chrome/browser/resources:history_resources",
"//chrome/browser/resources:local_ntp_resources",
"//chrome/browser/resources:new_tab_page_resources",
......
......@@ -225,6 +225,53 @@ WebView.prototype.contentWindow;
*/
WebView.prototype.request;
/**
* @constructor
* @see https://developer.chrome.com/apps/tags/webview#type-ContextMenus
*/
function ContextMenus() {}
ContextMenus.prototype.onShow;
ContextMenus.prototype.onShow.addListener = function() {};
/**
* @type {ContextMenus}
* @see https://developer.chrome.com/apps/tags/webview#property-contextMenus
*/
WebView.prototype.contextMenus;
/**
* @typedef{{
* code: ?string,
* files: ?Array<string>
* }}
* @see https://developer.chrome.com/apps/tags/webview#type-InjectionItems
*/
var InjectionItems;
/**
* Details of the content script to inject.
* @typedef{{
* name: string,
* matches: Array<string>,
* exclude_matches: ?Array<string>,
* match_about_blank: ?boolean,
* css: ?InjectionItems,
* js: ?InjectionItems,
* run_at: ?string,
* all_frames: ?boolean,
* include_globs: ?Array<string>,
* exclude_globs: ?Array<string>,
* }}
* @see https://developer.chrome.com/apps/tags/webview#type-ContentScriptDetails
*/
var ContentScriptDetails;
/**
* @param {Array<ContentScriptDetails>} contentScriptList
* @see https://developer.chrome.com/apps/tags/webview#method-addContentScripts
*/
WebView.prototype.addContentScripts = function(contentScriptList) {};
/**
* @see https://developer.chrome.com/apps/tags/webview#method-back
*/
......@@ -318,6 +365,12 @@ WebView.prototype.print = function() {};
*/
WebView.prototype.reload = function() {};
/**
* @param {Array<string>} contentScriptList
* @see https://developer.chrome.com/apps/tags/webview#method-removeContentScripts
*/
WebView.prototype.removeContentScripts = function(contentScriptList) {};
/**
* @param {string} userAgent
* @see https://developer.chrome.com/apps/tags/webview#method-setUserAgentOverride
......@@ -331,6 +384,14 @@ WebView.prototype.setUserAgentOverride = function(userAgent) {};
*/
WebView.prototype.setZoom = function(zoomFactor, opt_callback) {};
/**
* @param {string} zoomMode Allowed values: "per-origin", "per-view", "disabled"
* @see https://developer.chrome.com/apps/tags/webview#type-ZoomMode
* @param {Function=} opt_callback
* @see https://developer.chrome.com/apps/tags/webview#method-setZoomMode
*/
WebView.prototype.setZoomMode = function(zoomMode, opt_callback) {};
/**
* @see https://developer.chrome.com/apps/tags/webview#method-stop
*/
......
......@@ -200,6 +200,9 @@
"chrome/browser/resources/bluetooth_internals/resources.grd": {
"includes": [2020],
},
"chrome/browser/resources/gaia_auth_host/gaia_auth_host_resources.grd": {
"includes": [2030],
},
"chrome/browser/resources/invalidations/invalidations_resources.grd": {
"includes": [2040],
},
......
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