NavigationParams.cpp 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibWeb/DOM/Document.h>
  7. #include <LibWeb/Fetch/Infrastructure/FetchController.h>
  8. #include <LibWeb/HTML/Navigable.h>
  9. #include <LibWeb/HTML/NavigationParams.h>
  10. #include <LibWeb/HTML/Scripting/Environments.h>
  11. namespace Web::HTML {
  12. GC_DEFINE_ALLOCATOR(NavigationParams);
  13. GC_DEFINE_ALLOCATOR(NonFetchSchemeNavigationParams);
  14. void NavigationParams::visit_edges(Visitor& visitor)
  15. {
  16. Base::visit_edges(visitor);
  17. visitor.visit(navigable);
  18. visitor.visit(request);
  19. visitor.visit(response);
  20. visitor.visit(fetch_controller);
  21. visitor.visit(reserved_environment);
  22. }
  23. void NonFetchSchemeNavigationParams::visit_edges(Visitor& visitor)
  24. {
  25. Base::visit_edges(visitor);
  26. visitor.visit(navigable);
  27. }
  28. // https://html.spec.whatwg.org/multipage/document-lifecycle.html#check-a-navigation-response's-adherence-to-x-frame-options
  29. // FIXME: Add the cspList parameter
  30. bool check_a_navigation_responses_adherence_to_x_frame_options(GC::Ptr<Fetch::Infrastructure::Response> response, Navigable* navigable, URL::Origin destination_origin)
  31. {
  32. // 1. If navigable is not a child navigable, then return true.
  33. if (!navigable->parent()) {
  34. return true;
  35. }
  36. // FIXME: 2. For each policy of cspList:
  37. // 1. If policy's disposition is not "enforce", then continue.
  38. // 2. If policy's directive set contains a frame-ancestors directive, then return true.
  39. // 3. Let rawXFrameOptions be the result of getting, decoding, and splitting `X-Frame-Options` from response's header list.
  40. auto raw_x_frame_options = response->header_list()->get_decode_and_split("X-Frame-Options"sv.bytes());
  41. // 4. Let xFrameOptions be a new set.
  42. auto x_frame_options = AK::OrderedHashTable<String>();
  43. // 5. For each value of rawXFrameOptions, append value, converted to ASCII lowercase, to xFrameOptions.
  44. if (raw_x_frame_options.has_value()) {
  45. for (auto const& value : raw_x_frame_options.value()) {
  46. x_frame_options.set(value.to_ascii_lowercase());
  47. }
  48. }
  49. // 6. If xFrameOptions's size is greater than 1, and xFrameOptions contains any of "deny", "allowall", or "sameorigin", then return false.
  50. if (x_frame_options.size() > 1 && (x_frame_options.contains("deny"sv) || x_frame_options.contains("allowall"sv) || x_frame_options.contains("sameorigin"sv))) {
  51. return false;
  52. }
  53. // 7. If xFrameOptions's size is greater than 1, then return true.
  54. if (x_frame_options.size() > 1) {
  55. return true;
  56. }
  57. // 8. If xFrameOptions[0] is "deny", then return false.
  58. auto first_x_frame_option = x_frame_options.begin();
  59. if (!x_frame_options.is_empty() && *first_x_frame_option == "deny"sv) {
  60. return false;
  61. }
  62. // 9. If xFrameOptions[0] is "sameorigin", then:
  63. if (!x_frame_options.is_empty() && *first_x_frame_option == "sameorigin"sv) {
  64. // 1. Let containerDocument be navigable's container document.
  65. auto container_document = navigable->container_document();
  66. // 2. While containerDocument is not null:
  67. while (container_document) {
  68. // 1. If containerDocument's origin is not same origin with destinationOrigin, then return false.
  69. if (!container_document->origin().is_same_origin(destination_origin)) {
  70. return false;
  71. }
  72. // 2. Set containerDocument to containerDocument's container document.
  73. container_document = container_document->container_document();
  74. }
  75. }
  76. // 10. Return true.
  77. return true;
  78. }
  79. }