Remove deprecated GetInteger methods in chromedriver

Removes uses of the deprecated DictionaryValue::GetInteger method in
chromedriver code. In *most* cases, this requires converting the int
that was previously used to an optional<int> and using that value
instead of the return value from the GetInteger method for any logic. A
few places, particularly in unit tests, make use of .value_or when there
is a clear "incorrect" value that can be assigned, or when the number is
already being validated.

A few places in window_commands that did not check the return value
either now add a check or force a ".value" call to trigger a CHECK, to
more closely match what seems to be the intended behavior.

This is a refactor with no intended behavior change (though a couple of
places ended up with simpler conditional checks).

Bug: 1187034
Change-Id: I555b6c57d07a16feaf6ce9c8eece2a8c6e792415
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3360229
Auto-Submit: Alexander Cooper <alcooper@chromium.org>
Reviewed-by: Mathias Bynens <mathias@chromium.org>
Commit-Queue: Alexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/main@{#954616}
diff --git a/chrome/test/chromedriver/capabilities.cc b/chrome/test/chromedriver/capabilities.cc
index 5348f9b..83a6faf2 100644
--- a/chrome/test/chromedriver/capabilities.cc
+++ b/chrome/test/chromedriver/capabilities.cc
@@ -158,15 +158,18 @@
     if (!mobile_emulation->GetDictionary("deviceMetrics", &metrics))
       return Status(kInvalidArgument, "'deviceMetrics' must be a dictionary");
 
-    int width = 0;
-    int height = 0;
-
-    if (metrics->FindKey("width") && !metrics->GetInteger("width", &width))
+    const base::Value* width_value = metrics->FindKey("width");
+    if (width_value && !width_value->is_int())
       return Status(kInvalidArgument, "'width' must be an integer");
 
-    if (metrics->FindKey("height") && !metrics->GetInteger("height", &height))
+    int width = width_value ? width_value->GetInt() : 0;
+
+    const base::Value* height_value = metrics->FindKey("height");
+    if (height_value && !height_value->is_int())
       return Status(kInvalidArgument, "'height' must be an integer");
 
+    int height = height_value ? height_value->GetInt() : 0;
+
     absl::optional<double> maybe_device_scale_factor =
         metrics->FindDoubleKey("pixelRatio");
     if (metrics->FindKey("pixelRatio") &&
@@ -332,11 +335,7 @@
       }
       std::string value = option_value->GetString();
       if (proxy_servers_options[i][0] == kSocksProxy) {
-        int socksVersion;
-        if (!proxy_dict->GetInteger("socksVersion", &socksVersion))
-          return Status(
-              kInvalidArgument,
-              "Specifying 'socksProxy' requires an integer for 'socksVersion'");
+        int socksVersion = proxy_dict->FindIntKey("socksVersion").value_or(-1);
         if (socksVersion < 0 || socksVersion > 255)
           return Status(
               kInvalidArgument,
diff --git a/chrome/test/chromedriver/chrome/console_logger.cc b/chrome/test/chromedriver/chrome/console_logger.cc
index 83fbd76..35f38e8 100644
--- a/chrome/test/chromedriver/chrome/console_logger.cc
+++ b/chrome/test/chromedriver/chrome/console_logger.cc
@@ -79,8 +79,8 @@
     origin = source;
 
   std::string line_number;
-  int line = -1;
-  if (entry->GetInteger("lineNumber", &line)) {
+  int line = entry->FindIntKey("lineNumber").value_or(-1);
+  if (line >= 0) {
     line_number = base::StringPrintf("%d", line);
   } else {
     // No line number, but print anyway, just to maintain the number of fields
@@ -124,11 +124,11 @@
         return Status(kUnknownError, "missing or invalid url");
       if (!url.empty())
         origin = url;
-      int line = -1;
-      if (!call_frame.GetInteger("lineNumber", &line))
+      int line = call_frame.FindIntKey("lineNumber").value_or(-1);
+      if (line < 0)
         return Status(kUnknownError, "missing or invalid lineNumber");
-      int column = -1;
-      if (!call_frame.GetInteger("columnNumber", &column))
+      int column = call_frame.FindIntKey("columnNumber").value_or(-1);
+      if (column < 0)
         return Status(kUnknownError, "missing or invalid columnNumber");
       line_column = base::StringPrintf("%d:%d", line, column);
     }
@@ -187,11 +187,11 @@
   if (!exception_details->GetString("url", &origin))
     origin = "javascript";
 
-  int line = -1;
-  if (!exception_details->GetInteger("lineNumber", &line))
+  int line = exception_details->FindIntKey("lineNumber").value_or(-1);
+  if (line < 0)
     return Status(kUnknownError, "missing or invalid lineNumber");
-  int column = -1;
-  if (!exception_details->GetInteger("columnNumber", &column))
+  int column = exception_details->FindIntKey("columnNumber").value_or(-1);
+  if (column < 0)
     return Status(kUnknownError, "missing or invalid columnNumber");
   std::string line_column = base::StringPrintf("%d:%d", line, column);
 
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.cc b/chrome/test/chromedriver/chrome/devtools_client_impl.cc
index cccf5758..056c993e 100644
--- a/chrome/test/chromedriver/chrome/devtools_client_impl.cc
+++ b/chrome/test/chromedriver/chrome/devtools_client_impl.cc
@@ -667,8 +667,9 @@
   session_id->clear();
   if (message_dict->HasKey("sessionId"))
     message_dict->GetString("sessionId", session_id);
-  int id;
-  if (!message_dict->HasKey("id")) {
+
+  base::Value* id_value = message_dict->FindKey("id");
+  if (!id_value) {
     std::string method;
     if (!message_dict->GetString("method", &method))
       return false;
@@ -682,11 +683,11 @@
     else
       event->params = std::make_unique<base::DictionaryValue>();
     return true;
-  } else if (message_dict->GetInteger("id", &id)) {
+  } else if (id_value->is_int()) {
     base::DictionaryValue* unscoped_error = nullptr;
     base::DictionaryValue* unscoped_result = nullptr;
     *type = kCommandResponseMessageType;
-    command_response->id = id;
+    command_response->id = id_value->GetInt();
     // As per Chromium issue 392577, DevTools does not necessarily return a
     // "result" dictionary for every valid response. In particular,
     // Tracing.start and Tracing.end command responses do not contain one.
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl_unittest.cc b/chrome/test/chromedriver/chrome/devtools_client_impl_unittest.cc
index e9b9667..4b6317a 100644
--- a/chrome/test/chromedriver/chrome/devtools_client_impl_unittest.cc
+++ b/chrome/test/chromedriver/chrome/devtools_client_impl_unittest.cc
@@ -58,8 +58,7 @@
       EXPECT_TRUE(dict->GetDictionary("params", &params));
       if (!params)
         return false;
-      int param = -1;
-      EXPECT_TRUE(params->GetInteger("param", &param));
+      int param = params->FindIntKey("param").value_or(-1);
       EXPECT_EQ(1, param);
     }
     return true;
@@ -78,7 +77,11 @@
     dict->reset(temp_dict->DeepCopy());
     if (!dict)
       return false;
-    EXPECT_TRUE((*dict)->GetInteger("id", &id_));
+    absl::optional<int> maybe_id = (*dict)->FindIntKey("id");
+    EXPECT_TRUE(maybe_id);
+    if (!maybe_id)
+      return false;
+    id_ = *maybe_id;
     EXPECT_TRUE((*dict)->GetString("method", method));
     // Because ConnectIfNecessary is not waiting for the response, Send can
     // set connect_complete to true
@@ -605,8 +608,7 @@
       0, &session_id, &type, &event, &response));
   ASSERT_EQ(internal::kEventMessageType, type);
   ASSERT_STREQ("method", event.method.c_str());
-  int key;
-  ASSERT_TRUE(event.params->GetInteger("key", &key));
+  int key = event.params->FindIntKey("key").value_or(-1);
   ASSERT_EQ(100, key);
   EXPECT_EQ("AB3A", session_id);
 }
@@ -650,8 +652,7 @@
   ASSERT_EQ(internal::kCommandResponseMessageType, type);
   ASSERT_EQ(1, response.id);
   ASSERT_FALSE(response.error.length());
-  int key;
-  ASSERT_TRUE(response.result->GetInteger("key", &key));
+  int key = response.result->FindIntKey("key").value_or(-1);
   ASSERT_EQ(1, key);
 }
 
@@ -1262,7 +1263,11 @@
     EXPECT_TRUE(value->GetAsDictionary(&dict));
     if (!dict)
       return false;
-    EXPECT_TRUE(dict->GetInteger("id", &id_));
+    absl::optional<int> maybe_id = dict->FindIntKey("id");
+    EXPECT_TRUE(maybe_id);
+    if (!maybe_id)
+      return false;
+    id_ = *maybe_id;
     std::string method;
     EXPECT_TRUE(dict->GetString("method", &method));
     EXPECT_STREQ("method", method.c_str());
diff --git a/chrome/test/chromedriver/chrome/dom_tracker.cc b/chrome/test/chromedriver/chrome/dom_tracker.cc
index bcacb8f..ff82daa 100644
--- a/chrome/test/chromedriver/chrome/dom_tracker.cc
+++ b/chrome/test/chromedriver/chrome/dom_tracker.cc
@@ -110,12 +110,12 @@
   const base::DictionaryValue* dict;
   if (!node.GetAsDictionary(&dict))
     return false;
-  int node_id;
-  if (!dict->GetInteger("nodeId", &node_id))
+  absl::optional<int> node_id = dict->FindIntKey("nodeId");
+  if (!node_id)
     return false;
   std::string frame_id;
   if (dict->GetString("frameId", &frame_id)) {
-    node_to_frame_map_.insert(std::make_pair(node_id, frame_id));
+    node_to_frame_map_.insert(std::make_pair(*node_id, frame_id));
   }
 
   if (const base::Value* children = dict->FindKey("children"))
diff --git a/chrome/test/chromedriver/chrome/frame_tracker.cc b/chrome/test/chromedriver/chrome/frame_tracker.cc
index 01919c5..d65745e 100644
--- a/chrome/test/chromedriver/chrome/frame_tracker.cc
+++ b/chrome/test/chromedriver/chrome/frame_tracker.cc
@@ -101,11 +101,11 @@
                     "Runtime.executionContextCreated missing dict 'context'");
     }
 
