| Index: chrome/browser/ui/sad_tab.cc
|
| diff --git a/chrome/browser/ui/sad_tab.cc b/chrome/browser/ui/sad_tab.cc
|
| index 03c5c4dc8d254bff248da5ab2a29104ca374703f..d4f23c3351322a4c6175428483cb6ec31c729898 100644
|
| --- a/chrome/browser/ui/sad_tab.cc
|
| +++ b/chrome/browser/ui/sad_tab.cc
|
| @@ -2,20 +2,210 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "build/build_config.h"
|
| #include "chrome/browser/ui/sad_tab.h"
|
|
|
| +#include "base/metrics/histogram_macros.h"
|
| +#include "chrome/browser/net/referrer.h"
|
| +#include "chrome/browser/ui/browser_finder.h"
|
| +#include "chrome/browser/ui/chrome_pages.h"
|
| +#include "chrome/common/url_constants.h"
|
| +#include "chrome/grit/generated_resources.h"
|
| +#include "components/feedback/feedback_util.h"
|
| +#include "components/strings/grit/components_strings.h"
|
| +#include "content/public/browser/navigation_controller.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +
|
| +#if defined(OS_CHROMEOS)
|
| +#include "chrome/browser/memory/oom_memory_details.h"
|
| +#endif
|
| +
|
| +namespace {
|
| +
|
| +// These stats should use the same counting approach and bucket size as tab
|
| +// discard events in memory::OomPriorityManager so they can be directly
|
| +// compared.
|
| +
|
| +// This macro uses a static counter to track how many times it's hit in a
|
| +// session. See Tabs.SadTab.CrashCreated in histograms.xml for details.
|
| +#define UMA_SAD_TAB_COUNTER(histogram_name) \
|
| + { \
|
| + static int count = 0; \
|
| + ++count; \
|
| + UMA_HISTOGRAM_COUNTS_1000(histogram_name, count); \
|
| + }
|
| +
|
| +// This enum backs an UMA histogram, so it should be treated as append-only.
|
| +enum SadTabEvent {
|
| + DISPLAYED,
|
| + BUTTON_CLICKED,
|
| + HELP_LINK_CLICKED,
|
| + MAX_SAD_TAB_EVENT
|
| +};
|
| +
|
| +void RecordEvent(bool feedback, SadTabEvent event) {
|
| + if (feedback) {
|
| + UMA_HISTOGRAM_ENUMERATION("Tabs.SadTab.Feedback.Event", event,
|
| + SadTabEvent::MAX_SAD_TAB_EVENT);
|
| + } else {
|
| + UMA_HISTOGRAM_ENUMERATION("Tabs.SadTab.Reload.Event", event,
|
| + SadTabEvent::MAX_SAD_TAB_EVENT);
|
| + }
|
| +}
|
| +
|
| +const char kCategoryTagCrash[] = "Crash";
|
| +
|
| +bool ShouldShowFeedbackButton() {
|
| +#if defined(GOOGLE_CHROME_BUILD)
|
| + const int kCrashesBeforeFeedbackIsDisplayed = 1;
|
| +
|
| + static int total_crashes = 0;
|
| + return ++total_crashes > kCrashesBeforeFeedbackIsDisplayed;
|
| +#else
|
| + return false;
|
| +#endif
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| namespace chrome {
|
|
|
| // static
|
| bool SadTab::ShouldShow(base::TerminationStatus status) {
|
| - return (status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
|
| - status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ||
|
| + switch (status) {
|
| + case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
|
| + case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
|
| +#if defined(OS_CHROMEOS)
|
| + case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
|
| +#endif
|
| + case base::TERMINATION_STATUS_PROCESS_CRASHED:
|
| + case base::TERMINATION_STATUS_OOM:
|
| + return true;
|
| + case base::TERMINATION_STATUS_NORMAL_TERMINATION:
|
| + case base::TERMINATION_STATUS_STILL_RUNNING:
|
| +#if defined(OS_ANDROID)
|
| + case base::TERMINATION_STATUS_OOM_PROTECTED:
|
| +#endif
|
| + case base::TERMINATION_STATUS_LAUNCH_FAILED:
|
| + case base::TERMINATION_STATUS_MAX_ENUM:
|
| + return false;
|
| + }
|
| + NOTREACHED();
|
| + return false;
|
| +}
|
| +
|
| +int SadTab::GetTitle() {
|
| + return IDS_SAD_TAB_TITLE;
|
| +}
|
| +
|
| +int SadTab::GetMessage() {
|
| + switch (kind_) {
|
| +#if defined(OS_CHROMEOS)
|
| + case chrome::SAD_TAB_KIND_KILLED_BY_OOM:
|
| + return IDS_KILLED_TAB_BY_OOM_MESSAGE;
|
| +#endif
|
| + case chrome::SAD_TAB_KIND_OOM:
|
| + return IDS_SAD_TAB_OOM_MESSAGE;
|
| + case chrome::SAD_TAB_KIND_CRASHED:
|
| + case chrome::SAD_TAB_KIND_KILLED:
|
| + return IDS_SAD_TAB_MESSAGE;
|
| + }
|
| + NOTREACHED();
|
| + return 0;
|
| +}
|
| +
|
| +int SadTab::GetButtonTitle() {
|
| + return show_feedback_button_ ? IDS_CRASHED_TAB_FEEDBACK_LINK
|
| + : IDS_SAD_TAB_RELOAD_LABEL;
|
| +}
|
| +
|
| +int SadTab::GetHelpLinkTitle() {
|
| + return IDS_SAD_TAB_LEARN_MORE_LINK;
|
| +}
|
| +
|
| +const char* SadTab::GetHelpLinkURL() {
|
| + return show_feedback_button_ ? chrome::kCrashReasonFeedbackDisplayedURL
|
| + : chrome::kCrashReasonURL;
|
| +}
|
| +
|
| +void SadTab::RecordFirstPaint() {
|
| + DCHECK(!recorded_paint_);
|
| + recorded_paint_ = true;
|
| +
|
| + switch (kind_) {
|
| + case chrome::SAD_TAB_KIND_CRASHED:
|
| + UMA_SAD_TAB_COUNTER("Tabs.SadTab.CrashDisplayed");
|
| + break;
|
| + case chrome::SAD_TAB_KIND_OOM:
|
| + UMA_SAD_TAB_COUNTER("Tabs.SadTab.OomDisplayed");
|
| + break;
|
| +#if defined(OS_CHROMEOS)
|
| + case chrome::SAD_TAB_KIND_KILLED_BY_OOM:
|
| + UMA_SAD_TAB_COUNTER("Tabs.SadTab.KillDisplayed.OOM");
|
| +#endif
|
| + // Fallthrough
|
| + case chrome::SAD_TAB_KIND_KILLED:
|
| + UMA_SAD_TAB_COUNTER("Tabs.SadTab.KillDisplayed");
|
| + break;
|
| + }
|
| +
|
| + RecordEvent(show_feedback_button_, SadTabEvent::DISPLAYED);
|
| +}
|
| +
|
| +void SadTab::PerformAction(SadTab::Action action) {
|
| + DCHECK(recorded_paint_);
|
| + switch (action) {
|
| + case Action::BUTTON:
|
| + RecordEvent(show_feedback_button_, SadTabEvent::BUTTON_CLICKED);
|
| + if (show_feedback_button_) {
|
| + chrome::ShowFeedbackPage(
|
| + chrome::FindBrowserWithWebContents(web_contents_),
|
| + l10n_util::GetStringUTF8(kind_ == chrome::SAD_TAB_KIND_CRASHED
|
| + ? IDS_CRASHED_TAB_FEEDBACK_MESSAGE
|
| + : IDS_KILLED_TAB_FEEDBACK_MESSAGE),
|
| + std::string(kCategoryTagCrash));
|
| + } else {
|
| + web_contents_->GetController().Reload(true);
|
| + }
|
| + break;
|
| + case Action::HELP_LINK:
|
| + RecordEvent(show_feedback_button_, SadTabEvent::HELP_LINK_CLICKED);
|
| + content::OpenURLParams params(GURL(GetHelpLinkURL()), content::Referrer(),
|
| + WindowOpenDisposition::CURRENT_TAB,
|
| + ui::PAGE_TRANSITION_LINK, false);
|
| + web_contents_->OpenURL(params);
|
| + break;
|
| + }
|
| +}
|
| +
|
| +SadTab::SadTab(content::WebContents* web_contents, SadTabKind kind)
|
| + : web_contents_(web_contents),
|
| + kind_(kind),
|
| + show_feedback_button_(ShouldShowFeedbackButton()),
|
| + recorded_paint_(false) {
|
| + switch (kind) {
|
| + case chrome::SAD_TAB_KIND_CRASHED:
|
| + UMA_SAD_TAB_COUNTER("Tabs.SadTab.CrashCreated");
|
| + break;
|
| + case chrome::SAD_TAB_KIND_OOM:
|
| + UMA_SAD_TAB_COUNTER("Tabs.SadTab.OomCreated");
|
| + break;
|
| #if defined(OS_CHROMEOS)
|
| - status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM ||
|
| + case chrome::SAD_TAB_KIND_KILLED_BY_OOM:
|
| + UMA_SAD_TAB_COUNTER("Tabs.SadTab.KillCreated.OOM");
|
| + {
|
| + const std::string spec = web_contents->GetURL().GetOrigin().spec();
|
| + memory::OomMemoryDetails::Log(
|
| + "Tab OOM-Killed Memory details: " + spec + ", ", base::Closure());
|
| + }
|
| #endif
|
| - status == base::TERMINATION_STATUS_PROCESS_CRASHED ||
|
| - status == base::TERMINATION_STATUS_OOM);
|
| + // Fall through
|
| + case chrome::SAD_TAB_KIND_KILLED:
|
| + UMA_SAD_TAB_COUNTER("Tabs.SadTab.KillCreated");
|
| + LOG(WARNING) << "Tab Killed: "
|
| + << web_contents->GetURL().GetOrigin().spec();
|
| + break;
|
| + }
|
| }
|
|
|
| } // namespace chrome
|
|
|