Chamar código do lado nativo a partir do código do lado da Web
O WebView2 permite às aplicações colmatar a lacuna entre os lados Web e nativo de uma aplicação ao permitir que um objeto seja transmitido para a Web. Expõe as APIs nativas selecionadas no JavaScript da sua página Web através de um objeto anfitrião nativo intermediário definido no código nativo. As APIs nativas são projetadas em JavaScript com a API WebView2 AddHostObjectToScript
.
Este artigo abrange principalmente Win32/C++, e abrange também alguns aspetos do .NET/C# dentro de frames. Para WinRT, consulte Chamar código WinRT do lado nativo a partir do código do lado da Web.
Porquê utilizar AddHostObjectToScript
?
Ao desenvolver uma aplicação WebView2, pode encontrar um objeto nativo cujos métodos ou propriedades acha úteis. Poderá querer acionar estes métodos de objeto nativo a partir do código do lado da Web, como resultado da interação do utilizador no lado Web da sua aplicação. Além disso, poderá não querer voltar a implementar os métodos dos objetos nativos no código do lado da Web. A
AddHostObjectToScript
API permite a reutilização do código do lado nativo por código do lado da Web.Por exemplo, pode existir uma API web nativa, o que exigiria reescrever uma grande quantidade de código no lado da Web. Ter a capacidade de chamar os métodos do objeto nativo é mais rápido e eficiente do que voltar a codificar os métodos do objeto no lado Web da sua aplicação. Neste caso, o código do lado nativo pode transmitir o objeto para o código JavaScript do lado da Web da sua aplicação, para que o código JavaScript possa reutilizar os métodos da API nativa.
Cenários que podem beneficiar da utilização de objetos de anfitrião no script:
Existe uma API de teclado e pretende chamar a função a
keyboardObject.showKeyboard
partir do lado da Web.Aceder ao sistema de ficheiros, não apenas ao sandbox da página Web, através de JavaScript. O JavaScript é em sandbox, o que o impede de aceder diretamente ao sistema de ficheiros. Ao utilizar
AddHostObjectToScript
para criar um objeto nativo exposto ao JavaScript, pode utilizar o objeto anfitrião para manipular ficheiros no sistema de ficheiros e não apenas no sandbox da página Web.
Este artigo utiliza a aplicação de exemplo Win32 para demonstrar algumas aplicações práticas do AddHostObjectToScript
.
Passo 1: Instalar o Visual Studio, instalar o git, clonar o repositório WebView2Samples e abrir a solução
Transfira e instale o Microsoft Visual Studio 2019 (versão 16.11.10) ou posterior e outros pré-requisitos, conforme descrito na aplicação de exemplo Win32. A aplicação de exemplo Win32 foi criada com o Visual Studio 2019, pelo que, para seguir os passos de exemplo neste artigo, recomendamos que comece com o Visual Studio 2019 em vez do Visual Studio 2022.
Clone o repositório WebView2Samples . O repositório inclui a aplicação WebView2 específica do Win32. Para obter instruções, numa nova janela ou separador, consulte Win32 sample app (Aplicação de exemplo Win32).
Abra o Microsoft Visual Studio. Recomendamos que abra inicialmente o exemplo Win32 com o Visual Studio 2019.
Na cópia local do repositório clonado
WebView2Samples
, abraSampleApps
>WebView2Samples
>WebView2Samples.sln.WebView2Samples.sln
inclui oWebView2APISample
projeto, que é a aplicação de exemplo Win32. Mantenha a solução de aplicação de exemplo aberta, para acompanhar o resto deste artigo.
Passo 2: definir a interface COM do objeto anfitrião com o IDL
Defina a interface COM do objeto anfitrião num .idl
ficheiro, como HostObjectSample.idl, para descrever os métodos e propriedades no objeto anfitrião.
Primeiro, utilize idioma de definição de interface (IDL) para definir a interface COM do objeto anfitrião. Esta definição de objeto anfitrião num idl
ficheiro descreve as propriedades e métodos nativos expostos (ou "moldados"). O ficheiro IDL (.idl
) define uma interface, mas não a implementa.
No Explorador de Soluções do Visual Studio, expanda WebView2APISample>Source Files e, em seguida, faça duplo clique
HostObjectSample.idl
para abri-lo.O código seguinte define a
IHostObjectSample
interface, que herdaIUnknown
como é padrão para COM. Utilize estaIHostObjectSample
definição como modelo para definir os métodos, propriedades, funções de chamada de retorno do objeto, etc.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(); };
Acima, tenha em atenção o
DateProperty
, que utiliza umDATE
tipo. Vamos focar-nos nesta propriedade de demonstração de data neste artigo.
Passo 3: Definir uma coclasse de objeto anfitrião
Em seguida, o exemplo define a HostObjectSample
coclasse a incluir IHostObjectSample
e IDispatch
.
No
HostObjectSample.idl
, examine aHostObjectSample
coclasse (classe de objeto de componente), que inclui asIHostObjectSample
interfaces eIDispatch
:[uuid(637abc45-11f7-4dde-84b4-317d62a638d3)] coclass HostObjectSample { [default] interface IHostObjectSample; interface IDispatch; }; }
A
HostObjectSample
coclasse incluiinterface IDispatch
, que é necessário para que o objeto anfitrião funcione comAddHostObjectToScript
.
Passo 4: Implementar os membros do objeto C++
No código da aplicação de exemplo Win32, HostObjectSampleImpl.cpp utiliza a estrutura criada no ficheiro IDL COM e implementa cada membro do objeto C++. Este ficheiro C++ (.cpp
) implementa a interface definida (e também implementa IDispatch
).
Implemente todas as funções que estão definidas na interface do objeto, conforme descrevemos no ficheiro IDL. Certifique-se de que implementa as funções necessárias para IDispatch
. O compilador emitirá um erro se estas funções não estiverem definidas.
Em seguida, vamos examinar duas propriedades específicas que foram definidas no IDL, para mostrar como o IDL está relacionado com o .cpp
ficheiro.
No Explorador de Soluções do Visual Studio, expanda WebView2APISample>Source Files e, em seguida, faça duplo clique HostObjectSampleImpl.cpp para abri-lo.
Examine as declarações de propriedade em 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();
Examine a implementação das propriedades do objeto no 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; }
Examine
DateProperty
, que analisamos ao longo deste artigo.
Passo 5: Implementar o IDispatch
O objeto anfitrião tem de ser implementado IDispatch
para que o WebView2 possa projetar o objeto anfitrião nativo no código do lado da Web da aplicação.
IDispatch
permite-lhe invocar dinamicamente métodos e propriedades. Normalmente, chamar objetos requer invocações estáticas, mas pode utilizar JavaScript para criar dinamicamente chamadas de objeto. No código da aplicação de exemplo Win32, HostObjectSampleImpl.cpp implementa IDispatch
, o que significa implementar estes métodos:
GetIDsOfNames
GetTypeInfo
GetTypeInfoCount
Invoke
Implemente IDispatch
conforme descrito em Bibliotecas de Tipos e na Linguagem de Descrição do Objeto. Para obter mais informações sobre IDispatch
a herança e os métodos, veja IDispatch interface (oaidl.h).
Se o objeto que pretende adicionar ao JavaScript ainda não implementar IDispatch
, terá de escrever um IDispatch
wrapper de classe para o objeto que pretende expor.
Poderão existir bibliotecas para o fazer automaticamente. Para saber mais sobre os passos necessários para escrever um IDispatch
wrapper de classe para o objeto que pretende expor, veja Automatização.
Em seguida, guarde as alterações efetuadas no projeto.
No Explorador de Soluções, clique com o botão direito do rato em WebView2APISample (que é a aplicação de exemplo Win32) e, em seguida, selecione Compilar. Esta ação cria um ficheiro de biblioteca
.tlb
de tipo COM. Tem de referenciar o ficheiro a.tlb
partir do código fonte C++. Para obter mais informações, veja Type Library in COM, DCOM, and Type Libraries (Biblioteca de Tipos em COM, DCOM e Bibliotecas de Tipos).
Passo 6: Chamar AddHostObjectToScript para passar o objeto anfitrião para o código do lado da Web
Até agora, criámos a nossa interface e implementámos o nosso objeto anfitrião nativo. Agora, estamos prontos para utilizar AddHostObjectToScript
para transmitir o objeto anfitrião nativo para o código JavaScript do lado da Web da nossa aplicação. A aplicação de exemplo Win32 chama AddHostObjectToScript
no ScenarioAddHostObject.cpp, conforme mostrado abaixo.
No Explorador de Soluções do Visual Studio, abra WebView2APISample>Source Files>ScenarioAddHostObject.cpp.
Aceda à implementação da
ScenarioAddHostObject
classe. Esta classe apresenta HTML e processa a navegação: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); });
A
Make
instrução mostra como instanciar oHostObjectSample
objeto COM que foi definido no ficheiro IDL. Este é o objeto que utilizaremos mais tarde quando chamarmosAddHostObjectToScript
. AMake
instrução dá-nos um ponteiro para a interface implementada no HostObjectSampleImpl.cpp.Em seguida, adicionamos um processador de eventos para escutar o
NavigationStarting
evento: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());
No processador
NavigationStarting
de eventos, aquery_to
linha (abaixo) converte o objeto COM recentemente criado numIDispatch
tipo e, em seguida, converte o objeto numVARIANT
.VARIANT
os tipos permitem-lhe utilizar estruturas de dados, como números inteiros e matrizes, bem como tipos mais complexos, comoIDispatch
.Para obter uma lista completa dos tipos de dados suportados, veja Estrutura VARIANT (oaidl.h). Nem todos os tipos no
VARIANT
sindicato são suportados peloAddHostObjectToScript
. Para obter detalhes, consulte o método ICoreWebView2::AddHostObjectToScript.if (AreFileUrisEqual(sampleUri, uriTarget)) { VARIANT remoteObjectAsVariant = {}; m_hostObject.query_to<IDispatch>(&remoteObjectAsVariant.pdispVal); remoteObjectAsVariant.vt = VT_DISPATCH;
Agora que temos uma variante do objeto compatível com o código C++, o código nativo da aplicação de exemplo está pronto para transmitir o objeto anfitrião ao código do lado da Web da aplicação.
Na linha de fundo acima, o
NavigationStarting
processador de eventos define o tipo de variante do objeto remoto comoIDispatch
.// 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(); }
Acima, no processador de
NavigationStarting
eventos, oVARIANT
é transmitido paraAddHostObjectToScript
, com o nomesample
.
Passo 7: Aceder aos membros do objeto anfitrião a partir da página Web JavaScript
Nos passos acima, o código nativo da aplicação de exemplo criou um objeto anfitrião que implementa IDispatch
. Este código nativo também chama a API ICoreWebView2::AddHostObjectToScript
WebView2 ou ICoreWebView2Frame::AddHostObjectToScriptWithOrigins
e transmite o objeto anfitrião para o código do lado da Web da aplicação.
Agora, o código do lado da Web da aplicação pode aceder às APIs nativas que são expostas pelo objeto anfitrião. As instruções JavaScript no elemento da página .html
Web script
ou num ficheiro JavaScript referenciado .js
podem aceder às APIs do lado nativo exportadas.
O código do lado da Web da aplicação de exemplo Win32 consegue agora aceder às propriedades e métodos do objeto anfitrião nativo para aceder às APIs nativas. Vamos utilizar os controlos de página Web da aplicação de exemplo, na página WebObjetos de Anfitrião do Cenário> da aplicação, para demonstrar isto.
No Microsoft Visual Studio, selecioneGuardar Todos osFicheiros> (Ctrl+Shift+S) para guardar o projeto.
No Explorador de Soluções, abra WebView2APISample>ScenarioAddHostObject.html. Vamos comparar este ficheiro com a página Web correspondente na aplicação de exemplo Win32 em execução.
No Explorador de Soluções, clique com o botão direito do rato em WebView2APISample (que é a aplicação de exemplo Win32) e, em seguida, selecione Compilar.
Prima F5 para executar o projeto no modo de Depuração.
Na aplicação de exemplo Win32 (que tem a barra de título de WebView2APISample), clique no menu Cenário e, em seguida, selecione o menuItem Objetos de Anfitrião . É apresentada a página Web De Exemplo AddHostObjectToScript , definida por
ScenarioAddHostObject.html
:A página Web sugere a utilização da ferramenta consola de DevTools para executar instruções JavaScript no
chrome.webview.hostObjects.sample
objeto. Se quiser abrir o DevTools a partir da aplicação de exemplo, clique com o botão direito do rato na página e, em seguida, selecione Inspecionar. Em seguida, selecione o separador Consola . Para obter mais informações, veja Descrição geral da consola.Para abrir DevTools, premir F12 pode não funcionar neste contexto e pode acionar uma exceção. Se for o caso, no Visual Studio, selecione Parar Depuração e, em seguida, prima F5 para reiniciar a depuração. Na aplicação de exemplo, selecioneObjetos de Anfitrião do Cenário> novamente. Para obter mais informações, veja Open DevTools using an approach other than F12 in Debug WebView2 apps with Visual Studio (Abrir DevTools com uma abordagem diferente de F12 em Depurar aplicações WebView2 com o Visual Studio).
A parte inferior da página de demonstração Objetos anfitriões duplica os membros do objeto de demonstração num
<iframe>
:Na página de demonstração composta na aplicação de exemplo, leia o texto da etiqueta que explica os botões Data .
Clique nos botões Data . É apresentada uma cadeia de data abaixo dos botões, tais como:
sample.dateProperty: Tue Nov 01 2022 12:45:25 GMT-0700 (Pacific Daylight Time)
Explore as propriedades e os métodos ao clicar nos botões na página Web de demonstração e introduzir valores para ver o comportamento do código de exemplo. Os botões demonstram o acesso às propriedades e métodos do objeto anfitrião a partir do código do lado da Web da aplicação.
Para obter informações sobre o que está a acontecer no JavaScript, examine o seguinte código no ScenarioAddHostObject.html.
O código seguinte é uma propriedade de demonstração
Date
, diretamente dentro dobody
elemento :<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>
Também pode ler o texto da etiqueta acima na página de demonstração composta na aplicação de exemplo, explicando o código do botão Data .
O código seguinte é uma propriedade de demonstração
Date
que está encapsulada numiframe
elemento criado numscript
elemento:// 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; });
A expressão
chrome.webview.hostObjects.sync.sample.dateProperty
é dodateProperty
objeto anfitrião nativo..idl
No ficheiro HostObjectSample.idl, descrito anteriormente, a propriedade date é definida como parte do objeto anfitrião.
Utilizar a aplicação de exemplo
Pode experimentar utilizar e modificar a aplicação de exemplo Win32. Em seguida, siga o mesmo padrão na sua própria aplicação:
- Crie um objeto anfitrião no código nativo da sua aplicação.
- Transmita o objeto anfitrião para o código do lado da Web da sua aplicação.
- Utilize o objeto anfitrião do código do lado da Web da aplicação.
Para saber que outras APIs existem no ecossistema de objetos anfitriões, consulte WebView2 Win32 C++ ICoreWebView2.
Descrição geral da Referência da API
Veja Partilha de objetos Anfitrião/Web na Descrição geral das funcionalidades e APIs do WebView2.
Confira também
- Interoperabilidade Web/nativa na Descrição geral das funcionalidades e APIs do WebView2.
- Utilizar frames em aplicações WebView2
- Chamar código WinRT do lado nativo a partir de código do lado da Web
GitHub: