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

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

Issue 10491010: Reland r140188: CommandLine Page Cycler (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 6 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 | Annotate | Revision Log
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_number_conversions.h"
13 #include "base/string_split.h"
14 #include "base/utf_string_conversions.h"
15 #include "chrome/app/chrome_command_ids.h"
16 #include "chrome/common/chrome_notification_types.h"
17 #include "chrome/test/base/chrome_process_util.h"
18 #include "chrome/test/perf/perf_test.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/notification_service.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/common/url_constants.h"
24
25 using content::NavigationController;
26 using content::OpenURLParams;
27 using content::Referrer;
28 using content::WebContents;
29
30 PageCycler::PageCycler(Browser* browser,
31 FilePath urls_file)
32 : content::WebContentsObserver(browser->GetSelectedWebContents()),
33 browser_(browser),
34 urls_file_(urls_file),
35 url_index_(0),
36 total_iterations_(0),
37 current_iteration_(0),
38 aborted_(false) {
39 BrowserList::AddObserver(this);
40 AddRef(); // Balanced in Finish()/Abort() (only one should be called).
41 }
42
43 PageCycler::~PageCycler() {
44 }
45
46 bool PageCycler::IsLoadCallbackValid(const GURL& validated_url,
47 bool is_main_frame) {
48 // If |url_index_| is equal to zero, that means that this was called before
49 // LoadNextURL() - this can happen at startup, loading the new tab page; or
50 // if the user specified a bad url as the final url in the list. In these
51 // cases, do not report success or failure, and load the next page.
52 if (!url_index_) {
53 LoadNextURL();
54 return false;
55 }
56 return (is_main_frame &&
57 validated_url.spec() != content::kUnreachableWebDataURL);
58 }
59
60 void PageCycler::DidFinishLoad(int64 frame_id,
61 const GURL& validated_url,
62 bool is_main_frame) {
63 if (IsLoadCallbackValid(validated_url, is_main_frame))
64 LoadSucceeded();
65 }
66
67 void PageCycler::DidFailProvisionalLoad(
68 int64 frame_id,
69 bool is_main_frame,
70 const GURL& validated_url,
71 int error_code,
72 const string16& error_description,
73 content::RenderViewHost* render_view_host) {
74 if (IsLoadCallbackValid(validated_url, is_main_frame))
75 LoadFailed(validated_url, error_description);
76 }
77
78 void PageCycler::Run(const int& total_iterations) {
79 total_iterations_ = total_iterations;
80 if (browser_)
81 content::BrowserThread::PostBlockingPoolTask(
82 FROM_HERE,
83 base::Bind(&PageCycler::ReadURLsOnBackgroundThread, this));
84 }
85
86 void PageCycler::ReadURLsOnBackgroundThread() {
87 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
88
89 std::string file_contents;
90 std::vector<std::string> url_strings;
91
92 CHECK(file_util::PathExists(urls_file_)) << urls_file_.value();
93 file_util::ReadFileToString(urls_file_, &file_contents);
94 base::SplitStringAlongWhitespace(file_contents, &url_strings);
95
96 if (!url_strings.size()) {
97 #if defined(OS_POSIX)
98 error_.append(ASCIIToUTF16("Page Cycler: No URLs in given file: " +
99 urls_file_.value()));
100 #elif defined(OS_WIN)
101 error_.append(ASCIIToUTF16("Page Cycler: No URLs in given file: "))
102 .append(urls_file_.value());
103 #endif // OS_WIN
104 }
105
106 for (std::vector<std::string>::const_iterator iter = url_strings.begin();
107 iter != url_strings.end(); ++iter) {
108 GURL gurl(*iter);
109 if (!gurl.is_valid())
110 error_.append(ASCIIToUTF16("Omitting invalid URL: " + *iter + ".\n"));
111 // Since we don't count kUnreachableWebData as a valid load, we don't want
112 // the user to specify this as one of the pages to visit.
113 else if (*iter == content::kUnreachableWebDataURL) {
114 error_.append(ASCIIToUTF16(
115 "Chrome error pages are not allowed as urls. Omitting url: " +
116 *iter + ".\n"));
117 } else {
118 urls_.push_back(gurl);
119 }
120 }
121
122 content::BrowserThread::PostTask(content::BrowserThread::UI,
123 FROM_HERE,
124 base::Bind(&PageCycler::BeginCycle, this));
125 }
126
127 void PageCycler::BeginCycle() {
128 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
129
130 CHECK(browser_);
131 // Upon launch, Chrome will automatically load the newtab page. This can
132 // result in the browser being in a state of loading when PageCycler is ready
133 // to start. Instead of interrupting the load, we wait for it to finish, and
134 // will call LoadNextURL() from DidFinishLoad() or DidFailProvisionalLoad().
135 if (browser_->GetSelectedWebContents()->IsLoading())
136 return;
137 LoadNextURL();
138 }
139
140 void PageCycler::LoadNextURL() {
141 CHECK(browser_);
142 if (url_index_ >= urls_.size()) {
143 if (current_iteration_ < total_iterations_ - 1) {
144 ++current_iteration_;
145 url_index_ = 0;
146 } else {
147 content::BrowserThread::PostBlockingPoolTask(
148 FROM_HERE,
149 base::Bind(&PageCycler::PrepareResultsOnBackgroundThread, this));
150 return;
151 }
152 }
153 if (url_index_ || current_iteration_) {
154 timings_string_.append(", ");
155 urls_string_.append(", ");
156 }
157 urls_string_.append(urls_[url_index_].spec());
158 initial_time_ = base::TimeTicks::HighResNow();
159 OpenURLParams params(urls_[url_index_],
160 Referrer(),
161 CURRENT_TAB,
162 content::PAGE_TRANSITION_TYPED,
163 false);
164 ++url_index_;
165 browser_->OpenURL(params);
166 }
167
168 void PageCycler::LoadSucceeded() {
169 base::TimeDelta time_elapsed =
170 (base::TimeTicks::HighResNow() - initial_time_) / 1000.0;
171 timings_string_.append(base::Int64ToString(time_elapsed.ToInternalValue()));
172 LoadNextURL();
173 }
174
175 void PageCycler::LoadFailed(const GURL& url,
176 const string16& error_description) {
177 error_.append(ASCIIToUTF16("Failed to load the page at: " +
178 url.spec() + ": ")).append(error_description).
179 append(ASCIIToUTF16("\n"));
180 base::TimeDelta time_elapsed =
181 (base::TimeTicks::HighResNow() - initial_time_) / 1000.0;
182 timings_string_.append(base::Int64ToString(time_elapsed.ToInternalValue()) +
183 (" (failed)"));
184 LoadNextURL();
185 }
186
187 void PageCycler::PrepareResultsOnBackgroundThread() {
188 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
189 std::string output;
190 if (!stats_file_.empty()) {
191 #if defined(OS_POSIX)
192 base::ProcessId pid = base::GetParentProcessId(base::GetCurrentProcId());
193 #elif defined(OS_WIN)
194 base::ProcessId pid = base::GetCurrentProcId();
195 #endif // OS_WIN
196 ChromeProcessList chrome_processes(GetRunningChromeProcesses(pid));
197 output += perf_test::MemoryUsageInfoToString("", chrome_processes, pid);
198 output += perf_test::IOPerfInfoToString("", chrome_processes, pid);
199 output += perf_test::SystemCommitChargeToString("",
200 base::GetSystemCommitCharge(), false);
201 output.append("Pages: [" + urls_string_ + "]\n");
202 output.append("*RESULT times: t_ref= [" + timings_string_ + "] ms\n");
203 }
204 WriteResultsOnBackgroundThread(output);
205 }
206
207 void PageCycler::WriteResultsOnBackgroundThread(std::string output) {
208 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
209
210 if (!output.empty()) {
211 CHECK(!stats_file_.empty());
212 file_util::WriteFile(stats_file_, output.c_str(), output.size());
213 }
214 if (!errors_file_.empty()) {
215 if (!error_.empty()) {
216 file_util::WriteFile(errors_file_, UTF16ToUTF8(error_).c_str(),
217 error_.size());
218 } else if (file_util::PathExists(errors_file_)) {
219 // If there is an old error file, delete it to avoid confusion.
220 file_util::Delete(errors_file_, false);
221 }
222 }
223 if (aborted_) {
224 content::BrowserThread::PostTask(content::BrowserThread::UI,
225 FROM_HERE,
226 base::Bind(&PageCycler::Abort, this));
227 } else {
228 content::BrowserThread::PostTask(content::BrowserThread::UI,
229 FROM_HERE,
230 base::Bind(&PageCycler::Finish, this));
231 }
232 }
233
234 void PageCycler::Finish() {
235 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
236 BrowserList::RemoveObserver(this);
237 browser_->OnWindowClosing();
238 browser_->ExecuteCommand(IDC_EXIT);
239 Release(); // Balanced in PageCycler constructor;
240 // (only one of Finish/Abort should be called).
241 }
242
243 void PageCycler::Abort() {
244 browser_ = NULL;
245 BrowserList::RemoveObserver(this);
246 Release(); // Balanced in PageCycler constructor;
247 // (only one of Finish/Abort should be called).
248 }
249
250 void PageCycler::OnBrowserAdded(Browser* browser) {}
251
252 void PageCycler::OnBrowserRemoved(Browser* browser) {
253 if (browser == browser_) {
254 aborted_ = true;
255 error_.append(ASCIIToUTF16(
256 "Browser was closed before the run was completed."));
257 DLOG(WARNING) <<
258 "Page Cycler: browser was closed before the run was completed.";
259 content::BrowserThread::PostBlockingPoolTask(
260 FROM_HERE,
261 base::Bind(&PageCycler::PrepareResultsOnBackgroundThread, this));
262 }
263 }
OLDNEW
« no previous file with comments | « chrome/browser/page_cycler/page_cycler.h ('k') | chrome/browser/page_cycler/page_cycler_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698