<commit_before>// Copyright (c) 2006-2008 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/external_tab_container.h"

#include <string>

#include "app/l10n_util.h"
#include "app/win_util.h"
#include "base/logging.h"
#include "base/win_util.h"
#include "chrome/browser/automation/automation_provider.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/debugger/devtools_manager.h"
#include "chrome/browser/load_notification_details.h"
#include "chrome/browser/page_info_window.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/provisional_load_details.h"
#include "chrome/browser/views/tab_contents/render_view_context_menu_external_win.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/views/tab_contents/tab_contents_container.h"
#include "chrome/common/bindings_policy.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/notification_service.h"
#include "chrome/test/automation/automation_messages.h"
#include "grit/generated_resources.h"
#include "views/window/window.h"

static const wchar_t kWindowObjectKey[] = L"ChromeWindowObject";

ExternalTabContainer::PendingTabs ExternalTabContainer::pending_tabs_;

ExternalTabContainer::ExternalTabContainer(
    AutomationProvider* automation, AutomationResourceMessageFilter* filter)
    : automation_(automation),
      tab_contents_(NULL),
      tab_contents_container_(NULL),
      tab_handle_(0),
      ignore_next_load_notification_(false),
      automation_resource_message_filter_(filter),
      load_requests_via_automation_(false),
      handle_top_level_requests_(false) {
}

ExternalTabContainer::~ExternalTabContainer() {
  Uninitialize();
}

bool ExternalTabContainer::Init(Profile* profile,
                                HWND parent,
                                const gfx::Rect& bounds,
                                DWORD style,
                                bool load_requests_via_automation,
                                bool handle_top_level_requests,
                                TabContents* existing_contents,
                                const GURL& initial_url) {
  if (IsWindow()) {
    NOTREACHED();
    return false;
  }

  load_requests_via_automation_ = load_requests_via_automation;
  handle_top_level_requests_ = handle_top_level_requests;

  set_window_style(WS_POPUP | WS_CLIPCHILDREN);
  views::WidgetWin::Init(NULL, bounds);
  if (!IsWindow()) {
    NOTREACHED();
    return false;
  }

  // TODO(jcampan): limit focus traversal to contents.

  // We don't ever remove the prop because the lifetime of this object
  // is the same as the lifetime of the window
  SetProp(GetNativeView(), kWindowObjectKey, this);

  if (load_requests_via_automation) {
    // Customize our profile.
    // TODO(joshia): If we are loading requests via automation
    // and handling cookies in automation then it's probably better to
    // use OTR profile so that cookies are not persisted in chrome.
    automation_profile_.reset(new AutomationProfileImpl);
    automation_profile_->Initialize(profile,
                                    automation_resource_message_filter_);
    profile = automation_profile_.get();
  }

  if (existing_contents) {
    tab_contents_ = existing_contents;
    tab_contents_->controller().set_profile(profile);
  } else {
    tab_contents_ = new TabContents(profile, NULL, MSG_ROUTING_NONE, NULL,
                                    NULL);
  }

  tab_contents_->set_delegate(this);

  tab_contents_->GetMutableRendererPrefs()->browser_handles_top_level_requests =
      handle_top_level_requests;

  if (!existing_contents) {
    tab_contents_->render_view_host()->AllowBindings(
        BindingsPolicy::EXTERNAL_HOST);
  }

  // Create a TabContentsContainer to handle focus cycling using Tab and
  // Shift-Tab.
  tab_contents_container_ = new TabContentsContainer;
  SetContentsView(tab_contents_container_);

  // Note that SetTabContents must be called after AddChildView is called
  tab_contents_container_->ChangeTabContents(tab_contents_);

  NavigationController* controller = &tab_contents_->controller();
  registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
                 Source<NavigationController>(controller));
  registrar_.Add(this, NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR,
                 Source<NavigationController>(controller));
  registrar_.Add(this, NotificationType::LOAD_STOP,
                 Source<NavigationController>(controller));
  registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
                 Source<TabContents>(tab_contents_));
  registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED,
                 Source<TabContents>(tab_contents_));

  NotificationService::current()->Notify(
      NotificationType::EXTERNAL_TAB_CREATED,
      Source<NavigationController>(controller),
      NotificationService::NoDetails());

  // Start loading initial URL
  if (!initial_url.is_empty()) {
    // Navigate out of context since we don't have a 'tab_handle_' yet.
    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
        this, &ExternalTabContainer::Navigate, initial_url, GURL()));
  }

  // We need WS_POPUP to be on the window during initialization, but
  // once initialized we apply the requested style which may or may not
  // include the popup bit.
  // Note that it's important to do this before we call SetParent since
  // during the SetParent call we will otherwise get a WA_ACTIVATE call
  // that causes us to steal the current focus.
  SetWindowLong(GWL_STYLE, (GetWindowLong(GWL_STYLE) & ~WS_POPUP) | style);

  // Now apply the parenting and style
  if (parent)
    SetParent(GetNativeView(), parent);

  ::ShowWindow(tab_contents_->GetNativeView(), SW_SHOWNA);

  disabled_context_menu_ids_.push_back(
      IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD);
  return true;
}

