Example #1
0
        /// <summary>
        /// Continues request with optional request overrides. To use this, request interception should be enabled with <see cref="Page.SetRequestInterceptionAsync(bool)"/>. Exception is immediately thrown if the request interception is not enabled.
        /// If the URL is set it won't perform a redirect. The request will be silently forwarded to the new url. For example, the address bar will show the original url.
        /// </summary>
        /// <param name="overrides">Optional request overwrites.</param>
        /// <returns>Task</returns>
        public async Task ContinueAsync(Payload overrides = null)
        {
            // Request interception is not supported for data: urls.
            if (Url.StartsWith("data:", StringComparison.InvariantCultureIgnoreCase))
            {
                return;
            }
            if (!_allowInterception)
            {
                throw new PuppeteerException("Request Interception is not enabled!");
            }
            if (_interceptionHandled)
            {
                throw new PuppeteerException("Request is already handled!");
            }

            _interceptionHandled = true;

            try
            {
                var requestData = new FetchContinueRequestRequest
                {
                    RequestId = InterceptionId
                };
                if (overrides?.Url != null)
                {
                    requestData.Url = overrides.Url;
                }

                if (overrides?.Method != null)
                {
                    requestData.Method = overrides.Method.ToString();
                }

                if (overrides?.PostData != null)
                {
                    requestData.PostData = overrides.PostData;
                }

                if (overrides?.Headers?.Count > 0)
                {
                    requestData.Headers = HeadersArray(overrides.Headers);
                }

                await _client.SendAsync("Fetch.continueRequest", requestData).ConfigureAwait(false);
            }
            catch (PuppeteerException ex)
            {
                // In certain cases, protocol will return error if the request was already canceled
                // or the page was closed. We should tolerate these errors
                _logger.LogError(ex.ToString());
            }
        }
        internal async Task InitializeAsync()
        {
            await _client.SendAsync("Network.enable").ConfigureAwait(false);

            if (_ignoreHTTPSErrors)
            {
                await _client.SendAsync("Security.setIgnoreCertificateErrors", new SecuritySetIgnoreCertificateErrorsRequest
                {
                    Ignore = true
                }).ConfigureAwait(false);
            }
        }
Example #3
0
        /// <summary>
        /// Continues request with optional request overrides. To use this, request interception should be enabled with <see cref="Page.SetRequestInterceptionAsync(bool)"/>. Exception is immediately thrown if the request interception is not enabled.
        /// If the URL is set it won't perform a redirect. The request will be silently forwarded to the new url. For example, the address bar will show the original url.
        /// </summary>
        /// <param name="overrides">Optional request overwrites.</param>
        /// <returns>Task</returns>
        public async Task ContinueAsync(Payload overrides = null)
        {
            // Request interception is not supported for data: urls.
            if (Url.StartsWith("data:", StringComparison.InvariantCultureIgnoreCase))
            {
                return;
            }
            if (!_allowInterception)
            {
                throw new PuppeteerException("Request Interception is not enabled!");
            }
            if (_interceptionHandled)
            {
                throw new PuppeteerException("Request is already handled!");
            }

            _interceptionHandled = true;

            try
            {
                var requestData = new FetchContinueRequestRequest
                {
                    RequestId = InterceptionId
                };
                if (overrides?.Url != null)
                {
                    requestData.Url = overrides.Url;
                }

                if (overrides?.Method != null)
                {
                    requestData.Method = overrides.Method.ToString();
                }

                if (overrides?.PostData != null)
                {
                    requestData.PostData = overrides.PostData;
                }

                if (overrides?.Headers?.Count > 0)
                {
                    requestData.Headers = HeadersArray(overrides.Headers);
                }

                await _client.SendAsync("Fetch.continueRequest", requestData).ConfigureAwait(false);
            }
            catch (PuppeteerException)
            {
            }
        }
