1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
// Copyright 2014 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.
/**
* @fileoverview CryptoToken background page
*/
'use strict';
/** @const */
var HTTP_ORIGINS_ALLOWED = false;
/** @const */
var LOG_SAVER_EXTENSION_ID = 'fjajfjhkeibgmiggdfehjplbhmfkialk';
var LOG_SAVER_EXTENSION_ORIGIN = 'chrome-extension://' + LOG_SAVER_EXTENSION_ID;
var FACTORY_REGISTRY = (function() {
var windowTimer = new WindowTimer();
var xhrTextFetcher = new XhrTextFetcher();
return new FactoryRegistry(
new XhrAppIdCheckerFactory(xhrTextFetcher),
new CryptoTokenApprovedOrigin(), new CountdownTimerFactory(windowTimer),
new CryptoTokenOriginChecker(), windowTimer);
})();
/**
* @param {*} request The received request
* @return {boolean} Whether the request is a register/enroll request.
*/
function isRegisterRequest(request) {
if (!request) {
return false;
}
switch (request.type) {
case MessageTypes.U2F_REGISTER_REQUEST:
return true;
default:
return false;
}
}
/**
* Default response callback to deliver a response to a request.
* @param {*} request The received request.
* @param {function(*): void} sendResponse A callback that delivers a response.
* @param {*} response The response to return.
*/
function defaultResponseCallback(request, sendResponse, response) {
response['requestId'] = request['requestId'];
try {
sendResponse(response);
} catch (e) {
console.warn(UTIL_fmt('caught: ' + e.message));
}
}
/**
* Response callback that delivers a response to a request only when the
* sender is a foreground tab.
* @param {*} request The received request.
* @param {!MessageSender} sender The message sender.
* @param {function(*): void} sendResponse A callback that delivers a response.
* @param {*} response The response to return.
*/
function sendResponseToActiveTabOnly(request, sender, sendResponse, response) {
// For WebAuthn-proxied requests on Windows, dismissing the native Windows
// UI after a timeout races with the error being returned here. Hence, skip
// the focus check for all timeouts.
if (response.responseData &&
response.responseData.errorCode == ErrorCodes.TIMEOUT) {
defaultResponseCallback(request, sendResponse, response);
return;
}
tabInForeground(sender.tab.id).then(function(result) {
// If the tab is no longer in the foreground, drop the result: the user
// is no longer interacting with the tab that originated the request.
if (result) {
defaultResponseCallback(request, sendResponse, response);
}
});
}
/**
* Common handler for messages received from chrome.runtime.sendMessage and
* chrome.runtime.connect + postMessage.
* @param {*} request The received request
* @param {!MessageSender} sender The message sender
* @param {function(*): void} sendResponse A callback that delivers a response
* @return {Closeable} A Closeable request handler.
*/
function messageHandler(request, sender, sendResponse) {
var responseCallback;
if (isRegisterRequest(request)) {
responseCallback =
sendResponseToActiveTabOnly.bind(null, request, sender, sendResponse);
} else {
responseCallback =
defaultResponseCallback.bind(null, request, sendResponse);
}
var closeable = handleWebPageRequest(
/** @type {Object} */ (request), sender, responseCallback);
return closeable;
}
/**
* Listen to individual messages sent from (allowlisted) extensions/apps via
* chrome.runtime.sendMessage
* @param {*} request The received request
* @param {!MessageSender} sender The message sender
* @param {function(*): void} sendResponse A callback that delivers a response
* @return {boolean}
*/
function messageHandlerExternal(request, sender, sendResponse) {
if (sender.origin && sender.origin === LOG_SAVER_EXTENSION_ORIGIN) {
return handleLogSaverMessage(request);
}
messageHandler(request, sender, sendResponse);
return true; // Tell Chrome not to destroy sendResponse yet
}
chrome.runtime.onMessageExternal.addListener(messageHandlerExternal);
// Listen to direct connection events, and wire up a message handler on the port
chrome.runtime.onConnectExternal.addListener(function(port) {
function sendResponse(response) {
port.postMessage(response);
}
var closeable;
port.onMessage.addListener(function(request) {
var sender = /** @type {!MessageSender} */ (port.sender);
closeable = messageHandler(request, sender, sendResponse);
});
port.onDisconnect.addListener(function() {
if (closeable) {
closeable.close();
}
});
});
/**
* Handles messages from the log-saver app. Temporarily replaces UTIL_fmt with
* a wrapper that also sends formatted messages to the app.
* @param {*} request The message received from the app
* @return {boolean} Used as chrome.runtime.onMessage handler return value
*/
function handleLogSaverMessage(request) {
if (request === 'start') {
if (originalUtilFmt) {
// We're already sending
return false;
}
originalUtilFmt = UTIL_fmt;
UTIL_fmt = function(s) {
var line = originalUtilFmt(s);
chrome.runtime.sendMessage(LOG_SAVER_EXTENSION_ID, line);
return line;
};
} else if (request === 'stop') {
if (originalUtilFmt) {
UTIL_fmt = originalUtilFmt;
originalUtilFmt = null;
}
}
return false;
}
/** @private */
var originalUtilFmt = null;
|