// Copyright (c) 2011 The Chromium Embedded Framework 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 "include/cef.h" #include "testing/gtest/include/gtest/gtest.h" #include "test_handler.h" namespace { class TestDOMHandler : public TestHandler { public: class Visitor : public CefThreadSafeBase { public: Visitor(TestDOMHandler* handler) : handler_(handler) {} void TestHeadNodeStructure(CefRefPtr headNode) { EXPECT_TRUE(headNode.get()); EXPECT_TRUE(headNode->IsElement()); EXPECT_FALSE(headNode->IsText()); EXPECT_EQ(headNode->GetName(), "HEAD"); EXPECT_EQ(headNode->GetElementTagName(), "HEAD"); EXPECT_TRUE(headNode->HasChildren()); EXPECT_FALSE(headNode->HasElementAttributes()); CefRefPtr titleNode = headNode->GetFirstChild(); EXPECT_TRUE(titleNode.get()); EXPECT_TRUE(titleNode->IsElement()); EXPECT_FALSE(titleNode->IsText()); EXPECT_EQ(titleNode->GetName(), "TITLE"); EXPECT_EQ(titleNode->GetElementTagName(), "TITLE"); EXPECT_FALSE(titleNode->GetNextSibling().get()); EXPECT_FALSE(titleNode->GetPreviousSibling().get()); EXPECT_TRUE(titleNode->HasChildren()); EXPECT_FALSE(titleNode->HasElementAttributes()); CefRefPtr textNode = titleNode->GetFirstChild(); EXPECT_TRUE(textNode.get()); EXPECT_FALSE(textNode->IsElement()); EXPECT_TRUE(textNode->IsText()); EXPECT_EQ(textNode->GetValue(), "The Title"); EXPECT_FALSE(textNode->GetNextSibling().get()); EXPECT_FALSE(textNode->GetPreviousSibling().get()); EXPECT_FALSE(textNode->HasChildren()); } void TestBodyNodeStructure(CefRefPtr bodyNode) { EXPECT_TRUE(bodyNode.get()); EXPECT_TRUE(bodyNode->IsElement()); EXPECT_FALSE(bodyNode->IsText()); EXPECT_EQ(bodyNode->GetName(), "BODY"); EXPECT_EQ(bodyNode->GetElementTagName(), "BODY"); EXPECT_TRUE(bodyNode->HasChildren()); EXPECT_FALSE(bodyNode->HasElementAttributes()); CefRefPtr h1Node = bodyNode->GetFirstChild(); EXPECT_TRUE(h1Node.get()); EXPECT_TRUE(h1Node->IsElement()); EXPECT_FALSE(h1Node->IsText()); EXPECT_EQ(h1Node->GetName(), "H1"); EXPECT_EQ(h1Node->GetElementTagName(), "H1"); EXPECT_FALSE(h1Node->GetNextSibling().get()); EXPECT_FALSE(h1Node->GetPreviousSibling().get()); EXPECT_TRUE(h1Node->HasChildren()); EXPECT_FALSE(h1Node->HasElementAttributes()); CefRefPtr textNode = h1Node->GetFirstChild(); EXPECT_TRUE(textNode.get()); EXPECT_FALSE(textNode->IsElement()); EXPECT_TRUE(textNode->IsText()); EXPECT_EQ(textNode->GetValue(), "Hello From"); EXPECT_FALSE(textNode->GetPreviousSibling().get()); EXPECT_FALSE(textNode->HasChildren()); CefRefPtr brNode = textNode->GetNextSibling(); EXPECT_TRUE(brNode.get()); EXPECT_TRUE(brNode->IsElement()); EXPECT_FALSE(brNode->IsText()); EXPECT_EQ(brNode->GetName(), "BR"); EXPECT_EQ(brNode->GetElementTagName(), "BR"); EXPECT_FALSE(brNode->HasChildren()); EXPECT_TRUE(brNode->HasElementAttributes()); EXPECT_TRUE(brNode->HasElementAttribute("class")); EXPECT_EQ(brNode->GetElementAttribute("class"), "some_class"); EXPECT_TRUE(brNode->HasElementAttribute("id")); EXPECT_EQ(brNode->GetElementAttribute("id"), "some_id"); EXPECT_FALSE(brNode->HasElementAttribute("no_existing")); CefDOMNode::AttributeMap map; brNode->GetElementAttributes(map); ASSERT_EQ(map.size(), (size_t)2); EXPECT_EQ(map["class"], "some_class"); EXPECT_EQ(map["id"], "some_id"); // Can also retrieve by ID. brNode = bodyNode->GetDocument()->GetElementById("some_id"); EXPECT_TRUE(brNode.get()); EXPECT_TRUE(brNode->IsElement()); EXPECT_FALSE(brNode->IsText()); EXPECT_EQ(brNode->GetName(), "BR"); EXPECT_EQ(brNode->GetElementTagName(), "BR"); textNode = brNode->GetNextSibling(); EXPECT_TRUE(textNode.get()); EXPECT_FALSE(textNode->IsElement()); EXPECT_TRUE(textNode->IsText()); EXPECT_EQ(textNode->GetValue(), "Main Frame"); EXPECT_FALSE(textNode->GetNextSibling().get()); EXPECT_FALSE(textNode->HasChildren()); } // Test document structure by iterating through the DOM tree. void TestStructure(CefRefPtr document) { EXPECT_EQ(document->GetTitle(), "The Title"); EXPECT_EQ(document->GetBaseURL(), "http://tests/main.html"); EXPECT_EQ(document->GetCompleteURL("foo.html"), "http://tests/foo.html"); // Navigate the complete document structure. CefRefPtr docNode = document->GetDocument(); EXPECT_TRUE(docNode.get()); EXPECT_FALSE(docNode->IsElement()); EXPECT_FALSE(docNode->IsText()); CefRefPtr htmlNode = docNode->GetFirstChild(); EXPECT_TRUE(htmlNode.get()); EXPECT_TRUE(htmlNode->IsElement()); EXPECT_FALSE(htmlNode->IsText()); EXPECT_EQ(htmlNode->GetName(), "HTML"); EXPECT_EQ(htmlNode->GetElementTagName(), "HTML"); EXPECT_TRUE(htmlNode->HasChildren()); EXPECT_FALSE(htmlNode->HasElementAttributes()); CefRefPtr headNode = htmlNode->GetFirstChild(); TestHeadNodeStructure(headNode); CefRefPtr bodyNode = headNode->GetNextSibling(); TestBodyNodeStructure(bodyNode); // Retrieve the head node directly. headNode = document->GetHead(); TestHeadNodeStructure(headNode); // Retrieve the body node directly. bodyNode = document->GetBody(); TestBodyNodeStructure(bodyNode); } // Test document modification by changing the H1 tag. void TestModify(CefRefPtr document) { CefRefPtr bodyNode = document->GetBody(); CefRefPtr h1Node = bodyNode->GetFirstChild(); ASSERT_EQ(h1Node->GetAsMarkup(), "

