OLD | NEW |
| (Empty) |
1 // Copyright (c) 2006-2008 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/tab_contents/network_status_view.h" | |
6 | |
7 #include <stdio.h> | |
8 | |
9 #include "base/string_util.h" | |
10 #include "base/thread.h" | |
11 #include "chrome/browser/browser.h" | |
12 #include "chrome/browser/browser_process.h" | |
13 #include "chrome/browser/tab_contents/tab_contents_delegate.h" | |
14 #include "chrome/views/root_view.h" | |
15 #include "net/url_request/url_request.h" | |
16 #include "net/url_request/url_request_job.h" | |
17 | |
18 namespace { | |
19 const wchar_t kTitleMsg[] = L"Network Status"; | |
20 const wchar_t kStartTrackingMsg[] = L"Start I/O Tracking"; | |
21 const wchar_t kStopTrackingMsg[] = L"Stop I/O Tracking"; | |
22 | |
23 const wchar_t kShowIOStatusMsg[] = L"Show Current I/O Status"; | |
24 const wchar_t kClearOutputMsg[] = L"Clear Output"; | |
25 | |
26 // Returns a string representing the URL, handling the case where the spec | |
27 // is invalid. | |
28 std::wstring StringForURL(const GURL& url) { | |
29 if (url.is_valid()) | |
30 return UTF8ToWide(url.spec()); | |
31 return UTF8ToWide(url.possibly_invalid_spec()) + L" (invalid)"; | |
32 } | |
33 | |
34 std::wstring URLForJob(URLRequestJob* job) { | |
35 URLRequest* request = job->request(); | |
36 if (request) | |
37 return StringForURL(request->url()); | |
38 return std::wstring(L"(orphaned)"); | |
39 } | |
40 | |
41 } // namespace | |
42 | |
43 NetworkStatusView::NetworkStatusView() | |
44 : StatusView(TAB_CONTENTS_NETWORK_STATUS_VIEW) { | |
45 tracker_ = new JobTracker(this); | |
46 } | |
47 | |
48 NetworkStatusView::~NetworkStatusView() { | |
49 if (monospaced_font_) | |
50 DeleteObject(monospaced_font_); | |
51 | |
52 if (is_tracking_) { | |
53 tracker_->StopTracking(); | |
54 is_tracking_ = false; | |
55 } | |
56 | |
57 tracker_->DetachView(); | |
58 } | |
59 | |
60 const std::wstring NetworkStatusView::GetDefaultTitle() { | |
61 return kTitleMsg; | |
62 } | |
63 | |
64 void NetworkStatusView::OnCreate(const CRect& rect) { | |
65 CreateButton(IDC_CONFIG_TRACKING_BUTTON, kStartTrackingMsg); | |
66 CreateButton(IDC_CURRENT_STATUS_BUTTON, kShowIOStatusMsg); | |
67 CreateButton(IDC_CLEAR, kClearOutputMsg); | |
68 | |
69 is_tracking_ = false; | |
70 | |
71 // Initialize the text box for network tracking | |
72 // Don't worry about the size, we'll resize when we get WM_SIZE | |
73 text_area_.Create(m_hWnd, const_cast<CRect&>(rect), NULL, | |
74 WS_CHILD | WS_HSCROLL | WS_VSCROLL | | |
75 ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0); | |
76 | |
77 // This raises the maximum number of chars from 32K to some large maximum, | |
78 // probably 2GB. 32K is not nearly enough for our use-case. | |
79 text_area_.SendMessageW(EM_SETLIMITTEXT, 0, 0); | |
80 | |
81 // make a monospaced font for the edit control | |
82 LOGFONT lf = {0}; | |
83 lf.lfHeight = 16; | |
84 wcscpy_s(lf.lfFaceName, LF_FACESIZE, L"Courier New"); | |
85 monospaced_font_ = CreateFontIndirect(&lf); | |
86 text_area_.SetFont(monospaced_font_); | |
87 } | |
88 | |
89 void NetworkStatusView::OnSize(const CRect& rect) { | |
90 // re-layout the edit control | |
91 text_area_.MoveWindow(rect); | |
92 | |
93 // re-layout the performance view | |
94 CRect new_rect(rect); | |
95 int list_width = rect.Width(); | |
96 int list_height = static_cast<int>(rect.Height() / 5); | |
97 int page_width = rect.Width() / 2; | |
98 int page_height = static_cast<int>(rect.Height() * 4 / 5); | |
99 } | |
100 | |
101 void NetworkStatusView::OnConfigTrackingClicked(UINT code, int button_id, | |
102 HWND hwnd) { | |
103 if (is_tracking_) { | |
104 tracker_->StopTracking(); | |
105 is_tracking_ = false; | |
106 | |
107 SetButtonText(IDC_CONFIG_TRACKING_BUTTON, kStartTrackingMsg); | |
108 } else { | |
109 tracker_->StartTracking(); | |
110 is_tracking_ = true; | |
111 | |
112 ClearTrackingResults(); | |
113 ShowTrackingResults(); | |
114 | |
115 SetButtonText(IDC_CONFIG_TRACKING_BUTTON, kStopTrackingMsg); | |
116 } | |
117 } | |
118 | |
119 void NetworkStatusView::OnCurrentStatusClicked(UINT code, int button_id, | |
120 HWND hwnd) { | |
121 ShowTrackingResults(); | |
122 if (is_tracking_) { | |
123 tracker_->ReportStatus(); | |
124 } | |
125 } | |
126 | |
127 void NetworkStatusView::OnClearClicked(UINT code, int button_id, HWND hwnd) { | |
128 ClearTrackingResults(); | |
129 } | |
130 | |
131 void NetworkStatusView::AppendText(const std::wstring& text) { | |
132 text_area_.AppendText(text.c_str()); | |
133 } | |
134 | |
135 void NetworkStatusView::HideTrackingResults() { | |
136 text_area_.ShowWindow(SW_HIDE); | |
137 } | |
138 | |
139 void NetworkStatusView::ShowTrackingResults() { | |
140 text_area_.ShowWindow(SW_SHOW); | |
141 } | |
142 | |
143 void NetworkStatusView::ClearTrackingResults() { | |
144 text_area_.SetSelAll(); | |
145 text_area_.Clear(); | |
146 } | |
147 | |
148 //----------------------------------------------------------------------------- | |
149 | |
150 // main thread: | |
151 NetworkStatusView::JobTracker::JobTracker(NetworkStatusView* view) | |
152 : view_(view), | |
153 view_message_loop_(MessageLoop::current()) { | |
154 } | |
155 | |
156 // main thread: | |
157 void NetworkStatusView::JobTracker::InvokeOnIOThread(void (JobTracker::*m)()) { | |
158 base::Thread* thread = g_browser_process->io_thread(); | |
159 if (!thread) | |
160 return; | |
161 thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, m)); | |
162 } | |
163 | |
164 // main thread: | |
165 void NetworkStatusView::JobTracker::StartTracking() { | |
166 DCHECK(MessageLoop::current() == view_message_loop_); | |
167 DCHECK(view_); | |
168 InvokeOnIOThread(&JobTracker::OnStartTracking); | |
169 } | |
170 | |
171 // main thread: | |
172 void NetworkStatusView::JobTracker::StopTracking() { | |
173 DCHECK(MessageLoop::current() == view_message_loop_); | |
174 // The tracker should not be deleted before it is removed from observer | |
175 // list. | |
176 AddRef(); | |
177 InvokeOnIOThread(&JobTracker::OnStopTracking); | |
178 } | |
179 | |
180 // main thread: | |
181 void NetworkStatusView::JobTracker::ReportStatus() { | |
182 DCHECK(MessageLoop::current() == view_message_loop_); | |
183 InvokeOnIOThread(&JobTracker::OnReportStatus); | |
184 } | |
185 | |
186 // main thread: | |
187 void NetworkStatusView::JobTracker::OnAppendText(const std::wstring& text) { | |
188 DCHECK(MessageLoop::current() == view_message_loop_); | |
189 if (view_ && view_->is_tracking_) | |
190 view_->AppendText(text); | |
191 } | |
192 | |
193 // IO thread: | |
194 void NetworkStatusView::JobTracker::AppendText(const std::wstring& text) { | |
195 DCHECK(MessageLoop::current() != view_message_loop_); | |
196 view_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
197 this, &JobTracker::OnAppendText, text)); | |
198 } | |
199 | |
200 // IO thread: | |
201 void NetworkStatusView::JobTracker::OnStartTracking() { | |
202 DCHECK(MessageLoop::current() != view_message_loop_); | |
203 g_url_request_job_tracker.AddObserver(this); | |
204 } | |
205 | |
206 // IO thread: | |
207 void NetworkStatusView::JobTracker::OnStopTracking() { | |
208 DCHECK(MessageLoop::current() != view_message_loop_); | |
209 g_url_request_job_tracker.RemoveObserver(this); | |
210 // Balance the AddRef() in StopTracking() called in main thread. | |
211 Release(); | |
212 } | |
213 | |
214 // IO thread: | |
215 void NetworkStatusView::JobTracker::OnReportStatus() { | |
216 DCHECK(MessageLoop::current() != view_message_loop_); | |
217 | |
218 std::wstring text(L"\r\n===== Active Job Summary =====\r\n"); | |
219 | |
220 URLRequestJobTracker::JobIterator begin_job = | |
221 g_url_request_job_tracker.begin(); | |
222 URLRequestJobTracker::JobIterator end_job = g_url_request_job_tracker.end(); | |
223 int orphaned_count = 0; | |
224 int regular_count = 0; | |
225 for (URLRequestJobTracker::JobIterator cur = begin_job; | |
226 cur != end_job; ++cur) { | |
227 URLRequestJob* job = (*cur); | |
228 URLRequest* request = job->request(); | |
229 if (!request) { | |
230 orphaned_count++; | |
231 continue; | |
232 } | |
233 | |
234 regular_count++; | |
235 | |
236 // active state | |
237 if (job->is_done()) | |
238 text.append(L" Done: "); | |
239 else | |
240 text.append(L" Active: "); | |
241 | |
242 // URL | |
243 text.append(StringForURL(request->url())); | |
244 text.append(L"\r\n"); | |
245 } | |
246 | |
247 if (regular_count == 0) | |
248 text.append(L" (No active jobs)\r\n"); | |
249 | |
250 if (orphaned_count) { | |
251 wchar_t buf[64]; | |
252 swprintf(buf, arraysize(buf), L" %d orphaned jobs\r\n", orphaned_count); | |
253 text.append(buf); | |
254 } | |
255 | |
256 text.append(L"=====\r\n\r\n"); | |
257 AppendText(text); | |
258 } | |
259 | |
260 // IO thread: | |
261 void NetworkStatusView::JobTracker::OnJobAdded(URLRequestJob* job) { | |
262 DCHECK(MessageLoop::current() != view_message_loop_); | |
263 | |
264 std::wstring text(L"+ New job : "); | |
265 text.append(URLForJob(job)); | |
266 text.append(L"\r\n"); | |
267 AppendText(text); | |
268 } | |
269 | |
270 // IO thread: | |
271 void NetworkStatusView::JobTracker::OnJobRemoved(URLRequestJob* job) { | |
272 DCHECK(MessageLoop::current() != view_message_loop_); | |
273 } | |
274 | |
275 // IO thread: | |
276 void NetworkStatusView::JobTracker::OnJobDone(URLRequestJob* job, | |
277 const URLRequestStatus& status) { | |
278 DCHECK(MessageLoop::current() != view_message_loop_); | |
279 | |
280 std::wstring text; | |
281 if (status.is_success()) { | |
282 text.assign(L"- Complete: "); | |
283 } else if (status.status() == URLRequestStatus::CANCELED) { | |
284 text.assign(L"- Canceled: "); | |
285 } else if (status.status() == URLRequestStatus::HANDLED_EXTERNALLY) { | |
286 text.assign(L"- Handled externally: "); | |
287 } else { | |
288 wchar_t buf[32]; | |
289 swprintf(buf, arraysize(buf), L"Failed with %d: ", status.os_error()); | |
290 text.assign(buf); | |
291 } | |
292 | |
293 text.append(URLForJob(job)); | |
294 text.append(L"\r\n"); | |
295 AppendText(text); | |
296 } | |
297 | |
298 // IO thread: | |
299 void NetworkStatusView::JobTracker::OnJobRedirect(URLRequestJob* job, | |
300 const GURL& location, | |
301 int status_code) { | |
302 DCHECK(MessageLoop::current() != view_message_loop_); | |
303 | |
304 std::wstring text(L"- Redirect: "); | |
305 text.append(URLForJob(job)); | |
306 text.append(L"\r\n "); | |
307 | |
308 wchar_t buf[16]; | |
309 swprintf(buf, arraysize(buf), L"(%d) to: ", status_code); | |
310 text.append(buf); | |
311 | |
312 text.append(StringForURL(location)); | |
313 text.append(L"\r\n"); | |
314 AppendText(text); | |
315 } | |
316 | |
317 void NetworkStatusView::JobTracker::OnBytesRead(URLRequestJob* job, | |
318 int byte_count) { | |
319 } | |
320 | |
OLD | NEW |