← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~rharding/launchpad/wire_new_banner into lp:launchpad

 

Richard Harding has proposed merging lp:~rharding/launchpad/wire_new_banner into lp:launchpad.

Commit message:
Wire up the new ui.banner code and the global.js view to handle all banner displaying.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1056466 in Launchpad itself: "Privacy banner missing from +addspec when creating proprietary-by-default blueprints"
  https://bugs.launchpad.net/launchpad/+bug/1056466

For more details, see:
https://code.launchpad.net/~rharding/launchpad/wire_new_banner/+merge/133927

= Summary =

In a previous MP [1] a new banner handling JS code was landed. This branch
wires that code into play and replaces all of the old banner code.

The basic change is that the old macros are gone and we generate the banners
from the JS code. It's handled by firing an information type event. View code
must watch for that event and handle updating banners as required.

== Pre Implementation ==

It's been a long road. Lots of chatter. The big thing here is that review of
the previous MP brought up messaging for non-js users. This branch does add in
a <noscript> message for those users.


== Implementation Notes ==

We need to make sure we combine our new css file for widget styling.

All of the old banner code is removed. This includes the old beta css, the
global-notification (which was really just the privacy/beta banner css), the
whole app/banner JS folder. The new code is all contained in
lp/app/ui/banner.js.

Since we're not using any of the global-notification css the css generating
tales needs to be updated along with tests referencing it.

One hack is that security invokes a privacy banner. Ideally, we'd create a new
security banner and treat it separately as we do the beta banner. This will now
be possible, but it's not implemented in this branch. Because of this we have
some special casing around the event work to generate the correct banner
message.

Anywhere we manually updated the banner we change that to just fire the
information type event that the information type has changed. The global.js
will catch and handle all banner issues. This also allows other code to watch
that event so that more than banners can update as appropriate when the
information type changes.

global.js makes sure we watch for things on all pages that use the base
layout. In the future all of the JS in base-layout-macros should be moved with
tests added, however this just starts with replacing the banner code and
adding tests for it.

For the use case of the lynx users on the server we add <noscript> messages.
This has been tested to work and because it's <strong> it appears in red using
default colors.

There's a few drive by fixes of not enabling the green flash effect when the
information type changes in places where that is not performing an ajax
request per our design guidelines.

Finally we add a nice message to the private project feature flag in order to
make sure the beta banner shows in a pretty way.


== Q/A ==

Banners for beta and privacy should function on:

- registering a new project
- editing a current project
- creating and editing a new blueprint

Privacy banner should still function for:

- filing a bug, editing a bug, changing the info type via portlet
- changing the info type via portlet


[1] https://code.launchpad.net/~rharding/launchpad/add_new_banner/+merge/133736


-- 
https://code.launchpad.net/~rharding/launchpad/wire_new_banner/+merge/133927
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rharding/launchpad/wire_new_banner into lp:launchpad.
=== modified file 'buildout-templates/bin/combine-css.in'
--- buildout-templates/bin/combine-css.in	2012-08-23 19:56:15 +0000
+++ buildout-templates/bin/combine-css.in	2012-11-12 16:13:23 +0000
@@ -27,6 +27,7 @@
     #'lazr/build/yui/cssgrids/grids.css',
     'cssgrids/grids.css',
     'build/ui/assets/skins/sam/lazr.css',
+    'build/ui/assets/skins/sam/banner.css',
     'build/inlineedit/assets/skins/sam/editor.css',
     'build/autocomplete/assets/skins/sam/autocomplete.css',
     'build/overlay/assets/skins/sam/pretty-overlay.css',

=== removed file 'lib/canonical/launchpad/icing/css/components/beta_banner.css'
--- lib/canonical/launchpad/icing/css/components/beta_banner.css	2012-05-16 20:32:47 +0000
+++ lib/canonical/launchpad/icing/css/components/beta_banner.css	1970-01-01 00:00:00 +0000
@@ -1,48 +0,0 @@
-/* ===========
-   Beta banner
-*/
-.yui3-betabanner-content .global-notification {
-    position: fixed;
-    z-index: 9;
-    top: 0;
-    left: 0;
-    right: 0;
-    padding: 7px 20px;
-    /* Define colour for browsers that don't support transparency */
-    background-color: #606060;
-    /* Set transparent background for browsers that support it */
-    background-color: rgba(64, 64, 64, 0.9);
-    box-shadow: 0 0 5px #333;
-    color: #fff;
-    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5);
-    font-size: 14px;
-    line-height: 21px;
-    text-align: left;
-    }
-.beta-banner .info-link {
-    color: #4884ef;
-}
-.beta-warning {
-    padding: 3px 6px 4px 6px;
-    margin-right: 12px;
-    background-color: #be0000;
-    font-weight: bold;
-    font-size: 12px;
-    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-    border-radius: 5px;
-    border-top: 1px solid #e20000;
-    background-color: #c10000;
-    background: linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%);
-    background: -o-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%);
-    background: -moz-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%);
-    background: -webkit-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%);
-    background: -ms-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%);
-    }
-.beta-feature {
-    font-weight: bold;
-    }
-.yui3-betabanner-content .global-notification-close,
-.yui3-betabanner-content .global-notification-close:active,
-.yui3-betabanner-content .global-notification-close:visited {
-    color: #fff;
-    }

=== removed file 'lib/canonical/launchpad/icing/css/components/global_notification.css'
--- lib/canonical/launchpad/icing/css/components/global_notification.css	2012-05-16 19:09:45 +0000
+++ lib/canonical/launchpad/icing/css/components/global_notification.css	1970-01-01 00:00:00 +0000
@@ -1,66 +0,0 @@
-/* ====================
-   Global notifications
-*/
-/* Move the content down so the notification banner doesn't hide any content. */
-body.global-notification-visible {
-    padding-top: 40px;
-    }
-body.global-notification-visible .login-logout {
-    top: 45px;
-    }
-.global-notification {
-    position: fixed;
-    z-index: 10;
-    top: 0;
-    left: 0;
-    right: 0;
-    padding: 8px 20px;
-    text-shadow: 0 -1px 0 #631616;
-    font-size: 14px;
-    line-height: 21px;
-    font-weight: bold;
-    box-shadow: 0 0 5px #333;
-    }
-.global-notification .sprite.notification-private {
-    float: left;
-    display: inline-block;
-    height: 21px;
-    width: 20px;
-    margin-right: 10px;
-    padding: 0;
-    }
-.global-notification-close,
-.global-notification-close:active,
-.global-notification-close:visited {
-    color: #e47a7a;
-    }
-.global-notification-close {
-    display: block;
-    position: absolute;
-    top: 11px;
-    right: 20px;
-    font-size: 12px;
-    font-weight: normal;
-    line-height: 14px;
-    }
-.global-notification-close .sprite.notification-close {
-    float: right;
-    display: block;
-    height: 9px;
-    width: 8px;
-    margin: 3px 0 0 7px;
-    padding: 0;
-    }
-
-/* =======
-   Privacy
-*/
-
-.yui3-privacybanner-content .global-notification{
-    /* Define colour for browsers that don't support transparency */
-    background-color: #8d1f1f;
-    /* Set transparent background for browsers that support it */
-    background-color: rgba(125,0,0,0.9);
-    color: #fff;
-    text-align: left;
-}

=== modified file 'lib/lp/app/browser/configure.zcml'
--- lib/lp/app/browser/configure.zcml	2012-08-09 03:50:49 +0000
+++ lib/lp/app/browser/configure.zcml	2012-11-12 16:13:23 +0000
@@ -33,13 +33,6 @@
         />
     <browser:page
         for="*"
-        name="+banner-macros"
-        template="../templates/banner-macros.pt"
-        permission="zope.Public"
-        class="lp.app.browser.launchpad.Macro"
-        />
-    <browser:page
-        for="*"
         name="launchpad_form"
         layer="lp.layers.LaunchpadLayer"
         permission="zope.Public"

=== modified file 'lib/lp/app/browser/tales.py'
--- lib/lp/app/browser/tales.py	2012-09-28 06:15:58 +0000
+++ lib/lp/app/browser/tales.py	2012-11-12 16:13:23 +0000
@@ -663,15 +663,16 @@
     def global_css(self):
         css_classes = set([])
         view = self._context
+
+        # XXX: Bug #1076074
         private = getattr(view, 'private', False)
         if private:
             css_classes.add('private')
-            css_classes.add('global-notification-visible')
         else:
             css_classes.add('public')
         beta = getattr(view, 'beta_features', [])
-        if beta != []:
-            css_classes.add('global-notification-visible')
+        if beta:
+            css_classes.add('beta')
         return ' '.join(list(css_classes))
 
     def _getSaneBreadcrumbDetail(self, breadcrumb):

=== modified file 'lib/lp/app/browser/tests/base-layout.txt'
--- lib/lp/app/browser/tests/base-layout.txt	2012-05-22 17:00:08 +0000
+++ lib/lp/app/browser/tests/base-layout.txt	2012-11-12 16:13:23 +0000
@@ -158,12 +158,10 @@
 -------------------------------
 
 The base-layout master templates uses the fmt:global-css formatter to
-add the 'public' or 'private' CSS class to the body tag as well as the
-'global-notification-visible' tag, if needed.
+add the 'public' or 'private' CSS class to the body tag.
 
 When the context is private, the 'private' class is added to the body's class
-attribute. If the context is private or there are beta features,
-'global-notification-visible' is added to the body's class attribute.
+attribute.
 
     >>> from lp.registry.interfaces.person import PersonVisibility
 
@@ -174,7 +172,10 @@
     >>> view = MainOnlyView(team, request)
     >>> body = find_tag_by_id(view.render(), 'document')
     >>> print body['class']
-    tab-overview main_only global-notification-visible private yui3-skin-sam
+    tab-overview
+        main_only
+        private
+        yui3-skin-sam
 
 When the context is public, the 'public' class is in the class attribute.
 

=== modified file 'lib/lp/app/browser/tests/test_formatters.py'
--- lib/lp/app/browser/tests/test_formatters.py	2012-08-08 07:23:58 +0000
+++ lib/lp/app/browser/tests/test_formatters.py	2012-11-12 16:13:23 +0000
@@ -91,7 +91,7 @@
         view = create_view(person, name="+archivesubscriptions")
         formatter = ObjectFormatterAPI(view)
         self.assertEqual(
-            'global-notification-visible private',
+            'private',
             formatter.global_css())
 
 class TestPillarFormatterAPI(TestCaseWithFactory):

=== modified file 'lib/lp/app/doc/tales.txt'
--- lib/lp/app/doc/tales.txt	2012-06-15 16:23:50 +0000
+++ lib/lp/app/doc/tales.txt	2012-11-12 16:13:23 +0000
@@ -1551,7 +1551,7 @@
     True
 
     >>> print test_tales('context/fmt:global-css', context=bug)
-    global-notification-visible private
+    private
 
     >>> login(ANONYMOUS)
 

=== removed directory 'lib/lp/app/javascript/banners'
=== removed file 'lib/lp/app/javascript/banners/banner.js'
--- lib/lp/app/javascript/banners/banner.js	2012-10-04 14:17:23 +0000
+++ lib/lp/app/javascript/banners/banner.js	1970-01-01 00:00:00 +0000
@@ -1,156 +0,0 @@
-/*
- * Copyright 2012 Canonical Ltd.  This software is licensed under the
- * GNU Affero General Public License version 3 (see the file LICENSE).
- *
- * Notification banner widget
- *
- * @module lp.app.banner
- */
-
-YUI.add('lp.app.banner', function (Y) {
-var ns = Y.namespace('lp.app.banner');
-
-ns.Banner = Y.Base.create('banner', Y.Widget, [], {
-
-    _getAnimTimes: function() {
-        var anim_times;
-        if (this.get('skip_animation')) {
-            anim_times = {
-                fade: 0.0,
-                slide_out: 0.0
-            };
-        } else {
-            anim_times = {
-                fade: 0.3,
-                slide_out: 0.2
-            };
-        }
-        return anim_times;
-    },
-
-    _showBanner: function () {
-        var body = Y.one('body');
-        var global_notification = Y.one('.global-notification');
-        var anim_times = this._getAnimTimes();
-
-        body.addClass('global-notification-visible');
-        global_notification.removeClass('hidden');
-
-        var fade_in = new Y.Anim({
-            node: global_notification,
-            to: {opacity: 1},
-            duration: anim_times.fade
-        });
-        var body_space = new Y.Anim({
-            node: body,
-            to: {'paddingTop': '40px'},
-            duration: anim_times.slide_out,
-            easing: Y.Easing.easeOut
-        });
-        var login_space = new Y.Anim({
-            node: '.login-logout',
-            to: {'top': '45px'},
-            duration: anim_times.slide_out,
-            easing: Y.Easing.easeOut
-        });
-        // For testing, we don't do the animations or else the tests will fail.
-        if (anim_times.fade > 0) {
-            fade_in.run();
-        }
-        if (anim_times.slide_out > 0) {
-            body_space.run();
-            login_space.run();
-        }
-    },
-
-    _hideBanner: function () {
-        var body = Y.one('body');
-        var global_notification = Y.one('.global-notification');
-        var anim_times = this._getAnimTimes();
-
-        global_notification.addClass('transparent');
-
-        var fade_out = new Y.Anim({
-            node: global_notification,
-            to: {opacity: 0},
-            duration: anim_times.fade
-        });
-        var body_space = new Y.Anim({
-            node: body,
-            to: {'paddingTop': 0},
-            duration: anim_times.slide_out,
-            easing: Y.Easing.easeOut
-        });
-        var login_space = new Y.Anim({
-            node: '.login-logout',
-            to: {'top': '6px'},
-            duration: anim_times.slide_out,
-            easing: Y.Easing.easeOut
-        });
-        fade_out.on('end', function() {
-            global_notification.addClass('hidden');
-        });
-        body_space.on('end', function() {
-            body.removeClass('global-notification-visible');
-        });
-
-        fade_out.run();
-        body_space.run();
-        login_space.run();
-    },
-
-    bindUI: function() {
-        this.after('visibleChange', function() {
-            if (this.get('visible')) {
-                this._showBanner();
-            } else {
-                this._hideBanner();
-            }
-        });
-    },
-
-    renderUI: function () {
-        var banner_data = {
-            badge: this.get('banner_icon'),
-            text: this.get('notification_text')
-        };
-        var banner_html = Y.lp.mustache.to_html(
-            this.get('banner_template'),
-            banner_data);
-        this.get('contentBox').append(banner_html);
-    },
-
-    updateText: function (new_text) {
-        var text_node = this.get('contentBox').one('.banner-text');
-        if (!Y.Lang.isValue(new_text)) {
-            new_text = this.get('notification_text');
-        }
-
-        if (text_node) {
-            text_node.set('text', new_text);
-        } else {
-            Y.log('No text node to update banner text.', 'error');
-        }
-    }
-
-}, {
-    ATTRS: {
-        banner_icon: { value: "<span></span>" },
-        banner_template: {
-            valueFn: function() {
-                return [
-                    '<div class="global-notification transparent hidden">',
-                        '{{{ badge }}}',
-                        '<span class="banner-text">{{ text }}</span>',
-                    "</div>"].join('');
-            }
-        },
-        notification_text: { value: "" },
-        skip_animation: { value: false },
-        visible: { value: false }
-    }
-});
-
-}, '0.1', {
-    requires: ['base', 'node', 'anim', 'widget', 'lp.mustache', 'yui-log']
-});

=== removed file 'lib/lp/app/javascript/banners/beta-notification.js'
--- lib/lp/app/javascript/banners/beta-notification.js	2012-09-25 18:47:19 +0000
+++ lib/lp/app/javascript/banners/beta-notification.js	1970-01-01 00:00:00 +0000
@@ -1,104 +0,0 @@
-/**
- * Add a BetaBanner widget for use.
- *
- * @namespace lp.app.banner
- * @module beta
- *
- */
-YUI.add('lp.app.banner.beta', function(Y) {
-
-var ns = Y.namespace('lp.app.banner.beta');
-var Banner = Y.lp.app.banner.Banner;
-
-// For the beta banner to work, it needs to have one instance, and one
-// instance only.
-window._singleton_beta_banner = null;
-
-ns.show_beta_if_needed = function () {
-    if (window._singleton_beta_banner === null) {
-        var src = Y.one('.yui3-betabanner');
-        window._singleton_beta_banner = new ns.BetaBanner({ srcNode: src });
-    }
-    if (window._singleton_beta_banner.get('features').length !== 0) {
-        window._singleton_beta_banner.render();
-        window._singleton_beta_banner.show();
-    }
-};
-
-
-/**
- * Banner to display for beta features.
- *
- * @class BetaBanner
- * @extends Banner
- *
- */
-ns.BetaBanner = Y.Base.create('betaBanner', Banner, [], {
-
-    bindUI: function () {
-        Banner.prototype.bindUI.apply(this, arguments);
-        var close_box = Y.one('.global-notification-close');
-        var that = this;
-        close_box.on('click', function(e) {
-            e.halt();
-            that.hide();
-        });
-    },
-
-    renderUI: function () {
-        var banner_data = {
-            badge: this.get('banner_icon'),
-            text: this.get('notification_text'),
-            features: this.get('features'),
-        };
-        var banner_html = Y.lp.mustache.to_html(
-            this.get('banner_template'),
-            banner_data);
-        this.get('contentBox').append(banner_html);
-        var beta_node = Y.one('.global-notification');
-        var close_box = Y.Node.create(
-            '<a href="#" class="global-notification-close">Hide' +
-            '<span class="notification-close sprite" /></a>');
-        beta_node.appendChild(close_box);
-    }
-
-}, {
-    ATTRS: {
-        banner_icon: { value: '<span class="beta-warning">BETA!</span>' },
-
-        banner_template: {
-            valueFn: function() {
-                return [
-                    '<div class="global-notification transparent hidden">',
-                        '{{{ badge }}}',
-                        '<span class="banner-text">',
-                            '{{ text }}{{{ features }}}',
-                        '</span>',
-                    "</div>"].join('');
-            }
-        },
-
-        features: {
-            valueFn: function () {
-                var features_template = [
-                    '{{#features}}{{#is_beta}}',
-                    '<span class="beta-feature"> {{title}}',
-                    '{{#url}}',
-                    ' (<a href="{{url}}" class="info-link">read more</a>)',
-                    '{{/url}}',
-                    '</span>',
-                    '{{/is_beta}}{{/features}}'].join('');
-                var feature_data = {
-                    features: Y.Object.values(LP.cache.related_features)
-                };
-                return Y.lp.mustache.to_html(features_template, feature_data);
-            }
-        },
-
-        notification_text: { value: "Some parts of this page are in beta: " }
-    }
-});
-
-
-}, '0.1', {'requires': ['base', 'node', 'anim', 'lp.mustache',
-                        'lp.app.banner']});

