// Copyright (c) 2013 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 "base/command_line.h"
#include "base/containers/hash_tables.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"

namespace content {

namespace {

// This is a helper function for the tests which attempt to create a
// duplicate RenderViewHost or RenderWidgetHost. It tries to create two objects
// with the same process and routing ids, which causes a collision.
// It creates a couple of windows in process 1, which causes a few routing ids
// to be allocated. Then a cross-process navigation is initiated, which causes a
// new process 2 to be created and have a pending RenderViewHost for it. The
// routing id of the RenderViewHost which is target for a duplicate is set
// into |target_routing_id| and the pending RenderViewHost which is used for
// the attempt is the return value.
RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell,
                                            int* target_routing_id) {
  GURL foo("http://foo.com/files/simple_page.html");

  // Start off with initial navigation, so we get the first process allocated.
  NavigateToURL(shell, foo);

  // Open another window, so we generate some more routing ids.
  ShellAddedObserver shell2_observer;
  EXPECT_TRUE(ExecuteScript(
      shell->web_contents(), "window.open(document.URL + '#2');"));
  Shell* shell2 = shell2_observer.GetShell();

  // The new window must be in the same process, but have a new routing id.
  EXPECT_EQ(shell->web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
            shell2->web_contents()->GetRenderViewHost()->GetProcess()->GetID());
  *target_routing_id =
      shell2->web_contents()->GetRenderViewHost()->GetRoutingID();
  EXPECT_NE(*target_routing_id,
            shell->web_contents()->GetRenderViewHost()->GetRoutingID());

  // Now, simulate a link click coming from the renderer.
  GURL extension_url("https://bar.com/files/simple_page.html");
  WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell->web_contents());
  wc->RequestOpenURL(
      shell->web_contents()->GetRenderViewHost(), extension_url,
      Referrer(), CURRENT_TAB, wc->GetFrameTree()->root()->frame_id(),
      false, true);

  // Since the navigation above requires a cross-process swap, there will be a
  // pending RenderViewHost. Ensure it exists and is in a different process
  // than the initial page.
  RenderViewHostImpl* pending_rvh =
      wc->GetRenderManagerForTesting()->pending_render_view_host();
  EXPECT_TRUE(pending_rvh != NULL);
  EXPECT_NE(shell->web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
            pending_rvh->GetProcess()->GetID());

  return pending_rvh;
}

}  // namespace


// The goal of these tests will be to "simulate" exploited renderer processes,
// which can send arbitrary IPC messages and confuse browser process internal
// state, leading to security bugs. We are trying to verify that the browser
// doesn't perform any dangerous operations in such cases.
class SecurityExploitBrowserTest : public ContentBrowserTest {
 public:
  SecurityExploitBrowserTest() {}
  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    ASSERT_TRUE(test_server()->Start());

    // Add a host resolver rule to map all outgoing requests to the test server.
    // This allows us to use "real" hostnames in URLs, which we can use to
    // create arbitrary SiteInstances.
    command_line->AppendSwitchASCII(
        switches::kHostResolverRules,
        "MAP * " + test_server()->host_port_pair().ToString() +
            ",EXCLUDE localhost");
  }
};

// Ensure that we kill the renderer process if we try to give it WebUI
// properties and it doesn't have enabled WebUI bindings.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, SetWebUIProperty) {
  GURL foo("http://foo.com/files/simple_page.html");

  NavigateToURL(shell(), foo);
  EXPECT_EQ(0,
      shell()->web_contents()->GetRenderViewHost()->GetEnabledBindings());

  content::WindowedNotificationObserver terminated(
      content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
      content::NotificationService::AllSources());
  shell()->web_contents()->GetRenderViewHost()->SetWebUIProperty(
      "toolkit", "views");
  terminated.Wait();
}

// This is a test for crbug.com/312016 attempting to create duplicate
// RenderViewHosts. SetupForDuplicateHosts sets up this test case and leaves
// it in a state with pending RenderViewHost. Before the commit of the new
// pending RenderViewHost, this test case creates a new window through the new
// process.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       AttemptDuplicateRenderViewHost) {
  int duplicate_routing_id = MSG_ROUTING_NONE;
  RenderViewHostImpl* pending_rvh =
      PrepareToDuplicateHosts(shell(), &duplicate_routing_id);
  EXPECT_NE(MSG_ROUTING_NONE, duplicate_routing_id);

  // Since this test executes on the UI thread and hopping threads might cause
  // different timing in the test, let's simulate a CreateNewWindow call coming
  // from the IO thread.
  ViewHostMsg_CreateWindow_Params params;
  DOMStorageContextWrapper* dom_storage_context =
      static_cast<DOMStorageContextWrapper*>(
          BrowserContext::GetStoragePartition(
              shell()->web_contents()->GetBrowserContext(),
              pending_rvh->GetSiteInstance())->GetDOMStorageContext());
  scoped_refptr<SessionStorageNamespaceImpl> session_storage(
      new SessionStorageNamespaceImpl(dom_storage_context));
  // Cause a deliberate collision in routing ids.
  int main_frame_routing_id = duplicate_routing_id + 1;
  pending_rvh->CreateNewWindow(
      duplicate_routing_id, main_frame_routing_id, params, session_storage);

  // If the above operation doesn't cause a crash, the test has succeeded!
}

// This is a test for crbug.com/312016. It tries to create two RenderWidgetHosts
// with the same process and routing ids, which causes a collision. It is almost
// identical to the AttemptDuplicateRenderViewHost test case.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       AttemptDuplicateRenderWidgetHost) {
  int duplicate_routing_id = MSG_ROUTING_NONE;
  RenderViewHostImpl* pending_rvh =
      PrepareToDuplicateHosts(shell(), &duplicate_routing_id);
  EXPECT_NE(MSG_ROUTING_NONE, duplicate_routing_id);

  // Since this test executes on the UI thread and hopping threads might cause
  // different timing in the test, let's simulate a CreateNewWidget call coming
  // from the IO thread.  Use the existing window routing id to cause a
  // deliberate collision.
  pending_rvh->CreateNewWidget(duplicate_routing_id, blink::WebPopupTypeSelect);

  // If the above operation doesn't crash, the test has succeeded!
}

}  // namespace content
