// Copyright (c) 2020 Samuel Maddock . // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. #include "shell/browser/api/electron_api_web_frame_main.h" #include #include #include #include #include "base/logging.h" #include "base/no_destructor.h" #include "content/browser/renderer_host/render_frame_host_impl.h" // nogncheck #include "content/public/browser/frame_tree_node_id.h" #include "content/public/browser/render_frame_host.h" #include "content/public/common/isolated_world_ids.h" #include "electron/shell/common/api/api.mojom.h" #include "gin/handle.h" #include "gin/object_template_builder.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "shell/browser/api/message_port.h" #include "shell/browser/browser.h" #include "shell/browser/javascript_environment.h" #include "shell/common/gin_converters/blink_converter.h" #include "shell/common/gin_converters/frame_converter.h" #include "shell/common/gin_converters/gurl_converter.h" #include "shell/common/gin_converters/value_converter.h" #include "shell/common/gin_helper/dictionary.h" #include "shell/common/gin_helper/error_thrower.h" #include "shell/common/gin_helper/object_template_builder.h" #include "shell/common/gin_helper/promise.h" #include "shell/common/node_includes.h" #include "shell/common/v8_util.h" namespace { // RenderFrameHost (RFH) exists as a child of a FrameTreeNode. When a // cross-origin navigation occurs, the FrameTreeNode swaps RFHs. After // swapping, the old RFH will be marked for deletion and run any unload // listeners. If an IPC is sent during an unload/beforeunload listener, // it's possible that it arrives after the RFH swap and has been // detached from the FrameTreeNode. bool IsDetachedFrameHost(content::RenderFrameHost* rfh) { if (!rfh) return true; // RenderFrameCreated is called for speculative frames which may not be // used in certain cross-origin navigations. Invoking // RenderFrameHost::GetLifecycleState currently crashes when called for // speculative frames so we need to filter it out for now. Check // https://crbug.com/1183639 for details on when this can be removed. auto* rfh_impl = static_cast(rfh); // During cross-origin navigation, a RFH may be swapped out of its // FrameTreeNode with a new RFH. In these cases, it's marked for // deletion. As this pending deletion RFH won't be following future // swaps, we need to indicate that its been pinned. return (rfh_impl->lifecycle_state() != content::RenderFrameHostImpl::LifecycleStateImpl::kSpeculative && rfh->GetLifecycleState() == content::RenderFrameHost::LifecycleState::kPendingDeletion); } } // namespace namespace gin { template <> struct Converter { static v8::Local ToV8(v8::Isolate* isolate, blink::mojom::PageVisibilityState val) { std::string visibility; switch (val) { case blink::mojom::PageVisibilityState::kVisible: visibility = "visible"; break; case blink::mojom::PageVisibilityState::kHidden: case blink::mojom::PageVisibilityState::kHiddenButPainting: visibility = "hidden"; break; } return gin::ConvertToV8(isolate, visibility); } }; } // namespace gin namespace electron::api { // FrameTreeNodeId -> WebFrameMain* // Using FrameTreeNode allows us to track frame across navigations. This // is most similar to how