| Index: content/common/origin_trials/trial_token.cc
|
| diff --git a/content/common/origin_trials/trial_token.cc b/content/common/origin_trials/trial_token.cc
|
| index 0a137edc68b43e780e572c1d083379c864921fc8..4e93efd89c4be2c51f33b795d24c14c3ab92d0cc 100644
|
| --- a/content/common/origin_trials/trial_token.cc
|
| +++ b/content/common/origin_trials/trial_token.cc
|
| @@ -43,49 +43,64 @@ const uint8_t kVersion2 = 2;
|
|
|
| TrialToken::~TrialToken() {}
|
|
|
| -// static
|
| -std::unique_ptr<TrialToken> TrialToken::From(const std::string& token_text,
|
| - base::StringPiece public_key) {
|
| - std::unique_ptr<std::string> token_payload = Extract(token_text, public_key);
|
| - if (!token_payload) {
|
| - return nullptr;
|
| +// Static
|
| +TrialTokenStatus TrialToken::From(const std::string& token_text,
|
| + base::StringPiece public_key,
|
| + std::unique_ptr<TrialToken>& out_token) {
|
| + std::unique_ptr<std::string> token_payload;
|
| + TrialTokenStatus status = Extract(token_text, public_key, token_payload);
|
| + if (status != TRIAL_TOKEN_STATUS_SUCCESS) {
|
| + out_token.reset();
|
| + return status;
|
| }
|
| - return Parse(*token_payload);
|
| + out_token = Parse(*token_payload);
|
| + return out_token ? TRIAL_TOKEN_STATUS_SUCCESS : TRIAL_TOKEN_STATUS_MALFORMED;
|
| }
|
|
|
| -bool TrialToken::IsValidForFeature(const url::Origin& origin,
|
| - base::StringPiece feature_name,
|
| - const base::Time& now) const {
|
| - return ValidateOrigin(origin) && ValidateFeatureName(feature_name) &&
|
| - ValidateDate(now);
|
| +TrialTokenStatus TrialToken::IsValidForFeature(const url::Origin& origin,
|
| + base::StringPiece feature_name,
|
| + const base::Time& now) const {
|
| + // The order of these checks is intentional. For example, will only report a
|
| + // token as expired if it is valid for the origin + feature combination.
|
| + if (!ValidateOrigin(origin)) {
|
| + return TRIAL_TOKEN_STATUS_WRONG_ORIGIN;
|
| + }
|
| + if (!ValidateFeatureName(feature_name)) {
|
| + return TRIAL_TOKEN_STATUS_WRONG_FEATURE;
|
| + }
|
| + if (!ValidateDate(now)) {
|
| + return TRIAL_TOKEN_STATUS_EXPIRED;
|
| + }
|
| + return TRIAL_TOKEN_STATUS_SUCCESS;
|
| }
|
|
|
| -std::unique_ptr<std::string> TrialToken::Extract(
|
| +TrialTokenStatus TrialToken::Extract(
|
| const std::string& token_payload,
|
| - base::StringPiece public_key) {
|
| + base::StringPiece public_key,
|
| + std::unique_ptr<std::string>& out_token_json) {
|
| if (token_payload.empty()) {
|
| - return nullptr;
|
| + return TRIAL_TOKEN_STATUS_MALFORMED;
|
| }
|
|
|
| // Token is base64-encoded; decode first.
|
| std::string token_contents;
|
| if (!base::Base64Decode(token_payload, &token_contents)) {
|
| - return nullptr;
|
| + return TRIAL_TOKEN_STATUS_MALFORMED;
|
| }
|
|
|
| // Only version 2 currently supported.
|
| if (token_contents.length() < (kVersionOffset + kVersionSize)) {
|
| - return nullptr;
|
| + return TRIAL_TOKEN_STATUS_MALFORMED;
|
| }
|
| uint8_t version = token_contents[kVersionOffset];
|
| if (version != kVersion2) {
|
| - return nullptr;
|
| + return TRIAL_TOKEN_STATUS_MALFORMED;
|
| }
|
|
|
| // Token must be large enough to contain a version, signature, and payload
|
| // length.
|
| if (token_contents.length() < (kPayloadLengthOffset + kPayloadLengthSize)) {
|
| - return nullptr;
|
| + return TRIAL_TOKEN_STATUS_MALFORMED;
|
| }
|
|
|
| // Extract the length of the signed data (Big-endian).
|
| @@ -94,7 +109,7 @@ std::unique_ptr<std::string> TrialToken::Extract(
|
|
|
| // Validate that the stated length matches the actual payload length.
|
| if (payload_length != token_contents.length() - kPayloadOffset) {
|
| - return nullptr;
|
| + return TRIAL_TOKEN_STATUS_MALFORMED;
|
| }
|
|
|
| // Extract the version-specific contents of the token.
|
| @@ -110,12 +125,13 @@ std::unique_ptr<std::string> TrialToken::Extract(
|
|
|
| // Validate the signature on the data before proceeding.
|
| if (!TrialToken::ValidateSignature(signature, signed_data, public_key)) {
|
| - return nullptr;
|
| + return TRIAL_TOKEN_STATUS_INVALID_SIGNATURE;
|
| }
|
|
|
| // Return just the payload, as a new string.
|
| - return base::WrapUnique(
|
| + out_token_json.reset(
|
| new std::string(token_contents, kPayloadOffset, payload_length));
|
| + return TRIAL_TOKEN_STATUS_SUCCESS;
|
| }
|
|
|
| std::unique_ptr<TrialToken> TrialToken::Parse(const std::string& token_json) {
|
|
|