canmove, Confirmed users
2,056
edits
(document the service API) |
|||
| Line 121: | Line 121: | ||
== API Changes == | == API Changes == | ||
This feature changes no existing APIs, but it does add several APIs. First, it adds a application-wide API for getting and setting site-specific preferences. Second, it adds a window-specific API for registering as a | This feature changes no existing APIs, but it does add several APIs. First, it adds a application-wide "service" API for getting and setting site-specific preferences. Second, it adds a window-specific "controller" API for registering as a pref handler and observing pref-related events. Third, it adds a "sidebar" API for adding controls to a sidebar presenting a consolidated view of preferences for the current site. | ||
=== Service API === | |||
The service is implemented as a JavaScript XPCOM component with contract ID "@mozilla.org/content-pref/service;1" that implements the nsIContentPrefService interface. | |||
==== Core Methods ==== | |||
The service's core API comprises the following four methods: | |||
nsIVariant getPref(in nsIURI uri, in AString name); | |||
void setPref(in nsIURI uri, in AString name, in nsIVariant value); | |||
boolean hasPref(in nsIURI uri, in AString name); | |||
void removePref(in nsIURI uri, in AString name); | |||
All four methods take as input a URI belonging to the site in question and a name for the preference. The service is responsible for extracting the name of the site from the URI. | |||
Question: should we make the consumer responsible for extracting site names from URIs so consumers can set preferences for non-standard groupings? | |||
The name of the preference is an arbitrary string. Preference namespacing is the responsibility of the consumer, as it is with the application-wide preferences accessed via nsIPrefBranch. | |||
The setPref method also takes as input an nsIVariant representing the value of the preference, while the getPref method returns such an nsIVariant. Consumers can set the value of a preference to null (nsIVariant::VTYPE_EMPTY), and the service distinguishes between preferences set to null and those that have not been set by representing the latter as the undefined value (nsIVariant::VTYPE_VOID). | |||
==== Getting All Prefs ==== | |||
The getPrefs method allows consumers to retrieve all preferences for a given site: | |||
nsIPropertyBag getPrefs(in nsIURI uri); | |||
The method returns an instance of "@mozilla.org/hash-property-bag;1", which implements both the nsIPropertyBag and the nsIPropertyBag2 interfaces. Bag keys are preference names, while bag values are preference values. | |||
==== Observers ==== | |||
The service also implements methods for adding and removing observers: | |||
void addObserver(in AString name, in nsIObserver observer, in boolean holdWeak); | |||
void removeObserver(in AString name, in nsIObserver observer); | |||
When a pref changes, the service notifies observers via the "content-pref-changed" topic. The notification is similar to one nsIPrefBranch2 sends with the "nsPref:changed" topic, but it has two key differences: | |||
* nsIContentPrefService takes only an exact preference name (nsIPrefBranch2 permits a consumer to watch an entire preference branch by passing in a branch prefix like "foo.bar.") | |||
* nsIContentPrefService passes the new value of the pref in notification's subject parameter, which is an nsIPropertyBag containing the following properties: | |||
** group: the site (or other grouping) to which the preference belongs; | |||
** name: the name of the preference; | |||
** oldValue: the old value of the preference; | |||
** newValue: the new value of the preference. | |||
Question: should the service support preference branches? | |||
Question: should the service pass a custom component with a custom interface (like the LiveTitleNotificationSubject component with the nsILiveTitleNotificationSubject interface) instead of a property bag? | |||
Question: is there any use for the notification's data parameter? | |||
==== Groupers ==== | |||
Finally, the service implements an attribute representing the grouper (i.e. the component implementing the nsIContentURIGrouper interface, about which see below) that the service uses to extract a site from a URI: | |||
attribute nsIContentURIGrouper grouper; | |||
The attribute is read/write so that extensions can change the grouper (and thus the way the service groups URIs). | |||
Question: would make more sense for this to be read-only and for the service to set the value of the attribute to the grouper specified by an application-wide preference? | |||
Groupers are components that categorize URIs into groups (f.e. by site). They implement a simple interface, nsIContentURIGrouper: | |||
readonly attribute AString name; | |||
AString group(in nsIURI uri); | |||
The name attribute is an arbitrary identifier for the grouper that the service uses to associate a preference in the database with the grouper responsible for determining its group. The group method returns the name of the group to which a given URI belongs. | |||
Question: should we just use the contract ID as the arbitrary identifier for the grouper, and how do we retrieve that from an instance of the component? | |||
The default grouper categorizes URIs by effective TLD + one additional hostname segment (i.e. example.com or bbc.co.uk). | |||
Question: should the default grouper categorize URIs by entire hostname? | |||
The service distinguishes between groups with the same name that have been categorized by different groupers to avoid collisions between groups that have the same name but are semantically different. | |||
Question: should we make groupers responsible for namespacing group names to avoid these collisions by the same way we make pref consumers responsible for namespacing pref names? | |||
== Extensibility == | == Extensibility == | ||