diff options
author | samarth@chromium.org <samarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-17 22:44:47 +0000 |
---|---|---|
committer | samarth@chromium.org <samarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-17 22:44:47 +0000 |
commit | 03bb71001fa5ec1a6fca64c8461b8df6d81c993d (patch) | |
tree | b698fbe506698d087d5dfbe7a6a7d6c8952ad6be /chrome/browser/ui/search/instant_controller.h | |
parent | 373c09e1076f3a77e61ef46c97b4a01b74965049 (diff) | |
download | chromium_src-03bb71001fa5ec1a6fca64c8461b8df6d81c993d.zip chromium_src-03bb71001fa5ec1a6fca64c8461b8df6d81c993d.tar.gz chromium_src-03bb71001fa5ec1a6fca64c8461b8df6d81c993d.tar.bz2 |
Move desktop-specific Instant bits to c/b/ui/search.
This is part 2 of the cleanup described in the attached bug.
Also, added sreeram to c/b/ui/search/OWNERS and dhollowa to c/b/instant/OWNERS.
BUG=179184
Review URL: https://chromiumcodereview.appspot.com/12520005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188656 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/ui/search/instant_controller.h')
-rw-r--r-- | chrome/browser/ui/search/instant_controller.h | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/chrome/browser/ui/search/instant_controller.h b/chrome/browser/ui/search/instant_controller.h new file mode 100644 index 0000000..4c5ceb5 --- /dev/null +++ b/chrome/browser/ui/search/instant_controller.h @@ -0,0 +1,468 @@ +// Copyright 2012 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 CHROME_BROWSER_UI_SEARCH_INSTANT_CONTROLLER_H_ +#define CHROME_BROWSER_UI_SEARCH_INSTANT_CONTROLLER_H_ + +#include <list> +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include "base/basictypes.h" +#include "base/gtest_prod_util.h" +#include "base/memory/scoped_ptr.h" +#include "base/string16.h" +#include "base/time.h" +#include "base/timer.h" +#include "chrome/browser/history/history_types.h" +#include "chrome/browser/ui/omnibox/omnibox_edit_model.h" +#include "chrome/browser/ui/search/instant_commit_type.h" +#include "chrome/browser/ui/search/instant_overlay_model.h" +#include "chrome/browser/ui/search/instant_page.h" +#include "chrome/common/instant_types.h" +#include "chrome/common/search_types.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" +#include "content/public/common/page_transition_types.h" +#include "googleurl/src/gurl.h" +#include "ui/base/window_open_disposition.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gfx/rect.h" + +struct AutocompleteMatch; +class AutocompleteProvider; +class InstantNTP; +class InstantOverlay; +class InstantTab; +class TemplateURL; + +namespace chrome { +class BrowserInstantController; +} + +namespace content { +class WebContents; +} + +// Macro used for logging debug events. |message| should be a std::string. +#define LOG_INSTANT_DEBUG_EVENT(controller, message) \ + controller->LogDebugEvent(message) + +// InstantController drives Chrome Instant, i.e., the browser implementation of +// the Embedded Search API (see http://dev.chromium.org/embeddedsearch). +// +// In extended mode, InstantController maintains and coordinates three +// instances of InstantPage: +// (1) An InstantOverlay instance that is used to show search suggestions and +// results in an overlay over a non-search page. +// (2) An InstantNTP instance which is a preloaded search page that will be +// swapped-in the next time the user navigates to the New Tab Page. It is +// never shown to the user in an uncommitted state. +// (3) An InstantTab instance which points to the currently active tab, if it +// supports the Embedded Search API. +// +// All three are backed by a WebContents. InstantOverlay and InstantNTP own +// their corresponding WebContents; InstantTab does not. In non-extended mode, +// only an InstantOverlay instance is kept. +// +// InstantController is owned by Browser via BrowserInstantController. +class InstantController : public InstantPage::Delegate, + public content::NotificationObserver { + public: + InstantController(chrome::BrowserInstantController* browser, + bool extended_enabled); + virtual ~InstantController(); + + // Invoked as the user types into the omnibox. |user_text| is what the user + // has typed. |full_text| is what the omnibox is showing. These may differ if + // the user typed only some text, and the rest was inline autocompleted. If + // |verbatim| is true, search results are shown for the exact omnibox text, + // rather than the best guess as to what the user means. Returns true if the + // update is accepted (i.e., if |match| is a search rather than a URL). + // |is_keyword_search| is true if keyword searching is in effect. + bool Update(const AutocompleteMatch& match, + const string16& user_text, + const string16& full_text, + size_t selection_start, + size_t selection_end, + bool verbatim, + bool user_input_in_progress, + bool omnibox_popup_is_open, + bool escape_pressed, + bool is_keyword_search); + + // Releases and returns the NTP WebContents. May be NULL. Loads a new + // WebContents for the NTP. + scoped_ptr<content::WebContents> ReleaseNTPContents() WARN_UNUSED_RESULT; + + // Sets the bounds of the omnibox popup, in screen coordinates. + void SetPopupBounds(const gfx::Rect& bounds); + + // Sets the stored start-edge margin and width of the omnibox. + void SetOmniboxBounds(const gfx::Rect& bounds); + + // Send autocomplete results from |providers| to the overlay page. + void HandleAutocompleteResults( + const std::vector<AutocompleteProvider*>& providers); + + // Called when the user presses up or down. |count| is a repeat count, + // negative for moving up, positive for moving down. Returns true if Instant + // handled the key press. + bool OnUpOrDownKeyPressed(int count); + + // Called when the user has arrowed into the suggestions but wants to cancel, + // typically by pressing ESC. The omnibox text is expected to have been + // reverted to |full_text| by the OmniboxEditModel prior to calling this. + // |match| is the match reverted to. + void OnCancel(const AutocompleteMatch& match, + const string16& user_text, + const string16& full_text); + + // The overlay WebContents. May be NULL. InstantController retains ownership. + content::WebContents* GetOverlayContents() const; + + // Returns true if Instant is showing a search results overlay. Returns false + // if the overlay is not showing, or if it's showing only suggestions. + bool IsOverlayingSearchResults() const; + + // If the overlay is showing search results, commits the overlay, calling + // CommitInstant() on the browser, and returns true. Else, returns false. + bool CommitIfPossible(InstantCommitType type); + + // Called to indicate that the omnibox focus state changed with the given + // |reason|. If |focus_state| is FOCUS_NONE, |view_gaining_focus| is set to + // the view gaining focus. + void OmniboxFocusChanged(OmniboxFocusState focus_state, + OmniboxFocusChangeReason reason, + gfx::NativeView view_gaining_focus); + + // The search mode in the active tab has changed. Pass the message down to + // the overlay which will notify the renderer. Create |instant_tab_| if the + // |new_mode| reflects an Instant search results page. + void SearchModeChanged(const chrome::search::Mode& old_mode, + const chrome::search::Mode& new_mode); + + // The user switched tabs. Hide the overlay. Create |instant_tab_| if the + // newly active tab is an Instant search results page. + void ActiveTabChanged(); + + // The user is about to switch tabs. Commit the overlay if needed. + void TabDeactivated(content::WebContents* contents); + + // Sets whether Instant should show result overlays. |use_local_overlay_only| + // will force the use of kLocalOmniboxPopupURL as the Instant URL and is only + // applicable if |extended_enabled_| is true. + void SetInstantEnabled(bool instant_enabled, bool use_local_overlay_only); + + // The theme has changed. Pass the message to the overlay page. + void ThemeChanged(const ThemeBackgroundInfo& theme_info); + + // Called when someone else swapped in a different contents in the |overlay_|. + void SwappedOverlayContents(); + + // Called when contents for |overlay_| received focus. + void FocusedOverlayContents(); + + // Called when the |overlay_| might be stale. If it's actually stale, and the + // omnibox doesn't have focus, and the overlay isn't showing, the |overlay_| + // is deleted and recreated. Else the refresh is skipped. + void ReloadOverlayIfStale(); + + // Called when the |overlay_|'s main frame has finished loading. + void OverlayLoadCompletedMainFrame(); + + // Adds a new event to |debug_events_| and also DVLOG's it. Ensures that + // |debug_events_| doesn't get too large. + void LogDebugEvent(const std::string& info) const; + + // Resets list of debug events. + void ClearDebugEvents(); + + // See comments for |debug_events_| below. + const std::list<std::pair<int64, std::string> >& debug_events() { + return debug_events_; + } + + // Returns the transition type of the last AutocompleteMatch passed to Update. + content::PageTransition last_transition_type() const { + return last_transition_type_; + } + + // Non-const for Add/RemoveObserver only. Other model changes should only + // happen through the InstantController interface. + InstantOverlayModel* model() { return &model_; } + + private: + FRIEND_TEST_ALL_PREFIXES(InstantTest, OmniboxFocusLoadsInstant); + FRIEND_TEST_ALL_PREFIXES(InstantTest, SetWithTemplateURL); + FRIEND_TEST_ALL_PREFIXES(InstantTest, NonInstantSearchProvider); + FRIEND_TEST_ALL_PREFIXES(InstantTest, InstantOverlayRefresh); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, ExtendedModeIsOn); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, MostVisited); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, RestrictedItemReadback); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, OmniboxFocusLoadsInstant); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, + OmniboxTextUponFocusedCommittedSERP); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, + MiddleClickOnSuggestionOpensInNewTab); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, NTPIsPreloaded); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, PreloadedNTPIsUsedInNewTab); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, PreloadedNTPIsUsedInSameTab); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, ProcessIsolation); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, UnrelatedSiteInstance); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, ValidatesSuggestions); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, + OmniboxCommitsWhenShownFullHeight); + FRIEND_TEST_ALL_PREFIXES(InstantExtendedManualTest, + MANUAL_OmniboxFocusLoadsInstant); + + // Overridden from content::NotificationObserver: + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + // Overridden from InstantPage::Delegate: + // TODO(shishir): We assume that the WebContent's current RenderViewHost is + // the RenderViewHost being created which is not always true. Fix this. + virtual void InstantPageRenderViewCreated( + const content::WebContents* contents) OVERRIDE; + virtual void InstantSupportDetermined( + const content::WebContents* contents, + bool supports_instant) OVERRIDE; + virtual void InstantPageRenderViewGone( + const content::WebContents* contents) OVERRIDE; + virtual void InstantPageAboutToNavigateMainFrame( + const content::WebContents* contents, + const GURL& url) OVERRIDE; + virtual void SetSuggestions( + const content::WebContents* contents, + const std::vector<InstantSuggestion>& suggestions) OVERRIDE; + virtual void ShowInstantOverlay( + const content::WebContents* contents, + int height, + InstantSizeUnits units) OVERRIDE; + virtual void FocusOmnibox(const content::WebContents* contents) OVERRIDE; + virtual void StartCapturingKeyStrokes( + const content::WebContents* contents) OVERRIDE; + virtual void StopCapturingKeyStrokes(content::WebContents* contents) OVERRIDE; + virtual void NavigateToURL( + const content::WebContents* contents, + const GURL& url, + content::PageTransition transition, + WindowOpenDisposition disposition) OVERRIDE; + + // Invoked by the InstantLoader when the Instant page wants to delete a + // Most Visited item. + virtual void DeleteMostVisitedItem(uint64 most_visited_item_id) OVERRIDE; + + // Invoked by the InstantLoader when the Instant page wants to undo a + // Most Visited deletion. + virtual void UndoMostVisitedDeletion(uint64 most_visited_item_id) OVERRIDE; + + // Invoked by the InstantLoader when the Instant page wants to undo all + // Most Visited deletions. + virtual void UndoAllMostVisitedDeletions() OVERRIDE; + + // Helper for OmniboxFocusChanged. Commit or discard the overlay. + void OmniboxLostFocus(gfx::NativeView view_gaining_focus); + + // Creates a new NTP, using the instant_url property of the default + // TemplateURL. + void ResetNTP(); + + // Ensures that |overlay_| uses the Instant URL returned by GetInstantURL(), + // creating a new overlay if necessary. In extended mode, will fallback to + // using the kLocalOmniboxPopupURL as the Instant URL in case GetInstantURL() + // returns false. Returns true if an Instant URL could be determined. + // For |ignore_blacklist| look at comments in |GetInstantURL|. + bool EnsureOverlayIsCurrent(bool ignore_blacklist); + + // Recreates the |overlay_| with |instant_url|. Note that |overlay_| is + // deleted in this call. + void CreateOverlay(const std::string& instant_url, + const content::WebContents* active_tab); + + // If the |overlay_| being used is in fallback mode, it will be switched back + // to the remote overlay if the overlay is not showing and the omnibox does + // not have focus. + void MaybeSwitchToRemoteOverlay(); + + // If the active tab is an Instant search results page, sets |instant_tab_| to + // point to it. Else, deletes any existing |instant_tab_|. + void ResetInstantTab(); + + // Hide the overlay. Also sends an onchange event (with blank query) to the + // overlay, telling it to clear out results for any old queries. + void HideOverlay(); + + // Like HideOverlay(), but doesn't call OnStaleOverlay(). Use HideOverlay() + // unless you are going to call overlay_.reset() yourself subsequently. + void HideInternal(); + + // Counterpart to HideOverlay(). Asks the |browser_| to display the overlay + // with the given |height| in |units|. + void ShowOverlay(int height, InstantSizeUnits units); + + // Send the omnibox popup bounds to the page. + void SendPopupBoundsToPage(); + + // Determines the Instant URL based on a number of factors: + // If |extended_enabled_|: + // - If |use_local_overlay_only_| is true return kLocalOmniboxPopupURL, else + // - If the Instant URL is specified by command line, returns it, else + // - If the default Instant URL is present returns it. + // If !|extended_enabled_|: + // - If the Instant URL is specified by command line, returns it, else + // - If the default Instant URL is present returns it. + // + // If |ignore_blacklist| is set to true, Instant URLs are not filtered through + // the blacklist. + // + // Returns true if a valid Instant URL could be found that is not blacklisted. + bool GetInstantURL(Profile* profile, + bool ignore_blacklist, + std::string* instant_url) const; + + // Adds the URL for the page to the blacklist. Deletes the contents held and + // recreates a new page. + void BlacklistAndResetOverlay(); + void BlacklistAndResetNTP(); + + // Removes |url| from the blacklist. + void RemoveFromBlacklist(const std::string& url); + + InstantOverlay* overlay() const { return overlay_.get(); } + InstantTab* instant_tab() const { return instant_tab_.get(); } + InstantNTP* ntp() const { return ntp_.get(); } + + // Begin listening to change notifications from TopSites and fire off an + // initial request for most visited items. + void StartListeningToMostVisitedChanges(); + + // Fire off an async request for most visited items to the TopNav code. + void RequestMostVisitedItems(); + + // Called when we get new most visited items from the TopNav code, + // registered as an async callback. Parses them and sends them to the + // renderer via SendMostVisitedItems. + void OnMostVisitedItemsReceived(const history::MostVisitedURLList& data); + + // Sends a collection of MostVisitedItems to the renderer process via + // the appropriate InstantPage subclass. + void SendMostVisitedItems(const std::vector<InstantMostVisitedItem>& items); + + // If possible, tries to mutate |suggestion| to a valid suggestion. Returns + // true if successful. (Note that |suggestion| may be modified even if this + // returns false.) + bool FixSuggestion(InstantSuggestion* suggestion) const; + + chrome::BrowserInstantController* const browser_; + + // Whether the extended API and regular API are enabled. If both are false, + // Instant is effectively disabled. + const bool extended_enabled_; + bool instant_enabled_; + + // If true, the Instant URL is set to kLocalOmniboxPopupURL. + bool use_local_overlay_only_; + + // The state of the overlay page, i.e., the page owned by |overlay_|. Ignored + // if |instant_tab_| is in use. + InstantOverlayModel model_; + + // The three instances of InstantPage maintained by InstantController as + // described above. All three may be non-NULL in extended mode. If + // |instant_tab_| is not NULL, then |overlay_| is guaranteed to be hidden and + // messages will be sent to |instant_tab_| instead. + // + // In non-extended mode, only |overlay_| is ever non-NULL. + scoped_ptr<InstantOverlay> overlay_; + scoped_ptr<InstantNTP> ntp_; + scoped_ptr<InstantTab> instant_tab_; + + // The most recent full_text passed to Update(). If empty, we'll not accept + // search suggestions from |overlay_| or |instant_tab_|. + string16 last_omnibox_text_; + + // The most recent user_text passed to Update(). Used to filter out-of-date + // URL suggestions from the Instant page. + string16 last_user_text_; + + // True if the last Update() had an inline autocompletion. Used only to make + // sure that we don't accidentally suggest gray text suggestion in that case. + bool last_omnibox_text_has_inline_autocompletion_; + + // The most recent verbatim passed to Update(). Used only to ensure that we + // don't accidentally suggest an inline autocompletion. + bool last_verbatim_; + + // The most recent suggestion received from the page, minus any prefix that + // the user has typed. + InstantSuggestion last_suggestion_; + + // See comments on the getter above. + content::PageTransition last_transition_type_; + + // True if the last match passed to Update() was a search (versus a URL). + // Used to ensure that the overlay page is committable. + bool last_match_was_search_; + + // Omnibox focus state. + OmniboxFocusState omnibox_focus_state_; + + // The search model mode for the active tab. + chrome::search::Mode search_mode_; + + // Current omnibox popup bounds. + gfx::Rect popup_bounds_; + + // Last popup bounds passed to the page. + gfx::Rect last_popup_bounds_; + + // The start-edge margin and width of the omnibox, used by the page to align + // its suggestions with the omnibox. + gfx::Rect omnibox_bounds_; + + // Timer used to update the bounds of the omnibox popup. + base::OneShotTimer<InstantController> update_bounds_timer_; + + // For each key K => value N, the map says that we found that the search + // engine identified by Instant URL K didn't support the Instant API, or + // caused RenderView crashes in each of the last N times that we loaded it. + // If an Instant URL isn't present in the map at all or has a value 0, + // it means that search engine supports the Instant API (or we assume it does, + // since we haven't determined it doesn't) and it did not cause a crash. + std::map<std::string, int> blacklisted_urls_; + + // Search terms extraction (for autocomplete history matches) doesn't work + // on Instant URLs. So, whenever the user commits an Instant search, we add + // an equivalent non-Instant search URL to history, so that the search shows + // up in autocomplete history matches. + // TODO(sreeram): Remove when http://crbug.com/155373 is fixed. + GURL url_for_history_; + + // The timestamp at which query editing began. This value is used when the + // overlay is showed and cleared when the overlay is hidden. + base::Time first_interaction_time_; + + // Whether to allow the overlay to show search suggestions. In general, the + // overlay is allowed to show search suggestions whenever |search_mode_| is + // MODE_SEARCH_SUGGESTIONS, except in those cases where this is false. + bool allow_overlay_to_show_search_suggestions_; + + // List of events and their timestamps, useful in debugging Instant behaviour. + mutable std::list<std::pair<int64, std::string> > debug_events_; + + // Used for Top Sites async retrieval. + base::WeakPtrFactory<InstantController> weak_ptr_factory_; + + // Used to get notifications about Most Visted changes. + content::NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(InstantController); +}; + +#endif // CHROME_BROWSER_UI_SEARCH_INSTANT_CONTROLLER_H_ |