0

Migrate OAuth2MintTokenFlow to Value::Dict.

It was using deprecated base::Value methods to manipulate dictionaries.

Bug: 1187001
Change-Id: I6c9b867f9b0b82e7748ceb6382bb155c2f8b2640
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4002750
Commit-Queue: Matt Menke <mmenke@chromium.org>
Reviewed-by: Alex Ilin <alexilin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1067701}
This commit is contained in:
Matt Menke
2022-11-04 21:39:45 +00:00
committed by Chromium LUCI CQ
parent ad1364ae76
commit c655400881
3 changed files with 142 additions and 139 deletions

@ -249,7 +249,8 @@ void OAuth2MintTokenFlow::ProcessApiCallSuccess(
return;
}
std::string* issue_advice_value = value->FindStringKey(kIssueAdviceKey);
base::Value::Dict& dict = value->GetDict();
std::string* issue_advice_value = dict.FindString(kIssueAdviceKey);
if (!issue_advice_value) {
RecordApiCallResult(
OAuth2MintTokenApiCallResult::kIssueAdviceKeyNotFoundFailure);
@ -260,7 +261,7 @@ void OAuth2MintTokenFlow::ProcessApiCallSuccess(
if (*issue_advice_value == kIssueAdviceValueRemoteConsent) {
RemoteConsentResolutionData resolution_data;
if (ParseRemoteConsentResponse(&(*value), &resolution_data)) {
if (ParseRemoteConsentResponse(dict, &resolution_data)) {
RecordApiCallResult(OAuth2MintTokenApiCallResult::kRemoteConsentSuccess);
ReportRemoteConsentSuccess(resolution_data);
} else {
@ -276,7 +277,7 @@ void OAuth2MintTokenFlow::ProcessApiCallSuccess(
std::string access_token;
std::set<std::string> granted_scopes;
int time_to_live;
if (ParseMintTokenResponse(&(*value), &access_token, &granted_scopes,
if (ParseMintTokenResponse(dict, &access_token, &granted_scopes,
&time_to_live)) {
RecordApiCallResult(OAuth2MintTokenApiCallResult::kMintTokenSuccess);
ReportSuccess(access_token, granted_scopes, time_to_live);
@ -300,28 +301,25 @@ void OAuth2MintTokenFlow::ProcessApiCallFailure(
// static
bool OAuth2MintTokenFlow::ParseMintTokenResponse(
const base::Value* dict,
const base::Value::Dict& dict,
std::string* access_token,
std::set<std::string>* granted_scopes,
int* time_to_live) {
CHECK(dict);
CHECK(dict->is_dict());
CHECK(access_token);
CHECK(granted_scopes);
CHECK(time_to_live);
const std::string* ttl_string = dict->FindStringKey(kExpiresInKey);
const std::string* ttl_string = dict.FindString(kExpiresInKey);
if (!ttl_string || !base::StringToInt(*ttl_string, time_to_live))
return false;
const std::string* access_token_ptr = dict->FindStringKey(kAccessTokenKey);
const std::string* access_token_ptr = dict.FindString(kAccessTokenKey);
if (!access_token_ptr)
return false;
*access_token = *access_token_ptr;
const std::string* granted_scopes_string =
dict->FindStringKey(kGrantedScopesKey);
const std::string* granted_scopes_string = dict.FindString(kGrantedScopesKey);
if (!granted_scopes_string)
return false;
@ -340,80 +338,80 @@ bool OAuth2MintTokenFlow::ParseMintTokenResponse(
// static
bool OAuth2MintTokenFlow::ParseRemoteConsentResponse(
const base::Value* dict,
const base::Value::Dict& dict,
RemoteConsentResolutionData* resolution_data) {
CHECK(dict);
CHECK(resolution_data);
const base::Value* resolution_dict = dict->FindDictKey("resolutionData");
const base::Value::Dict* resolution_dict = dict.FindDict("resolutionData");
if (!resolution_dict)
return false;
const std::string* resolution_approach =
resolution_dict->FindStringKey("resolutionApproach");
resolution_dict->FindString("resolutionApproach");
if (!resolution_approach || *resolution_approach != "resolveInBrowser")
return false;
const std::string* resolution_url_string =
resolution_dict->FindStringKey("resolutionUrl");
resolution_dict->FindString("resolutionUrl");
if (!resolution_url_string)
return false;
GURL resolution_url(*resolution_url_string);
if (!resolution_url.is_valid())
return false;
const base::Value* browser_cookies =
resolution_dict->FindListKey("browserCookies");
base::span<const base::Value> cookie_list;
if (browser_cookies)
cookie_list = browser_cookies->GetListDeprecated();
const base::Value::List* browser_cookies =
resolution_dict->FindList("browserCookies");
base::Time time_now = base::Time::Now();
bool success = true;
std::vector<net::CanonicalCookie> cookies;
for (const auto& cookie_dict : cookie_list) {
if (!cookie_dict.is_dict()) {
success = false;
break;
if (browser_cookies) {
for (const auto& cookie_value : *browser_cookies) {
const base::Value::Dict* cookie_dict = cookie_value.GetIfDict();
if (!cookie_dict) {
success = false;
break;
}
// Required parameters:
const std::string* name = cookie_dict->FindString("name");
const std::string* value = cookie_dict->FindString("value");
const std::string* domain = cookie_dict->FindString("domain");
if (!name || !value || !domain) {
success = false;
break;
}
// Optional parameters:
const std::string* path = cookie_dict->FindString("path");
const std::string* max_age_seconds =
cookie_dict->FindString("maxAgeSeconds");
absl::optional<bool> is_secure = cookie_dict->FindBool("isSecure");
absl::optional<bool> is_http_only = cookie_dict->FindBool("isHttpOnly");
const std::string* same_site = cookie_dict->FindString("sameSite");
int64_t max_age = -1;
if (max_age_seconds && !base::StringToInt64(*max_age_seconds, &max_age)) {
success = false;
break;
}
base::Time expiration_time = base::Time();
if (max_age > 0)
expiration_time = time_now + base::Seconds(max_age);
std::unique_ptr<net::CanonicalCookie> cookie =
net::CanonicalCookie::CreateSanitizedCookie(
resolution_url, *name, *value, *domain, path ? *path : "/",
time_now, expiration_time, time_now,
is_secure ? *is_secure : false,
is_http_only ? *is_http_only : false,
net::StringToCookieSameSite(same_site ? *same_site : ""),
net::COOKIE_PRIORITY_DEFAULT, /* same_party */ false,
/* partition_key */ absl::nullopt);
cookies.push_back(*cookie);
}
// Required parameters:
const std::string* name = cookie_dict.FindStringKey("name");
const std::string* value = cookie_dict.FindStringKey("value");
const std::string* domain = cookie_dict.FindStringKey("domain");
if (!name || !value || !domain) {
success = false;
break;
}
// Optional parameters:
const std::string* path = cookie_dict.FindStringKey("path");
const std::string* max_age_seconds =
cookie_dict.FindStringKey("maxAgeSeconds");
absl::optional<bool> is_secure = cookie_dict.FindBoolKey("isSecure");
absl::optional<bool> is_http_only = cookie_dict.FindBoolKey("isHttpOnly");
const std::string* same_site = cookie_dict.FindStringKey("sameSite");
int64_t max_age = -1;
if (max_age_seconds && !base::StringToInt64(*max_age_seconds, &max_age)) {
success = false;
break;
}
base::Time expiration_time = base::Time();
if (max_age > 0)
expiration_time = time_now + base::Seconds(max_age);
std::unique_ptr<net::CanonicalCookie> cookie =
net::CanonicalCookie::CreateSanitizedCookie(
resolution_url, *name, *value, *domain, path ? *path : "/",
time_now, expiration_time, time_now, is_secure ? *is_secure : false,
is_http_only ? *is_http_only : false,
net::StringToCookieSameSite(same_site ? *same_site : ""),
net::COOKIE_PRIORITY_DEFAULT, /* same_party */ false,
/* partition_key */ absl::nullopt);
cookies.push_back(*cookie);
}
if (success) {

@ -12,6 +12,7 @@
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "google_apis/gaia/oauth2_api_call_flow.h"
#include "net/cookies/canonical_cookie.h"
#include "services/network/public/mojom/url_response_head.mojom-forward.h"
@ -20,10 +21,6 @@
class GoogleServiceAuthError;
class OAuth2MintTokenFlowTest;
namespace base {
class Value;
}
extern const char kOAuth2MintTokenApiCallResultHistogram[];
// Values carrying the result of processing a successful API call.
@ -184,7 +181,7 @@ class OAuth2MintTokenFlow : public OAuth2ApiCallFlow {
void ReportFailure(const GoogleServiceAuthError& error);
static bool ParseRemoteConsentResponse(
const base::Value* dict,
const base::Value::Dict& dict,
RemoteConsentResolutionData* resolution_data);
// Currently, grantedScopes is a new parameter for an unlaunched feature, so
@ -194,7 +191,7 @@ class OAuth2MintTokenFlow : public OAuth2ApiCallFlow {
// and the function returns true, granted_scopes will include the scopes
// returned by the server. Once the feature is fully launched, this function
// will be updated to fail if the grantedScopes parameter is missing.
static bool ParseMintTokenResponse(const base::Value* dict,
static bool ParseMintTokenResponse(const base::Value::Dict& dict,
std::string* access_token,
std::set<std::string>* granted_scopes,
int* time_to_live);

@ -14,6 +14,7 @@
#include "base/json/json_reader.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/values_test_util.h"
#include "base/values.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_access_token_fetcher.h"
@ -210,14 +211,6 @@ class OAuth2MintTokenFlowTest : public testing::Test {
flow_->ProcessApiCallFailure(net_error, head, std::move(body));
}
// Helper to parse the given string to base::Value.
static std::unique_ptr<base::Value> ParseJson(const std::string& str) {
absl::optional<base::Value> value = base::JSONReader::Read(str);
EXPECT_TRUE(value.has_value());
EXPECT_TRUE(value->is_dict());
return std::make_unique<base::Value>(std::move(*value));
}
std::unique_ptr<MockMintTokenFlow> flow_;
StrictMock<MockDelegate> delegate_;
base::HistogramTester histogram_tester_;
@ -344,41 +337,42 @@ TEST_F(OAuth2MintTokenFlowTest, CreateApiCallBody) {
TEST_F(OAuth2MintTokenFlowTest, ParseMintTokenResponse) {
{ // Access token missing.
std::unique_ptr<base::Value> json = ParseJson(kTokenResponseNoAccessToken);
base::Value::Dict json =
base::test::ParseJsonDict(kTokenResponseNoAccessToken);
std::string access_token;
std::set<std::string> granted_scopes;
int time_to_live;
EXPECT_FALSE(OAuth2MintTokenFlow::ParseMintTokenResponse(
json.get(), &access_token, &granted_scopes, &time_to_live));
json, &access_token, &granted_scopes, &time_to_live));
EXPECT_TRUE(access_token.empty());
}
{ // Granted scopes parameter is there but is empty.
std::unique_ptr<base::Value> json =
ParseJson(kTokenResponseEmptyGrantedScopes);
base::Value::Dict json =
base::test::ParseJsonDict(kTokenResponseEmptyGrantedScopes);
std::string access_token;
std::set<std::string> granted_scopes;
int time_to_live;
EXPECT_FALSE(OAuth2MintTokenFlow::ParseMintTokenResponse(
json.get(), &access_token, &granted_scopes, &time_to_live));
json, &access_token, &granted_scopes, &time_to_live));
EXPECT_TRUE(granted_scopes.empty());
}
{ // Granted scopes parameter is missing.
std::unique_ptr<base::Value> json =
ParseJson(kTokenResponseNoGrantedScopes);
base::Value::Dict json =
base::test::ParseJsonDict(kTokenResponseNoGrantedScopes);
std::string access_token;
std::set<std::string> granted_scopes;
int time_to_live;
EXPECT_FALSE(OAuth2MintTokenFlow::ParseMintTokenResponse(
json.get(), &access_token, &granted_scopes, &time_to_live));
json, &access_token, &granted_scopes, &time_to_live));
EXPECT_TRUE(granted_scopes.empty());
}
{ // All good.
std::unique_ptr<base::Value> json = ParseJson(kValidTokenResponse);
base::Value::Dict json = base::test::ParseJsonDict(kValidTokenResponse);
std::string access_token;
std::set<std::string> granted_scopes;
int time_to_live;
EXPECT_TRUE(OAuth2MintTokenFlow::ParseMintTokenResponse(
json.get(), &access_token, &granted_scopes, &time_to_live));
json, &access_token, &granted_scopes, &time_to_live));
EXPECT_EQ("at1", access_token);
EXPECT_EQ(3600, time_to_live);
EXPECT_EQ(std::set<std::string>({"http://scope1", "http://scope2"}),
@ -387,21 +381,23 @@ TEST_F(OAuth2MintTokenFlowTest, ParseMintTokenResponse) {
}
TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse) {
std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
base::Value::Dict json =
base::test::ParseJsonDict(kValidRemoteConsentResponse);
RemoteConsentResolutionData resolution_data;
ASSERT_TRUE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
json.get(), &resolution_data));
ASSERT_TRUE(
OAuth2MintTokenFlow::ParseRemoteConsentResponse(json, &resolution_data));
RemoteConsentResolutionData expected_resolution_data =
CreateRemoteConsentResolutionData();
EXPECT_EQ(resolution_data, expected_resolution_data);
}
TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_EmptyCookies) {
std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
json->FindListPath("resolutionData.browserCookies")->ClearList();
base::Value::Dict json =
base::test::ParseJsonDict(kValidRemoteConsentResponse);
json.FindListByDottedPath("resolutionData.browserCookies")->clear();
RemoteConsentResolutionData resolution_data;
EXPECT_TRUE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
json.get(), &resolution_data));
EXPECT_TRUE(
OAuth2MintTokenFlow::ParseRemoteConsentResponse(json, &resolution_data));
RemoteConsentResolutionData expected_resolution_data =
CreateRemoteConsentResolutionData();
expected_resolution_data.cookies.clear();
@ -409,11 +405,12 @@ TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_EmptyCookies) {
}
TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_NoCookies) {
std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
EXPECT_TRUE(json->RemovePath("resolutionData.browserCookies"));
base::Value::Dict json =
base::test::ParseJsonDict(kValidRemoteConsentResponse);
EXPECT_TRUE(json.RemoveByDottedPath("resolutionData.browserCookies"));
RemoteConsentResolutionData resolution_data;
EXPECT_TRUE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
json.get(), &resolution_data));
EXPECT_TRUE(
OAuth2MintTokenFlow::ParseRemoteConsentResponse(json, &resolution_data));
RemoteConsentResolutionData expected_resolution_data =
CreateRemoteConsentResolutionData();
expected_resolution_data.cookies.clear();
@ -421,52 +418,58 @@ TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_NoCookies) {
}
TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_NoResolutionData) {
std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
EXPECT_TRUE(json->RemoveKey("resolutionData"));
base::Value::Dict json =
base::test::ParseJsonDict(kValidRemoteConsentResponse);
EXPECT_TRUE(json.Remove("resolutionData"));
RemoteConsentResolutionData resolution_data;
EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
json.get(), &resolution_data));
EXPECT_FALSE(
OAuth2MintTokenFlow::ParseRemoteConsentResponse(json, &resolution_data));
EXPECT_TRUE(resolution_data.url.is_empty());
EXPECT_TRUE(resolution_data.cookies.empty());
}
TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_NoUrl) {
std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
EXPECT_TRUE(json->RemovePath("resolutionData.resolutionUrl"));
base::Value::Dict json =
base::test::ParseJsonDict(kValidRemoteConsentResponse);
EXPECT_TRUE(json.RemoveByDottedPath("resolutionData.resolutionUrl"));
RemoteConsentResolutionData resolution_data;
EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
json.get(), &resolution_data));
EXPECT_FALSE(
OAuth2MintTokenFlow::ParseRemoteConsentResponse(json, &resolution_data));
EXPECT_TRUE(resolution_data.url.is_empty());
EXPECT_TRUE(resolution_data.cookies.empty());
}
TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_BadUrl) {
std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
EXPECT_TRUE(json->SetStringPath("resolutionData.resolutionUrl", "not-a-url"));
base::Value::Dict json =
base::test::ParseJsonDict(kValidRemoteConsentResponse);
EXPECT_TRUE(
json.SetByDottedPath("resolutionData.resolutionUrl", "not-a-url"));
RemoteConsentResolutionData resolution_data;
EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
json.get(), &resolution_data));
EXPECT_FALSE(
OAuth2MintTokenFlow::ParseRemoteConsentResponse(json, &resolution_data));
EXPECT_TRUE(resolution_data.url.is_empty());
EXPECT_TRUE(resolution_data.cookies.empty());
}
TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_NoApproach) {
std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
EXPECT_TRUE(json->RemovePath("resolutionData.resolutionApproach"));
base::Value::Dict json =
base::test::ParseJsonDict(kValidRemoteConsentResponse);
EXPECT_TRUE(json.RemoveByDottedPath("resolutionData.resolutionApproach"));
RemoteConsentResolutionData resolution_data;
EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
json.get(), &resolution_data));
EXPECT_FALSE(
OAuth2MintTokenFlow::ParseRemoteConsentResponse(json, &resolution_data));
EXPECT_TRUE(resolution_data.url.is_empty());
EXPECT_TRUE(resolution_data.cookies.empty());
}
TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_BadApproach) {
std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
base::Value::Dict json =
base::test::ParseJsonDict(kValidRemoteConsentResponse);
EXPECT_TRUE(
json->SetStringPath("resolutionData.resolutionApproach", "badApproach"));
json.SetByDottedPath("resolutionData.resolutionApproach", "badApproach"));
RemoteConsentResolutionData resolution_data;
EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
json.get(), &resolution_data));
EXPECT_FALSE(
OAuth2MintTokenFlow::ParseRemoteConsentResponse(json, &resolution_data));
EXPECT_TRUE(resolution_data.url.is_empty());
EXPECT_TRUE(resolution_data.cookies.empty());
}
@ -475,14 +478,15 @@ TEST_F(OAuth2MintTokenFlowTest,
ParseRemoteConsentResponse_BadCookie_MissingRequiredField) {
static const char* kRequiredFields[] = {"name", "value", "domain"};
for (const auto* required_field : kRequiredFields) {
std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
base::Value::ListView cookies =
json->FindListPath("resolutionData.browserCookies")
->GetListDeprecated();
EXPECT_TRUE(cookies[0].RemoveKey(required_field));
base::Value::Dict json =
base::test::ParseJsonDict(kValidRemoteConsentResponse);
base::Value::List* cookies =
json.FindListByDottedPath("resolutionData.browserCookies");
ASSERT_TRUE(cookies);
EXPECT_TRUE((*cookies)[0].GetDict().Remove(required_field));
RemoteConsentResolutionData resolution_data;
EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
json.get(), &resolution_data));
json, &resolution_data));
EXPECT_TRUE(resolution_data.url.is_empty());
EXPECT_TRUE(resolution_data.cookies.empty());
}
@ -493,14 +497,15 @@ TEST_F(OAuth2MintTokenFlowTest,
static const char* kOptionalFields[] = {"path", "maxAgeSeconds", "isSecure",
"isHttpOnly", "sameSite"};
for (const auto* optional_field : kOptionalFields) {
std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
base::Value::ListView cookies =
json->FindListPath("resolutionData.browserCookies")
->GetListDeprecated();
EXPECT_TRUE(cookies[0].RemoveKey(optional_field));
base::Value::Dict json =
base::test::ParseJsonDict(kValidRemoteConsentResponse);
base::Value::List* cookies =
json.FindListByDottedPath("resolutionData.browserCookies");
ASSERT_TRUE(cookies);
EXPECT_TRUE((*cookies)[0].GetDict().Remove(optional_field));
RemoteConsentResolutionData resolution_data;
EXPECT_TRUE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
json.get(), &resolution_data));
json, &resolution_data));
RemoteConsentResolutionData expected_resolution_data =
CreateRemoteConsentResolutionData();
EXPECT_EQ(resolution_data, expected_resolution_data);
@ -509,23 +514,26 @@ TEST_F(OAuth2MintTokenFlowTest,
TEST_F(OAuth2MintTokenFlowTest,
ParseRemoteConsentResponse_BadCookie_BadMaxAge) {
std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
base::Value::ListView cookies =
json->FindListPath("resolutionData.browserCookies")->GetListDeprecated();
cookies[0].SetStringKey("maxAgeSeconds", "not-a-number");
base::Value::Dict json =
base::test::ParseJsonDict(kValidRemoteConsentResponse);
base::Value::List* cookies =
json.FindListByDottedPath("resolutionData.browserCookies");
ASSERT_TRUE(cookies);
(*cookies)[0].GetDict().Set("maxAgeSeconds", "not-a-number");
RemoteConsentResolutionData resolution_data;
EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
json.get(), &resolution_data));
EXPECT_FALSE(
OAuth2MintTokenFlow::ParseRemoteConsentResponse(json, &resolution_data));
EXPECT_TRUE(resolution_data.url.is_empty());
EXPECT_TRUE(resolution_data.cookies.empty());
}
TEST_F(OAuth2MintTokenFlowTest, ParseRemoteConsentResponse_BadCookieList) {
std::unique_ptr<base::Value> json = ParseJson(kValidRemoteConsentResponse);
json->FindListPath("resolutionData.browserCookies")->Append(42);
base::Value::Dict json =
base::test::ParseJsonDict(kValidRemoteConsentResponse);
json.FindListByDottedPath("resolutionData.browserCookies")->Append(42);
RemoteConsentResolutionData resolution_data;
EXPECT_FALSE(OAuth2MintTokenFlow::ParseRemoteConsentResponse(
json.get(), &resolution_data));
EXPECT_FALSE(
OAuth2MintTokenFlow::ParseRemoteConsentResponse(json, &resolution_data));
EXPECT_TRUE(resolution_data.url.is_empty());
EXPECT_TRUE(resolution_data.cookies.empty());
}