summaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authordroger@chromium.org <droger@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-18 15:09:41 +0000
committerdroger@chromium.org <droger@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-18 15:09:41 +0000
commit051655ad35d7b3c442ba1df8880da91123bf9bc9 (patch)
tree25d7d1fa8cb99621c927f1deb2707e1d7b3d0fc6 /components
parent8e37bf2199e37e270163eb407fab789c4ba77846 (diff)
downloadchromium_src-051655ad35d7b3c442ba1df8880da91123bf9bc9.zip
chromium_src-051655ad35d7b3c442ba1df8880da91123bf9bc9.tar.gz
chromium_src-051655ad35d7b3c442ba1df8880da91123bf9bc9.tar.bz2
Move Infobars core files to the Infobars component
This CL sets up the directory structure for the Infobars component and the infobars_core target. It also does a simple code move to the compoonent. This CL does not move ConfirmInfoBarDelegate because it still has a dependency on chrome/ (for strings). BUG=354379 TBR=sky, reed Review URL: https://codereview.chromium.org/240193003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@264792 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components')
-rw-r--r--components/OWNERS2
-rw-r--r--components/components.gyp1
-rw-r--r--components/infobars.gypi32
-rw-r--r--components/infobars/DEPS8
-rw-r--r--components/infobars/OWNERS1
-rw-r--r--components/infobars/README7
-rw-r--r--components/infobars/core/infobar.cc179
-rw-r--r--components/infobars/core/infobar.h153
-rw-r--r--components/infobars/core/infobar_container.cc178
-rw-r--r--components/infobars/core/infobar_container.h137
-rw-r--r--components/infobars/core/infobar_delegate.cc111
-rw-r--r--components/infobars/core/infobar_delegate.h148
-rw-r--r--components/infobars/core/infobar_manager.cc141
-rw-r--r--components/infobars/core/infobar_manager.h124
-rw-r--r--components/infobars/core/infobars_switches.cc14
-rw-r--r--components/infobars/core/infobars_switches.h16
16 files changed, 1252 insertions, 0 deletions
diff --git a/components/OWNERS b/components/OWNERS
index 5024899..6f9da6d 100644
--- a/components/OWNERS
+++ b/components/OWNERS
@@ -43,6 +43,8 @@ per-file favicon*=blundell@chromium.org
# Temporary for the duration of the favicon componentization.
per-file favicon*=droger@chromium.org
+per-file infobars.gypi=pkasting@chromium.org
+
per-file json_schema.gypi=asargent@chromium.org
per-file json_schema.gypi=calamity@chromium.org
per-file json_schema.gypi=kalman@chromium.org
diff --git a/components/components.gyp b/components/components.gyp
index cb2052a..aa4c7ac 100644
--- a/components/components.gyp
+++ b/components/components.gyp
@@ -21,6 +21,7 @@
'domain_reliability.gypi',
'favicon.gypi',
'favicon_base.gypi',
+ 'infobars.gypi',
'json_schema.gypi',
'keyed_service.gypi',
'language_usage_metrics.gypi',
diff --git a/components/infobars.gypi b/components/infobars.gypi
new file mode 100644
index 0000000..7ca15b5
--- /dev/null
+++ b/components/infobars.gypi
@@ -0,0 +1,32 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'infobars_core',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '..',
+ ],
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../skia/skia.gyp:skia',
+ '../ui/gfx/gfx.gyp:gfx',
+ ],
+ 'sources': [
+ 'infobars/core/infobar.cc',
+ 'infobars/core/infobar.h',
+ 'infobars/core/infobar_container.cc',
+ 'infobars/core/infobar_container.h',
+ 'infobars/core/infobar_delegate.cc',
+ 'infobars/core/infobar_delegate.h',
+ 'infobars/core/infobar_manager.cc',
+ 'infobars/core/infobar_manager.h',
+ 'infobars/core/infobars_switches.cc',
+ 'infobars/core/infobars_switches.h',
+ ],
+ },
+ ],
+}
diff --git a/components/infobars/DEPS b/components/infobars/DEPS
new file mode 100644
index 0000000..4f66f6c
--- /dev/null
+++ b/components/infobars/DEPS
@@ -0,0 +1,8 @@
+include_rules = [
+ # Infobars is a layered component; subdirectories must explicitly introduce
+ # the ability to use the content layer as appropriate.
+ "-content",
+
+ "+ui",
+ "+third_party/skia"
+]
diff --git a/components/infobars/OWNERS b/components/infobars/OWNERS
new file mode 100644
index 0000000..bf426d6
--- /dev/null
+++ b/components/infobars/OWNERS
@@ -0,0 +1 @@
+pkasting@chromium.org
diff --git a/components/infobars/README b/components/infobars/README
new file mode 100644
index 0000000..8b736f1
--- /dev/null
+++ b/components/infobars/README
@@ -0,0 +1,7 @@
+- Infobars is a layered component
+(https://sites.google.com/a/chromium.org/dev/developers/design-documents/layered-components-design)
+to enable it to be shared cleanly on iOS.
+
+Directory structure:
+core/: shared code that does not depend on src/content/
+content/: Driver for the shared code based on the content layer.
diff --git a/components/infobars/core/infobar.cc b/components/infobars/core/infobar.cc
new file mode 100644
index 0000000..1ddfffd
--- /dev/null
+++ b/components/infobars/core/infobar.cc
@@ -0,0 +1,179 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/infobars/core/infobar.h"
+
+#include <cmath>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "components/infobars/core/infobar_container.h"
+#include "components/infobars/core/infobar_manager.h"
+#include "ui/gfx/animation/slide_animation.h"
+
+namespace infobars {
+
+InfoBar::InfoBar(scoped_ptr<InfoBarDelegate> delegate)
+ : owner_(NULL),
+ delegate_(delegate.Pass()),
+ container_(NULL),
+ animation_(this),
+ arrow_height_(0),
+ arrow_target_height_(kDefaultArrowTargetHeight),
+ arrow_half_width_(0),
+ bar_height_(0),
+ bar_target_height_(kDefaultBarTargetHeight) {
+ DCHECK(delegate_ != NULL);
+ animation_.SetTweenType(gfx::Tween::LINEAR);
+ delegate_->set_infobar(this);
+}
+
+InfoBar::~InfoBar() {
+ DCHECK(!owner_);
+}
+
+// static
+SkColor InfoBar::GetTopColor(InfoBarDelegate::Type infobar_type) {
+ static const SkColor kWarningBackgroundColorTop =
+ SkColorSetRGB(255, 242, 183); // Yellow
+ static const SkColor kPageActionBackgroundColorTop =
+ SkColorSetRGB(237, 237, 237); // Gray
+ return (infobar_type == InfoBarDelegate::WARNING_TYPE) ?
+ kWarningBackgroundColorTop : kPageActionBackgroundColorTop;
+}
+
+// static
+SkColor InfoBar::GetBottomColor(InfoBarDelegate::Type infobar_type) {
+ static const SkColor kWarningBackgroundColorBottom =
+ SkColorSetRGB(250, 230, 145); // Yellow
+ static const SkColor kPageActionBackgroundColorBottom =
+ SkColorSetRGB(217, 217, 217); // Gray
+ return (infobar_type == InfoBarDelegate::WARNING_TYPE) ?
+ kWarningBackgroundColorBottom : kPageActionBackgroundColorBottom;
+}
+
+void InfoBar::SetOwner(InfoBarManager* owner) {
+ DCHECK(!owner_);
+ owner_ = owner;
+ delegate_->StoreActiveEntryUniqueID();
+ PlatformSpecificSetOwner();
+}
+
+void InfoBar::Show(bool animate) {
+ PlatformSpecificShow(animate);
+ if (animate) {
+ animation_.Show();
+ } else {
+ animation_.Reset(1.0);
+ RecalculateHeights(true);
+ }
+}
+
+void InfoBar::Hide(bool animate) {
+ PlatformSpecificHide(animate);
+ if (animate) {
+ animation_.Hide();
+ } else {
+ animation_.Reset(0.0);
+ // We want to remove ourselves from the container immediately even if we
+ // still have an owner, which MaybeDelete() won't do.
+ DCHECK(container_);
+ container_->RemoveInfoBar(this);
+ MaybeDelete(); // Necessary if the infobar was already closing.
+ }
+}
+
+void InfoBar::SetArrowTargetHeight(int height) {
+ DCHECK_LE(height, kMaximumArrowTargetHeight);
+ // Once the closing animation starts, we ignore further requests to change the
+ // target height.
+ if ((arrow_target_height_ != height) && !animation_.IsClosing()) {
+ arrow_target_height_ = height;
+ RecalculateHeights(false);
+ }
+}
+
+void InfoBar::CloseSoon() {
+ owner_ = NULL;
+ PlatformSpecificOnCloseSoon();
+ MaybeDelete();
+}
+
+void InfoBar::RemoveSelf() {
+ if (owner_)
+ owner_->RemoveInfoBar(this);
+}
+
+void InfoBar::SetBarTargetHeight(int height) {
+ if (bar_target_height_ != height) {
+ bar_target_height_ = height;
+ RecalculateHeights(false);
+ }
+}
+
+void InfoBar::AnimationProgressed(const gfx::Animation* animation) {
+ RecalculateHeights(false);
+}
+
+void InfoBar::AnimationEnded(const gfx::Animation* animation) {
+ // When the animation ends, we must ensure the container is notified even if
+ // the heights haven't changed, lest it never get an "animation finished"
+ // notification. (If the browser doesn't get this notification, it will not
+ // bother to re-layout the content area for the new infobar size.)
+ RecalculateHeights(true);
+ MaybeDelete();
+}
+
+void InfoBar::RecalculateHeights(bool force_notify) {
+ int old_arrow_height = arrow_height_;
+ int old_bar_height = bar_height_;
+
+ // Find the desired arrow height/half-width. The arrow area is
+ // |arrow_height_| * |arrow_half_width_|. When the bar is opening or closing,
+ // scaling each of these with the square root of the animation value causes a
+ // linear animation of the area, which matches the perception of the animation
+ // of the bar portion.
+ double scale_factor = sqrt(animation_.GetCurrentValue());
+ arrow_height_ = static_cast<int>(arrow_target_height_ * scale_factor);
+ if (animation_.is_animating()) {
+ arrow_half_width_ = static_cast<int>(std::min(arrow_target_height_,
+ kMaximumArrowTargetHalfWidth) * scale_factor);
+ } else {
+ // When the infobar is not animating (i.e. fully open), we set the
+ // half-width to be proportionally the same distance between its default and
+ // maximum values as the height is between its.
+ arrow_half_width_ = kDefaultArrowTargetHalfWidth +
+ ((kMaximumArrowTargetHalfWidth - kDefaultArrowTargetHalfWidth) *
+ ((arrow_height_ - kDefaultArrowTargetHeight) /
+ (kMaximumArrowTargetHeight - kDefaultArrowTargetHeight)));
+ }
+ // Add pixels for the stroke, if the arrow is to be visible at all. Without
+ // this, changing the arrow height from 0 to kSeparatorLineHeight would
+ // produce no visible effect, because the stroke would paint atop the divider
+ // line above the infobar.
+ if (arrow_height_)
+ arrow_height_ += kSeparatorLineHeight;
+
+ bar_height_ = animation_.CurrentValueBetween(0, bar_target_height_);
+
+ // Don't re-layout if nothing has changed, e.g. because the animation step was
+ // not large enough to actually change the heights by at least a pixel.
+ bool heights_differ =
+ (old_arrow_height != arrow_height_) || (old_bar_height != bar_height_);
+ if (heights_differ)
+ PlatformSpecificOnHeightsRecalculated();
+
+ if (container_ && (heights_differ || force_notify))
+ container_->OnInfoBarStateChanged(animation_.is_animating());
+}
+
+void InfoBar::MaybeDelete() {
+ if (!owner_ && (animation_.GetCurrentValue() == 0.0)) {
+ if (container_)
+ container_->RemoveInfoBar(this);
+ delete this;
+ }
+}
+
+} // namespace infobars
diff --git a/components/infobars/core/infobar.h b/components/infobars/core/infobar.h
new file mode 100644
index 0000000..9aef299
--- /dev/null
+++ b/components/infobars/core/infobar.h
@@ -0,0 +1,153 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_INFOBARS_CORE_INFOBAR_H_
+#define COMPONENTS_INFOBARS_CORE_INFOBAR_H_
+
+#include <utility>
+
+#include "base/memory/scoped_ptr.h"
+#include "components/infobars/core/infobar_delegate.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/animation/animation_delegate.h"
+#include "ui/gfx/animation/slide_animation.h"
+#include "ui/gfx/size.h"
+
+namespace infobars {
+
+class InfoBarContainer;
+class InfoBarManager;
+
+// InfoBar is a cross-platform base class for an infobar "view" (in the MVC
+// sense), which owns a corresponding InfoBarDelegate "model". Typically,
+// a caller will call XYZInfoBarDelegate::Create() and pass in the
+// InfoBarManager for the relevant tab. This will create an XYZInfoBarDelegate,
+// create a platform-specific subclass of InfoBar to own it, and then call
+// InfoBarManager::AddInfoBar() to give it ownership of the infobar.
+// During its life, the InfoBar may be shown and hidden as the owning tab is
+// switched between the foreground and background. Eventually, InfoBarManager
+// will instruct the InfoBar to close itself. At this point, the InfoBar will
+// optionally animate closed; once it's no longer visible, it deletes itself,
+// destroying the InfoBarDelegate in the process.
+//
+// Thus, InfoBarDelegate and InfoBar implementations can assume they share
+// lifetimes, and not NULL-check each other; but if one needs to reach back into
+// the owning InfoBarManager, it must check whether that's still possible.
+class InfoBar : public gfx::AnimationDelegate {
+ public:
+ // These are the types passed as Details for infobar-related notifications.
+ typedef InfoBar AddedDetails;
+ typedef std::pair<InfoBar*, bool> RemovedDetails;
+ typedef std::pair<InfoBar*, InfoBar*> ReplacedDetails;
+
+ // Platforms must define these.
+ static const int kDefaultBarTargetHeight;
+ static const int kSeparatorLineHeight;
+ static const int kDefaultArrowTargetHeight;
+ static const int kMaximumArrowTargetHeight;
+ // The half-width (see comments on |arrow_half_width_| below) scales to its
+ // default and maximum values proportionally to how the height scales to its.
+ static const int kDefaultArrowTargetHalfWidth;
+ static const int kMaximumArrowTargetHalfWidth;
+
+ explicit InfoBar(scoped_ptr<InfoBarDelegate> delegate);
+ virtual ~InfoBar();
+
+ static SkColor GetTopColor(InfoBarDelegate::Type infobar_type);
+ static SkColor GetBottomColor(InfoBarDelegate::Type infobar_type);
+
+ InfoBarManager* owner() { return owner_; }
+ InfoBarDelegate* delegate() { return delegate_.get(); }
+ const InfoBarDelegate* delegate() const { return delegate_.get(); }
+ void set_container(InfoBarContainer* container) { container_ = container; }
+
+ // Sets |owner_|. This also calls StoreActiveEntryUniqueID() on |delegate_|.
+ // This must only be called once as there's no way to extract an infobar from
+ // its owner without deleting it, for reparenting in another tab.
+ void SetOwner(InfoBarManager* owner);
+
+ // Makes the infobar visible. If |animate| is true, the infobar is then
+ // animated to full size.
+ void Show(bool animate);
+
+ // Makes the infobar hidden. If |animate| is false, the infobar is
+ // immediately removed from the container, and, if now unowned, deleted. If
+ // |animate| is true, the infobar is animated to zero size, ultimately
+ // triggering a call to AnimationEnded().
+ void Hide(bool animate);
+
+ // Changes the target height of the arrow portion of the infobar. This has no
+ // effect once the infobar is animating closed.
+ void SetArrowTargetHeight(int height);
+
+ // Notifies the infobar that it is no longer owned and should delete itself
+ // once it is invisible.
+ void CloseSoon();
+
+ // Forwards a close request to our owner. This is a no-op if we're already
+ // unowned.
+ void RemoveSelf();
+
+ // Changes the target height of the main ("bar") portion of the infobar.
+ void SetBarTargetHeight(int height);
+
+ const gfx::SlideAnimation& animation() const { return animation_; }
+ int arrow_height() const { return arrow_height_; }
+ int arrow_target_height() const { return arrow_target_height_; }
+ int arrow_half_width() const { return arrow_half_width_; }
+ int total_height() const { return arrow_height_ + bar_height_; }
+
+ protected:
+ // gfx::AnimationDelegate:
+ virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
+
+ const InfoBarContainer* container() const { return container_; }
+ InfoBarContainer* container() { return container_; }
+ gfx::SlideAnimation* animation() { return &animation_; }
+ int bar_height() const { return bar_height_; }
+ int bar_target_height() const { return bar_target_height_; }
+
+ // Platforms may optionally override these if they need to do work during
+ // processing of the given calls.
+ virtual void PlatformSpecificSetOwner() {}
+ virtual void PlatformSpecificShow(bool animate) {}
+ virtual void PlatformSpecificHide(bool animate) {}
+ virtual void PlatformSpecificOnCloseSoon() {}
+ virtual void PlatformSpecificOnHeightsRecalculated() {}
+
+ private:
+ // gfx::AnimationDelegate:
+ virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
+
+ // Finds the new desired arrow and bar heights, and if they differ from the
+ // current ones, calls PlatformSpecificOnHeightRecalculated(). Informs our
+ // container our state has changed if either the heights have changed or
+ // |force_notify| is set.
+ void RecalculateHeights(bool force_notify);
+
+ // Checks whether the infobar is unowned and done with all animations. If so,
+ // notifies the container that it should remove this infobar, and deletes
+ // itself.
+ void MaybeDelete();
+
+ InfoBarManager* owner_;
+ scoped_ptr<InfoBarDelegate> delegate_;
+ InfoBarContainer* container_;
+ gfx::SlideAnimation animation_;
+
+ // The current and target heights of the arrow and bar portions, and half the
+ // current arrow width. (It's easier to work in half-widths as we draw the
+ // arrow as two halves on either side of a center point.)
+ int arrow_height_; // Includes both fill and top stroke.
+ int arrow_target_height_;
+ int arrow_half_width_; // Includes only fill.
+ int bar_height_; // Includes both fill and bottom separator.
+ int bar_target_height_;
+
+ DISALLOW_COPY_AND_ASSIGN(InfoBar);
+};
+
+} // namespace infobars
+
+#endif // COMPONENTS_INFOBARS_CORE_INFOBAR_H_
diff --git a/components/infobars/core/infobar_container.cc b/components/infobars/core/infobar_container.cc
new file mode 100644
index 0000000..f435dd7
--- /dev/null
+++ b/components/infobars/core/infobar_container.cc
@@ -0,0 +1,178 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/infobars/core/infobar_container.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "components/infobars/core/infobar.h"
+#include "components/infobars/core/infobar_delegate.h"
+#include "ui/gfx/animation/slide_animation.h"
+
+namespace infobars {
+
+InfoBarContainer::Delegate::~Delegate() {
+}
+
+InfoBarContainer::InfoBarContainer(Delegate* delegate)
+ : delegate_(delegate),
+ infobar_manager_(NULL),
+ top_arrow_target_height_(InfoBar::kDefaultArrowTargetHeight) {
+}
+
+InfoBarContainer::~InfoBarContainer() {
+ // RemoveAllInfoBarsForDestruction() should have already cleared our infobars.
+ DCHECK(infobars_.empty());
+ if (infobar_manager_)
+ infobar_manager_->RemoveObserver(this);
+}
+
+void InfoBarContainer::ChangeInfoBarManager(InfoBarManager* infobar_manager) {
+ if (infobar_manager_)
+ infobar_manager_->RemoveObserver(this);
+
+ // Hides all infobars in this container without animation.
+ while (!infobars_.empty()) {
+ InfoBar* infobar = infobars_.front();
+ // Inform the infobar that it's hidden. If it was already closing, this
+ // deletes it. Otherwise, this ensures the infobar will be deleted if it's
+ // closed while it's not in an InfoBarContainer.
+ infobar->Hide(false);
+ }
+
+ infobar_manager_ = infobar_manager;
+ if (infobar_manager_) {
+ infobar_manager_->AddObserver(this);
+
+ for (size_t i = 0; i < infobar_manager_->infobar_count(); ++i) {
+ // As when we removed the infobars above, we prevent callbacks to
+ // OnInfoBarStateChanged() for each infobar.
+ AddInfoBar(infobar_manager_->infobar_at(i), i, false, NO_CALLBACK);
+ }
+ }
+
+ // Now that everything is up to date, signal the delegate to re-layout.
+ OnInfoBarStateChanged(false);
+}
+
+int InfoBarContainer::GetVerticalOverlap(int* total_height) {
+ // Our |total_height| is the sum of the preferred heights of the InfoBars
+ // contained within us plus the |vertical_overlap|.
+ int vertical_overlap = 0;
+ int next_infobar_y = 0;
+
+ for (InfoBars::iterator i(infobars_.begin()); i != infobars_.end(); ++i) {
+ InfoBar* infobar = *i;
+ next_infobar_y -= infobar->arrow_height();
+ vertical_overlap = std::max(vertical_overlap, -next_infobar_y);
+ next_infobar_y += infobar->total_height();
+ }
+
+ if (total_height)
+ *total_height = next_infobar_y + vertical_overlap;
+ return vertical_overlap;
+}
+
+void InfoBarContainer::SetMaxTopArrowHeight(int height) {
+ // Decrease the height by the arrow stroke thickness, which is the separator
+ // line height, because the infobar arrow target heights are without-stroke.
+ top_arrow_target_height_ = std::min(
+ std::max(height - InfoBar::kSeparatorLineHeight, 0),
+ InfoBar::kMaximumArrowTargetHeight);
+ UpdateInfoBarArrowTargetHeights();
+}
+
+void InfoBarContainer::OnInfoBarStateChanged(bool is_animating) {
+ if (delegate_)
+ delegate_->InfoBarContainerStateChanged(is_animating);
+ UpdateInfoBarArrowTargetHeights();
+ PlatformSpecificInfoBarStateChanged(is_animating);
+}
+
+void InfoBarContainer::RemoveInfoBar(InfoBar* infobar) {
+ infobar->set_container(NULL);
+ InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(), infobar));
+ DCHECK(i != infobars_.end());
+ PlatformSpecificRemoveInfoBar(infobar);
+ infobars_.erase(i);
+}
+
+void InfoBarContainer::RemoveAllInfoBarsForDestruction() {
+ // Before we remove any children, we reset |delegate_|, so that no removals
+ // will result in us trying to call
+ // delegate_->InfoBarContainerStateChanged(). This is important because at
+ // this point |delegate_| may be shutting down, and it's at best unimportant
+ // and at worst disastrous to call that.
+ delegate_ = NULL;
+ ChangeInfoBarManager(NULL);
+}
+
+void InfoBarContainer::OnInfoBarAdded(InfoBar* infobar) {
+ AddInfoBar(infobar, infobars_.size(), true, WANT_CALLBACK);
+}
+
+void InfoBarContainer::OnInfoBarRemoved(InfoBar* infobar, bool animate) {
+ infobar->Hide(animate);
+ UpdateInfoBarArrowTargetHeights();
+}
+
+void InfoBarContainer::OnInfoBarReplaced(InfoBar* old_infobar,
+ InfoBar* new_infobar) {
+ PlatformSpecificReplaceInfoBar(old_infobar, new_infobar);
+ InfoBars::const_iterator i(std::find(infobars_.begin(), infobars_.end(),
+ old_infobar));
+ DCHECK(i != infobars_.end());
+ size_t position = i - infobars_.begin();
+ old_infobar->Hide(false);
+ AddInfoBar(new_infobar, position, false, WANT_CALLBACK);
+}
+
+void InfoBarContainer::OnManagerShuttingDown(InfoBarManager* manager) {
+ DCHECK_EQ(infobar_manager_, manager);
+ infobar_manager_->RemoveObserver(this);
+ infobar_manager_ = NULL;
+}
+
+void InfoBarContainer::AddInfoBar(InfoBar* infobar,
+ size_t position,
+ bool animate,
+ CallbackStatus callback_status) {
+ DCHECK(std::find(infobars_.begin(), infobars_.end(), infobar) ==
+ infobars_.end());
+ DCHECK_LE(position, infobars_.size());
+ infobars_.insert(infobars_.begin() + position, infobar);
+ UpdateInfoBarArrowTargetHeights();
+ PlatformSpecificAddInfoBar(infobar, position);
+ if (callback_status == WANT_CALLBACK)
+ infobar->set_container(this);
+ infobar->Show(animate);
+ if (callback_status == NO_CALLBACK)
+ infobar->set_container(this);
+}
+
+void InfoBarContainer::UpdateInfoBarArrowTargetHeights() {
+ for (size_t i = 0; i < infobars_.size(); ++i)
+ infobars_[i]->SetArrowTargetHeight(ArrowTargetHeightForInfoBar(i));
+}
+
+int InfoBarContainer::ArrowTargetHeightForInfoBar(size_t infobar_index) const {
+ if (!delegate_ || !delegate_->DrawInfoBarArrows(NULL))
+ return 0;
+ if (infobar_index == 0)
+ return top_arrow_target_height_;
+ const gfx::SlideAnimation& first_infobar_animation =
+ const_cast<const InfoBar*>(infobars_.front())->animation();
+ if ((infobar_index > 1) || first_infobar_animation.IsShowing())
+ return InfoBar::kDefaultArrowTargetHeight;
+ // When the first infobar is animating closed, we animate the second infobar's
+ // arrow target height from the default to the top target height. Note that
+ // the animation values here are going from 1.0 -> 0.0 as the top bar closes.
+ return top_arrow_target_height_ + static_cast<int>(
+ (InfoBar::kDefaultArrowTargetHeight - top_arrow_target_height_) *
+ first_infobar_animation.GetCurrentValue());
+}
+
+} // namespace infobars
diff --git a/components/infobars/core/infobar_container.h b/components/infobars/core/infobar_container.h
new file mode 100644
index 0000000..6663821
--- /dev/null
+++ b/components/infobars/core/infobar_container.h
@@ -0,0 +1,137 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_INFOBARS_CORE_INFOBAR_CONTAINER_H_
+#define COMPONENTS_INFOBARS_CORE_INFOBAR_CONTAINER_H_
+
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/time/time.h"
+#include "components/infobars/core/infobar_manager.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace infobars {
+
+class InfoBar;
+
+// InfoBarContainer is a cross-platform base class to handle the visibility-
+// related aspects of InfoBars. While InfoBarManager owns the InfoBars, the
+// InfoBarContainer is responsible for telling particular InfoBars that they
+// should be hidden or visible.
+//
+// Platforms need to subclass this to implement a few platform-specific
+// functions, which are pure virtual here.
+class InfoBarContainer : public InfoBarManager::Observer {
+ public:
+ class Delegate {
+ public:
+ // The separator color may vary depending on where the container is hosted.
+ virtual SkColor GetInfoBarSeparatorColor() const = 0;
+
+ // The delegate is notified each time the infobar container changes height,
+ // as well as when it stops animating.
+ virtual void InfoBarContainerStateChanged(bool is_animating) = 0;
+
+ // The delegate needs to tell us whether "unspoofable" arrows should be
+ // drawn, and if so, at what |x| coordinate. |x| may be NULL.
+ virtual bool DrawInfoBarArrows(int* x) const = 0;
+
+ protected:
+ virtual ~Delegate();
+ };
+
+ explicit InfoBarContainer(Delegate* delegate);
+ virtual ~InfoBarContainer();
+
+ // Changes the InfoBarManager for which this container is showing infobars.
+ // This will hide all current infobars, remove them from the container, add
+ // the infobars from |infobar_manager|, and show them all. |infobar_manager|
+ // may be NULL.
+ void ChangeInfoBarManager(InfoBarManager* infobar_manager);
+
+ // Returns the amount by which to overlap the toolbar above, and, when
+ // |total_height| is non-NULL, set it to the height of the InfoBarContainer
+ // (including overlap).
+ int GetVerticalOverlap(int* total_height);
+
+ // Called by the delegate when the distance between what the top infobar's
+ // "unspoofable" arrow would point to and the top infobar itself changes.
+ // This enables the top infobar to show a longer arrow (e.g. because of a
+ // visible bookmark bar) or shorter (e.g. due to being in a popup window) if
+ // desired.
+ //
+ // IMPORTANT: This MUST NOT result in a call back to
+ // Delegate::InfoBarContainerStateChanged() unless it causes an actual
+ // change, lest we infinitely recurse.
+ void SetMaxTopArrowHeight(int height);
+
+ // Called when a contained infobar has animated or by some other means changed
+ // its height, or when it stops animating. The container is expected to do
+ // anything necessary to respond, e.g. re-layout.
+ void OnInfoBarStateChanged(bool is_animating);
+
+ // Called by |infobar| to request that it be removed from the container. At
+ // this point, |infobar| should already be hidden.
+ void RemoveInfoBar(InfoBar* infobar);
+
+ const Delegate* delegate() const { return delegate_; }
+
+ protected:
+ // Subclasses must call this during destruction, so that we can remove
+ // infobars (which will call the pure virtual functions below) while the
+ // subclass portion of |this| has not yet been destroyed.
+ void RemoveAllInfoBarsForDestruction();
+
+ // These must be implemented on each platform to e.g. adjust the visible
+ // object hierarchy. The first two functions should each be called exactly
+ // once during an infobar's life (see comments on RemoveInfoBar() and
+ // AddInfoBar()).
+ virtual void PlatformSpecificAddInfoBar(InfoBar* infobar,
+ size_t position) = 0;
+ // TODO(miguelg): Remove this; it is only necessary for Android, and only
+ // until the translate infobar is implemented as three different infobars like
+ // GTK does.
+ virtual void PlatformSpecificReplaceInfoBar(InfoBar* old_infobar,
+ InfoBar* new_infobar) {}
+ virtual void PlatformSpecificRemoveInfoBar(InfoBar* infobar) = 0;
+ virtual void PlatformSpecificInfoBarStateChanged(bool is_animating) {}
+
+ private:
+ typedef std::vector<InfoBar*> InfoBars;
+
+ // InfoBarManager::Observer:
+ virtual void OnInfoBarAdded(InfoBar* infobar) OVERRIDE;
+ virtual void OnInfoBarRemoved(InfoBar* infobar, bool animate) OVERRIDE;
+ virtual void OnInfoBarReplaced(InfoBar* old_infobar,
+ InfoBar* new_infobar) OVERRIDE;
+ virtual void OnManagerShuttingDown(InfoBarManager* manager) OVERRIDE;
+
+ // Adds |infobar| to this container before the existing infobar at position
+ // |position| and calls Show() on it. |animate| is passed along to
+ // infobar->Show(). Depending on the value of |callback_status|, this calls
+ // infobar->set_container(this) either before or after the call to Show() so
+ // that OnInfoBarStateChanged() either will or won't be called as a result.
+ enum CallbackStatus { NO_CALLBACK, WANT_CALLBACK };
+ void AddInfoBar(InfoBar* infobar,
+ size_t position,
+ bool animate,
+ CallbackStatus callback_status);
+
+ void UpdateInfoBarArrowTargetHeights();
+ int ArrowTargetHeightForInfoBar(size_t infobar_index) const;
+
+ Delegate* delegate_;
+ InfoBarManager* infobar_manager_;
+ InfoBars infobars_;
+
+ // Calculated in SetMaxTopArrowHeight().
+ int top_arrow_target_height_;
+
+ DISALLOW_COPY_AND_ASSIGN(InfoBarContainer);
+};
+
+} // namespace infobars
+
+#endif // COMPONENTS_INFOBARS_CORE_INFOBAR_CONTAINER_H_
diff --git a/components/infobars/core/infobar_delegate.cc b/components/infobars/core/infobar_delegate.cc
new file mode 100644
index 0000000..d3f5165
--- /dev/null
+++ b/components/infobars/core/infobar_delegate.cc
@@ -0,0 +1,111 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/infobars/core/infobar_delegate.h"
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "components/infobars/core/infobar.h"
+#include "components/infobars/core/infobar_manager.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace infobars {
+
+const int InfoBarDelegate::kNoIconID = 0;
+
+InfoBarDelegate::~InfoBarDelegate() {
+}
+
+InfoBarDelegate::InfoBarAutomationType
+ InfoBarDelegate::GetInfoBarAutomationType() const {
+ return UNKNOWN_INFOBAR;
+}
+
+bool InfoBarDelegate::EqualsDelegate(InfoBarDelegate* delegate) const {
+ return false;
+}
+
+bool InfoBarDelegate::ShouldExpire(const NavigationDetails& details) const {
+ if (!details.is_navigation_to_different_page)
+ return false;
+
+ return ShouldExpireInternal(details);
+}
+
+void InfoBarDelegate::InfoBarDismissed() {
+}
+
+int InfoBarDelegate::GetIconID() const {
+ return kNoIconID;
+}
+
+InfoBarDelegate::Type InfoBarDelegate::GetInfoBarType() const {
+ return WARNING_TYPE;
+}
+
+AutoLoginInfoBarDelegate* InfoBarDelegate::AsAutoLoginInfoBarDelegate() {
+ return NULL;
+}
+
+ConfirmInfoBarDelegate* InfoBarDelegate::AsConfirmInfoBarDelegate() {
+ return NULL;
+}
+
+ExtensionInfoBarDelegate* InfoBarDelegate::AsExtensionInfoBarDelegate() {
+ return NULL;
+}
+
+InsecureContentInfoBarDelegate*
+ InfoBarDelegate::AsInsecureContentInfoBarDelegate() {
+ return NULL;
+}
+
+MediaStreamInfoBarDelegate* InfoBarDelegate::AsMediaStreamInfoBarDelegate() {
+ return NULL;
+}
+
+PopupBlockedInfoBarDelegate* InfoBarDelegate::AsPopupBlockedInfoBarDelegate() {
+ return NULL;
+}
+
+RegisterProtocolHandlerInfoBarDelegate*
+ InfoBarDelegate::AsRegisterProtocolHandlerInfoBarDelegate() {
+ return NULL;
+}
+
+ScreenCaptureInfoBarDelegate*
+ InfoBarDelegate::AsScreenCaptureInfoBarDelegate() {
+ return NULL;
+}
+
+ThemeInstalledInfoBarDelegate*
+ InfoBarDelegate::AsThemePreviewInfobarDelegate() {
+ return NULL;
+}
+
+TranslateInfoBarDelegate* InfoBarDelegate::AsTranslateInfoBarDelegate() {
+ return NULL;
+}
+
+void InfoBarDelegate::StoreActiveEntryUniqueID() {
+ contents_unique_id_ = infobar()->owner()->GetActiveEntryID();
+}
+
+gfx::Image InfoBarDelegate::GetIcon() const {
+ int icon_id = GetIconID();
+ return (icon_id == kNoIconID) ? gfx::Image() :
+ ResourceBundle::GetSharedInstance().GetNativeImageNamed(icon_id);
+}
+
+InfoBarDelegate::InfoBarDelegate() : contents_unique_id_(0) {
+}
+
+bool InfoBarDelegate::ShouldExpireInternal(
+ const NavigationDetails& details) const {
+ // NOTE: If you change this, be sure to check and adjust the behavior of
+ // anyone who overrides this as necessary!
+ return (contents_unique_id_ != details.entry_id) || details.is_reload;
+}
+
+} // namespace infobars
diff --git a/components/infobars/core/infobar_delegate.h b/components/infobars/core/infobar_delegate.h
new file mode 100644
index 0000000..b6d63ac
--- /dev/null
+++ b/components/infobars/core/infobar_delegate.h
@@ -0,0 +1,148 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_INFOBARS_CORE_INFOBAR_DELEGATE_H_
+#define COMPONENTS_INFOBARS_CORE_INFOBAR_DELEGATE_H_
+
+#include "base/basictypes.h"
+#include "base/strings/string16.h"
+#include "ui/base/window_open_disposition.h"
+
+class AutoLoginInfoBarDelegate;
+class ConfirmInfoBarDelegate;
+class ExtensionInfoBarDelegate;
+class InsecureContentInfoBarDelegate;
+class MediaStreamInfoBarDelegate;
+class PopupBlockedInfoBarDelegate;
+class RegisterProtocolHandlerInfoBarDelegate;
+class ScreenCaptureInfoBarDelegate;
+class ThemeInstalledInfoBarDelegate;
+class ThreeDAPIInfoBarDelegate;
+class TranslateInfoBarDelegate;
+
+namespace gfx {
+class Image;
+}
+
+namespace infobars {
+
+class InfoBar;
+
+// An interface implemented by objects wishing to control an InfoBar.
+// Implementing this interface is not sufficient to use an InfoBar, since it
+// does not map to a specific InfoBar type. Instead, you must implement
+// ConfirmInfoBarDelegate, or override with your own delegate for your own
+// InfoBar variety.
+class InfoBarDelegate {
+ public:
+ // The type of the infobar. It controls its appearance, such as its background
+ // color.
+ enum Type {
+ WARNING_TYPE,
+ PAGE_ACTION_TYPE,
+ };
+
+ enum InfoBarAutomationType {
+ CONFIRM_INFOBAR,
+ PASSWORD_INFOBAR,
+ RPH_INFOBAR,
+ UNKNOWN_INFOBAR,
+ };
+
+ // Describes navigation events, used to decide whether infobars should be
+ // dismissed.
+ struct NavigationDetails {
+ // Unique identifier for the entry.
+ int entry_id;
+ // True if it is a navigation to a different page (as opposed to in-page).
+ bool is_navigation_to_different_page;
+ // True if the entry replaced the existing one.
+ bool did_replace_entry;
+ // True for the main frame, false for a sub-frame.
+ bool is_main_frame;
+ bool is_reload;
+ bool is_redirect;
+ };
+
+ // Value to use when the InfoBar has no icon to show.
+ static const int kNoIconID;
+
+ // Called when the InfoBar that owns this delegate is being destroyed. At
+ // this point nothing is visible onscreen.
+ virtual ~InfoBarDelegate();
+
+ virtual InfoBarAutomationType GetInfoBarAutomationType() const;
+
+ // Returns true if the supplied |delegate| is equal to this one. Equality is
+ // left to the implementation to define. This function is called by the
+ // InfoBarManager when determining whether or not a delegate should be
+ // added because a matching one already exists. If this function returns true,
+ // the InfoBarManager will not add the new delegate because it considers
+ // one to already be present.
+ virtual bool EqualsDelegate(InfoBarDelegate* delegate) const;
+
+ // Returns true if the InfoBar should be closed automatically after the page
+ // is navigated. By default this returns true if the navigation is to a new
+ // page (not including reloads). Subclasses wishing to change this behavior
+ // can override either this function or ShouldExpireInternal(), depending on
+ // what level of control they need.
+ virtual bool ShouldExpire(const NavigationDetails& details) const;
+
+ // Called when the user clicks on the close button to dismiss the infobar.
+ virtual void InfoBarDismissed();
+
+ // Return the resource ID of the icon to be shown for this InfoBar. If the
+ // value is equal to |kNoIconID|, no icon is shown.
+ virtual int GetIconID() const;
+
+ // Returns the type of the infobar. The type determines the appearance (such
+ // as background color) of the infobar.
+ virtual Type GetInfoBarType() const;
+
+ // Type-checking downcast routines:
+ virtual AutoLoginInfoBarDelegate* AsAutoLoginInfoBarDelegate();
+ virtual ConfirmInfoBarDelegate* AsConfirmInfoBarDelegate();
+ virtual ExtensionInfoBarDelegate* AsExtensionInfoBarDelegate();
+ virtual InsecureContentInfoBarDelegate* AsInsecureContentInfoBarDelegate();
+ virtual MediaStreamInfoBarDelegate* AsMediaStreamInfoBarDelegate();
+ virtual PopupBlockedInfoBarDelegate* AsPopupBlockedInfoBarDelegate();
+ virtual RegisterProtocolHandlerInfoBarDelegate*
+ AsRegisterProtocolHandlerInfoBarDelegate();
+ virtual ScreenCaptureInfoBarDelegate* AsScreenCaptureInfoBarDelegate();
+ virtual ThemeInstalledInfoBarDelegate* AsThemePreviewInfobarDelegate();
+ virtual TranslateInfoBarDelegate* AsTranslateInfoBarDelegate();
+
+ void set_infobar(InfoBar* infobar) { infobar_ = infobar; }
+
+ // Store the unique id for the active entry, to be used later upon navigation
+ // to determine if this InfoBarDelegate should be expired.
+ void StoreActiveEntryUniqueID();
+
+ // Return the icon to be shown for this InfoBar. If the returned Image is
+ // empty, no icon is shown.
+ virtual gfx::Image GetIcon() const;
+
+ protected:
+ InfoBarDelegate();
+
+ // Returns true if the navigation is to a new URL or a reload occured.
+ virtual bool ShouldExpireInternal(const NavigationDetails& details) const;
+
+ int contents_unique_id() const { return contents_unique_id_; }
+ InfoBar* infobar() { return infobar_; }
+
+ private:
+ // The unique id of the active NavigationEntry of the WebContents that we were
+ // opened for. Used to help expire on navigations.
+ int contents_unique_id_;
+
+ // The InfoBar associated with us.
+ InfoBar* infobar_;
+
+ DISALLOW_COPY_AND_ASSIGN(InfoBarDelegate);
+};
+
+} // namespace infobars
+
+#endif // COMPONENTS_INFOBARS_CORE_INFOBAR_DELEGATE_H_
diff --git a/components/infobars/core/infobar_manager.cc b/components/infobars/core/infobar_manager.cc
new file mode 100644
index 0000000..6525a9a
--- /dev/null
+++ b/components/infobars/core/infobar_manager.cc
@@ -0,0 +1,141 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/infobars/core/infobar_manager.h"
+
+#include "base/command_line.h"
+#include "components/infobars/core/infobar.h"
+#include "components/infobars/core/infobars_switches.h"
+
+namespace infobars {
+
+InfoBar* InfoBarManager::AddInfoBar(scoped_ptr<InfoBar> infobar) {
+ DCHECK(infobar);
+ if (!infobars_enabled_)
+ return NULL;
+
+ for (InfoBars::const_iterator i(infobars_.begin()); i != infobars_.end();
+ ++i) {
+ if ((*i)->delegate()->EqualsDelegate(infobar->delegate())) {
+ DCHECK_NE((*i)->delegate(), infobar->delegate());
+ return NULL;
+ }
+ }
+
+ InfoBar* infobar_ptr = infobar.release();
+ infobars_.push_back(infobar_ptr);
+ infobar_ptr->SetOwner(this);
+
+ NotifyInfoBarAdded(infobar_ptr);
+
+ return infobar_ptr;
+}
+
+void InfoBarManager::RemoveInfoBar(InfoBar* infobar) {
+ RemoveInfoBarInternal(infobar, true);
+}
+
+void InfoBarManager::RemoveAllInfoBars(bool animate) {
+ while (!infobars_.empty())
+ RemoveInfoBarInternal(infobars_.back(), animate);
+}
+
+InfoBar* InfoBarManager::ReplaceInfoBar(InfoBar* old_infobar,
+ scoped_ptr<InfoBar> new_infobar) {
+ DCHECK(old_infobar);
+ if (!infobars_enabled_)
+ return AddInfoBar(new_infobar.Pass()); // Deletes the infobar.
+ DCHECK(new_infobar);
+
+ InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(),
+ old_infobar));
+ DCHECK(i != infobars_.end());
+
+ InfoBar* new_infobar_ptr = new_infobar.release();
+ i = infobars_.insert(i, new_infobar_ptr);
+ new_infobar_ptr->SetOwner(this);
+
+ // Remove the old infobar before notifying, so that if any observers call back
+ // to AddInfoBar() or similar, we don't dupe-check against this infobar.
+ infobars_.erase(++i);
+
+ NotifyInfoBarReplaced(old_infobar, new_infobar_ptr);
+
+ old_infobar->CloseSoon();
+ return new_infobar_ptr;
+}
+
+void InfoBarManager::AddObserver(Observer* obs) {
+ observer_list_.AddObserver(obs);
+}
+
+void InfoBarManager::RemoveObserver(Observer* obs) {
+ observer_list_.RemoveObserver(obs);
+}
+
+InfoBarManager::InfoBarManager()
+ : infobars_enabled_(true) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableInfoBars))
+ infobars_enabled_ = false;
+}
+
+InfoBarManager::~InfoBarManager() {}
+
+void InfoBarManager::ShutDown() {
+ // Destroy all remaining InfoBars. It's important to not animate here so that
+ // we guarantee that we'll delete all delegates before we do anything else.
+ RemoveAllInfoBars(false);
+ FOR_EACH_OBSERVER(Observer, observer_list_, OnManagerShuttingDown(this));
+}
+
+void InfoBarManager::OnNavigation(
+ const InfoBarDelegate::NavigationDetails& details) {
+ // NOTE: It is not safe to change the following code to count upwards or
+ // use iterators, as the RemoveInfoBar() call synchronously modifies our
+ // delegate list.
+ for (size_t i = infobars_.size(); i > 0; --i) {
+ InfoBar* infobar = infobars_[i - 1];
+ if (infobar->delegate()->ShouldExpire(details))
+ RemoveInfoBar(infobar);
+ }
+}
+
+void InfoBarManager::NotifyInfoBarAdded(InfoBar* infobar) {
+ FOR_EACH_OBSERVER(Observer, observer_list_, OnInfoBarAdded(infobar));
+}
+
+void InfoBarManager::NotifyInfoBarRemoved(InfoBar* infobar, bool animate) {
+ FOR_EACH_OBSERVER(Observer, observer_list_,
+ OnInfoBarRemoved(infobar, animate));
+}
+
+void InfoBarManager::NotifyInfoBarReplaced(InfoBar* old_infobar,
+ InfoBar* new_infobar) {
+ FOR_EACH_OBSERVER(Observer,
+ observer_list_,
+ OnInfoBarReplaced(old_infobar, new_infobar));
+}
+
+void InfoBarManager::RemoveInfoBarInternal(InfoBar* infobar, bool animate) {
+ DCHECK(infobar);
+ if (!infobars_enabled_) {
+ DCHECK(infobars_.empty());
+ return;
+ }
+
+ InfoBars::iterator i(std::find(infobars_.begin(), infobars_.end(), infobar));
+ DCHECK(i != infobars_.end());
+
+ // Remove the infobar before notifying, so that if any observers call back to
+ // AddInfoBar() or similar, we don't dupe-check against this infobar.
+ infobars_.erase(i);
+
+ // This notification must happen before the call to CloseSoon() below, since
+ // observers may want to access |infobar| and that call can delete it.
+ NotifyInfoBarRemoved(infobar, animate);
+
+ infobar->CloseSoon();
+}
+
+} // namespace infobars
diff --git a/components/infobars/core/infobar_manager.h b/components/infobars/core/infobar_manager.h
new file mode 100644
index 0000000..747d5ac
--- /dev/null
+++ b/components/infobars/core/infobar_manager.h
@@ -0,0 +1,124 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_INFOBARS_CORE_INFOBAR_MANAGER_H_
+#define COMPONENTS_INFOBARS_CORE_INFOBAR_MANAGER_H_
+
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "components/infobars/core/infobar_delegate.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace infobars {
+
+class InfoBar;
+
+// Provides access to creating, removing and enumerating info bars
+// attached to a tab.
+class InfoBarManager {
+ public:
+ // Observer class for infobar events.
+ class Observer {
+ public:
+ virtual void OnInfoBarAdded(InfoBar* infobar) = 0;
+ virtual void OnInfoBarRemoved(InfoBar* infobar, bool animate) = 0;
+ virtual void OnInfoBarReplaced(InfoBar* old_infobar,
+ InfoBar* new_infobar) = 0;
+ virtual void OnManagerShuttingDown(InfoBarManager* manager) = 0;
+ };
+
+ InfoBarManager();
+ virtual ~InfoBarManager();
+
+ // Must be called before destruction.
+ // TODO(droger): Merge this method with the destructor once the virtual calls
+ // for notifications are removed (see http://crbug.com/354380).
+ void ShutDown();
+
+ // Adds the specified |infobar|, which already owns a delegate.
+ //
+ // If infobars are disabled for this tab or the tab already has an infobar
+ // whose delegate returns true for
+ // InfoBarDelegate::EqualsDelegate(infobar->delegate()), |infobar| is deleted
+ // immediately without being added.
+ //
+ // Returns the infobar if it was successfully added.
+ InfoBar* AddInfoBar(scoped_ptr<InfoBar> infobar);
+
+ // Removes the specified |infobar|. This in turn may close immediately or
+ // animate closed; at the end the infobar will delete itself.
+ //
+ // If infobars are disabled for this tab, this will do nothing, on the
+ // assumption that the matching AddInfoBar() call will have already deleted
+ // the infobar (see above).
+ void RemoveInfoBar(InfoBar* infobar);
+
+ // Removes all the infobars.
+ void RemoveAllInfoBars(bool animate);
+
+ // Replaces one infobar with another, without any animation in between. This
+ // will result in |old_infobar| being synchronously deleted.
+ //
+ // If infobars are disabled for this tab, |new_infobar| is deleted immediately
+ // without being added, and nothing else happens.
+ //
+ // Returns the new infobar if it was successfully added.
+ //
+ // NOTE: This does not perform any EqualsDelegate() checks like AddInfoBar().
+ InfoBar* ReplaceInfoBar(InfoBar* old_infobar,
+ scoped_ptr<InfoBar> new_infobar);
+
+ // Returns the number of infobars for this tab.
+ size_t infobar_count() const { return infobars_.size(); }
+
+ // Returns the infobar at the given |index|. The InfoBarManager retains
+ // ownership.
+ //
+ // Warning: Does not sanity check |index|.
+ InfoBar* infobar_at(size_t index) { return infobars_[index]; }
+
+ // Must be called when a navigation happens.
+ void OnNavigation(const InfoBarDelegate::NavigationDetails& details);
+
+ void AddObserver(Observer* obs);
+ void RemoveObserver(Observer* obs);
+
+ // Returns the active entry ID.
+ virtual int GetActiveEntryID() = 0;
+
+ protected:
+ // Notifies the observer in |observer_list_|.
+ // TODO(droger): Absorb these methods back into their callers once virtual
+ // overrides are removed (see http://crbug.com/354380).
+ virtual void NotifyInfoBarAdded(InfoBar* infobar);
+ virtual void NotifyInfoBarRemoved(InfoBar* infobar, bool animate);
+ virtual void NotifyInfoBarReplaced(InfoBar* old_infobar,
+ InfoBar* new_infobar);
+
+ private:
+ // InfoBars associated with this InfoBarManager. We own these pointers.
+ // However, this is not a ScopedVector, because we don't delete the infobars
+ // directly once they've been added to this; instead, when we're done with an
+ // infobar, we instruct it to delete itself and then orphan it. See
+ // RemoveInfoBarInternal().
+ typedef std::vector<InfoBar*> InfoBars;
+
+ void RemoveInfoBarInternal(InfoBar* infobar, bool animate);
+
+ InfoBars infobars_;
+ bool infobars_enabled_;
+
+ ObserverList<Observer, true> observer_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(InfoBarManager);
+};
+
+} // namespace infobars
+
+#endif // COMPONENTS_INFOBARS_CORE_INFOBAR_MANAGER_H_
diff --git a/components/infobars/core/infobars_switches.cc b/components/infobars/core/infobars_switches.cc
new file mode 100644
index 0000000..deb21a7
--- /dev/null
+++ b/components/infobars/core/infobars_switches.cc
@@ -0,0 +1,14 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/infobars/core/infobars_switches.h"
+
+namespace infobars {
+namespace switches {
+
+// Prevent infobars from appearing.
+const char kDisableInfoBars[] = "disable-infobars";
+
+} // namespace switches
+} // namespace infobars
diff --git a/components/infobars/core/infobars_switches.h b/components/infobars/core/infobars_switches.h
new file mode 100644
index 0000000..d24a09a
--- /dev/null
+++ b/components/infobars/core/infobars_switches.h
@@ -0,0 +1,16 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_INFOBARS_CORE_INFOBARS_SWITCHES_H_
+#define COMPONENTS_INFOBARS_CORE_INFOBARS_SWITCHES_H_
+
+namespace infobars {
+namespace switches {
+
+extern const char kDisableInfoBars[];
+
+} // namespace switches
+} // namespace infobars
+
+#endif // COMPONENTS_INFOBARS_CORE_INFOBARS_SWITCHES_H_