Freigeben über


Aufrufen von systemeigenem Code aus webseitigem Code

WebView2 ermöglicht Es Anwendungen, die Lücke zwischen dem Web und der nativen Seite einer Anwendung zu schließen, indem ein Objekt an das Web übergeben werden kann. Sie machen ausgewählte native APIs für JavaScript ihrer Webseite über ein im nativen Code definiertes zwischengeschaltetes natives Hostobjekt verfügbar. Die nativen APIs werden mithilfe der WebView2-API AddHostObjectToScript in JavaScript projiziert.

In diesem Artikel wird hauptsächlich Win32/C++ behandelt, und es werden auch einige Aspekte von .NET/C# innerhalb von Frames behandelt. Informationen zu WinRT finden Sie unter Aufrufen von nativem WinRT-Code aus webseitigem Code.

Gründe für die Verwendung AddHostObjectToScriptvon ?

  • Beim Entwickeln einer WebView2-App tritt möglicherweise ein natives Objekt auf, dessen Methoden oder Eigenschaften Sie nützlich finden. Möglicherweise möchten Sie diese nativen Objektmethoden aus webseitigem Code als Ergebnis einer Benutzerinteraktion auf der Webseite Ihrer App auslösen. Darüber hinaus möchten Sie die Methoden Ihrer nativen Objekte möglicherweise nicht erneut in Ihren webseitigen Code implementieren. Die AddHostObjectToScript API ermöglicht die Wiederverwendung von nativem Code durch webseitigen Code.

  • Beispielsweise kann es eine native Webcam-API geben, für die eine große Menge an Code auf der Webseite neu geschrieben werden muss. Die Möglichkeit, die Methoden des nativen Objekts aufzurufen, ist schneller und effizienter, als die Methoden des Objekts auf der Webseite Ihrer App neu zu codieren. In diesem Fall kann Ihr nativer Code das Objekt an den webseitigen JavaScript-Code Ihrer App übergeben, sodass Ihr JavaScript-Code die Methoden der nativen API wiederverwenden kann.

Szenarien, die von der Verwendung von Hostobjekten im Skript profitieren können:

  • Es gibt eine Tastatur-API, und Sie möchten die keyboardObject.showKeyboard Funktion von der Webseite aufrufen.

  • Zugriff auf das Dateisystem, nicht nur auf die Sandbox für Webseiten, über JavaScript. JavaScript ist eine Sandbox, die verhindert, dass es direkt auf das Dateisystem zugreifen kann. Wenn Sie verwenden AddHostObjectToScript , um ein natives Objekt zu erstellen, das für JavaScript verfügbar gemacht wird, können Sie das Hostobjekt verwenden, um Dateien im Dateisystem zu bearbeiten, nicht nur in der Sandbox für Webseiten.

In diesem Artikel wird die Win32-Beispiel-App verwendet, um einige praktische Anwendungen von zu veranschaulichen AddHostObjectToScript.

Schritt 1: Installieren von Visual Studio, Installieren von Git, Klonen des WebView2Samples-Repositorys und Öffnen der Projektmappe

  1. Laden Sie Microsoft Visual Studio 2019 (Version 16.11.10) oder höher herunter, und installieren Sie sie, und installieren Sie es, und installieren Sie andere Voraussetzungen, wie unter Win32-Beispiel-App beschrieben. Die Win32-Beispiel-App wurde mit Visual Studio 2019 erstellt. Um die Beispielschritte in diesem Artikel auszuführen, empfehlen wir daher, mit Visual Studio 2019 statt mit Visual Studio 2022 zu beginnen.

  2. Klonen Sie das WebView2Samples-Repository . Das Repository enthält die Win32-spezifische WebView2-Beispiel-App. Anweisungen in einem neuen Fenster oder einer neuen Registerkarte finden Sie unter Win32-Beispiel-App.

  3. Öffnen Sie Microsoft Visual Studio. Es wird empfohlen, das Win32-Beispiel zunächst mit Visual Studio 2019 zu öffnen.

  4. Öffnen>WebView2Samples>SampleApps Sie in Ihrer lokalen Kopie des geklontenWebView2Samples Repositorys WebView2Samples.sln. WebView2Samples.sln enthält das WebView2APISample Projekt, bei dem es sich um die Win32-Beispiel-App handelt. Lassen Sie die Beispiel-App-Lösung geöffnet, um den Rest dieses Artikels zu befolgen.

Schritt 2: Definieren der COM-Schnittstelle des Hostobjekts mithilfe von IDL

Definieren Sie die COM-Schnittstelle des Hostobjekts in einer .idl Datei wie HostObjectSample.idl, um die Methoden und Eigenschaften für das Hostobjekt zu beschreiben.

