// 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 "components/app_modal/javascript_app_modal_dialog.h"

#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/app_modal/javascript_dialog_manager.h"
#include "components/app_modal/javascript_native_dialog_factory.h"
#include "ui/gfx/text_elider.h"

namespace app_modal {
namespace {

// Control maximum sizes of various texts passed to us from javascript.
#if defined(OS_POSIX) && !defined(OS_MACOSX)
// Two-dimensional eliding.  Reformat the text of the message dialog
// inserting line breaks because otherwise a single long line can overflow
// the message dialog (and crash/hang the GTK, depending on the version).
const int kMessageTextMaxRows = 32;
const int kMessageTextMaxCols = 132;
const int kDefaultPromptMaxRows = 24;
const int kDefaultPromptMaxCols = 132;
void EnforceMaxTextSize(const base::string16& in_string,
                        base::string16* out_string) {
  gfx::ElideRectangleString(in_string, kMessageTextMaxRows,
                           kMessageTextMaxCols, false, out_string);
}
void EnforceMaxPromptSize(const base::string16& in_string,
                          base::string16* out_string) {
  gfx::ElideRectangleString(in_string, kDefaultPromptMaxRows,
                           kDefaultPromptMaxCols, false, out_string);
}
#else
// One-dimensional eliding.  Trust the window system to break the string
// appropriately, but limit its overall length to something reasonable.
const size_t kMessageTextMaxSize = 2000;
const size_t kDefaultPromptMaxSize = 2000;
void EnforceMaxTextSize(const base::string16& in_string,
                        base::string16* out_string) {
  gfx::ElideString(in_string, kMessageTextMaxSize, out_string);
}
void EnforceMaxPromptSize(const base::string16& in_string,
                          base::string16* out_string) {
  gfx::ElideString(in_string, kDefaultPromptMaxSize, out_string);
}
#endif

}  // namespace

ChromeJavaScriptDialogExtraData::ChromeJavaScriptDialogExtraData()
    : has_already_shown_a_dialog_(false),
      suppress_javascript_messages_(false),
      suppressed_dialog_count_(0) {}

JavaScriptAppModalDialog::JavaScriptAppModalDialog(
    content::WebContents* web_contents,
    ExtraDataMap* extra_data_map,
    const base::string16& title,
    content::JavaScriptMessageType javascript_message_type,
    const base::string16& message_text,
    const base::string16& default_prompt_text,
    bool display_suppress_checkbox,
    bool is_before_unload_dialog,
    bool is_reload,
    const content::JavaScriptDialogManager::DialogClosedCallback& callback)
    : AppModalDialog(web_contents, title),
      extra_data_map_(extra_data_map),
      javascript_message_type_(javascript_message_type),
      display_suppress_checkbox_(display_suppress_checkbox),
      is_before_unload_dialog_(is_before_unload_dialog),
      is_reload_(is_reload),
      callback_(callback),
      use_override_prompt_text_(false),
      creation_time_(base::TimeTicks::Now()) {
  EnforceMaxTextSize(message_text, &message_text_);
  EnforceMaxPromptSize(default_prompt_text, &default_prompt_text_);
}

JavaScriptAppModalDialog::~JavaScriptAppModalDialog() {
}

NativeAppModalDialog* JavaScriptAppModalDialog::CreateNativeDialog() {
  return JavaScriptDialogManager::GetInstance()
      ->native_dialog_factory()
      ->CreateNativeJavaScriptDialog(this);
}

bool JavaScriptAppModalDialog::IsJavaScriptModalDialog() {
  return true;
}

void JavaScriptAppModalDialog::Invalidate(bool suppress_callbacks) {
  if (!IsValid())
    return;

  AppModalDialog::Invalidate(suppress_callbacks);
  if (!suppress_callbacks)
    CallDialogClosedCallback(false, base::string16());
  if (native_dialog())
    CloseModalDialog();
}

void JavaScriptAppModalDialog::OnCancel(bool suppress_js_messages) {
  // We need to do this before WM_DESTROY (WindowClosing()) as any parent frame
  // will receive its activation messages before this dialog receives
  // WM_DESTROY. The parent frame would then try to activate any modal dialogs
  // that were still open in the ModalDialogQueue, which would send activation
  // back to this one. The framework should be improved to handle this, so this
  // is a temporary workaround.
  CompleteDialog();

  NotifyDelegate(false, base::string16(), suppress_js_messages);
}

void JavaScriptAppModalDialog::OnAccept(const base::string16& prompt_text,
                                        bool suppress_js_messages) {
  base::string16 prompt_text_to_use = prompt_text;
  // This is only for testing.
  if (use_override_prompt_text_)
    prompt_text_to_use = override_prompt_text_;

  CompleteDialog();
  NotifyDelegate(true, prompt_text_to_use, suppress_js_messages);
}

void JavaScriptAppModalDialog::OnClose() {
  NotifyDelegate(false, base::string16(), false);
}

void JavaScriptAppModalDialog::SetOverridePromptText(
    const base::string16& override_prompt_text) {
  override_prompt_text_ = override_prompt_text;
  use_override_prompt_text_ = true;
}

void JavaScriptAppModalDialog::NotifyDelegate(bool success,
                                              const base::string16& user_input,
                                              bool suppress_js_messages) {
  if (!IsValid())
    return;

  CallDialogClosedCallback(success, user_input);

  // The close callback above may delete web_contents_, thus removing the extra
  // data from the map owned by ::JavaScriptDialogManager. Make sure
  // to only use the data if still present. http://crbug.com/236476
  ExtraDataMap::iterator extra_data = extra_data_map_->find(web_contents());
  if (extra_data != extra_data_map_->end()) {
    extra_data->second.has_already_shown_a_dialog_ = true;
    extra_data->second.suppress_javascript_messages_ = suppress_js_messages;
  }

  // On Views, we can end up coming through this code path twice :(.
  // See crbug.com/63732.
  AppModalDialog::Invalidate(false);
}

void JavaScriptAppModalDialog::CallDialogClosedCallback(bool success,
    const base::string16& user_input) {
  // TODO(joenotcharles): Both the callers of this function also check IsValid
  // and call AppModalDialog::Invalidate, but in different orders. If the
  // difference is not significant, more common code could be moved here.
  UMA_HISTOGRAM_MEDIUM_TIMES(
      "JSDialogs.FineTiming.TimeBetweenDialogCreatedAndSameDialogClosed",
      base::TimeTicks::Now() - creation_time_);
  if (!callback_.is_null()) {
    callback_.Run(success, user_input);
    callback_.Reset();
  }
}

}  // namespace app_modal