Example #4
0
        /// <summary>
        /// Continues request with optional request overrides. To use this, request interception should be enabled with <see cref="Page.SetRequestInterceptionAsync(bool)"/>. Exception is immediately thrown if the request interception is not enabled.
        /// </summary>
        /// <param name="overrides">Optional request overwrites.</param>
        /// <returns>Task</returns>
        public async Task ContinueAsync(Payload overrides = null)
        {
            if (!_allowInterception)
            {
                throw new PuppeteerException("Request Interception is not enabled!");
            }
            if (_interceptionHandled)
            {
                throw new PuppeteerException("Request is already handled!");
            }

            _interceptionHandled = true;

            try
            {
                var requestData = new NetworkContinueInterceptedRequestRequest
                {
                    InterceptionId = InterceptionId
                };
                if (overrides?.Url != null)
                {
                    requestData.Url = overrides.Url;
                }

                if (overrides?.Method != null)
                {
                    requestData.Method = overrides.Method.ToString();
                }

                if (overrides?.PostData != null)
                {
                    requestData.PostData = overrides.PostData;
                }

                if (overrides?.Headers?.Count > 0)
                {
                    requestData.Headers = overrides.Headers;
                }

                await _client.SendAsync("Network.continueInterceptedRequest", requestData).ConfigureAwait(false);
            }
            catch (PuppeteerException ex)
            {
                // In certain cases, protocol will return error if the request was already canceled
                // or the page was closed. We should tolerate these errors
                _logger.LogError(ex.ToString());
            }
        }
Example #5
0
        /// <summary>
        /// Returns a Task which resolves to a buffer with response body
        /// </summary>
        /// <returns>A Task which resolves to a buffer with response body</returns>
        public Task <string> BufferAsync()
        {
            if (ContentTaskWrapper == null)
            {
                ContentTaskWrapper = new TaskCompletionSource <string>();

                Request.CompleteTask.ContinueWith(async(task) =>
                {
                    try
                    {
                        var response = await _client.SendAsync("Network.getResponseBody", new Dictionary <string, object>
                        {
                            { "requestId", Request.RequestId }
                        });

                        ContentTaskWrapper.SetResult(response.body.ToString());
                    }
                    catch (Exception ex)
                    {
                        ContentTaskWrapper.SetException(new BufferException("Unable to get response body", ex));
                    }
                });
            }

            return(ContentTaskWrapper.Task);
        }
Example #6
0
        /// <summary>
        /// Accept the file chooser request with given paths.
        /// If some of the filePaths are relative paths, then they are resolved relative to the current working directory.
        /// </summary>
        /// <param name="filePaths">File paths to send to the file chooser</param>
        /// <returns>A task that resolves after the accept message is processed by the browser</returns>
        public Task AcceptAsync(params string[] filePaths)
        {
            if (_handled)
            {
                throw new PuppeteerException("Cannot accept FileChooser which is already handled!");
            }

            _handled = true;
            var files = filePaths.Select(Path.GetFullPath);

            return(_client.SendAsync("Page.handleFileChooser", new PageHandleFileChooserRequest
            {
                Action = FileChooserAction.Accept,
                Files = files,
            }));
        }
Example #7
0
        /// <summary>
        /// Returns a Task which resolves to a buffer with response body
        /// </summary>
        /// <returns>A Task which resolves to a buffer with response body</returns>
        public async ValueTask <byte[]> BufferAsync()
        {
            if (_buffer == null)
            {
                var success = await BodyLoadedTaskWrapper.Task.ConfigureAwait(false);

                if (!success)
                {
                    throw new PuppeteerException("Response body is unavailable for redirect responses");
                }

                try
                {
                    var response = await _client.SendAsync <NetworkGetResponseBodyResponse>("Network.getResponseBody", new NetworkGetResponseBodyRequest
                    {
                        RequestId = Request.RequestId
                    }).ConfigureAwait(false);

                    _buffer = response.Base64Encoded
                        ? Convert.FromBase64String(response.Body)
                        : Encoding.UTF8.GetBytes(response.Body);
                }
                catch (Exception ex)
                {
                    throw new BufferException("Unable to get response body", ex);
                }
            }

            return(_buffer);
        }
Example #8
0
        /// <summary>
        /// Returns a Task which resolves to a buffer with response body
        /// </summary>
        /// <returns>A Task which resolves to a buffer with response body</returns>
        public async ValueTask <byte[]> BufferAsync()
        {
            if (_buffer == null)
            {
                await BodyLoadedTaskWrapper.Task.ConfigureAwait(false);

                try
                {
                    var response = await _client.SendAsync <NetworkGetResponseBodyResponse>("Network.getResponseBody", new Dictionary <string, object>
                    {
                        { MessageKeys.RequestId, Request.RequestId }
                    }).ConfigureAwait(false);

                    _buffer = response.Base64Encoded
                        ? Convert.FromBase64String(response.Body)
                        : Encoding.UTF8.GetBytes(response.Body);
                }
                catch (Exception ex)
                {
                    throw new BufferException("Unable to get response body", ex);
                }
            }

            return(_buffer);
        }
