Skip to content

Commit feb3c30

Browse files
[GTK][WPE] Add API to provide browser information required by automation
https://bugs.webkit.org/show_bug.cgi?id=175130 Source/JavaScriptCore: Reviewed by Brian Burg. Add browserName and browserVersion to RemoteInspector::Client::Capabilities and virtual methods to the Client to get them. * inspector/remote/RemoteInspector.cpp: (Inspector::RemoteInspector::updateClientCapabilities): Update also browserName and browserVersion. * inspector/remote/RemoteInspector.h: * inspector/remote/glib/RemoteInspectorGlib.cpp: (Inspector::RemoteInspector::requestAutomationSession): Call updateClientCapabilities() after the session is requested to ensure they are updated before StartAutomationSession reply is sent. * inspector/remote/glib/RemoteInspectorServer.cpp: Add browserName and browserVersion as return values of StartAutomationSession mesasage. Source/WebDriver: Reviewed by Brian Burg. * Session.cpp: (WebDriver::Session::createTopLevelBrowsingContext): Check if startAutomationSession and complete the command with error in that case. * SessionHost.h: * glib/SessionHostGlib.cpp: (WebDriver::SessionHost::matchCapabilities): Match the capabilities that are known only after the browser has been launched. (WebDriver::SessionHost::startAutomationSession): Handle the StartAutomationSession response, extracting the capabilities and calling matchCapabilities() to match them. (WebDriver::SessionHost::setTargetList): Return early if the session was rejected before due to invalid capabilities. Source/WebKit: Reviewed by Michael Catanzaro. When a new automation session is started, the web driver receives some required capabilities from the client, like browser name and version. The session should be rejected if those required capabilities don't match with the actual browser that is launched. We don't know that information in WebKit, so we need to add API so that users can provide it when a new session request is made. This patch adds boxed object WebKitApplicationInfo that can be used to set the application name and version. This object can be set to a WebKitAutomationSession when WebKitWebContext::automation-started signal is emitted. * PlatformGTK.cmake: * PlatformWPE.cmake: * UIProcess/API/glib/WebKitApplicationInfo.cpp: Added. (webkit_application_info_new): (webkit_application_info_ref): (webkit_application_info_unref): (webkit_application_info_set_name): (webkit_application_info_get_name): (webkit_application_info_set_version): (webkit_application_info_get_version): * UIProcess/API/glib/WebKitAutomationSession.cpp: (webkitAutomationSessionDispose): (webkit_automation_session_class_init): (webkitAutomationSessionGetBrowserName): (webkitAutomationSessionGetBrowserVersion): (webkit_automation_session_set_application_info): (webkit_automation_session_get_application_info): * UIProcess/API/glib/WebKitAutomationSessionPrivate.h: * UIProcess/API/glib/WebKitWebContext.cpp: * UIProcess/API/gtk/WebKitApplicationInfo.h: Added. * UIProcess/API/gtk/WebKitAutomationSession.h: * UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt: * UIProcess/API/gtk/docs/webkit2gtk-docs.sgml: * UIProcess/API/gtk/webkit2.h: * UIProcess/API/wpe/WebKitApplicationInfo.h: Added. * UIProcess/API/wpe/WebKitAutomationSession.h: * UIProcess/API/wpe/webkit.h: Tools: Reviewed by Michael Catanzaro. * MiniBrowser/gtk/main.c: (automationStartedCallback): Set browser information when a new automation session is started. * TestWebKitAPI/Tests/WebKitGLib/TestAutomationSession.cpp: (testAutomationSessionApplicationInfo): (beforeAll): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@220329 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent f07f206 commit feb3c30

27 files changed

+682
-15
lines changed

Source/JavaScriptCore/ChangeLog

+19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
2017-08-05 Carlos Garcia Campos <[email protected]>
2+
3+
[GTK][WPE] Add API to provide browser information required by automation
4+
https://bugs.webkit.org/show_bug.cgi?id=175130
5+
6+
Reviewed by Brian Burg.
7+
8+
Add browserName and browserVersion to RemoteInspector::Client::Capabilities and virtual methods to the Client to
9+
get them.
10+
11+
* inspector/remote/RemoteInspector.cpp:
12+
(Inspector::RemoteInspector::updateClientCapabilities): Update also browserName and browserVersion.
13+
* inspector/remote/RemoteInspector.h:
14+
* inspector/remote/glib/RemoteInspectorGlib.cpp:
15+
(Inspector::RemoteInspector::requestAutomationSession): Call updateClientCapabilities() after the session is
16+
requested to ensure they are updated before StartAutomationSession reply is sent.
17+
* inspector/remote/glib/RemoteInspectorServer.cpp: Add browserName and browserVersion as return values of
18+
StartAutomationSession mesasage.
19+
120
2017-08-06 Yusuke Suzuki <[email protected]>
221

