├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── java
└── com
│ └── google
│ └── devtoolsdriver
│ ├── devtools
│ ├── Console.java
│ ├── DOM.java
│ ├── DevtoolsCommand.java
│ ├── DevtoolsDebugger.java
│ ├── DevtoolsDomain.java
│ ├── DevtoolsErrorException.java
│ ├── DevtoolsEvent.java
│ ├── DevtoolsMessage.java
│ ├── DevtoolsObject.java
│ ├── DevtoolsResult.java
│ ├── IdGenerator.java
│ ├── Network.java
│ ├── ObjectWrapper.java
│ ├── Page.java
│ ├── Runtime.java
│ └── Timeline.java
│ ├── examples
│ └── ExampleMobileSafariWebTest.java
│ ├── safari
│ ├── ConfigProfiles.java
│ ├── InspectorMessenger.java
│ ├── SafariBrowser.java
│ ├── SafariBrowserLauncher.java
│ └── profiles
│ │ ├── BUILD
│ │ ├── cert_profile_template.mobileconfig
│ │ └── http_proxy_template.mobileconfig
│ ├── util
│ └── JavaxJson.java
│ └── webdriver
│ ├── Browser.java
│ ├── BrowserException.java
│ ├── BrowserLauncher.java
│ ├── JsAtoms.java
│ └── PageId.java
├── javatests
└── com
│ └── google
│ └── devtoolsdriver
│ ├── devtools
│ ├── CommandGenerationTest.java
│ ├── DevtoolsDebuggerTest.java
│ ├── DevtoolsObjectTest.java
│ └── MessageFromJsonTest.java
│ ├── safari
│ ├── FakeScheduledExecutorService.java
│ └── InspectorMessengerTest.java
│ └── webdriver
│ └── JsAtomsTest.java
├── pom.xml
└── third_party
├── ios_driver
├── LICENSE
└── org
│ └── uiautomation
│ └── ios
│ ├── HostInfo.java
│ ├── IOSServer.java
│ ├── IOSServerConfiguration.java
│ ├── IOSServerManager.java
│ ├── SafariDriver.java
│ ├── ServerSideSession.java
│ ├── WebDriverMain.java
│ ├── command
│ ├── AddCookieHandler.java
│ ├── AlertHandler.java
│ ├── BackHandler.java
│ ├── ClearHandler.java
│ ├── ClickHandler.java
│ ├── CommandHandler.java
│ ├── CssPropertyHandler.java
│ ├── DeleteAllCookiesHandler.java
│ ├── DeleteCookieByNameHandler.java
│ ├── ExecuteAsyncScriptHandler.java
│ ├── ExecuteScriptHandler.java
│ ├── FindElementHandler.java
│ ├── FindElementsHandler.java
│ ├── ForwardHandler.java
│ ├── GetAttributeHandler.java
│ ├── GetCapabilitiesHandler.java
│ ├── GetConfigurationHandler.java
│ ├── GetCookiesHandler.java
│ ├── GetCurrentContextHandler.java
│ ├── GetElementSizeHandler.java
│ ├── GetHandler.java
│ ├── GetLocationHandler.java
│ ├── GetPageSizeHandler.java
│ ├── GetPageSourceHandler.java
│ ├── GetSessionsHandler.java
│ ├── GetTagNameHandler.java
│ ├── GetTextHandler.java
│ ├── GetTitleHandler.java
│ ├── GetURL.java
│ ├── GetWindowHandlesHandler.java
│ ├── IsDisplayedHandler.java
│ ├── IsEnabledHandler.java
│ ├── IsEqualHandler.java
│ ├── IsSelectedHandler.java
│ ├── LogHandler.java
│ ├── LogTypesHandler.java
│ ├── MoveToHandler.java
│ ├── NewSessionHandler.java
│ ├── QuitSessionHandler.java
│ ├── RefreshHandler.java
│ ├── ServerStatusHandler.java
│ ├── SetConfigurationHandler.java
│ ├── SetCurrentContextHandler.java
│ ├── SetFrameHandler.java
│ ├── SetImplicitWaitTimeoutHandler.java
│ ├── SetScriptTimeoutHandler.java
│ ├── SetTimeoutHandler.java
│ ├── SetValueHandler.java
│ ├── SubmitHandler.java
│ ├── TakeScreenshotHandler.java
│ ├── ToCSSSelectorConverter.java
│ └── configuration
│ │ ├── CommandConfigurationStore.java
│ │ └── DriverConfigurationStore.java
│ ├── drivers
│ └── RemoteIOSWebDriver.java
│ ├── logging
│ ├── IOSLogManager.java
│ ├── Log.java
│ ├── PerformanceListener.java
│ └── WebDriverLog.java
│ ├── servlet
│ ├── CommandConfiguration.java
│ ├── DriverBasedServlet.java
│ ├── DriverConfiguration.java
│ ├── IOSServlet.java
│ ├── WebDriverLikeCommand.java
│ └── WebDriverLikeRequest.java
│ └── wkrdp
│ ├── DOMContext.java
│ ├── WebInspectorHelper.java
│ ├── events
│ ├── ChildIframeInserted.java
│ ├── ChildNodeRemoved.java
│ ├── Event.java
│ ├── EventFactory.java
│ ├── EventHistory.java
│ └── NodeEvent.java
│ └── model
│ ├── NodeId.java
│ ├── RemoteObject.java
│ ├── RemoteObjectArray.java
│ ├── RemoteObjectIterator.java
│ └── RemoteWebElement.java
└── jsatoms
├── LICENSE
├── back_ios.js
├── clear_ios.js
├── forward_ios.js
├── get_effective_style_ios.js
├── get_interactable_size_ios.js
├── get_location_ios.js
├── get_size_ios.js
├── get_visible_text_ios.js
├── is_enabled_ios.js
├── is_selected_ios.js
├── is_shown_ios.js
├── move_mouse_ios.js
├── stringify_ios.js
├── submit_ios.js
├── tap_ios.js
├── type_ios.js
├── xpath_ios.js
└── xpaths_ios.js
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Contributor License Agreement
7 |
8 | Contributions to this project must be accompanied by a Contributor License
9 | Agreement. You (or your employer) retain the copyright to your contribution,
10 | this simply gives us permission to use and redistribute your contributions as
11 | part of the project. Head over to to see
12 | your current agreements on file or to sign a new one.
13 |
14 | You generally only need to submit a CLA once, so if you've already submitted one
15 | (even if it was for a different project), you probably don't need to do it
16 | again.
17 |
18 | ## Code reviews
19 |
20 | All submissions, including submissions by project members, require review. We
21 | use GitHub pull requests for this purpose. Consult
22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
23 | information on using pull requests.
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DevTools Driver
2 |
3 | DevTools Driver is a Java framework for creating a WebDriver server
4 | implementation for any browser that supports the [DevTools Remote Debugging
5 | Protocol](https://chromedevtools.github.io/devtools-protocol/), including any
6 | browser based on the WebKit or Blink browser engines. Implementations for such
7 | browsers can be created simply by providing a few relatively simple hook
8 | methods, and the framework handles the rest, largely through JavaScript
9 | injection of [browser automation
10 | atoms](https://github.com/SeleniumHQ/selenium/wiki/Automation-Atoms) over
11 | DevTools.
12 |
13 | This project includes a WebDriver implementation for Mobile Safari on iOS. This
14 | implementation, which works for both iOS simulators and real devices, uses the
15 | [iOS Device Control library](https://github.com/google/ios-device-control) to
16 | control devices. An example of a web test controlling a remote Mobile Safari
17 | Devtools Driver can be found in [ExampleMobileSafariWebTest.java](src/com/google/devtoolsdriver/examples/ExampleMobileSafariWebTest.java).
18 |
19 | ## Installation
20 |
21 | 1. Before assembling a runnable jar for a Selenium server, the iOS Device
22 | Control dependency has to be installed. This can be done by following the
23 | steps outlined [here](https://github.com/google/ios-device-control).
24 |
25 | 2. The library must then be installed into the local Maven repository:
26 |
27 | ```console
28 | git clone https://github.com/google/ios-device-control.git
29 | cd ios-device-control/
30 | mvn install
31 | ```
32 |
33 | 3. A runnable jar of a Mobile Safari capable Selenium server can be assembled
34 | (along with the example provided) by running:
35 |
36 | ```console
37 | git clone https://github.com/google/devtools-driver
38 | cd devtools-driver/
39 | mvn assembly:assembly
40 | ```
41 |
42 | 4. Run the assembled jar found at
43 | target/SafariDriverServer-jar-with-dependencies.jar on a Mac:
44 |
45 | ```console
46 | # The -simulator flag indicates that all requested WebDriver instances will be of an iOS Simulator. Omit it for real devices
47 | java -jar SafariDriverServer-jar-with-dependencies.jar -simulator
48 | ```
49 |
50 | ## License
51 |
52 | DevTools Driver is licensed under the open-source [Apache 2.0 license](LICENSE)
53 |
54 | ## Contributing
55 |
56 | Please [see the guidelines for contributing](CONTRIBUTING.md) before creating
57 | pull requests
58 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/devtools/Console.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.devtools;
16 |
17 | import static com.google.devtoolsdriver.devtools.DevtoolsDomain.CONSOLE;
18 |
19 | /**
20 | * Factory for messages in the devtools Console domain. For a specification of this domain's
21 | * methods, see the debugging protocol
23 | * viewer. Note that not all the domain's methods have been implemented yet.
24 | */
25 | public final class Console {
26 | private static DevtoolsCommand command(String methodSuffix) {
27 | return new DevtoolsCommand.NoOptionals(CONSOLE.methodName(methodSuffix));
28 | }
29 |
30 | public static DevtoolsCommand enable() {
31 | return command("enable");
32 | }
33 |
34 | public static DevtoolsCommand disable() {
35 | return command("disable");
36 | }
37 |
38 | public static DevtoolsCommand clearMessages() {
39 | return command("clearMessages");
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/devtools/DevtoolsCommand.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.devtools;
16 |
17 | import com.google.common.base.MoreObjects;
18 | import java.util.List;
19 | import java.util.Objects;
20 | import javax.json.Json;
21 | import javax.json.JsonObject;
22 | import javax.json.JsonObjectBuilder;
23 |
24 | /** A command message in the Devtools protocol. */
25 | public abstract class DevtoolsCommand extends ObjectWrapper
26 | implements DevtoolsMessage {
27 | private final String method;
28 |
29 | private DevtoolsCommand(String method, JsonObject object) {
30 | super(object);
31 | this.method = method;
32 | }
33 |
34 | @Override
35 | public final String method() {
36 | return method;
37 | }
38 |
39 | @Override
40 | public final JsonObject params() {
41 | return object;
42 | }
43 |
44 | @Override
45 | public final boolean equals(Object other) {
46 | if (other == this) {
47 | return true;
48 | }
49 | if (other instanceof DevtoolsCommand) {
50 | DevtoolsCommand that = (DevtoolsCommand) other;
51 | return method().equals(that.method()) && object.equals(that.object);
52 | }
53 | return false;
54 | }
55 |
56 | @Override
57 | public final int hashCode() {
58 | return Objects.hash(method(), object);
59 | }
60 |
61 | @Override
62 | public final String toString() {
63 | return MoreObjects.toStringHelper(DevtoolsCommand.class)
64 | .add("method", method())
65 | .add("params", params())
66 | .toString();
67 | }
68 |
69 | /**
70 | * Convert this JSON command to a JsonObject message that can be sent to a remote debugger. The
71 | * returned messages will have the specified id in its 'id' field.
72 | */
73 | final JsonObject toJson(int id) {
74 | JsonObjectBuilder builder = Json.createObjectBuilder().add("method", method());
75 | if (!object.isEmpty()) {
76 | builder.add("params", object);
77 | }
78 | builder.add("id", id);
79 | return builder.build();
80 | }
81 |
82 | /** A devtools command with no optional parameters */
83 | static final class NoOptionals extends DevtoolsCommand {
84 | NoOptionals(String method) {
85 | super(method, Json.createObjectBuilder().build());
86 | }
87 |
88 | NoOptionals(String method, JsonObject params) {
89 | super(method, params);
90 | }
91 |
92 | @Override
93 | NoOptionals create(JsonObject params) {
94 | return new NoOptionals(method(), params);
95 | }
96 | }
97 |
98 | /** A devtools command with publicly exposed functions for adding optional parameters */
99 | abstract static class WithOptionals extends DevtoolsCommand {
100 | WithOptionals(String method) {
101 | super(method, Json.createObjectBuilder().build());
102 | }
103 |
104 | WithOptionals(String method, JsonObject params) {
105 | super(method, params);
106 | }
107 |
108 | /*
109 | * The with methods will always call the create method, which will be overrided to
110 | * return a new instance of an object of type T. This makes the below suppressions safe
111 | * to add.
112 | */
113 | @SuppressWarnings("unchecked")
114 | @Override
115 | final C with(String name, boolean value) {
116 | return (C) super.with(name, value);
117 | }
118 |
119 | @SuppressWarnings("unchecked")
120 | @Override
121 | final C with(String name, long value) {
122 | return (C) super.with(name, value);
123 | }
124 |
125 | @SuppressWarnings("unchecked")
126 | @Override
127 | final C with(String name, double value) {
128 | return (C) super.with(name, value);
129 | }
130 |
131 | @SuppressWarnings("unchecked")
132 | @Override
133 | final C with(String name, String value) {
134 | return (C) super.with(name, value);
135 | }
136 |
137 | @SuppressWarnings("unchecked")
138 | @Override
139 | final C with(String name, DevtoolsObject value) {
140 | return (C) super.with(name, value);
141 | }
142 |
143 | @SuppressWarnings("unchecked")
144 | @Override
145 | final C withNumberArray(String name, List numberList) {
146 | return (C) super.withNumberArray(name, numberList);
147 | }
148 |
149 | @SuppressWarnings("unchecked")
150 | @Override
151 | final C withStringArray(String name, List stringList) {
152 | return (C) super.withStringArray(name, stringList);
153 | }
154 |
155 | @SuppressWarnings("unchecked")
156 | @Override
157 | final C withObjectArray(String name, List extends DevtoolsObject> objectList) {
158 | return (C) super.withObjectArray(name, objectList);
159 | }
160 |
161 | @Override
162 | abstract C create(JsonObject object);
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/devtools/DevtoolsDomain.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.devtools;
16 |
17 | /** An enumeration and utility for generating qualified names of methods in the devtools protocol */
18 | enum DevtoolsDomain {
19 | CONSOLE("Console"),
20 | DOM("DOM"),
21 | NETWORK("Network"),
22 | PAGE("Page"),
23 | RUNTIME("Runtime"),
24 | TIMELINE("Timeline");
25 |
26 | private final String name;
27 |
28 | private DevtoolsDomain(String name) {
29 | this.name = name;
30 | }
31 |
32 | String methodName(String methodSuffix) {
33 | return name + "." + methodSuffix;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/devtools/DevtoolsErrorException.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.devtools;
16 |
17 | import javax.json.JsonObject;
18 |
19 | /** Indicates a devtools command caused an error when executed by the debugger. */
20 | public final class DevtoolsErrorException extends Exception {
21 | private final DevtoolsCommand command;
22 | private final JsonObject response;
23 |
24 | DevtoolsErrorException(DevtoolsCommand command, JsonObject response) {
25 | super(String.format("Devtools command %s caused an error: %s", command, response));
26 | this.command = command;
27 | this.response = response;
28 | }
29 |
30 | public DevtoolsCommand command() {
31 | return command;
32 | }
33 |
34 | public JsonObject response() {
35 | return response;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/devtools/DevtoolsEvent.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.devtools;
16 |
17 | import com.google.auto.value.AutoValue;
18 | import com.google.common.base.Optional;
19 | import com.google.devtoolsdriver.util.JavaxJson;
20 | import javax.json.JsonObject;
21 |
22 | /** An event message in the Devtools protocol. */
23 | @AutoValue
24 | public abstract class DevtoolsEvent implements DevtoolsMessage {
25 | public static DevtoolsEvent fromJson(JsonObject json) {
26 | String method = json.getString("method");
27 | Optional params = Optional.fromNullable(json.getJsonObject("params"));
28 | return new AutoValue_DevtoolsEvent(method, params.or(JavaxJson.EMPTY_OBJECT));
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/devtools/DevtoolsMessage.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.devtools;
16 |
17 | import javax.json.JsonObject;
18 |
19 | /** A message (command or event) in the Devtools protocol. */
20 | interface DevtoolsMessage {
21 | /* The fully qualified Domain.methodName method name of this message */
22 | String method();
23 |
24 | /* The Json parameters of this message */
25 | JsonObject params();
26 | }
27 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/devtools/DevtoolsObject.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.devtools;
16 |
17 | import com.google.common.base.MoreObjects;
18 | import java.util.List;
19 | import java.util.Objects;
20 | import javax.json.Json;
21 | import javax.json.JsonObject;
22 |
23 | /** A Devtool-defined object (JSON object with defined schema) to be used in Devtools commands. */
24 | public abstract class DevtoolsObject extends ObjectWrapper {
25 | private DevtoolsObject(JsonObject object) {
26 | super(object);
27 | }
28 |
29 | /** Get the json properties of this object. */
30 | public final JsonObject properties() {
31 | return object;
32 | }
33 |
34 | @Override
35 | public final boolean equals(Object other) {
36 | if (other == this) {
37 | return true;
38 | }
39 | if (other instanceof DevtoolsObject) {
40 | DevtoolsObject that = (DevtoolsObject) other;
41 | return object.equals(that.object);
42 | }
43 | return false;
44 | }
45 |
46 | @Override
47 | public final int hashCode() {
48 | return Objects.hashCode(object);
49 | }
50 |
51 | @Override
52 | public final String toString() {
53 | return MoreObjects.toStringHelper(DevtoolsObject.class)
54 | .add("properties", properties())
55 | .toString();
56 | }
57 |
58 | /** A Devtools type with no optional field */
59 | static final class NoOptionals extends DevtoolsObject {
60 | NoOptionals() {
61 | super(Json.createObjectBuilder().build());
62 | }
63 |
64 | NoOptionals(JsonObject properties) {
65 | super(properties);
66 | }
67 |
68 | @Override
69 | NoOptionals create(JsonObject object) {
70 | return new NoOptionals(object);
71 | }
72 | }
73 |
74 | /** Abstract type for a Devtools type with optional fields */
75 | abstract static class WithOptionals extends DevtoolsObject {
76 | WithOptionals() {
77 | super(Json.createObjectBuilder().build());
78 | }
79 |
80 | WithOptionals(JsonObject properties) {
81 | super(properties);
82 | }
83 |
84 | /*
85 | * The with methods will always call the create method, which will be overrided to
86 | * return a new instance of an object of type T. This makes the below suppressions safe
87 | * to add.
88 | */
89 | @SuppressWarnings("unchecked")
90 | @Override
91 | final T with(String name, boolean value) {
92 | return (T) super.with(name, value);
93 | }
94 |
95 | @SuppressWarnings("unchecked")
96 | @Override
97 | final T with(String name, long value) {
98 | return (T) super.with(name, value);
99 | }
100 |
101 | @SuppressWarnings("unchecked")
102 | @Override
103 | final T with(String name, String value) {
104 | return (T) super.with(name, value);
105 | }
106 |
107 | @SuppressWarnings("unchecked")
108 | @Override
109 | final T with(String name, DevtoolsObject value) {
110 | return (T) super.with(name, value);
111 | }
112 |
113 | @SuppressWarnings("unchecked")
114 | @Override
115 | final T with(String name, double value) {
116 | return (T) super.with(name, value);
117 | }
118 |
119 | @SuppressWarnings("unchecked")
120 | @Override
121 | final T withNumberArray(String name, List numberList) {
122 | return (T) super.withNumberArray(name, numberList);
123 | }
124 |
125 | @SuppressWarnings("unchecked")
126 | @Override
127 | final T withStringArray(String name, List stringList) {
128 | return (T) super.withStringArray(name, stringList);
129 | }
130 |
131 | @SuppressWarnings("unchecked")
132 | @Override
133 | final T withObjectArray(String name, List extends DevtoolsObject> objectList) {
134 | return (T) super.withObjectArray(name, objectList);
135 | }
136 |
137 | @Override
138 | abstract T create(JsonObject object);
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/devtools/DevtoolsResult.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.devtools;
16 |
17 | import com.google.auto.value.AutoValue;
18 | import javax.json.JsonObject;
19 |
20 | /** A command result in the Devtools protocol. */
21 | @AutoValue
22 | public abstract class DevtoolsResult {
23 | static DevtoolsResult fromJson(JsonObject response) {
24 | JsonObject result = response.getJsonObject("result");
25 | return new AutoValue_DevtoolsResult(result);
26 | }
27 |
28 | /** Get the JSON result */
29 | public abstract JsonObject json();
30 | }
31 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/devtools/IdGenerator.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.devtools;
16 |
17 | /**
18 | * An IdGenerator is a utility used during message generation to assign a unique id to a message.
19 | */
20 | interface IdGenerator {
21 | /** Return the next unique integer id. */
22 | int nextId();
23 | }
24 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/devtools/ObjectWrapper.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.devtools;
16 |
17 | import com.google.devtoolsdriver.util.JavaxJson;
18 | import java.util.List;
19 | import javax.json.Json;
20 | import javax.json.JsonArrayBuilder;
21 | import javax.json.JsonObject;
22 | import javax.json.JsonObjectBuilder;
23 |
24 | /** A fluent base for all Devtools objects */
25 | abstract class ObjectWrapper {
26 | final JsonObject object;
27 |
28 | ObjectWrapper(JsonObject object) {
29 | this.object = object;
30 | }
31 |
32 | T with(String name, boolean value) {
33 | return create(toObjectBuilder().add(name, value));
34 | }
35 |
36 | T with(String name, long value) {
37 | return create(toObjectBuilder().add(name, value));
38 | }
39 |
40 | T with(String name, double value) {
41 | return create(toObjectBuilder().add(name, value));
42 | }
43 |
44 | T with(String name, String value) {
45 | return create(toObjectBuilder().add(name, value));
46 | }
47 |
48 | T with(String name, DevtoolsObject value) {
49 | return create(toObjectBuilder().add(name, value.object));
50 | }
51 |
52 | T withNumberArray(String name, List numList) {
53 | JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
54 | for (long l : numList) {
55 | arrayBuilder.add(l);
56 | }
57 | return create(toObjectBuilder().add(name, arrayBuilder));
58 | }
59 |
60 | T withStringArray(String name, List stringList) {
61 | JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
62 | for (String s : stringList) {
63 | arrayBuilder.add(s);
64 | }
65 | return create(toObjectBuilder().add(name, arrayBuilder));
66 | }
67 |
68 | T withObjectArray(String name, List extends DevtoolsObject> objectList) {
69 | JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
70 | for (DevtoolsObject t : objectList) {
71 | arrayBuilder.add(t.object);
72 | }
73 | return create(toObjectBuilder().add(name, arrayBuilder));
74 | }
75 |
76 | /** Create a new instance of the DevtoolsObject subclass, using parameters */
77 | abstract T create(JsonObject params);
78 |
79 | private T create(JsonObjectBuilder builder) {
80 | return create(builder.build());
81 | }
82 |
83 | private JsonObjectBuilder toObjectBuilder() {
84 | return JavaxJson.toBuilder(object);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/devtools/Timeline.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.devtools;
16 |
17 | import static com.google.devtoolsdriver.devtools.DevtoolsDomain.TIMELINE;
18 |
19 | /**
20 | * Factory for messages in the formerly used devtools Timeline domain. Since stable version 1.1,
21 | * this domain has been deprecated. This class still exists to maintain support for legacy clients.
22 | */
23 | public final class Timeline {
24 | private static DevtoolsCommand command(String methodSuffix) {
25 | return new DevtoolsCommand.NoOptionals(TIMELINE.methodName(methodSuffix));
26 | }
27 |
28 | public static DevtoolsCommand start() {
29 | return command("start");
30 | }
31 |
32 | public static DevtoolsCommand stop() {
33 | return command("stop");
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/examples/ExampleMobileSafariWebTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.examples;
16 |
17 | import com.google.iosdevicecontrol.util.FluentLogger;
18 | import java.net.URL;
19 | import java.nio.file.Files;
20 | import java.nio.file.Path;
21 | import org.openqa.selenium.By;
22 | import org.openqa.selenium.NoSuchElementException;
23 | import org.openqa.selenium.OutputType;
24 | import org.openqa.selenium.TakesScreenshot;
25 | import org.openqa.selenium.WebDriver;
26 | import org.openqa.selenium.WebElement;
27 | import org.openqa.selenium.remote.DesiredCapabilities;
28 | import org.openqa.selenium.remote.RemoteWebDriver;
29 |
30 | /**
31 | * This class contains an example use case of the DevTools Driver library for automating iOS devices
32 | * running on a Selenium server.
33 | */
34 | public class ExampleMobileSafariWebTest {
35 | private static final FluentLogger logger = FluentLogger.forEnclosingClass();
36 |
37 | private static WebDriver driver;
38 |
39 | public static void main(String[] args) throws Exception {
40 | // Create a DesiredCapabilities object to request specific devices from the WebDriver server.
41 | // A udid can be optionally specified, otherwise an arbitrary device is chosen.
42 | DesiredCapabilities caps = new DesiredCapabilities();
43 | // caps.setCapability("uuid", udid);
44 | // Start a WebDriver session. The local machine has to be running the SafariDriverServer, or
45 | // change localhost below to an IP running the SafariDriverServer.
46 | driver = new RemoteWebDriver(new URL("http://localhost:5555/wd/hub"), caps);
47 | // Connect to a URL
48 | driver.get("http://www.google.com");
49 |
50 | // Interact with the web page. In this example use case, the Webdriver API is used to find
51 | // specific elements, test a google search and take a screenshot.
52 | driver.findElement(By.id("hplogo"));
53 |
54 | // Google New York
55 | WebElement mobileSearchBox = driver.findElement(By.id("lst-ib"));
56 | mobileSearchBox.sendKeys("New York");
57 | WebElement searchBox;
58 | try {
59 | searchBox = driver.findElement(By.id("tsbb"));
60 | } catch (NoSuchElementException e) {
61 | searchBox = driver.findElement(By.name("btnG"));
62 | }
63 | searchBox.click();
64 |
65 | takeScreenshot();
66 | driver.navigate().refresh();
67 | takeScreenshot();
68 |
69 | // Quit the WebDriver instance on completion of the test.
70 | driver.quit();
71 | driver = null;
72 | }
73 |
74 | private static void takeScreenshot() throws Exception {
75 | byte[] screenshotBytes = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
76 | Path screenshotPath = Files.createTempFile("screenshot", ".png");
77 | Files.write(screenshotPath, screenshotBytes);
78 | logger.atInfo().log("Screenshot written to: %s", screenshotPath);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/safari/ConfigProfiles.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.safari;
16 |
17 | import static com.google.common.base.Preconditions.checkState;
18 | import static java.nio.charset.StandardCharsets.UTF_8;
19 |
20 | import com.dd.plist.NSArray;
21 | import com.dd.plist.NSData;
22 | import com.dd.plist.NSDictionary;
23 | import com.dd.plist.NSObject;
24 | import com.google.common.io.Resources;
25 | import com.google.common.net.HostAndPort;
26 | import com.google.iosdevicecontrol.IosDeviceException;
27 | import com.google.iosdevicecontrol.real.RealDevice;
28 | import com.google.iosdevicecontrol.util.PlistParser;
29 | import java.io.IOException;
30 | import java.nio.file.Files;
31 | import java.nio.file.Path;
32 | import java.util.Map;
33 |
34 | /** ProfileEditorUtils provides utilities for editing real device configuration profiles. */
35 | final class ConfigProfiles {
36 | private static final String PROFILES_ROOT = "com/google/devtoolsdriver/safari/profiles/";
37 | private static final String PROXY_PROFILE_PATH =
38 | PROFILES_ROOT + "http_proxy_template.mobileconfig";
39 | private static final String CERT_PROFILE_PATH =
40 | PROFILES_ROOT + "cert_profile_template.mobileconfig";
41 | private static final String PROXY_PROFILE_ID = "com.google.devtoolsdriver.safari.http_proxy";
42 | private static final String CERT_PROFILE_ID = "com.google.devtoolsdriver.safari.https_cert";
43 |
44 | /** Installs a profile to communicate with a specified HTTP/S proxy and port. */
45 | static void installProxyProfile(RealDevice device, HostAndPort hostAndPort)
46 | throws IosDeviceException {
47 | checkState(hostAndPort.hasPort());
48 | NSDictionary replacementDict = new NSDictionary();
49 | replacementDict.put("ProxyServer", hostAndPort.getHost());
50 | replacementDict.put("ProxyServerPort", hostAndPort.getPort());
51 | ConfigProfiles.installProfile(device, PROXY_PROFILE_PATH, replacementDict);
52 | }
53 |
54 | /** Installs a profile to set up an HTTPS certificate on the device. */
55 | static void installCertProfile(RealDevice device, String certName, String certContentBase64)
56 | throws IosDeviceException {
57 | NSDictionary replacementDict = new NSDictionary();
58 | replacementDict.put("PayloadCertificateFileName", certName + ".cer");
59 | try {
60 | replacementDict.put("PayloadContent", new NSData(certContentBase64));
61 | } catch (IOException e) {
62 | throw new IosDeviceException(device, e);
63 | }
64 | replacementDict.put("PayloadDisplayName", certName);
65 | ConfigProfiles.installProfile(device, CERT_PROFILE_PATH, replacementDict);
66 | }
67 |
68 | private static void installProfile(RealDevice device, String profilePath, NSDictionary newPayload)
69 | throws IosDeviceException {
70 | try {
71 | String templateXml = Resources.toString(Resources.getResource(profilePath), UTF_8);
72 | NSDictionary plistDict = (NSDictionary) PlistParser.fromXml(templateXml);
73 | NSArray plistArray = (NSArray) plistDict.get("PayloadContent");
74 | NSDictionary plistInnerDict = (NSDictionary) plistArray.objectAtIndex(0);
75 | for (Map.Entry entry : newPayload.entrySet()) {
76 | plistInnerDict.put(entry.getKey(), entry.getValue());
77 | }
78 | String plist = plistDict.toXMLPropertyList();
79 |
80 | Path configFile = Files.createTempFile("modified_profile", ".mobileconfig");
81 | Files.write(configFile, plist.getBytes(UTF_8));
82 | device.installProfile(configFile.toAbsolutePath());
83 | } catch (IOException e) {
84 | throw new IosDeviceException(device, e);
85 | }
86 | }
87 |
88 | static void removeProxyProfile(RealDevice device) throws IosDeviceException {
89 | removeProfile(device, PROXY_PROFILE_ID);
90 | }
91 |
92 | static void removeCertProfile(RealDevice device) throws IosDeviceException {
93 | removeProfile(device, CERT_PROFILE_ID);
94 | }
95 |
96 | private static void removeProfile(RealDevice device, String profileId) throws IosDeviceException {
97 | boolean profileInstalled =
98 | device.listConfigurationProfiles().stream().anyMatch(p -> p.identifier().equals(profileId));
99 | if (profileInstalled) {
100 | device.removeProfile(profileId);
101 | }
102 | }
103 |
104 | private ConfigProfiles() {}
105 | }
106 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/safari/profiles/BUILD:
--------------------------------------------------------------------------------
1 | licenses(["notice"]) # Apache License 2.0
2 |
3 | filegroup(
4 | name = "opensource_files",
5 | srcs = glob(["*"]),
6 | visibility = ["//third_party/java_src/devtoolsdriver/opensource:__pkg__"],
7 | )
8 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/safari/profiles/cert_profile_template.mobileconfig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PayloadContent
6 |
7 |
8 | PayloadCertificateFileName
9 | PLACEHOLDER
10 | PayloadContent
11 |
12 | PLACEHOLDER
13 |
14 | PayloadDescription
15 | Adds a CA root certificate
16 | PayloadDisplayName
17 | PLACEHOLDER
18 | PayloadIdentifier
19 | com.apple.security.root.5051B0E0-F165-429F-9435-6B76B8889E5B
20 | PayloadType
21 | com.apple.security.root
22 | PayloadUUID
23 | 5051B0E0-F165-429F-9435-6B76B8889E5B
24 | PayloadVersion
25 | 1
26 |
27 |
28 | PayloadDisplayName
29 | HTTPS Certificate Profile
30 | PayloadIdentifier
31 | com.google.devtoolsdriver.safari.https_cert
32 | PayloadRemovalDisallowed
33 |
34 | PayloadType
35 | Configuration
36 | PayloadUUID
37 | E2174BFF-F292-4C26-959C-D4E07DC2BF8A
38 | PayloadVersion
39 | 1
40 |
41 |
42 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/safari/profiles/http_proxy_template.mobileconfig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PayloadContent
6 |
7 |
8 | PayloadDescription
9 | Global HTTP Proxy
10 | PayloadDisplayName
11 | Global HTTP Proxy
12 | PayloadIdentifier
13 | com.apple.proxy.http.global.CF237754-A774-4832-A507-E944FB58A670
14 | PayloadType
15 | com.apple.proxy.http.global
16 | PayloadUUID
17 | CF237754-A774-4832-A507-E944FB58A670
18 | PayloadVersion
19 | 1
20 | ProxyCaptiveLoginAllowed
21 |
22 | ProxyServer
23 | HOSTNAME
24 | ProxyServerPort
25 | 0
26 | ProxyType
27 | Manual
28 |
29 |
30 | PayloadDisplayName
31 | HTTP Proxy Settings
32 | PayloadIdentifier
33 | com.google.devtoolsdriver.safari.http_proxy
34 | PayloadRemovalDisallowed
35 |
36 | PayloadType
37 | Configuration
38 | PayloadUUID
39 | B6F9E2AA-0514-4AF4-ACA0-60F7872A4F5F
40 | PayloadVersion
41 | 1
42 |
43 |
44 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/webdriver/Browser.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.webdriver;
16 |
17 | import com.google.common.collect.ImmutableList;
18 | import com.google.devtoolsdriver.devtools.DevtoolsCommand;
19 | import com.google.devtoolsdriver.devtools.DevtoolsEvent;
20 | import com.google.devtoolsdriver.devtools.DevtoolsResult;
21 | import java.time.Duration;
22 | import java.util.function.Consumer;
23 |
24 | /**
25 | * An strategy to interact with a browser for the purpose of providing a WebDriver implementation.
26 | */
27 | public interface Browser extends AutoCloseable {
28 | /** Returns the id of the currently active page in the browser. */
29 | PageId activePage();
30 |
31 | /** Returns a list of {@link PageId} for every open page. */
32 | ImmutableList listPages() throws BrowserException;
33 |
34 | /**
35 | * Switches the browser to the specified pageId; a noop if {@code pageId} identifies the page that
36 | * is already active. Returns whether the specified page differed from the active page.
37 | */
38 | boolean switchTo(PageId pageId) throws BrowserException;
39 |
40 | /** Send a devtools command to the browser. */
41 | DevtoolsResult sendCommand(DevtoolsCommand command, Duration timeout) throws BrowserException;
42 |
43 | /** Set a listener for devtools events */
44 | void addEventListener(Consumer listener);
45 |
46 | /** Takes a screenshot in PNG format and returns it as a byte array. */
47 | byte[] takeScreenshot() throws BrowserException;
48 |
49 | /** Returns the WebDriver "browserName" capability for this browser. */
50 | String browserName();
51 |
52 | /** Returns the WebDriver "platformName" capability for this browser. */
53 | String platformName();
54 |
55 | @Override
56 | void close() throws BrowserException;
57 | }
58 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/webdriver/BrowserException.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.webdriver;
16 |
17 | /** Wrapper for all of the exceptions thrown by {@link Browser} */
18 | public class BrowserException extends Exception {
19 |
20 | public BrowserException(String message, Throwable cause) {
21 | super(message, cause);
22 | }
23 |
24 | public BrowserException(String message) {
25 | super(message);
26 | }
27 |
28 | public BrowserException(Throwable cause) {
29 | super(cause);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/webdriver/BrowserLauncher.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.webdriver;
16 |
17 | import org.openqa.selenium.remote.DesiredCapabilities;
18 |
19 | /** A tool for launching browser instances. */
20 | public interface BrowserLauncher {
21 | /** Launch a new browser instance. */
22 | Browser launch(DesiredCapabilities caps) throws BrowserException;
23 | }
24 |
--------------------------------------------------------------------------------
/java/com/google/devtoolsdriver/webdriver/PageId.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.webdriver;
16 |
17 | import com.google.auto.value.AutoValue;
18 |
19 | /** A unique id of a page in the browser. */
20 | @AutoValue
21 | public abstract class PageId {
22 | /** Creates a browser pageId. */
23 | public static PageId of(String asString) {
24 | return new AutoValue_PageId(asString);
25 | }
26 |
27 | /** PageId id. */
28 | public abstract String asString();
29 | }
30 |
--------------------------------------------------------------------------------
/javatests/com/google/devtoolsdriver/devtools/DevtoolsObjectTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.devtools;
16 |
17 | import static com.google.common.truth.Truth.assertThat;
18 |
19 | import org.junit.Test;
20 | import org.junit.runner.RunWith;
21 | import org.junit.runners.JUnit4;
22 |
23 | @RunWith(JUnit4.class)
24 | public class DevtoolsObjectTest {
25 | @Test
26 | public void testEqualsAndHashCode() {
27 | DevtoolsObject first = Runtime.callArgument().withValue("val").withObjectId("567");
28 | DevtoolsObject firstEqual = Runtime.callArgument().withValue("val").withObjectId("567");
29 | DevtoolsObject firstNotEqual = Runtime.callArgument().withValue("val").withObjectId("568");
30 |
31 | assertThat(first).isEqualTo(firstEqual);
32 | assertThat(first).isNotEqualTo(firstNotEqual);
33 |
34 | assertThat(first.hashCode()).isEqualTo(firstEqual.hashCode());
35 | assertThat(first.hashCode()).isNotEqualTo(firstNotEqual.hashCode());
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/javatests/com/google/devtoolsdriver/devtools/MessageFromJsonTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.devtools;
16 |
17 | import static com.google.common.truth.Truth.assertThat;
18 |
19 | import com.google.devtoolsdriver.util.JavaxJson;
20 | import org.junit.Test;
21 | import org.junit.runner.RunWith;
22 | import org.junit.runners.JUnit4;
23 |
24 | /* A remote message is a message created by the browser, as opposed to the devtools client */
25 | @RunWith(JUnit4.class)
26 | public class MessageFromJsonTest {
27 | @Test
28 | public void testEventFromJson() {
29 | String paramsText =
30 | "{\"scriptId\":\"69\","
31 | + "\"url\":\"https://docs.oracle.com/javaee/7/api/script.js\","
32 | + "\"startLine\":0,\"startColumn\":0,\"endLine\":31,\"endColumn\":0,"
33 | + "\"executionContextId\":3,"
34 | + "\"hash\":\"0FDEBE32DE7C1F965D844FA75116EE9B72483064\","
35 | + "\"isContentScript\":false,\"isInternalScript\":false,\"isLiveEdit\":false,"
36 | + "\"sourceMapURL\":\"\",\"hasSourceURL\":false,"
37 | + "\"deprecatedCommentWasUsed\":false}";
38 | String eventText = "{\"method\":\"Debugger.scriptParsed\", \"params\":" + paramsText + "}";
39 | DevtoolsEvent event = DevtoolsEvent.fromJson(JavaxJson.parseObject(eventText));
40 | assertThat(event.method()).isEqualTo("Debugger.scriptParsed");
41 | assertThat(event.params()).isEqualTo(JavaxJson.parseObject(paramsText));
42 | }
43 |
44 | @Test
45 | public void testEventWithNoParamsFromJson() {
46 | String eventText = "{\"method\":\"Console.messagesCleared\"}";
47 | DevtoolsEvent event = DevtoolsEvent.fromJson(JavaxJson.parseObject(eventText));
48 | assertThat(event.method()).isEqualTo("Console.messagesCleared");
49 | assertThat(event.params()).isEqualTo(JavaxJson.EMPTY_OBJECT);
50 | }
51 |
52 | @Test
53 | public void testResultFromJson() {
54 | String resultText = "{\"value\": \"Hello world!\"}";
55 | String messageText = "{\"id\": 38, \"result\": " + resultText + "}";
56 | DevtoolsResult result = DevtoolsResult.fromJson(JavaxJson.parseObject(messageText));
57 | assertThat(result.json()).isEqualTo(JavaxJson.parseObject(resultText));
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/javatests/com/google/devtoolsdriver/webdriver/JsAtomsTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.google.devtoolsdriver.webdriver;
16 |
17 | import static com.google.common.truth.Truth.assertThat;
18 |
19 | import com.google.devtoolsdriver.webdriver.JsAtoms.JsFunction;
20 | import java.util.Arrays;
21 | import org.junit.Test;
22 | import org.junit.runner.RunWith;
23 | import org.junit.runners.JUnit4;
24 |
25 | /** Unit tests for {@link JsAtoms}. */
26 | @RunWith(JUnit4.class)
27 | public class JsAtomsTest {
28 | @Test
29 | public void testAllAtomFunctions() {
30 | for (JsFunction function : JsFunction.values()) {
31 | assertThat(function.call(fakeArgs(function))).isNotNull();
32 | }
33 | }
34 |
35 | private static String[] fakeArgs(JsFunction function) {
36 | String[] fakeArgs = new String[function.numArgs()];
37 | Arrays.fill(fakeArgs, "arg");
38 | return fakeArgs;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/HostInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 |
15 | package org.uiautomation.ios;
16 |
17 | final class HostInfo {
18 | private static final String OS_NAME = System.getProperty("os.name");
19 | private static final String OS_ARCH = System.getProperty("os.arch");
20 | private static final String OS_VERSION = System.getProperty("os.version");
21 | private static final String OS_INFO = OS_NAME + " " + OS_VERSION + " (" + OS_ARCH + ')';
22 | private static final String JAVA_VERSION = System.getProperty("java.version");
23 |
24 | static String osInfo() {
25 | return OS_INFO;
26 | }
27 |
28 | static String javaVersion() {
29 | return JAVA_VERSION;
30 | }
31 |
32 | private HostInfo() {}
33 | }
34 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/IOSServerConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 |
15 | package org.uiautomation.ios;
16 |
17 | import com.beust.jcommander.Parameter;
18 |
19 | /**
20 | * Class IOSServerConfiguration Configures with the given configurable arguments: -port #
21 | * Start server in port with value . Default port = 5555.
22 | */
23 | public abstract class IOSServerConfiguration {
24 | @Parameter(description = "port the server will listen on.", names = "-port")
25 | private int port = 5555;
26 |
27 | /**
28 | * ***********************************************************************************************
29 | * ****** DO NOT DELETE THIS METHOD. IF YOU DELETE IT, JCOMMANDER CANNOT SET THE PORT FLAG! ******
30 | * ***********************************************************************************************
31 | */
32 | public void setPort(int port) {
33 | this.port = port;
34 | }
35 |
36 | public int getPort() {
37 | return port;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/IOSServerManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 | package org.uiautomation.ios;
15 |
16 | import com.google.common.collect.Sets;
17 | import com.google.devtoolsdriver.webdriver.BrowserLauncher;
18 | import java.io.File;
19 | import java.util.Set;
20 | import java.util.logging.FileHandler;
21 | import java.util.logging.LogManager;
22 | import java.util.logging.Logger;
23 | import org.openqa.selenium.WebDriverException;
24 | import org.openqa.selenium.remote.DesiredCapabilities;
25 | import org.uiautomation.ios.ServerSideSession.SessionState;
26 |
27 | /** Manages the ios-driver server sessions. */
28 | public final class IOSServerManager {
29 | private static final Logger log = Logger.getLogger(IOSServerManager.class.getName());
30 |
31 | private final Set sessions = Sets.newConcurrentHashSet();
32 | private final Set stoppedSessionIds = Sets.newConcurrentHashSet();
33 | private final BrowserLauncher launcher;
34 | private final Object lock = new Object();
35 | private State state = State.stopped;
36 |
37 | /** State of the server. */
38 | public enum State {
39 | starting,
40 | running,
41 | stopping,
42 | stopped;
43 | }
44 |
45 | IOSServerManager(BrowserLauncher launcher) {
46 | // force stop session if running for too long
47 | setState(State.starting);
48 | this.launcher = launcher;
49 |
50 | // setup logging
51 | String loggingConfigFile = System.getProperty("java.util.logging.config.file");
52 | if (loggingConfigFile != null) {
53 | if (!new File(loggingConfigFile).exists()) {
54 | System.err.println(
55 | "logging file not found: " + new File(loggingConfigFile).getAbsolutePath());
56 | loggingConfigFile = null; // to revert to builtin one
57 | }
58 | }
59 | if (loggingConfigFile == null) {
60 | // do not use builtin ios-logging.properties if -Djava.util.logging.config.file set
61 | // or if skipLoggingConfiguration is set to true
62 | try {
63 | LogManager.getLogManager()
64 | .readConfiguration(
65 | IOSServerManager.class.getResourceAsStream("/ios-logging.properties"));
66 | } catch (Exception e) {
67 | System.err.println("Cannot configure logger.");
68 | }
69 | }
70 |
71 | setState(State.running);
72 | }
73 |
74 | public void stop() {
75 | for (java.util.logging.Handler h : log.getHandlers()) {
76 | if (h instanceof FileHandler) {
77 | ((FileHandler) h).close();
78 | }
79 | }
80 | for (ServerSideSession session : sessions) {
81 | session.stop();
82 | }
83 | sessions.clear();
84 | }
85 |
86 | public ServerSideSession createSession(DesiredCapabilities cap) {
87 | if (getState() != State.running) {
88 | return null;
89 | }
90 | ServerSideSession session = new ServerSideSession(this, cap, launcher);
91 | sessions.add(session);
92 | return session;
93 | }
94 |
95 | void registerSessionHasStop(ServerSideSession session) {
96 | stoppedSessionIds.add(session.getSessionId());
97 | sessions.remove(session);
98 | }
99 |
100 | public Set getSessions() {
101 | return sessions;
102 | }
103 |
104 | public ServerSideSession getSession(String sessionId) {
105 | // first, check if the session stopped already
106 | if (stoppedSessionIds.contains(sessionId)) {
107 | throw newSessionStoppedException(sessionId);
108 | }
109 |
110 | // check if the session is in the process of stopping
111 | for (ServerSideSession session : sessions) {
112 | if (session.getSessionId().equals(sessionId)) {
113 | if (session.getSessionState() == SessionState.STOPPED) {
114 | throw newSessionStoppedException(sessionId);
115 | } else {
116 | return session;
117 | }
118 | }
119 | }
120 |
121 | throw new WebDriverException("Cannot find session " + sessionId + " on the server.");
122 | }
123 |
124 | private static WebDriverException newSessionStoppedException(String sessionId) {
125 | return new WebDriverException(String.format("Session %s stopped", sessionId));
126 | }
127 |
128 | public void stopGracefully() throws InterruptedException {
129 | // refuse further requests
130 | setState(State.stopping);
131 | // wait for requests to be processed
132 | while (getSessions().size() != 0) {
133 | Thread.sleep(250);
134 | }
135 | // stops
136 | stop();
137 | setState(State.stopped);
138 | }
139 |
140 | private void setState(State state) {
141 | synchronized (lock) {
142 | this.state = state;
143 | }
144 | }
145 |
146 | private State getState() {
147 | synchronized (lock) {
148 | return this.state;
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/SafariDriver.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.uiautomation.ios;
16 |
17 | import com.beust.jcommander.JCommander;
18 | import com.beust.jcommander.Parameter;
19 | import com.google.devtoolsdriver.safari.SafariBrowserLauncher;
20 | import com.google.iosdevicecontrol.real.RealDeviceHost;
21 | import java.nio.file.Paths;
22 | import java.util.ArrayList;
23 | import java.util.Collections;
24 | import java.util.HashSet;
25 | import java.util.List;
26 | import java.util.Set;
27 |
28 | /** Runner class for a webdriver for Safari */
29 | public final class SafariDriver {
30 | public static void main(String[] args) throws Exception {
31 | WebDriverMain.getTmpIOSFolder(); // Ensures logging directory exists.
32 | SafariIOSServerConfiguration options = new SafariIOSServerConfiguration();
33 | new JCommander(options).parse(args);
34 |
35 | SafariBrowserLauncher launcher;
36 | if (options.getIsSimulator()) {
37 | launcher = SafariBrowserLauncher.onSimulator(true);
38 | } else {
39 | RealDeviceHost.Configuration hostConf = RealDeviceHost.withDeveloperDiskImagesFromXcode();
40 | if (!options.supervisionCert.isEmpty() && !options.supervisionKey.isEmpty()) {
41 | hostConf =
42 | hostConf.withSupervisionIdentity(
43 | Paths.get(options.supervisionCert), Paths.get(options.supervisionKey));
44 | } else if (options.supervisionCert.isEmpty() != options.supervisionKey.isEmpty()) {
45 | throw new IllegalArgumentException("Supervision cert passed without key, or vice-versa");
46 | }
47 | launcher = SafariBrowserLauncher.onRealDevice(hostConf.initialize());
48 | }
49 |
50 | WebDriverMain.run(options, launcher);
51 | }
52 |
53 | private static class SafariIOSServerConfiguration extends IOSServerConfiguration {
54 | @Parameter(description = "supported real device uuid to whitelist.", names = "-uuid")
55 | private final List uuidWhitelist = new ArrayList<>();
56 |
57 | @Parameter(
58 | description = "optional set true to run against simulator, defaults to real device",
59 | names = "-simulator"
60 | )
61 | private boolean isSimulator = false;
62 |
63 | @Parameter(
64 | description = "path to the supervision certificate for real devices.",
65 | names = "-supervision_cert"
66 | )
67 | private String supervisionCert = "";
68 |
69 | @Parameter(
70 | description = "path to the supervision private key for real devices.",
71 | names = "-supervision_key"
72 | )
73 | private String supervisionKey = "";
74 |
75 | private SafariIOSServerConfiguration() {}
76 |
77 | public Set getUuidWhitelist() {
78 | return Collections.unmodifiableSet(new HashSet<>(uuidWhitelist));
79 | }
80 |
81 | boolean getIsSimulator() {
82 | return isSimulator;
83 | }
84 |
85 | public String getSupervisionCert() {
86 | return supervisionCert;
87 | }
88 |
89 | public String getSupervisionKey() {
90 | return supervisionKey;
91 | }
92 | }
93 |
94 | private SafariDriver() {}
95 | }
96 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/ServerSideSession.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 | package org.uiautomation.ios;
15 |
16 | import static com.google.common.base.Preconditions.checkNotNull;
17 | import static org.openqa.selenium.remote.CapabilityType.LOGGING_PREFS;
18 |
19 | import com.google.devtoolsdriver.webdriver.BrowserLauncher;
20 | import java.util.UUID;
21 | import java.util.logging.Level;
22 | import java.util.logging.Logger;
23 | import javax.annotation.concurrent.GuardedBy;
24 | import org.openqa.selenium.SessionNotCreatedException;
25 | import org.openqa.selenium.logging.LoggingPreferences;
26 | import org.openqa.selenium.remote.DesiredCapabilities;
27 | import org.uiautomation.ios.command.configuration.DriverConfigurationStore;
28 | import org.uiautomation.ios.drivers.RemoteIOSWebDriver;
29 | import org.uiautomation.ios.logging.IOSLogManager;
30 | import org.uiautomation.ios.servlet.CommandConfiguration;
31 | import org.uiautomation.ios.servlet.DriverConfiguration;
32 | import org.uiautomation.ios.servlet.WebDriverLikeCommand;
33 |
34 | /** A WebDriver session. */
35 | public final class ServerSideSession {
36 | /** State of a session. */
37 | enum SessionState {
38 | CREATED,
39 | RUNNING,
40 | STOPPED
41 | }
42 |
43 | private static final Logger log = Logger.getLogger(ServerSideSession.class.getName());
44 |
45 | private final String sessionId;
46 | private final IOSServerManager server;
47 | private final DesiredCapabilities capabilities;
48 | private final RemoteIOSWebDriver driver;
49 | private final DriverConfiguration configuration;
50 | private final IOSLogManager logManager;
51 |
52 | @GuardedBy("this")
53 | private SessionState state = SessionState.CREATED;
54 |
55 | ServerSideSession(
56 | IOSServerManager server, DesiredCapabilities desiredCapabilities, BrowserLauncher launcher) {
57 | sessionId = UUID.randomUUID().toString();
58 | this.server = checkNotNull(server);
59 | this.capabilities = checkNotNull(desiredCapabilities);
60 |
61 | logManager = createLogManager(desiredCapabilities);
62 | driver = new RemoteIOSWebDriver(this, launcher);
63 | configuration = new DriverConfigurationStore();
64 | }
65 |
66 | private static IOSLogManager createLogManager(DesiredCapabilities caps) {
67 | LoggingPreferences loggingPrefs = (LoggingPreferences) caps.getCapability(LOGGING_PREFS);
68 | if (loggingPrefs == null) {
69 | loggingPrefs = new LoggingPreferences();
70 | }
71 | try {
72 | return new IOSLogManager(loggingPrefs);
73 | } catch (Exception ex) {
74 | log.log(Level.SEVERE, "log manager error", ex);
75 | throw new SessionNotCreatedException("Cannot create logManager", ex);
76 | }
77 | }
78 |
79 | public String getSessionId() {
80 | return sessionId;
81 | }
82 |
83 | public synchronized SessionState getSessionState() {
84 | return state;
85 | }
86 |
87 | public DesiredCapabilities getCapabilities() {
88 | return capabilities;
89 | }
90 |
91 | public CommandConfiguration configure(WebDriverLikeCommand command) {
92 | return configuration.configure(command);
93 | }
94 |
95 | public RemoteIOSWebDriver getWebDriver() {
96 | return driver;
97 | }
98 |
99 | public synchronized void start() {
100 | driver.start();
101 | state = SessionState.RUNNING;
102 | }
103 |
104 | public synchronized void stop() {
105 | if (state != SessionState.STOPPED) {
106 | state = SessionState.STOPPED;
107 | server.registerSessionHasStop(this);
108 | driver.close();
109 | }
110 | }
111 |
112 | public IOSLogManager getLogManager() {
113 | return logManager;
114 | }
115 |
116 | @Override
117 | public String toString() {
118 | return sessionId;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/WebDriverMain.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.uiautomation.ios;
16 |
17 | import com.google.devtoolsdriver.webdriver.BrowserLauncher;
18 | import java.io.File;
19 | import java.util.logging.Level;
20 | import java.util.logging.Logger;
21 |
22 | /** Runner class for a webdriver for a generic browser */
23 | final class WebDriverMain {
24 | private static final Logger log = Logger.getLogger(WebDriverMain.class.getName());
25 |
26 | /** Start a webdriver server for the browser specified by factory. */
27 | static void run(IOSServerConfiguration options, BrowserLauncher launcher) {
28 | final IOSServer server = new IOSServer(options, launcher);
29 | Runtime.getRuntime()
30 | .addShutdownHook(
31 | new Thread() {
32 | @Override
33 | public void run() {
34 | try {
35 | server.stopGracefully();
36 | } catch (Exception e) {
37 | log.log(Level.SEVERE, "error in shutdown hook", e);
38 | }
39 | }
40 | });
41 |
42 | try {
43 | server.start();
44 | } catch (Exception e) {
45 | log.log(Level.SEVERE, "cannot start ios-driver server.", e);
46 | Runtime.getRuntime().exit(1);
47 | }
48 | }
49 |
50 | static File getTmpIOSFolder() {
51 | File f = new File(System.getProperty("java.io.tmpdir") + "/.ios-driver/");
52 | f.mkdirs();
53 | return f;
54 | }
55 |
56 | private WebDriverMain() {}
57 | }
58 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/command/AddCookieHandler.java:
--------------------------------------------------------------------------------
1 | // Copyright 2017 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package org.uiautomation.ios.command;
16 |
17 | import java.net.URL;
18 | import java.time.Instant;
19 | import java.time.OffsetDateTime;
20 | import java.time.ZoneOffset;
21 | import javax.json.JsonObject;
22 | import org.openqa.selenium.remote.Response;
23 | import org.uiautomation.ios.IOSServerManager;
24 | import org.uiautomation.ios.servlet.WebDriverLikeRequest;
25 |
26 | /**
27 | * Handles adding cookies.
28 | */
29 | public class AddCookieHandler extends CommandHandler {
30 | public AddCookieHandler(IOSServerManager driver, WebDriverLikeRequest request) {
31 | super(driver, request);
32 | }
33 |
34 | @Override
35 | public Response handle() throws Exception {
36 | JsonObject payload = getRequest().getPayload();
37 | JsonObject cookie = payload.getJsonObject("cookie");
38 |
39 | String name = cookie.getString("name", "");
40 | String value = cookie.getString("value", "");
41 | String path = cookie.getString("path", "/");
42 | String domain;
43 | if (cookie.containsKey("domain")) {
44 | domain = cookie.getString("domain");
45 | } else {
46 | URL url = new URL(getWebDriver().getCurrentUrl());
47 | domain = url.getHost();
48 | }
49 | boolean secure = cookie.getBoolean("secure", false);
50 | boolean httpOnly = cookie.getBoolean("httpOnly", false);
51 | Instant expiry =
52 | cookie.containsKey("expiry")
53 | ? Instant.ofEpochSecond(cookie.getJsonNumber("expiry").longValueExact())
54 | : OffsetDateTime.now(ZoneOffset.UTC).plusYears(20).toInstant();
55 |
56 | getWebDriver().addCookie(name, value, path, domain, secure, httpOnly, expiry);
57 | Response res = new Response();
58 | res.setSessionId(getSession().getSessionId());
59 | res.setStatus(0);
60 | return res;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/command/AlertHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 |
15 | package org.uiautomation.ios.command;
16 |
17 | import org.openqa.selenium.remote.ErrorCodes;
18 | import org.openqa.selenium.remote.Response;
19 | import org.uiautomation.ios.IOSServerManager;
20 | import org.uiautomation.ios.servlet.WebDriverLikeRequest;
21 |
22 | /**
23 | * Handles WebDriver alert commands.
24 | */
25 | public class AlertHandler extends CommandHandler {
26 | public AlertHandler(IOSServerManager driver, WebDriverLikeRequest request) {
27 | super(driver, request);
28 | }
29 |
30 | @Override
31 | public Response handle() throws Exception {
32 | // We don't have any way currently of dealing with alert dialogs with pure JS, so we respond to
33 | // every alert command with the "no alert present" error code.
34 | Response response = new Response();
35 | response.setSessionId(getSession().getSessionId());
36 | response.setStatus(ErrorCodes.NO_ALERT_PRESENT);
37 | response.setValue(new ErrorCodes().toState(ErrorCodes.NO_ALERT_PRESENT));
38 | return response;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/command/BackHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 | package org.uiautomation.ios.command;
15 |
16 | import org.json.JSONObject;
17 | import org.openqa.selenium.remote.Response;
18 | import org.uiautomation.ios.IOSServerManager;
19 | import org.uiautomation.ios.servlet.WebDriverLikeRequest;
20 |
21 | public class BackHandler extends CommandHandler {
22 | public BackHandler(IOSServerManager driver, WebDriverLikeRequest request) {
23 | super(driver, request);
24 | }
25 |
26 | @Override
27 | public Response handle() throws Exception {
28 | getWebDriver().back();
29 | getWebDriver().getContext().newContext();
30 | getWebDriver().waitForPageToLoad();
31 | Response resp = new Response();
32 | resp.setSessionId(getSession().getSessionId());
33 | resp.setStatus(0);
34 | resp.setValue(new JSONObject());
35 | return resp;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/command/ClearHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 | package org.uiautomation.ios.command;
15 |
16 | import org.json.JSONObject;
17 | import org.openqa.selenium.remote.Response;
18 | import org.uiautomation.ios.IOSServerManager;
19 | import org.uiautomation.ios.servlet.WebDriverLikeRequest;
20 | import org.uiautomation.ios.wkrdp.model.RemoteWebElement;
21 |
22 | public class ClearHandler extends CommandHandler {
23 | public ClearHandler(IOSServerManager driver, WebDriverLikeRequest request) {
24 | super(driver, request);
25 | }
26 |
27 | @Override
28 | public Response handle() throws Exception {
29 | String ref = getRequest().getVariableValue(":reference");
30 | RemoteWebElement element = getWebDriver().createElement(ref);
31 | element.clear();
32 | Response resp = new Response();
33 | resp.setSessionId(getSession().getSessionId());
34 | resp.setStatus(0);
35 | resp.setValue(new JSONObject());
36 | return resp;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/command/ClickHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 | package org.uiautomation.ios.command;
15 |
16 | import org.json.JSONObject;
17 | import org.openqa.selenium.remote.Response;
18 | import org.uiautomation.ios.IOSServerManager;
19 | import org.uiautomation.ios.servlet.WebDriverLikeRequest;
20 | import org.uiautomation.ios.wkrdp.model.RemoteWebElement;
21 |
22 | public class ClickHandler extends CommandHandler {
23 | public ClickHandler(IOSServerManager driver, WebDriverLikeRequest request) {
24 | super(driver, request);
25 | }
26 |
27 | @Override
28 | public Response handle() throws Exception {
29 | String reference = getRequest().getVariableValue(":reference");
30 | RemoteWebElement element = getWebDriver().createElement(reference);
31 | element.click();
32 |
33 | Response resp = new Response();
34 | resp.setSessionId(getSession().getSessionId());
35 | resp.setStatus(0);
36 | resp.setValue(new JSONObject());
37 | return resp;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/command/CommandHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 |
15 | package org.uiautomation.ios.command;
16 |
17 | import org.openqa.selenium.remote.Response;
18 | import org.uiautomation.ios.IOSServerManager;
19 | import org.uiautomation.ios.ServerSideSession;
20 | import org.uiautomation.ios.drivers.RemoteIOSWebDriver;
21 | import org.uiautomation.ios.servlet.CommandConfiguration;
22 | import org.uiautomation.ios.servlet.WebDriverLikeRequest;
23 |
24 | /** Handles a WebDriver request. */
25 | public abstract class CommandHandler {
26 | private final IOSServerManager server;
27 | private final ServerSideSession session;
28 | private final WebDriverLikeRequest request;
29 |
30 | CommandHandler(IOSServerManager server, WebDriverLikeRequest request) {
31 | this.server = server;
32 | this.request = request;
33 |
34 | if (request.hasVariable(":sessionId")) {
35 | session = server.getSession(request.getSession());
36 | } else {
37 | session = null;
38 | }
39 | }
40 |
41 | public abstract Response handle() throws Exception;
42 |
43 | final RemoteIOSWebDriver getWebDriver() {
44 | return getSession().getWebDriver();
45 | }
46 |
47 | final ServerSideSession getSession() {
48 | return session;
49 | }
50 |
51 | final IOSServerManager getServer() {
52 | return server;
53 | }
54 |
55 | final WebDriverLikeRequest getRequest() {
56 | return request;
57 | }
58 |
59 | final void waitForPageToLoad() {
60 | getWebDriver().waitForPageToLoad();
61 | }
62 |
63 | @SuppressWarnings("unchecked")
64 | final T getConf(String key, T defaultValue) {
65 | CommandConfiguration conf = getSession().configure(getRequest().getGenericCommand());
66 | T res = (T) conf.get(key);
67 | return res != null ? res : defaultValue;
68 | }
69 |
70 | final Response createResponse(Object value) {
71 | Response r = new Response();
72 | r.setSessionId(getSession().getSessionId());
73 | r.setStatus(0);
74 | r.setValue(value);
75 | return r;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/command/CssPropertyHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 | package org.uiautomation.ios.command;
15 |
16 | import org.openqa.selenium.remote.Response;
17 | import org.uiautomation.ios.IOSServerManager;
18 | import org.uiautomation.ios.servlet.WebDriverLikeRequest;
19 | import org.uiautomation.ios.wkrdp.model.RemoteWebElement;
20 |
21 | public class CssPropertyHandler extends CommandHandler {
22 | public CssPropertyHandler(IOSServerManager driver, WebDriverLikeRequest request) {
23 | super(driver, request);
24 | }
25 |
26 | @Override
27 | public Response handle() throws Exception {
28 | String propertyName = getRequest().getVariableValue(":name");
29 | String ref = getRequest().getVariableValue(":reference");
30 | RemoteWebElement element = getWebDriver().createElement(ref);
31 | Object value = element.getCssValue(propertyName);
32 | Response res = new Response();
33 | res.setSessionId(getSession().getSessionId());
34 | res.setStatus(0);
35 | res.setValue(value);
36 | return res;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/command/DeleteAllCookiesHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 |
15 | package org.uiautomation.ios.command;
16 |
17 | import org.json.JSONObject;
18 | import org.openqa.selenium.Cookie;
19 | import org.openqa.selenium.remote.Response;
20 | import org.uiautomation.ios.IOSServerManager;
21 | import org.uiautomation.ios.servlet.WebDriverLikeRequest;
22 | import java.util.List;
23 |
24 | public class DeleteAllCookiesHandler extends CommandHandler {
25 | public DeleteAllCookiesHandler(IOSServerManager driver, WebDriverLikeRequest request) {
26 | super(driver, request);
27 | }
28 |
29 | @Override
30 | public Response handle() throws Exception {
31 | String url = getWebDriver().getCurrentUrl();
32 | List cookies = getWebDriver().getCookies();
33 | for (Cookie c : cookies) {
34 | getWebDriver().deleteCookie(c.getName(), url);
35 | }
36 |
37 | Response res = new Response();
38 | res.setSessionId(getSession().getSessionId());
39 | res.setStatus(0);
40 | res.setValue(new JSONObject());
41 | return res;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/command/DeleteCookieByNameHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 |
15 | package org.uiautomation.ios.command;
16 |
17 | import org.json.JSONObject;
18 | import org.openqa.selenium.remote.Response;
19 | import org.uiautomation.ios.IOSServerManager;
20 | import org.uiautomation.ios.servlet.WebDriverLikeRequest;
21 |
22 | public class DeleteCookieByNameHandler extends CommandHandler {
23 | public DeleteCookieByNameHandler(IOSServerManager driver, WebDriverLikeRequest request) {
24 | super(driver, request);
25 | }
26 |
27 | @Override
28 | public Response handle() throws Exception {
29 | String name = getRequest().getVariableValue(":name");
30 | String url = getWebDriver().getCurrentUrl();
31 | getWebDriver().deleteCookie(name, url);
32 |
33 | Response res = new Response();
34 | res.setSessionId(getSession().getSessionId());
35 | res.setStatus(0);
36 | res.setValue(new JSONObject());
37 | return res;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/third_party/ios_driver/org/uiautomation/ios/command/ExecuteAsyncScriptHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 | package org.uiautomation.ios.command;
15 |
16 | import java.util.ArrayList;
17 | import java.util.Collection;
18 | import java.util.List;
19 | import javax.json.JsonArray;
20 | import org.json.JSONObject;
21 | import org.openqa.selenium.remote.Response;
22 | import org.uiautomation.ios.IOSServerManager;
23 | import org.uiautomation.ios.servlet.WebDriverLikeRequest;
24 | import org.uiautomation.ios.wkrdp.model.RemoteObject;
25 | import org.uiautomation.ios.wkrdp.model.RemoteWebElement;
26 |
27 | public class ExecuteAsyncScriptHandler extends CommandHandler {
28 | public ExecuteAsyncScriptHandler(IOSServerManager driver, WebDriverLikeRequest request) {
29 | super(driver, request);
30 | }
31 |
32 | @Override
33 | public Response handle() throws Exception {
34 | String script = getRequest().getPayload().getString("script");
35 | JsonArray args = getRequest().getPayload().getJsonArray("args");
36 | Object res = getWebDriver().executeAsyncScript(script, args);
37 |
38 | Response resp = new Response();
39 | resp.setSessionId(getSession().getSessionId());
40 | resp.setStatus(0);
41 |
42 | if (res instanceof RemoteObject) {
43 | RemoteObject ro = (RemoteObject) res;
44 | RemoteWebElement rwe = ro.getWebElement();
45 | JSONObject jo = new JSONObject().put("ELEMENT", rwe.getReference());
46 | resp.setValue(jo);
47 | } else if (res instanceof Integer) {
48 | resp.setValue(res);
49 | } else if (res instanceof Boolean) {
50 | resp.setValue(res);
51 | } else if (res instanceof Collection) {
52 | List