Example #1
0
def get_api(settings: Settings):
    """
    Fetch API-Instance from settings object, automatically requests new session

    :param settings: Settings object, will be modified if no session is active
    """
    if settings.identity is None:
        # create new identity
        if settings.security_key is None:
            # No security key, no api instance
            return None
        settings.identity = uuid.uuid4().hex
        api_factory = APIFactory(host=settings.gateway_ip,
                                 psk_id=settings.identity)
        settings.key = api_factory.generate_psk(settings.security_key)
        settings.save()
        return api_factory.request

    api_factory = APIFactory(host=settings.gateway_ip,
                             psk_id=settings.identity,
                             psk=settings.key)
    return api_factory.request
Example #2
0
class WebBrowser(QObject):
    dic_url = {'SWGS': 'http://172.31.196.21:8060/websquare/websquare.html?w2xPath=/SWING/lib/xml/ZLIBSMAN90010.xml&coClCd=T&svrLocation=SWGS'}
    browser_log = []
    requestList = []
    eventList = []
    browser_log_hst = []

    HOME = os.path.expanduser("~")
    SAVE_PATH = os.path.join(HOME, 'Test_Tool')
    HOME_SAVE_PATH = os.path.join(HOME, '.test_tool')

    def __init__(self, sid, url='', websocket_server=None):
        QObject.__init__(self)
        self.sid = sid
        self.url = url
        self.driver = None
        self.recorder = None
        self.requestList = []
        self.eventList = []
        self.browser_log = []
        self.browser_log_hst = []

        self.chromedriver_version = ''

        self.recording = False
        self.web_iframe_list = []

        # Load setting in the main thread
        self.settings = Settings(self.HOME_SAVE_PATH)
        self.settings.load()
        self.settings.save()

        self._loadSetting()

        self.config = Config()
        self.paths = [r"C:\Program Files\Google\Chrome\Application\chrome.exe",
                        r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"]
        self.paths.extend(self.config.getlist("section_browser", "BROWSER_PATH"))

        self.browser_version = self.config.get('section_browser', 'BROWSER_VER')

        if self.sid in self.dic_url.keys():
            print(self.dic_url[self.sid])
        elif self.sid == 'URL':
            print(self.url)
            self.dic_url[self.sid] = self.url
        else:
            print('미존재 SID')

        self.websocket_server = websocket_server
        self.websocket_server.receivedSignal.connect(self.websocketSeverReceived)


    def _loadSetting(self):
        '''
        설정값으로 재설정
        :return: None
        '''
        self.getDriverVersion()


    def getDriverVersion(self):
        self.settings.load()
        self.chromedriver_version = self.settings.get("CHROMEDRIVER_VERSION", "")


    def getVersionViaCom(self):
        version_info = []
        paths = self.paths

        try:
            parser = Dispatch("Scripting.FileSystemObject")
        except:
            if self.browser_version:
                result_verion= self.browser_version
            else:
                result_verion = ''
            return result_verion

        for file_name in paths:
            try:
                version = parser.GetFileVersion(file_name)
                version_info.append(version)
            except:
                pass
        try:
            result_verion = version_info[0].split('.')[0]
        except:
            result_verion = ''
        return result_verion


    def processBrowserLogEntry(self, entry):
        response = json.loads(entry['message'])['message']
        return response


    def findEventLog(self, type, evets):
        requestList = []

        xhr_events = [event for event in evets if 'type' in event['params'].keys() and event['params']['type'] == type]
        xhr_events = [event for event in xhr_events if event['params']['request']['method'] == 'POST' and 'postData' in event['params']['request'].keys()]

        #print('==== XHR List ====')
        for idx, xhr in enumerate(xhr_events):
            post_data = xhr['params']['request']['postData']

            try:
                trx_code = json.loads(post_data)['HEAD']['Trx_Code']
            except json.JSONDecodeError as e:
                print(e)
                print(post_data)

            request_id = xhr['params']['requestId']
            #print('{index} - {trxCode} - {requestId}'.format(index=idx, trxCode=trx_code, requestId=request_id))

            inputData = {}
            outputData = {}

            # request결과가 없는 경우가 있음 (ZNGMSATH10060_TR03) 결과가 없으면 제외

            try:
                inputData = json.loads(self.driver.execute_cdp_cmd('Network.getRequestPostData', {'requestId': str(request_id)})['postData'])
                outputData = json.loads(self.driver.execute_cdp_cmd('Network.getResponseBody', {'requestId': str(request_id)})['body'])

                if 'dataInfo' not in list(outputData.keys()):
                    outputData = makeDataInfo(outputData)

                requestDtl = {'trx_code': trx_code,
                              'request_id': request_id,
                              'input_data': inputData,
                              'output_data': outputData}

                requestList.append(requestDtl)
            except:
                pass

        return requestList


    def getInputDataset(self, events, idx):
        return json.loads(events[idx]['params']['request']['postData'])

    def popUp(self):
        version = self.getVersionViaCom()
        chromedriver_path = os.path.join(self.SAVE_PATH, 'chromedriver.exe')

        self.getDriverVersion()

        if not os.path.exists(chromedriver_path):
            print('chromedriver 파일 미존재 - 생성....')
            self.downloadChromedriver(version, chromedriver_path)
        elif version == self.chromedriver_version:
            print('동일한 Chrome / chromedriver 버전 - [{}]'.format(version))
        else:
            print('Chrome [{chrome_version}] / chromedriver [{chromedriver_version}] 버전이 다른 경우'.format(chrome_version=version, chromedriver_version=self.chromedriver_version))
            self.downloadChromedriver(version, chromedriver_path)

        self.web_iframe_list = []

        chrome_options = Options()
        #chrome_options.add_argument("start-maximized")
        chrome_options.add_argument("disable-infobars")
        chrome_options.add_argument("--disable-extensions")
        chrome_options.add_argument("--no-sandbox")
        chrome_options.add_argument("--disable-gpu")
        chrome_options.add_argument("window-size=1920x1080")  # 가져올 크기를 결정
        chrome_options.set_capability('unhandledPromptBehavior', 'accept')

        caps = DesiredCapabilities.CHROME
        caps['goog:loggingPrefs'] = {'performance': 'ALL'}

        if self.driver and self.getStatus():
            pass
        else:
            # 드라이버 객체 생성
            self.driver = webdriver.Chrome(chromedriver_path, chrome_options=chrome_options, desired_capabilities=caps)

        #self.driver.implicitly_wait(3)  # 드라이버 초기화를 위해 3초 대기
        self.get()

    def get(self):
        self.driver.get(self.dic_url[self.sid])

        if self.sid == 'SWGS':
            try:
                self.driver.switch_to_alert()
                alert = WebDriverWait(self.driver, 1).until(EC.alert_is_present())
                alert.accept()
            except NoAlertPresentException:
                pass
            finally:
                while True:
                    try:
                        WebDriverWait(self.driver, 0).until(EC.element_to_be_clickable((By.ID, 'bodyBlock')))
                    except:
                        break

                try:
                    WebDriverWait(self.driver, 60).until(EC.presence_of_element_located((By.ID, 'mdi01_subWindow0_iframe')))
                finally:
                    print('Page is ready!')
                    self.driver.execute_script('''top.document.title = "(FOR AUTO TEST TOOL)"''')
                    # Recorder 선언
                    self.recorder = Recorder(self.driver)
                    self.recorder.addEventListener()
                    #threading.Timer(3, self.getBrowserEvents).start()

    def getRequest(self):
        try:
            self.driver.switch_to_alert()
        except NoAlertPresentException:
            log = self.driver.get_log('performance')
            self.browser_log.extend(log)
            self.browser_log_hst.extend(log)
            events = [self.processBrowserLogEntry(entry) for entry in self.browser_log]

            # response_events = [event for event in events if 'Network.response' in event['method']]
            request_events = [event for event in events if 'Network.requestWillBeSent' in event['method']]
            self.requestList = self.findEventLog('XHR', request_events)

        return self.requestList

    def getRequestHst(self):
        try:
            self.driver.switch_to_alert()
        except NoAlertPresentException:
            log = self.driver.get_log('performance')
            self.browser_log.extend(log)
            self.browser_log_hst.extend(log)
            events = [self.processBrowserLogEntry(entry) for entry in self.browser_log_hst]

            # response_events = [event for event in events if 'Network.response' in event['method']]
            request_events = [event for event in events if 'Network.requestWillBeSent' in event['method']]
            self.requestHst = self.findEventLog('XHR', request_events)

        return self.requestHst

    def clear(self):
        self.browser_log_hst.extend(self.driver.get_log('performance'))
        self.browser_log = []
        self.requestList = []

        print('Request Clear Successful')


    def clearUiEventList(self):
        self.recorder.clearEventList()


    def recordUiEvent(self):
        if not self.recording:
            self.recorder.clearEventList()
            self.recorder.addEventListener()

        self.recording = not self.recording


    def websocketSeverReceived(self, data):
        '''
        :websocket Server로부터 data를 받았을때 발생하는 이벤트
         data: (str) 'add_iframe'
        '''
        #print(data)
        if data == 'add_iframe':
            self.recorder.addEventListener()

    def getBrowserEvents(self):
        events = []

        try:
            events = self.recorder.getEventList()
            #threading.Timer(3, self.getBrowserEvents).start()
        except JavascriptException:
            self.recorder.addEventListener()
            events = self.recorder.getEventList()
            #threading.Timer(3, self.getBrowserEvents).start()
        except WebDriverException:
            print('Browser 종료')
        finally:
            #print(events)
            self.recorder.addEventListener()
            return events

        # if events:
        #     print(events)
        #     self.eventList.extend(events)
            #self.recorder.clearEventList()

            # for event in events:
            #     # One-time initialization
            #     toaster = ToastNotifier()
            #
            #     # Show notification whenever needed
            #     toaster.show_toast(title="Command Record",
            #                        msg="Command:{command}\nTarget:{target}\nValue:{value}".format(command=event[1], target=event[3], value=event[5]),
            #                        threaded=True,
            #                        icon_path='auto_test_main.ico',
            #                        duration=1)
                # notification.notify(
                #     title='Command Record',
                #     ticker='A',
                #     message="Command:{command}\nTarget:{target}\nValue:{value}".format(command=event[1], target=event[3], value=event[5]),
                #     app_name="Auto Test Tool 0.0.4",
                #     app_icon='auto_test_main.ico',
                #     timeout=5,  # seconds
                # )

    def getDriver(self):
        return self.driver

    def getEventList(self):
        return self.eventList

    def getSessionId(self):
        if self.driver:
            return self.driver.session_id
        else:
            return False

    def setSessionId(self, session_id):
        self.driver.session_id = session_id

    def getStatus(self):
        try:
            self.driver.window_handles
            return True
        except:
            return False

    def setFocus(self):
        self.driver.switch_to_window(self.driver.current_window_handle)


    def saveChromedriverVersion(self, version):
        '''
        chromedriver version 정보를 저장
        '''
        self.settings.load()
        self.settings["CHROMEDRIVER_VERSION"] = version
        self.settings.save()


    def chromedriverWebOn(self):
        '''
        chromedriver site 접속 가능여부 체크
        '''
        url = "https://chromedriver.chromium.org/downloads"
        try:
            res = urllib.request.urlopen(url)

            if res.status == 200:
                return True
            else:
                return False
        except:
            return False


    def downloadChromedriver(self, version, chromedriver_path):
        '''
        chromedriver가 미존재하거나 버전이 다른 경우 발생하는 이벤트
            - 온라인 연결이 가능한 경우는 다운로드
            - 온라인 연결이 불가능한 경우 임시 파일 중 가능한 버전으로 대체
        :param version: (str) '81'
        :param chromedriver_path: (str)
        '''
        if self.chromedriverWebOn():
            print("Chromedriver Downloading...")
            download_url  = self.findDriverVersion(version)
            download_path = os.path.join(self.SAVE_PATH, "chromedriver.zip")
            urllib.request.urlretrieve(download_url, download_path)
            print("Download Complete!")

            proc_name = "chromedriver.exe"

            # 현재 수행중인 chromedriver 존재여부 확인
            for proc in psutil.process_iter():
                try:
                    if proc.name().lower() == proc_name.lower():
                        print('현재 수행중인 chromedriver kill [{}]'.format(proc.name()))
                        proc.kill()
                except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                    pass

            try:
                with zipfile.ZipFile(download_path) as zf:
                    zf.extractall(path=self.SAVE_PATH)
                os.remove(download_path)
            except Exception as e:
                print(e)

            self.saveChromedriverVersion(version)
        else:
            print('Online 연결 불가능 - 오프라인 파일 생성')

            try:
                if version == '81':
                    shutil.copy('chromedriver_tmp/chromedriver_81.exe', chromedriver_path)
                    self.saveChromedriverVersion(version)
                elif version == '80':
                    shutil.copy('chromedriver_tmp/chromedriver_80.exe', chromedriver_path)
                    self.saveChromedriverVersion(version)
                elif version == '79':
                    shutil.copy('chromedriver_tmp/chromedriver_79.exe', chromedriver_path)
                    self.saveChromedriverVersion(version)
                elif version in ['65', '66', '67']:
                    shutil.copy('chromedriver_tmp/chromedriver_65.exe', chromedriver_path)
                    self.saveChromedriverVersion(version)
                else:
                    print('Chrome Version Check : {} - 오프라인은 65, 66, 67, 79, 80, 81 Version만 지원가능'.format(version))
                    return False
            except:
                pass
        pass


    def findDriverVersion(self, find_version):
        '''
        chromedriver를 다운로드 할 url를 찾아 string으로 Return
            chromedriver    chrome
            85              85
            .               .
            .               .
            71              71
            70              70
            ---------------------
            2.46            71-73
            2.45            70-72
            2.44            69-71
            2.43            69-71
            2.42            68-70
            2.41            67-69
            2.40            66-68
            2.39            66-68
            2.38            65-67
            2.37            64-66
            2.36            63-65
            2.35            62-64
            2.34            61-63
            2.33            60-62
            ---------------------
            2.28            57+
            2.25            54+
            2.24            53+
            2.22            51+
            2.19            44+
            2.15            42+
        :param find_version: (str) '81'
        :return: (str) https://chromedriver.storage.googleapis.com/81.0.4044.138/chromedriver_win32.zip
        '''
        download_url = ''

        base_url = "https://chromedriver.chromium.org/downloads"

        base_req = requests.get(base_url)
        base_soup = BeautifulSoup(base_req.content, "html.parser")

        atags = base_soup.select("a")

        for a in atags:
            m = re.compile("ChromeDriver (.*)")
            p = m.search(a.text)

            try:
                version = p.group(1)
                try:

                    m = re.compile("(\d*)\..*")
                    p = m.search(version)

                    if int(find_version) == int(p.group(1)):
                        download_url = "/".join(
                            [
                                "https://chromedriver.storage.googleapis.com",
                                version,
                                "chromedriver_win32.zip",
                            ]
                        )
                        break

                except:
                    pass
            except AttributeError:
                pass

        return download_url