11using System ;
2+ using System . Collections . Generic ;
23using System . Threading . Tasks ;
34using PuppeteerSharp . Media ;
45using 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}
0 commit comments