 Chromium Code Reviews
 Chromium Code Reviews Issue 2753753005:
  [sync] WebContentsObserver based sessions notifications  (Closed)
    
  
    Issue 2753753005:
  [sync] WebContentsObserver based sessions notifications  (Closed) 
  | OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "chrome/browser/sync/test/integration/sessions_helper.h" | 5 #include "chrome/browser/sync/test/integration/sessions_helper.h" | 
| 6 | 6 | 
| 7 #include <stddef.h> | 7 #include <stddef.h> | 
| 8 | 8 | 
| 9 #include <set> | 9 #include <set> | 
| 10 #include <utility> | 10 #include <utility> | 
| 11 | 11 | 
| 12 #include "base/bind.h" | 12 #include "base/bind.h" | 
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" | 
| 14 #include "base/location.h" | 14 #include "base/location.h" | 
| 15 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" | 
| 16 #include "base/memory/weak_ptr.h" | 16 #include "base/memory/weak_ptr.h" | 
| 17 #include "base/single_thread_task_runner.h" | 17 #include "base/single_thread_task_runner.h" | 
| 18 #include "base/test/test_timeouts.h" | 18 #include "base/test/test_timeouts.h" | 
| 19 #include "base/threading/thread_task_runner_handle.h" | 19 #include "base/threading/thread_task_runner_handle.h" | 
| 20 #include "base/time/time.h" | 20 #include "base/time/time.h" | 
| 21 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" | 
| 22 #include "chrome/browser/sync/profile_sync_service_factory.h" | 22 #include "chrome/browser/sync/profile_sync_service_factory.h" | 
| 23 #include "chrome/browser/sync/sessions/notification_service_sessions_router.h" | |
| 24 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" | 23 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" | 
| 25 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h" | 24 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h" | 
| 26 #include "chrome/browser/ui/browser.h" | 25 #include "chrome/browser/ui/browser.h" | 
| 27 #include "chrome/browser/ui/browser_tabstrip.h" | 26 #include "chrome/browser/ui/browser_tabstrip.h" | 
| 28 #include "chrome/browser/ui/singleton_tabs.h" | 27 #include "chrome/browser/ui/singleton_tabs.h" | 
| 29 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 28 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 
| 30 #include "chrome/common/chrome_switches.h" | 29 #include "chrome/common/chrome_switches.h" | 
| 31 #include "chrome/test/base/ui_test_utils.h" | 30 #include "chrome/test/base/ui_test_utils.h" | 
| 32 #include "components/browser_sync/profile_sync_service.h" | 31 #include "components/browser_sync/profile_sync_service.h" | 
| 33 #include "components/sync/driver/sync_client.h" | 32 #include "components/sync/driver/sync_client.h" | 
| 34 #include "components/sync/test/fake_server/fake_server.h" | 33 #include "components/sync/test/fake_server/fake_server.h" | 
| 35 #include "components/sync/test/fake_server/sessions_hierarchy.h" | 34 #include "components/sync/test/fake_server/sessions_hierarchy.h" | 
| 36 #include "components/sync_sessions/open_tabs_ui_delegate.h" | 35 #include "components/sync_sessions/open_tabs_ui_delegate.h" | 
| 37 #include "content/public/browser/navigation_entry.h" | 36 #include "content/public/browser/navigation_entry.h" | 
| 37 #include "content/public/browser/render_frame_host.h" | |
| 38 #include "content/public/browser/render_process_host.h" | |
| 38 #include "content/public/browser/web_contents.h" | 39 #include "content/public/browser/web_contents.h" | 
| 40 #include "content/public/test/browser_test_utils.cc" | |
| 39 #include "content/public/test/test_utils.h" | 41 #include "content/public/test/test_utils.h" | 
| 40 #include "url/gurl.h" | 42 #include "url/gurl.h" | 
| 41 | 43 | 
| 42 using sync_datatype_helper::test; | 44 using sync_datatype_helper::test; | 
| 43 | 45 | 
| 44 namespace sessions_helper { | 46 namespace sessions_helper { | 
| 45 | 47 | 
| 46 bool GetLocalSession(int index, const sync_sessions::SyncedSession** session) { | 48 bool GetLocalSession(int index, const sync_sessions::SyncedSession** session) { | 
| 47 return ProfileSyncServiceFactory::GetInstance() | 49 return ProfileSyncServiceFactory::GetInstance() | 
| 48 ->GetForProfile(test()->GetProfile(index)) | 50 ->GetForProfile(test()->GetProfile(index)) | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 94 } | 96 } | 
| 95 | 97 | 
| 96 bool OpenTab(int index, const GURL& url) { | 98 bool OpenTab(int index, const GURL& url) { | 
| 97 DVLOG(1) << "Opening tab: " << url.spec() << " using browser " << index | 99 DVLOG(1) << "Opening tab: " << url.spec() << " using browser " << index | 
| 98 << "."; | 100 << "."; | 
| 99 return OpenTabAtIndex(index, 0, url); | 101 return OpenTabAtIndex(index, 0, url); | 
| 100 } | 102 } | 
| 101 | 103 | 
| 102 bool OpenTabAtIndex(int index, int tab_index, const GURL& url) { | 104 bool OpenTabAtIndex(int index, int tab_index, const GURL& url) { | 
| 103 chrome::AddTabAt(test()->GetBrowser(index), url, tab_index, true); | 105 chrome::AddTabAt(test()->GetBrowser(index), url, tab_index, true); | 
| 104 return WaitForTabsToLoad(index, {url}); | 106 return WaitForTabToLoad( | 
| 107 index, url, | |
| 108 test()->GetBrowser(index)->tab_strip_model()->GetWebContentsAt( | |
| 109 tab_index)); | |
| 105 } | 110 } | 
| 106 | 111 | 
| 107 bool OpenMultipleTabs(int index, const std::vector<GURL>& urls) { | 112 bool OpenMultipleTabs(int index, const std::vector<GURL>& urls) { | 
| 108 Browser* browser = test()->GetBrowser(index); | 113 Browser* browser = test()->GetBrowser(index); | 
| 109 for (std::vector<GURL>::const_iterator it = urls.begin(); | 114 for (std::vector<GURL>::const_iterator it = urls.begin(); | 
| 110 it != urls.end(); ++it) { | 115 it != urls.end(); ++it) { | 
| 111 DVLOG(1) << "Opening tab: " << it->spec() << " using browser " << index | 116 DVLOG(1) << "Opening tab: " << it->spec() << " using browser " << index | 
| 112 << "."; | 117 << "."; | 
| 113 chrome::ShowSingletonTab(browser, *it); | 118 chrome::ShowSingletonTab(browser, *it); | 
| 114 } | 119 } | 
| 115 return WaitForTabsToLoad(index, urls); | 120 return WaitForTabsToLoad(index, urls); | 
| 116 } | 121 } | 
| 117 | 122 | 
| 123 bool OpenTabFromSourceIndex(int index, | |
| 124 int index_of_source_tab, | |
| 125 const GURL& url, | |
| 126 WindowOpenDisposition disposition) { | |
| 127 content::WebContents* source_contents = | |
| 128 test()->GetBrowser(index)->tab_strip_model()->GetWebContentsAt( | |
| 129 index_of_source_tab); | |
| 130 | |
| 131 content::OpenURLParams open_url_params(url, content::Referrer(), disposition, | |
| 132 ui::PAGE_TRANSITION_LINK, false, | |
| 133 false); | |
| 134 open_url_params.source_render_frame_id = | |
| 135 source_contents->GetMainFrame()->GetRoutingID(); | |
| 136 open_url_params.source_render_process_id = | |
| 137 source_contents->GetRenderProcessHost()->GetID(); | |
| 138 | |
| 139 content::WebContents* new_contents = | |
| 140 source_contents->OpenURL(open_url_params); | |
| 141 if (!new_contents) { | |
| 142 return false; | |
| 143 } | |
| 144 | |
| 145 return WaitForTabToLoad(index, url, new_contents); | |
| 146 } | |
| 147 | |
| 118 void MoveTab(int from_index, int to_index, int tab_index) { | 148 void MoveTab(int from_index, int to_index, int tab_index) { | 
| 119 content::WebContents* detached_contents = | 149 content::WebContents* detached_contents = | 
| 120 test() | 150 test() | 
| 121 ->GetBrowser(from_index) | 151 ->GetBrowser(from_index) | 
| 122 ->tab_strip_model() | 152 ->tab_strip_model() | 
| 123 ->DetachWebContentsAt(tab_index); | 153 ->DetachWebContentsAt(tab_index); | 
| 124 | 154 | 
| 125 TabStripModel* target_strip = test()->GetBrowser(to_index)->tab_strip_model(); | 155 TabStripModel* target_strip = test()->GetBrowser(to_index)->tab_strip_model(); | 
| 126 target_strip->InsertWebContentsAt(target_strip->count(), detached_contents, | 156 target_strip->InsertWebContentsAt(target_strip->count(), detached_contents, | 
| 127 TabStripModel::ADD_ACTIVE); | 157 TabStripModel::ADD_ACTIVE); | 
| 128 } | 158 } | 
| 129 | 159 | 
| 130 bool NavigateTab(int index, const GURL& url) { | 160 bool NavigateTab(int index, const GURL& url) { | 
| 131 chrome::NavigateParams params(test()->GetBrowser(index), url, | 161 chrome::NavigateParams params(test()->GetBrowser(index), url, | 
| 132 ui::PAGE_TRANSITION_LINK); | 162 ui::PAGE_TRANSITION_LINK); | 
| 133 params.disposition = WindowOpenDisposition::CURRENT_TAB; | 163 params.disposition = WindowOpenDisposition::CURRENT_TAB; | 
| 134 | 164 | 
| 135 ui_test_utils::NavigateToURL(¶ms); | 165 ui_test_utils::NavigateToURL(¶ms); | 
| 136 return WaitForTabsToLoad(index, {url}); | 166 return WaitForTabToLoad(index, url, params.target_contents); | 
| 137 } | 167 } | 
| 138 | 168 | 
| 139 void NavigateTabBack(int index) { | 169 void NavigateTabBack(int index) { | 
| 140 test() | 170 test() | 
| 141 ->GetBrowser(index) | 171 ->GetBrowser(index) | 
| 142 ->tab_strip_model() | 172 ->tab_strip_model() | 
| 143 ->GetWebContentsAt(0) | 173 ->GetWebContentsAt(0) | 
| 144 ->GetController() | 174 ->GetController() | 
| 145 .GoBack(); | 175 .GoBack(); | 
| 146 } | 176 } | 
| 147 | 177 | 
| 148 void NavigateTabForward(int index) { | 178 void NavigateTabForward(int index) { | 
| 149 test() | 179 test() | 
| 150 ->GetBrowser(index) | 180 ->GetBrowser(index) | 
| 151 ->tab_strip_model() | 181 ->tab_strip_model() | 
| 152 ->GetWebContentsAt(0) | 182 ->GetWebContentsAt(0) | 
| 153 ->GetController() | 183 ->GetController() | 
| 154 .GoForward(); | 184 .GoForward(); | 
| 155 } | 185 } | 
| 156 | 186 | 
| 157 namespace { | 187 bool WaitForTabsToLoad(int index, const std::vector<GURL>& urls) { | 
| 188 int tab_index = 0; | |
| 189 for (const auto& url : urls) { | |
| 190 bool success = WaitForTabToLoad( | |
| 191 index, url, | |
| 192 test()->GetBrowser(index)->tab_strip_model()->GetWebContentsAt( | |
| 193 tab_index)); | |
| 194 if (!success) { | |
| 195 return false; | |
| 196 } | |
| 197 tab_index++; | |
| 198 } | |
| 199 return true; | |
| 200 } | |
| 158 | 201 | 
| 159 class TabEventHandler : public sync_sessions::LocalSessionEventHandler { | 202 bool WaitForTabToLoad(int index, | 
| 160 public: | 203 const GURL& url, | 
| 161 TabEventHandler() : weak_factory_(this) { | 204 content::WebContents* web_contents) { | 
| 162 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 163 FROM_HERE, | |
| 164 base::Bind(&TabEventHandler::QuitLoop, weak_factory_.GetWeakPtr()), | |
| 165 TestTimeouts::action_max_timeout()); | |
| 166 } | |
| 167 | |
| 168 void OnLocalTabModified( | |
| 169 sync_sessions::SyncedTabDelegate* modified_tab) override { | |
| 170 // Unwind to ensure SessionsSyncManager has processed the event. | |
| 171 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 172 FROM_HERE, | |
| 173 base::Bind(&TabEventHandler::QuitLoop, weak_factory_.GetWeakPtr())); | |
| 174 } | |
| 175 | |
| 176 void OnFaviconsChanged(const std::set<GURL>& /* page_urls */, | |
| 177 const GURL& /* icon_url */) override { | |
| 178 // Unwind to ensure SessionsSyncManager has processed the event. | |
| 179 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 180 FROM_HERE, | |
| 181 base::Bind(&TabEventHandler::QuitLoop, weak_factory_.GetWeakPtr())); | |
| 182 } | |
| 183 | |
| 184 private: | |
| 185 void QuitLoop() { base::MessageLoop::current()->QuitWhenIdle(); } | |
| 186 | |
| 187 base::WeakPtrFactory<TabEventHandler> weak_factory_; | |
| 188 }; | |
| 189 | |
| 190 } // namespace | |
| 191 | |
| 192 bool WaitForTabsToLoad(int index, const std::vector<GURL>& urls) { | |
| 193 DVLOG(1) << "Waiting for session to propagate to associator."; | 205 DVLOG(1) << "Waiting for session to propagate to associator."; | 
| 194 base::TimeTicks start_time = base::TimeTicks::Now(); | 206 base::TimeTicks start_time = base::TimeTicks::Now(); | 
| 195 base::TimeTicks end_time = start_time + TestTimeouts::action_max_timeout(); | 207 base::TimeTicks end_time = start_time + TestTimeouts::action_max_timeout(); | 
| 196 bool found; | 208 bool found = false; | 
| 197 for (std::vector<GURL>::const_iterator it = urls.begin(); | 209 while (!found) { | 
| 198 it != urls.end(); ++it) { | 210 found = ModelAssociatorHasTabWithUrl(index, url); | 
| 
Nicolas Zea
2017/03/20 18:14:50
nit: SyncableServiceHasTabWithURL (or perhaps Sync
 
Patrick Noland
2017/03/21 22:54:31
Done.
 | |
| 199 found = false; | 211 if (base::TimeTicks::Now() >= end_time) { | 
| 200 while (!found) { | 212 LOG(ERROR) << "Failed to find url " << url.spec() << " in tab after " | 
| 201 found = ModelAssociatorHasTabWithUrl(index, *it); | 213 << TestTimeouts::action_max_timeout().InSecondsF() | 
| 202 if (base::TimeTicks::Now() >= end_time) { | 214 << " seconds."; | 
| 203 LOG(ERROR) << "Failed to find all tabs after " | 215 return false; | 
| 204 << TestTimeouts::action_max_timeout().InSecondsF() | 216 } | 
| 205 << " seconds."; | 217 if (!found) { | 
| 206 return false; | 218 content::WaitForLoadStop(web_contents); | 
| 207 } | |
| 208 if (!found) { | |
| 209 TabEventHandler handler; | |
| 210 sync_sessions::NotificationServiceSessionsRouter router( | |
| 211 test()->GetProfile(index), | |
| 212 ProfileSyncServiceFactory::GetInstance() | |
| 213 ->GetForProfile(test()->GetProfile(index)) | |
| 214 ->GetSyncClient() | |
| 215 ->GetSyncSessionsClient(), | |
| 216 syncer::SyncableService::StartSyncFlare()); | |
| 217 router.StartRoutingTo(&handler); | |
| 218 content::RunMessageLoop(); | |
| 219 } | |
| 220 } | 219 } | 
| 221 } | 220 } | 
| 222 return true; | 221 return true; | 
| 223 } | 222 } | 
| 224 | 223 | 
| 225 bool GetLocalWindows(int index, ScopedWindowMap* local_windows) { | 224 bool GetLocalWindows(int index, ScopedWindowMap* local_windows) { | 
| 226 // The local session provided by GetLocalSession is owned, and has lifetime | 225 // The local session provided by GetLocalSession is owned, and has lifetime | 
| 227 // controlled, by the model associator, so we must make our own copy. | 226 // controlled, by the model associator, so we must make our own copy. | 
| 
Nicolas Zea
2017/03/20 18:14:50
nit: model associator -> SyncableService (may as w
 
Patrick Noland
2017/03/21 22:54:31
Done.
 | |
| 228 const sync_sessions::SyncedSession* local_session; | 227 const sync_sessions::SyncedSession* local_session; | 
| 229 if (!GetLocalSession(index, &local_session)) { | 228 if (!GetLocalSession(index, &local_session)) { | 
| 230 return false; | 229 return false; | 
| 231 } | 230 } | 
| 232 for (auto w = local_session->windows.begin(); | 231 for (auto w = local_session->windows.begin(); | 
| 233 w != local_session->windows.end(); ++w) { | 232 w != local_session->windows.end(); ++w) { | 
| 234 const sessions::SessionWindow& window = *(w->second); | 233 const sessions::SessionWindow& window = *(w->second); | 
| 235 std::unique_ptr<sessions::SessionWindow> new_window = | 234 std::unique_ptr<sessions::SessionWindow> new_window = | 
| 236 base::MakeUnique<sessions::SessionWindow>(); | 235 base::MakeUnique<sessions::SessionWindow>(); | 
| 237 new_window->window_id.set_id(window.window_id.id()); | 236 new_window->window_id.set_id(window.window_id.id()); | 
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 436 index_(index), | 435 index_(index), | 
| 437 windows_(windows) {} | 436 windows_(windows) {} | 
| 438 | 437 | 
| 439 bool ForeignSessionsMatchChecker::IsExitConditionSatisfied() { | 438 bool ForeignSessionsMatchChecker::IsExitConditionSatisfied() { | 
| 440 return sessions_helper::CheckForeignSessionsAgainst(index_, windows_); | 439 return sessions_helper::CheckForeignSessionsAgainst(index_, windows_); | 
| 441 } | 440 } | 
| 442 | 441 | 
| 443 std::string ForeignSessionsMatchChecker::GetDebugMessage() const { | 442 std::string ForeignSessionsMatchChecker::GetDebugMessage() const { | 
| 444 return "Waiting for matching foreign sessions"; | 443 return "Waiting for matching foreign sessions"; | 
| 445 } | 444 } | 
| OLD | NEW |