public async Task <Response> NavigateFrameAsync(Frame frame, string url, NavigationOptions options) { var referrer = string.IsNullOrEmpty(options.Referer) ? NetworkManager.ExtraHTTPHeaders?.GetValueOrDefault(MessageKeys.Referer) : options.Referer; var requests = new Dictionary <string, Request>(); var timeout = options?.Timeout ?? DefaultNavigationTimeout; using (var watcher = new LifecycleWatcher(this, frame, timeout, options)) { try { var navigateTask = NavigateAsync(Client, url, referrer, frame.Id); var task = await Task.WhenAny( watcher.TimeoutOrTerminationTask, navigateTask).ConfigureAwait(false); await task; task = await Task.WhenAny( watcher.TimeoutOrTerminationTask, _ensureNewDocumentNavigation?watcher.NewDocumentNavigationTask : watcher.SameDocumentNavigationTask ).ConfigureAwait(false); await task; } catch (Exception ex) { throw new NavigationException(ex.Message, ex); } return(watcher.NavigationResponse); } }
public async Task <Response> WaitForFrameNavigationAsync(Frame frame, NavigationOptions options = null) { var timeout = options?.Timeout ?? DefaultNavigationTimeout; using (var watcher = new NavigatorWatcher(_client, this, frame, _networkManager, timeout, options)) { var raceTask = await Task.WhenAny( watcher.NewDocumentNavigationTask, watcher.SameDocumentNavigationTask, watcher.TimeoutOrTerminationTask ).ConfigureAwait(false); var exception = raceTask.Exception; if (exception == null && watcher.TimeoutOrTerminationTask.IsCompleted && watcher.TimeoutOrTerminationTask.Result.IsFaulted) { exception = watcher.TimeoutOrTerminationTask.Result.Exception; } if (exception != null) { throw new NavigationException(exception.Message, exception); } return(watcher.NavigationResponse); } }
public NavigatorWatcher(FrameManager frameManager, Frame mainFrame, int timeout, NavigationOptions options) { var waitUntil = new[] { WaitUntilNavigation.Load }; if (options?.WaitUntil != null) { waitUntil = options.WaitUntil; } _expectedLifecycle = waitUntil.Select(w => { var protocolEvent = _puppeteerToProtocolLifecycle.GetValueOrDefault(w); Contract.Assert(protocolEvent != null, $"Unknown value for options.waitUntil: {w}"); return(protocolEvent); }); _frameManager = frameManager; _frame = mainFrame; _options = options; _initialLoaderId = mainFrame.LoaderId; _timeout = timeout; _hasSameDocumentNavigation = false; frameManager.LifecycleEvent += CheckLifecycleComplete; frameManager.FrameNavigatedWithinDocument += NavigatedWithinDocument; frameManager.FrameDetached += CheckLifecycleComplete; SameDocumentNavigationTaskWrapper = new TaskCompletionSource <bool>(); NewDocumentNavigationTaskWrapper = new TaskCompletionSource <bool>(); TimeoutTask = TaskHelper.CreateTimeoutTask(timeout); }
private async Task <Response> WaitForNavigation(NavigationOptions options = null) { var mainFrame = _frameManager.MainFrame; var timeout = options?.Timeout ?? DefaultNavigationTimeout; var watcher = new NavigatorWatcher(_frameManager, mainFrame, timeout, options); var responses = new Dictionary <string, Response>(); EventHandler <ResponseCreatedEventArgs> createResponseEventListener = (object sender, ResponseCreatedEventArgs e) => responses.Add(e.Response.Url, e.Response); _networkManager.ResponseCreated += createResponseEventListener; await watcher.NavigationTask; _networkManager.ResponseCreated -= createResponseEventListener; var exception = watcher.NavigationTask.Exception; if (exception != null) { throw new NavigationException(exception.Message, exception); } return(responses.GetValueOrDefault(_frameManager.MainFrame.Url)); }
public async Task <Response> ReloadAsync(NavigationOptions options = null) { var navigationTask = WaitForNavigation(options); await Task.WhenAll( navigationTask, _client.SendAsync("Page.reload") ); return(navigationTask.Result); }
public async Task <Response> GoToAsync(string url, NavigationOptions options = null) { var referrer = _networkManager.ExtraHTTPHeaders?.GetValueOrDefault("referer"); var requests = new Dictionary <string, Request>(); EventHandler <RequestEventArgs> createRequestEventListener = (object sender, RequestEventArgs e) => { if (!requests.ContainsKey(e.Request.Url)) { requests.Add(e.Request.Url, e.Request); } }; _networkManager.RequestCreated += createRequestEventListener; var mainFrame = _frameManager.MainFrame; var timeout = options?.Timeout ?? DefaultNavigationTimeout; var watcher = new NavigatorWatcher(_frameManager, mainFrame, timeout, options); var navigateTask = Navigate(_client, url, referrer); await Task.WhenAny( navigateTask, watcher.NavigationTask ); var exception = navigateTask.Exception; if (exception == null) { await watcher.NavigationTask; exception = watcher.NavigationTask.Exception; } watcher.Cancel(); _networkManager.RequestCreated -= createRequestEventListener; if (exception != null) { throw new NavigationException(exception.Message, exception); } Request request = null; if (requests.ContainsKey(_frameManager.MainFrame.Url)) { request = requests[_frameManager.MainFrame.Url]; } return(request?.Response); }
public async Task <Response> WaitForFrameNavigationAsync(Frame frame, NavigationOptions options = null) { var timeout = options?.Timeout ?? TimeoutSettings.NavigationTimeout; using (var watcher = new LifecycleWatcher(this, frame, options?.WaitUntil, timeout)) { var raceTask = await Task.WhenAny( watcher.NewDocumentNavigationTask, watcher.SameDocumentNavigationTask, watcher.TimeoutOrTerminationTask).ConfigureAwait(false); await raceTask.ConfigureAwait(false); return(watcher.NavigationResponse); } }
public NavigatorWatcher( CDPSession client, FrameManager frameManager, Frame mainFrame, NetworkManager networkManager, int timeout, NavigationOptions options) { var waitUntil = new[] { WaitUntilNavigation.Load }; if (options?.WaitUntil != null) { waitUntil = options.WaitUntil; } _expectedLifecycle = waitUntil.Select(w => { var protocolEvent = _puppeteerToProtocolLifecycle.GetValueOrDefault(w); Contract.Assert(protocolEvent != null, $"Unknown value for options.waitUntil: {w}"); return(protocolEvent); }); _frameManager = frameManager; _frame = mainFrame; _options = options; _initialLoaderId = mainFrame.LoaderId; _timeout = timeout; _hasSameDocumentNavigation = false; frameManager.LifecycleEvent += CheckLifecycleComplete; frameManager.FrameNavigatedWithinDocument += NavigatedWithinDocument; frameManager.FrameDetached += OnFrameDetached; networkManager.Request += OnRequest; var connection = Connection.FromSession(client); connection.Closed += (sender, e) => Terminate(new TargetClosedException("Navigation failed because browser has disconnected!", connection.CloseReason)); _sameDocumentNavigationTaskWrapper = new TaskCompletionSource <bool>(); _newDocumentNavigationTaskWrapper = new TaskCompletionSource <bool>(); _terminationTaskWrapper = new TaskCompletionSource <bool>(); _timeoutTask = TaskHelper.CreateTimeoutTask(timeout); }
internal async Task SetContentAsync(string html, NavigationOptions options = null) { var waitUntil = options?.WaitUntil ?? new[] { WaitUntilNavigation.Load }; var timeout = options?.Timeout ?? _timeoutSettings.NavigationTimeout; // We rely upon the fact that document.open() will reset frame lifecycle with "init" // lifecycle event. @see https://crrev.com/608658 await EvaluateFunctionAsync(@"html => { document.open(); document.write(html); document.close(); }", html).ConfigureAwait(false); var watcher = new LifecycleWatcher(_frameManager, Frame, waitUntil, timeout); var watcherTask = await Task.WhenAny( watcher.TimeoutOrTerminationTask, watcher.LifecycleTask).ConfigureAwait(false); await watcherTask.ConfigureAwait(false); }
public async Task <Response> NavigateFrameAsync(Frame frame, string url, NavigationOptions options) { var referrer = string.IsNullOrEmpty(options.Referer) ? _networkManager.ExtraHTTPHeaders?.GetValueOrDefault(MessageKeys.Referer) : options.Referer; var requests = new Dictionary <string, Request>(); var timeout = options?.Timeout ?? DefaultNavigationTimeout; using (var watcher = new NavigatorWatcher(_client, this, frame, _networkManager, timeout, options)) { var navigateTask = NavigateAsync(_client, url, referrer, frame.Id); await Task.WhenAny( watcher.TimeoutOrTerminationTask, navigateTask).ConfigureAwait(false); AggregateException exception = null; if (navigateTask.IsFaulted) { exception = navigateTask.Exception; } else { await Task.WhenAny( watcher.TimeoutOrTerminationTask, _ensureNewDocumentNavigation?watcher.NewDocumentNavigationTask : watcher.SameDocumentNavigationTask ).ConfigureAwait(false); if (watcher.TimeoutOrTerminationTask.IsCompleted && watcher.TimeoutOrTerminationTask.Result.IsFaulted) { exception = watcher.TimeoutOrTerminationTask.Result.Exception; } } if (exception != null) { throw new NavigationException(exception.InnerException.Message, exception.InnerException); } return(watcher.NavigationResponse); } }
public LifecycleWatcher( FrameManager frameManager, Frame frame, int timeout, NavigationOptions options) { var waitUntil = _defaultWaitUntil; if (options?.WaitUntil != null) { waitUntil = options.WaitUntil; } _expectedLifecycle = waitUntil.Select(w => { var protocolEvent = _puppeteerToProtocolLifecycle.GetValueOrDefault(w); Contract.Assert(protocolEvent != null, $"Unknown value for options.waitUntil: {w}"); return(protocolEvent); }); _frameManager = frameManager; _frame = frame; _options = options; _initialLoaderId = frame.LoaderId; _timeout = timeout; _hasSameDocumentNavigation = false; _sameDocumentNavigationTaskWrapper = new TaskCompletionSource <bool>(); _newDocumentNavigationTaskWrapper = new TaskCompletionSource <bool>(); _lifecycleTaskWrapper = new TaskCompletionSource <bool>(); _terminationTaskWrapper = new TaskCompletionSource <bool>(); frameManager.LifecycleEvent += CheckLifecycleComplete; frameManager.FrameNavigatedWithinDocument += NavigatedWithinDocument; frameManager.FrameDetached += OnFrameDetached; frameManager.NetworkManager.Request += OnRequest; frameManager.Client.Disconnected += OnClientDisconnected; }
public NavigatorWatcher(FrameManager frameManager, Frame mainFrame, int timeout, NavigationOptions options) { var waitUntil = new[] { WaitUntilNavigation.Load }; if (options?.WaitUntil != null) { waitUntil = options.WaitUntil; } _expectedLifecycle = waitUntil.Select(w => { var protocolEvent = _puppeteerToProtocolLifecycle.GetValueOrDefault(w); Contract.Assert(protocolEvent != null, $"Unknown value for options.waitUntil: {w}"); return(protocolEvent); }); _frameManager = frameManager; _frame = mainFrame; _options = options; _initialLoaderId = mainFrame.LoaderId; _timeout = timeout; frameManager.LifecycleEvent += FrameManager_LifecycleEvent; frameManager.FrameDetached += FrameManager_LifecycleEvent; LifeCycleCompleteTaskWrapper = new TaskCompletionSource <bool>(); NavigationTask = Task.WhenAny(new[] { CreateTimeoutTask(), LifeCycleCompleteTask, }).ContinueWith((task) => { CleanUp(); return(task.GetAwaiter().GetResult()); }); }
/// <summary> /// Sets the HTML markup to the page /// </summary> /// <param name="html">HTML markup to assign to the page.</param> /// <param name="options">The options</param> /// <returns>Task.</returns> /// <seealso cref="Page.SetContentAsync(string, NavigationOptions)"/> public Task SetContentAsync(string html, NavigationOptions options = null) => SecondaryWorld.SetContentAsync(html, options);
/// <summary> /// This resolves when the frame navigates to a new URL or reloads. /// It is useful for when you run code which will indirectly cause the frame to navigate. /// </summary> /// <param name="options">navigation options</param> /// <returns>Task which resolves to the main resource response. /// In case of multiple redirects, the navigation will resolve with the response of the last redirect. /// In case of navigation to a different anchor or navigation due to History API usage, the navigation will resolve with `null`. /// </returns> /// <remarks> /// Usage of the <c>History API</c> <see href="https://developer.mozilla.org/en-US/docs/Web/API/History_API"/> to change the URL is considered a navigation /// </remarks> /// <example> /// <code> /// <![CDATA[ /// var navigationTask =frame.page.WaitForNavigationAsync(); /// await frame.ClickAsync("a.my-link"); /// await navigationTask; /// ]]> /// </code> /// </example> public Task <Response> WaitForNavigationAsync(NavigationOptions options = null) => FrameManager.WaitForFrameNavigationAsync(this, options);
/// <summary> /// Navigates to an url /// </summary> /// <remarks> /// <see cref="GoToAsync(string, int?, WaitUntilNavigation[])"/> will throw an error if: /// - there's an SSL error (e.g. in case of self-signed certificates). /// - target URL is invalid. /// - the `timeout` is exceeded during navigation. /// - the remote server does not respond or is unreachable. /// - the main resource failed to load. /// /// <see cref="GoToAsync(string, int?, WaitUntilNavigation[])"/> will not throw an error when any valid HTTP status code is returned by the remote server, /// including 404 "Not Found" and 500 "Internal Server Error". The status code for such responses can be retrieved by calling <see cref="Response.Status"/> /// /// > **NOTE** <see cref="GoToAsync(string, int?, WaitUntilNavigation[])"/> either throws an error or returns a main resource response. /// The only exceptions are navigation to `about:blank` or navigation to the same URL with a different hash, which would succeed and return `null`. /// /// > **NOTE** Headless mode doesn't support navigation to a PDF document. See the <see fref="https://bugs.chromium.org/p/chromium/issues/detail?id=761295">upstream issue</see>. /// </remarks> /// <param name="url">URL to navigate page to. The url should include scheme, e.g. https://.</param> /// <param name="options">Navigation parameters.</param> /// <returns>Task which resolves to the main resource response. In case of multiple redirects, the navigation will resolve with the response of the last redirect.</returns> /// <seealso cref="GoToAsync(string, int?, WaitUntilNavigation[])"/> public Task <Response> GoToAsync(string url, NavigationOptions options) => FrameManager.NavigateFrameAsync(this, url, options);
public static async Task Main(string[] args) { var currentDirectory = Directory.GetCurrentDirectory(); var downloadPath = Path.Combine(currentDirectory, "CustomChromium"); Console.WriteLine($"Attemping to set up puppeteer to use Chromium found under directory {downloadPath} "); if (!Directory.Exists(downloadPath)) { Console.WriteLine("Custom directory not found. Creating directory"); Directory.CreateDirectory(downloadPath); } Console.WriteLine("Downloading Chromium..."); var browserFetcherOptions = new BrowserFetcherOptions { Path = downloadPath }; var browserFetcher = new BrowserFetcher(browserFetcherOptions); await browserFetcher.DownloadAsync(BrowserFetcher.DefaultRevision); var executablePath = browserFetcher.GetExecutablePath(BrowserFetcher.DefaultRevision); if (string.IsNullOrEmpty(executablePath)) { Console.WriteLine("Custom Chromium location is empty. Unable to start Chromium. Exiting.\n Press any key to continue"); Console.ReadLine(); return; } Console.WriteLine($"Attemping to start Chromium using executable path: {executablePath}"); var options = new LaunchOptions { Headless = true, ExecutablePath = executablePath }; using (var browser = await Puppeteer.LaunchAsync(options)) using (var page = await browser.NewPageAsync()) { await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision); await page.SetViewportAsync(new ViewPortOptions { Width = 1920, Height = 1080 }); var waitUntil = new NavigationOptions { Timeout = 0, WaitUntil = new[] { WaitUntilNavigation.Networkidle0 } }; string url = "https://github.com/puppeteer/puppeteer/issues/1345"; await page.GoToAsync(url, waitUntil); #region Screenshot Dashboard: var optionsScreenShot = new ScreenshotOptions { FullPage = true }; //Đường dẫn lưu file var savePath = Path.Combine(currentDirectory, "Capture"); if (!Directory.Exists(savePath)) { Console.WriteLine("SavePath directory not found. Creating directory"); Directory.CreateDirectory(savePath); } string date = DateTime.Now.ToString("yyyyMMddHHmmss"); var outputfile = savePath + "/capture_" + date + ".png"; await page.ScreenshotAsync(outputfile, optionsScreenShot); Console.WriteLine("Capture completed! Path: " + outputfile, ConsoleColor.Green); #endregion await page.CloseAsync(); } return; }