diff options
Diffstat (limited to 'src/lib.rs')
| -rw-r--r-- | src/lib.rs | 150 |
1 files changed, 108 insertions, 42 deletions
| @@ -12,8 +12,10 @@ | |||
| 12 | 12 | ||
| 13 | use adblock::blocker::BlockerError as RustBlockerError; | 13 | use adblock::blocker::BlockerError as RustBlockerError; |
| 14 | use adblock::blocker::BlockerResult as RustBlockerResult; | 14 | use adblock::blocker::BlockerResult as RustBlockerResult; |
| 15 | use adblock::cosmetic_filter_cache::HostnameSpecificResources as RustHostnameSpecificResources; | 15 | use adblock::cosmetic_filter_cache::UrlSpecificResources as RustUrlSpecificResources; |
| 16 | use adblock::engine::Engine as RustEngine; | 16 | use adblock::engine::Engine as RustEngine; |
| 17 | use adblock::lists::FilterFormat; | ||
| 18 | use adblock::lists::FilterSet as RustFilterSet; | ||
| 17 | use pyo3::class::PyObjectProtocol; | 19 | use pyo3::class::PyObjectProtocol; |
| 18 | use pyo3::exceptions::ValueError as PyValueError; | 20 | use pyo3::exceptions::ValueError as PyValueError; |
| 19 | use pyo3::prelude::*; | 21 | use pyo3::prelude::*; |
| @@ -32,8 +34,9 @@ use std::io::{Read, Write}; | |||
| 32 | fn adblock(_py: Python<'_>, m: &PyModule) -> PyResult<()> { | 34 | fn adblock(_py: Python<'_>, m: &PyModule) -> PyResult<()> { |
| 33 | m.add("__version__", env!("CARGO_PKG_VERSION"))?; | 35 | m.add("__version__", env!("CARGO_PKG_VERSION"))?; |
| 34 | m.add_class::<Engine>()?; | 36 | m.add_class::<Engine>()?; |
| 37 | m.add_class::<FilterSet>()?; | ||
| 35 | m.add_class::<BlockerResult>()?; | 38 | m.add_class::<BlockerResult>()?; |
| 36 | m.add_class::<HostnameSpecificResources>()?; | 39 | m.add_class::<UrlSpecificResources>()?; |
| 37 | Ok(()) | 40 | Ok(()) |
| 38 | } | 41 | } |
| 39 | 42 | ||
| @@ -163,10 +166,71 @@ impl Into<BlockerError> for RustBlockerError { | |||
| 163 | } | 166 | } |
| 164 | } | 167 | } |
| 165 | 168 | ||
| 169 | fn filter_format_from_string(filter_format: &str) -> PyResult<FilterFormat> { | ||
| 170 | match filter_format { | ||
| 171 | "standard" => Ok(FilterFormat::Standard), | ||
| 172 | "hosts" => Ok(FilterFormat::Hosts), | ||
| 173 | _ => Err(PyErr::new::<PyValueError, _>("Invalid format value")), | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | /// Manages a set of rules to be added to an Engine. | ||
| 178 | /// | ||
| 179 | /// To be able to efficiently handle special options like $badfilter, and to | ||
| 180 | /// allow optimizations, all rules must be available when the Engine is first | ||
| 181 | /// created. FilterSet allows assembling a compound list from multiple | ||
| 182 | /// different sources before compiling the rules into an Engine. | ||
| 183 | #[pyclass] | ||
| 184 | #[text_signature = "($self, debug)"] | ||
| 185 | #[derive(Clone)] | ||
| 186 | pub struct FilterSet { | ||
| 187 | filter_set: RustFilterSet, | ||
| 188 | } | ||
| 189 | |||
| 190 | #[pymethods] | ||
| 191 | impl FilterSet { | ||
| 192 | /// Creates a new `FilterSet`. The `debug` argument specifies whether or | ||
| 193 | /// not to save information about the original raw filter rules alongside | ||
| 194 | /// the more compact internal representation. If enabled, this information | ||
| 195 | /// will be passed to the corresponding Engine. | ||
| 196 | #[new] | ||
| 197 | #[args(debug = false)] | ||
| 198 | pub fn new(debug: bool) -> Self { | ||
| 199 | Self { | ||
| 200 | filter_set: RustFilterSet::new(debug), | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | /// Adds the contents of an entire filter list to this FilterSet. Filters | ||
| 205 | /// that cannot be parsed successfully are ignored. | ||
| 206 | /// | ||
| 207 | /// The format is a string containing either "standard" (ABP/uBO-style) | ||
| 208 | /// or "hosts". | ||
| 209 | #[text_signature = "($self, filter_list, format)"] | ||
| 210 | #[args(filter_list, format = "\"standard\"")] | ||
| 211 | pub fn add_filter_list(&mut self, filter_list: &str, format: &str) -> PyResult<()> { | ||
| 212 | let filter_format = filter_format_from_string(format)?; | ||
| 213 | self.filter_set.add_filter_list(filter_list, filter_format); | ||
| 214 | Ok(()) | ||
| 215 | } | ||
| 216 | |||
| 217 | /// Adds a collection of filter rules to this FilterSet. Filters that | ||
| 218 | /// cannot be parsed successfully are ignored. | ||
| 219 | /// | ||
| 220 | /// The format is a string containing either "standard" (ABP/uBO-style) | ||
| 221 | /// or "hosts". | ||
| 222 | #[text_signature = "($self, filters, format)"] | ||
| 223 | #[args(filters, format = "\"standard\"")] | ||
| 224 | pub fn add_filters(&mut self, filters: Vec<String>, format: &str) -> PyResult<()> { | ||
| 225 | let filter_format = filter_format_from_string(format)?; | ||
| 226 | self.filter_set.add_filters(&filters, filter_format); | ||
| 227 | Ok(()) | ||
| 228 | } | ||
| 229 | } | ||
| 166 | /// Contains cosmetic filter information intended to be injected into a | 230 | /// Contains cosmetic filter information intended to be injected into a |
| 167 | /// particular hostname. | 231 | /// particular hostname. |
| 168 | #[pyclass] | 232 | #[pyclass] |
| 169 | pub struct HostnameSpecificResources { | 233 | pub struct UrlSpecificResources { |
| 170 | /// A set of any CSS selector on the page that should be hidden, i.e. | 234 | /// A set of any CSS selector on the page that should be hidden, i.e. |
| 171 | /// styled as `{ display: none !important; }`. | 235 | /// styled as `{ display: none !important; }`. |
| 172 | #[pyo3(get)] | 236 | #[pyo3(get)] |
| @@ -187,9 +251,9 @@ pub struct HostnameSpecificResources { | |||
| 187 | pub injected_script: String, | 251 | pub injected_script: String, |
| 188 | } | 252 | } |
| 189 | 253 | ||
| 190 | impl Into<HostnameSpecificResources> for RustHostnameSpecificResources { | 254 | impl Into<UrlSpecificResources> for RustUrlSpecificResources { |
| 191 | fn into(self) -> HostnameSpecificResources { | 255 | fn into(self) -> UrlSpecificResources { |
| 192 | HostnameSpecificResources { | 256 | UrlSpecificResources { |
| 193 | hide_selectors: self.hide_selectors, | 257 | hide_selectors: self.hide_selectors, |
| 194 | style_selectors: self.style_selectors, | 258 | style_selectors: self.style_selectors, |
| 195 | exceptions: self.exceptions, | 259 | exceptions: self.exceptions, |
| @@ -199,10 +263,10 @@ impl Into<HostnameSpecificResources> for RustHostnameSpecificResources { | |||
| 199 | } | 263 | } |
| 200 | 264 | ||
| 201 | #[pyproto] | 265 | #[pyproto] |
| 202 | impl PyObjectProtocol for HostnameSpecificResources { | 266 | impl PyObjectProtocol for UrlSpecificResources { |
| 203 | fn __repr__(&self) -> PyResult<String> { | 267 | fn __repr__(&self) -> PyResult<String> { |
| 204 | Ok(format!( | 268 | Ok(format!( |
| 205 | "HostnameSpecificResources<{} hide selectors, {} style selectors, {} exceptions, injected_javascript={:?}>", | 269 | "UrlSpecificResources<{} hide selectors, {} style selectors, {} exceptions, injected_javascript={:?}>", |
| 206 | self.hide_selectors.len(), | 270 | self.hide_selectors.len(), |
| 207 | self.style_selectors.len(), | 271 | self.style_selectors.len(), |
| 208 | self.exceptions.len(), | 272 | self.exceptions.len(), |
| @@ -231,7 +295,7 @@ impl PyObjectProtocol for HostnameSpecificResources { | |||
| 231 | /// | 295 | /// |
| 232 | /// [1]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/ResourceType | 296 | /// [1]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/ResourceType |
| 233 | #[pyclass] | 297 | #[pyclass] |
| 234 | #[text_signature = "($self, network_filters=None, load_network=True, load_cosmetic=False, debug=False)"] | 298 | #[text_signature = "($self, filter_set, optimize)"] |
| 235 | pub struct Engine { | 299 | pub struct Engine { |
| 236 | engine: RustEngine, | 300 | engine: RustEngine, |
| 237 | } | 301 | } |
| @@ -240,21 +304,9 @@ pub struct Engine { | |||
| 240 | impl Engine { | 304 | impl Engine { |
| 241 | /// Create a new adblocking engine | 305 | /// Create a new adblocking engine |
| 242 | #[new] | 306 | #[new] |
| 243 | #[args(network_filters="None", load_network=true, load_cosmetic=false, debug=false)] | 307 | #[args(filter_set, optimize = true)] |
| 244 | pub fn new( | 308 | pub fn new(filter_set: FilterSet, optimize: bool) -> Self { |
| 245 | network_filters: Option<Vec<String>>, | 309 | let engine = RustEngine::from_filter_set(filter_set.filter_set, optimize); |
| 246 | load_network: bool, | ||
| 247 | load_cosmetic: bool, | ||
| 248 | debug: bool, | ||
| 249 | ) -> Self { | ||
| 250 | let filters = network_filters.unwrap_or(Vec::new()); | ||
| 251 | let engine = RustEngine::from_rules_parametrised( | ||
| 252 | &filters, | ||
| 253 | load_network, | ||
| 254 | load_cosmetic, | ||
| 255 | debug, | ||
| 256 | true, | ||
| 257 | ); | ||
| 258 | Self { engine } | 310 | Self { engine } |
| 259 | } | 311 | } |
| 260 | 312 | ||
| @@ -404,43 +456,57 @@ impl Engine { | |||
| 404 | self.deserialize(&data) | 456 | self.deserialize(&data) |
| 405 | } | 457 | } |
| 406 | 458 | ||
| 407 | /// Add the contents of a block list file to the blocking engine. | ||
| 408 | #[text_signature = "($self, filter_list)"] | ||
| 409 | pub fn add_filter_list(&mut self, filter_list: &str) { | ||
| 410 | self.engine.add_filter_list(filter_list); | ||
| 411 | } | ||
| 412 | |||
| 413 | /// Checks if the given filter exists in the blocking engine. | 459 | /// Checks if the given filter exists in the blocking engine. |
| 414 | #[text_signature = "($self, filter)"] | 460 | #[text_signature = "($self, filter)"] |
| 415 | pub fn filter_exists(&self, filter: &str) -> bool { | 461 | pub fn filter_exists(&self, filter: &str) -> bool { |
| 416 | self.engine.filter_exists(filter) | 462 | self.engine.filter_exists(filter) |
| 417 | } | 463 | } |
| 418 | 464 | ||
| 419 | /// Enable the given tags | 465 | /// Sets this engine's tags to be _only_ the ones provided in tags. |
| 466 | /// | ||
| 467 | /// Tags can be used to cheaply enable or disable network rules with a | ||
| 468 | /// corresponding $tag option. | ||
| 420 | #[text_signature = "($self, tags)"] | 469 | #[text_signature = "($self, tags)"] |
| 421 | pub fn tags_enable(&mut self, tags: Vec<&str>) { | 470 | pub fn use_tags(&mut self, tags: Vec<&str>) { |
| 422 | self.engine.tags_enable(&tags); | 471 | self.engine.use_tags(&tags); |
| 423 | } | 472 | } |
| 424 | 473 | ||
| 425 | /// Disable the given tags | 474 | /// Sets this engine's tags to additionally include the ones provided in |
| 475 | /// tags. | ||
| 476 | /// | ||
| 477 | /// Tags can be used to cheaply enable or disable network rules with a | ||
| 478 | /// corresponding $tag option. | ||
| 426 | #[text_signature = "($self, tags)"] | 479 | #[text_signature = "($self, tags)"] |
| 427 | pub fn tags_disable(&mut self, tags: Vec<&str>) { | 480 | pub fn enable_tags(&mut self, tags: Vec<&str>) { |
| 428 | self.engine.tags_disable(&tags); | 481 | self.engine.enable_tags(&tags); |
| 429 | } | 482 | } |
| 430 | 483 | ||
| 431 | /// Check if the given tag exists | 484 | /// Sets this engine's tags to no longer include the ones provided in |
| 485 | /// tags. | ||
| 486 | /// | ||
| 487 | /// Tags can be used to cheaply enable or disable network rules with a | ||
| 488 | /// corresponding $tag option. | ||
| 489 | #[text_signature = "($self, tags)"] | ||
| 490 | pub fn disable_tags(&mut self, tags: Vec<&str>) { | ||
| 491 | self.engine.disable_tags(&tags); | ||
| 492 | } | ||
| 493 | |||
| 494 | /// Checks if a given tag exists in this engine. | ||
| 495 | /// | ||
| 496 | /// Tags can be used to cheaply enable or disable network rules with a | ||
| 497 | /// corresponding $tag option. | ||
| 432 | #[text_signature = "($self, tag)"] | 498 | #[text_signature = "($self, tag)"] |
| 433 | pub fn tag_exists(&self, tag: &str) -> bool { | 499 | pub fn tag_exists(&self, tag: &str) -> bool { |
| 434 | self.engine.tag_exists(tag) | 500 | self.engine.tag_exists(tag) |
| 435 | } | 501 | } |
| 436 | 502 | ||
| 437 | /// Returns a set of cosmetic filter resources required for a particular | 503 | /// Returns a set of cosmetic filter resources required for a particular |
| 438 | /// hostname. Once this has been called, all CSS ids and classes on a | 504 | /// url. Once this has been called, all CSS ids and classes on a |
| 439 | /// page should be passed to hidden_class_id_selectors to obtain any | 505 | /// page should be passed to hidden_class_id_selectors to obtain any |
| 440 | /// stylesheets consisting of generic rules. | 506 | /// stylesheets consisting of generic rules. |
| 441 | #[text_signature = "($self, hostname)"] | 507 | #[text_signature = "($self, url)"] |
| 442 | pub fn hostname_cosmetic_resources(&self, hostname: &str) -> HostnameSpecificResources { | 508 | pub fn url_cosmetic_resources(&self, url: &str) -> UrlSpecificResources { |
| 443 | self.engine.hostname_cosmetic_resources(hostname).into() | 509 | self.engine.url_cosmetic_resources(url).into() |
| 444 | } | 510 | } |
| 445 | 511 | ||
| 446 | /// If any of the provided CSS classes or ids could cause a certain generic | 512 | /// If any of the provided CSS classes or ids could cause a certain generic |
| @@ -449,7 +515,7 @@ impl Engine { | |||
| 449 | /// referencing those classes or ids, provided that the corresponding rules | 515 | /// referencing those classes or ids, provided that the corresponding rules |
| 450 | /// are not excepted. | 516 | /// are not excepted. |
| 451 | /// | 517 | /// |
| 452 | /// Exceptions should be passed directly from HostnameSpecificResources. | 518 | /// Exceptions should be passed directly from UrlSpecificResources. |
| 453 | #[text_signature = "($self, classes, ids, exceptions)"] | 519 | #[text_signature = "($self, classes, ids, exceptions)"] |
| 454 | pub fn hidden_class_id_selectors( | 520 | pub fn hidden_class_id_selectors( |
| 455 | &self, | 521 | &self, |
