Skip to content

Commit

Permalink
Back up user.js as well (#2773)
Browse files Browse the repository at this point in the history
* Back up user.js as well

* bump patch

* some fixes

* self review

* cr

* mark as beta
  • Loading branch information
kblok authored Sep 5, 2024
1 parent 270c7a2 commit 72d0541
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 33 deletions.
32 changes: 32 additions & 0 deletions lib/PuppeteerSharp.Tests/LauncherTests/PuppeteerLaunchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -372,5 +372,37 @@ public async Task ShouldSupportCustomTransport()
Assert.That(customTransportCreated, Is.True);
}
}

[Test, Retry(2), PuppeteerTest("launcher.spec", "Launcher specs Puppeteer Puppeteer.launch", "userDataDir option restores preferences")]
public async Task UserDataDirOptionRestoresPreferences()
{
using var userDataDir = new TempDirectory();
var userDataDirInfo = new DirectoryInfo(userDataDir.Path);
var prefsJSPath = Path.Combine(userDataDir.Path, "prefs.js");
var userJSPath = Path.Combine(userDataDir.Path, "user.js");
var prefsJSContent = """user_pref("browser.warnOnQuit", true);""";
await File.WriteAllTextAsync(prefsJSPath, prefsJSContent);
await File.WriteAllTextAsync(userJSPath, prefsJSContent);

var options = TestConstants.DefaultBrowserOptions();
options.UserDataDir = userDataDir.Path;

await using var browser = await Puppeteer.LaunchAsync(options, TestConstants.LoggerFactory);
await browser.NewPageAsync();

Assert.That(userDataDirInfo.GetFiles(), Is.Not.Empty);
await browser.CloseAsync();
await Assert.MultipleAsync(async () =>
{
Assert.That(userDataDirInfo.GetFiles(), Is.Not.Empty);

Assert.That(
await File.ReadAllTextAsync(Path.Combine(userDataDir.Path, "prefs.js")),
Is.EqualTo(prefsJSContent));
Assert.That(
await File.ReadAllTextAsync(Path.Combine(userDataDir.Path, "user.js")),
Is.EqualTo(prefsJSContent));
});
}
}
}
39 changes: 25 additions & 14 deletions lib/PuppeteerSharp/BrowserData/Firefox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using PuppeteerSharp.Helpers;

namespace PuppeteerSharp.BrowserData
Expand Down Expand Up @@ -109,23 +110,33 @@ internal static string RelativeExecutablePath(Platform platform, string buildId)

internal static void CreateProfile(string tempUserDataDirectory, Dictionary<string, object> preferences)
{
// If the tempUserDataDirectory begins and ends with a quote, remove the quote
if (tempUserDataDirectory.StartsWith("\"", StringComparison.OrdinalIgnoreCase) && tempUserDataDirectory.EndsWith("\"", StringComparison.OrdinalIgnoreCase))
{
tempUserDataDirectory = tempUserDataDirectory.Substring(1, tempUserDataDirectory.Length - 2);
}

tempUserDataDirectory = tempUserDataDirectory.Unquote();
var defaultPreferences = GetDefaultPreferences(preferences);

File.WriteAllText(
Path.Combine(tempUserDataDirectory, "user.js"),
string.Join(
"\n",
defaultPreferences.Select(i =>
$"user_pref({JsonSerializer.Serialize(i.Key)}, {JsonSerializer.Serialize(i.Value)});")
.ToArray()));
SyncPreferences(defaultPreferences, tempUserDataDirectory);
}

private static void SyncPreferences(Dictionary<string, object> defaultPreferences, string tempUserDataDirectory)
{
var prefsPath = Path.Combine(tempUserDataDirectory, "prefs.js");
var userPath = Path.Combine(tempUserDataDirectory, "user.js");
var lines = string.Join(
"\n",
defaultPreferences.Select(i => $"user_pref({JsonSerializer.Serialize(i.Key)}, {JsonSerializer.Serialize(i.Value)});").ToArray());

BackupFile(userPath);
BackupFile(prefsPath);
File.WriteAllText(userPath, lines);
File.WriteAllText(prefsPath, string.Empty);
}

File.WriteAllText(Path.Combine(tempUserDataDirectory, "prefs.js"), string.Empty);
private static void BackupFile(string userPath)
{
if (File.Exists(userPath))
{
var backupPath = $"{userPath}.puppeteer";
File.Copy(userPath, backupPath, true);
}
}

private static (FirefoxChannel Channel, string BuildId) ParseBuildId(string buildId)
Expand Down
36 changes: 33 additions & 3 deletions lib/PuppeteerSharp/FirefoxLauncher.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
Expand All @@ -20,6 +21,7 @@ public class FirefoxLauncher : LauncherBase
];

private static readonly string[] _profileCommandLineArguments = ["-profile", "--profile"];
private readonly string _userDataDir;