Example #9
0
        /// <summary>
        /// Continues request with optional request overrides. To use this, request interception should be enabled with <see cref="Page.SetRequestInterceptionAsync(bool)"/>. Exception is immediately thrown if the request interception is not enabled.
        /// </summary>
        /// <param name="overrides">Optional request overwrites.</param>
        /// <returns>Task</returns>
        public async Task ContinueAsync(Payload overrides = null)
        {
            if (!_allowInterception)
            {
                throw new PuppeteerException("Request Interception is not enabled!");
            }
            if (_interceptionHandled)
            {
                throw new PuppeteerException("Request is already handled!");
            }

            _interceptionHandled = true;

            try
            {
                var requestData = new Dictionary <string, object> {
                    ["interceptionId"] = InterceptionId
                };
                if (overrides?.Url != null)
                {
                    requestData["url"] = overrides.Url;
                }

                if (overrides?.Method != null)
                {
                    requestData["method"] = overrides.Method;
                }

                if (overrides?.PostData != null)
                {
                    requestData["postData"] = overrides.PostData;
                }

                if (overrides?.Headers != null)
                {
                    requestData["headers"] = overrides.Headers;
                }

                await _client.SendAsync("Network.continueInterceptedRequest", requestData);
            }
            catch (PuppeteerException ex)
            {
                // In certain cases, protocol will return error if the request was already canceled
                // or the page was closed. We should tolerate these errors
                _logger.LogError(ex.ToString());
            }
        }
Example #10
0
        /// <summary>
        /// The method iterates JavaScript heap and finds all the objects with the given prototype.
        /// </summary>
        /// <returns>A task which resolves to a handle to an array of objects with this prototype.</returns>
        /// <param name="prototypeHandle">A handle to the object prototype.</param>
        public async Task <dynamic> QueryObjectsAsync(JSHandle prototypeHandle)
        {
            if (prototypeHandle.Disposed)
            {
                throw new PuppeteerException("Prototype JSHandle is disposed!");
            }

            if (!((JObject)prototypeHandle.RemoteObject).TryGetValue("objectId", out var objectId))
            {
                throw new PuppeteerException("Prototype JSHandle must not be referencing primitive value");
            }

            dynamic response = await _client.SendAsync("Runtime.queryObjects", new Dictionary <string, object>()
            {
                { "prototypeObjectId", objectId.ToString() }
            });

            return(ObjectHandleFactory(response.objects));
        }
        /// <summary>
        /// The method iterates JavaScript heap and finds all the objects with the given prototype.
        /// </summary>
        /// <returns>A task which resolves to a handle to an array of objects with this prototype.</returns>
        /// <param name="prototypeHandle">A handle to the object prototype.</param>
        public async Task <JSHandle> QueryObjectsAsync(JSHandle prototypeHandle)
        {
            if (prototypeHandle.Disposed)
            {
                throw new PuppeteerException("Prototype JSHandle is disposed!");
            }

            if (prototypeHandle.RemoteObject.ObjectId == null)
            {
                throw new PuppeteerException("Prototype JSHandle must not be referencing primitive value");
            }

            var response = await _client.SendAsync <RuntimeQueryObjectsResponse>("Runtime.queryObjects", new RuntimeQueryObjectsRequest
            {
                PrototypeObjectId = prototypeHandle.RemoteObject.ObjectId
            }).ConfigureAwait(false);

            return(CreateJSHandle(response.Objects));
        }
Example #12
0
        internal Worker(
            CDPSession client,
            string url,
            Func <ConsoleType, JSHandle[], Task> consoleAPICalled,
            Action <EvaluateExceptionResponseDetails> exceptionThrown)
        {
            _client                  = client;
            Url                      = url;
            _exceptionThrown         = exceptionThrown;
            _client.MessageReceived += OnMessageReceived;

            _executionContextCallback = new TaskCompletionSource <ExecutionContext>(TaskCreationOptions.RunContinuationsAsynchronously);
            _ = _client.SendAsync("Runtime.enable").ContinueWith(task =>
            {
            });
            _ = _client.SendAsync("Log.enable").ContinueWith(task =>
            {
            });
        }
