Example #1
0
    def blocking_navigate(self, url, timeout=DEFAULT_TIMEOUT_SECS):
        '''
		Do a blocking navigate to url `url`.

		This function triggers a navigation, and then waits for the browser
		to claim the page has finished loading.

		Roughly, this corresponds to the javascript `DOMContentLoaded` event,
		meaning the dom for the page is ready.


		Internals:

		A navigation command results in a sequence of events:

		 - Page.frameStartedLoading" (with frameid)
		 - Page.frameStoppedLoading" (with frameid)
		 - Page.loadEventFired" (not attached to an ID)

		Therefore, this call triggers a navigation option,
		and then waits for the expected set of response event messages.

		'''

        self.transport.flush(tab_key=self.tab_id)

        self.log.debug("Blocking navigate to URL: '%s'", url)
        ret = self.Page_navigate(url=url)

        assert ("result" in ret), "Missing return content"
        assert ("frameId"
                in ret['result']), "Missing 'frameId' in return content"
        assert ("loaderId"
                in ret['result']), "Missing 'loaderId' in return content"

        expected_id = ret['result']['frameId']
        loader_id = ret['result']['loaderId']

        try:
            self.log.debug("Waiting for frame navigated command response.")
            self.transport.recv_filtered(
                filter_funcs.check_frame_navigated_command(expected_id),
                tab_key=self.tab_id,
                timeout=timeout)
            self.log.debug("Waiting for frameStartedLoading response.")
            self.transport.recv_filtered(filter_funcs.check_frame_load_command(
                "Page.frameStartedLoading"),
                                         tab_key=self.tab_id,
                                         timeout=timeout)
            self.log.debug("Waiting for frameStoppedLoading response.")
            self.transport.recv_filtered(filter_funcs.check_frame_load_command(
                "Page.frameStoppedLoading"),
                                         tab_key=self.tab_id,
                                         timeout=timeout)
            # self.transport.recv_filtered(check_load_event_fired, tab_key=self.tab_id, timeout=timeout)

            self.log.debug("Waiting for responseReceived response.")
            resp = self.transport.recv_filtered(
                filter_funcs.network_response_recieved_for_url(
                    url=None, expected_id=expected_id),
                tab_key=self.tab_id,
                timeout=timeout)

            if resp is None:
                raise ChromeNavigateTimedOut("Blocking navigate timed out!")

            return resp['params']
        # The `Page.frameNavigated ` event does not get fired for non-markup responses.
        # Therefore, if we timeout on waiting for that, check to see if we received a binary response.
        except ChromeResponseNotReceived:
            # So this is basically broken, fix is https://bugs.chromium.org/p/chromium/issues/detail?id=831887
            # but that bug report isn't fixed yet.
            # Siiiigh.
            self.log.warning(
                "Failed to receive expected response to navigate command. Checking if response is a binary object."
            )
            resp = self.transport.recv_filtered(
                keycheck=filter_funcs.check_frame_loader_command(
                    method_name="Network.responseReceived",
                    loader_id=loader_id),
                tab_key=self.tab_id,
                timeout=timeout)

            return resp['params']
Example #2
0
    def blocking_navigate(self, url, timeout=DEFAULT_TIMEOUT_SECS):
        '''
		Do a blocking navigate to url `url`.

		This function triggers a navigation, and then waits for the browser
		to claim the page has finished loading.

		Roughly, this corresponds to the javascript `DOMContentLoaded` event,
		meaning the dom for the page is ready.


		Internals:

		A navigation command results in a sequence of events:

		 - Page.frameStartedLoading" (with frameid)
		 - Page.frameStoppedLoading" (with frameid)
		 - Page.loadEventFired" (not attached to an ID)

		Therefore, this call triggers a navigation option,
		and then waits for the expected set of response event messages.

		'''
        ret = self.Page_navigate(url=url)

        assert ("result" in ret), "Missing return content"
        assert ("frameId"
                in ret['result']), "Missing 'frameId' in return content"

        expected_id = ret['result']['frameId']

        def check_frame_navigated(message):
            if not message:
                return False
            if "method" not in message:
                return False
            if message['method'] != "Page.frameNavigated":
                return False
            if 'params' not in message:
                return False
            params = message['params']
            if 'frame' not in params:
                return False
            frame = params['frame']
            if 'id' in frame:
                ret = frame['id'] == expected_id
                # print('check_frame_navigated', message)
                return ret
            return False

        def check_frame_load_command(method_name):
            def frame_loading_tracker(message):
                if not message:
                    return False
                if "method" not in message:
                    return False
                if message['method'] != method_name:
                    return False
                if 'params' not in message:
                    return False
                return ret

                # Disabled. See https://bugs.chromium.org/p/chromedriver/issues/detail?id=1387
                # params = message['params']
                # if 'frameId' not in params:
                # 	return False
                # if 'frameId' in params:
                # 	ret = params['frameId'] == expected_id
                # 	# print("frame_loading_tracker", message)
                # return False

            return frame_loading_tracker

        def check_load_event_fired(message):
            if not message:
                return False
            if "method" not in message:
                return False
            if message['method'] == 'Page.loadEventFired':
                # print("check_load_event_fired", message)
                return True
            return False

        def network_response_recieved_for_url(url):
            def network_response_recieved_tracker(message):
                if not message:
                    return False
                if "method" not in message:
                    return False
                if message['method'] != 'Network.responseReceived':
                    return False
                if 'params' not in message:
                    return False
                params = message['params']
                if 'frameId' not in params:
                    return False
                if 'frameId' in params:
                    if params[
                            'frameId'] == expected_id and 'response' in params:
                        return True

                        # Checking the url in the response breaks if
                        # the remote issues a 301 or 302.
                        # response = params['response']
                        # if 'url' in response:
                        # 	return url == response['url']
                return False

            return network_response_recieved_tracker

        self.transport.recv_filtered(check_frame_navigated,
                                     tab_key=self.tab_id)

        self.transport.recv_filtered(
            check_frame_load_command("Page.frameStartedLoading"),
            tab_key=self.tab_id)
        self.transport.recv_filtered(
            check_frame_load_command("Page.frameStoppedLoading"),
            tab_key=self.tab_id)
        # self.transport.recv_filtered(check_load_event_fired, tab_key=self.tab_id)

        resp = self.transport.recv_filtered(
            network_response_recieved_for_url(url), tab_key=self.tab_id)

        if resp is None:
            raise ChromeNavigateTimedOut("Blocking navigate timed out!")

        return resp['params']