<commit_before>// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "atom/browser/native_window.h"

#include <string>
#include <utility>
#include <vector>

#include "atom/browser/api/atom_browser_bindings.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/atom_javascript_dialog_manager.h"
#include "atom/browser/browser.h"
#include "atom/browser/devtools_delegate.h"
#include "atom/browser/devtools_web_contents_observer.h"
#include "atom/browser/ui/file_dialog.h"
#include "atom/browser/window_list.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/atom_version.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/json/json_writer.h"
#include "base/prefs/pref_service.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/renderer_preferences.h"
#include "ipc/ipc_message_macros.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
#include "vendor/brightray/browser/inspectable_web_contents.h"
#include "vendor/brightray/browser/inspectable_web_contents_view.h"
#include "webkit/common/user_agent/user_agent_util.h"
#include "webkit/common/webpreferences.h"

using content::NavigationEntry;

namespace atom {

namespace {

const char kDockSidePref[] = "brightray.devtools.dockside";

}  // namespace

NativeWindow::NativeWindow(content::WebContents* web_contents,
                           base::DictionaryValue* options)
    : content::WebContentsObserver(web_contents),
      has_frame_(true),
      is_closed_(false),
      node_integration_("except-iframe"),
      has_dialog_attached_(false),
      weak_factory_(this),
      inspectable_web_contents_(
          brightray::InspectableWebContents::Create(web_contents)) {
  options->GetBoolean(switches::kFrame, &has_frame_);

#if defined(OS_MACOSX)
  // Temporary fix for flashing devtools, try removing this after upgraded to
  // Chrome 32.
  web_contents->GetView()->SetAllowOverlappingViews(false);
#endif

  // Read icon before window is created.
  std::string icon;
  if (options->GetString(switches::kIcon, &icon) && !SetIcon(icon))
    LOG(ERROR) << "Failed to set icon to " << icon;

  // Read iframe security before any navigation.
  options->GetString(switches::kNodeIntegration, &node_integration_);

  web_contents->SetDelegate(this);
  inspectable_web_contents()->SetDelegate(this);

  WindowList::AddWindow(this);

  // Override the user agent to contain application and atom-shell's version.
  Browser* browser = Browser::Get();
  std::string product_name = base::StringPrintf(
      "%s/%s Atom-Shell/" ATOM_VERSION_STRING,
      browser->GetName().c_str(),
      browser->GetVersion().c_str());
  web_contents->GetMutableRendererPrefs()->user_agent_override =
      webkit_glue::BuildUserAgentFromProduct(product_name);

  // Get notified of title updated message.
  registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
      content::Source<content::WebContents>(web_contents));
}

NativeWindow::~NativeWindow() {
  // It's possible that the windows gets destroyed before it's closed, in that
  // case we need to ensure the OnWindowClosed message is still notified.
  NotifyWindowClosed();
}

// static
NativeWindow* NativeWindow::Create(base::DictionaryValue* options) {
  content::WebContents::CreateParams create_params(AtomBrowserContext::Get());
  return Create(content::WebContents::Create(create_params), options);
}

// static
NativeWindow* NativeWindow::Debug(content::WebContents* web_contents) {
  base::DictionaryValue options;
  NativeWindow* window = NativeWindow::Create(&options);
  window->devtools_delegate_.reset(new DevToolsDelegate(window, web_contents));
  return window;
}

// static
NativeWindow* NativeWindow::FromRenderView(int process_id, int routing_id) {
  // Stupid iterating.
  WindowList& window_list = *WindowList::GetInstance();
  for (auto w = window_list.begin(); w != window_list.end(); ++w) {
    auto& window = *w;
    content::WebContents* web_contents = window->GetWebContents();
    int window_process_id = web_contents->GetRenderProcessHost()->GetID();
    int window_routing_id = web_contents->GetRoutingID();
    if (window_routing_id == routing_id && window_process_id == process_id)
      return window;
  }

  return NULL;
}