322
Promise resolve and reject function should have length = 1

Source/JavaScriptCore/inspector/remote/RemoteInspector.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ void RemoteInspector::updateClientCapabilities()
133133
m_clientCapabilities = std::nullopt;
134134
else {
135135
RemoteInspector::Client::Capabilities updatedCapabilities = {
136-
m_client->remoteAutomationAllowed() // remoteAutomationAllowed
136+
m_client->remoteAutomationAllowed(),
137+
m_client->browserName(),
138+
m_client->browserVersion()
137139
};
138140

139141
m_clientCapabilities = updatedCapabilities;

Source/JavaScriptCore/inspector/remote/RemoteInspector.h

+6
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <wtf/Forward.h>
3131
#include <wtf/HashMap.h>
3232
#include <wtf/Lock.h>
33+
#include <wtf/text/WTFString.h>
3334

3435
#if PLATFORM(COCOA)
3536
#include "RemoteInspectorXPCConnection.h"
@@ -66,10 +67,14 @@ class JS_EXPORT_PRIVATE RemoteInspector final
6667
public:
6768
struct Capabilities {
6869
bool remoteAutomationAllowed : 1;
70+
String browserName;
71+
String browserVersion;
6972
};
7073

7174
virtual ~Client() { }
7275
virtual bool remoteAutomationAllowed() const = 0;
76+
virtual String browserName() const { return { }; }
77+
virtual String browserVersion() const { return { }; }
7378
virtual void requestAutomationSession(const String& sessionIdentifier) = 0;
7479
};
7580

@@ -85,6 +90,7 @@ class JS_EXPORT_PRIVATE RemoteInspector final
8590
RemoteInspector::Client* client() const { return m_client; }
8691
void setClient(RemoteInspector::Client*);
8792
void clientCapabilitiesDidChange();
93+
std::optional<RemoteInspector::Client::Capabilities> clientCapabilities() const { return m_clientCapabilities; }
8894

8995
void setupFailed(unsigned targetIdentifier);
9096
void setupCompleted(unsigned targetIdentifier);

Source/JavaScriptCore/inspector/remote/glib/RemoteInspectorGlib.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ void RemoteInspector::requestAutomationSession(const char* sessionID)
355355
return;
356356

357357
m_client->requestAutomationSession(String::fromUTF8(sessionID));
358+
updateClientCapabilities();
358359
}
359360

360361
} // namespace Inspector

Source/JavaScriptCore/inspector/remote/glib/RemoteInspectorServer.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ static const char introspectionXML[] =
7979
" </method>"
8080
" <method name='StartAutomationSession'>"
8181
" <arg type='s' name='sessionID' direction='in'/>"
82+
" <arg type='s' name='browserName' direction='out'/>"
83+
" <arg type='s' name='browserVersion' direction='out'/>"
8284
" </method>"
8385
" </interface>"
8486
"</node>";
@@ -121,7 +123,10 @@ const GDBusInterfaceVTable RemoteInspectorServer::s_interfaceVTable = {
121123
const char* sessionID;
122124
g_variant_get(parameters, "(&s)", &sessionID);
123125
inspectorServer->startAutomationSession(connection, sessionID);
124-
g_dbus_method_invocation_return_value(invocation, nullptr);
126+
auto capabilities = RemoteInspector::singleton().clientCapabilities();
127+
g_dbus_method_invocation_return_value(invocation, g_variant_new("(ss)",
128+
capabilities ? capabilities->browserName.utf8().data() : "",
129+
capabilities ? capabilities->browserVersion.utf8().data() : ""));
125130
} else
126131
g_dbus_method_invocation_return_value(invocation, nullptr);
127132
},

Source/WebDriver/ChangeLog

