|
| 1 | +// Copyright (C) Microsoft Corporation. All rights reserved. |
| 2 | +// Use of this source code is governed by a BSD-style license that can be |
| 3 | +// found in the LICENSE file. |
| 4 | + |
| 5 | +using System.Runtime.InteropServices; |
| 6 | +using System.Collections.Generic; |
| 7 | +using System.Reflection; |
| 8 | +using System; |
| 9 | + |
| 10 | +namespace WebView2WpfBrowser |
| 11 | +{ |
| 12 | + // BridgeAddRemoteObject is a .NET object that implements IDispatch and works with AddRemoteObject. |
| 13 | + // See the AddRemoteObjectCmdExecute method that demonstrates how to use it from JavaScript. |
| 14 | + [ClassInterface(ClassInterfaceType.AutoDual)] |
| 15 | + [ComVisible(true)] |
| 16 | + public class AnotherRemoteObject |
| 17 | + { |
| 18 | + |
| 19 | + // Sample property. |
| 20 | + public string Prop { get; set; } = "AnotherRemoteObject.Prop"; |
| 21 | + } |
| 22 | + |
| 23 | + [ClassInterface(ClassInterfaceType.AutoDual)] |
| 24 | + [ComVisible(true)] |
| 25 | + public class BridgeAddRemoteObject |
| 26 | + { |
| 27 | + // Sample function that takes a parameter. |
| 28 | + public string Func(string param) |
| 29 | + { |
| 30 | + return "BridgeAddRemoteObject.Func(" + param + ")"; |
| 31 | + } |
| 32 | + |
| 33 | + // Sample function that takes no parameters. |
| 34 | + public string Func2() |
| 35 | + { |
| 36 | + return "BridgeAddRemoteObject.Func2()"; |
| 37 | + } |
| 38 | + |
| 39 | + // Get type of an object. |
| 40 | + public string GetObjectType(object obj) |
| 41 | + { |
| 42 | + return obj.GetType().Name; |
| 43 | + } |
| 44 | + |
| 45 | + // Sample property. |
| 46 | + public string Prop { get; set; } = "BridgeAddRemoteObject.Prop"; |
| 47 | + |
| 48 | + public AnotherRemoteObject AnotherObject { get; set; } = new AnotherRemoteObject(); |
| 49 | + |
| 50 | + // Sample indexed property. |
| 51 | + [System.Runtime.CompilerServices.IndexerName("Items")] |
| 52 | + public string this[int index] |
| 53 | + { |
| 54 | + get { return m_dictionary[index]; } |
| 55 | + set { m_dictionary[index] = value; } |
| 56 | + } |
| 57 | + private Dictionary<int, string> m_dictionary = new Dictionary<int, string>(); |
| 58 | + |
| 59 | + static public string scenarioHtml = |
| 60 | +@"<!DOCTYPE html> |
| 61 | +
|
| 62 | +<button id='runTest'>Run Test</button> |
| 63 | +<button id='method'>Method with param</button> |
| 64 | +<button id='methodNoParam'>Method no param</button> |
| 65 | +<button id='propertyGet'>Property Get</button> |
| 66 | +<button id='propertySet'>Property Set</button> |
| 67 | +<button id='indexerGet'>Get object[index]</button> |
| 68 | +<button id='indexerSet'>Set object[index]</button> |
| 69 | +<button id='indexerGetAlias'>Get Items[index]</button> |
| 70 | +<button id='indexerSetAlias'>Set Items[index]</button> |
| 71 | +<script> |
| 72 | + function getStack() { |
| 73 | + try { |
| 74 | + throw new Error(''); |
| 75 | + } catch (error) { |
| 76 | + return error.stack; |
| 77 | + } |
| 78 | + } |
| 79 | +
|
| 80 | + function valueToString(value) { |
| 81 | + return '(' + JSON.stringify(value) + ', ' + (typeof value) + ')'; |
| 82 | + } |
| 83 | + async function assert(condition, text, message) { |
| 84 | + if (!condition) { |
| 85 | + alert('Assertion failed, ' + text + ': ' + message); |
| 86 | + } else { |
| 87 | + console.log('assert passed: ' + text); |
| 88 | + } |
| 89 | + } |
| 90 | +
|
| 91 | + function assertEqual(actual, expected, text) |
| 92 | + { |
| 93 | + assert(expected === actual, text, ('Equality assertion failed. ' + |
| 94 | + 'Expected ' + valueToString(expected) + ', ' + |
| 95 | + 'Actual ' + valueToString(actual) + ', ' + getStack())); |
| 96 | + } |
| 97 | + document.getElementById('runTest').addEventListener('click', async () => { |
| 98 | + const bridge = chrome.webview.hostObjects.bridge; |
| 99 | + let expected_result = 'value1'; |
| 100 | + bridge.Prop = expected_result; |
| 101 | + let result = await bridge.Prop; |
| 102 | + assertEqual(result, expected_result, 'property on bridge'); |
| 103 | + const value2 = 'value2'; |
| 104 | + result = await bridge.Func(value2); |
| 105 | + expected_result = 'BridgeAddRemoteObject.Func(' + value2 + ')'; |
| 106 | + assertEqual(result, expected_result, 'method with parameter'); |
| 107 | + result = await bridge.Func2(); |
| 108 | + expected_result = 'BridgeAddRemoteObject.Func2()'; |
| 109 | + assertEqual(result, expected_result, 'method with no parameter'); |
| 110 | +
|
| 111 | + const another_object = bridge.AnotherObject; |
| 112 | + another_object.Prop = value2; |
| 113 | + result = await another_object.Prop; |
| 114 | + expected_result = value2; |
| 115 | + assertEqual(result, expected_result, 'property on another_object'); |
| 116 | +
|
| 117 | + let index = 123; |
| 118 | + expected_result = 'aa'; |
| 119 | + bridge[index] = expected_result; |
| 120 | + result = await bridge[index]; |
| 121 | + assertEqual(result, expected_result, 'bridge[index]'); |
| 122 | + index = 321; |
| 123 | + expected_result = 'bb'; |
| 124 | + bridge.Items[index] = expected_result; |
| 125 | + result = await bridge.Items[index]; |
| 126 | + assertEqual(result, expected_result, 'bridge.Items[index]'); |
| 127 | +
|
| 128 | + let resolved_bridge = await bridge; |
| 129 | + result = await bridge.GetObjectType(resolved_bridge); |
| 130 | + expected_result = 'BridgeAddRemoteObject'; |
| 131 | + assertEqual(result, expected_result, 'type of resolved_bridge'); |
| 132 | + result = await bridge.GetObjectType(bridge); |
| 133 | + expected_result = 'BridgeAddRemoteObject'; |
| 134 | + assertEqual(result, expected_result, 'type of bridge'); |
| 135 | + result = await bridge.GetObjectType(another_object); |
| 136 | + expected_result = 'AnotherRemoteObject'; |
| 137 | + assertEqual(result, expected_result, 'type of another_object'); |
| 138 | +
|
| 139 | + alert('Test End'); |
| 140 | + }); |
| 141 | + document.getElementById('method').addEventListener('click', async () => { |
| 142 | + const bridge = chrome.webview.hostObjects.bridge; |
| 143 | + const result = await bridge.Func(prompt('Method parameter text', 'Method parameter text')); |
| 144 | + alert(result); |
| 145 | + }); |
| 146 | + document.getElementById('methodNoParam').addEventListener('click', async () => { |
| 147 | + const bridge = chrome.webview.hostObjects.bridge; |
| 148 | + const result = await bridge.Func2(); |
| 149 | + alert(result); |
| 150 | + }); |
| 151 | + document.getElementById('propertyGet').addEventListener('click', async () => { |
| 152 | + const bridge = chrome.webview.hostObjects.bridge; |
| 153 | + const result = await bridge.Prop; |
| 154 | + alert(result); |
| 155 | + }); |
| 156 | + document.getElementById('propertySet').addEventListener('click', async () => { |
| 157 | + const bridge = chrome.webview.hostObjects.bridge; |
| 158 | + bridge.Prop = prompt('Property text', 'Property text'); |
| 159 | + }); |
| 160 | + document.getElementById('indexerGet').addEventListener('click', async () => { |
| 161 | + const bridge = chrome.webview.hostObjects.bridge; |
| 162 | + const result = await bridge[1]; |
| 163 | + alert(result); |
| 164 | + }); |
| 165 | + document.getElementById('indexerSet').addEventListener('click', async () => { |
| 166 | + const bridge = chrome.webview.hostObjects.bridge; |
| 167 | + bridge[1] = prompt('Property text', 'Property text'); |
| 168 | + }); |
| 169 | + document.getElementById('indexerGetAlias').addEventListener('click', async () => { |
| 170 | + const bridge = chrome.webview.hostObjects.bridge; |
| 171 | + const result = await bridge.Items[12]; |
| 172 | + alert(result); |
| 173 | + }); |
| 174 | + document.getElementById('indexerSetAlias').addEventListener('click', async () => { |
| 175 | + const bridge = chrome.webview.hostObjects.bridge; |
| 176 | + bridge.Items[12] = prompt('Property text', 'Property text'); |
| 177 | + }); |
| 178 | +</script> |
| 179 | +"; |
| 180 | + } |
| 181 | +} |
0 commit comments