コード例 #1
0
                public async Task EnterFromAsync(FirefoxProcessManager p, State fromState)
                {
                    if (!TryEnter(p, fromState))
                    {
                        // Delegate KillAsync to current state, because it has already changed since
                        // transition to this state was initiated.
                        await p._currentState.KillAsync(p).ConfigureAwait(false);
                    }

                    try
                    {
                        await p._attemptToGracefullyCloseFunc().ConfigureAwait(false);

                        if (!p.Process.HasExited)
                        {
                            p.Process.Kill();
                        }
                    }
                    catch (InvalidOperationException)
                    {
                        // Ignore
                        return;
                    }

                    await WaitForExitAsync(p).ConfigureAwait(false);
                }
コード例 #2
0
                public Task EnterFromAsync(FirefoxProcessManager p, State fromState)
                {
                    if (TryEnter(p, fromState))
                    {
                        // Process has not exited or been killed since transition to this state was initiated
                        LogProcessCount(p, Interlocked.Increment(ref _processCount));
                    }

                    return(Task.CompletedTask);
                }
コード例 #3
0
            /// <summary>
            /// Attempts thread-safe transitions from a given state to this state.
            /// </summary>
            /// <param name="p">The Firefox process.</param>
            /// <param name="fromState">The state from which state transition takes place.</param>
            /// <returns>Returns <c>true</c> if transition is successful, or <c>false</c> if transition
            /// cannot be made because current state does not equal <paramref name="fromState"/>.</returns>
            protected bool TryEnter(FirefoxProcessManager p, State fromState)
            {
                if (Interlocked.CompareExchange(ref p._currentState, this, fromState) == fromState)
                {
                    fromState.Leave(p);
                    return(true);
                }

                return(false);
            }
コード例 #4
0
        /// <inheritdoc cref="IBrowserType.LaunchBrowserAppAsync(LaunchOptions)"/>
        public override async Task <IBrowserApp> LaunchBrowserAppAsync(LaunchOptions options = null)
        {
            options ??= new LaunchOptions();

            var(firefoxArguments, tempProfileDir) = PrepareFirefoxArgs(options);
            string     firefoxExecutable = GetBrowserExecutablePath(options);
            BrowserApp browserApp        = null;

            var process = new FirefoxProcessManager(
                firefoxExecutable,
                firefoxArguments,
                tempProfileDir,
                options.Timeout,
                async() =>
            {
                if (browserApp == null)
                {
                    return;
                }

                var transport = await BrowserHelper.CreateTransportAsync(browserApp.ConnectOptions).ConfigureAwait(false);
                await transport.SendAsync(new BrowserCloseRequest().Command).ConfigureAwait(false);
            },
                (exitCode) =>
            {
                browserApp?.ProcessKilled(exitCode);
            });

            try
            {
                SetEnvVariables(process.Process.StartInfo.Environment, options.Env, Environment.GetEnvironmentVariables());

                if (options.DumpIO)
                {
                    process.Process.ErrorDataReceived += (sender, e) => Console.Error.WriteLine(e.Data);
                }

                await process.StartAsync().ConfigureAwait(false);

                var connectOptions = new ConnectOptions()
                {
                    BrowserWSEndpoint = process.Endpoint,
                    SlowMo            = options.SlowMo,
                };

                return(new BrowserApp(process, () => Task.CompletedTask, connectOptions));
            }
            catch
            {
                await process.KillAsync().ConfigureAwait(false);

                throw;
            }
        }
コード例 #5
0
                public Task EnterFromAsync(FirefoxProcessManager p, State fromState)
                {
                    if (!TryEnter(p, fromState))
                    {
                        // Delegate StartAsync to current state, because it has already changed since
                        // transition to this state was initiated.
                        return(p._currentState.StartAsync(p));
                    }

                    return(StartCoreAsync(p));
                }
コード例 #6
0
 public override async Task ExitAsync(FirefoxProcessManager p, TimeSpan timeout)
 {
     var waitForExitTask = WaitForExitAsync(p);
     await waitForExitTask.WithTimeout(
         async() =>
     {
         await Killing.EnterFromAsync(p, this).ConfigureAwait(false);
         await waitForExitTask.ConfigureAwait(false);
     },
         timeout,
         CancellationToken.None).ConfigureAwait(false);
 }
コード例 #7
0
 /// <summary>
 /// Kills process if it is still alive.
 /// </summary>
 /// <param name="p">Process to kill.</param>
 private static void Kill(FirefoxProcessManager p)
 {
     try
     {
         if (!p.Process.HasExited)
         {
             p.Process.Kill();
         }
     }
     catch (InvalidOperationException)
     {
         // Ignore
     }
 }
コード例 #8
0
                private static void LogProcessCount(FirefoxProcessManager p, int processCount)
                {
                    // TODO Add logger
                    Console.WriteLine(p.ToString() + processCount);

                    /*
                     * try
                     * {
                     *  // p._logger?.LogInformation("Process Count: {ProcessCount}", processCount);
                     * }
                     * catch
                     * {
                     *  // Prevent logging exception from causing havoc
                     * }*/
                }
コード例 #9
0
                public void EnterFrom(FirefoxProcessManager p, State fromState)
                {
                    if (!TryEnter(p, fromState))
                    {
                        // Delegate Dispose to current state, because it has already changed since
                        // transition to this state was initiated.
                        p._currentState.Dispose(p);
                    }
                    else if (fromState != Exited)
                    {
                        Kill(p);

                        p._exitCompletionSource.TrySetException(new ObjectDisposedException(p.ToString()));
                        p._tempUserDataDir?.Dispose();
                    }
                }
