Skip to content
Snippets Groups Projects
Unverified Commit 0b1eaf92 authored by Bjoern Esswein's avatar Bjoern Esswein
Browse files

WIP: implement DomNodeWrapper

parent d7ba8822
No related branches found
No related tags found
No related merge requests found
Showing with 736 additions and 97 deletions
......@@ -14,7 +14,7 @@ namespace bessw.Unity.WebView.ChromeDevTools
{
/* singleton */
private static Browser instance;
private static Process browserProcess;
private Process browserProcess;
/* browser settings */
public static string browserExecutablePath = "chrome";
......@@ -37,7 +37,7 @@ namespace bessw.Unity.WebView.ChromeDevTools
*/
public static Browser getInstance()
{
if (instance == null)
if (instance == null || instance.browserProcess.HasExited)
{
instance = new Browser();
instance.launchBrowser();
......@@ -64,31 +64,45 @@ namespace bessw.Unity.WebView.ChromeDevTools
private void launchBrowser()
{
// allow only one instance of chrome
if (Browser.browserProcess == null || Browser.browserProcess.HasExited)
{
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} --hide-crash-restore-bubble";
if (browserProcess == null || browserProcess.HasExited)
{
browserProcess = new Process();
browserProcess.StartInfo.FileName = browserExecutablePath;
browserProcess.StartInfo.Arguments = String.Join(" ", new []{
$"--user-data-dir={Path.Join(Application.temporaryCachePath, "BrowserView")}",
$"--remote-debugging-port={debugPort}",
$"--remote-allow-origins=http://localhost:{debugPort}",
"--hide-crash-restore-bubble",
"--disable-first-run-ui",
"--no-first-run"
});
// set headlessBrowser to false to see the browser window
if (headless)
{
Browser.browserProcess.StartInfo.Arguments = string.Concat(Browser.browserProcess.StartInfo.Arguments, " --headless=new");
browserProcess.StartInfo.Arguments = string.Concat(browserProcess.StartInfo.Arguments, " --headless=new");
}
else
{
Browser.browserProcess.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
browserProcess.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
}
Browser.browserProcess.Start();
UnityEngine.Debug.Log($"launched '{Browser.browserProcess.StartInfo.FileName} {Browser.browserProcess.StartInfo.Arguments}'");
// register an error handler
browserProcess.ErrorDataReceived += (sender, e) => UnityEngine.Debug.LogError($"Browser Error: {e.Data} ExitCode: {browserProcess.ExitCode}");
browserProcess.Exited += (sender, e) => UnityEngine.Debug.LogError($"Browser Exited, ExitCode: {browserProcess.ExitCode}");
browserProcess.Start();
if (browserProcess.HasExited) {
UnityEngine.Debug.LogError("Failed to start browser");
}
UnityEngine.Debug.Log($"launched '{browserProcess.StartInfo.FileName} {browserProcess.StartInfo.Arguments}'");
}
}
/**
* send web request to the devTools API
*/
private IEnumerator DevToolsApiRequest(bool isPUT, string apiAddress, System.Action<string> callback)
private IEnumerator DevToolsApiRequest(bool isPUT, string apiAddress, Action<string> callback)
{
UnityEngine.Debug.Log($"DevTools api Request: {apiAddress}");
UnityWebRequest webRequest;
......@@ -114,7 +128,7 @@ namespace bessw.Unity.WebView.ChromeDevTools
}
}
public IEnumerator OpenNewTab(string targetUrl, System.Action<BrowserTab> callback)
public IEnumerator OpenNewTab(string targetUrl, Action<BrowserTab> callback)
{
yield return DevToolsApiRequest(true, $"/json/new?{targetUrl}", (response) =>
{
......
......@@ -3,6 +3,7 @@ using bessw.Unity.WebView.ChromeDevTools.Protocol.Page;
using bessw.Unity.WebView.ChromeDevTools.Protocol.Target;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
......@@ -12,19 +13,31 @@ namespace bessw.Unity.WebView.ChromeDevTools
public class BrowserTab
{
private PageTargetInfo pageTarget;
private DevtoolsProtocolHandler devtools;
public DevtoolsProtocolHandler devtools;
/// <summary>
/// width and height of the brower device
/// </summary>
public Vector2Int size { get; private set; }
public Dictionary<int, DomNodeWrapper> domNodes = new Dictionary<int, DomNodeWrapper>();
public BrowserTab(PageTargetInfo pageTarget)
{
this.pageTarget = pageTarget;
Debug.Log($"tab WebSocket: '{pageTarget.WebSocketDebuggerUrl}'");
this.devtools = new DevtoolsProtocolHandler(new DevtoolsWebsocket(pageTarget.WebSocketDebuggerUrl));
// register DOM event handlers
this.devtools.DOM_AttributeModifiedEventHandler += (attributeModifiedEvent) => DomNodeWrapper.onAttributeModified(this, attributeModifiedEvent);
this.devtools.DOM_AttributeRemovedEventHandler += (attributeRemovedEvent) => DomNodeWrapper.onAttributeRemoved(this, attributeRemovedEvent);
this.devtools.DOM_CharacterDataModifiedEventHandler += (characterDataModifiedEvent) => DomNodeWrapper.onCharacterDataModified(this, characterDataModifiedEvent);
this.devtools.DOM_ChildNodeCountUpdatedEventHandler += (childNodeCountUpdatedEvent) => DomNodeWrapper.onChildNodeCountUpdated(this, childNodeCountUpdatedEvent);
this.devtools.DOM_ChildNodeInsertedEventHandler += (childNodeInsertedEvent) => DomNodeWrapper.onChildNodeInserted(this, childNodeInsertedEvent);
this.devtools.DOM_ChildNodeRemovedEventHandler += (childNodeRemovedEvent) => DomNodeWrapper.onChildNodeRemoved(this, childNodeRemovedEvent);
this.devtools.DOM_DocumentUpdatedEventHandler += (documentUpdatedEvent) => DomNodeWrapper.onDocumentUpdated(this, documentUpdatedEvent);
this.devtools.DOM_SetChildNodesEventHandler += (setChildNodesEvent) => DomNodeWrapper.onSetChildNodes(this, setChildNodesEvent);
}
public IEnumerator Update()
......@@ -34,10 +47,14 @@ namespace bessw.Unity.WebView.ChromeDevTools
public IEnumerator CreateScreenshot(double width, double height, Action<Texture2D> callback)
{
var screenshotCommand = new captureScreenshot();
screenshotCommand.Clip = new Protocol.Types.Viewport();
screenshotCommand.Clip.Width = width;
screenshotCommand.Clip.Height = height;
var screenshotCommand = new captureScreenshot
{
Clip = new Protocol.Types.Viewport
{
Width = width,
Height = height
}
};
return devtools.SendCommand(screenshotCommand,
(response) => {
......@@ -59,8 +76,10 @@ namespace bessw.Unity.WebView.ChromeDevTools
devtools.screencastFrameEventHandler += (screencastFrameEvent frameEvent) =>
{
// send an ack for this frame
var frameAck = new screencastFrameAck();
frameAck.sessionId = frameEvent.sessionId;
var frameAck = new screencastFrameAck
{
sessionId = frameEvent.sessionId
};
_ = devtools.SendCommandAsync(frameAck);
size = new Vector2Int(frameEvent.metadata.deviceWidth, frameEvent.metadata.deviceHeight);
......@@ -76,10 +95,12 @@ namespace bessw.Unity.WebView.ChromeDevTools
callback(frameTexture);
};
var startScreencast = new startScreencast();
startScreencast.MaxWidth = maxWidth;
startScreencast.maxHeight = maxHeight;
startScreencast.everyNthFrame = 1;
var startScreencast = new startScreencast
{
MaxWidth = maxWidth,
maxHeight = maxHeight,
everyNthFrame = 1
};
return devtools.SendCommand(startScreencast);
}
......@@ -139,6 +160,11 @@ namespace bessw.Unity.WebView.ChromeDevTools
_ = devtools.SendCommandAsync(new cancelDragging());
}
public IEnumerator GetDocument(Action<DomNodeWrapper> callback)
{
return DomNodeWrapper.getDocument(this, callback);
}
/**
* close this tab
*/
......
using bessw.Unity.WebView.ChromeDevTools.Protocol;
using bessw.Unity.WebView.ChromeDevTools.Protocol.DOM;
using bessw.Unity.WebView.ChromeDevTools.Protocol.Page;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
......@@ -25,6 +26,19 @@ namespace bessw.Unity.WebView.ChromeDevTools
public event Action<screencastFrameEvent> screencastFrameEventHandler;
public event Action<screencastVisibilityChangedEvent> screencastVisibilityChangedEventHandler;
#region DOM events
public event Action<attributeModifiedEvent> DOM_AttributeModifiedEventHandler;
public event Action<attributeRemovedEvent> DOM_AttributeRemovedEventHandler;
public event Action<characterDataModifiedEvent> DOM_CharacterDataModifiedEventHandler;
public event Action<childNodeCountUpdatedEvent> DOM_ChildNodeCountUpdatedEventHandler;
public event Action<childNodeInsertedEvent> DOM_ChildNodeInsertedEventHandler;
public event Action<childNodeRemovedEvent> DOM_ChildNodeRemovedEventHandler;
public event Action<documentUpdatedEvent> DOM_DocumentUpdatedEventHandler;
public event Action<setChildNodesEvent> DOM_SetChildNodesEventHandler;
#endregion DOM events
public event Action<DevtoolsEventWrapper> unknownEventHandler;
public DevtoolsProtocolHandler(IDevtoolsConnection devtools)
{
this.devtools = devtools;
......@@ -113,10 +127,44 @@ namespace bessw.Unity.WebView.ChromeDevTools
case "Page.screencastVisibilityChanged":
screencastVisibilityChangedEventHandler?.Invoke( ev.Params.ToObject<screencastVisibilityChangedEvent>(Browser.devtoolsSerializer) );
break;
// switch cases that invoke the event handlers for the DOM events
#region DOM events
case "DOM.attributeModified":
DOM_AttributeModifiedEventHandler?.Invoke( ev.Params.ToObject<attributeModifiedEvent>(Browser.devtoolsSerializer) );
break;
case "DOM.attributeRemoved":
DOM_AttributeRemovedEventHandler?.Invoke( ev.Params.ToObject<attributeRemovedEvent>(Browser.devtoolsSerializer) );
break;
case "DOM.characterDataModified":
DOM_CharacterDataModifiedEventHandler?.Invoke( ev.Params.ToObject<characterDataModifiedEvent>(Browser.devtoolsSerializer) );
break;
case "DOM.childNodeCountUpdated":
DOM_ChildNodeCountUpdatedEventHandler?.Invoke( ev.Params.ToObject<childNodeCountUpdatedEvent>(Browser.devtoolsSerializer) );
break;
case "DOM.childNodeInserted":
DOM_ChildNodeInsertedEventHandler?.Invoke( ev.Params.ToObject<childNodeInsertedEvent>(Browser.devtoolsSerializer) );
break;
case "DOM.childNodeRemoved":
DOM_ChildNodeRemovedEventHandler?.Invoke( ev.Params.ToObject<childNodeRemovedEvent>(Browser.devtoolsSerializer) );
break;
case "DOM.documentUpdated":
DOM_DocumentUpdatedEventHandler?.Invoke( ev.Params.ToObject<documentUpdatedEvent>(Browser.devtoolsSerializer) );
break;
case "DOM.setChildNodes":
DOM_SetChildNodesEventHandler?.Invoke( ev.Params.ToObject<setChildNodesEvent>(Browser.devtoolsSerializer) );
break;
#endregion DOM events
default:
if (unknownEventHandler != null) {
unknownEventHandler.Invoke(ev);
break;
} else {
throw new UnexpectedMessageException($"Event of type '{ev}' is not implemented");
}
}
}
/// <summary>
......
using bessw.Unity.WebView.ChromeDevTools.Protocol.DOM;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
#nullable enable
namespace bessw.Unity.WebView.ChromeDevTools
{
public class DomNodeWrapper
{
/// <summary>
/// Node identifier that is passed into the rest of the DOM messages as the `nodeId`. Backend
/// will only push node with given `id` once. It is aware of all requested nodes and will only
/// fire DOM events for nodes known to the client.
/// </summary>
public int NodeId
{
get => Node.nodeId;
protected set => Node.nodeId = value;
}
/// <summary>
/// The id of the parent node if any.
/// </summary>
public int? ParentId
{
get => Node.parentId;
protected set => Node.parentId = value;
}
/// <summary>
/// The `Node`object returend by the browser
/// </summary>
/// <remarks>May be null if it has not jet been requested from the browser</remarks>
public Node Node { get; protected set; }
/// <summary>
/// Reference to the browser tab that this dom node belongs to
/// </summary>
private BrowserTab tab;
/// <summary>
/// private constructor, create instances with the static method <see cref="getDocument"/>,
/// or by calling instance methods on a <see cref="DomNodeWrapper"/> to get its child nodes.
/// </summary>
/// <param name="tab"></param>
private DomNodeWrapper(BrowserTab tab, Node node)
{
this.tab = tab;
this.Node = node;
}
private static DomNodeWrapper createOrUpdateNode(BrowserTab tab, int nodeId, int? parentId = null, int? backendNodeId = null, Node? node = null)
{
if (tab.domNodes.ContainsKey(nodeId))
{
var domNode = tab.domNodes[nodeId];
if (node != null) domNode.Node = node;
if (parentId != null) domNode.ParentId = parentId;
if (backendNodeId != null) domNode.Node.backendNodeId = (int)backendNodeId;
return domNode;
}
else
{
var domNode = new DomNodeWrapper(tab, node ?? new Node()
{
nodeId = nodeId,
parentId = parentId
});
tab.domNodes[nodeId] = domNode;
return domNode;
}
}
#region Event Handlers
public static void onAttributeModified(BrowserTab tab, attributeModifiedEvent eventData)
{
var domNode = createOrUpdateNode(tab, eventData.nodeId);
if (domNode.Node != null)
{
domNode.Node.attributes[eventData.name] = eventData.value;
} else {
throw new InvalidOperationException("AttributeModified event was fired, the node info has not yet been recieved");
}
}
public static void onAttributeRemoved(BrowserTab tab, attributeRemovedEvent eventData)
{
var domNode = createOrUpdateNode(tab, eventData.nodeId);
if (domNode.Node != null)
{
domNode.Node.attributes.Remove(eventData.name);
} else {
throw new InvalidOperationException("AttributeRemoved event was fired, the node info has not yet been recieved");
}
}
public static void onCharacterDataModified(BrowserTab tab, characterDataModifiedEvent eventData)
{
var domNode = createOrUpdateNode(tab, eventData.nodeId);
if (domNode.Node != null)
{
domNode.Node.nodeValue = eventData.characterData;
} else {
throw new InvalidOperationException("CharacterDataModified event was fired, the node info has not yet been recieved");
}
}
public static void onChildNodeCountUpdated(BrowserTab tab, childNodeCountUpdatedEvent eventData)
{
var domNode = createOrUpdateNode(tab, eventData.nodeId);
if (domNode.Node != null)
{
domNode.Node.childNodeCount = eventData.childNodeCount;
} else {
throw new InvalidOperationException("ChildNodeCountUpdated event was fired, the node info has not yet been recieved");
}
}
public static void onChildNodeInserted(BrowserTab tab, childNodeInsertedEvent eventData)
{
var parentNode = createOrUpdateNode(tab, eventData.parentNodeId);
var childNode = createOrUpdateNode(tab, eventData.node.nodeId, eventData.parentNodeId, eventData.node.backendNodeId, eventData.node);
if (parentNode.Node != null && childNode.Node != null)
{
parentNode.Node.children.Insert(eventData.previousNodeId, childNode.Node);
} else {
throw new InvalidOperationException("ChildNodeInserted event was fired, the node info has not yet been recieved");
}
}
public static void onChildNodeRemoved(BrowserTab tab, childNodeRemovedEvent eventData)
{
if (
tab.domNodes.TryGetValue(eventData.parentNodeId, out var parentNode) &&
tab.domNodes.TryGetValue(eventData.nodeId, out var childNode) &&
parentNode.Node != null &&
childNode.Node != null)
{
parentNode.Node.children.Remove(childNode.Node);
} else {
//throw new InvalidOperationException("ChildNodeRemoved event was fired, the node info has not yet been recieved");
}
}
public static void onDocumentUpdated(BrowserTab tab, documentUpdatedEvent eventData)
{
// clear the domNodes dictionary
tab.domNodes.Clear();
}
public static void onSetChildNodes(BrowserTab tab, setChildNodesEvent eventData)
{
var parentNode = createOrUpdateNode(tab, eventData.parentId);
if (parentNode.Node != null)
{
foreach (var node in eventData.nodes)
{
createOrUpdateNode(tab, node.nodeId, eventData.parentId, node.backendNodeId, node);
}
parentNode.Node.children = new(eventData.nodes);
} else {
throw new InvalidOperationException("SetChildNodes event was fired, the node info has not yet been recieved");
}
}
#endregion Event Handlers
#region Commands
/// <summary>
/// Enables DOM agent for the given page.
/// </summary>
public static IEnumerator enable(BrowserTab tab)
{
var enableCommand = new enable();
return tab.devtools.SendCommand(enableCommand);
}
/// <summary>
/// Disables DOM agent for the given page.
/// </summary>
public static IEnumerator disable(BrowserTab tab)
{
return tab.devtools.SendCommand( new disable() );
}
/// <summary>
/// Get the root node of the document, the root node is returned as an argument to the callback.
/// </summary>
/// <param name="tab"></param>
/// <param name="callback">The callback recieves the root node as argument</param>
/// <returns><see cref="DomNodeWrapper"/></returns>
public static IEnumerator getDocument(BrowserTab tab, Action<DomNodeWrapper> callback)
{
var domCommand = new getDocument();
return tab.devtools.SendCommand(domCommand, (response) =>
{
Node documentRoot = ((getDocumentCommandResponse)response).root;
var domNode = createOrUpdateNode(tab,
documentRoot.nodeId,
documentRoot.parentId,
documentRoot.backendNodeId,
documentRoot
);
callback(domNode);
});
}
/// <summary>
/// Describes the node, does not require domain to be enabled. Does not start tracking any
/// objects, can be used for automation.
/// </summary>
/// <param name="callback">The callback recieves the node as argument</param>
public IEnumerator describeNode(Action<Node> callback, int? depth = null, bool? pierce = null)
{
var describeNodeCommand = new describeNode
{
nodeId = NodeId,
depth = depth,
pierce = pierce
};
return tab.devtools.SendCommand(describeNodeCommand, (response) =>
{
callback(((describeNodeCommandResponse)response).node);
});
}
/// <summary>
/// Focus this node.
/// </summary>
public IEnumerator focus()
{
var focusCommand = new focus
{
nodeId = NodeId
};
return tab.devtools.SendCommand(focusCommand);
}
/// <summary>
/// Gets the nodes Attributes
/// </summary>
public IEnumerator getAttributes(Action<Dictionary<string, string>> callback)
{
var attributesCommand = new getAttributes
{
nodeId = NodeId
};
return tab.devtools.SendCommand(attributesCommand, (response) =>
{
var attibutes = ((getAttributesCommandResponse)response).attributes;
tab.domNodes[NodeId].Node.attributes = attibutes;
callback(attibutes);
});
}
public IEnumerator getBoxModel(Action<BoxModel> callback)
{
var boxModelCommand = new getBoxModel
{
nodeId = NodeId
};
return tab.devtools.SendCommand(boxModelCommand, (response) =>
{
callback(((getBoxModelCommandResponse) response).model);
});
}
public IEnumerator getNodeForLocation(int x, int y, Action<DomNodeWrapper> callback, Action<string>? errorCallback = null)
{
var nodeForLocationCommand = new getNodeForLocation
{
x = x,
y = y
};
return tab.devtools.SendCommand(nodeForLocationCommand, (response) =>
{
var responseNodeId = ((getNodeForLocationCommandResponse) response).nodeId;
if (responseNodeId != null) {
var domNode = createOrUpdateNode(tab, (int)responseNodeId);
callback(domNode);
} else {
errorCallback?.Invoke("nodeId was not provided, is the dom domain enabled?");
}
});
}
/// <summary>
/// Returns node's HTML markup.
/// </summary>
public IEnumerator getOuterHtml(Action<string> callback)
{
var outerHtmlCommand = new getOuterHTML
{
nodeId = NodeId
};
return tab.devtools.SendCommand(outerHtmlCommand, (response) =>
{
callback(((getOuterHTMLCommandResponse) response).outerHTML);
});
}
/// <summary>
/// Moves node into an other container node
/// </summary>
public IEnumerator moveTo(DomNodeWrapper targetNode, DomNodeWrapper? insertBeforeNode = null)
{
var moveToCommand = new moveTo
{
nodeId = NodeId,
targetNodeId = targetNode.NodeId,
insertBeforeNodeId = insertBeforeNode?.NodeId
};
return tab.devtools.SendCommand(moveToCommand, (response) =>
{
// update the new node id of the moved node
tab.domNodes.Remove(NodeId);
NodeId = ((moveToCommandResponse) response).nodeId;
tab.domNodes[NodeId] = this;
});
}
/// <summary>
/// search a child node by querySelector
/// </summary>
public IEnumerator querySelector(string selector, Action<DomNodeWrapper> callback)
{
var querySelectorCommand = new querySelector
{
nodeId = NodeId,
selector = selector
};
return tab.devtools.SendCommand(querySelectorCommand, (response) =>
{
var domNode = createOrUpdateNode(tab, ((querySelectorCommandResponse) response).nodeId);
callback(domNode);
});
}
/// <summary>
/// search all child nodes matching the querySelector
/// </summary>
public IEnumerator querySelectorAll(string selector, Action<DomNodeWrapper[]> callback)
{
var querySelectorAllCommand = new querySelectorAll
{
nodeId = NodeId,
selector = selector
};
return tab.devtools.SendCommand(querySelectorAllCommand, (response) =>
{
var nodeIds = ((querySelectorAllCommandResponse) response).nodeIds;
var domNodes = new DomNodeWrapper[nodeIds.Length];
for (int i = 0; i < nodeIds.Length; i++)
{
domNodes[i] = createOrUpdateNode(tab, nodeIds[i]);
}
callback(domNodes);
});
}
//TODO: implement the other commands of the DOM domain
#endregion Commands
}
}
fileFormatVersion: 2
guid: 9a49fdc400bfe5d46b76c0c1e154940e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
This diff is collapsed.
fileFormatVersion: 2
guid: f4e9b65319713e3478ca1d350419f8c4
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
......@@ -5,6 +5,7 @@ using Newtonsoft.Json.Serialization;
using UnityEngine.EventSystems;
using static UnityEngine.EventSystems.PointerEventData;
#nullable enable annotations
namespace bessw.Unity.WebView.ChromeDevTools.Protocol.Input
{
#region dispatchMouseEvent
......
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
namespace bessw.Unity.WebView.ChromeDevTools.Protocol
{
/// <summary>
/// Converts a interleaved JSON array like `[key1, value1, key2, value2, ...]` to a C# dictionary.
/// </summary>
/// <typeparam name="keyT"></typeparam>
/// <typeparam name="valueT"></typeparam>
public class JsonInterleavedArrayConverter<keyT, valueT> : JsonConverter<Dictionary<keyT,valueT>>
{
public override void WriteJson(JsonWriter writer, Dictionary<keyT,valueT> value, JsonSerializer serializer)
{
JArray obj = new JArray();
foreach (var pair in value)
{
obj.Add(pair.Key);
obj.Add(pair.Value);
}
obj.WriteTo(writer);
}
public override Dictionary<keyT,valueT> ReadJson(JsonReader reader, Type objectType, Dictionary<keyT,valueT> existingValue, bool hasExistingValue, JsonSerializer serializer)
{
JArray obj = JArray.Load(reader);
Dictionary<keyT,valueT> result = new Dictionary<keyT,valueT>();
for (int i = 0; i < obj.Count; i+=2)
{
result.Add(obj[i].Value<keyT>(), obj[i+1].Value<valueT>());
}
return result;
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 31c472a5e6adcf247b4e0d9835835e75
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
......@@ -39,7 +39,7 @@ namespace bessw.Unity.WebView
#endregion json serializer
private Browser browser;
private BrowserTab tab;
protected BrowserTab tab;
private RawImage rawImage;
private RectTransform rectTransform;
......@@ -87,6 +87,32 @@ namespace bessw.Unity.WebView
});
}
private IEnumerator getDropzoneState ()
{
Debug.LogWarning($"dropzone pre");
DomNodeWrapper doc = null;
yield return DomNodeWrapper.getDocument(tab, (document) => {
Debug.LogWarning($"dropzone 1: '{document}'");
doc = document;
StartCoroutine(document.querySelectorAll("[dropzone='copy']", (dropzones) => {
foreach (var dropzone in dropzones)
{
Debug.LogWarning($"dropzone 2: Node is Null?: '{dropzone.Node == null}'");
StartCoroutine(dropzone.getAttributes((attributes) =>
{
Debug.LogWarning($"dropzone 3 getAttributes: '{string.Join(", ", attributes.Values)}'");
}));
}
}));
});
Debug.LogWarning($"dropzone post: '{doc}'");
// alternative way to get the dropzone state
}
// Update is called once per frame
private void Update()
{
......@@ -132,12 +158,13 @@ namespace bessw.Unity.WebView
}
}
// TODO: OnDragMove -> PointerMove
public void OnDrop(PointerEventData eventData)
{
Debug.LogWarning($"OnDrop: {eventData.position}");
createDragEvent(DragEventType.drop, eventData);
// TODO: remove debug code
StartCoroutine(getDropzoneState());
}
public void OnPointerExit(PointerEventData eventData)
......
......@@ -34,11 +34,11 @@ RectTransform:
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -444.39624, y: -175.33963}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
m_Pivot: {x: 0, y: 0}
--- !u!222 &5559415116192402672
CanvasRenderer:
m_ObjectHideFlags: 0
......@@ -87,3 +87,4 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
headlessBrowser: 1
targetUrl: https://google.de
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment