diff options
author | kuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-19 11:23:05 +0000 |
---|---|---|
committer | kuan@chromium.org <kuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-19 11:23:05 +0000 |
commit | 5ee671febc6bc846bc3127932e9d3e6c26cb9ed9 (patch) | |
tree | 9b3d5b5a34cec2e0db431596085a955c947011b1 | |
parent | 02e44ae8d2d94044c1dd317d5dcab61923822cd4 (diff) | |
download | chromium_src-5ee671febc6bc846bc3127932e9d3e6c26cb9ed9.zip chromium_src-5ee671febc6bc846bc3127932e9d3e6c26cb9ed9.tar.gz chromium_src-5ee671febc6bc846bc3127932e9d3e6c26cb9ed9.tar.bz2 |
alternate ntp: implement Show/HideBars SearchBox API to reduce jank when showing/hiding bars
this is the chrome side combining melevin@'s renderer parts with my browser parts; gws side is implemented by melevin@.
- when suggestions show/hide, bookmark and info bars hide/show respectively; this causes contents to shift up/down respectively, resulting in jank.
- to reduce jank, these APIs synchronize the showing/hiding of suggestions in gws with the showing/hiding of bookmark and info bars in browser.
- gws sends HideBars() whenever suggestions show, and ShowBars() whenever they close.
- browser only obliges when bookmark and/or info bars are enabled and only on NTP and SERP pages, but always fires onbarshidden event for every HideBars() call, so that gws can proceed to show suggestions.
BUG=176146,178550,175776
TEST=verify as per bug rpts
Review URL: https://chromiumcodereview.appspot.com/12631008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188994 0039d316-1c4b-4281-b951-d872f2087c98
24 files changed, 348 insertions, 120 deletions
diff --git a/chrome/browser/infobars/infobar_container.cc b/chrome/browser/infobars/infobar_container.cc index 0dd6371..8ea298f 100644 --- a/chrome/browser/infobars/infobar_container.cc +++ b/chrome/browser/infobars/infobar_container.cc @@ -45,17 +45,23 @@ InfoBarContainer::~InfoBarContainer() { } void InfoBarContainer::ChangeInfoBarService(InfoBarService* infobar_service) { - registrar_.RemoveAll(); + // We have to call HideAllInfoBars() here and not after the early exit below, + // to handle the case we're switching from a tab with visible infobars to one + // where the SearchModel directs us to hide infobars. + HideAllInfoBars(); + + infobar_service_ = infobar_service; + + if (search_model_ && !search_model_->top_bars_visible()) + return; // Note that HideAllInfoBars() sets |infobars_shown_| to false, because that's // what the other, Instant-related callers want; but here we actually // explicitly want to reset this variable to true. So do that after calling // the function. - HideAllInfoBars(); infobars_shown_ = true; infobars_shown_time_ = base::TimeTicks(); - infobar_service_ = infobar_service; if (infobar_service_) { content::Source<InfoBarService> source(infobar_service_); registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, @@ -138,12 +144,8 @@ void InfoBarContainer::RemoveAllInfoBarsForDestruction() { void InfoBarContainer::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { - // When infobars are supposed to be hidden, we shouldn't try to hide or show - // anything in response to any notifications. Once infobars get un-hidden - // via ChangeInfoBarService(), we'll get the updated set of visible infobars - // from the InfoBarService. - if (!infobars_shown_) - return; + // When infobars are hidden, we shouldn't be listening for notifications. + DCHECK(infobars_shown_); switch (type) { case chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED: @@ -174,29 +176,17 @@ void InfoBarContainer::Observe(int type, } } -void InfoBarContainer::ModeChanged(const chrome::search::Mode& old_mode, - const chrome::search::Mode& new_mode) { - // Hide infobars when showing Instant Extended suggestions. - if (new_mode.is_search_suggestions()) { - // If suggestions are being shown on a |DEFAULT| page, delay the hiding - // until notification that Instant overlay is ready is received via - // OverlayStateChanged(); this prevents jankiness caused by infobars hiding - // followed by suggestions appearing. - if (new_mode.is_origin_default()) - return; - HideAllInfoBars(); - OnInfoBarStateChanged(false); - } else { +void InfoBarContainer::ModelChanged( + const chrome::search::SearchModel::State& old_state, + const chrome::search::SearchModel::State& new_state) { + if (!chrome::search::SearchModel::ShouldChangeTopBarsVisibility(old_state, + new_state)) + return; + + if (new_state.top_bars_visible && !infobars_shown_) { ChangeInfoBarService(infobar_service_); infobars_shown_time_ = base::TimeTicks::Now(); - } -} - -void InfoBarContainer::OverlayStateChanged(const InstantOverlayModel& model) { - // If suggestions are being shown on a |DEFAULT| page, hide the infobars now. - // See comments for ModeChanged() for explanation. - if (model.mode().is_search_suggestions() && - model.mode().is_origin_default()) { + } else if (!new_state.top_bars_visible && infobars_shown_) { HideAllInfoBars(); OnInfoBarStateChanged(false); } @@ -229,6 +219,8 @@ size_t InfoBarContainer::HideInfoBar(InfoBarDelegate* delegate, } void InfoBarContainer::HideAllInfoBars() { + registrar_.RemoveAll(); + infobars_shown_ = false; while (!infobars_.empty()) { InfoBar* infobar = infobars_.front(); diff --git a/chrome/browser/infobars/infobar_container.h b/chrome/browser/infobars/infobar_container.h index 896f112..da153a0ea 100644 --- a/chrome/browser/infobars/infobar_container.h +++ b/chrome/browser/infobars/infobar_container.h @@ -9,7 +9,6 @@ #include "base/compiler_specific.h" #include "base/time.h" -#include "chrome/browser/ui/search/instant_overlay_model_observer.h" #include "chrome/browser/ui/search/search_model_observer.h" #include "chrome/common/search_types.h" #include "content/public/browser/notification_observer.h" @@ -50,8 +49,7 @@ class SearchModel; // would re-show the infobars only to instantly animate them closed. The window // to re-hide infobars without animation is canceled if a tab change occurs. class InfoBarContainer : public content::NotificationObserver, - public chrome::search::SearchModelObserver, - public InstantOverlayModelObserver { + public chrome::search::SearchModelObserver { public: class Delegate { public: @@ -110,9 +108,6 @@ class InfoBarContainer : public content::NotificationObserver, const Delegate* delegate() const { return delegate_; } - // InstantOverlayModelObserver: - virtual void OverlayStateChanged(const InstantOverlayModel& model) OVERRIDE; - protected: // Subclasses must call this during destruction, so that we can remove // infobars (which will call the pure virtual functions below) while the @@ -135,8 +130,9 @@ class InfoBarContainer : public content::NotificationObserver, const content::NotificationDetails& details) OVERRIDE; // chrome::search::SearchModelObserver: - virtual void ModeChanged(const chrome::search::Mode& old_mode, - const chrome::search::Mode& new_mode) OVERRIDE; + virtual void ModelChanged( + const chrome::search::SearchModel::State& old_state, + const chrome::search::SearchModel::State& new_state) OVERRIDE; // Hides an InfoBar for the specified delegate, in response to a notification // from the selected InfoBarService. The InfoBar's disappearance will be diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index c34edf9..d16ac65 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -1225,20 +1225,6 @@ void Browser::ShowFirstRunBubble() { window()->GetLocationBar()->ShowFirstRunBubble(); } -void Browser::MaybeUpdateBookmarkBarStateForInstantOverlay( - const chrome::search::Mode& mode) { - // This is invoked by a platform-specific implementation of - // |InstantOverlayController| to update bookmark bar state according to - // Instant overlay state. - // ModeChanged() updates bookmark bar state for all mode transitions except - // when new mode is |SEARCH_SUGGESTIONS|, because that needs to be done when - // the suggestions are ready. - if (mode.is_search_suggestions() && - bookmark_bar_state_ == BookmarkBar::SHOW) { - UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TAB_STATE); - } -} - void Browser::ShowDownload(content::DownloadItem* download) { if (!window()) return; @@ -1814,22 +1800,13 @@ void Browser::Observe(int type, } } -void Browser::ModeChanged(const chrome::search::Mode& old_mode, - const chrome::search::Mode& new_mode) { - // If new mode is |SEARCH_SUGGESTIONS|, don't update bookmark bar state now; - // wait till the Instant overlay is ready to show suggestions before hiding - // the bookmark bar (in MaybeUpdateBookmarkBarStateForInstantOverlay()). - // TODO(kuan): but for now, only delay updating bookmark bar state if origin - // is |DEFAULT|; other origins require more complex logic to be implemented - // to prevent jankiness caused by hiding bookmark bar, so just hide the - // bookmark bar immediately and tolerate the jankiness for a while. - // For other mode transitions, update bookmark bar state accordingly. - if (new_mode.is_search_suggestions() && - new_mode.is_origin_default() && - bookmark_bar_state_ == BookmarkBar::SHOW) { - return; +void Browser::ModelChanged( + const chrome::search::SearchModel::State& old_state, + const chrome::search::SearchModel::State& new_state) { + if (chrome::search::SearchModel::ShouldChangeTopBarsVisibility(old_state, + new_state)) { + UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TAB_STATE); } - UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TAB_STATE); } /////////////////////////////////////////////////////////////////////////////// @@ -2139,16 +2116,22 @@ void Browser::UpdateBookmarkBarState(BookmarkBarStateChangeReason reason) { state = BookmarkBar::HIDDEN; } - // Don't allow the bookmark bar to be shown in suggestions mode. + // Bookmark bar may need to be hidden for |SEARCH_SUGGESTIONS| and + // |SEARCH_RESULTS| modes as per SearchBox API or Instant overlay or if it's + // detached. + // TODO(sail): remove conditional MACOSX flag when bookmark bar is actually + // hidden on mac; for now, mac keeps the bookmark bar shown but changes its + // z-order to stack it below contents. #if !defined(OS_MACOSX) - if (search_model_->mode().is_search_suggestions()) + if (search_model_->mode().is_search() && + (state == BookmarkBar::DETACHED || !search_model_->top_bars_visible())) { state = BookmarkBar::HIDDEN; -#endif - - // Don't allow detached bookmark bar to be shown in suggestions or results - // modes. + } +#else + // TODO(sail): remove this when the above block is enabled for mac. if (state == BookmarkBar::DETACHED && search_model_->mode().is_search()) state = BookmarkBar::HIDDEN; +#endif // !defined(OS_MACOSX) if (state == bookmark_bar_state_) return; diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index 35db7f3..280d58f 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h @@ -453,12 +453,6 @@ class Browser : public TabStripModelObserver, // Show the first run search engine bubble on the location bar. void ShowFirstRunBubble(); - // If necessary, update the bookmark bar state according to the Instant - // overlay state: when Instant overlay shows suggestions and bookmark bar is - // still showing attached, hide it. - void MaybeUpdateBookmarkBarStateForInstantOverlay( - const chrome::search::Mode& mode); - // Show a download on the download shelf. void ShowDownload(content::DownloadItem* download); @@ -680,8 +674,9 @@ class Browser : public TabStripModelObserver, const content::NotificationDetails& details) OVERRIDE; // Overridden from chrome::search::SearchModelObserver: - virtual void ModeChanged(const chrome::search::Mode& old_mode, - const chrome::search::Mode& new_mode) OVERRIDE; + virtual void ModelChanged( + const chrome::search::SearchModel::State& old_state, + const chrome::search::SearchModel::State& new_state) OVERRIDE; // Command and state updating /////////////////////////////////////////////// diff --git a/chrome/browser/ui/browser_instant_controller.cc b/chrome/browser/ui/browser_instant_controller.cc index ca47c0f..068aa504 100644 --- a/chrome/browser/ui/browser_instant_controller.cc +++ b/chrome/browser/ui/browser_instant_controller.cc @@ -236,8 +236,14 @@ void BrowserInstantController::ResetInstant(const std::string& pref_name) { //////////////////////////////////////////////////////////////////////////////// // BrowserInstantController, search::SearchModelObserver implementation: -void BrowserInstantController::ModeChanged(const search::Mode& old_mode, - const search::Mode& new_mode) { +void BrowserInstantController::ModelChanged( + const search::SearchModel::State& old_state, + const search::SearchModel::State& new_state) { + if (old_state.mode == new_state.mode) + return; + + const search::Mode& new_mode = new_state.mode; + if (search::IsInstantExtendedAPIEnabled()) { // Record some actions corresponding to the mode change. Note that to get // the full story, it's necessary to look at other UMA actions as well, @@ -252,7 +258,7 @@ void BrowserInstantController::ModeChanged(const search::Mode& old_mode, if (new_mode.is_ntp()) UpdateThemeInfo(); - instant_.SearchModeChanged(old_mode, new_mode); + instant_.SearchModeChanged(old_state.mode, new_mode); } //////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/ui/browser_instant_controller.h b/chrome/browser/ui/browser_instant_controller.h index f6d2bde..3708669 100644 --- a/chrome/browser/ui/browser_instant_controller.h +++ b/chrome/browser/ui/browser_instant_controller.h @@ -111,8 +111,9 @@ class BrowserInstantController : public content::NotificationObserver, void ResetInstant(const std::string& pref_name); // Overridden from search::SearchModelObserver: - virtual void ModeChanged(const search::Mode& old_mode, - const search::Mode& new_mode) OVERRIDE; + virtual void ModelChanged( + const search::SearchModel::State& old_state, + const search::SearchModel::State& new_state) OVERRIDE; // content::NotificationObserver implementation. virtual void Observe(int type, diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h index 8ce489a0..1ddc053 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.h +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h @@ -149,8 +149,9 @@ class BrowserWindowCocoa : GetActiveTabPermissionGranter() OVERRIDE; // Overridden from chrome::search::SearchModelObserver: - virtual void ModeChanged(const chrome::search::Mode& old_mode, - const chrome::search::Mode& new_mode) OVERRIDE; + virtual void ModelChanged( + const chrome::search::SearchModel::State& old_state, + const chrome::search::SearchModel::State& new_state) OVERRIDE; // Adds the given FindBar cocoa controller to this browser window. void AddFindBar(FindBarCocoaController* find_bar_cocoa_controller); diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index 6a0f839..2dd1dbc 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm @@ -665,9 +665,9 @@ extensions::ActiveTabPermissionGranter* return tab_helper ? tab_helper->active_tab_permission_granter() : NULL; } -void BrowserWindowCocoa::ModeChanged( - const chrome::search::Mode& old_mode, - const chrome::search::Mode& new_mode) { +void BrowserWindowCocoa::ModelChanged( + const chrome::search::SearchModel::State& old_state, + const chrome::search::SearchModel::State& new_state) { [controller_ updateBookmarkBarStateForInstantOverlay]; } diff --git a/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.mm b/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.mm index 13bad50..68006c7 100644 --- a/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.mm +++ b/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.mm @@ -2,11 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h" + +#include "chrome/browser/search/search.h" #include "chrome/browser/ui/browser.h" #import "chrome/browser/ui/cocoa/browser_window_controller.h" #include "chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h" #import "chrome/browser/ui/cocoa/tab_contents/overlayable_contents_controller.h" #include "chrome/browser/ui/search/instant_overlay_model.h" +#include "chrome/browser/ui/search/search_model.h" +#include "chrome/browser/ui/search/search_tab_helper.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" InstantOverlayControllerMac::InstantOverlayControllerMac( Browser* browser, @@ -22,6 +28,11 @@ InstantOverlayControllerMac::~InstantOverlayControllerMac() { void InstantOverlayControllerMac::OverlayStateChanged( const InstantOverlayModel& model) { + // TODO(sail): migrate from InstantOverlayControllerViews::OverlayStateChanged + // to only call SetTopBarsVisible if we did something with overlay; this + // prevents the top bars from flashing in this transition + // DEFAULT->SUGGESTIONS->SERP. + bool has_overlay = false; if (model.mode().is_ntp() || model.mode().is_search_suggestions()) { // Drop shadow is only needed if search mode is not |NTP| and overlay does // not fill up the entire contents page. @@ -32,12 +43,24 @@ void InstantOverlayControllerMac::OverlayStateChanged( height:model.height() heightUnits:model.height_units() drawDropShadow:drawDropShadow]; + has_overlay = true; } else { [overlay_ setOverlay:NULL height:0 heightUnits:INSTANT_SIZE_PIXELS drawDropShadow:NO]; } - browser_->MaybeUpdateBookmarkBarStateForInstantOverlay(model.mode()); + + if (chrome::search::IsInstantExtendedAPIEnabled()) { + // Set top bars (bookmark and info bars) visibility for current tab via + // |SearchTabHelper| of current active web contents: top bars are hidden if + // there's overlay. + chrome::search::SearchTabHelper* search_tab_helper = + chrome::search::SearchTabHelper::FromWebContents( + browser_->tab_strip_model()->GetActiveWebContents()); + if (search_tab_helper) + search_tab_helper->model()->SetTopBarsVisible(!has_overlay); + } + [window_ updateBookmarkBarStateForInstantOverlay]; } diff --git a/chrome/browser/ui/search/search_delegate.cc b/chrome/browser/ui/search/search_delegate.cc index 6e437c0..6c0ec71 100644 --- a/chrome/browser/ui/search/search_delegate.cc +++ b/chrome/browser/ui/search/search_delegate.cc @@ -20,8 +20,9 @@ SearchDelegate::~SearchDelegate() { DCHECK(!tab_model_) << "All tabs should have been deactivated or closed."; } -void SearchDelegate::ModeChanged(const Mode& old_mode, const Mode& new_mode) { - browser_model_->SetMode(new_mode); +void SearchDelegate::ModelChanged(const SearchModel::State& old_state, + const SearchModel::State& new_state) { + browser_model_->SetState(new_state); } void SearchDelegate::OnTabActivated(content::WebContents* web_contents) { @@ -29,7 +30,7 @@ void SearchDelegate::OnTabActivated(content::WebContents* web_contents) { tab_model_->RemoveObserver(this); tab_model_ = chrome::search::SearchTabHelper::FromWebContents(web_contents)->model(); - browser_model_->SetMode(tab_model_->mode()); + browser_model_->SetState(tab_model_->state()); tab_model_->AddObserver(this); } diff --git a/chrome/browser/ui/search/search_delegate.h b/chrome/browser/ui/search/search_delegate.h index f88e291..11b105c 100644 --- a/chrome/browser/ui/search/search_delegate.h +++ b/chrome/browser/ui/search/search_delegate.h @@ -33,7 +33,8 @@ class SearchDelegate : public SearchModelObserver { virtual ~SearchDelegate(); // Overrides for SearchModelObserver: - virtual void ModeChanged(const Mode& old_mode, const Mode& new_mode) OVERRIDE; + virtual void ModelChanged(const SearchModel::State& old_state, + const SearchModel::State& new_state) OVERRIDE; // When the active tab is changed, the model state of this new active tab is // propagated to the browser. diff --git a/chrome/browser/ui/search/search_model.cc b/chrome/browser/ui/search/search_model.cc index b1830e6..6637b8f 100644 --- a/chrome/browser/ui/search/search_model.cc +++ b/chrome/browser/ui/search/search_model.cc @@ -16,19 +16,68 @@ SearchModel::SearchModel() { SearchModel::~SearchModel() { } +// static. +bool SearchModel::ShouldChangeTopBarsVisibility(const State& old_state, + const State& new_state) { + // If mode has changed, only change top bars visibility if new mode is not + // |SEARCH_SUGGESTIONS| or |SEARCH_RESULTS|. Top bars visibility for + // these 2 modes is determined when the mode stays the same, and: + // - for |NTP/SERP| pages: by SearchBox API, or + // - for |DEFAULT| pages: by platform-specific implementation of + // |InstantOverlayController| when it shows/hides the Instant overlay. + return old_state.mode != new_state.mode ? + !new_state.mode.is_search() : new_state.mode.is_search(); +} + +void SearchModel::SetState(const State& new_state) { + DCHECK(IsInstantExtendedAPIEnabled()) + << "Please do not try to set the SearchModel mode without first " + << "checking if Search is enabled."; + + if (state_ == new_state) + return; + + const State old_state = state_; + state_ = new_state; + + FOR_EACH_OBSERVER(SearchModelObserver, observers_, + ModelChanged(old_state, state_)); +} + void SearchModel::SetMode(const Mode& new_mode) { DCHECK(IsInstantExtendedAPIEnabled()) << "Please do not try to set the SearchModel mode without first " << "checking if Search is enabled."; - if (mode_ == new_mode) + if (state_.mode == new_mode) + return; + + const State old_state = state_; + state_.mode = new_mode; + + // For |SEARCH_SUGGESTIONS| and |SEARCH_RESULTS| modes, SearchBox API will + // determine visibility of top bars via SetTopBarsVisible(); for other modes, + // top bars are always visible, if available. + if (!state_.mode.is_search()) + state_.top_bars_visible = true; + + FOR_EACH_OBSERVER(SearchModelObserver, observers_, + ModelChanged(old_state, state_)); +} + +void SearchModel::SetTopBarsVisible(bool visible) { + DCHECK(IsInstantExtendedAPIEnabled()) + << "Please do not try to set the SearchModel mode without first " + << "checking if Search is enabled."; + + if (state_.top_bars_visible == visible) return; - const Mode old_mode = mode_; - mode_ = new_mode; + const State old_state = state_; + state_.top_bars_visible = visible; FOR_EACH_OBSERVER(SearchModelObserver, observers_, - ModeChanged(old_mode, mode_)); + ModelChanged(old_state, state_)); } void SearchModel::AddObserver(SearchModelObserver* observer) { diff --git a/chrome/browser/ui/search/search_model.h b/chrome/browser/ui/search/search_model.h index 6a7f1f1..44322a6 100644 --- a/chrome/browser/ui/search/search_model.h +++ b/chrome/browser/ui/search/search_model.h @@ -18,23 +18,52 @@ class SearchModelObserver; // changes. class SearchModel { public: + struct State { + State() : top_bars_visible(true) {} + + bool operator==(const State& rhs) const { + return mode == rhs.mode && top_bars_visible == rhs.top_bars_visible; + } + + // The display mode of UI elements such as the toolbar, the tab strip, etc. + Mode mode; + // The visibility of top bars such as bookmark and info bars. + bool top_bars_visible; + }; + SearchModel(); ~SearchModel(); - // Change the mode. Change notifications are sent to observers. An animated - // transition may be requested. + // Returns true if visibility in top bars should be changed based on + // |old_state| and |new_state|. + static bool ShouldChangeTopBarsVisibility(const State& old_state, + const State& new_state); + + // Change the state. Change notifications are sent to observers. + void SetState(const State& state); + + // Get the current state. + const State& state() const { return state_; } + + // Change the mode. Change notifications are sent to observers. void SetMode(const Mode& mode); // Get the active mode. - const Mode& mode() const { return mode_; } + const Mode& mode() const { return state_.mode; } + + // Set visibility of top bars. Change notifications are sent to observers. + void SetTopBarsVisible(bool visible); + + // Get the visibility of top bars. + bool top_bars_visible() const { return state_.top_bars_visible; } // Add and remove observers. void AddObserver(SearchModelObserver* observer); void RemoveObserver(SearchModelObserver* observer); private: - // The display mode of UI elements such as the toolbar, the tab strip, etc. - Mode mode_; + // Current state of model. + State state_; // Observers. ObserverList<SearchModelObserver> observers_; diff --git a/chrome/browser/ui/search/search_model_observer.h b/chrome/browser/ui/search/search_model_observer.h index 970bba8..200356b 100644 --- a/chrome/browser/ui/search/search_model_observer.h +++ b/chrome/browser/ui/search/search_model_observer.h @@ -5,16 +5,17 @@ #ifndef CHROME_BROWSER_UI_SEARCH_SEARCH_MODEL_OBSERVER_H_ #define CHROME_BROWSER_UI_SEARCH_SEARCH_MODEL_OBSERVER_H_ +#include "chrome/browser/ui/search/search_model.h" + namespace chrome { namespace search { -struct Mode; - // This class defines the observer interface for the |SearchModel|. class SearchModelObserver { public: - // Informs the observer that the mode has changed. - virtual void ModeChanged(const Mode& old_mode, const Mode& new_mode) = 0; + // Informs the observer that the model's state has changed. + virtual void ModelChanged(const SearchModel::State& old_state, + const SearchModel::State& new_state) = 0; protected: virtual ~SearchModelObserver() {} diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc index cece414..d28404f 100644 --- a/chrome/browser/ui/search/search_tab_helper.cc +++ b/chrome/browser/ui/search/search_tab_helper.cc @@ -5,6 +5,7 @@ #include "chrome/browser/ui/search/search_tab_helper.h" #include "chrome/browser/search/search.h" +#include "chrome/common/render_messages.h" #include "chrome/common/url_constants.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_service.h" @@ -35,7 +36,8 @@ namespace chrome { namespace search { SearchTabHelper::SearchTabHelper(content::WebContents* web_contents) - : is_search_enabled_(chrome::search::IsInstantExtendedAPIEnabled()), + : WebContentsObserver(web_contents), + is_search_enabled_(chrome::search::IsInstantExtendedAPIEnabled()), user_input_in_progress_(false), web_contents_(web_contents) { if (!is_search_enabled_) @@ -60,14 +62,14 @@ void SearchTabHelper::OmniboxEditModelChanged(bool user_input_in_progress, if (!user_input_in_progress && !cancelling) return; - UpdateModel(); + UpdateMode(); } void SearchTabHelper::NavigationEntryUpdated() { if (!is_search_enabled_) return; - UpdateModel(); + UpdateMode(); } void SearchTabHelper::Observe( @@ -75,10 +77,22 @@ void SearchTabHelper::Observe( const content::NotificationSource& source, const content::NotificationDetails& details) { DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type); - UpdateModel(); + UpdateMode(); } -void SearchTabHelper::UpdateModel() { +bool SearchTabHelper::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(SearchTabHelper, message) + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxShowBars, + OnSearchBoxShowBars) + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxHideBars, + OnSearchBoxHideBars) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void SearchTabHelper::UpdateMode() { Mode::Type type = Mode::MODE_DEFAULT; Mode::Origin origin = Mode::ORIGIN_DEFAULT; if (IsNTP(web_contents_)) { @@ -93,5 +107,17 @@ void SearchTabHelper::UpdateModel() { model_.SetMode(Mode(type, origin)); } +void SearchTabHelper::OnSearchBoxShowBars(int page_id) { + if (web_contents()->IsActiveEntry(page_id)) + model_.SetTopBarsVisible(true); +} + +void SearchTabHelper::OnSearchBoxHideBars(int page_id) { + if (web_contents()->IsActiveEntry(page_id)) { + model_.SetTopBarsVisible(false); + Send(new ChromeViewMsg_SearchBoxBarsHidden(routing_id())); + } +} + } // namespace search } // namespace chrome diff --git a/chrome/browser/ui/search/search_tab_helper.h b/chrome/browser/ui/search/search_tab_helper.h index 7034705..e575dc2 100644 --- a/chrome/browser/ui/search/search_tab_helper.h +++ b/chrome/browser/ui/search/search_tab_helper.h @@ -10,6 +10,7 @@ #include "chrome/browser/ui/search/search_model.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" namespace content { @@ -22,6 +23,7 @@ namespace search { // Per-tab search "helper". Acts as the owner and controller of the tab's // search UI model. class SearchTabHelper : public content::NotificationObserver, + public content::WebContentsObserver, public content::WebContentsUserData<SearchTabHelper> { public: virtual ~SearchTabHelper(); @@ -50,8 +52,16 @@ class SearchTabHelper : public content::NotificationObserver, const content::NotificationSource& source, const content::NotificationDetails& details) OVERRIDE; + // Overridden from contents::WebContentsObserver: + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + // Sets the mode of the model based on the current URL of web_contents(). - void UpdateModel(); + void UpdateMode(); + + // Handlers for SearchBox API to show and hide top bars (bookmark and info + // bars). + void OnSearchBoxShowBars(int page_id); + void OnSearchBoxHideBars(int page_id); const bool is_search_enabled_; diff --git a/chrome/browser/ui/views/frame/instant_overlay_controller_views.cc b/chrome/browser/ui/views/frame/instant_overlay_controller_views.cc index 097d415..0478599 100644 --- a/chrome/browser/ui/views/frame/instant_overlay_controller_views.cc +++ b/chrome/browser/ui/views/frame/instant_overlay_controller_views.cc @@ -5,8 +5,12 @@ #include "chrome/browser/ui/views/frame/instant_overlay_controller_views.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search/search.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/search/instant_overlay_model.h" +#include "chrome/browser/ui/search/search_model.h" +#include "chrome/browser/ui/search/search_tab_helper.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/contents_container.h" @@ -25,6 +29,10 @@ InstantOverlayControllerViews::~InstantOverlayControllerViews() { void InstantOverlayControllerViews::OverlayStateChanged( const InstantOverlayModel& model) { + // Set top bars (bookmark and info bars) visibility if Instant Extended API + // is enabled. + bool set_top_bars_visibility = chrome::search::IsInstantExtendedAPIEnabled(); + if (model.mode().is_ntp() || model.mode().is_search_suggestions()) { // Show the overlay. if (!overlay_) { @@ -44,18 +52,26 @@ void InstantOverlayControllerViews::OverlayStateChanged( overlay_->SetWebContents(NULL); contents_->SetOverlay(NULL, NULL, 100, INSTANT_SIZE_PERCENT, false); overlay_.reset(); + } else { + // Don't set top bars visiblility if nothing was done with overlay. + set_top_bars_visibility = false; } - browser_->MaybeUpdateBookmarkBarStateForInstantOverlay(model.mode()); + if (set_top_bars_visibility) { + // Set top bars visibility for current tab via |SearchTabHelper| of current + // active web contents: top bars are hidden if there's overlay. + chrome::search::SearchTabHelper* search_tab_helper = + chrome::search::SearchTabHelper::FromWebContents( + browser_->tab_strip_model()->GetActiveWebContents()); + if (search_tab_helper) + search_tab_helper->model()->SetTopBarsVisible(!overlay_); + } // If an Instant overlay is added during an immersive mode reveal, the reveal // view needs to stay on top. - // Notify infobar container of change in overlay state. if (overlay_) { BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_); - if (browser_view) { + if (browser_view) browser_view->MaybeStackImmersiveRevealAtTop(); - browser_view->infobar_container()->OverlayStateChanged(model); - } } } diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index bdc6beb..7b420ef 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -312,6 +312,8 @@ IPC_MESSAGE_ROUTED2(ChromeViewMsg_SearchBoxMarginChange, int /* start */, int /* end */) +IPC_MESSAGE_ROUTED0(ChromeViewMsg_SearchBoxBarsHidden) + IPC_MESSAGE_ROUTED0(ChromeViewMsg_DetermineIfPageSupportsInstant) IPC_MESSAGE_ROUTED1(ChromeViewMsg_SearchBoxAutocompleteResults, @@ -698,6 +700,14 @@ IPC_MESSAGE_ROUTED3(ChromeViewHostMsg_ShowInstantOverlay, IPC_MESSAGE_ROUTED1(ChromeViewHostMsg_FocusOmnibox, int /* page_id */) +// Sent by Instant to show any attached bars. +IPC_MESSAGE_ROUTED1(ChromeViewHostMsg_SearchBoxShowBars, + int /* page_id */) + +// Sent by Instant to hide any attached bars. +IPC_MESSAGE_ROUTED1(ChromeViewHostMsg_SearchBoxHideBars, + int /* page_id */) + IPC_MESSAGE_ROUTED1(ChromeViewHostMsg_StartCapturingKeyStrokes, int /* page_id */) diff --git a/chrome/common/search_types.h b/chrome/common/search_types.h index 04d64b6..5fb85e7 100644 --- a/chrome/common/search_types.h +++ b/chrome/common/search_types.h @@ -50,6 +50,10 @@ struct Mode { return mode == rhs.mode && origin == rhs.origin; } + bool operator!=(const Mode& rhs) const { + return !(*this == rhs); + } + bool is_default() const { return mode == MODE_DEFAULT; } diff --git a/chrome/renderer/resources/extensions/searchbox_api.js b/chrome/renderer/resources/extensions/searchbox_api.js index f93a54c..cb9524b 100644 --- a/chrome/renderer/resources/extensions/searchbox_api.js +++ b/chrome/renderer/resources/extensions/searchbox_api.js @@ -105,6 +105,8 @@ if (!chrome.embeddedSearch) { native function StartCapturingKeyStrokes(); native function StopCapturingKeyStrokes(); native function NavigateSearchBox(); + native function ShowBars(); + native function HideBars(); function SafeWrapSuggestion(restrictedText) { return SafeWrap(restrictedText, window.innerWidth - 155, 22); @@ -270,6 +272,12 @@ if (!chrome.embeddedSearch) { this.navigateContentWindow = function(destination, disposition) { NavigateSearchBox(destination, disposition); } + this.showBars = function() { + ShowBars(); + }; + this.hideBars = function() { + HideBars(); + }; this.onchange = null; this.onsubmit = null; this.oncancel = null; @@ -278,6 +286,7 @@ if (!chrome.embeddedSearch) { this.onkeycapturechange = null; this.onmarginchange = null; this.onnativesuggestions = null; + this.onbarshidden = null; // DEPRECATED. These methods are from the legacy searchbox API. // TODO(jered): Delete these. diff --git a/chrome/renderer/searchbox/searchbox.cc b/chrome/renderer/searchbox/searchbox.cc index fda2c68..348e894 100644 --- a/chrome/renderer/searchbox/searchbox.cc +++ b/chrome/renderer/searchbox/searchbox.cc @@ -91,6 +91,18 @@ void SearchBox::UndoAllMostVisitedDeletions() { render_view()->GetRoutingID())); } +void SearchBox::ShowBars() { + DVLOG(1) << render_view() << " ShowBars"; + render_view()->Send(new ChromeViewHostMsg_SearchBoxShowBars( + render_view()->GetRoutingID(), render_view()->GetPageId())); +} + +void SearchBox::HideBars() { + DVLOG(1) << render_view() << " HideBars"; + render_view()->Send(new ChromeViewHostMsg_SearchBoxHideBars( + render_view()->GetRoutingID(), render_view()->GetPageId())); +} + int SearchBox::GetStartMargin() const { return static_cast<int>(start_margin_ / GetZoom()); } @@ -135,6 +147,7 @@ bool SearchBox::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxCancel, OnCancel) IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxPopupResize, OnPopupResize) IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxMarginChange, OnMarginChange) + IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxBarsHidden, OnBarsHidden) IPC_MESSAGE_HANDLER(ChromeViewMsg_DetermineIfPageSupportsInstant, OnDetermineIfPageSupportsInstant) IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxAutocompleteResults, @@ -225,6 +238,13 @@ void SearchBox::OnMarginChange(int margin, int width) { } } +void SearchBox::OnBarsHidden() { + if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { + extensions_v8::SearchBoxExtension::DispatchBarsHidden( + render_view()->GetWebView()->mainFrame()); + } +} + void SearchBox::OnDetermineIfPageSupportsInstant() { if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { bool result = extensions_v8::SearchBoxExtension::PageSupportsInstant( diff --git a/chrome/renderer/searchbox/searchbox.h b/chrome/renderer/searchbox/searchbox.h index cd94f0c..1243318 100644 --- a/chrome/renderer/searchbox/searchbox.h +++ b/chrome/renderer/searchbox/searchbox.h @@ -61,6 +61,13 @@ class SearchBox : public content::RenderViewObserver, // browser. void UndoAllMostVisitedDeletions(); + // Shows any attached bars. + void ShowBars(); + + // Hides any attached bars. When the bars are hidden, the "onbarshidden" + // event is fired to notify the page. + void HideBars(); + const string16& query() const { return query_; } bool verbatim() const { return verbatim_; } size_t selection_start() const { return selection_start_; } @@ -100,6 +107,7 @@ class SearchBox : public content::RenderViewObserver, void OnCancel(const string16& query); void OnPopupResize(const gfx::Rect& bounds); void OnMarginChange(int margin, int width); + void OnBarsHidden(); void OnDetermineIfPageSupportsInstant(); void OnAutocompleteResults( const std::vector<InstantAutocompleteResult>& results); diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc index a31b7de..bed2567 100644 --- a/chrome/renderer/searchbox/searchbox_extension.cc +++ b/chrome/renderer/searchbox/searchbox_extension.cc @@ -239,6 +239,15 @@ static const char kDispatchMostVisitedChangedScript[] = " true;" "}"; +static const char kDispatchBarsHiddenEventScript[] = + "if (window.chrome &&" + " window.chrome.searchBox &&" + " window.chrome.searchBox.onbarshidden &&" + " typeof window.chrome.searchBox.onbarshidden == 'function') {" + " window.chrome.searchBox.onbarshidden();" + " true;" + "}"; + // ---------------------------------------------------------------------------- class SearchBoxExtensionWrapper : public v8::Extension { @@ -365,6 +374,13 @@ class SearchBoxExtensionWrapper : public v8::Extension { static v8::Handle<v8::Value> UndoMostVisitedDeletion( const v8::Arguments& args); + // Shows any attached bars. + static v8::Handle<v8::Value> ShowBars(const v8::Arguments& args); + + // Hides any attached bars. When the bars are hidden, the "onbarshidden" + // event is fired to notify the page. + static v8::Handle<v8::Value> HideBars(const v8::Arguments& args); + private: DISALLOW_COPY_AND_ASSIGN(SearchBoxExtensionWrapper); }; @@ -440,6 +456,10 @@ v8::Handle<v8::FunctionTemplate> SearchBoxExtensionWrapper::GetNativeFunction( return v8::FunctionTemplate::New(UndoAllMostVisitedDeletions); if (name->Equals(v8::String::New("UndoMostVisitedDeletion"))) return v8::FunctionTemplate::New(UndoMostVisitedDeletion); + if (name->Equals(v8::String::New("ShowBars"))) + return v8::FunctionTemplate::New(ShowBars); + if (name->Equals(v8::String::New("HideBars"))) + return v8::FunctionTemplate::New(HideBars); return v8::Handle<v8::FunctionTemplate>(); } @@ -1099,6 +1119,27 @@ bool SearchBoxExtension::PageSupportsInstant(WebKit::WebFrame* frame) { return !v.IsEmpty() && v->BooleanValue(); } +v8::Handle<v8::Value> SearchBoxExtensionWrapper::ShowBars( + const v8::Arguments& args) { + content::RenderView* render_view = GetRenderView(); + if (!render_view) return v8::Undefined(); + + DVLOG(1) << render_view << " ShowBars"; + SearchBox::Get(render_view)->ShowBars(); + return v8::Undefined(); +} + +// static +v8::Handle<v8::Value> SearchBoxExtensionWrapper::HideBars( + const v8::Arguments& args) { + content::RenderView* render_view = GetRenderView(); + if (!render_view) return v8::Undefined(); + + DVLOG(1) << render_view << " HideBars"; + SearchBox::Get(render_view)->HideBars(); + return v8::Undefined(); +} + // static void SearchBoxExtension::DispatchChange(WebKit::WebFrame* frame) { Dispatch(frame, kDispatchChangeEventScript); @@ -1163,4 +1204,9 @@ void SearchBoxExtension::DispatchMostVisitedChanged( WebKit::WebFrame* frame) { Dispatch(frame, kDispatchMostVisitedChangedScript); } + +void SearchBoxExtension::DispatchBarsHidden(WebKit::WebFrame* frame) { + Dispatch(frame, kDispatchBarsHiddenEventScript); +} + } // namespace extensions_v8 diff --git a/chrome/renderer/searchbox/searchbox_extension.h b/chrome/renderer/searchbox/searchbox_extension.h index addaa0b..517c69f 100644 --- a/chrome/renderer/searchbox/searchbox_extension.h +++ b/chrome/renderer/searchbox/searchbox_extension.h @@ -40,6 +40,7 @@ class SearchBoxExtension { static void DispatchKeyCaptureChange(WebKit::WebFrame* frame); static void DispatchMarginChange(WebKit::WebFrame* frame); static void DispatchThemeChange(WebKit::WebFrame* frame); + static void DispatchBarsHidden(WebKit::WebFrame* frame); // New Tab Page API. static void DispatchMostVisitedChanged(WebKit::WebFrame* frame); |