Skip to content

Commit 9f464b2

Browse files
authored
Move more things to emulation manager (#2442)
* Move more things to emulation manager * format * some firefox fixes
1 parent f149fa9 commit 9f464b2

File tree

5 files changed

+154
-124
lines changed

5 files changed

+154
-124
lines changed

lib/PuppeteerSharp/Browser.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,12 @@ internal async Task<IPage> CreatePageInContextAsync(string contextId)
327327

328328
if (contextId != null)
329329
{
330-
createTargetRequest.BrowserContextId = contextId;
330+
// We don't have this code in upstream.
331+
// Puppeteer sends a number if the contextId is a number, even if the typing says that it should be a string.
332+
// It seems that firefox ignores the contextId if it's not a number. Which is what Firefox sent back.
333+
createTargetRequest.BrowserContextId = int.TryParse(contextId, out var contextIdAsNumber)
334+
? contextIdAsNumber
335+
: contextId;
331336
}
332337

333338
var targetId = (await Connection.SendAsync<TargetCreateTargetResponse>("Target.createTarget", createTargetRequest)
Lines changed: 125 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Threading.Tasks;
34
using PuppeteerSharp.Media;
45
using PuppeteerSharp.Messaging;
@@ -8,37 +9,80 @@ namespace PuppeteerSharp
89
internal class EmulationManager
910
{
1011
private CDPSession _client;
11-
private bool _hasTouch;
1212
private bool _emulatingMobile;
13+
private bool _hasTouch;
1314

1415
public EmulationManager(CDPSession client)
1516
{
1617
_client = client;
1718
}
1819

20+
public bool JavascriptEnabled { get; private set; } = true;
21+
1922
internal void UpdateClient(CDPSession client) => _client = client;
2023

24+
internal async Task EmulateTimezoneAsync(string timezoneId)
25+
{
26+
try
27+
{
28+
await _client.SendAsync(
29+
"Emulation.setTimezoneOverride",
30+
new EmulateTimezoneRequest { TimezoneId = timezoneId ?? string.Empty, }).ConfigureAwait(false);
31+
}
32+
catch (Exception ex) when (ex.Message.Contains("Invalid timezone"))
33+
{
34+
throw new PuppeteerException($"Invalid timezone ID: {timezoneId}");
35+
}
36+
}
37+
38+
internal Task EmulateVisionDeficiencyAsync(VisionDeficiency type)
39+
=> _client.SendAsync(
40+
"Emulation.setEmulatedVisionDeficiency",
41+
new EmulationSetEmulatedVisionDeficiencyRequest { Type = type, });
42+
43+
internal Task EmulateCPUThrottlingAsync(decimal? factor = null)
44+
{
45+
if (factor is < 1)
46+
{
47+
throw new ArgumentException("Throttling rate should be greater or equal to 1", nameof(factor));
48+
}
49+
50+
return _client.SendAsync(
51+
"Emulation.setCPUThrottlingRate",
52+
new EmulationSetCPUThrottlingRateRequest { Rate = factor ?? 1, });
53+
}
54+
55+
internal async Task EmulateIdleStateAsync(EmulateIdleOverrides overrides = null)
56+
{
57+
if (overrides != null)
58+
{
59+
await _client.SendAsync(
60+
"Emulation.setIdleOverride",
61+
new EmulationSetIdleOverrideRequest
62+
{
63+
IsUserActive = overrides.IsUserActive,
64+
IsScreenUnlocked = overrides.IsScreenUnlocked,
65+
}).ConfigureAwait(false);
66+
}
67+
else
68+
{
69+
await _client.SendAsync("Emulation.clearIdleOverride").ConfigureAwait(false);
70+
}
71+
}
72+
2173
internal async Task<bool> EmulateViewportAsync(ViewPortOptions viewport)
2274
{
2375
var mobile = viewport.IsMobile;
2476
var width = viewport.Width;
2577
var height = viewport.Height;
2678
var deviceScaleFactor = viewport.DeviceScaleFactor;
2779
var screenOrientation = viewport.IsLandscape
28-
? new ScreenOrientation
29-
{
30-
Angle = 90,
31-
Type = ScreenOrientationType.LandscapePrimary,
32-
}
33-
: new ScreenOrientation
34-
{
35-
Angle = 0,
36-
Type = ScreenOrientationType.PortraitPrimary,
37-
};
80+
? new ScreenOrientation { Angle = 90, Type = ScreenOrientationType.LandscapePrimary, }
81+
: new ScreenOrientation { Angle = 0, Type = ScreenOrientationType.PortraitPrimary, };
3882
var hasTouch = viewport.HasTouch;
3983

40-
await Task.WhenAll(new Task[]
41-
{
84+
await Task.WhenAll(
85+
[
4286
_client.SendAsync("Emulation.setDeviceMetricsOverride", new EmulationSetDeviceMetricsOverrideRequest
4387
{
4488
Mobile = mobile,
@@ -47,16 +91,79 @@ await Task.WhenAll(new Task[]
4791
DeviceScaleFactor = deviceScaleFactor,
4892
ScreenOrientation = screenOrientation,
4993
}),
50-
_client.SendAsync("Emulation.setTouchEmulationEnabled", new EmulationSetTouchEmulationEnabledRequest
51-
{
52-
Enabled = hasTouch,
53-
}),
54-
}).ConfigureAwait(false);
94+
_client.SendAsync(
95+
"Emulation.setTouchEmulationEnabled",
96+
new EmulationSetTouchEmulationEnabledRequest { Enabled = hasTouch, }),
97+
]).ConfigureAwait(false);
5598

5699
var reloadNeeded = _emulatingMobile != mobile || _hasTouch != hasTouch;
57100
_emulatingMobile = mobile;
58101
_hasTouch = hasTouch;
59102
return reloadNeeded;
60103
}
104+
105+
internal Task EmulateMediaTypeAsync(MediaType type)
106+
=> _client.SendAsync(
107+
"Emulation.setEmulatedMedia",
108+
new EmulationSetEmulatedMediaTypeRequest { Media = type });
109+
110+
internal Task EmulateMediaFeaturesAsync(IEnumerable<MediaFeatureValue> features)
111+
=> _client.SendAsync(
112+
"Emulation.setEmulatedMedia",
113+
new EmulationSetEmulatedMediaFeatureRequest { Features = features });
114+
115+
internal Task SetGeolocationAsync(GeolocationOption options)
116+
{
117+
if (options == null)
118+
{
119+
throw new ArgumentNullException(nameof(options));
120+
}
121+
122+
if (options.Longitude < -180 || options.Longitude > 180)
123+
{
124+
throw new ArgumentException($"Invalid longitude '{options.Longitude}': precondition - 180 <= LONGITUDE <= 180 failed.");
125+
}
126+
127+
if (options.Latitude < -90 || options.Latitude > 90)
128+
{
129+
throw new ArgumentException($"Invalid latitude '{options.Latitude}': precondition - 90 <= LATITUDE <= 90 failed.");
130+
}
131+
132+
if (options.Accuracy < 0)
133+
{
134+
throw new ArgumentException($"Invalid accuracy '{options.Accuracy}': precondition 0 <= ACCURACY failed.");
135+
}
136+
137+
return _client.SendAsync("Emulation.setGeolocationOverride", options);
138+
}
139+
140+
internal Task ResetDefaultBackgroundColorAsync()
141+
=> _client.SendAsync("Emulation.setDefaultBackgroundColorOverride");
142+
143+
internal Task SetTransparentBackgroundColorAsync()
144+
=> _client.SendAsync("Emulation.setDefaultBackgroundColorOverride", new EmulationSetDefaultBackgroundColorOverrideRequest
145+
{
146+
Color = new EmulationSetDefaultBackgroundColorOverrideColor
147+
{
148+
R = 0,
149+
G = 0,
150+
B = 0,
151+
A = 0,
152+
},
153+
});
154+
155+
internal Task SetJavaScriptEnabledAsync(bool enabled)
156+
{
157+
if (enabled == JavascriptEnabled)
158+
{
159+
return Task.CompletedTask;
160+
}
161+
162+
JavascriptEnabled = enabled;
163+
return _client.SendAsync("Emulation.setScriptExecutionDisabled", new EmulationSetScriptExecutionDisabledRequest
164+
{
165+
Value = !enabled,
166+
});
167+
}
61168
}
62169
}

lib/PuppeteerSharp/IPage.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,11 @@ public interface IPage : IDisposable, IAsyncDisposable
277277
/// </summary>
278278
WebWorker[] Workers { get; }
279279

280+
/// <summary>
281+
/// If the page has JavaScript enabled.
282+
/// </summary>
283+
bool IsJavaScriptEnabled { get; }
284+
280285
/// <summary>
281286
/// Adds a <c><![CDATA[<script>]]></c> tag into the page with the desired url or content.
282287
/// </summary>

lib/PuppeteerSharp/Messaging/TargetCreateTargetRequest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ internal class TargetCreateTargetRequest
44
{
55
public string Url { get; set; }
66

7-
public string BrowserContextId { get; set; }
7+
public object BrowserContextId { get; set; }
88
}
99
}

0 commit comments

Comments
 (0)