1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/data_usage/tab_id_annotator.h"
#include <stdint.h>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/time/time.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "components/data_usage/core/data_use.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/web_contents.h"
#include "net/base/network_change_notifier.h"
#include "net/base/request_priority.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using content::BrowserThread;
using data_usage::DataUse;
namespace chrome_browser_data_usage {
namespace {
class TabIdAnnotatorTest : public ChromeRenderViewHostTestHarness {
public:
TabIdAnnotatorTest() {
// Cannot use IO_MAIN_LOOP with RenderViewHostTestHarness.
SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD);
}
~TabIdAnnotatorTest() override {}
private:
DISALLOW_COPY_AND_ASSIGN(TabIdAnnotatorTest);
};
// Synthesizes a DataUse object with the given |tab_id|.
scoped_ptr<DataUse> CreateDataUse(int32_t tab_id) {
return scoped_ptr<DataUse>(new DataUse(
GURL("http://foo.com"), base::TimeTicks(), GURL(), tab_id,
net::NetworkChangeNotifier::CONNECTION_UNKNOWN, std::string(), 100, 100));
}
// Expects that |expected| and |actual| are equal.
void ExpectDataUse(scoped_ptr<DataUse> expected, scoped_ptr<DataUse> actual) {
// Single out the |tab_id| for better debug output in failure cases.
EXPECT_EQ(expected->tab_id, actual->tab_id);
EXPECT_EQ(*expected, *actual);
}
// Expects that |expected| and |actual| are equal, then quits |ui_run_loop| on
// the UI thread.
void ExpectDataUseAndQuit(base::RunLoop* ui_run_loop,
scoped_ptr<DataUse> expected,
scoped_ptr<DataUse> actual) {
DCHECK(ui_run_loop);
ExpectDataUse(std::move(expected), std::move(actual));
// This can't use run_loop->QuitClosure here because that uses WeakPtrs, which
// aren't thread safe.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&base::RunLoop::Quit, base::Unretained(ui_run_loop)));
}
// Tests that for a sample URLRequest, associated with the given
// |render_process_id| and |render_frame_id|, repeatedly annotating DataUse for
// that URLRequest yields the |expected_tab_id|. |ui_run_loop| is the RunLoop on
// the UI thread that should be quit after all the annotations are done.
// Passing in -1 for either or both of |render_process_id| or |render_frame_id|
// indicates that the URLRequest should have no associated ResourceRequestInfo.
void TestAnnotateOnIOThread(base::RunLoop* ui_run_loop,
int render_process_id,
int render_frame_id,
int32_t expected_tab_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(ui_run_loop);
TabIdAnnotator annotator;
net::TestURLRequestContext context;
net::TestDelegate test_delegate;
scoped_ptr<net::URLRequest> request =
context.CreateRequest(GURL("http://foo.com"), net::IDLE, &test_delegate);
if (render_process_id != -1 && render_frame_id != -1) {
// The only args that matter here for the ResourceRequestInfo are the
// |request|, the |render_process_id|, and the |render_frame_id|; arbitrary
// values are used for all the other args.
content::ResourceRequestInfo::AllocateForTesting(
request.get(), content::RESOURCE_TYPE_MAIN_FRAME, nullptr,
render_process_id, -1, render_frame_id, true, false, true, true, false);
}
// An invalid tab ID to check that the annotator always sets the tab ID. -2 is
// used because a tab ID of -1 is a valid value that means "no tab was found".
const int32_t kInvalidTabId = -2;
// Annotate two separate DataUse objects to ensure that repeated annotations
// for the same URLRequest work properly.
scoped_ptr<DataUse> first_expected_data_use = CreateDataUse(expected_tab_id);
annotator.Annotate(
request.get(), CreateDataUse(kInvalidTabId),
base::Bind(&ExpectDataUse, base::Passed(&first_expected_data_use)));
// Quit the |ui_run_loop| after the second annotation.
scoped_ptr<DataUse> second_expected_data_use = CreateDataUse(expected_tab_id);
annotator.Annotate(request.get(), CreateDataUse(kInvalidTabId),
base::Bind(&ExpectDataUseAndQuit, ui_run_loop,
base::Passed(&second_expected_data_use)));
}
TEST_F(TabIdAnnotatorTest, AnnotateWithNoRenderFrame) {
base::RunLoop ui_run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&TestAnnotateOnIOThread, &ui_run_loop,
-1 /* render_process_id */, -1 /* render_frame_id */,
-1 /* expected_tab_id */));
ui_run_loop.Run();
}
TEST_F(TabIdAnnotatorTest, AnnotateWithRenderFrameAndNoTab) {
base::RunLoop ui_run_loop;
// |web_contents()| isn't a tab, so it shouldn't have a tab ID.
EXPECT_EQ(-1, SessionTabHelper::IdForTab(web_contents()));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&TestAnnotateOnIOThread, &ui_run_loop,
web_contents()->GetMainFrame()->GetProcess()->GetID(),
web_contents()->GetMainFrame()->GetRoutingID(),
-1 /* expected_tab_id */));
ui_run_loop.Run();
}
TEST_F(TabIdAnnotatorTest, AnnotateWithRenderFrameAndTab) {
base::RunLoop ui_run_loop;
// Make |web_contents()| into a tab.
SessionTabHelper::CreateForWebContents(web_contents());
int32_t expected_tab_id = SessionTabHelper::IdForTab(web_contents());
// |web_contents()| is a tab, so it should have a tab ID.
EXPECT_NE(-1, expected_tab_id);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&TestAnnotateOnIOThread, &ui_run_loop,
web_contents()->GetMainFrame()->GetProcess()->GetID(),
web_contents()->GetMainFrame()->GetRoutingID(),
expected_tab_id));
ui_run_loop.Run();
}
} // namespace
} // namespace chrome_browser_data_usage
|