1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A set of unit tests for TokenValidatorFactoryImpl 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string> 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/json/json_writer.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/values.h" 110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "net/http/http_status_code.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_request_job_factory.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_request_job_factory_impl.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "net/url_request/url_request_status.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_request_test_job.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/url_request/url_request_test_util.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/base/rsa_key_pair.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/base/test_rsa_key_pair.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "remoting/host/token_validator_factory_impl.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kTokenUrl[] = "https://example.com/token"; 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kTokenValidationUrl[] = "https://example.com/validate"; 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kTokenValidationCertIssuer[] = ""; 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kLocalJid[] = "user@example.com/local"; 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kRemoteJid[] = "user@example.com/remote"; 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kToken[] = "xyz123456"; 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kSharedSecret[] = "abcdefgh"; 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Bad scope: no nonce element. 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kBadScope[] = 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "client:user@example.com/local host:user@example.com/remote"; 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class FakeProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FakeProtocolHandler(const std::string& headers, const std::string& response) 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : headers_(headers), 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) response_(response) { 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual net::URLRequestJob* MaybeCreateJob( 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::URLRequest* request, net::NetworkDelegate* network_delegate) const 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OVERRIDE { 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return new net::URLRequestTestJob( 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request, network_delegate, headers_, response_, true); 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string headers_; 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string response_; 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class SetResponseURLRequestContext: public net::TestURLRequestContext { 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SetResponse(const std::string& headers, const std::string& response) { 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::URLRequestJobFactoryImpl* factory = 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new net::URLRequestJobFactoryImpl(); 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) factory->SetProtocolHandler( 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "https", new FakeProtocolHandler(headers, response)); 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) context_storage_.set_job_factory(factory); 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace remoting { 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class TokenValidatorFactoryImplTest : public testing::Test { 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TokenValidatorFactoryImplTest() : message_loop_(base::MessageLoop::TYPE_IO) {} 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void SuccessCallback(const std::string& shared_secret) { 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_FALSE(shared_secret.empty()); 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_loop_.Quit(); 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void FailureCallback(const std::string& shared_secret) { 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(shared_secret.empty()); 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_loop_.Quit(); 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void DeleteOnFailureCallback(const std::string& shared_secret) { 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(shared_secret.empty()); 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_validator_.reset(); 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_loop_.Quit(); 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected: 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void SetUp() OVERRIDE { 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) key_pair_ = RsaKeyPair::FromString(kTestRsaKeyPair); 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<net::TestURLRequestContext> context( 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new SetResponseURLRequestContext()); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) request_context_getter_ = new net::TestURLRequestContextGetter( 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_loop_.message_loop_proxy(), context.Pass()); 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ThirdPartyAuthConfig config; 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) config.token_url = GURL(kTokenUrl); 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) config.token_validation_url = GURL(kTokenValidationUrl); 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) config.token_validation_cert_issuer = kTokenValidationCertIssuer; 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_validator_factory_.reset(new TokenValidatorFactoryImpl( 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) config, key_pair_, request_context_getter_)); 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static std::string CreateResponse(const std::string& scope) { 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue response_dict; 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) response_dict.SetString("access_token", kSharedSecret); 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) response_dict.SetString("token_type", "shared_secret"); 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) response_dict.SetString("scope", scope); 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string response; 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::JSONWriter::Write(&response_dict, &response); 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return response; 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static std::string CreateErrorResponse(const std::string& error) { 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue response_dict; 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) response_dict.SetString("error", error); 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string response; 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::JSONWriter::Write(&response_dict, &response); 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return response; 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SetResponse(const std::string& headers, const std::string& response) { 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetResponseURLRequestContext* context = 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<SetResponseURLRequestContext*>( 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_context_getter_->GetURLRequestContext()); 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) context->SetResponse(headers, response); 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::MessageLoop message_loop_; 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<RsaKeyPair> key_pair_; 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> request_context_getter_; 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<TokenValidatorFactoryImpl> token_validator_factory_; 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<protocol::TokenValidator> token_validator_; 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(TokenValidatorFactoryImplTest, Success) { 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_validator_ = token_validator_factory_->CreateTokenValidator( 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kLocalJid, kRemoteJid); 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetResponse(net::URLRequestTestJob::test_headers(), 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateResponse(token_validator_->token_scope())); 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_validator_->ValidateThirdPartyToken( 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kToken, base::Bind(&TokenValidatorFactoryImplTest::SuccessCallback, 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this))); 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_loop_.Run(); 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(TokenValidatorFactoryImplTest, BadToken) { 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_validator_ = token_validator_factory_->CreateTokenValidator( 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kLocalJid, kRemoteJid); 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetResponse(net::URLRequestTestJob::test_error_headers(), std::string()); 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_validator_->ValidateThirdPartyToken( 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kToken, base::Bind(&TokenValidatorFactoryImplTest::FailureCallback, 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this))); 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_loop_.Run(); 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(TokenValidatorFactoryImplTest, BadScope) { 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_validator_ = token_validator_factory_->CreateTokenValidator( 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kLocalJid, kRemoteJid); 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetResponse(net::URLRequestTestJob::test_headers(), 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateResponse(kBadScope)); 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_validator_->ValidateThirdPartyToken( 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kToken, base::Bind(&TokenValidatorFactoryImplTest::FailureCallback, 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this))); 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_loop_.Run(); 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(TokenValidatorFactoryImplTest, DeleteOnFailure) { 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_validator_ = token_validator_factory_->CreateTokenValidator( 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kLocalJid, kRemoteJid); 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetResponse(net::URLRequestTestJob::test_error_headers(), std::string()); 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) token_validator_->ValidateThirdPartyToken( 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kToken, base::Bind( 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &TokenValidatorFactoryImplTest::DeleteOnFailureCallback, 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this))); 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_loop_.Run(); 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace remoting 190