Partager via


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

  1. 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.

  2. 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.

  3. Ouvrez Microsoft Visual Studio. Nous vous recommandons d’ouvrir initialement l’exemple Win32 à l’aide de Visual Studio 2019.

  4. Dans votre copie locale du référentiel clonéWebView2Samples, ouvrezSampleApps>WebView2Samples>WebView2Samples.sln. WebView2Samples.sln inclut le WebView2APISample 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.

  1. 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érite IUnknown comme est standard pour COM. Utilisez cette IHostObjectSample 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();
    
        };
    
  2. Ci-dessus, notez le DateProperty, qui utilise un DATE 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.

  1. Dans HostObjectSample.idl, examinez la HostObjectSamplecoclasse (classe d’objet composant), qui inclut les IHostObjectSample interfaces et IDispatch :

        [uuid(637abc45-11f7-4dde-84b4-317d62a638d3)]
        coclass HostObjectSample
        {
            [default] interface IHostObjectSample;
            interface IDispatch;
        };
    }
    
  2. La HostObjectSample coclasse inclut interface IDispatch, qui est nécessaire pour que l’objet hôte fonctionne avec AddHostObjectToScript.

É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.

  1. Dans l’Explorateur de solutions Visual Studio, développez WebView2APISample>Source Files, puis double-cliquez sur HostObjectSampleImpl.cpp pour l’ouvrir.

  2. 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();
    
  3. 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;
    }
    
  4. 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 IDispatchpas 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.

  1. Ensuite, enregistrez les modifications que vous avez apportées au projet.

  2. 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.

  1. Dans l’Explorateur de solutions Visual Studio, ouvrez WebView2APISample>Source Files>ScenarioAddHostObject.cpp.

  2. 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);
        });
    
  3. L’instruction Make montre comment instancier l’objet HostObjectSample COM qui a été défini dans le fichier IDL. Il s’agit de l’objet que nous utiliserons ultérieurement lorsque nous appellerons AddHostObjectToScript. L’instruction Make nous obtient un pointeur vers l’interface implémentée dans HostObjectSampleImpl.cpp.

  4. 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());
    
  5. Dans le NavigationStarting gestionnaire d’événements, la query_to ligne (ci-dessous) convertit l’objet COM nouvellement créé en type IDispatch , puis convertit l’objet en VARIANT. 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 que IDispatch.

    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 par AddHostObjectToScript. 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.

  6. Dans la ligne inférieure ci-dessus, le NavigationStarting gestionnaire d’événements définit ensuite le type de variant de l’objet distant sur IDispatch.

                // 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();
            }
    
  7. Ci-dessus, dans le NavigationStarting gestionnaire d’événements, est VARIANT passé à , en AddHostObjectToScriptutilisant le nom sample.

É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.

  1. Dans Microsoft Visual Studio, sélectionnez Fichier>Enregistrer tout (Ctrl+Maj+S) pour enregistrer le projet.

  2. 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.

  3. 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.

  4. Appuyez sur F5 pour exécuter le projet en mode débogage.

  5. 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:

    Haut de la page de démonstration d’objets hôtes

  6. 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>:

    Bas de la page de démonstration d’objets hôtes

  7. Dans la page de démonstration affichée de l’exemple d’application, lisez le texte de l’étiquette expliquant les boutons Date .

  8. 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)
    
  9. 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.

  10. 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ément body :

    <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 .

  11. Le code suivant est une propriété de démonstration Date qui est encapsulée dans un iframe élément créé dans un script é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; 
    });
    
  12. L’expression chrome.webview.hostObjects.sync.sample.dateProperty est le dateProperty 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 :

  1. Créez un objet hôte dans le code côté natif de votre application.
  2. Passez l’objet hôte au code côté web de votre application.
  3. 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

GitHub :