示例#1
0
void BrowserView::create(RECT webViewRect, BrowserWindow* parentWindow)
{
    assert(!m_webView);

    bool isShiftKeyDown = ::GetKeyState(VK_SHIFT) & HIGH_BIT_MASK_SHORT;

    WKContextRef context;
    if (isShiftKeyDown)
        context = WKContextGetSharedThreadContext();
    else
        context = WKContextGetSharedProcessContext();

    WKPageNamespaceRef pageNamespace = WKPageNamespaceCreate(context);

    m_webView = WKViewCreate(webViewRect, pageNamespace, parentWindow->window());

    WKPageUIClient uiClient = {
        0,              /* version */
        parentWindow,   /* clientInfo */
        createNewPage,
        showPage,
        closePage,
        runJavaScriptAlert,
        runJavaScriptConfirm,
        runJavaScriptPrompt,
        setStatusText,
        contentsSizeChanged
    };

    WKPageSetPageUIClient(WKViewGetPage(m_webView), &uiClient);
}
示例#2
0
文件: Shell.cpp 项目: nickooms/webkit
gpointer Shell::launchWPE(gpointer data)
{
    Shell::m_instance = static_cast<Shell*>(data);

    GMainContext* threadContext = g_main_context_new();
    GMainLoop* threadLoop = g_main_loop_new(threadContext, FALSE);

    g_main_context_push_thread_default(threadContext);

    auto pageGroupIdentifier = adoptWK(WKStringCreateWithUTF8CString("WPEPageGroup"));
    auto pageGroup = adoptWK(WKPageGroupCreateWithIdentifier(pageGroupIdentifier.get()));

    auto context = adoptWK(WKContextCreate());

    Shell::instance().m_view = adoptWK(WKViewCreate(context.get(), pageGroup.get()));
    auto view = Shell::instance().m_view.get();
    WKViewResize(view, Shell::instance().m_environment.outputSize());
    WKViewMakeWPEInputTarget(view);

    const char* url = g_getenv("WPE_SHELL_URL");
    if (!url)
        url = "http://www.webkit.org/blog-files/3d-transforms/poster-circle.html";
    auto shellURL = adoptWK(WKURLCreateWithUTF8CString(url));
    WKPageLoadURL(WKViewGetPage(view), shellURL.get());

    g_main_loop_run(threadLoop);
    return nullptr;
}
PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
{
    m_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    m_view = WKViewCreate(contextRef, pageGroupRef);
    gtk_container_add(GTK_CONTAINER(m_window), GTK_WIDGET(m_view));
    gtk_widget_show(GTK_WIDGET(m_view));
    gtk_widget_show(m_window);
}
示例#4
0
PlatformWebView::PlatformWebView(WKPageNamespaceRef namespaceRef)
{
    registerWindowClass();

    RECT viewRect = {0, 0, 800, 600};
    m_window = CreateWindowExW(0, hostWindowClassName, L"WebKitTestRunner", WS_OVERLAPPEDWINDOW, 0 /*XOFFSET*/, 0 /*YOFFSET*/, viewRect.right, viewRect.bottom, 0, 0, GetModuleHandle(0), 0);
    m_view = WKViewCreate(viewRect, namespaceRef, m_window);
}
示例#5
0
void BrowserView::create(RECT webViewRect, BrowserWindow* parentWindow)
{
    assert(!m_webView);

    static WKContextRef context = WKContextCreate();

    m_webView = WKViewCreate(webViewRect, context, 0, parentWindow->window());

    WKPageUIClient uiClient = {
        kWKPageUIClientCurrentVersion,
        parentWindow,   /* clientInfo */
        0,          /* createNewPage_deprecatedForUseWithV0 */
        showPage,
        closePage,
        0,          /* takeFocus */
        0,          /* focus */
        0,          /* unfocus */
        runJavaScriptAlert,
        runJavaScriptConfirm,
        runJavaScriptPrompt,
        setStatusText,
        0,          /* mouseDidMoveOverElement_deprecatedForUseWithV0 */
        0,          /* missingPluginButtonClicked */
        0,          /* didNotHandleKeyEvent */
        0,          /* didNotHandleWheelEvent */
        0,          /* toolbarsAreVisible */
        0,          /* setToolbarsAreVisible */
        0,          /* menuBarIsVisible */
        0,          /* setMenuBarIsVisible */
        0,          /* statusBarIsVisible */
        0,          /* setStatusBarIsVisible */
        0,          /* isResizable */
        0,          /* setIsResizable */
        0,          /* getWindowFrame */
        0,          /* setWindowFrame */
        0,          /* runBeforeUnloadConfirmPanel */
        0,          /* didDraw */
        0,          /* pageDidScroll */
        0,          /* exceededDatabaseQuota */
        0,          /* runOpenPanel */
        0,          /* decidePolicyForGeolocationPermissionRequest */
        0,          /* headerHeight */
        0,          /* footerHeight */
        0,          /* drawHeader */
        0,          /* drawFooter */
        0,          /* printFrame */
        0,          /* runModal */
        0,          /* didCompleteRubberBandForMainFrame */
        0,          /* saveDataToFileInDownloadsFolder */
        0,          /* shouldInterruptJavaScript */
        createNewPage,
        mouseDidMoveOverElement,
    };

    WKPageSetPageUIClient(WKViewGetPage(m_webView), &uiClient);

    WKViewSetIsInWindow(m_webView, true);
}
PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
    : m_parentWindowMessageObserver(0)
{
    registerWindowClass();

    RECT viewRect = {0, 0, 800, 600};
    m_window = CreateWindowExW(0, hostWindowClassName, L"TestWebKitAPI", WS_OVERLAPPEDWINDOW, viewRect.left, viewRect.top, viewRect.right, viewRect.bottom, 0, 0, 0, this);
    m_view = WKViewCreate(viewRect, contextRef, pageGroupRef, m_window);
}
示例#7
0
void BrowserView::create(RECT webViewRect, HWND parentWindow)
{
    assert(!m_webView);

    WKContextRef context = WKContextCreateWithProcessModel(kWKProcessModelSecondaryProcess);
    WKPageNamespaceRef pageNamespace = WKPageNamespaceCreate(context);

    m_webView = WKViewCreate(webViewRect, pageNamespace, parentWindow);
}
PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef, WKPageRef /* relatedPage */, WKDictionaryRef /*options*/)
    : m_windowIsKey(true)
{
    registerWindowClass();

    RECT viewRect = {0, 0, 800, 600};
    m_window = CreateWindowExW(0, hostWindowClassName, L"WebKitTestRunner", WS_OVERLAPPEDWINDOW, 0 /*XOFFSET*/, 0 /*YOFFSET*/, viewRect.right, viewRect.bottom, 0, 0, GetModuleHandle(0), 0);
    m_view = WKViewCreate(viewRect, contextRef, pageGroupRef, m_window);
    WKViewSetIsInWindow(m_view, true);
}
示例#9
0
TEST(WebKitNix, WebViewTranslatedScaled)
{
    // This test opens a webpage that contains a white background, no viewport
    // metatag and a red rectangle (20x20)px at (0,0) position. The viewport is
    // then translated to (10,10) position. After that it's applied a scale=2.0
    // At this point we will have a red rectangle of (40x40)px at (10,10).

    const WKSize size = WKSizeMake(100, 100);
    ToolsNix::GLOffscreenBuffer offscreenBuffer(size.width, size.height);
    ASSERT_TRUE(offscreenBuffer.makeCurrent());

    WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
    WKRetainPtr<WKViewRef> view(AdoptWK, WKViewCreate(context.get(), 0));

    Util::ForceRepaintClient forceRepaintClient(view.get());
    forceRepaintClient.setClearColor(0, 0, 1, 1);

    const int delta = 10;
    WKViewSetUserViewportTranslation(view.get(), delta, delta);

    WKViewInitialize(view.get());
    WKPageSetUseFixedLayout(WKViewGetPage(view.get()), true);
    WKViewSetSize(view.get(), size);

    glViewport(0, 0, size.width, size.height);
    forceRepaintClient.clear();

    Util::PageLoader loader(view.get());

    loader.waitForLoadURLAndRepaint("../nix/red-square");

    for (double scale = 1.0; scale < 3.0; scale++) {
        WKViewSetContentScaleFactor(view.get(), scale);
        loader.forceRepaint();

        ToolsNix::RGBAPixel outsideTheContent = offscreenBuffer.readPixelAtPoint(delta - 1, delta - 1);
        EXPECT_EQ(ToolsNix::RGBAPixel::blue(), outsideTheContent);

        ToolsNix::RGBAPixel squareTopLeft = offscreenBuffer.readPixelAtPoint(delta, delta);
        EXPECT_EQ(ToolsNix::RGBAPixel::red(), squareTopLeft);

        const int scaledSize = scale * 20;
        ToolsNix::RGBAPixel squareBottomRight = offscreenBuffer.readPixelAtPoint(delta + scaledSize - 1, delta + scaledSize - 1);
        EXPECT_EQ(ToolsNix::RGBAPixel::red(), squareBottomRight);

        ToolsNix::RGBAPixel outsideSquare = offscreenBuffer.readPixelAtPoint(delta + scaledSize, delta + scaledSize);
        EXPECT_EQ(ToolsNix::RGBAPixel::white(), outsideSquare);
    }
}
示例#10
0
PlatformWebView::PlatformWebView(WKContextRef context, WKPageGroupRef pageGroup, WKPageRef /* relatedPage */, WKDictionaryRef options)
    : m_view(WKViewCreate(context, pageGroup))
    , m_window(gtk_window_new(GTK_WINDOW_POPUP))
    , m_windowIsKey(true)
    , m_options(options)
{
    gtk_container_add(GTK_CONTAINER(m_window), GTK_WIDGET(m_view));

    GtkAllocation size = { 0, 0, 800, 600 };
    gtk_widget_size_allocate(m_window, &size);
    gtk_window_resize(GTK_WINDOW(m_window), 800, 600);
    gtk_widget_show_all(m_window);

    while (gtk_events_pending())
        gtk_main_iteration();
}
示例#11
0
void BrowserView::create(RECT webViewRect, BrowserWindow* parentWindow)
{
    assert(!m_webView);

    bool isShiftKeyDown = ::GetKeyState(VK_SHIFT) & HIGH_BIT_MASK_SHORT;

    WKContextRef context;
    if (isShiftKeyDown)
        context = WKContextGetSharedThreadContext();
    else
        context = WKContextGetSharedProcessContext();

    m_webView = WKViewCreate(webViewRect, context, 0, parentWindow->window());

    WKPageUIClient uiClient = {
        0,              /* version */
        parentWindow,   /* clientInfo */
        createNewPage,
        showPage,
        closePage,
        runJavaScriptAlert,
        runJavaScriptConfirm,
        runJavaScriptPrompt,
        setStatusText,
        mouseDidMoveOverElement,
        0,          /* didNotHandleKeyEvent */
        0,          /* toolbarsAreVisible */
        0,          /* setToolbarsAreVisible */
        0,          /* menuBarIsVisible */
        0,          /* setMenuBarIsVisible */
        0,          /* statusBarIsVisible */
        0,          /* setStatusBarIsVisible */
        0,          /* isResizable */
        0,          /* setIsResizable */
        0,          /* getWindowFrame */
        0,          /* setWindowFrame */
        0,          /* runBeforeUnloadConfirmPanel */
        0,          /* didDraw */
        0,          /* pageDidScroll */
        0,          /* exceededDatabaseQuota */
        0           /* runOpenPanel */
    };

    WKPageSetPageUIClient(WKViewGetPage(m_webView), &uiClient);
}
示例#12
0
文件: Tab.cpp 项目: setanta/drowser
void Tab::init()
{
    m_view = WKViewCreate(m_context, m_browser->contentPageGroup());
    WKViewInitialize(m_view);
    WKViewSetIsFocused(m_view, true);
    WKViewSetIsVisible(m_view, true);
    m_page = WKViewGetPage(m_view);
    WKStringRef appName = WKStringCreateWithUTF8CString("Drowser");
    WKPageSetApplicationNameForUserAgent(m_page, appName);
    WKRelease(appName);

    WKViewClient client;
    std::memset(&client, 0, sizeof(WKViewClient));
    client.version = kWKViewClientCurrentVersion;
    client.clientInfo = this;
    client.viewNeedsDisplay = &Tab::onViewNeedsDisplayCallback;

    WKViewSetViewClient(m_view, &client);

    WKPageLoaderClient loaderClient;
    memset(&loaderClient, 0, sizeof(WKPageLoaderClient));
    loaderClient.version = kWKPageLoaderClientCurrentVersion;
    loaderClient.clientInfo = this;
    loaderClient.didStartProgress = &Tab::onStartProgressCallback;
    loaderClient.didChangeProgress = &Tab::onChangeProgressCallback;
    loaderClient.didFinishProgress = &Tab::onFinishProgressCallback;
    loaderClient.didCommitLoadForFrame = &Tab::onCommitLoadForFrame;
    loaderClient.didReceiveTitleForFrame = &Tab::onReceiveTitleForFrame;
    loaderClient.didFailProvisionalLoadWithErrorForFrame = &Tab::onFailProvisionalLoadWithErrorForFrameCallback;

    WKPageSetPageLoaderClient(m_page, &loaderClient);

    WKPageUIClient uiClient;
    memset(&uiClient, 0, sizeof(WKPageUIClient));
    uiClient.version = kWKPageUIClientCurrentVersion;
    uiClient.clientInfo = this;
    uiClient.createNewPage = &Tab::createNewPageCallback;
    uiClient.mouseDidMoveOverElement = &Tab::onMouseDidMoveOverElement;

    WKPageSetPageUIClient(m_page, &uiClient);
}
TEST(WebKit2, WKViewUserViewportToContents)
{
    // This test creates a WKView and uses the WKViewUserViewportToContents
    // function to convert viewport coordinates to contents (page) coordinates.
    // It scrolls and scales around the contents and check if the coordinates
    // conversion math is right.

    WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
    WKRetainPtr<WKViewRef> webView(AdoptWK, WKViewCreate(context.get(), 0));

    WKViewInitialize(webView.get());
    WKPageSetUseFixedLayout(WKViewGetPage(webView.get()), false);

    WKPoint out;

    // At scale 1.0 the viewport and contents coordinates should match.

    WKViewSetContentScaleFactor(webView.get(), 1.0);
    WKViewSetContentPosition(webView.get(), WKPointMake(0, 0));

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
    EXPECT_EQ(out.x, 0);
    EXPECT_EQ(out.y, 0);

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
    EXPECT_EQ(out.x, 10);
    EXPECT_EQ(out.y, 10);

    WKViewSetContentPosition(webView.get(), WKPointMake(20, 20));

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
    EXPECT_EQ(out.x, 20);
    EXPECT_EQ(out.y, 20);

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
    EXPECT_EQ(out.x, 30);
    EXPECT_EQ(out.y, 30);

    // At scale 2.0 the viewport distance values will be half
    // the ones seem in the contents.

    WKViewSetContentScaleFactor(webView.get(), 2.0);
    WKViewSetContentPosition(webView.get(), WKPointMake(0, 0));

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
    EXPECT_EQ(out.x, 0);
    EXPECT_EQ(out.y, 0);

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
    EXPECT_EQ(out.x, 5);
    EXPECT_EQ(out.y, 5);

    WKViewSetContentPosition(webView.get(), WKPointMake(20, 20));

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
    EXPECT_EQ(out.x, 20);
    EXPECT_EQ(out.y, 20);

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
    EXPECT_EQ(out.x, 25);
    EXPECT_EQ(out.y, 25);

    // At scale 0.5 the viewport distance values will be twice
    // the ones seem in the contents.

    WKViewSetContentScaleFactor(webView.get(), 0.5);
    WKViewSetContentPosition(webView.get(), WKPointMake(0, 0));

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
    EXPECT_EQ(out.x, 0);
    EXPECT_EQ(out.y, 0);

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
    EXPECT_EQ(out.x, 20);
    EXPECT_EQ(out.y, 20);

    WKViewSetContentPosition(webView.get(), WKPointMake(20, 20));

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
    EXPECT_EQ(out.x, 20);
    EXPECT_EQ(out.y, 20);

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
    EXPECT_EQ(out.x, 40);
    EXPECT_EQ(out.y, 40);

    // Let's add translation to the viewport.

    const int delta = 10;
    WKViewSetUserViewportTranslation(webView.get(), delta, delta);

    WKViewSetContentPosition(webView.get(), WKPointMake(0, 0));

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
    EXPECT_EQ(out.x, 0 - delta / 0.5);
    EXPECT_EQ(out.y, 0 - delta / 0.5);

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
    EXPECT_EQ(out.x, 20 - delta / 0.5);
    EXPECT_EQ(out.y, 20 - delta / 0.5);

    WKViewSetContentPosition(webView.get(), WKPointMake(20, 20));

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
    EXPECT_EQ(out.x, 20 - delta / 0.5);
    EXPECT_EQ(out.y, 20 - delta / 0.5);

    out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
    EXPECT_EQ(out.x, 40 - delta / 0.5);
    EXPECT_EQ(out.y, 40 - delta / 0.5);
}
示例#14
0
TEST(WebKitNix, WebViewUpdateTextInputState)
{
    memset(&stateReceived, 0, sizeof(stateReceived));
    WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
    WKRetainPtr<WKViewRef> view(AdoptWK, WKViewCreate(context.get(), 0));

    NIXViewClient nixViewClient;
    memset(&nixViewClient, 0, sizeof(NIXViewClient));
    nixViewClient.version = kNIXViewClientCurrentVersion;
    nixViewClient.updateTextInputState = updateTextInputState;
    NIXViewSetNixViewClient(view.get(), &nixViewClient);

    WKViewInitialize(view.get());

    WKPageLoaderClient pageLoaderClient;
    memset(&pageLoaderClient, 0, sizeof(WKPageLoaderClient));
    pageLoaderClient.version = kWKPageLoaderClientCurrentVersion;
    pageLoaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
    WKPageSetPageLoaderClient(WKViewGetPage(view.get()), &pageLoaderClient);

    const WKSize size = WKSizeMake(100, 100);
    WKViewSetSize(view.get(), size);

    NIXMouseEvent nixEvent;
    memset(&nixEvent, 0, sizeof(NIXMouseEvent));
    nixEvent.type = kNIXInputEventTypeMouseDown;
    nixEvent.button = kWKEventMouseButtonLeftButton;
    nixEvent.x = 55;
    nixEvent.y = 55;
    nixEvent.globalX = 55;
    nixEvent.globalY = 55;
    nixEvent.clickCount = 1;
    nixEvent.modifiers = static_cast<NIXInputEventModifiers>(0);;
    nixEvent.timestamp = 0;

    // Simple test on content editable.
    WKRetainPtr<WKURLRef> editableContentUrl = adoptWK(Util::createURLForResource("../nix/single-tap-on-editable-content", "html"));
    WKPageLoadURL(WKViewGetPage(view.get()), editableContentUrl.get());
    Util::run(&didFinishLoad);
    NIXViewSendMouseEvent(view.get(), &nixEvent);
    nixEvent.type = kNIXInputEventTypeMouseUp;
    NIXViewSendMouseEvent(view.get(), &nixEvent);

    Util::run(&didUpdateTextInputState);

    ASSERT_TRUE(didFinishLoad);
    ASSERT_TRUE(didUpdateTextInputState);
    ASSERT_TRUE(stateReceived.isContentEditable);

    ASSERT_TRUE(WKStringIsEqualToUTF8CString(stateReceived.surroundingText, "foobar"));
    WKRelease(stateReceived.surroundingText);
    ASSERT_TRUE(WKStringIsEmpty(stateReceived.submitLabel));
    WKRelease(stateReceived.submitLabel);
    ASSERT_FALSE(stateReceived.inputMethodHints & NIXImhSensitiveData);
    ASSERT_TRUE(!WKRectIsEqual(stateReceived.cursorRect, invalidRectState));
    ASSERT_TRUE(!WKRectIsEqual(stateReceived.editorRect, invalidRectState));
    ASSERT_TRUE(!WKRectIsEqual(stateReceived.cursorRect, stateReceived.editorRect));

    // Test on a form field.
    didFinishLoad = false;
    memset(&stateReceived, 0, sizeof(stateReceived));

    editableContentUrl = adoptWK(Util::createURLForResource("../nix/single-tap-on-form-field", "html"));
    WKPageLoadURL(WKViewGetPage(view.get()), editableContentUrl.get());
    Util::run(&didFinishLoad);
    nixEvent.type = kNIXInputEventTypeMouseDown;
    NIXViewSendMouseEvent(view.get(), &nixEvent);
    nixEvent.type = kNIXInputEventTypeMouseUp;
    NIXViewSendMouseEvent(view.get(), &nixEvent);

    didUpdateTextInputState = false;
    Util::run(&didUpdateTextInputState);

    WKRelease(stateReceived.surroundingText);
    ASSERT_TRUE(didFinishLoad);
    ASSERT_TRUE(didUpdateTextInputState);
    ASSERT_TRUE(WKStringIsEqualToUTF8CString(stateReceived.submitLabel, "submitLabelValue"));
    WKRelease(stateReceived.submitLabel);
    ASSERT_TRUE(stateReceived.inputMethodHints & NIXImhSensitiveData);
}
示例#15
0
TEST(WebKitNix, SuspendResumeAPI)
{
    // This test uses a page that changes its title - showing current time.
    // As the suspend method is called the page's changes are paused. The
    // animation continues as we call the resume method. During this process
    // there are checkpoints to ensure that changes are pausing/resuming.

    const WKSize size = WKSizeMake(150, 100);
    ToolsNix::GLOffscreenBuffer offscreenBuffer(size.width, size.height);
    ASSERT_TRUE(offscreenBuffer.makeCurrent());

    WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
    WKRetainPtr<WKViewRef> view(AdoptWK, WKViewCreate(context.get(), 0));

    Util::ForceRepaintClient forceRepaintClient(view.get());
    forceRepaintClient.setClearColor(0, 0, 1, 1);

    WKViewInitialize(view.get());
    WKViewSetSize(view.get(), size);

    glViewport(0, 0, size.width, size.height);
    forceRepaintClient.clear();

    Util::PageLoader loader(view.get());
    loader.waitForLoadURLAndRepaint("../nix/SuspendResume");

    size_t bufferSize = WKStringGetMaximumUTF8CStringSize(WKPageCopyTitle(WKViewGetPage(view.get())));
    char firstSampleBeforeSuspend[bufferSize];
    char secondSampleBeforeSuspend[bufferSize];
    char firstSampleAfterSuspend[bufferSize];
    char secondSampleAfterSuspend[bufferSize];
    char firstSampleAfterResume[bufferSize];

    WKStringGetUTF8CString(WKPageCopyTitle(WKViewGetPage(view.get())), firstSampleBeforeSuspend, bufferSize);

    // After collecting the first sample a repaint is needed to get viewport updated accordingly.
    // This proccess is repeated for each collected sample.
    Util::sleep(0.1);
    loader.forceRepaint();
    WKStringGetUTF8CString(WKPageCopyTitle(WKViewGetPage(view.get())), secondSampleBeforeSuspend, bufferSize);
    // The timer is ticking - two different samples.
    EXPECT_STRNE(firstSampleBeforeSuspend, secondSampleBeforeSuspend);

    // Force an update before suspending otherwise we can get same sample value after suspending
    // and the test becomes flacky.
    Util::sleep(0.1);
    loader.forceRepaint();
    WKViewSuspendActiveDOMObjectsAndAnimations(view.get());
    Util::sleep(0.1);
    loader.forceRepaint();
    WKStringGetUTF8CString(WKPageCopyTitle(WKViewGetPage(view.get())), firstSampleAfterSuspend, bufferSize);
    // The timer is paused - still two different samples.
    EXPECT_STRNE(secondSampleBeforeSuspend, firstSampleAfterSuspend);

    Util::sleep(0.1);
    loader.forceRepaint();
    WKStringGetUTF8CString(WKPageCopyTitle(WKViewGetPage(view.get())), secondSampleAfterSuspend, bufferSize);
    // The timer is paused - two samples collected while paused so they are equal.
    EXPECT_STREQ(firstSampleAfterSuspend, secondSampleAfterSuspend);

    WKViewResumeActiveDOMObjectsAndAnimations(view.get());
    Util::sleep(0.1);
    loader.forceRepaint();
    WKStringGetUTF8CString(WKPageCopyTitle(WKViewGetPage(view.get())), firstSampleAfterResume, bufferSize);
    // The timer is ticking again - two different samples.
    EXPECT_STRNE(secondSampleAfterSuspend, firstSampleAfterResume);
}