User:Anaaktgeboren/SearchEngineSync: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
No edit summary
 
(45 intermediate revisions by 2 users not shown)
Line 1: Line 1:
== State ==
* After a meeting of mobile product, desktop product, & engineering, this will be set aside for awhile. It is still desired as a feature by the end of the year.
== Goals ==
== Goals ==
** Sync search engine prefs on Desktop
* Sync search engine prefs on Desktop
** Format to be interoperable with firefox os, mobile firefox
** addition of an engine
** Nongoals:
** removal of an engine
*** implementation on firefox os
** reordering of engines
*** implementation on mobile firefox  
** keywords/aliases for a particular engine
** restore defaults (potentially not a special case for implementation, but could be considered a feature by users)
* Format to be interoperable with firefox os, mobile firefox, or other future clients


==  Requirements Gathering (deadline for input: july 26) ==
* Nongoals:
** implementation on firefox os
** implementation on mobile firefox
 
== Design ==
===  Requirements Gathering ===
* (deadline for input: july 26)
* Stakeholders
* Stakeholders
** Desktop: Gavin
** Desktop: Gavin
** Desktop UX: madhava, boriss, ibarlow on mobile, poked twice
** Desktop UX: madhava
** Mobile: bnicholson, mfinkle
** Mobile: bnicholson, mfinkle
** B@G: N/A, Ben Francis, b2g has no plugins and few preferences at this time
** B@G: N/A, Ben Francis, b2g has no plugins and few preferences at this time
Line 17: Line 27:
** Services Integration: Gps
** Services Integration: Gps
** Community: dev-planning, dev-apps-firefox lists
** Community: dev-planning, dev-apps-firefox lists
** Legal: bug 778823,  
** Legal: bug 778823, ok as long as based in user action & the defaults w/o user action don't change
 
* input  
* Current Requirements
** does not sync hijacked queries
*** origin: Asa, browser cannot currently detect this, requires a new browser feature
** syncs code & not a server call, mitigate risk
*** origin sstamm, reducing the addon sync threat
** search order preserved
** 3rd party plugins appear
 
==  Current Suggestions/Notes ==
* input
** want to avoid syncing app-shipped search plugins,  origin: gavin
** want to avoid syncing app-shipped search plugins,  origin: gavin
** dont sync XML files, sync the JSON cache that's the result of parse origin: gavin
** dont sync XML files, sync the JSON cache that's the result of parse origin: gavin
** "Search service changes will be required for this, almost certainly. Exposing the engine description as JSON and adding the ability to distinguish app-shipped plugins via the nsIBrowserSearchService API seem like good first steps to me"  - gavin
** "toolkit/components/search/nsSearchService.js. - gps
** See also the XML files in the 'searchplugins' directory of the app/profile" - gps
** mobile uses same nsISearchService as desktop -mfinkle
** mobile uses same nsISearchService as desktop -mfinkle
** should it be applicationID based, the way addons?
** should it be applicationID based, the way addons?
** should we limit to a blessed type of plugin to address hijacking?
** should we limit to a blessed type of plugin to address hijacking?
** what data represents a search plugin? and where are the keywords assoicated with it?
** impact of Australis?
 
