mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-01 03:21:10 +00:00
Backed out changesets b05343a5b533 and 57b2cda7e0db (bug 1818349) for causing bug 1819723.
This commit is contained in:
parent
f7edb0b474
commit
76b958d3b3
@ -15,6 +15,11 @@ git = "https://github.com/FirefoxGraphics/wpf-gpu-raster"
|
||||
rev = "a6514854d4518b02f2805719ff6cd74dae7dfde6"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."https://github.com/bendk/application-services"]
|
||||
git = "https://github.com/bendk/application-services"
|
||||
rev = "ecb35df5fc40357c49922f90e86bf4147fa52953"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."https://github.com/chris-zen/coremidi.git"]
|
||||
git = "https://github.com/chris-zen/coremidi.git"
|
||||
rev = "fc68464b5445caf111e41f643a2e69ccce0b4f83"
|
||||
@ -75,11 +80,6 @@ git = "https://github.com/mozilla-spidermonkey/jsparagus"
|
||||
rev = "688a6574cf830b4a3adaf9c5d41efc1f7dd4017f"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."https://github.com/mozilla/application-services"]
|
||||
git = "https://github.com/mozilla/application-services"
|
||||
rev = "5433b3dc9ac152a0da29ed6642df839d79515a59"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."https://github.com/mozilla/audioipc"]
|
||||
git = "https://github.com/mozilla/audioipc"
|
||||
rev = "fb7a2b12ced3b43e6a268621989c6191d1ed7e39"
|
||||
|
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -1595,7 +1595,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "error-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=5433b3dc9ac152a0da29ed6642df839d79515a59#5433b3dc9ac152a0da29ed6642df839d79515a59"
|
||||
source = "git+https://github.com/bendk/application-services?rev=ecb35df5fc40357c49922f90e86bf4147fa52953#ecb35df5fc40357c49922f90e86bf4147fa52953"
|
||||
dependencies = [
|
||||
"error-support-macros",
|
||||
"lazy_static",
|
||||
@ -1607,7 +1607,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "error-support-macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=5433b3dc9ac152a0da29ed6642df839d79515a59#5433b3dc9ac152a0da29ed6642df839d79515a59"
|
||||
source = "git+https://github.com/bendk/application-services?rev=ecb35df5fc40357c49922f90e86bf4147fa52953#ecb35df5fc40357c49922f90e86bf4147fa52953"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -2715,7 +2715,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "interrupt-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=5433b3dc9ac152a0da29ed6642df839d79515a59#5433b3dc9ac152a0da29ed6642df839d79515a59"
|
||||
source = "git+https://github.com/bendk/application-services?rev=ecb35df5fc40357c49922f90e86bf4147fa52953#ecb35df5fc40357c49922f90e86bf4147fa52953"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"parking_lot 0.12.999",
|
||||
@ -3837,7 +3837,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "nss_build_common"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=5433b3dc9ac152a0da29ed6642df839d79515a59#5433b3dc9ac152a0da29ed6642df839d79515a59"
|
||||
source = "git+https://github.com/bendk/application-services?rev=ecb35df5fc40357c49922f90e86bf4147fa52953#ecb35df5fc40357c49922f90e86bf4147fa52953"
|
||||
|
||||
[[package]]
|
||||
name = "nsstring"
|
||||
@ -5045,7 +5045,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "sql-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=5433b3dc9ac152a0da29ed6642df839d79515a59#5433b3dc9ac152a0da29ed6642df839d79515a59"
|
||||
source = "git+https://github.com/bendk/application-services?rev=ecb35df5fc40357c49922f90e86bf4147fa52953#ecb35df5fc40357c49922f90e86bf4147fa52953"
|
||||
dependencies = [
|
||||
"ffi-support",
|
||||
"interrupt-support",
|
||||
@ -5227,7 +5227,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "sync-guid"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=5433b3dc9ac152a0da29ed6642df839d79515a59#5433b3dc9ac152a0da29ed6642df839d79515a59"
|
||||
source = "git+https://github.com/bendk/application-services?rev=ecb35df5fc40357c49922f90e86bf4147fa52953#ecb35df5fc40357c49922f90e86bf4147fa52953"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"rand 0.8.5",
|
||||
@ -5238,7 +5238,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "sync15"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=5433b3dc9ac152a0da29ed6642df839d79515a59#5433b3dc9ac152a0da29ed6642df839d79515a59"
|
||||
source = "git+https://github.com/bendk/application-services?rev=ecb35df5fc40357c49922f90e86bf4147fa52953#ecb35df5fc40357c49922f90e86bf4147fa52953"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"error-support",
|
||||
@ -5268,7 +5268,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tabs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=5433b3dc9ac152a0da29ed6642df839d79515a59#5433b3dc9ac152a0da29ed6642df839d79515a59"
|
||||
source = "git+https://github.com/bendk/application-services?rev=ecb35df5fc40357c49922f90e86bf4147fa52953#ecb35df5fc40357c49922f90e86bf4147fa52953"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"error-support",
|
||||
@ -6042,7 +6042,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
[[package]]
|
||||
name = "viaduct"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=5433b3dc9ac152a0da29ed6642df839d79515a59#5433b3dc9ac152a0da29ed6642df839d79515a59"
|
||||
source = "git+https://github.com/bendk/application-services?rev=ecb35df5fc40357c49922f90e86bf4147fa52953#ecb35df5fc40357c49922f90e86bf4147fa52953"
|
||||
dependencies = [
|
||||
"ffi-support",
|
||||
"log",
|
||||
@ -6199,7 +6199,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "webext-storage"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=5433b3dc9ac152a0da29ed6642df839d79515a59#5433b3dc9ac152a0da29ed6642df839d79515a59"
|
||||
source = "git+https://github.com/bendk/application-services?rev=ecb35df5fc40357c49922f90e86bf4147fa52953#ecb35df5fc40357c49922f90e86bf4147fa52953"
|
||||
dependencies = [
|
||||
"error-support",
|
||||
"ffi-support",
|
||||
|
12
Cargo.toml
12
Cargo.toml
@ -170,12 +170,12 @@ warp = { git = "https://github.com/glandium/warp", rev = "4af45fae95bc98b0eba1ef
|
||||
cssparser = { git = "https://github.com/servo/rust-cssparser", rev = "b196a164dcbb317016d4aa6c58c13147e6045ebb" }
|
||||
|
||||
# application-services overrides to make updating them all simpler.
|
||||
interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "5433b3dc9ac152a0da29ed6642df839d79515a59" }
|
||||
sql-support = { git = "https://github.com/mozilla/application-services", rev = "5433b3dc9ac152a0da29ed6642df839d79515a59" }
|
||||
sync15 = { git = "https://github.com/mozilla/application-services", rev = "5433b3dc9ac152a0da29ed6642df839d79515a59" }
|
||||
tabs = { git = "https://github.com/mozilla/application-services", rev = "5433b3dc9ac152a0da29ed6642df839d79515a59" }
|
||||
viaduct = { git = "https://github.com/mozilla/application-services", rev = "5433b3dc9ac152a0da29ed6642df839d79515a59" }
|
||||
webext-storage = { git = "https://github.com/mozilla/application-services", rev = "5433b3dc9ac152a0da29ed6642df839d79515a59" }
|
||||
interrupt-support = { git = "https://github.com/bendk/application-services", rev = "ecb35df5fc40357c49922f90e86bf4147fa52953" }
|
||||
sql-support = { git = "https://github.com/bendk/application-services", rev = "ecb35df5fc40357c49922f90e86bf4147fa52953" }
|
||||
sync15 = { git = "https://github.com/bendk/application-services", rev = "ecb35df5fc40357c49922f90e86bf4147fa52953" }
|
||||
tabs = { git = "https://github.com/bendk/application-services", rev = "ecb35df5fc40357c49922f90e86bf4147fa52953" }
|
||||
viaduct = { git = "https://github.com/bendk/application-services", rev = "ecb35df5fc40357c49922f90e86bf4147fa52953" }
|
||||
webext-storage = { git = "https://github.com/bendk/application-services", rev = "ecb35df5fc40357c49922f90e86bf4147fa52953" }
|
||||
|
||||
# Patch mio 0.6 to use winapi 0.3 and miow 0.3, getting rid of winapi 0.2.
|
||||
# There is not going to be new version of mio 0.6, mio now being >= 0.7.11.
|
||||
|
@ -79,8 +79,6 @@ class TPSTestRunner(object):
|
||||
# hrm - not sure what the release/beta channels will do?
|
||||
"xpinstall.signatures.required": False,
|
||||
"services.sync.testing.tps": True,
|
||||
# removed data: schema restriction for easier testing of tabs
|
||||
"services.sync.engine.tabs.filteredSchemes": "about|resource|chrome|file|blob|moz-extension",
|
||||
"engine.bookmarks.repair.enabled": False,
|
||||
"extensions.experiments.enabled": True,
|
||||
"webextensions.storage.sync.kinto": False,
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"2a41a998c288fd049dd4dd62bc20e3ad13ded43642c27880dd5af0260bb72865","src/argument.rs":"bb97e801ce2c80b878328b15783678b913c2f34cf6f26a60d894c8da6b4e47aa","src/lib.rs":"8dd5b6225791730881a3500c3013c48678879430d859d0b92ac9dad4c42b04e0"},"package":null}
|
||||
{"files":{"Cargo.toml":"2a41a998c288fd049dd4dd62bc20e3ad13ded43642c27880dd5af0260bb72865","src/argument.rs":"1e4ec4140c536d2feea30eb1e4eef3a6e24533192108e91610ee5c2e75eb5e75","src/lib.rs":"fbd9c048ac86c16ef388fbb9a3c40f60d3aecab41a902740c81b3df6ee6631fe"},"package":null}
|
@ -2,20 +2,16 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
const ERR_MSG: &str = "Expected #[handle_error(path::to::Error)]";
|
||||
|
||||
/// Returns the path to the type of the "internal" error.
|
||||
pub(crate) fn validate(arguments: &syn::AttributeArgs) -> syn::Result<&syn::Path> {
|
||||
if arguments.len() != 1 {
|
||||
return Err(syn::Error::new(proc_macro2::Span::call_site(), ERR_MSG));
|
||||
}
|
||||
|
||||
let nested_meta = arguments.iter().next().unwrap();
|
||||
if let syn::NestedMeta::Meta(syn::Meta::Path(path)) = nested_meta {
|
||||
Ok(path)
|
||||
} else {
|
||||
Err(syn::Error::new(nested_meta.span(), ERR_MSG))
|
||||
pub(crate) fn validate(arguments: &syn::AttributeArgs) -> syn::Result<()> {
|
||||
// For now we validate that there are no arguments.
|
||||
// if we want to improve the macro to support attributes, for example,
|
||||
// if we'd like to pass in the return type of the body we can modify this
|
||||
// logic to parse and return the type.
|
||||
if !arguments.is_empty() {
|
||||
return Err(syn::Error::new(
|
||||
proc_macro2::Span::call_site(),
|
||||
"Expected #[handle_error] with no arguments",
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
17
third_party/rust/error-support-macros/src/lib.rs
vendored
17
third_party/rust/error-support-macros/src/lib.rs
vendored
@ -48,11 +48,9 @@ mod argument;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // The `handle_error` macro maps from the error supplied in the mandatory argument
|
||||
/// // (ie, `Error` in this example) to the error returned by the function (`ExternalError`
|
||||
/// // in this example)
|
||||
/// #[handle_error(Error)]
|
||||
/// #[handle_error]
|
||||
/// fn do_something() -> std::result::Result<String, ExternalError> {
|
||||
/// // The `handle_error` macro maps from `Error` to `ExternalError`
|
||||
/// Err(Error{})
|
||||
/// }
|
||||
///
|
||||
@ -74,13 +72,18 @@ fn impl_handle_error(
|
||||
arguments: &syn::AttributeArgs,
|
||||
) -> syn::Result<proc_macro2::TokenStream> {
|
||||
if let syn::Item::Fn(item_fn) = input {
|
||||
let err_path = argument::validate(arguments)?;
|
||||
argument::validate(arguments)?;
|
||||
let original_body = &item_fn.block;
|
||||
|
||||
let mut new_fn = item_fn.clone();
|
||||
new_fn.block = parse_quote! {
|
||||
{
|
||||
(|| -> ::std::result::Result<_, #err_path> {
|
||||
// Note: the `Result` here is a smell
|
||||
// because the macro is **assuming** a `Result` exists
|
||||
// that reflects the return value of the block
|
||||
// An improvement would include the error of the `original_block`
|
||||
// as an attribute to the macro itself.
|
||||
(|| -> Result<_> {
|
||||
#original_body
|
||||
})().map_err(::error_support::convert_log_report_error)
|
||||
}
|
||||
@ -92,7 +95,7 @@ fn impl_handle_error(
|
||||
} else {
|
||||
Err(syn::Error::new(
|
||||
input.span(),
|
||||
"#[handle_error(..)] can only be used on functions",
|
||||
"#[handle_error] can only be used on functions",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
2
third_party/rust/sync15/.cargo-checksum.json
vendored
2
third_party/rust/sync15/.cargo-checksum.json
vendored
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"1f11acaa90a112979205b4c7af9ba0c015afab5f3141dd082d58c862c84490e3","README.md":"6d4ff5b079ac5340d18fa127f583e7ad793c5a2328b8ecd12c3fc723939804f2","src/bso/content.rs":"d2d650f4932e9a7068a25dd7df0085b92cd8976a0635320e6ae306d5a425075c","src/bso/crypto.rs":"27602dcccb37d3a55620ee4e16b705da455d49af575de115c7c79c0178eb1d6d","src/bso/mod.rs":"09e723dc7e99295ecafdcadffaf604d66ea27cf2b7f1fd9ab3cac4f4698ff6a7","src/bso/test_utils.rs":"4ec5a2df5e1c0ec14dc770681e959bdcef6ef04f6fde435999197f46a8ae4831","src/client/coll_state.rs":"4301526b987532cd7ebd5d089980c9524aa29360e08fa0c1f5437696ed354822","src/client/coll_update.rs":"627e2266c5c8f1c5e0bc83061fa14c1287c7d17c78b47882543521f75543b499","src/client/collection_keys.rs":"c27b2277a3a52033b58ab01490fc2ea7007494195dd5e6dc2c6931a4ca96795a","src/client/mod.rs":"8f588d4a035cf79d96f2500f06d5651c1a7c566127c456ffa5429811ddce3fd6","src/client/request.rs":"8841524e37d8195867bdf6ba98c75f610cf47a4644adeebd6372cc6713f2260a","src/client/state.rs":"4e31193ef2471c1dfabf1c6a391bcb95e14ddb45855786a4194ff187d5c9347c","src/client/status.rs":"f445a8765dac9789444e23b5145148413407bb1d18a15ef56682243997f591bf","src/client/storage_client.rs":"8de72d4ba3ca4f68c8e1898466de83a2b543545a18679800cb4f7fbda2dc3183","src/client/sync.rs":"a04478c4e31bbf39f593decfc4844bfb7e678907031f0a93d1e005cf0047ebb4","src/client/sync_multiple.rs":"3729d4afd90ab1bd9982a3506252c99d8f37619cc1792ef4feba352ad01a7192","src/client/token.rs":"b268759d31e0fe17e0e2a428694cd9a317fcfbdd52f023d5d8c7cc6f00f1a102","src/client/util.rs":"71cc70ee41f821f53078675e636e9fad9c6046fa1a989e37f5487e340a2277d6","src/client_types.rs":"3c3cac1540b92482f43660d9e43bdde8481c4cc1a98253a68c80e791231f5976","src/clients_engine/engine.rs":"0eaa078978c95fc96284b48a7458ebff49f0aa70b1148ef019b9350b5ba4d0d4","src/clients_engine/mod.rs":"461729e6f89b66b2cbd89b041a03d4d6a8ba582284ed4f3015cb13e1a0c6da97","src/clients_engine/record.rs":"69357413571d688eea3a5207f9b88088cde285b9373c7bd4ea1e018dbc823dd2","src/clients_engine/ser.rs":"9796e44ed7daf04f22afbb51238ac25fd0de1438b72181351b4ca29fd70fd429","src/device_type.rs":"fe217453f19b374abcc10e9f503b25f4f712b555497bebe5aefcf2e9b258d28e","src/enc_payload.rs":"aa3eea7df49b24cd59831680a47c417b73a3e36e6b0f3f4baf14ca66bd68be6b","src/engine/bridged_engine.rs":"9c0d602b3553932e77a87caba9262d3a0fc146500c6d46f1770273be6636d064","src/engine/changeset.rs":"949c520e508da0158b2df9fa20235f942ad8096cebbfc942b0fae41c35830c6b","src/engine/mod.rs":"cb638c2170c3785785877dfd059f26fbbfeae5edc599745dd861e4c299d310ad","src/engine/request.rs":"5923025fb9550178339f880a1bf8526d8e853e7a0b2bce6d9d687cc808ac0085","src/engine/sync_engine.rs":"9a5c6993dcceec8f82ead97a6d1840c7ed7dc6b326f7234c77f18848b6baf836","src/error.rs":"a45cfe02e6301f473c34678b694943c1a04308b8c292c6e0448bf495194c3b5e","src/key_bundle.rs":"ff8b10b95add934ecbc434b37ed089805886828ed159fd38bd692d1f01d06f7f","src/lib.rs":"eca1fa801820238141c4badeeec45d430aaec8b2ce088446ef94456d51014889","src/record_types.rs":"02bb3d352fb808131d298f9b90d9c95b7e9e0138b97c5401f3b9fdacc5562f44","src/server_timestamp.rs":"0020f31971ccbfc485894cabc3087459d42252b86d7de07f2136997864b0373b","src/telemetry.rs":"35e0313a052f16326e451e3d6e371337c1d71a471f32234ad9649fc1fa9f2237"},"package":null}
|
||||
{"files":{"Cargo.toml":"1f11acaa90a112979205b4c7af9ba0c015afab5f3141dd082d58c862c84490e3","README.md":"6d4ff5b079ac5340d18fa127f583e7ad793c5a2328b8ecd12c3fc723939804f2","src/bso/content.rs":"d2d650f4932e9a7068a25dd7df0085b92cd8976a0635320e6ae306d5a425075c","src/bso/crypto.rs":"27602dcccb37d3a55620ee4e16b705da455d49af575de115c7c79c0178eb1d6d","src/bso/mod.rs":"09e723dc7e99295ecafdcadffaf604d66ea27cf2b7f1fd9ab3cac4f4698ff6a7","src/bso/test_utils.rs":"4ec5a2df5e1c0ec14dc770681e959bdcef6ef04f6fde435999197f46a8ae4831","src/client/coll_state.rs":"b0c47e44168ea2c7017cd8531f76bb230f9be66b119bb7416537b8693a1d0a0a","src/client/coll_update.rs":"cc12dfde0817eae68aa8e176497ed16e9e3307f72a33faa3fe329d7a3bfd1598","src/client/collection_keys.rs":"c27b2277a3a52033b58ab01490fc2ea7007494195dd5e6dc2c6931a4ca96795a","src/client/mod.rs":"9500b1d22a5064bbbd6a3d6bcc63fc4191e8ea4605ded359bc6c2dc2887626a3","src/client/request.rs":"8841524e37d8195867bdf6ba98c75f610cf47a4644adeebd6372cc6713f2260a","src/client/state.rs":"4e31193ef2471c1dfabf1c6a391bcb95e14ddb45855786a4194ff187d5c9347c","src/client/status.rs":"f445a8765dac9789444e23b5145148413407bb1d18a15ef56682243997f591bf","src/client/storage_client.rs":"3637b4522048353b06ad24031c150c66c13d9c27cef293e400db88807421633c","src/client/sync.rs":"ed7225c314df27793ed5de6da93cc4b75a98da1c14ac82e37a723a99821d4dc7","src/client/sync_multiple.rs":"3729d4afd90ab1bd9982a3506252c99d8f37619cc1792ef4feba352ad01a7192","src/client/token.rs":"b268759d31e0fe17e0e2a428694cd9a317fcfbdd52f023d5d8c7cc6f00f1a102","src/client/util.rs":"71cc70ee41f821f53078675e636e9fad9c6046fa1a989e37f5487e340a2277d6","src/client_types.rs":"3c3cac1540b92482f43660d9e43bdde8481c4cc1a98253a68c80e791231f5976","src/clients_engine/engine.rs":"b4a9c92f251b23e5a5452930e4472e7fea9ed12784a78836ce7337a94457ab86","src/clients_engine/mod.rs":"461729e6f89b66b2cbd89b041a03d4d6a8ba582284ed4f3015cb13e1a0c6da97","src/clients_engine/record.rs":"69357413571d688eea3a5207f9b88088cde285b9373c7bd4ea1e018dbc823dd2","src/clients_engine/ser.rs":"9796e44ed7daf04f22afbb51238ac25fd0de1438b72181351b4ca29fd70fd429","src/device_type.rs":"fe217453f19b374abcc10e9f503b25f4f712b555497bebe5aefcf2e9b258d28e","src/enc_payload.rs":"aa3eea7df49b24cd59831680a47c417b73a3e36e6b0f3f4baf14ca66bd68be6b","src/engine/bridged_engine.rs":"9c0d602b3553932e77a87caba9262d3a0fc146500c6d46f1770273be6636d064","src/engine/changeset.rs":"5e323aa07f0b18d22495a695b829326d18287ff75155b4818adf66b86e16ba00","src/engine/mod.rs":"f84a254642c1876fe56506703fb010a7866eb5d40af3fc238bf92b62a61cb6cc","src/engine/request.rs":"f40bac0b3f5286446a4056de885fd81e4fa77e4dc7d5bbb6aa644b93201046de","src/engine/sync_engine.rs":"5314d0163ccc93d78f5879d52cf2b60b9622e80722d84d3482cfa7c26df6bfdd","src/error.rs":"a45cfe02e6301f473c34678b694943c1a04308b8c292c6e0448bf495194c3b5e","src/key_bundle.rs":"ff8b10b95add934ecbc434b37ed089805886828ed159fd38bd692d1f01d06f7f","src/lib.rs":"25bec0ac0f8ed0e6a341f645f7f265c7e9a19332c13d05876f7332eccbd2a2de","src/record_types.rs":"02bb3d352fb808131d298f9b90d9c95b7e9e0138b97c5401f3b9fdacc5562f44","src/server_timestamp.rs":"0020f31971ccbfc485894cabc3087459d42252b86d7de07f2136997864b0373b","src/telemetry.rs":"35e0313a052f16326e451e3d6e371337c1d71a471f32234ad9649fc1fa9f2237"},"package":null}
|
51
third_party/rust/sync15/src/client/coll_state.rs
vendored
51
third_party/rust/sync15/src/client/coll_state.rs
vendored
@ -9,18 +9,17 @@ use crate::error;
|
||||
use crate::KeyBundle;
|
||||
use crate::ServerTimestamp;
|
||||
|
||||
/// Holds state for a collection necessary to perform a sync of it. Lives for the lifetime
|
||||
/// of a single sync.
|
||||
/// Holds state for a collection. In general, only the CollState is
|
||||
/// needed to sync a collection (but a valid GlobalState is needed to obtain
|
||||
/// a CollState)
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CollState {
|
||||
// Info about the server configuration/capabilities
|
||||
pub config: InfoConfiguration,
|
||||
// from meta/global, used for XIUS when we POST outgoing record based on this state.
|
||||
// initially from meta/global, updated after an xius POST/PUT.
|
||||
pub last_modified: ServerTimestamp,
|
||||
pub key: KeyBundle,
|
||||
}
|
||||
|
||||
/// This mini state-machine helps build a CollState
|
||||
#[derive(Debug)]
|
||||
pub enum LocalCollState {
|
||||
/// The state is unknown, with the EngineSyncAssociation the collection
|
||||
@ -39,7 +38,7 @@ pub enum LocalCollState {
|
||||
SyncIdChanged { ids: CollSyncIds },
|
||||
|
||||
/// The collection is ready to sync.
|
||||
Ready { coll_state: CollState },
|
||||
Ready { key: KeyBundle },
|
||||
}
|
||||
|
||||
pub struct LocalCollStateMachine<'state> {
|
||||
@ -72,27 +71,14 @@ impl<'state> LocalCollStateMachine<'state> {
|
||||
if ids.global == meta_global.sync_id
|
||||
&& ids.coll == engine_meta.sync_id =>
|
||||
{
|
||||
// We are done - build the CollState
|
||||
let coll_keys = CollectionKeys::from_encrypted_payload(
|
||||
self.global_state.keys.clone(),
|
||||
self.global_state.keys_timestamp,
|
||||
self.root_key,
|
||||
)?;
|
||||
let key = coll_keys.key_for_collection(name).clone();
|
||||
let name = engine.collection_name();
|
||||
let config = self.global_state.config.clone();
|
||||
let last_modified = self
|
||||
.global_state
|
||||
.collections
|
||||
.get(name.as_ref())
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
let coll_state = CollState {
|
||||
config,
|
||||
last_modified,
|
||||
key,
|
||||
};
|
||||
Ok(LocalCollState::Ready { coll_state })
|
||||
Ok(LocalCollState::Ready {
|
||||
key: coll_keys.key_for_collection(name).clone(),
|
||||
})
|
||||
}
|
||||
_ => Ok(LocalCollState::SyncIdChanged {
|
||||
ids: CollSyncIds {
|
||||
@ -134,8 +120,23 @@ impl<'state> LocalCollStateMachine<'state> {
|
||||
loop {
|
||||
log::trace!("LocalCollState in {:?}", s);
|
||||
match s {
|
||||
LocalCollState::Ready { coll_state } => return Ok(Some(coll_state)),
|
||||
LocalCollState::Ready { key } => {
|
||||
let name = engine.collection_name();
|
||||
let config = self.global_state.config.clone();
|
||||
let last_modified = self
|
||||
.global_state
|
||||
.collections
|
||||
.get(name.as_ref())
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
return Ok(Some(CollState {
|
||||
config,
|
||||
last_modified,
|
||||
key,
|
||||
}));
|
||||
}
|
||||
LocalCollState::Declined | LocalCollState::NoSuchCollection => return Ok(None),
|
||||
|
||||
_ => {
|
||||
count += 1;
|
||||
if count > 10 {
|
||||
@ -171,7 +172,7 @@ mod tests {
|
||||
use crate::engine::CollectionRequest;
|
||||
use crate::engine::{IncomingChangeset, OutgoingChangeset};
|
||||
use crate::record_types::{MetaGlobalEngine, MetaGlobalRecord};
|
||||
use crate::{telemetry, CollectionName};
|
||||
use crate::telemetry;
|
||||
use anyhow::Result;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::HashMap;
|
||||
@ -226,7 +227,7 @@ mod tests {
|
||||
}
|
||||
|
||||
impl SyncEngine for TestSyncEngine {
|
||||
fn collection_name(&self) -> CollectionName {
|
||||
fn collection_name(&self) -> std::borrow::Cow<'static, str> {
|
||||
self.collection_name.into()
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,9 @@ use super::{
|
||||
};
|
||||
use crate::bso::OutgoingEncryptedBso;
|
||||
use crate::engine::{CollectionRequest, IncomingChangeset, OutgoingChangeset};
|
||||
use crate::error::{self, Error, Result};
|
||||
use crate::{CollectionName, KeyBundle, ServerTimestamp};
|
||||
use crate::error::{self, Error, ErrorResponse, Result};
|
||||
use crate::{KeyBundle, ServerTimestamp};
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub fn encrypt_outgoing(
|
||||
o: OutgoingChangeset,
|
||||
@ -23,8 +24,8 @@ pub fn encrypt_outgoing(
|
||||
|
||||
pub fn fetch_incoming(
|
||||
client: &Sync15StorageClient,
|
||||
state: &CollState,
|
||||
collection_request: CollectionRequest,
|
||||
state: &mut CollState,
|
||||
collection_request: &CollectionRequest,
|
||||
) -> Result<IncomingChangeset> {
|
||||
let collection = collection_request.collection.clone();
|
||||
let (records, timestamp) = match client.get_encrypted_records(collection_request)? {
|
||||
@ -35,6 +36,8 @@ pub fn fetch_incoming(
|
||||
} => (record, last_modified),
|
||||
other => return Err(other.create_storage_error()),
|
||||
};
|
||||
// xxx - duplication below of `timestamp` smells wrong
|
||||
state.last_modified = timestamp;
|
||||
let mut result = IncomingChangeset::new(collection, timestamp);
|
||||
result.changes.reserve(records.len());
|
||||
for record in records {
|
||||
@ -51,7 +54,7 @@ pub fn fetch_incoming(
|
||||
pub struct CollectionUpdate<'a> {
|
||||
client: &'a Sync15StorageClient,
|
||||
state: &'a CollState,
|
||||
collection: CollectionName,
|
||||
collection: Cow<'static, str>,
|
||||
xius: ServerTimestamp,
|
||||
to_update: Vec<OutgoingEncryptedBso>,
|
||||
fully_atomic: bool,
|
||||
@ -61,7 +64,7 @@ impl<'a> CollectionUpdate<'a> {
|
||||
pub fn new(
|
||||
client: &'a Sync15StorageClient,
|
||||
state: &'a CollState,
|
||||
collection: CollectionName,
|
||||
collection: Cow<'static, str>,
|
||||
xius: ServerTimestamp,
|
||||
records: Vec<OutgoingEncryptedBso>,
|
||||
fully_atomic: bool,
|
||||
@ -83,12 +86,19 @@ impl<'a> CollectionUpdate<'a> {
|
||||
fully_atomic: bool,
|
||||
) -> Result<CollectionUpdate<'a>> {
|
||||
let collection = changeset.collection.clone();
|
||||
let xius = changeset.timestamp;
|
||||
if xius < state.last_modified {
|
||||
// We know we are going to fail the XIUS check...
|
||||
return Err(Error::StorageHttpError(ErrorResponse::PreconditionFailed {
|
||||
route: collection.into_owned(),
|
||||
}));
|
||||
}
|
||||
let to_update = encrypt_outgoing(changeset, &state.key)?;
|
||||
Ok(CollectionUpdate::new(
|
||||
client,
|
||||
state,
|
||||
collection,
|
||||
state.last_modified,
|
||||
xius,
|
||||
to_update,
|
||||
fully_atomic,
|
||||
))
|
||||
|
2
third_party/rust/sync15/src/client/mod.rs
vendored
2
third_party/rust/sync15/src/client/mod.rs
vendored
@ -25,7 +25,7 @@ mod sync_multiple;
|
||||
mod token;
|
||||
mod util;
|
||||
|
||||
pub(crate) use coll_state::{CollState, LocalCollStateMachine};
|
||||
pub(crate) use coll_state::CollState;
|
||||
pub(crate) use coll_update::{fetch_incoming, CollectionUpdate};
|
||||
pub(crate) use collection_keys::CollectionKeys;
|
||||
pub(crate) use request::InfoConfiguration;
|
||||
|
144
third_party/rust/sync15/src/client/storage_client.rs
vendored
144
third_party/rust/sync15/src/client/storage_client.rs
vendored
@ -7,10 +7,10 @@ use super::request::{
|
||||
};
|
||||
use super::token;
|
||||
use crate::bso::{IncomingBso, IncomingEncryptedBso, OutgoingBso, OutgoingEncryptedBso};
|
||||
use crate::engine::{CollectionPost, CollectionRequest};
|
||||
use crate::engine::CollectionRequest;
|
||||
use crate::error::{self, Error, ErrorResponse};
|
||||
use crate::record_types::MetaGlobalRecord;
|
||||
use crate::{CollectionName, Guid, ServerTimestamp};
|
||||
use crate::{Guid, ServerTimestamp};
|
||||
use serde_json::Value;
|
||||
use std::str::FromStr;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
@ -293,7 +293,7 @@ impl Sync15StorageClient {
|
||||
|
||||
pub fn get_encrypted_records(
|
||||
&self,
|
||||
collection_request: CollectionRequest,
|
||||
collection_request: &CollectionRequest,
|
||||
) -> error::Result<Sync15ClientResponse<Vec<IncomingEncryptedBso>>> {
|
||||
self.collection_request(Method::Get, collection_request)
|
||||
}
|
||||
@ -356,7 +356,7 @@ impl Sync15StorageClient {
|
||||
fn collection_request<T>(
|
||||
&self,
|
||||
method: Method,
|
||||
r: CollectionRequest,
|
||||
r: &CollectionRequest,
|
||||
) -> error::Result<Sync15ClientResponse<T>>
|
||||
where
|
||||
for<'a> T: serde::de::Deserialize<'a>,
|
||||
@ -367,12 +367,15 @@ impl Sync15StorageClient {
|
||||
|
||||
pub fn new_post_queue<'a, F: PostResponseHandler>(
|
||||
&'a self,
|
||||
coll: &'a CollectionName,
|
||||
coll: &str,
|
||||
config: &InfoConfiguration,
|
||||
ts: ServerTimestamp,
|
||||
on_response: F,
|
||||
) -> error::Result<PostQueue<PostWrapper<'a>, F>> {
|
||||
let pw = PostWrapper { client: self, coll };
|
||||
let pw = PostWrapper {
|
||||
client: self,
|
||||
coll: coll.into(),
|
||||
};
|
||||
Ok(PostQueue::new(config, ts, pw, on_response))
|
||||
}
|
||||
|
||||
@ -423,7 +426,7 @@ impl Sync15StorageClient {
|
||||
|
||||
pub struct PostWrapper<'a> {
|
||||
client: &'a Sync15StorageClient,
|
||||
coll: &'a CollectionName,
|
||||
coll: String,
|
||||
}
|
||||
|
||||
impl<'a> BatchPoster for PostWrapper<'a> {
|
||||
@ -435,10 +438,10 @@ impl<'a> BatchPoster for PostWrapper<'a> {
|
||||
commit: bool,
|
||||
_: &PostQueue<T, O>,
|
||||
) -> error::Result<PostResponse> {
|
||||
let r = CollectionPost::new(self.coll.clone())
|
||||
let r = CollectionRequest::new(self.coll.clone())
|
||||
.batch(batch)
|
||||
.commit(commit);
|
||||
let url = build_collection_post_url(Url::parse(&self.client.tsc.api_endpoint()?)?, r)?;
|
||||
let url = build_collection_request_url(Url::parse(&self.client.tsc.api_endpoint()?)?, &r)?;
|
||||
|
||||
let req = self
|
||||
.client
|
||||
@ -450,27 +453,19 @@ impl<'a> BatchPoster for PostWrapper<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_collection_url(mut base_url: Url, collection: CollectionName) -> error::Result<Url> {
|
||||
fn build_collection_request_url(mut base_url: Url, r: &CollectionRequest) -> error::Result<Url> {
|
||||
base_url
|
||||
.path_segments_mut()
|
||||
.map_err(|_| Error::UnacceptableUrl("Storage server URL is not a base".to_string()))?
|
||||
.extend(&["storage", &collection]);
|
||||
.extend(&["storage", &r.collection]);
|
||||
|
||||
// This is strange but just accessing query_pairs_mut makes you have
|
||||
// a trailing question mark on your url. I don't think anything bad
|
||||
// would happen here, but I don't know, and also, it looks dumb so
|
||||
// I'd rather not have it.
|
||||
if base_url.query() == Some("") {
|
||||
base_url.set_query(None);
|
||||
}
|
||||
Ok(base_url)
|
||||
}
|
||||
|
||||
fn build_collection_request_url(mut base_url: Url, r: CollectionRequest) -> error::Result<Url> {
|
||||
let mut pairs = base_url.query_pairs_mut();
|
||||
if r.full {
|
||||
pairs.append_pair("full", "1");
|
||||
}
|
||||
if r.limit > 0 {
|
||||
pairs.append_pair("limit", &r.limit.to_string());
|
||||
}
|
||||
if let Some(ids) = &r.ids {
|
||||
// Most ids are 12 characters, and we comma separate them, so 13.
|
||||
let mut buf = String::with_capacity(ids.len() * 13);
|
||||
@ -482,33 +477,32 @@ fn build_collection_request_url(mut base_url: Url, r: CollectionRequest) -> erro
|
||||
}
|
||||
pairs.append_pair("ids", &buf);
|
||||
}
|
||||
if let Some(ts) = r.older {
|
||||
pairs.append_pair("older", &ts.to_string());
|
||||
}
|
||||
if let Some(ts) = r.newer {
|
||||
pairs.append_pair("newer", &ts.to_string());
|
||||
}
|
||||
if let Some(l) = r.limit {
|
||||
pairs.append_pair("sort", l.order.as_str());
|
||||
pairs.append_pair("limit", &l.num.to_string());
|
||||
}
|
||||
pairs.finish();
|
||||
drop(pairs);
|
||||
build_collection_url(base_url, r.collection)
|
||||
}
|
||||
|
||||
#[cfg(feature = "sync-client")]
|
||||
fn build_collection_post_url(mut base_url: Url, r: CollectionPost) -> error::Result<Url> {
|
||||
let mut pairs = base_url.query_pairs_mut();
|
||||
if let Some(batch) = &r.batch {
|
||||
pairs.append_pair("batch", batch);
|
||||
}
|
||||
if r.commit {
|
||||
pairs.append_pair("commit", "true");
|
||||
}
|
||||
if let Some(ts) = r.older {
|
||||
pairs.append_pair("older", &ts.to_string());
|
||||
}
|
||||
if let Some(ts) = r.newer {
|
||||
pairs.append_pair("newer", &ts.to_string());
|
||||
}
|
||||
if let Some(o) = r.order {
|
||||
pairs.append_pair("sort", o.as_str());
|
||||
}
|
||||
pairs.finish();
|
||||
drop(pairs);
|
||||
build_collection_url(base_url, r.collection)
|
||||
|
||||
// This is strange but just accessing query_pairs_mut makes you have
|
||||
// a trailing question mark on your url. I don't think anything bad
|
||||
// would happen here, but I don't know, and also, it looks dumb so
|
||||
// I'd rather not have it.
|
||||
if base_url.query() == Some("") {
|
||||
base_url.set_query(None);
|
||||
}
|
||||
Ok(base_url)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -542,15 +536,34 @@ mod test {
|
||||
let base = Url::parse("https://example.com/sync").unwrap();
|
||||
|
||||
let empty =
|
||||
build_collection_request_url(base.clone(), CollectionRequest::new("foo".into()))
|
||||
.unwrap();
|
||||
build_collection_request_url(base.clone(), &CollectionRequest::new("foo")).unwrap();
|
||||
assert_eq!(empty.as_str(), "https://example.com/sync/storage/foo");
|
||||
let batch_start = build_collection_request_url(
|
||||
base.clone(),
|
||||
&CollectionRequest::new("bar")
|
||||
.batch(Some("true".into()))
|
||||
.commit(false),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
batch_start.as_str(),
|
||||
"https://example.com/sync/storage/bar?batch=true"
|
||||
);
|
||||
let batch_commit = build_collection_request_url(
|
||||
base.clone(),
|
||||
&CollectionRequest::new("asdf")
|
||||
.batch(Some("1234abc".into()))
|
||||
.commit(true),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
batch_commit.as_str(),
|
||||
"https://example.com/sync/storage/asdf?batch=1234abc&commit=true"
|
||||
);
|
||||
|
||||
let idreq = build_collection_request_url(
|
||||
base.clone(),
|
||||
CollectionRequest::new("wutang".into())
|
||||
.full()
|
||||
.ids(&["rza", "gza"]),
|
||||
&CollectionRequest::new("wutang").full().ids(&["rza", "gza"]),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
@ -560,46 +573,15 @@ mod test {
|
||||
|
||||
let complex = build_collection_request_url(
|
||||
base,
|
||||
CollectionRequest::new("specific".into())
|
||||
&CollectionRequest::new("specific")
|
||||
.full()
|
||||
.limit(10, RequestOrder::Oldest)
|
||||
.limit(10)
|
||||
.sort_by(RequestOrder::Oldest)
|
||||
.older_than(ServerTimestamp(9_876_540))
|
||||
.newer_than(ServerTimestamp(1_234_560)),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(complex.as_str(),
|
||||
"https://example.com/sync/storage/specific?full=1&older=9876.54&newer=1234.56&sort=oldest&limit=10");
|
||||
}
|
||||
|
||||
#[cfg(feature = "sync-client")]
|
||||
#[test]
|
||||
fn test_post_query_building() {
|
||||
let base = Url::parse("https://example.com/sync").unwrap();
|
||||
|
||||
let empty =
|
||||
build_collection_post_url(base.clone(), CollectionPost::new("foo".into())).unwrap();
|
||||
assert_eq!(empty.as_str(), "https://example.com/sync/storage/foo");
|
||||
let batch_start = build_collection_post_url(
|
||||
base.clone(),
|
||||
CollectionPost::new("bar".into())
|
||||
.batch(Some("true".into()))
|
||||
.commit(false),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
batch_start.as_str(),
|
||||
"https://example.com/sync/storage/bar?batch=true"
|
||||
);
|
||||
let batch_commit = build_collection_post_url(
|
||||
base,
|
||||
CollectionPost::new("asdf".into())
|
||||
.batch(Some("1234abc".into()))
|
||||
.commit(true),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
batch_commit.as_str(),
|
||||
"https://example.com/sync/storage/asdf?batch=1234abc&commit=true"
|
||||
);
|
||||
"https://example.com/sync/storage/specific?full=1&limit=10&older=9876.54&newer=1234.56&sort=oldest");
|
||||
}
|
||||
}
|
||||
|
41
third_party/rust/sync15/src/client/sync.rs
vendored
41
third_party/rust/sync15/src/client/sync.rs
vendored
@ -2,7 +2,10 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use super::{CollectionUpdate, GlobalState, LocalCollStateMachine, Sync15StorageClient};
|
||||
use super::coll_state::LocalCollStateMachine;
|
||||
use super::coll_update::CollectionUpdate;
|
||||
use super::state::GlobalState;
|
||||
use super::storage_client::Sync15StorageClient;
|
||||
use crate::clients_engine;
|
||||
use crate::engine::{IncomingChangeset, SyncEngine};
|
||||
use crate::error::Error;
|
||||
@ -25,17 +28,18 @@ pub fn synchronize_with_clients_engine(
|
||||
log::info!("Syncing collection {}", collection);
|
||||
|
||||
// our global state machine is ready - get the collection machine going.
|
||||
let coll_state = match LocalCollStateMachine::get_state(engine, global_state, root_sync_key)? {
|
||||
Some(coll_state) => coll_state,
|
||||
None => {
|
||||
// XXX - this is either "error" or "declined".
|
||||
log::warn!(
|
||||
"can't setup for the {} collection - hopefully it works later",
|
||||
collection
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let mut coll_state =
|
||||
match LocalCollStateMachine::get_state(engine, global_state, root_sync_key)? {
|
||||
Some(coll_state) => coll_state,
|
||||
None => {
|
||||
// XXX - this is either "error" or "declined".
|
||||
log::warn!(
|
||||
"can't setup for the {} collection - hopefully it works later",
|
||||
collection
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(clients) = clients {
|
||||
engine.prepare_for_sync(&|| clients.get_client_data())?;
|
||||
@ -55,7 +59,7 @@ pub fn synchronize_with_clients_engine(
|
||||
.map(|(idx, collection_request)| {
|
||||
interruptee.err_if_interrupted()?;
|
||||
let incoming_changes =
|
||||
super::fetch_incoming(client, &coll_state, collection_request)?;
|
||||
super::fetch_incoming(client, &mut coll_state, &collection_request)?;
|
||||
|
||||
log::info!(
|
||||
"Downloaded {} remote changes (request {} of {})",
|
||||
@ -68,18 +72,25 @@ pub fn synchronize_with_clients_engine(
|
||||
.collect::<Result<Vec<_>, Error>>()?
|
||||
};
|
||||
|
||||
let outgoing = engine.apply_incoming(incoming, telem_engine)?;
|
||||
let new_timestamp = incoming.last().expect("must have >= 1").timestamp;
|
||||
let mut outgoing = engine.apply_incoming(incoming, telem_engine)?;
|
||||
|
||||
interruptee.err_if_interrupted()?;
|
||||
// Bump the timestamps now just incase the upload fails.
|
||||
// xxx - duplication below smells wrong
|
||||
outgoing.timestamp = new_timestamp;
|
||||
coll_state.last_modified = new_timestamp;
|
||||
|
||||
log::info!("Uploading {} outgoing changes", outgoing.changes.len());
|
||||
let upload_info =
|
||||
CollectionUpdate::new_from_changeset(client, &coll_state, outgoing, fully_atomic)?
|
||||
.upload()?;
|
||||
|
||||
log::info!(
|
||||
"Upload success ({} records success, {} records failed)",
|
||||
upload_info.successful_ids.len(),
|
||||
upload_info.failed_ids.len()
|
||||
);
|
||||
|
||||
// ideally we'd report this per-batch, but for now, let's just report it
|
||||
// as a total.
|
||||
let mut telem_outgoing = telemetry::EngineOutgoing::new();
|
||||
|
@ -54,11 +54,13 @@ impl<'a> Driver<'a> {
|
||||
inbound: IncomingChangeset,
|
||||
should_refresh_client: bool,
|
||||
) -> Result<OutgoingChangeset> {
|
||||
let mut outgoing = OutgoingChangeset::new(COLLECTION_NAME, inbound.timestamp);
|
||||
outgoing.timestamp = inbound.timestamp;
|
||||
|
||||
self.interruptee.err_if_interrupted()?;
|
||||
let outgoing_commands = self.command_processor.fetch_outgoing_commands()?;
|
||||
|
||||
let mut has_own_client_record = false;
|
||||
let mut changes = Vec::new();
|
||||
|
||||
for bso in inbound.changes {
|
||||
self.interruptee.err_if_interrupted()?;
|
||||
@ -126,7 +128,9 @@ impl<'a> Driver<'a> {
|
||||
ttl: Some(CLIENTS_TTL),
|
||||
..Default::default()
|
||||
};
|
||||
changes.push(OutgoingBso::from_content(envelope, current_client_record)?);
|
||||
outgoing
|
||||
.changes
|
||||
.push(OutgoingBso::from_content(envelope, current_client_record)?);
|
||||
}
|
||||
} else {
|
||||
// Add the other client to our map of recently synced clients.
|
||||
@ -172,7 +176,9 @@ impl<'a> Driver<'a> {
|
||||
ttl: Some(CLIENTS_TTL),
|
||||
..Default::default()
|
||||
};
|
||||
changes.push(OutgoingBso::from_content(envelope, new_client)?);
|
||||
outgoing
|
||||
.changes
|
||||
.push(OutgoingBso::from_content(envelope, new_client)?);
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,10 +191,12 @@ impl<'a> Driver<'a> {
|
||||
ttl: Some(CLIENTS_TTL),
|
||||
..Default::default()
|
||||
};
|
||||
changes.push(OutgoingBso::from_content(envelope, current_client_record)?);
|
||||
outgoing
|
||||
.changes
|
||||
.push(OutgoingBso::from_content(envelope, current_client_record)?);
|
||||
}
|
||||
|
||||
Ok(OutgoingChangeset::new(COLLECTION_NAME.into(), changes))
|
||||
Ok(outgoing)
|
||||
}
|
||||
|
||||
/// Builds a fresh client record for this device.
|
||||
@ -283,7 +291,7 @@ impl<'a> Engine<'a> {
|
||||
global_state.keys_timestamp,
|
||||
root_sync_key,
|
||||
)?;
|
||||
let coll_state = CollState {
|
||||
let mut coll_state = CollState {
|
||||
config: global_state.config.clone(),
|
||||
last_modified: global_state
|
||||
.collections
|
||||
@ -293,7 +301,7 @@ impl<'a> Engine<'a> {
|
||||
key: coll_keys.key_for_collection(COLLECTION_NAME).clone(),
|
||||
};
|
||||
|
||||
let inbound = self.fetch_incoming(storage_client, &coll_state)?;
|
||||
let inbound = self.fetch_incoming(storage_client, &mut coll_state)?;
|
||||
|
||||
let mut driver = Driver::new(
|
||||
self.command_processor,
|
||||
@ -304,6 +312,8 @@ impl<'a> Engine<'a> {
|
||||
let outgoing = driver.sync(inbound, should_refresh_client)?;
|
||||
self.recent_clients = driver.recent_clients;
|
||||
|
||||
coll_state.last_modified = outgoing.timestamp;
|
||||
|
||||
self.interruptee.err_if_interrupted()?;
|
||||
let upload_info =
|
||||
CollectionUpdate::new_from_changeset(storage_client, &coll_state, outgoing, true)?
|
||||
@ -322,15 +332,15 @@ impl<'a> Engine<'a> {
|
||||
fn fetch_incoming(
|
||||
&self,
|
||||
storage_client: &Sync15StorageClient,
|
||||
coll_state: &CollState,
|
||||
coll_state: &mut CollState,
|
||||
) -> Result<IncomingChangeset> {
|
||||
// Note that, unlike other stores, we always fetch the full collection
|
||||
// on every sync, so `inbound` will return all clients, not just the
|
||||
// ones that changed since the last sync.
|
||||
let coll_request = CollectionRequest::new(COLLECTION_NAME.into()).full();
|
||||
let coll_request = CollectionRequest::new(COLLECTION_NAME).full();
|
||||
|
||||
self.interruptee.err_if_interrupted()?;
|
||||
let inbound = crate::client::fetch_incoming(storage_client, coll_state, coll_request)?;
|
||||
let inbound = crate::client::fetch_incoming(storage_client, coll_state, &coll_request)?;
|
||||
|
||||
Ok(inbound)
|
||||
}
|
||||
@ -550,7 +560,7 @@ mod tests {
|
||||
.into_iter()
|
||||
.map(|c| OutgoingBso::to_test_incoming(&c))
|
||||
.collect(),
|
||||
timestamp: ServerTimestamp::default(),
|
||||
timestamp: outgoing.timestamp,
|
||||
collection: outgoing.collection,
|
||||
};
|
||||
if let Value::Array(expected) = expected {
|
||||
@ -789,7 +799,7 @@ mod tests {
|
||||
.into_iter()
|
||||
.map(|c| OutgoingBso::to_test_incoming(&c))
|
||||
.collect(),
|
||||
timestamp: ServerTimestamp::default(),
|
||||
timestamp: outgoing.timestamp,
|
||||
collection: outgoing.collection,
|
||||
};
|
||||
for (incoming_cleartext, record) in zip(incoming.changes, expected) {
|
||||
|
52
third_party/rust/sync15/src/engine/changeset.rs
vendored
52
third_party/rust/sync15/src/engine/changeset.rs
vendored
@ -3,50 +3,40 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::bso::{IncomingBso, OutgoingBso};
|
||||
use crate::{CollectionName, ServerTimestamp};
|
||||
use crate::ServerTimestamp;
|
||||
|
||||
// Incoming and Outgoing changesets are almost identical except for the timestamp.
|
||||
// Separate types still helps avoid confusion with that timestamp, so they're split.
|
||||
#[derive(Debug)]
|
||||
pub struct IncomingChangeset {
|
||||
pub changes: Vec<IncomingBso>,
|
||||
/// The server timestamp of the collection.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RecordChangeset<T> {
|
||||
pub changes: Vec<T>,
|
||||
/// For GETs, the last sync timestamp that should be persisted after
|
||||
/// applying the records.
|
||||
/// For POSTs, this is the XIUS timestamp.
|
||||
pub timestamp: ServerTimestamp,
|
||||
pub collection: CollectionName,
|
||||
pub collection: std::borrow::Cow<'static, str>,
|
||||
}
|
||||
|
||||
impl IncomingChangeset {
|
||||
pub type IncomingChangeset = RecordChangeset<IncomingBso>;
|
||||
pub type OutgoingChangeset = RecordChangeset<OutgoingBso>;
|
||||
|
||||
impl<T> RecordChangeset<T> {
|
||||
#[inline]
|
||||
pub fn new(collection: CollectionName, timestamp: ServerTimestamp) -> Self {
|
||||
pub fn new(
|
||||
collection: impl Into<std::borrow::Cow<'static, str>>,
|
||||
timestamp: ServerTimestamp,
|
||||
) -> RecordChangeset<T> {
|
||||
Self::new_with_changes(collection, timestamp, Vec::new())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_with_changes(
|
||||
collection: CollectionName,
|
||||
collection: impl Into<std::borrow::Cow<'static, str>>,
|
||||
timestamp: ServerTimestamp,
|
||||
changes: Vec<IncomingBso>,
|
||||
) -> Self {
|
||||
Self {
|
||||
changes: Vec<T>,
|
||||
) -> RecordChangeset<T> {
|
||||
RecordChangeset {
|
||||
changes,
|
||||
timestamp,
|
||||
collection,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OutgoingChangeset {
|
||||
pub changes: Vec<OutgoingBso>,
|
||||
pub collection: CollectionName,
|
||||
}
|
||||
|
||||
impl OutgoingChangeset {
|
||||
#[inline]
|
||||
pub fn new(collection: CollectionName, changes: Vec<OutgoingBso>) -> Self {
|
||||
Self {
|
||||
collection,
|
||||
changes,
|
||||
collection: collection.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
third_party/rust/sync15/src/engine/mod.rs
vendored
2
third_party/rust/sync15/src/engine/mod.rs
vendored
@ -32,7 +32,5 @@ mod sync_engine;
|
||||
|
||||
pub use bridged_engine::{ApplyResults, BridgedEngine};
|
||||
pub use changeset::{IncomingChangeset, OutgoingChangeset};
|
||||
#[cfg(feature = "sync-client")]
|
||||
pub(crate) use request::CollectionPost;
|
||||
pub use request::{CollectionRequest, RequestOrder};
|
||||
pub use sync_engine::{CollSyncIds, EngineSyncAssociation, SyncEngine, SyncEngineId};
|
||||
|
68
third_party/rust/sync15/src/engine/request.rs
vendored
68
third_party/rust/sync15/src/engine/request.rs
vendored
@ -1,24 +1,37 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
use crate::{CollectionName, Guid, ServerTimestamp};
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
use crate::{Guid, ServerTimestamp};
|
||||
use std::borrow::Cow;
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct CollectionRequest {
|
||||
pub collection: CollectionName,
|
||||
pub collection: Cow<'static, str>,
|
||||
pub full: bool,
|
||||
pub ids: Option<Vec<Guid>>,
|
||||
|
||||
pub limit: Option<RequestLimit>,
|
||||
pub limit: usize,
|
||||
pub older: Option<ServerTimestamp>,
|
||||
pub newer: Option<ServerTimestamp>,
|
||||
pub order: Option<RequestOrder>,
|
||||
pub commit: bool,
|
||||
pub batch: Option<String>,
|
||||
}
|
||||
|
||||
impl CollectionRequest {
|
||||
#[inline]
|
||||
pub fn new(collection: CollectionName) -> CollectionRequest {
|
||||
pub fn new<S>(collection: S) -> CollectionRequest
|
||||
where
|
||||
S: Into<Cow<'static, str>>,
|
||||
{
|
||||
CollectionRequest {
|
||||
collection,
|
||||
..Default::default()
|
||||
collection: collection.into(),
|
||||
full: false,
|
||||
ids: None,
|
||||
limit: 0,
|
||||
older: None,
|
||||
newer: None,
|
||||
order: None,
|
||||
commit: false,
|
||||
batch: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,47 +64,30 @@ impl CollectionRequest {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn limit(mut self, num: usize, order: RequestOrder) -> CollectionRequest {
|
||||
self.limit = Some(RequestLimit { num, order });
|
||||
pub fn sort_by(mut self, order: RequestOrder) -> CollectionRequest {
|
||||
self.order = Some(order);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// This is just used interally - consumers just provide the content, not request params.
|
||||
#[cfg(feature = "sync-client")]
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct CollectionPost {
|
||||
pub collection: CollectionName,
|
||||
pub commit: bool,
|
||||
pub batch: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "sync-client")]
|
||||
impl CollectionPost {
|
||||
#[inline]
|
||||
pub fn new(collection: CollectionName) -> Self {
|
||||
Self {
|
||||
collection,
|
||||
..Default::default()
|
||||
}
|
||||
pub fn limit(mut self, num: usize) -> CollectionRequest {
|
||||
self.limit = num;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn batch(mut self, batch: Option<String>) -> Self {
|
||||
pub fn batch(mut self, batch: Option<String>) -> CollectionRequest {
|
||||
self.batch = batch;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn commit(mut self, v: bool) -> Self {
|
||||
pub fn commit(mut self, v: bool) -> CollectionRequest {
|
||||
self.commit = v;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// Asking for the order of records only makes sense if you are limiting them
|
||||
// in some way - consumers don't care about the order otherwise as everything
|
||||
// is processed as a set.
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub enum RequestOrder {
|
||||
Oldest,
|
||||
@ -115,11 +111,3 @@ impl std::fmt::Display for RequestOrder {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
// If you specify a numerical limit you must provide the order so backfilling
|
||||
// is possible (ie, so you know which ones you got!)
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct RequestLimit {
|
||||
pub(crate) num: usize,
|
||||
pub(crate) order: RequestOrder,
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
use super::{CollectionRequest, IncomingChangeset, OutgoingChangeset};
|
||||
use crate::client_types::ClientData;
|
||||
use crate::{telemetry, CollectionName, Guid, ServerTimestamp};
|
||||
use crate::{telemetry, Guid, ServerTimestamp};
|
||||
use anyhow::Result;
|
||||
use std::fmt;
|
||||
|
||||
@ -104,7 +104,7 @@ impl TryFrom<&str> for SyncEngineId {
|
||||
/// Different engines will produce errors of different types. To accommodate
|
||||
/// this, we force them all to return anyhow::Error.
|
||||
pub trait SyncEngine {
|
||||
fn collection_name(&self) -> CollectionName;
|
||||
fn collection_name(&self) -> std::borrow::Cow<'static, str>;
|
||||
|
||||
/// Prepares the engine for syncing. The tabs engine currently uses this to
|
||||
/// store the current list of clients, which it uses to look up device names
|
||||
@ -167,7 +167,7 @@ pub trait SyncEngine {
|
||||
records_synced: Vec<Guid>,
|
||||
) -> Result<()>;
|
||||
|
||||
/// The engine is responsible for building collection requests. Engines
|
||||
/// The engine is responsible for building the collection request. Engines
|
||||
/// typically will store a lastModified timestamp and use that to build a
|
||||
/// request saying "give me full records since that date" - however, other
|
||||
/// engines might do something fancier. This could even later be extended to
|
||||
|
5
third_party/rust/sync15/src/lib.rs
vendored
5
third_party/rust/sync15/src/lib.rs
vendored
@ -37,11 +37,6 @@ pub use key_bundle::KeyBundle;
|
||||
pub use server_timestamp::ServerTimestamp;
|
||||
pub use sync_guid::Guid;
|
||||
|
||||
// Collection names are almost always `static, so we use a `Cow`:
|
||||
// * Either a `String` or a `'static &str` can be `.into()`'d into one of these.
|
||||
// * Cloning one with a `'static &str` is extremely cheap and doesn't allocate memory.
|
||||
pub type CollectionName = std::borrow::Cow<'static, str>;
|
||||
|
||||
// For skip_serializing_if
|
||||
fn skip_if_default<T: PartialEq + Default>(v: &T) -> bool {
|
||||
*v == T::default()
|
||||
|
2
third_party/rust/tabs/.cargo-checksum.json
vendored
2
third_party/rust/tabs/.cargo-checksum.json
vendored
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"8ae43dd6969feea0eabc5c53d830960212e6cb1a18b43a00f47e8784c2fd0063","README.md":"c48b8f391ef822c4f3971b5f453a1e7b43bea232752d520460d2f04803aead1a","build.rs":"33e61b811b19ed2b58e319cc65d5988bed258d2c4fea2d706301184c59847a0f","src/error.rs":"ac3d450f0ba6a855c37fa2dd829004b22dce5ad4416ebec66a3d7d6212bdbcd7","src/lib.rs":"7208f78955e015ef8bab7916307e551cd3c1bd56d7fe14f8b53cd53bc4b38555","src/schema.rs":"2b7b51f3c2edc0ca603495c10b917603fd9ac791c4a366080e40d090b13b91f2","src/storage.rs":"eb9505477a926919769b09988ebbeeba96ceada634aec79b73fa75f79c038b03","src/store.rs":"ab0b6214b30b0f0fa7c6a89098ff3db1a8f76264f6711c4481c0be460afe522b","src/sync/bridge.rs":"705a24934c90494c2074288d03266504a866c4f04cb89c4e17b762cb498d621e","src/sync/engine.rs":"f2c5e4a2cb400ca33b649a078fc56e59a01a81a6e16e42b126e8b00d22b5eeea","src/sync/full_sync.rs":"47660644b3a66f3adff1130bb64e2ef40cb29749a40bc28d71246641d28ad080","src/sync/mod.rs":"81f98303b2a60aa6c6ed0d9777a95d6bbff46e57a494a0172d81c5819296802e","src/sync/record.rs":"896ebc6aa213bac9e6170c7e0b7dbee322f62e5f6c28462cb6da0bfe8ce938ba","src/tabs.udl":"a555fe11b5fa7ea9aefa7d7be31906a63b31cbc16b9b7f5ad952fd0e08ba5c61","uniffi.toml":"5156701368f0b5856e658143714a43058385c8ac53bee72d7a5a332b576dfb82"},"package":null}
|
||||
{"files":{"Cargo.toml":"8ae43dd6969feea0eabc5c53d830960212e6cb1a18b43a00f47e8784c2fd0063","README.md":"c48b8f391ef822c4f3971b5f453a1e7b43bea232752d520460d2f04803aead1a","build.rs":"33e61b811b19ed2b58e319cc65d5988bed258d2c4fea2d706301184c59847a0f","src/error.rs":"ac3d450f0ba6a855c37fa2dd829004b22dce5ad4416ebec66a3d7d6212bdbcd7","src/lib.rs":"7208f78955e015ef8bab7916307e551cd3c1bd56d7fe14f8b53cd53bc4b38555","src/schema.rs":"2b7b51f3c2edc0ca603495c10b917603fd9ac791c4a366080e40d090b13b91f2","src/storage.rs":"0a74e341d33b6734f6ef0130e2ba506ec313b5a5f8d6660c535ffc53520edabc","src/store.rs":"ab0b6214b30b0f0fa7c6a89098ff3db1a8f76264f6711c4481c0be460afe522b","src/sync/bridge.rs":"a444c97991cfa8e0dd92ba3b35c6864ddd0cfec1d17e5cc514b9c36ada8d46c3","src/sync/engine.rs":"bbee416c9d45b90b945016d26c2133639c1ad057c6f52fdbdfa5a4f4f631a378","src/sync/full_sync.rs":"514668bb76d1fe6de3a36e64e6984b8dbd391155685ea21cbf91f67a957babdd","src/sync/mod.rs":"81f98303b2a60aa6c6ed0d9777a95d6bbff46e57a494a0172d81c5819296802e","src/sync/record.rs":"896ebc6aa213bac9e6170c7e0b7dbee322f62e5f6c28462cb6da0bfe8ce938ba","src/tabs.udl":"a555fe11b5fa7ea9aefa7d7be31906a63b31cbc16b9b7f5ad952fd0e08ba5c61","uniffi.toml":"5156701368f0b5856e658143714a43058385c8ac53bee72d7a5a332b576dfb82"},"package":null}
|
142
third_party/rust/tabs/src/storage.rs
vendored
142
third_party/rust/tabs/src/storage.rs
vendored
@ -27,8 +27,6 @@ pub type RemoteTabRecord = RemoteTab;
|
||||
|
||||
pub(crate) const TABS_CLIENT_TTL: u32 = 15_552_000; // 180 days, same as CLIENTS_TTL
|
||||
const FAR_FUTURE: i64 = 4_102_405_200_000; // 2100/01/01
|
||||
const MAX_PAYLOAD_SIZE: usize = 512 * 1024; // Twice as big as desktop, still smaller than server max (2MB)
|
||||
const MAX_TITLE_CHAR_LENGTH: usize = 512; // We put an upper limit on title sizes for tabs to reduce memory
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct RemoteTab {
|
||||
@ -148,44 +146,30 @@ impl TabsStorage {
|
||||
self.local_tabs.borrow_mut().replace(local_state);
|
||||
}
|
||||
|
||||
// We try our best to fit as many tabs in a payload as possible, this includes
|
||||
// limiting the url history entries, title character count and finally drop enough tabs
|
||||
// until we have small enough payload that the server will accept
|
||||
pub fn prepare_local_tabs_for_upload(&self) -> Option<Vec<RemoteTab>> {
|
||||
if let Some(local_tabs) = self.local_tabs.borrow().as_ref() {
|
||||
let mut sanitized_tabs: Vec<RemoteTab> = local_tabs
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter_map(|mut tab| {
|
||||
if tab.url_history.is_empty() || !is_url_syncable(&tab.url_history[0]) {
|
||||
return None;
|
||||
}
|
||||
let mut sanitized_history = Vec::with_capacity(TAB_ENTRIES_LIMIT);
|
||||
for url in tab.url_history {
|
||||
if sanitized_history.len() == TAB_ENTRIES_LIMIT {
|
||||
break;
|
||||
return Some(
|
||||
local_tabs
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter_map(|mut tab| {
|
||||
if tab.url_history.is_empty() || !is_url_syncable(&tab.url_history[0]) {
|
||||
return None;
|
||||
}
|
||||
if is_url_syncable(&url) {
|
||||
sanitized_history.push(url);
|
||||
let mut sanitized_history = Vec::with_capacity(TAB_ENTRIES_LIMIT);
|
||||
for url in tab.url_history {
|
||||
if sanitized_history.len() == TAB_ENTRIES_LIMIT {
|
||||
break;
|
||||
}
|
||||
if is_url_syncable(&url) {
|
||||
sanitized_history.push(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tab.url_history = sanitized_history;
|
||||
// Truncate the title to some limit and append ellipsis
|
||||
// to incate that we've truncated
|
||||
if tab.title.len() > MAX_TITLE_CHAR_LENGTH {
|
||||
tab.title.truncate(MAX_TITLE_CHAR_LENGTH - 3);
|
||||
// Append ellipsis char for any client displaying the full title
|
||||
tab.title.push('\u{2026}');
|
||||
}
|
||||
Some(tab)
|
||||
})
|
||||
.collect();
|
||||
// Sort the tabs so when we trim tabs it's the oldest tabs
|
||||
sanitized_tabs.sort_by(|a, b| b.last_used.cmp(&a.last_used));
|
||||
// If trimming the tab length failed for some reason, just return the untrimmed tabs
|
||||
trim_tabs_length(&mut sanitized_tabs, MAX_PAYLOAD_SIZE);
|
||||
return Some(sanitized_tabs);
|
||||
tab.url_history = sanitized_history;
|
||||
Some(tab)
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
None
|
||||
}
|
||||
@ -346,11 +330,12 @@ impl TabsStorage {
|
||||
}
|
||||
|
||||
pub(crate) fn put_meta(&mut self, key: &str, value: &dyn ToSql) -> Result<()> {
|
||||
let db = self.open_or_create()?;
|
||||
db.execute_cached(
|
||||
"REPLACE INTO moz_meta (key, value) VALUES (:key, :value)",
|
||||
&[(":key", &key as &dyn ToSql), (":value", value)],
|
||||
)?;
|
||||
if let Some(db) = self.open_if_exists()? {
|
||||
db.execute_cached(
|
||||
"REPLACE INTO moz_meta (key, value) VALUES (:key, :value)",
|
||||
&[(":key", &key as &dyn ToSql), (":value", value)],
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -377,28 +362,6 @@ impl TabsStorage {
|
||||
}
|
||||
}
|
||||
|
||||
// Trim the amount of tabs in a list to fit the specified memory size
|
||||
fn trim_tabs_length(tabs: &mut Vec<RemoteTab>, payload_size_max_bytes: usize) {
|
||||
// Ported from https://searchfox.org/mozilla-central/rev/84fb1c4511312a0b9187f647d90059e3a6dd27f8/services/sync/modules/util.sys.mjs#422
|
||||
// See bug 535326 comment 8 for an explanation of the estimation
|
||||
let max_serialized_size = (payload_size_max_bytes / 4) * 3 - 1500;
|
||||
let size = compute_serialized_size(tabs);
|
||||
if size > max_serialized_size {
|
||||
// Estimate a little more than the direct fraction to maximize packing
|
||||
let cutoff = (tabs.len() * max_serialized_size) / size;
|
||||
tabs.truncate(cutoff);
|
||||
|
||||
// Keep dropping off the last entry until the data fits.
|
||||
while compute_serialized_size(tabs) > max_serialized_size {
|
||||
tabs.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_serialized_size(v: &Vec<RemoteTab>) -> usize {
|
||||
serde_json::to_string(v).unwrap_or_default().len()
|
||||
}
|
||||
|
||||
// Try to keep in sync with https://searchfox.org/mozilla-central/rev/2ad13433da20a0749e1e9a10ec0ab49b987c2c8e/modules/libpref/init/all.js#3927
|
||||
fn is_url_syncable(url: &str) -> bool {
|
||||
url.len() <= URI_LENGTH_MAX
|
||||
@ -442,15 +405,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_tabs_meta() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let db_name = dir.path().join("test_tabs_meta.db");
|
||||
let mut db = TabsStorage::new(db_name);
|
||||
let mut db = TabsStorage::new_with_mem_path("test");
|
||||
let test_key = "TEST KEY A";
|
||||
let test_value = "TEST VALUE A";
|
||||
let test_key2 = "TEST KEY B";
|
||||
let test_value2 = "TEST VALUE B";
|
||||
|
||||
// should automatically make the DB if one doesn't exist
|
||||
db.put_meta(test_key, &test_value).unwrap();
|
||||
db.put_meta(test_key2, &test_value2).unwrap();
|
||||
|
||||
@ -545,54 +505,6 @@ mod tests {
|
||||
])
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_trimming_tab_title() {
|
||||
let mut storage = TabsStorage::new_with_mem_path("test_prepare_local_tabs_for_upload");
|
||||
assert_eq!(storage.prepare_local_tabs_for_upload(), None);
|
||||
storage.update_local_state(vec![RemoteTab {
|
||||
title: "a".repeat(MAX_TITLE_CHAR_LENGTH + 10), // Fill a string more than max
|
||||
url_history: vec!["https://foo.bar".to_owned()],
|
||||
icon: None,
|
||||
last_used: 0,
|
||||
}]);
|
||||
let mut truncated_title = "a".repeat(MAX_TITLE_CHAR_LENGTH - 3);
|
||||
truncated_title.push('\u{2026}');
|
||||
assert_eq!(
|
||||
storage.prepare_local_tabs_for_upload(),
|
||||
Some(vec![
|
||||
// title trimmed to 50 characters
|
||||
RemoteTab {
|
||||
title: truncated_title, // title was trimmed to only max char length
|
||||
url_history: vec!["https://foo.bar".to_owned()],
|
||||
icon: None,
|
||||
last_used: 0,
|
||||
},
|
||||
])
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_trim_tabs_length() {
|
||||
let mut storage = TabsStorage::new_with_mem_path("test_prepare_local_tabs_for_upload");
|
||||
assert_eq!(storage.prepare_local_tabs_for_upload(), None);
|
||||
let mut too_many_tabs: Vec<RemoteTab> = Vec::new();
|
||||
for n in 1..5000 {
|
||||
too_many_tabs.push(RemoteTab {
|
||||
title: "aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa" //50 characters
|
||||
.to_owned(),
|
||||
url_history: vec![format!("https://foo{}.bar", n)],
|
||||
icon: None,
|
||||
last_used: 0,
|
||||
});
|
||||
}
|
||||
let tabs_mem_size = compute_serialized_size(&too_many_tabs);
|
||||
// ensure we are definitely over the payload limit
|
||||
assert!(tabs_mem_size > MAX_PAYLOAD_SIZE);
|
||||
// Add our over-the-limit tabs to the local state
|
||||
storage.update_local_state(too_many_tabs.clone());
|
||||
// prepare_local_tabs_for_upload did the trimming we needed to get under payload size
|
||||
let tabs_to_upload = &storage.prepare_local_tabs_for_upload().unwrap();
|
||||
assert!(compute_serialized_size(tabs_to_upload) <= MAX_PAYLOAD_SIZE);
|
||||
}
|
||||
// Helper struct to model what's stored in the DB
|
||||
struct TabsSQLRecord {
|
||||
guid: String,
|
||||
|
32
third_party/rust/tabs/src/sync/bridge.rs
vendored
32
third_party/rust/tabs/src/sync/bridge.rs
vendored
@ -4,7 +4,7 @@
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::error::{ApiResult, TabsApiError};
|
||||
use crate::error::{ApiResult, Result, TabsApiError};
|
||||
use crate::sync::engine::TabsSyncImpl;
|
||||
use crate::TabsStore;
|
||||
use error_support::handle_error;
|
||||
@ -47,7 +47,7 @@ impl BridgedEngineImpl {
|
||||
impl BridgedEngine for BridgedEngineImpl {
|
||||
type Error = TabsApiError;
|
||||
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn last_sync(&self) -> ApiResult<i64> {
|
||||
Ok(self
|
||||
.sync_impl
|
||||
@ -58,7 +58,7 @@ impl BridgedEngine for BridgedEngineImpl {
|
||||
.as_millis())
|
||||
}
|
||||
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn set_last_sync(&self, last_sync_millis: i64) -> ApiResult<()> {
|
||||
self.sync_impl
|
||||
.lock()
|
||||
@ -67,7 +67,7 @@ impl BridgedEngine for BridgedEngineImpl {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn sync_id(&self) -> ApiResult<Option<String>> {
|
||||
Ok(match self.sync_impl.lock().unwrap().get_sync_assoc()? {
|
||||
EngineSyncAssociation::Connected(id) => Some(id.coll.to_string()),
|
||||
@ -75,7 +75,7 @@ impl BridgedEngine for BridgedEngineImpl {
|
||||
})
|
||||
}
|
||||
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn reset_sync_id(&self) -> ApiResult<String> {
|
||||
let new_id = SyncGuid::random().to_string();
|
||||
let new_coll_ids = CollSyncIds {
|
||||
@ -89,7 +89,7 @@ impl BridgedEngine for BridgedEngineImpl {
|
||||
Ok(new_id)
|
||||
}
|
||||
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn ensure_current_sync_id(&self, sync_id: &str) -> ApiResult<String> {
|
||||
let mut sync_impl = self.sync_impl.lock().unwrap();
|
||||
let assoc = sync_impl.get_sync_assoc()?;
|
||||
@ -105,7 +105,7 @@ impl BridgedEngine for BridgedEngineImpl {
|
||||
Ok(sync_id.to_string()) // this is a bit odd, why the result?
|
||||
}
|
||||
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn prepare_for_sync(&self, client_data: &str) -> ApiResult<()> {
|
||||
let data: ClientData = serde_json::from_str(client_data)?;
|
||||
self.sync_impl.lock().unwrap().prepare_for_sync(data)
|
||||
@ -116,14 +116,14 @@ impl BridgedEngine for BridgedEngineImpl {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn store_incoming(&self, incoming: Vec<IncomingBso>) -> ApiResult<()> {
|
||||
// Store the incoming payload in memory so we can use it in apply
|
||||
*(self.incoming.lock().unwrap()) = incoming;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn apply(&self) -> ApiResult<ApplyResults> {
|
||||
let mut incoming = self.incoming.lock().unwrap();
|
||||
// We've a reference to a Vec<> but it's owned by the mutex - swap the mutex owned
|
||||
@ -141,7 +141,7 @@ impl BridgedEngine for BridgedEngineImpl {
|
||||
})
|
||||
}
|
||||
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn set_uploaded(&self, server_modified_millis: i64, ids: &[SyncGuid]) -> ApiResult<()> {
|
||||
self.sync_impl
|
||||
.lock()
|
||||
@ -149,13 +149,13 @@ impl BridgedEngine for BridgedEngineImpl {
|
||||
.sync_finished(ServerTimestamp::from_millis(server_modified_millis), ids)
|
||||
}
|
||||
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn sync_finished(&self) -> ApiResult<()> {
|
||||
*(self.incoming.lock().unwrap()) = Vec::default();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn reset(&self) -> ApiResult<()> {
|
||||
self.sync_impl
|
||||
.lock()
|
||||
@ -164,7 +164,7 @@ impl BridgedEngine for BridgedEngineImpl {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn wipe(&self) -> ApiResult<()> {
|
||||
self.sync_impl.lock().unwrap().wipe()?;
|
||||
Ok(())
|
||||
@ -210,7 +210,7 @@ impl TabsBridgedEngine {
|
||||
}
|
||||
|
||||
// Decode the JSON-encoded IncomingBso's that UniFFI passes to us
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn convert_incoming_bsos(&self, incoming: Vec<String>) -> ApiResult<Vec<IncomingBso>> {
|
||||
let mut bsos = Vec::with_capacity(incoming.len());
|
||||
for inc in incoming {
|
||||
@ -220,7 +220,7 @@ impl TabsBridgedEngine {
|
||||
}
|
||||
|
||||
// Encode OutgoingBso's into JSON for UniFFI
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
fn convert_outgoing_bsos(&self, outgoing: Vec<OutgoingBso>) -> ApiResult<Vec<String>> {
|
||||
let mut bsos = Vec::with_capacity(outgoing.len());
|
||||
for e in outgoing {
|
||||
@ -279,7 +279,7 @@ mod tests {
|
||||
title: "my first tab".to_string(),
|
||||
url_history: vec!["http://1.com".to_string()],
|
||||
icon: None,
|
||||
last_used: 2,
|
||||
last_used: 0,
|
||||
},
|
||||
RemoteTab {
|
||||
title: "my second tab".to_string(),
|
||||
|
10
third_party/rust/tabs/src/sync/engine.rs
vendored
10
third_party/rust/tabs/src/sync/engine.rs
vendored
@ -311,7 +311,11 @@ impl SyncEngine for TabsEngine {
|
||||
.unwrap()
|
||||
.apply_incoming(inbound.changes, telem)?;
|
||||
|
||||
Ok(OutgoingChangeset::new("tabs".into(), outgoing_records))
|
||||
Ok(OutgoingChangeset::new_with_changes(
|
||||
"tabs",
|
||||
inbound.timestamp,
|
||||
outgoing_records,
|
||||
))
|
||||
}
|
||||
|
||||
fn sync_finished(
|
||||
@ -339,9 +343,7 @@ impl SyncEngine for TabsEngine {
|
||||
Ok(if since == server_timestamp {
|
||||
vec![]
|
||||
} else {
|
||||
vec![CollectionRequest::new("tabs".into())
|
||||
.full()
|
||||
.newer_than(since)]
|
||||
vec![CollectionRequest::new("tabs").full().newer_than(since)]
|
||||
})
|
||||
}
|
||||
|
||||
|
6
third_party/rust/tabs/src/sync/full_sync.rs
vendored
6
third_party/rust/tabs/src/sync/full_sync.rs
vendored
@ -2,7 +2,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::{sync::engine::TabsSyncImpl, ApiResult, TabsEngine, TabsStore};
|
||||
use crate::{sync::engine::TabsSyncImpl, ApiResult, Result, TabsEngine, TabsStore};
|
||||
use error_support::handle_error;
|
||||
use interrupt_support::NeverInterrupts;
|
||||
use std::sync::Arc;
|
||||
@ -11,7 +11,7 @@ use sync15::engine::EngineSyncAssociation;
|
||||
use sync15::KeyBundle;
|
||||
|
||||
impl TabsStore {
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
pub fn reset(self: Arc<Self>) -> ApiResult<()> {
|
||||
let mut sync_impl = TabsSyncImpl::new(Arc::clone(&self));
|
||||
sync_impl.reset(&EngineSyncAssociation::Disconnected)?;
|
||||
@ -19,7 +19,7 @@ impl TabsStore {
|
||||
}
|
||||
|
||||
/// A convenience wrapper around sync_multiple.
|
||||
#[handle_error(crate::Error)]
|
||||
#[handle_error]
|
||||
pub fn sync(
|
||||
self: Arc<Self>,
|
||||
key_id: String,
|
||||
|
Loading…
x
Reference in New Issue
Block a user