=== removed file 'lib/lp/app/javascript/banners/privacy.js'
--- lib/lp/app/javascript/banners/privacy.js	2012-10-04 14:17:23 +0000
+++ lib/lp/app/javascript/banners/privacy.js	1970-01-01 00:00:00 +0000
@@ -1,119 +0,0 @@
-/**
- * Add a PrivacyBanner widget for use.
- *
- * @namespace lp.app.banner
- * @module privacy
- *
- */
-YUI.add('lp.app.banner.privacy', function(Y) {
-var ns = Y.namespace('lp.app.banner.privacy');
-var Banner = Y.lp.app.banner.Banner;
-
-ns.EV_SHOW = 'privacy_banner:show';
-ns.EV_HIDE = 'privacy_banner:hide';
-
-/**
- * Allow for adjusting the global instance of the Privacy Banner via events.
- *
- * @event privacy_banner:show
- * @param text The message to show
- */
-Y.publish(ns.EV_SHOW, {
-    emitFacade: true
-});
-
-/**
- * Hide the global instance of the banner via events.
- *
- * @event privacy_banner:hide
- */
-Y.publish(ns.EV_HIDE, {
-    emitFacade: true
-});
-
-
-// For the privacy banner to work, it needs to have one instance, and one
-// instance only.
-window._singleton_privacy_banner = null;
-ns.getPrivacyBanner = function (banner_text, skip_animation) {
-    if (window._singleton_privacy_banner === null) {
-        var src = Y.one('.yui3-privacybanner');
-        window._singleton_privacy_banner = new ns.PrivacyBanner(
-            { srcNode: src, skip_animation: skip_animation });
-        window._singleton_privacy_banner.render();
-    }
-    if (Y.Lang.isValue(banner_text)) {
-        window._singleton_privacy_banner.updateText(banner_text);
-    }
-    return window._singleton_privacy_banner;
-};
-
-
-/**
- * Banner to display when page contains private information.
- *
- * @class PrivacyBanner
- * @extends Banner
- *
- */
-ns.PrivacyBanner = Y.Base.create('privacyBanner', Banner, [], {
-    _custom_message: function (ev) {
-        var body = Y.one('body');
-        body.replaceClass('public', 'private');
-        if (!ev.text) {
-            throw('A custom privacy banner must have a text attribute');
-        }
-        this.updateText(ev.text);
-        this.show();
-    },
-
-    _make_public: function (ev) {
-        var body = Y.one('body');
-        body.replaceClass('private', 'public');
-        this.hide();
-    },
-
-    _make_private: function (ev) {
-        // Update the text in the banner before we show it.
-        var body = Y.one('body');
-        body.replaceClass('public', 'private');
-
-        if (!ev.text) {
-            throw('Showing a privacy banner must supply text for the banner');
-        }
-        this.updateText(ev.text);
-        this.show();
-    },
-
-    bindUI: function () {
-        var that = this;
-        var info_type = Y.lp.app.information_type;
-        Banner.prototype.bindUI.apply(this, arguments);
-
-        // We care about changes to Information Type in the UI.
-        Y.on(info_type.EV_ISPUBLIC, that._make_public, that);
-        Y.on(info_type.EV_ISPRIVATE, that._make_private, that);
-
-        // And provide our own manual events for the Security banner usage.
-        Y.on(ns.EV_SHOW, that._custom_message, that);
-        Y.on(ns.EV_HIDE, function (ev) {
-            that.hide();
-        }, that);
-    }
-
-}, {
-    ATTRS: {
-        banner_icon: {
-            value: '<span class="sprite notification-private"></span>'
-        },
-        notification_text: {
-            value: "The information on this page is private."
-        }
-    }
-});
-
-}, "0.1", {
-    requires: [
-        "base", "node", "anim", "lp.app.banner",
-        "lp.app.information_type"]
-});

=== removed directory 'lib/lp/app/javascript/banners/tests'
=== removed file 'lib/lp/app/javascript/banners/tests/test_banner.html'
--- lib/lp/app/javascript/banners/tests/test_banner.html	2012-10-26 09:54:28 +0000
+++ lib/lp/app/javascript/banners/tests/test_banner.html	1970-01-01 00:00:00 +0000
@@ -1,46 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright 2012 Canonical Ltd.  This software is licensed under the
-GNU Affero General Public License version 3 (see the file LICENSE).
--->
-
-<html>
-  <head>
-      <title>lp.app.banner Tests</title>
-
-      <!-- YUI and test setup -->
-      <script type="text/javascript"
-              src="../../../../../../build/js/yui/yui/yui.js">
-      </script>
-      <link rel="stylesheet"
-      href="../../../../../../build/js/yui/console/assets/console-core.css" />
-      <link rel="stylesheet"
-      href="../../../../../../build/js/yui/test-console/assets/skins/sam/test-console.css" />
-      <link rel="stylesheet"
-      href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" />
-
-      <script type="text/javascript"
-              src="../../../../../../build/js/lp/app/testing/testrunner.js"></script>
-
-      <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
-
-      <!-- Dependencies -->
-      <script type="text/javascript"
-          src="../../../../../../build/js/lp/app/mustache.js"></script>
-
-      <!-- The module under test. -->
-      <script type="text/javascript" src="../banner.js"></script>
-
-      <!-- Placeholder for any css asset for this module. -->
-      <!-- <link rel="stylesheet" href="../assets/${LIBRARY}-core.css" /> -->
-
-      <!-- The test suite -->
-      <script type="text/javascript" src="test_banner.js"></script>
-
-    </head>
-    <body class="yui3-skin-sam">
-        <ul id="suites">
-            <li>lp.app.banner.test</li>
-        </ul>
-    </body>
-</html>

=== removed file 'lib/lp/app/javascript/banners/tests/test_banner.js'
--- lib/lp/app/javascript/banners/tests/test_banner.js	2012-10-26 10:00:20 +0000
+++ lib/lp/app/javascript/banners/tests/test_banner.js	1970-01-01 00:00:00 +0000
@@ -1,110 +0,0 @@
-/* Copyright (c) 2012, Canonical Ltd. All rights reserved. */
-
-YUI.add('lp.app.banner.test', function (Y) {
-
-    var tests = Y.namespace('lp.app.banner.test');
-    tests.suite = new Y.Test.Suite('lp.app.banner Tests');
-
-    tests.suite.add(new Y.Test.Case({
-        name: 'banner_tests',
-
-        setUp: function () {
-            var main = Y.Node.create('<div id="maincontent"></div>');
-            var login_logout = Y.Node.create('<div></div>')
-                .addClass('login-logout');
-            main.appendChild(login_logout);
-            Y.one('body').appendChild(main);
-        },
-
-        tearDown: function () {
-            Y.one('#maincontent').remove(true);
-            Y.all('.yui3-banner').remove(true);
-        },
-
-        test_library_exists: function () {
-            Y.Assert.isObject(Y.lp.app.banner,
-                "Could not locate the lp.app.banner module");
-        },
-
-        test_init_without_config: function () {
-            var banner = new Y.lp.app.banner.Banner();
-            Y.Assert.areEqual("", banner.get('notification_text'));
-            Y.Assert.areEqual("<span></span>", banner.get('banner_icon'));
-        },
-
-        test_init_with_config: function () {
-            var cfg = {
-                notification_text: "Some text.",
-                banner_icon: '<span class="sprite"></span>'
-            };
-            var banner = new Y.lp.app.banner.Banner(cfg);
-            Y.Assert.areEqual(
-                cfg.notification_text,
-                banner.get('notification_text'));
-            Y.Assert.areEqual(cfg.banner_icon, banner.get('banner_icon'));
-        },
-
-        test_render_no_config: function () {
-            var banner = new Y.lp.app.banner.Banner({ skip_animation: true });
-            banner.render();
-
-            var banner_node = Y.one(".global-notification");
-            Y.Assert.isObject(banner_node);
-            Y.Assert.isTrue(banner_node.hasClass('hidden'));
-        },
-
-        test_render_with_config: function () {
-            var cfg = {
-                notification_text: "Some text.",
-                banner_icon: '<span class="sprite"></span>',
-                skip_animation: true
-            };
-            var banner = new Y.lp.app.banner.Banner(cfg);
-            banner.render();
-
-            var banner_node = Y.one(".global-notification");
-            var badge = banner_node.one('.sprite');
-            Y.Assert.isObject(banner_node);
-            Y.Assert.areEqual(cfg.notification_text, banner_node.get('text'));
-            Y.Assert.isObject(badge);
-        },
-
-        test_show: function() {
-            var banner = new Y.lp.app.banner.Banner({ skip_animation: true });
-            banner.render();
-            banner.show();
-            var banner_node = Y.one(".global-notification");
-            Y.Assert.isFalse(banner_node.hasClass('hidden'));
-        },
-
-        test_hide: function() {
-            var banner = new Y.lp.app.banner.Banner({ skip_animation: true });
-            banner.render();
-            banner.show();
-
-            // Even with animation times set to 0, this test needs a slight
-            // delay in order for the animation end events to fire.
-            var banner_node = Y.one(".global-notification");
-            var wait_for_anim = 20;
-            var check = function () {
-                Y.Assert.isTrue(banner_node.hasClass('hidden'));
-            };
-            banner.hide();
-            this.wait(check, wait_for_anim);
-        },
-
-        test_updateText: function() {
-            var banner = new Y.lp.app.banner.Banner({ skip_animation: true });
-            banner.render();
-            var new_text = 'some new text';
-            banner.updateText(new_text);
-            var banner_node = Y.one(".global-notification");
-            Y.Assert.areEqual(new_text, banner_node.get('text'));
-
-            banner.updateText();
-            banner_node = Y.one(".global-notification");
-            Y.Assert.areEqual("", banner_node.get('text'));
-        }
-    }));
-
-}, '0.1', {'requires': ['test', 'test-console', 'lp.app.banner']});