void NativeWindow::InitFromOptions(base::DictionaryValue* options) {
  // Setup window from options.
  int x = -1, y = -1;
  bool center;
  if (options->GetInteger(switches::kX, &x) &&
      options->GetInteger(switches::kY, &y)) {
    int width = -1, height = -1;
    options->GetInteger(switches::kWidth, &width);
    options->GetInteger(switches::kHeight, &height);
    Move(gfx::Rect(x, y, width, height));
  } else if (options->GetBoolean(switches::kCenter, &center) && center) {
    Center();
  }
  int min_height = -1, min_width = -1;
  if (options->GetInteger(switches::kMinHeight, &min_height) &&
      options->GetInteger(switches::kMinWidth, &min_width)) {
    SetMinimumSize(gfx::Size(min_width, min_height));
  }
  int max_height = -1, max_width = -1;
  if (options->GetInteger(switches::kMaxHeight, &max_height) &&
      options->GetInteger(switches::kMaxWidth, &max_width)) {
    SetMaximumSize(gfx::Size(max_width, max_height));
  }
  bool resizable;
  if (options->GetBoolean(switches::kResizable, &resizable)) {
    SetResizable(resizable);
  }
  bool top;
  if (options->GetBoolean(switches::kAlwaysOnTop, &top) && top) {
    SetAlwaysOnTop(true);
  }
  bool fullscreen;
  if (options->GetBoolean(switches::kFullscreen, &fullscreen) && fullscreen) {
    SetFullscreen(true);
  }
  bool kiosk;
  if (options->GetBoolean(switches::kKiosk, &kiosk) && kiosk) {
    SetKiosk(kiosk);
  }
  std::string title("Atom Shell");
  options->GetString(switches::kTitle, &title);
  SetTitle(title);

  // Then show it.
  bool show = true;
  options->GetBoolean(switches::kShow, &show);
  if (show)
    Show();
}

bool NativeWindow::HasModalDialog() {
  return has_dialog_attached_;
}

void NativeWindow::OpenDevTools() {
  if (devtools_window_) {
    devtools_window_->Focus(true);
    devtools_web_contents_observer_.reset(new DevToolsWebContentsObserver(
        this, devtools_window_->GetWebContents()));
  } else {
    inspectable_web_contents()->ShowDevTools();
    devtools_web_contents_observer_.reset(new DevToolsWebContentsObserver(
        this, GetDevToolsWebContents()));
#if defined(OS_MACOSX)
    // Temporary fix for flashing devtools, try removing this after upgraded to
    // Chrome 32.
    GetDevToolsWebContents()->GetView()->SetAllowOverlappingViews(false);
#endif
  }
}

void NativeWindow::CloseDevTools() {
  if (devtools_window_)
    devtools_window_->Close();
  else
    inspectable_web_contents()->CloseDevTools();
}

bool NativeWindow::IsDevToolsOpened() {
  return (devtools_window_ && devtools_window_->IsFocused()) ||
         inspectable_web_contents()->IsDevToolsViewShowing();
}

void NativeWindow::InspectElement(int x, int y) {
  OpenDevTools();
  content::RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
  scoped_refptr<content::DevToolsAgentHost> agent(
      content::DevToolsAgentHost::GetOrCreateFor(rvh));
  agent->InspectElement(x, y);
}

void NativeWindow::FocusOnWebView() {
  GetWebContents()->GetRenderViewHost()->Focus();
}

void NativeWindow::BlurWebView() {
  GetWebContents()->GetRenderViewHost()->Blur();
}

bool NativeWindow::IsWebViewFocused() {
  content::RenderWidgetHostView* host_view =
      GetWebContents()->GetRenderViewHost()->GetView();
  return host_view && host_view->HasFocus();
}

bool NativeWindow::SetIcon(const std::string& str_path) {
  base::FilePath path = base::FilePath::FromUTF8Unsafe(str_path);

  // Read the file from disk.
  std::string file_contents;
  if (path.empty() || !base::ReadFileToString(path, &file_contents))
    return false;

  // Decode the bitmap using WebKit's image decoder.
  const unsigned char* data =
      reinterpret_cast<const unsigned char*>(file_contents.data());
  scoped_ptr<SkBitmap> decoded(new SkBitmap());
  gfx::PNGCodec::Decode(data, file_contents.length(), decoded.get());
  if (decoded->empty())
    return false;  // Unable to decode.

  icon_ = gfx::Image::CreateFrom1xBitmap(*decoded.release());
  return true;
}

