-
-
Notifications
You must be signed in to change notification settings - Fork 745
Expand file tree
/
Copy pathWebContents.cs
More file actions
402 lines (349 loc) · 13.1 KB
/
WebContents.cs
File metadata and controls
402 lines (349 loc) · 13.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
using System;
using System.Threading.Tasks;
using ElectronNET.API.Entities;
using ElectronNET.Common;
// ReSharper disable InconsistentNaming
namespace ElectronNET.API;
/// <summary>
/// Render and control web pages.
/// </summary>
public class WebContents : ApiBase
{
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketTaskMessageNameTypes SocketTaskMessageNameType => SocketTaskMessageNameTypes.DashesLowerFirst;
protected override SocketEventNameTypes SocketEventNameType => SocketEventNameTypes.CamelCase;
/// <summary>
/// Gets the identifier.
/// </summary>
/// <value>
/// The identifier.
/// </value>
public override int Id { get; protected set; }
/// <summary>
/// Manage browser sessions, cookies, cache, proxy settings, etc.
/// </summary>
public Session Session { get; internal set; }
/// <summary>
/// Emitted when the renderer process crashes or is killed.
/// </summary>
public event Action<bool> OnCrashed
{
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
/// <summary>
/// Emitted when the navigation is done, i.e. the spinner of the tab has
/// stopped spinning, and the onload event was dispatched.
/// </summary>
public event Action OnDidFinishLoad
{
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
/// <summary>
/// Emitted when any frame (including main) starts navigating.
/// </summary>
public event Action<string> OnDidStartNavigation
{
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
/// <summary>
/// Emitted when a main frame navigation is done.
/// This event is not emitted for in-page navigations, such as clicking anchor links or updating the window.location.hash. Use did-navigate-in-page event for this purpose.
/// </summary>
public event Action<OnDidNavigateInfo> OnDidNavigate
{
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
/// <summary>
/// Emitted when a server side redirect occurs during navigation. For example a 302 redirect.
/// This event will be emitted after OnDidStartNavigation and always before the OnDidRedirectNavigation event for the same navigation.
/// </summary>
public event Action<string> OnWillRedirect
{
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
/// <summary>
/// Emitted after a server side redirect occurs during navigation. For example a 302 redirect.
/// </summary>
public event Action<string> OnDidRedirectNavigation
{
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
/// <summary>
/// This event is like OnDidFinishLoad but emitted when the load failed.
/// </summary>
public event Action<OnDidFailLoadInfo> OnDidFailLoad
{
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
/// <summary>
/// Emitted when an input event is sent to the WebContents.
/// </summary>
public event Action<InputEvent> InputEvent
{
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
/// <summary>
/// Emitted when the document in the top-level frame is loaded.
/// </summary>
public event Action OnDomReady
{
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
internal WebContents(int id)
{
Id = id;
Session = new Session(id);
}
/// <summary>
/// Opens the devtools.
/// </summary>
public void OpenDevTools()
{
BridgeConnector.Socket.Emit("webContents-openDevTools", Id);
}
/// <summary>
/// Opens the devtools.
/// </summary>
/// <param name="openDevToolsOptions"></param>
public void OpenDevTools(OpenDevToolsOptions openDevToolsOptions)
{
BridgeConnector.Socket.Emit("webContents-openDevTools", Id, openDevToolsOptions);
}
/// <summary>
/// Toggles the devtools.
/// </summary>
public void ToggleDevTools()
{
BridgeConnector.Socket.Emit("webContents-toggleDevTools", Id);
}
/// <summary>
/// Closes the devtools.
/// </summary>
public void CloseDevTools()
{
BridgeConnector.Socket.Emit("webContents-closeDevTools", Id);
}
/// <summary>
/// Returns boolean - Whether the devtools is opened.
/// </summary>
/// <returns></returns>
public bool IsDevToolsOpened()
{
return Task.Run(() => InvokeAsync<bool>()).Result;
}
/// <summary>
/// Returns boolean - Whether the devtools view is focused.
/// </summary>
/// <returns></returns>
public bool IsDevToolsFocused()
{
return Task.Run(() => InvokeAsync<bool>()).Result;
}
/// <summary>
/// Get system printers.
/// </summary>
/// <returns>printers</returns>
public Task<PrinterInfo[]> GetPrintersAsync() => this.InvokeAsyncWithTimeout<PrinterInfo[]>(8.seconds());
/// <summary>
/// Prints window's web page.
/// </summary>
/// <param name="options"></param>
/// <returns>success</returns>
public Task<bool> PrintAsync(PrintOptions options) => this.InvokeAsync<bool>(options);
/// <summary>
/// Prints window's web page.
/// </summary>
/// <returns>success</returns>
public Task<bool> PrintAsync() => this.InvokeAsync<bool>(string.Empty);
/// <summary>
/// Prints window's web page as PDF with Chromium's preview printing custom
/// settings.The landscape will be ignored if @page CSS at-rule is used in the web page.
/// By default, an empty options will be regarded as: Use page-break-before: always;
/// CSS style to force to print to a new page.
/// </summary>
/// <param name="path"></param>
/// <param name="options"></param>
/// <returns>success</returns>
public Task<bool> PrintToPDFAsync(string path, PrintToPDFOptions options = null)
{
var tcs = new TaskCompletionSource<bool>();
BridgeConnector.Socket.Once<bool>("webContents-printToPDF-completed", tcs.SetResult);
if (options == null)
{
BridgeConnector.Socket.Emit("webContents-printToPDF", Id, "", path);
}
else
{
BridgeConnector.Socket.Emit("webContents-printToPDF", Id, options, path);
}
return tcs.Task;
}
/// <summary>
/// Evaluates script code in page.
/// </summary>
/// <param name="code">The code to execute.</param>
/// <param name="userGesture">if set to <c>true</c> simulate a user gesture.</param>
/// <returns>The result of the executed code.</returns>
/// <remarks>
/// <para>
/// In the browser window some HTML APIs like `requestFullScreen` can only be
/// invoked by a gesture from the user. Setting `userGesture` to `true` will remove
/// this limitation.
/// </para>
/// <para>
/// Code execution will be suspended until web page stop loading.
/// </para>
/// </remarks>
public Task<T> ExecuteJavaScriptAsync<T>(string code, bool userGesture = false)
{
var tcs = new TaskCompletionSource<T>();
BridgeConnector.Socket.Once<T>("webContents-executeJavaScript-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("webContents-executeJavaScript", Id, code, userGesture);
return tcs.Task;
}
/// <summary>
/// Is used to get the Url of the loaded page.
/// It's usefull if a web-server redirects you and you need to know where it redirects. For instance, It's useful in case of Implicit Authorization.
/// </summary>
/// <returns>URL of the loaded page</returns>
public Task<string> GetUrl()
{
var tcs = new TaskCompletionSource<string>();
BridgeConnector.Socket.Once<string>("webContents-getUrl" + Id, tcs.SetResult);
BridgeConnector.Socket.Emit("webContents-getUrl", Id);
return tcs.Task;
}
/// <summary>
/// The async method will resolve when the page has finished loading,
/// and rejects if the page fails to load.
///
/// A noop rejection handler is already attached, which avoids unhandled rejection
/// errors.
///
/// Loads the `url` in the window. The `url` must contain the protocol prefix, e.g.
/// the `http://` or `file://`. If the load should bypass http cache then use the
/// `pragma` header to achieve it.
/// </summary>
/// <param name="url"></param>
public Task LoadURLAsync(string url)
{
return LoadURLAsync(url, new LoadURLOptions());
}
/// <summary>
/// The async method will resolve when the page has finished loading,
/// and rejects if the page fails to load.
///
/// A noop rejection handler is already attached, which avoids unhandled rejection
/// errors.
///
/// Loads the `url` in the window. The `url` must contain the protocol prefix, e.g.
/// the `http://` or `file://`. If the load should bypass http cache then use the
/// `pragma` header to achieve it.
/// </summary>
/// <param name="url"></param>
/// <param name="options"></param>
public Task LoadURLAsync(string url, LoadURLOptions options)
{
var tcs = new TaskCompletionSource();
BridgeConnector.Socket.Once("webContents-loadURL-complete" + Id, () =>
{
BridgeConnector.Socket.Off("webContents-loadURL-error" + Id);
tcs.SetResult();
});
BridgeConnector.Socket.Once<string>("webContents-loadURL-error" + Id, (error) => { tcs.SetException(new InvalidOperationException(error)); });
BridgeConnector.Socket.Emit("webContents-loadURL", Id, url, options);
return tcs.Task;
}
/// <summary>
/// Inserts CSS into the web page.
/// See: https://www.electronjs.org/docs/api/web-contents#contentsinsertcsscss-options
/// Works for both BrowserWindows and BrowserViews.
/// </summary>
/// <param name="isBrowserWindow">Whether the webContents belong to a BrowserWindow or not (the other option is a BrowserView)</param>
/// <param name="path">Absolute path to the CSS file location</param>
public void InsertCSS(bool isBrowserWindow, string path)
{
BridgeConnector.Socket.Emit("webContents-insertCSS", Id, isBrowserWindow, path);
}
/// <summary>
/// Returns number - The current zoom factor.
/// </summary>
/// <returns></returns>
public Task<double> GetZoomFactorAsync() => InvokeAsync<double>();
/// <summary>
/// Changes the zoom factor to the specified factor.
/// Zoom factor is zoom percent divided by 100, so 300% = 3.0.
/// The factor must be greater than 0.0.
/// </summary>
/// <param name="factor"></param>
public void SetZoomFactor(double factor)
{
BridgeConnector.Socket.Emit("webContents-setZoomFactor", Id, factor);
}
/// <summary>
/// Returns number - The current zoom level.
/// </summary>
/// <returns></returns>
public Task<int> GetZoomLevelAsync() => InvokeAsync<int>();
/// <summary>
/// Changes the zoom level to the specified level.
/// The original size is 0 and each increment above or below represents zooming 20% larger or smaller to default limits of 300% and 50% of original size, respectively.
/// </summary>
/// <param name="level"></param>
public void SetZoomLevel(int level)
{
BridgeConnector.Socket.Emit("webContents-setZoomLevel", Id, level);
}
/// <summary>
/// Sets the maximum and minimum pinch-to-zoom level.
/// </summary>
/// <param name="minimumLevel"></param>
/// <param name="maximumLevel"></param>
public Task SetVisualZoomLevelLimitsAsync(int minimumLevel, int maximumLevel)
{
var tcs = new TaskCompletionSource();
BridgeConnector.Socket.Once("webContents-setVisualZoomLevelLimits-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("webContents-setVisualZoomLevelLimits", Id, minimumLevel, maximumLevel);
return tcs.Task;
}
/// <summary>
/// Returns boolean - Whether this page has been muted.
/// </summary>
/// <returns></returns>
public Task<bool> IsAudioMutedAsync() => InvokeAsync<bool>();
/// <summary>
/// Returns boolean - Whether audio is currently playing.
/// </summary>
/// <returns></returns>
public Task<bool> IsCurrentlyAudibleAsync() => InvokeAsync<bool>();
/// <summary>
/// Mute the audio on the current web page.
/// </summary>
/// <param name="muted"></param>
public void SetAudioMuted(bool muted)
{
BridgeConnector.Socket.Emit("webContents-setAudioMuted", Id, muted);
}
/// <summary>
/// Returns string - The user agent for this web page.
/// </summary>
/// <returns></returns>
public Task<string> GetUserAgentAsync() => InvokeAsyncWithTimeout<string>(3.seconds());
/// <summary>
/// Overrides the user agent for this web page.
/// </summary>
/// <param name="userAgent"></param>
public void SetUserAgent(string userAgent)
{
BridgeConnector.Socket.Emit("webContents-setUserAgent", Id, userAgent);
}
}