| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/common/origin_trials/trial_token_validator.h" | 5 #include "content/common/origin_trials/trial_token_validator.h" |
| 6 | 6 |
| 7 #include "base/feature_list.h" | 7 #include "base/feature_list.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/time/time.h" | 9 #include "base/time/time.h" |
| 10 #include "content/common/origin_trials/trial_token.h" | 10 #include "content/common/origin_trials/trial_token.h" |
| 11 #include "content/public/common/content_client.h" | 11 #include "content/public/common/content_client.h" |
| 12 #include "content/public/common/content_features.h" | 12 #include "content/public/common/content_features.h" |
| 13 #include "content/public/common/origin_trial_policy.h" | 13 #include "content/public/common/origin_trial_policy.h" |
| 14 #include "content/public/common/origin_util.h" | 14 #include "content/public/common/origin_util.h" |
| 15 #include "net/http/http_response_headers.h" | 15 #include "net/http/http_response_headers.h" |
| 16 #include "net/url_request/url_request.h" | 16 #include "net/url_request/url_request.h" |
| 17 #include "third_party/WebKit/public/platform/WebOriginTrialTokenStatus.h" | 17 #include "third_party/WebKit/public/platform/WebOriginTrialTokenStatus.h" |
| 18 | 18 |
| 19 namespace content { | 19 namespace content { |
| 20 | 20 |
| 21 blink::WebOriginTrialTokenStatus TrialTokenValidator::ValidateToken( | 21 blink::WebOriginTrialTokenStatus TrialTokenValidator::ValidateToken( |
| 22 const std::string& token, | 22 const std::string& token, |
| 23 const url::Origin& origin, | 23 const url::Origin& origin, |
| 24 std::string* feature_name) { | 24 std::string* feature_name, |
| 25 base::Time current_time) { |
| 25 ContentClient* content_client = GetContentClient(); | 26 ContentClient* content_client = GetContentClient(); |
| 26 const OriginTrialPolicy* origin_trial_policy = | 27 const OriginTrialPolicy* origin_trial_policy = |
| 27 content_client->GetOriginTrialPolicy(); | 28 content_client->GetOriginTrialPolicy(); |
| 28 if (!origin_trial_policy) | 29 if (!origin_trial_policy) |
| 29 return blink::WebOriginTrialTokenStatus::kNotSupported; | 30 return blink::WebOriginTrialTokenStatus::kNotSupported; |
| 30 | 31 |
| 31 // TODO(iclelland): Allow for multiple signing keys, and iterate over all | 32 // TODO(iclelland): Allow for multiple signing keys, and iterate over all |
| 32 // active keys here. https://crbug.com/543220 | 33 // active keys here. https://crbug.com/543220 |
| 33 base::StringPiece public_key = origin_trial_policy->GetPublicKey(); | 34 base::StringPiece public_key = origin_trial_policy->GetPublicKey(); |
| 34 if (public_key.empty()) | 35 if (public_key.empty()) |
| 35 return blink::WebOriginTrialTokenStatus::kNotSupported; | 36 return blink::WebOriginTrialTokenStatus::kNotSupported; |
| 36 | 37 |
| 37 blink::WebOriginTrialTokenStatus status; | 38 blink::WebOriginTrialTokenStatus status; |
| 38 std::unique_ptr<TrialToken> trial_token = | 39 std::unique_ptr<TrialToken> trial_token = |
| 39 TrialToken::From(token, public_key, &status); | 40 TrialToken::From(token, public_key, &status); |
| 40 if (status != blink::WebOriginTrialTokenStatus::kSuccess) | 41 if (status != blink::WebOriginTrialTokenStatus::kSuccess) |
| 41 return status; | 42 return status; |
| 42 | 43 |
| 43 status = trial_token->IsValid(origin, base::Time::Now()); | 44 status = trial_token->IsValid(origin, current_time); |
| 44 if (status != blink::WebOriginTrialTokenStatus::kSuccess) | 45 if (status != blink::WebOriginTrialTokenStatus::kSuccess) |
| 45 return status; | 46 return status; |
| 46 | 47 |
| 47 if (origin_trial_policy->IsFeatureDisabled(trial_token->feature_name())) | 48 if (origin_trial_policy->IsFeatureDisabled(trial_token->feature_name())) |
| 48 return blink::WebOriginTrialTokenStatus::kFeatureDisabled; | 49 return blink::WebOriginTrialTokenStatus::kFeatureDisabled; |
| 49 | 50 |
| 50 if (origin_trial_policy->IsTokenDisabled(trial_token->signature())) | 51 if (origin_trial_policy->IsTokenDisabled(trial_token->signature())) |
| 51 return blink::WebOriginTrialTokenStatus::kTokenDisabled; | 52 return blink::WebOriginTrialTokenStatus::kTokenDisabled; |
| 52 | 53 |
| 53 *feature_name = trial_token->feature_name(); | 54 *feature_name = trial_token->feature_name(); |
| 54 return blink::WebOriginTrialTokenStatus::kSuccess; | 55 return blink::WebOriginTrialTokenStatus::kSuccess; |
| 55 } | 56 } |
| 56 | 57 |
| 57 bool TrialTokenValidator::RequestEnablesFeature( | 58 bool TrialTokenValidator::RequestEnablesFeature(const net::URLRequest* request, |
| 58 const net::URLRequest* request, | 59 base::StringPiece feature_name, |
| 59 base::StringPiece feature_name) { | 60 base::Time current_time) { |
| 60 // TODO(mek): Possibly cache the features that are availble for request in | 61 // TODO(mek): Possibly cache the features that are availble for request in |
| 61 // UserData associated with the request. | 62 // UserData associated with the request. |
| 62 return RequestEnablesFeature(request->url(), request->response_headers(), | 63 return RequestEnablesFeature(request->url(), request->response_headers(), |
| 63 feature_name); | 64 feature_name, current_time); |
| 64 } | 65 } |
| 65 | 66 |
| 66 bool TrialTokenValidator::RequestEnablesFeature( | 67 bool TrialTokenValidator::RequestEnablesFeature( |
| 67 const GURL& request_url, | 68 const GURL& request_url, |
| 68 const net::HttpResponseHeaders* response_headers, | 69 const net::HttpResponseHeaders* response_headers, |
| 69 base::StringPiece feature_name) { | 70 base::StringPiece feature_name, |
| 71 base::Time current_time) { |
| 70 if (!base::FeatureList::IsEnabled(features::kOriginTrials)) | 72 if (!base::FeatureList::IsEnabled(features::kOriginTrials)) |
| 71 return false; | 73 return false; |
| 72 | 74 |
| 73 if (!IsOriginSecure(request_url)) | 75 if (!IsOriginSecure(request_url)) |
| 74 return false; | 76 return false; |
| 75 | 77 |
| 76 url::Origin origin(request_url); | 78 url::Origin origin(request_url); |
| 77 size_t iter = 0; | 79 size_t iter = 0; |
| 78 std::string token; | 80 std::string token; |
| 79 while (response_headers->EnumerateHeader(&iter, "Origin-Trial", &token)) { | 81 while (response_headers->EnumerateHeader(&iter, "Origin-Trial", &token)) { |
| 80 std::string token_feature; | 82 std::string token_feature; |
| 81 // TODO(mek): Log the validation errors to histograms? | 83 // TODO(mek): Log the validation errors to histograms? |
| 82 if (ValidateToken(token, origin, &token_feature) == | 84 if (ValidateToken(token, origin, &token_feature, current_time) == |
| 83 blink::WebOriginTrialTokenStatus::kSuccess) | 85 blink::WebOriginTrialTokenStatus::kSuccess) |
| 84 if (token_feature == feature_name) | 86 if (token_feature == feature_name) |
| 85 return true; | 87 return true; |
| 86 } | 88 } |
| 87 return false; | 89 return false; |
| 88 } | 90 } |
| 89 | 91 |
| 90 std::unique_ptr<TrialTokenValidator::FeatureToTokensMap> | 92 std::unique_ptr<TrialTokenValidator::FeatureToTokensMap> |
| 91 TrialTokenValidator::GetValidTokensFromHeaders( | 93 TrialTokenValidator::GetValidTokensFromHeaders( |
| 92 const url::Origin& origin, | 94 const url::Origin& origin, |
| 93 const net::HttpResponseHeaders* headers) { | 95 const net::HttpResponseHeaders* headers, |
| 96 base::Time current_time) { |
| 94 std::unique_ptr<FeatureToTokensMap> tokens( | 97 std::unique_ptr<FeatureToTokensMap> tokens( |
| 95 base::MakeUnique<FeatureToTokensMap>()); | 98 base::MakeUnique<FeatureToTokensMap>()); |
| 96 if (!base::FeatureList::IsEnabled(features::kOriginTrials)) | 99 if (!base::FeatureList::IsEnabled(features::kOriginTrials)) |
| 97 return tokens; | 100 return tokens; |
| 98 | 101 |
| 99 if (!IsOriginSecure(origin.GetURL())) | 102 if (!IsOriginSecure(origin.GetURL())) |
| 100 return tokens; | 103 return tokens; |
| 101 | 104 |
| 102 size_t iter = 0; | 105 size_t iter = 0; |
| 103 std::string token; | 106 std::string token; |
| 104 while (headers->EnumerateHeader(&iter, "Origin-Trial", &token)) { | 107 while (headers->EnumerateHeader(&iter, "Origin-Trial", &token)) { |
| 105 std::string token_feature; | 108 std::string token_feature; |
| 106 if (TrialTokenValidator::ValidateToken(token, origin, &token_feature) == | 109 if (TrialTokenValidator::ValidateToken(token, origin, &token_feature, |
| 110 current_time) == |
| 107 blink::WebOriginTrialTokenStatus::kSuccess) { | 111 blink::WebOriginTrialTokenStatus::kSuccess) { |
| 108 (*tokens)[token_feature].push_back(token); | 112 (*tokens)[token_feature].push_back(token); |
| 109 } | 113 } |
| 110 } | 114 } |
| 111 return tokens; | 115 return tokens; |
| 112 } | 116 } |
| 113 | 117 |
| 114 std::unique_ptr<TrialTokenValidator::FeatureToTokensMap> | 118 std::unique_ptr<TrialTokenValidator::FeatureToTokensMap> |
| 115 TrialTokenValidator::GetValidTokens(const url::Origin& origin, | 119 TrialTokenValidator::GetValidTokens(const url::Origin& origin, |
| 116 const FeatureToTokensMap& tokens) { | 120 const FeatureToTokensMap& tokens, |
| 121 base::Time current_time) { |
| 117 std::unique_ptr<FeatureToTokensMap> out_tokens( | 122 std::unique_ptr<FeatureToTokensMap> out_tokens( |
| 118 base::MakeUnique<FeatureToTokensMap>()); | 123 base::MakeUnique<FeatureToTokensMap>()); |
| 119 if (!base::FeatureList::IsEnabled(features::kOriginTrials)) | 124 if (!base::FeatureList::IsEnabled(features::kOriginTrials)) |
| 120 return out_tokens; | 125 return out_tokens; |
| 121 | 126 |
| 122 if (!IsOriginSecure(origin.GetURL())) | 127 if (!IsOriginSecure(origin.GetURL())) |
| 123 return out_tokens; | 128 return out_tokens; |
| 124 | 129 |
| 125 for (const auto& feature : tokens) { | 130 for (const auto& feature : tokens) { |
| 126 for (const std::string& token : feature.second) { | 131 for (const std::string& token : feature.second) { |
| 127 std::string token_feature; | 132 std::string token_feature; |
| 128 if (TrialTokenValidator::ValidateToken(token, origin, &token_feature) == | 133 if (TrialTokenValidator::ValidateToken(token, origin, &token_feature, |
| 134 current_time) == |
| 129 blink::WebOriginTrialTokenStatus::kSuccess) { | 135 blink::WebOriginTrialTokenStatus::kSuccess) { |
| 130 DCHECK_EQ(token_feature, feature.first); | 136 DCHECK_EQ(token_feature, feature.first); |
| 131 (*out_tokens)[feature.first].push_back(token); | 137 (*out_tokens)[feature.first].push_back(token); |
| 132 } | 138 } |
| 133 } | 139 } |
| 134 } | 140 } |
| 135 return out_tokens; | 141 return out_tokens; |
| 136 } | 142 } |
| 137 | 143 |
| 138 } // namespace content | 144 } // namespace content |
| OLD | NEW |