base::ProcessHandle NativeWindow::GetRenderProcessHandle() {
  return GetWebContents()->GetRenderProcessHost()->GetHandle();
}

void NativeWindow::CapturePage(const gfx::Rect& rect,
                               const CapturePageCallback& callback) {
  gfx::Rect flipped_y_rect = rect;
  flipped_y_rect.set_y(-rect.y());

  GetWebContents()->GetRenderViewHost()->CopyFromBackingStore(
      flipped_y_rect,
      gfx::Size(),
      base::Bind(&NativeWindow::OnCapturePageDone,
                 weak_factory_.GetWeakPtr(),
                 callback));
}

void NativeWindow::CloseWebContents() {
  bool prevent_default = false;
  FOR_EACH_OBSERVER(NativeWindowObserver,
                    observers_,
                    WillCloseWindow(&prevent_default));
  if (prevent_default) {
    WindowList::WindowCloseCancelled(this);
    return;
  }

  content::WebContents* web_contents(GetWebContents());

  // Assume the window is not responding if it doesn't cancel the close and is
  // not closed in 2000ms, in this way we can quickly show the unresponsive
  // dialog when the window is busy executing some script withouth waiting for
  // the unresponsive timeout.
  if (!Browser::Get()->is_quiting() &&
      window_unresposive_closure_.IsCancelled())
    ScheduleUnresponsiveEvent(2000);

  if (web_contents->NeedToFireBeforeUnload())
    web_contents->GetRenderViewHost()->FirePageBeforeUnload(false);
  else
    web_contents->Close();
}