+19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
2017-08-05 Carlos Garcia Campos <[email protected]>
2+
3+
[GTK][WPE] Add API to provide browser information required by automation
4+
https://bugs.webkit.org/show_bug.cgi?id=175130
5+
6+
Reviewed by Brian Burg.
7+
8+
* Session.cpp:
9+
(WebDriver::Session::createTopLevelBrowsingContext): Check if startAutomationSession and complete the command
10+
with error in that case.
11+
* SessionHost.h:
12+
* glib/SessionHostGlib.cpp:
13+
(WebDriver::SessionHost::matchCapabilities): Match the capabilities that are known only after the browser has
14+
been launched.
15+
(WebDriver::SessionHost::startAutomationSession): Handle the StartAutomationSession response, extracting the
16+
capabilities and calling matchCapabilities() to match them.
17+
(WebDriver::SessionHost::setTargetList): Return early if the session was rejected before due to invalid
18+
capabilities.
19+
120
2017-08-05 Carlos Garcia Campos <[email protected]>
221

322
WebDriver: Implement page load strategy

Source/WebDriver/Session.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,11 @@ std::optional<String> Session::pageLoadStrategyString() const
122122
void Session::createTopLevelBrowsingContext(Function<void (CommandResult&&)>&& completionHandler)
123123
{
124124
ASSERT(!m_toplevelBrowsingContext.value());
125-
m_host->startAutomationSession(m_id, [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable {
125+
m_host->startAutomationSession(m_id, [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](std::optional<String> errorMessage) mutable {
126+
if (errorMessage) {
127+
completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError, errorMessage.value()));
128+
return;
129+
}
126130
m_host->sendCommandToBackend(ASCIILiteral("createBrowsingContext"), nullptr, [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) mutable {
127131
if (response.isError || !response.responseObject) {
128132
completionHandler(CommandResult::fail(WTFMove(response.responseObject)));

Source/WebDriver/SessionHost.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class SessionHost {
5656

5757
enum class Succeeded { No, Yes };
5858
void connectToBrowser(Function<void (Succeeded)>&&);
59-
void startAutomationSession(const String& sessionID, Function<void ()>&&);
59+
void startAutomationSession(const String& sessionID, Function<void (std::optional<String>)>&&);
6060

6161
struct CommandResponse {
6262
RefPtr<Inspector::InspectorObject> responseObject;
@@ -80,6 +80,7 @@ class SessionHost {
8080
static const GDBusInterfaceVTable s_interfaceVTable;
8181
void launchBrowser(Function<void (Succeeded)>&&);
8282
void connectToBrowser(std::unique_ptr<ConnectToBrowserAsyncData>&&);
83+
std::optional<String> matchCapabilities(GVariant*);
8384
void setupConnection(GRefPtr<GDBusConnection>&&, Function<void (Succeeded)>&&);
8485
void setTargetList(uint64_t connectionID, Vector<Target>&&);
8586
void sendMessageToFrontend(uint64_t connectionID, uint64_t targetID, const char* message);
@@ -94,7 +95,7 @@ class SessionHost {
9495
long m_closeMessageID { 0 };
9596

9697
#if USE(GLIB)
97-
Function<void ()> m_startSessionCompletionHandler;
98+
Function<void (std::optional<String>)> m_startSessionCompletionHandler;
9899
GRefPtr<GSubprocess> m_browser;
99100
GRefPtr<GDBusConnection> m_dbusConnection;
100101
GRefPtr<GCancellable> m_cancellable;

Source/WebDriver/glib/SessionHostGlib.cpp

+50-4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "config.h"
2727
#include "SessionHost.h"
2828

29+
#include "WebDriverService.h"
2930
#include <gio/gio.h>
3031
#include <wtf/RunLoop.h>
3132
#include <wtf/glib/GUniquePtr.h>
@@ -220,19 +221,59 @@ void SessionHost::setupConnection(GRefPtr<GDBusConnection>&& connection, Functio
220221
completionHandler(Succeeded::Yes);
221222
}
222223

223-
void SessionHost::startAutomationSession(const String& sessionID, Function<void ()>&& completionHandler)
224+
std::optional<String> SessionHost::matchCapabilities(GVariant* capabilities)
225+
{
226+
const char* browserName;
227+
const char* browserVersion;
228+
g_variant_get(capabilities, "(&s&s)", &browserName, &browserVersion);
229+
230+
if (m_capabilities.browserName) {
231+
if (m_capabilities.browserName.value() != browserName)
232+
return makeString("expected browserName ", m_capabilities.browserName.value(), " but got ", browserName);
233+
} else
234+
m_capabilities.browserName = String(browserName);
235+
236+
if (m_capabilities.browserVersion) {
237+
if (!WebDriverService::platformCompareBrowserVersions(m_capabilities.browserVersion.value(), browserVersion))
238+
return makeString("requested browserVersion is ", m_capabilities.browserVersion.value(), " but actual version is ", browserVersion);
239+
} else
240+
m_capabilities.browserVersion = String(browserVersion);
241+
242+
return std::nullopt;
243+
}
244+
245+
void SessionHost::startAutomationSession(const String& sessionID, Function<void (std::optional<String>)>&& completionHandler)
224246
{
225247
ASSERT(m_dbusConnection);
226248
ASSERT(!m_startSessionCompletionHandler);
227-
// FIXME: Make StartAutomationSession return browser information and we use it to match capabilities.
228249
m_startSessionCompletionHandler = WTFMove(completionHandler);
229250
g_dbus_connection_call(m_dbusConnection.get(), nullptr,
230251
INSPECTOR_DBUS_OBJECT_PATH,
231252
INSPECTOR_DBUS_INTERFACE,
232253
"StartAutomationSession",
233254
g_variant_new("(s)", sessionID.utf8().data()),
234255
nullptr, G_DBUS_CALL_FLAGS_NO_AUTO_START,
235-
-1, m_cancellable.get(), dbusConnectionCallAsyncReadyCallback, nullptr);
256+
-1, m_cancellable.get(), [](GObject* source, GAsyncResult* result, gpointer userData) {
257+
GUniqueOutPtr<GError> error;
258+
GRefPtr<GVariant> resultVariant = adoptGRef(g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), result, &error.outPtr()));
259+
if (!resultVariant && g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED))
260+
return;
261+
262+
auto sessionHost = static_cast<SessionHost*>(userData);
263+
if (!resultVariant) {
264+
auto completionHandler = std::exchange(sessionHost->m_startSessionCompletionHandler, nullptr);
265+
completionHandler(String("Failed to start automation session"));
266+
return;
267+
}
268+
269+
auto errorString = sessionHost->matchCapabilities(resultVariant.get());
270+
if (errorString) {
271+
auto completionHandler = std::exchange(sessionHost->m_startSessionCompletionHandler, nullptr);
272+
completionHandler(errorString);
273+
return;
274+
}
275+
}, this
276+
);
236277
}
237278

238279
void SessionHost::setTargetList(uint64_t connectionID, Vector<Target>&& targetList)
@@ -255,6 +296,11 @@ void SessionHost::setTargetList(uint64_t connectionID, Vector<Target>&& targetLi
255296
return;
256297
}
257298

299+
if (!m_startSessionCompletionHandler) {
300+
// Session creation was already rejected.
301+
return;
302+
}
303+
258304
m_connectionID = connectionID;
259305
g_dbus_connection_call(m_dbusConnection.get(), nullptr,
260306
INSPECTOR_DBUS_OBJECT_PATH,
@@ -265,7 +311,7 @@ void SessionHost::setTargetList(uint64_t connectionID, Vector<Target>&& targetLi
265311
-1, m_cancellable.get(), dbusConnectionCallAsyncReadyCallback, nullptr);
266312

267313
auto startSessionCompletionHandler = std::exchange(m_startSessionCompletionHandler, nullptr);
268-
startSessionCompletionHandler();
314+
startSessionCompletionHandler(std::nullopt);
269315
}
270316

271317
void SessionHost::sendMessageToFrontend(uint64_t connectionID, uint64_t targetID, const char* message)

Source/WebKit/ChangeLog

+42
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,45 @@
1+
2017-08-05 Carlos Garcia Campos <[email protected]>
2+
3+
[GTK][WPE] Add API to provide browser information required by automation
4+
https://bugs.webkit.org/show_bug.cgi?id=175130
5+
6+
Reviewed by Michael Catanzaro.
7+
8+
When a new automation session is started, the web driver receives some required capabilities from the client,
9+
like browser name and version. The session should be rejected if those required capabilities don't match with
10+
the actual browser that is launched. We don't know that information in WebKit, so we need to add API so that
11+
users can provide it when a new session request is made. This patch adds boxed object WebKitApplicationInfo that
12+
can be used to set the application name and version. This object can be set to a WebKitAutomationSession when
13+
WebKitWebContext::automation-started signal is emitted.
14+
15+
* PlatformGTK.cmake:
16+
* PlatformWPE.cmake:
17+
* UIProcess/API/glib/WebKitApplicationInfo.cpp: Added.
18+
(webkit_application_info_new):
19+
(webkit_application_info_ref):
20+
(webkit_application_info_unref):
21+
(webkit_application_info_set_name):
22+
(webkit_application_info_get_name):
23+
(webkit_application_info_set_version):
24+
(webkit_application_info_get_version):
25+
* UIProcess/API/glib/WebKitAutomationSession.cpp:
26+
(webkitAutomationSessionDispose):
27+
(webkit_automation_session_class_init):
28+
(webkitAutomationSessionGetBrowserName):
29+
(webkitAutomationSessionGetBrowserVersion):
30+
(webkit_automation_session_set_application_info):
31+
(webkit_automation_session_get_application_info):
32+
* UIProcess/API/glib/WebKitAutomationSessionPrivate.h:
33+
* UIProcess/API/glib/WebKitWebContext.cpp:
34+
* UIProcess/API/gtk/WebKitApplicationInfo.h: Added.
35+
* UIProcess/API/gtk/WebKitAutomationSession.h:
36+
* UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt:
37+
* UIProcess/API/gtk/docs/webkit2gtk-docs.sgml:
38+
* UIProcess/API/gtk/webkit2.h:
39+
* UIProcess/API/wpe/WebKitApplicationInfo.h: Added.
40+
* UIProcess/API/wpe/WebKitAutomationSession.h:
41+
* UIProcess/API/wpe/webkit.h:
42+
143
2017-08-06 Carlos Alberto Lopez Perez <[email protected]>
244

345
[GTK][WPE] CFLAGS from pkg-config for (E)GL are not passed to WebKit

Source/WebKit/PlatformGTK.cmake

+2
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ list(APPEND WebKit2_SOURCES
117117
UIProcess/API/C/gtk/WKView.cpp
118118

119119
UIProcess/API/glib/IconDatabase.cpp
120+
UIProcess/API/glib/WebKitApplicationInfo.cpp
120121
UIProcess/API/glib/WebKitAuthenticationRequest.cpp
121122
UIProcess/API/glib/WebKitAutomationSession.cpp
122123
UIProcess/API/glib/WebKitBackForwardList.cpp
@@ -417,6 +418,7 @@ endif ()
417418
set(WebKit2GTK_INSTALLED_HEADERS
418419
${DERIVED_SOURCES_WEBKIT2GTK_API_DIR}/WebKitEnumTypes.h
419420
${DERIVED_SOURCES_WEBKIT2GTK_API_DIR}/WebKitVersion.h
421+
${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitApplicationInfo.h
420422
${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitAuthenticationRequest.h
421423
${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitAutocleanups.h
422424
${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitAutomationSession.h

Source/WebKit/PlatformWPE.cmake

+2
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ list(APPEND WebKit2_SOURCES
132132
UIProcess/API/C/wpe/WKView.cpp
133133

134134
UIProcess/API/glib/IconDatabase.cpp
135+
UIProcess/API/glib/WebKitApplicationInfo.cpp
135136
UIProcess/API/glib/WebKitAuthenticationRequest.cpp
136137
UIProcess/API/glib/WebKitAutomationSession.cpp
137138
UIProcess/API/glib/WebKitBackForwardList.cpp
@@ -275,6 +276,7 @@ list(APPEND WebKit2_DERIVED_SOURCES
275276

276277
set(WPE_API_INSTALLED_HEADERS
277278
${DERIVED_SOURCES_WPE_API_DIR}/WebKitEnumTypes.h
279+
${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitApplicationInfo.h
278280
${WEBKIT2_DIR}/UIProcess/API/wpe/WebKitAuthenticationRequest.h
279281
${WEBKIT2_DIR}/UIProcess/API/wpe/WebKitAutomationSession.h
280282
${WEBKIT2_DIR}/UIProcess/API/wpe/WebKitBackForwardList.h

0 commit comments

Comments
 (0)