=== removed file 'lib/lp/app/javascript/banners/tests/test_beta_notification.html'
--- lib/lp/app/javascript/banners/tests/test_beta_notification.html	2012-10-26 09:54:28 +0000
+++ lib/lp/app/javascript/banners/tests/test_beta_notification.html	1970-01-01 00:00:00 +0000
@@ -1,51 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright 2012 Canonical Ltd.  This software is licensed under the
-GNU Affero General Public License version 3 (see the file LICENSE).
--->
-
-<html>
-  <head>
-      <title>Test beta-notification</title>
-
-      <!-- YUI and test setup -->
-      <script type="text/javascript"
-              src="../../../../../../build/js/yui/yui/yui.js">
-      </script>
-      <link rel="stylesheet"
-      href="../../../../../../build/js/yui/console/assets/console-core.css" />
-      <link rel="stylesheet"
-      href="../../../../../../build/js/yui/test-console/assets/skins/sam/test-console.css" />
-      <link rel="stylesheet"
-      href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" />
-
-      <script type="text/javascript"
-              src="../../../../../../build/js/lp/app/testing/testrunner.js"></script>
-
-      <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
-
-      <!-- Dependencies -->
-      <script type="text/javascript"
-          src="../../../../../../build/js/lp/app/banners/banner.js"></script>
-      <script type="text/javascript"
-          src="../../../../../../build/js/lp/app/mustache.js"></script>
-
-      <!-- The module under test. -->
-      <script type="text/javascript" src="../beta-notification.js"></script>
-
-      <!-- Placeholder for any css asset for this module. -->
-      <!-- <link rel="stylesheet" href="../assets/beta-notification-core.css" /> -->
-
-      <!-- The test suite. -->
-      <script type="text/javascript" src="test_beta_notification.js"></script>
-
-    </head>
-    <body class="yui3-skin-sam">
-        <ul id="suites">
-            <!-- <li>lp.large_indicator.test</li> -->
-            <li>lp.app.banner.beta.test</li>
-        </ul>
-        <!-- The example markup required by the script to run. -->
-        <div id="maincontent"></div>
-    </body>
-</html>

=== removed file 'lib/lp/app/javascript/banners/tests/test_beta_notification.js'
--- lib/lp/app/javascript/banners/tests/test_beta_notification.js	2012-10-26 10:00:20 +0000
+++ lib/lp/app/javascript/banners/tests/test_beta_notification.js	1970-01-01 00:00:00 +0000
@@ -1,140 +0,0 @@
-/* Copyright (c) 2012, Canonical Ltd. All rights reserved. */
-
-// Set the "enabled" variable, normally set by base-layout-macros.
-// This must be a global variable for the code being tested to work.
-var privacy_notification_enabled = true;
-
-YUI.add('lp.app.banner.beta.test', function (Y) {
-
-    var tests = Y.namespace('lp.app.banner.beta.test');
-    tests.suite = new Y.Test.Suite('lp.app.banner.beta Tests');
-
-    tests.suite.add(new Y.Test.Case({
-        name: 'beta-notification',
-
-        setUp: function () {
-            var main = Y.Node.create('<div id="maincontent"></div>');
-            var login_logout = Y.Node.create('<div></div>')
-                .addClass('login-logout');
-            main.appendChild(login_logout);
-            Y.one('body').append(main);
-            window.LP = {
-                cache: {}
-            };
-        },
-
-        tearDown: function () {
-            Y.one('#maincontent').remove(true);
-            Y.all('.yui3-banner').remove(true);
-        },
-
-        test_library_exists: function () {
-            Y.Assert.isObject(Y.lp.app.banner.beta,
-                "Could not locate the lp.app.banner.beta module");
-        },
-
-        test_beta_banner_one_beta_feature: function() {
-            LP.cache.related_features = {
-                '': {
-                    is_beta: true,
-                    title: 'A beta feature',
-                    url: 'http://lp.dev/LEP/one'
-            }};
-            var betabanner = new Y.lp.app.banner.beta.BetaBanner(
-                {skip_animation: true});
-            betabanner.render();
-            betabanner.show();
-
-            var body = Y.one('body');
-            // The <body> node has the class global-notification-visible,
-            // so that the element has enough padding for the beta banner.
-            Y.Assert.isTrue(body.hasClass('global-notification-visible'));
-
-            feature_info = Y.one('.beta-feature');
-            // The message about a beta feature consists of the feature
-            // title and a link to a page with more information about
-            // the feature.
-            Y.Assert.areEqual(
-                ' A beta feature (read more)', feature_info.get('text'));
-            info_link = feature_info.get('children').item(0);
-            Y.Assert.areEqual('http://lp.dev/LEP/one', info_link.get('href'));
-        },
-
-        test_beta_banner_two_beta_features: function() {
-            LP.cache.related_features = {
-                '1': {
-                    is_beta: true,
-                    title: 'Beta feature 1',
-                    url: 'http://lp.dev/LEP/one'
-                },
-                '2': {
-                    is_beta: true,
-                    title: 'Beta feature 2',
-                    url: ''
-                }};
-            var betabanner = new Y.lp.app.banner.beta.BetaBanner(
-                {skip_animation: true});
-            betabanner.render();
-            betabanner.show();
-
-            var body = Y.one('body');
-            Y.Assert.isTrue(body.hasClass('global-notification-visible'));
-
-            // Notifications about several features can be displayed.
-            feature_info = Y.all('.beta-feature').item(0);
-            Y.Assert.areEqual(
-                ' Beta feature 1 (read more)', feature_info.get('text'));
-            info_link = feature_info.get('children').item(0);
-            Y.Assert.areEqual('http://lp.dev/LEP/one', info_link.get('href'));
-
-            // If an entry in LP.cache.related_features does not provide a
-            // "read more" link, the corrsponding node is not added.
-            feature_info = Y.all('.beta-feature').item(1);
-            Y.Assert.areEqual(
-                ' Beta feature 2', feature_info.get('text'));
-            Y.Assert.isNull(feature_info.get('children').item(0));
-        },
-
-        test_beta_banner_no_beta_features_defined: function() {
-            LP.cache.related_features = {
-                foo_feature: {
-                    is_beta: false,
-                    title: 'Non-beta feature',
-                    url: 'http://example.org'
-                }};
-            Y.lp.app.banner.beta.show_beta_if_needed();
-            Y.Assert.isNull(Y.one('.global-notification'));
-        },
-
-        test_hide_beta_banner: function() {
-            LP.cache.related_features = {
-                '': {
-                    is_beta: true,
-                    title: 'A beta feature',
-                    url: 'http://lp.dev/LEP/one'
-            }};
-            var betabanner = new Y.lp.app.banner.beta.BetaBanner(
-                {skip_animation: true});
-            betabanner.render();
-            betabanner.show();
-            var body = Y.one('body');
-            var banner = Y.one('.global-notification');
-            Y.Assert.isFalse(banner.hasClass('hidden'));
-
-            // Even with animation times set to 0, this test needs a slight
-            // delay in order for the animation end events to fire.
-            var check = function() {
-                Y.Assert.isTrue(banner.hasClass('hidden'));
-                Y.Assert.isFalse(
-                    body.hasClass('global-notification-visible'));
-            };
-            close_link = Y.one('.global-notification-close');
-            close_link.simulate('click');
-            var wait_time = 20;
-            this.wait(check, wait_time);
-        }
-    }));
-
-}, '0.1', { 'requires': ['test', 'test-console', 'node', 'lp.app.banner.beta',
-                         'node-event-simulate']
-});

=== removed file 'lib/lp/app/javascript/banners/tests/test_privacy.html'
--- lib/lp/app/javascript/banners/tests/test_privacy.html	2012-10-26 09:54:28 +0000
+++ lib/lp/app/javascript/banners/tests/test_privacy.html	1970-01-01 00:00:00 +0000
@@ -1,47 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright 2012 Canonical Ltd.  This software is licensed under the
-GNU Affero General Public License version 3 (see the file LICENSE).
--->
-
-<html>
-  <head>
-      <title>lp.app.banner.privacy Tests</title>
-
-      <!-- YUI and test setup -->
-      <script type="text/javascript"
-              src="../../../../../../build/js/yui/yui/yui.js">
-      </script>
-      <link rel="stylesheet"
-      href="../../../../../../build/js/yui/console/assets/console-core.css" />
-      <link rel="stylesheet"
-      href="../../../../../../build/js/yui/test-console/assets/skins/sam/test-console.css" />
-      <link rel="stylesheet"
-      href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" />
-
-      <script type="text/javascript"
-              src="../../../../../../build/js/lp/app/testing/testrunner.js"></script>
-
-      <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
-
-      <!-- Dependencies -->
-      <script type="text/javascript"
-          src="../../../../../../build/js/lp/app/mustache.js"></script>
-      <script type="text/javascript"
-          src="../../../../../../build/js/lp/app/banners/banner.js"></script>
-      <script type="text/javascript"
-          src="../../../../../../build/js/lp/app/information_type.js"></script>
-
-      <!-- The module under test. -->
-      <script type="text/javascript" src="../privacy.js"></script>
-
-      <!-- The test suite. -->
-      <script type="text/javascript" src="test_privacy.js"></script>
-
-    </head>
-    <body class="yui3-skin-sam">
-        <ul id="suites">
-            <li>lp.app.banner.privacy.test</li>
-        </ul>
-    </body>
-</html>