content::WebContents* NativeWindow::GetWebContents() const {<commit_msg>Increase the closing time limit to 5s.<commit_after>// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "atom/browser/native_window.h"

#include <string>
#include <utility>
#include <vector>

#include "atom/browser/api/atom_browser_bindings.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/atom_javascript_dialog_manager.h"
#include "atom/browser/browser.h"
#include "atom/browser/devtools_delegate.h"
#include "atom/browser/devtools_web_contents_observer.h"
#include "atom/browser/ui/file_dialog.h"
#include "atom/browser/window_list.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/atom_version.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/json/json_writer.h"
#include "base/prefs/pref_service.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/renderer_preferences.h"
#include "ipc/ipc_message_macros.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
#include "vendor/brightray/browser/inspectable_web_contents.h"
#include "vendor/brightray/browser/inspectable_web_contents_view.h"
#include "webkit/common/user_agent/user_agent_util.h"
#include "webkit/common/webpreferences.h"

using content::NavigationEntry;

namespace atom {

namespace {

const char kDockSidePref[] = "brightray.devtools.dockside";

}  // namespace

NativeWindow::NativeWindow(content::WebContents* web_contents,
                           base::DictionaryValue* options)
    : content::WebContentsObserver(web_contents),
      has_frame_(true),
      is_closed_(false),
      node_integration_("except-iframe"),
      has_dialog_attached_(false),
      weak_factory_(this),
      inspectable_web_contents_(
          brightray::InspectableWebContents::Create(web_contents)) {
  options->GetBoolean(switches::kFrame, &has_frame_);

#if defined(OS_MACOSX)
  // Temporary fix for flashing devtools, try removing this after upgraded to
  // Chrome 32.
  web_contents->GetView()->SetAllowOverlappingViews(false);
#endif

  // Read icon before window is created.
  std::string icon;
  if (options->GetString(switches::kIcon, &icon) && !SetIcon(icon))
    LOG(ERROR) << "Failed to set icon to " << icon;

  // Read iframe security before any navigation.
  options->GetString(switches::kNodeIntegration, &node_integration_);

  web_contents->SetDelegate(this);
  inspectable_web_contents()->SetDelegate(this);

  WindowList::AddWindow(this);

  // Override the user agent to contain application and atom-shell's version.
  Browser* browser = Browser::Get();
  std::string product_name = base::StringPrintf(
      "%s/%s Atom-Shell/" ATOM_VERSION_STRING,
      browser->GetName().c_str(),
      browser->GetVersion().c_str());
  web_contents->GetMutableRendererPrefs()->user_agent_override =
      webkit_glue::BuildUserAgentFromProduct(product_name);

  // Get notified of title updated message.
  registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
      content::Source<content::WebContents>(web_contents));
}

NativeWindow::~NativeWindow() {
  // It's possible that the windows gets destroyed before it's closed, in that
  // case we need to ensure the OnWindowClosed message is still notified.
  NotifyWindowClosed();
}

// static
NativeWindow* NativeWindow::Create(base::DictionaryValue* options) {
  content::WebContents::CreateParams create_params(AtomBrowserContext::Get());
  return Create(content::WebContents::Create(create_params), options);
}

// static
NativeWindow* NativeWindow::Debug(content::WebContents* web_contents) {
  base::DictionaryValue options;
  NativeWindow* window = NativeWindow::Create(&options);
  window->devtools_delegate_.reset(new DevToolsDelegate(window, web_contents));
  return window;
}

// static
NativeWindow* NativeWindow::FromRenderView(int process_id, int routing_id) {
  // Stupid iterating.
  WindowList& window_list = *WindowList::GetInstance();
  for (auto w = window_list.begin(); w != window_list.end(); ++w) {
    auto& window = *w;
    content::WebContents* web_contents = window->GetWebContents();
    int window_process_id = web_contents->GetRenderProcessHost()->GetID();
    int window_routing_id = web_contents->GetRoutingID();
    if (window_routing_id == routing_id && window_process_id == process_id)
      return window;
  }

  return NULL;
}

void NativeWindow::InitFromOptions(base::DictionaryValue* options) {
  // Setup window from options.
  int x = -1, y = -1;
  bool center;
  if (options->GetInteger(switches::kX, &x) &&
      options->GetInteger(switches::kY, &y)) {
    int width = -1, height = -1;
    options->GetInteger(switches::kWidth, &width);
    options->GetInteger(switches::kHeight, &height);
    Move(gfx::Rect(x, y, width, height));
  } else if (options->GetBoolean(switches::kCenter, &center) && center) {
    Center();
  }
  int min_height = -1, min_width = -1;
  if (options->GetInteger(switches::kMinHeight, &min_height) &&
      options->GetInteger(switches::kMinWidth, &min_width)) {
    SetMinimumSize(gfx::Size(min_width, min_height));
  }
  int max_height = -1, max_width = -1;
  if (options->GetInteger(switches::kMaxHeight, &max_height) &&
      options->GetInteger(switches::kMaxWidth, &max_width)) {
    SetMaximumSize(gfx::Size(max_width, max_height));
  }
  bool resizable;
  if (options->GetBoolean(switches::kResizable, &resizable)) {
    SetResizable(resizable);
  }
  bool top;
  if (options->GetBoolean(switches::kAlwaysOnTop, &top) && top) {
    SetAlwaysOnTop(true);
  }
  bool fullscreen;
  if (options->GetBoolean(switches::kFullscreen, &fullscreen) && fullscreen) {
    SetFullscreen(true);
  }
  bool kiosk;
  if (options->GetBoolean(switches::kKiosk, &kiosk) && kiosk) {
    SetKiosk(kiosk);
  }
  std::string title("Atom Shell");
  options->GetString(switches::kTitle, &title);
  SetTitle(title);

  // Then show it.
  bool show = true;
  options->GetBoolean(switches::kShow, &show);
  if (show)
    Show();
}

bool NativeWindow::HasModalDialog() {
  return has_dialog_attached_;
}

void NativeWindow::OpenDevTools() {
  if (devtools_window_) {
    devtools_window_->Focus(true);
    devtools_web_contents_observer_.reset(new DevToolsWebContentsObserver(
        this, devtools_window_->GetWebContents()));
  } else {
    inspectable_web_contents()->ShowDevTools();
    devtools_web_contents_observer_.reset(new DevToolsWebContentsObserver(
        this, GetDevToolsWebContents()));
#if defined(OS_MACOSX)
    // Temporary fix for flashing devtools, try removing this after upgraded to
    // Chrome 32.
    GetDevToolsWebContents()->GetView()->SetAllowOverlappingViews(false);
#endif
  }
}

void NativeWindow::CloseDevTools() {
  if (devtools_window_)
    devtools_window_->Close();
  else
    inspectable_web_contents()->CloseDevTools();
}

bool NativeWindow::IsDevToolsOpened() {
  return (devtools_window_ && devtools_window_->IsFocused()) ||
         inspectable_web_contents()->IsDevToolsViewShowing();
}

void NativeWindow::InspectElement(int x, int y) {
  OpenDevTools();
  content::RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
  scoped_refptr<content::DevToolsAgentHost> agent(
      content::DevToolsAgentHost::GetOrCreateFor(rvh));
  agent->InspectElement(x, y);
}

void NativeWindow::FocusOnWebView() {
  GetWebContents()->GetRenderViewHost()->Focus();
}

void NativeWindow::BlurWebView() {
  GetWebContents()->GetRenderViewHost()->Blur();
}

bool NativeWindow::IsWebViewFocused() {
  content::RenderWidgetHostView* host_view =
      GetWebContents()->GetRenderViewHost()->GetView();
  return host_view && host_view->HasFocus();
}

bool NativeWindow::SetIcon(const std::string& str_path) {
  base::FilePath path = base::FilePath::FromUTF8Unsafe(str_path);

  // Read the file from disk.
  std::string file_contents;
  if (path.empty() || !base::ReadFileToString(path, &file_contents))
    return false;

  // Decode the bitmap using WebKit's image decoder.
  const unsigned char* data =
      reinterpret_cast<const unsigned char*>(file_contents.data());
  scoped_ptr<SkBitmap> decoded(new SkBitmap());
  gfx::PNGCodec::Decode(data, file_contents.length(), decoded.get());
  if (decoded->empty())
    return false;  // Unable to decode.

  icon_ = gfx::Image::CreateFrom1xBitmap(*decoded.release());
  return true;
}

base::ProcessHandle NativeWindow::GetRenderProcessHandle() {
  return GetWebContents()->GetRenderProcessHost()->GetHandle();
}

void NativeWindow::CapturePage(const gfx::Rect& rect,
                               const CapturePageCallback& callback) {
  gfx::Rect flipped_y_rect = rect;
  flipped_y_rect.set_y(-rect.y());

  GetWebContents()->GetRenderViewHost()->CopyFromBackingStore(
      flipped_y_rect,
      gfx::Size(),
      base::Bind(&NativeWindow::OnCapturePageDone,
                 weak_factory_.GetWeakPtr(),
                 callback));
}

void NativeWindow::CloseWebContents() {
  bool prevent_default = false;
  FOR_EACH_OBSERVER(NativeWindowObserver,
                    observers_,
                    WillCloseWindow(&prevent_default));
  if (prevent_default) {
    WindowList::WindowCloseCancelled(this);
    return;
  }

  content::WebContents* web_contents(GetWebContents());

  // Assume the window is not responding if it doesn't cancel the close and is
  // not closed in 5000ms, in this way we can quickly show the unresponsive
  // dialog when the window is busy executing some script withouth waiting for
  // the unresponsive timeout.
  if (!Browser::Get()->is_quiting() &&
      window_unresposive_closure_.IsCancelled())
    ScheduleUnresponsiveEvent(5000);

  if (web_contents->NeedToFireBeforeUnload())
    web_contents->GetRenderViewHost()->FirePageBeforeUnload(false);
  else
    web_contents->Close();
}

content::WebContents* NativeWindow::GetWebContents() const {
{'fraction_non_alphanumeric': 0.13306168329352255, 'fraction_numerical': 0.002482319329305419, 'mean_word_length': 5.048725212464589, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 135, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5143887', 'n_tokens_mistral': 6801, 'n_tokens_neox': 6694, 'n_words': 1264}