Commit 629b3084 authored by Mikel Astiz's avatar Mikel Astiz Committed by Commit Bot

Add sync integration tests for closed tabs

There are certain requirements wrt. how sync should behave when a tab
is closed. This patch introduces the first related integration tests,
which reflect current behavior and most notably include the need to sync
history for navigations issued immediately before closing a tab.

Bug: 882489
Change-Id: I255a5082f4a75a24d91ef4be443324094427bd1e
Reviewed-on: https://chromium-review.googlesource.com/c/1355127
Commit-Queue: Mikel Astiz <mastiz@chromium.org>
Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612372}
parent d973a55b
...@@ -44,17 +44,12 @@ using sync_datatype_helper::test; ...@@ -44,17 +44,12 @@ using sync_datatype_helper::test;
namespace sessions_helper { namespace sessions_helper {
bool GetLocalSession(int index, const sync_sessions::SyncedSession** session) { namespace {
return SessionSyncServiceFactory::GetInstance()
->GetForProfile(test()->GetProfile(index))
->GetOpenTabsUIDelegate()
->GetLocalSession(session);
}
bool SessionsSyncManagerHasTabWithURL(int index, const GURL& url) { bool SessionsSyncBridgeHasTabWithURL(int browser_index, const GURL& url) {
content::RunAllPendingInMessageLoop(); content::RunAllPendingInMessageLoop();
const sync_sessions::SyncedSession* local_session; const sync_sessions::SyncedSession* local_session;
if (!GetLocalSession(index, &local_session)) { if (!GetLocalSession(browser_index, &local_session)) {
return false; return false;
} }
...@@ -94,37 +89,53 @@ bool SessionsSyncManagerHasTabWithURL(int index, const GURL& url) { ...@@ -94,37 +89,53 @@ bool SessionsSyncManagerHasTabWithURL(int index, const GURL& url) {
return false; return false;
} }
bool OpenTab(int index, const GURL& url) { } // namespace
DVLOG(1) << "Opening tab: " << url.spec() << " using browser " << index
<< "."; bool GetLocalSession(int browser_index,
return OpenTabAtIndex(index, 0, url); const sync_sessions::SyncedSession** session) {
return SessionSyncServiceFactory::GetInstance()
->GetForProfile(test()->GetProfile(browser_index))
->GetOpenTabsUIDelegate()
->GetLocalSession(session);
} }
bool OpenTabAtIndex(int index, int tab_index, const GURL& url) { bool OpenTab(int browser_index, const GURL& url) {
chrome::AddTabAt(test()->GetBrowser(index), url, tab_index, true); DVLOG(1) << "Opening tab: " << url.spec() << " using browser "
return WaitForTabToLoad( << browser_index << ".";
index, url, TabStripModel* tab_strip =
test()->GetBrowser(index)->tab_strip_model()->GetWebContentsAt( test()->GetBrowser(browser_index)->tab_strip_model();
tab_index)); int tab_index = tab_strip->count();
return OpenTabAtIndex(browser_index, tab_index, url);
} }
bool OpenMultipleTabs(int index, const std::vector<GURL>& urls) { bool OpenTabAtIndex(int browser_index, int tab_index, const GURL& url) {
Browser* browser = test()->GetBrowser(index); chrome::AddTabAt(test()->GetBrowser(browser_index), url, tab_index, true);
return WaitForTabToLoad(browser_index, url,
test()
->GetBrowser(browser_index)
->tab_strip_model()
->GetWebContentsAt(tab_index));
}
bool OpenMultipleTabs(int browser_index, const std::vector<GURL>& urls) {
Browser* browser = test()->GetBrowser(browser_index);
for (auto it = urls.begin(); it != urls.end(); ++it) { for (auto it = urls.begin(); it != urls.end(); ++it) {
DVLOG(1) << "Opening tab: " << it->spec() << " using browser " << index DVLOG(1) << "Opening tab: " << it->spec() << " using browser "
<< "."; << browser_index << ".";
ShowSingletonTab(browser, *it); ShowSingletonTab(browser, *it);
} }
return WaitForTabsToLoad(index, urls); return WaitForTabsToLoad(browser_index, urls);
} }
bool OpenTabFromSourceIndex(int index, bool OpenTabFromSourceIndex(int browser_index,
int index_of_source_tab, int index_of_source_tab,
const GURL& url, const GURL& url,
WindowOpenDisposition disposition) { WindowOpenDisposition disposition) {
content::WebContents* source_contents = content::WebContents* source_contents =
test()->GetBrowser(index)->tab_strip_model()->GetWebContentsAt( test()
index_of_source_tab); ->GetBrowser(browser_index)
->tab_strip_model()
->GetWebContentsAt(index_of_source_tab);
content::OpenURLParams open_url_params(url, content::Referrer(), disposition, content::OpenURLParams open_url_params(url, content::Referrer(), disposition,
ui::PAGE_TRANSITION_LINK, false, ui::PAGE_TRANSITION_LINK, false,
...@@ -140,56 +151,66 @@ bool OpenTabFromSourceIndex(int index, ...@@ -140,56 +151,66 @@ bool OpenTabFromSourceIndex(int index,
return false; return false;
} }
return WaitForTabToLoad(index, url, new_contents); return WaitForTabToLoad(browser_index, url, new_contents);
} }
void MoveTab(int from_index, int to_index, int tab_index) { void CloseTab(int browser_index, int tab_index) {
TabStripModel* tab_strip =
test()->GetBrowser(browser_index)->tab_strip_model();
tab_strip->CloseWebContentsAt(tab_index, TabStripModel::CLOSE_USER_GESTURE);
}
void MoveTab(int from_browser_index, int to_browser_index, int tab_index) {
std::unique_ptr<content::WebContents> detached_contents = std::unique_ptr<content::WebContents> detached_contents =
test() test()
->GetBrowser(from_index) ->GetBrowser(from_browser_index)
->tab_strip_model() ->tab_strip_model()
->DetachWebContentsAt(tab_index); ->DetachWebContentsAt(tab_index);
TabStripModel* target_strip = test()->GetBrowser(to_index)->tab_strip_model(); TabStripModel* target_strip =
test()->GetBrowser(to_browser_index)->tab_strip_model();
target_strip->InsertWebContentsAt(target_strip->count(), target_strip->InsertWebContentsAt(target_strip->count(),
std::move(detached_contents), std::move(detached_contents),
TabStripModel::ADD_ACTIVE); TabStripModel::ADD_ACTIVE);
} }
bool NavigateTab(int index, const GURL& url) { void NavigateTab(int browser_index, const GURL& url) {
NavigateParams params(test()->GetBrowser(index), url, NavigateParams params(test()->GetBrowser(browser_index), url,
ui::PAGE_TRANSITION_LINK); ui::PAGE_TRANSITION_LINK);
params.disposition = WindowOpenDisposition::CURRENT_TAB; params.disposition = WindowOpenDisposition::CURRENT_TAB;
ui_test_utils::NavigateToURL(&params); ui_test_utils::NavigateToURL(&params);
return WaitForTabToLoad(index, url, params.navigated_or_inserted_contents);
} }
void NavigateTabBack(int index) { void NavigateTabBack(int browser_index) {
test() test()
->GetBrowser(index) ->GetBrowser(browser_index)
->tab_strip_model() ->tab_strip_model()
->GetWebContentsAt(0) ->GetWebContentsAt(0)
->GetController() ->GetController()
.GoBack(); .GoBack();
} }
void NavigateTabForward(int index) { void NavigateTabForward(int browser_index) {
test() test()
->GetBrowser(index) ->GetBrowser(browser_index)
->tab_strip_model() ->tab_strip_model()
->GetWebContentsAt(0) ->GetWebContentsAt(0)
->GetController() ->GetController()
.GoForward(); .GoForward();
} }
bool WaitForTabsToLoad(int index, const std::vector<GURL>& urls) { bool WaitForTabsToLoad(int browser_index, const std::vector<GURL>& urls) {
int tab_index = 0; int tab_index = 0;
for (const auto& url : urls) { for (const auto& url : urls) {
bool success = WaitForTabToLoad( content::WebContents* web_contents = test()
index, url, ->GetBrowser(browser_index)
test()->GetBrowser(index)->tab_strip_model()->GetWebContentsAt( ->tab_strip_model()
tab_index)); ->GetWebContentsAt(tab_index);
if (!web_contents) {
LOG(ERROR) << "Tab " << tab_index << " does not exist";
return false;
}
bool success = WaitForTabToLoad(browser_index, url, web_contents);
if (!success) { if (!success) {
return false; return false;
} }
...@@ -198,15 +219,16 @@ bool WaitForTabsToLoad(int index, const std::vector<GURL>& urls) { ...@@ -198,15 +219,16 @@ bool WaitForTabsToLoad(int index, const std::vector<GURL>& urls) {
return true; return true;
} }
bool WaitForTabToLoad(int index, bool WaitForTabToLoad(int browser_index,
const GURL& url, const GURL& url,
content::WebContents* web_contents) { content::WebContents* web_contents) {
DCHECK(web_contents);
DVLOG(1) << "Waiting for session to propagate to associator."; DVLOG(1) << "Waiting for session to propagate to associator.";
base::TimeTicks start_time = base::TimeTicks::Now(); base::TimeTicks start_time = base::TimeTicks::Now();
base::TimeTicks end_time = start_time + TestTimeouts::action_max_timeout(); base::TimeTicks end_time = start_time + TestTimeouts::action_max_timeout();
bool found = false; bool found = false;
while (!found) { while (!found) {
found = SessionsSyncManagerHasTabWithURL(index, url); found = SessionsSyncBridgeHasTabWithURL(browser_index, url);
if (base::TimeTicks::Now() >= end_time) { if (base::TimeTicks::Now() >= end_time) {
LOG(ERROR) << "Failed to find url " << url.spec() << " in tab after " LOG(ERROR) << "Failed to find url " << url.spec() << " in tab after "
<< TestTimeouts::action_max_timeout().InSecondsF() << TestTimeouts::action_max_timeout().InSecondsF()
...@@ -220,11 +242,11 @@ bool WaitForTabToLoad(int index, ...@@ -220,11 +242,11 @@ bool WaitForTabToLoad(int index,
return true; return true;
} }
bool GetLocalWindows(int index, ScopedWindowMap* local_windows) { bool GetLocalWindows(int browser_index, ScopedWindowMap* local_windows) {
// The local session provided by GetLocalSession is owned, and has lifetime // The local session provided by GetLocalSession is owned, and has lifetime
// controlled, by the sessions sync manager, so we must make our own copy. // controlled, by the sessions sync manager, so we must make our own copy.
const sync_sessions::SyncedSession* local_session; const sync_sessions::SyncedSession* local_session;
if (!GetLocalSession(index, &local_session)) { if (!GetLocalSession(browser_index, &local_session)) {
return false; return false;
} }
for (auto w = local_session->windows.begin(); for (auto w = local_session->windows.begin();
...@@ -250,26 +272,26 @@ bool GetLocalWindows(int index, ScopedWindowMap* local_windows) { ...@@ -250,26 +272,26 @@ bool GetLocalWindows(int index, ScopedWindowMap* local_windows) {
return true; return true;
} }
bool CheckInitialState(int index) { bool CheckInitialState(int browser_index) {
if (0 != GetNumWindows(index)) if (0 != GetNumWindows(browser_index))
return false; return false;
if (0 != GetNumForeignSessions(index)) if (0 != GetNumForeignSessions(browser_index))
return false; return false;
return true; return true;
} }
int GetNumWindows(int index) { int GetNumWindows(int browser_index) {
const sync_sessions::SyncedSession* local_session; const sync_sessions::SyncedSession* local_session;
if (!GetLocalSession(index, &local_session)) { if (!GetLocalSession(browser_index, &local_session)) {
return 0; return 0;
} }
return local_session->windows.size(); return local_session->windows.size();
} }
int GetNumForeignSessions(int index) { int GetNumForeignSessions(int browser_index) {
SyncedSessionVector sessions; SyncedSessionVector sessions;
if (!SessionSyncServiceFactory::GetInstance() if (!SessionSyncServiceFactory::GetInstance()
->GetForProfile(test()->GetProfile(index)) ->GetForProfile(test()->GetProfile(browser_index))
->GetOpenTabsUIDelegate() ->GetOpenTabsUIDelegate()
->GetAllForeignSessions(&sessions)) { ->GetAllForeignSessions(&sessions)) {
return 0; return 0;
...@@ -277,9 +299,9 @@ int GetNumForeignSessions(int index) { ...@@ -277,9 +299,9 @@ int GetNumForeignSessions(int index) {
return sessions.size(); return sessions.size();
} }
bool GetSessionData(int index, SyncedSessionVector* sessions) { bool GetSessionData(int browser_index, SyncedSessionVector* sessions) {
if (!SessionSyncServiceFactory::GetInstance() if (!SessionSyncServiceFactory::GetInstance()
->GetForProfile(test()->GetProfile(index)) ->GetForProfile(test()->GetProfile(browser_index))
->GetOpenTabsUIDelegate() ->GetOpenTabsUIDelegate()
->GetAllForeignSessions(sessions)) { ->GetAllForeignSessions(sessions)) {
return false; return false;
...@@ -390,18 +412,18 @@ bool WindowsMatch(const SessionWindowMap& win1, const ScopedWindowMap& win2) { ...@@ -390,18 +412,18 @@ bool WindowsMatch(const SessionWindowMap& win1, const ScopedWindowMap& win2) {
return WindowsMatchImpl(win1, win2); return WindowsMatchImpl(win1, win2);
} }
bool CheckForeignSessionsAgainst(int index, bool CheckForeignSessionsAgainst(int browser_index,
const std::vector<ScopedWindowMap>& windows) { const std::vector<ScopedWindowMap>& windows) {
SyncedSessionVector sessions; SyncedSessionVector sessions;
if (!GetSessionData(index, &sessions)) { if (!GetSessionData(browser_index, &sessions)) {
LOG(ERROR) << "Cannot get session data"; LOG(ERROR) << "Cannot get session data";
return false; return false;
} }
for (size_t w_index = 0; w_index < windows.size(); ++w_index) { for (size_t w_index = 0; w_index < windows.size(); ++w_index) {
// Skip the client's local window // Skip the client's local window
if (static_cast<int>(w_index) == index) { if (static_cast<int>(w_index) == browser_index) {
continue; continue;
} }
...@@ -421,9 +443,9 @@ bool CheckForeignSessionsAgainst(int index, ...@@ -421,9 +443,9 @@ bool CheckForeignSessionsAgainst(int index,
return true; return true;
} }
void DeleteForeignSession(int index, std::string session_tag) { void DeleteForeignSession(int browser_index, std::string session_tag) {
SessionSyncServiceFactory::GetInstance() SessionSyncServiceFactory::GetInstance()
->GetForProfile(test()->GetProfile(index)) ->GetForProfile(test()->GetProfile(browser_index))
->GetOpenTabsUIDelegate() ->GetOpenTabsUIDelegate()
->DeleteForeignSession(session_tag); ->DeleteForeignSession(session_tag);
} }
...@@ -431,15 +453,15 @@ void DeleteForeignSession(int index, std::string session_tag) { ...@@ -431,15 +453,15 @@ void DeleteForeignSession(int index, std::string session_tag) {
} // namespace sessions_helper } // namespace sessions_helper
ForeignSessionsMatchChecker::ForeignSessionsMatchChecker( ForeignSessionsMatchChecker::ForeignSessionsMatchChecker(
int index, int browser_index,
const std::vector<sessions_helper::ScopedWindowMap>& windows) const std::vector<sessions_helper::ScopedWindowMap>& windows)
: MultiClientStatusChangeChecker( : MultiClientStatusChangeChecker(
sync_datatype_helper::test()->GetSyncServices()), sync_datatype_helper::test()->GetSyncServices()),
index_(index), browser_index_(browser_index),
windows_(windows) {} windows_(windows) {}
bool ForeignSessionsMatchChecker::IsExitConditionSatisfied() { bool ForeignSessionsMatchChecker::IsExitConditionSatisfied() {
return sessions_helper::CheckForeignSessionsAgainst(index_, windows_); return sessions_helper::CheckForeignSessionsAgainst(browser_index_, windows_);
} }
std::string ForeignSessionsMatchChecker::GetDebugMessage() const { std::string ForeignSessionsMatchChecker::GetDebugMessage() const {
......
...@@ -30,21 +30,21 @@ using ScopedWindowMap = ...@@ -30,21 +30,21 @@ using ScopedWindowMap =
// Copies the local session windows of profile at |index| to |local_windows|. // Copies the local session windows of profile at |index| to |local_windows|.
// Returns true if successful. // Returns true if successful.
bool GetLocalWindows(int index, ScopedWindowMap* local_windows); bool GetLocalWindows(int browser_index, ScopedWindowMap* local_windows);
// Checks that window count and foreign session count are 0. // Checks that window count and foreign session count are 0.
bool CheckInitialState(int index); bool CheckInitialState(int browser_index);
// Returns number of open windows for a profile. // Returns number of open windows for a profile.
int GetNumWindows(int index); int GetNumWindows(int browser_index);
// Returns number of foreign sessions for a profile. // Returns number of foreign sessions for a profile.
int GetNumForeignSessions(int index); int GetNumForeignSessions(int browser_index);
// Fills the sessions vector with the SyncableService's foreign session data. // Fills the sessions vector with the SyncableService's foreign session data.
// Caller owns |sessions|, but not SyncedSessions objects within. // Caller owns |sessions|, but not SyncedSessions objects within.
// Returns true if foreign sessions were found, false otherwise. // Returns true if foreign sessions were found, false otherwise.
bool GetSessionData(int index, SyncedSessionVector* sessions); bool GetSessionData(int browser_index, SyncedSessionVector* sessions);
// Compares a foreign session based on the first session window. // Compares a foreign session based on the first session window.
// Returns true based on the comparison of the session windows. // Returns true based on the comparison of the session windows.
...@@ -74,75 +74,70 @@ bool WindowsMatch(const SessionWindowMap& win1, const ScopedWindowMap& win2); ...@@ -74,75 +74,70 @@ bool WindowsMatch(const SessionWindowMap& win1, const ScopedWindowMap& win2);
// with a reference SessionWindow list. // with a reference SessionWindow list.
// Returns true if the session windows of the foreign session matches the // Returns true if the session windows of the foreign session matches the
// reference. // reference.
bool CheckForeignSessionsAgainst(int index, bool CheckForeignSessionsAgainst(int browser_index,
const std::vector<ScopedWindowMap>& windows); const std::vector<ScopedWindowMap>& windows);
// Open a single tab in the browser at |index| and block until the // Opens (appends) a single tab in the browser at |index| and block until the
// session SyncableService is aware of it. Returns true upon success, false // sessions bridge is aware of it. Returns true upon success, false otherwise.
// otherwise. bool OpenTab(int browser_index, const GURL& url);
bool OpenTab(int index, const GURL& url);
// See OpenTab, except that the tab is opened in position |tab_index|. // See OpenTab, except that the tab is opened in position |tab_index|.
// If |tab_index| is -1 or greater than the number of tabs, the tab will be // If |tab_index| is -1 or greater than the number of tabs, the tab will be
// appended to the end of the strip. i.e. if tab_index is 3 for a tab strip of // appended to the end of the strip. i.e. if tab_index is 3 for a tab strip of
// size 1, the new tab will be in position 1. // size 1, the new tab will be in position 1.
bool OpenTabAtIndex(int index, int tab_index, const GURL& url); bool OpenTabAtIndex(int browser_index, int tab_index, const GURL& url);
// Like OpenTab, but opens |url| from the tab at |index_of_source_tab| using // Like OpenTab, but opens |url| from the tab at |index_of_source_tab| using
// |disposition|. // |disposition|.
bool OpenTabFromSourceIndex(int index, bool OpenTabFromSourceIndex(int browser_index,
int index_of_source_tab, int index_of_source_tab,
const GURL& url, const GURL& url,
WindowOpenDisposition disposition); WindowOpenDisposition disposition);
// Open multiple tabs and block until the session SyncableService is aware // Opens multiple tabs and blocks until the sessions bridge is aware of all of
// of all of them. Returns true on success, false on failure. // them. Returns true on success, false on failure.
bool OpenMultipleTabs(int index, const std::vector<GURL>& urls); bool OpenMultipleTabs(int browser_index, const std::vector<GURL>& urls);
// Closes the tab |tab_index| in the browser at |index|.
void CloseTab(int browser_index, int tab_index);
// Moves the tab in position |tab_index| in the TabStrip for browser at // Moves the tab in position |tab_index| in the TabStrip for browser at
// |from_index| to the TabStrip for browser at |to_index|. // |from_browser_index| to the TabStrip for browser at |to_browser_index|.
void MoveTab(int from_index, int to_index, int tab_index); void MoveTab(int from_browser_index, int to_browser_index, int tab_index);
// Navigate the active tab for browser in position |index| to the given // Navigate the active tab for browser in position |index| to the given
// url, and blocks until the session SyncableService is aware of it. // URL.
// WARNING: it's dangerous to assume this will return for any arbitrary URL. void NavigateTab(int browser_index, const GURL& url);
// For URLs that don't resolve to a valid server response, this can block
// indefinitely. Use a data uri or the embedded_test_server to ensure that this
// doesn't happen.
bool NavigateTab(int index, const GURL& url);
// Navigate the active tab for browser in position |index| back by one; // Navigate the active tab for browser in position |index| back by one;
// if this isn't possible, does nothing // if this isn't possible, does nothing
void NavigateTabBack(int index); void NavigateTabBack(int browser_index);
// Navigate the active tab for browser in position |index| forward by // Navigate the active tab for browser in position |index| forward by
// one; if this isn't possible, does nothing // one; if this isn't possible, does nothing
void NavigateTabForward(int index); void NavigateTabForward(int browser_index);
// Wait for a session change to |web_contents| to propagate to the model // Wait for a session change to |web_contents| to propagate to the model
// associator. Will return true once |url| has been found, or false if it times // associator. Will return true once |url| has been found, or false if it times
// out while waiting. // out while waiting.
bool WaitForTabToLoad(int index, bool WaitForTabToLoad(int browser_index,
const GURL& url, const GURL& url,
content::WebContents* web_contents); content::WebContents* web_contents);
// Wait for each url in |urls| to load. The ordering of |urls| is assumed to // Wait for each url in |urls| to load. The ordering of |urls| is assumed to
// match the ordering of the corresponding tabs. // match the ordering of the corresponding tabs.
bool WaitForTabsToLoad(int index, const std::vector<GURL>& urls); bool WaitForTabsToLoad(int browser_index, const std::vector<GURL>& urls);
// Check if the session SyncableService knows that the current open tab
// has this url.
bool SessionsSyncManagerHasTabWithURL(int index, const GURL& url);
// Stores a pointer to the local session for a given profile in |session|. // Stores a pointer to the local session for a given profile in |session|.
// Returns true on success, false on failure. // Returns true on success, false on failure.
bool GetLocalSession(int index, const sync_sessions::SyncedSession** session); bool GetLocalSession(int browser_index,
const sync_sessions::SyncedSession** session);
// Deletes the foreign session with tag |session_tag| from the profile specified // Deletes the foreign session with tag |session_tag| from the profile specified
// by |index|. This will affect all synced clients. // by |index|. This will affect all synced clients.
// Note: We pass the session_tag in by value to ensure it's not a reference // Note: We pass the session_tag in by value to ensure it's not a reference
// to the session tag within the SyncedSession we plan to delete. // to the session tag within the SyncedSession we plan to delete.
void DeleteForeignSession(int index, std::string session_tag); void DeleteForeignSession(int browser_index, std::string session_tag);
} // namespace sessions_helper } // namespace sessions_helper
...@@ -151,7 +146,7 @@ void DeleteForeignSession(int index, std::string session_tag); ...@@ -151,7 +146,7 @@ void DeleteForeignSession(int index, std::string session_tag);
class ForeignSessionsMatchChecker : public MultiClientStatusChangeChecker { class ForeignSessionsMatchChecker : public MultiClientStatusChangeChecker {
public: public:
ForeignSessionsMatchChecker( ForeignSessionsMatchChecker(
int index, int browser_index,
const std::vector<sessions_helper::ScopedWindowMap>& windows); const std::vector<sessions_helper::ScopedWindowMap>& windows);
// StatusChangeChecker implementation. // StatusChangeChecker implementation.
...@@ -159,7 +154,7 @@ class ForeignSessionsMatchChecker : public MultiClientStatusChangeChecker { ...@@ -159,7 +154,7 @@ class ForeignSessionsMatchChecker : public MultiClientStatusChangeChecker {
std::string GetDebugMessage() const override; std::string GetDebugMessage() const override;
private: private:
int index_; int browser_index_;
const std::vector<sessions_helper::ScopedWindowMap>& windows_; const std::vector<sessions_helper::ScopedWindowMap>& windows_;
}; };
......
...@@ -34,9 +34,9 @@ using base::HistogramSamples; ...@@ -34,9 +34,9 @@ using base::HistogramSamples;
using base::HistogramTester; using base::HistogramTester;
using fake_server::SessionsHierarchy; using fake_server::SessionsHierarchy;
using sessions_helper::CheckInitialState; using sessions_helper::CheckInitialState;
using sessions_helper::CloseTab;
using sessions_helper::GetLocalWindows; using sessions_helper::GetLocalWindows;
using sessions_helper::GetSessionData; using sessions_helper::GetSessionData;
using sessions_helper::SessionsSyncManagerHasTabWithURL;
using sessions_helper::MoveTab; using sessions_helper::MoveTab;
using sessions_helper::NavigateTab; using sessions_helper::NavigateTab;
using sessions_helper::NavigateTabBack; using sessions_helper::NavigateTabBack;
...@@ -53,6 +53,7 @@ using typed_urls_helper::GetUrlFromClient; ...@@ -53,6 +53,7 @@ using typed_urls_helper::GetUrlFromClient;
static const char* kURL1 = "data:text/html,<html><title>Test</title></html>"; static const char* kURL1 = "data:text/html,<html><title>Test</title></html>";
static const char* kURL2 = "data:text/html,<html><title>Test2</title></html>"; static const char* kURL2 = "data:text/html,<html><title>Test2</title></html>";
static const char* kURL3 = "data:text/html,<html><title>Test3</title></html>"; static const char* kURL3 = "data:text/html,<html><title>Test3</title></html>";
static const char* kURL4 = "data:text/html,<html><title>Test4</title></html>";
static const char* kBaseFragmentURL = static const char* kBaseFragmentURL =
"data:text/html,<html><title>Fragment</title><body></body></html>"; "data:text/html,<html><title>Fragment</title><body></body></html>";
static const char* kSpecifiedFragmentURL = static const char* kSpecifiedFragmentURL =
...@@ -69,6 +70,39 @@ void ExpectUniqueSampleGE(const HistogramTester& histogram_tester, ...@@ -69,6 +70,39 @@ void ExpectUniqueSampleGE(const HistogramTester& histogram_tester,
EXPECT_EQ(sample_count, samples->TotalCount()); EXPECT_EQ(sample_count, samples->TotalCount());
} }
class IsUrlSyncedChecker : public SingleClientStatusChangeChecker {
public:
IsUrlSyncedChecker(const std::string& url,
fake_server::FakeServer* fake_server,
browser_sync::ProfileSyncService* service)
: SingleClientStatusChangeChecker(service),
url_(url),
fake_server_(fake_server) {}
// StatusChangeChecker implementation.
bool IsExitConditionSatisfied() override {
std::vector<sync_pb::SyncEntity> entities =
fake_server_->GetSyncEntitiesByModelType(syncer::SESSIONS);
for (const sync_pb::SyncEntity& entity : entities) {
for (const auto& navigation :
entity.specifics().session().tab().navigation()) {
if (navigation.virtual_url() == url_) {
return true;
}
}
}
return false;
}
std::string GetDebugMessage() const override {
return "Waiting for URLs to be commited to the server";
}
private:
const std::string url_;
fake_server::FakeServer* fake_server_;
};
class SingleClientSessionsSyncTest : public SyncTest { class SingleClientSessionsSyncTest : public SyncTest {
public: public:
SingleClientSessionsSyncTest() : SyncTest(SINGLE_CLIENT) {} SingleClientSessionsSyncTest() : SyncTest(SINGLE_CLIENT) {}
...@@ -181,6 +215,30 @@ IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest, ChromeHistory) { ...@@ -181,6 +215,30 @@ IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest, ChromeHistory) {
WaitForURLOnServer(GURL(chrome::kChromeUIHistoryURL)); WaitForURLOnServer(GURL(chrome::kChromeUIHistoryURL));
} }
IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest, NavigateThenCloseTab) {
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
ASSERT_TRUE(CheckInitialState(0));
// Two tabs are opened initially.
ASSERT_TRUE(OpenTab(0, GURL(kURL1)));
ASSERT_TRUE(OpenTab(0, GURL(kURL2)));
WaitForHierarchyOnServer(SessionsHierarchy({{kURL1, kURL2}}));
// Close one of the two tabs immediately after issuing an navigation. We also
// issue another navigation to make sure association logic kicks in.
NavigateTab(0, GURL(kURL3));
CloseTab(/*index=*/0, /*tab_index=*/1);
NavigateTab(0, GURL(kURL4));
ASSERT_TRUE(
IsUrlSyncedChecker(kURL4, GetFakeServer(), GetSyncService(0)).Wait());
// All URLs should be synced, for synced history to be complete. In
// particular, |kURL3| should be synced despite the tab being closed.
EXPECT_TRUE(
IsUrlSyncedChecker(kURL3, GetFakeServer(), GetSyncService(0)).Wait());
}
IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest, TimestampMatchesHistory) { IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest, TimestampMatchesHistory) {
ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
...@@ -284,7 +342,7 @@ IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest, ...@@ -284,7 +342,7 @@ IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest,
WaitForURLOnServer(base_url); WaitForURLOnServer(base_url);
GURL first_url = GURL(kURL2); GURL first_url = GURL(kURL2);
ASSERT_TRUE(NavigateTab(0, first_url)); NavigateTab(0, first_url);
WaitForURLOnServer(first_url); WaitForURLOnServer(first_url);
// Check that the navigation chain matches the above sequence of {base_url, // Check that the navigation chain matches the above sequence of {base_url,
...@@ -448,7 +506,7 @@ IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest, ...@@ -448,7 +506,7 @@ IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest,
// Trigger a sync and wait for it. // Trigger a sync and wait for it.
GURL url = GURL(kURL2); GURL url = GURL(kURL2);
ASSERT_TRUE(NavigateTab(0, url)); NavigateTab(0, url);
WaitForURLOnServer(url); WaitForURLOnServer(url);
// Verify the cookie jar mismatch bool is set to false. // Verify the cookie jar mismatch bool is set to false.
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
namespace { namespace {
using sessions_helper::CheckInitialState; using sessions_helper::CheckInitialState;
using sessions_helper::CloseTab;
using sessions_helper::DeleteForeignSession; using sessions_helper::DeleteForeignSession;
using sessions_helper::GetLocalWindows; using sessions_helper::GetLocalWindows;
using sessions_helper::GetSessionData; using sessions_helper::GetSessionData;
...@@ -75,6 +76,30 @@ IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, ...@@ -75,6 +76,30 @@ IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest,
WaitForForeignSessionsToSync(0, 1); WaitForForeignSessionsToSync(0, 1);
} }
IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, SingleClientClosed) {
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
// Open two tabs on client 0.
OpenTab(0, GURL(kURL1));
OpenTab(0, GURL(kURL2));
WaitForForeignSessionsToSync(0, 1);
// Close one of the two tabs. We also issue another navigation to make sure
// association logic kicks in.
CloseTab(/*index=*/0, /*tab_index=*/1);
NavigateTab(0, GURL(kURL3));
WaitForForeignSessionsToSync(0, 1);
std::vector<sync_pb::SyncEntity> entities =
GetFakeServer()->GetSyncEntitiesByModelType(syncer::SESSIONS);
// Two header entities and two tab entities (one of the two has been closed
// but considered "free" for future recycling, i.e. not deleted).
ASSERT_EQ(4U, entities.size());
for (const auto& entity : entities) {
EXPECT_FALSE(entity.deleted());
}
}
IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, E2E_ENABLED(AllChanged)) { IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, E2E_ENABLED(AllChanged)) {
ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
......
...@@ -932,12 +932,20 @@ TEST_F(SessionSyncBridgeTest, ShouldRestoreLocalSessionWithFreedTab) { ...@@ -932,12 +932,20 @@ TEST_F(SessionSyncBridgeTest, ShouldRestoreLocalSessionWithFreedTab) {
InitializeBridge(); InitializeBridge();
StartSyncing(); StartSyncing();
ASSERT_THAT(GetData(header_storage_key), // One tab node de should be free at this point. In the current implementation
EntityDataHasSpecifics( // (subject to change), this is |kTabNodeId1|. This is because |kTabId3| is
MatchesHeader(kLocalSessionTag, {kWindowId2}, {kTabId3}))); // assigned |kTabNodeId2|.
ASSERT_THAT(
GetAllData(),
UnorderedElementsAre(
Pair(header_storage_key,
EntityDataHasSpecifics(
MatchesHeader(kLocalSessionTag, {kWindowId2}, {kTabId3}))),
Pair(tab_storage_key2, EntityDataHasSpecifics(MatchesTab(
kLocalSessionTag, kWindowId2, kTabId3,
kTabNodeId2, {"http://qux.com/"})))));
// |kTabNodeId1| should be free at this point. When a new tab is opened // When a new tab is opened (|kTabId4|), |kTabNodeId1| should be reused.
// (|kTabId4|), it should be reused.
AddTab(kWindowId2, "http://quux.com/", kTabId4); AddTab(kWindowId2, "http://quux.com/", kTabId4);
EXPECT_THAT( EXPECT_THAT(
GetAllData(), GetAllData(),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment