Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Side by Side Diff: chrome/browser/page_cycler/page_cycler.cc

Issue 9667009: CommandLine Page Cycler (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: PageCycler CommandLine Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/page_cycler/page_cycler.h"
6
7 #include "base/bind.h"
8 #include "base/file_path.h"
9 #include "base/file_util.h"
10 #include "base/message_loop.h"
11 #include "base/process_util.h"
12 #include "base/string_split.h"
13 #include "base/string_number_conversions.h"
14 #include "base/utf_string_conversions.h"
15 #include "chrome/common/chrome_notification_types.h"
16 #include "chrome/test/base/chrome_process_util.h"
17 #include "chrome/test/perf/perf_test.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/notification_source.h"
20 #include "content/public/browser/notification_service.h"
21 #include "content/public/browser/notification_details.h"
22 #include "content/public/browser/notification_types.h"
23 #include "content/public/browser/web_contents.h"
24 #include "content/public/common/url_constants.h"
25
26 using content::NavigationController;
27 using content::OpenURLParams;
28 using content::Referrer;
29 using content::WebContents;
30
31 PageCycler::PageCycler(Browser* browser,
32 FilePath urls_file,
33 FilePath errors_file)
34 : content::WebContentsObserver(browser->GetSelectedWebContents()),
35 browser_(browser),
36 urls_file_(urls_file),
37 errors_file_(errors_file),
38 url_index_(0),
39 iterations_(0) {
40 Init();
41 }
42
43 PageCycler::PageCycler(Browser* browser,
44 FilePath urls_file,
45 FilePath errors_file,
46 FilePath stats_file)
47 : content::WebContentsObserver(browser->GetSelectedWebContents()),
48 browser_(browser),
49 urls_file_(urls_file),
50 errors_file_(errors_file),
51 stats_file_(stats_file),
52 url_index_(0),
53 iterations_(0) {
54 Init();
55 }
56
57 PageCycler::~PageCycler() {
58 }
59
60 void PageCycler::Init() {
61 BrowserList::AddObserver(this);
62 AddRef(); // Balanced in Finish()/Abort() (only one should be called).
63 }
64
65 void PageCycler::DidFinishLoad(int64 frame_id,
66 const GURL& validated_url,
67 bool is_main_frame) {
68 // In the event of certain load failures, chrome will load the error page
69 // kUnreachableWebDataURL. We do not want to count this as a load success or
70 // failure, because it will throw off the count.
71 if (is_main_frame && validated_url.spec() != chrome::kUnreachableWebDataURL)
Aaron Boodman 2012/03/20 19:28:16 Man, that is a bummer. It would be easy for code e
72 LoadSucceeded();
73 }
74
75 void PageCycler::DidFailProvisionalLoad(int64 frame_id,
76 bool is_main_frame,
77 const GURL& validated_url,
78 int error_code,
79 const string16& error_description) {
80 // In the event of certain load failures, chrome will load the error page
81 // kUnreachableWebDataURL. We do not want to count this as a load success or
82 // failure, because it will throw off the count.
83 if (is_main_frame && validated_url.spec() != chrome::kUnreachableWebDataURL)
84 LoadFailed(validated_url, error_description);
85 }
86
87 void PageCycler::Run(unsigned int iterations) {
88 iterations_ = iterations;
89 content::BrowserThread::PostBlockingPoolTask(
90 FROM_HERE,
91 base::Bind(&PageCycler::ReadURLsOnBackgroundThread, this));
92 }
93
94 void PageCycler::ReadURLsOnBackgroundThread() {
95 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
96 std::string file_contents;
97 std::vector<std::string> url_strings;
98
99 CHECK(file_util::PathExists(urls_file_));
100 file_util::ReadFileToString(urls_file_, &file_contents);
101 base::SplitStringAlongWhitespace(file_contents, &url_strings);
102
103 if (!url_strings.size())
104 DLOG(WARNING) << "Page Cycler: No URLs in given file: " <<
105 urls_file_.value();
106
107 for (std::vector<std::string>::const_iterator iter = url_strings.begin();
108 iter != url_strings.end(); ++iter) {
109 // Since we don't count kUnreachableWebData as a valid load, we don't want
110 // the user to specify this as one of the pages to visit.
111 if (*iter == chrome::kUnreachableWebDataURL) {
112 DLOG(WARNING) << "Chrome error pages are not allowed as urls." <<
113 "Omitting url: " << *iter << ".";
114 } else {
115 urls_.push_back(GURL(*iter));
116 }
117 }
118
119 content::BrowserThread::PostTask(content::BrowserThread::UI,
120 FROM_HERE,
121 base::Bind(&PageCycler::BeginCycle, this));
122 }
123
124 void PageCycler::BeginCycle() {
125 CHECK(iterations_);
126 --iterations_;
127 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
128
129 // Upon launch, Chrome will automatically load the newtab page. This results
130 // in the browser most likely (but not definitely) being in a state of loading
131 // when PageCycler is ready to start. If we load the next URL when it is
132 // already trying to load, this will result in a page-load error for the
133 // previous URL (in this case, newtab); this will call LoadFailed(), and the
134 // first page of the url list will be skipped. If we are loading, we wait for
135 // the load to finish, which will then call LoadSucceeded() or LoadFailed(),
136 // and subsequently call LoadNextURL(). If we are not loading, we are safe to
137 // begin the cycle now.
138 if (browser_->GetSelectedWebContents()->IsLoading())
139 return;
140
141 LoadNextURL();
142 }
143
144 void PageCycler::LoadNextURL() {
145 CHECK(browser_);
146 if (url_index_ >= urls_.size()) {
147 if (iterations_) {
148 url_index_ = 0;
149 BeginCycle();
150 return;
151 } else {
152 PrepareResults();
153 return;
154 }
155 }
156
157 if (url_index_) {
158 timings_string_.append(", ");
159 urls_string_.append(", ");
160 }
161 urls_string_.append(urls_[url_index_].spec());
162 initial_time_ = base::TimeTicks::HighResNow();
163 OpenURLParams params(urls_[url_index_],
164 Referrer(),
165 CURRENT_TAB,
166 content::PAGE_TRANSITION_TYPED,
167 false);
168 ++url_index_;
169 browser_->OpenURL(params);
170 }
171
172 void PageCycler::LoadSucceeded() {
173 base::TimeDelta time_elapsed =
174 (base::TimeTicks::HighResNow() - initial_time_) / 1000.0;
175 timings_string_.append(base::Int64ToString(time_elapsed.ToInternalValue()));
176 LoadNextURL();
177 }
178
179 void PageCycler::LoadFailed(const GURL& url,
180 const string16& error_description) {
181 error_.append(ASCIIToUTF16("Failed to load the page at: " +
182 url.spec() + ": ")).append(error_description).
183 append(ASCIIToUTF16("\n"));
184 LoadNextURL();
185 }
186
187 void PageCycler::PrepareResults() {
188 std::string output;
189 if (!stats_file_.empty()) {
190 base::ProcessId pid = base::GetParentProcessId(base::GetCurrentProcId());
191 ChromeProcessList chrome_processes(GetRunningChromeProcesses(pid));
192 output += perf_test::MemoryUsageInfoToString("", chrome_processes, pid);
193 output += perf_test::IOPerfInfoToString("", chrome_processes, pid);
194 output += perf_test::SystemCommitChargeToString("",
195 base::GetSystemCommitCharge(), false);
196 output.append("Pages: [" + urls_string_ + "]\n");
197 output.append("*RESULT times: t_ref= [" + timings_string_ + "] ms\n");
198 }
199 content::BrowserThread::PostBlockingPoolTask(
200 FROM_HERE,
201 base::Bind(&PageCycler::WriteResultsOnBackgroundThread, this, output));
202 }
203
204 void PageCycler::WriteResultsOnBackgroundThread(std::string output) {
205 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
206 if (!output.empty()) {
207 CHECK(!stats_file_.empty());
208 file_util::WriteFile(stats_file_, output.c_str(), output.size());
209 }
210 CHECK(!errors_file_.empty());
211 if (!error_.empty()) {
212 file_util::WriteFile(errors_file_, UTF16ToUTF8(error_).c_str(),
213 error_.size());
214 } else if (file_util::PathExists(errors_file_)) {
215 // If there is an old error file, delete it to avoid confusion.
216 file_util::Delete(errors_file_, false);
217 }
218 content::BrowserThread::PostTask(content::BrowserThread::UI,
219 FROM_HERE,
220 base::Bind(&PageCycler::Finish, this));
221 }
222
223 void PageCycler::Finish() {
224 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
225 BrowserList::RemoveObserver(this);
226 browser_->Exit();
227 Release(); // Balanced in Init() (only one of Finish/Abort should be called).
228 }
229
230 void PageCycler::Abort() {
231 browser_ = NULL;
232 BrowserList::RemoveObserver(this);
233 Release(); // Balanced in Init() (only one of Finish/Abort should be called).
234 }
235
236 void PageCycler::OnBrowserAdded(const Browser* browser) {}
237
238 void PageCycler::OnBrowserRemoved(const Browser* browser) {
239 if (browser == browser_) {
240 DLOG(WARNING) <<
241 "Page Cycler: browser was closed before the run was completed.";
242 MessageLoop::current()->PostTask(FROM_HERE,
243 base::Bind(&PageCycler::Abort, this));
244 }
245 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698