Hello From
Main Frame

"); CefRefPtr textNode = h1Node->GetFirstChild(); ASSERT_EQ(textNode->GetValue(), "Hello From"); ASSERT_TRUE(textNode->SetValue("A Different Message From")); ASSERT_EQ(textNode->GetValue(), "A Different Message From"); CefRefPtr brNode = textNode->GetNextSibling(); EXPECT_EQ(brNode->GetElementAttribute("class"), "some_class"); EXPECT_TRUE(brNode->SetElementAttribute("class", "a_different_class")); EXPECT_EQ(brNode->GetElementAttribute("class"), "a_different_class"); ASSERT_EQ(h1Node->GetAsMarkup(), "

A Different Message From
Main Frame

"); ASSERT_FALSE(h1Node->SetValue("Something Different")); } virtual void Visit(CefRefPtr document) { handler_->got_visitor_called_.yes(); if (handler_->test_type_ == STRUCTURE) TestStructure(document); else if (handler_->test_type_ == MODIFY) TestModify(document); handler_->DestroyTest(); } protected: TestDOMHandler* handler_; }; enum TestType { STRUCTURE, MODIFY, }; TestDOMHandler(TestType test) : test_type_(test) { visitor_ = new Visitor(this); } virtual void RunTest() { std::stringstream mainHtml; mainHtml << "" "The Title" "" "

Hello From
Main Frame

" "" ""; AddResource("http://tests/main.html", mainHtml.str(), "text/html"); CreateBrowser("http://tests/main.html"); } virtual RetVal HandleLoadEnd(CefRefPtr browser, CefRefPtr frame, int httpStatusCode) { if(frame->IsMain()) { // The page is done loading so visit the DOM. browser->GetMainFrame()->VisitDOM(visitor_.get()); } return RV_CONTINUE; } CefRefPtr visitor_; TestType test_type_; TrackCallback got_visitor_called_; }; } // namespace // Test DOM structure reading. TEST(DOMTest, Read) { CefRefPtr handler = new TestDOMHandler(TestDOMHandler::STRUCTURE); handler->ExecuteTest(); EXPECT_TRUE(handler->got_visitor_called_); } // Test DOM modifications. TEST(DOMTest, Modify) { CefRefPtr handler = new TestDOMHandler(TestDOMHandler::MODIFY); handler->ExecuteTest(); EXPECT_TRUE(handler->got_visitor_called_); }