Skip to content

Commit 583b240

Browse files
kblokMeir017
authored andcommitted
New LaunchOptions properties DefaultViewport and IgnoredDefaultArgs (#615)
* New LaunchOptions properties DefaultViewport and IgnoredDefaultArgs * CodeFactor * appveyor * Make it build luke * Add #566 tests * #565 tests * cr
1 parent 2b5b1ea commit 583b240

File tree

14 files changed

+164
-108
lines changed

14 files changed

+164
-108
lines changed

lib/PuppeteerSharp.Tests/Issues/Issue0128.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public async Task LauncherShouldFailGracefully()
1414
await Assert.ThrowsAsync<ChromiumProcessException>(async () =>
1515
{
1616
var options = TestConstants.DefaultBrowserOptions();
17-
options.Args = new[] { "-remote-debugging-port=-2" };
17+
options.Args = new[] { "--remote-debugging-port=-2" };
1818
await Puppeteer.LaunchAsync(options, TestConstants.LoggerFactory);
1919
});
2020
}

lib/PuppeteerSharp.Tests/PuppeteerTests/AppModeTests.cs

Lines changed: 0 additions & 30 deletions
This file was deleted.

lib/PuppeteerSharp.Tests/PuppeteerTests/PuppeteerLaunchTests.cs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,16 @@ await page.EvaluateExpressionAsync(
210210
[Fact]
211211
public void ShouldReturnTheDefaultChromeArguments()
212212
{
213-
var args = Puppeteer.DefaultArgs;
214-
Assert.Contains("--no-first-run", args);
213+
Assert.Contains("--no-first-run", Puppeteer.GetDefaultArgs());
214+
Assert.Contains("--headless", Puppeteer.GetDefaultArgs());
215+
Assert.DoesNotContain("--headless", Puppeteer.GetDefaultArgs(new LaunchOptions
216+
{
217+
Headless = false
218+
}));
219+
Assert.Contains("--user-data-dir=\"foo\"", Puppeteer.GetDefaultArgs(new LaunchOptions
220+
{
221+
UserDataDir = "foo"
222+
}));
215223
}
216224

217225
[Fact]
@@ -332,6 +340,21 @@ public async Task ShouldWorkWithNoDefaultArguments()
332340
}
333341
}
334342

343+
[Fact]
344+
public async Task ShouldFilterOutIgnoredDefaultArguments()
345+
{
346+
var defaultArgs = Puppeteer.GetDefaultArgs();
347+
var options = TestConstants.DefaultBrowserOptions();
348+
options.IgnoredDefaultArgs = new[] { defaultArgs[0], defaultArgs[2] };
349+
using (var browser = await Puppeteer.LaunchAsync(options))
350+
{
351+
var spawnargs = browser.Process.StartInfo.Arguments;
352+
Assert.DoesNotContain(defaultArgs[0], spawnargs);
353+
Assert.Contains(defaultArgs[1], spawnargs);
354+
Assert.DoesNotContain(defaultArgs[2], spawnargs);
355+
}
356+
}
357+
335358
[Fact]
336359
public async Task ShouldHaveDefaultUrlWhenLaunchingBrowser()
337360
{
@@ -360,6 +383,37 @@ public async Task ShouldHaveCustomUrlWhenLaunchingBrowser()
360383
}
361384
}
362385

