OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/feedback/feedback_util.h" | 5 #include "chrome/browser/feedback/feedback_util.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/file_util.h" | 13 #include "base/file_util.h" |
14 #include "base/file_version_info.h" | 14 #include "base/file_version_info.h" |
15 #include "base/memory/singleton.h" | 15 #include "base/memory/singleton.h" |
16 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
18 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
19 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
20 #include "base/win/windows_version.h" | 20 #include "base/win/windows_version.h" |
21 #include "chrome/browser/browser_process.h" | 21 #include "chrome/browser/browser_process.h" |
22 #include "chrome/browser/extensions/api/feedback_private/feedback_private_api.h" | 22 #include "chrome/browser/extensions/api/feedback_private/feedback_private_api.h" |
23 #include "chrome/browser/feedback/feedback_data.h" | 23 #include "chrome/browser/feedback/feedback_data.h" |
24 #include "chrome/browser/metrics/variations/variations_http_header_provider.h" | 24 #include "chrome/browser/metrics/variations/variations_http_header_provider.h" |
25 #include "chrome/browser/profiles/profile.h" | 25 #include "chrome/browser/profiles/profile.h" |
| 26 #include "chrome/browser/profiles/profile_manager.h" |
26 #include "chrome/browser/safe_browsing/safe_browsing_util.h" | 27 #include "chrome/browser/safe_browsing/safe_browsing_util.h" |
27 #include "chrome/browser/ui/browser_finder.h" | 28 #include "chrome/browser/ui/browser_finder.h" |
28 #include "chrome/browser/ui/browser_list.h" | 29 #include "chrome/browser/ui/browser_list.h" |
29 #include "chrome/browser/ui/browser_window.h" | 30 #include "chrome/browser/ui/browser_window.h" |
30 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 31 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
31 #include "chrome/common/chrome_switches.h" | 32 #include "chrome/common/chrome_switches.h" |
32 #include "chrome/common/chrome_version_info.h" | 33 #include "chrome/common/chrome_version_info.h" |
33 #include "chrome/common/metrics/metrics_log_manager.h" | 34 #include "chrome/common/metrics/metrics_log_manager.h" |
34 #include "content/public/browser/browser_thread.h" | 35 #include "content/public/browser/browser_thread.h" |
35 #include "content/public/browser/navigation_controller.h" | 36 #include "content/public/browser/navigation_controller.h" |
(...skipping 18 matching lines...) Expand all Loading... |
54 #include "ui/aura/window.h" | 55 #include "ui/aura/window.h" |
55 #endif | 56 #endif |
56 | 57 |
57 namespace { | 58 namespace { |
58 | 59 |
59 const base::FilePath::CharType kLogsFilename[] = | 60 const base::FilePath::CharType kLogsFilename[] = |
60 FILE_PATH_LITERAL("system_logs.txt"); | 61 FILE_PATH_LITERAL("system_logs.txt"); |
61 | 62 |
62 void DispatchFeedback(Profile* profile, std::string* post_body, int64 delay); | 63 void DispatchFeedback(Profile* profile, std::string* post_body, int64 delay); |
63 | 64 |
64 // Check the key/value pair to see if it is one of the screensize, keys. If so, | |
65 // populate the screensize structure with the key. | |
66 bool IsScreensizeInfo(const std::string key, | |
67 const std::string value, | |
68 gfx::Rect* screen_size) { | |
69 if (key == FeedbackData::kScreensizeHeightKey) { | |
70 int height = 0; | |
71 base::StringToInt(value, &height); | |
72 screen_size->SetRect(0, 0, screen_size->width(), height); | |
73 return true; | |
74 } else if (key == FeedbackData::kScreensizeWidthKey) { | |
75 int width = 0; | |
76 base::StringToInt(value, &width); | |
77 screen_size->SetRect(0, 0, width, screen_size->height()); | |
78 return true; | |
79 } | |
80 return false; | |
81 } | |
82 | |
83 GURL GetTargetTabUrl(int session_id, int index) { | 65 GURL GetTargetTabUrl(int session_id, int index) { |
84 Browser* browser = chrome::FindBrowserWithID(session_id); | 66 Browser* browser = chrome::FindBrowserWithID(session_id); |
85 // Sanity checks. | 67 // Sanity checks. |
86 if (!browser || index >= browser->tab_strip_model()->count()) | 68 if (!browser || index >= browser->tab_strip_model()->count()) |
87 return GURL(); | 69 return GURL(); |
88 | 70 |
89 if (index >= 0) { | 71 if (index >= 0) { |
90 content::WebContents* target_tab = | 72 content::WebContents* target_tab = |
91 browser->tab_strip_model()->GetWebContentsAt(index); | 73 browser->tab_strip_model()->GetWebContentsAt(index); |
92 if (target_tab) | 74 if (target_tab) |
93 return target_tab->GetURL(); | 75 return target_tab->GetURL(); |
94 } | 76 } |
95 | 77 |
96 return GURL(); | 78 return GURL(); |
97 } | 79 } |
98 | 80 |
99 gfx::Rect GetScreenSize(Browser* browser) { | |
100 #if defined(OS_CHROMEOS) | |
101 // For ChromeOS, don't use the browser window but the root window | |
102 // instead to grab the screenshot. We want everything on the screen, not | |
103 // just the current browser. | |
104 gfx::NativeWindow native_window = ash::Shell::GetPrimaryRootWindow(); | |
105 return gfx::Rect(native_window->bounds()); | |
106 #else | |
107 return gfx::Rect(browser->window()->GetBounds().size()); | |
108 #endif | |
109 } | |
110 | |
111 // URL to post bug reports to. | 81 // URL to post bug reports to. |
112 const char kFeedbackPostUrl[] = | 82 const char kFeedbackPostUrl[] = |
113 "https://www.google.com/tools/feedback/chrome/__submit"; | 83 "https://www.google.com/tools/feedback/chrome/__submit"; |
114 | 84 |
115 const char kProtBufMimeType[] = "application/x-protobuf"; | 85 const char kProtBufMimeType[] = "application/x-protobuf"; |
116 const char kPngMimeType[] = "image/png"; | 86 const char kPngMimeType[] = "image/png"; |
117 | 87 |
118 const int kHttpPostSuccessNoContent = 204; | 88 const int kHttpPostSuccessNoContent = 204; |
119 const int kHttpPostFailNoConnection = -1; | 89 const int kHttpPostFailNoConnection = -1; |
120 const int kHttpPostFailClientError = 400; | 90 const int kHttpPostFailClientError = 400; |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 *(web_data->add_product_specific_data()) = log_value; | 217 *(web_data->add_product_specific_data()) = log_value; |
248 } | 218 } |
249 | 219 |
250 } // namespace | 220 } // namespace |
251 | 221 |
252 namespace chrome { | 222 namespace chrome { |
253 | 223 |
254 const char kAppLauncherCategoryTag[] = "AppLauncher"; | 224 const char kAppLauncherCategoryTag[] = "AppLauncher"; |
255 | 225 |
256 void ShowFeedbackPage(Browser* browser, | 226 void ShowFeedbackPage(Browser* browser, |
257 const std::string& description_template, | 227 const std::string& description_template, |
258 const std::string& category_tag) { | 228 const std::string& category_tag) { |
259 DCHECK(browser); | 229 GURL page_url; |
| 230 if (browser) { |
| 231 page_url = GetTargetTabUrl(browser->session_id().id(), |
| 232 browser->tab_strip_model()->active_index()); |
| 233 } |
260 | 234 |
261 // Get the current browser's screensize and send it with the feedback request | 235 Profile* profile = NULL; |
262 // event - this browser may have changed or even been closed by the time that | 236 if (browser) { |
263 // feedback is sent. | 237 profile = browser->profile(); |
264 gfx::Rect screen_size = GetScreenSize(browser); | 238 } else { |
265 GURL page_url = GetTargetTabUrl( | 239 profile = ProfileManager::GetLastUsedProfileAllowedByPolicy(); |
266 browser->session_id().id(), browser->tab_strip_model()->active_index()); | 240 } |
| 241 if (!profile) { |
| 242 LOG(ERROR) << "Cannot invoke feedback: No profile found!"; |
| 243 return; |
| 244 } |
267 | 245 |
268 extensions::FeedbackPrivateAPI* api = | 246 extensions::FeedbackPrivateAPI* api = |
269 extensions::FeedbackPrivateAPI::GetFactoryInstance()->GetForProfile( | 247 extensions::FeedbackPrivateAPI::GetFactoryInstance()->GetForProfile( |
270 browser->profile()); | 248 profile); |
271 | 249 |
272 api->RequestFeedback(description_template, | 250 api->RequestFeedback(description_template, |
273 category_tag, | 251 category_tag, |
274 page_url, | 252 page_url); |
275 screen_size); | |
276 } | 253 } |
277 | 254 |
278 } // namespace chrome | 255 } // namespace chrome |
279 | 256 |
280 namespace feedback_util { | 257 namespace feedback_util { |
281 | 258 |
282 void SendReport(scoped_refptr<FeedbackData> data) { | 259 void SendReport(scoped_refptr<FeedbackData> data) { |
283 if (!data.get()) { | 260 if (!data.get()) { |
284 LOG(ERROR) << "SendReport called with NULL data!"; | 261 LOG(ERROR) << "SendReport called with NULL data!"; |
285 NOTREACHED(); | 262 NOTREACHED(); |
(...skipping 14 matching lines...) Expand all Loading... |
300 common_data->set_source_description_language(chrome_locale); | 277 common_data->set_source_description_language(chrome_locale); |
301 | 278 |
302 userfeedback::WebData* web_data = feedback_data.mutable_web_data(); | 279 userfeedback::WebData* web_data = feedback_data.mutable_web_data(); |
303 web_data->set_url(data->page_url()); | 280 web_data->set_url(data->page_url()); |
304 web_data->mutable_navigator()->set_user_agent(content::GetUserAgent(GURL())); | 281 web_data->mutable_navigator()->set_user_agent(content::GetUserAgent(GURL())); |
305 | 282 |
306 gfx::Rect screen_size; | 283 gfx::Rect screen_size; |
307 if (data->sys_info()) { | 284 if (data->sys_info()) { |
308 for (FeedbackData::SystemLogsMap::const_iterator i = | 285 for (FeedbackData::SystemLogsMap::const_iterator i = |
309 data->sys_info()->begin(); i != data->sys_info()->end(); ++i) { | 286 data->sys_info()->begin(); i != data->sys_info()->end(); ++i) { |
310 if (!IsScreensizeInfo(i->first, i->second, &screen_size)) { | 287 if (FeedbackData::BelowCompressionThreshold(i->second)) |
311 if (FeedbackData::BelowCompressionThreshold(i->second)) | 288 AddFeedbackData(&feedback_data, i->first, i->second); |
312 AddFeedbackData(&feedback_data, i->first, i->second); | |
313 } | |
314 } | 289 } |
315 | 290 |
316 if (data->compressed_logs() && data->compressed_logs()->size()) { | 291 if (data->compressed_logs() && data->compressed_logs()->size()) { |
317 userfeedback::ProductSpecificBinaryData attachment; | 292 userfeedback::ProductSpecificBinaryData attachment; |
318 attachment.set_mime_type(kArbitraryMimeType); | 293 attachment.set_mime_type(kArbitraryMimeType); |
319 attachment.set_name(kLogsAttachmentName); | 294 attachment.set_name(kLogsAttachmentName); |
320 attachment.set_data(*(data->compressed_logs())); | 295 attachment.set_data(*(data->compressed_logs())); |
321 *(feedback_data.add_product_specific_binary_data()) = attachment; | 296 *(feedback_data.add_product_specific_binary_data()) = attachment; |
322 } | 297 } |
323 } | 298 } |
(...skipping 11 matching lines...) Expand all Loading... |
335 attached_file.set_data(*data->attached_filedata()); | 310 attached_file.set_data(*data->attached_filedata()); |
336 *(feedback_data.add_product_specific_binary_data()) = attached_file; | 311 *(feedback_data.add_product_specific_binary_data()) = attached_file; |
337 } | 312 } |
338 | 313 |
339 // NOTE: Screenshot needs to be processed after system info since we'll get | 314 // NOTE: Screenshot needs to be processed after system info since we'll get |
340 // the screenshot dimensions from system info. | 315 // the screenshot dimensions from system info. |
341 if (data->image() && data->image()->size()) { | 316 if (data->image() && data->image()->size()) { |
342 userfeedback::PostedScreenshot screenshot; | 317 userfeedback::PostedScreenshot screenshot; |
343 screenshot.set_mime_type(kPngMimeType); | 318 screenshot.set_mime_type(kPngMimeType); |
344 | 319 |
345 // Set the dimensions of the screenshot | 320 // Set that we 'have' dimensions of the screenshot. These dimensions are |
| 321 // ignored by the server but are a 'required' field in the protobuf. |
346 userfeedback::Dimensions dimensions; | 322 userfeedback::Dimensions dimensions; |
347 dimensions.set_width(static_cast<float>(screen_size.width())); | 323 dimensions.set_width(0.0); |
348 dimensions.set_height(static_cast<float>(screen_size.height())); | 324 dimensions.set_height(0.0); |
349 | 325 |
350 *(screenshot.mutable_dimensions()) = dimensions; | 326 *(screenshot.mutable_dimensions()) = dimensions; |
351 screenshot.set_binary_content(*data->image()); | 327 screenshot.set_binary_content(*data->image()); |
352 | 328 |
353 *(feedback_data.mutable_screenshot()) = screenshot; | 329 *(feedback_data.mutable_screenshot()) = screenshot; |
354 } | 330 } |
355 | 331 |
356 if (data->category_tag().size()) | 332 if (data->category_tag().size()) |
357 feedback_data.set_bucket(data->category_tag()); | 333 feedback_data.set_bucket(data->category_tag()); |
358 | 334 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 if (!zip::Zip(temp_path, zip_file, false)) | 379 if (!zip::Zip(temp_path, zip_file, false)) |
404 return false; | 380 return false; |
405 | 381 |
406 if (!base::ReadFileToString(zip_file, compressed_logs)) | 382 if (!base::ReadFileToString(zip_file, compressed_logs)) |
407 return false; | 383 return false; |
408 | 384 |
409 return true; | 385 return true; |
410 } | 386 } |
411 | 387 |
412 } // namespace feedback_util | 388 } // namespace feedback_util |
OLD | NEW |