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