| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Custom bindings for the webRequest API. | 5 // Custom bindings for the webRequest API. |
| 6 | 6 |
| 7 (function() { | 7 (function() { |
| 8 | 8 |
| 9 native function GetChromeHidden(); | 9 native function GetChromeHidden(); |
| 10 native function GetUniqueSubEventName(eventName); | 10 native function GetUniqueSubEventName(eventName); |
| 11 | 11 |
| 12 var chromeHidden = GetChromeHidden(); | 12 var chromeHidden = GetChromeHidden(); |
| 13 | 13 |
| 14 // WebRequestEvent object. This is used for special webRequest events with | 14 // WebRequestEvent object. This is used for special webRequest events with |
| 15 // extra parameters. Each invocation of addListener creates a new named | 15 // extra parameters. Each invocation of addListener creates a new named |
| 16 // sub-event. That sub-event is associated with the extra parameters in the | 16 // sub-event. That sub-event is associated with the extra parameters in the |
| 17 // browser process, so that only it is dispatched when the main event occurs | 17 // browser process, so that only it is dispatched when the main event occurs |
| 18 // matching the extra parameters. | 18 // matching the extra parameters. |
| 19 // | 19 // |
| 20 // Example: | 20 // Example: |
| 21 // chrome.webRequest.onBeforeRequest.addListener( | 21 // chrome.webRequest.onBeforeRequest.addListener( |
| 22 // callback, {urls: "http://*.google.com/*"}); | 22 // callback, {urls: "http://*.google.com/*"}); |
| 23 // ^ callback will only be called for onBeforeRequests matching the filter. | 23 // ^ callback will only be called for onBeforeRequests matching the filter. |
| 24 function WebRequestEvent(eventName, opt_argSchemas, opt_extraArgSchemas) { | 24 function WebRequestEvent(eventName, opt_argSchemas, opt_extraArgSchemas, |
| 25 opt_eventOptions) { |
| 25 if (typeof eventName != "string") | 26 if (typeof eventName != "string") |
| 26 throw new Error("chrome.WebRequestEvent requires an event name."); | 27 throw new Error("chrome.WebRequestEvent requires an event name."); |
| 27 | 28 |
| 28 this.eventName_ = eventName; | 29 this.eventName_ = eventName; |
| 29 this.argSchemas_ = opt_argSchemas; | 30 this.argSchemas_ = opt_argSchemas; |
| 30 this.extraArgSchemas_ = opt_extraArgSchemas; | 31 this.extraArgSchemas_ = opt_extraArgSchemas; |
| 31 this.subEvents_ = []; | 32 this.subEvents_ = []; |
| 33 this.eventOptions_ = opt_eventOptions || |
| 34 {"supportsListeners": true, "supportsRules": false}; |
| 35 |
| 36 if (this.eventOptions_.supportsRules) |
| 37 this.eventForRules_ = |
| 38 new chrome.Event(eventName, opt_argSchemas, opt_eventOptions); |
| 32 }; | 39 }; |
| 33 | 40 |
| 34 // Test if the given callback is registered for this event. | 41 // Test if the given callback is registered for this event. |
| 35 WebRequestEvent.prototype.hasListener = function(cb) { | 42 WebRequestEvent.prototype.hasListener = function(cb) { |
| 43 if (!this.eventOptions_.supportsListeners) |
| 44 throw new Error("This event does not support listeners."); |
| 36 return this.findListener_(cb) > -1; | 45 return this.findListener_(cb) > -1; |
| 37 }; | 46 }; |
| 38 | 47 |
| 39 // Test if any callbacks are registered fur thus event. | 48 // Test if any callbacks are registered fur thus event. |
| 40 WebRequestEvent.prototype.hasListeners = function() { | 49 WebRequestEvent.prototype.hasListeners = function() { |
| 50 if (!this.eventOptions_.supportsListeners) |
| 51 throw new Error("This event does not support listeners."); |
| 41 return this.subEvents_.length > 0; | 52 return this.subEvents_.length > 0; |
| 42 }; | 53 }; |
| 43 | 54 |
| 44 // Registers a callback to be called when this event is dispatched. If | 55 // Registers a callback to be called when this event is dispatched. If |
| 45 // opt_filter is specified, then the callback is only called for events that | 56 // opt_filter is specified, then the callback is only called for events that |
| 46 // match the given filters. If opt_extraInfo is specified, the given optional | 57 // match the given filters. If opt_extraInfo is specified, the given optional |
| 47 // info is sent to the callback. | 58 // info is sent to the callback. |
| 48 WebRequestEvent.prototype.addListener = | 59 WebRequestEvent.prototype.addListener = |
| 49 function(cb, opt_filter, opt_extraInfo) { | 60 function(cb, opt_filter, opt_extraInfo) { |
| 61 if (!this.eventOptions_.supportsListeners) |
| 62 throw new Error("This event does not support listeners."); |
| 50 var subEventName = GetUniqueSubEventName(this.eventName_); | 63 var subEventName = GetUniqueSubEventName(this.eventName_); |
| 51 // Note: this could fail to validate, in which case we would not add the | 64 // Note: this could fail to validate, in which case we would not add the |
| 52 // subEvent listener. | 65 // subEvent listener. |
| 53 chromeHidden.validate(Array.prototype.slice.call(arguments, 1), | 66 chromeHidden.validate(Array.prototype.slice.call(arguments, 1), |
| 54 this.extraArgSchemas_); | 67 this.extraArgSchemas_); |
| 55 chrome.webRequest.addEventListener( | 68 chrome.webRequest.addEventListener( |
| 56 cb, opt_filter, opt_extraInfo, this.eventName_, subEventName); | 69 cb, opt_filter, opt_extraInfo, this.eventName_, subEventName); |
| 57 | 70 |
| 58 var subEvent = new chrome.Event(subEventName, this.argSchemas_); | 71 var subEvent = new chrome.Event(subEventName, this.argSchemas_); |
| 59 var subEventCallback = cb; | 72 var subEventCallback = cb; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 83 cb.apply(null, [details, handledCallback]); | 96 cb.apply(null, [details, handledCallback]); |
| 84 }; | 97 }; |
| 85 } | 98 } |
| 86 this.subEvents_.push( | 99 this.subEvents_.push( |
| 87 {subEvent: subEvent, callback: cb, subEventCallback: subEventCallback}); | 100 {subEvent: subEvent, callback: cb, subEventCallback: subEventCallback}); |
| 88 subEvent.addListener(subEventCallback); | 101 subEvent.addListener(subEventCallback); |
| 89 }; | 102 }; |
| 90 | 103 |
| 91 // Unregisters a callback. | 104 // Unregisters a callback. |
| 92 WebRequestEvent.prototype.removeListener = function(cb) { | 105 WebRequestEvent.prototype.removeListener = function(cb) { |
| 106 if (!this.eventOptions_.supportsListeners) |
| 107 throw new Error("This event does not support listeners."); |
| 93 var idx; | 108 var idx; |
| 94 while ((idx = this.findListener_(cb)) >= 0) { | 109 while ((idx = this.findListener_(cb)) >= 0) { |
| 95 var e = this.subEvents_[idx]; | 110 var e = this.subEvents_[idx]; |
| 96 e.subEvent.removeListener(e.subEventCallback); | 111 e.subEvent.removeListener(e.subEventCallback); |
| 97 if (e.subEvent.hasListeners()) { | 112 if (e.subEvent.hasListeners()) { |
| 98 console.error( | 113 console.error( |
| 99 "Internal error: webRequest subEvent has orphaned listeners."); | 114 "Internal error: webRequest subEvent has orphaned listeners."); |
| 100 } | 115 } |
| 101 this.subEvents_.splice(idx, 1); | 116 this.subEvents_.splice(idx, 1); |
| 102 } | 117 } |
| 103 }; | 118 }; |
| 104 | 119 |
| 105 WebRequestEvent.prototype.findListener_ = function(cb) { | 120 WebRequestEvent.prototype.findListener_ = function(cb) { |
| 106 for (var i in this.subEvents_) { | 121 for (var i in this.subEvents_) { |
| 107 var e = this.subEvents_[i]; | 122 var e = this.subEvents_[i]; |
| 108 if (e.callback === cb) { | 123 if (e.callback === cb) { |
| 109 if (e.subEvent.findListener_(e.subEventCallback) > -1) | 124 if (e.subEvent.findListener_(e.subEventCallback) > -1) |
| 110 return i; | 125 return i; |
| 111 console.error("Internal error: webRequest subEvent has no callback."); | 126 console.error("Internal error: webRequest subEvent has no callback."); |
| 112 } | 127 } |
| 113 } | 128 } |
| 114 | 129 |
| 115 return -1; | 130 return -1; |
| 116 }; | 131 }; |
| 117 | 132 |
| 118 chromeHidden.registerCustomEvent('webRequest', WebRequestEvent); | 133 WebRequestEvent.prototype.addRules = function(rules, opt_cb) { |
| 134 if (!this.eventOptions_.supportsRules) |
| 135 throw new Error("This event does not support rules."); |
| 136 this.eventForRules_.addRules(rules, opt_cb); |
| 137 } |
| 119 | 138 |
| 120 chromeHidden.registerCustomHook('webRequest', function(api) { | 139 WebRequestEvent.prototype.removeRules = function(ruleIdentifiers, opt_cb) { |
| 140 if (!this.eventOptions_.supportsRules) |
| 141 throw new Error("This event does not support rules."); |
| 142 this.eventForRules_.removeRules(ruleIdentifiers, opt_cb); |
| 143 } |
| 144 |
| 145 WebRequestEvent.prototype.getRules = function(ruleIdentifiers, cb) { |
| 146 if (!this.eventOptions_.supportsRules) |
| 147 throw new Error("This event does not support rules."); |
| 148 this.eventForRules_.getRules(ruleIdentifiers, cb); |
| 149 } |
| 150 |
| 151 chromeHidden.registerCustomEvent("webRequest", WebRequestEvent); |
| 152 |
| 153 chromeHidden.registerCustomHook("webRequest", function(api) { |
| 121 var apiFunctions = api.apiFunctions; | 154 var apiFunctions = api.apiFunctions; |
| 122 var sendRequest = api.sendRequest; | 155 var sendRequest = api.sendRequest; |
| 123 | 156 |
| 124 apiFunctions.setHandleRequest("webRequest.addEventListener", | 157 apiFunctions.setHandleRequest("webRequest.addEventListener", |
| 125 function() { | 158 function() { |
| 126 var args = Array.prototype.slice.call(arguments); | 159 var args = Array.prototype.slice.call(arguments); |
| 127 sendRequest(this.name, args, this.definition.parameters, | 160 sendRequest(this.name, args, this.definition.parameters, |
| 128 {forIOThread: true}); | 161 {forIOThread: true}); |
| 129 }); | 162 }); |
| 130 | 163 |
| 131 apiFunctions.setHandleRequest("webRequest.eventHandled", | 164 apiFunctions.setHandleRequest("webRequest.eventHandled", |
| 132 function() { | 165 function() { |
| 133 var args = Array.prototype.slice.call(arguments); | 166 var args = Array.prototype.slice.call(arguments); |
| 134 sendRequest(this.name, args, this.definition.parameters, | 167 sendRequest(this.name, args, this.definition.parameters, |
| 135 {forIOThread: true}); | 168 {forIOThread: true}); |
| 136 }); | 169 }); |
| 137 | 170 |
| 138 apiFunctions.setHandleRequest("webRequest.handlerBehaviorChanged", | 171 apiFunctions.setHandleRequest("webRequest.handlerBehaviorChanged", |
| 139 function() { | 172 function() { |
| 140 var args = Array.prototype.slice.call(arguments); | 173 var args = Array.prototype.slice.call(arguments); |
| 141 sendRequest(this.name, args, this.definition.parameters, | 174 sendRequest(this.name, args, this.definition.parameters, |
| 142 {forIOThread: true}); | 175 {forIOThread: true}); |
| 143 }); | 176 }); |
| 144 }); | 177 }); |
| 145 | 178 |
| 146 })(); | 179 })(); |
| OLD | NEW |