blob: f4a7203edc299017390702f89d3fb5fa71aa9f88 [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h"
#include <memory>
#include <utility>
#include "components/guest_view/browser/guest_view_base.h"
#include "components/guest_view/browser/guest_view_manager.h"
#include "components/guest_view/common/guest_view_constants.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/child_process_host.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/common/content_features.h"
#include "extensions/browser/api/extensions_api_client.h"
#include "extensions/browser/browser_frame_context_data.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_util.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/guest_view/app_view/app_view_guest.h"
#include "extensions/browser/guest_view/extension_options/extension_options_guest.h"
#include "extensions/browser/guest_view/guest_view_events.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
#include "extensions/browser/guest_view/web_view/web_view_guest.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_map.h"
#include "extensions/browser/view_type_utils.h"
#include "extensions/common/constants.h"
#include "extensions/common/features/feature.h"
#include "extensions/common/features/feature_provider.h"
#include "extensions/common/mojom/event_dispatcher.mojom.h"
#include "extensions/common/mojom/view_type.mojom.h"
#include "extensions/common/utils/extension_utils.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-forward.h"
using guest_view::GuestViewBase;
using guest_view::GuestViewManager;
namespace extensions {
// Returns a HostID instance based on the given GuestViewBase.
mojom::HostID GenerateHostIdFromGuestView(
const guest_view::GuestViewBase& guest) {
// Note: We return a type of kExtensions for all cases where
// |guest.IsOwnedByExtension()| are true, as well as some additional cases
// where that call is false but also |guest.IsOwnedByWebUI()| and
// |guest.IsOwnedByControlledFrameEmbedder()| are false. Those appear to be
// when the provided extension identifier is blank. Future work in this area
// could improve the checks here so all the cases are declared relative to
// what the GuestView instance asserts itself to be.
mojom::HostID::HostType host_type = mojom::HostID::HostType::kExtensions;
if (guest.IsOwnedByWebUI()) {
host_type = mojom::HostID::HostType::kWebUi;
} else if (guest.IsOwnedByControlledFrameEmbedder()) {
host_type = mojom::HostID::HostType::kControlledFrameEmbedder;
}
return mojom::HostID(host_type, guest.owner_host());
}
// static
bool ExtensionsGuestViewManagerDelegate::IsGuestAvailableToContextWithFeature(
const GuestViewBase* guest,
const std::string& feature_name) {
const Feature* feature = FeatureProvider::GetAPIFeature(feature_name);
if (!feature) {
return false;
}
content::BrowserContext* context = guest->browser_context();
ProcessMap* process_map = ProcessMap::Get(context);
CHECK(process_map);
const Extension* owner_extension =
ProcessManager::Get(context)->GetExtensionForRenderFrameHost(
guest->owner_rfh());
const GURL& owner_site_url = guest->GetOwnerSiteURL();
// Ok for |owner_extension| to be nullptr, the embedder might be WebUI.
Feature::Availability availability = feature->IsAvailableToContext(
owner_extension,
process_map->GetMostLikelyContextType(
owner_extension, guest->owner_rfh()->GetProcess()->GetDeprecatedID(),
&owner_site_url),
owner_site_url, util::GetBrowserContextId(context),
BrowserFrameContextData(guest->owner_rfh()));
return availability.is_available();
}
ExtensionsGuestViewManagerDelegate::ExtensionsGuestViewManagerDelegate() =
default;
ExtensionsGuestViewManagerDelegate::~ExtensionsGuestViewManagerDelegate() =
default;
void ExtensionsGuestViewManagerDelegate::OnGuestAdded(
content::WebContents* guest_web_contents) const {
CHECK(!base::FeatureList::IsEnabled(features::kGuestViewMPArch));
// Set the view type so extensions sees the guest view as a foreground page.
SetViewType(guest_web_contents, mojom::ViewType::kExtensionGuest);
}
void ExtensionsGuestViewManagerDelegate::DispatchEvent(
const std::string& event_name,
base::Value::Dict args,
GuestViewBase* guest,
int instance_id) {
CHECK(guest);
mojom::EventFilteringInfoPtr info = mojom::EventFilteringInfo::New();
info->has_instance_id = true;
info->instance_id = instance_id;
base::Value::List event_args;
event_args.Append(std::move(args));
// GetEventHistogramValue maps guest view event names to their histogram
// value. It needs to be like this because the guest view component doesn't
// know about extensions, so GuestViewEvent can't have an
// extensions::events::HistogramValue as an argument.
events::HistogramValue histogram_value =
guest_view_events::GetEventHistogramValue(event_name);
DCHECK_NE(events::UNKNOWN, histogram_value) << "Event " << event_name
<< " must have a histogram value";
content::RenderFrameHost* owner = guest->owner_rfh();
if (!owner || !ExtensionsBrowserClient::Get()->IsValidContext(
guest->browser_context())) {
return; // Could happen at tab shutdown.
}
EventRouter::Get(guest->browser_context())
->DispatchEventToSender(owner->GetProcess(), guest->browser_context(),
GenerateHostIdFromGuestView(*guest),
histogram_value, event_name,
extensions::kMainThreadId,
blink::mojom::kInvalidServiceWorkerVersionId,
std::move(event_args), std::move(info));
}
bool ExtensionsGuestViewManagerDelegate::IsGuestAvailableToContext(
const GuestViewBase* guest) const {
return IsGuestAvailableToContextWithFeature(guest, guest->GetAPINamespace());
}
bool ExtensionsGuestViewManagerDelegate::IsOwnedByExtension(
const GuestViewBase* guest) {
content::BrowserContext* context = guest->browser_context();
return !!ProcessManager::Get(context)->GetExtensionForRenderFrameHost(
guest->owner_rfh());
}
bool ExtensionsGuestViewManagerDelegate::IsOwnedByControlledFrameEmbedder(
const GuestViewBase* guest) {
return false;
}
void ExtensionsGuestViewManagerDelegate::RegisterAdditionalGuestViewTypes(
GuestViewManager* manager) {
manager->RegisterGuestViewType(AppViewGuest::Type,
base::BindRepeating(&AppViewGuest::Create),
base::NullCallback());
manager->RegisterGuestViewType(
ExtensionOptionsGuest::Type,
base::BindRepeating(&ExtensionOptionsGuest::Create),
base::NullCallback());
manager->RegisterGuestViewType(
MimeHandlerViewGuest::Type,
base::BindRepeating(&MimeHandlerViewGuest::Create), base::NullCallback());
manager->RegisterGuestViewType(WebViewGuest::Type,
base::BindRepeating(&WebViewGuest::Create),
base::BindRepeating(&WebViewGuest::CleanUp));
}
} // namespace extensions