=== removed file 'lib/lp/app/javascript/banners/tests/test_privacy.js'
--- lib/lp/app/javascript/banners/tests/test_privacy.js	2012-10-26 10:00:20 +0000
+++ lib/lp/app/javascript/banners/tests/test_privacy.js	1970-01-01 00:00:00 +0000
@@ -1,117 +0,0 @@
-/* Copyright 2011-2012 Canonical Ltd.  This software is licensed under the
- * GNU Affero General Public License version 3 (see the file LICENSE).
- */
-
-YUI.add('lp.app.banner.privacy.test', function (Y) {
-
-    var tests = Y.namespace('lp.app.banner.privacy.test');
-    tests.suite = new Y.Test.Suite('lp.app.banner.privacy Tests');
-
-    tests.suite.add(new Y.Test.Case({
-        name: 'privacy_tests',
-
-        setUp: function () {
-            var main = Y.Node.create('<div id="maincontent"></div>');
-            var login_logout = Y.Node.create('<div></div>')
-                .addClass('login-logout');
-            main.appendChild(login_logout);
-
-            var banner_node = Y.Node.create('<div></div>')
-                .addClass('yui3-privacybanner');
-            main.appendChild(banner_node);
-            Y.one('body').appendChild(main);
-        },
-
-        tearDown: function () {
-            Y.one('#maincontent').remove(true);
-            window._singleton_privacy_banner = null;
-            delete window.LP;
-        },
-
-        test_library_exists: function () {
-            Y.Assert.isObject(Y.lp.app.banner.privacy,
-                "Could not locate the lp.app.banner.privacy module");
-        },
-        test_init: function () {
-            var banner = new Y.lp.app.banner.privacy.PrivacyBanner();
-            Y.Assert.areEqual(
-                "The information on this page is private.",
-                banner.get('notification_text'));
-            Y.Assert.areEqual(
-                '<span class="sprite notification-private"></span>',
-                banner.get('banner_icon'));
-        },
-
-        test_only_one_banner: function () {
-            // getPrivacyBanner only returns one banner.
-            var banner = Y.lp.app.banner.privacy.getPrivacyBanner();
-            Y.Assert.areEqual(1, Y.all('.global-notification').size());
-
-            var new_text = 'This is new text';
-            banner = Y.lp.app.banner.privacy.getPrivacyBanner(new_text);
-            Y.Assert.areEqual(1, Y.all('.global-notification').size());
-            var banner_node = Y.one('.global-notification');
-            Y.Assert.areEqual(
-                new_text,
-                Y.one('.global-notification').get('text'));
-        },
-
-        test_banner_with_custom_text: function () {
-            var banner = Y.lp.app.banner.privacy.getPrivacyBanner();
-            var new_text = 'New custom text';
-
-            Y.fire('privacy_banner:show', {
-                text: new_text
-            });
-            Y.Assert.areEqual(
-                new_text,
-                Y.one('.global-notification').get('text'));
-            Y.Assert.isTrue(banner.get('visible'),
-                            'Banner should be visible.');
-        },
-
-        test_banner_hide_event: function () {
-            var banner = Y.lp.app.banner.privacy.getPrivacyBanner();
-            var new_text = 'New custom text';
-
-            Y.fire('privacy_banner:show', {
-                text: new_text
-            });
-            Y.fire('privacy_banner:hide');
-            Y.Assert.isFalse(banner.get('visible'),
-                             'Banner should not be visible.');
-        },
-
-        test_info_type_private_event: function () {
-            var banner = Y.lp.app.banner.privacy.getPrivacyBanner();
-            var body = Y.one('body');
-            var msg = 'Some private message';
-            Y.fire('information_type:is_private', {
-                text: msg,
-                value: 'PROPRIETARY'
-            });
-            Y.Assert.areEqual(
-                msg,
-                Y.one('.global-notification').get('text'));
-            Y.Assert.isTrue(body.hasClass('private'),
-                            'Body should be private');
-            Y.Assert.isTrue(banner.get('visible'),
-                            'Banner should be visible.');
-        },
-
-        test_info_type_public_event: function () {
-            var banner = Y.lp.app.banner.privacy.getPrivacyBanner();
-            var new_text = 'New custom text';
-
-            Y.fire('privacy_banner:show', {
-                text: new_text
-            });
-            Y.fire('information_type:is_public');
-            var body = Y.one('body');
-            Y.Assert.isTrue(body.hasClass('public'), 'Body should be public');
-            Y.Assert.isFalse(banner.get('visible'),
-                             'Banner should not be visible.');
-        }
-    }));
-
-}, '0.1', {'requires': ['test', 'test-console', 'lp.app.banner.privacy']});

=== modified file 'lib/lp/app/javascript/information_type.js'
--- lib/lp/app/javascript/information_type.js	2012-10-04 14:17:23 +0000
+++ lib/lp/app/javascript/information_type.js	2012-11-12 16:13:23 +0000
@@ -44,6 +44,29 @@
     emitFacade: true
 });
 
+
+/**
+ * Provide some logic to check if this is a private inducing event. This could
+ * be due to a non-public information type or as security related information
+ * type/value.
+ */
+var is_private_event = function (value) {
+    var is_private = false;
+    if (ns.get_cache_data_from_key(value,
+                                  'value',
+                                  'is_private')) {
+
+        is_private = true;
+    }
+
+    if (value.indexOf('SECURITY') !== -1) {
+        is_private = true;
+    }
+
+    return is_private;
+};
+
+
 /**
  * Wire up a helper event so that if someone changes the event, we take care
  * of also firing any is_private/is_public event shortcuts others want to
@@ -58,9 +81,7 @@
         throw('Information type change event without new value');
     }
 
-    if (ns.get_cache_data_from_key(ev.value,
-                                  'value',
-                                  'is_private')) {
+    if (is_private_event(ev.value)) {
         Y.fire(ns.EV_ISPRIVATE, {
             text: ns.get_banner_text(ev.value),
             value: ev.value
@@ -155,16 +176,33 @@
 };
 
 ns.get_banner_text = function(value) {
-    var text_template = "This page contains {info_type} information.";
-    var info_type = ns.get_cache_data_from_key(value, 'value', 'name');
-    return Y.Lang.sub(text_template, {'info_type': info_type});
+    // Construct a different message for security related banner content.
+    var text;
+    if (value.indexOf('SECURITY') !== -1) {
+        var security_text = "This report will be private " +
+                            "because it is a security " +
+                            "vulnerability. You can " +
+                            "disclose it later.";
+        text = security_text;
+    } else {
+        var text_template = "This page contains {info_type} information.";
+        var info_type = ns.get_cache_data_from_key(value, 'value', 'name');
+        text = Y.Lang.sub(text_template, {'info_type': info_type});
+    }
+    return text;
 };
 
 ns.save_success = function(widget, context, value, subscribers_list,
                            result_data) {
     context.information_type =
         ns.get_cache_data_from_key(value, 'value', 'name');
-    ns.update_privacy_banner(value);
+
+    // Let the world know the information type has been updated. Allows
+    // banners to update.
+    Y.fire(ns.EV_CHANGE, {
+        value: value
+    });
+
     widget._showSucceeded();
     if (Y.Lang.isObject(result_data)) {
         var subscribers = result_data.subscription_data;
@@ -344,27 +382,7 @@
     }
 };
 
-/**
- * Update the privacy banner to display the specified information type value.
- *
- * @param value
- */
-ns.update_privacy_banner = function(value) {
-    var body = Y.one('body');
-    var privacy_banner = Y.lp.app.banner.privacy.getPrivacyBanner(
-            undefined, skip_animation);
-    var private_type = LP.cache.information_type_data[value].is_private;
-    if (private_type) {
-        body.replaceClass('public', 'private');
-        var banner_text = ns.get_banner_text(value);
-        privacy_banner.updateText(banner_text);
-        privacy_banner.show();
-    } else {
-        body.replaceClass('private', 'public');
-        privacy_banner.hide();
-    }
-};
 
 }, "0.1", {"requires": [
     "base", "oop", "node", "event", "io-base", "lp.mustache", "lp.app.choice",
-    "lp.bugs.bugtask_index", "lp.app.banner.privacy", "lp.ui.choiceedit"]});
+    "lp.bugs.bugtask_index", "lp.ui.choiceedit"]});

=== modified file 'lib/lp/app/javascript/tests/test_information_type.js'
--- lib/lp/app/javascript/tests/test_information_type.js	2012-10-26 10:00:20 +0000
+++ lib/lp/app/javascript/tests/test_information_type.js	2012-11-12 16:13:23 +0000
@@ -84,22 +84,6 @@
                 privacy_link, this.lp_client, LP.cache.bug, null, true);
         },
 
-        _shim_privacy_banner: function () {
-            var old_func = Y.lp.app.banner.privacy.getPrivacyBanner;
-            Y.lp.app.banner.privacy.getPrivacyBanner = function () {
-                return {
-                    show: function () { Y.fire('test:banner:show'); },
-                    hide: function () { Y.fire('test:banner:hide'); },
-                    updateText: function () { Y.fire('test:banner:update'); }
-                };
-            };
-            return old_func;
-        },
-
-        _unshim_privacy_banner: function (old_func) {
-            Y.lp.app.banner.privacy.getPrivacyBanner = old_func;
-        },
-
         test_library_exists: function () {
             Y.Assert.isObject(Y.lp.app.information_type,
                 "Cannot locate the lp.app.information_type module");
@@ -142,53 +126,9 @@
             ns.save_success = orig_save_success;
         },
 