=== Current Requirements ===
* does not sync hijacked queries
** origin: Asa, browser cannot currently detect this, requires a new browser feature
* don't require server call to install search engine (like add-on sync does). i.e. data self-contained
** origin sstamm, reducing the addon sync threat
* syncs keywords
* search order preserved
* 3rd party plugins appear
* honors enable/disable
** desktop does not match mobile
* does not assume matching default lists on different clients (which is to say, can't assume google et al are installed everywhere) and syncing of default engine code is likely
* syncs which engines support the search suggest api
 
=== Specifications ===
* Still missing a good reconciling algorithm for reordering
* mattn raises a good point that this does not handle recounciling duplicate aliases/keywords. It is currently handled locally on desktop. Should we try to regulate it, or force it to be a client responsibility?
* NB: thinking forward to resilient sync, canonical servers, and client engines that aren't us
==== Terms ====
* default plugin, default engine, app shipped plugin. a plugin that is shipped with the firefox build
* custom plugin, custom engine aka user added plugin. plugin added (presumably) by user action
* alias, keyword. user created string that is a shortcut to using a search engine
==== Generic Specification ====
* The goal of sync is the same experience everywhere. There exists one global ordering of search plugins. It may contain disabled, hidden, and platform-specific plugins, which may cause the visible order to be different on different clients.
** For example, a desktop only plugin will not show up on a mobile client.
 
* The currently selected engine will not be sync'ed. This is regarded as local to the client.
** NB: This is also believed to address some of the concern about hijacking.
 
* Sync's record may be more data rich/expressive than a particular client's internal representation. Client implementations may choose to disregard pieces of information in the record, but they may not destroy it.
** For example, fennec does not use keywords, but desktop does. syncing fennec should not destroy keywords associated with an engine on desktop.
 
* A plugin may be designated for one or more platforms. (Note, this field can be empty, implying it is suitable for use on all clients). If there is a platform designation, clients not in that list must ignore the plugin. They are not install it, alter it, or upload it.
 
* Default records of one client implementation cannot be deleted by other clients.
** For example, mobile cannot delete the desktop google plugin.
** Mobile's 'restore defaults' cannot destroy the desktop defaults and vice versa.
 
* Removal of custom plugins results in deletions on disk & propagates to other clients. "Removal" of defaults however, results in setting the hidden flag and propagating that change.


== Design & Design Review ==
* Hidden & disabled are similar but different concepts. No client should treat them interchangeably, as it will result in inconsistent behavior on other clients. Disabled plugins should appear in UI and not be active. Hidden plugins should not show up in UI and be inactive.
* Data Model, core of sync
 
** ordering of entries
* Clients must honor a distinction between global disabling and local disabling. Clients may choose (at the direction or needs of their ux) to enable/disable specific plugins valid for their platforms locally. These local decisions should not be propagated via sync.
** carrying code non-defaulted plugins
** Fennec will default to locally disable yahoo, bing, and amazon in their ux, but they should not be disabled on desktop after a mobile client has been synced.
* Desktop design
** If a user disables google on mobile, that should be propagated. It is the responsibility of the mobile client in that case to distinguish between the source of the disabling.
** Major dependencies
** Product page can be made at this point
* Reviews? privacy security
* UI changes?


==  Implementation ==
* No special rules for handling keyword addition/removal/change. latest change wins
** not started


== Release ==
* First Sync Behavior. May need special rules for first connecting to the constellation.
** targeted to land on Nightly during Q3 (not a promise, subject to scope change)


==  Reference ==
* Reconciling Rules: TBA. currently toying with inserting into list after all hidden & !yourplatform, but before disabled if present at your index.
* this implementation bug: 444284
* addon sync implemetnation bug: 534956
* https://developer.mozilla.org/en/Adding_search_engines_from_web_pages
* http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_description_document
* https://developer.mozilla.org/en/Creating_OpenSearch_plugins_for_Firefox
* http://docs.services.mozilla.com/sync/index.html


== Draft Plan ==
==== Additional Specification for Desktop Firefox ====
* currently full of holes
=== Spec ===
* The OpenSearch plugins, ordering of search engines, keywords for search engines (both custom & default), and hidden flags (default engines only afaik) will be sync'ed across platforms (between mobile & desktop)
** default engine OpenSearch objects will not be sync'ed, as these are hardcoded and already present on the machines. However their entries in the search db will synced as this contains the user generated ordering & keywords.
** on the fence about whether to sync Sherlock objects in 1.0, or iterate on that later if anyone screams
** on the fence about whether to sync extension shipped plugins, especially given Asa's concern about hijacking & the avg funny business, though searchservice will consider an extension shipped plugin as a default in _isDefault()
** the currently selected engine will not be synced, as that is a local setting and probably does not make sense to sync
** read-only engines cannot be serialized, and therefore probably should not be sync'ed (I believe this is just the default ones)
* When a user changes or removes a keyword or custom engine, the removal will be synced
* When a user removes a default engine, the removal will be synced (but note that the browser does not actually remove those, they are just hidden)
* The results of "Restore Defaults" will be synced (restores all deleted defaults, wipes db to default single entry (ketwords, ordering). This will not be treated as a special operation by sync
* Until the browser implements detecting hijacked searches, this engine will be preffed off by default for existing and new users
* Until the browser implements detecting hijacked searches, this engine will be preffed off by default for existing and new users
* Reconciliation: Merge by Default
* Default plugins need to be synced. They are expected to user accessible on mobile, other clients.
** When users choose model from settings, overrides this default?
* Engines that cannot be serialized probably should not be synced.
* The custom search plugins will be synced as json
* Desktop should implement enable/disable to comply with above spec
* Data Model
 
** each client will provide one record containing
==== Additional Specifications for Firefox Mobile ====
** CustomSearch array containing the json blobs of all custom search engines
* when synced to mobile, default engines that are not default on mobile (there are 4 to desktop's 7+) will be disabled (visible but greyed out). Users will have the option to enable those for their system.
** areHidden array containing names of all the default engines that are currently hidden
** this enable/disable for default-on-other-client-but-not-this one is local.
** SearchRows array containing all the rows of search db [engineid, name, value]
** implies that keywords wont work for disabled engines
*** note that value may be an intger or a string and that engineid is not unique. there may be several columns with hte same engineid
* custom plugins must start enabled by default (until user action disables them)
* mobile does not support keywords at this time, but will in the future
* mobile does not support context search for all plugins, but should in the future
 
=== proposed data model for a plugin record v3 ===
*  name, description, searchForm, iconurl, urls (very fat object on default engines), url values can be derived from openSearchRefObj
** search suggest api/support should be covered by guts of openSearchRefObj when it becomes relevant
* data not being synced
** directory - machine specific
** lastModifiedTime - machine & directory specific. used to invalidate cache
** filepath - path to the xml, which wont exist since we arent syncing the xml and would be specific to a machine (where fx is installed, where profile is installed, etc)
* data model
<div style="background-color: #F0F0F0"><pre>
{
  id // string id of the plugin usually looks like [app]google.xml
  guid // used for sync reconciliation
  openSearchRefObj //the whole of the OpenSearch xml object json-ifed. Clients may pick & choose which bits of data they will use/store in their representation. The sync store however, will hold onto this, to prevent differing internal representations from causing data loss on other platforms. It also ensures sync can in the future gracefully support any future features that are covered by the OpenSearch spec but not by the current internal representations.
  age //age in unix time of the ref object (so if the ref object changes, we know which one to keep)
  order // place in the global order (beware, even hidden engines have order)
  aliases // may be [], array of search keywords associated with this plugin
  isHidden // true if this engine should be globally disabled. Note some clients may treat some engines as 'removed' when they are actually disabled. (like desktop never actually removes the defaults even though the ui says it does)
  applicationIds // array of ids that this plugin should be installed on. [] if all platforms. (some plugins should not be installed on mobile, like desktop's google plugin, but others like twitter, are suitable for all platforms. Also leaves room for us to indicate a plugin meant for a subset, like mobile platforms {fennec, firefoxOS} and not desktop)
  locale //the locale of the plugin. Currently all plugins will have the same locale
  installLocation // optional. if not present, this plugin is default [app] on desktop
  type //optional, used to differentiate origins of plugins on desktop
  queryCharset // defaults on desktop do not have this, may be null
  isReadOnly //may be null
  isDefault //indicates that this is a default, needed for 'restore defaults'
}
</pre></div>
 
=== Design Reviews if needed ===
* privacy security?
* UI changes?
 
==  Implementation ==
* not started
* desktop will need code changes to address missing enable/disable state for custom search engines
* desktop will need nsSearchService changes to handle a consolidated data format
 


=== Implementation schedule ===
=== Implementation schedule ===
Line 95: Line 147:
* Implement engine + xpc tests by 7-sep
* Implement engine + xpc tests by 7-sep
** most likely to get snagged here
** most likely to get snagged here
* Implement tps tests (if possible) and any remaining xpc tests by sep-14
* Implement tps tests (if possible, see dependencies) and any remaining xpc tests by sep-14
* Debugging (unknown)
* Debugging (unknown)
** 'cause there's going to a landmine somewhere
** 'cause there's going to a landmine somewhere
=== Dependencies ===
* Solving the hijacking problem. Serious concern over syncing crapware
* TPS supporting desktop to mobile operations (jgriffin's team)
**TPS new data tupe addition (jgriffin's team)
* Desktop client supporting hijacked search detection (gavin?)
** so engine can be enabled by default for new or existing users
* Someone implementing the corresponding mobile engine (?)
* repositories rewrite (gps)


=== Test Plan ===
=== Test Plan ===
Line 104: Line 165:
** tps does not support the native mobile at this time. timeframe unknown for support
** tps does not support the native mobile at this time. timeframe unknown for support
** dependency - adding a new engine will require work on tps. timeframe unknown, but likely to be reasonable
** dependency - adding a new engine will require work on tps. timeframe unknown, but likely to be reasonable
*** tests cannot be written ahead of those changes to tps though
*** tests cannot really be written ahead of those changes to tps  
* Tests
* Tests
** only  reordering syncs between profile 1 & profile 2
** only  reordering syncs between profile 1 & profile 2
Line 116: Line 177:
* impacted by repositories re-write?
* impacted by repositories re-write?


== Dependencies ==
== Release ==
* TPS supporting desktop to mobile operations (jgriffen?)
** targeted to land on Nightly during Q3 (not a promise, subject to scope change)  
**iirc, engine additions require changes to tps each time
* Desktop client supporting hijacked search detection (gavin?)
* Someone implementing the corresponding mobile engine (?)
* repositories rewrite (gps)
* Do we know how many custom search engines the average user has? (asa?)
* What happens when one of the default engines are removed? I do not see it reflected in the db nor json


== Scratch and Notes ==
== Reference ==
* this implementation bug: {{bug|444284}}
* addon sync implemetnation {{bug|534956}}
* https://developer.mozilla.org/en/Adding_search_engines_from_web_pages
* http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_description_document
* https://developer.mozilla.org/en/Creating_OpenSearch_plugins_for_Firefox
* http://docs.services.mozilla.com/sync/index.html


* Insights
** user created keywords are called 'alias'es in code, stored in search-metadata.json
** /profile/search.json
*** "directories" will have two entries, the default one ("/Applications/Firefox.app/Contents/MacOS/searchplugins") & "/Users/mozilla/Documents/inbox-desktop/test_profiles/searchplugins" in my case) The first has no usefully syncable data, though it does have a lastModifiedTime (this is the lastModifiedTime of the directory, used for cache invalidation --Gavin)
** /profile/search.sqlite(DO NOT SYNC) (this is no longer used after bug 699856, replaced by search-metadata.json --Gavin)
*** engineid column identifies engine xml file, and notably where it came fromt[app] or [profile]
**** which would map to the directories list in the search.json?
*** value column identifies order of appearance in dropdown or is a string if a keyword has been added for that engine
*** name column is either "order" or "used"
*** the same 'logical' entry may have more than one entry in the db with subtly different values
** pref browser.search.selectedEngine represents the currently selected entry, status "user set" is useful
** pref browser.search.useDBForOrder i bet that represents ordering (this gets set to true once the user has customized the search engine order, to indicate that we should use the positioning information in search-metadata.json rather than the one in default prefs (browser.search.order.*) --Gavin)
** pref browser.search.order.1-3 are hard coded defaults. do not sync
** JAR loading code is for mobile, for their default plugin handling


* Poking Pointers
== Scratch and Notes ==
** changes frequently dont show up immediate (but get written on close)
=== Insights ===
** getting a 3rd party search thingy
* reconciling lists remain hard!
*** right click on a website search bar (ie youtube) and /profile/searchplugins will be created with an OpenSearch .xml
* what should happen when default lists dont match
*** searchplugins doesn't exist until you create a non-default one
** defaults should be synced because they may not be present on other systems and users can expect to see them (though the mobile client may grey them out)
** SQLite table: install addon, go to tools -> SQLiteManager -> select db, go
* user created keywords are called 'alias'es in code, stored in search-metadata.json
** default engines have a hidden value, which afaic, is never applied to custom engines?
* search-metadata.json
** may not exist if nothing has been changed
** contains per plugin: order placement, hidden, and keywords
* /profile/search.json
** "directories" will have two entries, the default one ("/Applications/Firefox.app/Contents/MacOS/searchplugins") & "/Users/mozilla/Documents/inbox-desktop/test_profiles/searchplugins" in my case) The first has no usefully syncable data, though it does have a lastModifiedTime (this is the lastModifiedTime of the directory, used for cache invalidation --Gavin)
* JAR loading code is for mobile, for their default plugin handling
* Australis is not making the search engines or their data go away
* "Search service changes will be required for this, almost certainly. Exposing the engine description as JSON and adding the ability to distinguish app-shipped plugins via the nsIBrowserSearchService API seem like good first steps to me"  - gavin
** Mobile will support search keywords & search suggest in the nearish future.
* /profile/search.sqlite(DO NOT SYNC) (this is no longer used after bug 699856, replaced by search-metadata.json --Gavin)
* pref browser.search.selectedEngine represents the currently selected entry, status "user set" is useful
* pref browser.search.useDBForOrder i bet that represents ordering (this gets set to true once the user has customized the search engine order, to indicate that we should use the positioning information in search-metadata.json rather than the one in default prefs (browser.search.order.*) --Gavin)
* pref browser.search.order.1-3 are hard coded defaults. do not sync


* current problems
=== current problems ===
** how do i gracefully slurp the json content?
* make sure search suggest is covered!
** can i dump the json content back into the data store *without* the xml?
* search suggest has global preferences associated with it. to sync or not to sync?
** design pondering
** and if so, should it go in the preferences engine, or in this one? I'm inclined to think it matters even if engines are not synced
*** Should this be like tabs and a one-record /client
*** or breakdown the table's multiple entry, grab the json and make it one record per 3rd party (but what about ordering of defaults?)
*** treat the table & the json as entirely separate things, essentially two record types? tis not really the sync way and I do not even know if it is feasible
*** do i extract the values of the json blob and rebuild it on the client, or send the thing over the wire wholesale?


* What do these data formats look like anyway?
=== What do these data formats look like anyway? ===
** search-metadata.json. reordering + keywords. Note this file can be empty
* search-metadata.json. reordering + keywords. Note this file can be empty
<div style="background-color: #F0F0F0"><pre>
<div style="background-color: #F0F0F0"><pre>
{
{
Line 201: Line 256:
}
}
</pre></div>
</pre></div>
** search.json, one default plugin, one custom (youtube) plugin
* search.json, one default plugin, one custom (youtube) plugin
<div style="background-color: #F0F0F0"><pre>
<div style="background-color: #F0F0F0"><pre>
{
{
Line 282: Line 337:
     }
     }
}
}
</pre></div>
* profile/searchplugins/  .xml
<div style="background-color: #F0F0F0"><pre>
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/" xmlns:os="http://a9.com/-/spec/opensearch/1.1/">
<os:ShortName>YouTube Video Search</os:ShortName>
<os:Description>Search for videos on YouTube</os:Description>
<os:InputEncoding>UTF-8</os:InputEncoding>
<os:Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAABMLAAATCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgNkQkIDZGiCA2RzAgNkcwIDZH/CA2R/wgNkf8IDZH/CA2R/wgNkf8IDZH/CA2R2AgNkcwIDZHMCA2RhAgNkQYIDpWHCA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpWHCQ6ZzAkOmf8JDpn/CQ6Z/wkOmf8JDpb/BQhc/wgMgf8JDpn/CQ6Z/wkOmf8JDpn/CQ6Z/wkOmf8JDpn/CQ6ZzAkOnuoJDp7/CQ6e/wkOnv8JDp7/Exed/8jIy/9RU4j/Bwp0/wkOm/8JDp7/CQ6e/wkOnv8JDp7/CQ6e/wkOnuoJD6T8CQ+k/wkPpP8JD6T/CQ+k/xUbo//V1dX/1dXV/4yNrP8QFG//CA6Y/wkPpP8JD6T/CQ+k/wkPpP8JD6T8CQ+q/wkPqv8JD6r/CQ+q/wkPqv8WG6n/3d3d/93d3f/d3d3/v7/M/y0wjv8JD6r/CQ+q/wkPqv8JD6r/CQ+q/woQr/8KEK//ChCv/woQr/8KEK//Fx2v/+fn5//n5+f/5+fn/+jo6P+YmtP/ChCv/woQr/8KEK//ChCv/woQr/8KELX8ChC1/woQtf8KELX/ChC1/xgdtf/x8fH/8fHx//Ly8v+bndv/Ehi3/woQtf8KELX/ChC1/woQtf8KELX8ChG76goRu/8KEbv/ChG7/woRu/8YH77/+fn5/+/v9/9fY9H/ChG7/woRu/8KEbv/ChG7/woRu/8KEbv/ChG76goRwMwKEcD/ChHA/woRwP8KEcD/EBfB/6Ol5/8tM8n/ChHA/woRwP8KEcD/ChHA/woRwP8KEcD/ChHA/woRwMwLEcSHCxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcSHCxLICQsSyKULEsjMCxLI+QsSyP8LEsj/CxLI/wsSyP8LEsj/CxLI/wsSyP8LEsj/CxLI0gsSyMwLEsiiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAD//wAA//8AAA==</os:Image>
<os:Url type="text/html" method="GET" template="http://www.youtube.com/results?search_query={searchTerms}&amp;page={startPage?}&amp;utm_source=opensearch">
</os:Url>
</SearchPlugin>
</pre></div>
</pre></div>
* google search xml
<div style="background-color: #F0F0F0"><pre>
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
<ShortName>Google</ShortName>
<Description>Google Search</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16">data:image/png;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA</Image>
<Url type="application/x-suggestions+json" method="GET" template="https://www.google.com/complete/search?client=firefox&amp;q={searchTerms}"/>
<Url type="text/html" method="GET" template="https://www.google.com/search">
  <Param name="q" value="{searchTerms}"/><Param name="ie" value="utf-8"/><Param name="oe" value="utf-8"/><Param name="aq" value="t"/><Param name="rls" value="{moz:distributionID}:{moz:locale}:{moz:official}"/>
  <MozParam name="client" condition="defaultEngine" trueValue="firefox-a" falseValue="firefox"/>
</Url>
<!-- Keyword search URL is the same as the default, but with an additional parameter -->
<Url type="application/x-moz-keywordsearch" method="GET" template="https://www.google.com/search">
  <Param name="q" value="{searchTerms}"/><Param name="ie" value="utf-8"/><Param name="oe" value="utf-8"/><Param name="aq" value="t"/><Param name="rls" value="{moz:distributionID}:{moz:locale}:{moz:official}"/>
  <MozParam name="client" condition="defaultEngine" trueValue="firefox-a" falseValue="firefox"/>
  <Param name="channel" value="fflb"/>
</Url>
<!-- Context/Right-click search URL is the same as the default, but with an additional parameter -->
<Url type="application/x-moz-contextsearch" method="GET" template="https://www.google.com/search">
  <Param name="q" value="{searchTerms}"/><Param name="ie" value="utf-8"/><Param name="oe" value="utf-8"/><Param name="aq" value="t"/><Param name="rls" value="{moz:distributionID}:{moz:locale}:{moz:official}"/>
  <MozParam name="client" condition="defaultEngine" trueValue="firefox-a" falseValue="firefox"/>
  <Param name="channel" value="rcs"/>
</Url>
<SearchForm>https://www.google.com/</SearchForm>
</SearchPlugin>
</pre></div>
* amazon xml
<div style="background-color: #F0F0F0"><pre>
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
<ShortName>Amazon.com</ShortName>
<InputEncoding>ISO-8859-1</InputEncoding>
<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZJREFUeNrEV01IFGEYfndXNzq0QdalJOoUbQiBUuopD2k/GFSG/Vxyq0OHbCUjwn7AEooUzUNRkdkhS1o9JBVaUDctKqhoRQi0WjtlxG6XVtfpfb6Z2caZ2ZnZXZdeeJxvx+973+f9+775XJIkkUaWMcoYG5TxfMpvxlvGMGM8+RYEFOxn/JJyLzOMiwwv7LqUCNQwHjpxIxKJ0Gg4LABZUVhIfr+f1jLSlNuMwyCwEHoZS6xmvxoZoc6Oq+JpJoVMpOncWdpcWZkOiRIQ2MKDp1az+kIhOtV40pHG6zdvpEOixc1/VtqFvKX5gmOX0pkL2yDgsZpxt+sORaPROe8Q6ncf3tPAk8eG3Ks14lA8brsZYZ2yukBAwOfzCeMHA3WGNXrCVpLnJKeqRyhAfX5RfNmILQF4urG0VIzxBBkU5aQI9agIeU4JqNLZ0UH9ob6sDWZE4MDefSn7P1txO/FcbxypQG18nhinew/u5zYC3dyG+qLL1qjjCKDg9C21q2a3oe9zRsCsn2PR2JzfKEy9PB96Nj8E0IJm54IaGZwPZsWJOU4jY1kD2OlAQhsJjKu3bSe7yPUzifpgMPsuOBY8brtR1evmyFt0IL0IzH4fJtcCH7kK1hn2/hh71G1yKKEdz/DBBIOTkUkRemzVl1uvCGKzE4OMIaFbiv1LSX51L7mXl4kxvgeO8vMaJk0PHiHvjl4DCTWs2lMOX0L6cwD/Bxlp6hNNv2gUT9MjsLiB8koaMOxJRgCMgPijWsqvaCP3qqqUZ4JVzUASYyFyL/WTqyggPxWH4qGtBlJzagCGIYjEzJv2zHe38vOUt6mNPGv20OyPMMV7yuVwL5IjBlLmRej1UX7VLdmLt+2CMVKTiSDn0wO1NPPyBOtdLL+MyzWkTbGhC5AGsBdKkEtWAjglgjUwCq/FGjhV0ZosdOhXI5FyH0DoIIK9slB0CS8UCgr8AlpvpamwqHpttcO4WtSqA57ioKENE05IqIYSY46uD4Is0qmGG2s9RYeS7adI3Paz3K6lTMmzIdFmXp/d1Gb1YvLF7i4IzxMfu1ITYWOe1VWix7U5tlKpXkzwYycONqfVLcW+cU7lQ0jePf360DqRS4zT/+Ny+ofRxPBoL6fa6zmu5uvtbkwZyE/lev6a8VV9+VeAAQADg36zc4GRNAAAAABJRU5ErkJggg==</Image>
<Url type="text/html" method="GET" template="http://www.amazon.com/exec/obidos/external-search/">
  <Param name="field-keywords" value="{searchTerms}"/>
  <Param name="mode" value="blended"/>
  <Param name="tag" value="mozilla-20"/>
  <Param name="sourceid" value="Mozilla-search"/>
</Url>
<SearchForm>http://www.amazon.com/</SearchForm>
</SearchPlugin>
</pre></div>
* Now let's turn those xml documents into JSON (records must contain JSONable code) (google, amz, custom(youtube))
<div style="background-color: #F0F0F0"><pre>
{
  "SearchPlugin": {
    "-xmlns": "http://www.mozilla.org/2006/browser/search/",
    "ShortName": "Google",
    "Description": "Google Search",
    "InputEncoding": "UTF-8",
    "Image": {
      "-width": "16",
      "-height": "16",
      "#text": "data:image/png;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA"
    },
    "Url": [
      {
        "-type": "application/x-suggestions+json",
        "-method": "GET",
        "-template": "https://www.google.com/complete/search?client=firefox&q={searchTerms}"
      },
      {
        "-type": "text/html",
        "-method": "GET",
        "-template": "https://www.google.com/search",
        "Param": [
          {
            "-name": "q",
            "-value": "{searchTerms}"
          },
          {
            "-name": "ie",
            "-value": "utf-8"
          },
          {
            "-name": "oe",
            "-value": "utf-8"
          },
          {
            "-name": "aq",
            "-value": "t"
          },
          {
            "-name": "rls",
            "-value": "{moz:distributionID}:{moz:locale}:{moz:official}"
          }
        ],
        "MozParam": {
          "-name": "client",
          "-condition": "defaultEngine",
          "-trueValue": "firefox-a",
          "-falseValue": "firefox"
        }
      },
      {
        "-type": "application/x-moz-keywordsearch",
        "-method": "GET",
        "-template": "https://www.google.com/search",
        "Param": [
          {
            "-name": "q",
            "-value": "{searchTerms}"
          },
          {
            "-name": "ie",
            "-value": "utf-8"
          },
          {
            "-name": "oe",
            "-value": "utf-8"
          },
          {
            "-name": "aq",
            "-value": "t"
          },
          {
            "-name": "rls",
            "-value": "{moz:distributionID}:{moz:locale}:{moz:official}"
          },
          {
            "-name": "channel",
            "-value": "fflb"
          }
        ],
        "MozParam": {
          "-name": "client",
          "-condition": "defaultEngine",
          "-trueValue": "firefox-a",
          "-falseValue": "firefox"
        }
      },
      {
        "-type": "application/x-moz-contextsearch",
        "-method": "GET",
        "-template": "https://www.google.com/search",
        "Param": [
          {
            "-name": "q",
            "-value": "{searchTerms}"
          },
          {
            "-name": "ie",
            "-value": "utf-8"
          },
          {
            "-name": "oe",
            "-value": "utf-8"
          },
          {
            "-name": "aq",
            "-value": "t"
          },
          {
            "-name": "rls",
            "-value": "{moz:distributionID}:{moz:locale}:{moz:official}"
          },
          {
            "-name": "channel",
            "-value": "rcs"
          }
        ],
        "MozParam": {
          "-name": "client",
          "-condition": "defaultEngine",
          "-trueValue": "firefox-a",
          "-falseValue": "firefox"
        }
      }
    ],
    "SearchForm": "https://www.google.com/"
  }
}
{
  "SearchPlugin": {
    "-xmlns": "http://www.mozilla.org/2006/browser/search/",
    "ShortName": "Amazon.com",
    "InputEncoding": "ISO-8859-1",
    "Image": {
      "-width": "16",
      "-height": "16",
      "#text": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZJREFUeNrEV01IFGEYfndXNzq0QdalJOoUbQiBUuopD2k/GFSG/Vxyq0OHbCUjwn7AEooUzUNRkdkhS1o9JBVaUDctKqhoRQi0WjtlxG6XVtfpfb6Z2caZ2ZnZXZdeeJxvx+973+f9+775XJIkkUaWMcoYG5TxfMpvxlvGMGM8+RYEFOxn/JJyLzOMiwwv7LqUCNQwHjpxIxKJ0Gg4LABZUVhIfr+f1jLSlNuMwyCwEHoZS6xmvxoZoc6Oq+JpJoVMpOncWdpcWZkOiRIQ2MKDp1az+kIhOtV40pHG6zdvpEOixc1/VtqFvKX5gmOX0pkL2yDgsZpxt+sORaPROe8Q6ncf3tPAk8eG3Ks14lA8brsZYZ2yukBAwOfzCeMHA3WGNXrCVpLnJKeqRyhAfX5RfNmILQF4urG0VIzxBBkU5aQI9agIeU4JqNLZ0UH9ob6sDWZE4MDefSn7P1txO/FcbxypQG18nhinew/u5zYC3dyG+qLL1qjjCKDg9C21q2a3oe9zRsCsn2PR2JzfKEy9PB96Nj8E0IJm54IaGZwPZsWJOU4jY1kD2OlAQhsJjKu3bSe7yPUzifpgMPsuOBY8brtR1evmyFt0IL0IzH4fJtcCH7kK1hn2/hh71G1yKKEdz/DBBIOTkUkRemzVl1uvCGKzE4OMIaFbiv1LSX51L7mXl4kxvgeO8vMaJk0PHiHvjl4DCTWs2lMOX0L6cwD/Bxlp6hNNv2gUT9MjsLiB8koaMOxJRgCMgPijWsqvaCP3qqqUZ4JVzUASYyFyL/WTqyggPxWH4qGtBlJzagCGIYjEzJv2zHe38vOUt6mNPGv20OyPMMV7yuVwL5IjBlLmRej1UX7VLdmLt+2CMVKTiSDn0wO1NPPyBOtdLL+MyzWkTbGhC5AGsBdKkEtWAjglgjUwCq/FGjhV0ZosdOhXI5FyH0DoIIK9slB0CS8UCgr8AlpvpamwqHpttcO4WtSqA57ioKENE05IqIYSY46uD4Is0qmGG2s9RYeS7adI3Paz3K6lTMmzIdFmXp/d1Gb1YvLF7i4IzxMfu1ITYWOe1VWix7U5tlKpXkzwYycONqfVLcW+cU7lQ0jePf360DqRS4zT/+Ny+ofRxPBoL6fa6zmu5uvtbkwZyE/lev6a8VV9+VeAAQADg36zc4GRNAAAAABJRU5ErkJggg=="
    },
    "Url": {
      "-type": "text/html",
      "-method": "GET",
      "-template": "http://www.amazon.com/exec/obidos/external-search/",
      "Param": [
        {
          "-name": "field-keywords",
          "-value": "{searchTerms}"
        },
        {
          "-name": "mode",
          "-value": "blended"
        },
        {
          "-name": "tag",
          "-value": "mozilla-20"
        },
        {
          "-name": "sourceid",
          "-value": "Mozilla-search"
        }
      ]
    },
    "SearchForm": "http://www.amazon.com/"
  }
}
{
  "SearchPlugin": {
    "-xmlns": "http://www.mozilla.org/2006/browser/search/",
    "-xmlns:os": "http://a9.com/-/spec/opensearch/1.1/",
    "os:ShortName": "YouTube Video Search",
    "os:Description": "Search for videos on YouTube",
    "os:InputEncoding": "UTF-8",
    "os:Image": {
      "-width": "16",
      "-height": "16",
      "#text": "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAABMLAAATCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgNkQkIDZGiCA2RzAgNkcwIDZH/CA2R/wgNkf8IDZH/CA2R/wgNkf8IDZH/CA2R2AgNkcwIDZHMCA2RhAgNkQYIDpWHCA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpWHCQ6ZzAkOmf8JDpn/CQ6Z/wkOmf8JDpb/BQhc/wgMgf8JDpn/CQ6Z/wkOmf8JDpn/CQ6Z/wkOmf8JDpn/CQ6ZzAkOnuoJDp7/CQ6e/wkOnv8JDp7/Exed/8jIy/9RU4j/Bwp0/wkOm/8JDp7/CQ6e/wkOnv8JDp7/CQ6e/wkOnuoJD6T8CQ+k/wkPpP8JD6T/CQ+k/xUbo//V1dX/1dXV/4yNrP8QFG//CA6Y/wkPpP8JD6T/CQ+k/wkPpP8JD6T8CQ+q/wkPqv8JD6r/CQ+q/wkPqv8WG6n/3d3d/93d3f/d3d3/v7/M/y0wjv8JD6r/CQ+q/wkPqv8JD6r/CQ+q/woQr/8KEK//ChCv/woQr/8KEK//Fx2v/+fn5//n5+f/5+fn/+jo6P+YmtP/ChCv/woQr/8KEK//ChCv/woQr/8KELX8ChC1/woQtf8KELX/ChC1/xgdtf/x8fH/8fHx//Ly8v+bndv/Ehi3/woQtf8KELX/ChC1/woQtf8KELX8ChG76goRu/8KEbv/ChG7/woRu/8YH77/+fn5/+/v9/9fY9H/ChG7/woRu/8KEbv/ChG7/woRu/8KEbv/ChG76goRwMwKEcD/ChHA/woRwP8KEcD/EBfB/6Ol5/8tM8n/ChHA/woRwP8KEcD/ChHA/woRwP8KEcD/ChHA/woRwMwLEcSHCxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcSHCxLICQsSyKULEsjMCxLI+QsSyP8LEsj/CxLI/wsSyP8LEsj/CxLI/wsSyP8LEsj/CxLI0gsSyMwLEsiiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAD//wAA//8AAA=="
    },
    "os:Url": {
      "-type": "text/html",
      "-method": "GET",
      "-template": "http://www.youtube.com/results?search_query={searchTerms}&page={startPage?}&utm_source=opensearch"
    }
  }
}
</pre></div>
=== Digging around in the code Pointers ===
** http://jsontoxml.utilities-online.info/ convert between the two data formats
** changes frequently dont show up immediate (but get written on close)
** ordering in data store includes hidden engines. the number may not match the observed number
*** note in the example below all engines are off by 1 because google is order:1 and hidden, so youtube appears first in the list but has order:2
** getting a 3rd party search thingy
*** right click on a website search bar (ie youtube) and /profile/searchplugins will be created with an OpenSearch .xml
*** searchplugins doesn't exist until you create a non-default one
** SQLite table: install addon, go to tools -> SQLiteManager -> select db, go
** default engines have a hidden value, which afaic, is never applied to custom engines?

Latest revision as of 21:55, 14 August 2012

State

  • After a meeting of mobile product, desktop product, & engineering, this will be set aside for awhile. It is still desired as a feature by the end of the year.

Goals

  • Sync search engine prefs on Desktop
    • addition of an engine
    • removal of an engine
    • reordering of engines
    • keywords/aliases for a particular engine
    • restore defaults (potentially not a special case for implementation, but could be considered a feature by users)
  • Format to be interoperable with firefox os, mobile firefox, or other future clients
  • Nongoals:
    • implementation on firefox os
    • implementation on mobile firefox

Design

Requirements Gathering

  • (deadline for input: july 26)
  • Stakeholders
    • Desktop: Gavin
    • Desktop UX: madhava
    • Mobile: bnicholson, mfinkle
    • B@G: N/A, Ben Francis, b2g has no plugins and few preferences at this time
    • Privacy: Tom, Sid
    • Security: David Chan
    • Product: Asa
    • Services Integration: Gps
    • Community: dev-planning, dev-apps-firefox lists
    • Legal: bug 778823, ok as long as based in user action & the defaults w/o user action don't change
  • input
    • want to avoid syncing app-shipped search plugins, origin: gavin
    • dont sync XML files, sync the JSON cache that's the result of parse origin: gavin
    • mobile uses same nsISearchService as desktop -mfinkle
    • should it be applicationID based, the way addons?
    • should we limit to a blessed type of plugin to address hijacking?
    • impact of Australis?

Current Requirements

  • does not sync hijacked queries
    • origin: Asa, browser cannot currently detect this, requires a new browser feature
  • don't require server call to install search engine (like add-on sync does). i.e. data self-contained
    • origin sstamm, reducing the addon sync threat
  • syncs keywords
  • search order preserved
  • 3rd party plugins appear
  • honors enable/disable
    • desktop does not match mobile
  • does not assume matching default lists on different clients (which is to say, can't assume google et al are installed everywhere) and syncing of default engine code is likely
  • syncs which engines support the search suggest api

Specifications

  • Still missing a good reconciling algorithm for reordering
  • mattn raises a good point that this does not handle recounciling duplicate aliases/keywords. It is currently handled locally on desktop. Should we try to regulate it, or force it to be a client responsibility?
  • NB: thinking forward to resilient sync, canonical servers, and client engines that aren't us

Terms

  • default plugin, default engine, app shipped plugin. a plugin that is shipped with the firefox build
  • custom plugin, custom engine aka user added plugin. plugin added (presumably) by user action
  • alias, keyword. user created string that is a shortcut to using a search engine

Generic Specification

  • The goal of sync is the same experience everywhere. There exists one global ordering of search plugins. It may contain disabled, hidden, and platform-specific plugins, which may cause the visible order to be different on different clients.
    • For example, a desktop only plugin will not show up on a mobile client.
  • The currently selected engine will not be sync'ed. This is regarded as local to the client.
    • NB: This is also believed to address some of the concern about hijacking.
  • Sync's record may be more data rich/expressive than a particular client's internal representation. Client implementations may choose to disregard pieces of information in the record, but they may not destroy it.
    • For example, fennec does not use keywords, but desktop does. syncing fennec should not destroy keywords associated with an engine on desktop.
  • A plugin may be designated for one or more platforms. (Note, this field can be empty, implying it is suitable for use on all clients). If there is a platform designation, clients not in that list must ignore the plugin. They are not install it, alter it, or upload it.
  • Default records of one client implementation cannot be deleted by other clients.
    • For example, mobile cannot delete the desktop google plugin.
    • Mobile's 'restore defaults' cannot destroy the desktop defaults and vice versa.
  • Removal of custom plugins results in deletions on disk & propagates to other clients. "Removal" of defaults however, results in setting the hidden flag and propagating that change.
  • Hidden & disabled are similar but different concepts. No client should treat them interchangeably, as it will result in inconsistent behavior on other clients. Disabled plugins should appear in UI and not be active. Hidden plugins should not show up in UI and be inactive.
  • Clients must honor a distinction between global disabling and local disabling. Clients may choose (at the direction or needs of their ux) to enable/disable specific plugins valid for their platforms locally. These local decisions should not be propagated via sync.
    • Fennec will default to locally disable yahoo, bing, and amazon in their ux, but they should not be disabled on desktop after a mobile client has been synced.
    • If a user disables google on mobile, that should be propagated. It is the responsibility of the mobile client in that case to distinguish between the source of the disabling.
  • No special rules for handling keyword addition/removal/change. latest change wins
  • First Sync Behavior. May need special rules for first connecting to the constellation.
  • Reconciling Rules: TBA. currently toying with inserting into list after all hidden & !yourplatform, but before disabled if present at your index.

Additional Specification for Desktop Firefox

  • Until the browser implements detecting hijacked searches, this engine will be preffed off by default for existing and new users
  • Default plugins need to be synced. They are expected to user accessible on mobile, other clients.
  • Engines that cannot be serialized probably should not be synced.
  • Desktop should implement enable/disable to comply with above spec

Additional Specifications for Firefox Mobile

  • when synced to mobile, default engines that are not default on mobile (there are 4 to desktop's 7+) will be disabled (visible but greyed out). Users will have the option to enable those for their system.
    • this enable/disable for default-on-other-client-but-not-this one is local.
    • implies that keywords wont work for disabled engines
  • custom plugins must start enabled by default (until user action disables them)
  • mobile does not support keywords at this time, but will in the future
  • mobile does not support context search for all plugins, but should in the future

proposed data model for a plugin record v3

  • name, description, searchForm, iconurl, urls (very fat object on default engines), url values can be derived from openSearchRefObj
    • search suggest api/support should be covered by guts of openSearchRefObj when it becomes relevant
  • data not being synced
    • directory - machine specific
    • lastModifiedTime - machine & directory specific. used to invalidate cache
    • filepath - path to the xml, which wont exist since we arent syncing the xml and would be specific to a machine (where fx is installed, where profile is installed, etc)
  • data model
{
  id // string id of the plugin usually looks like [app]google.xml
  guid // used for sync reconciliation 
  openSearchRefObj //the whole of the OpenSearch xml object json-ifed. Clients may pick & choose which bits of data they will use/store in their representation. The sync store however, will hold onto this, to prevent differing internal representations from causing data loss on other platforms. It also ensures sync can in the future gracefully support any future features that are covered by the OpenSearch spec but not by the current internal representations. 
  age //age in unix time of the ref object (so if the ref object changes, we know which one to keep)
  order // place in the global order (beware, even hidden engines have order)
  aliases // may be [], array of search keywords associated with this plugin
  isHidden // true if this engine should be globally disabled. Note some clients may treat some engines as 'removed' when they are actually disabled. (like desktop never actually removes the defaults even though the ui says it does)
  applicationIds // array of ids that this plugin should be installed on. [] if all platforms. (some plugins should not be installed on mobile, like desktop's google plugin, but others like twitter, are suitable for all platforms. Also leaves room for us to indicate a plugin meant for a subset, like mobile platforms {fennec, firefoxOS} and not desktop)
  locale //the locale of the plugin. Currently all plugins will have the same locale
  installLocation // optional. if not present, this plugin is default [app] on desktop
  type //optional, used to differentiate origins of plugins on desktop
  queryCharset // defaults on desktop do not have this, may be null
  isReadOnly //may be null 
  isDefault //indicates that this is a default, needed for 'restore defaults'
}

Design Reviews if needed

  • privacy security?
  • UI changes?

Implementation

  • not started
  • desktop will need code changes to address missing enable/disable state for custom search engines
  • desktop will need nsSearchService changes to handle a consolidated data format


Implementation schedule

  • largely made up, as the repositories re-write is a huge wild card
  • feedback due by 26-jul
  • spec finalized by 3-Aug
  • Implement store, record for json + tests by 10-aug
  • Implement store, record for db(ordering, keywords) + tests by 15-aug
  • Implement tracker + xpc tracker tests by 24-aug
  • Implement engine + xpc tests by 7-sep
    • most likely to get snagged here
  • Implement tps tests (if possible, see dependencies) and any remaining xpc tests by sep-14
  • Debugging (unknown)
    • 'cause there's going to a landmine somewhere

Dependencies

  • Solving the hijacking problem. Serious concern over syncing crapware
  • TPS supporting desktop to mobile operations (jgriffin's team)
    • TPS new data tupe addition (jgriffin's team)
  • Desktop client supporting hijacked search detection (gavin?)
    • so engine can be enabled by default for new or existing users
  • Someone implementing the corresponding mobile engine (?)
  • repositories rewrite (gps)

Test Plan

TPS Tests

  • Important Notes
    • tps does not support the native mobile at this time. timeframe unknown for support
    • dependency - adding a new engine will require work on tps. timeframe unknown, but likely to be reasonable
      • tests cannot really be written ahead of those changes to tps
  • Tests
    • only reordering syncs between profile 1 & profile 2
    • only keyword addition, change, and removal sync between profile 1 & 2
    • adding and removing a search engine plugin syncs between profile 1 & 2
    • add plugin, add keyword, reorder, sync between two desktops, remove & sync again
    • add plugin, add keyword, reorder, sync between mobile (if mobile client exists) & desktop, remove & sync again

XPC Shell Tests

  • make sure there is heavy testing about reordering with hidden & default engines, as some of the calls may have unexpected side effects (and some functions consider hidden in counts and others do not, same deal with what counts as default)
  • impacted by repositories re-write?

Release

    • targeted to land on Nightly during Q3 (not a promise, subject to scope change)

Reference


Scratch and Notes

Insights

  • reconciling lists remain hard!
  • what should happen when default lists dont match
    • defaults should be synced because they may not be present on other systems and users can expect to see them (though the mobile client may grey them out)
  • user created keywords are called 'alias'es in code, stored in search-metadata.json
  • search-metadata.json
    • may not exist if nothing has been changed
    • contains per plugin: order placement, hidden, and keywords
  • /profile/search.json
    • "directories" will have two entries, the default one ("/Applications/Firefox.app/Contents/MacOS/searchplugins") & "/Users/mozilla/Documents/inbox-desktop/test_profiles/searchplugins" in my case) The first has no usefully syncable data, though it does have a lastModifiedTime (this is the lastModifiedTime of the directory, used for cache invalidation --Gavin)
  • JAR loading code is for mobile, for their default plugin handling
  • Australis is not making the search engines or their data go away
  • "Search service changes will be required for this, almost certainly. Exposing the engine description as JSON and adding the ability to distinguish app-shipped plugins via the nsIBrowserSearchService API seem like good first steps to me" - gavin
    • Mobile will support search keywords & search suggest in the nearish future.
  • /profile/search.sqlite(DO NOT SYNC) (this is no longer used after bug 699856, replaced by search-metadata.json --Gavin)
  • pref browser.search.selectedEngine represents the currently selected entry, status "user set" is useful
  • pref browser.search.useDBForOrder i bet that represents ordering (this gets set to true once the user has customized the search engine order, to indicate that we should use the positioning information in search-metadata.json rather than the one in default prefs (browser.search.order.*) --Gavin)
  • pref browser.search.order.1-3 are hard coded defaults. do not sync

current problems

  • make sure search suggest is covered!
  • search suggest has global preferences associated with it. to sync or not to sync?
    • and if so, should it go in the preferences engine, or in this one? I'm inclined to think it matters even if engines are not synced

What do these data formats look like anyway?

  • search-metadata.json. reordering + keywords. Note this file can be empty
{
    "[app]/google.xml":
    {
        "hidden":true,
        "alias":null,
        "order":1
    },
    "[profile]/youtube-video-search.xml":
    {
        "order":2,
        "alias":"anaaktge_test_keyword"
    },
    "[app]/bing.xml":
    {
        "order":3
    },
    "[app]/amazondotcom.xml":
    {
        "order":4,
        "alias":"anaaktge_test_keyword_default"
    },
    "[app]/eBay.xml":
    {
        "order":5
    },
    "[app]/twitter.xml":
    {
        "order":6
    },
    "[app]/wikipedia.xml":
    {
        "order":7
    },
    "[app]/yahoo.xml":
    {
        "order":8
    }
}
  • search.json, one default plugin, one custom (youtube) plugin
{
    "version":7,
    "buildID":"20120730133507",
    "locale":"en-US",
    "directories":
    {
        "/Users/mozilla/moz/hg/services-central/./obj-x86_64-apple-darwin11.4.0/dist/NightlyDebug.app/Contents/MacOS/searchplugins":
        {
            "lastModifiedTime":1343683762000,
            "engines":
            [
                {
                    "_id":"[app]/amazondotcom.xml",
                    "_name":"Amazon.com",
                    "_hidden":false,
                    "description":"Amazon.com Search",
                    "__searchForm":"http://www.amazon.com/",
                    "_iconURL":"data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHgSURBVHjalFM9TNtQEP4cB7PwM1RITUXIgsRaYEEVEyKZwhiyZAQyd0BhpFOlIjoBqhjSqVQMoVMLLAjEwECCQJkSkBqJYDOAFOMKFSf28d7DTUxiUDnp/Pzeu/vuu7t3ICKF6SLTMv2/lB0fRWKfjwDm4JJisYh0Oo3fpZLYT0SjSCQS8JAFMADNDZ3NZsnf1taiqVTKi4nGASruk5lkkmTmMB6JUKFQqO+DfX1eABWeQoVR6f7HSdM0obqu48Yw8G1tDT82NsRd1TSbU9BbGPCog8PDj+jLzurFoAVgMh4XxoNDQ6SqKi0tL9eBvAB8zZwymYxYY7EYAoEA8vm82BNTg6XUIs0MeGTZoR1mhXSnwNl4pmAbjU7mcjkKhkL1ynMnntZ4OEw3VyrV8utk7s5TdW++0QXz+1i3P7IK36t+PCfVn1OQOoOA0gXr5DPak+cPXbBK+/T3S69AtY3LJ98vZ1or/iLr+pTuvr59/A6s003UdqZFJF/PCKQ3o5CUznoBST2AfbEF/9iqYEDaIfwj73VJPEfgNTe0tWNYR0uwy9uOW0OkrgHI7z5ADo2C7v48nLV3XHKAT+x/1m1sX58xsBxg8rZJrDYD8DHHp4aJj/MK09sXjPOt46PcCzAACXY8/u34wN0AAAAASUVORK5CYII=",
                    "_urls":
                    [
                        {
                        "template":"http://www.amazon.com/exec/obidos/external-search/",
                        "rels":[],
                        "params":
                        [
                            {
                                "name":"field-keywords",
                                "value":"{searchTerms}"
                            },
                            {
                                "name":"mode",
                                "value":"blended"
                            },
                            {
                                "name":"tag",
                                "value":"mozilla-20"
                            },
                            {
                                "name":"sourceid",
                                "value":"Mozilla-search"
                            }
                        ]
                        }
                    ],
                    "filePath":"/Users/mozilla/moz/hg/services-central/./obj-x86_64-apple-darwin11.4.0/dist/NightlyDebug.app/Contents/MacOS/searchplugins/amazondotcom.xml"
                }
            ]
        }
        "/Users/mozilla/Documents/inbox-desktop/test_profiles/search_engine_sync_0/searchplugins":
        {
            "lastModifiedTime":1343685412000,
            "engines":
            [
                {
                    "_id":"[profile]/youtube-video-search.xml",
                    "_name":"YouTube Video Search",
                    "_hidden":false,
                    "description":"Search for videos on YouTube",
                    "__searchForm":"http://www.youtube.com",
                    "_iconURL":"data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAABMLAAATCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgNkQkIDZGiCA2RzAgNkcwIDZH/CA2R/wgNkf8IDZH/CA2R/wgNkf8IDZH/CA2R2AgNkcwIDZHMCA2RhAgNkQYIDpWHCA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpWHCQ6ZzAkOmf8JDpn/CQ6Z/wkOmf8JDpb/BQhc/wgMgf8JDpn/CQ6Z/wkOmf8JDpn/CQ6Z/wkOmf8JDpn/CQ6ZzAkOnuoJDp7/CQ6e/wkOnv8JDp7/Exed/8jIy/9RU4j/Bwp0/wkOm/8JDp7/CQ6e/wkOnv8JDp7/CQ6e/wkOnuoJD6T8CQ+k/wkPpP8JD6T/CQ+k/xUbo//V1dX/1dXV/4yNrP8QFG//CA6Y/wkPpP8JD6T/CQ+k/wkPpP8JD6T8CQ+q/wkPqv8JD6r/CQ+q/wkPqv8WG6n/3d3d/93d3f/d3d3/v7/M/y0wjv8JD6r/CQ+q/wkPqv8JD6r/CQ+q/woQr/8KEK//ChCv/woQr/8KEK//Fx2v/+fn5//n5+f/5+fn/+jo6P+YmtP/ChCv/woQr/8KEK//ChCv/woQr/8KELX8ChC1/woQtf8KELX/ChC1/xgdtf/x8fH/8fHx//Ly8v+bndv/Ehi3/woQtf8KELX/ChC1/woQtf8KELX8ChG76goRu/8KEbv/ChG7/woRu/8YH77/+fn5/+/v9/9fY9H/ChG7/woRu/8KEbv/ChG7/woRu/8KEbv/ChG76goRwMwKEcD/ChHA/woRwP8KEcD/EBfB/6Ol5/8tM8n/ChHA/woRwP8KEcD/ChHA/woRwP8KEcD/ChHA/woRwMwLEcSHCxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcSHCxLICQsSyKULEsjMCxLI+QsSyP8LEsj/CxLI/wsSyP8LEsj/CxLI/wsSyP8LEsj/CxLI0gsSyMwLEsiiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAD//wAA//8AAA==",
                    "_urls":
                    [
                        {
                            "template":"http://www.youtube.com/results?search_query={searchTerms}&page={startPage?}&utm_source=opensearch",
                            "rels":[],
                            "params":[]
                        }
                    ],
                    "filePath":"/Users/mozilla/Documents/inbox-desktop/test_profiles/search_engine_sync_0/searchplugins/youtube-video-search.xml",
                    "_url":"http://www.youtube.com/opensearch?locale=en_US",
                    "_installLocation":2,
                    "type":3,
                    "queryCharset":"UTF-8",
                    "_readOnly":false
                }
            ]
        }
    }
}

  • profile/searchplugins/ .xml
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/" xmlns:os="http://a9.com/-/spec/opensearch/1.1/">
<os:ShortName>YouTube Video Search</os:ShortName>
<os:Description>Search for videos on YouTube</os:Description>
<os:InputEncoding>UTF-8</os:InputEncoding>
<os:Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAABMLAAATCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgNkQkIDZGiCA2RzAgNkcwIDZH/CA2R/wgNkf8IDZH/CA2R/wgNkf8IDZH/CA2R2AgNkcwIDZHMCA2RhAgNkQYIDpWHCA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpWHCQ6ZzAkOmf8JDpn/CQ6Z/wkOmf8JDpb/BQhc/wgMgf8JDpn/CQ6Z/wkOmf8JDpn/CQ6Z/wkOmf8JDpn/CQ6ZzAkOnuoJDp7/CQ6e/wkOnv8JDp7/Exed/8jIy/9RU4j/Bwp0/wkOm/8JDp7/CQ6e/wkOnv8JDp7/CQ6e/wkOnuoJD6T8CQ+k/wkPpP8JD6T/CQ+k/xUbo//V1dX/1dXV/4yNrP8QFG//CA6Y/wkPpP8JD6T/CQ+k/wkPpP8JD6T8CQ+q/wkPqv8JD6r/CQ+q/wkPqv8WG6n/3d3d/93d3f/d3d3/v7/M/y0wjv8JD6r/CQ+q/wkPqv8JD6r/CQ+q/woQr/8KEK//ChCv/woQr/8KEK//Fx2v/+fn5//n5+f/5+fn/+jo6P+YmtP/ChCv/woQr/8KEK//ChCv/woQr/8KELX8ChC1/woQtf8KELX/ChC1/xgdtf/x8fH/8fHx//Ly8v+bndv/Ehi3/woQtf8KELX/ChC1/woQtf8KELX8ChG76goRu/8KEbv/ChG7/woRu/8YH77/+fn5/+/v9/9fY9H/ChG7/woRu/8KEbv/ChG7/woRu/8KEbv/ChG76goRwMwKEcD/ChHA/woRwP8KEcD/EBfB/6Ol5/8tM8n/ChHA/woRwP8KEcD/ChHA/woRwP8KEcD/ChHA/woRwMwLEcSHCxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcSHCxLICQsSyKULEsjMCxLI+QsSyP8LEsj/CxLI/wsSyP8LEsj/CxLI/wsSyP8LEsj/CxLI0gsSyMwLEsiiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAD//wAA//8AAA==</os:Image>
<os:Url type="text/html" method="GET" template="http://www.youtube.com/results?search_query={searchTerms}&page={startPage?}&utm_source=opensearch">
</os:Url>
</SearchPlugin>

  • google search xml
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
<ShortName>Google</ShortName>
<Description>Google Search</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16">data:image/png;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA</Image>
<Url type="application/x-suggestions+json" method="GET" template="https://www.google.com/complete/search?client=firefox&q={searchTerms}"/>
<Url type="text/html" method="GET" template="https://www.google.com/search">
  <Param name="q" value="{searchTerms}"/><Param name="ie" value="utf-8"/><Param name="oe" value="utf-8"/><Param name="aq" value="t"/><Param name="rls" value="{moz:distributionID}:{moz:locale}:{moz:official}"/>
  <MozParam name="client" condition="defaultEngine" trueValue="firefox-a" falseValue="firefox"/>
</Url>
<!-- Keyword search URL is the same as the default, but with an additional parameter -->
<Url type="application/x-moz-keywordsearch" method="GET" template="https://www.google.com/search">
  <Param name="q" value="{searchTerms}"/><Param name="ie" value="utf-8"/><Param name="oe" value="utf-8"/><Param name="aq" value="t"/><Param name="rls" value="{moz:distributionID}:{moz:locale}:{moz:official}"/>
  <MozParam name="client" condition="defaultEngine" trueValue="firefox-a" falseValue="firefox"/>
  <Param name="channel" value="fflb"/>
</Url>
<!-- Context/Right-click search URL is the same as the default, but with an additional parameter -->
<Url type="application/x-moz-contextsearch" method="GET" template="https://www.google.com/search">
  <Param name="q" value="{searchTerms}"/><Param name="ie" value="utf-8"/><Param name="oe" value="utf-8"/><Param name="aq" value="t"/><Param name="rls" value="{moz:distributionID}:{moz:locale}:{moz:official}"/>
  <MozParam name="client" condition="defaultEngine" trueValue="firefox-a" falseValue="firefox"/>
  <Param name="channel" value="rcs"/>
</Url>
<SearchForm>https://www.google.com/</SearchForm>
</SearchPlugin>
  • amazon xml
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
<ShortName>Amazon.com</ShortName>
<InputEncoding>ISO-8859-1</InputEncoding>
<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZJREFUeNrEV01IFGEYfndXNzq0QdalJOoUbQiBUuopD2k/GFSG/Vxyq0OHbCUjwn7AEooUzUNRkdkhS1o9JBVaUDctKqhoRQi0WjtlxG6XVtfpfb6Z2caZ2ZnZXZdeeJxvx+973+f9+775XJIkkUaWMcoYG5TxfMpvxlvGMGM8+RYEFOxn/JJyLzOMiwwv7LqUCNQwHjpxIxKJ0Gg4LABZUVhIfr+f1jLSlNuMwyCwEHoZS6xmvxoZoc6Oq+JpJoVMpOncWdpcWZkOiRIQ2MKDp1az+kIhOtV40pHG6zdvpEOixc1/VtqFvKX5gmOX0pkL2yDgsZpxt+sORaPROe8Q6ncf3tPAk8eG3Ks14lA8brsZYZ2yukBAwOfzCeMHA3WGNXrCVpLnJKeqRyhAfX5RfNmILQF4urG0VIzxBBkU5aQI9agIeU4JqNLZ0UH9ob6sDWZE4MDefSn7P1txO/FcbxypQG18nhinew/u5zYC3dyG+qLL1qjjCKDg9C21q2a3oe9zRsCsn2PR2JzfKEy9PB96Nj8E0IJm54IaGZwPZsWJOU4jY1kD2OlAQhsJjKu3bSe7yPUzifpgMPsuOBY8brtR1evmyFt0IL0IzH4fJtcCH7kK1hn2/hh71G1yKKEdz/DBBIOTkUkRemzVl1uvCGKzE4OMIaFbiv1LSX51L7mXl4kxvgeO8vMaJk0PHiHvjl4DCTWs2lMOX0L6cwD/Bxlp6hNNv2gUT9MjsLiB8koaMOxJRgCMgPijWsqvaCP3qqqUZ4JVzUASYyFyL/WTqyggPxWH4qGtBlJzagCGIYjEzJv2zHe38vOUt6mNPGv20OyPMMV7yuVwL5IjBlLmRej1UX7VLdmLt+2CMVKTiSDn0wO1NPPyBOtdLL+MyzWkTbGhC5AGsBdKkEtWAjglgjUwCq/FGjhV0ZosdOhXI5FyH0DoIIK9slB0CS8UCgr8AlpvpamwqHpttcO4WtSqA57ioKENE05IqIYSY46uD4Is0qmGG2s9RYeS7adI3Paz3K6lTMmzIdFmXp/d1Gb1YvLF7i4IzxMfu1ITYWOe1VWix7U5tlKpXkzwYycONqfVLcW+cU7lQ0jePf360DqRS4zT/+Ny+ofRxPBoL6fa6zmu5uvtbkwZyE/lev6a8VV9+VeAAQADg36zc4GRNAAAAABJRU5ErkJggg==</Image>
<Url type="text/html" method="GET" template="http://www.amazon.com/exec/obidos/external-search/">
  <Param name="field-keywords" value="{searchTerms}"/>
  <Param name="mode" value="blended"/>
  <Param name="tag" value="mozilla-20"/>
  <Param name="sourceid" value="Mozilla-search"/>
</Url>
<SearchForm>http://www.amazon.com/</SearchForm>
</SearchPlugin>
  • Now let's turn those xml documents into JSON (records must contain JSONable code) (google, amz, custom(youtube))
{
  "SearchPlugin": {
    "-xmlns": "http://www.mozilla.org/2006/browser/search/",
    "ShortName": "Google",
    "Description": "Google Search",
    "InputEncoding": "UTF-8",
    "Image": {
      "-width": "16",
      "-height": "16",
      "#text": "data:image/png;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA"
    },
    "Url": [
      {
        "-type": "application/x-suggestions+json",
        "-method": "GET",
        "-template": "https://www.google.com/complete/search?client=firefox&q={searchTerms}"
      },
      {
        "-type": "text/html",
        "-method": "GET",
        "-template": "https://www.google.com/search",
        "Param": [
          {
            "-name": "q",
            "-value": "{searchTerms}"
          },
          {
            "-name": "ie",
            "-value": "utf-8"
          },
          {
            "-name": "oe",
            "-value": "utf-8"
          },
          {
            "-name": "aq",
            "-value": "t"
          },
          {
            "-name": "rls",
            "-value": "{moz:distributionID}:{moz:locale}:{moz:official}"
          }
        ],
        "MozParam": {
          "-name": "client",
          "-condition": "defaultEngine",
          "-trueValue": "firefox-a",
          "-falseValue": "firefox"
        }
      },
      {
        "-type": "application/x-moz-keywordsearch",
        "-method": "GET",
        "-template": "https://www.google.com/search",
        "Param": [
          {
            "-name": "q",
            "-value": "{searchTerms}"
          },
          {
            "-name": "ie",
            "-value": "utf-8"
          },
          {
            "-name": "oe",
            "-value": "utf-8"
          },
          {
            "-name": "aq",
            "-value": "t"
          },
          {
            "-name": "rls",
            "-value": "{moz:distributionID}:{moz:locale}:{moz:official}"
          },
          {
            "-name": "channel",
            "-value": "fflb"
          }
        ],
        "MozParam": {
          "-name": "client",
          "-condition": "defaultEngine",
          "-trueValue": "firefox-a",
          "-falseValue": "firefox"
        }
      },
      {
        "-type": "application/x-moz-contextsearch",
        "-method": "GET",
        "-template": "https://www.google.com/search",
        "Param": [
          {
            "-name": "q",
            "-value": "{searchTerms}"
          },
          {
            "-name": "ie",
            "-value": "utf-8"
          },
          {
            "-name": "oe",
            "-value": "utf-8"
          },
          {
            "-name": "aq",
            "-value": "t"
          },
          {
            "-name": "rls",
            "-value": "{moz:distributionID}:{moz:locale}:{moz:official}"
          },
          {
            "-name": "channel",
            "-value": "rcs"
          }
        ],
        "MozParam": {
          "-name": "client",
          "-condition": "defaultEngine",
          "-trueValue": "firefox-a",
          "-falseValue": "firefox"
        }
      }
    ],
    "SearchForm": "https://www.google.com/"
  }
}

{
  "SearchPlugin": {
    "-xmlns": "http://www.mozilla.org/2006/browser/search/",
    "ShortName": "Amazon.com",
    "InputEncoding": "ISO-8859-1",
    "Image": {
      "-width": "16",
      "-height": "16",
      "#text": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZJREFUeNrEV01IFGEYfndXNzq0QdalJOoUbQiBUuopD2k/GFSG/Vxyq0OHbCUjwn7AEooUzUNRkdkhS1o9JBVaUDctKqhoRQi0WjtlxG6XVtfpfb6Z2caZ2ZnZXZdeeJxvx+973+f9+775XJIkkUaWMcoYG5TxfMpvxlvGMGM8+RYEFOxn/JJyLzOMiwwv7LqUCNQwHjpxIxKJ0Gg4LABZUVhIfr+f1jLSlNuMwyCwEHoZS6xmvxoZoc6Oq+JpJoVMpOncWdpcWZkOiRIQ2MKDp1az+kIhOtV40pHG6zdvpEOixc1/VtqFvKX5gmOX0pkL2yDgsZpxt+sORaPROe8Q6ncf3tPAk8eG3Ks14lA8brsZYZ2yukBAwOfzCeMHA3WGNXrCVpLnJKeqRyhAfX5RfNmILQF4urG0VIzxBBkU5aQI9agIeU4JqNLZ0UH9ob6sDWZE4MDefSn7P1txO/FcbxypQG18nhinew/u5zYC3dyG+qLL1qjjCKDg9C21q2a3oe9zRsCsn2PR2JzfKEy9PB96Nj8E0IJm54IaGZwPZsWJOU4jY1kD2OlAQhsJjKu3bSe7yPUzifpgMPsuOBY8brtR1evmyFt0IL0IzH4fJtcCH7kK1hn2/hh71G1yKKEdz/DBBIOTkUkRemzVl1uvCGKzE4OMIaFbiv1LSX51L7mXl4kxvgeO8vMaJk0PHiHvjl4DCTWs2lMOX0L6cwD/Bxlp6hNNv2gUT9MjsLiB8koaMOxJRgCMgPijWsqvaCP3qqqUZ4JVzUASYyFyL/WTqyggPxWH4qGtBlJzagCGIYjEzJv2zHe38vOUt6mNPGv20OyPMMV7yuVwL5IjBlLmRej1UX7VLdmLt+2CMVKTiSDn0wO1NPPyBOtdLL+MyzWkTbGhC5AGsBdKkEtWAjglgjUwCq/FGjhV0ZosdOhXI5FyH0DoIIK9slB0CS8UCgr8AlpvpamwqHpttcO4WtSqA57ioKENE05IqIYSY46uD4Is0qmGG2s9RYeS7adI3Paz3K6lTMmzIdFmXp/d1Gb1YvLF7i4IzxMfu1ITYWOe1VWix7U5tlKpXkzwYycONqfVLcW+cU7lQ0jePf360DqRS4zT/+Ny+ofRxPBoL6fa6zmu5uvtbkwZyE/lev6a8VV9+VeAAQADg36zc4GRNAAAAABJRU5ErkJggg=="
    },
    "Url": {
      "-type": "text/html",
      "-method": "GET",
      "-template": "http://www.amazon.com/exec/obidos/external-search/",
      "Param": [
        {
          "-name": "field-keywords",
          "-value": "{searchTerms}"
        },
        {
          "-name": "mode",
          "-value": "blended"
        },
        {
          "-name": "tag",
          "-value": "mozilla-20"
        },
        {
          "-name": "sourceid",
          "-value": "Mozilla-search"
        }
      ]
    },
    "SearchForm": "http://www.amazon.com/"
  }
}

{
  "SearchPlugin": {
    "-xmlns": "http://www.mozilla.org/2006/browser/search/",
    "-xmlns:os": "http://a9.com/-/spec/opensearch/1.1/",
    "os:ShortName": "YouTube Video Search",
    "os:Description": "Search for videos on YouTube",
    "os:InputEncoding": "UTF-8",
    "os:Image": {
      "-width": "16",
      "-height": "16",
      "#text": "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAABMLAAATCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgNkQkIDZGiCA2RzAgNkcwIDZH/CA2R/wgNkf8IDZH/CA2R/wgNkf8IDZH/CA2R2AgNkcwIDZHMCA2RhAgNkQYIDpWHCA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpX/CA6V/wgOlf8IDpWHCQ6ZzAkOmf8JDpn/CQ6Z/wkOmf8JDpb/BQhc/wgMgf8JDpn/CQ6Z/wkOmf8JDpn/CQ6Z/wkOmf8JDpn/CQ6ZzAkOnuoJDp7/CQ6e/wkOnv8JDp7/Exed/8jIy/9RU4j/Bwp0/wkOm/8JDp7/CQ6e/wkOnv8JDp7/CQ6e/wkOnuoJD6T8CQ+k/wkPpP8JD6T/CQ+k/xUbo//V1dX/1dXV/4yNrP8QFG//CA6Y/wkPpP8JD6T/CQ+k/wkPpP8JD6T8CQ+q/wkPqv8JD6r/CQ+q/wkPqv8WG6n/3d3d/93d3f/d3d3/v7/M/y0wjv8JD6r/CQ+q/wkPqv8JD6r/CQ+q/woQr/8KEK//ChCv/woQr/8KEK//Fx2v/+fn5//n5+f/5+fn/+jo6P+YmtP/ChCv/woQr/8KEK//ChCv/woQr/8KELX8ChC1/woQtf8KELX/ChC1/xgdtf/x8fH/8fHx//Ly8v+bndv/Ehi3/woQtf8KELX/ChC1/woQtf8KELX8ChG76goRu/8KEbv/ChG7/woRu/8YH77/+fn5/+/v9/9fY9H/ChG7/woRu/8KEbv/ChG7/woRu/8KEbv/ChG76goRwMwKEcD/ChHA/woRwP8KEcD/EBfB/6Ol5/8tM8n/ChHA/woRwP8KEcD/ChHA/woRwP8KEcD/ChHA/woRwMwLEcSHCxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcT/CxHE/wsRxP8LEcSHCxLICQsSyKULEsjMCxLI+QsSyP8LEsj/CxLI/wsSyP8LEsj/CxLI/wsSyP8LEsj/CxLI0gsSyMwLEsiiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAD//wAA//8AAA=="
    },
    "os:Url": {
      "-type": "text/html",
      "-method": "GET",
      "-template": "http://www.youtube.com/results?search_query={searchTerms}&page={startPage?}&utm_source=opensearch"
    }
  }
}

Digging around in the code Pointers

    • http://jsontoxml.utilities-online.info/ convert between the two data formats
    • changes frequently dont show up immediate (but get written on close)
    • ordering in data store includes hidden engines. the number may not match the observed number
      • note in the example below all engines are off by 1 because google is order:1 and hidden, so youtube appears first in the list but has order:2
    • getting a 3rd party search thingy
      • right click on a website search bar (ie youtube) and /profile/searchplugins will be created with an OpenSearch .xml
      • searchplugins doesn't exist until you create a non-default one
    • SQLite table: install addon, go to tools -> SQLiteManager -> select db, go
    • default engines have a hidden value, which afaic, is never applied to custom engines?