Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions playwright/src/main/java/com/microsoft/playwright/Frame.java
Original file line number Diff line number Diff line change
Expand Up @@ -5457,5 +5457,11 @@ default void waitForURL(Predicate<String> url) {
* @since v1.11
*/
void waitForURL(Predicate<String> url, @Nullable WaitForURLOptions options);
/**
* Tools that the frame registers through the experimental {@code WebMCP} browser API. See {@code WebMCP} for details.
*
* @since v1.64
*/
WebMCP webmcp();
}

15 changes: 15 additions & 0 deletions playwright/src/main/java/com/microsoft/playwright/Locator.java
Original file line number Diff line number Diff line change
Expand Up @@ -4610,6 +4610,21 @@ default Locator locator(Locator selectorOrLocator) {
* and other user-facing attributes over CSS selectors. This is useful for converting implementation-detail selectors into
* more resilient, human-readable locators.
*
* <p> <strong>Usage</strong>
*
* <p> An agent can pick an element by its ref from an {@link com.microsoft.playwright.Page#ariaSnapshot Page.ariaSnapshot()}
* taken in the {@code "ai"} mode. Refs only work for the latest snapshot. Normalize the ref locator and convert it to a
* string to get resilient locator code in your language, the same way {@code codegen} does.
*
* <p> Consider the following aria snapshot.
*
* <p> You can turn the ref into locator code:
* <pre>{@code
* Locator normalized = page.getByRef("e2").normalize();
* System.out.println(normalized.toString());
* // getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Submit"))
* }</pre>
*
* @since v1.59
*/
Locator normalize();
Expand Down
10 changes: 10 additions & 0 deletions playwright/src/main/java/com/microsoft/playwright/Page.java
Original file line number Diff line number Diff line change
Expand Up @@ -8967,6 +8967,16 @@ default Worker waitForWorker(Runnable callback) {
* @since v1.9
*/
Worker waitForWorker(@Nullable WaitForWorkerOptions options, Runnable callback);
/**
* Tools that the main frame registers through the experimental {@code WebMCP} browser API. Shortcut for {@link
* com.microsoft.playwright.Frame#webmcp Frame.webmcp()} of {@link com.microsoft.playwright.Page#mainFrame
* Page.mainFrame()}, see {@code WebMCP} for details.
*
* <p> <strong>Usage</strong>
*
* @since v1.64
*/
WebMCP webmcp();
/**
* This method returns all of the dedicated <a
* href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API">WebWorkers</a> associated with the page.
Expand Down
133 changes: 133 additions & 0 deletions playwright/src/main/java/com/microsoft/playwright/WebMCP.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.microsoft.playwright;

import org.jspecify.annotations.Nullable;
import com.microsoft.playwright.options.*;
import java.util.*;

/**
* {@code WebMCP} exposes the tools that a frame registers through the experimental {@code WebMCP} browser API, {@code
* navigator.modelContext}. It lists the tools and calls them.
*
* <p> Instances are accessed through {@link com.microsoft.playwright.Frame#webmcp Frame.webmcp()}. {@link
* com.microsoft.playwright.Page#webmcp Page.webmcp()} is the instance of the main frame.
*
* <p> <strong>NOTE:</strong> WebMCP is an experimental browser feature. Chromium enables it with the {@code --enable-features=WebMCP} launch
* argument, Firefox with the {@code dom.modelcontext.enabled} and {@code dom.modelcontext.testing.enabled} preferences.
* WebKit does not implement it.
*
* <p> Tool names, descriptions, input schemas and results are provided by the page, so treat them as untrusted input.
*/
public interface WebMCP {
class CallToolOptions {
/**
* Maximum time in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout
* BrowserContext.setDefaultTimeout()} or {@link com.microsoft.playwright.Page#setDefaultTimeout Page.setDefaultTimeout()}
* methods.
*/
public @Nullable Double timeout;

/**
* Maximum time in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout
* BrowserContext.setDefaultTimeout()} or {@link com.microsoft.playwright.Page#setDefaultTimeout Page.setDefaultTimeout()}
* methods.
*/
public CallToolOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
class ToolsOptions {
/**
* Maximum time in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout
* BrowserContext.setDefaultTimeout()} or {@link com.microsoft.playwright.Page#setDefaultTimeout Page.setDefaultTimeout()}
* methods.
*/
public @Nullable Double timeout;

/**
* Maximum time in milliseconds. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to disable timeout. The default
* value can be changed by using the {@link com.microsoft.playwright.BrowserContext#setDefaultTimeout
* BrowserContext.setDefaultTimeout()} or {@link com.microsoft.playwright.Page#setDefaultTimeout Page.setDefaultTimeout()}
* methods.
*/
public ToolsOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
}
}
/**
* Calls a tool registered by the frame and returns its result. The result is whatever the tool's {@code execute} function
* resolved to, typically an object with a {@code content} array. A result with {@code isError: true} is returned as is.
* The method throws when the tool is not registered or its {@code execute} function throws.
*
* @param name Name of the tool, as reported by {@link com.microsoft.playwright.WebMCP#tools WebMCP.tools()}.
* @param input Input for the tool, matching its {@code inputSchema}. Defaults to an empty object.
* @since v1.64
*/
default @Nullable Object callTool(String name, @Nullable Object input) {
return callTool(name, input, null);
}
/**
* Calls a tool registered by the frame and returns its result. The result is whatever the tool's {@code execute} function
* resolved to, typically an object with a {@code content} array. A result with {@code isError: true} is returned as is.
* The method throws when the tool is not registered or its {@code execute} function throws.
*
* @param name Name of the tool, as reported by {@link com.microsoft.playwright.WebMCP#tools WebMCP.tools()}.
* @since v1.64
*/
default @Nullable Object callTool(String name) {
return callTool(name, null);
}
/**
* Calls a tool registered by the frame and returns its result. The result is whatever the tool's {@code execute} function
* resolved to, typically an object with a {@code content} array. A result with {@code isError: true} is returned as is.
* The method throws when the tool is not registered or its {@code execute} function throws.
*
* @param name Name of the tool, as reported by {@link com.microsoft.playwright.WebMCP#tools WebMCP.tools()}.
* @param input Input for the tool, matching its {@code inputSchema}. Defaults to an empty object.
* @since v1.64
*/
@Nullable Object callTool(String name, @Nullable Object input, @Nullable CallToolOptions options);
/**
* Returns the tools currently registered by the frame. Throws if the browser was launched without WebMCP support, see the
* note above for the launch options that enable it.
*
* <p> {@link com.microsoft.playwright.Page#webmcp Page.webmcp()} covers the main frame only, child frames list their tools
* through their own {@link com.microsoft.playwright.Frame#webmcp Frame.webmcp()}.
*
* @since v1.64
*/
default List<WebMCPTool> tools() {
return tools(null);
}
/**
* Returns the tools currently registered by the frame. Throws if the browser was launched without WebMCP support, see the
* note above for the launch options that enable it.
*
* <p> {@link com.microsoft.playwright.Page#webmcp Page.webmcp()} covers the main frame only, child frames list their tools
* through their own {@link com.microsoft.playwright.Frame#webmcp Frame.webmcp()}.
*
* @since v1.64
*/
List<WebMCPTool> tools(@Nullable ToolsOptions options);
}

Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ enum InternalEventType { NAVIGATED, LOADSTATE }
private final ListenerCollection<InternalEventType> internalListeners = new ListenerCollection<>();
PageImpl page;
boolean isDetached;
private final WebMCPImpl webmcp = new WebMCPImpl(this);

FrameImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
Expand Down Expand Up @@ -1137,6 +1138,11 @@ protected void handleEvent(String event, JsonObject params) {
}
}

@Override
public WebMCP webmcp() {
return webmcp;
}

protected double timeout(Double timeout) {
if (page != null) {
return page.timeoutSettings.timeout(timeout);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
class LocatorImpl implements Locator {
final FrameImpl frame;
final String selector;
private String stringRepresentation;

LocatorImpl(FrameImpl frame, String selector, LocatorOptions options) {
this(frame, selector, options, null);
Expand Down Expand Up @@ -113,8 +114,13 @@
public Locator normalize() {
JsonObject params = new JsonObject();
params.addProperty("selector", selector);
params.addProperty("sdkLanguage", "java");
JsonObject result = frame.sendMessage("resolveSelector", params, ChannelOwner.NO_TIMEOUT).getAsJsonObject();
return new LocatorImpl(frame, result.get("resolvedSelector").getAsString(), null);
LocatorImpl locator = new LocatorImpl(frame, result.get("resolvedSelector").getAsString(), null);
if (result.has("locatorCode")) {
locator.stringRepresentation = result.get("locatorCode").getAsString();
}
return locator;
}

@Override
Expand Down Expand Up @@ -689,6 +695,9 @@

@Override
public String toString() {
if (stringRepresentation != null) {
return stringRepresentation;
}
String description = description();
if (description != null) {
return description;
Expand All @@ -710,7 +719,7 @@
return frame.hashCode() ^ selector.hashCode();
}

FrameExpectResult expect(String expression, FrameExpectOptions options, String title) {

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, chromium)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, chromium)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / dev (macos-15-xlarge, webkit)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / dev (macos-15-xlarge, webkit)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, webkit)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, webkit)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / stable (ubuntu-latest, chrome)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / stable (ubuntu-latest, chrome)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / dev (macos-latest, chromium)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / dev (macos-latest, chromium)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, firefox)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, firefox)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, msedge)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, msedge)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / dev (macos-latest, firefox)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / dev (macos-latest, firefox)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, chrome)