-        // Setting a private type shows the privacy banner.
-        test_save_success_private: function() {
-            this.makeWidget();
-            var old_func = this._shim_privacy_banner();
-            var hide_flag = false;
-            var update_flag = false;
-            Y.on('test:banner:show', function() {
-                hide_flag = true;
-            });
-            Y.on('test:banner:update', function() {
-                update_flag = true;
-            });
-
-            ns.save_success(this.widget, LP.cache.bug,
-                                             'PROPRIETARY');
-            var body = Y.one('body');
-            Y.Assert.isTrue(body.hasClass('private'));
-            Y.Assert.isTrue(hide_flag);
-            Y.Assert.isTrue(update_flag);
-            Y.Assert.areEqual(
-                'Proprietary', LP.cache.bug.information_type);
-            this._unshim_privacy_banner(old_func);
-        },
-
-        // Setting a public type hides the privacy banner.
-        test_save_success_public: function() {
-            this.makeWidget();
-            var old_func = this._shim_privacy_banner();
-            var flag = false;
-            Y.on('test:banner:hide', function() {
-                flag = true;
-            });
-            var summary = Y.one('#information-type-summary');
-            summary.replaceClass('public', 'private');
-
-            ns.save_success(this.widget, 'PUBLIC', 'PUBLIC');
-            var body = Y.one('body');
-            Y.Assert.isTrue(body.hasClass('public'));
-            Y.Assert.isTrue(flag);
-            Y.Assert.areEqual('Public', LP.cache.bug.information_type);
-            this._unshim_privacy_banner(old_func);
-        },
-
         // A successful save updates the subscribers portlet.
         test_save_success_with_subscribers_data: function() {
             this.makeWidget();
-            var old_func = this._shim_privacy_banner();
             var flag = false;
             Y.on('test:banner:hide', function() {
                 flag = true;
@@ -216,7 +156,6 @@
             Y.Assert.isTrue(load_subscribers_called);
             Y.Assert.areEqual('value1', window.LP.cache.item1);
             Y.Assert.areEqual('value2', window.LP.cache.item2);
-            this._unshim_privacy_banner(old_func);
         },
 
         // A successful save updates the task actions.

=== modified file 'lib/lp/app/javascript/ui/assets/skins/sam/banner.css'
--- lib/lp/app/javascript/ui/assets/skins/sam/banner.css	2012-11-09 19:06:16 +0000
+++ lib/lp/app/javascript/ui/assets/skins/sam/banner.css	2012-11-12 16:13:23 +0000
@@ -27,7 +27,8 @@
     top: 94px;
 }
 
-/* If the container exists make sure we start out with the rest of the page
+/* If the container exists make sure we start out The information on this page
+ * is private.with the rest of the page
  * bumped down the starting distance to reduce flash effect
  */
 .beta_banner_container, .private_banner_container {

=== removed file 'lib/lp/app/templates/banner-macros.pt'
--- lib/lp/app/templates/banner-macros.pt	2012-05-30 13:59:24 +0000
+++ lib/lp/app/templates/banner-macros.pt	1970-01-01 00:00:00 +0000
@@ -1,56 +0,0 @@
-<macros
-  xmlns="http://www.w3.org/1999/xhtml";
-  xmlns:tal="http://xml.zope.org/namespaces/tal";
-  xmlns:metal="http://xml.zope.org/namespaces/metal";
-  xmlns:i18n="http://xml.zope.org/namespaces/i18n";
-  i18n:domain="launchpad"
-  tal:omit-tag=""
->
-
-<metal:privacy define-macro="privacy-banner">
-  <tal:show-banner condition="view/private">
-    <div class="yui3-widget yui3-banner yui3-privacybanner">
-      <div class="yui3-privacybanner-content">
-        <div class="global-notification">
-          <span class="sprite notification-private"></span>
-          <tal:info_type
-             define="info_type python: getattr(view, 'information_type', None)">
-            <span tal:condition="not: info_type" class="banner-text">
-              The information on this page is private.
-            </span>
-            <span tal:condition="info_type" class="banner-text">
-              <tal:text
-                content="string: This page contains ${info_type} information."/>
-            </span>
-          </tal:info_type>
-        </div>
-      </div>
-    </div>
-  </tal:show-banner>
-</metal:privacy>
-
-<metal:beta define-macro="beta-banner">
-  <tal:show-banner condition="view/beta_features">
-    <div class="yui3-widget yui3-banner yui3-betabanner">
-      <div class="yui3-betabanner-content">
-        <div class="global-notification">
-          <span class="beta-warning">BETA!</span>
-          <span class="banner-text">
-            Some parts of this page are in beta:&nbsp;
-            <span class="beta-feature">
-              <tal:features
-                repeat="feature view/beta_features">
-                <tal:feature replace="feature/title" />
-                <tal:link condition="feature/url">
-                  (<a tal:attributes="href feature/url" class="info-link">read more</a>)
-                </tal:link>
-              </tal:features>
-            </span>
-          </span>
-        </div>
-      </div>
-    </div>
-  </tal:show-banner>
-</metal:beta>
-
-</macros>

=== modified file 'lib/lp/app/templates/base-layout-macros.pt'
--- lib/lp/app/templates/base-layout-macros.pt	2012-08-13 17:49:31 +0000
+++ lib/lp/app/templates/base-layout-macros.pt	2012-11-12 16:13:23 +0000
@@ -163,19 +163,17 @@
     <script id="base-layout-load-scripts" type="text/javascript">
         //<![CDATA[
         LPJS.use('base', 'node', 'console', 'event',
-            'oop', 'lp', 'lp.app.banner.privacy',
-            'lp.app.banner.beta', 'lp.app.foldables','lp.app.sorttable',
+            'oop', 'lp', 'lp.app.foldables','lp.app.sorttable',
             'lp.app.inlinehelp', 'lp.app.links', 'lp.app.longpoll',
             'lp.bugs.bugtask_index', 'lp.bugs.subscribers',
             'lp.app.ellipsis', 'lp.code.branchmergeproposal.diff',
+            'lp.views.global',
              function(Y) {
 
             Y.on("domready", function () {
-                if (Y.one(document.body).hasClass('private')) {
-                    banner = Y.lp.app.banner.privacy.getPrivacyBanner();
-                    banner.show();
-                }
-                Y.lp.app.banner.beta.show_beta_if_needed();
+                var global_view = new Y.lp.views.Global();
+                global_view.render();
+
                 Y.lp.app.sorttable.SortTable.init();
                 Y.lp.app.inlinehelp.init_help();
                 Y.lp.activate_collapsibles();

=== modified file 'lib/lp/app/templates/base-layout.pt'
--- lib/lp/app/templates/base-layout.pt	2012-05-18 22:04:13 +0000
+++ lib/lp/app/templates/base-layout.pt	2012-11-12 16:13:23 +0000
@@ -64,6 +64,16 @@
       ${view/macro:pagetype}
       ${view/fmt:global-css}
       yui3-skin-sam">
+          <tal:beta-banner condition="view/beta_features">
+            <div class="beta_banner_container">
+                <noscript ><strong>Some parts of this page are in beta.</strong></noscript>
+            </div>
+          </tal:beta-banner>
+          <tal:private-banner condition="view/private">
+            <div class="private_banner_container">
+                <noscript><strong>The information on this page is private.</strong></noscript>
+            </div>
+          </tal:private-banner>
         <script type="text/javascript"
           tal:condition="python: is_lpnet">
           var _gaq = _gaq || [];
@@ -97,10 +107,6 @@
       <div class="yui-t4"
         tal:omit-tag="not: view/macro:pagehas/portlets">
         <div id="maincontent" class="yui-main">
-          <metal:privacy-banner
-            use-macro="view/@@+banner-macros/beta-banner"/>
-          <metal:privacy-banner
-            use-macro="view/@@+banner-macros/privacy-banner"/>
           <div class="yui-b"
             tal:attributes="
               lang view/lang|default_language|default;

=== modified file 'lib/lp/blueprints/javascript/addspec.js'
--- lib/lp/blueprints/javascript/addspec.js	2012-10-15 16:01:38 +0000
+++ lib/lp/blueprints/javascript/addspec.js	2012-11-12 16:13:23 +0000
@@ -10,11 +10,24 @@
 
 var namespace = Y.namespace('lp.blueprints.addspec');
 var to_choice = Y.lp.app.information_type.cache_to_choicesource;
+var info_type = Y.lp.app.information_type;
 
 namespace.set_up = function () {
     var choice_data = to_choice(LP.cache.information_type_data);
-    Y.lp.app.choice.addPopupChoiceForRadioButtons('information_type',
-                                                  choice_data);
+    var widget = Y.lp.app.choice.addPopupChoiceForRadioButtons(
+        'information_type',
+        choice_data);
+
+    // We are not doing ajax saves of the information type so we need to
+    // disable the flash on save for the widget.
+    widget.set('flashEnabled', false);
+
+    // Make sure we catch changes to the information type.
+    widget.on('save', function (ev) {
+        Y.fire(info_type.EV_CHANGE, {
+            value: ev.target.get('value')
+        });
+    });
 };
 
 }, "0.1", {"requires": ['lp.app.information_type', 'lp.app.choice']});

=== modified file 'lib/lp/bugs/javascript/bugtask_index.js'
--- lib/lp/bugs/javascript/bugtask_index.js	2012-10-11 04:57:59 +0000
+++ lib/lp/bugs/javascript/bugtask_index.js	2012-11-12 16:13:23 +0000
@@ -1131,6 +1131,5 @@
                         "lp.app.information_type",
                         "lp.app.widgets.expander", "lp.client", "escape",
                         "lp.client.plugins", "lp.app.errors",
-                        "lp.app.banner.privacy",
                         "lp.app.confirmationoverlay",
                         "lp.bugs.duplicates"]});

=== modified file 'lib/lp/bugs/javascript/filebug.js'
--- lib/lp/bugs/javascript/filebug.js	2012-09-25 19:15:04 +0000
+++ lib/lp/bugs/javascript/filebug.js	2012-11-12 16:13:23 +0000
@@ -9,6 +9,7 @@
 YUI.add('lp.bugs.filebug', function(Y) {
 
 var namespace = Y.namespace('lp.bugs.filebug');
+var info_type = Y.lp.app.information_type;
 
 // For tests.
 var skip_animation;
@@ -28,13 +29,40 @@
         if (Y.Lang.isValue(search_button )) {
             search_button.set('value', 'Check again');
         }
+        setup_plain_inputs();
         set_default_privacy_banner();
-        setup_information_type();
         setup_security_related();
         setupChoiceWidgets();
     }
 };
 
+
+/**
+ * If there are not choice widgets, but radio buttons, then we should watch
+ * those radio buttons for change to make sure we fire the information type
+ * change events.
+ */
+var setup_plain_inputs = function () {
+   var itypes_table = Y.one('.radio-button-widget');
+
+   if (itypes_table) {
+       itypes_table.delegate('change', function(ev) {
+           Y.fire(info_type.EV_CHANGE, {
+               value: this.get('value')
+           });
+       }, "input[name='field.information_type']");
+   }
+};
+
+/**
+ * Due to the privacy setting of the project/bugs we might only allow a
+ * non-public information type. In this case we need to go ahead and let the
+ * user know it's going to be private.
+ *
+ * This is used by the security checks. If the issue is unmade/not security
+ * related then we need to check the normal default behavior to make sure we
+ * show the correct banner.
+ */
 var set_default_privacy_banner = function() {
     var itypes_table = Y.one('.radio-button-widget');
     var val = null;
@@ -48,47 +76,12 @@
     if (LP.cache.bug_private_by_default) {
         var filebug_privacy_text = "This report will be private. " +
             "You can disclose it later.";
-        update_privacy_banner(true, filebug_privacy_text);
-    } else {
-        update_banner_from_information_type(val);
-    }
-};
-
-var update_privacy_banner = function(show, banner_text) {
-    var banner = Y.lp.app.banner.privacy.getPrivacyBanner(
-        banner_text, skip_animation);
-    if (show) {
-        banner.show();
-    } else {
-        banner.hide();
-    }
-};
-
-var get_new_banner_text = function(value) {
-    var cache = LP.cache.information_type_data;
-    var text_template = "This report contains {info_type} information." +
-        " You can change the information type later.";
-    return Y.Lang.substitute(text_template, {
-        'info_type': cache[value].name
-    });
-};
-
-var update_banner_from_information_type = function(value) {
-    var banner_text = get_new_banner_text(value);
-    var is_private = LP.cache.information_type_data[value].is_private;
-    update_privacy_banner(is_private, banner_text);
-};
-
-var setup_information_type = function() {
-    var itypes_table = Y.one('.radio-button-widget');
-    if (!Y.Lang.isValue(itypes_table)) {
-        return;
-    }
-
-
-    itypes_table.delegate('change', function() {
-        update_banner_from_information_type(this.get('value'));
-    }, "input[name='field.information_type']");
+
+        Y.fire(info_type.EV_ISPRIVATE, {
+            text: filebug_privacy_text,
+            value: val
+        });
+    }
 };
 
 
