1// Copyright 2016 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#import "ios/chrome/test/app/tab_test_util.h" 6 7#import <Foundation/Foundation.h> 8 9#import "base/mac/foundation_util.h" 10#import "ios/chrome/app/main_controller_private.h" 11#include "ios/chrome/browser/chrome_url_constants.h" 12#import "ios/chrome/browser/main/browser.h" 13#import "ios/chrome/browser/metrics/tab_usage_recorder_browser_agent.h" 14#import "ios/chrome/browser/sessions/session_restoration_browser_agent.h" 15#include "ios/chrome/browser/system_flags.h" 16#import "ios/chrome/browser/tabs/tab_title_util.h" 17#import "ios/chrome/browser/ui/commands/browser_commands.h" 18#import "ios/chrome/browser/ui/commands/open_new_tab_command.h" 19#import "ios/chrome/browser/ui/main/scene_controller.h" 20#import "ios/chrome/browser/ui/main/scene_controller_testing.h" 21#import "ios/chrome/browser/url_loading/url_loading_params.h" 22#import "ios/chrome/browser/web_state_list/web_state_list.h" 23#import "ios/chrome/browser/web_state_list/web_usage_enabler/web_usage_enabler_browser_agent.h" 24#import "ios/chrome/test/app/chrome_test_util.h" 25 26#if !defined(__has_feature) || !__has_feature(objc_arc) 27#error "This file requires ARC support." 28#endif 29 30namespace chrome_test_util { 31 32namespace { 33 34// Returns the browser for the current mode. 35Browser* GetCurrentBrowser() { 36 return GetMainController().interfaceProvider.currentInterface.browser; 37} 38 39// Returns the WebStateList for the current mode. Or nullptr of there is no 40// browser. 41WebStateList* GetCurrentWebStateList() { 42 Browser* browser = GetCurrentBrowser(); 43 return browser ? browser->GetWebStateList() : nullptr; 44} 45 46} // namespace 47 48BOOL IsIncognitoMode() { 49 return GetMainController().interfaceProvider.currentInterface.incognito; 50} 51 52void OpenNewTab() { 53 @autoreleasepool { // Make sure that all internals are deallocated. 54 OpenNewTabCommand* command = [OpenNewTabCommand command]; 55 if (GetForegroundActiveSceneController().isTabSwitcherActive) { 56 // The TabGrid is currently presented. 57 Browser* browser = 58 GetForegroundActiveScene().interfaceProvider.mainInterface.browser; 59 UrlLoadParams params = UrlLoadParams::InNewTab(GURL(kChromeUINewTabURL)); 60 [GetForegroundActiveSceneController() addANewTabAndPresentBrowser:browser 61 withURLLoadParams:params]; 62 return; 63 } 64 id<ApplicationCommands, BrowserCommands> handler = 65 chrome_test_util::HandlerForActiveBrowser(); 66 [handler openURLInNewTab:command]; 67 } 68} 69 70NSURL* SimulateExternalAppURLOpening() { 71 NSURL* url = [NSURL URLWithString:@"http://www.example.com"]; 72 UIApplication* application = UIApplication.sharedApplication; 73 id<UIApplicationDelegate> applicationDelegate = application.delegate; 74 [applicationDelegate application:application openURL:url options:@{}]; 75 return url; 76} 77 78void SimulateAddAccountFromWeb() { 79 id<ApplicationCommands, BrowserCommands> handler = 80 chrome_test_util::HandlerForActiveBrowser(); 81 [handler showAddAccountFromViewController:(UIViewController*) 82 GetForegroundActiveScene() 83 .interfaceProvider 84 .mainInterface.bvc]; 85} 86 87void OpenNewIncognitoTab() { 88 @autoreleasepool { // Make sure that all internals are deallocated. 89 OpenNewTabCommand* command = [OpenNewTabCommand incognitoTabCommand]; 90 if (GetForegroundActiveSceneController().isTabSwitcherActive) { 91 // The TabGrid is currently presented. 92 Browser* browser = GetForegroundActiveScene() 93 .interfaceProvider.incognitoInterface.browser; 94 UrlLoadParams params = UrlLoadParams::InNewTab(GURL(kChromeUINewTabURL)); 95 [GetForegroundActiveSceneController() addANewTabAndPresentBrowser:browser 96 withURLLoadParams:params]; 97 return; 98 } 99 id<ApplicationCommands, BrowserCommands> handler = 100 chrome_test_util::HandlerForActiveBrowser(); 101 [handler openURLInNewTab:command]; 102 } 103} 104 105web::WebState* GetCurrentWebState() { 106 WebStateList* web_state_list = GetCurrentWebStateList(); 107 return web_state_list ? web_state_list->GetActiveWebState() : nullptr; 108} 109 110web::WebState* GetNextWebState() { 111 WebStateList* web_state_list = GetCurrentWebStateList(); 112 if (!web_state_list || web_state_list->count() < 2) 113 return nullptr; 114 int next_index = web_state_list->active_index() + 1; 115 if (next_index >= web_state_list->count()) 116 next_index = 0; 117 return web_state_list->GetWebStateAt(next_index); 118} 119 120web::WebState* GetWebStateAtIndexInCurrentMode(int index) { 121 WebStateList* web_state_list = GetCurrentWebStateList(); 122 if (!web_state_list || !web_state_list->ContainsIndex(index)) 123 return nullptr; 124 return web_state_list->GetWebStateAt(index); 125} 126 127NSString* GetCurrentTabTitle() { 128 return tab_util::GetTabTitle(GetCurrentWebState()); 129} 130 131NSString* GetNextTabTitle() { 132 return tab_util::GetTabTitle(GetNextWebState()); 133} 134 135void CloseCurrentTab() { 136 WebStateList* web_state_list = GetCurrentWebStateList(); 137 if (!web_state_list || 138 web_state_list->active_index() == WebStateList::kInvalidIndex) 139 return; 140 web_state_list->CloseWebStateAt(web_state_list->active_index(), 141 WebStateList::CLOSE_USER_ACTION); 142} 143 144void CloseTabAtIndex(NSUInteger index) { 145 @autoreleasepool { // Make sure that all internals are deallocated. 146 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); 147 GetCurrentWebStateList()->CloseWebStateAt(static_cast<int>(index), 148 WebStateList::CLOSE_USER_ACTION); 149 } 150} 151 152NSUInteger GetIndexOfActiveNormalTab() { 153 Browser* browser = chrome_test_util::GetForegroundActiveSceneController() 154 .interfaceProvider.mainInterface.browser; 155 return browser->GetWebStateList()->active_index(); 156} 157 158void CloseAllTabsInCurrentMode() { 159 GetCurrentWebStateList()->CloseAllWebStates(WebStateList::CLOSE_USER_ACTION); 160} 161 162void CloseAllTabs() { 163 if (GetIncognitoTabCount() && GetForegroundActiveSceneController()) { 164 Browser* browser = GetForegroundActiveSceneController() 165 .interfaceProvider.incognitoInterface.browser; 166 DCHECK(browser); 167 browser->GetWebStateList()->CloseAllWebStates( 168 WebStateList::CLOSE_USER_ACTION); 169 } 170 if (GetMainTabCount() && GetForegroundActiveScene()) { 171 Browser* browser = 172 GetForegroundActiveScene().interfaceProvider.mainInterface.browser; 173 DCHECK(browser); 174 browser->GetWebStateList()->CloseAllWebStates( 175 WebStateList::CLOSE_USER_ACTION); 176 } 177} 178 179void SelectTabAtIndexInCurrentMode(NSUInteger index) { 180 @autoreleasepool { // Make sure that all internals are deallocated. 181 182 WebStateList* web_state_list = GetCurrentWebStateList(); 183 web_state_list->ActivateWebStateAt(static_cast<int>(index)); 184 } 185} 186 187NSUInteger GetMainTabCount() { 188 return GetMainController() 189 .interfaceProvider.mainInterface.browser->GetWebStateList() 190 ->count(); 191} 192 193NSUInteger GetIncognitoTabCount() { 194 return GetMainController() 195 .interfaceProvider.incognitoInterface.browser->GetWebStateList() 196 ->count(); 197} 198 199BOOL ResetTabUsageRecorder() { 200 TabUsageRecorderBrowserAgent* tab_usage_recorder = 201 TabUsageRecorderBrowserAgent::FromBrowser(GetCurrentBrowser()); 202 if (!tab_usage_recorder) 203 return NO; 204 tab_usage_recorder->ResetAll(); 205 return YES; 206} 207 208BOOL SetCurrentTabsToBeColdStartTabs() { 209 TabUsageRecorderBrowserAgent* tab_usage_recorder = 210 TabUsageRecorderBrowserAgent::FromBrowser(GetCurrentBrowser()); 211 212 if (!tab_usage_recorder) 213 return NO; 214 WebStateList* web_state_list = GetCurrentWebStateList(); 215 216 std::vector<web::WebState*> web_states; 217 web_states.reserve(web_state_list->count()); 218 for (int index = 0; index < web_state_list->count(); ++index) { 219 web_states.push_back(web_state_list->GetWebStateAt(index)); 220 } 221 tab_usage_recorder->InitialRestoredTabs(web_state_list->GetActiveWebState(), 222 web_states); 223 return YES; 224} 225 226BOOL SimulateTabsBackgrounding() { 227 TabUsageRecorderBrowserAgent* tab_usage_recorder = 228 TabUsageRecorderBrowserAgent::FromBrowser(GetCurrentBrowser()); 229 if (!tab_usage_recorder) 230 return NO; 231 tab_usage_recorder->AppDidEnterBackground(); 232 return YES; 233} 234 235void SaveSessionImmediately() { 236 SessionRestorationBrowserAgent::FromBrowser(GetCurrentBrowser()) 237 ->SaveSession(true); 238} 239 240void EvictOtherTabModelTabs() { 241 id<BrowserInterfaceProvider> provider = GetMainController().interfaceProvider; 242 Browser* otherBrowser = IsIncognitoMode() 243 ? provider.mainInterface.browser 244 : provider.incognitoInterface.browser; 245 // Disabling and enabling web usage will evict all web views. 246 WebUsageEnablerBrowserAgent* enabler = 247 WebUsageEnablerBrowserAgent::FromBrowser(otherBrowser); 248 DCHECK(enabler); 249 enabler->SetWebUsageEnabled(false); 250 enabler->SetWebUsageEnabled(true); 251} 252 253BOOL CloseAllNormalTabs() { 254 MainController* main_controller = GetMainController(); 255 DCHECK(main_controller); 256 257 Browser* browser = main_controller.interfaceProvider.mainInterface.browser; 258 DCHECK(browser); 259 browser->GetWebStateList()->CloseAllWebStates( 260 WebStateList::CLOSE_USER_ACTION); 261 return YES; 262} 263 264BOOL CloseAllIncognitoTabs() { 265 MainController* main_controller = GetMainController(); 266 DCHECK(main_controller); 267 Browser* browser = 268 GetMainController().interfaceProvider.incognitoInterface.browser; 269 DCHECK(browser); 270 browser->GetWebStateList()->CloseAllWebStates( 271 WebStateList::CLOSE_USER_ACTION); 272 return YES; 273} 274 275NSUInteger GetEvictedMainTabCount() { 276 Browser* browser = 277 GetMainController().interfaceProvider.mainInterface.browser; 278 TabUsageRecorderBrowserAgent* tab_usage_recorder = 279 TabUsageRecorderBrowserAgent::FromBrowser(browser); 280 if (!tab_usage_recorder) 281 return 0; 282 return tab_usage_recorder->EvictedTabsMapSize(); 283} 284 285} // namespace chrome_test_util 286