Extension:CentralNotice/Notes/Banner controller refactoring

Here's a place to keep some rough notes about reorganizing CentralNotice banner controller code.

Goals

 * Improve modularity and separation of concerns in banner controller code.
 * Adapt the banner controller API as needed for new campaign-associated mixins.
 * Improve site performance when banners are shown and when they're not.

Requirements

 * Separate concerns in a way that makes sense for selective loading of components based on campaigns available.
 * Follow typical and best-practice MW patterns, where applicable.
 * Remove any cruft.
 * If possible: move out code that has uses beyond CentralNotice (for example, GeoIP cookie stuff).

Proposal
Objects/modules:

init Checks contents of choiceData and the presence of a banner URL param and starts the appropriate processes.

controller Coordinates other objects, provides API for outside code, including banners and campaign-associated mixins.

chooser Selects a campaign and a banner based on choiceData.

bucketer Retrieves, stores, chooses and processes buckets.

kvStore Stores and retrieves items for different contexts (campaign, category, global).

testingBannerLoader Small module for loading banners for testing purposes. Loads dyamically via mw.loader.load when a banner parameter is included in the URL.

mobile Device checking (for mobile skin only).

geoIP Sets window.Geo. May be moved to a different extension or to MW core.

Requirements

 * Remain compatible with existing banners. Certain methods, properties and hooks should remain available. We can use JS get to deprecate properties as needed. The following should stick around:
 * Here are things that we don't need to keep publicly accessible outside CentralNotice:
 * (already deprecated)
 * (already deprecated)
 * New stuff the API will offer for campaign-associated mixins:
 * Retrieve bucket.
 * Set bucket.
 * A flag to be called by a mixin to signal that banners in a campaign are guaranteed to display to the user if loaded. This will disable Special:RecordImpression for such campaigns and add a parameter to the call to Special:BannerLoader to confirm that impressions may be counted using logs to that endpoint.
 * Access to the Key-Value store methods.
 * Everything should work smoothly with existing cached HTML.
 * (already deprecated)
 * (already deprecated)
 * New stuff the API will offer for campaign-associated mixins:
 * Retrieve bucket.
 * Set bucket.
 * A flag to be called by a mixin to signal that banners in a campaign are guaranteed to display to the user if loaded. This will disable Special:RecordImpression for such campaigns and add a parameter to the call to Special:BannerLoader to confirm that impressions may be counted using logs to that endpoint.
 * Access to the Key-Value store methods.
 * Everything should work smoothly with existing cached HTML.
 * New stuff the API will offer for campaign-associated mixins:
 * Retrieve bucket.
 * Set bucket.
 * A flag to be called by a mixin to signal that banners in a campaign are guaranteed to display to the user if loaded. This will disable Special:RecordImpression for such campaigns and add a parameter to the call to Special:BannerLoader to confirm that impressions may be counted using logs to that endpoint.
 * Access to the Key-Value store methods.
 * Everything should work smoothly with existing cached HTML.

Proposal
Get the bucket for this campaign. Guaranteed to be available in the  hook.

Guaranteed to influence which banner is selected in the  hook.

boolean property

Available key-value storage contexts

Reducing the size of top-loading RL modules

 * Does the fact that RL modules are cached in localStorage somewhat mitigate performance gains from doing this?
 * Why should any CentralNotice code be top-loaded?
 * The sooner the bannerController runs, the less of a page bump there will be when a banner is shown. Also, completely eliminating CentralNotice top-loaded modules would increase the number of round trips across the board.