@@ -100,8 +93,25 @@
     var information_helpers = Y.lp.app.information_type;
     var choices = information_helpers.cache_to_choicesource(cache);
 
-    Y.lp.app.choice.addPopupChoiceForRadioButtons(
+    var information_type = Y.lp.app.choice.addPopupChoiceForRadioButtons(
         'information_type', choices, true);
+
+    // When dealing with legacy inputs the information type could have not
+    // been created and we get back a null value.
+    if (information_type) {
+        // We are not doing ajax saves of the information type so we need to
+        // disable the flash on save for the widget.
+        information_type.set('flashEnabled', false);
+
+        // When the information type widget changes we need to let the
+        // information type module know so it can process the change and
+        // update things like banners displayed.
+        information_type.on('save', function (ev) {
+            Y.fire(info_type.EV_CHANGE, {
+                value: ev.target.get('value')
+            });
+        });
+    }
 };
 
 var setup_security_related = function() {
@@ -116,8 +126,19 @@
     security_related.on('change', function() {
         var checked = security_related.get('checked');
         if (checked) {
-            update_privacy_banner(true, notification_text);
+            // XXX: This should use the correct information type based on the
+            // project default. We use PRIVATESECURITY because it'll get the
+            // right banner shown.
+            Y.fire(info_type.EV_ISPRIVATE, {
+                text: notification_text,
+                value: 'PRIVATESECURITY'
+            });
         } else {
+            Y.fire(info_type.EV_ISPUBLIC, {
+                value: 'PUBLIC'
+            });
+            // Check with the default settings if we should add the privacy
+            // banner back because it's the default of the current project.
             set_default_privacy_banner();
         }
     });
@@ -127,5 +148,5 @@
 
 }, "0.1", {"requires": [
     "base", "node", "event", "node-event-delegate", "lp.ui.choiceedit",
-    "lp.app.banner.privacy", "lp.app.choice", "lp.app.information_type",
+    "lp.ui.banner", "lp.app.choice", "lp.app.information_type",
     "lp.bugs.filebug_dupefinder"]});

=== modified file 'lib/lp/bugs/javascript/tests/test_filebug.js'
--- lib/lp/bugs/javascript/tests/test_filebug.js	2012-10-26 10:00:20 +0000
+++ lib/lp/bugs/javascript/tests/test_filebug.js	2012-11-12 16:13:23 +0000
@@ -3,6 +3,8 @@
 YUI.add('lp.bugs.filebug.test', function (Y) {
 
     var tests = Y.namespace('lp.bugs.filebug.test');
+    var info_type = Y.lp.app.information_type;
+
     tests.suite = new Y.Test.Suite(
         'lp.bugs.filebug Tests');
 
@@ -73,96 +75,136 @@
 
         // Filing a public bug does not show the privacy banner.
         test_setup_filebug_public: function () {
+            // Watch out for the event that showing a privacy banner would
+            // fire.
+            var fired = false;
+            var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) {
+                fired = true;
+            });
             this.setupForm(true);
-            var banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNotNull(banner_hidden);
+            Y.Assert.isFalse(fired);
+            ev.detach();
         },
 
         // Filing a bug for a project with private bugs shows the privacy
         // banner.
         test_setup_filebug_private: function () {
+            var fired = false;
+            var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) {
+                fired = true;
+                Y.Assert.areEqual(
+                    'This report will be private. ' +
+                    'You can disclose it later.', ev.text);
+            });
+
             window.LP.cache.bug_private_by_default = true;
             this.setupForm(true);
-            var banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNull(banner_hidden);
-            var banner_text = Y.one('.banner-text').get('text');
-            Y.Assert.areEqual(
-                'This report will be private. ' +
-                'You can disclose it later.', banner_text);
+            Y.Assert.isTrue(fired);
+            ev.detach();
         },
 
         // Selecting a private info type using the legacy radio buttons
         // turns on the privacy banner.
         test_legacy_select_private_info_type: function () {
+            var fired = false;
+            var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) {
+                fired = true;
+                Y.Assert.areEqual(
+                    'This report will be private because it is a security ' +
+                    'vulnerability. You can disclose it later.', ev.text);
+            });
+
             this.setupForm(true);
-            var banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNotNull(banner_hidden);
+            Y.Assert.isFalse(fired);
+
             Y.one('[id="field.information_type.2"]').simulate('click');
-            banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNull(banner_hidden);
-            var banner_text = Y.one('.banner-text').get('text');
-            Y.Assert.areEqual(
-                'This report contains Private Security information. ' +
-                'You can change the information type later.', banner_text);
+            // And the event should be fired and caught.
+            Y.Assert.isTrue(fired);
+            ev.detach();
         },
 
         // Selecting a public info type using the legacy radio buttons
         // turns off the privacy banner.
         test_legacy_select_public_info_type: function () {
+            var fired = false;
+            var ev = Y.on(info_type.EV_ISPUBLIC, function (ev) {
+                fired = true;
+            });
+
             window.LP.cache.bug_private_by_default = true;
             this.setupForm(true);
+
+            // This will fire ISPRIVATE and a banner shows.
             Y.one('[id="field.information_type.2"]').simulate('click');
-            var banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNull(banner_hidden);
+
+            // The second one will fire ISPUBLIC and the banner disappears.
             Y.one('[id="field.information_type.0"]').simulate('click');
-            banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNotNull(banner_hidden);
+            Y.Assert.isTrue(fired);
         },
 
         // When non bug supervisors select a security related bug the privacy
         // banner is turned on.
         test_select_security_related: function () {
+            var fired = false;
+            var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) {
+                fired = true;
+                Y.Assert.areEqual(
+                    'This report will be private because it is a security ' +
+                    'vulnerability. You can disclose it later.', ev.text);
+            });
+
             this.setupForm(false);
-            var banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNotNull(banner_hidden);
+            Y.Assert.isFalse(fired);
+
             Y.one('[id="field.security_related"]').simulate('click');
-            banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNull(banner_hidden);
-            var banner_text = Y.one('.banner-text').get('text');
-            Y.Assert.areEqual(
-                'This report will be private because it is a ' +
-                'security vulnerability. You can disclose it later.',
-                banner_text);
+            // And the event should be fired and caught.
+            Y.Assert.isTrue(fired);
+            ev.detach();
         },
 
         // When non bug supervisors unselect a security related bug the privacy
         // banner is turned off.
         test_unselect_security_related: function () {
+            var fired = false;
+            var ev = Y.on(info_type.EV_ISPUBLIC, function (ev) {
+                fired = true;
+            });
+
             this.setupForm(false);
-            Y.one('[id="field.security_related"]').simulate('click');
-            var banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNull(banner_hidden);
-            Y.one('[id="field.security_related"]').simulate('click');
-            banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNotNull(banner_hidden);
+
+            Y.one('[id="field.security_related"]').simulate('click');
+            Y.Assert.isFalse(fired);
+
+            Y.one('[id="field.security_related"]').simulate('click');
+            Y.Assert.isTrue(fired);
         },
 
         // When non bug supervisors unselect a security related bug the privacy
         // banner remains on for private_by_default bugs.
         test_unselect_security_related_default_private: function () {
             window.LP.cache.bug_private_by_default = true;
+            var public = 0;
+            var private = 0;
+            var ev = Y.on(info_type.EV_ISPUBLIC, function (ev) {
+                public = public + 1;
+            });
+
+            var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) {
+                private = private + 1;
+            });
+
+
             this.setupForm(false);
