mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 09:58:11 +00:00
LibWeb: Remove unused navigation methods in BrowsingContext
This commit is contained in:
parent
c0c542d495
commit
24b3e315a0
4 changed files with 0 additions and 439 deletions
|
@ -1017,401 +1017,6 @@ void BrowsingContext::remove()
|
|||
// NOTE: This is done by ~BrowsingContextGroup() when the refcount reaches 0.
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate
|
||||
WebIDL::ExceptionOr<void> BrowsingContext::navigate(
|
||||
JS::NonnullGCPtr<Fetch::Infrastructure::Request> resource,
|
||||
BrowsingContext& source_browsing_context,
|
||||
bool exceptions_enabled,
|
||||
HistoryHandlingBehavior history_handling,
|
||||
Optional<PolicyContainer> history_policy_container,
|
||||
DeprecatedString navigation_type,
|
||||
Optional<String> navigation_id,
|
||||
Function<void(JS::NonnullGCPtr<Fetch::Infrastructure::Response>)> process_response_end_of_body)
|
||||
{
|
||||
// 1. If resource is a URL, then set resource to a new request whose URL is resource.
|
||||
// NOTE: This function only accepts resources that are already a request, so this is irrelevant.
|
||||
|
||||
// 2. If resource is a request and historyHandling is "reload", then set resource's reload-navigation flag.
|
||||
if (history_handling == HistoryHandlingBehavior::Reload)
|
||||
resource->set_reload_navigation(true);
|
||||
|
||||
// 3. If the source browsing context is not allowed to navigate browsingContext, then:
|
||||
if (!source_browsing_context.is_allowed_to_navigate(*this)) {
|
||||
// 1. If exceptionsEnabled is given and is true, then throw a "SecurityError" DOMException.
|
||||
if (exceptions_enabled) {
|
||||
VERIFY(source_browsing_context.active_document());
|
||||
return WebIDL::SecurityError::create(source_browsing_context.active_document()->realm(), "Source browsing context not allowed to navigate"_fly_string);
|
||||
}
|
||||
|
||||
// FIXME: 2. Otherwise, the user agent may instead offer to open resource in a new top-level browsing context
|
||||
// or in the top-level browsing context of the source browsing context, at the user's option,
|
||||
// in which case the user agent must navigate that designated top-level browsing context
|
||||
// to resource as if the user had requested it independently.
|
||||
}
|
||||
|
||||
// 4. If navigationId is null:
|
||||
if (!navigation_id.has_value()) {
|
||||
// 1. If historyHandling is "reload", and browsingContext's active document's navigation id is not null,
|
||||
if (history_handling == HistoryHandlingBehavior::Reload && active_document()->navigation_id().has_value()) {
|
||||
// let navigationId be browsingContext's active document's navigation id.
|
||||
navigation_id = active_document()->navigation_id();
|
||||
} else {
|
||||
// Otherwise let navigation id be the result of generating a random UUID. [UUID]
|
||||
// FIXME: Generate a UUID.
|
||||
navigation_id = "FIXME"_string;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: 5. If browsingContext's active document's unload counter is greater than 0,
|
||||
// then invoke WebDriver BiDi navigation failed
|
||||
// with a WebDriver BiDi navigation status whose id is navigationId, status is "canceled", and url is resource's url
|
||||
// and return.
|
||||
|
||||
// 6. If historyHandling is "default", and any of the following are true:
|
||||
// - browsingContext is still on its initial about:blank Document
|
||||
// - resource is a request whose URL equals browsingContext's active document's URL
|
||||
// - resource is a request whose URL's scheme is "javascript"
|
||||
if (history_handling == HistoryHandlingBehavior::Default
|
||||
&& (still_on_its_initial_about_blank_document()
|
||||
|| resource->url().equals(active_document()->url())
|
||||
|| resource->url().scheme() == "javascript"sv)) {
|
||||
// then set historyHandling to "replace".
|
||||
history_handling = HistoryHandlingBehavior::Replace;
|
||||
}
|
||||
|
||||
// 7. If historyHandling is not "reload", resource is a request,
|
||||
// resource's URL equals browsingContext's active document's URL with exclude fragments set to true,
|
||||
// and resource's URL's fragment is non-null, then:
|
||||
if (history_handling != HistoryHandlingBehavior::Reload
|
||||
&& resource->url().equals(active_document()->url(), AK::URL::ExcludeFragment::Yes)
|
||||
&& resource->url().fragment().has_value()) {
|
||||
// 1. Navigate to a fragment given browsingContext, resource's URL, historyHandling, and navigationId.
|
||||
TRY(navigate_to_a_fragment(resource->url(), history_handling, *navigation_id));
|
||||
|
||||
// 2. Return.
|
||||
return {};
|
||||
}
|
||||
|
||||
// FIXME: 8. Let incumbentNavigationOrigin be the origin of the incumbent settings object,
|
||||
// or if no script was involved, the origin of the node document of the element that initiated the navigation.
|
||||
|
||||
// FIXME: 9. Let initiatorPolicyContainer be a clone of the source browsing context's active document's policy container.
|
||||
|
||||
// FIXME: 10. If resource is a request, then set resource's policy container to initiatorPolicyContainer.
|
||||
|
||||
// FIXME: 11. Cancel any preexisting but not yet mature attempt to navigate browsingContext,
|
||||
// including canceling any instances of the fetch algorithm started by those attempts.
|
||||
// If one of those attempts has already created and initialized a new Document object,
|
||||
// abort that Document also.
|
||||
// (Navigation attempts that have matured already have session history entries,
|
||||
// and are therefore handled during the update the session history with the new page algorithm, later.)
|
||||
|
||||
// FIXME: 12. Let unloadPromptResult be the result of calling prompt to unload with the active document of browsingContext.
|
||||
// If this instance of the navigation algorithm gets canceled while this step is running,
|
||||
// the prompt to unload algorithm must nonetheless be run to completion.
|
||||
|
||||
// FIXME: 13. If unloadPromptResult is "refuse", then return a new WebDriver BiDi navigation status whose id is navigationId and status is "canceled".
|
||||
|
||||
// 14. Abort the active document of browsingContext.
|
||||
active_document()->abort();
|
||||
|
||||
// FIXME: 15. If browsingContext is a child browsing context, then put it in the delaying load events mode.
|
||||
// The user agent must take this child browsing context out of the delaying load events mode when this navigation algorithm later matures,
|
||||
// or when it terminates (whether due to having run all the steps, or being canceled, or being aborted),
|
||||
// whichever happens first.
|
||||
|
||||
// FIXME: 16. Let sandboxFlags be the result of determining the creation sandboxing flags given browsingContext and browsingContext's container.
|
||||
|
||||
// FIXME: 17. Let allowedToDownload be the result of running the allowed to download algorithm given the source browsing context and browsingContext.
|
||||
|
||||
// 18. Let hasTransientActivation be true if the source browsing context's active window has transient activation; otherwise false.
|
||||
[[maybe_unused]] bool has_transient_activation = source_browsing_context.active_window()->has_transient_activation();
|
||||
|
||||
// FIXME: 19. Invoke WebDriver BiDi navigation started with browsingContext, and a new WebDriver BiDi navigation status whose id is navigationId, url is resource's url, and status is "pending".
|
||||
|
||||
// 20. Return, and continue running these steps in parallel.
|
||||
|
||||
// FIXME: Implement the rest of this algorithm
|
||||
(void)history_policy_container;
|
||||
(void)navigation_type;
|
||||
(void)process_response_end_of_body;
|
||||
|
||||
// AD-HOC:
|
||||
auto request = LoadRequest::create_for_url_on_page(resource->url(), page());
|
||||
request.set_method(DeprecatedString { resource->method() });
|
||||
for (auto& header : *resource->header_list()) {
|
||||
request.set_header(DeprecatedString { header.name.bytes() }, DeprecatedString { header.value.bytes() });
|
||||
}
|
||||
if (request.method() == "POST"sv) {
|
||||
if (resource->body().has<ByteBuffer>()) {
|
||||
auto const& byte_buffer = resource->body().get<ByteBuffer>();
|
||||
request.set_body(byte_buffer);
|
||||
request.set_header("Content-Length", DeprecatedString::number(byte_buffer.size()));
|
||||
} else {
|
||||
request.set_header("Content-Length", DeprecatedString::number(0));
|
||||
}
|
||||
}
|
||||
loader().load(request, FrameLoader::Type::Navigation);
|
||||
return {};
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate-fragid
|
||||
WebIDL::ExceptionOr<void> BrowsingContext::navigate_to_a_fragment(AK::URL const& url, HistoryHandlingBehavior history_handling, String navigation_id)
|
||||
{
|
||||
// 1. If historyHandling is not "replace",
|
||||
if (history_handling != HistoryHandlingBehavior::Replace) {
|
||||
// FIXME: then remove all the entries in browsingContext's session history after the current entry.
|
||||
// (If the current entry is the last entry in the session history, then no entries are removed.)
|
||||
}
|
||||
|
||||
// 2. Remove any tasks queued by the history traversal task source that are associated with any Document objects
|
||||
// in browsingContext's top-level browsing context's document family.
|
||||
HTML::main_thread_event_loop().task_queue().remove_tasks_matching([&](HTML::Task const& task) {
|
||||
return task.source() == Task::Source::HistoryTraversal
|
||||
&& task.document()
|
||||
&& top_level_browsing_context().document_family_contains(*task.document());
|
||||
});
|
||||
|
||||
// 3. Append a new session history entry to the session history whose URL is url,
|
||||
// document is the current entry's document,
|
||||
// policy container is the current entry's policy-container
|
||||
// and scroll restoration mode is the current entry's scroll restoration mode.
|
||||
auto new_entry = heap().allocate_without_realm<SessionHistoryEntry>();
|
||||
new_entry->url = url;
|
||||
new_entry->document_state = *heap().allocate_without_realm<DocumentState>();
|
||||
new_entry->document_state->set_document(current_entry().document_state->document());
|
||||
new_entry->policy_container = current_entry().policy_container;
|
||||
new_entry->scroll_restoration_mode = current_entry().scroll_restoration_mode;
|
||||
new_entry->browsing_context_name = {};
|
||||
new_entry->original_source_browsing_context = {};
|
||||
m_session_history.append(*new_entry);
|
||||
|
||||
// 4. Traverse the history to the new entry, with historyHandling set to historyHandling.
|
||||
// This will scroll to the fragment given in what is now the document's URL.
|
||||
TRY(traverse_the_history(m_session_history.size() - 1, history_handling));
|
||||
|
||||
// FIXME: 5. Invoke WebDriver BiDi fragment navigated with browsingContext,
|
||||
// and a new WebDriver BiDi navigation status whose id is navigationId, url is resource's url, and status is "complete".
|
||||
(void)navigation_id;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#traverse-the-history
|
||||
WebIDL::ExceptionOr<void> BrowsingContext::traverse_the_history(size_t entry_index, HistoryHandlingBehavior history_handling, bool explicit_history_navigation)
|
||||
{
|
||||
auto entry = m_session_history[entry_index];
|
||||
|
||||
// 1. If entry's document is null, then:
|
||||
if (!entry->document_state->document()) {
|
||||
// 1. Assert: historyHandling is "default".
|
||||
VERIFY(history_handling == HistoryHandlingBehavior::Default);
|
||||
|
||||
// 2. Let request be a new request whose URL is entry's URL.
|
||||
auto& vm = Bindings::main_thread_vm();
|
||||
auto request = Fetch::Infrastructure::Request::create(vm);
|
||||
request->set_url(entry->url);
|
||||
|
||||
// 3. If explicitHistoryNavigation is true, then set request's history-navigation flag.
|
||||
if (explicit_history_navigation)
|
||||
request->set_history_navigation(true);
|
||||
|
||||
// 4. Navigate the browsing context to request with historyHandling set to "entry update"
|
||||
// and with historyPolicyContainer set to entry's policy container.
|
||||
// The navigation must be done using the same source browsing context as was used the first time entry was created.
|
||||
VERIFY(entry->original_source_browsing_context);
|
||||
TRY(navigate(request, *entry->original_source_browsing_context, false, HistoryHandlingBehavior::EntryUpdate, entry->policy_container));
|
||||
|
||||
// 5. Return.
|
||||
return {};
|
||||
}
|
||||
|
||||
// FIXME: 2. Save persisted state to the current entry.
|
||||
|
||||
// 3. Let newDocument be entry's document.
|
||||
JS::GCPtr<DOM::Document> new_document = entry->document_state->document().ptr();
|
||||
|
||||
// 4. Assert: newDocument's is initial about:blank is false,
|
||||
// i.e., we never traverse back to the initial about:blank Document because it always gets replaced when we navigate away from it.
|
||||
VERIFY(!new_document->is_initial_about_blank());
|
||||
|
||||
// 5. If newDocument is different than the current entry's document, or historyHandling is "entry update" or "reload", then:
|
||||
if (new_document.ptr() != current_entry().document_state->document().ptr()
|
||||
|| history_handling == HistoryHandlingBehavior::EntryUpdate) {
|
||||
// FIXME: 1. If newDocument's suspended timer handles is not empty:
|
||||
// FIXME: 1. Assert: newDocument's suspension time is not zero.
|
||||
// FIXME: 2. Let suspendDuration be the current high resolution time minus newDocument's suspension time.
|
||||
// FIXME: 3. Let activeTimers be newDocument's relevant global object's map of active timers.
|
||||
// FIXME: 4. For each handle in newDocument's suspended timer handles, if activeTimers[handle] exists, then increase activeTimers[handle] by suspendDuration.
|
||||
}
|
||||
|
||||
// 2. Remove any tasks queued by the history traversal task source
|
||||
// that are associated with any Document objects in the top-level browsing context's document family.
|
||||
HTML::main_thread_event_loop().task_queue().remove_tasks_matching([&](HTML::Task const& task) {
|
||||
return task.source() == Task::Source::HistoryTraversal
|
||||
&& task.document()
|
||||
&& top_level_browsing_context().document_family_contains(*task.document());
|
||||
});
|
||||
|
||||
// 3. If newDocument's origin is not same origin with the current entry's document's origin, then:
|
||||
if (!new_document->origin().is_same_origin(current_entry().document_state->document()->origin())) {
|
||||
// FIXME: 1. Let entriesToUpdate be all entries in the session history whose document's origin is same origin as the active document
|
||||
// and that are contiguous with the current entry.
|
||||
// FIXME: 2. For each entryToUpdate of entriesToUpdate, set entryToUpdate's browsing context name to the current browsing context name.
|
||||
// FIXME: 3. If the browsing context is a top-level browsing context, but not an auxiliary browsing context whose disowned is false, then set the browsing context's name to the empty string.
|
||||
}
|
||||
|
||||
// 4. Set the active document of the browsing context to newDocument.
|
||||
set_active_document(*new_document);
|
||||
|
||||
// 5. If entry's browsing context name is not null, then:
|
||||
if (entry->browsing_context_name.has_value()) {
|
||||
// 1. Set the browsing context's name to entry's browsing context name.
|
||||
m_name = *entry->browsing_context_name;
|
||||
|
||||
// FIXME: 2. Let entriesToUpdate be all entries in the session history whose document's origin is same origin as the new active document's origin and that are contiguous with entry.
|
||||
// FIXME: 3. For each entryToUpdate of entriesToUpdate, set entryToUpdate's browsing context name to null.
|
||||
}
|
||||
|
||||
// FIXME: 6. If newDocument has any form controls whose autofill field name is "off", invoke the reset algorithm of each of those elements.
|
||||
|
||||
// 7. If newDocument's current document readiness "complete",
|
||||
if (new_document->readiness() == HTML::DocumentReadyState::Complete) {
|
||||
// then queue a global task on the DOM manipulation task source given newDocument's relevant global object to run the following steps:
|
||||
|
||||
queue_global_task(Task::Source::DOMManipulation, relevant_global_object(*new_document), [new_document] {
|
||||
// 1. If newDocument's page showing flag is true, then abort these steps.
|
||||
if (new_document->page_showing())
|
||||
return;
|
||||
|
||||
// 2. Set newDocument's page showing flag to true.
|
||||
new_document->set_page_showing(true);
|
||||
|
||||
// 3. Update the visibility state of newDocument to "hidden".
|
||||
new_document->update_the_visibility_state(VisibilityState::Hidden);
|
||||
|
||||
// 4. Fire a page transition event named pageshow at newDocument's relevant global object with true.
|
||||
auto& window = verify_cast<HTML::Window>(relevant_global_object(*new_document));
|
||||
window.fire_a_page_transition_event(HTML::EventNames::pageshow, true);
|
||||
});
|
||||
}
|
||||
|
||||
// 6. Set newDocument's URL to entry's URL.
|
||||
new_document->set_url(entry->url);
|
||||
|
||||
// 7. Let hashChanged be false, and let oldURL and newURL be null.
|
||||
bool hash_changed = false;
|
||||
Optional<AK::URL> old_url;
|
||||
Optional<AK::URL> new_url;
|
||||
|
||||
// 8. If entry's URL's fragment is not identical to the current entry's URL's fragment,
|
||||
// and entry's document equals the current entry's document,
|
||||
if (entry->url.fragment() != current_entry().url.fragment()
|
||||
&& entry->document_state->document().ptr() == current_entry().document_state->document().ptr()) {
|
||||
// then set hashChanged to true, set oldURL to the current entry's URL, and set newURL to entry's URL.
|
||||
hash_changed = true;
|
||||
old_url = current_entry().url;
|
||||
new_url = entry->url;
|
||||
}
|
||||
|
||||
// 9. If historyHandling is "replace", then remove the entry immediately before entry in the session history.
|
||||
if (history_handling == HistoryHandlingBehavior::Replace) {
|
||||
// FIXME: This is gnarly.
|
||||
m_session_history.remove(entry_index - 1);
|
||||
entry_index--;
|
||||
entry = m_session_history[entry_index];
|
||||
}
|
||||
|
||||
// 10. If entry's persisted user state is null, and its URL's fragment is non-null, then scroll to the fragment.
|
||||
if (entry->url.fragment().has_value())
|
||||
active_document()->scroll_to_the_fragment();
|
||||
|
||||
// 11. Set the current entry to entry.
|
||||
m_session_history_index = entry_index;
|
||||
|
||||
// 12. Let targetRealm be the current Realm Record.
|
||||
auto* target_realm = Bindings::main_thread_vm().current_realm();
|
||||
VERIFY(target_realm);
|
||||
|
||||
// FIXME: 13. Let state be null.
|
||||
// FIXME: 14. If entry's serialized state is not null, then set state to StructuredDeserialize(entry's serialized state, targetRealm).
|
||||
// If this throws an exception, catch it and ignore the exception.
|
||||
// FIXME: 15. Set newDocument's History object's state to state.
|
||||
// FIXME: 16. Let stateChanged be true if newDocument has a latest entry, and that entry is not entry; otherwise let it be false.
|
||||
// FIXME: 17. Set newDocument's latest entry to entry.
|
||||
// FIXME: 18. If stateChanged is true, then fire an event named popstate at newDocument's relevant global object, using PopStateEvent, with the state attribute initialized to state.
|
||||
// FIXME: 19. Restore persisted state from entry.
|
||||
|
||||
// 20. If hashChanged is true,
|
||||
if (hash_changed) {
|
||||
// then queue a global task on the DOM manipulation task source given newDocument's relevant global object
|
||||
queue_global_task(Task::Source::DOMManipulation, relevant_global_object(*new_document), [new_document] {
|
||||
// to fire an event named hashchange at newDocument's relevant global object,
|
||||
// using HashChangeEvent, with the oldURL attribute initialized to oldURL
|
||||
// and the newURL attribute initialized to newURL.
|
||||
|
||||
// FIXME: Implement a proper HashChangeEvent class.
|
||||
auto event = DOM::Event::create(verify_cast<HTML::Window>(relevant_global_object(*new_document)).realm(), HTML::EventNames::hashchange);
|
||||
new_document->dispatch_event(event);
|
||||
});
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsers.html#allowed-to-navigate
|
||||
bool BrowsingContext::is_allowed_to_navigate(BrowsingContext const& other) const
|
||||
{
|
||||
VERIFY(active_window());
|
||||
VERIFY(active_document());
|
||||
|
||||
// 1. If A is not the same browsing context as B,
|
||||
// and A is not one of the ancestor browsing contexts of B,
|
||||
// and B is not a top-level browsing context,
|
||||
// FIXME: and A's active document's active sandboxing flag set has its sandboxed navigation browsing context flag set,
|
||||
// then return false.
|
||||
if (this != &other
|
||||
&& !this->is_ancestor_of(other)
|
||||
&& !other.is_top_level()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. Otherwise, if B is a top-level browsing context, and is one of the ancestor browsing contexts of A, then:
|
||||
if (other.is_top_level() && other.is_ancestor_of(*this)) {
|
||||
// 1. If A's active window has transient activation
|
||||
// and A's active document's active sandboxing flag set has its sandboxed top-level navigation with user activation browsing context flag set,
|
||||
// then return false.
|
||||
if (active_window()->has_transient_activation()
|
||||
&& has_flag(active_document()->active_sandboxing_flag_set(), SandboxingFlagSet::SandboxedTopLevelNavigationWithUserActivation)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. Otherwise, if A's active window does not have transient activation
|
||||
// and A's active document's active sandboxing flag set has its sandboxed top-level navigation without user activation browsing context flag set,
|
||||
// then return false.
|
||||
if (!active_window()->has_transient_activation()
|
||||
&& has_flag(active_document()->active_sandboxing_flag_set(), SandboxingFlagSet::SandboxedTopLevelNavigationWithoutUserActivation)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Otherwise, if B is a top-level browsing context,
|
||||
// and is neither A nor one of the ancestor browsing contexts of A,
|
||||
// and A's Document's active sandboxing flag set has its sandboxed navigation browsing context flag set,
|
||||
// and A is not the one permitted sandboxed navigator of B,
|
||||
// then return false.
|
||||
if (other.is_top_level()
|
||||
&& &other != this
|
||||
&& !other.is_ancestor_of(*this)
|
||||
&& has_flag(active_document()->active_sandboxing_flag_set(), SandboxingFlagSet::SandboxedNavigation)
|
||||
&& this != other.the_one_permitted_sandboxed_navigator()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/origin.html#one-permitted-sandboxed-navigator
|
||||
BrowsingContext const* BrowsingContext::the_one_permitted_sandboxed_navigator() const
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue