-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrecaptcha.js
More file actions
80 lines (75 loc) · 3.28 KB
/
Copy pathrecaptcha.js
File metadata and controls
80 lines (75 loc) · 3.28 KB
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
(function () {
'use strict';
var siteKey = '6Lf-EoAtAAAAAI8dwkXHkdisu4eoz1KaZlFMK47w';
var loadPromise = null;
function enterprise() {
return window.grecaptcha && window.grecaptcha.enterprise ? window.grecaptcha.enterprise : null;
}
function isReady() {
var api = enterprise();
return !!(api && typeof api.execute === 'function');
}
// Google's enterprise.js sets window.grecaptcha.enterprise ASYNCHRONOUSLY after
// the script element fires load. Resolving on onload alone therefore races it:
// measured in Chromium, onload resolved with enterprise.execute undefined, and
// the same property was a function ~3s later. The old code resolved `null` on
// that first miss, so getRecaptchaToken returned null intermittently and
// callers fell back to raw content.
//
// Poll instead. 10s covers the observed gap with room to spare, and on timeout
// resolve null exactly as before so callers keep their existing fallback.
function waitForEnterprise(timeoutMs) {
return new Promise(function (resolve) {
var deadline = Date.now() + (timeoutMs || 10000);
(function poll() {
if (isReady()) { resolve(enterprise()); return; }
if (Date.now() > deadline) { resolve(null); return; }
setTimeout(poll, 100);
})();
});
}
function loadRecaptcha() {
if (isReady()) return Promise.resolve(enterprise());
if (loadPromise) return loadPromise;
loadPromise = new Promise(function (resolve) {
var script = document.createElement('script');
script.src = 'https://www.google.com/recaptcha/enterprise.js?render=' + encodeURIComponent(siteKey);
script.async = true;
script.defer = true;
script.onload = function () { waitForEnterprise(10000).then(resolve); };
script.onerror = function () { resolve(null); };
document.head.appendChild(script);
});
// A failed load must not poison every later call.
loadPromise = loadPromise.then(function (api) {
if (!api) loadPromise = null;
return api;
});
return loadPromise;
}
window.getRecaptchaToken = function (action) {
return loadRecaptcha().then(function (api) {
if (!api) return null;
return new Promise(function (resolve) {
var settled = false;
var timeout = setTimeout(function () { if (!settled) { settled = true; resolve(null); } }, 8000);
function execute() {
if (settled || typeof api.execute !== 'function') return;
Promise.resolve(api.execute(siteKey, { action: action || 'submit' })).then(function (token) {
if (!settled) { settled = true; clearTimeout(timeout); resolve(token); }
}).catch(function () { if (!settled) { settled = true; clearTimeout(timeout); resolve(null); } });
}
// ready() is the documented gate, but guard on execute too: some builds
// resolve ready() before execute is attached.
if (typeof api.ready === 'function') {
var readyCalled = false;
api.ready(function () { if (!readyCalled) { readyCalled = true; execute(); } });
// If ready() never fires or fires too early, poll rather than stall.
setTimeout(function () { if (!readyCalled) { readyCalled = true; execute(); } }, 1500);
} else {
execute();
}
});
});
};
})();