OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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 <memory> |
| 6 #include <string> |
| 7 #include <vector> |
| 8 |
| 9 #include "base/base64.h" |
| 10 #include "base/json/json_reader.h" |
| 11 #include "base/path_service.h" |
| 12 #include "base/threading/thread_restrictions.h" |
| 13 #include "content/public/test/browser_test.h" |
| 14 #include "headless/grit/headless_browsertest_resources.h" |
| 15 #include "headless/public/devtools/domains/runtime.h" |
| 16 #include "headless/public/headless_browser.h" |
| 17 #include "headless/public/headless_devtools_client.h" |
| 18 #include "headless/public/headless_tab_socket.h" |
| 19 #include "headless/public/headless_web_contents.h" |
| 20 #include "headless/test/headless_browser_test.h" |
| 21 #include "testing/gmock/include/gmock/gmock.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" |
| 23 #include "ui/base/resource/resource_bundle.h" |
| 24 |
| 25 namespace headless { |
| 26 |
| 27 class HeadlessJsBindingsTest |
| 28 : public HeadlessAsyncDevTooledBrowserTest, |
| 29 public HeadlessTabSocket::Listener, |
| 30 public HeadlessDevToolsClient::RawProtocolListener { |
| 31 public: |
| 32 void SetUp() override { |
| 33 options()->mojo_service_names.insert("headless::TabSocket"); |
| 34 HeadlessAsyncDevTooledBrowserTest::SetUp(); |
| 35 } |
| 36 |
| 37 void SetUpOnMainThread() override { |
| 38 base::ThreadRestrictions::SetIOAllowed(true); |
| 39 base::FilePath pak_path; |
| 40 ASSERT_TRUE(PathService::Get(base::DIR_MODULE, &pak_path)); |
| 41 pak_path = pak_path.AppendASCII("headless_browser_tests.pak"); |
| 42 ResourceBundle::GetSharedInstance().AddDataPackFromPath( |
| 43 pak_path, ui::SCALE_FACTOR_NONE); |
| 44 } |
| 45 |
| 46 void RunDevTooledTest() override { |
| 47 headless_tab_socket_ = web_contents_->GetHeadlessTabSocket(); |
| 48 DCHECK(headless_tab_socket_); |
| 49 headless_tab_socket_->SetListener(this); |
| 50 devtools_client_->SetRawProtocolListener(this); |
| 51 devtools_client_->GetRuntime()->Evaluate( |
| 52 ResourceBundle::GetSharedInstance() |
| 53 .GetRawDataResource(DEVTOOLS_BINDINGS_TEST) |
| 54 .as_string(), |
| 55 base::Bind(&HeadlessJsBindingsTest::FailOnJsEvaluateException, |
| 56 base::Unretained(this))); |
| 57 RunJsBindingsTest(); |
| 58 } |
| 59 |
| 60 virtual void RunJsBindingsTest() = 0; |
| 61 virtual std::string GetExpectedResult() = 0; |
| 62 |
| 63 void FailOnJsEvaluateException( |
| 64 std::unique_ptr<runtime::EvaluateResult> result) { |
| 65 if (!result->HasExceptionDetails()) |
| 66 return; |
| 67 |
| 68 FinishAsynchronousTest(); |
| 69 |
| 70 const runtime::ExceptionDetails* exception_details = |
| 71 result->GetExceptionDetails(); |
| 72 FAIL() << exception_details->GetText() |
| 73 << (exception_details->HasException() |
| 74 ? exception_details->GetException()->GetDescription().c_str() |
| 75 : ""); |
| 76 } |
| 77 |
| 78 void OnMessageFromTab(const std::string& json_message) override { |
| 79 std::unique_ptr<base::Value> message = |
| 80 base::JSONReader::Read(json_message, base::JSON_PARSE_RFC); |
| 81 const base::DictionaryValue* message_dict; |
| 82 const base::DictionaryValue* params_dict; |
| 83 std::string method; |
| 84 int id; |
| 85 if (!message || !message->GetAsDictionary(&message_dict) || |
| 86 !message_dict->GetString("method", &method) || |
| 87 !message_dict->GetDictionary("params", ¶ms_dict) || |
| 88 !message_dict->GetInteger("id", &id)) { |
| 89 FinishAsynchronousTest(); |
| 90 FAIL() << "Badly formed message " << json_message; |
| 91 return; |
| 92 } |
| 93 |
| 94 if (method == "__Result") { |
| 95 std::string result; |
| 96 params_dict->GetString("result", &result); |
| 97 EXPECT_EQ(GetExpectedResult(), result); |
| 98 FinishAsynchronousTest(); |
| 99 return; |
| 100 } |
| 101 |
| 102 devtools_client_->SendRawDevToolsMessage(json_message); |
| 103 } |
| 104 |
| 105 HeadlessWebContents::Builder::TabSocketType GetTabSocketType() override { |
| 106 return HeadlessWebContents::Builder::TabSocketType::MAIN_WORLD; |
| 107 } |
| 108 |
| 109 bool OnProtocolMessage(const std::string& devtools_agent_host_id, |
| 110 const std::string& json_message, |
| 111 const base::DictionaryValue& parsed_message) override { |
| 112 int id; |
| 113 // If |parsed_message| contains an id we know this is a message reply. |
| 114 if (parsed_message.GetInteger("id", &id)) { |
| 115 // We are only interested in message replies (ones with an id) where the |
| 116 // id is odd. The reason is HeadlessDevToolsClientImpl uses even/oddness |
| 117 // to distinguish between commands send from the C++ bindings and those |
| 118 // via HeadlessDevToolsClientImpl::SendRawDevToolsMessage. |
| 119 if ((id % 2) == 0) |
| 120 return false; |
| 121 } |
| 122 |
| 123 headless_tab_socket_->SendMessageToTab(json_message); |
| 124 return true; |
| 125 } |
| 126 |
| 127 private: |
| 128 HeadlessTabSocket* headless_tab_socket_; |
| 129 }; |
| 130 |
| 131 class SimpleCommandJsBindingsTest : public HeadlessJsBindingsTest { |
| 132 public: |
| 133 void RunJsBindingsTest() override { |
| 134 devtools_client_->GetRuntime()->Evaluate( |
| 135 "new chromium.BindingsTest().evalOneAddOne();", |
| 136 base::Bind(&HeadlessJsBindingsTest::FailOnJsEvaluateException, |
| 137 base::Unretained(this))); |
| 138 } |
| 139 |
| 140 std::string GetExpectedResult() override { return "2"; } |
| 141 }; |
| 142 |
| 143 HEADLESS_ASYNC_DEVTOOLED_TEST_F(SimpleCommandJsBindingsTest); |
| 144 |
| 145 class SimpleEventJsBindingsTest : public HeadlessJsBindingsTest { |
| 146 public: |
| 147 void RunJsBindingsTest() override { |
| 148 devtools_client_->GetRuntime()->Evaluate( |
| 149 "new chromium.BindingsTest().listenForChildNodeCountUpdated();", |
| 150 base::Bind(&HeadlessJsBindingsTest::FailOnJsEvaluateException, |
| 151 base::Unretained(this))); |
| 152 } |
| 153 |
| 154 std::string GetExpectedResult() override { |
| 155 return "{\"nodeId\":4,\"childNodeCount\":1}"; |
| 156 } |
| 157 }; |
| 158 |
| 159 HEADLESS_ASYNC_DEVTOOLED_TEST_F(SimpleEventJsBindingsTest); |
| 160 } // namespace headless |
OLD | NEW |