| // 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/ui/search/search_tab_helper.h" |
| |
| #include <stdint.h> |
| |
| #include <memory> |
| #include <string> |
| #include <tuple> |
| |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/time/time.h" |
| #include "chrome/browser/signin/fake_signin_manager_builder.h" |
| #include "chrome/browser/signin/signin_manager_factory.h" |
| #include "chrome/browser/sync/profile_sync_service_factory.h" |
| #include "chrome/browser/sync/profile_sync_test_util.h" |
| #include "chrome/browser/ui/search/search_ipc_router.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/common/render_messages.h" |
| #include "chrome/common/search/mock_searchbox.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "chrome/test/base/browser_with_test_window_test.h" |
| #include "chrome/test/base/chrome_render_view_host_test_harness.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/browser_sync/profile_sync_service.h" |
| #include "components/omnibox/common/omnibox_focus_state.h" |
| #include "components/strings/grit/components_strings.h" |
| #include "content/public/browser/navigation_controller.h" |
| #include "content/public/browser/navigation_entry.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/mock_render_process_host.h" |
| #include "ipc/ipc_message.h" |
| #include "ipc/ipc_test_sink.h" |
| #include "net/base/net_errors.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "url/gurl.h" |
| |
| class OmniboxView; |
| |
| using testing::Eq; |
| using testing::Return; |
| using testing::_; |
| |
| namespace { |
| |
| class MockSearchIPCRouterDelegate : public SearchIPCRouter::Delegate { |
| public: |
| virtual ~MockSearchIPCRouterDelegate() {} |
| |
| MOCK_METHOD1(OnInstantSupportDetermined, void(bool supports_instant)); |
| MOCK_METHOD1(FocusOmnibox, void(OmniboxFocusState state)); |
| MOCK_METHOD2(NavigateToURL, void(const GURL&, WindowOpenDisposition)); |
| MOCK_METHOD1(OnDeleteMostVisitedItem, void(const GURL& url)); |
| MOCK_METHOD1(OnUndoMostVisitedDeletion, void(const GURL& url)); |
| MOCK_METHOD0(OnUndoAllMostVisitedDeletions, void()); |
| MOCK_METHOD2(OnLogEvent, void(NTPLoggingEventType event, |
| base::TimeDelta time)); |
| MOCK_METHOD2(OnLogMostVisitedImpression, |
| void(int position, ntp_tiles::NTPTileSource tile_source)); |
| MOCK_METHOD2(OnLogMostVisitedNavigation, |
| void(int position, ntp_tiles::NTPTileSource tile_source)); |
| MOCK_METHOD1(PasteIntoOmnibox, void(const base::string16&)); |
| MOCK_METHOD1(OnChromeIdentityCheck, void(const base::string16& identity)); |
| MOCK_METHOD0(OnHistorySyncCheck, void()); |
| }; |
| |
| class MockSearchBoxClientFactory |
| : public SearchIPCRouter::SearchBoxClientFactory { |
| public: |
| MOCK_METHOD0(GetSearchBox, chrome::mojom::SearchBox*(void)); |
| }; |
| |
| } // namespace |
| |
| class SearchTabHelperTest : public ChromeRenderViewHostTestHarness { |
| public: |
| SearchTabHelperTest() {} |
| |
| void SetUp() override { |
| ChromeRenderViewHostTestHarness::SetUp(); |
| SearchTabHelper::CreateForWebContents(web_contents()); |
| auto* search_tab = SearchTabHelper::FromWebContents(web_contents()); |
| auto factory = base::MakeUnique<MockSearchBoxClientFactory>(); |
| ON_CALL(*factory, GetSearchBox()).WillByDefault(Return(&mock_search_box_)); |
| search_tab->ipc_router_for_testing() |
| .set_search_box_client_factory_for_testing(std::move(factory)); |
| } |
| |
| content::BrowserContext* CreateBrowserContext() override { |
| TestingProfile::Builder builder; |
| builder.AddTestingFactory(SigninManagerFactory::GetInstance(), |
| BuildFakeSigninManagerBase); |
| builder.AddTestingFactory(ProfileSyncServiceFactory::GetInstance(), |
| BuildMockProfileSyncService); |
| return builder.Build().release(); |
| } |
| |
| // Creates a sign-in manager for tests. If |username| is not empty, the |
| // testing profile of the WebContents will be connected to the given account. |
| void CreateSigninManager(const std::string& username) { |
| SigninManagerBase* signin_manager = static_cast<SigninManagerBase*>( |
| SigninManagerFactory::GetForProfile(profile())); |
| |
| if (!username.empty()) { |
| ASSERT_TRUE(signin_manager); |
| signin_manager->SetAuthenticatedAccountInfo(username, username); |
| } |
| } |
| |
| // Configure the account to |sync_history| or not. |
| void SetHistorySync(bool sync_history) { |
| browser_sync::ProfileSyncServiceMock* sync_service = |
| static_cast<browser_sync::ProfileSyncServiceMock*>( |
| ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile())); |
| |
| syncer::ModelTypeSet result; |
| if (sync_history) { |
| result.Put(syncer::HISTORY_DELETE_DIRECTIVES); |
| } |
| EXPECT_CALL(*sync_service, GetPreferredDataTypes()) |
| .WillRepeatedly(Return(result)); |
| } |
| |
| MockSearchIPCRouterDelegate* mock_delegate() { return &delegate_; } |
| |
| MockSearchBox* mock_search_box() { return &mock_search_box_; } |
| |
| private: |
| MockSearchIPCRouterDelegate delegate_; |
| MockSearchBox mock_search_box_; |
| }; |
| |
| TEST_F(SearchTabHelperTest, DetermineIfPageSupportsInstant_Local) { |
| NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); |
| EXPECT_CALL(*mock_delegate(), OnInstantSupportDetermined(true)).Times(0); |
| |
| SearchTabHelper* search_tab_helper = |
| SearchTabHelper::FromWebContents(web_contents()); |
| ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper); |
| search_tab_helper->ipc_router_for_testing().set_delegate_for_testing( |
| mock_delegate()); |
| search_tab_helper->DetermineIfPageSupportsInstant(); |
| } |
| |
| TEST_F(SearchTabHelperTest, DetermineIfPageSupportsInstant_NonLocal) { |
| NavigateAndCommit(GURL("chrome-search://foo/bar")); |
| EXPECT_CALL(*mock_delegate(), OnInstantSupportDetermined(true)).Times(1); |
| |
| SearchTabHelper* search_tab_helper = |
| SearchTabHelper::FromWebContents(web_contents()); |
| ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper); |
| search_tab_helper->ipc_router_for_testing().set_delegate_for_testing( |
| mock_delegate()); |
| EXPECT_CALL(*mock_search_box(), DetermineIfPageSupportsInstant()); |
| search_tab_helper->DetermineIfPageSupportsInstant(); |
| |
| search_tab_helper->ipc_router_for_testing().InstantSupportDetermined( |
| search_tab_helper->ipc_router_for_testing().page_seq_no_for_testing(), |
| true); |
| } |
| |
| TEST_F(SearchTabHelperTest, PageURLDoesntBelongToInstantRenderer) { |
| // Navigate to a page URL that doesn't belong to Instant renderer. |
| // SearchTabHelper::DeterminerIfPageSupportsInstant() should return |
| // immediately without dispatching any message to the renderer. |
| NavigateAndCommit(GURL("http://www.example.com")); |
| EXPECT_CALL(*mock_delegate(), OnInstantSupportDetermined(false)).Times(0); |
| |
| SearchTabHelper* search_tab_helper = |
| SearchTabHelper::FromWebContents(web_contents()); |
| ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper); |
| search_tab_helper->ipc_router_for_testing().set_delegate_for_testing( |
| mock_delegate()); |
| EXPECT_CALL(*mock_search_box(), DetermineIfPageSupportsInstant()).Times(0); |
| search_tab_helper->DetermineIfPageSupportsInstant(); |
| } |
| |
| TEST_F(SearchTabHelperTest, OnChromeIdentityCheckMatch) { |
| NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); |
| CreateSigninManager(std::string("foo@bar.com")); |
| SearchTabHelper* search_tab_helper = |
| SearchTabHelper::FromWebContents(web_contents()); |
| ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper); |
| |
| const base::string16 test_identity = base::ASCIIToUTF16("foo@bar.com"); |
| EXPECT_CALL(*mock_search_box(), |
| ChromeIdentityCheckResult(Eq(test_identity), true)); |
| search_tab_helper->OnChromeIdentityCheck(test_identity); |
| } |
| |
| TEST_F(SearchTabHelperTest, OnChromeIdentityCheckMatchSlightlyDifferentGmail) { |
| NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); |
| CreateSigninManager(std::string("foobar123@gmail.com")); |
| SearchTabHelper* search_tab_helper = |
| SearchTabHelper::FromWebContents(web_contents()); |
| ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper); |
| |
| // For gmail, canonicalization is done so that email addresses have a |
| // standard form. |
| const base::string16 test_identity = |
| base::ASCIIToUTF16("Foo.Bar.123@gmail.com"); |
| EXPECT_CALL(*mock_search_box(), |
| ChromeIdentityCheckResult(Eq(test_identity), true)); |
| search_tab_helper->OnChromeIdentityCheck(test_identity); |
| } |
| |
| TEST_F(SearchTabHelperTest, OnChromeIdentityCheckMatchSlightlyDifferentGmail2) { |
| NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); |
| // |
| CreateSigninManager(std::string("chrome.user.7FOREVER")); |
| SearchTabHelper* search_tab_helper = |
| SearchTabHelper::FromWebContents(web_contents()); |
| ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper); |
| |
| // For gmail/googlemail, canonicalization is done so that email addresses have |
| // a standard form. |
| const base::string16 test_identity = |
| base::ASCIIToUTF16("chromeuser7forever@googlemail.com"); |
| EXPECT_CALL(*mock_search_box(), |
| ChromeIdentityCheckResult(Eq(test_identity), true)); |
| search_tab_helper->OnChromeIdentityCheck(test_identity); |
| } |
| |
| TEST_F(SearchTabHelperTest, OnChromeIdentityCheckMismatch) { |
| NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); |
| CreateSigninManager(std::string("foo@bar.com")); |
| SearchTabHelper* search_tab_helper = |
| SearchTabHelper::FromWebContents(web_contents()); |
| ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper); |
| |
| const base::string16 test_identity = base::ASCIIToUTF16("bar@foo.com"); |
| EXPECT_CALL(*mock_search_box(), |
| ChromeIdentityCheckResult(Eq(test_identity), false)); |
| search_tab_helper->OnChromeIdentityCheck(test_identity); |
| } |
| |
| TEST_F(SearchTabHelperTest, OnChromeIdentityCheckSignedOutMismatch) { |
| NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); |
| // This test does not sign in. |
| SearchTabHelper* search_tab_helper = |
| SearchTabHelper::FromWebContents(web_contents()); |
| ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper); |
| |
| const base::string16 test_identity = base::ASCIIToUTF16("bar@foo.com"); |
| EXPECT_CALL(*mock_search_box(), |
| ChromeIdentityCheckResult(Eq(test_identity), false)); |
| search_tab_helper->OnChromeIdentityCheck(test_identity); |
| } |
| |
| TEST_F(SearchTabHelperTest, OnHistorySyncCheckSyncing) { |
| NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); |
| SetHistorySync(true); |
| SearchTabHelper* search_tab_helper = |
| SearchTabHelper::FromWebContents(web_contents()); |
| ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper); |
| |
| EXPECT_CALL(*mock_search_box(), HistorySyncCheckResult(true)); |
| search_tab_helper->OnHistorySyncCheck(); |
| } |
| |
| TEST_F(SearchTabHelperTest, OnHistorySyncCheckNotSyncing) { |
| NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); |
| SetHistorySync(false); |
| SearchTabHelper* search_tab_helper = |
| SearchTabHelper::FromWebContents(web_contents()); |
| ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper); |
| |
| EXPECT_CALL(*mock_search_box(), HistorySyncCheckResult(false)); |
| search_tab_helper->OnHistorySyncCheck(); |
| } |
| |
| class TabTitleObserver : public content::WebContentsObserver { |
| public: |
| explicit TabTitleObserver(content::WebContents* contents) |
| : WebContentsObserver(contents) {} |
| |
| base::string16 title_on_start() { return title_on_start_; } |
| base::string16 title_on_commit() { return title_on_commit_; } |
| |
| private: |
| void DidStartNavigation( |
| content::NavigationHandle* navigation_handle) override { |
| title_on_start_ = web_contents()->GetTitle(); |
| } |
| |
| void DidFinishNavigation( |
| content::NavigationHandle* navigation_handle) override { |
| title_on_commit_ = web_contents()->GetTitle(); |
| } |
| |
| base::string16 title_on_start_; |
| base::string16 title_on_commit_; |
| }; |
| |
| TEST_F(SearchTabHelperTest, TitleIsSetForNTP) { |
| TabTitleObserver title_observer(web_contents()); |
| NavigateAndCommit(GURL(chrome::kChromeUINewTabURL)); |
| const base::string16 title = l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE); |
| EXPECT_EQ(title, title_observer.title_on_start()); |
| EXPECT_EQ(title, title_observer.title_on_commit()); |
| EXPECT_EQ(title, web_contents()->GetTitle()); |
| } |