386+
[Fact]
387+
public async Task ShouldSetTheDefaultViewport()
388+
{
389+
var options = TestConstants.DefaultBrowserOptions();
390+
options.DefaultViewport = new ViewPortOptions
391+
{
392+
Width = 456,
393+
Height = 789
394+
};
395+
396+
using (var browser = await Puppeteer.LaunchAsync(options))
397+
using (var page = await browser.NewPageAsync())
398+
{
399+
Assert.Equal(456, await page.EvaluateExpressionAsync<int>("window.innerWidth"));
400+
Assert.Equal(789, await page.EvaluateExpressionAsync<int>("window.innerHeight"));
401+
}
402+
}
403+
404+
[Fact]
405+
public async Task ShouldDisableTheDefaultViewport()
406+
{
407+
var options = TestConstants.DefaultBrowserOptions();
408+
options.DefaultViewport = null;
409+
410+
using (var browser = await Puppeteer.LaunchAsync(options))
411+
using (var page = await browser.NewPageAsync())
412+
{
413+
Assert.Null(page.Viewport);
414+
}
415+
}
416+
363417
[Fact]
364418
public async Task ShouldSupportCustomWebSocket()
365419
{

lib/PuppeteerSharp/Browser.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,18 @@ public class Browser : IDisposable
4646
/// <param name="connection">The connection</param>
4747
/// <param name="contextIds">The context ids></param>
4848
/// <param name="ignoreHTTPSErrors">The option to ignoreHTTPSErrors</param>
49-
/// <param name="setDefaultViewport">The option to setDefaultViewport</param>
49+
/// <param name="defaultViewport">Default viewport</param>
5050
/// <param name="chromiumProcess">The Chromium process</param>
5151
public Browser(
5252
Connection connection,
5353
string[] contextIds,
5454
bool ignoreHTTPSErrors,
55-
bool setDefaultViewport,
55+
ViewPortOptions defaultViewport,
5656
ChromiumProcess chromiumProcess)
5757
{
5858
Connection = connection;
5959
IgnoreHTTPSErrors = ignoreHTTPSErrors;
60-
SetDefaultViewport = setDefaultViewport;
60+
DefaultViewport = defaultViewport;
6161
TargetsMap = new Dictionary<string, Target>();
6262
ScreenshotTaskQueue = new TaskQueue();
6363
_defaultContext = new BrowserContext(this, null);
@@ -141,7 +141,7 @@ public Browser(
141141

142142
internal TaskQueue ScreenshotTaskQueue { get; set; }
143143
internal Connection Connection { get; }
144-
internal bool SetDefaultViewport { get; }
144+
internal ViewPortOptions DefaultViewport { get; }
145145

146146
#endregion
147147

@@ -399,10 +399,10 @@ internal static async Task<Browser> CreateAsync(
399399
Connection connection,
400400
string[] contextIds,
401401
bool ignoreHTTPSErrors,
402-
bool appMode,
402+
ViewPortOptions defaultViewPort,
403403
ChromiumProcess chromiumProcess)
404404
{
405-
var browser = new Browser(connection, contextIds, ignoreHTTPSErrors, appMode, chromiumProcess);
405+
var browser = new Browser(connection, contextIds, ignoreHTTPSErrors, defaultViewPort, chromiumProcess);
406406
await connection.SendAsync("Target.setDiscoverTargets", new
407407
{
408408
discover = true

lib/PuppeteerSharp/BrowserFetcher.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ public static string GetExecutablePath(Platform platform, string folderPath)
235235

236236
#region Private Methods
237237

238-
private static Platform GetCurrentPlatform()
238+
internal static Platform GetCurrentPlatform()
239239
{
240240
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
241241
{

lib/PuppeteerSharp/ChromiumProcess.cs

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@ public class ChromiumProcess : IDisposable
3636
"--disable-translate",
3737
"--metrics-recording-only",
3838
"--no-first-run",
39-
"--safebrowsing-disable-auto-update"
40-
};
41-
42-
internal static readonly string[] AutomationArgs = {
39+
"--safebrowsing-disable-auto-update",
4340
"--enable-automation",
4441
"--password-store=basic",
4542
"--use-mock-keychain"
@@ -205,69 +202,71 @@ public async Task<bool> WaitForExitAsync(TimeSpan? timeout)
205202

206203
private static (List<string> chromiumArgs, TempDirectory tempUserDataDir) PrepareChromiumArgs(LaunchOptions options)
207204
{
208-
var chromiumArgs = new List<string>(DefaultArgs);
209-
TempDirectory tempUserDataDir = null;
210205

211-
if (options.AppMode)
206+
var chromiumArgs = new List<string>();
207+
208+
if (!options.IgnoreDefaultArgs)
212209
{
213-
options.Headless = false;
210+
chromiumArgs.AddRange(GetDefaultArgs(options));
211+
}
212+
else if (options.IgnoredDefaultArgs?.Length > 0)
213+
{
214+
chromiumArgs.AddRange(GetDefaultArgs(options).Except(options.IgnoredDefaultArgs));
214215
}
215216
else
216217
{
217-
chromiumArgs.AddRange(AutomationArgs);
218+
chromiumArgs.AddRange(options.Args);
218219
}
219220

220-
if (!options.IgnoreDefaultArgs ||
221-
!chromiumArgs.Any(argument => argument.StartsWith("--remote-debugging-", StringComparison.Ordinal)))
221+
TempDirectory tempUserDataDir = null;
222+
223+
if (!chromiumArgs.Any(argument => argument.StartsWith("--remote-debugging-", StringComparison.Ordinal)))
222224
{
223225
chromiumArgs.Add("--remote-debugging-port=0");
224226
}
225227

226-
var userDataDirOption = options.Args.FirstOrDefault(i => i.StartsWith(UserDataDirArgument, StringComparison.Ordinal));
228+
var userDataDirOption = chromiumArgs.FirstOrDefault(i => i.StartsWith(UserDataDirArgument, StringComparison.Ordinal));
227229
if (string.IsNullOrEmpty(userDataDirOption))
228230
{
229-
if (string.IsNullOrEmpty(options.UserDataDir))
230-
{
231-
tempUserDataDir = new TempDirectory();
232-
chromiumArgs.Add($"{UserDataDirArgument}={tempUserDataDir.Path.Quote()}");
233-
}
234-
else
235-
{
236-
chromiumArgs.Add($"{UserDataDirArgument}={options.UserDataDir.Quote()}");
237-
}
231+
tempUserDataDir = new TempDirectory();
232+
chromiumArgs.Add($"{UserDataDirArgument}={tempUserDataDir.Path.Quote()}");
238233
}
239-
else
234+
235+
return (chromiumArgs, tempUserDataDir);
236+
}
237+
238+
internal static string[] GetDefaultArgs(LaunchOptions options)
239+
{
240+
var chromeArguments = new List<string>(DefaultArgs);
241+
242+
if (!string.IsNullOrEmpty(options.UserDataDir))
240243
{
241-
options.UserDataDir = userDataDirOption.Replace($"{UserDataDirArgument}=", string.Empty).UnQuote();
244+
chromeArguments.Add($"{UserDataDirArgument}={options.UserDataDir.Quote()}");
242245
}
243-
244246
if (options.Devtools)
245247
{
246-
chromiumArgs.Add("--auto-open-devtools-for-tabs");
247-
options.Headless = false;
248+
chromeArguments.Add("--auto-open-devtools-for-tabs");
248249
}
249-
250250
if (options.Headless)
251251
{
252-
chromiumArgs.AddRange(new[]{
252+
chromeArguments.AddRange(new[]{
253253
"--headless",
254-
"--disable-gpu",
255254
"--hide-scrollbars",
256255
"--mute-audio"
257256
});
257+
if (BrowserFetcher.GetCurrentPlatform() == Platform.Win32)
258+
{
259+
chromeArguments.Add("--disable-gpu");
260+
}
258261
}
259262

260263
if (options.Args.All(arg => arg.StartsWith("-", StringComparison.Ordinal)))
261264
{
262-
chromiumArgs.Add("about:blank");
263-
}
264-
265-
if (options.Args.Any())
266-
{
267-
chromiumArgs.AddRange(options.Args);
265+
chromeArguments.Add("about:blank");
268266
}
269267

270-
return (chromiumArgs, tempUserDataDir);
268+
chromeArguments.AddRange(options.Args);
269+
return chromeArguments.ToArray();
271270
}
272271

273272
private static void SetEnvVariables(IDictionary<string, string> environment, IDictionary<string, string> customEnv, IDictionary realEnv)
@@ -601,12 +600,7 @@ private class ExitingState : State
601600
{
602601
public Task EnterFromAsync(ChromiumProcess p, State fromState, TimeSpan timeout)
603602
{
604-
if (!TryEnter(p, fromState))
605-
{
606-
return p._currentState.ExitAsync(p, timeout);
607-
}
608-
609-
return ExitAsync(p, timeout);
603+
return !TryEnter(p, fromState) ? p._currentState.ExitAsync(p, timeout) : ExitAsync(p, timeout);
610604
}
611605

612606
public override async Task ExitAsync(ChromiumProcess p, TimeSpan timeout)

lib/PuppeteerSharp/ConnectOptions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,11 @@ public class ConnectOptions : IBrowserOptions, IConnectionOptions
4141
/// Optional factory for <see cref="WebSocket"/> implementations.
4242
/// </summary>
4343
public Func<Uri, IConnectionOptions, CancellationToken, Task<WebSocket>> WebSocketFactory { get; set; }
44+
45+
/// <summary>
46+
/// Gets or sets the default Viewport.
47+
/// </summary>
48+
/// <value>The default Viewport.</value>
49+
public ViewPortOptions DefaultViewport { get; set; } = ViewPortOptions.Default;
4450
}
4551
}

lib/PuppeteerSharp/IBrowserOptions.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ public interface IBrowserOptions
1111
bool IgnoreHTTPSErrors { get; }
1212

1313
/// <summary>
14-
/// If set to true, sets Headless = false, otherwise, enables automation.
14+
/// Gets or sets the default Viewport.
1515
/// </summary>
16-
bool AppMode { get; }
16+
/// <value>The default Viewport.</value>
17+
ViewPortOptions DefaultViewport { get; set; }
1718
}
18-
}
19+
}

lib/PuppeteerSharp/LaunchOptions.cs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,13 @@ namespace PuppeteerSharp
1111
/// </summary>
1212
public class LaunchOptions : IBrowserOptions, IConnectionOptions
1313
{
14+
private string[] _ignoredDefaultArgs;
15+
1416
/// <summary>
1517
/// Whether to ignore HTTPS errors during navigation. Defaults to false.
1618
/// </summary>
1719
public bool IgnoreHTTPSErrors { get; set; }
1820

19-
/// <summary>
20-
/// If set to true, sets Headless = false, otherwise, enables automation.
21-
/// </summary>
22-
/// <remarks>
23-
/// AppMode won't neither add the argument '--remote-debugging-pipe' nor implement Pipes
24-
/// due to limitations in .NET see <see href="https://github.com/dotnet/corefx/issues/30575"/>
25-
/// </remarks>
26-
public bool AppMode { get; set; }
27-
2821
/// <summary>
2922
/// Whether to run browser in headless mode. Defaults to true unless the devtools option is true.
3023
/// </summary>
@@ -82,14 +75,33 @@ public class LaunchOptions : IBrowserOptions, IConnectionOptions
8275
public bool LogProcess { get; set; }
8376

8477
/// <summary>
85-
/// Do not use it. Dangerous option; use with care. Defaults to false.
78+
/// If <c>true</c>, then do not use <see cref="Puppeteer.DefaultArgs"/>.
79+
/// Dangerous option; use with care. Defaults to <c>false</c>.
8680
/// </summary>
87-
/// <value><c>true</c> if ignore default arguments; otherwise, <c>false</c>.</value>
8881
public bool IgnoreDefaultArgs { get; set; }
8982

83+
/// <summary>
84+
/// if <see cref="IgnoreDefaultArgs"/> is set to <c>false</c> this list will be used to filter <see cref="Puppeteer.DefaultArgs"/>
85+
/// </summary>
86+
public string[] IgnoredDefaultArgs
87+
{
88+
get => _ignoredDefaultArgs;
89+
set
90+
{
91+
IgnoreDefaultArgs = true;
92+
_ignoredDefaultArgs = value;
93+
}
94+
}
95+
9096
/// <summary>
9197
/// Optional factory for <see cref="WebSocket"/> implementations.
9298
/// </summary>
9399
public Func<Uri, IConnectionOptions, CancellationToken, Task<WebSocket>> WebSocketFactory { get; set; }
100+
101+
/// <summary>
102+
/// Gets or sets the default Viewport.
103+
/// </summary>
104+
/// <value>The default Viewport.</value>
105+
public ViewPortOptions DefaultViewport { get; set; } = ViewPortOptions.Default;
94106
}
95107
}

0 commit comments

Comments
 (0)