Example #13
0
        internal async Task <bool> EmulateViewport(ViewPortOptions viewport)
        {
            var mobile            = viewport.IsMobile;
            var width             = viewport.Width;
            var height            = viewport.Height;
            var deviceScaleFactor = viewport.DeviceScaleFactor;
            var screenOrientation = viewport.IsLandscape ?
                                    new ScreenOrientation
            {
                Angle = 90,
                Type  = ScreenOrientationType.LandscapePrimary
            } :
            new ScreenOrientation
            {
                Angle = 0,
                Type  = ScreenOrientationType.PortraitPrimary
            };
            var hasTouch = viewport.HasTouch;

            await Task.WhenAll(new Task[] {
                _client.SendAsync("Emulation.setDeviceMetricsOverride", new EmulationSetDeviceMetricsOverrideRequest
                {
                    Mobile            = mobile,
                    Width             = width,
                    Height            = height,
                    DeviceScaleFactor = deviceScaleFactor,
                    ScreenOrientation = screenOrientation
                }),
                _client.SendAsync("Emulation.setTouchEmulationEnabled", new EmulationSetTouchEmulationEnabledRequest
                {
                    Enabled       = hasTouch,
                    Configuration = viewport.IsMobile ? "mobile" : "desktop"
                })
            }).ConfigureAwait(false);

            var reloadNeeded = _emulatingMobile != mobile || _hasTouch != hasTouch;

            _emulatingMobile = mobile;
            _hasTouch        = hasTouch;
            return(reloadNeeded);
        }
Example #14
0
        /// <summary>
        /// Starts tracing.
        /// </summary>
        /// <returns>Start task</returns>
        /// <param name="options">Tracing options</param>
        public Task StartAsync(TracingOptions options)
        {
            if (_recording)
            {
                throw new InvalidOperationException("Cannot start recording trace while already recording trace.");
            }

            var categories = options.Categories ?? _defaultCategories;

            if (options.Screenshots)
            {
                categories.Add("disabled-by-default-devtools.screenshot");
            }

            _path      = options.Path;
            _recording = true;

            return(_client.SendAsync("Tracing.start", new TracingStartRequest
            {
                TransferMode = "ReturnAsStream",
                Categories = string.Join(", ", categories)
            }));
        }
        internal Task SetExtraHTTPHeadersAsync(Dictionary <string, string> extraHTTPHeaders)
        {
            _extraHTTPHeaders = new Dictionary <string, string>();

            foreach (var item in extraHTTPHeaders)
            {
                _extraHTTPHeaders[item.Key.ToLower()] = item.Value;
            }
            return(_client.SendAsync("Network.setExtraHTTPHeaders", new Dictionary <string, object>
            {
                { MessageKeys.Headers, _extraHTTPHeaders }
            }));
        }
        internal async Task SetExtraHTTPHeadersAsync(Dictionary <string, string> extraHTTPHeaders)
        {
            _extraHTTPHeaders = new Dictionary <string, string>();

            foreach (var item in extraHTTPHeaders)
            {
                _extraHTTPHeaders[item.Key.ToLower()] = item.Value;
            }
            await _client.SendAsync("Network.setExtraHTTPHeaders", new Dictionary <string, object>
            {
                { "headers", _extraHTTPHeaders }
            });
        }
Example #17
0
        internal Task SetExtraHTTPHeadersAsync(Dictionary <string, string> extraHTTPHeaders)
        {
            _extraHTTPHeaders = new Dictionary <string, string>();

            foreach (var item in extraHTTPHeaders)
            {
                _extraHTTPHeaders[item.Key.ToLower()] = item.Value;
            }
            return(_client.SendAsync("Network.setExtraHTTPHeaders", new NetworkSetExtraHTTPHeadersRequest
            {
                Headers = _extraHTTPHeaders
            }));
        }
Example #18
0
        private async Task NavigateAsync(CDPSession client, string url, string referrer, string frameId)
        {
            var response = await client.SendAsync <PageNavigateResponse>("Page.navigate", new
            {
                url,
                referrer = referrer ?? string.Empty,
                frameId
            }).ConfigureAwait(false);

            _ensureNewDocumentNavigation = !string.IsNullOrEmpty(response.LoaderId);

            if (!string.IsNullOrEmpty(response.ErrorText))
            {
                throw new NavigationException(response.ErrorText, url);
            }
        }