コード例 #10
0
                public void EnterFrom(FirefoxProcessManager p, State fromState)
                {
                    while (!TryEnter(p, fromState))
                    {
                        // Current state has changed since transition to this state was requested.
                        // Therefore retry transition to this state from the current state. This ensures
                        // that Leave() operation of current state is properly called.
                        fromState = p._currentState;
                        if (fromState == this)
                        {
                            return;
                        }
                    }

                    p._onKill(p.Process?.ExitCode ?? 0);
                    p._exitCompletionSource.TrySetResult(true);
                    p._tempUserDataDir?.Dispose();
                }
コード例 #11
0
 public override Task KillAsync(FirefoxProcessManager p) => Task.CompletedTask;
コード例 #12
0
 public override Task ExitAsync(FirefoxProcessManager p, TimeSpan timeout) => Task.CompletedTask;
コード例 #13
0
 public override Task KillAsync(FirefoxProcessManager p) => WaitForExitAsync(p);
コード例 #14
0
 public override Task WaitForExitAsync(FirefoxProcessManager p) => Task.FromException(InvalidOperation("wait for exit"));
コード例 #15
0
 public override Task ExitAsync(FirefoxProcessManager p, TimeSpan timeout) => WaitForExitAsync(p);
コード例 #16
0
 public override void Dispose(FirefoxProcessManager p)
 {
     // Nothing to do
 }
コード例 #17
0
                private async Task StartCoreAsync(FirefoxProcessManager p)
                {
                    var output = new StringBuilder();

                    void OnProcessDataReceivedWhileStarting(object sender, DataReceivedEventArgs e)
                    {
                        if (e.Data != null)
                        {
                            output.AppendLine(e.Data);
                            var match = Regex.Match(e.Data, "^Juggler listening on (ws:\\/\\/.*)");
                            if (match.Success)
                            {
                                p._startCompletionSource.TrySetResult(match.Groups[1].Value);
                            }
                        }
                    }

                    void OnProcessExitedWhileStarting(object sender, EventArgs e)
                    => p._startCompletionSource.TrySetException(new PlaywrightSharpException($"Failed to launch Firefox! {output}"));
                    void OnProcessExited(object sender, EventArgs e) => Exited.EnterFrom(p, p._currentState);

                    p.Process.OutputDataReceived += OnProcessDataReceivedWhileStarting;
                    p.Process.Exited             += OnProcessExitedWhileStarting;
                    p.Process.Exited             += OnProcessExited;
                    CancellationTokenSource cts = null;

                    try
                    {
                        p.Process.Start();
                        await Started.EnterFromAsync(p, this).ConfigureAwait(false);

                        p.Process.BeginOutputReadLine();
                        p.Process.BeginErrorReadLine();

                        int timeout = p.Timeout;
                        if (timeout > 0)
                        {
                            cts = new CancellationTokenSource(timeout);
                            cts.Token.Register(() => p._startCompletionSource.TrySetException(
                                                   new PlaywrightSharpException($"Timed out after {timeout} ms while trying to connect to Firefox!")));
                        }

                        try
                        {
                            await p._startCompletionSource.Task.ConfigureAwait(false);

                            await Started.EnterFromAsync(p, this).ConfigureAwait(false);
                        }
                        catch
                        {
                            await Killing.EnterFromAsync(p, this).ConfigureAwait(false);

                            throw;
                        }
                    }
                    finally
                    {
                        cts?.Dispose();
                        p.Process.Exited             -= OnProcessExitedWhileStarting;
                        p.Process.OutputDataReceived -= OnProcessDataReceivedWhileStarting;
                    }
                }
コード例 #18
0
 public override Task StartAsync(FirefoxProcessManager p) => p._startCompletionSource.Task;
コード例 #19
0
 public override Task ExitAsync(FirefoxProcessManager p, TimeSpan timeout) => throw new ObjectDisposedException(p.ToString());
コード例 #20
0
 protected override void Leave(FirefoxProcessManager p)
 => LogProcessCount(p, Interlocked.Decrement(ref _processCount));
コード例 #21
0
 public override Task ExitAsync(FirefoxProcessManager p, TimeSpan timeout) => Exiting.EnterFromAsync(p, this, timeout);
コード例 #22
0
 public override Task StartAsync(FirefoxProcessManager p) => Starting.EnterFromAsync(p, this);
コード例 #23
0
 public override Task WaitForExitAsync(FirefoxProcessManager p) => Task.CompletedTask;
コード例 #24
0
 public override Task KillAsync(FirefoxProcessManager p)
 {
     Exited.EnterFrom(p, this);
     return(Task.CompletedTask);
 }
コード例 #25
0
 /// <summary>
 /// Notifies that state machine is about to transition to another state.
 /// </summary>
 /// <param name="p">The Firefox process.</param>
 protected virtual void Leave(FirefoxProcessManager p)
 {
 }
コード例 #26
0
 public override void Dispose(FirefoxProcessManager p)
 {
     p._startCompletionSource.TrySetException(new ObjectDisposedException(p.ToString()));
     base.Dispose(p);
 }
コード例 #27
0
 public override Task KillAsync(FirefoxProcessManager p) => throw new ObjectDisposedException(p.ToString());
コード例 #28
0
 public override Task KillAsync(FirefoxProcessManager p) => Killing.EnterFromAsync(p, this);
コード例 #29
0
 public Task EnterFromAsync(FirefoxProcessManager p, State fromState, TimeSpan timeout)
 => !TryEnter(p, fromState) ? p._currentState.ExitAsync(p, timeout) : ExitAsync(p, timeout);
コード例 #30
0
 public override Task ExitAsync(FirefoxProcessManager p, TimeSpan timeout)
 {
     Exited.EnterFrom(p, this);
     return(Task.CompletedTask);
 }