void ExternalTabContainer::Uninitialize() {
  RenderViewHost* rvh = tab_contents_->render_view_host();
  if (rvh) {
    DevToolsManager::GetInstance()->UnregisterDevToolsClientHostFor(rvh);
  }
  registrar_.RemoveAll();
  if (tab_contents_) {
    NotificationService::current()->Notify(
        NotificationType::EXTERNAL_TAB_CLOSED,
        Source<NavigationController>(&tab_contents_->controller()),
        Details<ExternalTabContainer>(this));

    delete tab_contents_;
    tab_contents_ = NULL;
  }
}

bool ExternalTabContainer::Reinitialize(<commit_msg>Reverting 27407. Review URL: http://codereview.chromium.org/249027<commit_after>// Copyright (c) 2006-2008 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/external_tab_container.h"

#include <string>

#include "app/l10n_util.h"
#include "app/win_util.h"
#include "base/logging.h"
#include "base/win_util.h"
#include "chrome/browser/automation/automation_provider.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/load_notification_details.h"
#include "chrome/browser/page_info_window.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/provisional_load_details.h"
#include "chrome/browser/views/tab_contents/render_view_context_menu_external_win.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/views/tab_contents/tab_contents_container.h"
#include "chrome/common/bindings_policy.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/notification_service.h"
#include "chrome/test/automation/automation_messages.h"
#include "grit/generated_resources.h"
#include "views/window/window.h"

static const wchar_t kWindowObjectKey[] = L"ChromeWindowObject";

ExternalTabContainer::PendingTabs ExternalTabContainer::pending_tabs_;

ExternalTabContainer::ExternalTabContainer(
    AutomationProvider* automation, AutomationResourceMessageFilter* filter)
    : automation_(automation),
      tab_contents_(NULL),
      tab_contents_container_(NULL),
      tab_handle_(0),
      ignore_next_load_notification_(false),
      automation_resource_message_filter_(filter),
      load_requests_via_automation_(false),
      handle_top_level_requests_(false) {
}

ExternalTabContainer::~ExternalTabContainer() {
  Uninitialize();
}

bool ExternalTabContainer::Init(Profile* profile,
                                HWND parent,
                                const gfx::Rect& bounds,
                                DWORD style,
                                bool load_requests_via_automation,
                                bool handle_top_level_requests,
                                TabContents* existing_contents,
                                const GURL& initial_url) {
  if (IsWindow()) {
    NOTREACHED();
    return false;
  }

  load_requests_via_automation_ = load_requests_via_automation;
  handle_top_level_requests_ = handle_top_level_requests;

  set_window_style(WS_POPUP | WS_CLIPCHILDREN);
  views::WidgetWin::Init(NULL, bounds);
  if (!IsWindow()) {
    NOTREACHED();
    return false;
  }

  // TODO(jcampan): limit focus traversal to contents.

  // We don't ever remove the prop because the lifetime of this object
  // is the same as the lifetime of the window
  SetProp(GetNativeView(), kWindowObjectKey, this);

  if (load_requests_via_automation) {
    // Customize our profile.
    // TODO(joshia): If we are loading requests via automation
    // and handling cookies in automation then it's probably better to
    // use OTR profile so that cookies are not persisted in chrome.
    automation_profile_.reset(new AutomationProfileImpl);
    automation_profile_->Initialize(profile,
                                    automation_resource_message_filter_);
    profile = automation_profile_.get();
  }

  if (existing_contents) {
    tab_contents_ = existing_contents;
    tab_contents_->controller().set_profile(profile);
  } else {
    tab_contents_ = new TabContents(profile, NULL, MSG_ROUTING_NONE, NULL,
                                    NULL);
  }

  tab_contents_->set_delegate(this);

  tab_contents_->GetMutableRendererPrefs()->browser_handles_top_level_requests =
      handle_top_level_requests;

  if (!existing_contents) {
    tab_contents_->render_view_host()->AllowBindings(
        BindingsPolicy::EXTERNAL_HOST);
  }

  // Create a TabContentsContainer to handle focus cycling using Tab and
  // Shift-Tab.
  tab_contents_container_ = new TabContentsContainer;
  SetContentsView(tab_contents_container_);

  // Note that SetTabContents must be called after AddChildView is called
  tab_contents_container_->ChangeTabContents(tab_contents_);

  NavigationController* controller = &tab_contents_->controller();
  registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
                 Source<NavigationController>(controller));
  registrar_.Add(this, NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR,
                 Source<NavigationController>(controller));
  registrar_.Add(this, NotificationType::LOAD_STOP,
                 Source<NavigationController>(controller));
  registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
                 Source<TabContents>(tab_contents_));
  registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED,
                 Source<TabContents>(tab_contents_));

  NotificationService::current()->Notify(
      NotificationType::EXTERNAL_TAB_CREATED,
      Source<NavigationController>(controller),
      NotificationService::NoDetails());

  // Start loading initial URL
  if (!initial_url.is_empty()) {
    // Navigate out of context since we don't have a 'tab_handle_' yet.
    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
        this, &ExternalTabContainer::Navigate, initial_url, GURL()));
  }

  // We need WS_POPUP to be on the window during initialization, but
  // once initialized we apply the requested style which may or may not
  // include the popup bit.
  // Note that it's important to do this before we call SetParent since
  // during the SetParent call we will otherwise get a WA_ACTIVATE call
  // that causes us to steal the current focus.
  SetWindowLong(GWL_STYLE, (GetWindowLong(GWL_STYLE) & ~WS_POPUP) | style);

  // Now apply the parenting and style
  if (parent)
    SetParent(GetNativeView(), parent);

  ::ShowWindow(tab_contents_->GetNativeView(), SW_SHOWNA);

  disabled_context_menu_ids_.push_back(
      IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD);
  return true;
}

void ExternalTabContainer::Uninitialize() {
  registrar_.RemoveAll();
  if (tab_contents_) {
    NotificationService::current()->Notify(
        NotificationType::EXTERNAL_TAB_CLOSED,
        Source<NavigationController>(&tab_contents_->controller()),
        Details<ExternalTabContainer>(this));

    delete tab_contents_;
    tab_contents_ = NULL;
  }
}

bool ExternalTabContainer::Reinitialize(
{'fraction_non_alphanumeric': 0.09431355997237358, 'fraction_numerical': 0.0025324226843680456, 'mean_word_length': 3.914027149321267, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '918856', 'n_tokens_mistral': 3821, 'n_tokens_neox': 3680, 'n_words': 779}