Appeler du code natif à partir d’un code côté web
WebView2 permet aux applications de combler l’écart entre le côté web et le côté natif d’une application en permettant à un objet d’être passé au web. Vous exposez les API côté natif sélectionnées à votre page web JavaScript via un objet hôte natif intermédiaire défini dans le code natif. Les API côté natif sont projetées en JavaScript à l’aide de l’API WebView2 AddHostObjectToScript
.
Cet article couvre principalement Win32/C++, ainsi que certains aspects de .NET/C# dans les cadres. Pour WinRT, consultez Appeler du code WinRT côté natif à partir d’un code côté web.
Pourquoi utiliser AddHostObjectToScript
?
Lorsque vous développez une application WebView2, vous pouvez rencontrer un objet natif dont les méthodes ou propriétés vous trouvent utiles. Vous souhaiterez peut-être déclencher ces méthodes d’objet natives à partir du code côté web, à la suite d’une interaction utilisateur sur le côté web de votre application. En outre, il se peut que vous ne souhaitiez pas réapplémenter les méthodes de vos objets natifs dans votre code côté web. L’API
AddHostObjectToScript
permet la réutilisation du code natif par du code côté web.Par exemple, il peut y avoir une API de webcam native, qui nécessiterait la réécriture d’une grande quantité de code côté web. La possibilité d’appeler les méthodes de l’objet natif est plus rapide et plus efficace que le re-codage des méthodes de l’objet sur le web de votre application. Dans ce cas, votre code côté natif peut passer l’objet au code JavaScript côté web de votre application, afin que votre code JavaScript puisse réutiliser les méthodes de l’API native.
Scénarios qui peuvent tirer parti de l’utilisation d’objets hôtes dans un script :
Il existe une API de clavier et vous souhaitez appeler la
keyboardObject.showKeyboard
fonction à partir du côté web.Accès au système de fichiers, pas seulement au bac à sable de la page web, via JavaScript. JavaScript est en bac à sable, ce qui l’empêche d’accéder directement au système de fichiers. En utilisant
AddHostObjectToScript
pour créer un objet natif exposé à JavaScript, vous pouvez utiliser l’objet hôte pour manipuler des fichiers sur le système de fichiers, pas seulement dans le bac à sable de la page web.
Cet article utilise l’exemple d’application Win32 pour illustrer certaines applications pratiques de AddHostObjectToScript
.
Étape 1 : Installer Visual Studio, installer git, cloner le référentiel WebView2Samples et ouvrir la solution
Téléchargez et installez Microsoft Visual Studio 2019 (version 16.11.10) ou ultérieure, ainsi que d’autres prérequis, comme décrit dans Exemple d’application Win32. L’exemple d’application Win32 a été créé à l’aide de Visual Studio 2019. Par conséquent, pour suivre les étapes de cet article, nous vous recommandons de commencer par Visual Studio 2019 plutôt que Visual Studio 2022.
Clonez le référentiel WebView2Samples . Le référentiel inclut l’exemple d’application WebView2 spécifique à Win32. Pour obtenir des instructions, dans une nouvelle fenêtre ou un nouvel onglet, consultez Exemple d’application Win32.
Ouvrez Microsoft Visual Studio. Nous vous recommandons d’ouvrir initialement l’exemple Win32 à l’aide de Visual Studio 2019.
Dans votre copie locale du référentiel cloné
WebView2Samples
, ouvrezSampleApps
>WebView2Samples
>WebView2Samples.sln.WebView2Samples.sln
inclut leWebView2APISample
projet, qui est l’exemple d’application Win32. Gardez l’exemple de solution d’application ouvert pour suivre le reste de cet article.
Étape 2 : Définir l’interface COM de l’objet hôte à l’aide d’IDL
Définissez l’interface COM de l’objet hôte dans un .idl
fichier, comme HostObjectSample.idl, pour décrire les méthodes et les propriétés de l’objet hôte.
Tout d’abord, utilisez le langage IDL (Interface Definition Language) pour définir l’interface COM de l’objet hôte. Cette définition d’objet hôte dans un idl
fichier décrit les méthodes et propriétés natives exposées (ou « encapsulées »). Le fichier IDL (.idl
) définit une interface, mais ne l’implémente pas.
Dans l’Explorateur de solutions Visual Studio, développez WebView2APISample>Source Files, puis double-cliquez pour
HostObjectSample.idl
l’ouvrir.Le code suivant définit l’interface
IHostObjectSample
, qui hériteIUnknown
comme est standard pour COM. Utilisez cetteIHostObjectSample
définition comme modèle pour définir les méthodes, les propriétés, les fonctions de rappel, etc. de votre objet.import "oaidl.idl"; import "ocidl.idl"; [uuid(0a7a4655-5660-47d0-8a37-98ae21399e57), version(0.1)] library HostObjectSampleLibrary { [uuid(3a14c9c0-bc3e-453f-a314-4ce4a0ec81d8), object, local] interface IHostObjectSample : IUnknown { // Demonstrates a basic method call with some parameters and a return value. HRESULT MethodWithParametersAndReturnValue([in] BSTR stringParameter, [in] INT integerParameter, [out, retval] BSTR* stringResult); // Demonstrate getting and setting a property. [propget] HRESULT Property([out, retval] BSTR* stringResult); [propput] HRESULT Property([in] BSTR stringValue); [propget] HRESULT IndexedProperty(INT index, [out, retval] BSTR * stringResult); [propput] HRESULT IndexedProperty(INT index, [in] BSTR stringValue); // Demonstrate native calling back into JavaScript. HRESULT CallCallbackAsynchronously([in] IDispatch* callbackParameter); // Demonstrates a property which uses Date types. [propget] HRESULT DateProperty([out, retval] DATE * dateResult); [propput] HRESULT DateProperty([in] DATE dateValue); // Creates a date object on the native side and sets the DateProperty to it. HRESULT CreateNativeDate(); };
Ci-dessus, notez le
DateProperty
, qui utilise unDATE
type . Nous allons nous concentrer sur cette propriété de démonstration de date dans cet article.
Étape 3 : Définir une coclasse d’objet hôte
Ensuite, l’exemple définit la HostObjectSample
coclasse à inclure IHostObjectSample
et IDispatch
.
Dans
HostObjectSample.idl
, examinez laHostObjectSample
coclasse (classe d’objet composant), qui inclut lesIHostObjectSample
interfaces etIDispatch
:[uuid(637abc45-11f7-4dde-84b4-317d62a638d3)] coclass HostObjectSample { [default] interface IHostObjectSample; interface IDispatch; }; }
La
HostObjectSample
coclasse inclutinterface IDispatch
, qui est nécessaire pour que l’objet hôte fonctionne avecAddHostObjectToScript
.
Étape 4 : Implémenter les membres de l’objet C++
Dans l’exemple de code d’application Win32, HostObjectSampleImpl.cpp prend le squelette créé dans le fichier IDL COM et implémente chaque membre de l’objet C++. Ce fichier C++ (.cpp
) implémente l’interface définie (et implémente IDispatch
également ).
Implémentez toutes les fonctions définies dans l’interface de votre objet, comme nous l’avons décrit dans le fichier IDL. Veillez à implémenter les fonctions requises par IDispatch
. Le compilateur génère une erreur si ces fonctions ne sont pas définies.
Ensuite, nous examinons deux propriétés spécifiques qui ont été définies dans l’IDL pour montrer comment l’IDL est lié au .cpp
fichier.
Dans l’Explorateur de solutions Visual Studio, développez WebView2APISample>Source Files, puis double-cliquez sur HostObjectSampleImpl.cpp pour l’ouvrir.
Examinez les déclarations de propriété dans HostObjectSample.idl :
// Demonstrate getting and setting a property. [propget] HRESULT Property([out, retval] BSTR* stringResult); [propput] HRESULT Property([in] BSTR stringValue); ... // Demonstrate a property which uses Date types [propget] HRESULT DateProperty([out, retval] DATE * dateResult); [propput] HRESULT DateProperty([in] DATE dateValue); // Creates a date object on the native side and sets the DateProperty to it. HRESULT CreateNativeDate();
Examinez l’implémentation des propriétés de l’objet dans HostObjectSampleImpl.cpp :
STDMETHODIMP HostObjectSample::get_Property(BSTR* stringResult) { *stringResult = SysAllocString(m_propertyValue.c_str()); return S_OK; } STDMETHODIMP HostObjectSample::put_Property(BSTR stringValue) { m_propertyValue = stringValue; return S_OK; } ... STDMETHODIMP HostObjectSample::get_DateProperty(DATE* dateResult) { *dateResult = m_date; return S_OK; } STDMETHODIMP HostObjectSample::put_DateProperty(DATE dateValue) { m_date = dateValue; SYSTEMTIME systemTime; if (VariantTimeToSystemTime(dateValue, &systemTime)) ... } STDMETHODIMP HostObjectSample::CreateNativeDate() { SYSTEMTIME systemTime; GetSystemTime(&systemTime); DATE date; if (SystemTimeToVariantTime(&systemTime, &date)) { return put_DateProperty(date); } return E_UNEXPECTED; }
Examinez
DateProperty
, que nous suivons tout au long de cet article.
Étape 5 : Implémenter IDispatch
L’objet hôte doit implémenter IDispatch
afin que WebView2 puisse projeter l’objet hôte natif dans le code côté web de l’application.
IDispatch
vous permet d’appeler dynamiquement des méthodes et des propriétés. Normalement, l’appel d’objets nécessite des appels statiques, mais vous pouvez utiliser JavaScript pour créer dynamiquement des appels d’objets. Dans l’exemple de code d’application Win32, HostObjectSampleImpl.cpp implémente IDispatch
, ce qui signifie que les méthodes suivantes sont implémentées :
GetIDsOfNames
GetTypeInfo
GetTypeInfoCount
Invoke
Implémentez IDispatch
comme décrit dans Bibliothèques de types et langage de description d’objet. Pour plus d’informations sur l’héritage IDispatch
et les méthodes, consultez Interface IDispatch (oaidl.h).
Si l’objet que vous souhaitez ajouter à JavaScript n’implémente IDispatch
pas déjà , vous devez écrire un IDispatch
wrapper de classe pour l’objet que vous souhaitez exposer.
Il peut y avoir des bibliothèques pour effectuer cette opération automatiquement. Pour en savoir plus sur les étapes nécessaires à l’écriture d’un IDispatch
wrapper de classe pour l’objet que vous souhaitez exposer, consultez Automation.
Ensuite, enregistrez les modifications que vous avez apportées au projet.
Dans l’Explorateur de solutions, cliquez avec le bouton droit sur WebView2APISample (qui est l’exemple d’application Win32), puis sélectionnez Générer. Cela crée un fichier de bibliothèque
.tlb
de types COM. Vous devez référencer le.tlb
fichier à partir du code source C++. Pour plus d’informations, consultez Bibliothèque de types dans COM, DCOM et bibliothèques de types.
Étape 6 : Appeler AddHostObjectToScript pour passer l’objet hôte au code côté web
Jusqu’à présent, nous avons créé notre interface et implémenté notre objet hôte natif. Nous sommes maintenant prêts à utiliser AddHostObjectToScript
pour passer l’objet hôte natif au code JavaScript côté web de notre application. L’exemple d’application Win32 appelle AddHostObjectToScript
dans ScenarioAddHostObject.cpp, comme indiqué ci-dessous.
Dans l’Explorateur de solutions Visual Studio, ouvrez WebView2APISample>Source Files>ScenarioAddHostObject.cpp.
Accédez à l’implémentation de classe
ScenarioAddHostObject
. Cette classe affiche du code HTML et gère la navigation :ScenarioAddHostObject::ScenarioAddHostObject(AppWindow* appWindow) : m_appWindow(appWindow), m_webView(appWindow->GetWebView()) { std::wstring sampleUri = m_appWindow->GetLocalUri(L"ScenarioAddHostObject.html"); m_hostObject = Microsoft::WRL::Make<HostObjectSample>( [appWindow = m_appWindow](std::function<void(void)> callback) { appWindow->RunAsync(callback); });
L’instruction
Make
montre comment instancier l’objetHostObjectSample
COM qui a été défini dans le fichier IDL. Il s’agit de l’objet que nous utiliserons ultérieurement lorsque nous appelleronsAddHostObjectToScript
. L’instructionMake
nous obtient un pointeur vers l’interface implémentée dans HostObjectSampleImpl.cpp.Ensuite, nous ajoutons un gestionnaire d’événements pour écouter l’événement
NavigationStarting
:CHECK_FAILURE(m_webView->add_NavigationStarting( Microsoft::WRL::Callback<ICoreWebView2NavigationStartingEventHandler>( [this, sampleUri](ICoreWebView2* sender, ICoreWebView2NavigationStartingEventArgs* args) -> HRESULT { wil::unique_cotaskmem_string navigationTargetUri; CHECK_FAILURE(args->get_Uri(&navigationTargetUri)); std::wstring uriTarget(navigationTargetUri.get());
Dans le
NavigationStarting
gestionnaire d’événements, laquery_to
ligne (ci-dessous) convertit l’objet COM nouvellement créé en typeIDispatch
, puis convertit l’objet enVARIANT
.VARIANT
les types vous permettent d’utiliser des structures de données telles que des entiers et des tableaux, ainsi que des types plus complexes tels queIDispatch
.Pour obtenir la liste complète des types de données pris en charge, consultez STRUCTURE VARIANT (oaidl.h). Tous les types de l’union
VARIANT
ne sont pas pris en charge parAddHostObjectToScript
. Pour plus d’informations, consultez Méthode ICoreWebView2 ::AddHostObjectToScript.if (AreFileUrisEqual(sampleUri, uriTarget)) { VARIANT remoteObjectAsVariant = {}; m_hostObject.query_to<IDispatch>(&remoteObjectAsVariant.pdispVal); remoteObjectAsVariant.vt = VT_DISPATCH;
Maintenant que nous avons une variante de l’objet compatible avec le code C++, le code côté natif de l’exemple d’application est prêt à passer l’objet hôte au code côté web de l’application.
Dans la ligne inférieure ci-dessus, le
NavigationStarting
gestionnaire d’événements définit ensuite le type de variant de l’objet distant surIDispatch
.// We can call AddHostObjectToScript multiple times in a row without // calling RemoveHostObject first. This will replace the previous object // with the new object. In our case this is the same object and everything // is fine. CHECK_FAILURE( m_webView->AddHostObjectToScript(L"sample", &remoteObjectAsVariant)); remoteObjectAsVariant.pdispVal->Release(); }
Ci-dessus, dans le
NavigationStarting
gestionnaire d’événements, estVARIANT
passé à , enAddHostObjectToScript
utilisant le nomsample
.
Étape 7 : Accéder aux membres de l’objet hôte à partir de la page web JavaScript
Dans les étapes ci-dessus, le code côté natif de l’exemple d’application a créé un objet hôte qui implémente IDispatch
. Ce code natif appelle également l’API ICoreWebView2::AddHostObjectToScript
WebView2 ou et ICoreWebView2Frame::AddHostObjectToScriptWithOrigins
transmet l’objet hôte au code côté web de l’application.
Désormais, le code côté web de l’application peut accéder aux API natives exposées par l’objet hôte. Les instructions JavaScript dans votre .html
élément de page web script
ou dans un fichier JavaScript référencé .js
peuvent accéder aux API côté natif exportées.
Le code côté web de l’exemple d’application Win32 est désormais en mesure d’accéder aux propriétés et méthodes de l’objet hôte natif pour accéder aux API natives. Nous allons utiliser les contrôles de page web de l’exemple d’application, dans la page WebObjets hôtes de scénario> de l’application, pour illustrer cela.
Dans Microsoft Visual Studio, sélectionnez Fichier>Enregistrer tout (Ctrl+Maj+S) pour enregistrer le projet.
Dans l’Explorateur de solutions, ouvrez WebView2APISample>ScenarioAddHostObject.html. Nous allons comparer ce fichier à la page web correspondante dans l’exemple d’application Win32 en cours d’exécution.
Dans l’Explorateur de solutions, cliquez avec le bouton droit sur WebView2APISample (qui est l’exemple d’application Win32), puis sélectionnez Générer.
Appuyez sur F5 pour exécuter le projet en mode débogage.
Dans l’exemple d’application Win32 (qui a la barre de titre de WebView2APISample), cliquez sur le menu Scénario , puis sélectionnez l’élément de menu Objets hôtes . La page web AddHostObjectToScript Sample s’affiche, définie par
ScenarioAddHostObject.html
:La page web suggère d’utiliser l’outil Console de DevTools pour exécuter des instructions JavaScript sur l’objet
chrome.webview.hostObjects.sample
. Si vous souhaitez ouvrir DevTools à partir de l’exemple d’application, cliquez avec le bouton droit sur la page, puis sélectionnez Inspecter. Sélectionnez ensuite l’onglet Console . Pour plus d’informations, consultez Vue d’ensemble de la console.Pour ouvrir DevTools, appuyer sur F12 peut ne pas fonctionner dans ce contexte et déclencher une exception. Si c’est le cas, dans Visual Studio, sélectionnez Arrêter le débogage, puis appuyez sur F5 pour redémarrer le débogage. Dans l’exemple d’application, sélectionnezà nouveau Objets hôtesde scénario>. Pour plus d’informations, consultez Ouvrir DevTools à l’aide d’une approche autre que F12 dans Déboguer des applications WebView2 avec Visual Studio.
Le bas de la page de démonstration Des objets hôtes duplique les membres de l’objet de démonstration au sein d’un
<iframe>
:Dans la page de démonstration affichée de l’exemple d’application, lisez le texte de l’étiquette expliquant les boutons Date .
Cliquez sur les boutons Date . Une chaîne de date s’affiche sous les boutons, par exemple :
sample.dateProperty: Tue Nov 01 2022 12:45:25 GMT-0700 (Pacific Daylight Time)
Explorez les propriétés et les méthodes en cliquant sur les boutons de la page web de démonstration et en entrant des valeurs pour voir le comportement de l’exemple de code. Les boutons illustrent l’accès aux propriétés et méthodes de l’objet hôte à partir du code côté web de l’application.
Pour obtenir des informations sur ce qui se passe dans JavaScript, examinez le code suivant dans ScenarioAddHostObject.html.
Le code suivant est une propriété de démonstration
Date
, directement dans l’élémentbody
:<h2>Date Objects</h2> <button id="setDateButton">Set Date to Now</button> <label for="setDateButton">Sets <code>chrome.webview.hostObjects.options.shouldSerializeDates = true</code> and then runs <code>chrome.webview.hostObjects.sample.dateProperty = new Date()</code></label> <br /> <button id="createRemoteDateButton">Set Remote Date</button> <label for="createRemoteDateButton">Calls <code>chrome.webview.hostObjects.sample.createNativeDate()</code> to have the native object create and set the current time to the DateProperty</label> <code><pre><span id="dateOutput"></span></pre></code> <div id="div_iframe" style="display: none;"> <h2>IFrame</h2> </div>
Vous pouvez également lire le texte de l’étiquette ci-dessus dans la page de démonstration affichée dans l’exemple d’application, en expliquant le code du bouton Date .
Le code suivant est une propriété de démonstration
Date
qui est encapsulée dans uniframe
élément créé dans unscript
élément :// Date property document.getElementById("setDateButton").addEventListener("click", () => { chrome.webview.hostObjects.options.shouldSerializeDates = true; chrome.webview.hostObjects.sync.sample.dateProperty = new Date(); document.getElementById("dateOutput").textContent = "sample.dateProperty: " + chrome.webview.hostObjects.sync.sample.dateProperty; }); document.getElementById("createRemoteDateButton").addEventListener("click", () => { chrome.webview.hostObjects.sync.sample.createNativeDate(); document.getElementById("dateOutput").textContent = "sample.dateProperty: " + chrome.webview.hostObjects.sync.sample.dateProperty; });
L’expression
chrome.webview.hostObjects.sync.sample.dateProperty
est ledateProperty
de l’objet hôte natif.Dans le
.idl
fichier HostObjectSample.idl, décrit précédemment, la propriété date est définie dans le cadre de l’objet hôte.
Utilisation de l’exemple d’application
Vous pouvez tester l’utilisation et la modification de l’exemple d’application Win32. Suivez ensuite le même modèle dans votre propre application :
- Créez un objet hôte dans le code côté natif de votre application.
- Passez l’objet hôte au code côté web de votre application.
- Utilisez l’objet hôte à partir du code côté web de l’application.
Pour savoir quelles autres API existent dans l’écosystème d’objets hôtes, consultez WebView2 Win32 C++ ICoreWebView2.
Vue d’ensemble des informations de référence sur les API
Consultez Partage d’objets hôte/web dans Vue d’ensemble des fonctionnalités et API WebView2.
Voir aussi
- Interopérabilité web/native dans Vue d’ensemble des fonctionnalités et API WebView2.
- Utilisation de cadres dans les applications WebView2
- Appeler du code WinRT côté natif à partir d’un code côté web
GitHub :