Using frames in WebView2 apps

Frames allow you to embed other webpages into your own webpage. A frame is a sub-page or area within a webpage, like a webpage within a webpage.

An iframe is one type of frame. Other types of frames are frameset, portal, embed, fencedFrame, and object. The main WebView2 type for frames is CoreWebView2Frame, which is currently enabled for top-level iframes. Support for other types of frames is planned.

WebView2 supports APIs to interact with iframes. You can:

  • Find out when iframes are created.
  • Find out when iframes are navigating to a different URL. This works the same as state machine Navigation events for WebView2 apps.
  • Communicate between the host app and iframes, sending messages in both directions.
  • Allow the app to ignore the X-Frame-Options HTTP response header.

See also:

Subscribe to the FrameCreated event to obtain a frame

To interact with frames in your host app, the first step is to subscribe to the FrameCreated event so that your host app obtains a frame object. The FrameCreated event is raised whenever a new frame is created. After your host app has obtained a frame object, use the frame object to monitor changes and interact with this specific frame.

Your host app must monitor the lifetime of a frame by subscribing to the CoreWebView2Frame.Destroyed event, because when the frame is destroyed, your host app can no longer reference that frame. Frames get created and destroyed during each new webpage navigation. Use the CoreWebView2Frame.IsDestroyed method to check whether the frame still exists.

See also:

  • iframes in Overview of WebView2 APIs.

After a frame is created, the frame navigates to the frame's source URL. iframes use navigation and navigation events, such as FrameNavigationStarting and NavigationCompleted. When the frame navigates to the source URL, the following navigation events are raised:

  • NavigationStarting
  • ContentLoading
  • HistoryChanged
  • DOMContentLoaded
  • NavigationCompleted

Frequency of navigating within a frame

Navigation can potentially happen within a frame. As a simple use case, an iframe element's source attribute is a URL, such as wikipedia.com, and the URL is loaded in an iframe. Usually the navigation happens immediately after the frame is created. The ContentLoading, DOMContentLoaded, and NavigationCompleted events are then raised.

The frame itself is navigating. A webpage navigates to a URL. Similarly, a frame potentially navigates.

After the frame is created, the frame navigates as driven by your host app. To monitor what's going on in the main page, events such as NavigationStarting, NavigationCompleted, and HistoryChanged enable the host app to navigate back and forth among frames or webpages. Frames are navigated to a new URL less often than webpages, but the same navigation style is supported. The user usually cannot navigate inside a frame, although JavaScript enables that; a frame is usually static regarding navigation.

See also:

Navigation events:

Regarding the duplicated equivalent NavigationStarting and NavigationCompleted events, the events on CoreWebView2Frame are recommended rather than the equivalent, superseded events on CoreWebView2, because the CoreWebView2Frame type supports more scenarios to allow interactions with frames.

See also:

Using host objects in an iframe

To communicate between the native side of the host app and JavaScript that's in an iframe, use host objects. A host object is an object that you create in the host app and then use from JavaScript code in the webpage side of the app.

Using native-side APIs from script within a frame, via a host object, is similar to web/native interop page structure as explained in Call native-side code from web-side code:

To use host objects within an iframe:

  1. Define the host object and implement IDispatch.
  2. Add the host object on the native side by using AddHostObjectToScriptWithOrigins (Win32) or AddHostObjectToScript (.NET).
  3. From JavaScript in your web-side code, access this host object by using chrome.webview.hostObjects.<name> API.

To access and control native-side objects from web-side JavaScript in a frame, use AddHostObjectToScriptWithOrigins (Win32) or CoreWebView2Frame.AddHostObjectToScript (.NET), which has an origins parameter. The origins parameter specifies which URLs iframes will be allowed to access, for security reasons. This parameter identifies the URLs for which iframes will have access to the host object.

If the frame is navigated to a URL that is not in the origins list, the frame won't be able to operate the host object; the frame won't be able to read or write any properties. See the Method name table in the AddHostObjectToScript method for your framework. See the following two rows:

  • applyHostFunction, getHostProperty, and setHostProperty.
  • getLocalProperty and setLocalProperty.

