helpers.py (3620B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 """ Helpers to build scenarii 5 """ 6 from condprof.util import logger 7 8 _SUPPORTED_MOBILE_BROWSERS = "fenix", "gecko", "firefox" 9 10 11 def is_mobile(platform): 12 return any(mobile in platform for mobile in _SUPPORTED_MOBILE_BROWSERS) 13 14 15 class TabSwitcher: 16 """Helper used to create tabs and circulate in them.""" 17 18 def __init__(self, session, options): 19 self.handles = None 20 self.current = 0 21 self.session = session 22 self._max = options.get("max_urls", 10) 23 self.platform = options.get("platform", "") 24 self.num_tabs = self._max >= 100 and 100 or self._max 25 self._mobile = is_mobile(self.platform) 26 27 async def create_windows(self): 28 # on mobile we don't use tabs for now 29 # see https://bugzil.la/1559120 30 if self._mobile: 31 return 32 # creating tabs 33 for i in range(self.num_tabs): 34 # see https://github.com/HDE/arsenic/issues/71 35 await self.session._request( 36 url="/window/new", method="POST", data={"type": "tab"} 37 ) 38 39 async def switch(self): 40 if self._mobile: 41 return 42 try: 43 if self.handles is None: 44 self.handles = await self.session.get_window_handles() 45 self.current = 0 46 except Exception: 47 logger.error("Could not get window handles") 48 return 49 50 handle = self.handles[self.current] 51 if self.current == len(self.handles) - 1: 52 self.current = 0 53 else: 54 self.current += 1 55 try: 56 await self.session.switch_to_window(handle) 57 except Exception: 58 logger.error("Could not switch to handle %s" % str(handle)) 59 60 61 # 10 minutes 62 _SCRIPT_TIMEOUT = 10 * 60 * 1000 63 64 65 async def execute_async_script(session, script, *args): 66 # switch to the right context if needed 67 current_context = await session._request(url="/moz/context", method="GET") 68 if current_context != "chrome": 69 await session._request( 70 url="/moz/context", method="POST", data={"context": "chrome"} 71 ) 72 switch_back = True 73 else: 74 switch_back = False 75 await session._request( 76 url="/timeouts", method="POST", data={"script": _SCRIPT_TIMEOUT} 77 ) 78 try: 79 attempts = 0 80 while True: 81 try: 82 return await session._request( 83 url="/execute/async", 84 method="POST", 85 data={"script": script, "args": list(args)}, 86 ) 87 except Exception as e: 88 attempts += 1 89 logger.error("The script failed.", exc_info=True) 90 if attempts > 2: 91 return { 92 "result": 1, 93 "result_message": str(e), 94 "result_exc": e, 95 "logs": {}, 96 } 97 finally: 98 if switch_back: 99 await session._request( 100 url="/moz/context", method="POST", data={"context": current_context} 101 ) 102 103 104 async def close_extra_windows(session): 105 logger.info("Closing all tabs") 106 handles = await session.get_window_handles() 107 # we're closing all tabs except the last one 108 for handle in handles[:-1]: 109 await session.switch_to_window(handle) 110 await session._request(url="/window", method="DELETE")