PageRenderTime 35ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/CefSharp/WebBrowserExtensions.cs

https://github.com/cefsharp/CefSharp
C# | 1611 lines | 716 code | 208 blank | 687 comment | 62 complexity | 80ee067feb3def19d73000f9d86d70a1 MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. // Copyright © 2015 The CefSharp Authors. All rights reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
  4. using System;
  5. using System.Collections.Specialized;
  6. using System.ComponentModel;
  7. using System.Globalization;
  8. using System.IO;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. using CefSharp.Internals;
  12. using CefSharp.Web;
  13. namespace CefSharp
  14. {
  15. /// <summary>
  16. /// WebBrowser extensions - These methods make performing common tasks easier.
  17. /// </summary>
  18. public static class WebBrowserExtensions
  19. {
  20. public const string BrowserNullExceptionString = "IBrowser instance is null. Browser has likely not finished initializing or is in the process of disposing.";
  21. public const string BrowserHostNullExceptionString = "IBrowserHost instance is null. Browser has likely not finished initializing or is in the process of disposing.";
  22. public const string FrameNullExceptionString = "IFrame instance is null. Browser has likely not finished initializing or is in the process of disposing.";
  23. #region Legacy Javascript Binding
  24. /// <summary>
  25. /// Registers a Javascript object in this specific browser instance.
  26. /// </summary>
  27. /// <param name="webBrowser">The browser to perform the registering on.</param>
  28. /// <param name="name">The name of the object. (e.g. "foo", if you want the object to be accessible as window.foo).</param>
  29. /// <param name="objectToBind">The object to be made accessible to Javascript.</param>
  30. /// <param name="options">(Optional) binding options - camelCaseJavascriptNames default to true.</param>
  31. /// <exception cref="Exception">Browser is already initialized. RegisterJsObject must be +
  32. /// called before the underlying CEF browser is created.</exception>
  33. [Obsolete("This method has been removed, see https://github.com/cefsharp/CefSharp/issues/2990 for details on migrating your code.")]
  34. [EditorBrowsable(EditorBrowsableState.Never)]
  35. public static void RegisterJsObject(this IWebBrowser webBrowser, string name, object objectToBind, BindingOptions options = null)
  36. {
  37. throw new NotImplementedException("This method has been removed, see https://github.com/cefsharp/CefSharp/issues/2990 for details on migrating your code.");
  38. }
  39. /// <summary>
  40. /// <para>Asynchronously registers a Javascript object in this specific browser instance.</para>
  41. /// <para>Only methods of the object will be availabe.</para>
  42. /// </summary>
  43. /// <param name="webBrowser">The browser to perform the registering on</param>
  44. /// <param name="name">The name of the object. (e.g. "foo", if you want the object to be accessible as window.foo).</param>
  45. /// <param name="objectToBind">The object to be made accessible to Javascript.</param>
  46. /// <param name="options">binding options - camelCaseJavascriptNames default to true </param>
  47. /// <exception cref="Exception">Browser is already initialized. RegisterJsObject must be +
  48. /// called before the underlying CEF browser is created.</exception>
  49. /// <remarks>The registered methods can only be called in an async way, they will all return immediately and the resulting
  50. /// object will be a standard javascript Promise object which is usable to wait for completion or failure.</remarks>
  51. [Obsolete("This method has been removed, see https://github.com/cefsharp/CefSharp/issues/2990 for details on migrating your code.")]
  52. [EditorBrowsable(EditorBrowsableState.Never)]
  53. public static void RegisterAsyncJsObject(this IWebBrowser webBrowser, string name, object objectToBind, BindingOptions options = null)
  54. {
  55. throw new NotImplementedException("This method has been removed, see https://github.com/cefsharp/CefSharp/issues/2990 for details on migrating your code.");
  56. }
  57. #endregion
  58. /// <summary>
  59. /// Returns the main (top-level) frame for the browser window.
  60. /// </summary>
  61. /// <param name="browser">the ChromiumWebBrowser instance.</param>
  62. /// <returns> the main frame. </returns>
  63. public static IFrame GetMainFrame(this IChromiumWebBrowserBase browser)
  64. {
  65. var cefBrowser = browser.BrowserCore;
  66. cefBrowser.ThrowExceptionIfBrowserNull();
  67. return cefBrowser.MainFrame;
  68. }
  69. /// <summary>
  70. /// Returns the focused frame for the browser window.
  71. /// </summary>
  72. /// <param name="browser">the ChromiumWebBrowser instance.</param>
  73. /// <returns>the focused frame.</returns>
  74. public static IFrame GetFocusedFrame(this IChromiumWebBrowserBase browser)
  75. {
  76. var cefBrowser = browser.BrowserCore;
  77. cefBrowser.ThrowExceptionIfBrowserNull();
  78. return cefBrowser.FocusedFrame;
  79. }
  80. /// <summary>
  81. /// Execute Undo on the focused frame.
  82. /// </summary>
  83. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  84. public static void Undo(this IChromiumWebBrowserBase browser)
  85. {
  86. browser.BrowserCore.Undo();
  87. }
  88. /// <summary>
  89. /// Execute Undo on the focused frame.
  90. /// </summary>
  91. /// <param name="browser">The IBrowser instance this method extends.</param>
  92. public static void Undo(this IBrowser browser)
  93. {
  94. browser.ThrowExceptionIfBrowserNull();
  95. using (var frame = browser.FocusedFrame)
  96. {
  97. ThrowExceptionIfFrameNull(frame);
  98. frame.Undo();
  99. }
  100. }
  101. /// <summary>
  102. /// Execute Redo on the focused frame.
  103. /// </summary>
  104. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  105. public static void Redo(this IChromiumWebBrowserBase browser)
  106. {
  107. browser.BrowserCore.Redo();
  108. }
  109. /// <summary>
  110. /// Execute Redo on the focused frame.
  111. /// </summary>
  112. /// <param name="browser">The IBrowser instance this method extends.</param>
  113. public static void Redo(this IBrowser browser)
  114. {
  115. browser.ThrowExceptionIfBrowserNull();
  116. using (var frame = browser.FocusedFrame)
  117. {
  118. ThrowExceptionIfFrameNull(frame);
  119. frame.Redo();
  120. }
  121. }
  122. /// <summary>
  123. /// Execute Cut on the focused frame.
  124. /// </summary>
  125. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  126. public static void Cut(this IChromiumWebBrowserBase browser)
  127. {
  128. browser.BrowserCore.Cut();
  129. }
  130. /// <summary>
  131. /// Execute Cut on the focused frame.
  132. /// </summary>
  133. /// <param name="browser">The IBrowser instance this method extends.</param>
  134. public static void Cut(this IBrowser browser)
  135. {
  136. browser.ThrowExceptionIfBrowserNull();
  137. using (var frame = browser.FocusedFrame)
  138. {
  139. ThrowExceptionIfFrameNull(frame);
  140. frame.Cut();
  141. }
  142. }
  143. /// <summary>
  144. /// Execute Copy on the focused frame.
  145. /// </summary>
  146. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  147. public static void Copy(this IChromiumWebBrowserBase browser)
  148. {
  149. browser.BrowserCore.Copy();
  150. }
  151. /// <summary>
  152. /// Execute Copy on the focused frame.
  153. /// </summary>
  154. /// <param name="browser">The IBrowser instance this method extends.</param>
  155. public static void Copy(this IBrowser browser)
  156. {
  157. browser.ThrowExceptionIfBrowserNull();
  158. using (var frame = browser.FocusedFrame)
  159. {
  160. ThrowExceptionIfFrameNull(frame);
  161. frame.Copy();
  162. }
  163. }
  164. /// <summary>
  165. /// Execute Paste on the focused frame.
  166. /// </summary>
  167. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  168. public static void Paste(this IChromiumWebBrowserBase browser)
  169. {
  170. browser.BrowserCore.Paste();
  171. }
  172. /// <summary>
  173. /// Execute Paste on the focused frame.
  174. /// </summary>
  175. /// <param name="browser">The IBrowser instance this method extends.</param>
  176. public static void Paste(this IBrowser browser)
  177. {
  178. browser.ThrowExceptionIfBrowserNull();
  179. using (var frame = browser.FocusedFrame)
  180. {
  181. ThrowExceptionIfFrameNull(frame);
  182. frame.Paste();
  183. }
  184. }
  185. /// <summary>
  186. /// Execute Delete on the focused frame.
  187. /// </summary>
  188. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  189. public static void Delete(this IChromiumWebBrowserBase browser)
  190. {
  191. browser.BrowserCore.Delete();
  192. }
  193. /// <summary>
  194. /// Execute Delete on the focused frame.
  195. /// </summary>
  196. /// <param name="browser">The IBrowser instance this method extends.</param>
  197. public static void Delete(this IBrowser browser)
  198. {
  199. browser.ThrowExceptionIfBrowserNull();
  200. using (var frame = browser.FocusedFrame)
  201. {
  202. ThrowExceptionIfFrameNull(frame);
  203. frame.Delete();
  204. }
  205. }
  206. /// <summary>
  207. /// Execute SelectAll on the focused frame.
  208. /// </summary>
  209. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  210. public static void SelectAll(this IChromiumWebBrowserBase browser)
  211. {
  212. browser.BrowserCore.SelectAll();
  213. }
  214. /// <summary>
  215. /// Execute SelectAll on the focused frame.
  216. /// </summary>
  217. /// <param name="browser">The IBrowser instance this method extends.</param>
  218. public static void SelectAll(this IBrowser browser)
  219. {
  220. browser.ThrowExceptionIfBrowserNull();
  221. using (var frame = browser.FocusedFrame)
  222. {
  223. ThrowExceptionIfFrameNull(frame);
  224. frame.SelectAll();
  225. }
  226. }
  227. /// <summary>
  228. /// Opens up a new program window (using the default text editor) where the source code of the currently displayed web page is
  229. /// shown.
  230. /// </summary>
  231. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  232. public static void ViewSource(this IChromiumWebBrowserBase browser)
  233. {
  234. browser.BrowserCore.ViewSource();
  235. }
  236. /// <summary>
  237. /// Opens up a new program window (using the default text editor) where the source code of the currently displayed web page is
  238. /// shown.
  239. /// </summary>
  240. /// <param name="browser">The IBrowser instance this method extends.</param>
  241. public static void ViewSource(this IBrowser browser)
  242. {
  243. browser.ThrowExceptionIfBrowserNull();
  244. using (var frame = browser.MainFrame)
  245. {
  246. ThrowExceptionIfFrameNull(frame);
  247. frame.ViewSource();
  248. }
  249. }
  250. /// <summary>
  251. /// Retrieve the main frame's HTML source using a <see cref="Task{String}"/>.
  252. /// </summary>
  253. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  254. /// <returns>
  255. /// <see cref="Task{String}"/> that when executed returns the main frame source as a string.
  256. /// </returns>
  257. public static Task<string> GetSourceAsync(this IChromiumWebBrowserBase browser)
  258. {
  259. return browser.BrowserCore.GetSourceAsync();
  260. }
  261. /// <summary>
  262. /// Retrieve the main frame's HTML source using a <see cref="Task{String}"/>.
  263. /// </summary>
  264. /// <param name="browser">The IBrowser instance this method extends.</param>
  265. /// <returns>
  266. /// <see cref="Task{String}"/> that when executed returns the main frame source as a string.
  267. /// </returns>
  268. public static Task<string> GetSourceAsync(this IBrowser browser)
  269. {
  270. browser.ThrowExceptionIfBrowserNull();
  271. using (var frame = browser.FocusedFrame)
  272. {
  273. ThrowExceptionIfFrameNull(frame);
  274. return frame.GetSourceAsync();
  275. }
  276. }
  277. /// <summary>
  278. /// Retrieve the main frame's display text using a <see cref="Task{String}"/>.
  279. /// </summary>
  280. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  281. /// <returns>
  282. /// <see cref="Task{String}"/> that when executed returns the main frame display text as a string.
  283. /// </returns>
  284. public static Task<string> GetTextAsync(this IChromiumWebBrowserBase browser)
  285. {
  286. return browser.BrowserCore.GetTextAsync();
  287. }
  288. /// <summary>
  289. /// Retrieve the main frame's display text using a <see cref="Task{String}"/>.
  290. /// </summary>
  291. /// <param name="browser">The IBrowser instance this method extends.</param>
  292. /// <returns>
  293. /// <see cref="Task{String}"/> that when executed returns the main frame display text as a string.
  294. /// </returns>
  295. public static Task<string> GetTextAsync(this IBrowser browser)
  296. {
  297. browser.ThrowExceptionIfBrowserNull();
  298. using (var frame = browser.FocusedFrame)
  299. {
  300. ThrowExceptionIfFrameNull(frame);
  301. return frame.GetTextAsync();
  302. }
  303. }
  304. /// <summary>
  305. /// Download the file at url using <see cref="IDownloadHandler"/>.
  306. /// </summary>
  307. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  308. /// <param name="url">url to download</param>
  309. public static void StartDownload(this IChromiumWebBrowserBase browser, string url)
  310. {
  311. browser.BrowserCore.StartDownload(url);
  312. }
  313. /// <summary>
  314. /// Download the file at url using <see cref="IDownloadHandler"/>.
  315. /// </summary>
  316. /// <param name="browser">The IBrowser instance this method extends.</param>
  317. /// <param name="url">url to download</param>
  318. public static void StartDownload(this IBrowser browser, string url)
  319. {
  320. browser.ThrowExceptionIfBrowserNull();
  321. var host = browser.GetHost();
  322. ThrowExceptionIfBrowserHostNull(host);
  323. host.StartDownload(url);
  324. }
  325. /// <summary>
  326. /// See <see cref="IChromiumWebBrowserBase.LoadUrlAsync(string)"/> for details
  327. /// </summary>
  328. /// <param name="chromiumWebBrowser">ChromiumWebBrowser instance (cannot be null)</param>
  329. /// <summary>
  330. /// Load the <paramref name="url"/> in the main frame of the browser
  331. /// </summary>
  332. /// <param name="url">url to load</param>
  333. /// <returns>See <see cref="IChromiumWebBrowserBase.LoadUrlAsync(string)"/> for details</returns>
  334. public static Task<LoadUrlAsyncResponse> LoadUrlAsync(IChromiumWebBrowserBase chromiumWebBrowser, string url)
  335. {
  336. if(string.IsNullOrEmpty(url))
  337. {
  338. throw new ArgumentNullException(nameof(url));
  339. }
  340. var tcs = new TaskCompletionSource<LoadUrlAsyncResponse>();
  341. EventHandler<LoadErrorEventArgs> loadErrorHandler = null;
  342. EventHandler<LoadingStateChangedEventArgs> loadingStateChangeHandler = null;
  343. loadErrorHandler = (sender, args) =>
  344. {
  345. //Actions that trigger a download will raise an aborted error.
  346. //Generally speaking Aborted is safe to ignore
  347. if (args.ErrorCode == CefErrorCode.Aborted)
  348. {
  349. return;
  350. }
  351. //If LoadError was called then we'll remove both our handlers
  352. //as we won't need to capture LoadingStateChanged, we know there
  353. //was an error
  354. chromiumWebBrowser.LoadError -= loadErrorHandler;
  355. chromiumWebBrowser.LoadingStateChanged -= loadingStateChangeHandler;
  356. //Ensure our continuation is executed on the ThreadPool
  357. //For the .Net Core implementation we could use
  358. //TaskCreationOptions.RunContinuationsAsynchronously
  359. tcs.TrySetResultAsync(new LoadUrlAsyncResponse(args.ErrorCode, -1));
  360. };
  361. loadingStateChangeHandler = (sender, args) =>
  362. {
  363. //Wait for IsLoading = false
  364. if (!args.IsLoading)
  365. {
  366. //If LoadingStateChanged was called then we'll remove both our handlers
  367. //as LoadError won't be called, our site has loaded with a valid HttpStatusCode
  368. //HttpStatusCodes can still be for example 404, this is considered a successful request,
  369. //the server responded, it just didn't have the page you were after.
  370. chromiumWebBrowser.LoadError -= loadErrorHandler;
  371. chromiumWebBrowser.LoadingStateChanged -= loadingStateChangeHandler;
  372. var host = args.Browser.GetHost();
  373. var navEntry = host?.GetVisibleNavigationEntry();
  374. int statusCode = navEntry?.HttpStatusCode ?? -1;
  375. //By default 0 is some sort of error, we map that to -1
  376. //so that it's clearer that something failed.
  377. if (statusCode == 0)
  378. {
  379. statusCode = -1;
  380. }
  381. //Ensure our continuation is executed on the ThreadPool
  382. //For the .Net Core implementation we could use
  383. //TaskCreationOptions.RunContinuationsAsynchronously
  384. tcs.TrySetResultAsync(new LoadUrlAsyncResponse(CefErrorCode.None, statusCode));
  385. }
  386. };
  387. chromiumWebBrowser.LoadError += loadErrorHandler;
  388. chromiumWebBrowser.LoadingStateChanged += loadingStateChangeHandler;
  389. chromiumWebBrowser.LoadUrl(url);
  390. return tcs.Task;
  391. }
  392. /// <summary>
  393. /// Execute Javascript code in the context of this Browser. As the method name implies, the script will be executed
  394. /// asynchronously, and the method therefore returns before the script has actually been executed. This simple helper extension
  395. /// will encapsulate params in single quotes (unless int, uint, etc)
  396. /// </summary>
  397. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  398. /// <param name="methodName">The javascript method name to execute.</param>
  399. /// <param name="args">the arguments to be passed as params to the method. Args are encoded using
  400. /// <see cref="EncodeScriptParam"/>, you can provide a custom implementation if you require one.</param>
  401. public static void ExecuteScriptAsync(this IChromiumWebBrowserBase browser, string methodName, params object[] args)
  402. {
  403. browser.BrowserCore.ExecuteScriptAsync(methodName, args);
  404. }
  405. /// <summary>
  406. /// Execute Javascript code in the context of this WebBrowser. As the method name implies, the script will be executed
  407. /// asynchronously, and the method therefore returns before the script has actually been executed. This simple helper extension
  408. /// will encapsulate params in single quotes (unless int, uint, etc)
  409. /// </summary>
  410. /// <param name="browser">The IBrowser instance this method extends.</param>
  411. /// <param name="methodName">The javascript method name to execute.</param>
  412. /// <param name="args">the arguments to be passed as params to the method. Args are encoded using
  413. /// <see cref="EncodeScriptParam"/>, you can provide a custom implementation if you require one.</param>
  414. public static void ExecuteScriptAsync(this IBrowser browser, string methodName, params object[] args)
  415. {
  416. var script = GetScriptForJavascriptMethodWithArgs(methodName, args);
  417. browser.ExecuteScriptAsync(script);
  418. }
  419. /// <summary>
  420. /// Execute Javascript in the context of this Browsers Main Frame. As the method name implies, the script will be executed
  421. /// asynchronously, and the method therefore returns before the script has actually been executed.
  422. /// </summary>
  423. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  424. /// <param name="script">The Javascript code that should be executed.</param>
  425. public static void ExecuteScriptAsync(this IChromiumWebBrowserBase browser, string script)
  426. {
  427. using (var frame = browser.GetMainFrame())
  428. {
  429. ThrowExceptionIfFrameNull(frame);
  430. frame.ExecuteJavaScriptAsync(script);
  431. }
  432. }
  433. /// <summary>
  434. /// Execute Javascript in the context of this Browser Main Frame. As the method name implies, the script will be executed
  435. /// asynchronously, and the method therefore returns before the script has actually been executed.
  436. /// </summary>
  437. /// <param name="browser">The IBrowser instance this method extends.</param>
  438. /// <param name="script">The Javascript code that should be executed.</param>
  439. public static void ExecuteScriptAsync(this IBrowser browser, string script)
  440. {
  441. browser.ThrowExceptionIfBrowserNull();
  442. using (var frame = browser.MainFrame)
  443. {
  444. ThrowExceptionIfFrameNull(frame);
  445. frame.ExecuteJavaScriptAsync(script);
  446. }
  447. }
  448. /// <summary>
  449. /// Execute Javascript code in the context of this Browsers Main Frame. This extension method uses the LoadingStateChanged event. As the
  450. /// method name implies, the script will be executed asynchronously, and the method therefore returns before the script has
  451. /// actually been executed.
  452. /// </summary>
  453. /// <remarks>
  454. /// Best effort is made to make sure the script is executed, there are likely a few edge cases where the script won't be executed,
  455. /// if you suspect your script isn't being executed, then try executing in the LoadingStateChanged event handler to confirm that
  456. /// it does indeed get executed.
  457. /// </remarks>
  458. /// <param name="webBrowser">The ChromiumWebBrowser instance this method extends.</param>
  459. /// <param name="script">The Javascript code that should be executed.</param>
  460. /// <param name="oneTime">(Optional) The script will only be executed on first page load, subsequent page loads will be ignored.</param>
  461. public static void ExecuteScriptAsyncWhenPageLoaded(this IChromiumWebBrowserBase webBrowser, string script, bool oneTime = true)
  462. {
  463. var useLoadingStateChangedEventHandler = webBrowser.IsBrowserInitialized == false || oneTime == false;
  464. //Browser has been initialized, we check if there is a valid document and we're not loading
  465. if (webBrowser.IsBrowserInitialized)
  466. {
  467. //CefBrowser wrapper
  468. var browser = webBrowser.BrowserCore;
  469. if (browser.HasDocument && browser.IsLoading == false)
  470. {
  471. webBrowser.ExecuteScriptAsync(script);
  472. }
  473. else
  474. {
  475. useLoadingStateChangedEventHandler = true;
  476. }
  477. }
  478. //If the browser hasn't been initialized we can just wire up the LoadingStateChanged event
  479. //If the script has already been executed and oneTime is false will be hooked up next page load.
  480. if (useLoadingStateChangedEventHandler)
  481. {
  482. EventHandler<LoadingStateChangedEventArgs> handler = null;
  483. handler = (sender, args) =>
  484. {
  485. //Wait for while page to finish loading not just the first frame
  486. if (!args.IsLoading)
  487. {
  488. if (oneTime)
  489. {
  490. webBrowser.LoadingStateChanged -= handler;
  491. }
  492. webBrowser.ExecuteScriptAsync(script);
  493. }
  494. };
  495. webBrowser.LoadingStateChanged += handler;
  496. }
  497. }
  498. /// <summary>
  499. /// Creates a new instance of IRequest with the specified Url and Method = POST and then calls
  500. /// <see cref="IFrame.LoadRequest(IRequest)"/>.
  501. /// </summary>
  502. /// <param name="browser">browser this method extends</param>
  503. /// <param name="url">url to load</param>
  504. /// <param name="postDataBytes">post data as byte array</param>
  505. /// <param name="contentType">(Optional) if set the Content-Type header will be set</param>
  506. public static void LoadUrlWithPostData(this IChromiumWebBrowserBase browser, string url, byte[] postDataBytes, string contentType = null)
  507. {
  508. browser.BrowserCore.LoadUrlWithPostData(url, postDataBytes, contentType);
  509. }
  510. /// <summary>
  511. /// Creates a new instance of IRequest with the specified Url and Method = POST and then calls
  512. /// <see cref="IFrame.LoadRequest(IRequest)"/>.
  513. /// </summary>
  514. /// <param name="browser">browser this method extends</param>
  515. /// <param name="url">url to load</param>
  516. /// <param name="postDataBytes">post data as byte array</param>
  517. /// <param name="contentType">(Optional) if set the Content-Type header will be set</param>
  518. public static void LoadUrlWithPostData(this IBrowser browser, string url, byte[] postDataBytes, string contentType = null)
  519. {
  520. browser.ThrowExceptionIfBrowserNull();
  521. using (var frame = browser.MainFrame)
  522. {
  523. ThrowExceptionIfFrameNull(frame);
  524. //Initialize Request with PostData
  525. var request = frame.CreateRequest(initializePostData: true);
  526. request.Url = url;
  527. request.Method = "POST";
  528. //Add AllowStoredCredentials as per suggestion linked in
  529. //https://github.com/cefsharp/CefSharp/issues/2705#issuecomment-476819788
  530. request.Flags = UrlRequestFlags.AllowStoredCredentials;
  531. request.PostData.AddData(postDataBytes);
  532. if (!string.IsNullOrEmpty(contentType))
  533. {
  534. var headers = new NameValueCollection();
  535. headers.Add("Content-Type", contentType);
  536. request.Headers = headers;
  537. }
  538. frame.LoadRequest(request);
  539. }
  540. }
  541. /// <summary>
  542. /// Registers and loads a <see cref="ResourceHandler"/> that represents the HTML content.
  543. /// </summary>
  544. /// <remarks>
  545. /// `Cef` Native `LoadHtml` is unpredictable and only works sometimes, this method wraps the provided HTML in a
  546. /// <see cref="ResourceHandler"/> and loads the provided url using the <see cref="IWebBrowser.Load"/> method. Defaults to using
  547. /// <see cref="Encoding.UTF8"/> for character encoding The url must start with a valid schema, other uri's such as about:blank
  548. /// are invalid A valid example looks like http://test/page.
  549. /// </remarks>
  550. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  551. /// <param name="html">The HTML content.</param>
  552. /// <param name="url">The URL that will be treated as the address of the content.</param>
  553. /// <returns>
  554. /// returns false if the Url was not successfully parsed into a Uri.
  555. /// </returns>
  556. public static bool LoadHtml(this IWebBrowser browser, string html, string url)
  557. {
  558. return browser.LoadHtml(html, url, Encoding.UTF8);
  559. }
  560. /// <summary>
  561. /// Loads html as Data Uri See https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs for details If
  562. /// base64Encode is false then html will be Uri encoded.
  563. /// </summary>
  564. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  565. /// <param name="html">Html to load as data uri.</param>
  566. /// <param name="base64Encode">(Optional) if true the html string will be base64 encoded using UTF8 encoding.</param>
  567. public static void LoadHtml(this IChromiumWebBrowserBase browser, string html, bool base64Encode = false)
  568. {
  569. var htmlString = new HtmlString(html, base64Encode);
  570. browser.LoadUrl(htmlString.ToDataUriString());
  571. }
  572. /// <summary>
  573. /// Loads html as Data Uri See https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs for details If
  574. /// base64Encode is false then html will be Uri encoded.
  575. /// </summary>
  576. /// <param name="frame">The <seealso cref="IFrame"/> instance this method extends.</param>
  577. /// <param name="html">Html to load as data uri.</param>
  578. /// <param name="base64Encode">(Optional) if true the html string will be base64 encoded using UTF8 encoding.</param>
  579. public static void LoadHtml(this IFrame frame, string html, bool base64Encode = false)
  580. {
  581. var htmlString = new HtmlString(html, base64Encode);
  582. frame.LoadUrl(htmlString.ToDataUriString());
  583. }
  584. /// <summary>
  585. /// Registers and loads a <see cref="ResourceHandler"/> that represents the HTML content.
  586. /// </summary>
  587. /// <remarks>
  588. /// `Cef` Native `LoadHtml` is unpredictable and only works sometimes, this method wraps the provided HTML in a
  589. /// <see cref="ResourceHandler"/> and loads the provided url using the <see cref="IWebBrowser.Load"/> method.
  590. /// </remarks>
  591. /// <exception cref="Exception">Thrown when an exception error condition occurs.</exception>
  592. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  593. /// <param name="html">The HTML content.</param>
  594. /// <param name="url">The URL that will be treated as the address of the content.</param>
  595. /// <param name="encoding">Character Encoding.</param>
  596. /// <param name="oneTimeUse">(Optional) Whether or not the handler should be used once (true) or until manually unregistered
  597. /// (false)</param>
  598. /// <returns>
  599. /// returns false if the Url was not successfully parsed into a Uri.
  600. /// </returns>
  601. public static bool LoadHtml(this IWebBrowser browser, string html, string url, Encoding encoding, bool oneTimeUse = false)
  602. {
  603. if (browser.ResourceRequestHandlerFactory == null)
  604. {
  605. browser.ResourceRequestHandlerFactory = new ResourceRequestHandlerFactory();
  606. }
  607. var handler = browser.ResourceRequestHandlerFactory as ResourceRequestHandlerFactory;
  608. if (handler == null)
  609. {
  610. throw new Exception("LoadHtml can only be used with the default IResourceRequestHandlerFactory(DefaultResourceRequestHandlerFactory) implementation");
  611. }
  612. if (handler.RegisterHandler(url, ResourceHandler.GetByteArray(html, encoding, true), ResourceHandler.DefaultMimeType, oneTimeUse))
  613. {
  614. browser.Load(url);
  615. return true;
  616. }
  617. return false;
  618. }
  619. /// <summary>
  620. /// Register a ResourceHandler. Can only be used when browser.ResourceHandlerFactory is an instance of
  621. /// DefaultResourceHandlerFactory.
  622. /// </summary>
  623. /// <exception cref="Exception">Thrown when an exception error condition occurs.</exception>
  624. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  625. /// <param name="url">the url of the resource to unregister.</param>
  626. /// <param name="stream">Stream to be registered, the stream should not be shared with any other instances of
  627. /// DefaultResourceHandlerFactory.</param>
  628. /// <param name="mimeType">(Optional) the mimeType.</param>
  629. /// <param name="oneTimeUse">(Optional) Whether or not the handler should be used once (true) or until manually unregistered
  630. /// (false). If true the Stream will be Diposed of when finished.</param>
  631. public static void RegisterResourceHandler(this IWebBrowser browser, string url, Stream stream, string mimeType = ResourceHandler.DefaultMimeType,
  632. bool oneTimeUse = false)
  633. {
  634. if (browser.ResourceRequestHandlerFactory == null)
  635. {
  636. browser.ResourceRequestHandlerFactory = new ResourceRequestHandlerFactory();
  637. }
  638. var handler = browser.ResourceRequestHandlerFactory as ResourceRequestHandlerFactory;
  639. if (handler == null)
  640. {
  641. throw new Exception("RegisterResourceHandler can only be used with the default IResourceRequestHandlerFactory(DefaultResourceRequestHandlerFactory) implementation");
  642. }
  643. using (var ms = new MemoryStream())
  644. {
  645. stream.CopyTo(ms);
  646. handler.RegisterHandler(url, ms.ToArray(), mimeType, oneTimeUse);
  647. }
  648. }
  649. /// <summary>
  650. /// Unregister a ResourceHandler. Can only be used when browser.ResourceHandlerFactory is an instance of
  651. /// DefaultResourceHandlerFactory.
  652. /// </summary>
  653. /// <exception cref="Exception">Thrown when an exception error condition occurs.</exception>
  654. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  655. /// <param name="url">the url of the resource to unregister.</param>
  656. public static void UnRegisterResourceHandler(this IWebBrowser browser, string url)
  657. {
  658. var handler = browser.ResourceRequestHandlerFactory as ResourceRequestHandlerFactory;
  659. if (handler == null)
  660. {
  661. throw new Exception("UnRegisterResourceHandler can only be used with the default IResourceRequestHandlerFactory(DefaultResourceRequestHandlerFactory) implementation");
  662. }
  663. handler.UnregisterHandler(url);
  664. }
  665. /// <summary>
  666. /// Stops loading the current page.
  667. /// </summary>
  668. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  669. public static void Stop(this IChromiumWebBrowserBase browser)
  670. {
  671. browser.BrowserCore.Stop();
  672. }
  673. /// <summary>
  674. /// Stops loading the current page.
  675. /// </summary>
  676. /// <param name="browser">The IBrowser instance this method extends.</param>
  677. public static void Stop(this IBrowser browser)
  678. {
  679. browser.ThrowExceptionIfBrowserNull();
  680. browser.StopLoad();
  681. }
  682. /// <summary>
  683. /// Navigates back, must check <see cref="IChromiumWebBrowserBase.CanGoBack"/> before calling this method.
  684. /// </summary>
  685. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  686. public static void Back(this IChromiumWebBrowserBase browser)
  687. {
  688. browser.BrowserCore.Back();
  689. }
  690. /// <summary>
  691. /// Navigates back, must check <see cref="IBrowser.CanGoBack"/> before calling this method.
  692. /// </summary>
  693. /// <param name="browser">The IBrowser instance this method extends.</param>
  694. public static void Back(this IBrowser browser)
  695. {
  696. browser.ThrowExceptionIfBrowserNull();
  697. browser.GoBack();
  698. }
  699. /// <summary>
  700. /// Navigates forward, must check <see cref="IChromiumWebBrowserBase.CanGoForward"/> before calling this method.
  701. /// </summary>
  702. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  703. public static void Forward(this IChromiumWebBrowserBase browser)
  704. {
  705. browser.BrowserCore.Forward();
  706. }
  707. /// <summary>
  708. /// Navigates forward, must check <see cref="IBrowser.CanGoForward"/> before calling this method.
  709. /// </summary>
  710. /// <param name="browser">The IBrowser instance this method extends.</param>
  711. public static void Forward(this IBrowser browser)
  712. {
  713. browser.ThrowExceptionIfBrowserNull();
  714. browser.GoForward();
  715. }
  716. /// <summary>
  717. /// Reloads the page being displayed. This method will use data from the browser's cache, if available.
  718. /// </summary>
  719. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  720. public static void Reload(this IChromiumWebBrowserBase browser)
  721. {
  722. browser.Reload(false);
  723. }
  724. /// <summary>
  725. /// Reloads the page being displayed, optionally ignoring the cache (which means the whole page including all .css, .js etc.
  726. /// resources will be re-fetched).
  727. /// </summary>
  728. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  729. /// <param name="ignoreCache"><c>true</c> A reload is performed ignoring browser cache; <c>false</c> A reload is performed using
  730. /// files from the browser cache, if available.</param>
  731. public static void Reload(this IChromiumWebBrowserBase browser, bool ignoreCache)
  732. {
  733. browser.BrowserCore.Reload(ignoreCache);
  734. }
  735. /// <summary>
  736. /// Reloads the page being displayed, optionally ignoring the cache (which means the whole page including all .css, .js etc.
  737. /// resources will be re-fetched).
  738. /// </summary>
  739. /// <param name="browser">The IBrowser instance this method extends.</param>
  740. /// <param name="ignoreCache"><c>true</c> A reload is performed ignoring browser cache; <c>false</c> A reload is performed using
  741. /// files from the browser cache, if available.</param>
  742. public static void Reload(this IBrowser browser, bool ignoreCache = false)
  743. {
  744. browser.ThrowExceptionIfBrowserNull();
  745. browser.Reload(ignoreCache);
  746. }
  747. /// <summary>
  748. /// Gets the default cookie manager associated with the <see cref="IChromiumWebBrowserBase"/> instance.
  749. /// </summary>
  750. /// <exception cref="Exception">Thrown when an exception error condition occurs.</exception>
  751. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  752. /// <param name="callback">(Optional) If not null it will be executed asynchronously on the CEF IO thread after the manager's
  753. /// storage has been initialized.</param>
  754. /// <returns>
  755. /// Cookie Manager.
  756. /// </returns>
  757. public static ICookieManager GetCookieManager(this IChromiumWebBrowserBase browser, ICompletionCallback callback = null)
  758. {
  759. var host = browser.GetBrowserHost();
  760. ThrowExceptionIfBrowserHostNull(host);
  761. var requestContext = host.RequestContext;
  762. if (requestContext == null)
  763. {
  764. throw new Exception("RequestContext is null, unable to obtain cookie manager");
  765. }
  766. return requestContext.GetCookieManager(callback);
  767. }
  768. /// <summary>
  769. /// Asynchronously gets the current Zoom Level.
  770. /// </summary>
  771. /// <param name="cefBrowser">The ChromiumWebBrowser instance this method extends.</param>
  772. /// <returns>
  773. /// An asynchronous result that yields the zoom level.
  774. /// </returns>
  775. public static Task<double> GetZoomLevelAsync(this IBrowser cefBrowser)
  776. {
  777. var host = cefBrowser.GetHost();
  778. ThrowExceptionIfBrowserHostNull(host);
  779. return host.GetZoomLevelAsync();
  780. }
  781. /// <summary>
  782. /// Asynchronously gets the current Zoom Level.
  783. /// </summary>
  784. /// <param name="browser">the ChromiumWebBrowser instance.</param>
  785. /// <returns>
  786. /// An asynchronous result that yields the zoom level.
  787. /// </returns>
  788. public static Task<double> GetZoomLevelAsync(this IChromiumWebBrowserBase browser)
  789. {
  790. return browser.BrowserCore.GetZoomLevelAsync();
  791. }
  792. /// <summary>
  793. /// Change the ZoomLevel to the specified value. Can be set to 0.0 to clear the zoom level.
  794. /// </summary>
  795. /// <remarks>
  796. /// If called on the CEF UI thread the change will be applied immediately. Otherwise, the change will be applied asynchronously
  797. /// on the CEF UI thread. The CEF UI thread is different to the WPF/WinForms UI Thread.
  798. /// </remarks>
  799. /// <param name="cefBrowser">The ChromiumWebBrowser instance this method extends.</param>
  800. /// <param name="zoomLevel">zoom level.</param>
  801. public static void SetZoomLevel(this IBrowser cefBrowser, double zoomLevel)
  802. {
  803. cefBrowser.ThrowExceptionIfBrowserNull();
  804. var host = cefBrowser.GetHost();
  805. ThrowExceptionIfBrowserHostNull(host);
  806. host.SetZoomLevel(zoomLevel);
  807. }
  808. /// <summary>
  809. /// Change the ZoomLevel to the specified value. Can be set to 0.0 to clear the zoom level.
  810. /// </summary>
  811. /// <remarks>
  812. /// If called on the CEF UI thread the change will be applied immediately. Otherwise, the change will be applied asynchronously
  813. /// on the CEF UI thread. The CEF UI thread is different to the WPF/WinForms UI Thread.
  814. /// </remarks>
  815. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  816. /// <param name="zoomLevel">zoom level.</param>
  817. public static void SetZoomLevel(this IChromiumWebBrowserBase browser, double zoomLevel)
  818. {
  819. browser.BrowserCore.SetZoomLevel(zoomLevel);
  820. }
  821. /// <summary>
  822. /// Search for text within the current page.
  823. /// </summary>
  824. /// <param name="cefBrowser">The ChromiumWebBrowser instance this method extends.</param>
  825. /// <param name="searchText">search text.</param>
  826. /// <param name="forward">indicates whether to search forward or backward within the page.</param>
  827. /// <param name="matchCase">indicates whether the search should be case-sensitive.</param>
  828. /// <param name="findNext">indicates whether this is the first request or a follow-up.</param>
  829. public static void Find(this IBrowser cefBrowser, string searchText, bool forward, bool matchCase, bool findNext)
  830. {
  831. var host = cefBrowser.GetHost();
  832. ThrowExceptionIfBrowserHostNull(host);
  833. host.Find(searchText, forward, matchCase, findNext);
  834. }
  835. /// <summary>
  836. /// Search for text within the current page.
  837. /// </summary>
  838. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  839. /// <param name="searchText">search text.</param>
  840. /// <param name="forward">indicates whether to search forward or backward within the page.</param>
  841. /// <param name="matchCase">indicates whether the search should be case-sensitive.</param>
  842. /// <param name="findNext">indicates whether this is the first request or a follow-up.</param>
  843. public static void Find(this IChromiumWebBrowserBase browser, string searchText, bool forward, bool matchCase, bool findNext)
  844. {
  845. var cefBrowser = browser.BrowserCore;
  846. cefBrowser.ThrowExceptionIfBrowserNull();
  847. cefBrowser.Find(searchText, forward, matchCase, findNext);
  848. }
  849. /// <summary>
  850. /// Cancel all searches that are currently going on.
  851. /// </summary>
  852. /// <param name="cefBrowser">The ChromiumWebBrowser instance this method extends.</param>
  853. /// <param name="clearSelection">clear the current search selection.</param>
  854. public static void StopFinding(this IBrowser cefBrowser, bool clearSelection)
  855. {
  856. cefBrowser.ThrowExceptionIfBrowserNull();
  857. var host = cefBrowser.GetHost();
  858. ThrowExceptionIfBrowserHostNull(host);
  859. host.StopFinding(clearSelection);
  860. }
  861. /// <summary>
  862. /// Cancel all searches that are currently going on.
  863. /// </summary>
  864. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  865. /// <param name="clearSelection">clear the current search selection.</param>
  866. public static void StopFinding(this IChromiumWebBrowserBase browser, bool clearSelection)
  867. {
  868. browser.BrowserCore.StopFinding(clearSelection);
  869. }
  870. /// <summary>
  871. /// Opens a Print Dialog which if used (can be user cancelled) will print the browser contents.
  872. /// </summary>
  873. /// <param name="cefBrowser">The ChromiumWebBrowser instance this method extends.</param>
  874. public static void Print(this IBrowser cefBrowser)
  875. {
  876. var host = cefBrowser.GetHost();
  877. ThrowExceptionIfBrowserHostNull(host);
  878. host.Print();
  879. }
  880. /// <summary>
  881. /// Asynchronously prints the current browser contents to the PDF file specified. The caller is responsible for deleting the file
  882. /// when done.
  883. /// </summary>
  884. /// <param name="cefBrowser">The <see cref="IBrowser"/> object this method extends.</param>
  885. /// <param name="path">Output file location.</param>
  886. /// <param name="settings">(Optional) Print Settings.</param>
  887. /// <returns>
  888. /// A task that represents the asynchronous print operation. The result is true on success or false on failure to generate the
  889. /// Pdf.
  890. /// </returns>
  891. public static Task<bool> PrintToPdfAsync(this IBrowser cefBrowser, string path, PdfPrintSettings settings = null)
  892. {
  893. var host = cefBrowser.GetHost();
  894. ThrowExceptionIfBrowserHostNull(host);
  895. var callback = new TaskPrintToPdfCallback();
  896. host.PrintToPdf(path, settings, callback);
  897. return callback.Task;
  898. }
  899. /// <summary>
  900. /// Opens a Print Dialog which if used (can be user cancelled) will print the browser contents.
  901. /// </summary>
  902. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  903. public static void Print(this IChromiumWebBrowserBase browser)
  904. {
  905. var cefBrowser = browser.BrowserCore;
  906. cefBrowser.ThrowExceptionIfBrowserNull();
  907. cefBrowser.Print();
  908. }
  909. /// <summary>
  910. /// Asynchronously prints the current browser contents to the PDF file specified. The caller is responsible for deleting the file
  911. /// when done.
  912. /// </summary>
  913. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  914. /// <param name="path">Output file location.</param>
  915. /// <param name="settings">(Optional) Print Settings.</param>
  916. /// <returns>
  917. /// A task that represents the asynchronous print operation. The result is true on success or false on failure to generate the
  918. /// Pdf.
  919. /// </returns>
  920. public static Task<bool> PrintToPdfAsync(this IChromiumWebBrowserBase browser, string path, PdfPrintSettings settings = null)
  921. {
  922. return browser.BrowserCore.PrintToPdfAsync(path, settings);
  923. }
  924. /// <summary>
  925. /// Open developer tools in its own window.
  926. /// </summary>
  927. /// <param name="cefBrowser">The ChromiumWebBrowser instance this method extends.</param>
  928. /// <param name="windowInfo">(Optional) window info used for showing dev tools.</param>
  929. /// <param name="inspectElementAtX">(Optional) x coordinate (used for inspectElement)</param>
  930. /// <param name="inspectElementAtY">(Optional) y coordinate (used for inspectElement)</param>
  931. public static void ShowDevTools(this IBrowser cefBrowser, IWindowInfo windowInfo = null, int inspectElementAtX = 0, int inspectElementAtY = 0)
  932. {
  933. var host = cefBrowser.GetHost();
  934. ThrowExceptionIfBrowserHostNull(host);
  935. host.ShowDevTools(windowInfo, inspectElementAtX, inspectElementAtY);
  936. }
  937. /// <summary>
  938. /// Open developer tools in its own window.
  939. /// </summary>
  940. /// <param name="browser">The ChromiumWebBrowser instance this method extends.</param>
  941. /// <param name="windowInfo">(Optional) window info used for showing dev tools.</param>
  942. /// <param name="inspectElementAtX">(Optional) x coordinate (used for inspectElement)</param>
  943. /// <param name="inspectElementAtY">(Optional) y coordinate (used for inspectElement)</param>
  944. public static void ShowDevTools(this IChromiumWebBrowserBase browser, IWindowInfo windowInfo = null, int inspe

Large files files are truncated, but you can click here to view the full file