Example #19
0
        /// <summary>
        /// The method iterates JavaScript heap and finds all the objects with the given prototype.
        /// </summary>
        /// <returns>A task which resolves to a handle to an array of objects with this prototype.</returns>
        /// <param name="prototypeHandle">A handle to the object prototype.</param>
        public async Task <JSHandle> QueryObjectsAsync(JSHandle prototypeHandle)
        {
            if (prototypeHandle.Disposed)
            {
                throw new PuppeteerException("Prototype JSHandle is disposed!");
            }

            if (!((JObject)prototypeHandle.RemoteObject).TryGetValue(MessageKeys.ObjectId, out var objectId))
            {
                throw new PuppeteerException("Prototype JSHandle must not be referencing primitive value");
            }

            var response = await _client.SendAsync("Runtime.queryObjects", new Dictionary <string, object>
            {
                { "prototypeObjectId", objectId.ToString() }
            }).ConfigureAwait(false);

            return(CreateJSHandle(response[MessageKeys.Objects]));
        }
Example #20
0
        /// <summary>
        /// Returns a Task which resolves to a buffer with response body
        /// </summary>
        /// <returns>A Task which resolves to a buffer with response body</returns>
        public async ValueTask <string> BufferAsync()
        {
            if (_buffer == null)
            {
                await BodyLoadedTaskWrapper.Task.ConfigureAwait(false);

                try
                {
                    var response = await _client.SendAsync("Network.getResponseBody", new Dictionary <string, object>
                    {
                        { "requestId", Request.RequestId }
                    }).ConfigureAwait(false);

                    _buffer = response.body.ToString();
                }
                catch (Exception ex)
                {
                    throw new BufferException("Unable to get response body", ex);
                }
            }

            return(_buffer);
        }
        internal async Task <bool> EmulateViewport(ViewPortOptions viewport)
        {
            var mobile            = viewport.IsMobile;
            var width             = viewport.Width;
            var height            = viewport.Height;
            var deviceScaleFactor = viewport.DeviceScaleFactor;
            ScreenOrientation screenOrientation = viewport.IsLandscape ?
                                                  new ScreenOrientation
            {
                Angle = 90,
                Type  = ScreenOrientationType.LandscapePrimary
            } :
            new ScreenOrientation
            {
                Angle = 0,
                Type  = ScreenOrientationType.PortraitPrimary
            };

            await Task.WhenAll(new Task[] {
                _client.SendAsync("Emulation.setDeviceMetricsOverride", new
                {
                    mobile,
                    width,
                    height,
                    deviceScaleFactor,
                    screenOrientation
                }),
                _client.SendAsync("Emulation.setTouchEmulationEnabled", new
                {
                    enabled       = viewport.HasTouch,
                    configuration = viewport.IsMobile ? "mobile" : "desktop"
                })
            });

            var reloadNeeded = false;

            if (viewport.HasTouch && string.IsNullOrEmpty(_injectedTouchScriptId))
            {
                //TODO: It's not clear what to do here

                /*
                 * var source = $"({ injectedTouchEventsFunction})()";
                 * this._injectedTouchScriptId = (await this._client.send('Page.addScriptToEvaluateOnNewDocument', { source })).identifier;
                 * reloadNeeded = true;
                 */
            }
            else if (!viewport.HasTouch && !string.IsNullOrEmpty(_injectedTouchScriptId))
            {
                await _client.SendAsync("Page.removeScriptToEvaluateOnNewDocument", new
                {
                    identifier = _injectedTouchScriptId
                });

                _injectedTouchScriptId = null;
                reloadNeeded           = true;
            }

            if (_emulatingMobile != mobile)
            {
                reloadNeeded = true;
            }
            _emulatingMobile = mobile;
            return(reloadNeeded);
        }
Example #22
0
 /// <summary>
 /// Accept the Dialog.
 /// </summary>
 /// <returns>Task which resolves when the dialog has been accepted.</returns>
 /// <param name="promptText">A text to enter in prompt. Does not cause any effects if the dialog's type is not prompt.</param>
 public Task Accept(string promptText = "")
 => _client.SendAsync("Page.handleJavaScriptDialog", new PageHandleJavaScriptDialogRequest
 {
     Accept     = true,
     PromptText = promptText
 });