/// <summary>
/// Initializes a new instance of the <see cref="FirefoxLauncher"/> class.
Expand All @@ -29,7 +31,7 @@ public class FirefoxLauncher : LauncherBase
public FirefoxLauncher(string executable, LaunchOptions options)
: base(executable, options)
{
(var firefoxArgs, TempUserDataDir) = PrepareFirefoxArgs(options);
(var firefoxArgs, TempUserDataDir, _userDataDir) = PrepareFirefoxArgs(options);

Process.StartInfo.Arguments = string.Join(" ", firefoxArgs);
}
Expand Down Expand Up @@ -79,7 +81,35 @@ internal static string[] GetDefaultArgs(LaunchOptions options)
return firefoxArguments.ToArray();
}

private static (List<string> FirefoxArgs, TempDirectory TempUserDataDirectory) PrepareFirefoxArgs(LaunchOptions options)
internal override void OnExit()
{
// If TempUserDataDir is null it means that the user provided their own userDataDir
if (TempUserDataDir is null)
{
var backupSuffix = ".puppeteer";
string[] backupFiles = ["prefs.js", "user.js"];
var basePath = _userDataDir.Unquote();
foreach (var backupFile in backupFiles)
{
var backupPath = Path.Combine(basePath, backupFile + backupSuffix);
var originalPath = Path.Combine(basePath, backupFile);
if (File.Exists(backupPath))
{
// We don't have the overwrite parameter in netstandard
if (File.Exists(originalPath))
{
File.Delete(originalPath);
}

File.Move(backupPath, Path.Combine(basePath, backupFile));
}
}
}

base.OnExit();
}

private static (List<string> FirefoxArgs, TempDirectory TempUserDataDirectory, string UserDataDir) PrepareFirefoxArgs(LaunchOptions options)
{
var firefoxArguments = new List<string>();

Expand Down Expand Up @@ -126,7 +156,7 @@ private static (List<string> FirefoxArgs, TempDirectory TempUserDataDirectory) P

Firefox.CreateProfile(userDataDir, GetPreferences(options.ExtraPrefsFirefox));

return (firefoxArguments, tempUserDataDirectory);
return (firefoxArguments, tempUserDataDirectory, userDataDir);
}

private static Dictionary<string, object> GetPreferences(Dictionary<string, object> optionsExtraPreferencesFirefox)
Expand Down
8 changes: 8 additions & 0 deletions lib/PuppeteerSharp/Helpers/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ public static string Quote(this string value)
return value;
}

/// <summary>
/// Unquotes the specified <see cref="string"/>.
/// </summary>
/// <param name="value">The string to unquote.</param>
/// <returns>An unquoted string.</returns>
public static string Unquote(this string value)
=> IsQuoted(value) ? value.Substring(1, value.Length - 2) : value;

private static bool IsQuoted(this string value)
{
return value.StartsWith("\"", StringComparison.OrdinalIgnoreCase)
Expand Down
19 changes: 19 additions & 0 deletions lib/PuppeteerSharp/LauncherBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,25 @@ await ExitCompletionSource.Task.WithTimeout(
return true;
}

/// <summary>
/// Cleans up temporary user data directory.
/// </summary>
internal virtual void OnExit()
{
if (TempUserDataDir is { } tempUserDataDir)
{
tempUserDataDir
.DeleteAsync()
.ContinueWith(
t => ExitCompletionSource.TrySetResult(true),
TaskScheduler.Default);
}
else
{
ExitCompletionSource.TrySetResult(true);
}
}

/// <summary>
/// Set Env Variables.
/// </summary>
Expand Down
8 changes: 4 additions & 4 deletions lib/PuppeteerSharp/PuppeteerSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
<Description>Headless Browser .NET API</Description>
<PackageId>PuppeteerSharp</PackageId>
<PackageReleaseNotes></PackageReleaseNotes>
<PackageVersion>20.0.0</PackageVersion>
<ReleaseVersion>20.0.0</ReleaseVersion>
<AssemblyVersion>20.0.0</AssemblyVersion>
<FileVersion>20.0.0</FileVersion>
<PackageVersion>20.0.1-beta1</PackageVersion>
<ReleaseVersion>20.0.1</ReleaseVersion>
<AssemblyVersion>20.0.1</AssemblyVersion>
<FileVersion>20.0.1</FileVersion>
<SynchReleaseVersion>false</SynchReleaseVersion>
<StyleCopTreatErrorsAsWarnings>false</StyleCopTreatErrorsAsWarnings>
<DebugType>embedded</DebugType>
Expand Down
13 changes: 1 addition & 12 deletions lib/PuppeteerSharp/States/ExitedState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,7 @@ public void EnterFrom(LauncherBase launcher, State fromState)
}
}

if (launcher.TempUserDataDir is { } tempUserDataDir)
{
tempUserDataDir
.DeleteAsync()
.ContinueWith(
t => launcher.ExitCompletionSource.TrySetResult(true),
TaskScheduler.Default);
}
else
{
launcher.ExitCompletionSource.TrySetResult(true);
}
launcher.OnExit();
}

public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => Task.CompletedTask;
Expand Down

0 comments on commit 72d0541

Please sign in to comment.