This gives us performance wins in sevaral areas:
- Creating a structured clone blob of storage data directly from the source
compartment allows us to avoid X-ray and JSON serialization overhead when
storing new values.
- Storing the intermediate StructuredCloneBlob, rather than JSON values,
in-memory saves us additional JSON and structured clone overhead when
passing the values to listeners and API callers, and saves us a fair amount
of memory to boot.
- Serializing storage values before sending them over a message manager allows
us to deserialize them directly into an extension scope on the other side,
saving us a lot of additional structured clone overhead and intermediate
garbage generation.
- Using JSONFile.jsm for storage lets us consolidate multiple storage file
write operations, rather than performing a separate JSON serialization for
each individual storage write.
- Additionally, this paves the way for us to transition to IndexedDB as a
storage backend, with full support for arbitrary structured-clone-compatible
data structures.
MozReview-Commit-ID: JiRE7EFMYxn
--HG--
extra : rebase_source : caed13b099e7cb05de8d516761e32298a7a81ee5
extra : source : 42d3c1599af53b047d7ccd6b1c92ab08975284d7
This gives us performance wins in sevaral areas:
- Creating a structured clone blob of storage data directly from the source
compartment allows us to avoid X-ray and JSON serialization overhead when
storing new values.
- Storing the intermediate StructuredCloneBlob, rather than JSON values,
in-memory saves us additional JSON and structured clone overhead when
passing the values to listeners and API callers, and saves us a fair amount
of memory to boot.
- Serializing storage values before sending them over a message manager allows
us to deserialize them directly into an extension scope on the other side,
saving us a lot of additional structured clone overhead and intermediate
garbage generation.
- Using JSONFile.jsm for storage lets us consolidate multiple storage file
write operations, rather than performing a separate JSON serialization for
each individual storage write.
- Additionally, this paves the way for us to transition to IndexedDB as a
storage backend, with full support for arbitrary structured-clone-compatible
data structures.
MozReview-Commit-ID: JiRE7EFMYxn
--HG--
extra : rebase_source : 04a5681c604c5d2acd781b7ce4f66a757465071a
Also changed some function names to attempt to guarantee uniqueness across API files.
MozReview-Commit-ID: GnwWwTADF3a
--HG--
extra : rebase_source : 2d51f3de2958089de97ce98ed1f01c68ec0ed74a
Get rid of the ugly hack where test code monkeypatches a singleton to
convince the rest of the ExtensionStorageSync code that a fake user is
logged in. Instead, take a handle to the fxAccounts service at
construction time. Test code can provide any kind of fxAccounts it
wants, including one that has a hard-coded user.
This provokes a bunch of changes:
- ExtensionStorageSync is now no longer a singleton, but a class. You
have to instantiate it in order to do anything with it. A global
instance extensionStorageSync is provided for use by Sync code as
well as WebExtension code.
- CryptoCollection is now also a class, and each ExtensionStorageSync
instance has its own CryptoCollection. This dependency should maybe
also be injected, but for the time being it doesn't provide us any
value to do so.
- Converting singletons with asynchronous methods to classes is a pain
in the neck. We convert async method foo from `foo:
Task.async(....)` to `async foo() { .... }`. While we're here,
convert KeyRingEncryptionRemoteTransformer#decode to async/await to
eliminate a need for `let self = this`.
- Update Sync code and WebExtension code to use extensionStorageSync.
- There's a cyclic dependency where CryptoCollection#sync depends on
ExtensionStorageSync#_syncCollection which depends on
CryptoCollection#getKeyRing. As a short-term hack, we now require an
ExtensionStorageSync argument to CryptoCollection#sync.
- KeyRingEncryptionRemoteTransformer now takes a handle to fxAccounts
on construction time as well. Because this is the only
EncryptionRemoteTransformer subclass that accesses fxAccounts, we
can get rid of the hack where the tests monkeypatch something in the
EncryptionRemoteTransformer prototype.
- CollectionKeyEncryptionRemoteTransformer now takes a handle to a
CryptoCollection, rather than relying on a global one.
- A bunch of methods that previously assumed access to fxAccounts now
check if fxAccounts is present (i.e. if we're on Android). Strictly
speaking, this isn't required by this change, but it helps make
certain kinds of failure a little easier to diagnose.
- Update tests, including extracting a domain-specific helper method
to hide the use of CollectionKeyEncryptionRemoteTransformer. We now
no longer monkeypatch in our mock fxaService, but pass it to the
test so that it can do whatever it wants with it. We also provide an
ExtensionStorageSync instance for convenience. Access to the global
cryptoCollection is now done through an ExtensionStorageSync
instance.
To summarize, we've gone from a situation where a bunch of singletons
had implicit dependencies on other singletons in a shared global
namespace, to a situation where dependencies are provided explicitly
using method/constructor arguments. This highlights some of the
dependencies present:
- ExtensionStorageSync depends on CryptoCollection and fxAccounts if
it needs to sync
- Every collection created via openCollection needs a handle to
CryptoCollection so it can correctly create its remote transformers
- CryptoCollection needs a handle to fxAccounts so it can create its
own remote transformer for its special collection
Most of this is only possible, or at least much easier, because we no
longer try to juggle Sqlite connections but just keep one around
forever.
However, please note:
- CryptoCollection needs a handle to ExtensionStorageSync to actually
perform syncing logic because that's where we foolishly put the
logic to make requests
- There's still a backing Sqlite store which is shared by everything
- There's still a singleton tracking contexts that opened extensions
which we manage to try to clean contexts up correctly
MozReview-Commit-ID: DGIzyRTdYZ1
--HG--
extra : rebase_source : 305a98b8e1ece3ae7a5e8a2fdb5c58d8e7c496d9
CLOSED TREE
Backed out changeset 2d42350d209a (bug 1203330)
Backed out changeset 3a12c51c3eca (bug 1203330)
Backed out changeset 31fac390e15d (bug 1203330)
This protection is in ext-storage.js rather than
ExtensionStorageSync.jsm because storage.local may one day be migrated
to work using the same code as ExtensionStorageSync, but without any
syncing event loop. When this happens, we still want to raise but only
in the storage.sync case.
MozReview-Commit-ID: Jwu9FA5DZA6
--HG--
extra : rebase_source : fa749703bb9aeea214ea9c19fd42d9fdf9ed6efa
- Add `envType` to BaseContext.
- Pass an explicit envType to all `registerSchemaAPI` invocations.
- The factories passed to `registerSchemaAPI` will be split up later, so
that content scripts (`content_child`) and addon pages can share
common implementations.
- The factories that implement the addon API will also be split up,
to separate code running in the main process (`addon_parent`) from
code running in a child process (`addon_child`).
- Remove the use of a hardcoded list of `namespaces` from ProxyContext.
Now `envType` is used to specify whether an API should be activated.
MozReview-Commit-ID: Jiff8HIwG92
--HG--
extra : rebase_source : 946a3c0009a4e3223c2d10044b3099a94c845394
ExtensionContext in Extension.jsm has |extension| as an instance member,
so use it instead of passing |extension| to registerSchemaAPI's
callback.
And to make sure that this pattern also works in content processes, move
the |extension| member to BaseContext.
MozReview-Commit-ID: BgsGGCPQxJR
--HG--
extra : rebase_source : 7aa9fb7a53e057e8d3d8c477bd6821f8344c571a
ExtensionContext in Extension.jsm has |extension| as an instance member,
so use it instead of passing |extension| to registerSchemaAPI's
callback.
And to make sure that this pattern also works in content processes, move
the |extension| member to BaseContext.
MozReview-Commit-ID: BgsGGCPQxJR
--HG--
extra : rebase_source : 9a85d95f0c147198938b86c57127f6e7403fd53c
The base .eslintrc is essentially a merge of the root Toolkit .eslintrc and
the devtools .eslintrc, with some minor changes to match our prevalent style.
For the most enforces the coding styles that we've been using most
consistently. There are a couple of significant differences, though:
* The rule for opening brace alignment can only be applied globally, and
doesn't make exceptions for top-level functions. I chose to turn it on, and
change the brace style of existing top-level functions that violated it,
since the rule seemed worth using, and that's the direction most Toolkit JS
code has been headed anyway.
* The rule for switch/case statements requires an added indentation level for
case statements. Most of our switch statements did not use an extra level
of indentation, and I initially wrote the rule to enforce that style, until
I came across case statements that used blocks, and required the extra
indentation level for sanity.
--HG--
rename : devtools/.eslintrc => toolkit/components/extensions/.eslintrc
extra : commitid : 4aDZOi5MNPc
extra : rebase_source : f34ba43aeb8046a0c971cb76b76410497bd12b42
extra : source : 2a7eb4ef7b375e5fd52d843ca206a071367a6475