summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/history/DEPS2
-rw-r--r--chrome/browser/history/history_tab_helper.cc10
-rw-r--r--chrome/browser/instant/instant_browsertest.cc60
-rw-r--r--chrome/browser/instant/instant_client.cc179
-rw-r--r--chrome/browser/instant/instant_client.h175
-rw-r--r--chrome/browser/instant/instant_controller.cc605
-rw-r--r--chrome/browser/instant/instant_controller.h219
-rw-r--r--chrome/browser/instant/instant_extended_browsertest.cc179
-rw-r--r--chrome/browser/instant/instant_loader.cc448
-rw-r--r--chrome/browser/instant/instant_loader.h213
-rw-r--r--chrome/browser/instant/instant_ntp.cc66
-rw-r--r--chrome/browser/instant/instant_ntp.h62
-rw-r--r--chrome/browser/instant/instant_overlay.cc154
-rw-r--r--chrome/browser/instant/instant_overlay.h117
-rw-r--r--chrome/browser/instant/instant_page.cc238
-rw-r--r--chrome/browser/instant/instant_page.h223
-rw-r--r--chrome/browser/instant/instant_tab.cc98
-rw-r--r--chrome/browser/instant/instant_tab.h65
-rw-r--r--chrome/browser/instant/instant_test_utils.cc10
-rw-r--r--chrome/browser/ui/browser.cc4
-rw-r--r--chrome/browser/ui/browser.h2
-rw-r--r--chrome/browser/ui/browser_instant_controller.cc94
-rw-r--r--chrome/browser/ui/browser_instant_controller.h26
-rw-r--r--chrome/browser/ui/browser_navigator.cc109
-rw-r--r--chrome/browser/ui/search/search_tab_helper.cc21
-rw-r--r--chrome/browser/ui/search/search_tab_helper.h9
-rw-r--r--chrome/browser/ui/toolbar/toolbar_model_impl.cc3
27 files changed, 1959 insertions, 1432 deletions
diff --git a/chrome/browser/history/DEPS b/chrome/browser/history/DEPS
index e9482fc7..0553d7b 100644
--- a/chrome/browser/history/DEPS
+++ b/chrome/browser/history/DEPS
@@ -26,7 +26,7 @@ include_rules = [
"!chrome/browser/content_settings/cookie_settings.h",
"!chrome/browser/diagnostics/sqlite_diagnostics.h",
"!chrome/browser/favicon/favicon_service.h",
- "!chrome/browser/instant/instant_loader.h",
+ "!chrome/browser/instant/instant_overlay.h",
"!chrome/browser/prefs/pref_service.h",
"!chrome/browser/prefs/scoped_user_pref_update.h",
"!chrome/browser/prerender/prerender_contents.h",
diff --git a/chrome/browser/history/history_tab_helper.cc b/chrome/browser/history/history_tab_helper.cc
index fc4db96..56b2dee 100644
--- a/chrome/browser/history/history_tab_helper.cc
+++ b/chrome/browser/history/history_tab_helper.cc
@@ -8,7 +8,7 @@
#include "chrome/browser/history/history_service.h"
#include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/instant/instant_loader.h"
+#include "chrome/browser/instant/instant_overlay.h"
#include "chrome/browser/prerender/prerender_contents.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/prerender/prerender_manager_factory.h"
@@ -127,10 +127,10 @@ void HistoryTabHelper::DidNavigateAnyFrame(
}
}
- InstantLoader* instant_loader =
- InstantLoader::FromWebContents(web_contents());
- if (instant_loader) {
- instant_loader->DidNavigate(add_page_args);
+ InstantOverlay* instant_overlay =
+ InstantOverlay::FromWebContents(web_contents());
+ if (instant_overlay) {
+ instant_overlay->DidNavigate(add_page_args);
return;
}
diff --git a/chrome/browser/instant/instant_browsertest.cc b/chrome/browser/instant/instant_browsertest.cc
index 88e79c9..b29cdd7 100644
--- a/chrome/browser/instant/instant_browsertest.cc
+++ b/chrome/browser/instant/instant_browsertest.cc
@@ -4,7 +4,7 @@
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/instant/instant_loader.h"
+#include "chrome/browser/instant/instant_overlay.h"
#include "chrome/browser/instant/instant_service.h"
#include "chrome/browser/instant/instant_service_factory.h"
#include "chrome/browser/instant/instant_test_utils.h"
@@ -16,9 +16,11 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "grit/generated_resources.h"
@@ -31,6 +33,14 @@ class InstantTest : public InstantTestBase {
instant_url_ = test_server()->GetURL("files/instant.html?");
}
+ void FocusOmniboxAndWaitForInstantSupport() {
+ content::WindowedNotificationObserver observer(
+ chrome::NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED,
+ content::NotificationService::AllSources());
+ FocusOmnibox();
+ observer.Wait();
+ }
+
bool UpdateSearchState(content::WebContents* contents) WARN_UNUSED_RESULT {
return GetIntFromJS(contents, "onvisibilitycalls", &onvisibilitycalls_) &&
GetIntFromJS(contents, "onchangecalls", &onchangecalls_) &&
@@ -65,7 +75,7 @@ IN_PROC_BROWSER_TEST_F(InstantTest, OmniboxFocusLoadsInstant) {
EXPECT_FALSE(omnibox()->model()->has_focus());
// Delete any existing preview.
- instant()->loader_.reset();
+ instant()->overlay_.reset();
EXPECT_FALSE(instant()->GetPreviewContents());
// Refocus the omnibox. The InstantController should've preloaded Instant.
@@ -78,7 +88,7 @@ IN_PROC_BROWSER_TEST_F(InstantTest, OmniboxFocusLoadsInstant) {
EXPECT_TRUE(preview_tab);
// Check that the page supports Instant, but it isn't showing.
- EXPECT_TRUE(instant()->loader_->supports_instant());
+ EXPECT_TRUE(instant()->overlay_->supports_instant());
EXPECT_FALSE(instant()->IsPreviewingSearchResults());
EXPECT_TRUE(instant()->model()->mode().is_default());
@@ -115,7 +125,7 @@ IN_PROC_BROWSER_TEST_F(InstantTest, SetWithTemplateURL) {
EXPECT_FALSE(omnibox()->model()->has_focus());
// Delete any existing preview.
- instant()->loader_.reset();
+ instant()->overlay_.reset();
EXPECT_FALSE(instant()->GetPreviewContents());
// Refocus the omnibox. The InstantController should've preloaded Instant.
@@ -128,7 +138,7 @@ IN_PROC_BROWSER_TEST_F(InstantTest, SetWithTemplateURL) {
EXPECT_TRUE(preview_tab);
// Check that the page supports Instant, but it isn't showing.
- EXPECT_TRUE(instant()->loader_->supports_instant());
+ EXPECT_TRUE(instant()->overlay_->supports_instant());
EXPECT_FALSE(instant()->IsPreviewingSearchResults());
EXPECT_TRUE(instant()->model()->mode().is_default());
}
@@ -213,7 +223,7 @@ IN_PROC_BROWSER_TEST_F(InstantTest, OnSubmitEvent) {
EXPECT_FALSE(instant()->IsPreviewingSearchResults());
EXPECT_TRUE(instant()->model()->mode().is_default());
- // The old loader is deleted and a new one is created.
+ // The old overlay is deleted and a new one is created.
EXPECT_TRUE(instant()->GetPreviewContents());
EXPECT_NE(instant()->GetPreviewContents(), preview_tab);
@@ -273,7 +283,7 @@ IN_PROC_BROWSER_TEST_F(InstantTest, OnCancelEvent) {
EXPECT_FALSE(instant()->IsPreviewingSearchResults());
EXPECT_TRUE(instant()->model()->mode().is_default());
- // The old loader is deleted and a new one is created.
+ // The old overlay is deleted and a new one is created.
EXPECT_TRUE(instant()->GetPreviewContents());
EXPECT_NE(instant()->GetPreviewContents(), preview_tab);
@@ -777,37 +787,37 @@ IN_PROC_BROWSER_TEST_F(InstantTest, MAYBE_NewWindowDismissesInstant) {
EXPECT_TRUE(instant()->model()->mode().is_default());
}
-// Test that the Instant loader is recreated when all these conditions are met:
-// - The stale loader timer has fired.
+// Test that the Instant overlay is recreated when all these conditions are met:
+// - The stale overlay timer has fired.
// - The preview is not showing.
// - The omnibox doesn't have focus.
-IN_PROC_BROWSER_TEST_F(InstantTest, InstantLoaderRefresh) {
+IN_PROC_BROWSER_TEST_F(InstantTest, InstantOverlayRefresh) {
ASSERT_NO_FATAL_FAILURE(SetupInstant());
FocusOmniboxAndWaitForInstantSupport();
// The preview is refreshed only after all three conditions above are met.
SetOmniboxTextAndWaitForInstantToShow("query");
- instant()->stale_loader_timer_.Stop();
- instant()->OnStaleLoader();
- EXPECT_TRUE(instant()->loader_->supports_instant());
- instant()->HideLoader();
- EXPECT_TRUE(instant()->loader_->supports_instant());
+ instant()->overlay_->is_stale_ = true;
+ instant()->ReloadOverlayIfStale();
+ EXPECT_TRUE(instant()->overlay_->supports_instant());
+ instant()->HideOverlay();
+ EXPECT_TRUE(instant()->overlay_->supports_instant());
instant()->OmniboxFocusChanged(OMNIBOX_FOCUS_NONE,
OMNIBOX_FOCUS_CHANGE_EXPLICIT, NULL);
- EXPECT_FALSE(instant()->loader_->supports_instant());
+ EXPECT_FALSE(instant()->overlay_->supports_instant());
// Try with a different ordering.
SetOmniboxTextAndWaitForInstantToShow("query");
- instant()->stale_loader_timer_.Stop();
- instant()->OnStaleLoader();
- EXPECT_TRUE(instant()->loader_->supports_instant());
+ instant()->overlay_->is_stale_ = true;
+ instant()->ReloadOverlayIfStale();
+ EXPECT_TRUE(instant()->overlay_->supports_instant());
instant()->OmniboxFocusChanged(OMNIBOX_FOCUS_NONE,
OMNIBOX_FOCUS_CHANGE_EXPLICIT, NULL);
- // TODO(sreeram): Currently, OmniboxLostFocus() calls HideLoader(). When it
+ // TODO(sreeram): Currently, OmniboxLostFocus() calls HideOverlay(). When it
// stops hiding the preview eventually, uncomment these two lines:
- // EXPECT_TRUE(instant()->loader_->supports_instant());
- // instant()->HideLoader();
- EXPECT_FALSE(instant()->loader_->supports_instant());
+ // EXPECT_TRUE(instant()->overlay_->supports_instant());
+ // instant()->HideOverlay();
+ EXPECT_FALSE(instant()->overlay_->supports_instant());
}
// Test that suggestions are case insensitive. http://crbug.com/150728
@@ -917,7 +927,7 @@ IN_PROC_BROWSER_TEST_F(InstantTest, MAYBE_CommitInNewTab) {
EXPECT_FALSE(instant()->IsPreviewingSearchResults());
EXPECT_TRUE(instant()->model()->mode().is_default());
- // The old loader is deleted and a new one is created.
+ // The old overlay is deleted and a new one is created.
EXPECT_TRUE(instant()->GetPreviewContents());
EXPECT_NE(instant()->GetPreviewContents(), preview_tab);
@@ -971,7 +981,7 @@ IN_PROC_BROWSER_TEST_F(InstantTest, SuggestionsAreReusable) {
EXPECT_EQ(ASCIIToUTF16(""), omnibox()->GetInstantSuggestion());
}
-// Test that instant loader is recreated if it gets destroyed.
+// Test that instant overlay is recreated if it gets destroyed.
IN_PROC_BROWSER_TEST_F(InstantTest, InstantRenderViewGone) {
ASSERT_NO_FATAL_FAILURE(SetupInstant());
FocusOmniboxAndWaitForInstantSupport();
diff --git a/chrome/browser/instant/instant_client.cc b/chrome/browser/instant/instant_client.cc
deleted file mode 100644
index ab5d339..0000000
--- a/chrome/browser/instant/instant_client.cc
+++ /dev/null
@@ -1,179 +0,0 @@
-// 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.
-
-#include "chrome/browser/instant/instant_client.h"
-
-#include "base/utf_string_conversions.h"
-#include "chrome/common/render_messages.h"
-#include "content/public/browser/web_contents.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/font.h"
-
-InstantClient::Delegate::~Delegate() {
-}
-
-InstantClient::InstantClient(Delegate* delegate) : delegate_(delegate) {
-}
-
-InstantClient::~InstantClient() {
-}
-
-void InstantClient::SetContents(content::WebContents* contents) {
- Observe(contents);
-}
-
-void InstantClient::Update(const string16& text,
- size_t selection_start,
- size_t selection_end,
- bool verbatim) {
- Send(new ChromeViewMsg_SearchBoxChange(routing_id(), text, verbatim,
- selection_start, selection_end));
-}
-
-void InstantClient::Submit(const string16& text) {
- Send(new ChromeViewMsg_SearchBoxSubmit(routing_id(), text));
-}
-
-void InstantClient::Cancel(const string16& text) {
- Send(new ChromeViewMsg_SearchBoxCancel(routing_id(), text));
-}
-
-void InstantClient::SetPopupBounds(const gfx::Rect& bounds) {
- Send(new ChromeViewMsg_SearchBoxPopupResize(routing_id(), bounds));
-}
-
-void InstantClient::SetMarginSize(const int start, const int end) {
- Send(new ChromeViewMsg_SearchBoxMarginChange(routing_id(), start, end));
-}
-
-void InstantClient::InitializeFonts() {
- const gfx::Font& omnibox_font =
- ui::ResourceBundle::GetSharedInstance().GetFont(
- ui::ResourceBundle::MediumFont);
- string16 omnibox_font_name = UTF8ToUTF16(omnibox_font.GetFontName());
- size_t omnibox_font_size = omnibox_font.GetFontSize();
- Send(new ChromeViewMsg_SearchBoxFontInformation(
- routing_id(), omnibox_font_name, omnibox_font_size));
-}
-
-void InstantClient::DetermineIfPageSupportsInstant() {
- Send(new ChromeViewMsg_DetermineIfPageSupportsInstant(routing_id()));
-}
-
-void InstantClient::SendAutocompleteResults(
- const std::vector<InstantAutocompleteResult>& results) {
- Send(new ChromeViewMsg_SearchBoxAutocompleteResults(routing_id(), results));
-}
-
-void InstantClient::UpOrDownKeyPressed(int count) {
- Send(new ChromeViewMsg_SearchBoxUpOrDownKeyPressed(routing_id(), count));
-}
-
-void InstantClient::SearchModeChanged(const chrome::search::Mode& mode) {
- Send(new ChromeViewMsg_SearchBoxModeChanged(routing_id(), mode));
-}
-
-void InstantClient::SendThemeBackgroundInfo(
- const ThemeBackgroundInfo& theme_info) {
- Send(new ChromeViewMsg_SearchBoxThemeChanged(routing_id(), theme_info));
-}
-
-void InstantClient::SendThemeAreaHeight(int height) {
- Send(new ChromeViewMsg_SearchBoxThemeAreaHeightChanged(routing_id(), height));
-}
-
-void InstantClient::SetDisplayInstantResults(bool display_instant_results) {
- Send(new ChromeViewMsg_SearchBoxSetDisplayInstantResults(routing_id(),
- display_instant_results));
-}
-
-void InstantClient::KeyCaptureChanged(bool is_key_capture_enabled) {
- Send(new ChromeViewMsg_SearchBoxKeyCaptureChanged(routing_id(),
- is_key_capture_enabled));
-}
-
-void InstantClient::RenderViewCreated(
- content::RenderViewHost* render_view_host) {
- delegate_->RenderViewCreated();
-}
-
-void InstantClient::DidFinishLoad(
- int64 /* frame_id */,
- const GURL& /* validated_url */,
- bool is_main_frame,
- content::RenderViewHost* /* render_view_host */) {
- if (is_main_frame)
- DetermineIfPageSupportsInstant();
-}
-
-bool InstantClient::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(InstantClient, message)
- IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SetSuggestions, SetSuggestions)
- IPC_MESSAGE_HANDLER(ChromeViewHostMsg_InstantSupportDetermined,
- InstantSupportDetermined)
- IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ShowInstantPreview,
- ShowInstantPreview)
- IPC_MESSAGE_HANDLER(ChromeViewHostMsg_StartCapturingKeyStrokes,
- StartCapturingKeyStrokes);
- IPC_MESSAGE_HANDLER(ChromeViewHostMsg_StopCapturingKeyStrokes,
- StopCapturingKeyStrokes);
- IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxNavigate,
- SearchBoxNavigate);
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void InstantClient::RenderViewGone(base::TerminationStatus status) {
- delegate_->RenderViewGone();
-}
-
-void InstantClient::DidCommitProvisionalLoadForFrame(
- int64 frame_id,
- bool is_main_frame,
- const GURL& url,
- content::PageTransition transition_type,
- content::RenderViewHost* render_view_host) {
- if (!is_main_frame)
- return;
- delegate_->AboutToNavigateMainFrame(url);
-}
-
-void InstantClient::SetSuggestions(
- int page_id,
- const std::vector<InstantSuggestion>& suggestions) {
- if (web_contents()->IsActiveEntry(page_id))
- delegate_->SetSuggestions(suggestions);
-}
-
-void InstantClient::InstantSupportDetermined(int page_id, bool result) {
- if (web_contents()->IsActiveEntry(page_id))
- delegate_->InstantSupportDetermined(result);
-}
-
-void InstantClient::ShowInstantPreview(int page_id,
- InstantShownReason reason,
- int height,
- InstantSizeUnits units) {
- if (web_contents()->IsActiveEntry(page_id))
- delegate_->ShowInstantPreview(reason, height, units);
-}
-
-void InstantClient::StartCapturingKeyStrokes(int page_id) {
- if (web_contents()->IsActiveEntry(page_id))
- delegate_->StartCapturingKeyStrokes();
-}
-
-void InstantClient::StopCapturingKeyStrokes(int page_id) {
- if (web_contents()->IsActiveEntry(page_id))
- delegate_->StopCapturingKeyStrokes();
-}
-
-void InstantClient::SearchBoxNavigate(int page_id,
- const GURL& url,
- content::PageTransition transition) {
- if (web_contents()->IsActiveEntry(page_id))
- delegate_->NavigateToURL(url, transition);
-}
diff --git a/chrome/browser/instant/instant_client.h b/chrome/browser/instant/instant_client.h
deleted file mode 100644
index dffdc6b..0000000
--- a/chrome/browser/instant/instant_client.h
+++ /dev/null
@@ -1,175 +0,0 @@
-// 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_INSTANT_INSTANT_CLIENT_H_
-#define CHROME_BROWSER_INSTANT_INSTANT_CLIENT_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/string16.h"
-#include "chrome/common/instant_types.h"
-#include "content/public/browser/web_contents_observer.h"
-
-namespace chrome {
-namespace search {
-struct Mode;
-}
-}
-
-namespace content {
-class WebContents;
-}
-
-namespace gfx {
-class Rect;
-}
-
-// InstantClient is used to exchange messages between its delegate and a page
-// that supports the Instant API (http://dev.chromium.org/searchbox).
-class InstantClient : public content::WebContentsObserver {
- public:
- // When InstantClient receives messages from the page, it calls the following
- // methods on its delegate.
- class Delegate {
- public:
- // Called when the page has suggestions. Usually in response to Change(),
- // SendAutocompleteResults() or UpOrDownKeyPressed().
- virtual void SetSuggestions(
- const std::vector<InstantSuggestion>& suggestions) = 0;
-
- // Called upon determination of Instant API support. Usually in response to
- // SetContents() or when the page first finishes loading.
- virtual void InstantSupportDetermined(bool supports_instant) = 0;
-
- // Called when the page wants to be shown. Usually in response to Change(),
- // SendAutocompleteResults() or SearchModeChanged().
- virtual void ShowInstantPreview(InstantShownReason reason,
- int height,
- InstantSizeUnits units) = 0;
-
- // Called when the page wants the browser to start capturing user key
- // strokes.
- virtual void StartCapturingKeyStrokes() = 0;
-
- // Called when the page wants the browser to stop capturing user key
- // strokes.
- virtual void StopCapturingKeyStrokes() = 0;
-
- // Called when the underlying RenderView crashes.
- virtual void RenderViewGone() = 0;
-
- // Called when the page is about to navigate.
- virtual void AboutToNavigateMainFrame(const GURL& url) = 0;
-
- // Called when the SearchBox wants to navigate to the specified URL.
- virtual void NavigateToURL(const GURL& url,
- content::PageTransition transition) = 0;
-
- // Called when a RenderView is created, so that state can be initialized.
- virtual void RenderViewCreated() = 0;
-
- protected:
- virtual ~Delegate();
- };
-
- // Doesn't take ownership of |delegate|.
- explicit InstantClient(Delegate* delegate);
- virtual ~InstantClient();
-
- // Sets |contents| as the page to communicate with. |contents| can be NULL,
- // which effectively stops all communication.
- void SetContents(content::WebContents* contents);
-
- // Tells the page that the user typed |text| into the omnibox. If |verbatim|
- // is false, the page predicts the query the user means to type and fetches
- // results for the prediction. If |verbatim| is true, |text| is taken as the
- // exact query (no prediction is made).
- void Update(const string16& text,
- size_t selection_start,
- size_t selection_end,
- bool verbatim);
-
- // Tells the page that the user pressed Enter in the omnibox.
- void Submit(const string16& text);
-
- // Tells the page that the user clicked on it. Nothing is being cancelled; the
- // poor choice of name merely reflects the IPC of the same (poor) name.
- void Cancel(const string16& text);
-
- // Tells the page the bounds of the omnibox dropdown (in screen coordinates).
- // This is used by the page to offset the results to avoid them being covered
- // by the omnibox dropdown.
- void SetPopupBounds(const gfx::Rect& bounds);
-
- // Tells the page what size start and end margins to use.
- void SetMarginSize(const int start, const int end);
-
- // Tells the page about the font information.
- void InitializeFonts();
-
- // Tells the renderer to determine if the page supports the Instant API, which
- // results in a call to InstantSupportDetermined() when the reply is received.
- void DetermineIfPageSupportsInstant();
-
- // Tells the page about the available autocomplete results.
- void SendAutocompleteResults(
- const std::vector<InstantAutocompleteResult>& results);
-
- // Tells the page that the user pressed Up or Down in the omnibox. |count| is
- // a repeat count, negative for moving up, positive for moving down.
- void UpOrDownKeyPressed(int count);
-
- // Tells the page that the active tab's search mode has changed.
- void SearchModeChanged(const chrome::search::Mode& mode);
-
- // Tells the page about the current theme background.
- void SendThemeBackgroundInfo(const ThemeBackgroundInfo& theme_info);
-
- // Tells the page about the current theme area height.
- void SendThemeAreaHeight(int height);
-
- // Tells the page whether it is allowed to display Instant results.
- void SetDisplayInstantResults(bool display_instant_results);
-
- // Tells the page whether the browser is capturing user key strokes.
- void KeyCaptureChanged(bool is_key_capture_enabled);
-
- private:
- // Overridden from content::WebContentsObserver:
- virtual void RenderViewCreated(
- content::RenderViewHost* render_view_host) OVERRIDE;
- virtual void DidFinishLoad(
- int64 frame_id,
- const GURL& validated_url,
- bool is_main_frame,
- content::RenderViewHost* render_view_host) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE;
- virtual void DidCommitProvisionalLoadForFrame(
- int64 frame_id,
- bool is_main_frame,
- const GURL& url,
- content::PageTransition transition_type,
- content::RenderViewHost* render_view_host) OVERRIDE;
-
- void SetSuggestions(int page_id,
- const std::vector<InstantSuggestion>& suggestions);
- void InstantSupportDetermined(int page_id, bool result);
- void ShowInstantPreview(int page_id,
- InstantShownReason reason,
- int height,
- InstantSizeUnits units);
- void StartCapturingKeyStrokes(int page_id);
- void StopCapturingKeyStrokes(int page_id);
- void SearchBoxNavigate(int page_id, const GURL& url,
- content::PageTransition transition);
-
- Delegate* const delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(InstantClient);
-};
-
-#endif // CHROME_BROWSER_INSTANT_INSTANT_CLIENT_H_
diff --git a/chrome/browser/instant/instant_controller.cc b/chrome/browser/instant/instant_controller.cc
index 72bf030..80f9b79 100644
--- a/chrome/browser/instant/instant_controller.cc
+++ b/chrome/browser/instant/instant_controller.cc
@@ -14,7 +14,8 @@
#include "chrome/browser/history/history_service.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/history/history_tab_helper.h"
-#include "chrome/browser/instant/instant_loader.h"
+#include "chrome/browser/instant/instant_ntp.h"
+#include "chrome/browser/instant/instant_overlay.h"
#include "chrome/browser/instant/instant_tab.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/search_engines/template_url_service.h"
@@ -23,6 +24,7 @@
#include "chrome/browser/ui/search/search_tab_helper.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/url_constants.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_widget_host_view.h"
@@ -45,10 +47,6 @@ const int kUpdateBoundsDelayMS = 1000;
// before we give up and blacklist it for the rest of the browsing session.
const int kMaxInstantSupportFailures = 10;
-// If an Instant page has not been used in these many milliseconds, it is
-// reloaded so that the page does not become stale.
-const int kStaleLoaderTimeoutMS = 3 * 3600 * 1000;
-
// For reporting events of interest.
enum InstantControllerEvent {
INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST = 0,
@@ -160,6 +158,11 @@ bool IsFullHeight(const InstantModel& model) {
return model.height() == 100 && model.height_units() == INSTANT_SIZE_PERCENT;
}
+bool IsContentsFrom(const InstantPage* page,
+ const content::WebContents* contents) {
+ return page && (page->contents() == contents);
+}
+
} // namespace
// static
@@ -217,7 +220,7 @@ bool InstantController::Update(const AutocompleteMatch& match,
if (instant_tab_)
instant_tab_->Update(string16(), 0, 0, true);
else
- HideLoader();
+ HideOverlay();
last_match_was_search_ = false;
return false;
}
@@ -239,13 +242,13 @@ bool InstantController::Update(const AutocompleteMatch& match,
// The preview is being clicked and will commit soon. Don't change anything.
// TODO(sreeram): Add a browser test for this.
- if (loader_ && loader_->is_pointer_down_from_activate())
+ if (overlay_ && overlay_->is_pointer_down_from_activate())
return false;
// In non-extended mode, SearchModeChanged() is never called, so fake it. The
// mode is set to "disallow suggestions" here, so that if one of the early
// "return false" conditions is hit, suggestions will be disallowed. If the
- // query is sent to the loader, the mode is set to "allow" further below.
+ // query is sent to the overlay, the mode is set to "allow" further below.
if (!extended_enabled_)
search_mode_.mode = chrome::search::Mode::MODE_DEFAULT;
@@ -256,15 +259,15 @@ bool InstantController::Update(const AutocompleteMatch& match,
if (!extended_enabled_ &&
(!last_match_was_search_ ||
match.type == AutocompleteMatch::SEARCH_OTHER_ENGINE)) {
- HideLoader();
+ HideOverlay();
return false;
}
- // If we have an |instant_tab_| use it, else ensure we have a loader that is
+ // If we have an |instant_tab_| use it, else ensure we have a overlay that is
// current or is using local preview.
- if (!instant_tab_ && !(loader_ && loader_->IsUsingLocalPreview()) &&
- !EnsureLoaderIsCurrent(false)) {
- HideLoader();
+ if (!instant_tab_ && !(overlay_ && overlay_->IsUsingLocalPreview()) &&
+ !EnsureOverlayIsCurrent(false)) {
+ HideOverlay();
return false;
}
@@ -289,7 +292,7 @@ bool InstantController::Update(const AutocompleteMatch& match,
} else if (!full_text.empty()) {
// If |full_text| is empty, the user is on the NTP. The preview may
// be showing custom NTP content; hide only if that's not the case.
- HideLoader();
+ HideOverlay();
}
} else if (full_text.empty()) {
// The user is typing, and backspaced away all omnibox text. Clear
@@ -302,13 +305,13 @@ bool InstantController::Update(const AutocompleteMatch& match,
} else if (search_mode_.is_origin_ntp()) {
// On the NTP, tell the preview to clear old results. Don't hide the
// preview so it can show a blank page or logo if it wants.
- loader_->Update(string16(), 0, 0, true);
+ overlay_->Update(string16(), 0, 0, true);
} else {
- HideLoader();
+ HideOverlay();
}
} else {
// The user switched to a tab with partial text already in the omnibox.
- HideLoader();
+ HideOverlay();
// The new tab may or may not be a search results page; we don't know
// since SearchModeChanged() hasn't been called yet. If it later turns
@@ -327,15 +330,15 @@ bool InstantController::Update(const AutocompleteMatch& match,
if (instant_tab_)
instant_tab_->Update(string16(), 0, 0, true);
else if (search_mode_.is_origin_ntp())
- loader_->Update(string16(), 0, 0, true);
+ overlay_->Update(string16(), 0, 0, true);
else
- HideLoader();
+ HideOverlay();
return false;
}
} else if (!omnibox_popup_is_open || full_text.empty()) {
// In the non-extended case, hide the preview as long as the user isn't
// actively typing a non-empty query.
- HideLoader();
+ HideOverlay();
return false;
}
@@ -387,13 +390,13 @@ bool InstantController::Update(const AutocompleteMatch& match,
// For extended mode, if the loader is not ready at this point, switch over
// to a backup loader.
- if (extended_enabled_ && !loader_->supports_instant() &&
- !loader_->IsUsingLocalPreview() && browser_->GetActiveWebContents()) {
- CreateLoader(kLocalOmniboxPopupURL, browser_->GetActiveWebContents());
+ if (extended_enabled_ && !overlay_->supports_instant() &&
+ !overlay_->IsUsingLocalPreview() && browser_->GetActiveWebContents()) {
+ CreateOverlay(kLocalOmniboxPopupURL, browser_->GetActiveWebContents());
}
- loader_->Update(extended_enabled_ ? user_text : full_text,
- selection_start, selection_end, verbatim);
+ overlay_->Update(extended_enabled_ ? user_text : full_text,
+ selection_start, selection_end, verbatim);
}
content::NotificationService::current()->Notify(
@@ -408,6 +411,18 @@ bool InstantController::Update(const AutocompleteMatch& match,
return true;
}
+scoped_ptr<content::WebContents> InstantController::ReleaseNTPContents() {
+ if (!extended_enabled_ || !ntp_)
+ return scoped_ptr<content::WebContents>(NULL);
+
+ LOG_INSTANT_DEBUG_EVENT(this, "ReleaseNTPContents");
+
+ scoped_ptr<content::WebContents> ntp_contents = ntp_->ReleaseContents();
+ ntp_.reset();
+ ResetNTP();
+ return ntp_contents.Pass();
+}
+
// TODO(tonyg): This method only fires when the omnibox bounds change. It also
// needs to fire when the preview bounds change (e.g.: open/close info bar).
void InstantController::SetPopupBounds(const gfx::Rect& bounds) {
@@ -434,8 +449,10 @@ void InstantController::SetMarginSize(int start, int end) {
start_margin_ = start;
end_margin_ = end;
- if (loader_)
- loader_->SetMarginSize(start_margin_, end_margin_);
+ if (overlay_)
+ overlay_->SetMarginSize(start_margin_, end_margin_);
+ if (ntp_)
+ ntp_->SetMarginSize(start_margin_, end_margin_);
if (instant_tab_)
instant_tab_->SetMarginSize(start_margin_, end_margin_);
}
@@ -445,7 +462,7 @@ void InstantController::HandleAutocompleteResults(
if (!extended_enabled_)
return;
- if (!instant_tab_ && !loader_)
+ if (!instant_tab_ && !overlay_)
return;
DVLOG(1) << "AutocompleteResults:";
@@ -474,26 +491,26 @@ void InstantController::HandleAutocompleteResults(
if (instant_tab_)
instant_tab_->SendAutocompleteResults(results);
else
- loader_->SendAutocompleteResults(results);
+ overlay_->SendAutocompleteResults(results);
}
bool InstantController::OnUpOrDownKeyPressed(int count) {
if (!extended_enabled_)
return false;
- if (!instant_tab_ && !loader_)
+ if (!instant_tab_ && !overlay_)
return false;
if (instant_tab_)
instant_tab_->UpOrDownKeyPressed(count);
else
- loader_->UpOrDownKeyPressed(count);
+ overlay_->UpOrDownKeyPressed(count);
return true;
}
content::WebContents* InstantController::GetPreviewContents() const {
- return loader_ ? loader_->contents() : NULL;
+ return overlay_ ? overlay_->contents() : NULL;
}
bool InstantController::IsPreviewingSearchResults() const {
@@ -530,21 +547,21 @@ bool InstantController::CommitIfPossible(InstantCommitType type) {
// There may re-entrance here, from the call to browser_->CommitInstant below,
// which can cause a TabDeactivated notification which gets back here.
- // In this case, loader_->ReleaseContents() was called already.
+ // In this case, overlay_->ReleaseContents() was called already.
if (!GetPreviewContents())
return false;
// Never commit the local omnibox.
- if (loader_->IsUsingLocalPreview())
+ if (overlay_->IsUsingLocalPreview())
return false;
if (type == INSTANT_COMMIT_FOCUS_LOST)
- loader_->Cancel(last_omnibox_text_);
+ overlay_->Cancel(last_omnibox_text_);
else if (type != INSTANT_COMMIT_NAVIGATED &&
type != INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION)
- loader_->Submit(last_omnibox_text_);
+ overlay_->Submit(last_omnibox_text_);
- content::WebContents* preview = loader_->ReleaseContents();
+ scoped_ptr<content::WebContents> preview = overlay_->ReleaseContents();
if (extended_enabled_) {
// Consider what's happening:
@@ -577,7 +594,7 @@ bool InstantController::CommitIfPossible(InstantCommitType type) {
entry->SetVirtualURL(GURL(
url + "#q=" +
net::EscapeQueryParamValue(query, true)));
- chrome::search::SearchTabHelper::FromWebContents(preview)->
+ chrome::search::SearchTabHelper::FromWebContents(preview.get())->
NavigationEntryUpdated();
}
}
@@ -586,11 +603,11 @@ bool InstantController::CommitIfPossible(InstantCommitType type) {
// the navigation to history ourselves. Else, the page will navigate after
// commit, and it will be added to history in the usual manner.
const history::HistoryAddPageArgs& last_navigation =
- loader_->last_navigation();
+ overlay_->last_navigation();
if (!last_navigation.url.is_empty()) {
content::NavigationEntry* entry = preview->GetController().GetActiveEntry();
- // The last navigation should be the same as the active entry if the loader
+ // The last navigation should be the same as the active entry if the overlay
// is in search mode. During navigation, the active entry could have
// changed since DidCommitProvisionalLoadForFrame is called after the entry
// is changed.
@@ -601,7 +618,7 @@ bool InstantController::CommitIfPossible(InstantCommitType type) {
// Add the page to history.
HistoryTabHelper* history_tab_helper =
- HistoryTabHelper::FromWebContents(preview);
+ HistoryTabHelper::FromWebContents(preview.get());
history_tab_helper->UpdateHistoryForNavigation(last_navigation);
// Update the page title.
@@ -623,28 +640,31 @@ bool InstantController::CommitIfPossible(InstantCommitType type) {
if (type != INSTANT_COMMIT_PRESSED_ALT_ENTER) {
content::WebContents* active_tab = browser_->GetActiveWebContents();
- AddSessionStorageHistogram(extended_enabled_, active_tab, preview);
+ AddSessionStorageHistogram(extended_enabled_, active_tab, preview.get());
preview->GetController().CopyStateFromAndPrune(
&active_tab->GetController());
}
- // Browser takes ownership of the preview.
- browser_->CommitInstant(preview, type == INSTANT_COMMIT_PRESSED_ALT_ENTER);
+ // Save notification source before we release the preview.
+ content::Source<content::WebContents> notification_source(preview.get());
+
+ browser_->CommitInstant(preview.Pass(),
+ type == INSTANT_COMMIT_PRESSED_ALT_ENTER);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_INSTANT_COMMITTED,
- content::Source<content::WebContents>(preview),
+ notification_source,
content::NotificationService::NoDetails());
- // Hide explicitly. See comments in HideLoader() for why.
+ // Hide explicitly. See comments in HideOverlay() for why.
model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT);
- // Delay deletion as we could've gotten here from an InstantLoader method.
- MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release());
+ // Delay deletion as we could've gotten here from an InstantOverlay method.
+ MessageLoop::current()->DeleteSoon(FROM_HERE, overlay_.release());
- // Try to create another loader immediately so that it is ready for the next
+ // Try to create another overlay immediately so that it is ready for the next
// user interaction.
- EnsureLoaderIsCurrent(false);
+ EnsureOverlayIsCurrent(false);
LOG_INSTANT_DEBUG_EVENT(this, "Committed");
return true;
@@ -672,15 +692,21 @@ void InstantController::OmniboxFocusChanged(
// have no way of telling whether the keycapturechange happened because of
// some actual user action or just because they started typing.)
if (extended_enabled_ && GetPreviewContents() &&
- reason != OMNIBOX_FOCUS_CHANGE_TYPING)
- loader_->KeyCaptureChanged(omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE);
+ reason != OMNIBOX_FOCUS_CHANGE_TYPING) {
+ const bool is_key_capture_enabled =
+ omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE;
+ if (overlay_)
+ overlay_->KeyCaptureChanged(is_key_capture_enabled);
+ if (instant_tab_)
+ instant_tab_->KeyCaptureChanged(is_key_capture_enabled);
+ }
// If focus went from outside the omnibox to the omnibox, preload the default
// search engine, in anticipation of the user typing a query. If the reverse
// happened, commit or discard the preview.
if (state != OMNIBOX_FOCUS_NONE && old_focus_state == OMNIBOX_FOCUS_NONE) {
// On explicit user actions, ignore the Instant blacklist.
- EnsureLoaderIsCurrent(reason == OMNIBOX_FOCUS_CHANGE_EXPLICIT);
+ EnsureOverlayIsCurrent(reason == OMNIBOX_FOCUS_CHANGE_EXPLICIT);
} else if (state == OMNIBOX_FOCUS_NONE &&
old_focus_state != OMNIBOX_FOCUS_NONE) {
OmniboxLostFocus(view_gaining_focus);
@@ -699,10 +725,10 @@ void InstantController::SearchModeChanged(
search_mode_ = new_mode;
if (!new_mode.is_search_suggestions())
- HideLoader();
+ HideOverlay();
- if (loader_)
- loader_->SearchModeChanged(new_mode);
+ if (overlay_)
+ overlay_->SearchModeChanged(new_mode);
ResetInstantTab();
}
@@ -713,10 +739,8 @@ void InstantController::ActiveTabChanged() {
LOG_INSTANT_DEBUG_EVENT(this, "ActiveTabChanged");
- // When switching tabs, always hide the preview, except if it's showing NTP
- // content, and the new tab is also an NTP.
- if (!search_mode_.is_ntp() || !model_.mode().is_ntp())
- HideLoader();
+ // When switching tabs, always hide the preview.
+ HideOverlay();
if (extended_enabled_)
ResetInstantTab();
@@ -744,9 +768,11 @@ void InstantController::SetInstantEnabled(bool instant_enabled,
instant_enabled_ = instant_enabled;
use_local_preview_only_ = use_local_preview_only;
HideInternal();
- loader_.reset();
+ overlay_.reset();
if (extended_enabled_ || instant_enabled_)
- EnsureLoaderIsCurrent(false);
+ EnsureOverlayIsCurrent(false);
+ if (extended_enabled_)
+ ResetNTP();
if (instant_tab_)
instant_tab_->SetDisplayInstantResults(instant_enabled_);
}
@@ -755,16 +781,159 @@ void InstantController::ThemeChanged(const ThemeBackgroundInfo& theme_info) {
if (!extended_enabled_)
return;
- if (loader_)
- loader_->SendThemeBackgroundInfo(theme_info);
+ if (overlay_)
+ overlay_->SendThemeBackgroundInfo(theme_info);
+ if (ntp_)
+ ntp_->SendThemeBackgroundInfo(theme_info);
+ if (instant_tab_)
+ instant_tab_->SendThemeBackgroundInfo(theme_info);
}
void InstantController::ThemeAreaHeightChanged(int height) {
if (!extended_enabled_)
return;
- if (loader_)
- loader_->SendThemeAreaHeight(height);
+ if (overlay_)
+ overlay_->SendThemeAreaHeight(height);
+ if (ntp_)
+ ntp_->SendThemeAreaHeight(height);
+ if (instant_tab_)
+ instant_tab_->SendThemeAreaHeight(height);
+}
+
+void InstantController::SwappedOverlayContents() {
+ model_.SetPreviewContents(GetPreviewContents());
+}
+
+void InstantController::FocusedOverlayContents() {
+#if defined(USE_AURA)
+ // On aura the omnibox only receives a focus lost if we initiate the focus
+ // change. This does that.
+ if (!model_.mode().is_default())
+ browser_->InstantPreviewFocused();
+#endif
+}
+
+void InstantController::ReloadOverlayIfStale() {
+ // The local popup is never stale.
+ if (overlay_ && overlay_->IsUsingLocalPreview())
+ return;
+
+ // If the preview is showing or the omnibox has focus, don't delete the
+ // overlay. It will get refreshed the next time the preview is hidden or the
+ // omnibox loses focus.
+ if ((!overlay_ || overlay_->is_stale()) &&
+ omnibox_focus_state_ == OMNIBOX_FOCUS_NONE &&
+ model_.mode().is_default()) {
+ overlay_.reset();
+ EnsureOverlayIsCurrent(false);
+ }
+}
+
+void InstantController::LogDebugEvent(const std::string& info) const {
+ DVLOG(1) << info;
+
+ debug_events_.push_front(std::make_pair(
+ base::Time::Now().ToInternalValue(), info));
+ static const size_t kMaxDebugEventSize = 2000;
+ if (debug_events_.size() > kMaxDebugEventSize)
+ debug_events_.pop_back();
+}
+
+// TODO(shishir): We assume that the WebContent's current RenderViewHost is the
+// RenderViewHost being created which is not always true. Fix this.
+void InstantController::InstantPageRenderViewCreated(
+ const content::WebContents* contents) {
+ if (!extended_enabled_)
+ return;
+
+ // Update theme info so that the page picks it up.
+ browser_->UpdateThemeInfoForPreview();
+
+ // Ensure the searchbox API has the correct initial state.
+ if (IsContentsFrom(overlay(), contents)) {
+ overlay_->SetDisplayInstantResults(instant_enabled_);
+ overlay_->SearchModeChanged(search_mode_);
+ overlay_->KeyCaptureChanged(
+ omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE);
+ overlay_->SetMarginSize(start_margin_, end_margin_);
+ overlay_->InitializeFonts();
+ } else if (IsContentsFrom(ntp(), contents)) {
+ ntp_->SetDisplayInstantResults(instant_enabled_);
+ ntp_->SetMarginSize(start_margin_, end_margin_);
+ ntp_->InitializeFonts();
+ } else {
+ NOTREACHED();
+ }
+}
+
+void InstantController::InstantSupportDetermined(
+ const content::WebContents* contents,
+ bool supports_instant) {
+ if (IsContentsFrom(instant_tab(), contents)) {
+ if (!supports_instant)
+ MessageLoop::current()->DeleteSoon(FROM_HERE, instant_tab_.release());
+ } else if (IsContentsFrom(ntp(), contents)) {
+ if (supports_instant)
+ RemoveFromBlacklist(ntp_->instant_url());
+ else
+ BlacklistAndResetNTP();
+
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_INSTANT_NTP_SUPPORT_DETERMINED,
+ content::Source<InstantController>(this),
+ content::NotificationService::NoDetails());
+
+ } else if (IsContentsFrom(overlay(), contents)) {
+ if (supports_instant)
+ RemoveFromBlacklist(overlay_->instant_url());
+ else
+ BlacklistAndResetOverlay();
+
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED,
+ content::Source<InstantController>(this),
+ content::NotificationService::NoDetails());
+ }
+}
+
+void InstantController::InstantPageRenderViewGone(
+ const content::WebContents* contents) {
+ if (IsContentsFrom(overlay(), contents))
+ BlacklistAndResetOverlay();
+ else if (IsContentsFrom(ntp(), contents))
+ BlacklistAndResetNTP();
+ else
+ NOTREACHED();
+}
+
+void InstantController::InstantPageAboutToNavigateMainFrame(
+ const content::WebContents* contents,
+ const GURL& url) {
+ DCHECK(IsContentsFrom(overlay(), contents));
+
+ // If the page does not yet support instant, we allow redirects and other
+ // navigations to go through since the instant URL can redirect - e.g. to
+ // country specific pages.
+ if (!overlay_->supports_instant())
+ return;
+
+ GURL instant_url(overlay_->instant_url());
+
+ // If we are navigating to the instant URL, do nothing.
+ if (url == instant_url)
+ return;
+
+ // Commit the navigation if either:
+ // - The page is in NTP mode (so it could only navigate on a user click) or
+ // - The page is not in NTP mode and we are navigating to a URL with a
+ // different host or path than the instant URL. This enables the instant
+ // page when it is showing search results to change the query parameters
+ // and fragments of the URL without it navigating.
+ if (model_.mode().is_ntp() ||
+ (url.host() != instant_url.host() || url.path() != instant_url.path())) {
+ CommitIfPossible(INSTANT_COMMIT_NAVIGATED);
+ }
}
void InstantController::SetSuggestions(
@@ -773,13 +942,13 @@ void InstantController::SetSuggestions(
LOG_INSTANT_DEBUG_EVENT(this, "SetSuggestions");
// Ignore if the message is from an unexpected source.
- if (instant_tab_) {
- if (instant_tab_->contents() != contents)
- return;
- } else if (!loader_ || loader_->contents() != contents ||
- !allow_preview_to_show_search_suggestions_) {
+ if (IsContentsFrom(ntp(), contents))
+ return;
+ if (instant_tab_ && !IsContentsFrom(instant_tab(), contents))
+ return;
+ if (IsContentsFrom(overlay(), contents) &&
+ !allow_preview_to_show_search_suggestions_)
return;
- }
InstantSuggestion suggestion;
if (!suggestions.empty())
@@ -860,122 +1029,48 @@ void InstantController::SetSuggestions(
}
}
- // Extended mode pages will call ShowLoader() when they are ready.
+ // Extended mode pages will call ShowOverlay() when they are ready.
if (!extended_enabled_)
- ShowLoader(INSTANT_SHOWN_QUERY_SUGGESTIONS, 100, INSTANT_SIZE_PERCENT);
+ ShowOverlay(INSTANT_SHOWN_QUERY_SUGGESTIONS, 100, INSTANT_SIZE_PERCENT);
}
-void InstantController::InstantSupportDetermined(
- const content::WebContents* contents,
- bool supports_instant) {
- LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
- "InstantSupportDetermined: supports_instant=%d", supports_instant));
-
- if (instant_tab_ && instant_tab_->contents() == contents) {
- if (!supports_instant)
- MessageLoop::current()->DeleteSoon(FROM_HERE, instant_tab_.release());
- return;
- }
-
- if (loader_ && loader_->contents() == contents) {
- if (supports_instant) {
- if (blacklisted_urls_.erase(loader_->instant_url())) {
- RecordEventHistogram(
- INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST);
- }
- } else {
- ++blacklisted_urls_[loader_->instant_url()];
- RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST);
- HideInternal();
- delete loader_->ReleaseContents();
- MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release());
- EnsureLoaderIsCurrent(false);
- }
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_INSTANT_SUPPORT_DETERMINED,
- content::Source<InstantController>(this),
- content::NotificationService::NoDetails());
- }
-}
-
-void InstantController::ShowInstantPreview(InstantShownReason reason,
+void InstantController::ShowInstantPreview(const content::WebContents* contents,
+ InstantShownReason reason,
int height,
InstantSizeUnits units) {
- if (extended_enabled_)
- ShowLoader(reason, height, units);
-}
-
-void InstantController::StartCapturingKeyStrokes() {
- // Ignore unless the loader is active and on the NTP.
- if (extended_enabled_ && !instant_tab_ && model_.mode().is_ntp())
- browser_->FocusOmniboxInvisibly();
-}
-
-void InstantController::StopCapturingKeyStrokes() {
- // Ignore unless the loader is active and on the NTP, and the omnibox has
- // invisible focus.
- if (extended_enabled_ && !instant_tab_ && model_.mode().is_ntp() &&
- omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE)
- loader_->contents()->Focus();
+ if (extended_enabled_ && IsContentsFrom(overlay(), contents))
+ ShowOverlay(reason, height, units);
}
-void InstantController::SwappedWebContents() {
- model_.SetPreviewContents(GetPreviewContents());
-}
-
-void InstantController::InstantLoaderContentsFocused() {
-#if defined(USE_AURA)
- // On aura the omnibox only receives a focus lost if we initiate the focus
- // change. This does that.
- if (!model_.mode().is_default())
- browser_->InstantPreviewFocused();
-#endif
-}
-
-void InstantController::InstantLoaderRenderViewGone() {
- ++blacklisted_urls_[loader_->instant_url()];
- HideInternal();
- delete loader_->ReleaseContents();
- // Delay deletion as we have gotten here from an InstantLoader method.
- MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release());
- EnsureLoaderIsCurrent(false);
-}
-
-void InstantController::InstantLoaderAboutToNavigateMainFrame(const GURL& url) {
- // If the page does not yet support instant, we allow redirects and other
- // navigations to go through since the instant URL can redirect - e.g. to
- // country specific pages.
- if (!loader_->supports_instant())
+void InstantController::StartCapturingKeyStrokes(
+ const content::WebContents* contents) {
+ if (!extended_enabled_)
return;
- GURL instant_url(loader_->instant_url());
+ DCHECK(IsContentsFrom(instant_tab(), contents));
+ browser_->FocusOmniboxInvisibly();
+}
- // If we are navigating to the instant URL, do nothing.
- if (url == instant_url)
+void InstantController::StopCapturingKeyStrokes(
+ content::WebContents* contents) {
+ // Nothing to do if omnibox doesn't have invisible focus.
+ if (!extended_enabled_ || omnibox_focus_state_ != OMNIBOX_FOCUS_INVISIBLE)
return;
- // Commit the navigation if either:
- // - The page is in NTP mode (so it could only navigate on a user click) or
- // - The page is not in NTP mode and we are navigating to a URL with a
- // different host or path than the instant URL. This enables the instant
- // page when it is showing search results to change the query parameters
- // and fragments of the URL without it navigating.
- if (model_.mode().is_ntp() ||
- (url.host() != instant_url.host() || url.path() != instant_url.path())) {
- CommitIfPossible(INSTANT_COMMIT_NAVIGATED);
- }
+ DCHECK(IsContentsFrom(instant_tab(), contents));
+ contents->Focus();
}
-void InstantController::InstantLoaderRenderViewCreated() {
+void InstantController::NavigateToURL(const content::WebContents* contents,
+ const GURL& url,
+ content::PageTransition transition) {
+ // TODO(samarth): handle case where contents are no longer "active" (e.g. user
+ // has switched tabs).
if (!extended_enabled_)
return;
-
- // Ensure the searchbox API has the correct initial state.
- loader_->SetDisplayInstantResults(instant_enabled_);
- loader_->SearchModeChanged(search_mode_);
- loader_->KeyCaptureChanged(omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE);
- loader_->SetMarginSize(start_margin_, end_margin_);
- loader_->InitializeFonts();
+ if (overlay_)
+ HideOverlay();
+ browser_->OpenURLInCurrentTab(url, transition);
}
void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) {
@@ -986,8 +1081,8 @@ void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) {
// If the preview is not showing at all, recreate it if it's stale.
if (model_.mode().is_default()) {
- OnStaleLoader();
- MaybeSwitchToRemoteLoader();
+ ReloadOverlayIfStale();
+ MaybeSwitchToRemoteOverlay();
return;
}
@@ -998,47 +1093,39 @@ void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) {
#if defined(OS_MACOSX)
// TODO(sreeram): See if Mac really needs this special treatment.
- if (!loader_->is_pointer_down_from_activate())
- HideLoader();
+ if (!overlay_->is_pointer_down_from_activate())
+ HideOverlay();
#else
if (IsViewInContents(GetViewGainingFocus(view_gaining_focus),
- loader_->contents()))
+ overlay_->contents()))
CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST);
else
- HideLoader();
+ HideOverlay();
#endif
}
-void InstantController::NavigateToURL(const GURL& url,
- content::PageTransition transition) {
- LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
- "NavigateToURL: url='%s'", url.spec().c_str()));
-
- if (!extended_enabled_)
+void InstantController::ResetNTP() {
+ ntp_.reset();
+ std::string instant_url;
+ if (!GetInstantURL(browser_->profile(), false, &instant_url))
return;
- if (loader_)
- HideLoader();
- browser_->OpenURLInCurrentTab(url, transition);
-}
-
-void InstantController::LogDebugEvent(const std::string& info) const {
- DVLOG(1) << info;
- debug_events_.push_front(std::make_pair(
- base::Time::Now().ToInternalValue(), info));
- static const size_t kMaxDebugEventSize = 2000;
- if (debug_events_.size() > kMaxDebugEventSize)
- debug_events_.pop_back();
+ ntp_.reset(new InstantNTP(this, instant_url));
+ ntp_->InitContents(browser_->profile(), browser_->GetActiveWebContents(),
+ base::Bind(&InstantController::ResetNTP,
+ base::Unretained(this)));
}
-bool InstantController::EnsureLoaderIsCurrent(bool ignore_blacklist) {
+bool InstantController::EnsureOverlayIsCurrent(bool ignore_blacklist) {
// If there's no active tab, the browser is closing.
const content::WebContents* active_tab = browser_->GetActiveWebContents();
if (!active_tab)
return false;
+ Profile* profile = Profile::FromBrowserContext(
+ active_tab->GetBrowserContext());
std::string instant_url;
- if (!GetInstantURL(active_tab, ignore_blacklist, &instant_url)) {
+ if (!GetInstantURL(profile, ignore_blacklist, &instant_url)) {
// If we are in extended mode, fallback to the local popup.
if (extended_enabled_)
instant_url = kLocalOmniboxPopupURL;
@@ -1046,79 +1133,58 @@ bool InstantController::EnsureLoaderIsCurrent(bool ignore_blacklist) {
return false;
}
- if (!loader_ || loader_->instant_url() != instant_url)
- CreateLoader(instant_url, active_tab);
+ if (!overlay_ || overlay_->instant_url() != instant_url)
+ CreateOverlay(instant_url, active_tab);
return true;
}
-void InstantController::CreateLoader(const std::string& instant_url,
- const content::WebContents* active_tab) {
- // Update theme info so that the loader picks up the correct fonts.
- if (extended_enabled_)
- browser_->UpdateThemeInfoForPreview();
-
+void InstantController::CreateOverlay(const std::string& instant_url,
+ const content::WebContents* active_tab) {
HideInternal();
- loader_.reset(new InstantLoader(this, instant_url));
- loader_->InitContents(active_tab);
+ overlay_.reset(new InstantOverlay(this, instant_url));
+ overlay_->InitContents(browser_->profile(), active_tab);
LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
- "CreateLoader: instant_url='%s'", instant_url.c_str()));
-
- // Restart the stale loader timer.
- stale_loader_timer_.Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(kStaleLoaderTimeoutMS), this,
- &InstantController::OnStaleLoader);
-}
-
-void InstantController::OnStaleLoader() {
- // The local popup is never stale.
- if (loader_ && loader_->IsUsingLocalPreview())
- return;
-
- // If the preview is showing or the omnibox has focus, don't delete the
- // loader. It will get refreshed the next time the preview is hidden or the
- // omnibox loses focus.
- if (!stale_loader_timer_.IsRunning() &&
- omnibox_focus_state_ == OMNIBOX_FOCUS_NONE &&
- model_.mode().is_default()) {
- loader_.reset();
- EnsureLoaderIsCurrent(false);
- }
+ "CreateOverlay: instant_url='%s'", instant_url.c_str()));
}
-void InstantController::MaybeSwitchToRemoteLoader() {
- if (!loader_ || omnibox_focus_state_ != OMNIBOX_FOCUS_NONE ||
+void InstantController::MaybeSwitchToRemoteOverlay() {
+ if (!overlay_ || omnibox_focus_state_ != OMNIBOX_FOCUS_NONE ||
!model_.mode().is_default()) {
return;
}
- EnsureLoaderIsCurrent(false);
+ EnsureOverlayIsCurrent(false);
}
void InstantController::ResetInstantTab() {
// Do not wire up the InstantTab if instant should only use local previews, to
// prevent it from sending data to the page.
- if (search_mode_.is_origin_search() && !use_local_preview_only_) {
+ if (!search_mode_.is_origin_default() && !use_local_preview_only_) {
content::WebContents* active_tab = browser_->GetActiveWebContents();
if (!instant_tab_ || active_tab != instant_tab_->contents()) {
- instant_tab_.reset(new InstantTab(this, active_tab));
- instant_tab_->Init();
+ instant_tab_.reset(new InstantTab(this));
+ instant_tab_->Init(active_tab);
+ // Update theme info for this tab.
+ browser_->UpdateThemeInfoForPreview();
instant_tab_->SetDisplayInstantResults(instant_enabled_);
instant_tab_->SetMarginSize(start_margin_, end_margin_);
instant_tab_->InitializeFonts();
+ instant_tab_->KeyCaptureChanged(
+ omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE);
}
- // Hide the |loader_| since we are now using |instant_tab_| instead.
- HideLoader();
+ // Hide the |overlay_| since we are now using |instant_tab_| instead.
+ HideOverlay();
} else {
instant_tab_.reset();
}
}
-void InstantController::HideLoader() {
+void InstantController::HideOverlay() {
HideInternal();
- OnStaleLoader();
- MaybeSwitchToRemoteLoader();
+ ReloadOverlayIfStale();
+ MaybeSwitchToRemoteOverlay();
}
void InstantController::HideInternal() {
@@ -1133,35 +1199,36 @@ void InstantController::HideInternal() {
allow_preview_to_show_search_suggestions_ = false;
// Send a message asking the preview to clear out old results.
- loader_->Update(string16(), 0, 0, true);
+ overlay_->Update(string16(), 0, 0, true);
}
// Clear the first interaction timestamp for later use.
first_interaction_time_ = base::Time();
}
-void InstantController::ShowLoader(InstantShownReason reason,
- int height,
- InstantSizeUnits units) {
- // If we are on a committed search results page, the |loader_| is not in use.
+void InstantController::ShowOverlay(InstantShownReason reason,
+ int height,
+ InstantSizeUnits units) {
+ // If we are on a committed search results page, the |overlay_| is not in use.
if (instant_tab_)
return;
LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf(
"Show: reason=%d height=%d units=%d", reason, height, units));
- // Must be on NTP to show NTP content.
- if (reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT && !search_mode_.is_ntp())
+ // INSTANT_SHOWN_CUSTOM_NTP_CONTENT is no longer supported.
+ // TODO(samarth): remove once the server has been updated.
+ if (reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT)
return;
- // Must have updated omnibox after the last HideLoader() to show suggestions.
+ // Must have updated omnibox after the last HideOverlay() to show suggestions.
if ((reason == INSTANT_SHOWN_QUERY_SUGGESTIONS ||
reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION) &&
!allow_preview_to_show_search_suggestions_)
return;
// The page is trying to hide itself. Hide explicitly (i.e., don't use
- // HideLoader()) so that it can change its mind.
+ // HideOverlay()) so that it can change its mind.
if (height == 0) {
model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT);
return;
@@ -1180,7 +1247,7 @@ void InstantController::ShowLoader(InstantShownReason reason,
// - The page wants to show custom NTP content.
// - The page is over a website other than search or an NTP, and is not
// already showing at 100% height.
- if (loader_->IsUsingLocalPreview() || !instant_enabled_ ||
+ if (overlay_->IsUsingLocalPreview() || !instant_enabled_ ||
reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT ||
(search_mode_.is_origin_default() && !IsFullHeight(model_)))
model_.SetPreviewState(search_mode_, height, units);
@@ -1196,8 +1263,8 @@ void InstantController::ShowLoader(InstantShownReason reason,
}
void InstantController::SendPopupBoundsToPage() {
- if (last_popup_bounds_ == popup_bounds_ || !loader_ ||
- loader_->is_pointer_down_from_activate())
+ if (last_popup_bounds_ == popup_bounds_ || !overlay_ ||
+ overlay_->is_pointer_down_from_activate())
return;
last_popup_bounds_ = popup_bounds_;
@@ -1219,13 +1286,13 @@ void InstantController::SendPopupBoundsToPage() {
DCHECK_LE(0, intersection.width());
DCHECK_LE(0, intersection.height());
- loader_->SetPopupBounds(intersection);
+ overlay_->SetPopupBounds(intersection);
}
-bool InstantController::GetInstantURL(const content::WebContents* active_tab,
+bool InstantController::GetInstantURL(Profile* profile,
bool ignore_blacklist,
std::string* instant_url) const {
- DCHECK(active_tab);
+ DCHECK(profile);
instant_url->clear();
if (extended_enabled_ && use_local_preview_only_) {
@@ -1234,8 +1301,7 @@ bool InstantController::GetInstantURL(const content::WebContents* active_tab,
}
const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile(
- Profile::FromBrowserContext(active_tab->GetBrowserContext()))->
- GetDefaultSearchProvider();
+ profile)->GetDefaultSearchProvider();
if (!template_url) {
LOG_INSTANT_DEBUG_EVENT(this, "GetInstantURL: No template URL");
@@ -1316,3 +1382,26 @@ bool InstantController::GetInstantURL(const content::WebContents* active_tab,
return true;
}
+
+void InstantController::BlacklistAndResetNTP() {
+ ++blacklisted_urls_[ntp_->instant_url()];
+ RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST);
+ delete ntp_->ReleaseContents().release();
+ MessageLoop::current()->DeleteSoon(FROM_HERE, ntp_.release());
+ ResetNTP();
+}
+
+void InstantController::BlacklistAndResetOverlay() {
+ ++blacklisted_urls_[overlay_->instant_url()];
+ RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST);
+ HideInternal();
+ delete overlay_->ReleaseContents().release();
+ MessageLoop::current()->DeleteSoon(FROM_HERE, overlay_.release());
+ EnsureOverlayIsCurrent(false);
+}
+
+void InstantController::RemoveFromBlacklist(const std::string& url) {
+ if (blacklisted_urls_.erase(url)) {
+ RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST);
+ }
+}
diff --git a/chrome/browser/instant/instant_controller.h b/chrome/browser/instant/instant_controller.h
index 40bbfc8..1a08425 100644
--- a/chrome/browser/instant/instant_controller.h
+++ b/chrome/browser/instant/instant_controller.h
@@ -19,6 +19,7 @@
#include "base/timer.h"
#include "chrome/browser/instant/instant_commit_type.h"
#include "chrome/browser/instant/instant_model.h"
+#include "chrome/browser/instant/instant_page.h"
#include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
#include "chrome/common/instant_types.h"
#include "chrome/common/search_types.h"
@@ -29,7 +30,8 @@
struct AutocompleteMatch;
class AutocompleteProvider;
-class InstantLoader;
+class InstantNTP;
+class InstantOverlay;
class InstantTab;
class TemplateURL;
@@ -45,17 +47,32 @@ class WebContents;
#define LOG_INSTANT_DEBUG_EVENT(controller, message) \
controller->LogDebugEvent(message)
-// InstantController maintains a WebContents that is intended to give a preview
-// of search suggestions and results. InstantController is owned by Browser via
-// BrowserInstantController.
-class InstantController {
+// 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 sarch 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:
// The URL for the local omnibox popup.
static const char* kLocalOmniboxPopupURL;
InstantController(chrome::BrowserInstantController* browser,
bool extended_enabled);
- ~InstantController();
+ 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
@@ -75,6 +92,10 @@ class InstantController {
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);
@@ -108,7 +129,7 @@ class InstantController {
gfx::NativeView view_gaining_focus);
// The search mode in the active tab has changed. Pass the message down to
- // the loader which will notify the renderer. Create |instant_tab_| if the
+ // 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);
@@ -131,58 +152,16 @@ class InstantController {
// The theme area height has changed. Pass the message to the preview page.
void ThemeAreaHeightChanged(int height);
- // 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.
- InstantModel* model() { return &model_; }
-
- // Invoked by the page when it has suggested text.
- void SetSuggestions(const content::WebContents* contents,
- const std::vector<InstantSuggestion>& suggestions);
+ // Called when someone else swapped in a different contents in the |overlay_|.
+ void SwappedOverlayContents();
- // Invoked by the page when its support for the Instant API is determined.
- void InstantSupportDetermined(const content::WebContents* contents,
- bool supports_instant);
-
- // Invoked by InstantLoader to request that the preview be shown.
- void ShowInstantPreview(InstantShownReason reason,
- int height,
- InstantSizeUnits units);
-
- // Invoked by InstantLoader to request the browser to start capturing user key
- // strokes.
- void StartCapturingKeyStrokes();
-
- // Invoked by InstantLoader to request the browser to stop capturing user key
- // strokes.
- void StopCapturingKeyStrokes();
-
- // Invoked by InstantLoader when it has swapped a different WebContents into
- // the preview, usually because a prerendered page was navigated to.
- void SwappedWebContents();
-
- // Invoked by InstantLoader when the preview gains focus, usually due to the
- // user clicking on it.
- void InstantLoaderContentsFocused();
-
- // Invoked by the InstantLoader when its RenderView crashes.
- void InstantLoaderRenderViewGone();
-
- // Invoked by InstantLoader when the instant page is about to navigate.
- void InstantLoaderAboutToNavigateMainFrame(const GURL& url);
-
- // Invoked by InstantLoader when it's underlying RenderView is created.
- // TODO(shishir): We assume that the WebContent's current RenderViewHost is
- // the RenderViewHost being created which is not always true. Fix this.
- void InstantLoaderRenderViewCreated();
+ // Called when contents for |overlay_| received focus.
+ void FocusedOverlayContents();
- // Invoked by the InstantLoader when the instant page wants to navigate to
- // the speicfied URL.
- void NavigateToURL(const GURL& url, content::PageTransition transition);
+ // Called when the |overlay_| might be stale. If it's actually stale, and the
+ // omnibox doesn't have focus, and the preview isn't showing, the |overlay_|
+ // is deleted and recreated. Else the refresh is skipped.
+ void ReloadOverlayIfStale();
// Adds a new event to |debug_events_| and also DVLOG's it. Ensures that
// |debug_events_| doesn't get too large.
@@ -193,39 +172,79 @@ class InstantController {
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.
+ InstantModel* 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, InstantLoaderRefresh);
+ FRIEND_TEST_ALL_PREFIXES(InstantTest, InstantOverlayRefresh);
FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, ExtendedModeIsOn);
FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, OmniboxFocusLoadsInstant);
+ FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, NTPIsPreloaded);
+ FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, PreloadedNTPIsUsedInNewTab);
+ FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, PreloadedNTPIsUsedInSameTab);
+ FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, ProcessIsolation);
+
+ // 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 ShowInstantPreview(
+ const content::WebContents* contents,
+ InstantShownReason reason,
+ int height,
+ InstantSizeUnits units) 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) OVERRIDE;
// Helper for OmniboxFocusChanged. Commit or discard the preview.
void OmniboxLostFocus(gfx::NativeView view_gaining_focus);
- // Ensures that |loader_| uses the Instant URL returned by GetInstantURL(),
- // creating a new loader if necessary. In extended mode, will fallback to
+ // 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 EnsureLoaderIsCurrent(bool ignore_blacklist);
+ bool EnsureOverlayIsCurrent(bool ignore_blacklist);
- // Recreates the |loader_| with the input |instant_url|. The caller should
- // ensure that the |loader_| is not already on the stack since it is deleted
- // in this call.
- void CreateLoader(const std::string& instant_url,
- const content::WebContents* active_tab);
+ // 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);
- // Called when the |loader_| might be stale. If it's actually stale, and the
- // omnibox doesn't have focus, and the preview isn't showing, the |loader_| is
- // deleted and recreated. Else the refresh is skipped.
- void OnStaleLoader();
-
- // If the |loader_| being used is in fallback mode, it will be switched back
- // to the remote loader if the loader is not showing and the omnibox does not
- // have focus.
- void MaybeSwitchToRemoteLoader();
+ // 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_|.
@@ -233,17 +252,17 @@ class InstantController {
// Hide the preview. Also sends an onchange event (with blank query) to the
// preview, telling it to clear out results for any old queries.
- void HideLoader();
+ void HideOverlay();
- // Like HideLoader(), but doesn't call OnStaleLoader(). Use HideLoader()
- // unless you are going to call loader_.reset() yourself subsequently.
+ // Like HideOverlay(), but doesn't call OnStaleOverlay(). Use HideOverlay()
+ // unless you are going to call overlay_.reset() yourself subsequently.
void HideInternal();
- // Counterpart to HideLoader(). Asks the |browser_| to display the preview
- // with the given |height|.
- void ShowLoader(InstantShownReason reason,
- int height,
- InstantSizeUnits units);
+ // Counterpart to HideOverlay(). Asks the |browser_| to display the preview
+ // with the given |height| in |units|.
+ void ShowOverlay(InstantShownReason reason,
+ int height,
+ InstantSizeUnits units);
// Send the omnibox popup bounds to the page.
void SendPopupBoundsToPage();
@@ -261,10 +280,22 @@ class InstantController {
// the blacklist.
//
// Returns true if a valid Instant URL could be found that is not blacklisted.
- bool GetInstantURL(const content::WebContents* active_tab,
+ 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(); }
+
chrome::BrowserInstantController* const browser_;
// Whether the extended API and regular API are enabled. If both are false,
@@ -275,19 +306,22 @@ class InstantController {
// If true, the instant URL is set to kLocalOmniboxPopupURL.
bool use_local_preview_only_;
- // The state of the preview page, i.e., the page owned by |loader_|. Ignored
+ // The state of the preview page, i.e., the page owned by |overlay_|. Ignored
// if |instant_tab_| is in use.
InstantModel model_;
- // The preview WebContents.
- scoped_ptr<InstantLoader> loader_;
-
- // A committed WebContents that supports Instant. If non-NULL, the |loader_|
- // is guaranteed to be hidden and messages will be sent to this instead.
+ // 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 |loader_| or |instant_tab_|.
+ // search suggestions from |overlay_| or |instant_tab_|.
string16 last_omnibox_text_;
// True if the last Update() had an inline autocompletion. Used only to make
@@ -330,9 +364,6 @@ class InstantController {
// Timer used to update the bounds of the omnibox popup.
base::OneShotTimer<InstantController> update_bounds_timer_;
- // Timer used to ensure that the Instant page does not get too stale.
- base::OneShotTimer<InstantController> stale_loader_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.
diff --git a/chrome/browser/instant/instant_extended_browsertest.cc b/chrome/browser/instant/instant_extended_browsertest.cc
index 6defb4b..33195fc 100644
--- a/chrome/browser/instant/instant_extended_browsertest.cc
+++ b/chrome/browser/instant/instant_extended_browsertest.cc
@@ -3,11 +3,20 @@
// found in the LICENSE file.
#include "chrome/browser/instant/instant_commit_type.h"
-#include "chrome/browser/instant/instant_loader.h"
+#include "chrome/browser/instant/instant_ntp.h"
+#include "chrome/browser/instant/instant_overlay.h"
+#include "chrome/browser/instant/instant_service.h"
+#include "chrome/browser/instant/instant_service_factory.h"
#include "chrome/browser/instant/instant_test_utils.h"
#include "chrome/browser/ui/search/search.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/url_constants.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
class InstantExtendedTest : public InstantTestBase {
protected:
@@ -18,6 +27,18 @@ class InstantExtendedTest : public InstantTestBase {
GetURL("files/instant_extended.html?strk=1&");
}
+ void FocusOmniboxAndWaitForInstantSupport() {
+ content::WindowedNotificationObserver ntp_observer(
+ chrome::NOTIFICATION_INSTANT_NTP_SUPPORT_DETERMINED,
+ content::NotificationService::AllSources());
+ content::WindowedNotificationObserver overlay_observer(
+ chrome::NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED,
+ content::NotificationService::AllSources());
+ FocusOmnibox();
+ ntp_observer.Wait();
+ overlay_observer.Wait();
+ }
+
std::string GetOmniboxText() {
return UTF16ToUTF8(omnibox()->GetText());
}
@@ -52,7 +73,7 @@ IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OmniboxFocusLoadsInstant) {
EXPECT_FALSE(omnibox()->model()->has_focus());
// Delete any existing preview.
- instant()->loader_.reset();
+ instant()->overlay_.reset();
EXPECT_FALSE(instant()->GetPreviewContents());
// Refocus the omnibox. The InstantController should've preloaded Instant.
@@ -65,7 +86,7 @@ IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OmniboxFocusLoadsInstant) {
EXPECT_TRUE(preview_tab);
// Check that the page supports Instant, but it isn't showing.
- EXPECT_TRUE(instant()->loader_->supports_instant());
+ EXPECT_TRUE(instant()->overlay_->supports_instant());
EXPECT_FALSE(instant()->IsPreviewingSearchResults());
EXPECT_TRUE(instant()->model()->mode().is_default());
@@ -168,3 +189,155 @@ IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NavigateSuggestionsWithArrowKeys) {
SendUpArrow();
EXPECT_EQ("hello", GetOmniboxText());
}
+
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest, NTPIsPreloaded) {
+ // Setup Instant.
+ ASSERT_NO_FATAL_FAILURE(SetupInstant());
+ FocusOmniboxAndWaitForInstantSupport();
+
+ // NTP contents should be preloaded.
+ ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
+ content::WebContents* ntp_contents = instant()->ntp_->contents();
+ EXPECT_TRUE(ntp_contents);
+}
+
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest, PreloadedNTPIsUsedInNewTab) {
+ // Setup Instant.
+ ASSERT_NO_FATAL_FAILURE(SetupInstant());
+ FocusOmniboxAndWaitForInstantSupport();
+
+ // NTP contents should be preloaded.
+ ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
+ content::WebContents* ntp_contents = instant()->ntp_->contents();
+ EXPECT_TRUE(ntp_contents);
+
+ // Open new tab. Preloaded NTP contents should have been used.
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(),
+ GURL(chrome::kChromeUINewTabURL),
+ NEW_FOREGROUND_TAB,
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+ content::WebContents* active_tab =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ EXPECT_EQ(ntp_contents, active_tab);
+}
+
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest, PreloadedNTPIsUsedInSameTab) {
+ // Setup Instant.
+ ASSERT_NO_FATAL_FAILURE(SetupInstant());
+ FocusOmniboxAndWaitForInstantSupport();
+
+ // NTP contents should be preloaded.
+ ASSERT_NE(static_cast<InstantNTP*>(NULL), instant()->ntp());
+ content::WebContents* ntp_contents = instant()->ntp_->contents();
+ EXPECT_TRUE(ntp_contents);
+
+ // Open new tab. Preloaded NTP contents should have been used.
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(),
+ GURL(chrome::kChromeUINewTabURL),
+ CURRENT_TAB,
+ ui_test_utils::BROWSER_TEST_NONE);
+ content::WebContents* active_tab =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ EXPECT_EQ(ntp_contents, active_tab);
+}
+
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OmniboxHasFocusOnNewTab) {
+ // Setup Instant.
+ ASSERT_NO_FATAL_FAILURE(SetupInstant());
+ FocusOmniboxAndWaitForInstantSupport();
+
+ // Explicitly unfocus the omnibox.
+ EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+ ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
+ EXPECT_FALSE(omnibox()->model()->has_focus());
+
+ // Open new tab. Preloaded NTP contents should have been used.
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(),
+ GURL(chrome::kChromeUINewTabURL),
+ NEW_FOREGROUND_TAB,
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+
+ // Omnibox should have focus.
+ EXPECT_TRUE(omnibox()->model()->has_focus());
+}
+
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest, OmniboxEmptyOnNewTabPage) {
+ // Setup Instant.
+ ASSERT_NO_FATAL_FAILURE(SetupInstant());
+ FocusOmniboxAndWaitForInstantSupport();
+
+ // Open new tab. Preloaded NTP contents should have been used.
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(),
+ GURL(chrome::kChromeUINewTabURL),
+ CURRENT_TAB,
+ ui_test_utils::BROWSER_TEST_NONE);
+
+ // Omnibox should be empty.
+ EXPECT_TRUE(omnibox()->GetText().empty());
+}
+
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest, InputOnNTPDoesntShowOverlay) {
+ ASSERT_NO_FATAL_FAILURE(SetupInstant());
+
+ // Focus omnibox and confirm overlay isn't shown.
+ FocusOmniboxAndWaitForInstantSupport();
+ content::WebContents* preview_tab = instant()->GetPreviewContents();
+ EXPECT_TRUE(preview_tab);
+ EXPECT_FALSE(instant()->IsPreviewingSearchResults());
+ EXPECT_TRUE(instant()->model()->mode().is_default());
+
+ // Navigate to the NTP.
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(),
+ GURL(chrome::kChromeUINewTabURL),
+ CURRENT_TAB,
+ ui_test_utils::BROWSER_TEST_NONE);
+
+ // Typing in the omnibox should not show the overlay.
+ SetOmniboxText("query");
+ EXPECT_FALSE(instant()->IsPreviewingSearchResults());
+ EXPECT_TRUE(instant()->model()->mode().is_default());
+}
+
+IN_PROC_BROWSER_TEST_F(InstantExtendedTest, ProcessIsolation) {
+ // Prior to setup no render process is dedicated to Instant.
+ InstantService* instant_service =
+ InstantServiceFactory::GetForProfile(browser()->profile());
+ ASSERT_NE(static_cast<InstantService*>(NULL), instant_service);
+ EXPECT_EQ(0, instant_service->GetInstantProcessCount());
+
+ // Setup Instant.
+ ASSERT_NO_FATAL_FAILURE(SetupInstant());
+ FocusOmniboxAndWaitForInstantSupport();
+
+ // Now there should be a registered Instant render process.
+ EXPECT_LT(0, instant_service->GetInstantProcessCount());
+
+ // And the Instant overlay and ntp should live inside it.
+ content::WebContents* preview = instant()->GetPreviewContents();
+ EXPECT_TRUE(instant_service->IsInstantProcess(
+ preview->GetRenderProcessHost()->GetID()));
+ content::WebContents* ntp_contents = instant()->ntp_->contents();
+ EXPECT_TRUE(instant_service->IsInstantProcess(
+ ntp_contents->GetRenderProcessHost()->GetID()));
+
+ // Navigating to the NTP should use the Instant render process.
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(),
+ GURL(chrome::kChromeUINewTabURL),
+ CURRENT_TAB,
+ ui_test_utils::BROWSER_TEST_NONE);
+ content::WebContents* active_tab =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ EXPECT_TRUE(instant_service->IsInstantProcess(
+ active_tab->GetRenderProcessHost()->GetID()));
+
+ // Navigating elsewhere should not use the Instant render process.
+ ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIAboutURL));
+ EXPECT_FALSE(instant_service->IsInstantProcess(
+ active_tab->GetRenderProcessHost()->GetID()));
+}
diff --git a/chrome/browser/instant/instant_loader.cc b/chrome/browser/instant/instant_loader.cc
index 18f4bdd..543a580 100644
--- a/chrome/browser/instant/instant_loader.cc
+++ b/chrome/browser/instant/instant_loader.cc
@@ -8,348 +8,73 @@
#include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h"
#include "chrome/browser/favicon/favicon_tab_helper.h"
#include "chrome/browser/history/history_tab_helper.h"
-#include "chrome/browser/instant/instant_controller.h"
#include "chrome/browser/safe_browsing/safe_browsing_tab_observer.h"
+#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h"
#include "chrome/browser/ui/search/search_tab_helper.h"
#include "chrome/browser/ui/tab_contents/core_tab_helper.h"
-#include "chrome/browser/ui/tab_contents/core_tab_helper_delegate.h"
+#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/site_instance.h"
-#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_view.h"
-#include "ipc/ipc_message.h"
namespace {
-int kUserDataKey;
+const int kStalePageTimeoutMS = 3 * 3600 * 1000; // 3 hours
-class InstantLoaderUserData : public base::SupportsUserData::Data {
- public:
- explicit InstantLoaderUserData(InstantLoader* loader) : loader_(loader) {}
+// This HTTP header and value are set on loads that originate from Instant.
+const char kInstantHeader[] = "X-Purpose: Instant";
- InstantLoader* loader() const { return loader_; }
+} // namespace
- private:
- virtual ~InstantLoaderUserData() {}
-
- InstantLoader* const loader_;
-
- DISALLOW_COPY_AND_ASSIGN(InstantLoaderUserData);
-};
-
-}
-
-// WebContentsDelegateImpl -----------------------------------------------------
-
-class InstantLoader::WebContentsDelegateImpl
- : public CoreTabHelperDelegate,
- public content::WebContentsDelegate {
- public:
- explicit WebContentsDelegateImpl(InstantLoader* loader);
-
- private:
- // Overridden from CoreTabHelperDelegate:
- virtual void SwapTabContents(content::WebContents* old_contents,
- content::WebContents* new_contents) OVERRIDE;
-
- // Overridden from content::WebContentsDelegate:
- virtual bool ShouldSuppressDialogs() OVERRIDE;
- virtual bool ShouldFocusPageAfterCrash() OVERRIDE;
- virtual void LostCapture() OVERRIDE;
- virtual void WebContentsFocused(content::WebContents* contents) OVERRIDE;
- virtual bool CanDownload(content::RenderViewHost* render_view_host,
- int request_id,
- const std::string& request_method) OVERRIDE;
- virtual void HandleMouseDown() OVERRIDE;
- virtual void HandleMouseUp() OVERRIDE;
- virtual void HandlePointerActivate() OVERRIDE;
- virtual void HandleGestureEnd() OVERRIDE;
- virtual void DragEnded() OVERRIDE;
- virtual bool OnGoToEntryOffset(int offset) OVERRIDE;
- virtual content::WebContents* OpenURLFromTab(
- content::WebContents* source,
- const content::OpenURLParams& params) OVERRIDE;
-
- void MaybeCommitFromPointerRelease();
-
- InstantLoader* const loader_;
-
- DISALLOW_COPY_AND_ASSIGN(WebContentsDelegateImpl);
-};
-
-InstantLoader::WebContentsDelegateImpl::WebContentsDelegateImpl(
- InstantLoader* loader)
- : loader_(loader) {
-}
-
-void InstantLoader::WebContentsDelegateImpl::SwapTabContents(
- content::WebContents* old_contents,
- content::WebContents* new_contents) {
- // If this is being called, something is swapping in to loader's |contents_|
- // before we've added it to the tab strip.
- loader_->ReplacePreviewContents(old_contents, new_contents);
-}
-
-bool InstantLoader::WebContentsDelegateImpl::ShouldSuppressDialogs() {
- // Any message shown during Instant cancels Instant, so we suppress them.
- return true;
+InstantLoader::Delegate::~Delegate() {
}
-bool InstantLoader::WebContentsDelegateImpl::ShouldFocusPageAfterCrash() {
- return false;
-}
-
-void InstantLoader::WebContentsDelegateImpl::LostCapture() {
- MaybeCommitFromPointerRelease();
-}
-
-void InstantLoader::WebContentsDelegateImpl::WebContentsFocused(
- content::WebContents* /* contents */) {
- // The preview is getting focus. Equivalent to it being clicked.
- bool tmp = loader_->is_pointer_down_from_activate_;
- loader_->is_pointer_down_from_activate_ = true;
- loader_->controller_->InstantLoaderContentsFocused();
- loader_->is_pointer_down_from_activate_ = tmp;
-}
-
-bool InstantLoader::WebContentsDelegateImpl::CanDownload(
- content::RenderViewHost* /* render_view_host */,
- int /* request_id */,
- const std::string& /* request_method */) {
- // Downloads are disabled.
- return false;
-}
-
-void InstantLoader::WebContentsDelegateImpl::HandleMouseDown() {
- loader_->is_pointer_down_from_activate_ = true;
-}
-
-void InstantLoader::WebContentsDelegateImpl::HandleMouseUp() {
- MaybeCommitFromPointerRelease();
-}
-
-void InstantLoader::WebContentsDelegateImpl::HandlePointerActivate() {
- loader_->is_pointer_down_from_activate_ = true;
-}
-
-void InstantLoader::WebContentsDelegateImpl::HandleGestureEnd() {
- MaybeCommitFromPointerRelease();
-}
-
-void InstantLoader::WebContentsDelegateImpl::DragEnded() {
- // If the user drags, we won't get a mouse up (at least on Linux). Commit the
- // Instant result when the drag ends, so that during the drag the page won't
- // move around.
- MaybeCommitFromPointerRelease();
-}
-
-bool InstantLoader::WebContentsDelegateImpl::OnGoToEntryOffset(int offset) {
- return false;
-}
-
-content::WebContents* InstantLoader::WebContentsDelegateImpl::OpenURLFromTab(
- content::WebContents* source,
- const content::OpenURLParams& params) {
- content::WebContents* preview = loader_->contents_.get();
- if (loader_->controller_->CommitIfPossible(INSTANT_COMMIT_NAVIGATED))
- return preview->GetDelegate()->OpenURLFromTab(source, params);
- return NULL;
-}
-
-void InstantLoader::WebContentsDelegateImpl::MaybeCommitFromPointerRelease() {
- if (loader_->is_pointer_down_from_activate_) {
- loader_->is_pointer_down_from_activate_ = false;
- loader_->controller_->CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST);
- }
-}
-
-// InstantLoader ---------------------------------------------------------------
-
-// static
-InstantLoader* InstantLoader::FromWebContents(
- const content::WebContents* web_contents) {
- InstantLoaderUserData* data = static_cast<InstantLoaderUserData*>(
- web_contents->GetUserData(&kUserDataKey));
- return data ? data->loader() : NULL;
-}
-
-InstantLoader::InstantLoader(InstantController* controller,
- const std::string& instant_url)
- : client_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
- controller_(controller),
- delegate_(new WebContentsDelegateImpl(
- ALLOW_THIS_IN_INITIALIZER_LIST(this))),
- instant_url_(instant_url),
- supports_instant_(false),
- is_pointer_down_from_activate_(false) {
+InstantLoader::InstantLoader(Delegate* delegate)
+ : delegate_(delegate),
+ contents_(NULL),
+ stale_page_timer_(false, false) {
}
InstantLoader::~InstantLoader() {
}
-void InstantLoader::InitContents(const content::WebContents* active_tab) {
- content::WebContents::CreateParams create_params(
- active_tab->GetBrowserContext(),
- active_tab->GetSiteInstance()->GetRelatedSiteInstance(
- GURL(instant_url_)));
- if (active_tab)
+void InstantLoader::Init(const GURL& instant_url,
+ Profile* profile,
+ const content::WebContents* active_tab,
+ const base::Closure& on_stale_callback) {
+ content::WebContents::CreateParams create_params(profile);
+ if (active_tab) {
create_params.initial_size = active_tab->GetView()->GetContainerSize();
- contents_.reset(content::WebContents::CreateWithSessionStorage(
- create_params,
- active_tab->GetController().GetSessionStorageNamespaceMap()));
- SetupPreviewContents();
+ create_params.site_instance = active_tab->GetSiteInstance()->
+ GetRelatedSiteInstance(instant_url);
+ } else {
+ create_params.site_instance = content::SiteInstance::CreateForURL(
+ profile, instant_url);
+ }
+ SetContents(scoped_ptr<content::WebContents>(
+ content::WebContents::Create(create_params)));
+ instant_url_ = instant_url;
+ on_stale_callback_ = on_stale_callback;
+}
- // This HTTP header and value are set on loads that originate from Instant.
- const char kInstantHeader[] = "X-Purpose: Instant";
+void InstantLoader::Load() {
DVLOG(1) << "LoadURL: " << instant_url_;
- contents_->GetController().LoadURL(GURL(instant_url_), content::Referrer(),
+ contents_->GetController().LoadURL(
+ instant_url_, content::Referrer(),
content::PAGE_TRANSITION_GENERATED, kInstantHeader);
contents_->WasHidden();
+ stale_page_timer_.Start(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kStalePageTimeoutMS),
+ on_stale_callback_);
}
-content::WebContents* InstantLoader::ReleaseContents() {
- CleanupPreviewContents();
- return contents_.release();
-}
-
-void InstantLoader::DidNavigate(
- const history::HistoryAddPageArgs& add_page_args) {
- last_navigation_ = add_page_args;
-}
-
-bool InstantLoader::IsUsingLocalPreview() const {
- return instant_url_ == InstantController::kLocalOmniboxPopupURL;
-}
-
-void InstantLoader::Update(const string16& text,
- size_t selection_start,
- size_t selection_end,
- bool verbatim) {
- last_navigation_ = history::HistoryAddPageArgs();
- client_.Update(text, selection_start, selection_end, verbatim);
-}
-
-void InstantLoader::Submit(const string16& text) {
- client_.Submit(text);
-}
-
-void InstantLoader::Cancel(const string16& text) {
- client_.Cancel(text);
-}
-
-void InstantLoader::SetPopupBounds(const gfx::Rect& bounds) {
- client_.SetPopupBounds(bounds);
-}
-
-void InstantLoader::SetMarginSize(int start, int end) {
- client_.SetMarginSize(start, end);
-}
-
-void InstantLoader::InitializeFonts() {
- client_.InitializeFonts();
-}
-
-void InstantLoader::SendAutocompleteResults(
- const std::vector<InstantAutocompleteResult>& results) {
- client_.SendAutocompleteResults(results);
-}
-
-void InstantLoader::UpOrDownKeyPressed(int count) {
- client_.UpOrDownKeyPressed(count);
-}
-
-void InstantLoader::SearchModeChanged(const chrome::search::Mode& mode) {
- client_.SearchModeChanged(mode);
-}
-
-void InstantLoader::SendThemeBackgroundInfo(
- const ThemeBackgroundInfo& theme_info) {
- client_.SendThemeBackgroundInfo(theme_info);
-}
-
-void InstantLoader::SendThemeAreaHeight(int height) {
- client_.SendThemeAreaHeight(height);
-}
-
-void InstantLoader::SetDisplayInstantResults(bool display_instant_results) {
- client_.SetDisplayInstantResults(display_instant_results);
-}
-
-void InstantLoader::KeyCaptureChanged(bool is_key_capture_enabled) {
- client_.KeyCaptureChanged(is_key_capture_enabled);
-}
-
-void InstantLoader::SetSuggestions(
- const std::vector<InstantSuggestion>& suggestions) {
- InstantSupportDetermined(true);
- controller_->SetSuggestions(contents(), suggestions);
-}
-
-void InstantLoader::InstantSupportDetermined(bool supports_instant) {
- // If we had already determined that the page supports Instant, nothing to do.
- if (supports_instant_)
- return;
-
- supports_instant_ = supports_instant;
- controller_->InstantSupportDetermined(contents(), supports_instant);
-}
-
-void InstantLoader::ShowInstantPreview(InstantShownReason reason,
- int height,
- InstantSizeUnits units) {
- InstantSupportDetermined(true);
- controller_->ShowInstantPreview(reason, height, units);
-}
-
-void InstantLoader::StartCapturingKeyStrokes() {
- InstantSupportDetermined(true);
- controller_->StartCapturingKeyStrokes();
-}
-
-void InstantLoader::StopCapturingKeyStrokes() {
- InstantSupportDetermined(true);
- controller_->StopCapturingKeyStrokes();
-}
-
-void InstantLoader::RenderViewGone() {
- controller_->InstantLoaderRenderViewGone();
-}
-
-void InstantLoader::AboutToNavigateMainFrame(const GURL& url) {
- controller_->InstantLoaderAboutToNavigateMainFrame(url);
-}
-
-void InstantLoader::NavigateToURL(const GURL& url,
- content::PageTransition transition) {
- InstantSupportDetermined(true);
- controller_->NavigateToURL(url, transition);
-}
-
-void InstantLoader::RenderViewCreated() {
- controller_->InstantLoaderRenderViewCreated();
-}
-
-void InstantLoader::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
-#if defined(OS_MACOSX)
- if (type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED) {
- if (content::RenderWidgetHostView* rwhv =
- contents_->GetRenderWidgetHostView())
- rwhv->SetTakesFocusOnlyOnMouseDown(true);
- return;
- }
- NOTREACHED();
-#endif
-}
-
-void InstantLoader::SetupPreviewContents() {
- client_.SetContents(contents());
- contents_->SetUserData(&kUserDataKey, new InstantLoaderUserData(this));
- contents_->SetDelegate(delegate_.get());
+void InstantLoader::SetContents(scoped_ptr<content::WebContents> new_contents) {
+ contents_.reset(new_contents.release());
+ contents_->SetDelegate(this);
// Set up various tab helpers. The rest will get attached when (if) the
// contents is added to the tab strip.
@@ -364,7 +89,7 @@ void InstantLoader::SetupPreviewContents() {
// A tab helper to catch prerender content swapping shenanigans.
CoreTabHelper::CreateForWebContents(contents());
- CoreTabHelper::FromWebContents(contents())->set_delegate(delegate_.get());
+ CoreTabHelper::FromWebContents(contents())->set_delegate(this);
// Tab helpers used when committing a preview.
chrome::search::SearchTabHelper::CreateForWebContents(contents());
@@ -391,12 +116,10 @@ void InstantLoader::SetupPreviewContents() {
#endif
}
-void InstantLoader::CleanupPreviewContents() {
- client_.SetContents(NULL);
- contents_->RemoveUserData(&kUserDataKey);
+scoped_ptr<content::WebContents> InstantLoader::ReleaseContents() {
contents_->SetDelegate(NULL);
- // Undo tab helper work done in SetupPreviewContents().
+ // Undo tab helper work done in SetContents().
BlockedContentTabHelper::FromWebContents(contents())->
SetAllContentsBlocked(false);
@@ -413,16 +136,87 @@ void InstantLoader::CleanupPreviewContents() {
content::Source<content::NavigationController>(
&contents_->GetController()));
#endif
+
+ return contents_.Pass();
}
-void InstantLoader::ReplacePreviewContents(content::WebContents* old_contents,
- content::WebContents* new_contents) {
+void InstantLoader::Observe(int type,
+ const content::NotificationSource& /* source */,
+ const content::NotificationDetails& /* details */) {
+#if defined(OS_MACOSX)
+ if (type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED) {
+ if (content::RenderWidgetHostView* rwhv =
+ contents_->GetRenderWidgetHostView())
+ rwhv->SetTakesFocusOnlyOnMouseDown(true);
+ return;
+ }
+ NOTREACHED();
+#endif
+}
+
+void InstantLoader::SwapTabContents(content::WebContents* old_contents,
+ content::WebContents* new_contents) {
DCHECK_EQ(old_contents, contents());
- CleanupPreviewContents();
- // We release here without deleting so that the caller still has the
- // responsibility for deleting the WebContents.
- ignore_result(contents_.release());
- contents_.reset(new_contents);
- SetupPreviewContents();
- controller_->SwappedWebContents();
+ // We release here without deleting since the caller has the responsibility
+ // for deleting the old WebContents.
+ ignore_result(ReleaseContents().release());
+ SetContents(scoped_ptr<content::WebContents>(new_contents));
+ delegate_->OnSwappedContents();
+}
+
+bool InstantLoader::ShouldSuppressDialogs() {
+ // Messages shown during Instant cancel Instant, so we suppress them.
+ return true;
+}
+
+bool InstantLoader::ShouldFocusPageAfterCrash() {
+ return false;
+}
+
+void InstantLoader::LostCapture() {
+ delegate_->OnMouseUp();
+}
+
+void InstantLoader::WebContentsFocused(content::WebContents* /* contents */) {
+ delegate_->OnFocus();
+}
+
+bool InstantLoader::CanDownload(content::RenderViewHost* /* render_view_host */,
+ int /* request_id */,
+ const std::string& /* request_method */) {
+ // Downloads are disabled.
+ return false;
+}
+
+void InstantLoader::HandleMouseDown() {
+ delegate_->OnMouseDown();
+}
+
+void InstantLoader::HandleMouseUp() {
+ delegate_->OnMouseUp();
+}
+
+void InstantLoader::HandlePointerActivate() {
+ delegate_->OnMouseDown();
+}
+
+void InstantLoader::HandleGestureEnd() {
+ delegate_->OnMouseUp();
+}
+
+void InstantLoader::DragEnded() {
+ // If the user drags, we won't get a mouse up (at least on Linux). Commit
+ // the Instant result when the drag ends, so that during the drag the page
+ // won't move around.
+ delegate_->OnMouseUp();
+}
+
+bool InstantLoader::OnGoToEntryOffset(int /* offset */) {
+ return false;
+}
+
+content::WebContents* InstantLoader::OpenURLFromTab(
+ content::WebContents* source,
+ const content::OpenURLParams& params) {
+ return delegate_->OpenURLFromTab(source, params);
}
diff --git a/chrome/browser/instant/instant_loader.h b/chrome/browser/instant/instant_loader.h
index be244f5..b9f9fa9 100644
--- a/chrome/browser/instant/instant_loader.h
+++ b/chrome/browser/instant/instant_loader.h
@@ -5,152 +5,127 @@
#ifndef CHROME_BROWSER_INSTANT_INSTANT_LOADER_H_
#define CHROME_BROWSER_INSTANT_INSTANT_LOADER_H_
-#include <string>
-#include <vector>
-
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "base/string16.h"
-#include "chrome/browser/history/history_types.h"
-#include "chrome/browser/instant/instant_client.h"
+#include "base/timer.h"
+#include "chrome/browser/ui/tab_contents/core_tab_helper_delegate.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/web_contents_delegate.h"
-struct InstantAutocompleteResult;
-class InstantController;
-struct ThemeBackgroundInfo;
-
-namespace chrome {
-namespace search {
-struct Mode;
-}
-}
+class GURL;
+class Profile;
namespace content {
+struct OpenURLParams;
class WebContents;
}
-namespace gfx {
-class Rect;
-}
-
-// InstantLoader is used to communicate with a preview WebContents that it owns
-// and loads the "Instant URL" into. This preview can appear and disappear at
-// will as the user types in the omnibox (compare: InstantTab, which talks to a
-// committed tab on the tab strip).
-class InstantLoader : public InstantClient::Delegate,
- public content::NotificationObserver {
+// InstantLoader is used to create and maintain a WebContents where we can
+// preload a page into. It is used by InstantOverlay and InstantNTP to
+// preload an Instant page.
+class InstantLoader : public content::NotificationObserver,
+ public content::WebContentsDelegate,
+ public CoreTabHelperDelegate {
public:
- // Returns the Instant loader for |contents| if it's used for Instant.
- static InstantLoader* FromWebContents(const content::WebContents* contents);
-
- // Doesn't take ownership of |controller|.
- InstantLoader(InstantController* controller, const std::string& instant_url);
+ // InstantLoader calls these methods on its delegate in response to certain
+ // changes in the underlying contents.
+ class Delegate {
+ public:
+ // Called after someone has swapped in a different WebContents for ours.
+ virtual void OnSwappedContents() = 0;
+
+ // Called when the underlying contents receive focus.
+ virtual void OnFocus() = 0;
+
+ // Called when the mouse pointer is down.
+ virtual void OnMouseDown() = 0;
+
+ // Called when the mouse pointer is released (or a drag event ends).
+ virtual void OnMouseUp() = 0;
+
+ // Called to open a URL using the underlying contents (see
+ // WebContentsDelegate::OpenURLFromTab). The Delegate should return the
+ // WebContents the URL is opened in, or NULL if the URL wasn't opened
+ // immediately.
+ virtual content::WebContents* OpenURLFromTab(
+ content::WebContents* source,
+ const content::OpenURLParams& params) = 0;
+
+ protected:
+ ~Delegate();
+ };
+
+ explicit InstantLoader(Delegate* delegate);
virtual ~InstantLoader();
- // The preview WebContents. InstantLoader retains ownership. This will be
- // non-NULL after InitFromContents(), and until ReleaseContents() is called.
+ // Creates a new WebContents in the context of |profile| that will be used to
+ // load |instant_url|. The page is not actually loaded until Load() is
+ // called. Uses |active_contents|, if non-NULL, to initialize the size of the
+ // new contents. |on_stale_callback| will be called after kStalePageTimeoutMS
+ // has elapsed after Load() being called.
+ void Init(const GURL& instant_url,
+ Profile* profile,
+ const content::WebContents* active_contents,
+ const base::Closure& on_stale_callback);
+
+ // Loads |instant_url_| in |contents_|.
+ void Load();
+
+ // Returns the contents currently held. May be NULL.
content::WebContents* contents() const { return contents_.get(); }
- // Creates a new WebContents and loads |instant_url_| into it. |active_tab| is
- // the page the preview will be shown on top of and potentially replace.
- void InitContents(const content::WebContents* active_tab);
-
- // Releases the preview WebContents passing ownership to the caller. This
- // should be called when the preview is committed.
- content::WebContents* ReleaseContents() WARN_UNUSED_RESULT;
-
- // Returns the URL that we're loading.
- const std::string& instant_url() const { return instant_url_; }
-
- // Returns true if the preview is known to support the Instant API. This
- // starts out false, and becomes true whenever we get any message from the
- // page. Once true, it never becomes false (the page isn't expected to drop
- // Instant API support suddenly).
- bool supports_instant() const { return supports_instant_; }
-
- // Returns true if the mouse or a touch pointer is down due to activating the
- // preview contents.
- bool is_pointer_down_from_activate() const {
- return is_pointer_down_from_activate_;
- }
-
- // Returns info about the last navigation by the Instant page. If the page
- // hasn't navigated since the last Update(), the URL is empty.
- const history::HistoryAddPageArgs& last_navigation() const {
- return last_navigation_;
- }
-
- // Called by the history tab helper with information that it would have added
- // to the history service had this WebContents not been used for Instant.
- void DidNavigate(const history::HistoryAddPageArgs& add_page_args);
-
- // Returns true if the loader is using
- // InstantController::kLocalOmniboxPopupURL as the |instant_url_|.
- bool IsUsingLocalPreview() const;
-
- // Calls through to methods of the same name on InstantClient.
- void Update(const string16& text,
- size_t selection_start,
- size_t selection_end,
- bool verbatim);
- void Submit(const string16& text);
- void Cancel(const string16& text);
- void SetPopupBounds(const gfx::Rect& bounds);
- void SetMarginSize(int start, int end);
- void InitializeFonts();
- void SendAutocompleteResults(
- const std::vector<InstantAutocompleteResult>& results);
- void UpOrDownKeyPressed(int count);
- void SearchModeChanged(const chrome::search::Mode& mode);
- void SendThemeBackgroundInfo(const ThemeBackgroundInfo& theme_info);
- void SendThemeAreaHeight(int height);
- void SetDisplayInstantResults(bool display_instant_results);
- void KeyCaptureChanged(bool is_key_capture_enabled);
+ // Replaces the contents held with |contents|. Any existing contents is
+ // deleted. The expiration timer is not restarted.
+ void SetContents(scoped_ptr<content::WebContents> contents);
- private:
- class WebContentsDelegateImpl;
-
- // Overridden from InstantClient::Delegate:
- virtual void SetSuggestions(
- const std::vector<InstantSuggestion>& suggestions) OVERRIDE;
- virtual void InstantSupportDetermined(bool supports_instant) OVERRIDE;
- virtual void ShowInstantPreview(InstantShownReason reason,
- int height,
- InstantSizeUnits units) OVERRIDE;
- virtual void StartCapturingKeyStrokes() OVERRIDE;
- virtual void StopCapturingKeyStrokes() OVERRIDE;
- virtual void RenderViewGone() OVERRIDE;
- virtual void AboutToNavigateMainFrame(const GURL& url) OVERRIDE;
- virtual void NavigateToURL(const GURL& url,
- content::PageTransition transition) OVERRIDE;
- virtual void RenderViewCreated() OVERRIDE;
+ // Releases the contents currently held. Must only be called if contents() is
+ // not NULL.
+ scoped_ptr<content::WebContents> ReleaseContents() WARN_UNUSED_RESULT;
+ private:
// Overridden from content::NotificationObserver:
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
- void SetupPreviewContents();
- void CleanupPreviewContents();
- void ReplacePreviewContents(content::WebContents* old_contents,
- content::WebContents* new_contents);
+ // Overridden from CoreTabHelperDelegate:
+ virtual void SwapTabContents(content::WebContents* old_contents,
+ content::WebContents* new_contents) OVERRIDE;
+
+ // Overridden from content::WebContentsDelegate:
+ virtual bool ShouldSuppressDialogs() OVERRIDE;
+ virtual bool ShouldFocusPageAfterCrash() OVERRIDE;
+ virtual void LostCapture() OVERRIDE;
+ virtual void WebContentsFocused(content::WebContents* contents) OVERRIDE;
+ virtual bool CanDownload(content::RenderViewHost* render_view_host,
+ int request_id,
+ const std::string& request_method) OVERRIDE;
+ virtual void HandleMouseDown() OVERRIDE;
+ virtual void HandleMouseUp() OVERRIDE;
+ virtual void HandlePointerActivate() OVERRIDE;
+ virtual void HandleGestureEnd() OVERRIDE;
+ virtual void DragEnded() OVERRIDE;
+ virtual bool OnGoToEntryOffset(int offset) OVERRIDE;
+ virtual content::WebContents* OpenURLFromTab(
+ content::WebContents* source,
+ const content::OpenURLParams& params) OVERRIDE;
+
+ Delegate* const delegate_;
+ scoped_ptr<content::WebContents> contents_;
- InstantClient client_;
- InstantController* const controller_;
+ // The URL we will be loading.
+ GURL instant_url_;
- // Delegate of the preview WebContents. Used when the user does some gesture
- // on the preview and it needs to be activated.
- scoped_ptr<WebContentsDelegateImpl> delegate_;
- scoped_ptr<content::WebContents> contents_;
+ // Called when |stale_page_timer_| fires.
+ base::Closure on_stale_callback_;
- const std::string instant_url_;
- bool supports_instant_;
- bool is_pointer_down_from_activate_;
- history::HistoryAddPageArgs last_navigation_;
+ // Used to mark when the page is stale.
+ base::Timer stale_page_timer_;
- // Used to get notifications about renderers coming and going.
+ // Used to get notifications about renderers.
content::NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(InstantLoader);
diff --git a/chrome/browser/instant/instant_ntp.cc b/chrome/browser/instant/instant_ntp.cc
new file mode 100644
index 0000000..f23a3bf
--- /dev/null
+++ b/chrome/browser/instant/instant_ntp.cc
@@ -0,0 +1,66 @@
+// Copyright 2013 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 "chrome/browser/instant/instant_ntp.h"
+
+#include "chrome/common/url_constants.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/web_contents.h"
+
+InstantNTP::InstantNTP(InstantPage::Delegate* delegate,
+ const std::string& instant_url)
+ : InstantPage(delegate),
+ loader_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+ instant_url_(instant_url) {
+}
+
+InstantNTP::~InstantNTP() {
+}
+
+void InstantNTP::InitContents(Profile* profile,
+ const content::WebContents* active_tab,
+ const base::Closure& on_stale_callback) {
+ loader_.Init(GURL(instant_url_), profile, active_tab, on_stale_callback);
+ SetContents(loader_.contents());
+ loader_.Load();
+ contents()->GetController().GetPendingEntry()->SetVirtualURL(
+ GURL(chrome::kChromeUINewTabURL));
+}
+
+scoped_ptr<content::WebContents> InstantNTP::ReleaseContents() {
+ SetContents(NULL);
+ return loader_.ReleaseContents();
+}
+
+void InstantNTP::OnSwappedContents() {
+ SetContents(loader_.contents());
+ contents()->GetController().GetPendingEntry()->SetVirtualURL(
+ GURL(chrome::kChromeUINewTabURL));
+}
+
+void InstantNTP::OnFocus() {
+ NOTREACHED();
+}
+
+void InstantNTP::OnMouseDown() {
+ NOTREACHED();
+}
+
+void InstantNTP::OnMouseUp() {
+ NOTREACHED();
+}
+
+content::WebContents* InstantNTP::OpenURLFromTab(
+ content::WebContents* source,
+ const content::OpenURLParams& params) {
+ return NULL;
+}
+
+bool InstantNTP::ShouldProcessRenderViewCreated() {
+ return true;
+}
+
+bool InstantNTP::ShouldProcessRenderViewGone() {
+ return true;
+}
diff --git a/chrome/browser/instant/instant_ntp.h b/chrome/browser/instant/instant_ntp.h
new file mode 100644
index 0000000..fb72ec9
--- /dev/null
+++ b/chrome/browser/instant/instant_ntp.h
@@ -0,0 +1,62 @@
+// Copyright 2013 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_INSTANT_INSTANT_NTP_H_
+#define CHROME_BROWSER_INSTANT_INSTANT_NTP_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/instant/instant_loader.h"
+#include "chrome/browser/instant/instant_page.h"
+
+class Profile;
+
+// InstantNTP is used to preload an Instant page that will be swapped in when a
+// user navigates to a New Tab Page (NTP). The InstantNTP contents are never
+// shown in an un-committed state.
+class InstantNTP : public InstantPage,
+ public InstantLoader::Delegate {
+ public:
+ InstantNTP(InstantPage::Delegate* delegate, const std::string& instant_url);
+ virtual ~InstantNTP();
+
+ // Creates a new WebContents and loads |instant_url_| into it. Uses
+ // |active_tab|, if non-NULL, to initialize the size of the WebContents.
+ // |on_stale_callback| will be called when |loader_| determines the page to
+ // be stale.
+ void InitContents(Profile* profile,
+ const content::WebContents* active_tab,
+ const base::Closure& on_stale_callback);
+
+ // Releases the WebContents for the instant page. This should be called when
+ // the page is about to be committed.
+ scoped_ptr<content::WebContents> ReleaseContents() WARN_UNUSED_RESULT;
+
+ // Returns the URL that we're loading.
+ const std::string& instant_url() const { return instant_url_; }
+
+ private:
+ // Overriden from InstantLoader::Delegate:
+ virtual void OnSwappedContents() OVERRIDE;
+ virtual void OnFocus() OVERRIDE;
+ virtual void OnMouseDown() OVERRIDE;
+ virtual void OnMouseUp() OVERRIDE;
+ virtual content::WebContents* OpenURLFromTab(
+ content::WebContents* source,
+ const content::OpenURLParams& params) OVERRIDE;
+
+ // Overridden from InstantPage:
+ virtual bool ShouldProcessRenderViewCreated() OVERRIDE;
+ virtual bool ShouldProcessRenderViewGone() OVERRIDE;
+
+ InstantLoader loader_;
+ const std::string instant_url_;
+
+ DISALLOW_COPY_AND_ASSIGN(InstantNTP);
+};
+
+#endif // CHROME_BROWSER_INSTANT_INSTANT_NTP_H_
diff --git a/chrome/browser/instant/instant_overlay.cc b/chrome/browser/instant/instant_overlay.cc
new file mode 100644
index 0000000..ebe1a4a
--- /dev/null
+++ b/chrome/browser/instant/instant_overlay.cc
@@ -0,0 +1,154 @@
+// Copyright 2013 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 "chrome/browser/instant/instant_overlay.h"
+
+#include "base/auto_reset.h"
+#include "base/supports_user_data.h"
+#include "content/public/browser/web_contents.h"
+
+namespace {
+
+int kUserDataKey;
+
+class InstantOverlayUserData : public base::SupportsUserData::Data {
+ public:
+ explicit InstantOverlayUserData(InstantOverlay* overlay)
+ : overlay_(overlay) {}
+
+ virtual InstantOverlay* overlay() const { return overlay_; }
+
+ private:
+ ~InstantOverlayUserData() {}
+
+ InstantOverlay* const overlay_;
+
+ DISALLOW_COPY_AND_ASSIGN(InstantOverlayUserData);
+};
+
+} // namespace
+
+// static
+InstantOverlay* InstantOverlay::FromWebContents(
+ const content::WebContents* web_contents) {
+ InstantOverlayUserData* data = static_cast<InstantOverlayUserData*>(
+ web_contents->GetUserData(&kUserDataKey));
+ return data ? data->overlay() : NULL;
+}
+
+InstantOverlay::InstantOverlay(InstantController* controller,
+ const std::string& instant_url)
+ : InstantPage(controller),
+ loader_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+ instant_url_(instant_url),
+ is_stale_(false),
+ is_pointer_down_from_activate_(false) {
+}
+
+InstantOverlay::~InstantOverlay() {
+}
+
+void InstantOverlay::InitContents(Profile* profile,
+ const content::WebContents* active_tab) {
+ loader_.Init(GURL(instant_url_), profile, active_tab,
+ base::Bind(&InstantOverlay::HandleStalePage,
+ base::Unretained(this)));
+ SetContents(loader_.contents());
+ contents()->SetUserData(&kUserDataKey, new InstantOverlayUserData(this));
+ loader_.Load();
+}
+
+scoped_ptr<content::WebContents> InstantOverlay::ReleaseContents() {
+ contents()->RemoveUserData(&kUserDataKey);
+ SetContents(NULL);
+ return loader_.ReleaseContents();
+}
+
+void InstantOverlay::DidNavigate(
+ const history::HistoryAddPageArgs& add_page_args) {
+ last_navigation_ = add_page_args;
+}
+
+bool InstantOverlay::IsUsingLocalPreview() const {
+ return instant_url_ == InstantController::kLocalOmniboxPopupURL;
+}
+
+void InstantOverlay::Update(const string16& text,
+ size_t selection_start,
+ size_t selection_end,
+ bool verbatim) {
+ last_navigation_ = history::HistoryAddPageArgs();
+ InstantPage::Update(text, selection_start, selection_end, verbatim);
+}
+
+bool InstantOverlay::ShouldProcessRenderViewCreated() {
+ return true;
+}
+
+bool InstantOverlay::ShouldProcessRenderViewGone() {
+ return true;
+}
+
+bool InstantOverlay::ShouldProcessAboutToNavigateMainFrame() {
+ return true;
+}
+
+bool InstantOverlay::ShouldProcessSetSuggestions() {
+ return true;
+}
+
+bool InstantOverlay::ShouldProcessShowInstantPreview() {
+ return true;
+}
+
+bool InstantOverlay::ShouldProcessNavigateToURL() {
+ return true;
+}
+
+void InstantOverlay::OnSwappedContents() {
+ contents()->RemoveUserData(&kUserDataKey);
+ SetContents(loader_.contents());
+ contents()->SetUserData(&kUserDataKey, new InstantOverlayUserData(this));
+ instant_controller()->SwappedOverlayContents();
+}
+
+void InstantOverlay::OnFocus() {
+ // The preview is getting focus. Equivalent to it being clicked.
+ base::AutoReset<bool> reset(&is_pointer_down_from_activate_, true);
+ instant_controller()->FocusedOverlayContents();
+}
+
+void InstantOverlay::OnMouseDown() {
+ is_pointer_down_from_activate_ = true;
+}
+
+void InstantOverlay::OnMouseUp() {
+ if (is_pointer_down_from_activate_) {
+ is_pointer_down_from_activate_ = false;
+ instant_controller()->CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST);
+ }
+}
+
+content::WebContents* InstantOverlay::OpenURLFromTab(
+ content::WebContents* source,
+ const content::OpenURLParams& params) {
+ // We will allow the navigate to continue if we are able to commit the
+ // overlay.
+ //
+ // First, cache the overlay contents since committing it will cause the
+ // contents to be released (and be set to NULL).
+ content::WebContents* overlay = contents();
+ if (instant_controller()->CommitIfPossible(INSTANT_COMMIT_NAVIGATED)) {
+ // If the commit was successful, the overlay's delegate should be the tab
+ // strip, which will be able to handle the navigation.
+ DCHECK_NE(&loader_, overlay->GetDelegate());
+ return overlay->GetDelegate()->OpenURLFromTab(source, params);
+ }
+ return NULL;
+}
+
+void InstantOverlay::HandleStalePage() {
+ is_stale_ = true;
+ instant_controller()->ReloadOverlayIfStale();
+}
diff --git a/chrome/browser/instant/instant_overlay.h b/chrome/browser/instant/instant_overlay.h
new file mode 100644
index 0000000..99b7c2e
--- /dev/null
+++ b/chrome/browser/instant/instant_overlay.h
@@ -0,0 +1,117 @@
+// Copyright 2013 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_INSTANT_INSTANT_OVERLAY_H_
+#define CHROME_BROWSER_INSTANT_INSTANT_OVERLAY_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/history/history_types.h"
+#include "chrome/browser/instant/instant_controller.h"
+#include "chrome/browser/instant/instant_loader.h"
+#include "chrome/browser/instant/instant_page.h"
+
+class Profile;
+
+namespace content {
+class WebContents;
+}
+
+// InstantOverlay is used to communicate with a preview WebContents that it owns
+// and loads the "Instant URL" into. This preview can appear and disappear at
+// will as the user types in the omnibox.
+class InstantOverlay : public InstantPage,
+ public InstantLoader::Delegate {
+ public:
+ // Returns the InstantOverlay for |contents| if it's used for Instant.
+ static InstantOverlay* FromWebContents(const content::WebContents* contents);
+
+ InstantOverlay(InstantController* controller,
+ const std::string& instant_url);
+ virtual ~InstantOverlay();
+
+ // Creates a new WebContents and loads |instant_url_| into it. Uses
+ // |active_tab|, if non-NULL, to initialize the size of the WebContents.
+ void InitContents(Profile* profile,
+ const content::WebContents* active_tab);
+
+ // Releases the overlay WebContents. This should be called when the overlay
+ // is committed.
+ scoped_ptr<content::WebContents> ReleaseContents() WARN_UNUSED_RESULT;
+
+ // Returns the URL that we're loading.
+ const std::string& instant_url() const { return instant_url_; }
+
+ // Returns whether the underlying contents is stale (i.e. was loaded too long
+ // ago).
+ bool is_stale() const { return is_stale_; }
+
+ // Returns true if the mouse or a touch pointer is down due to activating the
+ // preview contents.
+ bool is_pointer_down_from_activate() const {
+ return is_pointer_down_from_activate_;
+ }
+
+ // Returns info about the last navigation by the Instant page. If the page
+ // hasn't navigated since the last Update(), the URL is empty.
+ const history::HistoryAddPageArgs& last_navigation() const {
+ return last_navigation_;
+ }
+
+ // Called by the history tab helper with information that it would have added
+ // to the history service had this WebContents not been used for Instant.
+ void DidNavigate(const history::HistoryAddPageArgs& add_page_args);
+
+ // Returns true if the overlay is using
+ // InstantController::kLocalOmniboxPopupURL as the |instant_url_|.
+ bool IsUsingLocalPreview() const;
+
+ // Overridden from InstantPage:
+ virtual void Update(const string16& text,
+ size_t selection_start,
+ size_t selection_end,
+ bool verbatim) OVERRIDE;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(InstantTest, InstantOverlayRefresh);
+
+ // Helper to access delegate() as an InstantController object.
+ InstantController* instant_controller() const {
+ return static_cast<InstantController*>(delegate());
+ }
+
+ // Overridden from InstantPage:
+ virtual bool ShouldProcessRenderViewCreated() OVERRIDE;
+ virtual bool ShouldProcessRenderViewGone() OVERRIDE;
+ virtual bool ShouldProcessAboutToNavigateMainFrame() OVERRIDE;
+ virtual bool ShouldProcessSetSuggestions() OVERRIDE;
+ virtual bool ShouldProcessShowInstantPreview() OVERRIDE;
+ virtual bool ShouldProcessNavigateToURL() OVERRIDE;
+
+ // Overriden from InstantLoader::Delegate:
+ virtual void OnSwappedContents() OVERRIDE;
+ virtual void OnFocus() OVERRIDE;
+ virtual void OnMouseDown() OVERRIDE;
+ virtual void OnMouseUp() OVERRIDE;
+ virtual content::WebContents* OpenURLFromTab(
+ content::WebContents* source,
+ const content::OpenURLParams& params) OVERRIDE;
+
+ // Called when the underlying page becomes stale.
+ void HandleStalePage();
+
+ InstantLoader loader_;
+ const std::string instant_url_;
+ bool is_stale_;
+ bool is_pointer_down_from_activate_;
+ history::HistoryAddPageArgs last_navigation_;
+
+ DISALLOW_COPY_AND_ASSIGN(InstantOverlay);
+};
+
+#endif // CHROME_BROWSER_INSTANT_INSTANT_OVERLAY_H_
diff --git a/chrome/browser/instant/instant_page.cc b/chrome/browser/instant/instant_page.cc
new file mode 100644
index 0000000..8343975
--- /dev/null
+++ b/chrome/browser/instant/instant_page.cc
@@ -0,0 +1,238 @@
+// Copyright 2013 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 "chrome/browser/instant/instant_page.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/common/render_messages.h"
+#include "content/public/browser/web_contents.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/font.h"
+
+InstantPage::Delegate::~Delegate() {
+}
+
+InstantPage::~InstantPage() {
+}
+
+void InstantPage::Update(const string16& text,
+ size_t selection_start,
+ size_t selection_end,
+ bool verbatim) {
+ Send(new ChromeViewMsg_SearchBoxChange(routing_id(), text, verbatim,
+ selection_start, selection_end));
+}
+
+void InstantPage::Submit(const string16& text) {
+ Send(new ChromeViewMsg_SearchBoxSubmit(routing_id(), text));
+}
+
+void InstantPage::Cancel(const string16& text) {
+ Send(new ChromeViewMsg_SearchBoxCancel(routing_id(), text));
+}
+
+void InstantPage::SetPopupBounds(const gfx::Rect& bounds) {
+ Send(new ChromeViewMsg_SearchBoxPopupResize(routing_id(), bounds));
+}
+
+void InstantPage::SetMarginSize(const int start, const int end) {
+ Send(new ChromeViewMsg_SearchBoxMarginChange(routing_id(), start, end));
+}
+
+void InstantPage::InitializeFonts() {
+ const gfx::Font& omnibox_font =
+ ui::ResourceBundle::GetSharedInstance().GetFont(
+ ui::ResourceBundle::MediumFont);
+ string16 omnibox_font_name = UTF8ToUTF16(omnibox_font.GetFontName());
+ size_t omnibox_font_size = omnibox_font.GetFontSize();
+ Send(new ChromeViewMsg_SearchBoxFontInformation(
+ routing_id(), omnibox_font_name, omnibox_font_size));
+}
+
+void InstantPage::DetermineIfPageSupportsInstant() {
+ Send(new ChromeViewMsg_DetermineIfPageSupportsInstant(routing_id()));
+}
+
+void InstantPage::SendAutocompleteResults(
+ const std::vector<InstantAutocompleteResult>& results) {
+ Send(new ChromeViewMsg_SearchBoxAutocompleteResults(routing_id(), results));
+}
+
+void InstantPage::UpOrDownKeyPressed(int count) {
+ Send(new ChromeViewMsg_SearchBoxUpOrDownKeyPressed(routing_id(), count));
+}
+
+void InstantPage::SearchModeChanged(const chrome::search::Mode& mode) {
+ Send(new ChromeViewMsg_SearchBoxModeChanged(routing_id(), mode));
+}
+
+void InstantPage::SendThemeBackgroundInfo(
+ const ThemeBackgroundInfo& theme_info) {
+ Send(new ChromeViewMsg_SearchBoxThemeChanged(routing_id(), theme_info));
+}
+
+void InstantPage::SendThemeAreaHeight(int height) {
+ Send(new ChromeViewMsg_SearchBoxThemeAreaHeightChanged(routing_id(), height));
+}
+
+void InstantPage::SetDisplayInstantResults(bool display_instant_results) {
+ Send(new ChromeViewMsg_SearchBoxSetDisplayInstantResults(
+ routing_id(), display_instant_results));
+}
+
+void InstantPage::KeyCaptureChanged(bool is_key_capture_enabled) {
+ Send(new ChromeViewMsg_SearchBoxKeyCaptureChanged(
+ routing_id(), is_key_capture_enabled));
+}
+
+InstantPage::InstantPage(Delegate* delegate)
+ : delegate_(delegate),
+ supports_instant_(false) {
+}
+
+void InstantPage::SetContents(content::WebContents* contents) {
+ Observe(contents);
+}
+
+bool InstantPage::ShouldProcessRenderViewCreated() {
+ return false;
+}
+
+bool InstantPage::ShouldProcessRenderViewGone() {
+ return false;
+}
+
+bool InstantPage::ShouldProcessAboutToNavigateMainFrame() {
+ return false;
+}
+
+bool InstantPage::ShouldProcessSetSuggestions() {
+ return false;
+}
+
+bool InstantPage::ShouldProcessShowInstantPreview() {
+ return false;
+}
+
+bool InstantPage::ShouldProcessStartCapturingKeyStrokes() {
+ return false;
+}
+
+bool InstantPage::ShouldProcessStopCapturingKeyStrokes() {
+ return false;
+}
+
+bool InstantPage::ShouldProcessNavigateToURL() {
+ return false;
+}
+
+void InstantPage::RenderViewCreated(content::RenderViewHost* render_view_host) {
+ if (ShouldProcessRenderViewCreated())
+ delegate_->InstantPageRenderViewCreated(contents());
+}
+
+void InstantPage::DidFinishLoad(
+ int64 /* frame_id */,
+ const GURL& /* validated_url */,
+ bool is_main_frame,
+ content::RenderViewHost* /* render_view_host */) {
+ if (is_main_frame && !supports_instant_)
+ DetermineIfPageSupportsInstant();
+}
+
+bool InstantPage::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(InstantPage, message)
+ IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SetSuggestions, OnSetSuggestions)
+ IPC_MESSAGE_HANDLER(ChromeViewHostMsg_InstantSupportDetermined,
+ OnInstantSupportDetermined)
+ IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ShowInstantPreview,
+ OnShowInstantPreview)
+ IPC_MESSAGE_HANDLER(ChromeViewHostMsg_StartCapturingKeyStrokes,
+ OnStartCapturingKeyStrokes);
+ IPC_MESSAGE_HANDLER(ChromeViewHostMsg_StopCapturingKeyStrokes,
+ OnStopCapturingKeyStrokes);
+ IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxNavigate,
+ OnSearchBoxNavigate);
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void InstantPage::RenderViewGone(base::TerminationStatus /* status */) {
+ if (ShouldProcessRenderViewGone())
+ delegate_->InstantPageRenderViewGone(contents());
+}
+
+void InstantPage::DidCommitProvisionalLoadForFrame(
+ int64 /* frame_id */,
+ bool is_main_frame,
+ const GURL& url,
+ content::PageTransition /* transition_type */,
+ content::RenderViewHost* /* render_view_host */) {
+ if (is_main_frame && ShouldProcessAboutToNavigateMainFrame())
+ delegate_->InstantPageAboutToNavigateMainFrame(contents(), url);
+}
+
+void InstantPage::OnSetSuggestions(
+ int page_id,
+ const std::vector<InstantSuggestion>& suggestions) {
+ if (contents()->IsActiveEntry(page_id)) {
+ OnInstantSupportDetermined(page_id, true);
+ if (ShouldProcessSetSuggestions())
+ delegate_->SetSuggestions(contents(), suggestions);
+ }
+}
+
+void InstantPage::OnInstantSupportDetermined(int page_id,
+ bool supports_instant) {
+ if (!contents()->IsActiveEntry(page_id) || supports_instant_) {
+ // Nothing to do if the page already supports Instant.
+ return;
+ }
+
+ supports_instant_ = supports_instant;
+ delegate_->InstantSupportDetermined(contents(), supports_instant);
+
+ // If the page doesn't support Instant, stop listening to it.
+ if (!supports_instant)
+ Observe(NULL);
+}
+
+void InstantPage::OnShowInstantPreview(int page_id,
+ InstantShownReason reason,
+ int height,
+ InstantSizeUnits units) {
+ if (contents()->IsActiveEntry(page_id)) {
+ OnInstantSupportDetermined(page_id, true);
+ if (ShouldProcessShowInstantPreview())
+ delegate_->ShowInstantPreview(contents(), reason, height, units);
+ }
+}
+
+void InstantPage::OnStartCapturingKeyStrokes(int page_id) {
+ if (contents()->IsActiveEntry(page_id)) {
+ OnInstantSupportDetermined(page_id, true);
+ if (ShouldProcessStartCapturingKeyStrokes())
+ delegate_->StartCapturingKeyStrokes(contents());
+ }
+}
+
+void InstantPage::OnStopCapturingKeyStrokes(int page_id) {
+ if (contents()->IsActiveEntry(page_id)) {
+ OnInstantSupportDetermined(page_id, true);
+ if (ShouldProcessStopCapturingKeyStrokes())
+ delegate_->StopCapturingKeyStrokes(contents());
+ }
+}
+
+void InstantPage::OnSearchBoxNavigate(int page_id,
+ const GURL& url,
+ content::PageTransition transition) {
+ if (contents()->IsActiveEntry(page_id)) {
+ OnInstantSupportDetermined(page_id, true);
+ if (ShouldProcessNavigateToURL())
+ delegate_->NavigateToURL(contents(), url, transition);
+ }
+}
diff --git a/chrome/browser/instant/instant_page.h b/chrome/browser/instant/instant_page.h
new file mode 100644
index 0000000..1051b22
--- /dev/null
+++ b/chrome/browser/instant/instant_page.h
@@ -0,0 +1,223 @@
+// Copyright 2013 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_INSTANT_INSTANT_PAGE_H_
+#define CHROME_BROWSER_INSTANT_INSTANT_PAGE_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/string16.h"
+#include "chrome/common/instant_types.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/page_transition_types.h"
+
+class GURL;
+
+namespace chrome {
+namespace search {
+struct Mode;
+}
+}
+
+namespace content {
+class WebContents;
+}
+
+namespace gfx {
+class Rect;
+}
+
+// InstantPage is used to exchange messages with a page that implements the
+// Instant/Embedded Search API (http://dev.chromium.org/embeddedsearch).
+// InstantPage is not used directly but via one of its derived classes:
+// InstantOverlay, InstantNTP and InstantTab.
+class InstantPage : public content::WebContentsObserver {
+ public:
+ // InstantPage calls its delegate in response to messages received from the
+ // page. Each method is called with the |contents| corresponding to the page
+ // we are observing.
+ class Delegate {
+ public:
+ // Called when a RenderView is created, so that state can be initialized.
+ virtual void InstantPageRenderViewCreated(
+ const content::WebContents* contents) = 0;
+
+ // Called upon determination of Instant API support. Either in response to
+ // the page loading or because we received some other message.
+ virtual void InstantSupportDetermined(const content::WebContents* contents,
+ bool supports_instant) = 0;
+
+ // Called when the underlying RenderView crashed.
+ virtual void InstantPageRenderViewGone(
+ const content::WebContents* contents) = 0;
+
+ // Called when the page is about to navigate to |url|.
+ virtual void InstantPageAboutToNavigateMainFrame(
+ const content::WebContents* contents,
+ const GURL& url) = 0;
+
+ // Called when the page has suggestions. Usually in response to Update(),
+ // SendAutocompleteResults() or UpOrDownKeyPressed().
+ virtual void SetSuggestions(
+ const content::WebContents* contents,
+ const std::vector<InstantSuggestion>& suggestions) = 0;
+
+ // Called when the page wants to be shown. Usually in response to Update(),
+ // SendAutocompleteResults() or SearchModeChanged().
+ virtual void ShowInstantPreview(const content::WebContents* contents,
+ InstantShownReason reason,
+ int height,
+ InstantSizeUnits units) = 0;
+
+ // Called when the page wants the omnibox to start capturing user key
+ // strokes. If this call is processed successfully, the omnibox will not
+ // look focused visibly but any user key strokes will go to the omnibox.
+ // Currently, this is implemented by focusing the omnibox invisibly.
+ virtual void StartCapturingKeyStrokes(
+ const content::WebContents* contents) = 0;
+
+ // Called when the page wants the omnibox to stop capturing user key
+ // strokes.
+ virtual void StopCapturingKeyStrokes(content::WebContents* contents) = 0;
+
+ // Called when the page wants to navigate to the specified URL. Usually
+ // used by the page to navigate to privileged destinations (e.g. chrome://
+ // URLs) or to navigate to URLs that are hidden from the page using
+ // Restricted IDs (rid in the API).
+ virtual void NavigateToURL(const content::WebContents* contents,
+ const GURL& url,
+ content::PageTransition transition) = 0;
+
+ protected:
+ virtual ~Delegate();
+ };
+
+ virtual ~InstantPage();
+
+ // The WebContents corresponding to the page we're talking to. May be NULL.
+ content::WebContents* contents() const { return web_contents(); }
+
+ // Returns true if the page is known to support the Instant API. This starts
+ // out false, and is set to true whenever we get any message from the page.
+ // Once true, it never becomes false (the page isn't expected to drop API
+ // support suddenly).
+ bool supports_instant() const { return supports_instant_; }
+
+ // Tells the page that the user typed |text| into the omnibox. If |verbatim|
+ // is false, the page predicts the query the user means to type and fetches
+ // results for the prediction. If |verbatim| is true, |text| is taken as the
+ // exact query (no prediction is made).
+ virtual void Update(const string16& text,
+ size_t selection_start,
+ size_t selection_end,
+ bool verbatim);
+
+ // Tells the page that the user pressed Enter in the omnibox.
+ void Submit(const string16& text);
+
+ // Tells the page that the user clicked on it. Nothing is being cancelled; the
+ // poor choice of name merely reflects the IPC of the same (poor) name.
+ void Cancel(const string16& text);
+
+ // Tells the page the bounds of the omnibox dropdown (in screen coordinates).
+ // This is used by the page to offset the results to avoid them being covered
+ // by the omnibox dropdown.
+ void SetPopupBounds(const gfx::Rect& bounds);
+
+ // Tells the page the start and end margins of the omnibox (in screen
+ // coordinates). This is used by the page to align text or assets properly
+ // with the omnibox.
+ void SetMarginSize(int start, int end);
+
+ // Tells the page about the font information.
+ void InitializeFonts();
+
+ // Tells the renderer to determine if the page supports the Instant API, which
+ // results in a call to InstantSupportDetermined() when the reply is received.
+ void DetermineIfPageSupportsInstant();
+
+ // Tells the page about the available autocomplete results.
+ void SendAutocompleteResults(
+ const std::vector<InstantAutocompleteResult>& results);
+
+ // Tells the page that the user pressed Up or Down in the omnibox. |count| is
+ // a repeat count, negative for moving up, positive for moving down.
+ void UpOrDownKeyPressed(int count);
+
+ // Tells the page that the active tab's search mode has changed.
+ void SearchModeChanged(const chrome::search::Mode& mode);
+
+ // Tells the page about the current theme background.
+ void SendThemeBackgroundInfo(const ThemeBackgroundInfo& theme_info);
+
+ // Tells the page about the current theme area height.
+ void SendThemeAreaHeight(int height);
+
+ // Tells the page whether it is allowed to display Instant results.
+ void SetDisplayInstantResults(bool display_instant_results);
+
+ // Tells the page whether the browser is capturing user key strokes.
+ void KeyCaptureChanged(bool is_key_capture_enabled);
+
+ protected:
+ explicit InstantPage(Delegate* delegate);
+
+ // Sets |contents| as the page to communicate with. |contents| may be NULL,
+ // which effectively stops all communication.
+ void SetContents(content::WebContents* contents);
+
+ Delegate* delegate() const { return delegate_; }
+
+ // These functions are called before processing messages received from the
+ // page. By default, all messages are handled, but any derived classes may
+ // choose to ingore some or all of the received messages by overriding these
+ // methods.
+ virtual bool ShouldProcessRenderViewCreated();
+ virtual bool ShouldProcessRenderViewGone();
+ virtual bool ShouldProcessAboutToNavigateMainFrame();
+ virtual bool ShouldProcessSetSuggestions();
+ virtual bool ShouldProcessShowInstantPreview();
+ virtual bool ShouldProcessStartCapturingKeyStrokes();
+ virtual bool ShouldProcessStopCapturingKeyStrokes();
+ virtual bool ShouldProcessNavigateToURL();
+
+ private:
+ // Overridden from content::WebContentsObserver:
+ virtual void RenderViewCreated(
+ content::RenderViewHost* render_view_host) OVERRIDE;
+ virtual void DidFinishLoad(
+ int64 frame_id,
+ const GURL& validated_url,
+ bool is_main_frame,
+ content::RenderViewHost* render_view_host) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE;
+ virtual void DidCommitProvisionalLoadForFrame(
+ int64 frame_id,
+ bool is_main_frame,
+ const GURL& url,
+ content::PageTransition transition_type,
+ content::RenderViewHost* render_view_host) OVERRIDE;
+
+ void OnSetSuggestions(int page_id,
+ const std::vector<InstantSuggestion>& suggestions);
+ void OnInstantSupportDetermined(int page_id, bool supports_instant);
+ void OnShowInstantPreview(int page_id,
+ InstantShownReason reason,
+ int height,
+ InstantSizeUnits units);
+ void OnStartCapturingKeyStrokes(int page_id);
+ void OnStopCapturingKeyStrokes(int page_id);
+ void OnSearchBoxNavigate(int page_id, const GURL& url,
+ content::PageTransition transition);
+
+ Delegate* const delegate_;
+ bool supports_instant_;
+
+ DISALLOW_COPY_AND_ASSIGN(InstantPage);
+};
+
+#endif // CHROME_BROWSER_INSTANT_INSTANT_PAGE_H_
diff --git a/chrome/browser/instant/instant_tab.cc b/chrome/browser/instant/instant_tab.cc
index 733c6f0..0a4b51a 100644
--- a/chrome/browser/instant/instant_tab.cc
+++ b/chrome/browser/instant/instant_tab.cc
@@ -4,102 +4,30 @@
#include "chrome/browser/instant/instant_tab.h"
-#include "chrome/browser/instant/instant_controller.h"
-
-InstantTab::InstantTab(InstantController* controller,
- content::WebContents* contents)
- : client_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
- controller_(controller),
- contents_(contents),
- supports_instant_(false) {
+InstantTab::InstantTab(InstantPage::Delegate* delegate)
+ : InstantPage(delegate) {
}
InstantTab::~InstantTab() {
}
-void InstantTab::Init() {
- client_.SetContents(contents_);
- client_.DetermineIfPageSupportsInstant();
-}
-
-void InstantTab::Update(const string16& text,
- size_t selection_start,
- size_t selection_end,
- bool verbatim) {
- client_.Update(text, selection_start, selection_end, verbatim);
-}
-
-void InstantTab::Submit(const string16& text) {
- client_.Submit(text);
-}
-
-void InstantTab::SendAutocompleteResults(
- const std::vector<InstantAutocompleteResult>& results) {
- client_.SendAutocompleteResults(results);
-}
-
-void InstantTab::SetDisplayInstantResults(bool display_instant_results) {
- client_.SetDisplayInstantResults(display_instant_results);
-}
-
-void InstantTab::UpOrDownKeyPressed(int count) {
- client_.UpOrDownKeyPressed(count);
-}
-
-void InstantTab::SetMarginSize(int start, int end) {
- client_.SetMarginSize(start, end);
-}
-
-void InstantTab::InitializeFonts() {
- client_.InitializeFonts();
-}
-
-void InstantTab::SetSuggestions(
- const std::vector<InstantSuggestion>& suggestions) {
- InstantSupportDetermined(true);
- controller_->SetSuggestions(contents_, suggestions);
-}
-
-void InstantTab::InstantSupportDetermined(bool supports_instant) {
- // If we had already determined that the page supports Instant, nothing to do.
- if (supports_instant_)
- return;
-
- supports_instant_ = supports_instant;
-
- // If the page doesn't support Instant, stop communicating with it.
- if (!supports_instant)
- client_.SetContents(NULL);
-
- controller_->InstantSupportDetermined(contents_, supports_instant);
-}
-
-void InstantTab::ShowInstantPreview(InstantShownReason /* reason */,
- int /* height */,
- InstantSizeUnits /* units */) {
- // The page is a committed tab (i.e., always showing), so nothing to do.
-}
-
-void InstantTab::StartCapturingKeyStrokes() {
- // We don't honor this call from committed tabs.
-}
-
-void InstantTab::StopCapturingKeyStrokes() {
- // We don't honor this call from committed tabs.
+void InstantTab::Init(content::WebContents* contents) {
+ SetContents(contents);
+ DetermineIfPageSupportsInstant();
}
-void InstantTab::RenderViewGone() {
- // For a commit page, a crash should not be handled differently.
+bool InstantTab::ShouldProcessSetSuggestions() {
+ return true;
}
-void InstantTab::AboutToNavigateMainFrame(const GURL& url) {
- // The client is a committed tab, navigations will happen as expected.
+bool InstantTab::ShouldProcessStartCapturingKeyStrokes() {
+ return true;
}
-void InstantTab::NavigateToURL(const GURL& url,
- content::PageTransition transition) {
- controller_->NavigateToURL(url, transition);
+bool InstantTab::ShouldProcessStopCapturingKeyStrokes() {
+ return true;
}
-void InstantTab::RenderViewCreated() {
+bool InstantTab::ShouldProcessNavigateToURL() {
+ return true;
}
diff --git a/chrome/browser/instant/instant_tab.h b/chrome/browser/instant/instant_tab.h
index 8546c08..bbc675d 100644
--- a/chrome/browser/instant/instant_tab.h
+++ b/chrome/browser/instant/instant_tab.h
@@ -5,68 +5,27 @@
#ifndef CHROME_BROWSER_INSTANT_INSTANT_TAB_H_
#define CHROME_BROWSER_INSTANT_INSTANT_TAB_H_
-#include <vector>
-
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "base/string16.h"
-#include "chrome/browser/instant/instant_client.h"
-
-struct InstantAutocompleteResult;
-class InstantController;
-
-namespace content {
-class WebContents;
-}
+#include "chrome/browser/instant/instant_page.h"
-// InstantTab is used to communicate with a committed search results page, i.e.,
-// an actual tab on the tab strip (compare: InstantLoader, which has a preview
-// page that appears and disappears as the user types in the omnibox).
-class InstantTab : public InstantClient::Delegate {
+// InstantTab represents a committed page (i.e. an actual tab on the tab strip)
+// that supports the Instant API.
+class InstantTab : public InstantPage {
public:
- // Doesn't take ownership of either |controller| or |contents|.
- InstantTab(InstantController* controller, content::WebContents* contents);
+ explicit InstantTab(InstantPage::Delegate* delegate);
virtual ~InstantTab();
- content::WebContents* contents() const { return contents_; }
-
- // Start observing |contents_| for messages. Sends a message to determine if
+ // Start observing |contents| for messages. Sends a message to determine if
// the page supports the Instant API.
- void Init();
-
- // Calls through to methods of the same name on InstantClient.
- void Update(const string16& text,
- size_t selection_start,
- size_t selection_end,
- bool verbatim);
- void Submit(const string16& text);
- void SendAutocompleteResults(
- const std::vector<InstantAutocompleteResult>& results);
- void SetDisplayInstantResults(bool display_instant_results);
- void UpOrDownKeyPressed(int count);
- void SetMarginSize(int start, int end);
- void InitializeFonts();
+ void Init(content::WebContents* contents);
private:
- // Overridden from InstantClient::Delegate:
- virtual void SetSuggestions(
- const std::vector<InstantSuggestion>& suggestions) OVERRIDE;
- virtual void InstantSupportDetermined(bool supports_instant) OVERRIDE;
- virtual void ShowInstantPreview(InstantShownReason reason,
- int height,
- InstantSizeUnits units) OVERRIDE;
- virtual void StartCapturingKeyStrokes() OVERRIDE;
- virtual void StopCapturingKeyStrokes() OVERRIDE;
- virtual void RenderViewGone() OVERRIDE;
- virtual void AboutToNavigateMainFrame(const GURL& url) OVERRIDE;
- virtual void NavigateToURL(const GURL& url,
- content::PageTransition transition) OVERRIDE;
- virtual void RenderViewCreated() OVERRIDE;
-
- InstantClient client_;
- InstantController* const controller_;
- content::WebContents* const contents_;
- bool supports_instant_;
+ // Overridden from InstantPage:
+ virtual bool ShouldProcessSetSuggestions() OVERRIDE;
+ virtual bool ShouldProcessStartCapturingKeyStrokes() OVERRIDE;
+ virtual bool ShouldProcessStopCapturingKeyStrokes() OVERRIDE;
+ virtual bool ShouldProcessNavigateToURL() OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(InstantTab);
};
diff --git a/chrome/browser/instant/instant_test_utils.cc b/chrome/browser/instant/instant_test_utils.cc
index 65451db..efd35a3 100644
--- a/chrome/browser/instant/instant_test_utils.cc
+++ b/chrome/browser/instant/instant_test_utils.cc
@@ -9,12 +9,10 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
-#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/result_codes.h"
@@ -99,14 +97,6 @@ void InstantTestBase::FocusOmnibox() {
}
}
-void InstantTestBase::FocusOmniboxAndWaitForInstantSupport() {
- content::WindowedNotificationObserver observer(
- chrome::NOTIFICATION_INSTANT_SUPPORT_DETERMINED,
- content::NotificationService::AllSources());
- FocusOmnibox();
- observer.Wait();
-}
-
void InstantTestBase::SetOmniboxText(const std::string& text) {
FocusOmnibox();
omnibox()->SetUserText(UTF8ToUTF16(text));
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index e81eebc..d969bfa 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -1389,6 +1389,10 @@ void Browser::BeforeUnloadFired(WebContents* web_contents,
unload_controller_->BeforeUnloadFired(web_contents, proceed);
}
+bool Browser::ShouldFocusLocationBarByDefault(WebContents* source) {
+ return source->GetURL() == GURL(chrome::kChromeUINewTabURL);
+}
+
void Browser::SetFocusToLocationBar(bool select_all) {
// Two differences between this and FocusLocationBar():
// (1) This doesn't get recorded in user metrics, since it's called
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 8d0ce58..e029a39 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -556,6 +556,8 @@ class Browser : public TabStripModelObserver,
virtual void BeforeUnloadFired(content::WebContents* source,
bool proceed,
bool* proceed_to_fire_unload) OVERRIDE;
+ virtual bool ShouldFocusLocationBarByDefault(
+ content::WebContents* source) OVERRIDE;
virtual void SetFocusToLocationBar(bool select_all) OVERRIDE;
virtual void RenderWidgetShowing() OVERRIDE;
virtual int GetExtraRenderViewHeight() const OVERRIDE;
diff --git a/chrome/browser/ui/browser_instant_controller.cc b/chrome/browser/ui/browser_instant_controller.cc
index 49d93da..ae5c0b0 100644
--- a/chrome/browser/ui/browser_instant_controller.cc
+++ b/chrome/browser/ui/browser_instant_controller.cc
@@ -19,6 +19,7 @@
#include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
#include "content/public/browser/notification_service.h"
#include "grit/theme_resources.h"
#include "ui/gfx/color_utils.h"
@@ -39,13 +40,13 @@ namespace chrome {
BrowserInstantController::BrowserInstantController(Browser* browser)
: browser_(browser),
instant_(ALLOW_THIS_IN_INITIALIZER_LIST(this),
- chrome::search::IsInstantExtendedAPIEnabled(browser->profile())),
+ chrome::search::IsInstantExtendedAPIEnabled(profile())),
instant_unload_handler_(browser),
initialized_theme_info_(false),
theme_area_height_(0) {
- profile_pref_registrar_.Init(browser_->profile()->GetPrefs());
+ profile_pref_registrar_.Init(profile()->GetPrefs());
profile_pref_registrar_.Add(
- GetInstantPrefName(browser_->profile()),
+ GetInstantPrefName(profile()),
base::Bind(&BrowserInstantController::ResetInstant,
base::Unretained(this)));
profile_pref_registrar_.Add(
@@ -59,7 +60,7 @@ BrowserInstantController::BrowserInstantController(Browser* browser)
// Listen for theme installation.
registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
content::Source<ThemeService>(
- ThemeServiceFactory::GetForProfile(browser_->profile())));
+ ThemeServiceFactory::GetForProfile(profile())));
#endif // defined(ENABLE_THEMES)
}
@@ -98,6 +99,33 @@ void BrowserInstantController::RegisterUserPrefs(PrefServiceSyncable* prefs) {
PrefServiceSyncable::SYNCABLE_PREF);
}
+bool BrowserInstantController::MaybeSwapInInstantNTPContents(
+ const GURL& url,
+ content::WebContents* source_contents,
+ content::WebContents** target_contents) {
+ if (url != GURL(chrome::kChromeUINewTabURL))
+ return false;
+
+ scoped_ptr<content::WebContents> instant_ntp = instant_.ReleaseNTPContents();
+ if (!instant_ntp)
+ return false;
+
+ *target_contents = instant_ntp.get();
+ instant_ntp->GetController().PruneAllButActive();
+ if (source_contents) {
+ instant_ntp->GetController().CopyStateFromAndPrune(
+ &source_contents->GetController());
+ ReplaceWebContentsAt(
+ browser_->tab_strip_model()->GetIndexOfWebContents(source_contents),
+ instant_ntp.Pass());
+ } else {
+ // If |source_contents| is NULL, then the caller is responsible for
+ // inserting instant_ntp into the tabstrip and will take ownership.
+ ignore_result(instant_ntp.release());
+ }
+ return true;
+}
+
bool BrowserInstantController::OpenInstant(WindowOpenDisposition disposition) {
// Unsupported dispositions.
if (disposition == NEW_BACKGROUND_TAB || disposition == NEW_WINDOW)
@@ -113,31 +141,43 @@ bool BrowserInstantController::OpenInstant(WindowOpenDisposition disposition) {
INSTANT_COMMIT_PRESSED_ENTER : INSTANT_COMMIT_PRESSED_ALT_ENTER);
}
-void BrowserInstantController::CommitInstant(content::WebContents* preview,
- bool in_new_tab) {
+Profile* BrowserInstantController::profile() const {
+ return browser_->profile();
+}
+
+void BrowserInstantController::CommitInstant(
+ scoped_ptr<content::WebContents> preview,
+ bool in_new_tab) {
+ if (profile()->GetExtensionService()->IsInstalledApp(preview->GetURL())) {
+ AppLauncherHandler::RecordAppLaunchType(
+ extension_misc::APP_LAUNCH_OMNIBOX_INSTANT);
+ }
if (in_new_tab) {
// TabStripModel takes ownership of |preview|.
- browser_->tab_strip_model()->AddWebContents(preview, -1,
+ browser_->tab_strip_model()->AddWebContents(preview.release(), -1,
instant_.last_transition_type(), TabStripModel::ADD_ACTIVE);
} else {
- int index = browser_->tab_strip_model()->active_index();
- DCHECK_NE(TabStripModel::kNoTab, index);
- content::WebContents* active_tab =
- browser_->tab_strip_model()->GetWebContentsAt(index);
- // TabStripModel takes ownership of |preview|.
- browser_->tab_strip_model()->ReplaceWebContentsAt(index, preview);
- // InstantUnloadHandler takes ownership of |active_tab|.
- instant_unload_handler_.RunUnloadListenersOrDestroy(active_tab, index);
-
- GURL url = preview->GetURL();
- DCHECK(browser_->profile()->GetExtensionService());
- if (browser_->profile()->GetExtensionService()->IsInstalledApp(url)) {
- AppLauncherHandler::RecordAppLaunchType(
- extension_misc::APP_LAUNCH_OMNIBOX_INSTANT);
- }
+ ReplaceWebContentsAt(
+ browser_->tab_strip_model()->active_index(),
+ preview.Pass());
}
}
+void BrowserInstantController::ReplaceWebContentsAt(
+ int index,
+ scoped_ptr<content::WebContents> new_contents) {
+ DCHECK_NE(TabStripModel::kNoTab, index);
+ content::WebContents* old_contents =
+ browser_->tab_strip_model()->GetWebContentsAt(index);
+ // TabStripModel takes ownership of |new_contents|.
+ browser_->tab_strip_model()->ReplaceWebContentsAt(
+ index, new_contents.release());
+ // TODO(samarth): use scoped_ptr instead of comments to document ownership
+ // transfer.
+ // InstantUnloadHandler takes ownership of |old_contents|.
+ instant_unload_handler_.RunUnloadListenersOrDestroy(old_contents, index);
+}
+
void BrowserInstantController::SetInstantSuggestion(
const InstantSuggestion& suggestion) {
browser_->window()->GetLocationBar()->SetInstantSuggestion(suggestion);
@@ -180,7 +220,7 @@ void BrowserInstantController::UpdateThemeInfoForPreview() {
// Initialize |theme_info| if necessary.
// |OnThemeChanged| also updates theme area height if necessary.
if (!initialized_theme_info_)
- OnThemeChanged(ThemeServiceFactory::GetForProfile(browser_->profile()));
+ OnThemeChanged(ThemeServiceFactory::GetForProfile(profile()));
else
OnThemeChanged(NULL);
}
@@ -200,12 +240,10 @@ void BrowserInstantController::SetMarginSize(int start, int end) {
}
void BrowserInstantController::ResetInstant() {
- Profile* profile = browser_->profile();
-
- bool instant_enabled = IsInstantEnabled(profile);
- bool use_local_preview_only = profile->IsOffTheRecord() ||
+ bool instant_enabled = IsInstantEnabled(profile());
+ bool use_local_preview_only = profile()->IsOffTheRecord() ||
(!instant_enabled &&
- !profile->GetPrefs()->GetBoolean(prefs::kSearchSuggestEnabled));
+ !profile()->GetPrefs()->GetBoolean(prefs::kSearchSuggestEnabled));
instant_.SetInstantEnabled(instant_enabled, use_local_preview_only);
}
diff --git a/chrome/browser/ui/browser_instant_controller.h b/chrome/browser/ui/browser_instant_controller.h
index f154992..1063988 100644
--- a/chrome/browser/ui/browser_instant_controller.h
+++ b/chrome/browser/ui/browser_instant_controller.h
@@ -43,23 +43,38 @@ class BrowserInstantController : public content::NotificationObserver,
// Registers Instant related preferences.
static void RegisterUserPrefs(PrefServiceSyncable* prefs);
+ // If |url| is the new tab page URL, set |target_contents| to the preloaded
+ // NTP contents from InstantController. If |source_contents| is not NULL, we
+ // replace it with the new |target_contents| in the tabstrip and delete
+ // |source_contents|. Otherwise, the caller owns |target_contents| and is
+ // responsible for inserting it into the tabstrip.
+ //
+ // Returns true if and only if we update |target_contents|.
+ bool MaybeSwapInInstantNTPContents(
+ const GURL& url,
+ content::WebContents* source_contents,
+ content::WebContents** target_contents);
+
// Commits the current Instant, returning true on success. This is intended
// for use from OpenCurrentURL.
bool OpenInstant(WindowOpenDisposition disposition);
+ // Returns the Profile associated with the Browser that owns this object.
+ Profile* profile() const;
+
// Returns the InstantController or NULL if there is no InstantController for
// this BrowserInstantController.
InstantController* instant() { return &instant_; }
// Invoked by |instant_| to commit the |preview| by merging it into the active
- // tab or adding it as a new tab. We take ownership of |preview|.
- void CommitInstant(content::WebContents* preview, bool in_new_tab);
+ // tab or adding it as a new tab.
+ void CommitInstant(scoped_ptr<content::WebContents> preview, bool in_new_tab);
// Invoked by |instant_| to autocomplete the |suggestion| into the omnibox.
void SetInstantSuggestion(const InstantSuggestion& suggestion);
// Invoked by |instant_| to get the bounds that the preview is placed at,
- // in screen coordinated.
+ // in screen coordinates.
gfx::Rect GetInstantBounds();
// Invoked by |instant_| to notify that the preview gained focus, usually due
@@ -113,6 +128,11 @@ class BrowserInstantController : public content::NotificationObserver,
// Helper for handling theme area height change.
void OnThemeAreaHeightChanged(int height);
+ // Replaces the contents at tab |index| with |new_contents| and deletes the
+ // existing contents.
+ void ReplaceWebContentsAt(int index,
+ scoped_ptr<content::WebContents> new_contents);
+
Browser* const browser_;
InstantController instant_;
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc
index a3ad3eb..5b290b0 100644
--- a/chrome/browser/ui/browser_navigator.cc
+++ b/chrome/browser/ui/browser_navigator.cc
@@ -21,6 +21,7 @@
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_instant_controller.h"
#include "chrome/browser/ui/browser_tab_contents.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/host_desktop.h"
@@ -309,6 +310,41 @@ class ScopedTargetContentsOwner {
DISALLOW_COPY_AND_ASSIGN(ScopedTargetContentsOwner);
};
+content::WebContents* CreateTargetContents(const chrome::NavigateParams& params,
+ const GURL& url) {
+ WebContents::CreateParams create_params(
+ params.browser->profile(),
+ tab_util::GetSiteInstanceForNewTab(params.browser->profile(), url));
+ if (params.source_contents) {
+ create_params.initial_size =
+ params.source_contents->GetView()->GetContainerSize();
+ }
+#if defined(USE_AURA)
+ if (params.browser->window() &&
+ params.browser->window()->GetNativeWindow()) {
+ create_params.context =
+ params.browser->window()->GetNativeWindow();
+ }
+#endif
+
+ content::WebContents* target_contents = WebContents::Create(create_params);
+ // New tabs can have WebUI URLs that will make calls back to arbitrary
+ // tab helpers, so the entire set of tab helpers needs to be set up
+ // immediately.
+ BrowserNavigatorWebContentsAdoption::AttachTabHelpers(target_contents);
+ extensions::TabHelper::FromWebContents(target_contents)->
+ SetExtensionAppById(params.extension_app_id);
+ // TODO(sky): Figure out why this is needed. Without it we seem to get
+ // failures in startup tests.
+ // By default, content believes it is not hidden. When adding contents
+ // in the background, tell it that it's hidden.
+ if ((params.tabstrip_add_types & TabStripModel::ADD_ACTIVE) == 0) {
+ // TabStripModel::AddWebContents invokes WasHidden if not foreground.
+ target_contents->WasHidden();
+ }
+ return target_contents;
+}
+
// If a prerendered page exists for |url|, replace the page at |target_contents|
// with it.
bool SwapInPrerender(WebContents* target_contents, const GURL& url) {
@@ -319,6 +355,15 @@ bool SwapInPrerender(WebContents* target_contents, const GURL& url) {
prerender_manager->MaybeUsePrerenderedPage(target_contents, url);
}
+bool SwapInInstantNTP(chrome::NavigateParams* params,
+ const GURL& url,
+ content::WebContents* source_contents) {
+ chrome::BrowserInstantController* instant =
+ params->browser->instant_controller();
+ return instant && instant->MaybeSwapInInstantNTPContents(
+ url, source_contents, &params->target_contents);
+}
+
} // namespace
namespace chrome {
@@ -466,6 +511,9 @@ void Navigate(NavigateParams* params) {
// Check if this is a singleton tab that already exists
int singleton_index = chrome::GetIndexOfSingletonTab(params);
+ // Did we use Instant's NTP contents?
+ bool swapped_in_instant = false;
+
// If no target WebContents was specified, we need to construct one if
// we are supposed to target a new tab; unless it's a singleton that already
// exists.
@@ -480,59 +528,39 @@ void Navigate(NavigateParams* params) {
}
if (params->disposition != CURRENT_TAB) {
- WebContents::CreateParams create_params(
- params->browser->profile(),
- tab_util::GetSiteInstanceForNewTab(params->browser->profile(), url));
- if (params->source_contents) {
- create_params.initial_size =
- params->source_contents->GetView()->GetContainerSize();
- }
-#if defined(USE_AURA)
- if (params->browser->window() &&
- params->browser->window()->GetNativeWindow()) {
- create_params.context =
- params->browser->window()->GetNativeWindow();
- }
-#endif
- params->target_contents = WebContents::Create(create_params);
- // New tabs can have WebUI URLs that will make calls back to arbitrary
- // tab helpers, so the entire set of tab helpers needs to be set up
- // immediately.
- BrowserNavigatorWebContentsAdoption::AttachTabHelpers(
- params->target_contents);
+ swapped_in_instant = SwapInInstantNTP(params, url, NULL);
+ if (!swapped_in_instant)
+ params->target_contents = CreateTargetContents(*params, url);
+
// This function takes ownership of |params->target_contents| until it
// is added to a TabStripModel.
target_contents_owner.TakeOwnership();
- extensions::TabHelper::FromWebContents(params->target_contents)->
- SetExtensionAppById(params->extension_app_id);
- // TODO(sky): Figure out why this is needed. Without it we seem to get
- // failures in startup tests.
- // By default, content believes it is not hidden. When adding contents
- // in the background, tell it that it's hidden.
- if ((params->tabstrip_add_types & TabStripModel::ADD_ACTIVE) == 0) {
- // TabStripModel::AddWebContents invokes WasHidden if not foreground.
- params->target_contents->WasHidden();
- }
} else {
// ... otherwise if we're loading in the current tab, the target is the
// same as the source.
- params->target_contents = params->source_contents;
+ DCHECK(params->source_contents);
+ swapped_in_instant = SwapInInstantNTP(params, url,
+ params->source_contents);
+ if (!swapped_in_instant)
+ params->target_contents = params->source_contents;
DCHECK(params->target_contents);
}
if (user_initiated)
params->target_contents->UserGestureDone();
- if (SwapInPrerender(params->target_contents, url))
- return;
+ if (!swapped_in_instant) {
+ if (SwapInPrerender(params->target_contents, url))
+ return;
- // Try to handle non-navigational URLs that popup dialogs and such, these
- // should not actually navigate.
- if (!HandleNonNavigationAboutURL(url)) {
- // Perform the actual navigation, tracking whether it came from the
- // renderer.
+ // Try to handle non-navigational URLs that popup dialogs and such, these
+ // should not actually navigate.
+ if (!HandleNonNavigationAboutURL(url)) {
+ // Perform the actual navigation, tracking whether it came from the
+ // renderer.
- LoadURLInContents(params->target_contents, url, params);
+ LoadURLInContents(params->target_contents, url, params);
+ }
}
} else {
// |target_contents| was specified non-NULL, and so we assume it has already
@@ -549,7 +577,8 @@ void Navigate(NavigateParams* params) {
(params->tabstrip_add_types & TabStripModel::ADD_INHERIT_OPENER))
params->source_contents->Focus();
- if (params->source_contents == params->target_contents) {
+ if (params->source_contents == params->target_contents ||
+ (swapped_in_instant && params->disposition == CURRENT_TAB)) {
// The navigation occurred in the source tab.
params->browser->UpdateUIForNavigationInTab(params->target_contents,
params->transition,
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 9bc6c73..186834fa 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -61,8 +61,7 @@ namespace chrome {
namespace search {
SearchTabHelper::SearchTabHelper(content::WebContents* web_contents)
- : WebContentsObserver(web_contents),
- is_search_enabled_(IsSearchEnabled(ProfileFromWebContents(web_contents))),
+ : is_search_enabled_(IsSearchEnabled(ProfileFromWebContents(web_contents))),
user_input_in_progress_(false),
model_(web_contents) {
if (!is_search_enabled_)
@@ -96,19 +95,6 @@ void SearchTabHelper::NavigationEntryUpdated() {
UpdateModelBasedOnURL(web_contents()->GetURL());
}
-void SearchTabHelper::NavigateToPendingEntry(
- const GURL& url,
- content::NavigationController::ReloadType reload_type) {
- if (!is_search_enabled_)
- return;
-
- // NTP mode changes are initiated at "pending", all others are initiated
- // when "committed". This is because NTP is rendered natively so is faster
- // to render than the web contents and we need to coordinate the animations.
- if (IsNTP(url))
- UpdateModelBasedOnURL(url);
-}
-
void SearchTabHelper::Observe(
int type,
const content::NotificationSource& source,
@@ -116,10 +102,7 @@ void SearchTabHelper::Observe(
DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type);
content::LoadCommittedDetails* committed_details =
content::Details<content::LoadCommittedDetails>(details).ptr();
- // See comment in |NavigateToPendingEntry()| about why |!IsNTP()| is used.
- if (!IsNTP(committed_details->entry->GetURL())) {
- UpdateModelBasedOnURL(committed_details->entry->GetURL());
- }
+ UpdateModelBasedOnURL(committed_details->entry->GetVirtualURL());
}
void SearchTabHelper::UpdateModelBasedOnURL(const GURL& url) {
diff --git a/chrome/browser/ui/search/search_tab_helper.h b/chrome/browser/ui/search/search_tab_helper.h
index db57c4e..114cc66 100644
--- a/chrome/browser/ui/search/search_tab_helper.h
+++ b/chrome/browser/ui/search/search_tab_helper.h
@@ -9,7 +9,6 @@
#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"
class OmniboxEditModel;
@@ -23,8 +22,7 @@ namespace search {
// Per-tab search "helper". Acts as the owner and controller of the tab's
// search UI model.
-class SearchTabHelper : public content::WebContentsObserver,
- public content::NotificationObserver,
+class SearchTabHelper : public content::NotificationObserver,
public content::WebContentsUserData<SearchTabHelper> {
public:
virtual ~SearchTabHelper();
@@ -43,11 +41,6 @@ class SearchTabHelper : public content::WebContentsObserver,
// the notification system and shouldn't call this method.
void NavigationEntryUpdated();
- // Overridden from contents::WebContentsObserver:
- virtual void NavigateToPendingEntry(
- const GURL& url,
- content::NavigationController::ReloadType reload_type) OVERRIDE;
-
// Overridden from content::NotificationObserver:
virtual void Observe(int type,
const content::NotificationSource& source,
diff --git a/chrome/browser/ui/toolbar/toolbar_model_impl.cc b/chrome/browser/ui/toolbar/toolbar_model_impl.cc
index 1d20fa0..5c4c475 100644
--- a/chrome/browser/ui/toolbar/toolbar_model_impl.cc
+++ b/chrome/browser/ui/toolbar/toolbar_model_impl.cc
@@ -136,6 +136,9 @@ bool ToolbarModelImpl::ShouldDisplayURL() const {
return false;
#endif
+ if (entry && entry->GetVirtualURL() == GURL(chrome::kChromeUINewTabURL))
+ return false;
+
return true;
}