-    int context_id;
     std::string frame_id;
     bool is_default = true;
 
-    if (!context->GetInteger("id", &context_id)) {
+    absl::optional<int> context_id = context->FindIntKey("id");
+    if (!context_id) {
       std::string json;
       base::JSONWriter::Write(*context, &json);
       return Status(kUnknownError, method + " has invalid 'context': " + json);
@@ -128,13 +128,14 @@
     }
 
     if (is_default && !frame_id.empty())
-      frame_to_context_map_[frame_id] = context_id;
+      frame_to_context_map_[frame_id] = *context_id;
   } else if (method == "Runtime.executionContextDestroyed") {
-    int execution_context_id;
-    if (!params.GetInteger("executionContextId", &execution_context_id))
+    absl::optional<int> execution_context_id =
+        params.FindIntKey("executionContextId");
+    if (!execution_context_id)
       return Status(kUnknownError, method + " missing 'executionContextId'");
     for (auto entry : frame_to_context_map_) {
-      if (entry.second == execution_context_id) {
+      if (entry.second == *execution_context_id) {
         frame_to_context_map_.erase(entry.first);
         break;
       }
diff --git a/chrome/test/chromedriver/chrome/mobile_device.cc b/chrome/test/chromedriver/chrome/mobile_device.cc
index 4437206..46a1ece 100644
--- a/chrome/test/chromedriver/chrome/mobile_device.cc
+++ b/chrome/test/chromedriver/chrome/mobile_device.cc
@@ -40,13 +40,13 @@
     return Status(kUnknownError,
                   "malformed device user agent: should be a string");
   }
-  int width = 0;
-  int height = 0;
-  if (!device->GetInteger("width",  &width)) {
+  absl::optional<int> maybe_width = device->FindIntKey("width");
+  absl::optional<int> maybe_height = device->FindIntKey("height");
+  if (!maybe_width) {
     return Status(kUnknownError,
                   "malformed device width: should be an integer");
   }
-  if (!device->GetInteger("height", &height)) {
+  if (!maybe_height) {
     return Status(kUnknownError,
                   "malformed device height: should be an integer");
   }
@@ -66,7 +66,7 @@
     return Status(kUnknownError, "malformed mobile: should be a bool");
   }
   tmp_mobile_device->device_metrics = std::make_unique<DeviceMetrics>(
-      width, height, *maybe_device_scale_factor, *touch, *mobile);
+      *maybe_width, *maybe_height, *maybe_device_scale_factor, *touch, *mobile);
 
   *mobile_device = std::move(tmp_mobile_device);
   return Status(kOk);
diff --git a/chrome/test/chromedriver/chrome/mobile_emulation_override_manager_unittest.cc b/chrome/test/chromedriver/chrome/mobile_emulation_override_manager_unittest.cc
index 4f1c8d36..ea598de 100644
--- a/chrome/test/chromedriver/chrome/mobile_emulation_override_manager_unittest.cc
+++ b/chrome/test/chromedriver/chrome/mobile_emulation_override_manager_unittest.cc
@@ -17,17 +17,19 @@
 void AssertDeviceMetricsCommand(const Command& command,
                                 const DeviceMetrics& device_metrics) {
   ASSERT_EQ("Page.setDeviceMetricsOverride", command.method);
-  int width, height;
-  ASSERT_TRUE(command.params.GetInteger("width", &width));
-  ASSERT_TRUE(command.params.GetInteger("height", &height));
+  absl::optional<int> width = command.params.FindIntKey("width");
+
+  absl::optional<int> height = command.params.FindIntKey("height");
+  ASSERT_TRUE(width);
+  ASSERT_TRUE(height);
   ASSERT_THAT(command.params.FindBoolKey("mobile"),
               Optional(device_metrics.mobile));
   ASSERT_THAT(command.params.FindBoolKey("fitWindow"),
               Optional(device_metrics.fit_window));
   ASSERT_THAT(command.params.FindBoolKey("textAutosizing"),
               Optional(device_metrics.text_autosizing));
-  ASSERT_EQ(device_metrics.width, width);
-  ASSERT_EQ(device_metrics.height, height);
+  ASSERT_EQ(device_metrics.width, *width);
+  ASSERT_EQ(device_metrics.height, *height);
   ASSERT_EQ(device_metrics.device_scale_factor,
             command.params.FindDoubleKey("deviceScaleFactor").value());
   ASSERT_EQ(device_metrics.font_scale_factor,
diff --git a/chrome/test/chromedriver/chrome/web_view_impl.cc b/chrome/test/chromedriver/chrome/web_view_impl.cc
index 76e1dd19..098fba74 100644
--- a/chrome/test/chromedriver/chrome/web_view_impl.cc
+++ b/chrome/test/chromedriver/chrome/web_view_impl.cc
@@ -283,14 +283,14 @@
                                                    params, &result);
   if (status.IsError())
     return status;
-  int current_index = 0;
-  if (!result.GetInteger("currentIndex", &current_index))
+  absl::optional<int> current_index = result.FindIntKey("currentIndex");
+  if (!current_index)
     return Status(kUnknownError, "navigation history missing currentIndex");
   base::ListValue* entries = nullptr;
   if (!result.GetList("entries", &entries))
     return Status(kUnknownError, "navigation history missing entries");
   base::DictionaryValue* entry = nullptr;
-  if (!entries->GetDictionary(current_index, &entry))
+  if (!entries->GetDictionary(*current_index, &entry))
     return Status(kUnknownError, "navigation history missing entry");
   if (!entry->GetString("url", url))
     return Status(kUnknownError, "navigation history entry is missing url");
@@ -379,8 +379,8 @@
       return status;
   }
 
-  int current_index;
-  if (!result.GetInteger("currentIndex", &current_index))
+  absl::optional<int> current_index = result.FindIntKey("currentIndex");
+  if (!current_index)
     return Status(kUnknownError, "DevTools didn't return currentIndex");
 
   base::ListValue* entries;
@@ -388,17 +388,17 @@
     return Status(kUnknownError, "DevTools didn't return entries");
 
   base::DictionaryValue* entry;
-  if (!entries->GetDictionary(current_index + delta, &entry)) {
+  if (!entries->GetDictionary(*current_index + delta, &entry)) {
     // The WebDriver spec says that if there are no pages left in the browser's
     // history (i.e. |current_index + delta| is out of range), then we must not
     // navigate anywhere.
     return Status(kOk);
   }
 
-  int entry_id;
-  if (!entry->GetInteger("id", &entry_id))
+  absl::optional<int> entry_id = entry->FindIntKey("id");
+  if (!entry_id)
     return Status(kUnknownError, "history entry does not have an id");
-  params.SetInteger("entryId", entry_id);
+  params.SetInteger("entryId", *entry_id);
 
   return client_->SendCommandWithTimeout("Page.navigateToHistoryEntry", params,
                                          timeout);
@@ -1036,7 +1036,7 @@
     }
 
     // figure out how many files there are
-    int numberOfFiles = 0;
+    absl::optional<int> numberOfFiles = 0;
     {
       base::DictionaryValue cmd_result;
       base::DictionaryValue params;
@@ -1047,12 +1047,13 @@
                                                 params, &cmd_result);
       if (status.IsError())
         return status;
-      if (!cmd_result.GetInteger("result.value", &numberOfFiles))
+      numberOfFiles = cmd_result.FindIntPath("result.value");
+      if (!numberOfFiles)
         return Status(kUnknownError, "DevTools didn't return value");
     }
 
     // Ask for each Runtime.RemoteObject and add them to the list
-    for (int i = 0; i < numberOfFiles; i++) {
+    for (int i = 0; i < *numberOfFiles; i++) {
       std::string fileObjectId;
       {
         base::DictionaryValue cmd_result;
@@ -1237,13 +1238,13 @@
     base::DictionaryValue* result_info = NULL;
     if (!query_value->GetAsDictionary(&result_info))
       return Status(kUnknownError, "async result info is not a dictionary");
-    int status_code;
-    if (!result_info->GetInteger("status", &status_code))
+    absl::optional<int> status_code = result_info->FindIntKey("status");
+    if (!status_code)
       return Status(kUnknownError, "async result info has no int 'status'");
-    if (status_code != kOk) {
+    if (*status_code != kOk) {
       std::string message;
       result_info->GetString("value", &message);
-      return Status(static_cast<StatusCode>(status_code), message);
+      return Status(static_cast<StatusCode>(*status_code), message);
     }
 
     if (base::Value* value = result_info->FindKey("value")) {
@@ -1468,15 +1469,15 @@
   const base::DictionaryValue* dict;
   if (!temp_result.GetAsDictionary(&dict))
     return Status(kUnknownError, "call function result must be a dictionary");
-  int status_code;
-  if (!dict->GetInteger("status", &status_code)) {
+  absl::optional<int> status_code = dict->FindIntKey("status");
+  if (!status_code) {
     return Status(kUnknownError,
                   "call function result missing int 'status'");
   }
-  if (status_code != kOk) {
+  if (*status_code != kOk) {
     std::string message;
     dict->GetString("value", &message);
-    return Status(static_cast<StatusCode>(status_code), message);
+    return Status(static_cast<StatusCode>(*status_code), message);
   }
   const base::Value* unscoped_value = dict->FindKey("value");
   if (unscoped_value == nullptr) {
@@ -1538,8 +1539,15 @@
   if (status.IsError())
     return status;
 
-  if (!cmd_result.GetInteger("nodeId", node_id))
+  absl::optional<int> maybe_node_id = cmd_result.FindIntKey("nodeId");
+
+  if (!maybe_node_id)
     return Status(kUnknownError, "DOM.requestNode missing int 'nodeId'");
+
+  // Note that this emulates the previous Deprecated GetInteger behavior, but
+  // should likely be changed.
+  if (node_id)
+    *node_id = *maybe_node_id;
   *found_node = true;
   return Status(kOk);
 }
diff --git a/chrome/test/chromedriver/element_commands.cc b/chrome/test/chromedriver/element_commands.cc
index 62a52bd..f9305c1 100644
--- a/chrome/test/chromedriver/element_commands.cc
+++ b/chrome/test/chromedriver/element_commands.cc
@@ -391,12 +391,18 @@
     return status;
 
   int xoffset, yoffset, speed;
-  if (!params.GetInteger("xoffset", &xoffset))
+
+  absl::optional<int> maybe_xoffset = params.FindIntKey("xoffset");
+  if (!maybe_xoffset)
     return Status(kInvalidArgument, "'xoffset' must be an integer");
-  if (!params.GetInteger("yoffset", &yoffset))
+  xoffset = *maybe_xoffset;
+
+  absl::optional<int> maybe_yoffset = params.FindIntKey("yoffset");
+  if (!maybe_yoffset)
     return Status(kInvalidArgument, "'yoffset' must be an integer");
-  if (!params.GetInteger("speed", &speed))
-    return Status(kInvalidArgument, "'speed' must be an integer");
+  yoffset = *maybe_yoffset;
+
+  speed = params.FindIntKey("speed").value_or(-1);
   if (speed < 1)
     return Status(kInvalidArgument, "'speed' must be a positive integer");
 
diff --git a/chrome/test/chromedriver/key_converter.cc b/chrome/test/chromedriver/key_converter.cc
index 17a4ade..8833ca9 100644
--- a/chrome/test/chromedriver/key_converter.cc
+++ b/chrome/test/chromedriver/key_converter.cc
@@ -668,10 +668,12 @@
     }
   }
 
-  int modifiers;
-  if (!input_state->GetInteger("modifiers", &modifiers))
+  absl::optional<int> maybe_modifiers = input_state->FindIntKey("modifiers");
+  if (!maybe_modifiers)
     return Status(kUnknownError, "missing 'modifiers'");
 
+  int modifiers = *maybe_modifiers;
+
   bool is_modifier_key = false;
   bool is_special_key = false;
   bool should_skip = false;
diff --git a/chrome/test/chromedriver/net/sync_websocket_impl.cc b/chrome/test/chromedriver/net/sync_websocket_impl.cc
index 7553701..b37cb39 100644
--- a/chrome/test/chromedriver/net/sync_websocket_impl.cc
+++ b/chrome/test/chromedriver/net/sync_websocket_impl.cc
@@ -141,10 +141,10 @@
     *send_to_chromedriver = true;
     return;
   }
-  int id;
+  base::Value* id = message_dict->FindKey("id");
   *send_to_chromedriver =
-      !message_dict->HasKey("id") || (message_dict->GetInteger("id", &id) &&
-                                      CommandId::IsChromeDriverCommandId(id));
+      id == nullptr ||
+      (id->is_int() && CommandId::IsChromeDriverCommandId(id->GetInt()));
 }
 
 void SyncWebSocketImpl::Core::OnClose() {
diff --git a/chrome/test/chromedriver/net/sync_websocket_impl_unittest.cc b/chrome/test/chromedriver/net/sync_websocket_impl_unittest.cc
index 4543162..94872e7 100644
--- a/chrome/test/chromedriver/net/sync_websocket_impl_unittest.cc
+++ b/chrome/test/chromedriver/net/sync_websocket_impl_unittest.cc
@@ -96,9 +96,8 @@
   ASSERT_TRUE(message_value->GetAsDictionary(&message_dict));
   std::string method;
   ASSERT_TRUE(message_dict->GetString("method", &method));
-  int id;
-  ASSERT_TRUE(message_dict->GetInteger("id", &id));
   ASSERT_EQ(method, "Page.enable");
+  int id = message_dict->FindIntKey("id").value_or(-1);
   ASSERT_EQ(id, 1);
 }
 
diff --git a/chrome/test/chromedriver/performance_logger_unittest.cc b/chrome/test/chromedriver/performance_logger_unittest.cc
index 1cf190f..a742284 100644
--- a/chrome/test/chromedriver/performance_logger_unittest.cc
+++ b/chrome/test/chromedriver/performance_logger_unittest.cc
@@ -304,9 +304,8 @@
   EXPECT_EQ("benchmark", categories->GetList()[0].GetString());
   ASSERT_TRUE(categories->GetList()[1].is_string());
   EXPECT_EQ("blink.console", categories->GetList()[1].GetString());
-  int expected_interval = 0;
-  EXPECT_TRUE(cmd->params->GetInteger("bufferUsageReportingInterval",
-                                      &expected_interval));
+  int expected_interval =
+      cmd->params->FindIntKey("bufferUsageReportingInterval").value_or(-1);
   EXPECT_GT(expected_interval, 0);
   ASSERT_FALSE(client.PopSentCommand(&cmd));
 
diff --git a/chrome/test/chromedriver/session_commands_unittest.cc b/chrome/test/chromedriver/session_commands_unittest.cc
index 3e2a245..6684dc1b 100644
--- a/chrome/test/chromedriver/session_commands_unittest.cc
+++ b/chrome/test/chromedriver/session_commands_unittest.cc
@@ -35,14 +35,11 @@
   base::DictionaryValue* response;
   ASSERT_TRUE(value->GetAsDictionary(&response));
 
-  int script;
-  ASSERT_TRUE(response->GetInteger("script", &script));
+  int script = response->FindIntKey("script").value_or(-1);
   ASSERT_EQ(script, 30000);
-  int page_load;
-  ASSERT_TRUE(response->GetInteger("pageLoad", &page_load));
+  int page_load = response->FindIntKey("pageLoad").value_or(-1);
   ASSERT_EQ(page_load, 300000);
-  int implicit;
-  ASSERT_TRUE(response->GetInteger("implicit", &implicit));
+  int implicit = response->FindIntKey("implicit").value_or(-1);
   ASSERT_EQ(implicit, 0);
 }
 
diff --git a/chrome/test/chromedriver/window_commands.cc b/chrome/test/chromedriver/window_commands.cc
index d8592ada..37d53cbd 100644
--- a/chrome/test/chromedriver/window_commands.cc
+++ b/chrome/test/chromedriver/window_commands.cc
@@ -71,10 +71,9 @@
 
 Status GetMouseButton(const base::DictionaryValue& params,
                       MouseButton* button) {
-  int button_num;
-  if (!params.GetInteger("button", &button_num)) {
-    button_num = 0;  // Default to left mouse button.
-  } else if (button_num < 0 || button_num > 2) {
+  // Default to left mouse button.
+  int button_num = params.FindIntKey("button").value_or(0);
+  if (button_num < 0 || button_num > 2) {
     return Status(kInvalidArgument,
                   base::StringPrintf("invalid button: %d", button_num));
   }
@@ -335,11 +334,10 @@
     return status;
   base::DictionaryValue* view_attrib;
   value->GetAsDictionary(&view_attrib);
-  int view_x, view_y, view_width, view_height;
-  view_attrib->GetInteger("view_x", &view_x);
-  view_attrib->GetInteger("view_y", &view_y);
-  view_attrib->GetInteger("view_width", &view_width);
-  view_attrib->GetInteger("view_height", &view_height);
+  int view_x = view_attrib->FindIntKey("view_x").value_or(0);
+  int view_y = view_attrib->FindIntKey("view_y").value_or(0);
+  int view_width = view_attrib->FindIntKey("view_width").value_or(0);
+  int view_height = view_attrib->FindIntKey("view_height").value_or(0);
   *offset_x = x - view_x;
   *offset_y = y - view_y;
   if (*offset_x < 0 || *offset_x >= view_width || *offset_y < 0 ||
@@ -351,15 +349,16 @@
 Status ExecuteTouchEvent(
     Session* session, WebView* web_view, TouchEventType type,
     const base::DictionaryValue& params) {
-  int x, y;
-  if (!params.GetInteger("x", &x))
+  absl::optional<int> x = params.FindIntKey("x");
+  absl::optional<int> y = params.FindIntKey("y");
+  if (!x)
     return Status(kInvalidArgument, "'x' must be an integer");
-  if (!params.GetInteger("y", &y))
+  if (!y)
     return Status(kInvalidArgument, "'y' must be an integer");
-  int relative_x = x;
-  int relative_y = y;
-  Status status = ScrollCoordinateInToView(
-      session, web_view, x, y, &relative_x, &relative_y);
+  int relative_x = *x;
+  int relative_y = *y;
+  Status status = ScrollCoordinateInToView(session, web_view, *x, *y,
+                                           &relative_x, &relative_y);
   if (!status.IsOk())
     return status;
   std::vector<TouchEvent> events;
@@ -386,8 +385,14 @@
     return status;
   base::DictionaryValue* view_attrib;
   value->GetAsDictionary(&view_attrib);
-  view_attrib->GetInteger("view_width", innerWidth);
-  view_attrib->GetInteger("view_height", innerHeight);
+  absl::optional<int> maybe_inner_width = view_attrib->FindIntKey("view_width");
+  if (innerWidth && maybe_inner_width)
+    *innerWidth = *maybe_inner_width;
+
+  absl::optional<int> maybe_inner_height =
+      view_attrib->FindIntKey("view_height");
+  if (innerHeight && maybe_inner_height)
+    *innerHeight = *maybe_inner_height;
   return Status(kOk);
 }
 
@@ -1077,17 +1082,18 @@
                           Timeout* timeout) {
   std::string element_id;
   bool has_element = params.GetString("element", &element_id);
-  int x_offset = 0;
-  int y_offset = 0;
-  bool has_offset = params.GetInteger("xoffset", &x_offset) &&
-      params.GetInteger("yoffset", &y_offset);
+  absl::optional<int> x_offset = params.FindIntKey("xoffset");
+  absl::optional<int> y_offset = params.FindIntKey("yoffset");
+  bool has_offset = x_offset.has_value() && y_offset.has_value();
   if (!has_element && !has_offset)
     return Status(kInvalidArgument,
                   "at least an element or offset should be set");
 
   WebPoint location;
   if (has_element) {
-    WebPoint offset(x_offset, y_offset);
+    WebPoint offset;
+    if (has_offset)
+      offset.Offset(*x_offset, *y_offset);
     Status status = ScrollElementIntoView(session, web_view, element_id,
         has_offset ? &offset : nullptr, &location);
     if (status.IsError())
@@ -1095,7 +1101,7 @@
   } else {
     location = session->mouse_position;
     if (has_offset)
-      location.Offset(x_offset, y_offset);
+      location.Offset(*x_offset, *y_offset);
   }
 
   std::vector<MouseEvent> events;
@@ -1234,14 +1240,14 @@
     if (status.IsError())
       return status;
   }
-  int xoffset;
-  if (!params.GetInteger("xoffset", &xoffset))
+  absl::optional<int> xoffset = params.FindIntKey("xoffset");
+  if (!xoffset)
     return Status(kInvalidArgument, "'xoffset' must be an integer");
-  int yoffset;
-  if (!params.GetInteger("yoffset", &yoffset))
+  absl::optional<int> yoffset = params.FindIntKey("yoffset");
+  if (!yoffset)
     return Status(kInvalidArgument, "'yoffset' must be an integer");
-  return web_view->SynthesizeScrollGesture(
-      location.x, location.y, xoffset, yoffset);
+  return web_view->SynthesizeScrollGesture(location.x, location.y, *xoffset,
+                                           *yoffset);
 }
 
 Status ProcessInputActionSequence(
@@ -1428,9 +1434,8 @@
 
       if (subtype == "pointerDown" || subtype == "pointerUp") {
         if (pointer_type == "mouse" || pointer_type == "pen") {
-          int button;
-          if (!action_item->GetInteger("button", &button) || button < 0 ||
-              button > 4) {
+          int button = action_item->FindIntKey("button").value_or(-1);
+          if (button < 0 || button > 4) {
             return Status(
                 kInvalidArgument,
                 "'button' must be a non-negative int and between 0 and 4");
@@ -1442,14 +1447,14 @@
           action->SetString("button", button_str);
         }
       } else if (subtype == "pointerMove" || subtype == "scroll") {
-        int x;
-        if (!action_item->GetInteger("x", &x))
+        absl::optional<int> x = action_item->FindIntKey("x");
+        if (!x.has_value())
           return Status(kInvalidArgument, "'x' must be an int");
-        int y;
-        if (!action_item->GetInteger("y", &y))
+        absl::optional<int> y = action_item->FindIntKey("y");
+        if (!y.has_value())
           return Status(kInvalidArgument, "'y' must be an int");
-        action->SetInteger("x", x);
-        action->SetInteger("y", y);
+        action->SetIntKey("x", *x);
+        action->SetIntKey("y", *y);
 
         std::string origin;
         if (action_item->FindKey("origin")) {
@@ -1480,14 +1485,14 @@
           return status;
 
         if (subtype == "scroll") {
-          int delta_x;
-          if (!action_item->GetInteger("deltaX", &delta_x))
+          absl::optional<int> delta_x = action_item->FindIntKey("deltaX");
+          if (!delta_x)
             return Status(kInvalidArgument, "'delta x' must be an int");
-          int delta_y;
-          if (!action_item->GetInteger("deltaY", &delta_y))
+          absl::optional<int> delta_y = action_item->FindIntKey("deltaY");
+          if (!delta_y)
             return Status(kInvalidArgument, "'delta y' must be an int");
-          action->SetInteger("deltaX", delta_x);
-          action->SetInteger("deltaY", delta_y);
+          action->SetIntKey("deltaX", *delta_x);
+          action->SetIntKey("deltaY", *delta_y);
         }
       } else if (subtype == "pause") {
         Status status = ProcessPauseAction(action_item, action.get());
@@ -1651,9 +1656,13 @@
                 session, web_view, &viewport_width, &viewport_height);
             if (status.IsError())
               return status;
+            absl::optional<int> maybe_init_x = input_state->FindIntKey("x");
+            if (maybe_init_x)
+              init_x = *maybe_init_x;
 
-            input_state->GetInteger("x", &init_x);
-            input_state->GetInteger("y", &init_y);
+            absl::optional<int> maybe_init_y = input_state->FindIntKey("y");
+            if (maybe_init_y)
+              init_y = *maybe_init_y;
             action_locations.insert(
                 std::make_pair(id, gfx::Point(init_x, init_y)));
 
@@ -1745,9 +1754,8 @@
               tick_duration = std::max(tick_duration, duration);
 
               if (action_type == "scroll") {
-                int delta_x = 0, delta_y = 0;
-                action->GetInteger("deltaX", &delta_x);
-                action->GetInteger("deltaY", &delta_y);
+                int delta_x = action->FindIntKey("deltaX").value_or(0);
+                int delta_y = action->FindIntKey("deltaY").value_or(0);
                 std::vector<MouseEvent> dispatch_wheel_events;
                 MouseEvent event(StringToMouseEventType(action_type),
                                  StringToMouseButton(button_type[id]),
@@ -1969,13 +1977,12 @@
   if (!params.GetDictionary("params", &cmdParams)) {
     return Status(kInvalidArgument, "params not passed");
   }
-  int client_cmd_id;
-  if (!params.GetInteger("id", &client_cmd_id) ||
-      !CommandId::IsClientCommandId(client_cmd_id)) {
+  absl::optional<int> client_cmd_id = params.FindIntKey("id");
+  if (!client_cmd_id || !CommandId::IsClientCommandId(*client_cmd_id)) {
     return Status(kInvalidArgument, "command id must be negative");
   }
 
-  return web_view->SendCommandFromWebSocket(cmd, *cmdParams, client_cmd_id);
+  return web_view->SendCommandFromWebSocket(cmd, *cmdParams, *client_cmd_id);
 }
 
 Status ExecuteSendCommandAndGetResult(Session* session,
diff --git a/chrome/test/chromedriver/window_commands_unittest.cc b/chrome/test/chromedriver/window_commands_unittest.cc
index fe55ba8..10b8bff 100644
--- a/chrome/test/chromedriver/window_commands_unittest.cc
+++ b/chrome/test/chromedriver/window_commands_unittest.cc
@@ -151,8 +151,8 @@
   ASSERT_EQ("mouse", pointer_type);
   ASSERT_EQ("pointer1", id);
   action1->GetString("subtype", &action_type);
-  action1->GetInteger("x", &x);
-  action1->GetInteger("y", &y);
+  x = action1->FindIntKey("x").value_or(-1);
+  y = action1->FindIntKey("y").value_or(-1);
   ASSERT_EQ("pointerMove", action_type);
   ASSERT_EQ(30, x);
   ASSERT_EQ(60, y);
@@ -228,8 +228,8 @@
   ASSERT_EQ("touch", pointer_type);
   ASSERT_EQ("pointer1", id);
   action1->GetString("subtype", &action_type);
-  action1->GetInteger("x", &x);
-  action1->GetInteger("y", &y);
+  x = action1->FindIntKey("x").value_or(-1);
+  y = action1->FindIntKey("y").value_or(-1);
   ASSERT_EQ("pointerMove", action_type);
   ASSERT_EQ(30, x);
   ASSERT_EQ(60, y);