1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/command_line.h"
6#include "base/compiler_specific.h"
7#include "base/prefs/pref_service.h"
8#include "base/strings/string_number_conversions.h"
9#include "chrome/browser/devtools/browser_list_tabcontents_provider.h"
10#include "chrome/browser/devtools/device/devtools_android_bridge.h"
11#include "chrome/browser/devtools/device/self_device_provider.h"
12#include "chrome/browser/profiles/profile.h"
13#include "chrome/browser/ui/browser.h"
14#include "chrome/browser/ui/tabs/tab_strip_model.h"
15#include "chrome/common/chrome_switches.h"
16#include "chrome/common/pref_names.h"
17#include "chrome/test/base/in_process_browser_test.h"
18#include "chrome/test/base/ui_test_utils.h"
19#include "content/public/browser/web_contents.h"
20#include "content/public/test/browser_test_utils.h"
21#include "content/public/test/test_utils.h"
22
23namespace {
24const char kPortForwardingTestPage[] =
25    "files/devtools/port_forwarding/main.html";
26
27const int kDefaultDebuggingPort = 9223;
28}
29
30class PortForwardingTest: public InProcessBrowserTest {
31  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
32    InProcessBrowserTest::SetUpCommandLine(command_line);
33    command_line->AppendSwitchASCII(switches::kRemoteDebuggingPort,
34        base::IntToString(kDefaultDebuggingPort));
35  }
36
37 protected:
38  class Listener : public DevToolsAndroidBridge::PortForwardingListener {
39   public:
40    explicit Listener(Profile* profile)
41        : profile_(profile),
42          skip_empty_devices_(true) {
43      DevToolsAndroidBridge::Factory::GetForProfile(profile_)->
44          AddPortForwardingListener(this);
45    }
46
47    virtual ~Listener() {
48      DevToolsAndroidBridge::Factory::GetForProfile(profile_)->
49          RemovePortForwardingListener(this);
50    }
51
52    virtual void PortStatusChanged(const DevicesStatus& status) OVERRIDE {
53      if (status.empty() && skip_empty_devices_)
54        return;
55      base::MessageLoop::current()->PostTask(
56          FROM_HERE, base::MessageLoop::QuitClosure());
57    }
58
59    void set_skip_empty_devices(bool skip_empty_devices) {
60      skip_empty_devices_ = skip_empty_devices;
61    }
62
63   private:
64    Profile* profile_;
65    bool skip_empty_devices_;
66  };
67};
68
69IN_PROC_BROWSER_TEST_F(PortForwardingTest,
70                       LoadPageWithStyleAnsScript) {
71  Profile* profile = browser()->profile();
72
73  AndroidDeviceManager::DeviceProviders device_providers;
74  device_providers.push_back(new SelfAsDeviceProvider(kDefaultDebuggingPort));
75  DevToolsAndroidBridge::Factory::GetForProfile(profile)->
76      set_device_providers_for_test(device_providers);
77
78  ASSERT_TRUE(test_server()->Start());
79  GURL original_url = test_server()->GetURL(kPortForwardingTestPage);
80
81  std::string forwarding_port("8000");
82  GURL forwarding_url(original_url.scheme() + "://" +
83      original_url.host() + ":" + forwarding_port + original_url.path());
84
85  PrefService* prefs = profile->GetPrefs();
86  prefs->SetBoolean(prefs::kDevToolsPortForwardingEnabled, true);
87
88  base::DictionaryValue config;
89  config.SetString(
90      forwarding_port, original_url.host() + ":" + original_url.port());
91  prefs->Set(prefs::kDevToolsPortForwardingConfig, config);
92
93  Listener wait_for_port_forwarding(profile);
94  content::RunMessageLoop();
95
96  BrowserListTabContentsProvider::EnableTethering();
97
98  ui_test_utils::NavigateToURL(browser(), forwarding_url);
99
100  content::RenderViewHost* rvh = browser()->tab_strip_model()->
101      GetWebContentsAt(0)->GetRenderViewHost();
102
103  std::string result;
104  ASSERT_TRUE(
105      content::ExecuteScriptAndExtractString(
106          rvh,
107          "window.domAutomationController.send(document.title)",
108          &result));
109  ASSERT_EQ("Port forwarding test", result) << "Document has not loaded.";
110
111  ASSERT_TRUE(
112      content::ExecuteScriptAndExtractString(
113          rvh,
114          "window.domAutomationController.send(getBodyTextContent())",
115          &result));
116  ASSERT_EQ("content", result) << "Javascript has not loaded.";
117
118  ASSERT_TRUE(
119      content::ExecuteScriptAndExtractString(
120          rvh,
121          "window.domAutomationController.send(getBodyMarginLeft())",
122          &result));
123  ASSERT_EQ("100px", result) << "CSS has not loaded.";
124
125  // Test that disabling port forwarding is handled normally.
126  wait_for_port_forwarding.set_skip_empty_devices(false);
127  prefs->SetBoolean(prefs::kDevToolsPortForwardingEnabled, false);
128  content::RunMessageLoop();
129}
130