var CHECK = requireNative('logging').CHECK;
var idGeneratorNatives = requireNative('id_generator');
var utils = require('utils');
var webRequestInternal = getInternalApi('webRequestInternal');
const allowAsyncResponsesForAllEvents =
requireNative('web_request_natives').AllowAsyncResponsesForAllEvents();
const isServiceWorkerContext =
requireNative('service_worker_natives').IsServiceWorkerContext();
function getGloballyUniqueSubEventName(eventName) {
return eventName + '/g' + idGeneratorNatives.GetNextId();
}
function getScopedUniqueSubEventName(eventName) {
return eventName + '/s' + idGeneratorNatives.GetNextScopedId();
}
function getUniqueSubEventName(eventName) {
return isServiceWorkerContext ?
getScopedUniqueSubEventName(eventName) :
getGloballyUniqueSubEventName(eventName);
}
function WebRequestEventImpl(eventName, opt_argSchemas, opt_extraArgSchemas,
opt_eventOptions, opt_webViewInstanceId) {
if (typeof eventName != 'string') {
throw new Error('chrome.WebRequestEvent requires an event name.');
}
bindingUtil.addCustomSignature(eventName, opt_extraArgSchemas);
this.eventName = eventName;
this.argSchemas = opt_argSchemas;
this.extraArgSchemas = opt_extraArgSchemas;
this.webViewInstanceId = opt_webViewInstanceId || 0;
this.subEvents = [];
}
$Object.setPrototypeOf(WebRequestEventImpl.prototype, null);
WebRequestEventImpl.prototype.hasListener = function(cb) {
return this.findListener_(cb) > -1;
};
WebRequestEventImpl.prototype.hasListeners = function() {
return this.subEvents.length > 0;
};
WebRequestEventImpl.prototype.addListener =
function(cb, opt_filter, opt_extraInfo) {
var subEventName = getUniqueSubEventName(this.eventName);
bindingUtil.validateCustomSignature(this.eventName,
$Array.slice(arguments, 1));
webRequestInternal.addEventListener(
cb, opt_filter, opt_extraInfo, this.eventName, subEventName,
this.webViewInstanceId);
var supportsFilters = false;
var supportsLazyListeners = true;
var subEvent =
bindingUtil.createCustomEvent(subEventName, supportsFilters,
supportsLazyListeners);
var subEventCallback = cb;
if (opt_extraInfo && $Array.indexOf(opt_extraInfo, 'blocking') >= 0) {
var eventName = this.eventName;
var webViewInstanceId = this.webViewInstanceId;
subEventCallback = function() {
var requestId = arguments[0].requestId;
function sendEventHandledWithResult(result) {
webRequestInternal.eventHandled(
eventName, subEventName, requestId, webViewInstanceId, result);
}
function handleHandlerError(e) {
webRequestInternal.eventHandled(
eventName, subEventName, requestId, webViewInstanceId);
throw e;
}
try {
let result = $Function.apply(cb, null, arguments);
if (allowAsyncResponsesForAllEvents &&
result instanceof $Promise.self) {
$Promise.catch(
$Promise.then(result, (asyncResult) => {
sendEventHandledWithResult(asyncResult);
}),
(e) => {
handleHandlerError(e);
});
} else {
sendEventHandledWithResult(result);
}
} catch (e) {
handleHandlerError(e);
}
};
} else if (
opt_extraInfo && $Array.indexOf(opt_extraInfo, 'asyncBlocking') >= 0) {
var eventName = this.eventName;
var webViewInstanceId = this.webViewInstanceId;
subEventCallback = function() {
var details = arguments[0];
var requestId = details.requestId;
var handledCallback = function(response) {
webRequestInternal.eventHandled(
eventName, subEventName, requestId, webViewInstanceId, response);
};
$Function.apply(cb, null, [details, handledCallback]);
};
}
$Array.push(this.subEvents,
{subEvent: subEvent, callback: cb, subEventCallback: subEventCallback});
subEvent.addListener(subEventCallback);
};
WebRequestEventImpl.prototype.removeListener = function(cb) {
var idx;
while ((idx = this.findListener_(cb)) >= 0) {
var e = this.subEvents[idx];
e.subEvent.removeListener(e.subEventCallback);
if (e.subEvent.hasListeners()) {
console.error(
'Internal error: webRequest subEvent has orphaned listeners.');
}
$Array.splice(this.subEvents, idx, 1);
}
};
WebRequestEventImpl.prototype.findListener_ = function(cb) {
for (var i in this.subEvents) {
var e = this.subEvents[i];
if (e.callback === cb) {
if (e.subEvent.hasListener(e.subEventCallback)) {
return i;
}
console.error('Internal error: webRequest subEvent has no callback.');
}
}
return -1;
};
WebRequestEventImpl.prototype.addRules = function(rules, opt_cb) {
throw new Error('This event does not support rules.');
};
WebRequestEventImpl.prototype.removeRules =
function(ruleIdentifiers, opt_cb) {
throw new Error('This event does not support rules.');
};
WebRequestEventImpl.prototype.getRules = function(ruleIdentifiers, cb) {
throw new Error('This event does not support rules.');
};
function WebRequestEvent() {
privates(WebRequestEvent).constructPrivate(this, arguments);
}
function createWebRequestEvent(eventName, opt_argSchemas, opt_extraArgSchemas,
opt_eventOptions, opt_webViewInstanceId) {
return new WebRequestEvent(eventName, opt_argSchemas, opt_extraArgSchemas,
opt_eventOptions, opt_webViewInstanceId);
}
utils.expose(WebRequestEvent, WebRequestEventImpl, {
functions: [
'hasListener',
'hasListeners',
'addListener',
'removeListener',
'addRules',
'removeRules',
'getRules',
],
});
exports.$set('WebRequestEvent', WebRequestEvent);
exports.$set('createWebRequestEvent', createWebRequestEvent);