Verwenden Sie zunächst die Schnittstellendefinitionssprache (Interface Definition Language, IDL), um die COM-Schnittstelle des Hostobjekts zu definieren. Diese Hostobjektdefinition in einer idl Datei beschreibt die verfügbar gemachten (oder "umschlossenen") nativen Eigenschaften und Methoden. Die IDL-Datei (.idl) definiert eine Schnittstelle, implementiert sie jedoch nicht.

  1. Erweitern Sie im Projektmappen-Explorer von Visual Studio WebView2APIQuelldateien>, und doppelklicken Sie dann,HostObjectSample.idl um es zu öffnen.

    Der folgende Code definiert die IHostObjectSample -Schnittstelle, die gemäß dem Standard für COM erbt IUnknown . Verwenden Sie diese IHostObjectSample Definition als Vorlage zum Definieren der Methoden, Eigenschaften, Rückruffunktionen usw. ihres Objekts.

    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. Beachten Sie oben die DateProperty, die einen DATE -Typ verwendet. Wir konzentrieren uns in diesem Artikel auf diese Datumsdemoeigenschaft.

Schritt 3: Definieren einer Hostobjekt-Co-Klasse

Als Nächstes definiert das Beispiel die HostObjectSample Co-Klasse, um und IDispatcheinzuschließenIHostObjectSample.

  1. Untersuchen Sie in HostObjectSample.idldie HostObjectSampleCo-Klasse (Komponentenobjektklasse), die die IHostObjectSample Schnittstellen und IDispatch enthält:

        [uuid(637abc45-11f7-4dde-84b4-317d62a638d3)]
        coclass HostObjectSample
        {
            [default] interface IHostObjectSample;
            interface IDispatch;
        };
    }
    
  2. Die HostObjectSample Co-Klasse enthält interface IDispatch, was erforderlich ist, damit das Hostobjekt mit AddHostObjectToScriptfunktioniert.

Schritt 4: Implementieren der Elemente des C++-Objekts

Im Win32-Beispiel-App-Code übernimmt HostObjectSampleImpl.cpp das Gerüst, das in der COM-IDL-Datei erstellt wurde, und implementiert jedes Element des C++-Objekts. Diese C++-Datei (.cpp) implementiert die definierte Schnittstelle (und implementiert IDispatchauch ).

Implementieren Sie alle Funktionen, die in der Schnittstelle Ihres Objekts definiert sind, wie in der IDL-Datei beschrieben. Stellen Sie sicher, dass Sie die Funktionen implementieren, die für IDispatcherforderlich sind. Der Compiler löst einen Fehler aus, wenn diese Funktionen nicht definiert sind.

Als Nächstes untersuchen wir zwei spezifische Eigenschaften, die in der IDL definiert wurden, um zu zeigen, wie die IDL mit der .cpp Datei verknüpft ist.

  1. Erweitern Sie im Projektmappen-Explorer von Visual Studio WebView2APIQuelldateien>, und doppelklicken Sie dann auf HostObjectSampleImpl.cpp, um es zu öffnen.

  2. Untersuchen Sie die Eigenschaftendeklarationen in 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. Untersuchen Sie die Implementierung der Eigenschaften des Objekts in 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. Untersuchen Sie DateProperty, die wir in diesem Artikel nachverfolgen.

Schritt 5: Implementieren von IDispatch

Das Hostobjekt muss implementieren IDispatch , damit WebView2 das native Hostobjekt in den webseitigen Code der App projizieren kann.

IDispatch ermöglicht das dynamische Aufrufen von Methoden und Eigenschaften. Normalerweise erfordert das Aufrufen von Objekten statische Aufrufe, aber Sie können JavaScript verwenden, um Objektaufrufe dynamisch zu erstellen. Im Win32-Beispiel-App-Code implementiert IDispatchHostObjectSampleImpl.cpp , was bedeutet, dass diese Methoden implementiert werden:

  • GetIDsOfNames
  • GetTypeInfo
  • GetTypeInfoCount
  • Invoke

Implementieren Sie IDispatch wie unter Typbibliotheken und objektbeschreibungssprache beschrieben. Weitere Informationen zu IDispatch Vererbung und Methoden finden Sie unter IDispatch-Schnittstelle (oaidl.h).

Wenn das Objekt, das Sie JavaScript hinzufügen möchten, noch nicht implementiert IDispatch, müssen Sie einen IDispatch Klassenwrapper für das Objekt schreiben, das Sie verfügbar machen möchten.

Möglicherweise gibt es Bibliotheken, die dies automatisch tun. Weitere Informationen zu den Schritten, die zum Schreiben eines IDispatch Klassenwrappers für das Objekt erforderlich sind, das Sie verfügbar machen möchten, finden Sie unter Automatisierung.

  1. Speichern Sie als Nächstes alle Änderungen, die Sie im Projekt vorgenommen haben.

  2. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf WebView2APISample (die Win32-Beispiel-App), und wählen Sie dann Erstellen aus. Dadurch wird eine COM-Typbibliotheksdatei .tlb erstellt. Sie müssen aus dem .tlb C++-Quellcode auf die Datei verweisen. Weitere Informationen finden Sie unter Typbibliothek in COM, DCOM und Typbibliotheken.

Schritt 6: Aufrufen von AddHostObjectToScript, um das Hostobjekt an webseitigen Code zu übergeben

Bisher haben wir unsere Schnittstelle erstellt und unser natives Hostobjekt implementiert. Jetzt können wir verwenden AddHostObjectToScript , um das native Hostobjekt an den webseitigen JavaScript-Code unserer App zu übergeben. Die Win32-Beispiel-App ruft AddHostObjectToScript in ScenarioAddHostObject.cpp auf, wie unten gezeigt.

  1. Öffnen Sie im Projektmappen-Explorer von Visual Studio WebView2APISample>Source Files>ScenarioAddHostObject.cpp.

  2. Wechseln Sie zur ScenarioAddHostObject Klassenimplementierung. Diese Klasse zeigt HTML an und behandelt die 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. Die Make -Anweisung zeigt, wie das HostObjectSample COM-Objekt instanziiert wird, das in der IDL-Datei definiert wurde. Dies ist das Objekt, das wir später verwenden werden, wenn wir aufrufen AddHostObjectToScript. Die Make -Anweisung ruft uns einen Zeiger auf die Schnittstelle ab, die in HostObjectSampleImpl.cpp implementiert ist.

  4. Als Nächstes fügen wir einen Ereignishandler hinzu, um auf das NavigationStarting Ereignis zu lauschen:

        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. NavigationStarting Im Ereignishandler wandelt die query_to Zeile (unten) das neu erstellte COM-Objekt in einen IDispatch Typ um und konvertiert das Objekt dann in ein VARIANT. VARIANT mit -Typen können Sie Datenstrukturen wie ganze Zahlen und Arrays sowie komplexere Typen wie IDispatchverwenden.

    Eine vollständige Liste der unterstützten Datentypen finden Sie unter VARIANT-Struktur (oaidl.h). Nicht alle Typen in der VARIANT Union werden von AddHostObjectToScriptunterstützt. Weitere Informationen finden Sie unter ICoreWebView2::AddHostObjectToScript-Methode.

            if (AreFileUrisEqual(sampleUri, uriTarget))
            {
                VARIANT remoteObjectAsVariant = {};
                m_hostObject.query_to<IDispatch>(&remoteObjectAsVariant.pdispVal);
                remoteObjectAsVariant.vt = VT_DISPATCH;
    

    Da wir nun über eine Variante des Objekts verfügen, die C++-codefreundlich ist, ist der native Code der Beispiel-App bereit, um das Hostobjekt an den webseitigen Code der App zu übergeben.

  6. In der unteren Zeile oben legt der NavigationStarting Ereignishandler dann den Variant-Typ des Remoteobjekts auf IDispatchfest.

                // 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. Oben wird im NavigationStarting -Ereignishandler an VARIANT übergeben AddHostObjectToScript, wobei der Name sampleverwendet wird.

Schritt 7: Zugreifen auf Hostobjektmember über Webseiten-JavaScript

In den obigen IDispatchSchritten hat der native Code der Beispiel-App ein Hostobjekt erstellt, das implementiert. Dieser native Code ruft auch die WebView2-API ICoreWebView2::AddHostObjectToScript oder ICoreWebView2Frame::AddHostObjectToScriptWithOrigins auf und übergibt das Hostobjekt an den webseitigen Code der App.

Jetzt kann der webseitige Code der App auf die nativen APIs zugreifen, die vom Hostobjekt verfügbar gemacht werden. JavaScript-Anweisungen in Ihrem .html Webseitenelement script oder in einer JavaScript-Datei, auf die verwiesen wird .js , können auf die exportierten nativen APIs zugreifen.

Der webseitige Code der Win32-Beispiel-App kann jetzt auf die Eigenschaften und Methoden des nativen Hostobjekts zugreifen, um auf die nativen APIs zuzugreifen. Wir verwenden die Webseitensteuerelemente der Beispiel-App auf der WebseiteSzenariohostobjekte> der App, um dies zu veranschaulichen.

  1. Wählen Sie in Microsoft Visual Studio Datei>Alle speichern (STRG+UMSCHALT+S) aus, um das Projekt zu speichern.

  2. Öffnen Sie im Projektmappen-Explorer WebView2APISample>ScenarioAddHostObject.html. Wir vergleichen diese Datei mit der entsprechenden Webseite in der ausgeführten Win32-Beispiel-App.

  3. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf WebView2APISample (die Win32-Beispiel-App), und wählen Sie dann Erstellen aus.

  4. Drücken Sie F5 , um das Projekt im Debugmodus auszuführen.

  5. Klicken Sie in der Win32-Beispiel-App (die über die Titelleiste von WebView2APISample verfügt) auf das Menü Szenario , und wählen Sie dann das Menüelement Hostobjekte aus. Die Webseite AddHostObjectToScript-Beispiel wird angezeigt, die durch definiert wird ScenarioAddHostObject.html:

    Oben auf der Demoseite für Hostobjekte

  6. Die Webseite schlägt vor, das Konsolentool von DevTools zum Ausführen von JavaScript-Anweisungen für das chrome.webview.hostObjects.sample Objekt zu verwenden. Wenn Sie DevTools über die Beispiel-App öffnen möchten, klicken Sie mit der rechten Maustaste auf die Seite, und wählen Sie dann Untersuchen aus. Wählen Sie dann die Registerkarte Konsole aus. Weitere Informationen finden Sie unter Übersicht über die Konsole.

    Um DevTools zu öffnen, funktioniert das Drücken von F12 in diesem Kontext möglicherweise nicht und löst möglicherweise eine Ausnahme aus. Wenn ja, wählen Sie in Visual Studio Debuggen beenden aus, und drücken Sie dann F5 , um das Debuggen neu zu starten. Wählen Sie in der Beispiel-App erneutSzenariohostobjekte> aus. Weitere Informationen finden Sie unter Öffnen von DevTools mit einem anderen Ansatz als F12 unter Debuggen von WebView2-Apps mit Visual Studio.

    Am unteren Rand der Demoseite host objects werden die Demoobjektmember in einem <iframe>dupliziert:

    Unten auf der Demoseite für Hostobjekte

  7. Lesen Sie auf der gerenderten Demoseite in der Beispiel-App den Beschriftungstext, der die Schaltflächen "Datum " erläutert.

  8. Klicken Sie auf die Schaltflächen Datum . Unter den Schaltflächen wird eine Datumszeichenfolge angezeigt, z. B.:

    sample.dateProperty: Tue Nov 01 2022 12:45:25 GMT-0700 (Pacific Daylight Time)
    
  9. Erkunden Sie Eigenschaften und Methoden, indem Sie auf die Schaltflächen auf der Demowebseite klicken und Werte eingeben, um zu sehen, wie sich der Beispielcode verhält. Die Schaltflächen veranschaulichen den Zugriff auf Eigenschaften und Methoden des Hostobjekts aus dem webseitigen Code der App.

  10. Um Einen Einblick in die Vorgänge in JavaScript zu erhalten, untersuchen Sie den folgenden Code in ScenarioAddHostObject.html.

    Der folgende Code ist eine Demoeigenschaft Date direkt im body -Element:

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

    Sie können auch den obigen Beschriftungstext auf der gerenderten Demoseite in der Beispiel-App lesen und den Code der Datumsschaltfläche erläutern.

  11. Der folgende Code ist eine Demoeigenschaft Date , die in einem iframe Element umschlossen ist, das in einem script -Element erstellt wird:

    // 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. Der Ausdruck chrome.webview.hostObjects.sync.sample.dateProperty ist der dateProperty des nativen Hostobjekts.

    In der .idl zuvor beschriebenen Datei HostObjectSample.idl wird die date-Eigenschaft als Teil des Hostobjekts definiert.

Verwenden der Beispiel-App

Sie können mit der Verwendung und Änderung der Win32-Beispiel-App experimentieren. Folgen Sie dann demselben Muster in Ihrer eigenen App:

  1. Erstellen Sie ein Hostobjekt im nativen Code Ihrer App.
  2. Übergeben Sie das Hostobjekt an den webseitigen Code Ihrer App.
  3. Verwenden Sie das Hostobjekt aus dem webseitigen Code der App.

Informationen zu anderen APIs im Hostobjektökosystem finden Sie unter WebView2 Win32 C++ ICoreWebView2.

Übersicht über die API-Referenz

Weitere Informationen finden Sie unter Host-/Webobjektfreigabe in Übersicht über WebView2-Features und -APIs.

Siehe auch

GitHub: