Skip to content

Commit 563e048

Browse files
Fetch API missing support handling (#578)
* Fixes vague errors thrown in older browsers such as IE10/11 and iOS mobile Safari related to worker support. Most of these are attributed to lack of support for fetch related APIs even when web workers are still supported. In that case we throw an operation not supported in environment error on operations that require http requests. * Added yarn.lock auto changes.
1 parent ef14d4f commit 563e048

File tree

8 files changed

+286
-13
lines changed

8 files changed

+286
-13
lines changed

packages/auth/demo/public/script.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,9 +1146,11 @@ function populateActionCodes() {
11461146
/**
11471147
* Provides basic Database checks for authenticated and unauthenticated access.
11481148
* The Database node being tested has the following rule:
1149-
* "$user_id": {
1150-
* ".read": "$user_id === auth.uid",
1151-
* ".write": "$user_id === auth.uid"
1149+
* "users": {
1150+
* "$user_id": {
1151+
* ".read": "$user_id === auth.uid",
1152+
* ".write": "$user_id === auth.uid"
1153+
* }
11521154
* }
11531155
* This applies when Real-time database service is available.
11541156
*/
@@ -1226,7 +1228,7 @@ function onRunWebWorkTests() {
12261228
return;
12271229
}
12281230
var onError = function(error) {
1229-
alertError('Error: ' + error.code);
1231+
alertError('Error code: ' + error.code + ' message: ' + error.message);
12301232
};
12311233
auth.signInWithPopup(new firebase.auth.GoogleAuthProvider())
12321234
.then(function(result) {

packages/auth/demo/public/web-worker.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ importScripts('/dist/firebase-app.js');
2323
importScripts('/dist/firebase-auth.js');
2424
importScripts('config.js');
2525

26+
// Polyfill Promise in case it is not supported.
27+
if (typeof Promise === 'undefined') {
28+
var Promise = firebase.Promise;
29+
}
30+
2631
// Initialize the Firebase app in the web worker.
2732
firebase.initializeApp(config);
2833

@@ -179,7 +184,8 @@ self.onmessage = function(e) {
179184
self.postMessage(result);
180185
}).catch(function(error) {
181186
result.status = 'failure';
182-
result.error = error;
187+
// DataCloneError when postMessaging in IE11 and 10.
188+
result.error = error.code ? error : error.message;
183189
self.postMessage(result);
184190
});
185191
break;

packages/auth/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"del": "^3.0.0",
2929
"express": "^4.16.2",
3030
"firebase-tools": "^3.17.4",
31+
"firebase-functions": "^0.9.0",
3132
"google-closure-compiler": "^20180204.0.0",
3233
"google-closure-library": "^20180204.0.0",
3334
"gulp": "^3.9.1",

packages/auth/src/rpchandler.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,13 @@ fireauth.RpcHandler.prototype.sendXhrUsingXhrIo_ = function(
462462
opt_data,
463463
opt_headers,
464464
opt_timeout) {
465+
if (fireauth.util.isWorker() && !fireauth.util.isFetchSupported()) {
466+
throw new fireauth.AuthError(
467+
fireauth.authenum.Error.OPERATION_NOT_SUPPORTED,
468+
'fetch, Headers and Request native APIs or equivalent Polyfills ' +
469+
'must be available to support HTTP requests from a Worker ' +
470+
'environment.');
471+
}
465472
var xhrIo = new goog.net.XhrIo(this.rpcHandlerXhrFactory_);
466473

467474
// xhrIo.setTimeoutInterval not working in IE10 and IE11, handle manually.

packages/auth/src/utils.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,20 @@ fireauth.util.isWorker = function(opt_global) {
629629
};
630630

631631

632+
/**
633+
* @param {?Object=} opt_global The optional global scope.
634+
* @return {boolean} Whether current environment supports fetch API and other
635+
* APIs it depends on.
636+
*/
637+
fireauth.util.isFetchSupported = function(opt_global) {
638+
// Required by fetch API calls.
639+
var scope = opt_global || goog.global;
640+
return typeof scope['fetch'] !== 'undefined' &&
641+
typeof scope['Headers'] !== 'undefined' &&
642+
typeof scope['Request'] !== 'undefined';
643+
};
644+
645+
632646
/**
633647
* Enum for the runtime environment.
634648
* @enum {string}

packages/auth/test/rpchandler_test.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,11 @@ function testRpcHandler_XMLHttpRequest_worker() {
209209
fireauth.util,
210210
'isWorker',
211211
function() {return true;});
212+
// Simulate fetch, Request and Headers API supported.
213+
stubs.replace(
214+
fireauth.util,
215+
'isFetchSupported',
216+
function() {return true;});
212217
// No XMLHttpRequest available.
213218
stubs.replace(
214219
fireauth.RpcHandler,
@@ -233,6 +238,42 @@ function testRpcHandler_XMLHttpRequest_worker() {
233238
}
234239

235240

241+
function testRpcHandler_XMLHttpRequest_worker_fetchNotSupported() {
242+
// Test worker environment where fetch, Headers and Request are not supported.
243+
// Simulates global self in a worker environment.
244+
goog.global['self'] = {};
245+
var expectedError = new fireauth.AuthError(
246+
fireauth.authenum.Error.OPERATION_NOT_SUPPORTED,
247+
'fetch, Headers and Request native APIs or equivalent Polyfills ' +
248+
'must be available to support HTTP requests from a Worker environment.');
249+
stubs.reset();
250+
// Simulate worker environment.
251+
stubs.replace(
252+
fireauth.util,
253+
'isWorker',
254+
function() {return true;});
255+
// Simulate fetch, Request and Headers API not supported.
256+
stubs.replace(
257+
fireauth.util,
258+
'isFetchSupported',
259+
function() {return false;});
260+
// No XMLHttpRequest available.
261+
stubs.replace(
262+
fireauth.RpcHandler,
263+
'getXMLHttpRequest',
264+
function() {return undefined;});
265+
asyncTestCase.waitForSignals(1);
266+
rpcHandler = new fireauth.RpcHandler('apiKey');
267+
// Simulate RPC and then expected error thrown.
268+
rpcHandler.fetchProvidersForIdentifier('[email protected]')
269+
.thenCatch(function(actualError) {
270+
fireauth.common.testHelper.assertErrorEquals(
271+
expectedError, actualError);
272+
asyncTestCase.signal();
273+
});
274+
}
275+
276+
236277
function testRpcHandler_XMLHttpRequest_corsBrowser() {
237278
// Test CORS browser environment that CorsXmlHttpFactory is used in
238279
// initialization of goog.net.XhrIo.

packages/auth/test/utils_test.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,31 @@ function testIsWorker() {
520520
}
521521

522522

523+
function testIsFetchSupported() {
524+
// All fetch related APIs supported.
525+
assertTrue(fireauth.util.isFetchSupported({
526+
'fetch': function() {},
527+
'Request': function() {},
528+
'Headers': function() {}
529+
}));
530+
// Headers missing.
531+
assertFalse(fireauth.util.isFetchSupported({
532+
'fetch': function() {},
533+
'Request': function() {},
534+
}));
535+
// Request missing.
536+
assertFalse(fireauth.util.isFetchSupported({
537+
'fetch': function() {},
538+
'Headers': function() {}
539+
}));
540+
// fetch missing.
541+
assertFalse(fireauth.util.isFetchSupported({
542+
'Request': function() {},
543+
'Headers': function() {}
544+
}));
545+
}
546+
547+
523548
function testGetBrowserName_opera() {
524549
assertEquals('Opera', fireauth.util.getBrowserName(operaUA));
525550
}

0 commit comments

Comments
 (0)