diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib.rs | 251 |
1 files changed, 88 insertions, 163 deletions
| @@ -12,21 +12,18 @@ | |||
| 12 | )] | 12 | )] |
| 13 | 13 | ||
| 14 | use adblock::blocker::BlockerResult as RustBlockerResult; | 14 | use adblock::blocker::BlockerResult as RustBlockerResult; |
| 15 | use adblock::blocker::{BlockerError as RustBlockerError, Redirection}; | ||
| 16 | use adblock::cosmetic_filter_cache::UrlSpecificResources as RustUrlSpecificResources; | 15 | use adblock::cosmetic_filter_cache::UrlSpecificResources as RustUrlSpecificResources; |
| 17 | use adblock::engine::Engine as RustEngine; | 16 | use adblock::engine::Engine as RustEngine; |
| 18 | use adblock::lists::FilterSet as RustFilterSet; | 17 | use adblock::lists::FilterSet as RustFilterSet; |
| 19 | use adblock::lists::{FilterFormat, ParseOptions, RuleTypes}; | 18 | use adblock::lists::{FilterFormat, ParseOptions, RuleTypes}; |
| 19 | use adblock::request::Request; | ||
| 20 | use pyo3::create_exception; | 20 | use pyo3::create_exception; |
| 21 | use pyo3::exceptions::PyException; | 21 | use pyo3::exceptions::PyException; |
| 22 | use pyo3::prelude::*; | 22 | use pyo3::prelude::*; |
| 23 | use pyo3::types::PyBytes; | 23 | use pyo3::types::PyBytes; |
| 24 | use pyo3::PyErr; | 24 | use pyo3::PyErr; |
| 25 | 25 | ||
| 26 | use adblock::resources::{ | 26 | use adblock::resources::{MimeType, PermissionMask, Resource, ResourceType}; |
| 27 | AddResourceError as RustAddResourceError, MimeType, Resource, ResourceType, | ||
| 28 | }; | ||
| 29 | use std::collections::HashMap; | ||
| 30 | use std::collections::HashSet; | 27 | use std::collections::HashSet; |
| 31 | use std::error::Error; | 28 | use std::error::Error; |
| 32 | use std::fmt::{self, Display}; | 29 | use std::fmt::{self, Display}; |
| @@ -35,39 +32,39 @@ use std::io::{Read, Write}; | |||
| 35 | 32 | ||
| 36 | /// Brave's adblocking library in Python! | 33 | /// Brave's adblocking library in Python! |
| 37 | #[pymodule] | 34 | #[pymodule] |
| 38 | fn adblock(py: Python<'_>, m: &PyModule) -> PyResult<()> { | 35 | fn adblock_py(m: &Bound<'_, PyModule>) -> PyResult<()> { |
| 39 | m.add("__version__", env!("CARGO_PKG_VERSION"))?; | 36 | m.add("__version__", env!("CARGO_PKG_VERSION"))?; |
| 40 | m.add_class::<Engine>()?; | 37 | m.add_class::<Engine>()?; |
| 41 | m.add_class::<FilterSet>()?; | 38 | m.add_class::<FilterSet>()?; |
| 42 | m.add_class::<BlockerResult>()?; | 39 | m.add_class::<BlockerResult>()?; |
| 43 | m.add_class::<UrlSpecificResources>()?; | 40 | m.add_class::<UrlSpecificResources>()?; |
| 44 | m.add("AdblockException", py.get_type::<AdblockException>())?; | 41 | m.add("AdblockException", m.py().get_type_bound::<AdblockException>())?; |
| 45 | m.add("BlockerException", py.get_type::<BlockerException>())?; | 42 | m.add("BlockerException", m.py().get_type_bound::<BlockerException>())?; |
| 46 | m.add("SerializationError", py.get_type::<SerializationError>())?; | 43 | m.add("SerializationError", m.py().get_type_bound::<SerializationError>())?; |
| 47 | m.add( | 44 | m.add( |
| 48 | "DeserializationError", | 45 | "DeserializationError", |
| 49 | py.get_type::<DeserializationError>(), | 46 | m.py().get_type_bound::<DeserializationError>(), |
| 50 | )?; | 47 | )?; |
| 51 | m.add( | 48 | m.add( |
| 52 | "OptimizedFilterExistence", | 49 | "OptimizedFilterExistence", |
| 53 | py.get_type::<OptimizedFilterExistence>(), | 50 | m.py().get_type_bound::<OptimizedFilterExistence>(), |
| 54 | )?; | 51 | )?; |
| 55 | m.add( | 52 | m.add( |
| 56 | "BadFilterAddUnsupported", | 53 | "BadFilterAddUnsupported", |
| 57 | py.get_type::<BadFilterAddUnsupported>(), | 54 | m.py().get_type_bound::<BadFilterAddUnsupported>(), |
| 58 | )?; | 55 | )?; |
| 59 | m.add("FilterExists", py.get_type::<FilterExists>())?; | 56 | m.add("FilterExists", m.py().get_type_bound::<FilterExists>())?; |
| 60 | m.add( | 57 | m.add( |
| 61 | "AddResourceException", | 58 | "AddResourceException", |
| 62 | py.get_type::<AddResourceException>(), | 59 | m.py().get_type_bound::<AddResourceException>(), |
| 63 | )?; | 60 | )?; |
| 64 | m.add( | 61 | m.add( |
| 65 | "InvalidBase64ContentError", | 62 | "InvalidBase64ContentError", |
| 66 | py.get_type::<InvalidBase64ContentError>(), | 63 | m.py().get_type_bound::<InvalidBase64ContentError>(), |
| 67 | )?; | 64 | )?; |
| 68 | m.add( | 65 | m.add( |
| 69 | "InvalidUtf8ContentError", | 66 | "InvalidUtf8ContentError", |
| 70 | py.get_type::<InvalidUtf8ContentError>(), | 67 | m.py().get_type_bound::<InvalidUtf8ContentError>(), |
| 71 | )?; | 68 | )?; |
| 72 | Ok(()) | 69 | Ok(()) |
| 73 | } | 70 | } |
| @@ -94,14 +91,11 @@ pub struct BlockerResult { | |||
| 94 | /// | 91 | /// |
| 95 | /// [1]: https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#redirect | 92 | /// [1]: https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#redirect |
| 96 | #[pyo3(get)] | 93 | #[pyo3(get)] |
| 97 | pub redirect_type: Option<String>, | ||
| 98 | /// Exception is not `None` when the blocker matched on an exception rule. | ||
| 99 | /// Effectively this means that there was a match, but the request should | ||
| 100 | /// not be blocked. It is a non-empty string if the blocker was initialized | ||
| 101 | /// from a list of rules with debugging enabled, otherwise the original | ||
| 102 | /// string representation is discarded to reduce memory use. | ||
| 103 | #[pyo3(get)] | ||
| 104 | pub redirect: Option<String>, | 94 | pub redirect: Option<String>, |
| 95 | /// `removeparam` may remove URL parameters. If the original request URL was | ||
| 96 | /// modified at all, the new version will be here. | ||
| 97 | #[pyo3(get)] | ||
| 98 | pub rewritten_url: Option<String>, | ||
| 105 | /// Exception is not `None` when the blocker matched on an exception rule. | 99 | /// Exception is not `None` when the blocker matched on an exception rule. |
| 106 | /// Effectively this means that there was a match, but the request should | 100 | /// Effectively this means that there was a match, but the request should |
| 107 | /// not be blocked. It is a non-empty string if the blocker was initialized | 101 | /// not be blocked. It is a non-empty string if the blocker was initialized |
| @@ -114,32 +108,17 @@ pub struct BlockerResult { | |||
| 114 | /// a match, it is not `None`. | 108 | /// a match, it is not `None`. |
| 115 | #[pyo3(get)] | 109 | #[pyo3(get)] |
| 116 | pub filter: Option<String>, | 110 | pub filter: Option<String>, |
| 117 | /// The `error` field is only used to signal that there was an error in | ||
| 118 | /// parsing the provided URLs when using the simpler | ||
| 119 | /// `check_network_urls` method. | ||
| 120 | #[pyo3(get)] | ||
| 121 | pub error: Option<String>, | ||
| 122 | } | 111 | } |
| 123 | 112 | ||
| 124 | impl From<RustBlockerResult> for BlockerResult { | 113 | impl From<RustBlockerResult> for BlockerResult { |
| 125 | fn from(br: RustBlockerResult) -> Self { | 114 | fn from(br: RustBlockerResult) -> Self { |
| 126 | let (redirect, redirect_type) = if let Some(resource) = br.redirect { | ||
| 127 | match resource { | ||
| 128 | Redirection::Resource(resource) => (Some(resource), Some("resource".to_string())), | ||
| 129 | Redirection::Url(url) => (Some(url), Some("url".to_string())), | ||
| 130 | } | ||
| 131 | } else { | ||
| 132 | (None, None) | ||
| 133 | }; | ||
| 134 | |||
| 135 | Self { | 115 | Self { |
| 136 | matched: br.matched, | 116 | matched: br.matched, |
| 137 | important: br.important, | 117 | important: br.important, |
| 118 | redirect: br.redirect, | ||
| 119 | rewritten_url: br.rewritten_url, | ||
| 138 | exception: br.exception, | 120 | exception: br.exception, |
| 139 | filter: br.filter, | 121 | filter: br.filter, |
| 140 | error: br.error, | ||
| 141 | redirect_type, | ||
| 142 | redirect, | ||
| 143 | } | 122 | } |
| 144 | } | 123 | } |
| 145 | } | 124 | } |
| @@ -148,13 +127,13 @@ impl From<RustBlockerResult> for BlockerResult { | |||
| 148 | impl BlockerResult { | 127 | impl BlockerResult { |
| 149 | fn __repr__(&self) -> PyResult<String> { | 128 | fn __repr__(&self) -> PyResult<String> { |
| 150 | Ok(format!( | 129 | Ok(format!( |
| 151 | "BlockerResult(matched={}, important={}, redirect={}, exception={}, filter={}, error={})", | 130 | "BlockerResult(matched={}, important={}, redirect={}, rewritten_url={}, exception={}, filter={})", |
| 152 | self.matched.diy_python_repr(), | 131 | self.matched.diy_python_repr(), |
| 153 | self.important.diy_python_repr(), | 132 | self.important.diy_python_repr(), |
| 154 | self.redirect.diy_python_repr(), | 133 | self.redirect.diy_python_repr(), |
| 134 | self.rewritten_url.diy_python_repr(), | ||
| 155 | self.exception.diy_python_repr(), | 135 | self.exception.diy_python_repr(), |
| 156 | self.filter.diy_python_repr(), | 136 | self.filter.diy_python_repr(), |
| 157 | self.error.diy_python_repr(), | ||
| 158 | )) | 137 | )) |
| 159 | } | 138 | } |
| 160 | } | 139 | } |
| @@ -214,17 +193,6 @@ impl From<BlockerError> for PyErr { | |||
| 214 | } | 193 | } |
| 215 | } | 194 | } |
| 216 | 195 | ||
| 217 | impl From<RustBlockerError> for BlockerError { | ||
| 218 | fn from(err: RustBlockerError) -> Self { | ||
| 219 | match err { | ||
| 220 | RustBlockerError::SerializationError => Self::SerializationError, | ||
| 221 | RustBlockerError::DeserializationError => Self::DeserializationError, | ||
| 222 | RustBlockerError::OptimizedFilterExistence => Self::OptimizedFilterExistence, | ||
| 223 | RustBlockerError::BadFilterAddUnsupported => Self::BadFilterAddUnsupported, | ||
| 224 | RustBlockerError::FilterExists => Self::FilterExists, | ||
| 225 | } | ||
| 226 | } | ||
| 227 | } | ||
| 228 | 196 | ||
| 229 | fn filter_format_from_string(filter_format: &str) -> PyResult<FilterFormat> { | 197 | fn filter_format_from_string(filter_format: &str) -> PyResult<FilterFormat> { |
| 230 | match filter_format { | 198 | match filter_format { |
| @@ -252,7 +220,6 @@ fn rule_types_from_string(rule_types: &str) -> PyResult<RuleTypes> { | |||
| 252 | /// created. FilterSet allows assembling a compound list from multiple | 220 | /// created. FilterSet allows assembling a compound list from multiple |
| 253 | /// different sources before compiling the rules into an Engine. | 221 | /// different sources before compiling the rules into an Engine. |
| 254 | #[pyclass] | 222 | #[pyclass] |
| 255 | #[pyo3(text_signature = "($self, debug)")] | ||
| 256 | #[derive(Clone)] | 223 | #[derive(Clone)] |
| 257 | pub struct FilterSet { | 224 | pub struct FilterSet { |
| 258 | filter_set: RustFilterSet, | 225 | filter_set: RustFilterSet, |
| @@ -266,7 +233,7 @@ impl FilterSet { | |||
| 266 | /// the more compact internal representation. If enabled, this information | 233 | /// the more compact internal representation. If enabled, this information |
| 267 | /// will be passed to the corresponding Engine. | 234 | /// will be passed to the corresponding Engine. |
| 268 | #[new] | 235 | #[new] |
| 269 | #[args(debug = false)] | 236 | #[pyo3(signature = (debug = false))] |
| 270 | pub fn new(debug: bool) -> Self { | 237 | pub fn new(debug: bool) -> Self { |
| 271 | Self { | 238 | Self { |
| 272 | filter_set: RustFilterSet::new(debug), | 239 | filter_set: RustFilterSet::new(debug), |
| @@ -279,18 +246,11 @@ impl FilterSet { | |||
| 279 | /// | 246 | /// |
| 280 | /// The format is a string containing either "standard" (ABP/uBO-style) | 247 | /// The format is a string containing either "standard" (ABP/uBO-style) |
| 281 | /// or "hosts". | 248 | /// or "hosts". |
| 282 | #[pyo3(text_signature = "($self, filter_list, format, include_redirect_urls, rule_types)")] | 249 | #[pyo3(signature = (filter_list, format = "standard", rule_types = "all"))] |
| 283 | #[args( | ||
| 284 | filter_list, | ||
| 285 | format = "\"standard\"", | ||
| 286 | include_redirect_urls = "false", | ||
| 287 | rule_types = "\"all\"" | ||
| 288 | )] | ||
| 289 | pub fn add_filter_list( | 250 | pub fn add_filter_list( |
| 290 | &mut self, | 251 | &mut self, |
| 291 | filter_list: &str, | 252 | filter_list: &str, |
| 292 | format: &str, | 253 | format: &str, |
| 293 | include_redirect_urls: bool, | ||
| 294 | rule_types: &str, | 254 | rule_types: &str, |
| 295 | ) -> PyResult<()> { | 255 | ) -> PyResult<()> { |
| 296 | let filter_format = filter_format_from_string(format)?; | 256 | let filter_format = filter_format_from_string(format)?; |
| @@ -299,8 +259,8 @@ impl FilterSet { | |||
| 299 | filter_list, | 259 | filter_list, |
| 300 | ParseOptions { | 260 | ParseOptions { |
| 301 | format: filter_format, | 261 | format: filter_format, |
| 302 | include_redirect_urls, | ||
| 303 | rule_types, | 262 | rule_types, |
| 263 | permissions: PermissionMask::default(), | ||
| 304 | }, | 264 | }, |
| 305 | ); | 265 | ); |
| 306 | Ok(()) | 266 | Ok(()) |
| @@ -311,18 +271,11 @@ impl FilterSet { | |||
| 311 | /// | 271 | /// |
| 312 | /// The format is a string containing either "standard" (ABP/uBO-style) | 272 | /// The format is a string containing either "standard" (ABP/uBO-style) |
| 313 | /// or "hosts". | 273 | /// or "hosts". |
| 314 | #[pyo3(text_signature = "($self, filters, format, include_redirect_urls, rule_types)")] | 274 | #[pyo3(signature = (filters, format = "standard", rule_types = "all"))] |
| 315 | #[args( | ||
| 316 | filters, | ||
| 317 | format = "\"standard\"", | ||
| 318 | include_redirect_urls = "false", | ||
| 319 | rule_types = "\"all\"" | ||
| 320 | )] | ||
| 321 | pub fn add_filters( | 275 | pub fn add_filters( |
| 322 | &mut self, | 276 | &mut self, |
| 323 | filters: Vec<String>, | 277 | filters: Vec<String>, |
| 324 | format: &str, | 278 | format: &str, |
| 325 | include_redirect_urls: bool, | ||
| 326 | rule_types: &str, | 279 | rule_types: &str, |
| 327 | ) -> PyResult<()> { | 280 | ) -> PyResult<()> { |
| 328 | let filter_format = filter_format_from_string(format)?; | 281 | let filter_format = filter_format_from_string(format)?; |
| @@ -331,8 +284,8 @@ impl FilterSet { | |||
| 331 | &filters, | 284 | &filters, |
| 332 | ParseOptions { | 285 | ParseOptions { |
| 333 | format: filter_format, | 286 | format: filter_format, |
| 334 | include_redirect_urls, | ||
| 335 | rule_types, | 287 | rule_types, |
| 288 | permissions: PermissionMask::default(), | ||
| 336 | }, | 289 | }, |
| 337 | ); | 290 | ); |
| 338 | Ok(()) | 291 | Ok(()) |
| @@ -351,10 +304,9 @@ pub struct UrlSpecificResources { | |||
| 351 | /// styled as `{ display: none !important; }`. | 304 | /// styled as `{ display: none !important; }`. |
| 352 | #[pyo3(get)] | 305 | #[pyo3(get)] |
| 353 | pub hide_selectors: HashSet<String>, | 306 | pub hide_selectors: HashSet<String>, |
| 354 | /// A map of CSS selectors on the page to respective non-hide style rules, | 307 | /// Set of JSON-encoded procedural filters or filters with an action. |
| 355 | /// i.e. any required styles other than `display: none`. | ||
| 356 | #[pyo3(get)] | 308 | #[pyo3(get)] |
| 357 | pub style_selectors: HashMap<String, Vec<String>>, | 309 | pub procedural_actions: HashSet<String>, |
| 358 | /// A set of any class or id CSS selectors that should not have generic | 310 | /// A set of any class or id CSS selectors that should not have generic |
| 359 | /// rules applied. | 311 | /// rules applied. |
| 360 | // In practice, these should be passed to `class_id_stylesheet` and not | 312 | // In practice, these should be passed to `class_id_stylesheet` and not |
| @@ -376,7 +328,7 @@ impl From<RustUrlSpecificResources> for UrlSpecificResources { | |||
| 376 | fn from(r: RustUrlSpecificResources) -> Self { | 328 | fn from(r: RustUrlSpecificResources) -> Self { |
| 377 | Self { | 329 | Self { |
| 378 | hide_selectors: r.hide_selectors, | 330 | hide_selectors: r.hide_selectors, |
| 379 | style_selectors: r.style_selectors, | 331 | procedural_actions: r.procedural_actions, |
| 380 | exceptions: r.exceptions, | 332 | exceptions: r.exceptions, |
| 381 | injected_script: r.injected_script, | 333 | injected_script: r.injected_script, |
| 382 | generichide: r.generichide, | 334 | generichide: r.generichide, |
| @@ -388,9 +340,9 @@ impl From<RustUrlSpecificResources> for UrlSpecificResources { | |||
| 388 | impl UrlSpecificResources { | 340 | impl UrlSpecificResources { |
| 389 | fn __repr__(&self) -> PyResult<String> { | 341 | fn __repr__(&self) -> PyResult<String> { |
| 390 | Ok(format!( | 342 | Ok(format!( |
| 391 | "UrlSpecificResources<{} hide selectors, {} style selectors, {} exceptions, injected_javascript={}, generichide={}>", | 343 | "UrlSpecificResources<{} hide selectors, {} procedural actions, {} exceptions, injected_javascript={}, generichide={}>", |
| 392 | self.hide_selectors.len(), | 344 | self.hide_selectors.len(), |
| 393 | self.style_selectors.len(), | 345 | self.procedural_actions.len(), |
| 394 | self.exceptions.len(), | 346 | self.exceptions.len(), |
| 395 | self.injected_script.diy_python_repr(), | 347 | self.injected_script.diy_python_repr(), |
| 396 | self.generichide.diy_python_repr(), | 348 | self.generichide.diy_python_repr(), |
| @@ -418,7 +370,6 @@ impl UrlSpecificResources { | |||
| 418 | /// | 370 | /// |
| 419 | /// [1]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/ResourceType | 371 | /// [1]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/ResourceType |
| 420 | #[pyclass] | 372 | #[pyclass] |
| 421 | #[pyo3(text_signature = "($self, filter_set, optimize)")] | ||
| 422 | pub struct Engine { | 373 | pub struct Engine { |
| 423 | engine: RustEngine, | 374 | engine: RustEngine, |
| 424 | optimize: bool, | 375 | optimize: bool, |
| @@ -428,7 +379,7 @@ pub struct Engine { | |||
| 428 | impl Engine { | 379 | impl Engine { |
| 429 | /// Create a new adblocking engine | 380 | /// Create a new adblocking engine |
| 430 | #[new] | 381 | #[new] |
| 431 | #[args(filter_set, optimize = true)] | 382 | #[pyo3(signature = (filter_set, optimize = true))] |
| 432 | pub fn new(filter_set: FilterSet, optimize: bool) -> Self { | 383 | pub fn new(filter_set: FilterSet, optimize: bool) -> Self { |
| 433 | let engine = RustEngine::from_filter_set(filter_set.filter_set, optimize); | 384 | let engine = RustEngine::from_filter_set(filter_set.filter_set, optimize); |
| 434 | Self { engine, optimize } | 385 | Self { engine, optimize } |
| @@ -442,17 +393,26 @@ impl Engine { | |||
| 442 | /// * `url` - The URL of the request to check | 393 | /// * `url` - The URL of the request to check |
| 443 | /// * `source_url` - The URL from where the request is made | 394 | /// * `source_url` - The URL from where the request is made |
| 444 | /// * `request_type` - The resource type that the request points to | 395 | /// * `request_type` - The resource type that the request points to |
| 445 | #[pyo3(text_signature = "($self, url, source_url, request_type)")] | ||
| 446 | pub fn check_network_urls( | 396 | pub fn check_network_urls( |
| 447 | &self, | 397 | &self, |
| 448 | url: &str, | 398 | url: &str, |
| 449 | source_url: &str, | 399 | source_url: &str, |
| 450 | request_type: &str, | 400 | request_type: &str, |
| 451 | ) -> BlockerResult { | 401 | ) -> BlockerResult { |
| 452 | let blocker_result = self | 402 | match Request::new(url, source_url, request_type) { |
| 453 | .engine | 403 | Ok(request) => { |
| 454 | .check_network_urls(url, source_url, request_type); | 404 | let blocker_result = self.engine.check_network_request(&request); |
| 455 | blocker_result.into() | 405 | blocker_result.into() |
| 406 | } | ||
| 407 | Err(_) => BlockerResult { | ||
| 408 | matched: false, | ||
| 409 | important: false, | ||
| 410 | redirect: None, | ||
| 411 | rewritten_url: None, | ||
| 412 | exception: None, | ||
| 413 | filter: None, | ||
| 414 | } | ||
| 415 | } | ||
| 456 | } | 416 | } |
| 457 | 417 | ||
| 458 | /// Check if a request should be blocked based on the given parameters. | 418 | /// Check if a request should be blocked based on the given parameters. |
| @@ -465,9 +425,7 @@ impl Engine { | |||
| 465 | /// * `third_party_request` - Is the given request to a third-party? Here, | 425 | /// * `third_party_request` - Is the given request to a third-party? Here, |
| 466 | /// `None` can be given and the engine will figure it out based on the | 426 | /// `None` can be given and the engine will figure it out based on the |
| 467 | /// `hostname` and `source_hostname`. | 427 | /// `hostname` and `source_hostname`. |
| 468 | #[pyo3( | 428 | #[pyo3(signature = (url, hostname, source_hostname, request_type, third_party_request = None))] |
| 469 | text_signature = "($self, url, hostname, source_hostname, requsest_type, third_party_request)" | ||
| 470 | )] | ||
| 471 | pub fn check_network_urls_with_hostnames( | 429 | pub fn check_network_urls_with_hostnames( |
| 472 | &self, | 430 | &self, |
| 473 | url: &str, | 431 | url: &str, |
| @@ -476,13 +434,11 @@ impl Engine { | |||
| 476 | request_type: &str, | 434 | request_type: &str, |
| 477 | third_party_request: Option<bool>, | 435 | third_party_request: Option<bool>, |
| 478 | ) -> BlockerResult { | 436 | ) -> BlockerResult { |
| 479 | let blocker_result = self.engine.check_network_urls_with_hostnames( | 437 | let third_party = third_party_request.unwrap_or_else(|| { |
| 480 | url, | 438 | hostname != source_hostname |
| 481 | hostname, | 439 | }); |
| 482 | source_hostname, | 440 | let request = Request::preparsed(url, hostname, source_hostname, request_type, third_party); |
| 483 | request_type, | 441 | let blocker_result = self.engine.check_network_request(&request); |
| 484 | third_party_request, | ||
| 485 | ); | ||
| 486 | blocker_result.into() | 442 | blocker_result.into() |
| 487 | } | 443 | } |
| 488 | 444 | ||
| @@ -499,10 +455,7 @@ impl Engine { | |||
| 499 | /// * `previously_matched_rule` - Return a match as long as there are no | 455 | /// * `previously_matched_rule` - Return a match as long as there are no |
| 500 | /// exceptions | 456 | /// exceptions |
| 501 | /// * `force_check_exceptions` - Check exceptions even if no other rule matches | 457 | /// * `force_check_exceptions` - Check exceptions even if no other rule matches |
| 502 | #[pyo3( | 458 | #[pyo3(signature = (url, hostname, source_hostname, request_type, third_party_request = None, previously_matched_rule = false, force_check_exceptions = false))] |
| 503 | text_signature = "($self, url, hostname, source_hostname, request_type, \ | ||
| 504 | third_party_request, previously_matched_rule, force_check_exceptions)" | ||
| 505 | )] | ||
| 506 | #[allow(clippy::too_many_arguments)] | 459 | #[allow(clippy::too_many_arguments)] |
| 507 | pub fn check_network_urls_with_hostnames_subset( | 460 | pub fn check_network_urls_with_hostnames_subset( |
| 508 | &self, | 461 | &self, |
| @@ -514,12 +467,12 @@ impl Engine { | |||
| 514 | previously_matched_rule: bool, | 467 | previously_matched_rule: bool, |
| 515 | force_check_exceptions: bool, | 468 | force_check_exceptions: bool, |
| 516 | ) -> BlockerResult { | 469 | ) -> BlockerResult { |
| 517 | let blocker_result = self.engine.check_network_urls_with_hostnames_subset( | 470 | let third_party = third_party_request.unwrap_or_else(|| { |
| 518 | url, | 471 | hostname != source_hostname |
| 519 | hostname, | 472 | }); |
| 520 | source_hostname, | 473 | let request = Request::preparsed(url, hostname, source_hostname, request_type, third_party); |
| 521 | request_type, | 474 | let blocker_result = self.engine.check_network_request_subset( |
| 522 | third_party_request, | 475 | &request, |
| 523 | previously_matched_rule, | 476 | previously_matched_rule, |
| 524 | force_check_exceptions, | 477 | force_check_exceptions, |
| 525 | ); | 478 | ); |
| @@ -534,7 +487,7 @@ impl Engine { | |||
| 534 | /// Use `"template"` if wanting to specify a template resource type. | 487 | /// Use `"template"` if wanting to specify a template resource type. |
| 535 | /// * `content`: The resource data, encoded using standard base64 configuration | 488 | /// * `content`: The resource data, encoded using standard base64 configuration |
| 536 | /// * `aliases`: List of aliases for the resource | 489 | /// * `aliases`: List of aliases for the resource |
| 537 | #[pyo3(text_signature = "($self, name, content_type, content, aliases)")] | 490 | #[pyo3(signature = (name, content_type, content, aliases = None))] |
| 538 | pub fn add_resource( | 491 | pub fn add_resource( |
| 539 | &mut self, | 492 | &mut self, |
| 540 | name: &str, | 493 | name: &str, |
| @@ -542,7 +495,7 @@ impl Engine { | |||
| 542 | content: &str, | 495 | content: &str, |
| 543 | aliases: Option<Vec<String>>, | 496 | aliases: Option<Vec<String>>, |
| 544 | ) -> PyResult<()> { | 497 | ) -> PyResult<()> { |
| 545 | let result = self.engine.add_resource(Resource { | 498 | let resource = Resource { |
| 546 | name: name.to_string(), | 499 | name: name.to_string(), |
| 547 | aliases: aliases.unwrap_or_default(), | 500 | aliases: aliases.unwrap_or_default(), |
| 548 | kind: match content_type { | 501 | kind: match content_type { |
| @@ -552,47 +505,27 @@ impl Engine { | |||
| 552 | ))), | 505 | ))), |
| 553 | }, | 506 | }, |
| 554 | content: content.to_string(), | 507 | content: content.to_string(), |
| 555 | }); | 508 | dependencies: Vec::new(), |
| 509 | permission: PermissionMask::default(), | ||
| 510 | }; | ||
| 556 | 511 | ||
| 557 | match result { | 512 | self.engine.use_resources(std::iter::once(resource)); |
| 558 | Ok(_) => Ok(()), | 513 | Ok(()) |
| 559 | Err(err) => match err { | ||
| 560 | RustAddResourceError::InvalidBase64Content => Err( | ||
| 561 | InvalidBase64ContentError::new_err("invalid base64 content".to_string()), | ||
| 562 | ), | ||
| 563 | RustAddResourceError::InvalidUtf8Content => Err(InvalidUtf8ContentError::new_err( | ||
| 564 | "invalid utf content".to_string(), | ||
| 565 | )), | ||
| 566 | }, | ||
| 567 | } | ||
| 568 | } | 514 | } |
| 569 | 515 | ||
| 570 | /// Serialize this blocking engine to bytes. They can then be deserialized | 516 | /// Serialize this blocking engine to bytes. They can then be deserialized |
| 571 | /// using `deserialize()` to get the same engine again. | 517 | /// using `deserialize()` to get the same engine again. |
| 572 | #[pyo3(text_signature = "($self)")] | 518 | pub fn serialize<'p>(&self, py: Python<'p>) -> PyResult<Bound<'p, PyBytes>> { |
| 573 | pub fn serialize<'p>(&mut self, py: Python<'p>) -> PyResult<&'p PyBytes> { | 519 | let bytes = self.engine.serialize(); |
| 574 | let bytes = self.serialize_inner()?; | 520 | let py_bytes = PyBytes::new_bound(py, &bytes); |
| 575 | let py_bytes = PyBytes::new(py, &bytes); | ||
| 576 | Ok(py_bytes) | 521 | Ok(py_bytes) |
| 577 | } | 522 | } |
| 578 | 523 | ||
| 579 | fn serialize_inner(&mut self) -> PyResult<Vec<u8>> { | ||
| 580 | let result = self.engine.serialize_raw(); | ||
| 581 | match result { | ||
| 582 | Ok(x) => Ok(x), | ||
| 583 | Err(error) => { | ||
| 584 | let my_blocker_error: BlockerError = error.into(); | ||
| 585 | Err(my_blocker_error.into()) | ||
| 586 | } | ||
| 587 | } | ||
| 588 | } | ||
| 589 | |||
| 590 | /// Serialize this blocking engine to a file. The file can then be | 524 | /// Serialize this blocking engine to a file. The file can then be |
| 591 | /// deserialized using `deserialize_from_file()` to get the same engine | 525 | /// deserialized using `deserialize_from_file()` to get the same engine |
| 592 | /// again. | 526 | /// again. |
| 593 | #[pyo3(text_signature = "($self, file)")] | 527 | pub fn serialize_to_file(&self, file: &str) -> PyResult<()> { |
| 594 | pub fn serialize_to_file(&mut self, file: &str) -> PyResult<()> { | 528 | let data = self.engine.serialize(); |
| 595 | let data = self.serialize_inner()?; | ||
| 596 | let mut fd = fs::OpenOptions::new() | 529 | let mut fd = fs::OpenOptions::new() |
| 597 | .create(true) | 530 | .create(true) |
| 598 | .truncate(true) | 531 | .truncate(true) |
| @@ -603,21 +536,14 @@ impl Engine { | |||
| 603 | } | 536 | } |
| 604 | 537 | ||
| 605 | /// Deserialize a blocking engine from bytes produced with `serialize()`. | 538 | /// Deserialize a blocking engine from bytes produced with `serialize()`. |
| 606 | #[pyo3(text_signature = "($self, serialized)")] | ||
| 607 | pub fn deserialize(&mut self, serialized: &[u8]) -> PyResult<()> { | 539 | pub fn deserialize(&mut self, serialized: &[u8]) -> PyResult<()> { |
| 608 | let result = self.engine.deserialize(serialized); | 540 | self.engine.deserialize(serialized).map_err(|_| { |
| 609 | match result { | 541 | DeserializationError::new_err("Failed to deserialize engine data") |
| 610 | Ok(_) => Ok(()), | 542 | }) |
| 611 | Err(error) => { | ||
| 612 | let my_blocker_error: BlockerError = error.into(); | ||
| 613 | Err(my_blocker_error.into()) | ||
| 614 | } | ||
| 615 | } | ||
| 616 | } | 543 | } |
| 617 | 544 | ||
| 618 | /// Deserialize a blocking engine from file produced with | 545 | /// Deserialize a blocking engine from file produced with |
| 619 | /// `serialize_to_file()`. | 546 | /// `serialize_to_file()`. |
| 620 | #[pyo3(text_signature = "($self, file)")] | ||
| 621 | pub fn deserialize_from_file(&mut self, file: &str) -> PyResult<()> { | 547 | pub fn deserialize_from_file(&mut self, file: &str) -> PyResult<()> { |
| 622 | let mut fd = fs::File::open(file)?; | 548 | let mut fd = fs::File::open(file)?; |
| 623 | let mut data: Vec<u8> = Vec::new(); | 549 | let mut data: Vec<u8> = Vec::new(); |
| @@ -626,18 +552,20 @@ impl Engine { | |||
| 626 | } | 552 | } |
| 627 | 553 | ||
| 628 | /// Checks if the given filter exists in the blocking engine. | 554 | /// Checks if the given filter exists in the blocking engine. |
| 629 | #[pyo3(text_signature = "($self, filter)")] | 555 | /// Note: This method has been removed in the latest version of adblock-rust. |
| 630 | pub fn filter_exists(&self, filter: &str) -> bool { | 556 | /// It will always return false. |
| 631 | self.engine.filter_exists(filter) | 557 | pub fn filter_exists(&self, _filter: &str) -> bool { |
| 558 | // This method no longer exists in the adblock-rust API | ||
| 559 | false | ||
| 632 | } | 560 | } |
| 633 | 561 | ||
| 634 | /// Sets this engine's tags to be _only_ the ones provided in tags. | 562 | /// Sets this engine's tags to be _only_ the ones provided in tags. |
| 635 | /// | 563 | /// |
| 636 | /// Tags can be used to cheaply enable or disable network rules with a | 564 | /// Tags can be used to cheaply enable or disable network rules with a |
| 637 | /// corresponding $tag option. | 565 | /// corresponding $tag option. |
| 638 | #[pyo3(text_signature = "($self, tags)")] | 566 | pub fn use_tags(&mut self, tags: Vec<String>) { |
| 639 | pub fn use_tags(&mut self, tags: Vec<&str>) { | 567 | let tag_refs: Vec<&str> = tags.iter().map(|s| s.as_str()).collect(); |
| 640 | self.engine.use_tags(&tags); | 568 | self.engine.use_tags(&tag_refs); |
| 641 | } | 569 | } |
| 642 | 570 | ||
| 643 | /// Sets this engine's tags to additionally include the ones provided in | 571 | /// Sets this engine's tags to additionally include the ones provided in |
| @@ -645,9 +573,9 @@ impl Engine { | |||
| 645 | /// | 573 | /// |
| 646 | /// Tags can be used to cheaply enable or disable network rules with a | 574 | /// Tags can be used to cheaply enable or disable network rules with a |
| 647 | /// corresponding $tag option. | 575 | /// corresponding $tag option. |
| 648 | #[pyo3(text_signature = "($self, tags)")] | 576 | pub fn enable_tags(&mut self, tags: Vec<String>) { |
| 649 | pub fn enable_tags(&mut self, tags: Vec<&str>) { | 577 | let tag_refs: Vec<&str> = tags.iter().map(|s| s.as_str()).collect(); |
| 650 | self.engine.enable_tags(&tags); | 578 | self.engine.enable_tags(&tag_refs); |
| 651 | } | 579 | } |
| 652 | 580 | ||
| 653 | /// Sets this engine's tags to no longer include the ones provided in | 581 | /// Sets this engine's tags to no longer include the ones provided in |
| @@ -655,16 +583,15 @@ impl Engine { | |||
| 655 | /// | 583 | /// |
| 656 | /// Tags can be used to cheaply enable or disable network rules with a | 584 | /// Tags can be used to cheaply enable or disable network rules with a |
| 657 | /// corresponding $tag option. | 585 | /// corresponding $tag option. |
| 658 | #[pyo3(text_signature = "($self, tags)")] | 586 | pub fn disable_tags(&mut self, tags: Vec<String>) { |
| 659 | pub fn disable_tags(&mut self, tags: Vec<&str>) { | 587 | let tag_refs: Vec<&str> = tags.iter().map(|s| s.as_str()).collect(); |
| 660 | self.engine.disable_tags(&tags); | 588 | self.engine.disable_tags(&tag_refs); |
| 661 | } | 589 | } |
| 662 | 590 | ||
| 663 | /// Checks if a given tag exists in this engine. | 591 | /// Checks if a given tag exists in this engine. |
| 664 | /// | 592 | /// |
| 665 | /// Tags can be used to cheaply enable or disable network rules with a | 593 | /// Tags can be used to cheaply enable or disable network rules with a |
| 666 | /// corresponding $tag option. | 594 | /// corresponding $tag option. |
| 667 | #[pyo3(text_signature = "($self, tag)")] | ||
| 668 | pub fn tag_exists(&self, tag: &str) -> bool { | 595 | pub fn tag_exists(&self, tag: &str) -> bool { |
| 669 | self.engine.tag_exists(tag) | 596 | self.engine.tag_exists(tag) |
| 670 | } | 597 | } |
| @@ -673,7 +600,6 @@ impl Engine { | |||
| 673 | /// url. Once this has been called, all CSS ids and classes on a | 600 | /// url. Once this has been called, all CSS ids and classes on a |
| 674 | /// page should be passed to hidden_class_id_selectors to obtain any | 601 | /// page should be passed to hidden_class_id_selectors to obtain any |
| 675 | /// stylesheets consisting of generic rules. | 602 | /// stylesheets consisting of generic rules. |
| 676 | #[pyo3(text_signature = "($self, url)")] | ||
| 677 | pub fn url_cosmetic_resources(&self, url: &str) -> UrlSpecificResources { | 603 | pub fn url_cosmetic_resources(&self, url: &str) -> UrlSpecificResources { |
| 678 | self.engine.url_cosmetic_resources(url).into() | 604 | self.engine.url_cosmetic_resources(url).into() |
| 679 | } | 605 | } |
| @@ -685,7 +611,6 @@ impl Engine { | |||
| 685 | /// are not excepted. | 611 | /// are not excepted. |
| 686 | /// | 612 | /// |
| 687 | /// Exceptions should be passed directly from UrlSpecificResources. | 613 | /// Exceptions should be passed directly from UrlSpecificResources. |
| 688 | #[pyo3(text_signature = "($self, classes, ids, exceptions)")] | ||
| 689 | pub fn hidden_class_id_selectors( | 614 | pub fn hidden_class_id_selectors( |
| 690 | &self, | 615 | &self, |
| 691 | classes: Vec<String>, | 616 | classes: Vec<String>, |
