OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <memory> | 5 #include <memory> |
6 | 6 |
7 #include "base/json/json_reader.h" | 7 #include "base/json/json_reader.h" |
| 8 #include "base/json/json_writer.h" |
8 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
9 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| 11 #include "base/strings/string_util.h" |
10 #include "content/public/browser/render_widget_host_view.h" | 12 #include "content/public/browser/render_widget_host_view.h" |
11 #include "content/public/browser/web_contents.h" | 13 #include "content/public/browser/web_contents.h" |
12 #include "content/public/common/url_constants.h" | 14 #include "content/public/common/url_constants.h" |
13 #include "content/public/test/browser_test.h" | 15 #include "content/public/test/browser_test.h" |
14 #include "headless/lib/browser/headless_web_contents_impl.h" | 16 #include "headless/lib/browser/headless_web_contents_impl.h" |
15 #include "headless/public/devtools/domains/browser.h" | 17 #include "headless/public/devtools/domains/browser.h" |
16 #include "headless/public/devtools/domains/dom.h" | 18 #include "headless/public/devtools/domains/dom.h" |
| 19 #include "headless/public/devtools/domains/dom_snapshot.h" |
17 #include "headless/public/devtools/domains/emulation.h" | 20 #include "headless/public/devtools/domains/emulation.h" |
18 #include "headless/public/devtools/domains/inspector.h" | 21 #include "headless/public/devtools/domains/inspector.h" |
19 #include "headless/public/devtools/domains/network.h" | 22 #include "headless/public/devtools/domains/network.h" |
20 #include "headless/public/devtools/domains/page.h" | 23 #include "headless/public/devtools/domains/page.h" |
21 #include "headless/public/devtools/domains/runtime.h" | 24 #include "headless/public/devtools/domains/runtime.h" |
22 #include "headless/public/devtools/domains/target.h" | 25 #include "headless/public/devtools/domains/target.h" |
23 #include "headless/public/headless_browser.h" | 26 #include "headless/public/headless_browser.h" |
24 #include "headless/public/headless_devtools_client.h" | 27 #include "headless/public/headless_devtools_client.h" |
25 #include "headless/public/headless_devtools_target.h" | 28 #include "headless/public/headless_devtools_target.h" |
26 #include "headless/test/headless_browser_test.h" | 29 #include "headless/test/headless_browser_test.h" |
(...skipping 1171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 EXPECT_TRUE(dev_tools_client_detached_); | 1201 EXPECT_TRUE(dev_tools_client_detached_); |
1199 } | 1202 } |
1200 | 1203 |
1201 private: | 1204 private: |
1202 bool dev_tools_client_attached_ = false; | 1205 bool dev_tools_client_attached_ = false; |
1203 bool dev_tools_client_detached_ = false; | 1206 bool dev_tools_client_detached_ = false; |
1204 }; | 1207 }; |
1205 | 1208 |
1206 HEADLESS_ASYNC_DEVTOOLED_TEST_F(DevToolsAttachAndDetachNotifications); | 1209 HEADLESS_ASYNC_DEVTOOLED_TEST_F(DevToolsAttachAndDetachNotifications); |
1207 | 1210 |
| 1211 namespace { |
| 1212 |
| 1213 std::string NormaliseJSON(const std::string& json) { |
| 1214 std::unique_ptr<base::Value> parsed_json = base::JSONReader::Read(json); |
| 1215 DCHECK(parsed_json); |
| 1216 std::string normalized_json; |
| 1217 base::JSONWriter::WriteWithOptions( |
| 1218 *parsed_json, base::JSONWriter::OPTIONS_PRETTY_PRINT, &normalized_json); |
| 1219 return normalized_json; |
| 1220 } |
| 1221 |
| 1222 } // namespace |
| 1223 |
| 1224 class DomTreeExtractionBrowserTest : public HeadlessAsyncDevTooledBrowserTest, |
| 1225 public page::Observer { |
| 1226 public: |
| 1227 void RunDevTooledTest() override { |
| 1228 EXPECT_TRUE(embedded_test_server()->Start()); |
| 1229 devtools_client_->GetPage()->AddObserver(this); |
| 1230 devtools_client_->GetPage()->Enable(); |
| 1231 devtools_client_->GetPage()->Navigate( |
| 1232 embedded_test_server()->GetURL("/dom_tree_test.html").spec()); |
| 1233 } |
| 1234 |
| 1235 void OnLoadEventFired(const page::LoadEventFiredParams& params) override { |
| 1236 devtools_client_->GetPage()->Disable(); |
| 1237 devtools_client_->GetPage()->RemoveObserver(this); |
| 1238 |
| 1239 std::vector<std::string> css_whitelist = { |
| 1240 "color", "display", "font-style", "font-family", |
| 1241 "margin-left", "margin-right", "margin-top", "margin-bottom"}; |
| 1242 devtools_client_->GetDOMSnapshot()->GetExperimental()->GetSnapshot( |
| 1243 dom_snapshot::GetSnapshotParams::Builder() |
| 1244 .SetComputedStyleWhitelist(std::move(css_whitelist)) |
| 1245 .Build(), |
| 1246 base::Bind(&DomTreeExtractionBrowserTest::OnGetSnapshotResult, |
| 1247 base::Unretained(this))); |
| 1248 } |
| 1249 |
| 1250 void OnGetSnapshotResult( |
| 1251 std::unique_ptr<dom_snapshot::GetSnapshotResult> result) { |
| 1252 GURL::Replacements replace_port; |
| 1253 replace_port.SetPortStr(""); |
| 1254 |
| 1255 std::vector<std::unique_ptr<base::DictionaryValue>> dom_nodes( |
| 1256 result->GetDomNodes()->size()); |
| 1257 |
| 1258 // For convenience, flatten the dom tree into an array of dicts. |
| 1259 for (size_t i = 0; i < result->GetDomNodes()->size(); i++) { |
| 1260 dom_snapshot::DOMNode* node = (*result->GetDomNodes())[i].get(); |
| 1261 |
| 1262 dom_nodes[i].reset( |
| 1263 static_cast<base::DictionaryValue*>(node->Serialize().release())); |
| 1264 base::DictionaryValue* node_dict = dom_nodes[i].get(); |
| 1265 |
| 1266 // Frame IDs are random. |
| 1267 if (node_dict->HasKey("frameId")) |
| 1268 node_dict->SetString("frameId", "?"); |
| 1269 |
| 1270 // Ports are random. |
| 1271 std::string url; |
| 1272 if (node_dict->GetString("baseURL", &url)) { |
| 1273 node_dict->SetString("baseURL", |
| 1274 GURL(url).ReplaceComponents(replace_port).spec()); |
| 1275 } |
| 1276 |
| 1277 if (node_dict->GetString("documentURL", &url)) { |
| 1278 node_dict->SetString("documentURL", |
| 1279 GURL(url).ReplaceComponents(replace_port).spec()); |
| 1280 } |
| 1281 |
| 1282 // Merge LayoutTreeNode data into the dictionary. |
| 1283 int layout_node_index; |
| 1284 if (node_dict->GetInteger("layoutNodeIndex", &layout_node_index)) { |
| 1285 ASSERT_LE(0, layout_node_index); |
| 1286 ASSERT_GT(result->GetLayoutTreeNodes()->size(), |
| 1287 static_cast<size_t>(layout_node_index)); |
| 1288 const std::unique_ptr<dom_snapshot::LayoutTreeNode>& layout_node = |
| 1289 (*result->GetLayoutTreeNodes())[layout_node_index]; |
| 1290 |
| 1291 node_dict->Set("boundingBox", |
| 1292 layout_node->GetBoundingBox()->Serialize()); |
| 1293 |
| 1294 if (layout_node->HasLayoutText()) |
| 1295 node_dict->SetString("layoutText", layout_node->GetLayoutText()); |
| 1296 |
| 1297 if (layout_node->HasStyleIndex()) |
| 1298 node_dict->SetInteger("styleIndex", layout_node->GetStyleIndex()); |
| 1299 |
| 1300 if (layout_node->HasInlineTextNodes()) { |
| 1301 std::unique_ptr<base::ListValue> inline_text_nodes( |
| 1302 new base::ListValue()); |
| 1303 for (const std::unique_ptr<css::InlineTextBox>& inline_text_box : |
| 1304 *layout_node->GetInlineTextNodes()) { |
| 1305 size_t index = inline_text_nodes->GetSize(); |
| 1306 inline_text_nodes->Set(index, inline_text_box->Serialize()); |
| 1307 } |
| 1308 node_dict->Set("inlineTextNodes", std::move(inline_text_nodes)); |
| 1309 } |
| 1310 } |
| 1311 } |
| 1312 |
| 1313 std::vector<std::unique_ptr<base::DictionaryValue>> computed_styles( |
| 1314 result->GetComputedStyles()->size()); |
| 1315 |
| 1316 for (size_t i = 0; i < result->GetComputedStyles()->size(); i++) { |
| 1317 std::unique_ptr<base::DictionaryValue> style(new base::DictionaryValue()); |
| 1318 for (const auto& style_property : |
| 1319 *(*result->GetComputedStyles())[i]->GetProperties()) { |
| 1320 style->SetString(style_property->GetName(), style_property->GetValue()); |
| 1321 } |
| 1322 computed_styles[i] = std::move(style); |
| 1323 } |
| 1324 |
| 1325 // TODO(eseckler): Extract expectation strings into external files to make |
| 1326 // them easier to maintain. |
| 1327 const std::vector<std::string> expected_dom_nodes = { |
| 1328 R"raw_string({ |
| 1329 "backendNodeId": 3, |
| 1330 "baseURL": "http://127.0.0.1/dom_tree_test.html", |
| 1331 "boundingBox": { |
| 1332 "height": 600.0, |
| 1333 "width": 800.0, |
| 1334 "x": 0.0, |
| 1335 "y": 0.0 |
| 1336 }, |
| 1337 "childNodeIndexes": [ 1 ], |
| 1338 "documentURL": "http://127.0.0.1/dom_tree_test.html", |
| 1339 "layoutNodeIndex": 0, |
| 1340 "nodeName": "#document", |
| 1341 "nodeType": 9, |
| 1342 "nodeValue": "" |
| 1343 } |
| 1344 )raw_string", |
| 1345 |
| 1346 R"raw_string({ |
| 1347 "backendNodeId": 4, |
| 1348 "boundingBox": { |
| 1349 "height": 600.0, |
| 1350 "width": 800.0, |
| 1351 "x": 0.0, |
| 1352 "y": 0.0 |
| 1353 }, |
| 1354 "childNodeIndexes": [ 2, 9, 10 ], |
| 1355 "frameId": "?", |
| 1356 "layoutNodeIndex": 1, |
| 1357 "nodeName": "HTML", |
| 1358 "nodeType": 1, |
| 1359 "nodeValue": "", |
| 1360 "styleIndex": 0 |
| 1361 } |
| 1362 )raw_string", |
| 1363 |
| 1364 R"raw_string({ |
| 1365 "backendNodeId": 5, |
| 1366 "childNodeIndexes": [ 3, 4, 6, 7, 8 ], |
| 1367 "nodeName": "HEAD", |
| 1368 "nodeType": 1, |
| 1369 "nodeValue": "" |
| 1370 } |
| 1371 )raw_string", |
| 1372 |
| 1373 R"raw_string({ |
| 1374 "backendNodeId": 6, |
| 1375 "nodeName": "#text", |
| 1376 "nodeType": 3, |
| 1377 "nodeValue": "\n" |
| 1378 } |
| 1379 )raw_string", |
| 1380 |
| 1381 R"raw_string({ |
| 1382 "backendNodeId": 7, |
| 1383 "childNodeIndexes": [ 5 ], |
| 1384 "nodeName": "TITLE", |
| 1385 "nodeType": 1, |
| 1386 "nodeValue": "" |
| 1387 } |
| 1388 )raw_string", |
| 1389 |
| 1390 R"raw_string({ |
| 1391 "backendNodeId": 8, |
| 1392 "nodeName": "#text", |
| 1393 "nodeType": 3, |
| 1394 "nodeValue": "Hello world!" |
| 1395 } |
| 1396 )raw_string", |
| 1397 |
| 1398 R"raw_string({ |
| 1399 "backendNodeId": 9, |
| 1400 "nodeName": "#text", |
| 1401 "nodeType": 3, |
| 1402 "nodeValue": "\n" |
| 1403 } |
| 1404 )raw_string", |
| 1405 |
| 1406 R"raw_string({ |
| 1407 "attributes": [ { |
| 1408 "name": "href", |
| 1409 "value": "dom_tree_test.css" |
| 1410 }, { |
| 1411 "name": "rel", |
| 1412 "value": "stylesheet" |
| 1413 }, { |
| 1414 "name": "type", |
| 1415 "value": "text/css" |
| 1416 } ], |
| 1417 "backendNodeId": 10, |
| 1418 "nodeName": "LINK", |
| 1419 "nodeType": 1, |
| 1420 "nodeValue": "" |
| 1421 } |
| 1422 )raw_string", |
| 1423 |
| 1424 R"raw_string({ |
| 1425 "backendNodeId": 11, |
| 1426 "nodeName": "#text", |
| 1427 "nodeType": 3, |
| 1428 "nodeValue": "\n" |
| 1429 } |
| 1430 )raw_string", |
| 1431 |
| 1432 R"raw_string({ |
| 1433 "backendNodeId": 12, |
| 1434 "nodeName": "#text", |
| 1435 "nodeType": 3, |
| 1436 "nodeValue": "\n" |
| 1437 } |
| 1438 )raw_string", |
| 1439 |
| 1440 R"raw_string({ |
| 1441 "backendNodeId": 13, |
| 1442 "boundingBox": { |
| 1443 "height": 584.0, |
| 1444 "width": 784.0, |
| 1445 "x": 8.0, |
| 1446 "y": 8.0 |
| 1447 }, |
| 1448 "childNodeIndexes": [ 11, 12 ], |
| 1449 "layoutNodeIndex": 2, |
| 1450 "nodeName": "BODY", |
| 1451 "nodeType": 1, |
| 1452 "nodeValue": "", |
| 1453 "styleIndex": 1 |
| 1454 } |
| 1455 )raw_string", |
| 1456 |
| 1457 R"raw_string({ |
| 1458 "backendNodeId": 14, |
| 1459 "nodeName": "#text", |
| 1460 "nodeType": 3, |
| 1461 "nodeValue": "\n" |
| 1462 } |
| 1463 )raw_string", |
| 1464 |
| 1465 R"raw_string({ |
| 1466 "attributes": [ { |
| 1467 "name": "id", |
| 1468 "value": "id1" |
| 1469 } ], |
| 1470 "backendNodeId": 15, |
| 1471 "boundingBox": { |
| 1472 "height": 354.0, |
| 1473 "width": 784.0, |
| 1474 "x": 8.0, |
| 1475 "y": 8.0 |
| 1476 }, |
| 1477 "childNodeIndexes": [ 13, 14, 16, 17, 26, 27, 49 ], |
| 1478 "layoutNodeIndex": 3, |
| 1479 "nodeName": "DIV", |
| 1480 "nodeType": 1, |
| 1481 "nodeValue": "", |
| 1482 "styleIndex": 0 |
| 1483 } |
| 1484 )raw_string", |
| 1485 |
| 1486 R"raw_string({ |
| 1487 "backendNodeId": 16, |
| 1488 "nodeName": "#text", |
| 1489 "nodeType": 3, |
| 1490 "nodeValue": "\n" |
| 1491 } |
| 1492 )raw_string", |
| 1493 |
| 1494 R"raw_string({ |
| 1495 "attributes": [ { |
| 1496 "name": "class", |
| 1497 "value": "red" |
| 1498 } ], |
| 1499 "backendNodeId": 17, |
| 1500 "boundingBox": { |
| 1501 "height": 32.0, |
| 1502 "width": 784.0, |
| 1503 "x": 8.0, |
| 1504 "y": 8.0 |
| 1505 }, |
| 1506 "childNodeIndexes": [ 15 ], |
| 1507 "layoutNodeIndex": 4, |
| 1508 "nodeName": "H1", |
| 1509 "nodeType": 1, |
| 1510 "nodeValue": "", |
| 1511 "styleIndex": 2 |
| 1512 } |
| 1513 )raw_string", |
| 1514 |
| 1515 R"raw_string({ |
| 1516 "backendNodeId": 18, |
| 1517 "boundingBox": { |
| 1518 "height": 32.0, |
| 1519 "width": 320.0, |
| 1520 "x": 8.0, |
| 1521 "y": 8.0 |
| 1522 }, |
| 1523 "inlineTextNodes": [ { |
| 1524 "boundingBox": { |
| 1525 "height": 32.0, |
| 1526 "width": 320.0, |
| 1527 "x": 8.0, |
| 1528 "y": 8.0 |
| 1529 }, |
| 1530 "numCharacters": 10, |
| 1531 "startCharacterIndex": 0 |
| 1532 } ], |
| 1533 "layoutNodeIndex": 5, |
| 1534 "layoutText": "Some text.", |
| 1535 "nodeName": "#text", |
| 1536 "nodeType": 3, |
| 1537 "nodeValue": "Some text.", |
| 1538 "styleIndex": 2 |
| 1539 } |
| 1540 )raw_string", |
| 1541 |
| 1542 R"raw_string({ |
| 1543 "backendNodeId": 19, |
| 1544 "nodeName": "#text", |
| 1545 "nodeType": 3, |
| 1546 "nodeValue": "\n" |
| 1547 } |
| 1548 )raw_string", |
| 1549 |
| 1550 R"raw_string({ |
| 1551 "attributes": [ { |
| 1552 "name": "src", |
| 1553 "value": "/iframe.html" |
| 1554 }, { |
| 1555 "name": "width", |
| 1556 "value": "400" |
| 1557 }, { |
| 1558 "name": "height", |
| 1559 "value": "200" |
| 1560 } ], |
| 1561 "backendNodeId": 20, |
| 1562 "boundingBox": { |
| 1563 "height": 205.0, |
| 1564 "width": 404.0, |
| 1565 "x": 8.0, |
| 1566 "y": 61.0 |
| 1567 }, |
| 1568 "contentDocumentIndex": 18, |
| 1569 "frameId": "?", |
| 1570 "layoutNodeIndex": 6, |
| 1571 "nodeName": "IFRAME", |
| 1572 "nodeType": 1, |
| 1573 "nodeValue": "", |
| 1574 "styleIndex": 3 |
| 1575 } |
| 1576 )raw_string", |
| 1577 |
| 1578 R"raw_string({ |
| 1579 "backendNodeId": 21, |
| 1580 "baseURL": "http://127.0.0.1/iframe.html", |
| 1581 "boundingBox": { |
| 1582 "height": 200.0, |
| 1583 "width": 400.0, |
| 1584 "x": 0.0, |
| 1585 "y": 0.0 |
| 1586 }, |
| 1587 "childNodeIndexes": [ 19 ], |
| 1588 "documentURL": "http://127.0.0.1/iframe.html", |
| 1589 "layoutNodeIndex": 7, |
| 1590 "nodeName": "#document", |
| 1591 "nodeType": 9, |
| 1592 "nodeValue": "" |
| 1593 } |
| 1594 )raw_string", |
| 1595 |
| 1596 R"raw_string({ |
| 1597 "backendNodeId": 22, |
| 1598 "boundingBox": { |
| 1599 "height": 200.0, |
| 1600 "width": 400.0, |
| 1601 "x": 10.0, |
| 1602 "y": 63.0 |
| 1603 }, |
| 1604 "childNodeIndexes": [ 20, 21 ], |
| 1605 "frameId": "?", |
| 1606 "layoutNodeIndex": 8, |
| 1607 "nodeName": "HTML", |
| 1608 "nodeType": 1, |
| 1609 "nodeValue": "", |
| 1610 "styleIndex": 4 |
| 1611 } |
| 1612 )raw_string", |
| 1613 |
| 1614 R"raw_string({ |
| 1615 "backendNodeId": 23, |
| 1616 "nodeName": "HEAD", |
| 1617 "nodeType": 1, |
| 1618 "nodeValue": "" |
| 1619 } |
| 1620 )raw_string", |
| 1621 |
| 1622 R"raw_string({ |
| 1623 "backendNodeId": 24, |
| 1624 "boundingBox": { |
| 1625 "height": 171.0, |
| 1626 "width": 384.0, |
| 1627 "x": 18.0, |
| 1628 "y": 71.0 |
| 1629 }, |
| 1630 "childNodeIndexes": [ 22, 23, 25 ], |
| 1631 "layoutNodeIndex": 9, |
| 1632 "nodeName": "BODY", |
| 1633 "nodeType": 1, |
| 1634 "nodeValue": "", |
| 1635 "styleIndex": 5 |
| 1636 } |
| 1637 )raw_string", |
| 1638 |
| 1639 R"raw_string({ |
| 1640 "backendNodeId": 25, |
| 1641 "nodeName": "#text", |
| 1642 "nodeType": 3, |
| 1643 "nodeValue": "\n" |
| 1644 } |
| 1645 )raw_string", |
| 1646 |
| 1647 R"raw_string({ |
| 1648 "backendNodeId": 26, |
| 1649 "boundingBox": { |
| 1650 "height": 37.0, |
| 1651 "width": 384.0, |
| 1652 "x": 18.0, |
| 1653 "y": 71.0 |
| 1654 }, |
| 1655 "childNodeIndexes": [ 24 ], |
| 1656 "layoutNodeIndex": 10, |
| 1657 "nodeName": "H1", |
| 1658 "nodeType": 1, |
| 1659 "nodeValue": "", |
| 1660 "styleIndex": 6 |
| 1661 } |
| 1662 )raw_string", |
| 1663 |
| 1664 R"raw_string({ |
| 1665 "backendNodeId": 27, |
| 1666 "boundingBox": { |
| 1667 "height": 36.0, |
| 1668 "width": 308.0, |
| 1669 "x": 8.0, |
| 1670 "y": 8.0 |
| 1671 }, |
| 1672 "inlineTextNodes": [ { |
| 1673 "boundingBox": { |
| 1674 "height": 36.0, |
| 1675 "width": 307.734375, |
| 1676 "x": 8.0, |
| 1677 "y": 8.0 |
| 1678 }, |
| 1679 "numCharacters": 22, |
| 1680 "startCharacterIndex": 0 |
| 1681 } ], |
| 1682 "layoutNodeIndex": 11, |
| 1683 "layoutText": "Hello from the iframe!", |
| 1684 "nodeName": "#text", |
| 1685 "nodeType": 3, |
| 1686 "nodeValue": "Hello from the iframe!", |
| 1687 "styleIndex": 6 |
| 1688 } |
| 1689 )raw_string", |
| 1690 |
| 1691 R"raw_string({ |
| 1692 "backendNodeId": 28, |
| 1693 "nodeName": "#text", |
| 1694 "nodeType": 3, |
| 1695 "nodeValue": "\n\n\n" |
| 1696 } |
| 1697 )raw_string", |
| 1698 |
| 1699 R"raw_string({ |
| 1700 "backendNodeId": 29, |
| 1701 "boundingBox": { |
| 1702 "height": 0.0, |
| 1703 "width": 0.0, |
| 1704 "x": 0.0, |
| 1705 "y": 0.0 |
| 1706 }, |
| 1707 "layoutNodeIndex": 12, |
| 1708 "layoutText": "\n", |
| 1709 "nodeName": "#text", |
| 1710 "nodeType": 3, |
| 1711 "nodeValue": "\n", |
| 1712 "styleIndex": 0 |
| 1713 } |
| 1714 )raw_string", |
| 1715 |
| 1716 R"raw_string({ |
| 1717 "attributes": [ { |
| 1718 "name": "id", |
| 1719 "value": "id2" |
| 1720 } ], |
| 1721 "backendNodeId": 30, |
| 1722 "boundingBox": { |
| 1723 "height": 97.0, |
| 1724 "width": 784.0, |
| 1725 "x": 8.0, |
| 1726 "y": 265.0 |
| 1727 }, |
| 1728 "childNodeIndexes": [ 28, 29, 48 ], |
| 1729 "layoutNodeIndex": 13, |
| 1730 "nodeName": "DIV", |
| 1731 "nodeType": 1, |
| 1732 "nodeValue": "", |
| 1733 "styleIndex": 0 |
| 1734 } |
| 1735 )raw_string", |
| 1736 |
| 1737 R"raw_string({ |
| 1738 "backendNodeId": 31, |
| 1739 "nodeName": "#text", |
| 1740 "nodeType": 3, |
| 1741 "nodeValue": "\n " |
| 1742 } |
| 1743 )raw_string", |
| 1744 |
| 1745 R"raw_string({ |
| 1746 "attributes": [ { |
| 1747 "name": "id", |
| 1748 "value": "id3" |
| 1749 } ], |
| 1750 "backendNodeId": 32, |
| 1751 "boundingBox": { |
| 1752 "height": 97.0, |
| 1753 "width": 784.0, |
| 1754 "x": 8.0, |
| 1755 "y": 265.0 |
| 1756 }, |
| 1757 "childNodeIndexes": [ 30, 31, 47 ], |
| 1758 "layoutNodeIndex": 14, |
| 1759 "nodeName": "DIV", |
| 1760 "nodeType": 1, |
| 1761 "nodeValue": "", |
| 1762 "styleIndex": 0 |
| 1763 } |
| 1764 )raw_string", |
| 1765 |
| 1766 R"raw_string({ |
| 1767 "backendNodeId": 33, |
| 1768 "nodeName": "#text", |
| 1769 "nodeType": 3, |
| 1770 "nodeValue": "\n " |
| 1771 } |
| 1772 )raw_string", |
| 1773 |
| 1774 R"raw_string({ |
| 1775 "attributes": [ { |
| 1776 "name": "id", |
| 1777 "value": "id4" |
| 1778 } ], |
| 1779 "backendNodeId": 34, |
| 1780 "boundingBox": { |
| 1781 "height": 97.0, |
| 1782 "width": 784.0, |
| 1783 "x": 8.0, |
| 1784 "y": 265.0 |
| 1785 }, |
| 1786 "childNodeIndexes": [ 32, 33, 35, 36, 38, 39, 40, 41, 46 ], |
| 1787 "layoutNodeIndex": 15, |
| 1788 "nodeName": "DIV", |
| 1789 "nodeType": 1, |
| 1790 "nodeValue": "", |
| 1791 "styleIndex": 0 |
| 1792 } |
| 1793 )raw_string", |
| 1794 |
| 1795 R"raw_string({ |
| 1796 "backendNodeId": 35, |
| 1797 "nodeName": "#text", |
| 1798 "nodeType": 3, |
| 1799 "nodeValue": "\n " |
| 1800 } |
| 1801 )raw_string", |
| 1802 |
| 1803 R"raw_string({ |
| 1804 "attributes": [ { |
| 1805 "name": "href", |
| 1806 "value": "https://www.google.com" |
| 1807 } ], |
| 1808 "backendNodeId": 36, |
| 1809 "boundingBox": { |
| 1810 "height": 17.0, |
| 1811 "width": 112.0, |
| 1812 "x": 8.0, |
| 1813 "y": 265.0 |
| 1814 }, |
| 1815 "childNodeIndexes": [ 34 ], |
| 1816 "layoutNodeIndex": 16, |
| 1817 "nodeName": "A", |
| 1818 "nodeType": 1, |
| 1819 "nodeValue": "", |
| 1820 "styleIndex": 7 |
| 1821 } |
| 1822 )raw_string", |
| 1823 |
| 1824 R"raw_string({ |
| 1825 "backendNodeId": 37, |
| 1826 "boundingBox": { |
| 1827 "height": 17.0, |
| 1828 "width": 112.0, |
| 1829 "x": 8.0, |
| 1830 "y": 265.0 |
| 1831 }, |
| 1832 "inlineTextNodes": [ { |
| 1833 "boundingBox": { |
| 1834 "height": 16.0, |
| 1835 "width": 112.0, |
| 1836 "x": 8.0, |
| 1837 "y": 265.4375 |
| 1838 }, |
| 1839 "numCharacters": 7, |
| 1840 "startCharacterIndex": 0 |
| 1841 } ], |
| 1842 "layoutNodeIndex": 17, |
| 1843 "layoutText": "Google!", |
| 1844 "nodeName": "#text", |
| 1845 "nodeType": 3, |
| 1846 "nodeValue": "Google!", |
| 1847 "styleIndex": 7 |
| 1848 } |
| 1849 )raw_string", |
| 1850 |
| 1851 R"raw_string({ |
| 1852 "backendNodeId": 38, |
| 1853 "boundingBox": { |
| 1854 "height": 0.0, |
| 1855 "width": 0.0, |
| 1856 "x": 0.0, |
| 1857 "y": 0.0 |
| 1858 }, |
| 1859 "layoutNodeIndex": 18, |
| 1860 "layoutText": "\n ", |
| 1861 "nodeName": "#text", |
| 1862 "nodeType": 3, |
| 1863 "nodeValue": "\n ", |
| 1864 "styleIndex": 0 |
| 1865 } |
| 1866 )raw_string", |
| 1867 |
| 1868 R"raw_string({ |
| 1869 "backendNodeId": 39, |
| 1870 "boundingBox": { |
| 1871 "height": 17.0, |
| 1872 "width": 784.0, |
| 1873 "x": 8.0, |
| 1874 "y": 297.0 |
| 1875 }, |
| 1876 "childNodeIndexes": [ 37 ], |
| 1877 "layoutNodeIndex": 19, |
| 1878 "nodeName": "P", |
| 1879 "nodeType": 1, |
| 1880 "nodeValue": "", |
| 1881 "styleIndex": 8 |
| 1882 } |
| 1883 )raw_string", |
| 1884 |
| 1885 R"raw_string({ |
| 1886 "backendNodeId": 40, |
| 1887 "boundingBox": { |
| 1888 "height": 17.0, |
| 1889 "width": 192.0, |
| 1890 "x": 8.0, |
| 1891 "y": 297.0 |
| 1892 }, |
| 1893 "inlineTextNodes": [ { |
| 1894 "boundingBox": { |
| 1895 "height": 16.0, |
| 1896 "width": 192.0, |
| 1897 "x": 8.0, |
| 1898 "y": 297.4375 |
| 1899 }, |
| 1900 "numCharacters": 12, |
| 1901 "startCharacterIndex": 0 |
| 1902 } ], |
| 1903 "layoutNodeIndex": 20, |
| 1904 "layoutText": "A paragraph!", |
| 1905 "nodeName": "#text", |
| 1906 "nodeType": 3, |
| 1907 "nodeValue": "A paragraph!", |
| 1908 "styleIndex": 8 |
| 1909 } |
| 1910 )raw_string", |
| 1911 |
| 1912 R"raw_string({ |
| 1913 "backendNodeId": 41, |
| 1914 "nodeName": "#text", |
| 1915 "nodeType": 3, |
| 1916 "nodeValue": "\n " |
| 1917 } |
| 1918 )raw_string", |
| 1919 |
| 1920 R"raw_string({ |
| 1921 "backendNodeId": 42, |
| 1922 "boundingBox": { |
| 1923 "height": 0.0, |
| 1924 "width": 0.0, |
| 1925 "x": 0.0, |
| 1926 "y": 0.0 |
| 1927 }, |
| 1928 "inlineTextNodes": [ { |
| 1929 "boundingBox": { |
| 1930 "height": 16.0, |
| 1931 "width": 0.0, |
| 1932 "x": 8.0, |
| 1933 "y": 329.4375 |
| 1934 }, |
| 1935 "numCharacters": 1, |
| 1936 "startCharacterIndex": 0 |
| 1937 } ], |
| 1938 "layoutNodeIndex": 21, |
| 1939 "layoutText": "\n", |
| 1940 "nodeName": "BR", |
| 1941 "nodeType": 1, |
| 1942 "nodeValue": "", |
| 1943 "styleIndex": 3 |
| 1944 } |
| 1945 )raw_string", |
| 1946 |
| 1947 R"raw_string({ |
| 1948 "backendNodeId": 43, |
| 1949 "nodeName": "#text", |
| 1950 "nodeType": 3, |
| 1951 "nodeValue": "\n " |
| 1952 } |
| 1953 )raw_string", |
| 1954 |
| 1955 R"raw_string({ |
| 1956 "attributes": [ { |
| 1957 "name": "class", |
| 1958 "value": "green" |
| 1959 } ], |
| 1960 "backendNodeId": 44, |
| 1961 "boundingBox": { |
| 1962 "height": 17.0, |
| 1963 "width": 784.0, |
| 1964 "x": 8.0, |
| 1965 "y": 345.0 |
| 1966 }, |
| 1967 "childNodeIndexes": [ 42, 43, 45 ], |
| 1968 "layoutNodeIndex": 22, |
| 1969 "nodeName": "DIV", |
| 1970 "nodeType": 1, |
| 1971 "nodeValue": "", |
| 1972 "styleIndex": 9 |
| 1973 } |
| 1974 )raw_string", |
| 1975 |
| 1976 R"raw_string({ |
| 1977 "backendNodeId": 45, |
| 1978 "boundingBox": { |
| 1979 "height": 17.0, |
| 1980 "width": 80.0, |
| 1981 "x": 8.0, |
| 1982 "y": 345.0 |
| 1983 }, |
| 1984 "inlineTextNodes": [ { |
| 1985 "boundingBox": { |
| 1986 "height": 16.0, |
| 1987 "width": 80.0, |
| 1988 "x": 8.0, |
| 1989 "y": 345.4375 |
| 1990 }, |
| 1991 "numCharacters": 5, |
| 1992 "startCharacterIndex": 0 |
| 1993 } ], |
| 1994 "layoutNodeIndex": 23, |
| 1995 "layoutText": "Some ", |
| 1996 "nodeName": "#text", |
| 1997 "nodeType": 3, |
| 1998 "nodeValue": "Some ", |
| 1999 "styleIndex": 9 |
| 2000 } |
| 2001 )raw_string", |
| 2002 |
| 2003 R"raw_string({ |
| 2004 "backendNodeId": 46, |
| 2005 "boundingBox": { |
| 2006 "height": 17.0, |
| 2007 "width": 80.0, |
| 2008 "x": 88.0, |
| 2009 "y": 345.0 |
| 2010 }, |
| 2011 "childNodeIndexes": [ 44 ], |
| 2012 "layoutNodeIndex": 24, |
| 2013 "nodeName": "EM", |
| 2014 "nodeType": 1, |
| 2015 "nodeValue": "", |
| 2016 "styleIndex": 10 |
| 2017 } |
| 2018 )raw_string", |
| 2019 |
| 2020 R"raw_string({ |
| 2021 "backendNodeId": 47, |
| 2022 "boundingBox": { |
| 2023 "height": 17.0, |
| 2024 "width": 80.0, |
| 2025 "x": 88.0, |
| 2026 "y": 345.0 |
| 2027 }, |
| 2028 "inlineTextNodes": [ { |
| 2029 "boundingBox": { |
| 2030 "height": 16.0, |
| 2031 "width": 80.0, |
| 2032 "x": 88.0, |
| 2033 "y": 345.4375 |
| 2034 }, |
| 2035 "numCharacters": 5, |
| 2036 "startCharacterIndex": 0 |
| 2037 } ], |
| 2038 "layoutNodeIndex": 25, |
| 2039 "layoutText": "green", |
| 2040 "nodeName": "#text", |
| 2041 "nodeType": 3, |
| 2042 "nodeValue": "green", |
| 2043 "styleIndex": 10 |
| 2044 } |
| 2045 )raw_string", |
| 2046 |
| 2047 R"raw_string({ |
| 2048 "backendNodeId": 48, |
| 2049 "boundingBox": { |
| 2050 "height": 17.0, |
| 2051 "width": 128.0, |
| 2052 "x": 168.0, |
| 2053 "y": 345.0 |
| 2054 }, |
| 2055 "inlineTextNodes": [ { |
| 2056 "boundingBox": { |
| 2057 "height": 16.0, |
| 2058 "width": 128.0, |
| 2059 "x": 168.0, |
| 2060 "y": 345.4375 |
| 2061 }, |
| 2062 "numCharacters": 8, |
| 2063 "startCharacterIndex": 0 |
| 2064 } ], |
| 2065 "layoutNodeIndex": 26, |
| 2066 "layoutText": " text...", |
| 2067 "nodeName": "#text", |
| 2068 "nodeType": 3, |
| 2069 "nodeValue": " text...", |
| 2070 "styleIndex": 9 |
| 2071 } |
| 2072 )raw_string", |
| 2073 |
| 2074 R"raw_string({ |
| 2075 "backendNodeId": 49, |
| 2076 "nodeName": "#text", |
| 2077 "nodeType": 3, |
| 2078 "nodeValue": "\n " |
| 2079 } |
| 2080 )raw_string", |
| 2081 |
| 2082 R"raw_string({ |
| 2083 "backendNodeId": 50, |
| 2084 "nodeName": "#text", |
| 2085 "nodeType": 3, |
| 2086 "nodeValue": "\n " |
| 2087 } |
| 2088 )raw_string", |
| 2089 |
| 2090 R"raw_string({ |
| 2091 "backendNodeId": 51, |
| 2092 "nodeName": "#text", |
| 2093 "nodeType": 3, |
| 2094 "nodeValue": "\n" |
| 2095 } |
| 2096 )raw_string", |
| 2097 |
| 2098 R"raw_string({ |
| 2099 "backendNodeId": 52, |
| 2100 "nodeName": "#text", |
| 2101 "nodeType": 3, |
| 2102 "nodeValue": "\n\n\n" |
| 2103 } |
| 2104 )raw_string"}; |
| 2105 |
| 2106 EXPECT_EQ(expected_dom_nodes.size(), dom_nodes.size()); |
| 2107 |
| 2108 for (size_t i = 0; i < dom_nodes.size(); i++) { |
| 2109 std::string result_json; |
| 2110 base::JSONWriter::WriteWithOptions( |
| 2111 *dom_nodes[i], base::JSONWriter::OPTIONS_PRETTY_PRINT, &result_json); |
| 2112 |
| 2113 ASSERT_LT(i, expected_dom_nodes.size()); |
| 2114 EXPECT_EQ(NormaliseJSON(expected_dom_nodes[i]), result_json) |
| 2115 << " Node # " << i; |
| 2116 } |
| 2117 |
| 2118 const std::vector<std::string> expected_styles = { |
| 2119 R"raw_string({ |
| 2120 "color": "rgb(0, 0, 0)", |
| 2121 "display": "block", |
| 2122 "font-family": "ahem", |
| 2123 "font-style": "normal", |
| 2124 "margin-bottom": "0px", |
| 2125 "margin-left": "0px", |
| 2126 "margin-right": "0px", |
| 2127 "margin-top": "0px" |
| 2128 })raw_string", |
| 2129 |
| 2130 R"raw_string({ |
| 2131 "color": "rgb(0, 0, 0)", |
| 2132 "display": "block", |
| 2133 "font-family": "ahem", |
| 2134 "font-style": "normal", |
| 2135 "margin-bottom": "8px", |
| 2136 "margin-left": "8px", |
| 2137 "margin-right": "8px", |
| 2138 "margin-top": "8px" |
| 2139 })raw_string", |
| 2140 |
| 2141 R"raw_string({ |
| 2142 "color": "rgb(255, 0, 0)", |
| 2143 "display": "block", |
| 2144 "font-family": "ahem", |
| 2145 "font-style": "normal", |
| 2146 "margin-bottom": "21.44px", |
| 2147 "margin-left": "0px", |
| 2148 "margin-right": "0px", |
| 2149 "margin-top": "21.44px" |
| 2150 })raw_string", |
| 2151 |
| 2152 R"raw_string({ |
| 2153 "color": "rgb(0, 0, 0)", |
| 2154 "display": "inline", |
| 2155 "font-family": "ahem", |
| 2156 "font-style": "normal", |
| 2157 "margin-bottom": "0px", |
| 2158 "margin-left": "0px", |
| 2159 "margin-right": "0px", |
| 2160 "margin-top": "0px" |
| 2161 })raw_string", |
| 2162 |
| 2163 R"raw_string({ |
| 2164 "color": "rgb(0, 0, 0)", |
| 2165 "display": "block", |
| 2166 "font-family": "\"Times New Roman\"", |
| 2167 "font-style": "normal", |
| 2168 "margin-bottom": "0px", |
| 2169 "margin-left": "0px", |
| 2170 "margin-right": "0px", |
| 2171 "margin-top": "0px" |
| 2172 })raw_string", |
| 2173 |
| 2174 R"raw_string({ |
| 2175 "color": "rgb(0, 0, 0)", |
| 2176 "display": "block", |
| 2177 "font-family": "\"Times New Roman\"", |
| 2178 "font-style": "normal", |
| 2179 "margin-bottom": "8px", |
| 2180 "margin-left": "8px", |
| 2181 "margin-right": "8px", |
| 2182 "margin-top": "8px" |
| 2183 })raw_string", |
| 2184 |
| 2185 R"raw_string({ |
| 2186 "color": "rgb(0, 0, 0)", |
| 2187 "display": "block", |
| 2188 "font-family": "\"Times New Roman\"", |
| 2189 "font-style": "normal", |
| 2190 "margin-bottom": "21.44px", |
| 2191 "margin-left": "0px", |
| 2192 "margin-right": "0px", |
| 2193 "margin-top": "21.44px" |
| 2194 })raw_string", |
| 2195 |
| 2196 R"raw_string({ |
| 2197 "color": "rgb(0, 0, 238)", |
| 2198 "display": "inline", |
| 2199 "font-family": "ahem", |
| 2200 "font-style": "normal", |
| 2201 "margin-bottom": "0px", |
| 2202 "margin-left": "0px", |
| 2203 "margin-right": "0px", |
| 2204 "margin-top": "0px" |
| 2205 })raw_string", |
| 2206 |
| 2207 R"raw_string({ |
| 2208 "color": "rgb(0, 0, 0)", |
| 2209 "display": "block", |
| 2210 "font-family": "ahem", |
| 2211 "font-style": "normal", |
| 2212 "margin-bottom": "16px", |
| 2213 "margin-left": "0px", |
| 2214 "margin-right": "0px", |
| 2215 "margin-top": "16px" |
| 2216 })raw_string", |
| 2217 |
| 2218 R"raw_string({ |
| 2219 "color": "rgb(0, 128, 0)", |
| 2220 "display": "block", |
| 2221 "font-family": "ahem", |
| 2222 "font-style": "normal", |
| 2223 "margin-bottom": "0px", |
| 2224 "margin-left": "0px", |
| 2225 "margin-right": "0px", |
| 2226 "margin-top": "0px" |
| 2227 })raw_string", |
| 2228 |
| 2229 R"raw_string({ |
| 2230 "color": "rgb(0, 128, 0)", |
| 2231 "display": "inline", |
| 2232 "font-family": "ahem", |
| 2233 "font-style": "italic", |
| 2234 "margin-bottom": "0px", |
| 2235 "margin-left": "0px", |
| 2236 "margin-right": "0px", |
| 2237 "margin-top": "0px" |
| 2238 } |
| 2239 )raw_string"}; |
| 2240 |
| 2241 EXPECT_EQ(expected_styles.size(), computed_styles.size()); |
| 2242 |
| 2243 for (size_t i = 0; i < computed_styles.size(); i++) { |
| 2244 std::string result_json; |
| 2245 base::JSONWriter::WriteWithOptions(*computed_styles[i], |
| 2246 base::JSONWriter::OPTIONS_PRETTY_PRINT, |
| 2247 &result_json); |
| 2248 |
| 2249 ASSERT_LT(i, expected_styles.size()); |
| 2250 EXPECT_EQ(NormaliseJSON(expected_styles[i]), result_json) |
| 2251 << " Style # " << i; |
| 2252 } |
| 2253 |
| 2254 FinishAsynchronousTest(); |
| 2255 } |
| 2256 }; |
| 2257 |
| 2258 HEADLESS_ASYNC_DEVTOOLED_TEST_F(DomTreeExtractionBrowserTest); |
| 2259 |
1208 } // namespace headless | 2260 } // namespace headless |
OLD | NEW |