cannot find symbol

Check failure on line 722 in playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, chrome)

cannot find symbol
options.selector = selector;
return frame.expect(expression, options, title);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,11 @@ public Frame mainFrame() {
return mainFrame;
}

@Override
public WebMCP webmcp() {
return mainFrame.webmcp();
}

@Override
public void hideHighlight() {
sendMessage("hideHighlight", new JsonObject(), NO_TIMEOUT);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright (c) Microsoft Corporation.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.microsoft.playwright.impl;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.microsoft.playwright.WebMCP;
import com.microsoft.playwright.options.WebMCPTool;

import java.util.Arrays;
import java.util.List;

import static com.microsoft.playwright.impl.Serialization.deserialize;
import static com.microsoft.playwright.impl.Serialization.gson;
import static com.microsoft.playwright.impl.Serialization.serializeArgument;

class WebMCPImpl implements WebMCP {
private final FrameImpl frame;

WebMCPImpl(FrameImpl frame) {
this.frame = frame;
}

@Override
public List<WebMCPTool> tools(ToolsOptions options) {
JsonElement json = frame.sendMessage("webmcpTools", new JsonObject(), frame.timeout(options == null ? null : options.timeout));
WebMCPTool[] tools = gson().fromJson(json.getAsJsonObject().get("tools"), WebMCPTool[].class);
return Arrays.asList(tools);
}

@Override
public Object callTool(String name, Object input, CallToolOptions options) {
JsonObject params = new JsonObject();
params.addProperty("name", name);
params.add("input", gson().toJsonTree(serializeArgument(input)));
JsonElement json = frame.sendMessage("webmcpCallTool", params, frame.timeout(options == null ? null : options.timeout));
SerializedValue value = gson().fromJson(json.getAsJsonObject().get("result"), SerializedValue.class);
return deserialize(value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.microsoft.playwright.options;

import org.jspecify.annotations.Nullable;

public class WebMCPTool {
/**
* Tool name, unique within the frame.
*/
public String name;
/**
* Tool description.
*/
public String description;
/**
* JSON Schema of the tool input, when the page provides one.
*/
public @Nullable Object inputSchema;
/**
* Hints the page provides about the tool.
*/
public @Nullable WebMCPToolAnnotations annotations;

}
Loading
Loading