The above method works like the following method:

Example code

See Step 6: Call AddHostObjectToScript to pass the host object to web-side code in Call native-side code from web-side code.

See also:

Sending and receiving messages

Messages can be sent between the native app and JavaScript code that's in an iframe:

  • You can send messages from JavaScript in an iframe in an HTML page to the host app.
  • You can send messages from the host app to JavaScript in an iframe in an HTML page.

Sending web messages from an iframe to the host app

To send web messages from an iframe to the host app, use the window.chrome.webview.postMessage method:

window.chrome.webview.postMessage(`SetTitleText ${titleText.value}`);

To receive these messages in the host app, the host app must subscribe to the WebMessageReceived event.

Sending messages from the host app to the iframe

The host app sends messages to the iframe by calling the PostWebMessageAsJson or PostWebMessageAsString method.

The iframe receives the message by subscribing to the window.chrome.webview.addEventListener('message') event, as follows:

window.chrome.webview.addEventListener('message', arg => {
    // implement event listener here
});

See also:

Run JavaScript code in iframes by using ExecuteScript

A WebView2 app can run any JavaScript in a frame, by using ExecuteScript.

In order for script to be run in an iframe, an execution context must be created. An execution context is created after the ContentLoading event, that's why if ExecuteScript is called before the ContentLoading event is raised, the script will not be run and the string null will be returned.

For information about the ContentLoading event, see Navigation events for WebView2 apps, which is valid for frames as well as webpages.

See also:

Modifying network events by using the WebResourceRequested event in iframes

This feature is experimental

For iframes, you can listen to network events and modify them, by using the WebResourceRequested event.

See also:

See the latest prerelease APIs. The following links contain 1.0.1466-prerelease. In the Version dropdown list in the upper left of the API Reference docs, select the latest prerelease.

Ignoring X-Frame-Options to render a webpage inside of a frame

The X-Frame-Options HTTP response header is used by webpages to prevent an application from rendering that webpage inside of a frame. The AdditionalAllowedFrameAncestors property allows your application to bypass the X-Frame-Options header, to render the webpage inside a frame.

See also:

Example of using iframes in a host app

This sample code shows how to use frame APIs, including:

  • FrameCreated
    • CoreWebView2FrameCreatedEventArgs
  • DOMContentLoaded
    • CoreWebView2DOMContentLoadedEventArgs
  • ExecuteScript

This sample code is condensed from MainWindow.xaml.cs in the WebView2WpfBrowser sample.

        void DOMContentLoadedCmdExecuted(object target, ExecutedRoutedEventArgs e)
        {
            // Subscribe to the FrameCreated event to obtain the frame object when 
            // it's created.
            webView.CoreWebView2.FrameCreated += WebView_FrameCreatedDOMContentLoaded;
            webView.NavigateToString(@"<!DOCTYPE html>" +
                                      "<h1>DOMContentLoaded sample page</h1>" +
                                      "<h2>The content to the iframe and below will be added after DOM content is loaded </h2>" +
                                      "<iframe style='height: 200px; width: 100%;'/>");
        }

        void WebView_FrameCreatedDOMContentLoaded(object sender, CoreWebView2FrameCreatedEventArgs args)
        {
            // In order for ExecuteScriptAsync to successfully run inside the iframe, 
            // subscribe to the ContentLoading or DOMContentLoaded event.  Once these 
            // events are raised, you can call ExecuteScriptAsync.
            args.Frame.DOMContentLoaded += (frameSender, DOMContentLoadedArgs) =>
            {
                args.Frame.ExecuteScriptAsync(
                    "let content = document.createElement(\"h2\");" +
                    "content.style.color = 'blue';" +
                    "content.textContent = \"This text was added to the iframe by the host app\";" +
                    "document.body.appendChild(content);");
            };
        }

API Reference overview

The following features, listed in Overview of WebView2 APIs, include frame-related APIs:

See also

External pages: