1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/browser/geolocation/access_token_store.h" 6 7 #include "base/string_util.h" 8 #include "base/utf_string_conversions.h" 9 #include "chrome/test/in_process_browser_test.h" 10 #include "chrome/test/ui_test_utils.h" 11 #include "content/browser/browser_thread.h" 12 13 namespace { 14 15 // The token store factory implementation expects to be used from any well-known 16 // chrome thread other than UI. We could use any arbitrary thread; IO is 17 // a good choice as this is the expected usage. 18 const BrowserThread::ID kExpectedClientThreadId = BrowserThread::IO; 19 const char* kRefServerUrl1 = "https://test.domain.example/foo?id=bar.bar"; 20 const char* kRefServerUrl2 = "http://another.domain.example/foo?id=bar.bar#2"; 21 22 class GeolocationAccessTokenStoreTest 23 : public InProcessBrowserTest { 24 public: 25 GeolocationAccessTokenStoreTest() 26 : token_to_expect_(NULL), token_to_set_(NULL) {} 27 28 void DoTestStepAndWaitForResults( 29 const char* ref_url, const string16* token_to_expect, 30 const string16* token_to_set); 31 32 void OnAccessTokenStoresLoaded( 33 AccessTokenStore::AccessTokenSet access_token_set); 34 35 scoped_refptr<AccessTokenStore> token_store_; 36 CancelableRequestConsumer request_consumer_; 37 GURL ref_url_; 38 const string16* token_to_expect_; 39 const string16* token_to_set_; 40 }; 41 42 void StartTestStepFromClientThread( 43 scoped_refptr<AccessTokenStore>* store, 44 CancelableRequestConsumerBase* consumer, 45 AccessTokenStore::LoadAccessTokensCallbackType* callback) { 46 ASSERT_TRUE(BrowserThread::CurrentlyOn(kExpectedClientThreadId)); 47 if (*store == NULL) 48 (*store) = NewChromePrefsAccessTokenStore(); 49 (*store)->LoadAccessTokens(consumer, callback); 50 } 51 52 struct TokenLoadClientForTest { 53 void NotReachedCallback(AccessTokenStore::AccessTokenSet /*tokens*/) { 54 NOTREACHED() << "This request should have been canceled before callback"; 55 } 56 }; 57 58 void RunCancelTestInClientTread() { 59 ASSERT_TRUE(BrowserThread::CurrentlyOn(kExpectedClientThreadId)); 60 scoped_refptr<AccessTokenStore> store(NewChromePrefsAccessTokenStore()); 61 CancelableRequestConsumer consumer; 62 TokenLoadClientForTest load_client; 63 64 // Single request, canceled explicitly 65 CancelableRequestProvider::Handle first_handle = 66 store->LoadAccessTokens(&consumer, NewCallback( 67 &load_client, &TokenLoadClientForTest::NotReachedCallback)); 68 EXPECT_TRUE(consumer.HasPendingRequests()); 69 // Test this handle is valid. 70 consumer.GetClientData(store.get(), first_handle); 71 store->CancelRequest(first_handle); 72 EXPECT_FALSE(consumer.HasPendingRequests()); 73 74 // 2 requests, canceled globally. 75 store->LoadAccessTokens(&consumer, NewCallback( 76 &load_client, &TokenLoadClientForTest::NotReachedCallback)); 77 store->LoadAccessTokens(&consumer, NewCallback( 78 &load_client, &TokenLoadClientForTest::NotReachedCallback)); 79 EXPECT_TRUE(consumer.HasPendingRequests()); 80 EXPECT_EQ(2u, consumer.PendingRequestCount()); 81 consumer.CancelAllRequests(); 82 EXPECT_FALSE(consumer.HasPendingRequests()); 83 EXPECT_EQ(0u, consumer.PendingRequestCount()); 84 85 BrowserThread::PostTask( 86 BrowserThread::UI, FROM_HERE, new MessageLoop::QuitTask); 87 } 88 89 void GeolocationAccessTokenStoreTest::DoTestStepAndWaitForResults( 90 const char* ref_url, const string16* token_to_expect, 91 const string16* token_to_set) { 92 ref_url_ = GURL(ref_url); 93 token_to_expect_ = token_to_expect; 94 token_to_set_ = token_to_set; 95 96 BrowserThread::PostTask( 97 kExpectedClientThreadId, FROM_HERE, NewRunnableFunction( 98 &StartTestStepFromClientThread, &token_store_, &request_consumer_, 99 NewCallback(this, 100 &GeolocationAccessTokenStoreTest::OnAccessTokenStoresLoaded))); 101 ui_test_utils::RunMessageLoop(); 102 } 103 104 void GeolocationAccessTokenStoreTest::OnAccessTokenStoresLoaded( 105 AccessTokenStore::AccessTokenSet access_token_set) { 106 ASSERT_TRUE(BrowserThread::CurrentlyOn(kExpectedClientThreadId)) 107 << "Callback from token factory should be from the same thread as the " 108 "LoadAccessTokenStores request was made on"; 109 EXPECT_TRUE(token_to_set_ || token_to_expect_) << "No work to do?"; 110 AccessTokenStore::AccessTokenSet::const_iterator item = 111 access_token_set.find(ref_url_); 112 if (!token_to_expect_) { 113 EXPECT_TRUE(item == access_token_set.end()); 114 } else { 115 EXPECT_FALSE(item == access_token_set.end()); 116 EXPECT_EQ(*token_to_expect_, item->second); 117 } 118 119 if (token_to_set_) { 120 scoped_refptr<AccessTokenStore> store( 121 NewChromePrefsAccessTokenStore()); 122 store->SaveAccessToken(ref_url_, *token_to_set_); 123 } 124 BrowserThread::PostTask( 125 BrowserThread::UI, FROM_HERE, new MessageLoop::QuitTask); 126 } 127 128 IN_PROC_BROWSER_TEST_F(GeolocationAccessTokenStoreTest, SetAcrossInstances) { 129 const string16 ref_token1 = ASCIIToUTF16("jksdfo90,'s#\"#1*("); 130 const string16 ref_token2 = ASCIIToUTF16("\1\2\3\4\5\6\7\10\11\12=023"); 131 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); 132 133 DoTestStepAndWaitForResults(kRefServerUrl1, NULL, &ref_token1); 134 // Check it was set, and change to new value. 135 DoTestStepAndWaitForResults(kRefServerUrl1, &ref_token1, &ref_token2); 136 // And change back. 137 DoTestStepAndWaitForResults(kRefServerUrl1, &ref_token2, &ref_token1); 138 DoTestStepAndWaitForResults(kRefServerUrl1, &ref_token1, NULL); 139 140 // Set a second server URL 141 DoTestStepAndWaitForResults(kRefServerUrl2, NULL, &ref_token2); 142 DoTestStepAndWaitForResults(kRefServerUrl2, &ref_token2, NULL); 143 DoTestStepAndWaitForResults(kRefServerUrl1, &ref_token1, NULL); 144 } 145 146 IN_PROC_BROWSER_TEST_F(GeolocationAccessTokenStoreTest, CancelRequest) { 147 BrowserThread::PostTask( 148 kExpectedClientThreadId, FROM_HERE, NewRunnableFunction( 149 RunCancelTestInClientTread)); 150 ui_test_utils::RunMessageLoop(); 151 } 152 153 } // namespace 154