-            Y.one('[id="field.security_related"]').simulate('click');
-            var banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNull(banner_hidden);
-            Y.one('[id="field.security_related"]').simulate('click');
-            banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNull(banner_hidden);
-            var banner_text = Y.one('.banner-text').get('text');
+            Y.Assert.areEqual(1, private, 'Private is the default state.');
+
+            Y.one('[id="field.security_related"]').simulate('click');
+            Y.Assert.areEqual(2, private, 'The first click fires ISPRIVATE');
+
+            Y.one('[id="field.security_related"]').simulate('click');
+            Y.Assert.areEqual(1, public, 'The second click fires ISPUBLIC');
             Y.Assert.areEqual(
-                'This report will be private. ' +
-                'You can disclose it later.',
-                banner_text);
+                3, private,
+                "It also fires an ISPRIVATE since that's the default state.");
         },
 
         // The dupe finder functionality is setup.
@@ -280,44 +322,59 @@
         // Selecting a private info type using the popup choice widget
         // turns on the privacy banner.
         test_select_private_info_type: function () {
+            var fired = false;
+            var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) {
+                fired = true;
+                Y.Assert.areEqual(
+                    'This report contains Private information. ' +
+                    'You can change the information type later.', ev.text);
+            });
+
             this.setupForm(true);
-            var banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNotNull(banner_hidden);
+            Y.Assert.isFalse(fired);
+
             var information_type_popup = Y.one('.information_type-content a');
             information_type_popup.simulate('click');
             var information_type_choice = Y.one(
                 '.yui3-ichoicelist-content a[href="#USERDATA"]');
             information_type_choice.simulate('click');
-            banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNull(banner_hidden);
-            var banner_text = Y.one('.banner-text').get('text');
-            Y.Assert.areEqual(
-                'This report contains Private information. ' +
-                'You can change the information type later.', banner_text);
+
+            // And the event should be fired and caught.
+            Y.Assert.isTrue(fired);
+            ev.detach();
         },
 
         // Selecting a public info type using the popup choice widget
         // turns off the privacy banner.
         test_select_public_info_type: function () {
+            var fired = false;
+            var ev = Y.on(info_type.EV_ISPUBLIC, function (ev) {
+                fired = true;
+            });
+
             window.LP.cache.bug_private_by_default = true;
             this.setupForm(true);
+
+            // This will fire ISPRIVATE and a banner shows.
             var information_type_popup = Y.one('.information_type-content a');
             information_type_popup.simulate('click');
             var information_type_choice = Y.one(
                 '.yui3-ichoicelist-content a[href="#USERDATA"]');
             information_type_choice.simulate('click');
-            var banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNull(banner_hidden);
+
+            // The second one will fire ISPUBLIC and the banner disappears.
             information_type_popup.simulate('click');
             information_type_choice = Y.one(
                 '.yui3-ichoicelist-content a[href="#PUBLIC"]');
             information_type_choice.simulate('click');
-            banner_hidden = Y.one('.yui3-privacybanner-hidden');
-            Y.Assert.isNotNull(banner_hidden);
+
+            Y.Assert.isTrue(fired);
         }
     }));
 
-}, '0.1', {'requires': ['test', 'test-console', 'event', 'node-event-simulate',
-        'lp.app.banner.privacy', 'lp.app.choice',
-        'lp.bugs.filebug_dupefinder', 'lp.bugs.filebug'
-        ]});
+}, '0.1', {
+    requires: [
+        'test', 'test-console', 'event', 'node-event-simulate',
+        'lp.app.banner.privacy', 'lp.app.choice', 'lp.app.information_type',
+        'lp.bugs.filebug_dupefinder', 'lp.bugs.filebug' ]
+});

=== modified file 'lib/lp/code/javascript/branch.information_type_choice.js'
--- lib/lp/code/javascript/branch.information_type_choice.js	2012-09-21 15:39:22 +0000
+++ lib/lp/code/javascript/branch.information_type_choice.js	2012-11-12 16:13:23 +0000
@@ -105,7 +105,9 @@
         LP.cache.context.information_type =
             information_type.get_cache_data_from_key(
                     value, 'value', 'name');
-        information_type.update_privacy_banner(value);
+        Y.fire(information_type.EV_CHANGE, {
+            value: value
+        });
         if (this.get('use_animation')) {
             this.information_type_edit._showSucceeded();
         }
@@ -119,7 +121,8 @@
     }
 });
 
-}, "0.1", {"requires": ["base", "oop", "node", "event", "io-base",
-                        "lp.ui.choiceedit", "lp.app.banner.privacy",
-                        "lp.app.errors", "lp.app.choice",
-                        "lp.app.information_type"]});
+}, "0.1", {
+    requires: [
+        "base", "oop", "node", "event", "io-base", "lp.ui.choiceedit",
+        "lp.app.errors", "lp.app.choice", "lp.app.information_type"]
+});

=== modified file 'lib/lp/code/javascript/tests/test_information_type_choice.js'
--- lib/lp/code/javascript/tests/test_information_type_choice.js	2012-10-26 10:00:20 +0000
+++ lib/lp/code/javascript/tests/test_information_type_choice.js	2012-11-12 16:13:23 +0000
@@ -4,6 +4,8 @@
 
     var tests = Y.namespace('lp.code.branch.information_type_choice.test');
     var ns = Y.lp.code.branch.information_type_choice;
+    var info_type = Y.lp.app.information_type;
+
     tests.suite = new Y.Test.Suite(
             'lp.code.branch.information_type_choice Tests');
 
@@ -62,22 +64,6 @@
             this.widget.render();
         },
 
-        _shim_privacy_banner: function () {
-            var old_func = Y.lp.app.banner.privacy.getPrivacyBanner;
-            Y.lp.app.banner.privacy.getPrivacyBanner = function () {
-                return {
-                    show: function () { Y.fire('test:banner:show'); },
-                    hide: function () { Y.fire('test:banner:hide'); },
-                    updateText: function () { Y.fire('test:banner:update'); }
-                };
-            };
-            return old_func;
-        },
-
-        _unshim_privacy_banner: function (old_func) {
-            Y.lp.app.banner.privacy.getPrivacyBanner = old_func;
-        },
-
         test_library_exists: function () {
             Y.Assert.isObject(Y.lp.code.branch.information_type_choice,
                 "Cannot locate the " +
@@ -118,44 +104,31 @@
 
         // Setting a private type shows the privacy banner.
         test_information_type_save_success_private: function() {
+            var fired = false;
+            Y.on(info_type.EV_ISPRIVATE, function (ev) {
+                fired = true;
+            });
+
             this.makeWidget();
-            var old_func = this._shim_privacy_banner();
-            var hide_flag = false;
-            var update_flag = false;
-            Y.on('test:banner:show', function() {
-                hide_flag = true;
-            });
-            Y.on('test:banner:update', function() {
-                update_flag = true;
-            });
 
             this.widget._information_type_save_success('PROPRIETARY');
-            var body = Y.one('body');
-            Y.Assert.isTrue(body.hasClass('private'));
-            Y.Assert.isTrue(hide_flag);
-            Y.Assert.isTrue(update_flag);
+            Y.Assert.isTrue(fired);
             Y.Assert.areEqual(
                 'Proprietary', LP.cache.context.information_type);
-            this._unshim_privacy_banner(old_func);
         },
 
         // Setting a private type hides the privacy banner.
         test_information_type_save_success_public: function() {
+            var fired = false;
+            Y.on(info_type.EV_ISPUBLIC, function (ev) {
+                fired = true;
+            });
+
             this.makeWidget();
-            var old_func = this._shim_privacy_banner();
-            var flag = false;
-            Y.on('test:banner:hide', function() {
-                flag = true;
-            });
-            var summary = Y.one('#information-type-summary');
-            summary.replaceClass('public', 'private');
 
             this.widget._information_type_save_success('PUBLIC');
-            var body = Y.one('body');
-            Y.Assert.isTrue(body.hasClass('public'));
-            Y.Assert.isTrue(flag);
+            Y.Assert.isTrue(fired);
             Y.Assert.areEqual('Public', LP.cache.context.information_type);
-            this._unshim_privacy_banner(old_func);
         },
 
         // Test error handling when a save fails.

=== modified file 'lib/lp/registry/javascript/product_views.js'
--- lib/lp/registry/javascript/product_views.js	2012-10-26 06:59:14 +0000
+++ lib/lp/registry/javascript/product_views.js	2012-11-12 16:13:23 +0000
@@ -95,6 +95,9 @@
          */
         information_type_change: function (value) {
             toggle_license_field(value);
+            Y.fire(info_type.EV_CHANGE, {
+                value: value
+            });
         },
 
         /**
@@ -349,6 +352,9 @@
          */
         information_type_change: function (value) {
             toggle_license_field(value);
+            Y.fire(info_type.EV_CHANGE, {
+                value: value
+            });
             var driver_cont =
                 Y.one('input[name="field.driver"]').ancestor('td');
             var bug_super_cont =

=== modified file 'lib/lp/services/features/flags.py'
--- lib/lp/services/features/flags.py	2012-11-08 06:06:22 +0000
+++ lib/lp/services/features/flags.py	2012-11-12 16:13:23 +0000
@@ -236,7 +236,7 @@
      'boolean',
      'If true, enabled access to private project registration features.',
      'disabled',
-     '',
+     'Allow registering a non-public project.',
      'http://blog.launchpad.net/general/private-projects-beta'),
     ('disclosure.private_project.traversal_override',
      'boolean',


Follow ups