https://wiki.mozilla.org/api.php?action=feedcontributions&user=Comrade693&feedformat=atomMozillaWiki - User contributions [en]2024-03-28T10:32:39ZUser contributionsMediaWiki 1.27.4https://wiki.mozilla.org/index.php?title=Auto-tools/Projects/OrangeFactor&diff=313457Auto-tools/Projects/OrangeFactor2011-05-27T17:54:58Z<p>Comrade693: /* How Tinderbox Stores Its Data */</p>
<hr />
<div>== Status ==<br />
<br />
We have weekly meetings! <br />
<br />
Wednesdays, 2PM PDT, 1-800-707-2533, PIN: 369, Conf# 304<br />
(or) 650-903-0800 ext: 92, Conf# 304 <br />
<br />
* [[Auto-tools/Projects/WarOnOrange/2010-11-03|November 3, 2010]]<br />
* [[Auto-tools/Projects/WarOnOrange/2010-10-20|October 20, 2010]]<br />
* [[Auto-tools/Projects/WarOnOrange/2010-10-13|October 13, 2010]]<br />
* [[Auto-tools/Projects/WarOnOrange/2010-09-22|September 22, 2010]]<br />
<br />
== Goals ==<br />
<br />
'''Primary Goal'''<br />
<br />
To develop a web dashboard that is useful for identifying and tracking the state of intermittent oranges in our tinderbox unit tests. This should help developers identify which oranges are most 'interesting', and should give people a notion of the overall state of oranges over time.<br />
<br />
'''Secondary Goals'''<br />
<br />
Since the implementation of the dashboard will require tinderbox failures be put into a database, we could potentially use this database in the tinderbox+pushlog UI, which would allow it to query data from a (fast) database, rather than parsing buildbot logs as it sometimes currently does.<br />
<br />
== History ==<br />
<br />
'''Topfails'''<br />
<br />
[http://brasstacks.mozilla.com/topfails/ Topfails] was the first database-driven orange tracker developed in our team. It shows failures in terms of overall occurrences. It suffers from a buggy log parser, and a UI with relatively few views.<br />
<br />
source: http://hg.mozilla.org/automation/topfails/<br />
<br />
'''Orange Factor'''<br />
<br />
[http://jmaher.couchone.com/orange_factor/_design/woo/orange.html Orange Factor] is a newer dashboard by jmaher. It calculates the average number of oranges per push (the 'orange factor'), and tracks that number over time. We're currently using it as a base to explore the usefulness of other statistics.<br />
<br />
source: http://github.com/jmaher/Orange-Factor<br />
<br />
[[Auto-tools/Projects/WarOnOrange/InstallationInstructions|Installation instructions]]<br />
<br />
[https://bugzilla.mozilla.org/buglist.cgi?resolution=---&component=Orange%20Factor&product=Testing bugs]<br />
<br />
== Architecture ==<br />
<br />
The system has several moving parts:<br />
<br />
* modifications to TBPL that write orange comments to a database<br />
<br />
* a [http://pulse.mozilla.org/ Mozilla Pulse] consumer that listens for buildbot messages that are generated when unit tests are finished<br />
<br />
* a unittest [http://hg.mozilla.org/automation/logparser/ logparser], that parses buildbot logs, and feeds the resulting data into ElasticSearch<br />
<br />
* an instance of [http://www.elasticsearch.org/ ElasticSearch], which is hosted by the Metrics team, that stores the parsed log data and the TBPL bug data<br />
<br />
* a [http://brasstacks.mozilla.com/orangefactor/ web dashboard] that pulls data from the database and displays various interesting statistics about it<br />
<br />
'''Note:''' The system no longer depends upon flume for writing data into ES. Instead, we use [https://github.com/aparo/pyes pyes], plus a helper library we've written on top of it, [http://hg.mozilla.org/automation/mozautoeslib/ mozautoeslib].<br />
<br />
== Making Oranges Interesting ==<br />
<br />
Currently, our intermittent oranges are not very interesting. After they've been identified, they are usually more-or-less ignored. This has caused us to accumulate oranges to the point where we have to deal with several of them for every commit (and by 'deal with', I mean 'log it and forget it'), which is time consuming for the sheriffs and for anyone who pushes a commit. At the same time, it demotivates any effort to actually fix them.<br />
<br />
We'd like to help change that. We think we can help by creating a dashboard to analyze oranges in the following ways:<br />
<br />
* identify the oranges that occur most frequently; these are the oranges that would produce the greatest improvement in our orange factor if fixed<br />
<br />
* identify significant changes in the frequency of a given orange; if a known intermittent orange suddenly begins to occur more frequently, it may be related to a recent code change, and this might give developers more information about when/why it occurred, which would hopefully help in fixing it<br />
<br />
* identify interesting patterns in failures; some failures may occur more frequently on certain OS's, build types, architectures, or other factors; by providing views which can track oranges across a range of factors, we might be able to provide developers with data that would help them reproduce failures or give them insight into their cause<br />
<br />
* identify overall trends in orange occurrences, already part of [http://jmaher.couchone.com/orange_factor/_design/woo/orange.html Orange Factor]; this can help track the 'orangeness' of a product over time, and can help measure the helpfulness of orange-fixing activities<br />
<br />
== Dashboard Views ==<br />
<br />
A list of dashboard views that may be interesting. We're currently using Orange Factor as a platform to experiment with views.<br />
<br />
* {{done|display}} of overall orange factor over time<br />
** do we need to be able display orange factor per OS, build type, etc?<br />
* {{done|display}} of failures/day, for a given failure<br />
* {{done|dipslay}} of failures/commit/day, for a given failure<br />
* {{ok|display}} of moving averages of the above<br />
** which moving averages are most useful?<br />
* display of failure frequencies which exceed certain limits (probably based on standard deviation)<br />
* display of most common failures, in aggregate, and separated by various factors: platform, OS version, architecture, build type, etc<br />
* other...?<br />
<br />
<br />
== Statistics ==<br />
<br />
The amount of information yielded from the parsed logs is vast. The raw data will be noisy and the trends will not be easily discerned. So statistical analysis should be used to manipulate the data and seek insight into trends.<br />
<br />
[[Auto-tools/Projects/WarOnOrange/Statistics|War On Orange Statistics]]<br />
<br />
== How Tinderbox Stores Its Data ==<br />
<br />
Tinderbox stores logs in the format<br />
<br />
1291054515.1291054887.26068.gz<br />
<br />
or<br />
<br />
xxx.yyy.zzz.gz<br />
<br />
where<br />
<br />
* xxx is approximately the time that buildbot picked up the test to run<br />
* yyy is the time the log was e-mailed to tinderbox<br />
* zzz is the pid of the perl process that processed the log ([https://mxr.mozilla.org/webtools/source/tinderbox/processbuild.pl#143 no really])<br />
<br />
Tinderbox maintains a list of bug->log associations at http://tinderbox.mozilla.org/Firefox/notes.txt. The format used therein is:<br />
<br />
1291056044|WINNT 5.2 mozilla-central debug test mochitests-2/5|jmathies@mozilla.com|1291059392|Bug%20614474<br />
<br />
or<br />
<br />
yyy|mmm|[user]|ttt|[bug #]<br />
<br />
where<br />
<br />
* yyy is the same as yyy above<br />
* mmm is a string representing the testrun, in a format which isn't in the raw buildbot log<br />
* ttt is the time that the bug was starred<br />
<br />
None of this data can be found in the raw buildbot logs themselves, although yyy is approximately the same as the timestamp of the logfile on stage.mozilla.org (they're not exact though, there is usually a few seconds difference between the time the log was e-mailed to tinderbox (yyy) and the time the log was copied to stage).<br />
<br />
== ElasticSearch Queries ==<br />
<br />
The log metadata is all stored in ElasticSearch, see the [[Auto-tools/Projects/WarOnOrange/ElasticSearch|ElasticSearch]] page for details on querying this database.<br />
<br />
== Attacking Oranges ==<br />
<br />
https://developer.mozilla.org/en/QA/Fixing_intermittent_oranges<br />
<br />
== REST API ==<br />
<br />
The War on Orange site pulls its data from a REST API. Other applications can hook into this to get the raw orange data.<br />
<br />
The API root is at http://brasstacks.mozilla.com/orangefactor/api/. Parameters are passed via the query string, eg. ?key1=value1&key2=value2. Example: http://brasstacks.mozilla.com/orangefactor/api/count?startday=2011-05-21&endday=2011-05-27&tree=mozilla-central<br />
<br />
All returned data is in JSON format.<br />
<br />
=== bybug ===<br />
<br />
Provides a date-indexed list of oranges, with bug numbers, along with minimal details of each bug.<br />
<br />
Parameters:<br />
* startday: Mandatory. In ISO format, e.g. 2011-05-27.<br />
* endday: Mandatory. Also in ISO format.<br />
* bugid: Optional. Return orange data for this bug only.<br />
* tree: Optional. Return information about this tree only. Defaults to mozilla-central. Pass "all" for orange data on all trees.<br />
* type: Optional. Return information for this build type only. Must be "opt" or "debug". Defaults to none (both build types).<br />
<br />
Returns an object with two properties:<br />
* oranges: An object with dates as properties, e.g. data['oranges']['2011-05-27']. Each property is another object with orange data for the day, with the following properties:<br />
** orangecount: total number of oranges for that day, e.g. 54.<br />
** testruns: number of test runs that day, e.g. 24. The "Orange Factor" is orangecount/testruns.<br />
** oranges: details of the oranges that occurred that day. It is an array of objects, each one having these simple properties:<br />
*** buildtype<br />
*** date<br />
*** starttime<br />
*** timestamp<br />
*** platform<br />
*** branch<br />
*** machinename<br />
*** test<br />
*** bug<br />
*** revision<br />
* bugs: An object with bug ids as properties. Each bug in the above list of oranges is represented here. The information is gathered via pulse and thus is quicker to access than querying Bugzilla. Only a few basic properties are available; for more detailed info, you will have to consult Bugzilla:<br />
** id<br />
** status<br />
** summary<br />
<br />
=== count ===<br />
<br />
Returns a date-indexed summary of orange data.<br />
<br />
The parameters are the same as for bybug. The returned data is also the same, except that the 'bugs' property is not returned, and the array of orange details (data['oranges'][<date>]['oranges']) is empty. This is a faster way to get just the summarized numerical data for, e.g., Orange Factor calculations.<br />
<br />
=== bugdetails ===<br />
<br />
Returns minimal details for one or more bugs.<br />
<br />
The only parameter is "bugid", which takes a bug id or a comma-separated list of bug ids.<br />
<br />
Returns the same data as the "bugs" property of the bybug returned data.<br />
<br />
=== testrun ===<br />
<br />
Returns information on one or more test runs.<br />
<br />
Parameters:<br />
<br />
The request can be made in one of two fashions. To get information about only one test run,<br />
<br />
* starttime: Unix timestamp of the run's start time.<br />
* machine: Hostname of the test machine.<br />
<br />
Or to get information on several,<br />
<br />
* runs: a comma-separated list of timestamps and machines, in the form <timestamp>|<machine>,<timestamp>|<machine>, eg testrun?runs=1297070365|talos-r3-leopard-012,1295484366|talos-r3-xp-037<br />
<br />
Returns an object with properties in the form '<timestamp>|<machine>' (regardless of which parameter format was used). Each property has an array of matching test runs, with these properties:<br />
<br />
* tree<br />
* passed/failed/todo: the number of tests in each category; may be missing for testruns that never completed due to crashes, etc<br />
* elapsedtime: number of seconds it took for the testrun to complete<br />
* suitename<br />
* builder: the buildbot builder string<br />
* machine: the machine name<br />
* cmdline: the command line used to invoke the test<br />
* buildtype: opt or debug<br />
* platform: buildbot platform string<br />
* date: date the testrun was run, YYYY-MM-DD<br />
* buildid: the buildbot buildid used to run the test<br />
* revision: the hg revision used to run the test<br />
* testfailure_count: the number of failing tests in this testrun.<br />
* testrunerrors: an array of errors that could not be pinned to a specific test; these are usually memory leaks or crashes that occur at the end of a testrun. these errors are not included in 'testfailure_count'<br />
* testfailures: an array of testfailures which is testfailure_count in length; each member of this array has two keys:<br />
* test: the name of the test that failed<br />
* failures: a list of failures that occurred<br />
* logurl: URL to the complete test log.</div>Comrade693https://wiki.mozilla.org/index.php?title=Modules/Desktop_Firefox&diff=303539Modules/Desktop Firefox2011-04-27T21:00:28Z<p>Comrade693: Change my e-mail address.</p>
<hr />
<div>{{Module<br />
|name=Firefox<br />
|description=Standalone Web Browser<br />
|owner=[mailto:shaver@mozilla.org Mike Shaver]<br />
|peers=[mailto:dietrich@mozilla.com Dietrich Ayala], [mailto:dolske@mozilla.com Justin Dolske], [mailto:gavin@gavinsharp.com Gavin Sharp], [mailto:dtownsend@mozilla.com Dave Townsend], [mailto:vladimir@pobox.com Vladimir Vukicevic], [mailto:me@shawnwilsher.com Shawn Wilsher]<br />
|group=dev-apps-firefox<br />
|source_dirs=browser/, other-licenses/branding/firefox/<br />
|url=http://www.mozilla.org/projects/firefox/<br />
|components=<br />
}}<br />
<br />
===Sub Modules===<br />
<br />
{{Module<br />
|name=General UI bits<br />
|description=<br />
|owner=[mailto:gavin@gavinsharp.com Gavin Sharp]<br />
|peers=[mailto:dao@mozilla.com Dão Gottwald], [mailto:aromano@mozilla.com Asaf Romano]<br />
|source_dirs=browser/base/content, browser/components<br />
|components=Firefox::General<br />
}}<br />
<br />
{{Module<br />
|name=Build & Startup bits<br />
|description=<br />
|owner=[mailto:benjamin@smedbergs.us Benjamin Smedberg]<br />
|peers=[mailto:aromano@mozilla.com Asaf Romano], [mailto:gavin@gavinsharp.com Gavin Sharp]<br />
|source_dirs=browser/app, browser/components/nsBrowserContentHandler.js<br />
|components=Firefox::Build Config<br />
}}<br />
<br />
{{Module<br />
|name=Feed Preview<br />
|description=<br />
|owner=[mailto:aromano@mozilla.com Asaf Romano]<br />
|peers=[mailto:gavin@gavinsharp.com Gavin Sharp], [mailto:sayrer@mozilla.com Robert Sayre]<br />
|source_dirs=browser/components/feeds<br />
|components=Firefox::RSS Discovery and Preview<br />
}}<br />
<br />
{{Module<br />
|name=Installer<br />
|description=<br />
|owner=[mailto:rstrong@mozilla.com Robert Strong]<br />
|peers=[mailto:jmathies@mozilla.com Jim Mathies], [mailto:benjamin@smedbergs.us Benjamin Smedberg]<br />
|source_dirs=browser/installer<br />
|components=Firefox::Installer<br />
}}<br />
<br />
{{Module<br />
|name=Panorama<br />
|description=<br />
|owner=[mailto:ian@iangilman.com Ian Gilman]<br />
|peers=[mailto:aza@mozilla.com Aza Raskin]<br />
|source_dirs=browser/base/content/tabview<br />
|components=Firefox::tabcandy<br />
}}<br />
<br />
{{Module<br />
|name=Places<br />
|description=<br />
|owner=[mailto:dietrich@mozilla.com Dietrich Ayala]<br />
|peers=[mailto:mbonardo@mozilla.com Marco Bonardo], [mailto:aromano@mozilla.com Asaf Romano], [mailto:sdwilsh@forerunnerdesigns.com Shawn Wilsher]<br />
|source_dirs=browser/components/places, browser/components/microsummaries, browser/base/content (places-related code)<br />
|components=Toolkit::Places, Firefox::Bookmarks & History<br />
}}<br />
<br />
{{Module<br />
|name=Preferences Window<br />
|description=<br />
|owner=[mailto:gavin@gavinsharp.com Gavin Sharp]<br />
|peers=[mailto:dao@mozilla.com Dão Gottwald], [mailto:rstrong@mozilla.com Robert Strong], [mailto:aromano@mozilla.com Asaf Romano]<br />
|source_dirs=browser/components/preferences<br />
|components=Firefox::Preferences<br />
}}<br />
<br />
{{Module<br />
|name=Private Browsing<br />
|description=<br />
|owner=[mailto:ehsan@mozilla.com Ehsan Akhgari]<br />
|peers=<br />
|source_dirs=browser/components/privatebrowsing <br />
|components=Firefox::Private Browsing<br />
}}<br />
<br />
{{Module<br />
|name=Profile Migrators<br />
|description=<br />
|owner=[mailto:gavin@gavinsharp.com Gavin Sharp]<br />
|peers=[mailto:aromano@mozilla.com Asaf Romano]<br />
|source_dirs=browser/components/migration<br />
|components=Firefox::Migration<br />
}}<br />
<br />
{{Module<br />
|name=Safe Browsing<br />
|description=<br />
|owner=[mailto:tony@ponderer.org Tony Chang]<br />
|peers=[mailto:johnath@mozilla.com Johnathan Nightingale], [mailto:gavin@gavinsharp.com Gavin Sharp]<br />
|source_dirs=browser/components/safebrowsing<br />
|components=Firefox::Phishing Protection<br />
}}<br />
<br />
{{Module<br />
|name=Search<br />
|description=<br />
|owner=[mailto:rflint@mozilla.com Ryan Flint]<br />
|peers=[mailto:gavin@gavinsharp.com Gavin Sharp]<br />
|source_dirs=browser/components/search<br />
|components=Firefox::Search<br />
}}<br />
<br />
{{Module<br />
|name=Security UI<br />
|description=<br />
|owner=[mailto:johnath@mozilla.com Johnathan Nightingale]<br />
|peers=[mailto:gavin@gavinsharp.com Gavin Sharp]<br />
|source_dirs=browser/components/certerror, browser/base/content (SSL/security/privacy-related code)<br />
|components=Firefox::Security<br />
}}<br />
<br />
{{Module<br />
|name=Session Restore<br />
|description=<br />
|owner=[mailto:dietrich@mozilla.com Dietrich Ayala]<br />
|peers=[mailto:zeniko@gmail.com Simon Bünzli], [mailto:aromano@mozilla.com Asaf Romano], [mailto:gavin@gavinsharp.com Gavin Sharp]<br />
|source_dirs=browser/components/sessionstore<br />
|components=Firefox::Session Restore<br />
}}<br />
<br />
{{Module<br />
|name=Shell Service<br />
|description=<br />
|owner=[mailto:aromano@mozilla.com Asaf Romano]<br />
|peers=[mailto:rstrong@mozilla.com Robert Strong], [mailto:gavin@gavinsharp.com Gavin Sharp]<br />
|source_dirs=browser/components/shell<br />
|components=Firefox::Shell Integration<br />
}}<br />
<br />
{{Module<br />
|name=Themes<br />
|description=<br />
|owner=[mailto:dao@mozilla.com Dão Gottwald]<br />
|peers=[mailto:rflint@mozilla.com Ryan Flint], [mailto:gavin@gavinsharp.com Gavin Sharp]<br />
|source_dirs=browser/themes<br />
|components=Firefox::Theme<br />
}}<br />
<br />
<noinclude><br />
===Unassigned Bugzilla Components===<br />
<br />
The following Bugzilla components in the Firefox project have not been assigned to a module:<br />
<br />
<pre><br />
Firefox::Account Manager<br />
Firefox::Developer Tools<br />
Firefox::Disability Access<br />
Firefox::Extension Compatibility<br />
Firefox::File Handling<br />
Firefox::Help Documentation<br />
Firefox::Keyboard Navigation<br />
Firefox::Location Bar<br />
Firefox::Menus<br />
Firefox::Microsummaries<br />
Firefox::Page Info<br />
Firefox::TabCandy<br />
Firefox::Tabbed Browser<br />
Firefox::Toolbars<br />
</pre><br />
</noinclude></div>Comrade693https://wiki.mozilla.org/index.php?title=Features/Release_Tracking&diff=298484Features/Release Tracking2011-04-13T21:25:17Z<p>Comrade693: /* Desktop */</p>
<hr />
<div>Firefox Flight Tracking page, wherein each release gets a table, and each table is made up of table rows transcluded in from [[Feature Page Structure|feature pages]] (which are listed on the [[Features|Features List]]). ''Nothing here is necessarily final. If you have questions or would like to make changes, contact Deb (deb at mozilla.com).''<br />
<br />
== Firefox 5 ==<br />
=== Desktop ===<br />
{| class="fullwidth-table sortable" style="width: 800px;"<br />
|-<br />
| style="font-weight: bold; background: #DDD; width:35%" | Feature<br />
| style="font-weight: bold; background: #DDD; width:35%" | Status<br />
| style="font-weight: bold; background: #DDD; width:10%" | ETA<br />
| style="font-weight: bold; background: #DDD; width:20%" | Owner<br />
|-<br />
{{#lst:ChannelSwitching/ChannelSwitchingFeature|status}}<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=645288 Associate the webm file extension with Firefox]<br />
| landed <br />
| Fx5 <br />
| Jim Mathies<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=645063 Move Do-not-track setting to the Privacy pane] <br />
| landed <br />
| Fx5 <br />
| Sid Stamm<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=610208 When closing a tab in Panorama, don't immediately resize other tabs] <br />
| landed <br />
| Fx5 <br />
| Tim Taubert<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=627651 Improve smooth scrolling animation] <br />
| landed <br />
| Fx5 <br />
| Alex Faaborg<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=623495 Improve Hebrew font rendering on OS X]<br />
| landed <br />
| Fx5 <br />
| Jonathan Kew<br />
|-<br />
| Change in Keep-alive syntax<br />
| landed<br />
| Fx5 <br />
| Someone<br />
|-<br />
| SYN re-try<br />
| landed<br />
| Fx5 <br />
| Someone<br />
|-<br />
| HTTP Transactions sorted by CWND<br />
| landed<br />
| Fx5 <br />
| Someone<br />
|-<br />
| Content-Disposition changes<br />
| landed<br />
| Fx5 <br />
| Someone<br />
|-<br />
| CSS Animations<br />
| landed<br />
| Fx5 <br />
| Someone<br />
|-<br />
| Framerate & stats on video elements<br />
| landed<br />
| Fx5 <br />
| Someone<br />
|-<br />
| PGO 10% win on SS<br />
| landed<br />
| Fx5 <br />
| Someone<br />
|-<br />
| setTimeout now 4ms<br />
| landed<br />
| Fx5 <br />
| Someone<br />
|-<br />
| setTimeout in background tabs (614733 & 633421)<br />
| landed<br />
| Fx5 <br />
| Someone<br />
|-<br />
| make mozRequestAnimationFrame much smoother with large callback functions<br />
| landed<br />
| Fx5 <br />
| Someone<br />
|-<br />
| significant querySelector speedup <br />
| landed<br />
| Fx5 <br />
| Someone<br />
|-<br />
| better memory reporting for SQLite databases {{bug|615978}}<br />
| landed<br />
| Fx5<br />
| sdwilsh<br />
|}<br />
<br />
=== Mobile ===<br />
<br />
{| style="width: 800px;" class="fullwidth-table sortable"<br />
|-<br />
| style="font-weight: bold; background: #DDD; width:35%" | Feature <br />
| style="font-weight: bold; background: #DDD; width:35%" | Status <br />
| style="font-weight: bold; background: #DDD; width:10%" | ETA <br />
| style="font-weight: bold; background: #DDD; width:20%" | Owner<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=607417 Reconcile position:fixed with async scrolling (improved position:fixed support)] <br />
| landed <br />
| Fx5 <br />
| Thomas<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=646550 Tell Android to scan media items downloaded by Fennec] <br />
| landed <br />
| Fx5 <br />
| Thomas<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=610784 Handle overflow in the Android menu (adds a "More" button when needed)] <br />
| landed <br />
| Fx5 <br />
| Thomas<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=641014 Fix broken NEON Y'CbCr to RGB conversion (fixed color conversion)] <br />
| landed <br />
| Fx5 <br />
| Thomas<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=648268 Add remoteXUL strings for Firefox Mobile (recent breakage)] <br />
| landed <br />
| Fx5 <br />
| Thomas<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=561694 e10s HTTP: Implement nsIProgressEventSink: part2 (slightly faster pageloads, especially on 3g)] <br />
| landed <br />
| Fx5 <br />
| Thomas<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=648654 Add user-visible pref for Do Not Track (just adds the UI)] <br />
| landed<br />
| Fx5 <br />
| Thomas<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=618989 Finish new theme styles for dialogs/prompts (prompts and confirms look like android dialogs)] <br />
| landed <br />
| Fx5 <br />
| Thomas<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=639179 Consecutive pans are jumpy] <br />
| landed <br />
| Fx5 <br />
| Thomas<br />
|-<br />
| [https://bugzilla.mozilla.org/show_bug.cgi?id=614355 don't use fullscreen landscape keyboards on android] <br />
| landed <br />
| Fx5 <br />
| Thomas<br />
|}<br />
<br />
=== Jetpack ===<br />
{| class="fullwidth-table sortable" style="width: 800px;"<br />
|-<br />
| style="font-weight: bold; background: #DDD; width:35%" | Feature<br />
| style="font-weight: bold; background: #DDD; width:35%" | Status<br />
| style="font-weight: bold; background: #DDD; width:10%" | ETA<br />
| style="font-weight: bold; background: #DDD; width:20%" | Owner<br />
|-<br />
| Create Firefox Add-ons using standard web programming skills<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| APIs to cover at least 80% of all Add-on use-cases<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| Automatic testing of add-ons<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| Automatic packaging of add-ons<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| Full documentation & tutorial<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| API: Access to System Clipboard<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| API: Create New Context Menu Items<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| API: Create toaster-style notifications<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| API: Create new Keyboard shortcuts for features<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| API: Execute scripts on web pages to modify page content<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| API: Create pop-up dialogs, or panels<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| API: Store and access creditials/passwords for webpages or the add-on<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| API: Access Firefox's private browsing mode<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| API: Make network requests<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| API: Simple storage to persist data across restarts<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| API: Access tabs or windows and their events<br />
| landed<br />
| JP1.0<br />
| --<br />
|-<br />
| API: Clean widget creation that blends in well with Firefox<br />
| landed<br />
| JP1.0<br />
| --<br />
|}<br />
<br />
== Firefox 6 ==<br />
=== Desktop ===<br />
{| class="fullwidth-table sortable" style="width: 800px;"<br />
|-<br />
| style="font-weight: bold; background: #DDD; width:35%" | Feature<br />
| style="font-weight: bold; background: #DDD; width:35%" | Status<br />
| style="font-weight: bold; background: #DDD; width:10%" | ETA<br />
| style="font-weight: bold; background: #DDD; width:20%" | Owner<br />
|-<br />
{{#lst:Firefox/Features/50ms_ASSERT|status}}<br />
|-<br />
{{#lst:DevTools/Features/Workspaces|status}}<br />
|-<br />
{{#lst:Extension Manager:Projects:Confirm on Upgrade|status}}<br />
|-<br />
{{#lst:Labs/F1/Feature Blocks/F1|status}}<br />
|}<br />
<br />
=== Mobile ===<br />
{| class="fullwidth-table sortable" style="width: 800px;"<br />
|-<br />
| style="font-weight: bold; background: #DDD; width:35%" | Feature<br />
| style="font-weight: bold; background: #DDD; width:35%" | Status<br />
| style="font-weight: bold; background: #DDD; width:10%" | ETA<br />
| style="font-weight: bold; background: #DDD; width:20%" | Owner<br />
|-<br />
| <br />
|<br />
|<br />
|<br />
|}<br />
<br />
== Firefox 7 ==<br />
TBD<br />
<br />
== Legend ==<br />
{| class="fullwidth-table"<br />
|-<br />
| {{StatusHealthy|status=&nbsp;}}<br />
| Healthy: feature is progressing as expected.<br />
|-<br />
| {{StatusBlocked|status=&nbsp;}}<br />
| Blocked: feature is currently blocked.<br />
|-<br />
| {{StatusAtRisk|status=&nbsp;}}<br />
| At Risk: feature is at risk of missing its targeted release.<br />
|- <br />
| '''ETA'''<br />
| Estimated date for completion of the current feature task. Overall ETA for the feature is the product release date.<br />
|}<br />
<br />
__NOTOC__</div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=295761LandingQueue2011-03-31T22:54:33Z<p>Comrade693: </p>
<hr />
<div>'''Check with the sheriff in #developers if you have any questions.''' <br />
<br />
Staggering landings every 20 minutes!<br />
<br />
{{Queue|<br />
{{QueueEntry<br />
|name=peterv<br />
|bugs={{bug|626262}},{{bug|603844}},{{bug|607721}},{{bug|617247}},{{bug|637116}}<br />
|approval=sdwilsh @ 4:20 PDT<br />
|available=anytime today<br />
}}<br />
{{QueueEntry<br />
|name=cjones<br />
|bugs={{bug|577899}}<br />
|approval=<br />
|available=all day<br />
}}<br />
{{QueueEntry<br />
|name=your name<br />
|bugs={{bug|######}}<br />
|approval=pending<br />
|available=time zone and time of day<br />
}}<br />
}}</div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=295731LandingQueue2011-03-31T22:12:11Z<p>Comrade693: </p>
<hr />
<div>'''Check with the sheriff in #developers if you have any questions.''' <br />
<br />
Staggering landings every 20 minutes!<br />
<br />
{{Queue|<br />
{{QueueEntry<br />
|name=cpearce<br />
|bugs={{bug|646766}},{{bug|646819}},{{bug|640935}},{{bug|646682}},{{bug|644045}}<br />
|approval=sdwilsh @ 3:30 PDT<br />
|available=anytime today, now's good.<br />
}}<br />
{{QueueEntry<br />
|name=peterv<br />
|bugs={{bug|626262}},{{bug|603844}},{{bug|607721}},{{bug|617247}}<br />
|approval=pending<br />
|available=anytime today<br />
}}<br />
{{QueueEntry<br />
|name=your name<br />
|bugs={{bug|######}}<br />
|approval=pending<br />
|available=time zone and time of day<br />
}}<br />
}}</div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=295730LandingQueue2011-03-31T22:11:34Z<p>Comrade693: </p>
<hr />
<div>'''Check with the sheriff in #developers if you have any questions.''' <br />
<br />
Staggering landings every 20 minutes!<br />
<br />
{{Queue|<br />
{{QueueEntry<br />
|name=cpearce<br />
|bugs={{bug|646766}},{{bug|646819}},{{bug|640935}},{{bug|646682}},{{bug|644045}}<br />
|approval=sdwilsh @ 3:20 PDT<br />
|available=anytime today, now's good.<br />
}}<br />
{{QueueEntry<br />
|name=peterv<br />
|bugs={{bug|626262}},{{bug|603844}},{{bug|607721}},{{bug|617247}}<br />
|approval=pending<br />
|available=anytime today<br />
}}<br />
{{QueueEntry<br />
|name=your name<br />
|bugs={{bug|######}}<br />
|approval=pending<br />
|available=time zone and time of day<br />
}}<br />
}}</div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=295724LandingQueue2011-03-31T21:55:11Z<p>Comrade693: </p>
<hr />
<div>'''Check with the sheriff in #developers if you have any questions.''' <br />
<br />
Staggering landings every 20 minutes!<br />
<br />
{{Queue|<br />
{{QueueEntry<br />
|name=roc<br />
|bugs={{bug|617539}},{{bug|641770}},{{bug|644832}},{{bug|635373}},{{bug|622072}}<br />
|approval=sdwilsh<br />
|available=anytime today<br />
}}<br />
{{QueueEntry<br />
|name=cpearce<br />
|bugs={{bug|646766}},{{bug|646819}},{{bug|640935}},{{bug|646682}},{{bug|644045}}<br />
|approval=pending<br />
|available=anytime today, now's good.<br />
}}<br />
{{QueueEntry<br />
|name=peterv<br />
|bugs={{bug|626262}},{{bug|603844}},{{bug|607721}},{{bug|617247}}<br />
|approval=pending<br />
|available=anytime today<br />
}}<br />
{{QueueEntry<br />
|name=your name<br />
|bugs={{bug|######}}<br />
|approval=pending<br />
|available=time zone and time of day<br />
}}<br />
}}</div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=295691LandingQueue2011-03-31T21:10:39Z<p>Comrade693: </p>
<hr />
<div>'''Check with the sheriff in #developers if you have any questions.''' <br />
<br />
Staggering landings every 20 minutes!<br />
<br />
{{Queue|<br />
{{QueueEntry<br />
|name=roc<br />
|bugs={{bug|617539}},{{bug|641770}},{{bug|644832}},{{bug|635373}},{{bug|622072}}<br />
|approval=sdwilsh @ 2:30 PDT<br />
|available=anytime today<br />
}}<br />
{{QueueEntry<br />
|name=cpearce<br />
|bugs={{bug|646766}},{{bug|646819}},{{bug|640935}},{{bug|646682}},{{bug|644045}}<br />
|approval=sdwilsh @ 2:55 PDT<br />
|available=anytime today, now's good.<br />
}}<br />
{{QueueEntry<br />
|name=your name<br />
|bugs={{bug|######}}<br />
|approval=sheriff<br />
|available=time zone and time of day<br />
}}<br />
}}</div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=295661LandingQueue2011-03-31T19:52:11Z<p>Comrade693: </p>
<hr />
<div>'''Check with the sheriff in #developers if you have any questions.''' <br />
<br />
Staggering landings every 20 minutes!<br />
<br />
{{Queue|<br />
{{QueueEntry<br />
|name=your name<br />
|bugs={{bug|######}}<br />
|approval=sheriff<br />
|available=time zone and time of day<br />
}}<br />
}}</div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=295633LandingQueue2011-03-31T19:06:41Z<p>Comrade693: </p>
<hr />
<div>'''Check with the sheriff in #developers if you have any questions.''' <br />
<br />
Staggering landings every 20 minutes!<br />
<br />
{{Queue|<br />
{{QueueEntry<br />
|name=your name<br />
|bugs={{bug|######}}<br />
|approval=sheriff<br />
|available=time zone and time of day<br />
}}<br />
{{QueueEntry<br />
|name=cjones<br />
|bugs={{bug|645263}} {{bug|646259}}<br />
|approval=<br />
|available=all day<br />
}}<br />
{{QueueEntry<br />
|name=bzbarsky<br />
|bugs={{bug|610077}} {{bug|646912}} {{bug|646850}}<br />
|approval=sdwilsh<br />
|available=Until about 1:30 Pacific<br />
}}}}</div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=295623LandingQueue2011-03-31T18:48:08Z<p>Comrade693: </p>
<hr />
<div>'''Check with the sheriff in #developers if you have any questions.''' <br />
<br />
Staggering landings every 20 minutes!<br />
<br />
{{Queue|<br />
{{QueueEntry<br />
|name=your name<br />
|bugs={{bug|######}}<br />
|approval=sheriff<br />
|available=time zone and time of day<br />
}}<br />
{{QueueEntry<br />
|name=mwu<br />
|bugs={{bug|637286}}<br />
|approval=sdwilsh<br />
|available=PDT 1-5pm<br />
}}<br />
{{QueueEntry<br />
|name=josh<br />
|bugs={{bug|596078}}<br />
|approval=sdwilsh<br />
|available=all day<br />
}}<br />
{{QueueEntry<br />
|name=cjones<br />
|bugs={{bug|645263}} {{bug|646259}}<br />
|approval=<br />
|available=all day<br />
}}<br />
{{QueueEntry<br />
|name=bzbarsky<br />
|bugs={{bug|610077}} {{bug|646912}} {{bug|646850}}<br />
|approval=<br />
|available=Until about 1:30 Pacific<br />
}}}}</div>Comrade693https://wiki.mozilla.org/index.php?title=Talk:Modules/All&diff=286946Talk:Modules/All2011-02-25T17:17:26Z<p>Comrade693: Some directories don't have a module. Starting a place to keep this list.</p>
<hr />
<div>== Unknown Modules ==<br />
The following directories do not have any representation in any module:<br />
<br />
If someone could go ahead and place these in the right module, it would be greatly appreciated!</div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=280707LandingQueue2011-01-28T00:03:23Z<p>Comrade693: </p>
<hr />
<div>'''Check with the sheriff in #developers if you have any questions.''' <br />
<br />
Staggering landings every 20 minutes!<br />
<br />
{{Queue|<br />
{{QueueEntry<br />
|name=fryn<br />
|bugs=Panorama fix ({{bug|628165}}) and Work Offline fix ({{bug|620472}} and {{bug|627332}})<br />
|approval=blocking and approval2.0+<br />
|available=pacific afternoon/evening (16:15 PST)<br />
}}<br />
{{QueueEntry<br />
|name=jdaggett<br />
|bugs=dwrite font topcrasher ({{bug|628152}})<br />
|approval=blocking and topcrasher<br />
|available=afternoon/evening (16:35 PST)<br />
}}<br />
{{QueueEntry<br />
|name=iangilman<br />
|bugs=Panorama bugs ({{bug|627239}}, {{bug|628165}}, {{bug|612470}}, {{bug|620762}}, {{bug|628867}}, {{bug|609163}}, {{bug|628620}})<br />
|approval=blocking / approval2.0+<br />
|available=Pacific Afternoon (16:55 PST)<br />
}}<br />
}}</div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=280614LandingQueue2011-01-27T20:27:40Z<p>Comrade693: </p>
<hr />
<div>'''Check with the sheriff in #developers if you have any questions.''' <br />
<br />
{{Queue|<br />
{{QueueEntry<br />
|name=Mossop<br />
|bugs=Add-ons manager blockers {{bug|629237}} {{bug|628703}}<br />
|approval=blocking<br />
|available=morning/afternoon<br />
}}<br />
{{QueueEntry<br />
|name=rstrong<br />
|bugs=App Update fixes ({{bug|524294}} and {{bug|628829}} followup) and a Win7 jump list fix ({{bug|629275}})<br />
|approval=blocking and approval2.0<br />
|available=morning/afternoon<br />
}}<br />
{{QueueEntry<br />
|name=bent<br />
|bugs=Java fix ({{bug|563891}}<br />
|approval=blocking<br />
|available=morning/afternoon<br />
}}}}</div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=280559LandingQueue2011-01-27T19:01:58Z<p>Comrade693: </p>
<hr />
<div>'''Check with the sheriff in #developers if you have any questions.''' <br />
<br />
{{Queue|<br />
{{QueueEntry<br />
|name=sdwilsh<br />
|bugs=places branch<br />
|approval=blocking<br />
|available=morning/afternoon<br />
}}<br />
}}</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=270618Places/AsyncAPIsForSync2010-11-29T23:28:04Z<p>Comrade693: /* Predecessor */ alternate proposal</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronous Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
readonly long long frecency;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark. These are item annotations from nsIAnnotationService.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertItem ===<br />
<br />
/**<br />
* Inserts a bookmark item. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertItem(in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertItems ===<br />
<br />
/**<br />
* Inserts many bookmark items. Just like insertItem otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertItems([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateItem ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark item. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateItem(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateItems ===<br />
<br />
/**<br />
* Updates many bookmark items. Just like updateItem otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateItems([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
=== No need for "plural" methods ===<br />
Due to the way Sync engines work, we have no need for the batch operation methods (insertBookmarks, updateItems) as we deal with each bookmark record individually. We're running this in batchmode anyway. --philikon<br />
<br />
We didn't want runInBatchMode to have magic flags that deal with these async methods. Shouldn't be a problem for the Sync team to deal with this new way. --sdwilsh<br />
<br />
So the bookmarks store will just accumulate the incoming objects in memory and then the bookmarks engine, at the end of _processIncoming(), will flush the records to disk, using the async call. To avoid hogging too much memory when lots of bookmarks are involved, the store should flush after a certain number of records have accumulated as well. 50 seems like a good number since that's incidentally also the batch size for network fetches on mobile. --philikon<br />
<br />
=== Types of places items covered ===<br />
<br />
Just so we're on the same page, these are the data types Sync supports:<br />
* bookmarks (TYPE_BOOKMARK)<br />
* folders (TYPE_FOLDER)<br />
* separators (TYPE_SEPARATOR)<br />
* microsummary (TYPE_BOOKMARK with microsummary)<br />
* livemark (TYPE_FOLDER that's a livemark)<br />
* query (TYPE_BOOKMARK with a place: URI)<br />
Note that Sync does not support "dynamic containers" (TYPE_DYNAMIC_CONTAINER). --philikon<br />
<br />
We don't care about dynamic containers so far, mainly because the API lies and they just don't work. --mak<br />
<br />
All these are covered, but you may have to roll your own way with annotations. --sdwilsh<br />
<br />
To eloborate: microsummaries and livemarks are regular bookmarks and folders, respectively, with some annotations added to them. So instead of going through their APIs we're just going to add the necessary annotations. We might want to expose some of the internal constants these services use via their interfaces so that we don't have to copy & paste them. --philikon<br />
<br />
=== Interfaces ===<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
Dietrich suggested to just do a AsyncBookmarks.jsm module, and completely drop xpcom. I mostly agree, this interface is not going to have cpp users, and we are also making it hard for cpp users (the arrays and so on...). We'd just need some private interface in nsPIPlacesDatabase to forward notifications. What would block us from doing that? --mak<br />
<br />
=== Parent Name===<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
Having the parent name in there feels awkward but it would make our code much easier while making the places code only slightly more complicated (I hope). I will have to think about alternatives to our current duping algorithm, but there's probably little alternative to having it match folder names. --philikon<br />
<br />
Decision: keep the parentName. --sdwilsh<br />
<br />
=== Predecessor ===<br />
<br />
This is similar to the parent name issue: In order to preserve ordering, Sync maintains the GUID of an item's predecessor in each record. So it'd be good if nsIBookmarkInfo were to contain that info. Bonus points for making <code>updateItem</code> understand this and move the item appropriately. --philikon<br />
<br />
We'd like to just keep it at itemIndex, due to more complicated queries or more queries. philikon says it's possible, but will follow up. --sdwilsh<br />
<br />
It's possible but all options I can think of will require serious change:<br />
# We could make bookmarks have the itemIndex instead of predecessorid. However, adding a new bookmark in a folder or moving a bookmark would invalidate a lot of other bookmarks, potentially even all, in that folder.<br />
# We could store the predecessor GUID in annotations since we now have async APIs for querying and storing these. But we would have to ensure that this annotation exists on all bookmarks first which would mean a lot of I/O on first sync, pretty much exactly the same kind of I/O that we have to do for GUIDs right now.<br />
# Instead of maintaining the ordering on the bookmarks, maintain it on their folders. Inserting or moving a bookmark would invalidate one more object, its folder (as opposed to its successor as it does now). This would mean having a childrenGUIDs array on nsIBookmarkInfo that would get/set the order of a folder's children.<br />
Both option 1 and 3 would mean a version bump for the bookmark storage. These are similarly problematic as global storage version bumps. Fortunately, we're doing one very very soon, so we could just move to the new bookmark storage version now so that it's in place when we get the async APIs.<br />
I'm personally leaning towards option 3 --philikon<br />
<br />
Changing bookmarks table to drop position could not be that easy, I have to check, but iirc we rely pretty much on that positioning and on it not having "holes". So if that's the idea, we have to be cautious here, if the "bookmark storage" is something on Sync side, then nevermind! --mak<br />
<br />
Yes, "bookmark storage" is a Sync component. --philikon<br />
<br />
Alternate proposal: Sync adds an annotation on the folder containing the list of guids (in order). This results in no extra API frontage and solves all current issues. --sdwilsh<br />
<br />
=== Tags ===<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
We explicitly ignore the tags folder right now, so it doesn't magically work. Sync uses the tagging service API explicitly. So either we should perhaps start syncing the tags folder (if that does indeed magically work) or nsIBookmarkInfo should contain the tags. --philikon<br />
<br />
OK, we could add a getBookmarkInfoWithTags (or have another argument to getBookmarkInfo) that could obtain tags too. Syncing the bookmarg tags folder wouldn't work out right for things like the iphone client. --sdwilsh<br />
<br />
Take in count in future tags will have to move out of bookmarks folders/table to their own storage, thus it is not sane to request syncs of the tags root. What Sync does using taggign service is correct. Not working here though since it's sync. What's the cost of just returning tags always? If I use this interface is pretty clear I want to know EVERYTHING on a bookmark. --mak<br />
<br />
=== nsIBookmarkInfo readonly ===<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly. --mak<br />
<br />
It shouldn't matter. We don't have to return the same nsIBookmarkInfo object that we are passed in (in fact, for threadsafety reasons, we shouldn't!) --sdwilsh<br />
<br />
=== Query by URI ===<br />
<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
Pretty sure we don't have any need for querying bookmarks by URI. --philikon<br />
<br />
Let's just drop support for querying on URI. --sdwilsh<br />
<br />
I guess mobile could find querying by uri useful instead... but we can fix this later. --mak<br />
<br />
=== Missing attributes ignored on update ===<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
<code>updateItem({id:2}, {guid:"GUID_HERE"});</code><br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
Yes, it would be great if missing properties on the nsIBookmarkInfo object would simply be ignored in the update. The same should go for annotations. This means that this API wouldn't allow us to remove annotations, but that's ok since we have no need for it. But we do avoid having to first get all the information before updating it. --philikon<br />
<br />
This shouldn't be a problem. We can add an API in the future for removal of data, but we do not need to in this cycle (2.0). --sdwilsh<br />
<br />
=History=<br />
<br />
[[Places/AsyncAPIsForSync/History|See the full spec]]<br />
<br />
= Input History =<br />
<br />
Turns out we want to sync input history too, see {{bug|597874}}. It would be great if we could add the following to <code>nsIPlaceInfo</code>:<br />
<br />
/**<br />
* An array of nsIInputHistory objects for the place.<br />
*/<br />
readonly nsIVariant inputs;<br />
<br />
with <code>nsIInputHistory</code>:<br />
<br />
interface nsIInputHistory : nsISupports<br />
{<br />
ACString input;<br />
double use_count;<br />
}</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=268688Places/AsyncAPIsForSync2010-11-18T06:17:30Z<p>Comrade693: /* Detailed Proposal */ Tweak heading so links work to it</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
readonly long long frecency;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark. These are item annotations from nsIAnnotationService.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertItem ===<br />
<br />
/**<br />
* Inserts a bookmark item. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertItem(in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertItems ===<br />
<br />
/**<br />
* Inserts many bookmark items. Just like insertItem otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertItems([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateItem ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark item. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateItem(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateItems ===<br />
<br />
/**<br />
* Updates many bookmark items. Just like updateItem otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateItems([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
=== No need for "plural" methods ===<br />
Due to the way Sync engines work, we have no need for the batch operation methods (insertBookmarks, updateItems) as we deal with each bookmark record individually. We're running this in batchmode anyway. --philikon<br />
<br />
We didn't want runInBatchMode to have magic flags that deal with these async methods. Shouldn't be a problem for the Sync team to deal with this new way. --sdwilsh<br />
<br />
So the bookmarks store will just accumulate the incoming objects in memory and then the bookmarks engine, at the end of _processIncoming(), will flush the records to disk, using the async call. To avoid hogging too much memory when lots of bookmarks are involved, the store should flush after a certain number of records have accumulated as well. 50 seems like a good number since that's incidentally also the batch size for network fetches on mobile. --philikon<br />
<br />
=== Types of places items covered ===<br />
<br />
Just so we're on the same page, these are the data types Sync supports:<br />
* bookmarks (TYPE_BOOKMARK)<br />
* folders (TYPE_FOLDER)<br />
* separators (TYPE_SEPARATOR)<br />
* microsummary (TYPE_BOOKMARK with microsummary)<br />
* livemark (TYPE_FOLDER that's a livemark)<br />
* query (TYPE_BOOKMARK with a place: URI)<br />
Note that Sync does not support "dynamic containers" (TYPE_DYNAMIC_CONTAINER). --philikon<br />
<br />
We don't care about dynamic containers so far, mainly because the API lies and they just don't work. --mak<br />
<br />
All these are covered, but you may have to roll your own way with annotations. --sdwilsh<br />
<br />
To eloborate: microsummaries and livemarks are regular bookmarks and folders, respectively, with some annotations added to them. So instead of going through their APIs we're just going to add the necessary annotations. We might want to expose some of the internal constants these services use via their interfaces so that we don't have to copy & paste them. --philikon<br />
<br />
=== Interfaces ===<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
Dietrich suggested to just do a AsyncBookmarks.jsm module, and completely drop xpcom. I mostly agree, this interface is not going to have cpp users, and we are also making it hard for cpp users (the arrays and so on...). We'd just need some private interface in nsPIPlacesDatabase to forward notifications. What would block us from doing that? --mak<br />
<br />
=== Parent Name===<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
Having the parent name in there feels awkward but it would make our code much easier while making the places code only slightly more complicated (I hope). I will have to think about alternatives to our current duping algorithm, but there's probably little alternative to having it match folder names. --philikon<br />
<br />
Decision: keep the parentName. --sdwilsh<br />
<br />
=== Predecessor ===<br />
<br />
This is similar to the parent name issue: In order to preserve ordering, Sync maintains the GUID of an item's predecessor in each record. So it'd be good if nsIBookmarkInfo were to contain that info. Bonus points for making <code>updateItem</code> understand this and move the item appropriately. --philikon<br />
<br />
We'd like to just keep it at itemIndex, due to more complicated queries or more queries. philikon says it's possible, but will follow up. --sdwilsh<br />
<br />
It's possible but all options I can think of will require serious change:<br />
# We could make bookmarks have the itemIndex instead of predecessorid. However, adding a new bookmark in a folder or moving a bookmark would invalidate a lot of other bookmarks, potentially even all, in that folder.<br />
# We could store the predecessor GUID in annotations since we now have async APIs for querying and storing these. But we would have to ensure that this annotation exists on all bookmarks first which would mean a lot of I/O on first sync, pretty much exactly the same kind of I/O that we have to do for GUIDs right now.<br />
# Instead of maintaining the ordering on the bookmarks, maintain it on their folders. Inserting or moving a bookmark would invalidate one more object, its folder (as opposed to its successor as it does now). This would mean having a childrenGUIDs array on nsIBookmarkInfo that would get/set the order of a folder's children.<br />
Both option 1 and 3 would mean a version bump for the bookmark storage. These are similarly problematic as global storage version bumps. Fortunately, we're doing one very very soon, so we could just move to the new bookmark storage version now so that it's in place when we get the async APIs.<br />
I'm personally leaning towards option 3 --philikon<br />
<br />
Changing bookmarks table to drop position could not be that easy, I have to check, but iirc we rely pretty much on that positioning and on it not having "holes". So if that's the idea, we have to be cautious here, if the "bookmark storage" is something on Sync side, then nevermind! --mak<br />
<br />
Yes, "bookmark storage" is a Sync component. --philikon<br />
<br />
=== Tags ===<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
We explicitly ignore the tags folder right now, so it doesn't magically work. Sync uses the tagging service API explicitly. So either we should perhaps start syncing the tags folder (if that does indeed magically work) or nsIBookmarkInfo should contain the tags. --philikon<br />
<br />
OK, we could add a getBookmarkInfoWithTags (or have another argument to getBookmarkInfo) that could obtain tags too. Syncing the bookmarg tags folder wouldn't work out right for things like the iphone client. --sdwilsh<br />
<br />
Take in count in future tags will have to move out of bookmarks folders/table to their own storage, thus it is not sane to request syncs of the tags root. What Sync does using taggign service is correct. Not working here though since it's sync. What's the cost of just returning tags always? If I use this interface is pretty clear I want to know EVERYTHING on a bookmark. --mak<br />
<br />
=== nsIBookmarkInfo readonly ===<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly. --mak<br />
<br />
It shouldn't matter. We don't have to return the same nsIBookmarkInfo object that we are passed in (in fact, for threadsafety reasons, we shouldn't!) --sdwilsh<br />
<br />
=== Query by URI ===<br />
<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
Pretty sure we don't have any need for querying bookmarks by URI. --philikon<br />
<br />
Let's just drop support for querying on URI. --sdwilsh<br />
<br />
I guess mobile could find querying by uri useful instead... but we can fix this later. --mak<br />
<br />
=== Missing attributes ignored on update ===<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
<code>updateItem({id:2}, {guid:"GUID_HERE"});</code><br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
Yes, it would be great if missing properties on the nsIBookmarkInfo object would simply be ignored in the update. The same should go for annotations. This means that this API wouldn't allow us to remove annotations, but that's ok since we have no need for it. But we do avoid having to first get all the information before updating it. --philikon<br />
<br />
This shouldn't be a problem. We can add an API in the future for removal of data, but we do not need to in this cycle (2.0). --sdwilsh<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed History Proposal==<br />
<br />
This proposal is considered to be stable.<br />
<br />
=== nsIVisitInfo ===<br />
<br />
interface nsIVisitInfo : nsISupports<br />
{<br />
// moz_historyvisits.id<br />
readonly long long id;<br />
readonly PRTime date;<br />
readonly long transitionType;<br />
// optional (could be null)<br />
readonly nsIURI referrer;<br />
readonly long long sessionId;<br />
}<br />
<br />
This is a new interface that describes a visit for a place (that is described by nsIPlaceInfo).<br />
<br />
=== nsIPlaceInfo ===<br />
<br />
interface nsIPlaceInfo : nsISupports<br />
{<br />
// moz_places.id<br />
readonly long long id;<br />
readonly nsIURI uri;<br />
readonly AString title;<br />
readonly ACString guid;<br />
readonly long long frecency;<br />
<br />
/**<br />
* An array of nsIVisitInfo objects for the place.<br />
*/<br />
readonly nsIVariant visits;<br />
}<br />
<br />
This is a new interface that describes a place (stored in moz_places). This will currently only need to be implemented for nsIPlaceInfoCallback.<br />
<br />
The visits attribute can contain multiple visits the nsIPlaceInfo is passed into updatePlace or updatePlaces.<br />
<br />
The visits attribute will only ever have one entry when it is used with nsIPlaceInfoCallback.<br />
<br />
=== nsIPlaceInfoCallback ===<br />
<br />
interface nsIPlaceInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the visit methods has added a visit.<br />
*<br />
* @param aResultCode<br />
* nsresult of the visit addition. Success indicated by Components.isSuccessCode(aResultCode).<br />
* @param aPlaceInfo<br />
* The information about the visit.<br />
*/<br />
void onComplete(in nsresult aResultCode,<br />
in nsIPlaceInfo aPlaceInfo);<br />
}<br />
<br />
=== updatePlace ===<br />
<br />
/**<br />
* Adds a set of visits for a place info object. The callback is called once for each visit. Ignores duplicates. Also updates the guid or title.<br />
*<br />
* @param aPlaceInfo<br />
* Information about the place to add.<br />
* @param [optional] aCallback<br />
* Callback to be notified for each visit.<br />
*/<br />
void updatePlace(in nsIPlaceInfo aPlaceInfo,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
Method for adding or updating a place with visits to the database. If a place already exists, each visit is added to the database (without duplication). If the place does not exists, it is first added, and then each visit is added (duplication does not need to be checked in this case). The callback (if provided) is called for each successful visit addition.<br />
<br />
Required fields for inserting a new place:<br />
* uri<br />
* visits.length > 0<br />
<br />
Required fields for updating a place (only one needed):<br />
* id<br />
* guid<br />
<br />
Required fields for each visit (updating a place or inserting):<br />
* date<br />
* transition type<br />
<br />
This must also notify the appropriate events to the observers listening with a nsINavHistoryObserver.<br />
<br />
=== updatePlaces ===<br />
<br />
/**<br />
* Just like updatePlaceAndAddVisits.<br />
*<br />
* @param aPlaceInfos<br />
* Information about the places to add.<br />
* @param aPlaces<br />
* The number of aPlaceInfos.<br />
* @param [optional] aCallback<br />
* Callback to be notified for each visit.<br />
*/<br />
void updatePlaces([array, size_is(aPlaces)] in nsIPlaceInfo aPlaceInfos,<br />
in unsigned long aPlaces,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
Just like updatePlace but with one additional requirement:<br />
This must dispatch the appropriate batch notification when aPlaces > 1 (nsINavHistoryObserver::on[Begin|End]UpdateBatch)<br />
<br />
= Input History =<br />
<br />
Turns out we want to sync input history too, see {{bug|597874}}. It would be great if we could add the following to <code>nsIPlaceInfo</code>:<br />
<br />
/**<br />
* An array of nsIInputHistory objects for the place.<br />
*/<br />
readonly nsIVariant inputs;<br />
<br />
with <code>nsIInputHistory</code>:<br />
<br />
interface nsIInputHistory : nsISupports<br />
{<br />
ACString input;<br />
double use_count;<br />
}</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=268687Places/AsyncAPIsForSync2010-11-18T06:16:36Z<p>Comrade693: /* Notes and feedback on Proposal */ Remove section</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
readonly long long frecency;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark. These are item annotations from nsIAnnotationService.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertItem ===<br />
<br />
/**<br />
* Inserts a bookmark item. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertItem(in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertItems ===<br />
<br />
/**<br />
* Inserts many bookmark items. Just like insertItem otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertItems([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateItem ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark item. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateItem(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateItems ===<br />
<br />
/**<br />
* Updates many bookmark items. Just like updateItem otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateItems([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
=== No need for "plural" methods ===<br />
Due to the way Sync engines work, we have no need for the batch operation methods (insertBookmarks, updateItems) as we deal with each bookmark record individually. We're running this in batchmode anyway. --philikon<br />
<br />
We didn't want runInBatchMode to have magic flags that deal with these async methods. Shouldn't be a problem for the Sync team to deal with this new way. --sdwilsh<br />
<br />
So the bookmarks store will just accumulate the incoming objects in memory and then the bookmarks engine, at the end of _processIncoming(), will flush the records to disk, using the async call. To avoid hogging too much memory when lots of bookmarks are involved, the store should flush after a certain number of records have accumulated as well. 50 seems like a good number since that's incidentally also the batch size for network fetches on mobile. --philikon<br />
<br />
=== Types of places items covered ===<br />
<br />
Just so we're on the same page, these are the data types Sync supports:<br />
* bookmarks (TYPE_BOOKMARK)<br />
* folders (TYPE_FOLDER)<br />
* separators (TYPE_SEPARATOR)<br />
* microsummary (TYPE_BOOKMARK with microsummary)<br />
* livemark (TYPE_FOLDER that's a livemark)<br />
* query (TYPE_BOOKMARK with a place: URI)<br />
Note that Sync does not support "dynamic containers" (TYPE_DYNAMIC_CONTAINER). --philikon<br />
<br />
We don't care about dynamic containers so far, mainly because the API lies and they just don't work. --mak<br />
<br />
All these are covered, but you may have to roll your own way with annotations. --sdwilsh<br />
<br />
To eloborate: microsummaries and livemarks are regular bookmarks and folders, respectively, with some annotations added to them. So instead of going through their APIs we're just going to add the necessary annotations. We might want to expose some of the internal constants these services use via their interfaces so that we don't have to copy & paste them. --philikon<br />
<br />
=== Interfaces ===<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
Dietrich suggested to just do a AsyncBookmarks.jsm module, and completely drop xpcom. I mostly agree, this interface is not going to have cpp users, and we are also making it hard for cpp users (the arrays and so on...). We'd just need some private interface in nsPIPlacesDatabase to forward notifications. What would block us from doing that? --mak<br />
<br />
=== Parent Name===<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
Having the parent name in there feels awkward but it would make our code much easier while making the places code only slightly more complicated (I hope). I will have to think about alternatives to our current duping algorithm, but there's probably little alternative to having it match folder names. --philikon<br />
<br />
Decision: keep the parentName. --sdwilsh<br />
<br />
=== Predecessor ===<br />
<br />
This is similar to the parent name issue: In order to preserve ordering, Sync maintains the GUID of an item's predecessor in each record. So it'd be good if nsIBookmarkInfo were to contain that info. Bonus points for making <code>updateItem</code> understand this and move the item appropriately. --philikon<br />
<br />
We'd like to just keep it at itemIndex, due to more complicated queries or more queries. philikon says it's possible, but will follow up. --sdwilsh<br />
<br />
It's possible but all options I can think of will require serious change:<br />
# We could make bookmarks have the itemIndex instead of predecessorid. However, adding a new bookmark in a folder or moving a bookmark would invalidate a lot of other bookmarks, potentially even all, in that folder.<br />
# We could store the predecessor GUID in annotations since we now have async APIs for querying and storing these. But we would have to ensure that this annotation exists on all bookmarks first which would mean a lot of I/O on first sync, pretty much exactly the same kind of I/O that we have to do for GUIDs right now.<br />
# Instead of maintaining the ordering on the bookmarks, maintain it on their folders. Inserting or moving a bookmark would invalidate one more object, its folder (as opposed to its successor as it does now). This would mean having a childrenGUIDs array on nsIBookmarkInfo that would get/set the order of a folder's children.<br />
Both option 1 and 3 would mean a version bump for the bookmark storage. These are similarly problematic as global storage version bumps. Fortunately, we're doing one very very soon, so we could just move to the new bookmark storage version now so that it's in place when we get the async APIs.<br />
I'm personally leaning towards option 3 --philikon<br />
<br />
Changing bookmarks table to drop position could not be that easy, I have to check, but iirc we rely pretty much on that positioning and on it not having "holes". So if that's the idea, we have to be cautious here, if the "bookmark storage" is something on Sync side, then nevermind! --mak<br />
<br />
Yes, "bookmark storage" is a Sync component. --philikon<br />
<br />
=== Tags ===<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
We explicitly ignore the tags folder right now, so it doesn't magically work. Sync uses the tagging service API explicitly. So either we should perhaps start syncing the tags folder (if that does indeed magically work) or nsIBookmarkInfo should contain the tags. --philikon<br />
<br />
OK, we could add a getBookmarkInfoWithTags (or have another argument to getBookmarkInfo) that could obtain tags too. Syncing the bookmarg tags folder wouldn't work out right for things like the iphone client. --sdwilsh<br />
<br />
Take in count in future tags will have to move out of bookmarks folders/table to their own storage, thus it is not sane to request syncs of the tags root. What Sync does using taggign service is correct. Not working here though since it's sync. What's the cost of just returning tags always? If I use this interface is pretty clear I want to know EVERYTHING on a bookmark. --mak<br />
<br />
=== nsIBookmarkInfo readonly ===<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly. --mak<br />
<br />
It shouldn't matter. We don't have to return the same nsIBookmarkInfo object that we are passed in (in fact, for threadsafety reasons, we shouldn't!) --sdwilsh<br />
<br />
=== Query by URI ===<br />
<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
Pretty sure we don't have any need for querying bookmarks by URI. --philikon<br />
<br />
Let's just drop support for querying on URI. --sdwilsh<br />
<br />
I guess mobile could find querying by uri useful instead... but we can fix this later. --mak<br />
<br />
=== Missing attributes ignored on update ===<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
<code>updateItem({id:2}, {guid:"GUID_HERE"});</code><br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
Yes, it would be great if missing properties on the nsIBookmarkInfo object would simply be ignored in the update. The same should go for annotations. This means that this API wouldn't allow us to remove annotations, but that's ok since we have no need for it. But we do avoid having to first get all the information before updating it. --philikon<br />
<br />
This shouldn't be a problem. We can add an API in the future for removal of data, but we do not need to in this cycle (2.0). --sdwilsh<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
This proposal is considered to be stable.<br />
<br />
=== nsIVisitInfo ===<br />
<br />
interface nsIVisitInfo : nsISupports<br />
{<br />
// moz_historyvisits.id<br />
readonly long long id;<br />
readonly PRTime date;<br />
readonly long transitionType;<br />
// optional (could be null)<br />
readonly nsIURI referrer;<br />
readonly long long sessionId;<br />
}<br />
<br />
This is a new interface that describes a visit for a place (that is described by nsIPlaceInfo).<br />
<br />
=== nsIPlaceInfo ===<br />
<br />
interface nsIPlaceInfo : nsISupports<br />
{<br />
// moz_places.id<br />
readonly long long id;<br />
readonly nsIURI uri;<br />
readonly AString title;<br />
readonly ACString guid;<br />
readonly long long frecency;<br />
<br />
/**<br />
* An array of nsIVisitInfo objects for the place.<br />
*/<br />
readonly nsIVariant visits;<br />
}<br />
<br />
This is a new interface that describes a place (stored in moz_places). This will currently only need to be implemented for nsIPlaceInfoCallback.<br />
<br />
The visits attribute can contain multiple visits the nsIPlaceInfo is passed into updatePlace or updatePlaces.<br />
<br />
The visits attribute will only ever have one entry when it is used with nsIPlaceInfoCallback.<br />
<br />
=== nsIPlaceInfoCallback ===<br />
<br />
interface nsIPlaceInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the visit methods has added a visit.<br />
*<br />
* @param aResultCode<br />
* nsresult of the visit addition. Success indicated by Components.isSuccessCode(aResultCode).<br />
* @param aPlaceInfo<br />
* The information about the visit.<br />
*/<br />
void onComplete(in nsresult aResultCode,<br />
in nsIPlaceInfo aPlaceInfo);<br />
}<br />
<br />
=== updatePlace ===<br />
<br />
/**<br />
* Adds a set of visits for a place info object. The callback is called once for each visit. Ignores duplicates. Also updates the guid or title.<br />
*<br />
* @param aPlaceInfo<br />
* Information about the place to add.<br />
* @param [optional] aCallback<br />
* Callback to be notified for each visit.<br />
*/<br />
void updatePlace(in nsIPlaceInfo aPlaceInfo,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
Method for adding or updating a place with visits to the database. If a place already exists, each visit is added to the database (without duplication). If the place does not exists, it is first added, and then each visit is added (duplication does not need to be checked in this case). The callback (if provided) is called for each successful visit addition.<br />
<br />
Required fields for inserting a new place:<br />
* uri<br />
* visits.length > 0<br />
<br />
Required fields for updating a place (only one needed):<br />
* id<br />
* guid<br />
<br />
Required fields for each visit (updating a place or inserting):<br />
* date<br />
* transition type<br />
<br />
This must also notify the appropriate events to the observers listening with a nsINavHistoryObserver.<br />
<br />
=== updatePlaces ===<br />
<br />
/**<br />
* Just like updatePlaceAndAddVisits.<br />
*<br />
* @param aPlaceInfos<br />
* Information about the places to add.<br />
* @param aPlaces<br />
* The number of aPlaceInfos.<br />
* @param [optional] aCallback<br />
* Callback to be notified for each visit.<br />
*/<br />
void updatePlaces([array, size_is(aPlaces)] in nsIPlaceInfo aPlaceInfos,<br />
in unsigned long aPlaces,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
Just like updatePlace but with one additional requirement:<br />
This must dispatch the appropriate batch notification when aPlaces > 1 (nsINavHistoryObserver::on[Begin|End]UpdateBatch)<br />
<br />
= Input History =<br />
<br />
Turns out we want to sync input history too, see {{bug|597874}}. It would be great if we could add the following to <code>nsIPlaceInfo</code>:<br />
<br />
/**<br />
* An array of nsIInputHistory objects for the place.<br />
*/<br />
readonly nsIVariant inputs;<br />
<br />
with <code>nsIInputHistory</code>:<br />
<br />
interface nsIInputHistory : nsISupports<br />
{<br />
ACString input;<br />
double use_count;<br />
}</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=268686Places/AsyncAPIsForSync2010-11-18T06:15:41Z<p>Comrade693: /* Detailed Proposal */ Add details to the History spec, and mark it as "stable"</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
readonly long long frecency;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark. These are item annotations from nsIAnnotationService.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertItem ===<br />
<br />
/**<br />
* Inserts a bookmark item. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertItem(in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertItems ===<br />
<br />
/**<br />
* Inserts many bookmark items. Just like insertItem otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertItems([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateItem ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark item. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateItem(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateItems ===<br />
<br />
/**<br />
* Updates many bookmark items. Just like updateItem otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateItems([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
=== No need for "plural" methods ===<br />
Due to the way Sync engines work, we have no need for the batch operation methods (insertBookmarks, updateItems) as we deal with each bookmark record individually. We're running this in batchmode anyway. --philikon<br />
<br />
We didn't want runInBatchMode to have magic flags that deal with these async methods. Shouldn't be a problem for the Sync team to deal with this new way. --sdwilsh<br />
<br />
So the bookmarks store will just accumulate the incoming objects in memory and then the bookmarks engine, at the end of _processIncoming(), will flush the records to disk, using the async call. To avoid hogging too much memory when lots of bookmarks are involved, the store should flush after a certain number of records have accumulated as well. 50 seems like a good number since that's incidentally also the batch size for network fetches on mobile. --philikon<br />
<br />
=== Types of places items covered ===<br />
<br />
Just so we're on the same page, these are the data types Sync supports:<br />
* bookmarks (TYPE_BOOKMARK)<br />
* folders (TYPE_FOLDER)<br />
* separators (TYPE_SEPARATOR)<br />
* microsummary (TYPE_BOOKMARK with microsummary)<br />
* livemark (TYPE_FOLDER that's a livemark)<br />
* query (TYPE_BOOKMARK with a place: URI)<br />
Note that Sync does not support "dynamic containers" (TYPE_DYNAMIC_CONTAINER). --philikon<br />
<br />
We don't care about dynamic containers so far, mainly because the API lies and they just don't work. --mak<br />
<br />
All these are covered, but you may have to roll your own way with annotations. --sdwilsh<br />
<br />
To eloborate: microsummaries and livemarks are regular bookmarks and folders, respectively, with some annotations added to them. So instead of going through their APIs we're just going to add the necessary annotations. We might want to expose some of the internal constants these services use via their interfaces so that we don't have to copy & paste them. --philikon<br />
<br />
=== Interfaces ===<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
Dietrich suggested to just do a AsyncBookmarks.jsm module, and completely drop xpcom. I mostly agree, this interface is not going to have cpp users, and we are also making it hard for cpp users (the arrays and so on...). We'd just need some private interface in nsPIPlacesDatabase to forward notifications. What would block us from doing that? --mak<br />
<br />
=== Parent Name===<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
Having the parent name in there feels awkward but it would make our code much easier while making the places code only slightly more complicated (I hope). I will have to think about alternatives to our current duping algorithm, but there's probably little alternative to having it match folder names. --philikon<br />
<br />
Decision: keep the parentName. --sdwilsh<br />
<br />
=== Predecessor ===<br />
<br />
This is similar to the parent name issue: In order to preserve ordering, Sync maintains the GUID of an item's predecessor in each record. So it'd be good if nsIBookmarkInfo were to contain that info. Bonus points for making <code>updateItem</code> understand this and move the item appropriately. --philikon<br />
<br />
We'd like to just keep it at itemIndex, due to more complicated queries or more queries. philikon says it's possible, but will follow up. --sdwilsh<br />
<br />
It's possible but all options I can think of will require serious change:<br />
# We could make bookmarks have the itemIndex instead of predecessorid. However, adding a new bookmark in a folder or moving a bookmark would invalidate a lot of other bookmarks, potentially even all, in that folder.<br />
# We could store the predecessor GUID in annotations since we now have async APIs for querying and storing these. But we would have to ensure that this annotation exists on all bookmarks first which would mean a lot of I/O on first sync, pretty much exactly the same kind of I/O that we have to do for GUIDs right now.<br />
# Instead of maintaining the ordering on the bookmarks, maintain it on their folders. Inserting or moving a bookmark would invalidate one more object, its folder (as opposed to its successor as it does now). This would mean having a childrenGUIDs array on nsIBookmarkInfo that would get/set the order of a folder's children.<br />
Both option 1 and 3 would mean a version bump for the bookmark storage. These are similarly problematic as global storage version bumps. Fortunately, we're doing one very very soon, so we could just move to the new bookmark storage version now so that it's in place when we get the async APIs.<br />
I'm personally leaning towards option 3 --philikon<br />
<br />
Changing bookmarks table to drop position could not be that easy, I have to check, but iirc we rely pretty much on that positioning and on it not having "holes". So if that's the idea, we have to be cautious here, if the "bookmark storage" is something on Sync side, then nevermind! --mak<br />
<br />
Yes, "bookmark storage" is a Sync component. --philikon<br />
<br />
=== Tags ===<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
We explicitly ignore the tags folder right now, so it doesn't magically work. Sync uses the tagging service API explicitly. So either we should perhaps start syncing the tags folder (if that does indeed magically work) or nsIBookmarkInfo should contain the tags. --philikon<br />
<br />
OK, we could add a getBookmarkInfoWithTags (or have another argument to getBookmarkInfo) that could obtain tags too. Syncing the bookmarg tags folder wouldn't work out right for things like the iphone client. --sdwilsh<br />
<br />
Take in count in future tags will have to move out of bookmarks folders/table to their own storage, thus it is not sane to request syncs of the tags root. What Sync does using taggign service is correct. Not working here though since it's sync. What's the cost of just returning tags always? If I use this interface is pretty clear I want to know EVERYTHING on a bookmark. --mak<br />
<br />
=== nsIBookmarkInfo readonly ===<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly. --mak<br />
<br />
It shouldn't matter. We don't have to return the same nsIBookmarkInfo object that we are passed in (in fact, for threadsafety reasons, we shouldn't!) --sdwilsh<br />
<br />
=== Query by URI ===<br />
<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
Pretty sure we don't have any need for querying bookmarks by URI. --philikon<br />
<br />
Let's just drop support for querying on URI. --sdwilsh<br />
<br />
I guess mobile could find querying by uri useful instead... but we can fix this later. --mak<br />
<br />
=== Missing attributes ignored on update ===<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
<code>updateItem({id:2}, {guid:"GUID_HERE"});</code><br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
Yes, it would be great if missing properties on the nsIBookmarkInfo object would simply be ignored in the update. The same should go for annotations. This means that this API wouldn't allow us to remove annotations, but that's ok since we have no need for it. But we do avoid having to first get all the information before updating it. --philikon<br />
<br />
This shouldn't be a problem. We can add an API in the future for removal of data, but we do not need to in this cycle (2.0). --sdwilsh<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
This proposal is considered to be stable.<br />
<br />
=== nsIVisitInfo ===<br />
<br />
interface nsIVisitInfo : nsISupports<br />
{<br />
// moz_historyvisits.id<br />
readonly long long id;<br />
readonly PRTime date;<br />
readonly long transitionType;<br />
// optional (could be null)<br />
readonly nsIURI referrer;<br />
readonly long long sessionId;<br />
}<br />
<br />
This is a new interface that describes a visit for a place (that is described by nsIPlaceInfo).<br />
<br />
=== nsIPlaceInfo ===<br />
<br />
interface nsIPlaceInfo : nsISupports<br />
{<br />
// moz_places.id<br />
readonly long long id;<br />
readonly nsIURI uri;<br />
readonly AString title;<br />
readonly ACString guid;<br />
readonly long long frecency;<br />
<br />
/**<br />
* An array of nsIVisitInfo objects for the place.<br />
*/<br />
readonly nsIVariant visits;<br />
}<br />
<br />
This is a new interface that describes a place (stored in moz_places). This will currently only need to be implemented for nsIPlaceInfoCallback.<br />
<br />
The visits attribute can contain multiple visits the nsIPlaceInfo is passed into updatePlace or updatePlaces.<br />
<br />
The visits attribute will only ever have one entry when it is used with nsIPlaceInfoCallback.<br />
<br />
=== nsIPlaceInfoCallback ===<br />
<br />
interface nsIPlaceInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the visit methods has added a visit.<br />
*<br />
* @param aResultCode<br />
* nsresult of the visit addition. Success indicated by Components.isSuccessCode(aResultCode).<br />
* @param aPlaceInfo<br />
* The information about the visit.<br />
*/<br />
void onComplete(in nsresult aResultCode,<br />
in nsIPlaceInfo aPlaceInfo);<br />
}<br />
<br />
=== updatePlace ===<br />
<br />
/**<br />
* Adds a set of visits for a place info object. The callback is called once for each visit. Ignores duplicates. Also updates the guid or title.<br />
*<br />
* @param aPlaceInfo<br />
* Information about the place to add.<br />
* @param [optional] aCallback<br />
* Callback to be notified for each visit.<br />
*/<br />
void updatePlace(in nsIPlaceInfo aPlaceInfo,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
Method for adding or updating a place with visits to the database. If a place already exists, each visit is added to the database (without duplication). If the place does not exists, it is first added, and then each visit is added (duplication does not need to be checked in this case). The callback (if provided) is called for each successful visit addition.<br />
<br />
Required fields for inserting a new place:<br />
* uri<br />
* visits.length > 0<br />
<br />
Required fields for updating a place (only one needed):<br />
* id<br />
* guid<br />
<br />
Required fields for each visit (updating a place or inserting):<br />
* date<br />
* transition type<br />
<br />
This must also notify the appropriate events to the observers listening with a nsINavHistoryObserver.<br />
<br />
=== updatePlaces ===<br />
<br />
/**<br />
* Just like updatePlaceAndAddVisits.<br />
*<br />
* @param aPlaceInfos<br />
* Information about the places to add.<br />
* @param aPlaces<br />
* The number of aPlaceInfos.<br />
* @param [optional] aCallback<br />
* Callback to be notified for each visit.<br />
*/<br />
void updatePlaces([array, size_is(aPlaces)] in nsIPlaceInfo aPlaceInfos,<br />
in unsigned long aPlaces,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
Just like updatePlace but with one additional requirement:<br />
This must dispatch the appropriate batch notification when aPlaces > 1 (nsINavHistoryObserver::on[Begin|End]UpdateBatch)<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
I suggest using WithVisits rather than AndVisits... But as we did for bookmarks, there is not much gain in specifying WithVisits or WithInfo if all the APIs use them, maybe just updatePlace(), I can pass an empty array of visits after all. --mak<br />
<br />
Fair enough. Done. --sdwilsh<br />
<br />
nsIVisitInfo is missing from_visit and session. While it's possible Sync does not sync them, I think they should since we use them to discard useless redirects. Or they should discard redirects. Btw we want them in the interface. --mak<br />
<br />
Whoops, yeah. Not sure how I managed to miss that. Fixed. Pretty sure Sync doesn't do anything with session id though (seems difficult to do for that matter). --sdwilsh<br />
<br />
Sync does not sync ALL visits, do they need visit_count though? --mak<br />
<br />
Sync doesn't need visit_count; they just get the last N visits. --sdwilsh<br />
<br />
We sync the last 10 visits per place. We don't need visit_count and we don't care about from_visit and session. --philikon<br />
<br />
= Input History =<br />
<br />
Turns out we want to sync input history too, see {{bug|597874}}. It would be great if we could add the following to <code>nsIPlaceInfo</code>:<br />
<br />
/**<br />
* An array of nsIInputHistory objects for the place.<br />
*/<br />
readonly nsIVariant inputs;<br />
<br />
with <code>nsIInputHistory</code>:<br />
<br />
interface nsIInputHistory : nsISupports<br />
{<br />
ACString input;<br />
double use_count;<br />
}</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=268682Places/AsyncAPIsForSync2010-11-18T05:52:56Z<p>Comrade693: /* Input History */ Move out of History so we can mark History as stable.</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
readonly long long frecency;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark. These are item annotations from nsIAnnotationService.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertItem ===<br />
<br />
/**<br />
* Inserts a bookmark item. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertItem(in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertItems ===<br />
<br />
/**<br />
* Inserts many bookmark items. Just like insertItem otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertItems([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateItem ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark item. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateItem(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateItems ===<br />
<br />
/**<br />
* Updates many bookmark items. Just like updateItem otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateItems([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
=== No need for "plural" methods ===<br />
Due to the way Sync engines work, we have no need for the batch operation methods (insertBookmarks, updateItems) as we deal with each bookmark record individually. We're running this in batchmode anyway. --philikon<br />
<br />
We didn't want runInBatchMode to have magic flags that deal with these async methods. Shouldn't be a problem for the Sync team to deal with this new way. --sdwilsh<br />
<br />
So the bookmarks store will just accumulate the incoming objects in memory and then the bookmarks engine, at the end of _processIncoming(), will flush the records to disk, using the async call. To avoid hogging too much memory when lots of bookmarks are involved, the store should flush after a certain number of records have accumulated as well. 50 seems like a good number since that's incidentally also the batch size for network fetches on mobile. --philikon<br />
<br />
=== Types of places items covered ===<br />
<br />
Just so we're on the same page, these are the data types Sync supports:<br />
* bookmarks (TYPE_BOOKMARK)<br />
* folders (TYPE_FOLDER)<br />
* separators (TYPE_SEPARATOR)<br />
* microsummary (TYPE_BOOKMARK with microsummary)<br />
* livemark (TYPE_FOLDER that's a livemark)<br />
* query (TYPE_BOOKMARK with a place: URI)<br />
Note that Sync does not support "dynamic containers" (TYPE_DYNAMIC_CONTAINER). --philikon<br />
<br />
We don't care about dynamic containers so far, mainly because the API lies and they just don't work. --mak<br />
<br />
All these are covered, but you may have to roll your own way with annotations. --sdwilsh<br />
<br />
To eloborate: microsummaries and livemarks are regular bookmarks and folders, respectively, with some annotations added to them. So instead of going through their APIs we're just going to add the necessary annotations. We might want to expose some of the internal constants these services use via their interfaces so that we don't have to copy & paste them. --philikon<br />
<br />
=== Interfaces ===<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
Dietrich suggested to just do a AsyncBookmarks.jsm module, and completely drop xpcom. I mostly agree, this interface is not going to have cpp users, and we are also making it hard for cpp users (the arrays and so on...). We'd just need some private interface in nsPIPlacesDatabase to forward notifications. What would block us from doing that? --mak<br />
<br />
=== Parent Name===<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
Having the parent name in there feels awkward but it would make our code much easier while making the places code only slightly more complicated (I hope). I will have to think about alternatives to our current duping algorithm, but there's probably little alternative to having it match folder names. --philikon<br />
<br />
Decision: keep the parentName. --sdwilsh<br />
<br />
=== Predecessor ===<br />
<br />
This is similar to the parent name issue: In order to preserve ordering, Sync maintains the GUID of an item's predecessor in each record. So it'd be good if nsIBookmarkInfo were to contain that info. Bonus points for making <code>updateItem</code> understand this and move the item appropriately. --philikon<br />
<br />
We'd like to just keep it at itemIndex, due to more complicated queries or more queries. philikon says it's possible, but will follow up. --sdwilsh<br />
<br />
It's possible but all options I can think of will require serious change:<br />
# We could make bookmarks have the itemIndex instead of predecessorid. However, adding a new bookmark in a folder or moving a bookmark would invalidate a lot of other bookmarks, potentially even all, in that folder.<br />
# We could store the predecessor GUID in annotations since we now have async APIs for querying and storing these. But we would have to ensure that this annotation exists on all bookmarks first which would mean a lot of I/O on first sync, pretty much exactly the same kind of I/O that we have to do for GUIDs right now.<br />
# Instead of maintaining the ordering on the bookmarks, maintain it on their folders. Inserting or moving a bookmark would invalidate one more object, its folder (as opposed to its successor as it does now). This would mean having a childrenGUIDs array on nsIBookmarkInfo that would get/set the order of a folder's children.<br />
Both option 1 and 3 would mean a version bump for the bookmark storage. These are similarly problematic as global storage version bumps. Fortunately, we're doing one very very soon, so we could just move to the new bookmark storage version now so that it's in place when we get the async APIs.<br />
I'm personally leaning towards option 3 --philikon<br />
<br />
Changing bookmarks table to drop position could not be that easy, I have to check, but iirc we rely pretty much on that positioning and on it not having "holes". So if that's the idea, we have to be cautious here, if the "bookmark storage" is something on Sync side, then nevermind! --mak<br />
<br />
Yes, "bookmark storage" is a Sync component. --philikon<br />
<br />
=== Tags ===<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
We explicitly ignore the tags folder right now, so it doesn't magically work. Sync uses the tagging service API explicitly. So either we should perhaps start syncing the tags folder (if that does indeed magically work) or nsIBookmarkInfo should contain the tags. --philikon<br />
<br />
OK, we could add a getBookmarkInfoWithTags (or have another argument to getBookmarkInfo) that could obtain tags too. Syncing the bookmarg tags folder wouldn't work out right for things like the iphone client. --sdwilsh<br />
<br />
Take in count in future tags will have to move out of bookmarks folders/table to their own storage, thus it is not sane to request syncs of the tags root. What Sync does using taggign service is correct. Not working here though since it's sync. What's the cost of just returning tags always? If I use this interface is pretty clear I want to know EVERYTHING on a bookmark. --mak<br />
<br />
=== nsIBookmarkInfo readonly ===<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly. --mak<br />
<br />
It shouldn't matter. We don't have to return the same nsIBookmarkInfo object that we are passed in (in fact, for threadsafety reasons, we shouldn't!) --sdwilsh<br />
<br />
=== Query by URI ===<br />
<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
Pretty sure we don't have any need for querying bookmarks by URI. --philikon<br />
<br />
Let's just drop support for querying on URI. --sdwilsh<br />
<br />
I guess mobile could find querying by uri useful instead... but we can fix this later. --mak<br />
<br />
=== Missing attributes ignored on update ===<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
<code>updateItem({id:2}, {guid:"GUID_HERE"});</code><br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
Yes, it would be great if missing properties on the nsIBookmarkInfo object would simply be ignored in the update. The same should go for annotations. This means that this API wouldn't allow us to remove annotations, but that's ok since we have no need for it. But we do avoid having to first get all the information before updating it. --philikon<br />
<br />
This shouldn't be a problem. We can add an API in the future for removal of data, but we do not need to in this cycle (2.0). --sdwilsh<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
interface nsIVisitInfo : nsISupports<br />
{<br />
// visit id (moz_historyvisits.id)<br />
readonly long long id;<br />
readonly PRTime date;<br />
readonly long transitionType;<br />
readonly nsIURI referrer;<br />
readonly long long sessionId;<br />
}<br />
<br />
interface nsIPlaceInfo : nsISupports<br />
{<br />
// place id<br />
readonly long long id;<br />
readonly nsIURI uri;<br />
readonly AString title;<br />
readonly ACString guid;<br />
readonly long long frecency;<br />
<br />
/**<br />
* An array of nsIVisitInfo objects for the place.<br />
*/<br />
readonly nsIVariant visits;<br />
}<br />
<br />
interface nsIPlaceInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the visit methods has added a visit.<br />
*<br />
* @param aResultCode<br />
* nsresult of the visit addition. Success indicated by Components.isSuccessCode(aResultCode).<br />
* @param aPlaceInfo<br />
* The information about the visit.<br />
*/<br />
void onComplete(in nsresult aResultCode,<br />
in nsIPlaceInfo aPlaceInfo);<br />
}<br />
<br />
/**<br />
* Adds a set of visits for a place info object. The callback is called once for each visit. Ignores duplicates. Also updates the guid or title.<br />
*<br />
* @param aPlaceInfo<br />
* Information about the place to add.<br />
* @param [optional] aCallback<br />
* Callback to be notified for each visit.<br />
*/<br />
void updatePlace(in nsIPlaceInfo aPlaceInfo,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
<br />
/**<br />
* Just like updatePlaceAndAddVisits.<br />
*<br />
* @param aPlaceInfos<br />
* Information about the places to add.<br />
* @param aPlaces<br />
* The number of aPlaceInfos.<br />
* @param [optional] aCallback<br />
* Callback to be notified for each visit.<br />
*/<br />
void updatePlaces([array, size_is(aPlaces)] in nsIPlaceInfo aPlaceInfos,<br />
in unsigned long aPlaces,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
I suggest using WithVisits rather than AndVisits... But as we did for bookmarks, there is not much gain in specifying WithVisits or WithInfo if all the APIs use them, maybe just updatePlace(), I can pass an empty array of visits after all. --mak<br />
<br />
Fair enough. Done. --sdwilsh<br />
<br />
nsIVisitInfo is missing from_visit and session. While it's possible Sync does not sync them, I think they should since we use them to discard useless redirects. Or they should discard redirects. Btw we want them in the interface. --mak<br />
<br />
Whoops, yeah. Not sure how I managed to miss that. Fixed. Pretty sure Sync doesn't do anything with session id though (seems difficult to do for that matter). --sdwilsh<br />
<br />
Sync does not sync ALL visits, do they need visit_count though? --mak<br />
<br />
Sync doesn't need visit_count; they just get the last N visits. --sdwilsh<br />
<br />
We sync the last 10 visits per place. We don't need visit_count and we don't care about from_visit and session. --philikon<br />
<br />
= Input History =<br />
<br />
Turns out we want to sync input history too, see {{bug|597874}}. It would be great if we could add the following to <code>nsIPlaceInfo</code>:<br />
<br />
/**<br />
* An array of nsIInputHistory objects for the place.<br />
*/<br />
readonly nsIVariant inputs;<br />
<br />
with <code>nsIPlaceInfo</code>:<br />
<br />
interface nsIVisitInfo : nsISupports<br />
{<br />
ACString input,<br />
double use_count<br />
}</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=268452Places/AsyncAPIsForSync2010-11-17T16:40:24Z<p>Comrade693: /* Notes and feedback on Proposal */ Responding to feedback</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
readonly long long frecency;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark. These are item annotations from nsIAnnotationService.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertItem ===<br />
<br />
/**<br />
* Inserts a bookmark item. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertItem(in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertItems ===<br />
<br />
/**<br />
* Inserts many bookmark items. Just like insertItem otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertItems([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateItem ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark item. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateItem(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateItems ===<br />
<br />
/**<br />
* Updates many bookmark items. Just like updateItem otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateItems([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
=== No need for "plural" methods ===<br />
Due to the way Sync engines work, we have no need for the batch operation methods (insertBookmarks, updateItems) as we deal with each bookmark record individually. We're running this in batchmode anyway. --philikon<br />
<br />
We didn't want runInBatchMode to have magic flags that deal with these async methods. Shouldn't be a problem for the Sync team to deal with this new way. --sdwilsh<br />
<br />
So the bookmarks store will just accumulate the incoming objects in memory and then the bookmarks engine, at the end of _processIncoming(), will flush the records to disk, using the async call. To avoid hogging too much memory when lots of bookmarks are involved, the store should flush after a certain number of records have accumulated as well. 50 seems like a good number since that's incidentally also the batch size for network fetches on mobile. --philikon<br />
<br />
=== Types of places items covered ===<br />
<br />
Just so we're on the same page, these are the data types Sync supports:<br />
* bookmarks (TYPE_BOOKMARK)<br />
* folders (TYPE_FOLDER)<br />
* separators (TYPE_SEPARATOR)<br />
* microsummary (TYPE_BOOKMARK with microsummary)<br />
* livemark (TYPE_FOLDER that's a livemark)<br />
* query (TYPE_BOOKMARK with a place: URI)<br />
Note that Sync does not support "dynamic containers" (TYPE_DYNAMIC_CONTAINER). --philikon<br />
<br />
We don't care about dynamic containers so far, mainly because the API lies and they just don't work. --mak<br />
<br />
All these are covered, but you may have to roll your own way with annotations. --sdwilsh<br />
<br />
To eloborate: microsummaries and livemarks are regular bookmarks and folders, respectively, with some annotations added to them. So instead of going through their APIs we're just going to add the necessary annotations. We might want to expose some of the internal constants these services use via their interfaces so that we don't have to copy & paste them. --philikon<br />
<br />
=== Interfaces ===<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
Dietrich suggested to just do a AsyncBookmarks.jsm module, and completely drop xpcom. I mostly agree, this interface is not going to have cpp users, and we are also making it hard for cpp users (the arrays and so on...). We'd just need some private interface in nsPIPlacesDatabase to forward notifications. What would block us from doing that? --mak<br />
<br />
=== Parent Name===<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
Having the parent name in there feels awkward but it would make our code much easier while making the places code only slightly more complicated (I hope). I will have to think about alternatives to our current duping algorithm, but there's probably little alternative to having it match folder names. --philikon<br />
<br />
Decision: keep the parentName. --sdwilsh<br />
<br />
=== Predecessor ===<br />
<br />
This is similar to the parent name issue: In order to preserve ordering, Sync maintains the GUID of an item's predecessor in each record. So it'd be good if nsIBookmarkInfo were to contain that info. Bonus points for making <code>updateItem</code> understand this and move the item appropriately. --philikon<br />
<br />
We'd like to just keep it at itemIndex, due to more complicated queries or more queries. philikon says it's possible, but will follow up. --sdwilsh<br />
<br />
It's possible but all options I can think of will require serious change:<br />
# We could make bookmarks have the itemIndex instead of predecessorid. However, adding a new bookmark in a folder or moving a bookmark would invalidate a lot of other bookmarks, potentially even all, in that folder.<br />
# We could store the predecessor GUID in annotations since we now have async APIs for querying and storing these. But we would have to ensure that this annotation exists on all bookmarks first which would mean a lot of I/O on first sync, pretty much exactly the same kind of I/O that we have to do for GUIDs right now.<br />
# Instead of maintaining the ordering on the bookmarks, maintain it on their folders. Inserting or moving a bookmark would invalidate one more object, its folder (as opposed to its successor as it does now). This would mean having a childrenGUIDs array on nsIBookmarkInfo that would get/set the order of a folder's children.<br />
Both option 1 and 3 would mean a version bump for the bookmark storage. These are similarly problematic as global storage version bumps. Fortunately, we're doing one very very soon, so we could just move to the new bookmark storage version now so that it's in place when we get the async APIs.<br />
I'm personally leaning towards option 3 --philikon<br />
<br />
Changing bookmarks table to drop position could not be that easy, I have to check, but iirc we rely pretty much on that positioning and on it not having "holes". So if that's the idea, we have to be cautious here, if the "bookmark storage" is something on Sync side, then nevermind! --mak<br />
<br />
Yes, "bookmark storage" is a Sync component. --philikon<br />
<br />
=== Tags ===<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
We explicitly ignore the tags folder right now, so it doesn't magically work. Sync uses the tagging service API explicitly. So either we should perhaps start syncing the tags folder (if that does indeed magically work) or nsIBookmarkInfo should contain the tags. --philikon<br />
<br />
OK, we could add a getBookmarkInfoWithTags (or have another argument to getBookmarkInfo) that could obtain tags too. Syncing the bookmarg tags folder wouldn't work out right for things like the iphone client. --sdwilsh<br />
<br />
Take in count in future tags will have to move out of bookmarks folders/table to their own storage, thus it is not sane to request syncs of the tags root. What Sync does using taggign service is correct. Not working here though since it's sync. What's the cost of just returning tags always? If I use this interface is pretty clear I want to know EVERYTHING on a bookmark. --mak<br />
<br />
=== nsIBookmarkInfo readonly ===<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly. --mak<br />
<br />
It shouldn't matter. We don't have to return the same nsIBookmarkInfo object that we are passed in (in fact, for threadsafety reasons, we shouldn't!) --sdwilsh<br />
<br />
=== Query by URI ===<br />
<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
Pretty sure we don't have any need for querying bookmarks by URI. --philikon<br />
<br />
Let's just drop support for querying on URI. --sdwilsh<br />
<br />
I guess mobile could find querying by uri useful instead... but we can fix this later. --mak<br />
<br />
=== Missing attributes ignored on update ===<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
<code>updateItem({id:2}, {guid:"GUID_HERE"});</code><br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
Yes, it would be great if missing properties on the nsIBookmarkInfo object would simply be ignored in the update. The same should go for annotations. This means that this API wouldn't allow us to remove annotations, but that's ok since we have no need for it. But we do avoid having to first get all the information before updating it. --philikon<br />
<br />
This shouldn't be a problem. We can add an API in the future for removal of data, but we do not need to in this cycle (2.0). --sdwilsh<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
interface nsIVisitInfo : nsISupports<br />
{<br />
// visit id (moz_historyvisits.id)<br />
readonly long long id;<br />
readonly PRTime date;<br />
readonly long transitionType;<br />
readonly nsIURI referrer;<br />
readonly long long sessionId;<br />
}<br />
<br />
interface nsIPlaceInfo : nsISupports<br />
{<br />
// place id<br />
readonly long long id;<br />
readonly nsIURI uri;<br />
readonly AString title;<br />
readonly ACString guid;<br />
readonly long long frecency;<br />
<br />
/**<br />
* An array of nsIVisitInfo objects for the place.<br />
*/<br />
readonly nsIVariant visits;<br />
}<br />
<br />
interface nsIPlaceInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the visit methods has added a visit.<br />
*<br />
* @param aResultCode<br />
* nsresult of the visit addition. Success indicated by Components.isSuccessCode(aResultCode).<br />
* @param aPlaceInfo<br />
* The information about the visit.<br />
*/<br />
void onComplete(in nsresult aResultCode,<br />
in nsIPlaceInfo aPlaceInfo);<br />
}<br />
<br />
/**<br />
* Adds a set of visits for a place info object. The callback is called once for each visit. Ignores duplicates. Also updates the guid or title.<br />
*<br />
* @param aPlaceInfo<br />
* Information about the place to add.<br />
* @param [optional] aCallback<br />
* Callback to be notified for each visit.<br />
*/<br />
void updatePlace(in nsIPlaceInfo aPlaceInfo,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
<br />
/**<br />
* Just like updatePlaceAndAddVisits.<br />
*<br />
* @param aPlaceInfos<br />
* Information about the places to add.<br />
* @param aPlaces<br />
* The number of aPlaceInfos.<br />
* @param [optional] aCallback<br />
* Callback to be notified for each visit.<br />
*/<br />
void updatePlaces([array, size_is(aPlaces)] in nsIPlaceInfo aPlaceInfos,<br />
in unsigned long aPlaces,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
I suggest using WithVisits rather than AndVisits... But as we did for bookmarks, there is not much gain in specifying WithVisits or WithInfo if all the APIs use them, maybe just updatePlace(), I can pass an empty array of visits after all. --mak<br />
<br />
Fair enough. Done. --sdwilsh<br />
<br />
nsIVisitInfo is missing from_visit and session. While it's possible Sync does not sync them, I think they should since we use them to discard useless redirects. Or they should discard redirects. Btw we want them in the interface. --mak<br />
<br />
Whoops, yeah. Not sure how I managed to miss that. Fixed. Pretty sure Sync doesn't do anything with session id though (seems difficult to do for that matter). --sdwilsh<br />
<br />
Sync does not sync ALL visits, do they need visit_count though? --mak<br />
<br />
Sync doesn't need visit_count; they just get the last N visits. --sdwilsh</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=268451Places/AsyncAPIsForSync2010-11-17T16:40:14Z<p>Comrade693: /* Detailed Proposal */ Address feedback</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
readonly long long frecency;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark. These are item annotations from nsIAnnotationService.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertItem ===<br />
<br />
/**<br />
* Inserts a bookmark item. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertItem(in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertItems ===<br />
<br />
/**<br />
* Inserts many bookmark items. Just like insertItem otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertItems([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateItem ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark item. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateItem(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateItems ===<br />
<br />
/**<br />
* Updates many bookmark items. Just like updateItem otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateItems([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
=== No need for "plural" methods ===<br />
Due to the way Sync engines work, we have no need for the batch operation methods (insertBookmarks, updateItems) as we deal with each bookmark record individually. We're running this in batchmode anyway. --philikon<br />
<br />
We didn't want runInBatchMode to have magic flags that deal with these async methods. Shouldn't be a problem for the Sync team to deal with this new way. --sdwilsh<br />
<br />
So the bookmarks store will just accumulate the incoming objects in memory and then the bookmarks engine, at the end of _processIncoming(), will flush the records to disk, using the async call. To avoid hogging too much memory when lots of bookmarks are involved, the store should flush after a certain number of records have accumulated as well. 50 seems like a good number since that's incidentally also the batch size for network fetches on mobile. --philikon<br />
<br />
=== Types of places items covered ===<br />
<br />
Just so we're on the same page, these are the data types Sync supports:<br />
* bookmarks (TYPE_BOOKMARK)<br />
* folders (TYPE_FOLDER)<br />
* separators (TYPE_SEPARATOR)<br />
* microsummary (TYPE_BOOKMARK with microsummary)<br />
* livemark (TYPE_FOLDER that's a livemark)<br />
* query (TYPE_BOOKMARK with a place: URI)<br />
Note that Sync does not support "dynamic containers" (TYPE_DYNAMIC_CONTAINER). --philikon<br />
<br />
We don't care about dynamic containers so far, mainly because the API lies and they just don't work. --mak<br />
<br />
All these are covered, but you may have to roll your own way with annotations. --sdwilsh<br />
<br />
To eloborate: microsummaries and livemarks are regular bookmarks and folders, respectively, with some annotations added to them. So instead of going through their APIs we're just going to add the necessary annotations. We might want to expose some of the internal constants these services use via their interfaces so that we don't have to copy & paste them. --philikon<br />
<br />
=== Interfaces ===<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
Dietrich suggested to just do a AsyncBookmarks.jsm module, and completely drop xpcom. I mostly agree, this interface is not going to have cpp users, and we are also making it hard for cpp users (the arrays and so on...). We'd just need some private interface in nsPIPlacesDatabase to forward notifications. What would block us from doing that? --mak<br />
<br />
=== Parent Name===<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
Having the parent name in there feels awkward but it would make our code much easier while making the places code only slightly more complicated (I hope). I will have to think about alternatives to our current duping algorithm, but there's probably little alternative to having it match folder names. --philikon<br />
<br />
Decision: keep the parentName. --sdwilsh<br />
<br />
=== Predecessor ===<br />
<br />
This is similar to the parent name issue: In order to preserve ordering, Sync maintains the GUID of an item's predecessor in each record. So it'd be good if nsIBookmarkInfo were to contain that info. Bonus points for making <code>updateItem</code> understand this and move the item appropriately. --philikon<br />
<br />
We'd like to just keep it at itemIndex, due to more complicated queries or more queries. philikon says it's possible, but will follow up. --sdwilsh<br />
<br />
It's possible but all options I can think of will require serious change:<br />
# We could make bookmarks have the itemIndex instead of predecessorid. However, adding a new bookmark in a folder or moving a bookmark would invalidate a lot of other bookmarks, potentially even all, in that folder.<br />
# We could store the predecessor GUID in annotations since we now have async APIs for querying and storing these. But we would have to ensure that this annotation exists on all bookmarks first which would mean a lot of I/O on first sync, pretty much exactly the same kind of I/O that we have to do for GUIDs right now.<br />
# Instead of maintaining the ordering on the bookmarks, maintain it on their folders. Inserting or moving a bookmark would invalidate one more object, its folder (as opposed to its successor as it does now). This would mean having a childrenGUIDs array on nsIBookmarkInfo that would get/set the order of a folder's children.<br />
Both option 1 and 3 would mean a version bump for the bookmark storage. These are similarly problematic as global storage version bumps. Fortunately, we're doing one very very soon, so we could just move to the new bookmark storage version now so that it's in place when we get the async APIs.<br />
I'm personally leaning towards option 3 --philikon<br />
<br />
Changing bookmarks table to drop position could not be that easy, I have to check, but iirc we rely pretty much on that positioning and on it not having "holes". So if that's the idea, we have to be cautious here, if the "bookmark storage" is something on Sync side, then nevermind! --mak<br />
<br />
Yes, "bookmark storage" is a Sync component. --philikon<br />
<br />
=== Tags ===<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
We explicitly ignore the tags folder right now, so it doesn't magically work. Sync uses the tagging service API explicitly. So either we should perhaps start syncing the tags folder (if that does indeed magically work) or nsIBookmarkInfo should contain the tags. --philikon<br />
<br />
OK, we could add a getBookmarkInfoWithTags (or have another argument to getBookmarkInfo) that could obtain tags too. Syncing the bookmarg tags folder wouldn't work out right for things like the iphone client. --sdwilsh<br />
<br />
Take in count in future tags will have to move out of bookmarks folders/table to their own storage, thus it is not sane to request syncs of the tags root. What Sync does using taggign service is correct. Not working here though since it's sync. What's the cost of just returning tags always? If I use this interface is pretty clear I want to know EVERYTHING on a bookmark. --mak<br />
<br />
=== nsIBookmarkInfo readonly ===<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly. --mak<br />
<br />
It shouldn't matter. We don't have to return the same nsIBookmarkInfo object that we are passed in (in fact, for threadsafety reasons, we shouldn't!) --sdwilsh<br />
<br />
=== Query by URI ===<br />
<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
Pretty sure we don't have any need for querying bookmarks by URI. --philikon<br />
<br />
Let's just drop support for querying on URI. --sdwilsh<br />
<br />
I guess mobile could find querying by uri useful instead... but we can fix this later. --mak<br />
<br />
=== Missing attributes ignored on update ===<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
<code>updateItem({id:2}, {guid:"GUID_HERE"});</code><br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
Yes, it would be great if missing properties on the nsIBookmarkInfo object would simply be ignored in the update. The same should go for annotations. This means that this API wouldn't allow us to remove annotations, but that's ok since we have no need for it. But we do avoid having to first get all the information before updating it. --philikon<br />
<br />
This shouldn't be a problem. We can add an API in the future for removal of data, but we do not need to in this cycle (2.0). --sdwilsh<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
interface nsIVisitInfo : nsISupports<br />
{<br />
// visit id (moz_historyvisits.id)<br />
readonly long long id;<br />
readonly PRTime date;<br />
readonly long transitionType;<br />
readonly nsIURI referrer;<br />
readonly long long sessionId;<br />
}<br />
<br />
interface nsIPlaceInfo : nsISupports<br />
{<br />
// place id<br />
readonly long long id;<br />
readonly nsIURI uri;<br />
readonly AString title;<br />
readonly ACString guid;<br />
readonly long long frecency;<br />
<br />
/**<br />
* An array of nsIVisitInfo objects for the place.<br />
*/<br />
readonly nsIVariant visits;<br />
}<br />
<br />
interface nsIPlaceInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the visit methods has added a visit.<br />
*<br />
* @param aResultCode<br />
* nsresult of the visit addition. Success indicated by Components.isSuccessCode(aResultCode).<br />
* @param aPlaceInfo<br />
* The information about the visit.<br />
*/<br />
void onComplete(in nsresult aResultCode,<br />
in nsIPlaceInfo aPlaceInfo);<br />
}<br />
<br />
/**<br />
* Adds a set of visits for a place info object. The callback is called once for each visit. Ignores duplicates. Also updates the guid or title.<br />
*<br />
* @param aPlaceInfo<br />
* Information about the place to add.<br />
* @param [optional] aCallback<br />
* Callback to be notified for each visit.<br />
*/<br />
void updatePlace(in nsIPlaceInfo aPlaceInfo,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
<br />
/**<br />
* Just like updatePlaceAndAddVisits.<br />
*<br />
* @param aPlaceInfos<br />
* Information about the places to add.<br />
* @param aPlaces<br />
* The number of aPlaceInfos.<br />
* @param [optional] aCallback<br />
* Callback to be notified for each visit.<br />
*/<br />
void updatePlaces([array, size_is(aPlaces)] in nsIPlaceInfo aPlaceInfos,<br />
in unsigned long aPlaces,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
I suggest using WithVisits rather than AndVisits... But as we did for bookmarks, there is not much gain in specifying WithVisits or WithInfo if all the APIs use them, maybe just updatePlace(), I can pass an empty array of visits after all. --mak<br />
<br />
nsIVisitInfo is missing from_visit and session. While it's possible Sync does not sync them, I think they should since we use them to discard useless redirects. Or they should discard redirects. Btw we want them in the interface. --mak<br />
<br />
Sync does not sync ALL visits, do they need visit_count though? --mak</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=268255Places/AsyncAPIsForSync2010-11-17T00:53:13Z<p>Comrade693: /* Detailed Proposal */ Added frecency</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
readonly long long frecency;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark. These are item annotations from nsIAnnotationService.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertBookmark ===<br />
<br />
/**<br />
* Inserts a bookmark item. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertItem(in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertBookmarksWithInfo ===<br />
<br />
/**<br />
* Inserts many bookmark items. Just like insertItem otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertItems([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateBookmarkWithInfo ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark item. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateItem(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateItems ===<br />
<br />
/**<br />
* Updates many bookmark items. Just like updateItem otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateItems([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
=== No need for "plural" methods ===<br />
Due to the way Sync engines work, we have no need for the batch operation methods (insertBookmarks, updateItems) as we deal with each bookmark record individually. We're running this in batchmode anyway. --philikon<br />
<br />
We didn't want runInBatchMode to have magic flags that deal with these async methods. Shouldn't be a problem for the Sync team to deal with this new way. --sdwilsh<br />
<br />
=== Types of places items covered ===<br />
<br />
Just so we're on the same page, these are the data types Sync supports:<br />
* bookmarks (TYPE_BOOKMARK)<br />
* folders (TYPE_FOLDER)<br />
* separators (TYPE_SEPARATOR)<br />
* microsummary (TYPE_BOOKMARK with microsummary)<br />
* livemark (TYPE_FOLDER that's a livemark)<br />
* query (TYPE_BOOKMARK with a place: URI)<br />
Note that Sync does not support "dynamic containers" (TYPE_DYNAMIC_CONTAINER). --philikon<br />
<br />
All these are covered, but you may have to roll your own way with annotations. --sdwilsh<br />
<br />
=== Interfaces ===<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
=== Parent Name===<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
Having the parent name in there feels awkward but it would make our code much easier while making the places code only slightly more complicated (I hope). I will have to think about alternatives to our current duping algorithm, but there's probably little alternative to having it match folder names. --philikon<br />
<br />
Decision: keep the parentName. --sdwilsh<br />
<br />
=== Predecessor ===<br />
<br />
This is similar to the parent name issue: In order to preserve ordering, Sync maintains the GUID of an item's predecessor in each record. So it'd be good if nsIBookmarkInfo were to contain that info. Bonus points for making <code>updateItem</code> understand this and move the item appropriately. --philikon<br />
<br />
We'd like to just keep it at itemIndex, due to more complicated queries or more queries. philikon says it's possible, but will follow up. --sdwilsh<br />
<br />
=== Tags ===<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
We explicitly ignore the tags folder right now, so it doesn't magically work. Sync uses the tagging service API explicitly. So either we should perhaps start syncing the tags folder (if that does indeed magically work) or nsIBookmarkInfo should contain the tags. --philikon<br />
<br />
OK, we could add a getBookmarkInfoWithTags (or have another argument to getBookmarkInfo) that could obtain tags too. Syncing the bookmarg tags folder wouldn't work out right for things like the iphone client. --sdwilsh<br />
<br />
=== nsIBookmarkInfo readonly ===<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly. --mak<br />
<br />
It shouldn't matter. We don't have to return the same nsIBookmarkInfo object that we are passed in (in fact, for threadsafety reasons, we shouldn't!) --sdwilsh<br />
<br />
=== Query by URI ===<br />
<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
Pretty sure we don't have any need for querying bookmarks by URI. --philikon<br />
<br />
Let's just drop support for querying on URI. --sdwilsh<br />
<br />
=== Missing attributes ignored on update ===<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
<code>updateItem({id:2}, {guid:"GUID_HERE"});</code><br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
Yes, it would be great if missing properties on the nsIBookmarkInfo object would simply be ignored in the update. The same should go for annotations. This means that this API wouldn't allow us to remove annotations, but that's ok since we have no need for it. But we do avoid having to first get all the information before updating it. --philikon<br />
<br />
This shouldn't be a problem. We can add an API in the future for removal of data, but we do not need to in this cycle (2.0). --sdwilsh<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
interface nsIVisitInfo : nsISupports<br />
{<br />
// visit id (moz_historyvisits.id)<br />
readonly long long id;<br />
readonly PRTime date;<br />
readonly long transitionType;<br />
}<br />
<br />
interface nsIPlaceInfo : nsISupports<br />
{<br />
// place id<br />
readonly long long id;<br />
readonly nsIURI uri;<br />
readonly AString title;<br />
readonly ACString guid;<br />
readonly long long frecency;<br />
<br />
/**<br />
* An array of nsIVisitInfo objects for the place.<br />
*/<br />
readonly nsIVariant visits;<br />
}<br />
<br />
interface nsIPlaceInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the visit methods has added a visit.<br />
*<br />
* @param aResultCode<br />
* nsresult of the visit addition. Success indicated by Components.isSuccessCode(aResultCode).<br />
* @param aPlaceInfo<br />
* The information about the visit.<br />
*/<br />
void onComplete(in nsresult aResultCode,<br />
in nsIPlaceInfo aPlaceInfo);<br />
}<br />
<br />
/**<br />
* Adds a set of visits for a place info object. The callback is called once for each visit. Ignores duplicates. Also updates the guid or title.<br />
*<br />
* @param aPlaceInfo<br />
* Information about the place to add.<br />
* @param [optional] aCallback<br />
* Callback to be notified.<br />
*/<br />
void updatePlaceAndAddVisits(in nsIPlaceInfo aPlaceInfo,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
<br />
/**<br />
* Just like updatePlaceAndAddVisits.<br />
*<br />
* @param aPlaceInfos<br />
* Information about the places to add.<br />
* @param aPlaces<br />
* The number of aPlaceInfos.<br />
* @param [optional] aCallback<br />
* Callback to be notified.<br />
*/<br />
void updatePlacesAndAddVisits([array, size_is(aPlaces)] in nsIPlaceInfo aPlaceInfos,<br />
in unsigned long aPlaces,<br />
[optional] in nsIVisitInfoCallback aCallback);</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=268253Places/AsyncAPIsForSync2010-11-17T00:52:24Z<p>Comrade693: /* nsIBookmarkInfo */ Added frecency.</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
readonly long long frecency;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark. These are item annotations from nsIAnnotationService.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertBookmark ===<br />
<br />
/**<br />
* Inserts a bookmark item. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertItem(in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertBookmarksWithInfo ===<br />
<br />
/**<br />
* Inserts many bookmark items. Just like insertItem otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertItems([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateBookmarkWithInfo ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark item. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateItem(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateItems ===<br />
<br />
/**<br />
* Updates many bookmark items. Just like updateItem otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateItems([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
=== No need for "plural" methods ===<br />
Due to the way Sync engines work, we have no need for the batch operation methods (insertBookmarks, updateItems) as we deal with each bookmark record individually. We're running this in batchmode anyway. --philikon<br />
<br />
We didn't want runInBatchMode to have magic flags that deal with these async methods. Shouldn't be a problem for the Sync team to deal with this new way. --sdwilsh<br />
<br />
=== Types of places items covered ===<br />
<br />
Just so we're on the same page, these are the data types Sync supports:<br />
* bookmarks (TYPE_BOOKMARK)<br />
* folders (TYPE_FOLDER)<br />
* separators (TYPE_SEPARATOR)<br />
* microsummary (TYPE_BOOKMARK with microsummary)<br />
* livemark (TYPE_FOLDER that's a livemark)<br />
* query (TYPE_BOOKMARK with a place: URI)<br />
Note that Sync does not support "dynamic containers" (TYPE_DYNAMIC_CONTAINER). --philikon<br />
<br />
All these are covered, but you may have to roll your own way with annotations. --sdwilsh<br />
<br />
=== Interfaces ===<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
=== Parent Name===<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
Having the parent name in there feels awkward but it would make our code much easier while making the places code only slightly more complicated (I hope). I will have to think about alternatives to our current duping algorithm, but there's probably little alternative to having it match folder names. --philikon<br />
<br />
Decision: keep the parentName. --sdwilsh<br />
<br />
=== Predecessor ===<br />
<br />
This is similar to the parent name issue: In order to preserve ordering, Sync maintains the GUID of an item's predecessor in each record. So it'd be good if nsIBookmarkInfo were to contain that info. Bonus points for making <code>updateItem</code> understand this and move the item appropriately. --philikon<br />
<br />
We'd like to just keep it at itemIndex, due to more complicated queries or more queries. philikon says it's possible, but will follow up. --sdwilsh<br />
<br />
=== Tags ===<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
We explicitly ignore the tags folder right now, so it doesn't magically work. Sync uses the tagging service API explicitly. So either we should perhaps start syncing the tags folder (if that does indeed magically work) or nsIBookmarkInfo should contain the tags. --philikon<br />
<br />
OK, we could add a getBookmarkInfoWithTags (or have another argument to getBookmarkInfo) that could obtain tags too. Syncing the bookmarg tags folder wouldn't work out right for things like the iphone client. --sdwilsh<br />
<br />
=== nsIBookmarkInfo readonly ===<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly. --mak<br />
<br />
It shouldn't matter. We don't have to return the same nsIBookmarkInfo object that we are passed in (in fact, for threadsafety reasons, we shouldn't!) --sdwilsh<br />
<br />
=== Query by URI ===<br />
<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
Pretty sure we don't have any need for querying bookmarks by URI. --philikon<br />
<br />
Let's just drop support for querying on URI. --sdwilsh<br />
<br />
=== Missing attributes ignored on update ===<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
<code>updateItem({id:2}, {guid:"GUID_HERE"});</code><br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
Yes, it would be great if missing properties on the nsIBookmarkInfo object would simply be ignored in the update. The same should go for annotations. This means that this API wouldn't allow us to remove annotations, but that's ok since we have no need for it. But we do avoid having to first get all the information before updating it. --philikon<br />
<br />
This shouldn't be a problem. We can add an API in the future for removal of data, but we do not need to in this cycle (2.0). --sdwilsh<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
interface nsIVisitInfo : nsISupports<br />
{<br />
// visit id (moz_historyvisits.id)<br />
readonly long long id;<br />
readonly PRTime date;<br />
readonly long transitionType;<br />
}<br />
<br />
interface nsIPlaceInfo : nsISupports<br />
{<br />
// place id<br />
readonly long long id;<br />
readonly nsIURI uri;<br />
readonly AString title;<br />
readonly ACString guid;<br />
<br />
/**<br />
* An array of nsIVisitInfo objects for the place.<br />
*/<br />
readonly nsIVariant visits;<br />
}<br />
<br />
interface nsIPlaceInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the visit methods has added a visit.<br />
*<br />
* @param aResultCode<br />
* nsresult of the visit addition. Success indicated by Components.isSuccessCode(aResultCode).<br />
* @param aPlaceInfo<br />
* The information about the visit.<br />
*/<br />
void onComplete(in nsresult aResultCode,<br />
in nsIPlaceInfo aPlaceInfo);<br />
}<br />
<br />
/**<br />
* Adds a set of visits for a place info object. The callback is called once for each visit. Ignores duplicates. Also updates the guid or title.<br />
*<br />
* @param aPlaceInfo<br />
* Information about the place to add.<br />
* @param [optional] aCallback<br />
* Callback to be notified.<br />
*/<br />
void updatePlaceAndAddVisits(in nsIPlaceInfo aPlaceInfo,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
<br />
/**<br />
* Just like updatePlaceAndAddVisits.<br />
*<br />
* @param aPlaceInfos<br />
* Information about the places to add.<br />
* @param aPlaces<br />
* The number of aPlaceInfos.<br />
* @param [optional] aCallback<br />
* Callback to be notified.<br />
*/<br />
void updatePlacesAndAddVisits([array, size_is(aPlaces)] in nsIPlaceInfo aPlaceInfos,<br />
in unsigned long aPlaces,<br />
[optional] in nsIVisitInfoCallback aCallback);</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=268249Places/AsyncAPIsForSync2010-11-17T00:47:30Z<p>Comrade693: /* Detailed Proposal */ History proposal</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark. These are item annotations from nsIAnnotationService.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertBookmark ===<br />
<br />
/**<br />
* Inserts a bookmark item. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertItem(in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertBookmarksWithInfo ===<br />
<br />
/**<br />
* Inserts many bookmark items. Just like insertItem otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertItems([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateBookmarkWithInfo ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark item. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateItem(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateItems ===<br />
<br />
/**<br />
* Updates many bookmark items. Just like updateItem otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateItems([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
=== No need for "plural" methods ===<br />
Due to the way Sync engines work, we have no need for the batch operation methods (insertBookmarks, updateItems) as we deal with each bookmark record individually. We're running this in batchmode anyway. --philikon<br />
<br />
We didn't want runInBatchMode to have magic flags that deal with these async methods. Shouldn't be a problem for the Sync team to deal with this new way. --sdwilsh<br />
<br />
=== Types of places items covered ===<br />
<br />
Just so we're on the same page, these are the data types Sync supports:<br />
* bookmarks (TYPE_BOOKMARK)<br />
* folders (TYPE_FOLDER)<br />
* separators (TYPE_SEPARATOR)<br />
* microsummary (TYPE_BOOKMARK with microsummary)<br />
* livemark (TYPE_FOLDER that's a livemark)<br />
* query (TYPE_BOOKMARK with a place: URI)<br />
Note that Sync does not support "dynamic containers" (TYPE_DYNAMIC_CONTAINER). --philikon<br />
<br />
All these are covered, but you may have to roll your own way with annotations. --sdwilsh<br />
<br />
=== Interfaces ===<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
=== Parent Name===<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
Having the parent name in there feels awkward but it would make our code much easier while making the places code only slightly more complicated (I hope). I will have to think about alternatives to our current duping algorithm, but there's probably little alternative to having it match folder names. --philikon<br />
<br />
Decision: keep the parentName. --sdwilsh<br />
<br />
=== Predecessor ===<br />
<br />
This is similar to the parent name issue: In order to preserve ordering, Sync maintains the GUID of an item's predecessor in each record. So it'd be good if nsIBookmarkInfo were to contain that info. Bonus points for making <code>updateItem</code> understand this and move the item appropriately. --philikon<br />
<br />
We'd like to just keep it at itemIndex, due to more complicated queries or more queries. philikon says it's possible, but will follow up. --sdwilsh<br />
<br />
=== Tags ===<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
We explicitly ignore the tags folder right now, so it doesn't magically work. Sync uses the tagging service API explicitly. So either we should perhaps start syncing the tags folder (if that does indeed magically work) or nsIBookmarkInfo should contain the tags. --philikon<br />
<br />
OK, we could add a getBookmarkInfoWithTags (or have another argument to getBookmarkInfo) that could obtain tags too. Syncing the bookmarg tags folder wouldn't work out right for things like the iphone client. --sdwilsh<br />
<br />
=== nsIBookmarkInfo readonly ===<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly. --mak<br />
<br />
It shouldn't matter. We don't have to return the same nsIBookmarkInfo object that we are passed in (in fact, for threadsafety reasons, we shouldn't!) --sdwilsh<br />
<br />
=== Query by URI ===<br />
<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
Pretty sure we don't have any need for querying bookmarks by URI. --philikon<br />
<br />
Let's just drop support for querying on URI. --sdwilsh<br />
<br />
=== Missing attributes ignored on update ===<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
<code>updateItem({id:2}, {guid:"GUID_HERE"});</code><br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
Yes, it would be great if missing properties on the nsIBookmarkInfo object would simply be ignored in the update. The same should go for annotations. This means that this API wouldn't allow us to remove annotations, but that's ok since we have no need for it. But we do avoid having to first get all the information before updating it. --philikon<br />
<br />
This shouldn't be a problem. We can add an API in the future for removal of data, but we do not need to in this cycle (2.0). --sdwilsh<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
interface nsIVisitInfo : nsISupports<br />
{<br />
// visit id (moz_historyvisits.id)<br />
readonly long long id;<br />
readonly PRTime date;<br />
readonly long transitionType;<br />
}<br />
<br />
interface nsIPlaceInfo : nsISupports<br />
{<br />
// place id<br />
readonly long long id;<br />
readonly nsIURI uri;<br />
readonly AString title;<br />
readonly ACString guid;<br />
<br />
/**<br />
* An array of nsIVisitInfo objects for the place.<br />
*/<br />
readonly nsIVariant visits;<br />
}<br />
<br />
interface nsIPlaceInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the visit methods has added a visit.<br />
*<br />
* @param aResultCode<br />
* nsresult of the visit addition. Success indicated by Components.isSuccessCode(aResultCode).<br />
* @param aPlaceInfo<br />
* The information about the visit.<br />
*/<br />
void onComplete(in nsresult aResultCode,<br />
in nsIPlaceInfo aPlaceInfo);<br />
}<br />
<br />
/**<br />
* Adds a set of visits for a place info object. The callback is called once for each visit. Ignores duplicates. Also updates the guid or title.<br />
*<br />
* @param aPlaceInfo<br />
* Information about the place to add.<br />
* @param [optional] aCallback<br />
* Callback to be notified.<br />
*/<br />
void updatePlaceAndAddVisits(in nsIPlaceInfo aPlaceInfo,<br />
[optional] in nsIVisitInfoCallback aCallback);<br />
<br />
<br />
/**<br />
* Just like updatePlaceAndAddVisits.<br />
*<br />
* @param aPlaceInfos<br />
* Information about the places to add.<br />
* @param aPlaces<br />
* The number of aPlaceInfos.<br />
* @param [optional] aCallback<br />
* Callback to be notified.<br />
*/<br />
void updatePlacesAndAddVisits([array, size_is(aPlaces)] in nsIPlaceInfo aPlaceInfos,<br />
in unsigned long aPlaces,<br />
[optional] in nsIVisitInfoCallback aCallback);</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=268243Places/AsyncAPIsForSync2010-11-17T00:15:30Z<p>Comrade693: /* Notes and feedback on Proposal */ Bookmark API Feedback (responding to philikon)</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark. These are item annotations from nsIAnnotationService.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertBookmark ===<br />
<br />
/**<br />
* Inserts a bookmark item. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertItem(in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertBookmarksWithInfo ===<br />
<br />
/**<br />
* Inserts many bookmark items. Just like insertItem otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertItems([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateBookmarkWithInfo ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark item. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateItem(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateItems ===<br />
<br />
/**<br />
* Updates many bookmark items. Just like updateItem otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateItems([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
=== No need for "plural" methods ===<br />
Due to the way Sync engines work, we have no need for the batch operation methods (insertBookmarks, updateItems) as we deal with each bookmark record individually. We're running this in batchmode anyway. --philikon<br />
<br />
We didn't want runInBatchMode to have magic flags that deal with these async methods. Shouldn't be a problem for the Sync team to deal with this new way. --sdwilsh<br />
<br />
=== Types of places items covered ===<br />
<br />
Just so we're on the same page, these are the data types Sync supports:<br />
* bookmarks (TYPE_BOOKMARK)<br />
* folders (TYPE_FOLDER)<br />
* separators (TYPE_SEPARATOR)<br />
* microsummary (TYPE_BOOKMARK with microsummary)<br />
* livemark (TYPE_FOLDER that's a livemark)<br />
* query (TYPE_BOOKMARK with a place: URI)<br />
Note that Sync does not support "dynamic containers" (TYPE_DYNAMIC_CONTAINER). --philikon<br />
<br />
All these are covered, but you may have to roll your own way with annotations. --sdwilsh<br />
<br />
=== Interfaces ===<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
=== Parent Name===<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
Having the parent name in there feels awkward but it would make our code much easier while making the places code only slightly more complicated (I hope). I will have to think about alternatives to our current duping algorithm, but there's probably little alternative to having it match folder names. --philikon<br />
<br />
Decision: keep the parentName. --sdwilsh<br />
<br />
=== Predecessor ===<br />
<br />
This is similar to the parent name issue: In order to preserve ordering, Sync maintains the GUID of an item's predecessor in each record. So it'd be good if nsIBookmarkInfo were to contain that info. Bonus points for making <code>updateItem</code> understand this and move the item appropriately. --philikon<br />
<br />
We'd like to just keep it at itemIndex, due to more complicated queries or more queries. philikon says it's possible, but will follow up. --sdwilsh<br />
<br />
=== Tags ===<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
We explicitly ignore the tags folder right now, so it doesn't magically work. Sync uses the tagging service API explicitly. So either we should perhaps start syncing the tags folder (if that does indeed magically work) or nsIBookmarkInfo should contain the tags. --philikon<br />
<br />
OK, we could add a getBookmarkInfoWithTags (or have another argument to getBookmarkInfo) that could obtain tags too. Syncing the bookmarg tags folder wouldn't work out right for things like the iphone client. --sdwilsh<br />
<br />
=== nsIBookmarkInfo readonly ===<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly. --mak<br />
<br />
It shouldn't matter. We don't have to return the same nsIBookmarkInfo object that we are passed in (in fact, for threadsafety reasons, we shouldn't!) --sdwilsh<br />
<br />
=== Query by URI ===<br />
<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
Pretty sure we don't have any need for querying bookmarks by URI. --philikon<br />
<br />
Let's just drop support for querying on URI. --sdwilsh<br />
<br />
=== Missing attributes ignored on update ===<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
<code>updateItem({id:2}, {guid:"GUID_HERE"});</code><br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
Yes, it would be great if missing properties on the nsIBookmarkInfo object would simply be ignored in the update. The same should go for annotations. This means that this API wouldn't allow us to remove annotations, but that's ok since we have no need for it. But we do avoid having to first get all the information before updating it. --philikon<br />
<br />
This shouldn't be a problem. We can add an API in the future for removal of data, but we do not need to in this cycle (2.0). --sdwilsh<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
Introduce<br />
<br />
* addVisitsAsync(uri, title, [array of visits], callback)<br />
<br />
TODO flesh out</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=267475Places/AsyncAPIsForSync2010-11-12T20:06:14Z<p>Comrade693: /* Notes and feedback on Proposal */ Address one piece of feedback that I missed before.</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark. These are item annotations from nsIAnnotationService.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertBookmark ===<br />
<br />
/**<br />
* Inserts a bookmark item. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertItem(in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertBookmarksWithInfo ===<br />
<br />
/**<br />
* Inserts many bookmark items. Just like insertItem otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertItems([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateBookmarkWithInfo ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark item. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateItem(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateItem ===<br />
<br />
/**<br />
* Updates many bookmark items. Just like updateItem otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateItems([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly. --mak<br />
It shouldn't matter. We don't have to return the same nsIBookmarkInfo object that we are passed in (in fact, for threadsafety reasons, we shouldn't!) --sdwilsh<br />
<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
updateItem({id:2}, {guid:"GUID_HERE"});<br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
Introduce<br />
<br />
* addVisitsAsync(uri, title, [array of visits], callback)<br />
<br />
TODO flesh out</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=267473Places/AsyncAPIsForSync2010-11-12T19:58:44Z<p>Comrade693: Update proposal based on feedback from mak and remove feedback that was addressed.</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark. These are item annotations from nsIAnnotationService.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertBookmark ===<br />
<br />
/**<br />
* Inserts a bookmark item. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertItem(in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertBookmarksWithInfo ===<br />
<br />
/**<br />
* Inserts many bookmark items. Just like insertItem otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertItems([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateBookmarkWithInfo ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark item. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateItem(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateItem ===<br />
<br />
/**<br />
* Updates many bookmark items. Just like updateItem otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateItems([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
[optional] in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal ==<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly.<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
updateItem({id:2}, {guid:"GUID_HERE"});<br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
Introduce<br />
<br />
* addVisitsAsync(uri, title, [array of visits], callback)<br />
<br />
TODO flesh out</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=267471Places/AsyncAPIsForSync2010-11-12T19:51:09Z<p>Comrade693: /* Notes and feedback on Proposal 1 */ Responses to mak's feedback.</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal 1==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertBookmark ===<br />
<br />
/**<br />
* Inserts a bookmark. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertBookmarkWithInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertBookmarksWithInfo ===<br />
<br />
/**<br />
* Inserts many bookmarks. Just like insertBookmarkWithInfo otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertBookmarksWithInfo([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateBookmarkWithInfo ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateBookmarkInfo(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateBookmarksWithInfo ===<br />
<br />
/**<br />
* Updates many bookmarks. Just like updateBookmarkWithInfo otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateBookmarksWithInfo([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal 1 ==<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
Don't have a strong preference. I say just defer to sr on this. --sdwilsh<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
I think the whole setup is a bit volatile. We should see what the Sync team says about it and if they care that they might have to do a second query to get the actual name. It's not hard to add it if need be, it just feels awkward. --sdwilsh<br />
<br />
nsIAnnotationInfo could most likely drop "flags" support. It has never been really used nor we plan to start using it. --mak<br />
It's also cheap to keep for now. I think that as long as we support it on nsIAnnotaitonService, we should keep it here. --sdwilsh<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it? --mak<br />
I thought about this, but I'm pretty sure that because we store tags as a bookmark in a different root, Sync will just work magically anyway. We should confirm this with them though. I'd rather not add it yet if we can avoid it because this is already a lot of work. --sdwilsh<br />
<br />
dynamic containers are a dead-feature-walking. nothing is using them. --mak<br />
Yeah, we only kinda support them via the type argument. --sdwilsh<br />
<br />
is nsIBookmarkInfoCallback really useful? Probably yes if the implementer does not want to have a bookmarks observer, that on our side is also expensive. Most likely if the implementer has an observer the callback has no use. --mak<br />
Even if they have a bookmarks observer, they'd have to query to get things like guids (or also check for annotaitons, etc). Using the callback is a lot easier. However, it should be [optional] for all methods that take it. --sdwilsh<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly.<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
Last modified probably works fine, but we should check with the Sync team. I suspect they might actually care about all cases, in which case, we need to change our approach a bit. --sdwilsh<br />
<br />
insertBookmarkWithInfo looks a strange name. First it is clear I have to pass some info to create a bookmark, second this can create bookmarks, folders, separators... maybe we should go for a generic createItem() method --mak<br />
I'd be fine with insertItem. --sdwilsh<br />
<br />
insertBookmarksWithInfo same as above. Fine for batching since it's handled internally.<br />
Is the single instance useless if one can just use the multiple one with a 1-sized array? --mak<br />
Consumer convenience, really. The backend can easily just call the array method (this is how storage does the different executeAsyncs). --sdwilsh<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
How about updateItem then? The implementer should only have to pass in the id or the guid. I envisioned them also being able to specify only the parts that changed:<br />
updateItem({id:2}, {guid:"GUID_HERE"});<br />
This would set the guid on item with id of 2 to "GUID_HERE". Easy to implement because things will just throw NS_ERROR_NOT_IMPLEMENTED. I hope this doesn't get logged to the error console though... --sdwilsh<br />
<br />
regarding the batch thing, same as above, do we need both? --mak<br />
trivial to do, ends up being easier for the consumer (thinking really of the browser/fennec UI). --sdwilsh<br />
<br />
Regarding annotations, what should be set? a page or a bookmark annotation? most likely so far we just need bookmark annotations. Page annotations are mostly used for charsets. --mak<br />
bookmark annotation. --sdwilsh<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
Introduce<br />
<br />
* addVisitsAsync(uri, title, [array of visits], callback)<br />
<br />
TODO flesh out</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=267466Places/AsyncAPIsForSync2010-11-12T19:37:29Z<p>Comrade693: /* Notes and feedback on Proposal 1 */ Tag mak's feedback with his name.</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal 1==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertBookmark ===<br />
<br />
/**<br />
* Inserts a bookmark. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertBookmarkWithInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertBookmarksWithInfo ===<br />
<br />
/**<br />
* Inserts many bookmarks. Just like insertBookmarkWithInfo otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertBookmarksWithInfo([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateBookmarkWithInfo ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateBookmarkInfo(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateBookmarksWithInfo ===<br />
<br />
/**<br />
* Updates many bookmarks. Just like updateBookmarkWithInfo otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateBookmarksWithInfo([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
== Notes and feedback on Proposal 1 ==<br />
<br />
The separate interface is the best bet, both for compatibility and clear sync/async separation.<br />
Name could either be nsIBookmarksService (drop ns?) or IAsyncBookmarks. --mak<br />
<br />
Sync seem to use parentName for reconciliation, but does not look like something that should be part of the API, both the parent and the name can change easily and having 2 volatile informations seem fragile. On the other side caching parent names on the fly in a local hash is probably as efficient. --mak<br />
<br />
nsIAnnotationInfo could most likely drop "flags" support. It has never been really used nor we plan to start using it. --mak<br />
<br />
nsIBookmarkInfo should most likely include tags or we need a way to set tags async. It's indeed impossible to create a bookmark async and tag it synchronously. it could be possible to add tags in the bookmarks added notification, but is it worth it?<br />
dynamic containers are a dead-feature-walking. nothing is using them. --mak<br />
<br />
is nsIBookmarkInfoCallback really useful? Probably yes if the implementer does not want to have a bookmarks observer, that on our side is also expensive. Most likely if the implementer has an observer the callback has no use. --mak<br />
<br />
getBookmarkInfo takes a nsIBookmarkInfo object, thus we probably don't want all of its properties being readonly.<br />
Notice that while passing an id or guid will return a single bookmark, passing an uri is not guaranteed to do so. the same uri can have multiple bookmarks. what to do here? either don't allow by uri, or return last modified bookmark (that is what we do today) --mak<br />
<br />
insertBookmarkWithInfo looks a strange name. First it is clear I have to pass some info to create a bookmark, second this can create bookmarks, folders, separators... maybe we should go for a generic createItem() method --mak<br />
<br />
insertBookmarksWithInfo same as above. Fine for batching since it's handled internally.<br />
Is the single instance useless if one can just use the multiple one with a 1-sized array? --mak<br />
<br />
updatebookmarkWithInfo same as above for name. Actually how to handle missing information in the info object? Does the implementer have to collect all info, change and then submit? Or things that should not be changed must be null? How to set a null value then?<br />
Having to collect info to be able to change them is going to be more expensive than changing them one by one. --mak<br />
<br />
regarding the batch thing, same as above, do we need both? --mak<br />
<br />
Regarding annotations, what should be set? a page or a bookmark annotation? most likely so far we just need bookmark annotations. Page annotations are mostly used for charsets. --mak<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
Introduce<br />
<br />
* addVisitsAsync(uri, title, [array of visits], callback)<br />
<br />
TODO flesh out</div>Comrade693https://wiki.mozilla.org/index.php?title=Places/AsyncAPIsForSync&diff=267392Places/AsyncAPIsForSync2010-11-12T03:46:26Z<p>Comrade693: /* Detailed Proposal */ Bookmark API propospal</p>
<hr />
<div>=Overview=<br />
<br />
Tracking bug for Sync: {{bug|606353}}<br />
<br />
==Current situation==<br />
<br />
Right now Sync calls various synchronousm Places API methods to read and write records, with the exception of history reads where it rolls its own asynchronous SQL queries.<br />
<br />
==Problem==<br />
<br />
Synchronous sqlite I/O is hurting us a lot on mobile.<br />
<br />
==Proposed solution==<br />
<br />
Provide powerful asynchronous methods to replace Sync's many synchronous calls. So instead of adding a bookmark and then adding a bunch of annotations to it, it would be great if Places had an API that would let us do it one go, do all the writes async and then call us back.<br />
<br />
=Bookmarks=<br />
<br />
{{bug|519514}}<br />
<br />
Description of Sync's bookmark record (includes folders, separators, livemarks, etc.): https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#bookmark<br />
<br />
==Read==<br />
<br />
For syncing out as well as conflict resolution, right now we call<br />
<br />
* getFolderIdForItem()<br />
* getBookmarkURI()<br />
* getKeywordForBookmark()<br />
* and get the various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.).<br />
<br />
I imagine that this information could be retrieved with one query which could be wrapped into getBookmarkInfoAsync() or similar API call.<br />
<br />
==Write==<br />
<br />
We currently use the following nsINavBookmarksService methods to create items:<br />
<br />
* insertBookmark()<br />
* createFolder()<br />
* insertSeparator()<br />
* as well as nsILivemarkService::createLivemark()<br />
<br />
When we make these or a subset of these async, how will be notified of the ID (and later, when we add GUIDs, their GUID)? Through an nsINavBookmarkObserver? Or will there be a callback we can pass into? We need the ID / GUID so that we can set various "bookmarkProperties/" annotations (description, loadInSidebar, staticTitle, etc.) as well as keywords via setKeywordForBookmark(). Ideally, of course, we could follow aforementioned theme and have the insert*Async() methods allow us to pass those in as well. Then we'd only need a callback for special cases such as microsummaries and tags.<br />
<br />
To update already existing items, we call setItemTitle(), changeBookmarkURI(), setKeywordForBookmark() and update various annations. Perhaps there could be an updateBookmarkAsync() akin to insertBookmarkAsync() to save us these various separate method calls?<br />
<br />
==Detailed Proposal==<br />
<br />
The new methods can be added to a new interface. Maybe nsIBookmarksService (and it only ever does async stuff)?<br />
<br />
The only thing not covered here so far is livemarks. Not sure if it's worth an API for them or not (can we get data on how many people store now?).<br />
<br />
=== nsIAnnotationInfo ===<br />
<br />
/**<br />
* Interface that describes an annotation.<br />
*/<br />
interface nsIAnnotationInfo : nsISupports<br />
{<br />
readonly AUTF8String name;<br />
readonly nsIVariant value;<br />
readonly long flags;<br />
readonly unsigned short expiration;<br />
}<br />
<br />
Ideally, we could use this for a future async annotation service. For now, it's just purposed for nsIBookmarkInfo.<br />
<br />
=== nsIBookmarkInfo ===<br />
<br />
/**<br />
* Interface that describes a bookmark.<br />
*/<br />
interface nsIBookmarkInfo : nsISupports<br />
{<br />
readonly ACString guid;<br />
readonly long long id;<br />
readonly unsigned short type;<br />
readonly long long parentId;<br />
readonly ACString parentGuid;<br />
readonly long index;<br />
readonly nsIURI uri;<br />
readonly AString keyword;<br />
readonly AString title;<br />
/**<br />
* An array of nsIAnnotationInfo objects for the bookmark.<br />
*/<br />
readonly nsIVariant annotations;<br />
}<br />
<br />
The idea here is that this interface will be returned and given to places APIs when you ask for information about a bookmark, and when you want to add a bookmark. Because we have the type present, this will handle bookmarks, folders, separators, and dynamic containers (which, if I recall correctly, handles microsummaries and live bookmarks).<br />
<br />
I included guids here, which makes this gated (possibly) on {{bug|607117}}.<br />
<br />
Not clear to me if we need tags on here or not. Need input from the Sync team.<br />
<br />
=== nsIBookmarkInfoCallback ===<br />
<br />
interface nsIBookmarkInfoCallback : nsISupports<br />
{<br />
/**<br />
* Called when one of the bookmark methods is done with its work.<br />
*<br />
* @param aBookmarkInfo<br />
* The information about the bookmark, or undefined if nothing was found.<br />
*/<br />
void onComplete(in nsIBookmarkInfo aBookmarkInfo);<br />
}<br />
<br />
This should be marked with [function] so JS consumers can just pass a function in if they want.<br />
<br />
=== getBookmarkInfo ===<br />
<br />
/**<br />
* Gets all information known about a bookmark. Callers must specify the id, guid, or the URI of the bookmark in question.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have the information about the bookmark.<br />
*/<br />
void getBookmarkInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Consumers would do something like this:<br />
bs.getBookmarkInfo({guid:"..."}, function(aInfo) { ... });<br />
<br />
C++ consumers won't be happy, but I'm not sure I care.<br />
<br />
=== insertBookmark ===<br />
<br />
/**<br />
* Inserts a bookmark. Required fields on nsIBookmarkInfo are:<br />
* - parentId or parentGuid<br />
* - uri<br />
* - title<br />
* Everything else is optional.<br />
*<br />
* @param aInfo<br />
* The bookmark info object that contains the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added the bookmark.<br />
*/<br />
void insertBookmarkWithInfo(in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Need to document about everything that would make us throw. Also, how do we handle errors? Want to keep the callback simple, ideally.<br />
<br />
=== insertBookmarksWithInfo ===<br />
<br />
/**<br />
* Inserts many bookmarks. Just like insertBookmarkWithInfo otherwise.<br />
*<br />
* @param aInfo<br />
* The bookmark info objects that contain the data needed.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void insertBookmarksWithInfo([array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
Just like insertBookmarkWithInfo, but takes a big array of bookmark info and does it all at once. This is basically the batch mode version. I suspect mak and I are going to debate how to best do batch mode, so this may change a lot still.<br />
<br />
=== updateBookmarkWithInfo ===<br />
<br />
/**<br />
* <br />
* Update the information about a bookmark. Callers must specify the id, guid, xor the URI of the bookmark in question.<br />
*<br />
* @param aIdentifier<br />
* The bookmark info object that contains the id xor the guid xor the URI of the bookmark.<br />
* @param aInfo<br />
* The information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have updated the information about the bookmark.<br />
*/<br />
void updateBookmarkInfo(in nsIBookmarkInfo aIdentifier,<br />
in nsIBookmarkInfo aInfo,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
=== updateBookmarksWithInfo ===<br />
<br />
/**<br />
* Updates many bookmarks. Just like updateBookmarkWithInfo otherwise. aIdentifiers and aInfo must have a 1:1 mapping.<br />
*<br />
* @param aIdentifiers<br />
* Array of bookmark info objects that contains the id xor the guid xor the URI of the bookmarks.<br />
* @param aInfo<br />
* Array of information to update about the bookmark.<br />
* @param aCallback<br />
* The object/function to notify when we have added each bookmark.<br />
*/<br />
void updateBookmarksWithInfo([array, size_is(aLength) in nsIBookmarkInfo aIdentifiers,<br />
[array, size_is(aLength) in nsIBookmarkInfo aInfo,<br />
in unsigned long aLength,<br />
in nsIBookmarkInfoCallback aCallback);<br />
<br />
=History=<br />
<br />
{{bug|606966}}<br />
<br />
Same as with bookmarks, really, but much less complicated.<br />
<br />
Description of Sync's history records: https://wiki.mozilla.org/Labs/Weave/Developer/BrowserObjects#history<br />
<br />
==Read==<br />
<br />
We already roll our own async SQL queries to fetch the metadata for a history entry and its visits (two queries). We could push this down to Places, but given that we already do the right thing here, it probably has low priority.<br />
<br />
==Write==<br />
<br />
Right now call nsINavHistoryService::addVisit() for each visit in a history record that doesn't exist locally yet and then nsINavHistoryService::setPageTitle() to set the page title. As discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=606966#c14, an API that would allow us to pass in the page title and a list of visits would be great. It would asynchronously set the page title and add all the visits (unless they exist already)<br />
<br />
==Detailed Proposal==<br />
<br />
Introduce<br />
<br />
* addVisitsAsync(uri, title, [array of visits], callback)<br />
<br />
TODO flesh out</div>Comrade693https://wiki.mozilla.org/index.php?title=Mobile/Platforms/Android&diff=254795Mobile/Platforms/Android2010-09-21T13:29:44Z<p>Comrade693: /* ARMv7 */ nothumb builds do not help Galaxy-S phones</p>
<hr />
<div>== Firefox for Android ==<br />
<br />
Firefox for Android is part of the [[Fennec]] project to bring the Firefox web browser to mobile devices. For more information about Fennec, see the [http://www.mozilla.com/mobile/ Firefox Mobile web site].<br />
<br />
* '''Latest Version:''' Alpha 1<br />
* '''Optimized for:''' Droid, Nexus One, other phones with ~1 GHz CPU and 800x480 display<br />
* '''System Requirements:''' Android 2.0 or higher, OpenGL ES2.0, 256 MB RAM, 30 MB phone storage available<br />
<br />
== Status ==<br />
<br />
Firefox for Android is in very early development. Stay tuned and follow us on [http://twitter.com/mozmobile Twitter] and [http://www.facebook.com/firefoxformobile Facebook] to hear about new releases and other announcements. Or read our [http://planet.firefox.com/mobile/ developer blogs] to follow our progress.<br />
<br />
We have not yet set a date for the first release of Firefox for Android, but<br />
we are tentatively planning for a release before the end of 2010, with beta releases earlier in the year. See [[Mobile/Planning/2.0]] for more information.<br />
<br />
== Download Alpha ==<br />
<br />
The first Fenenc alpha for Android is now available. See the [http://blog.mozilla.com/blog/2010/08/27/fennec-alpha-released-for-android-and-nokia-n900/ blog post] and [http://www.mozilla.com/en-US/mobile/2.0a1/releasenotes/index.html release notes] for more information.<br />
<br />
Important notes:<br />
<br />
[[Image:Fennec-alpha-download.png|right]]<br />
<br />
* Check the [[#System Requirements|system requirements]] below. This alpha is available for '''ARMv7 only''', and requires '''Android 2.0 or higher'''.<br />
* If you installed a pre-release or nightly build of Fennec, you will need to '''uninstall the old build''' before installing the alpha. This will erase your profile.<br />
<br />
To install Fennec alpha:<br />
<br />
# Enable installation of non-Market applications in the "Applications" section of the Android settings.<br />
# Go to [http://mozilla.com/m/alpha mozilla.com/m/alpha] in your phone's browser (or scan the barcode to the right), and press the "Download Alpha" button.<br />
# Open the "fennec.apk" file when it finishes downloading.<br />
<br />
== Download Nightly Builds ==<br />
<br />
If you want to develop, test, or preview the next release of Fennec, you can download a nightly build:<br />
<br />
# Enable installation of non-Market applications in the "Applications" section of the Android settings.<br />
# Download the nightly build directly onto your Android device by scanning the barcode below, or by entering the URL in the Android browser.<br />
# Open the '''fennec.apk''' file when it finishes downloading.<br />
<br />
You can also [[Mobile/Platforms|try out Fennec on other platforms]], including on your Mac, Windows, or Linux PC.<br />
<br />
=== ARMv7 ===<br />
<br />
[[Image:Qrcode-fennec-nightly-android.png|right]]<br />
For Android devices with [http://en.wikipedia.org/wiki/ARM_architecture#ARM_cores ARMv7] (Cortex, Snapdragon, Hummingbird) processors, like the Motorola Droid, HTC Desire, HTC Evo 4G, or Samsung Galaxy S. (although you'll see random hangs due to {{bug|597093}}) (See [[#System Requirements|below]] for a longer list of phones.)<br />
<br />
* Short URL: http://bit.ly/b52meS<br />
* Full URL: http://ftp.mozilla.org/pub/mozilla.org/mobile/nightly/latest-mobile-trunk/fennec.apk<br />
<br />
=== ARMv6 (experimental) ===<br />
<br />
[[Image:Qr-code-fennec-nightly-android-nothumb.png|right]]<br />
For devices with [http://en.wikipedia.org/wiki/ARM_architecture#ARM_cores ARMv6] processors, like the HTC Hero, Legend, Droid Eris, Wildfire, or Samsung Moment. (See [[#System Requirements|below]] for a longer list of phones.)<br />
<br />
'''Note:''' The ARMv6 build is new and not widely tested. Many older Android phones do not have enough RAM or storage to run current Fennec builds. Fennec's visual design is not yet optimized for lower-resolution displays ({{Bug|590777}}).<br />
<br />
* Short URL: http://bit.ly/aQ22MP<br />
* Full URL: http://ftp.mozilla.org/pub/mozilla.org/mobile/nightly/latest-mozilla-central-android-r7-nothumb/fennec.apk<br />
<br />
== Known Issues ==<br />
<br />
We are working on fixing all of these bugs.<br />
<br />
'''Installation and Add-ons:'''<br />
* '''Fennec requires around 40 MB of internal storage'''. We have plans to reduce this to 20 MB or less. Like all Android NDK apps, Firefox must copy its native libraries out of the APK file before loading them, so they end up installed twice. We have plans to work around this problem and reduce the installation size ({{bug|588607}}).<br />
* '''Fennec might hang or crash at startup''' if there is very little internal storage available ({{bug|589906}}), or for other unknown reasons.<br />
* '''Adobe Flash and other plugins are not supported yet.'''<br />
* '''Automatic updates do not work in Android 2.1''' or earlier ({{bug|596662}}).<br />
<br />
'''Performance and stability:'''<br />
* '''<font color=red>New (2010-09-16):</font> Fennec hangs unpredictably''' (especially on Samsung Galaxy S phones?) ({{bug|597093}}).<br />
* '''Speed, responsiveness, power efficiency, and memory use''' are all being improved as part of our [[Mobile/Planning/2.0|Fennec 2.0]] effort.<br />
<br />
'''User Interface:'''<br />
* '''<font color=red>New (2010-09-15):</font> After opening a new tab in the background, the new tab's contents appear''' at the bottom of the page in the current tab ({{bug|596717}}).<br />
* '''Multi-touch zoom does not work on some devices''' including the Motorola Droid ({{Bug|589208}}).<br />
* '''Text does not wrap to fit the screen''' after zooming in, as it does in the Android browser ({{bug|578179}}). The [https://addons.mozilla.org/en-US/mobile/addon/157099 Easy Reading] add-on has some proof-of-concept code to do this.<br />
<br />
'''Keyboard:'''<br />
* '''<font color=red>New (2010-09-15):</font> The on-screen keyboard does not appear''' when clicking in form fields on web pages ({{bug|591047}}).<br />
* '''Some keyboards do not show updated text''' as you type in the address bar ({{bug|580388}}). This affects the standard Android keyboard in landscape orientation, and some alternate input methods.<br />
* '''You might need to hold down SHIFT or ALT''' while typing numbers/symbols/capitals on a hardware keyboard ({{bug|583327}}?).<br />
<br />
See also the complete list of [https://bugzilla.mozilla.org/buglist.cgi?resolution=---&op_sys=Android&query_format=advanced open Android bugs] and [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=blocking-fennec%3A2.0b1%2B 2.0 beta 1 blockers] in Bugzilla.<br />
<br />
== System Requirements ==<br />
<br />
Fennec requires '''Android 2.0''' or later. Installation requires about 30 MB of available internal storage. <br />
<br />
We are using these devices for development:<br />
<br />
<font color="#060"><br />
* HTC/Google Nexus One (ARMv7)<br />
</font><br />
<br />
Other users have successfully installed Fennec on these ARMv7 devices:<br />
<br />
<font color="#006"><br />
* Acer Liquid E<br />
* Dell Streak<br />
* HTC Desire<br />
* HTC Droid Incredible<br />
* HTC EVO 4G<br />
* Motorola Droid 2<br />
* Motorola Droid X<br />
* Motorola Milestone (Verizon Droid)<br />
* Samsung Epic 4G<br />
* Samsung Galaxy S (AT&amp;T Captivate, T-Mobile Vibrant)<br />
</font><br />
<br />
These devices are not compatible with our ARMv7-optimized builds, but might be able to run the new ARMv6 builds:<br />
<br />
<font color="#600"><br />
* Android SDK emulator<br />
* Augen GENTouch 7" Tablet<br />
* HTC Aria<br />
* HTC Dream (T-Mobile G1, Android Dev Phone 1)<br />
* HTC Droid Eris<br />
* HTC Hero (T-Mobile G2 Touch)<br />
* HTC Legend<br />
* HTC Magic (T-Mobile myTouch 3G, T-Mobile G1 Touch)<br />
* HTC Tattoo<br />
* HTC Wildfire<br />
* Huawei U8230<br />
* LG Ally<br />
* Motorola Backflip<br />
* Samsung Moment<br />
* Samsung Spica i5700<br />
</font><br />
<br />
We will test and support more Android 2.0 phones soon.<br />
<br />
== Support ==<br />
<br />
Please post any questions or comments to the [https://support.mozilla.com/en-US/questions/new?product=mobile Firefox Mobile support forum].<br />
<br />
== Development ==<br />
<br />
See [[Mobile/Fennec/Android]] for build instructions, developer documentation, and more project status.</div>Comrade693https://wiki.mozilla.org/index.php?title=Mobile/Platforms/Android&diff=254623Mobile/Platforms/Android2010-09-20T20:11:34Z<p>Comrade693: /* ARMv7 */ Point to nothumb builds for Galaxy-S phones</p>
<hr />
<div>== Firefox for Android ==<br />
<br />
Firefox for Android is part of the [[Fennec]] project to bring the Firefox web browser to mobile devices. For more information about Fennec, see the [http://www.mozilla.com/mobile/ Firefox Mobile web site].<br />
<br />
* '''Latest Version:''' Alpha 1<br />
* '''Optimized for:''' Droid, Nexus One, other phones with ~1 GHz CPU and 800x480 display<br />
* '''System Requirements:''' Android 2.0 or higher, OpenGL ES2.0, 256 MB RAM, 30 MB phone storage available<br />
<br />
== Status ==<br />
<br />
Firefox for Android is in very early development. Stay tuned and follow us on [http://twitter.com/mozmobile Twitter] and [http://www.facebook.com/firefoxformobile Facebook] to hear about new releases and other announcements. Or read our [http://planet.firefox.com/mobile/ developer blogs] to follow our progress.<br />
<br />
We have not yet set a date for the first release of Firefox for Android, but<br />
we are tentatively planning for a release before the end of 2010, with beta releases earlier in the year. See [[Mobile/Planning/2.0]] for more information.<br />
<br />
== Download Alpha ==<br />
<br />
The first Fenenc alpha for Android is now available. See the [http://blog.mozilla.com/blog/2010/08/27/fennec-alpha-released-for-android-and-nokia-n900/ blog post] and [http://www.mozilla.com/en-US/mobile/2.0a1/releasenotes/index.html release notes] for more information.<br />
<br />
Important notes:<br />
<br />
[[Image:Fennec-alpha-download.png|right]]<br />
<br />
* Check the [[#System Requirements|system requirements]] below. This alpha is available for '''ARMv7 only''', and requires '''Android 2.0 or higher'''.<br />
* If you installed a pre-release or nightly build of Fennec, you will need to '''uninstall the old build''' before installing the alpha. This will erase your profile.<br />
<br />
To install Fennec alpha:<br />
<br />
# Enable installation of non-Market applications in the "Applications" section of the Android settings.<br />
# Go to [http://mozilla.com/m/alpha mozilla.com/m/alpha] in your phone's browser (or scan the barcode to the right), and press the "Download Alpha" button.<br />
# Open the "fennec.apk" file when it finishes downloading.<br />
<br />
== Download Nightly Builds ==<br />
<br />
If you want to develop, test, or preview the next release of Fennec, you can download a nightly build:<br />
<br />
# Enable installation of non-Market applications in the "Applications" section of the Android settings.<br />
# Download the nightly build directly onto your Android device by scanning the barcode below, or by entering the URL in the Android browser.<br />
# Open the '''fennec.apk''' file when it finishes downloading.<br />
<br />
You can also [[Mobile/Platforms|try out Fennec on other platforms]], including on your Mac, Windows, or Linux PC.<br />
<br />
=== ARMv7 ===<br />
<br />
[[Image:Qrcode-fennec-nightly-android.png|right]]<br />
For Android devices with [http://en.wikipedia.org/wiki/ARM_architecture#ARM_cores ARMv7] (Cortex, Snapdragon, Hummingbird) processors, like the Motorola Droid, HTC Desire, or HTC Evo 4G. (See [[#System Requirements|below]] for a longer list of phones.)<br />
<br />
* Short URL: http://bit.ly/b52meS<br />
* Full URL: http://ftp.mozilla.org/pub/mozilla.org/mobile/nightly/latest-mobile-trunk/fennec.apk<br />
<br />
Samsung Galaxy S phones have some issues with the above builds, so you should grab this build instead:<br />
<br />
* Short URL: http://bit.ly/d77Is0<br />
* Full URL: http://ftp.mozilla.org/pub/mozilla.org/mobile/nightly/latest-mozilla-central-android-r7-nothumb/fennec.apk<br />
<br />
=== ARMv6 (experimental) ===<br />
<br />
[[Image:Qr-code-fennec-nightly-android-nothumb.png|right]]<br />
For devices with [http://en.wikipedia.org/wiki/ARM_architecture#ARM_cores ARMv6] processors, like the HTC Hero, Legend, Droid Eris, Wildfire, or Samsung Moment. (See [[#System Requirements|below]] for a longer list of phones.)<br />
<br />
'''Note:''' The ARMv6 build is new and not widely tested. Many older Android phones do not have enough RAM or storage to run current Fennec builds. Fennec's visual design is not yet optimized for lower-resolution displays ({{Bug|590777}}).<br />
<br />
* Short URL: http://bit.ly/aQ22MP<br />
* Full URL: http://ftp.mozilla.org/pub/mozilla.org/mobile/nightly/latest-mozilla-central-android-r7-nothumb/fennec.apk<br />
<br />
== Known Issues ==<br />
<br />
We are working on fixing all of these bugs.<br />
<br />
'''Installation and Add-ons:'''<br />
* '''Fennec requires around 40 MB of internal storage'''. We have plans to reduce this to 20 MB or less. Like all Android NDK apps, Firefox must copy its native libraries out of the APK file before loading them, so they end up installed twice. We have plans to work around this problem and reduce the installation size ({{bug|588607}}).<br />
* '''Fennec might hang or crash at startup''' if there is very little internal storage available ({{bug|589906}}), or for other unknown reasons.<br />
* '''Adobe Flash and other plugins are not supported yet.'''<br />
* '''Automatic updates do not work in Android 2.1''' or earlier ({{bug|596662}}).<br />
<br />
'''Performance and stability:'''<br />
* '''<font color=red>New (2010-09-16):</font> Fennec hangs unpredictably''' (especially on Samsung Galaxy S phones?) ({{bug|597093}}).<br />
* '''Speed, responsiveness, power efficiency, and memory use''' are all being improved as part of our [[Mobile/Planning/2.0|Fennec 2.0]] effort.<br />
<br />
'''User Interface:'''<br />
* '''<font color=red>New (2010-09-15):</font> After opening a new tab in the background, the new tab's contents appear''' at the bottom of the page in the current tab ({{bug|596717}}).<br />
* '''Multi-touch zoom does not work on some devices''' including the Motorola Droid ({{Bug|589208}}).<br />
* '''Text does not wrap to fit the screen''' after zooming in, as it does in the Android browser ({{bug|578179}}). The [https://addons.mozilla.org/en-US/mobile/addon/157099 Easy Reading] add-on has some proof-of-concept code to do this.<br />
<br />
'''Keyboard:'''<br />
* '''<font color=red>New (2010-09-15):</font> The on-screen keyboard does not appear''' when clicking in form fields on web pages ({{bug|591047}}).<br />
* '''Some keyboards do not show updated text''' as you type in the address bar ({{bug|580388}}). This affects the standard Android keyboard in landscape orientation, and some alternate input methods.<br />
* '''You might need to hold down SHIFT or ALT''' while typing numbers/symbols/capitals on a hardware keyboard ({{bug|583327}}?).<br />
<br />
See also the complete list of [https://bugzilla.mozilla.org/buglist.cgi?resolution=---&op_sys=Android&query_format=advanced open Android bugs] and [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=blocking-fennec%3A2.0b1%2B 2.0 beta 1 blockers] in Bugzilla.<br />
<br />
== System Requirements ==<br />
<br />
Fennec requires '''Android 2.0''' or later. Installation requires about 30 MB of available internal storage. <br />
<br />
We are using these devices for development:<br />
<br />
<font color="#060"><br />
* HTC/Google Nexus One (ARMv7)<br />
</font><br />
<br />
Other users have successfully installed Fennec on these ARMv7 devices:<br />
<br />
<font color="#006"><br />
* Acer Liquid E<br />
* Dell Streak<br />
* HTC Desire<br />
* HTC Droid Incredible<br />
* HTC EVO 4G<br />
* Motorola Droid 2<br />
* Motorola Droid X<br />
* Motorola Milestone (Verizon Droid)<br />
* Samsung Epic 4G<br />
* Samsung Galaxy S (AT&amp;T Captivate, T-Mobile Vibrant)<br />
</font><br />
<br />
These devices are not compatible with our ARMv7-optimized builds, but might be able to run the new ARMv6 builds:<br />
<br />
<font color="#600"><br />
* Android SDK emulator<br />
* Augen GENTouch 7" Tablet<br />
* HTC Aria<br />
* HTC Dream (T-Mobile G1, Android Dev Phone 1)<br />
* HTC Droid Eris<br />
* HTC Hero (T-Mobile G2 Touch)<br />
* HTC Legend<br />
* HTC Magic (T-Mobile myTouch 3G, T-Mobile G1 Touch)<br />
* HTC Tattoo<br />
* HTC Wildfire<br />
* Huawei U8230<br />
* LG Ally<br />
* Motorola Backflip<br />
* Samsung Moment<br />
* Samsung Spica i5700<br />
</font><br />
<br />
We will test and support more Android 2.0 phones soon.<br />
<br />
== Support ==<br />
<br />
Please post any questions or comments to the [https://support.mozilla.com/en-US/questions/new?product=mobile Firefox Mobile support forum].<br />
<br />
== Development ==<br />
<br />
See [[Mobile/Fennec/Android]] for build instructions, developer documentation, and more project status.</div>Comrade693https://wiki.mozilla.org/index.php?title=Firefox/Goals/2010Q3&diff=250643Firefox/Goals/2010Q32010-09-02T20:26:44Z<p>Comrade693: /* Firefox Development */ Add link to goal wiki page</p>
<hr />
<div>= Firefox Development =<br />
<onlyinclude><br />
* {{new|Feature complete}} Firefox 4<br />
** {{done|Switch to Tab}}<br />
** {{ok|Extension Manager}} - Bug list is converging, still a lot of work to do.<br />
** {{ok|Notification UI}} - Geo and EM notifications done, http auth next.<br />
** {{ok|New Theme}} - Windows and Mac good, Linux lagging.<br />
** {{ok|App Tabs}} - Scope for 4.0 reduced (non-global), near feature complete.<br />
** {{ok|TabCandy}} - Sorting out session restore behaviour, near feature complete.<br />
** {{risk|Silent updates on Windows}}<br />
** {{risk|Inspector}}<br />
** {{risk|Web Console}}<br />
** {{drop|Account Manager}} - WIP patches posted, but we can't contain the review load and code risk.<br />
<br />
* {{risk|Dirty profile startup}} within 20% of clean profile startup (modulo extensions, plugins; on windows)<br />
** Current status: {{:Firefox/Projects/2010Q3_Dirty_Startup_Reduction}}<br />
** [[Firefox/Projects/2010Q3_Dirty_Startup_Reduction|Details page]]<br />
** [http://shawnwilsher.com/archives/465 Shawn has an updated blog post]. Read it for more info.<br />
** Bugs on file that help:<br />
*** <strike>Excessive cookie i/o bug {{bug|572223}}</strike> (fixed)<br />
*** Session Restore negatively impacts startup time based on the number of tabs loaded {{bug|582005}}<br />
*** <strike>Suboptimal SQLite page size {{bug|416330}}</strike> (fixed)<br />
*** Provide a global VACUUM component {{bug|541373}}<br />
</onlyinclude><br />
<br />
* {{new|Jetpack}} API-complete for 1.0 (All JEPs E10s-aware/safe)<br />
** {{done|[[Labs/Jetpack/SDK/APIs#High-level_APIs|1.0 SDK]] final API set selected}}<br />
** {{done|[[Labs/Jetpack/SDK/0.6#Deliverables|0.6 Release]]}}<br />
** {{done|[[Labs/Jetpack/SDK/0.7#Deliverables|0.7 Release]]}}<br />
** {{ok|[[Labs/Jetpack/SDK/0.8#Deliverables|0.8 Release]]}} (1.0)<br />
<br />
= Developer Tools =<br />
'''Bespin'''<br />
* Highlight the use of official vs. unofficial modules in FlightDeck ([https://bugzilla.mozilla.org/show_bug.cgi?id=572115 bug 572115])<br />
* Detect errors in user code ([https://bugzilla.mozilla.org/show_bug.cgi?id=572259 bug 572259])<br />
* Initial JavaScript server ([https://bugzilla.mozilla.org/show_bug.cgi?id=572260 bug 572260])<br />
* JavaScript server hosting plan ([https://bugzilla.mozilla.org/show_bug.cgi?id=572261 bug 572261])<br />
<br />
'''Firefox 4'''<br />
* No beta-blocking bugs left for integrated Firefox 4 Inspector<br />
* No beta-blocking bugs left for integrated Firefox 4 Console<br />
<br />
'''Mobile UI/JS Framework'''<br />
* A basic cross-platform set of HTML/CSS/JavaScript for developers to create mobile applications with (includes basic form functionality as well).<br />
<br />
'''Org'''<br />
* Create cohesive vision & strategy for Developer Tools group going forward (includes both client and server based solutions)</div>Comrade693https://wiki.mozilla.org/index.php?title=Firefox/Goals/2010Q3&diff=250641Firefox/Goals/2010Q32010-09-02T20:24:30Z<p>Comrade693: /* Firefox Development */ Updated dirty startup goal information</p>
<hr />
<div>= Firefox Development =<br />
<onlyinclude><br />
* {{new|Feature complete}} Firefox 4<br />
** {{done|Switch to Tab}}<br />
** {{ok|Extension Manager}} - Bug list is converging, still a lot of work to do.<br />
** {{ok|Notification UI}} - Geo and EM notifications done, http auth next.<br />
** {{ok|New Theme}} - Windows and Mac good, Linux lagging.<br />
** {{ok|App Tabs}} - Scope for 4.0 reduced (non-global), near feature complete.<br />
** {{ok|TabCandy}} - Sorting out session restore behaviour, near feature complete.<br />
** {{risk|Silent updates on Windows}}<br />
** {{risk|Inspector}}<br />
** {{risk|Web Console}}<br />
** {{drop|Account Manager}} - WIP patches posted, but we can't contain the review load and code risk.<br />
<br />
* {{risk|Dirty profile startup}} within 20% of clean profile startup (modulo extensions, plugins; on windows)<br />
** Current status: {{:Firefox/Projects/2010Q3_Dirty_Startup_Reduction}}<br />
** [http://shawnwilsher.com/archives/465 Shawn has an updated blog post]. Read it for more info.<br />
** Bugs on file that help:<br />
*** <strike>Excessive cookie i/o bug {{bug|572223}}</strike> (fixed)<br />
*** Session Restore negatively impacts startup time based on the number of tabs loaded {{bug|582005}}<br />
*** <strike>Suboptimal SQLite page size {{bug|416330}}</strike> (fixed)<br />
*** Provide a global VACUUM component {{bug|541373}}<br />
</onlyinclude><br />
<br />
* {{new|Jetpack}} API-complete for 1.0 (All JEPs E10s-aware/safe)<br />
** {{done|[[Labs/Jetpack/SDK/APIs#High-level_APIs|1.0 SDK]] final API set selected}}<br />
** {{done|[[Labs/Jetpack/SDK/0.6#Deliverables|0.6 Release]]}}<br />
** {{done|[[Labs/Jetpack/SDK/0.7#Deliverables|0.7 Release]]}}<br />
** {{ok|[[Labs/Jetpack/SDK/0.8#Deliverables|0.8 Release]]}} (1.0)<br />
<br />
= Developer Tools =<br />
'''Bespin'''<br />
* Highlight the use of official vs. unofficial modules in FlightDeck ([https://bugzilla.mozilla.org/show_bug.cgi?id=572115 bug 572115])<br />
* Detect errors in user code ([https://bugzilla.mozilla.org/show_bug.cgi?id=572259 bug 572259])<br />
* Initial JavaScript server ([https://bugzilla.mozilla.org/show_bug.cgi?id=572260 bug 572260])<br />
* JavaScript server hosting plan ([https://bugzilla.mozilla.org/show_bug.cgi?id=572261 bug 572261])<br />
<br />
'''Firefox 4'''<br />
* No beta-blocking bugs left for integrated Firefox 4 Inspector<br />
* No beta-blocking bugs left for integrated Firefox 4 Console<br />
<br />
'''Mobile UI/JS Framework'''<br />
* A basic cross-platform set of HTML/CSS/JavaScript for developers to create mobile applications with (includes basic form functionality as well).<br />
<br />
'''Org'''<br />
* Create cohesive vision & strategy for Developer Tools group going forward (includes both client and server based solutions)</div>Comrade693https://wiki.mozilla.org/index.php?title=Firefox/Projects/2010Q3_Dirty_Startup_Reduction&diff=250635Firefox/Projects/2010Q3 Dirty Startup Reduction2010-09-02T20:17:02Z<p>Comrade693: /* Timeline / Milestones */ update bugs</p>
<hr />
<div>__NOTOC__I would like to teach Firefox to startup fast with a non-clean profile.<br />
<br />
*'''Project Lead''': sdwilsh<br />
*'''Dirty Profile Hunter''': limi<br />
<br />
== Status ==<br />
<br />
<onlyinclude>Lots of data has been collected and analyzed, but no solid conclusions have shaken out.</onlyinclude><br />
<br />
== Goals ==<br />
* Ensure that startup time for a "dirty" profile ''in a profile with no add-ons or plugins installed/enabled'' is no worse than 20% of a clean profile's startup time ''on windows''.<br />
<br />
== Non Goals ==<br />
* Reduce startup time for a clean profile.<br />
* Fix this for every possible dirty profile.<br />
* Fix any startup issue caused by add-ons.<br />
<br />
== Timeline / Milestones ==<br />
<br />
* Establish a few reproducible "dirty" profiles with add-ons and plugins uninstalled or disabled (limi). [dirty profiles have been collected]<br />
* Get an idea of what slows us down on dirty profiles (sdwilsh). [[http://shawnwilsher.com/archives/421 blog post of results]]<br />
* Look at collected dirty profiles and see if any other trends shake out (sdwilsh). [[http://shawnwilsher.com/archives/448 blog post of results]]<br />
* See if add-ons are a major factor (sdwilsh) [ETA 9/2]<br />
<br />
These are the bugs of interest:<br />
{| border="1"<br />
|-<br />
! scope="col" | Bug <br />
! scope="col" | Owner<br />
! scope="col" | Status<br />
|-<br />
| {{bug|572223}} - too much cookie I/O<br />
| dwitte<br />
| landed<br />
|-<br />
| {{bug|582005}} - Session Restore negatively impacts startup time based on the number of tabs loaded<br />
| zpao<br />
| work progressing<br />
|-<br />
| {{bug|416330}} - Suboptimal SQLite page size<br />
| taras<br />
| landed<br />
|-<br />
| {{bug|541373}} - Provide a global VACUUM component<br />
| mak<br />
| pending review<br />
|}<br />
<br />
== Requirements ==<br />
<br />
* A plan must be complete and work under way by the end of Q3 2010.<br />
<br />
== Dependencies ==<br />
<br />
None at the moment.<br />
<br />
== Testing ==<br />
<br />
Some performance benchmark will be created. Behavioral changes are covered by our automated test harness.<br />
<br />
== Related Projects ==<br />
<br />
Anything related to startup time reduction has potential.</div>Comrade693https://wiki.mozilla.org/index.php?title=Firefox/Projects/2010Q3_Dirty_Startup_Reduction&diff=250632Firefox/Projects/2010Q3 Dirty Startup Reduction2010-09-02T20:04:40Z<p>Comrade693: updates</p>
<hr />
<div>__NOTOC__I would like to teach Firefox to startup fast with a non-clean profile.<br />
<br />
*'''Project Lead''': sdwilsh<br />
*'''Dirty Profile Hunter''': limi<br />
<br />
== Status ==<br />
<br />
<onlyinclude>Lots of data has been collected and analyzed, but no solid conclusions have shaken out.</onlyinclude><br />
<br />
== Goals ==<br />
* Ensure that startup time for a "dirty" profile ''in a profile with no add-ons or plugins installed/enabled'' is no worse than 20% of a clean profile's startup time ''on windows''.<br />
<br />
== Non Goals ==<br />
* Reduce startup time for a clean profile.<br />
* Fix this for every possible dirty profile.<br />
* Fix any startup issue caused by add-ons.<br />
<br />
== Timeline / Milestones ==<br />
<br />
* Establish a few reproducible "dirty" profiles with add-ons and plugins uninstalled or disabled (limi). [dirty profiles have been collected]<br />
* Get an idea of what slows us down on dirty profiles (sdwilsh). [[http://shawnwilsher.com/archives/421 blog post of results]]<br />
* Look at collected dirty profiles and see if any other trends shake out (sdwilsh). [[http://shawnwilsher.com/archives/448 blog post of results]]<br />
* See if add-ons are a major factor (sdwilsh) [ETA 9/2]<br />
<br />
These are the bugs of interest:<br />
{| border="1"<br />
|-<br />
! scope="col" | Bug <br />
! scope="col" | Owner<br />
! scope="col" | Status<br />
|-<br />
| {{bug|572223}} - too much cookie I/O<br />
| dwitte<br />
| landed<br />
|-<br />
| {{bug|582005}} - Session Restore negatively impacts startup time based on the number of tabs loaded<br />
| zpao<br />
| work progressing<br />
|}<br />
<br />
== Requirements ==<br />
<br />
* A plan must be complete and work under way by the end of Q3 2010.<br />
<br />
== Dependencies ==<br />
<br />
None at the moment.<br />
<br />
== Testing ==<br />
<br />
Some performance benchmark will be created. Behavioral changes are covered by our automated test harness.<br />
<br />
== Related Projects ==<br />
<br />
Anything related to startup time reduction has potential.</div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=249010LandingQueue2010-08-27T16:24:15Z<p>Comrade693: /* Landing Queue for Mozilla-Central */</p>
<hr />
<div>= Landing Queue for Mozilla-Central =<br />
* bholley - {{bug|589469}} - blocking-beta-5<br />
* Bas - blocking-beta5<br />
* sdwilsh<br />
** {{bug|583882}} - Need a way to clone an existing connection (blocking b5)<br />
** {{bug|519769}} - Open shared/unshared connections with options instead of setting shared state always (blocks 583882 and has approval)<br />
** {{bug|590654}} - Let JavaScript read embedded nulls from input streams (blocking b5)<br />
<br />
<br />
Please add an item containing your name, the bugs you want to land, and what the blocking status of them is to the bottom of the list. After you push, remove yourself from the top of the list. You should only push after consulting with the tree sheriff.<br />
<br />
== Ride-along patches ==<br />
<br />
Add yourself here if you would prefer that some kind soul check your patch in on your behalf. <b>And make sure you've read http://blog.bonardo.net/2010/06/22/so-youre-about-to-use-checkin-needed !</b></div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=246724LandingQueue2010-08-19T15:43:55Z<p>Comrade693: /* Landing Queue for Mozilla-Central */</p>
<hr />
<div>= Landing Queue for Mozilla-Central =<br />
<br />
Please add your name to the bottom of the list, the bugs you want to land and what the blocking status of them is. After you push, remove yourself from the top of the list. All pushes should be made after consulting with the tree sheriff.<br><br />
<br />
* sicking - Lots of HTML5 forms stuff blocking beta5<br />
* cjones - {{bug|585817}} and {{bug|582057}} a-g: beta5 and fennec-b1 blockers<br />
<br />
== Ride-along patches ==<br />
<br />
Add yourself here if you would prefer that some kind soul check your patch in on your behalf.</div>Comrade693https://wiki.mozilla.org/index.php?title=LandingQueue&diff=246432LandingQueue2010-08-18T18:31:44Z<p>Comrade693: /* Landing Queue for Mozilla-Central */</p>
<hr />
<div>= Landing Queue for Mozilla-Central =<br />
<br />
Please add your name to the bottom of the list, the bugs you want to land and what the blocking status of them is. After you push, remove yourself from the top of the list. All pushes should be made after consulting with the tree sheriff.<br><br />
<br />
* mwu - landing Taras' patch - {{nbug|559961}} beta5+ (probably will be able to land around 10:30am PDT Wed unless taras gets to it first.)<br />
* blassey - {{bug|587695}} NPOTB (android only) and {{bug|585630}} disable failing mochitest on mobile<br />
* jlebar - {{bug|577950}} a2.0=jst, {{bug|587550}} a2.0=test-only, {{bug|580069}} a2.0=sicking<br />
* glandium - {{bug|435683}} (fix for linux deadlocks with jemalloc) a2.0=bsmedberg, {{bug|587593}} (cosmetic fix) a2.0=bsmedberg, {{bug|587028}} (make clean fix) a2.0=bsmedberg.<br />
* ddahl - {{bug|583359}} a=betaN+<br />
* sdwilsh - backout of {{bug|178506}} a=shaver<br />
<br />
== Ride-along patches ==<br />
<br />
Add yourself here if you would prefer that some kind soul check your patch in on your behalf.<br />
<br />
* Blair McBride (Unfocused) - {{bug|584053}} - Test-only change. Fix for an intermittent orange.<br />
* robc - landing {{nbug|561782}} betaN (wanted to land earlier, but tree outage prevented it)<br />
* robarnold {{bug|559613}} a=betaN Perf improvements for tab previews.<br />
* robarnold {{bug|587566}} a2.0=joe enabled D2D for DX9 devices.<br />
* zwol {{bug|471643}} a2.0=bsmedberg -moz-border-radius vertical percentages should be relative to box height, not width</div>Comrade693https://wiki.mozilla.org/index.php?title=Firefox/Goals/2010Q3&diff=245941Firefox/Goals/2010Q32010-08-17T18:00:13Z<p>Comrade693: /* Firefox Development */ Add notes about latest startup goal blog post</p>
<hr />
<div>= Firefox Development =<br />
<onlyinclude><br />
* {{new|Feature complete}} Firefox 4<br />
** {{done|Switch to Tab}}<br />
** {{ok|Extension Manager}} - Functionality there, lots of bugs to fix.<br />
** {{ok|Notification UI}} - Geo done, patches on follow up bugs.<br />
** {{ok|New Theme}} - Substantially done on Windows and Mac, Linux lagging.<br />
** {{ok|App Tabs}} - UI in place, functionality follow ups to get to feature complete<br />
** {{ok|Silent updates on Windows}}<br />
** {{ok|TabCandy}} - Landed, but lots of follow up work to do on interactions, integration with other features<br />
** {{risk|Account Manager}} - Partial work, restaffing to get this one done.<br />
** {{risk|Inspector}}<br />
** {{risk|Web Console}}<br />
<br />
* {{new|Dirty profile startup}} within 20% of clean profile startup (modulo extensions, plugins; on windows)<br />
** [http://shawnwilsher.com/archives/448 Shawn has an updated blog post]. Read it for more info.<br />
** <strike>Excessive cookie i/o bug {{bug|572223}}</strike>(fixed)<br />
** Session restore {{bug|582005}}<br />
** Still looking for more pathological profiles<br />
</onlyinclude><br />
<br />
* {{new|Jetpack}} API-complete for 1.0 (All JEPs E10s-aware/safe)<br />
** {{done|[[Labs/Jetpack/SDK/APIs#High-level_APIs|1.0 SDK]] final API set selected}}<br />
** {{done|[[Labs/Jetpack/SDK/0.6#Deliverables|0.6 Release]]}}<br />
** {{ok|[[Labs/Jetpack/SDK/0.7#Deliverables|0.7 Release]]}}<br />
** {{ok|[[Labs/Jetpack/SDK/0.8#Deliverables|0.8 Release]]}} (1.0)<br />
<br />
= Developer Tools =<br />
'''Bespin'''<br />
* Highlight the use of official vs. unofficial modules in FlightDeck ([https://bugzilla.mozilla.org/show_bug.cgi?id=572115 bug 572115])<br />
* Detect errors in user code ([https://bugzilla.mozilla.org/show_bug.cgi?id=572259 bug 572259])<br />
* Initial JavaScript server ([https://bugzilla.mozilla.org/show_bug.cgi?id=572260 bug 572260])<br />
* JavaScript server hosting plan ([https://bugzilla.mozilla.org/show_bug.cgi?id=572261 bug 572261])<br />
<br />
'''Firefox 4'''<br />
* No beta-blocking bugs left for integrated Firefox 4 Inspector<br />
* No beta-blocking bugs left for integrated Firefox 4 Console<br />
<br />
'''Mobile UI/JS Framework'''<br />
* A basic cross-platform set of HTML/CSS/JavaScript for developers to create mobile applications with (includes basic form functionality as well).<br />
<br />
'''Org'''<br />
* Create cohesive vision & strategy for Developer Tools group going forward (includes both client and server based solutions)</div>Comrade693https://wiki.mozilla.org/index.php?title=Platform/2010-08-10&diff=244278Platform/2010-08-102010-08-10T18:06:23Z<p>Comrade693: /* Tree Health */ Tweak wording of item (3)</p>
<hr />
<div><small>[[Platform/2010-08-03|&laquo; previous week]] | [[Platform|index]] | [[Platform/2010-08-10|next week &raquo;]]</small><br />
<br />
= Announcements =<br />
<br />
* Firefox 3.6.4 post-mortem is this Thursday, 2010-08-12 @ 11:00 am PST. [[Releases/Post-mortems/Firefox_3.6.4|More information is here]].<br />
* Continue to focus on blockers.<br />
<br />
== Tree Health ==<br />
<br />
Three things must improve:<br />
<br />
1) Mistakes must be less costly. This means faster build machines, faster infrastructure. We're making progress here.<br />
<br />
2) We must make fewer mistakes on shared infrastructure. Totally unacceptable: checking in and failing every build or leaking on every test, on every platform. This goes for TryServer as well: it is not your compiler. Be respectful of other people's time.<br />
<br />
3) Check to see if the tree is orange before checking in. Sheriffs are going to start backing people out for doing this because it's rude and may end up closing the tree because orange got landed on top of orange. When in doubt, ask the sheriff.<br />
<br />
Additionally, we're looking at separating some work onto separate repos, with the same rules as mozilla-central, in order to reduce traffic on mozilla-central.<br />
<br />
Feedback here [http://groups.google.com/group/mozilla.dev.platform/browse_thread/thread/a48296323d76cd62# mozilla.dev.platform thread].<br />
<br />
= Notices / Schedule =<br />
'''Firefox 4 Beta'''<br />
* Beta 3 should hit QA signoff later today, will release tomorrow<br />
* QA's [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=whiteboard%3A4b3 beta 3 bugs] for those interested<br />
* Beta 4 code freeze scheduled for next Monday<br />
** would like all major landings to be complete by this Friday, though (see Roundtable)<br />
* feature freeze still scheduled for Beta 5<br />
** a "feature" is any code which creates a new or makes a significant change to existing interactions between the user and the browser, developers and browser APIs, or web authors and the browser<br />
** after feature freeze we will only be stabilizing and polishing<br />
<br />
<br />
'''Firefox mobile (alpha)'''<br />
* CODE FREEZE IS TODAY<br />
* [http://bit.ly/cvWLkM Bug list]<br />
<br />
= Blocker Report =<br />
<br />
'''Firefox 3.6.9'''<br />
* There are [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=ALL%20blocking1.9.2:.9%2B%20-status1.9.2:.9-fixed&order=map_assigned_to.login_name,bugs.bug_id 26 open blockers] (+4 w/w)<br />
** Code freeze is currently scheduled for Thursday August 12 @ 11:59 pm PST <br />
** Let's try to not get them all in on the last day. I'll be bugging people furiously this week and the start of next<br />
* Only approving blockers at this point<br />
<br />
'''Firefox 3.5.12'''<br />
* There are [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=ALL%20blocking1.9.1:.12%2B%20-status1.9.1:.12-fixed&order=map_assigned_to.login_name,bugs.bug_id 16 open blockers] (+3 w/w)<br />
* Code freeze is tied to 3.6.9<br />
<br />
'''Firefox 4 Beta'''<br />
* a handy list of [[Firefox/4/Triage|triage queries]] is available for all!<br />
** Beta 4: [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=blocking2.0%3Abeta4 56 blockers]<br />
** Beta N: [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=blocking2.0%3AbetaN 218 blockers]<br />
** Final: [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=blocking2.0%3Afinal 232 blockers] (559 total)<br />
** nominations: [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=ALL%20blocking2.0%3A%22%3F%22 275 nominations] (153 OPEN)<br />
<br />
= Firefox Development =<br />
(from our [[Firefox/Goals/2010Q3|goals]]):<br />
{{:Firefox/Goals/2010Q3}}<br />
<br />
= Platform =<br />
(there is a [[Platform/2010-Q3-Goals|team-by-team goals breakdown]], as well)<br />
{{:Platform/2010-Q3-Goals}}<br />
<br />
== Layout ==<br />
<br />
* bzbarsky has implemented JS animation API that can keep in sync with transitions/SMIL etc<br />
** Very simple, should land shortly<br />
* Bug 130078 making progress, many parts landed<br />
* We're not testing retained layers very well on tinderbox machines: screen sizes mean our windows are too small to display entire reftest, so reftests don't grab data from the retained layers<br />
<br />
== Video ==<br />
<br />
* Landed 'buffered' support for Ogg/WAV<br />
** Patch in hand for basic WebM 'buffered' support, will follow up with optimizations<br />
* Will set up a test machine to compare Flash with our video under controlled conditions<br />
<br />
== JS ==<br />
<br />
* ES5<br />
** No landings this week, but now awaiting review on {{bug|514581}}, {{bug|514563}}, {{bug|584909}}, and very nearly {{bug|516255}}<br />
** Current work<br />
*** Requiring exact argument count for getters/setters in {{bug|536472}}<br />
*** {{bug|514581|Poison-pill for fun.caller}} and for {{bug|514563|arguments.caller and arguments.callee}}<br />
*** {{bug|516255|Make arguments[i] a copy of that initial parameter, not a reflection}}<br />
*** {{bug|584909|JSON stringification bugfixes}}<br />
*** {{bug|522158|Killing an extra warning for duplicated property names}}<br />
<br />
= Windows 7 Test Status =<br />
<br />
= Tree Management =<br />
* Tinderbox woes<br />
** Read [http://blog.mozilla.com/bhearsum/archives/150 Ben's blog] for current status and plans to make things better.<br />
** Rebalancing pool size - moving some machines from production to try<br />
** 10.6 builder upgrades in progress - should be unblocking buildsymbols today/tmrw<br />
<br />
= Roundtable =<br />
* [Beltzner] New milestone code freeze process<br />
** For Beta 3 we tried to land Firefox Sync. We failed to check assumptions about previous performance and unit testing, which left us in a bad state on Monday and eventually slipped the code freeze. Lots of things learned about tryserver (which can and should be used to pre-evaluate large landings!) and the implications of committing early to a feature in a specific beta in the ensuing investigation.<br />
** TraceMonkey merge caused some functional regressions that required respins and delayed beta ship - hard to see due to intermittent test failures and number of landings<br />
** We need to have a solid tree the weekend before a planned code freeze, with any major landings having been tested for performance and functionality before Friday and landing by Friday end of day. Anyone who lands after Friday *must* stay around to ensure there are no performance or test regressions in their code.<br />
** Suggested new process<br />
*** Code stabilization on Friday, end of day PT<br />
*** No new strings between stabilization and freeze<br />
*** Only bugfixes between stabilization and freeze<br />
*** Everyone must monitor full tests after checkin between stabilization and freeze<br />
*** Freeze Monday midday PT following code stabilization<br />
<br />
* <bsmedberg> wants to discuss the following blocker nominations<br />
** resource packages {{bug|529208}}: no cross-browser spec, concern about whether it will actually improve perf, questions about whether it will be deployed with a moz Prefix or not, and little or no reviewer time to actually take it<br />
** desktop omnijar {{bug|556644}}: the current plan involves repacking locale files, which is going to require lots of testing and regressions may show up late. I'm very concerned and if it is a blocker we need better ways to mitigate risk.<br />
<br />
* [Beltzner] Using Tryserver<br />
** investigation from Sync showed that Tryserver successfully predicted test failures and may have predicted Talos regressions - it's just that nobody looked<br />
** tryserver now faster (though wait time on Windows can still be high)<br />
** uses same test infrastructure as mozilla-central<br />
** releng very interested to hear why developers aren't using it, how they can help<br />
** joduinn to schedule follow up meeting<br />
** in the meantime, you can always [[Build:TryServer:Suggestions|leave a suggestion]] about what could make it easier for you to use the infrastructure</div>Comrade693https://wiki.mozilla.org/index.php?title=Platform/2010-08-03&diff=242693Platform/2010-08-032010-08-03T18:06:08Z<p>Comrade693: /* Blocker Report */ beta 3 is not beta 4</p>
<hr />
<div><small>[[Platform/2010-07-27|&laquo; previous week]] | [[Platform|index]] | [[Platform/2010-08-10|next week &raquo;]]</small><br />
<br />
= Announcements = <br />
<br />
* Focus on blockers<br />
* Do not check in performance regressions<br />
<br />
= Notices / Schedule =<br />
'''Previous release post-mortems'''<br />
* Firefox 3.6.7/8: 2010-08-03 @ 1:00 pm PST, duration 45 mins<br />
** Christian will be sending the location and call info around after this meeting. He'll also update this bullet point with the info.<br />
* Firefox 3.6.4/6: 2010-08-10 @ 1:00 pm PST, duration 1 hour<br />
** The details on how the post-mortem will be run will be sent out today<br />
<br />
'''Firefox (Supported Branches)'''<br />
* Schedules for [[Releases/Firefox_3.6.9|Firefox 3.6.9]]/[[Releases/Firefox_3.5.12|3.5.12]] are posted<br />
** Code freeze is currently scheduled for Thursday August 12 @ 11:59 pm PST<br />
<br />
'''Firefox (Beta)'''<br />
* missed code freeze for Firefox 4 Beta 3 due to leaks in Firefox Sync<br />
** [https://bugzilla.mozilla.org/buglist.cgi?type0-1-0=changedafter&field0-1-0=cf_blocking_20&field0-0-0=cf_blocking_20&resolution=---&chfield=cf_blocking_20&query_format=advanced&value0-1-0=2010-07-30&type0-0-0=changedfrom&value0-0-0=beta3%2B 23 blockers] changed from beta3+ to another milestone after July 30 - this isn't a sustainable pattern<br />
** * the [https://bugzilla.mozilla.org/buglist.cgi?resolution=FIXED,VERIFIED&chfieldfrom=2010-07-20%2015%3A00&chfield=resolution&query_format=advanced&chfieldto=2010-08-03%203%3A00&product=Core&product=Firefox&product=NSPR&product=NSS&product=Toolkit complete changelist for this beta]<br />
<br />
'''Firefox mobile (alpha)'''<br />
* aiming for code freeze on 8/10.<br />
* [http://bit.ly/cvWLkM Bug list]<br />
<br />
= Blocker Report =<br />
<br />
'''Firefox 3.6.9'''<br />
* There are [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=ALL%20blocking1.9.2:.9%2B%20-status1.9.2:.9-fixed&order=map_assigned_to.login_name,bugs.bug_id 22 open blockers] (+0 w/w)<br />
** Code freeze is currently scheduled for Thursday August 12 @ 11:59 pm PST <br />
** Let's try to not get them all in on the last day. I'll be bugging people furiously this week and the start of next<br />
<br />
'''Firefox 3.5.12'''<br />
* There are [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=ALL%20blocking1.9.1:.12%2B%20-status1.9.1:.12-fixed&order=map_assigned_to.login_name,bugs.bug_id 13 open blockers] (+0 w/w)<br />
* Code freeze is tied to 3.6.9<br />
<br />
'''Firefox 4 Beta'''<br />
* a handy list of [[Firefox/4/Triage|triage queries]] is available for all!<br />
** Beta 4: [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=blocking2.0%3Abeta4 34 blockers]<br />
** Beta N: [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=blocking2.0%3AbetaN 204 blockers]<br />
** Final: [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=blocking2.0%3Abeta,final 222 blockers] (462 total)<br />
** nominations: [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=ALL%20blocking2.0%3A%22%3F%22 462 nominations] (248 OPEN)<br />
<br />
= Firefox Development =<br />
(from our [[Firefox/Goals/2010Q3|goals]]):<br />
{{:Firefox/Goals/2010Q3}}<br />
<br />
= Platform =<br />
== GFX ==<br />
<br />
* Going to make enabling Direct2D a Beta 4 blocker, with the aim of blocking beta 5 on hardware accelerated layers (D3D9/OpenGL).<br />
* Direct2D gradient issues from last week are resolved.<br />
* libjpeg-turbo integration shows up to 2.5x (+?) speedups of the JPEG decoding code. {{bug|573948}} (jlebar)<br />
<br />
== JS ==<br />
* JS fatvals landed<br />
* ES5<br />
** Landings<br />
*** {{bug|562448|<code>Function.prototype.apply</code> updated to accept any vaguely array-looking arguments}}, not just arrays or arguments alone<br />
*** Back to {{bug|531675|ignoring a second argument to <code>eval</code>}}<br />
*** Changes/refactoring of <code>parseInt</code> in {{bug|577536}}, but after further discussion the one semantic change has been reversed in {{bug|583925}} (now back to status quo, but refactorings remain)<br />
*** We now {{bug|582643|reject "0x" as valid numeric-literal syntax}} (an ancient bug)<br />
** Current work<br />
*** Making getter/setter syntax require an exact number of arguments (zero/one) in {{bug|536472}}<br />
*** Adding {{bug|514581|poison-pill properties}} for <code>Function.prototype.caller</code> and <code>Function.prototype.arguments</code> when the function in question is a strict-mode function; doing likewise for <code>arguments.caller</code> and <code>arguments.callee</code> in {{bug|514563}} shortly after<br />
<br />
== Layout ==<br />
<br />
* Retained layers<br />
** The most obvious retained-layers regressions fixed for beta3<br />
** Regression involving invalidation during reflow: may need to implement display-list-based invalidation for reflow to fix cleanly (brings perf wins too)<br />
* Content/chrome rendering integration<br />
** Timothy needs help<br />
<br />
== Video ==<br />
<br />
* Improved software scaling ready to land<br />
* Standards compliance fixes<br />
** 'autobuffer' -> 'preload'<br />
** New load algorithm<br />
<br />
= Windows 7 Test Status =<br />
* Same remaining bugs as last week<br />
* 2 out of 10 test suites with oranges<br />
* The following bugs had no activity: {{bug|562955}} (jimm) and {{bug|581734}} (no one - smontagu suggested)<br />
* We also have {{bug|582315}} (felipe)<br />
<br />
= Tree Management =<br />
<br />
= Roundtable =<br />
* Supported Hardware & OS list for Firefox 4 (beltzner)<br />
** many questions from OSX, JS and build teams about this<br />
** beltzner gathering data about usage in {{bug|582848}} as well as from [http://stats.wikimedia.org/wikimedia/squids/SquidReportOperatingSystems.htm secondary sources]<br />
** current proposals are:<br />
*** drop OSX 10.4 (ease of coding, speedups from using better APIs)<br />
*** drop PPC (no OOPP support planned, no JM support planned)<br />
*** maintain W2K (no impact to coding schedule, not a lot of additional work)<br />
*** add OSX 64-bit (OOPP support planned, major speedup increase)<br />
*** do not add Windows 64-bit (no OOPP support planned)<br />
* Question for Tree Management: (zwol)<br />
** Try server pushes are consistently taking 13-14 hours from push to last result email. Try server does not *appear* to be under heavier load than m-c (push rate eyeballs about the same); why is there such a huge difference?</div>Comrade693https://wiki.mozilla.org/index.php?title=Firefox/Projects/2010Q3_Dirty_Startup_Reduction&diff=242441Firefox/Projects/2010Q3 Dirty Startup Reduction2010-08-02T21:05:20Z<p>Comrade693: /* Timeline / Milestones */</p>
<hr />
<div>__NOTOC__I would like to teach Firefox to startup fast with a non-clean profile.<br />
<br />
*'''Project Lead''': sdwilsh<br />
*'''Dirty Profile Hunter''': limi<br />
<br />
== Status ==<br />
<br />
<onlyinclude>Some data has been obtained. It is righteous and a plan is forming around it.</onlyinclude><br />
<br />
== Goals ==<br />
* Ensure that startup time for a "dirty" profile ''in a profile with no add-ons or plugins installed/enabled'' is no worse than 20% of a clean profile's startup time ''on windows''.<br />
<br />
== Non Goals ==<br />
* Reduce startup time for a clean profile.<br />
* Fix this for every possible dirty profile.<br />
* Fix any startup issue caused by add-ons.<br />
<br />
== Timeline / Milestones ==<br />
<br />
* Establish a few reproducible "dirty" profiles with add-ons and plugins uninstalled or disabled (limi). [dirty profiles have been collected]<br />
* Get an idea of what slows us down on dirty profiles (sdwilsh). [[http://shawnwilsher.com/archives/421 blog posts of results]]<br />
* Look at collected dirty profiles and see if any other trends shake out (sdwilsh). [ETA Aug 6]<br />
<br />
These are the bugs of interest:<br />
{| border="1"<br />
|-<br />
! scope="col" | Bug <br />
! scope="col" | Owner<br />
! scope="col" | Status<br />
|-<br />
| {{bug|572223}} - too much cookie I/O<br />
| dwitte<br />
| needs an issue to be figured out<br />
|-<br />
| {{bug|582005}} - Session Restore negatively impacts startup time based on the number of tabs loaded<br />
| zpao<br />
| work not yet started<br />
|}<br />
<br />
== Requirements ==<br />
<br />
* A plan must be complete and work under way by the end of Q3 2010.<br />
<br />
== Dependencies ==<br />
<br />
None at the moment.<br />
<br />
== Testing ==<br />
<br />
Some performance benchmark will be created. Behavioral changes are covered by our automated test harness.<br />
<br />
== Related Projects ==<br />
<br />
Anything related to startup time reduction has potential.</div>Comrade693https://wiki.mozilla.org/index.php?title=Platform/2010-07-27&diff=241537Platform/2010-07-272010-07-27T19:55:40Z<p>Comrade693: /* Roundtable */ Added SQLite to the list of things in b3</p>
<hr />
<div><small>[[Platform/2010-07-20|&laquo; previous week]] | [[Platform|index]] | [[Platform/2010-08-03|next week &raquo;]]</small><br />
<br />
= Notices / Schedule =<br />
* Blackhat is this week<br />
<br />
'''Firefox (Supported Branches)'''<br />
* Initial schedule for 3.6.9/3.5.12 is up at [[Releases/Firefox_3.6.9]].<br />
** Code freeze is currently scheduled for Thursday August 12 @ 11:59 pm PST<br />
** '''Please let [mailto:clegnitto@mozilla.com christian] or [mailto:release-drivers@mozilla.org release-drivers] know if there are issues with the schedule'''<br />
* Initial post-mortem dates & times have been scheduled<br />
** Firefox 3.6.7/8: 2010-08-03 @ 1:00 pm PST, duration 45 mins<br />
** Firefox 3.6.4/6: 2010-08-10 @ 1:00 pm PST, duration 1 hour<br />
* I know they are in conflict with critsmash meetings, let me know if that is an issue (probably only matters for 3.6.4/6, so I may move that one to a different day)<br />
<br />
'''Firefox (Beta)'''<br />
* should be shipping Firefox 4 Beta 2 around noon PT today<br />
* code freeze for Firefox 4 Beta 3 is set for next Monday, August 2nd, 23:00 PT<br />
** the [https://bugzilla.mozilla.org/buglist.cgi?resolution=FIXED,VERIFIED&chfieldfrom=2010-07-20%2015%3A00&chfield=resolution&query_format=advanced&chfieldto=Now&product=Core&product=Firefox&product=NSPR&product=NSS&product=Toolkit changelist as of this moment]<br />
<br />
= Blocker Report =<br />
<br />
'''Firefox 3.6.9'''<br />
* There are [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=ALL%20blocking1.9.2:.9%2B%20-status1.9.2:.9-fixed&order=map_assigned_to.login_name,bugs.bug_id 22 open blockers]<br />
** Code freeze is currently scheduled for Thursday August 12 @ 11:59 pm PST <br />
** Let's try to not get them all in on the last day. I'll be bugging people furiously this week and the start of next<br />
<br />
'''Firefox 3.5.12'''<br />
* There are [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=ALL%20blocking1.9.1:.12%2B%20-status1.9.1:.12-fixed&order=map_assigned_to.login_name,bugs.bug_id 13 open blockers]<br />
* Code freeze is tied to 3.6.9<br />
<br />
'''Firefox 4 Beta'''<br />
* a handy list of [[Firefox/4/Triage|triage queries]] is available for all!<br />
** Beta 3: [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=blocking2.0%3Abeta3 35 blockers]<br />
** Beta N: [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=blocking2.0%3AbetaN 132 blockers]<br />
** Final: [https://bugzilla.mozilla.org/buglist.cgi?quicksearch=blocking2.0%3Afinal 218 blockers]<br />
** nominations: <font color="red">'''[https://bugzilla.mozilla.org/buglist.cgi?quicksearch=ALL%20blocking2.0%3A%22%3F%22 500+ nominations]'''</font><br />
<br />
= Browser / Front End =<br />
<br />
johnath at BlackHat this week, frontend [[Firefox/Goals/2010Q3#Firefox_Development|Q3 Goals]] updated with team status.<br />
<br />
= Firefox Development =<br />
(from our [[Firefox/Goals/2010Q3|goals]]):<br />
<br />
{{:Firefox/Goals/2010Q3}}<br />
<br />
= Platform =<br />
* [[Platform/2010-Q3-Goals#GFX|GFX Goals]] Update:<br />
** D2D<br />
*** Down to 33 reftest failures {{bug|578110}}<br />
*** We're having some problems with the way gradients are implemented in D2D {{bug|582236}} and not sure how to solve them at this point. We'll need to figure out how bad this is and what we can do about it<br />
* [[Platform/2010-Q3-Goals#JS|JS]] Goals Update:<br />
** JaegerMonkey plan is on target<br />
** VM perf wins (strings, arrays) being checked in<br />
** ES5<br />
*** Landings<br />
**** Added U+FEFF to whitespace in {{bug|581067}} (discovered while writing another test)<br />
**** <code>/a/.lastIndex</code> is now a nearly plain-vanilla property, settable to any value (coerced to number for internal use), {{bug|465199}}<br />
**** Killed special handling (except for a new warning) of <code>eval</code> called with two arguments in {{bug|531675}}<br />
**** <code>Function.prototype.apply</code> no longer requires arguments to be an array or an arguments value -- any array-like object is valid now, {{bug|562448}} (includes recent spec erratum spawned by work on this)<br />
*** In progress<br />
**** Updating <code>parseInt</code> to reject octal input in strict mode (ES5 rejects everywhere, we're concerned about compatibility) in {{bug|577536}}; also significantly reorganized/cleaned up decade-old integer parsing code, much more understandable now with fewer mandatory special-case behaviors to internalize<br />
**** Requiring object-literal getters/setters to have 0/1 arguments, {{bug|536472}}, plus some prerequisite cleanups<br />
**** Yak-shaving to be able to make JSON.parse reject trailing commas<br />
* [[Platform/2010-Q3-Goals#Content|Content]] Goals Update:<br />
** Got a couple of boosts on Dromaeo last week! [http://mzl.la/dgNbsw graph] (peterv and smaug)<br />
* [[Platform/2010-Q3-Goals#Layout|Layout]] Goals Update:<br />
<br />
= Windows 7 Test Status =<br />
We must have our trees '''green''' on Windows 7 to ship Firefox 4.<br />
We need owners to make this happen.<br />
<br />
* [https://bugzilla.mozilla.org/show_bug.cgi?id=562489#c3 bug 562489] [tracking bug] for the various win7 32-bit unit tests orange<br />
* {{bug|562955}} - jimm - mochitests-4/5 - test_bug458898.html<br />
* <strike>{{bug|574042}}, [https://bugzilla.mozilla.org/show_bug.cgi?id=574040 bug 574040] - Enn / jimm (toolkit / widget) widgets/test_popupincontent.xul</strike><br />
* <strike>{{bug|578448}} - Mossop - browser_bug435788.js times out (waiting on manual retest from armen) - underlying issue is {{bug|542504}}</strike><br />
* <strike>{{bug|575748}} - Dão Gottwald - browser_overflowScroll.js (WIP patch posted)</strike><br />
* <strike>{{bug|562967}} - Justin Dolske - test_uriloader_exthandler\unit\test_handlerService.js</strike><br />
* <strike>{{bug|562957}} - Enn</strike><br />
* {{bug|581734}} - smontagu?? - mochitest-chrome timeout in toolkit/content/tests/chrome/test_bug558403.xul<br />
* <strike>comment 19 of {{bug|561350}} (but not the rest of the bug) - no owner - xpcshell test failing: test_punicodeURIs.js - underlying issue is {{bug|542504}}</strike><br />
* {{bug|582315}} - felipec?? - intermittent orange in test_taskbarprogress_downloadstates.xul and test_taskbarprogress_service.xul<br />
<br />
Direct 2D oranges:<br />
* [https://bugzilla.mozilla.org/show_bug.cgi?id=578110#c1 bug 578110] - [tracking bug] reftest Direct 2D oranges<br />
* <strike>{{bug|578127}} - no assignee - bidi/visualmarquee.html, logicalmarquee.html</strike><br />
* {{bug|578134}} - jrmuizel -box-shadow/boxshadow-rounded-spread.html<br />
* {{bug|578135}} - jrmuizel -box-shadow/boxshadow-onecorner.html<br />
* {{bug|578114}} - jrmuizel -bugs/289480.html#top<br />
* {{bug|578116}} - Bas Schouten -379349-1b.xhtml, 379349-1c.xhtml<br />
* {{bug|578118}} - Jonathan Kew -385569-1a.html, 385569-1b.html<br />
* <strike>{{bug|578121}} - jrmuizel -456219-1{a,b,c}.html, 456219-2.html</strike><br />
* {{bug|578124}} - jrmuizel -555388-1-ref.html<br />
<br />
Mac OS X 10.6/64-bit test oranges:<br />
* {{bug|561350}} - josh - test_punycodeURIs.js fails (was timing out) on 10.6 opt xpcshell test<br />
<br />
= Tree Management =<br />
To be announced:<br />
* we want to disable unit test on builders tomorrow Wednesday if no objections (Windows 2003 builder will wait until we have all test suites GREEN)<br />
<br />
For reference:<br />
* if anyone is curious [http://armenzg.blogspot.com/2010/07/releng-what-has-changed-in-last-week.html Releng's last week changes]<br />
* as of today, talos do not run for try server jobs<br />
* [http://groups.google.com/group/mozilla.dev.planning/browse_thread/thread/7e60fb50e283709c# running unit test on minis for all branches and all platforms (except Windows XP)]<br />
<br />
= Roundtable =<br />
* Hands-up for what's going into Beta 3 (beltzner)<br />
** new JS values - could affect add-ons that use JSAPI<br />
** OSX uses UNIX filesystem code instead of OSX filesystem code<br />
** Sync UI built in (needs review)<br />
** SQLite 3.7.0<br />
* Quick overview of new tree rules (beltzner)<br />
** patches on blocking (mozilla2.0, fennec2.0) bugs are always approved<br />
** NPOTB and tests are always approved<br />
** bustage fixes and backouts are always approved<br />
** question: bugs that block blockers - explicit approval/blocking status?<br />
*** no explicit approvals/flags needed until we see abuse<br />
** question: meta bugs allowed to block?<br />
*** still no, for now</div>Comrade693https://wiki.mozilla.org/index.php?title=WeeklyUpdates/2010-07-26&diff=241185WeeklyUpdates/2010-07-262010-07-26T18:05:42Z<p>Comrade693: /* Firefox */ Added bit about dirty startup goal</p>
<hr />
<div><small>[[WeeklyUpdates/2010-07-12|« previous week]] | [[WeeklyUpdates|index]] | [[WeeklyUpdates/2010-07-26|next week »]]</small><br />
<br />
= Video for today's meeting =<br />
<br />
<video controls="controls"><source src="http://videos.mozilla.org/serv/air_mozilla/monday_meetings/status-2010-07-26.ogg" type="video/ogg; codecs=&quot;theora, vorbis&quot;" /></video> <br />
<br />
= Friends of the Tree [[Image:Tree.gif|Friends of the Tree]] =<br />
<br />
= Upcoming Events =<br />
<br />
'''This Week''' <br />
<br />
'''Monday, 26 July''' <br />
<br />
*Black Hat (July 24 - 29, 2010) is the premier North American security conference. Mozilla will be in attendance at the event as well as having our own "[https://wiki.mozilla.org/Black_Hat_2010 Milk and Cookies]" Party on 7/28.<br />
<br />
<br />
'''Tuesday, 27 July''' <br />
<br />
*Black Hat (July 24 - 29, 2010) is the premier North American security conference. Mozilla will be in attendance at the event as well as having our own "[https://wiki.mozilla.org/Black_Hat_2010 Milk and Cookies]" Party on 7/28.<br />
<br />
<br />
'''Wednesday, 28 July'''<br> <br />
<br />
*Black Hat (July 24 - 29, 2010) is the premier North American security conference. Mozilla will be in attendance at the event as well as having our own "[https://wiki.mozilla.org/Black_Hat_2010 Milk and Cookies]" Party on 7/28.<br />
<br />
<br />
'''Thursday, 29 July''' <br />
<br />
*Black Hat (July 24 - 29, 2010) is the premier North American security conference. Mozilla will be in attendance at the event as well as having our own "[https://wiki.mozilla.org/Black_Hat_2010 Milk and Cookies]" Party on 7/28.<br />
<br />
<br> '''Friday, 30 July''' <br />
<br />
*Black Hat (July 24 - 29, 2010) is the premier North American security conference. Mozilla will be in attendance at the event as well as having our own "[https://wiki.mozilla.org/Black_Hat_2010 Milk and Cookies]" Party on 7/28.<br />
<br />
<br> '''Next Week'''<br />
<br />
= Product Status Updates =<br />
<br />
== Firefox 4 ==<br />
* due to the chemspill, we're a bit behind on schedule for [[Releases/Firefox_4.0b2|beta 2]]<br />
* getting a QA update today, hoping for release tomorrow<br />
* beta 3 planning and landings going on this week<br />
* a set of [[Firefox/4/Beta#Milestones|planned milestones and release dates]] for beta revisions is available<br />
<br />
== Firefox 3.6 ==<br />
* Released Firefox 3.6.7 on last Tuesday<br />
* Saw a high-volume crash regression with certain combinations of object and embed tags ([https://bugzilla.mozilla.org/show_bug.cgi?id=575836 bug 575836])<br />
* Released Firefox 3.6.8 with the fix on Friday...an amazingly quick turnaround!<br />
* Post-mortems for 3.6.(7|8) will be happening the week of the 1st and 3.6.(4|6) will be happening the week of August 9th. Exact dates will be sent out today<br />
* We are ready to do a chemspill release if anything comes up at BlackHat, though there are no talks we are too concerned about for Firefox<br />
* The [https://wiki.mozilla.org/Releases/Firefox_3.6.9 Firefox 3.6.9 schedule] will be out today<br />
* Any approvals for 1.9.2.'''8''' are now for 1.9.2.'''9'''<br />
<br />
== Mobile Firefox ==<br />
<br />
== Thunderbird ==<br />
* Released Thunderbird 3.1.1 and 3.0.6<br />
* Found a bad crasher; we expect to need to spin 3.1.2 before offering advertised major updates to 3.1.x from older versions<br />
<br />
== Older Branch Work ==<br />
<br />
= Speakers =<br />
<br />
The limit is 3 minutes per speaker. It's like a lightning talk, but don't feel that you have to have slides in order to make a presentation. <br />
<br />
{| class="fullwidth-table"<br />
|-<br />
! Title <br />
! Presenter <br />
! Topic <br />
! Media <br />
! More Details<br />
|-<br />
| Mozilla Social Media Toolkit<br><br />
| Sarah Doherty<br><br />
| Mozilla Social Media Toolkit<br><br />
| [http://mozilla.sarahdoherty.net/temp/MozillaSocialMediaToolkit.zip http://mozilla.sarahdoherty.net/temp/MozillaSocialMediaToolkit.zip]<br />
| [http://mzl.la/sfxsocialmediatoolkit mzl.la/sfxsocialmediatoolkit]<br />
|-<br />
| <br />
| John O'Duinn <br />
| FF3.6.8 <br />
| <br />
| [http://oduinn.com/blog/2010/07/26/firefox-3-6-8-by-the-wall-clock-numbers blog post] <br />
|-<br />
| Your Title Here <br />
| Your Name Here <br />
| What are you going to talk about? <br />
| Links to slides or images you want displayed on screen <br />
| Link to where audience can find out more information<br />
|-<br />
| <br />
| <br />
| <br />
| <br />
| <br />
|}<br />
<br />
= Status Updates By Team =<br />
<br />
== Firefox ==<br />
* Announced Tab Candy on Friday. Over the weekend we had:<br />
** 28 press articles, including dream headlines: "Firefox Just Perfected Tabs Browsing" from Techcrunch and "With FireFox's Tab Candy Feature, We'll Finally Achieve Tab Nirvana" from Gizmodo.<br />
** 3 million views of the video, with half a million watching all the way through.<br />
** Tens of thousands of tweets, with many saying they'll never look at another browser again.<br />
** 30k+ installs of the Tab Candy alpha build of Firefox.<br />
** Hundreds of feature suggestions and votes for them, not all of which say Opera did it first.<br />
** Dozens of direct emails, some of which expressing a desire to have babies with Firefox.<br />
* The Tab Candy team (especially Ian Gilman, Edward Lee, and Mitcho Erlewine) deserve all the credit for pushing long and hard to get Tab Candy this far.<br />
* Please do some dogfooding with our [http://azarask.in/projects/tabcandy/build.php Tab Candy build].<br />
* [[Firefox/Projects/2010Q3_Dirty_Startup_Reduction|"Dirty" startup goal]] work underway with [http://shawnwilsher.com/archives/421 interesting results].<br />
<br />
== Platform ==<br />
<br />
== Messaging ==<br />
* Raindrop is rebooting: the backend is being rewritten for simplicity and speed on top of SQLAlchemy & MySQL/sqlite<br />
* related to Tb participation work, dmose held BOF at OSCON about community & contribution metrics, will blog soon<br />
<br />
== Mobile ==<br />
<br />
== IT ==<br />
''' Last Week'''<br />
* Working through Firefix Sync scaling issues<br />
* Pre-planning for Amsterdam datacenter move (could happen as soon as Friday)<br />
* Wrapped up long-delayed Firewall upgrades in San Jose<br />
<br />
'''This Week'''<br />
* Performance problems with the generic web server cluster this morning<br />
** Affected <code>wiki.mozilla.org</code> as well as others<br />
<br />
== Release Engineering ==<br />
<br />
<br />
== QA ==<br />
* '''Desktop QA''':<br />
** 3.6.8 chemspill release testing. Shipped next day (Friday).<br />
** 4.0beta2, ongoing testing. Should ship tomorrow.<br />
* '''Browser Technologies QA''':<br />
** [https://wiki.mozilla.org/QA/Fennec/Milestones/2.0 Fennec 2.0 features] are landing and specs are getting assigned. looking to eta an alpha end of month<br />
** Sync 1.4.2b1 tested and pushed to AMO<br />
** Firefox Home 1.0.1 tested and submitted to App Store<br />
* '''WebQA''':<br />
** Pushed [https://bugzilla.mozilla.org/show_bug.cgi?id=578053 AMO 5.11.4] on 7/13<br />
** Shipped a [https://bugzilla.mozilla.org/show_bug.cgi?id=579341 new version] of [http://input.mozilla.com/en-US/ Input] last week<br />
** Pushed a [https://bugzilla.mozilla.org/show_bug.cgi?id=579983 small change] to fix some galleries in Personas<br />
** Released the [https://bugzilla.mozilla.org/buglist.cgi?resolution=FIXED&classification=Other&query_format=advanced&component=plugins.mozilla.org&product=Websites&target_milestone=1.1 1.1 version] of the plugin directory<br />
* '''QA Services''':<br />
**Meetup next week in NYC: http://www.meetup.com/Mozilla-in-the-Big-Apple/calendar/14115600/ as part of BlogHer - all NYC community welcome to attend! As part of the action packed weekend there will also be a Drumbeat Festival in NYC on August 7<br />
<br />
== Automation & Tools ==<br />
* Lots of things in progress:<br />
** Android work finalizing apace<br />
** Mozmill moving quickly toward 1.4.2<br />
** Cycle collector talos runs in progress<br />
** Cross weave full automation should be ready for production at the end of the week<br />
* Held test day on grafx bot on Friday, submitted it to AMO.<br />
* More info [https://wiki.mozilla.org/Auto-tools/Meetings/2010-07-26 here].<br />
<br />
== Security ==<br />
<br />
== Engagement ==<br />
<br />
'''PR''' <br />
*[http://www.mercurynews.com/breaking-news/ci_15587773?nclick_check=1 Mercury News interview: Mitchell Baker, chairwoman, Mozilla] <br />
<br />
*[http://techcrunch.com/2010/07/23/firefox-tab-candy/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+Techcrunch+%28TechCrunch%29 Firefox Just Perfected Tabbed Browsing. It’s Like Apple’s Expose Plus Spaces For The Web] <br />
* [http://www.theregister.co.uk/2010/07/23/firefox_tab_candy/ Mozilla tames Firefox tab monster with Candy] <br />
*[http://gizmodo.com/5595017/with-firefoxs-tab-candy-feature-well-finally-achieve-tab-nirvana With Firefox's Tab Candy Feature, We'll Finally Achieve Tab Nirvana] <br />
*[http://www.webmonkey.com/2010/07/firefox-offers-a-taste-of-tabcandy/ Firefox Offers a Taste of Tab Candy] <br />
*[http://mashable.com/2010/07/23/tab-candy-firefox/ Tab Candy: Firefox Invents a Better Way to Manage Tabs [VIDEO]<br />
<br />
*[http://www.ghacks.net/2010/07/24/firefox-3-6-8-released/ Firefox 3.6.8 Released] <br />
*[http://www.h-online.com/open/news/item/Mozilla-delays-second-Firefox-4-beta-1045234.html Mozilla delays second Firefox 4 beta] <br />
*[http://www.itproportal.com/portal/news/article/2010/7/26/mozilla-firefox-368-update-released/ Mozilla Firefox 3.6.8 Update Released] <br />
*[http://www.computerworld.com/s/article/9179638/Mozilla_re_patches_Firefox_3.6_to_fix_plug_in_problem Mozilla re-patches Firefox 3.6 to fix plug-in problem] <br />
<br />
<br />
<br> '''Events''' <br />
<br />
*[http://www.blackhat.com/html/bh-us-10/bh-us-10-home.html Black Hat USA 2010] July 24-29, 2010; Las Vegas, NV - We will be hosting our "traditional" Mozilla milk &amp; cookies party on 7/28.&nbsp; Check out the information on the [https://wiki.mozilla.org/Black_Hat_2010 wiki].<br> <br />
*[http://www.guadec.org/index.php/guadec/2010 GUADEC 2010] - July 24-30, 2010; Netherlands.&nbsp; We are sponsoring at the bronze level.&nbsp; No Mozilla talks scheduled. <br />
*[http://www.blogher.com/blogher-10 BlogHer '10] - August 6-7, 2010 - We will be having a hotel suite and a presence in the GeekLab as well as a meetup on Thursday (open to non BlogHer folk)&nbsp; - sign up for the meetup [http://www.meetup.com/Mozilla-in-the-Big-Apple/calendar/14115600/ here]. <br> <br />
*[http://www.openvideoconference.org/ Open Video Conference 2010] - October 1-2, 2010; New York, NY&nbsp; - Looking over sponsorship opportunities. <br />
*[http://makerfaireafrica.com/ Maker Faire Africa] - August 27-28, 2010; Nairobi, Kenya - Looking into sponsorship opportunties. <br />
*[http://www.renegadecraft.com/chicago Renegade Craft Fair Chicago 2010] - September 11-12, 2010 - We will have a booth and be doing some innovative activities. &nbsp;Check out the [https://wiki.mozilla.org/RenegadeCraftFair2010_Chicago wiki] for more details Looking into sponsorship opportunities.<br><br />
<br />
<br> '''Creative Team''' <br />
<br />
<br> '''Community Marketing''' <br />
<br />
*Community Marketing Call: Next call is Wednesday July 28th at 10 a.m. PST/17:00 UTC. Please send agenda items to mary at mozilla dot com.<br />
<br />
== Support ==<br />
<br />
== Metrics ==<br />
<br />
== Evangelism ==<br />
<br />
== Labs ==<br />
<br />
<br />
== Developer Tools ==<br />
<br />
== Add-ons ==<br />
<br />
== Webdev ==<br />
<br />
== L10n ==<br />
* The L10n-drivers and Firefox Home team are finalizing a plan to localize the application. An announcement to the l10n newsgroup on instructions is forthcoming, hoping to post this week.<br />
* Firefox 4 beta 2 will ship with 23 locales, some taking advantage of our "l10n-merge" technology. <br />
* Firefox 4 beta web l10n work has been led by Pascal C. (Excellent work by Pascal) This [https://bugzilla.mozilla.org/show_bug.cgi?id=578126 tracking bug] gives a good summary of the status of pages. <br />
* KaiRo (Robert Kaiser) posted [http://groups.google.com/group/mozilla.dev.platform/msg/611e83f34faba1f7 an explanation about the goals of the l20n project] in the dev.platform newsgroup. Thanks, KaiRo!<br />
* Congrats to the Malayalam localization for moving out of beta and into "official" status<br />
** Oriya, es-CL, and es-MX will be next to de-beta<br />
** L10n-drivers have a quarterly goal to reduce the number of locales in beta<br />
* Several new locales are expected for Firefox 4 as the l10n-drivers team starts afresh with outreach to long-standing contributors trying to make it into an official release. <br />
** Because of that, the team is refining the process by articulating more clearly what it takes to enter an official release, what is expected from both the l10n-drivers and the community proposing the new localization, and what are the consequences if all to-do items are not completed.<br />
<br />
= Introducing New Hires =<br />
* Laura Forrest<br />
<br />
= Foundation Updates =<br />
<br />
= Roundtable =</div>Comrade693https://wiki.mozilla.org/index.php?title=Firefox/Projects/2010Q3_Dirty_Startup_Reduction&diff=241181Firefox/Projects/2010Q3 Dirty Startup Reduction2010-07-26T18:02:40Z<p>Comrade693: /* Timeline / Milestones */ Added bug 582005</p>
<hr />
<div>__NOTOC__I would like to teach Firefox to startup fast with a non-clean profile.<br />
<br />
*'''Project Lead''': sdwilsh<br />
*'''Dirty Profile Hunter''': limi<br />
<br />
== Status ==<br />
<br />
<onlyinclude>Some data has been obtained. It is righteous and a plan is forming around it.</onlyinclude><br />
<br />
== Goals ==<br />
* Ensure that startup time for a "dirty" profile ''in a profile with no add-ons or plugins installed/enabled'' is no worse than 20% of a clean profile's startup time ''on windows''.<br />
<br />
== Non Goals ==<br />
* Reduce startup time for a clean profile.<br />
* Fix this for every possible dirty profile.<br />
* Fix any startup issue caused by add-ons.<br />
<br />
== Timeline / Milestones ==<br />
<br />
* Establish a few reproducible "dirty" profiles with add-ons and plugins uninstalled or disabled (limi). [dirty profiles have been collected]<br />
* Get an idea of what slows us down on dirty profiles (sdwilsh). [[http://shawnwilsher.com/archives/421 blog posts of results]]<br />
* Look at collected dirty profiles and see if any other trends shake out (sdwilsh). [ETA Aug 6]<br />
<br />
These are the bugs of interest:<br />
{| border="1"<br />
|-<br />
! scope="col" | Bug <br />
! scope="col" | Owner<br />
! scope="col" | Status<br />
|-<br />
| {{bug|572223}} - too much cookie I/O<br />
| dwitte<br />
| needs review sdwilsh<br />
|-<br />
| {{bug|582005}} - Session Restore negatively impacts startup time based on the number of tabs loaded<br />
| zpao<br />
| work not yet started<br />
|}<br />
<br />
== Requirements ==<br />
<br />
* A plan must be complete and work under way by the end of Q3 2010.<br />
<br />
== Dependencies ==<br />
<br />
None at the moment.<br />
<br />
== Testing ==<br />
<br />
Some performance benchmark will be created. Behavioral changes are covered by our automated test harness.<br />
<br />
== Related Projects ==<br />
<br />
Anything related to startup time reduction has potential.</div>Comrade693https://wiki.mozilla.org/index.php?title=Firefox/Projects/2010Q3_Dirty_Startup_Reduction&diff=241168Firefox/Projects/2010Q3 Dirty Startup Reduction2010-07-26T17:53:24Z<p>Comrade693: /* Timeline / Milestones */ Added some milestones and bugs</p>
<hr />
<div>__NOTOC__I would like to teach Firefox to startup fast with a non-clean profile.<br />
<br />
*'''Project Lead''': sdwilsh<br />
*'''Dirty Profile Hunter''': limi<br />
<br />
== Status ==<br />
<br />
<onlyinclude>Some data has been obtained. It is righteous and a plan is forming around it.</onlyinclude><br />
<br />
== Goals ==<br />
* Ensure that startup time for a "dirty" profile ''in a profile with no add-ons or plugins installed/enabled'' is no worse than 20% of a clean profile's startup time ''on windows''.<br />
<br />
== Non Goals ==<br />
* Reduce startup time for a clean profile.<br />
* Fix this for every possible dirty profile.<br />
* Fix any startup issue caused by add-ons.<br />
<br />
== Timeline / Milestones ==<br />
<br />
* Establish a few reproducible "dirty" profiles with add-ons and plugins uninstalled or disabled (limi). [dirty profiles have been collected]<br />
* Get an idea of what slows us down on dirty profiles (sdwilsh). [[http://shawnwilsher.com/archives/421 blog posts of results]]<br />
* Look at collected dirty profiles and see if any other trends shake out (sdwilsh). [ETA Aug 6]<br />
<br />
These are the bugs of interest:<br />
{| border="1"<br />
|-<br />
! scope="col" | Bug <br />
! scope="col" | Owner<br />
! scope="col" | Status<br />
|-<br />
| {{bug|572223}} - too much cookie I/O<br />
| dwitte<br />
| needs review sdwilsh<br />
|}<br />
<br />
== Requirements ==<br />
<br />
* A plan must be complete and work under way by the end of Q3 2010.<br />
<br />
== Dependencies ==<br />
<br />
None at the moment.<br />
<br />
== Testing ==<br />
<br />
Some performance benchmark will be created. Behavioral changes are covered by our automated test harness.<br />
<br />
== Related Projects ==<br />
<br />
Anything related to startup time reduction has potential.</div>Comrade693https://wiki.mozilla.org/index.php?title=Firefox/Projects/2010Q3_Dirty_Startup_Reduction&diff=241154Firefox/Projects/2010Q3 Dirty Startup Reduction2010-07-26T17:44:54Z<p>Comrade693: /* Status */ Updated status</p>
<hr />
<div>__NOTOC__I would like to teach Firefox to startup fast with a non-clean profile.<br />
<br />
*'''Project Lead''': sdwilsh<br />
*'''Dirty Profile Hunter''': limi<br />
<br />
== Status ==<br />
<br />
<onlyinclude>Some data has been obtained. It is righteous and a plan is forming around it.</onlyinclude><br />
<br />
== Goals ==<br />
* Ensure that startup time for a "dirty" profile ''in a profile with no add-ons or plugins installed/enabled'' is no worse than 20% of a clean profile's startup time ''on windows''.<br />
<br />
== Non Goals ==<br />
* Reduce startup time for a clean profile.<br />
* Fix this for every possible dirty profile.<br />
* Fix any startup issue caused by add-ons.<br />
<br />
== Timeline / Milestones ==<br />
<br />
* Establish a few reproducible "dirty" profiles with add-ons and plugins uninstalled or disabled (limi). ETA July 16.<br />
* Start profiling "dirty profiles" and come up with a plan. ETA August 15.<br />
<br />
<!--<br />
These are the bugs of interest:<br />
{| border="1"<br />
|-<br />
! scope="col" | Bug <br />
! scope="col" | Owner<br />
! scope="col" | Status<br />
|-<br />
| {{bug|12345}} - platform team sings offkey<br />
| damons<br />
| hopeless<br />
|}<br />
--><br />
<br />
== Requirements ==<br />
<br />
* A plan must be complete and work under way by the end of Q3 2010.<br />
<br />
== Dependencies ==<br />
<br />
None at the moment.<br />
<br />
== Testing ==<br />
<br />
Some performance benchmark will be created. Behavioral changes are covered by our automated test harness.<br />
<br />
== Related Projects ==<br />
<br />
Anything related to startup time reduction has potential.</div>Comrade693https://wiki.mozilla.org/index.php?title=Firefox/Projects/2010Q3_Dirty_Startup_Reduction&diff=239132Firefox/Projects/2010Q3 Dirty Startup Reduction2010-07-19T15:47:03Z<p>Comrade693: /* Timeline / Milestones */ tweaked wording</p>
<hr />
<div>__NOTOC__I would like to teach Firefox to startup fast with a non-clean profile.<br />
<br />
*'''Project Lead''': sdwilsh<br />
*'''Dirty Profile Hunter''': limi<br />
<br />
== Status ==<br />
<br />
<onlyinclude>I have a dream. It's sorta like a plan.</onlyinclude><br />
<br />
== Goals ==<br />
* Ensure that startup time for a "dirty" profile ''in a profile with no add-ons or plugins installed/enabled'' is no worse than 20% of a clean profile's startup time ''on windows''.<br />
<br />
== Non Goals ==<br />
* Reduce startup time for a clean profile.<br />
* Fix this for every possible dirty profile.<br />
* Fix any startup issue caused by add-ons.<br />
<br />
== Timeline / Milestones ==<br />
<br />
* Establish a few reproducible "dirty" profiles with add-ons and plugins uninstalled or disabled (limi). ETA July 16.<br />
* Start profiling "dirty profiles" and come up with a plan. ETA August 15.<br />
<br />
<!--<br />
These are the bugs of interest:<br />
{| border="1"<br />
|-<br />
! scope="col" | Bug <br />
! scope="col" | Owner<br />
! scope="col" | Status<br />
|-<br />
| {{bug|12345}} - platform team sings offkey<br />
| damons<br />
| hopeless<br />
|}<br />
--><br />
<br />
== Requirements ==<br />
<br />
* A plan must be complete and work under way by the end of Q3 2010.<br />
<br />
== Dependencies ==<br />
<br />
None at the moment.<br />
<br />
== Testing ==<br />
<br />
Some performance benchmark will be created. Behavioral changes are covered by our automated test harness.<br />
<br />
== Related Projects ==<br />
<br />
Anything related to startup time reduction has potential.</div>Comrade693