blob: 973629d065ccfa71caabd836d428de4560495941 [file] [log] [blame]
// Copyright 2017 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/sync/sessions/browser_list_router_helper.h"
#include <memory>
#include <vector>
#include "base/stl_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/resource_coordinator/tab_manager.h"
#include "chrome/browser/sync/sessions/sync_sessions_web_contents_router.h"
#include "chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/sync_sessions/synced_tab_delegate.h"
namespace sync_sessions {
class MockLocalSessionEventHandler : public LocalSessionEventHandler {
public:
void OnSessionRestoreComplete() override {}
void OnLocalTabModified(SyncedTabDelegate* modified_tab) override {
seen_urls_.push_back(modified_tab->GetVirtualURLAtIndex(
modified_tab->GetCurrentEntryIndex()));
seen_ids_.push_back(modified_tab->GetSessionId());
}
void OnFaviconsChanged(const std::set<GURL>& page_urls,
const GURL& icon_url) override {}
std::vector<GURL>* seen_urls() { return &seen_urls_; }
std::vector<SessionID>* seen_ids() { return &seen_ids_; }
private:
std::vector<GURL> seen_urls_;
std::vector<SessionID> seen_ids_;
};
class BrowserListRouterHelperTest : public BrowserWithTestWindowTest {
protected:
~BrowserListRouterHelperTest() override {}
MockLocalSessionEventHandler handler_1;
MockLocalSessionEventHandler handler_2;
};
TEST_F(BrowserListRouterHelperTest, ObservationScopedToSingleProfile) {
TestingProfile* profile_1 = profile();
TestingProfile* profile_2 =
profile_manager()->CreateTestingProfile("testing_profile2");
std::unique_ptr<BrowserWindow> window_2(CreateBrowserWindow());
std::unique_ptr<Browser> browser_2(
CreateBrowser(profile_2, browser()->type(), false, window_2.get()));
SyncSessionsWebContentsRouterFactory::GetInstance()
->GetForProfile(profile_1)
->StartRoutingTo(&handler_1);
SyncSessionsWebContentsRouterFactory::GetInstance()
->GetForProfile(profile_2)
->StartRoutingTo(&handler_2);
GURL gurl_1("http://foo1.com");
GURL gurl_2("http://foo2.com");
AddTab(browser(), gurl_1);
AddTab(browser_2.get(), gurl_2);
std::vector<GURL>* handler_1_urls = handler_1.seen_urls();
EXPECT_TRUE(base::ContainsValue(*handler_1_urls, gurl_1));
EXPECT_FALSE(base::ContainsValue(*handler_1_urls, gurl_2));
std::vector<GURL>* handler_2_urls = handler_2.seen_urls();
EXPECT_TRUE(base::ContainsValue(*handler_2_urls, gurl_2));
EXPECT_FALSE(base::ContainsValue(*handler_2_urls, gurl_1));
// Add a browser for each profile.
std::unique_ptr<BrowserWindow> window_3(CreateBrowserWindow());
std::unique_ptr<BrowserWindow> window_4(CreateBrowserWindow());
std::unique_ptr<Browser> new_browser_in_first_profile(
CreateBrowser(profile_1, browser()->type(), false, window_3.get()));
std::unique_ptr<Browser> new_browser_in_second_profile(
CreateBrowser(profile_2, browser()->type(), false, window_4.get()));
GURL gurl_3("http://foo3.com");
GURL gurl_4("http://foo4.com");
AddTab(new_browser_in_first_profile.get(), gurl_3);
AddTab(new_browser_in_second_profile.get(), gurl_4);
handler_1_urls = handler_1.seen_urls();
EXPECT_TRUE(base::ContainsValue(*handler_1_urls, gurl_3));
EXPECT_FALSE(base::ContainsValue(*handler_1_urls, gurl_4));
handler_2_urls = handler_2.seen_urls();
EXPECT_TRUE(base::ContainsValue(*handler_2_urls, gurl_4));
EXPECT_FALSE(base::ContainsValue(*handler_2_urls, gurl_3));
// Cleanup needed for manually created browsers so they don't complain about
// having open tabs when destructing.
browser_2->tab_strip_model()->CloseAllTabs();
new_browser_in_first_profile->tab_strip_model()->CloseAllTabs();
new_browser_in_second_profile->tab_strip_model()->CloseAllTabs();
}
// Added when fixing https://crbug.com/777745, ensure tab discards are observed.
TEST_F(BrowserListRouterHelperTest, NotifyOnDiscardTab) {
TestingProfile* profile_1 = profile();
TestingProfile* profile_2 =
profile_manager()->CreateTestingProfile("testing_profile2");
std::unique_ptr<BrowserWindow> window_2(CreateBrowserWindow());
std::unique_ptr<Browser> browser_2(
CreateBrowser(profile_2, browser()->type(), false, window_2.get()));
SyncSessionsWebContentsRouterFactory::GetInstance()
->GetForProfile(profile_1)
->StartRoutingTo(&handler_1);
SyncSessionsWebContentsRouterFactory::GetInstance()
->GetForProfile(profile_2)
->StartRoutingTo(&handler_2);
GURL gurl_1("http://foo1.com");
AddTab(browser(), gurl_1);
// Tab needs to have been active to be found when discarding.
BrowserList::GetInstance()->SetLastActive(browser());
EXPECT_EQ(gurl_1, *handler_1.seen_urls()->rbegin());
SessionID old_id = *handler_1.seen_ids()->rbegin();
// Remove previous any observations from setup to make checking expectations
// easier below.
handler_1.seen_urls()->clear();
handler_1.seen_ids()->clear();
g_browser_process->GetTabManager()->DiscardTabByExtension(
browser()->tab_strip_model()->GetWebContentsAt(0));
// We're typically notified twice while discarding tabs. Once for the
// destruction of the old web contents, and once for the new. This test case
// is really trying to make sure the TabReplacedAt() method is called, which
// is going to be invoked for the new web contents. We can tell it is the new
// one by finding |gurl_1| for an id that is not |old_id|.
bool found_new_id = false;
for (size_t i = 0; i < handler_1.seen_ids()->size(); ++i) {
if (handler_1.seen_ids()->at(i) != old_id &&
handler_1.seen_urls()->at(i) == gurl_1) {
found_new_id = true;
break;
}
}
EXPECT_TRUE(found_new_id);
// And of course |profile_2| shouldn't have seen anything.
EXPECT_EQ(0U, handler_2.seen_urls()->size());
// Cleanup needed for manually created browsers so they don't complain about
// having open tabs when destructing.
browser_2->tab_strip_model()->CloseAllTabs();
}
} // namespace sync_sessions