diff --git a/BrowserView.prefab b/BrowserView.prefab index dbdb25933fd27697dfc315709fce66d5ccfd3273..732b376306d20147774431dae831fa093bb693ab 100644 --- a/BrowserView.prefab +++ b/BrowserView.prefab @@ -10,8 +10,8 @@ GameObject: m_Component: - component: {fileID: 2974656142881083530} - component: {fileID: 5559415116192402672} - - component: {fileID: 4531839590213585742} - - component: {fileID: 5511584970398147175} + - component: {fileID: 3767983593885104582} + - component: {fileID: 2459857651630437765} m_Layer: 5 m_Name: BrowserView m_TagString: Untagged @@ -47,7 +47,7 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 8825460134736404412} m_CullTransparentMesh: 1 ---- !u!114 &4531839590213585742 +--- !u!114 &3767983593885104582 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -67,14 +67,14 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_Texture: {fileID: 0} + m_Texture: {fileID: 2800000, guid: 7ee48c5fba4919649a8a6094cbead669, type: 3} m_UVRect: serializedVersion: 2 x: 0 y: 0 width: 1 height: 1 ---- !u!114 &5511584970398147175 +--- !u!114 &2459857651630437765 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -86,4 +86,4 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 6893fa42f929f894286c6f00c40bcd06, type: 3} m_Name: m_EditorClassIdentifier: - targetUrl: https://google.de + headlessBrowser: 1 diff --git a/Runtime/BrowserView.cs b/Runtime/BrowserView.cs index 86ad1fb2d0bb35023fd4d5f91eb6d445fe795231..32bc7be6bf9ec035d013557dfcfd552f14a591b0 100644 --- a/Runtime/BrowserView.cs +++ b/Runtime/BrowserView.cs @@ -1,28 +1,29 @@ using ChromeDevTools; using System.Collections; -using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; -//using Unity.Networking.Transport; [RequireComponent(typeof(RawImage))] -public class BrowserView : MonoBehaviour //TODO: Extends RawImage instead? +public class BrowserView : MonoBehaviour { private Browser browser; private BrowserTab tab; private RawImage rawImage; + public bool headlessBrowser = true; + //TODO: handle changed targetUrl public string targetUrl = "https://google.de"; // Start is called before the first frame update - void Start() + private void Start() { rawImage = this.gameObject.GetComponent<RawImage>(); } - void OnEnable() + private void OnEnable() { + Browser.headless = headlessBrowser; browser = Browser.getInstance(); //StartCoroutine(GetOpenTabs()); @@ -45,7 +46,7 @@ public class BrowserView : MonoBehaviour //TODO: Extends RawImage instead? } // Update is called once per frame - void Update() + private void Update() { } @@ -65,7 +66,7 @@ public class BrowserView : MonoBehaviour //TODO: Extends RawImage instead? /** * Close all browser windows. */ - void OnApplicationQuit() + private void OnApplicationQuit() { tab.Close(); browser.Close(); diff --git a/Runtime/ChromeDevtools/Browser.cs b/Runtime/ChromeDevtools/Browser.cs index 49fad21a58a027d9f08d5f7da9c0e6d0aba7a3f3..b57c646e1681de69be9c519a896ea37529aac215 100644 --- a/Runtime/ChromeDevtools/Browser.cs +++ b/Runtime/ChromeDevtools/Browser.cs @@ -17,8 +17,8 @@ namespace ChromeDevTools private static Process browserProcess; /* browser settings */ - private const string browserExecutablePath = "chrome"; - private const bool headlessBrowser = false; + public static string browserExecutablePath = "chrome"; + public static bool headless = true; private const int debugPort = 9222; /* JsonSerializer */ @@ -63,10 +63,10 @@ namespace ChromeDevTools { Browser.browserProcess = new Process(); Browser.browserProcess.StartInfo.FileName = browserExecutablePath; - Browser.browserProcess.StartInfo.Arguments = $"--user-data-dir={Path.Join(Application.temporaryCachePath, "BrowserView")} --remote-debugging-port={debugPort} --remote-allow-origins=http://localhost:{debugPort}"; + Browser.browserProcess.StartInfo.Arguments = $"--user-data-dir={Path.Join(Application.temporaryCachePath, "BrowserView")} --remote-debugging-port={debugPort} --remote-allow-origins=http://localhost:{debugPort} --hide-crash-restore-bubble"; // set headlessBrowser to false to see the browser window - if (headlessBrowser) + if (headless) { Browser.browserProcess.StartInfo.Arguments = string.Concat(Browser.browserProcess.StartInfo.Arguments, " --headless=new"); } diff --git a/Runtime/ChromeDevtools/Protocol/Cast.meta b/Runtime/ChromeDevtools/Protocol/Cast.meta new file mode 100644 index 0000000000000000000000000000000000000000..f9da9a2cd4bbaf27c3aa4ad82774f1cb67ece359 --- /dev/null +++ b/Runtime/ChromeDevtools/Protocol/Cast.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1f4e0afa13be5aa4da5b06d9d861002a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/ChromeDevtools/Protocol/Cast/Cast.cs b/Runtime/ChromeDevtools/Protocol/Cast/Cast.cs new file mode 100644 index 0000000000000000000000000000000000000000..4a67cb36e0666c850736f8ce156eb7b49b93f28f --- /dev/null +++ b/Runtime/ChromeDevtools/Protocol/Cast/Cast.cs @@ -0,0 +1,124 @@ +using Newtonsoft.Json; + +namespace ChromeDevTools +{ + namespace Protocol + { + namespace Cast + { + } + } +} + + +/* +Devtools protocol.json: +{ + "domain": "Cast", + "description": "A domain for interacting with Cast, Presentation API, and Remote Playback API\nfunctionalities.", + "experimental": true, + "types": [ + { + "id": "Sink", + "type": "object", + "properties": [ + { + "name": "name", + "type": "string" + }, + { + "name": "id", + "type": "string" + }, + { + "name": "session", + "description": "Text describing the current session. Present only if there is an active\nsession on the sink.", + "optional": true, + "type": "string" + } + ] + } + ], + "commands": [ + { + "name": "enable", + "description": "Starts observing for sinks that can be used for tab mirroring, and if set,\nsinks compatible with |presentationUrl| as well. When sinks are found, a\n|sinksUpdated| event is fired.\nAlso starts observing for issue messages. When an issue is added or removed,\nan |issueUpdated| event is fired.", + "parameters": [ + { + "name": "presentationUrl", + "optional": true, + "type": "string" + } + ] + }, + { + "name": "disable", + "description": "Stops observing for sinks and issues." + }, + { + "name": "setSinkToUse", + "description": "Sets a sink to be used when the web page requests the browser to choose a\nsink via Presentation API, Remote Playback API, or Cast SDK.", + "parameters": [ + { + "name": "sinkName", + "type": "string" + } + ] + }, + { + "name": "startDesktopMirroring", + "description": "Starts mirroring the desktop to the sink.", + "parameters": [ + { + "name": "sinkName", + "type": "string" + } + ] + }, + { + "name": "startTabMirroring", + "description": "Starts mirroring the tab to the sink.", + "parameters": [ + { + "name": "sinkName", + "type": "string" + } + ] + }, + { + "name": "stopCasting", + "description": "Stops the active Cast session on the sink.", + "parameters": [ + { + "name": "sinkName", + "type": "string" + } + ] + } + ], + "events": [ + { + "name": "sinksUpdated", + "description": "This is fired whenever the list of available sinks changes. A sink is a\ndevice or a software surface that you can cast to.", + "parameters": [ + { + "name": "sinks", + "type": "array", + "items": { + "$ref": "Sink" + } + } + ] + }, + { + "name": "issueUpdated", + "description": "This is fired whenever the outstanding issue/error message changes.\n|issueMessage| is empty if there is no issue.", + "parameters": [ + { + "name": "issueMessage", + "type": "string" + } + ] + } + ] +}*/ \ No newline at end of file diff --git a/Runtime/ChromeDevtools/Protocol/Cast/Cast.cs.meta b/Runtime/ChromeDevtools/Protocol/Cast/Cast.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..d2b9e03c0e9b06e09d703c79509941ddcf2713c1 --- /dev/null +++ b/Runtime/ChromeDevtools/Protocol/Cast/Cast.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b4f546ce82c7cb84b8003bc93d5cf73f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/ChromeDevtools/Protocol/DevtoolsCommand.cs b/Runtime/ChromeDevtools/Protocol/DevtoolsCommand.cs index 0fd27d776aeba96d7ac8ac23a9affc124dcb0e2d..1601a8537571c25b7896d95b20bc0cbfed770a67 100644 --- a/Runtime/ChromeDevtools/Protocol/DevtoolsCommand.cs +++ b/Runtime/ChromeDevtools/Protocol/DevtoolsCommand.cs @@ -25,20 +25,5 @@ namespace ChromeDevTools public DevtoolsCommandWrapper(T command) => Params = command; } public interface IDevtoolsCommand {} - - public class DevtoolsResponseWrapper - { - public long Id { get; set; } - public JObject Result { get; set; } - } - /// - /// Every devtools command response has the same id and a method as the corresponding command - /// - public class DevtoolsResponseWrapper<T>: DevtoolsResponseWrapper where T: IDevtoolsResponse - { - public new T Result { get; set; } - } - - public interface IDevtoolsResponse {} } } \ No newline at end of file diff --git a/Runtime/ChromeDevtools/Protocol/DevtoolsEvent.cs b/Runtime/ChromeDevtools/Protocol/DevtoolsEvent.cs new file mode 100644 index 0000000000000000000000000000000000000000..a4c124e444c8e03978b01247792e0c674ae6c206 --- /dev/null +++ b/Runtime/ChromeDevtools/Protocol/DevtoolsEvent.cs @@ -0,0 +1,23 @@ +using Newtonsoft.Json.Linq; +using System; + +namespace ChromeDevTools +{ + namespace Protocol + { + public class DevtoolsEventWrapper + { + public string Method { get; set; } + public JObject Params { get; set; } + } + /// + /// Every devtools command response has the same id and a method as the corresponding command + /// + public class DevtoolsEventWrapper<T> : DevtoolsEventWrapper where T : IDevtoolsEvent + { + public new T Params { get; set; } + } + + public interface IDevtoolsEvent { } + } +} \ No newline at end of file diff --git a/Runtime/ChromeDevtools/Protocol/DevtoolsEvent.cs.meta b/Runtime/ChromeDevtools/Protocol/DevtoolsEvent.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..e4ed691c6bb042f09269a206a05c7e541fd47257 --- /dev/null +++ b/Runtime/ChromeDevtools/Protocol/DevtoolsEvent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 399f2cceede40aa4ebe787a7f276de78 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/ChromeDevtools/Protocol/DevtoolsResponse.cs b/Runtime/ChromeDevtools/Protocol/DevtoolsResponse.cs new file mode 100644 index 0000000000000000000000000000000000000000..8d4f55cf2cef9ebb6b43123141da6b9c4bdea180 --- /dev/null +++ b/Runtime/ChromeDevtools/Protocol/DevtoolsResponse.cs @@ -0,0 +1,23 @@ +using Newtonsoft.Json.Linq; +using System; + +namespace ChromeDevTools +{ + namespace Protocol + { + public class DevtoolsResponseWrapper + { + public long Id { get; set; } + public JObject Result { get; set; } + } + /// + /// Every devtools command response has the same id and a method as the corresponding command + /// + public class DevtoolsResponseWrapper<T> : DevtoolsResponseWrapper where T : IDevtoolsResponse + { + public new T Result { get; set; } + } + + public interface IDevtoolsResponse { } + } +} \ No newline at end of file diff --git a/Runtime/ChromeDevtools/Protocol/DevtoolsResponse.cs.meta b/Runtime/ChromeDevtools/Protocol/DevtoolsResponse.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..ea0de6bba5b1bf95ab066be9565d463238b32cb1 --- /dev/null +++ b/Runtime/ChromeDevtools/Protocol/DevtoolsResponse.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 81e639e1e8ae9084ab868731d8c5742f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/ChromeDevtools/Protocol/Page/Screencast.cs b/Runtime/ChromeDevtools/Protocol/Page/Screencast.cs new file mode 100644 index 0000000000000000000000000000000000000000..d3dac2e818521a7ce1bfb8a419650ac09575ed37 --- /dev/null +++ b/Runtime/ChromeDevtools/Protocol/Page/Screencast.cs @@ -0,0 +1,137 @@ +using Newtonsoft.Json; + +namespace ChromeDevTools +{ + namespace Protocol + { + namespace Page + { + /// <summary> + /// Starts sending each frame using the `screencastFrame` event. + /// "experimental": true + /// + /// No Response + /// </summary> + //[CommandResponseAttribute(typeof(StartScreencastCommandResponse))] + public class startScreencast : IDevtoolsCommand + { + /// <summary> + /// Gets or sets Image compression format (defaults to png). + /// Can be "jpeg" or "png" + /// </summary> + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string Format { get; set; } + /// <summary> + /// Gets or sets Compression quality from range [0..100]. + /// </summary> + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public int? Quality { get; set; } + /// <summary> + /// Maximum screenshot width. + /// </summary> + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public int MaxWidth { get; set; } + /// <summary> + /// Maximum screenshot height. + /// </summary> + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public int maxHeight { get; set; } + /// <summary> + /// Send every n-th frame. + /// </summary> + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public int everyNthFrame { get; set; } + } + + + /// <summary> + /// Acknowledges that a screencast frame has been received by the frontend. + /// "experimental": true + /// </summary> + public class screencastFrameAck : IDevtoolsCommand + { + /// <summary> + /// Frame number. + /// </summary> + public int sessionId { get; set; } + } + + /// <summary> + /// Stops sending each frame in the `screencastFrame`. + /// "experimental": true + /// </summary> + public class stopScreencast : IDevtoolsCommand + { } + + /// <summary> + /// Compressed image data requested by the `startScreencast`. + /// </summary> + public class screencastFrameEvent : IDevtoolsEvent + { + /// <summary> + /// Gets or sets Base64-encoded image data. + /// </summary> + public string Data { get; set; } + /// <summary> + /// Screencast frame metadata. + /// </summary> + public Types.ScreencastFrameMetadata metadata { get; set; } + /// <summary> + /// Frame number. + /// </summary> + public int sessionId { get; set; } + } + + /// <summary> + /// Fired when the page with currently enabled screencast was shown or hidden `. + /// </summary> + public class screencastVisibilityChanged : IDevtoolsEvent + { + /// <summary> + /// True if the page is visible. + /// </summary> + public bool visible { get; set; } + } + + namespace Types + { + /// <summary> + /// Screencast frame metadata. + /// </summary> + public class ScreencastFrameMetadata + { + /// <summary> + /// Top offset in DIP. + /// </summary> + public int offsetTop { get; set; } + /// <summary> + /// Page scale factor. + /// </summary> + public int pageScaleFactor { get; set; } + /// <summary> + /// Device screen width in DIP. + /// </summary> + public int deviceWidth { get; set; } + /// <summary> + /// Device screen height in DIP. + /// </summary> + public int deviceHeight { get; set; } + /// <summary> + /// Position of horizontal scroll in CSS pixels. + /// </summary> + public int scrollOffsetX { get; set; } + /// <summary> + /// Position of vertical scroll in CSS pixels. + /// </summary> + public int scrollOffsetY { get; set; } + /// <summary> + /// Frame swap timestamp. + /// UTC time in seconds, counted from January 1, 1970. + /// </summary> + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public long? timestamp { get; set; } + } + } + } + } +} \ No newline at end of file diff --git a/Runtime/ChromeDevtools/Protocol/Page/Screencast.cs.meta b/Runtime/ChromeDevtools/Protocol/Page/Screencast.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..157140b843a6742fb2cb51d86b5436df5cb2d529 --- /dev/null +++ b/Runtime/ChromeDevtools/Protocol/Page/Screencast.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f7a2406fccd8c74d89d419e99a8bf29 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: