root/chrome/browser/ui/views/hung_renderer_view_win.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. PlatformShowCustomHungRendererDialog
  2. PlatformHideCustomHungRendererDialog
  3. KillRendererProcess
  4. Create
  5. GetInstance
  6. metro_dialog_displayed_
  7. Show
  8. Hide
  9. ResetMetroState
  10. OnMetroKillProcess
  11. OnMetroWait

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/hung_renderer_view_win.h"

#include "base/win/metro.h"
#include "chrome/browser/hang_monitor/hang_crash_dump_win.h"
#include "chrome/browser/ui/views/hung_renderer_view.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "win8/util/win8_util.h"

// Metro functions for displaying and dismissing a dialog box.
typedef void (*MetroShowDialogBox)(
    const wchar_t* title,
    const wchar_t* content,
    const wchar_t* button1_label,
    const wchar_t* button2_label,
    base::win::MetroDialogButtonPressedHandler button1_handler,
    base::win::MetroDialogButtonPressedHandler button2_handler);

typedef void (*MetroDismissDialogBox)();

using content::BrowserThread;
using content::WebContents;

HungRendererDialogMetro* HungRendererDialogMetro::g_instance_ = NULL;

bool PlatformShowCustomHungRendererDialog(WebContents* contents) {
  if (!win8::IsSingleWindowMetroMode())
    return false;

  HungRendererDialogMetro::Create()->Show(contents);
  return true;
}

bool PlatformHideCustomHungRendererDialog(WebContents* contents) {
  if (!win8::IsSingleWindowMetroMode())
    return false;

  if (HungRendererDialogMetro::GetInstance())
    HungRendererDialogMetro::GetInstance()->Hide(contents);
  return true;
}

// static
void HungRendererDialogView::KillRendererProcess(
    base::ProcessHandle process_handle) {
  // Try to generate a crash report for the hung process.
  CrashDumpAndTerminateHungChildProcess(process_handle);
}

// static
HungRendererDialogMetro* HungRendererDialogMetro::Create() {
  if (!GetInstance())
    g_instance_ = new HungRendererDialogMetro;
  return g_instance_;
}

// static
HungRendererDialogMetro* HungRendererDialogMetro::GetInstance() {
  return g_instance_;
}

HungRendererDialogMetro::HungRendererDialogMetro()
    : contents_(NULL),
      metro_dialog_displayed_(false) {
}

HungRendererDialogMetro::~HungRendererDialogMetro() {
  g_instance_ = NULL;
}

void HungRendererDialogMetro::Show(WebContents* contents) {
  if (!metro_dialog_displayed_ &&
      HungRendererDialogView::IsFrameActive(contents)) {
    HMODULE metro_dll = base::win::GetMetroModule();
    DCHECK(metro_dll);
    if (metro_dll) {
      MetroShowDialogBox show_dialog_box = reinterpret_cast<MetroShowDialogBox>
          (::GetProcAddress(metro_dll, "ShowDialogBox"));
      DCHECK(show_dialog_box);
      if (show_dialog_box) {
        base::string16 dialog_box_title =
            l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_TITLE);

        base::string16 kill_button_label =
            l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_END);

        base::string16 wait_button_label =
            l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_WAIT);

        contents_ = contents;
        metro_dialog_displayed_ = true;

        (*show_dialog_box)(dialog_box_title.c_str(),
                           contents->GetTitle().c_str(),
                           kill_button_label.c_str(),
                           wait_button_label.c_str(),
                           HungRendererDialogMetro::OnMetroKillProcess,
                           HungRendererDialogMetro::OnMetroWait);
      }
    }
  }
}

void HungRendererDialogMetro::Hide(WebContents* contents) {
  HMODULE metro_dll = base::win::GetMetroModule();
  DCHECK(metro_dll);
  if (metro_dll) {
    MetroDismissDialogBox dismiss_dialog_box =
        reinterpret_cast<MetroDismissDialogBox>
            (::GetProcAddress(metro_dll, "DismissDialogBox"));
    DCHECK(dismiss_dialog_box);
    if (dismiss_dialog_box) {
      (*dismiss_dialog_box)();
      ResetMetroState();
    }
  }
}

void HungRendererDialogMetro::ResetMetroState() {
  metro_dialog_displayed_ = false;
  contents_ = NULL;
  delete g_instance_;
}

// static
void HungRendererDialogMetro::OnMetroKillProcess() {
  // Metro chrome will invoke these handlers on the metro thread. Ensure that
  // we switch to the UI thread.
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(HungRendererDialogMetro::OnMetroKillProcess));
    return;
  }

  // Its possible that we got deleted in the meantime.
  if (!GetInstance())
    return;

  DCHECK(GetInstance()->contents_);

  HungRendererDialogView::KillRendererProcess(
      GetInstance()->contents_->GetRenderProcessHost()->GetHandle());

  // The metro dialog box is dismissed when the button handlers are invoked.
  GetInstance()->ResetMetroState();
}

// static
void HungRendererDialogMetro::OnMetroWait() {
  // Metro chrome will invoke these handlers on the metro thread. Ensure that
  // we switch to the UI thread.
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(HungRendererDialogMetro::OnMetroWait));
    return;
  }

  // Its possible that we got deleted in the meantime.
  if (!GetInstance())
    return;

  GetInstance()->ResetMetroState();
}

/* [<][>][^][v][top][bottom][index][help] */