1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
// Copyright 2014 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/url_request_util.h"
#include <string_view>
#include "base/types/optional_util.h"
#include "components/guest_view/buildflags/buildflags.h"
#include "extensions/browser/extension_navigation_ui_data.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/process_map.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/manifest_handlers/icons_handler.h"
#include "extensions/common/manifest_handlers/web_accessible_resources_info.h"
#include "extensions/common/manifest_handlers/webview_info.h"
#include "pdf/buildflags.h"
#include "services/network/public/cpp/request_destination.h"
#include "services/network/public/cpp/resource_request.h"
#include "third_party/blink/public/common/loader/resource_type_util.h"
#include "url/gurl.h"
#if BUILDFLAG(ENABLE_GUEST_VIEW)
#include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
#endif
#if BUILDFLAG(ENABLE_PDF)
#include "pdf/pdf_features.h"
#endif // BUILDFLAG(ENABLE_PDF)
namespace extensions::url_request_util {
bool AllowCrossRendererResourceLoad(
const network::ResourceRequest& request,
network::mojom::RequestDestination destination,
ui::PageTransition page_transition,
int child_id,
bool is_incognito,
const Extension* extension,
const ExtensionSet& extensions,
const ProcessMap& process_map,
const GURL& upstream_url,
bool* allowed) {
const GURL& url = request.url;
std::string_view resource_path = url.path_piece();
// This logic is performed for main frame requests in
// ExtensionNavigationThrottle::WillStartRequest.
if (child_id != -1 ||
destination != network::mojom::RequestDestination::kDocument) {
// Extensions with webview: allow loading certain resources by guest
// renderers with privileged partition IDs as specified in owner's extension
// the manifest file.
bool is_guest = false;
std::string partition_id;
const Extension* owner_extension = nullptr;
#if BUILDFLAG(ENABLE_GUEST_VIEW)
int owner_process_id;
std::string owner_extension_id;
WebViewRendererState::GetInstance()->GetOwnerInfo(
child_id, &owner_process_id, &owner_extension_id);
owner_extension = extensions.GetByID(owner_extension_id);
is_guest = WebViewRendererState::GetInstance()->GetPartitionID(
child_id, &partition_id);
#endif
if (AllowCrossRendererResourceLoadHelper(
is_guest, extension, owner_extension, partition_id, resource_path,
page_transition, allowed)) {
return true;
}
}
// The following checks require that we have an actual extension object. If we
// don't have it, allow the request handling to continue with the rest of the
// checks.
if (!extension) {
*allowed = true;
return true;
}
// Disallow loading of packaged resources for hosted apps. We don't allow
// hybrid hosted/packaged apps. The one exception is access to icons, since
// some extensions want to be able to do things like create their own
// launchers.
std::string_view resource_root_relative_path =
url.path_piece().empty() ? std::string_view()
: url.path_piece().substr(1);
if (extension->is_hosted_app() &&
!IconsInfo::GetIcons(extension)
.ContainsPath(resource_root_relative_path)) {
LOG(ERROR) << "Denying load of " << url.spec() << " from hosted app.";
*allowed = false;
return true;
}
DCHECK_EQ(extension->url(), url.GetWithEmptyPath());
// Navigating the main frame to an extension URL is allowed, even if not
// explicitly listed as web_accessible_resource.
if (destination == network::mojom::RequestDestination::kDocument) {
*allowed = true;
return true;
}
// When navigating in subframe, verify that the extension the resource is
// loaded from matches the process loading it.
if (network::IsRequestDestinationEmbeddedFrame(destination) &&
process_map.Contains(extension->id(), child_id)) {
*allowed = true;
return true;
}
// If the request is initiated by an opaque origin, allow it if the origin's
// precursor matches the extension. This allows sandboxed data URLs and srcdoc
// documents from an extension to access its resources (necessary for
// backwards compatibility), even if they rendered in a non-extension process.
if (request.request_initiator && request.request_initiator.value().opaque()) {
const GURL precursor_url = request.request_initiator.value()
.GetTupleOrPrecursorTupleIfOpaque()
.GetURL();
if (extension->origin() == url::Origin::Create(precursor_url)) {
*allowed = true;
return true;
}
}
// Allow web accessible extension resources to be loaded as
// subresources/sub-frames.
if (url.SchemeIs(extensions::kExtensionScheme) &&
WebAccessibleResourcesInfo::IsResourceWebAccessibleRedirect(
extension, url, request.request_initiator, upstream_url)) {
*allowed = true;
return true;
}
if (!ui::PageTransitionIsWebTriggerable(page_transition)) {
*allowed = false;
return true;
}
// Couldn't determine if the resource is allowed or not.
return false;
}
bool AllowCrossRendererResourceLoadHelper(bool is_guest,
const Extension* extension,
const Extension* owner_extension,
const std::string& partition_id,
std::string_view resource_path,
ui::PageTransition page_transition,
bool* allowed) {
if (is_guest) {
#if BUILDFLAG(ENABLE_PDF)
// Allow the PDF Viewer extension to load in guests.
if (chrome_pdf::features::IsOopifPdfEnabled() && extension &&
extension->id() == extension_misc::kPdfExtensionId) {
*allowed = true;
return true;
}
#endif // BUILDFLAG(ENABLE_PDF)
// An extension's resources should only be accessible to WebViews owned by
// that extension.
if (owner_extension != extension) {
*allowed = false;
return true;
}
*allowed = WebviewInfo::IsResourceWebviewAccessible(
extension, partition_id, std::string(resource_path));
return true;
}
return false;
}
} // namespace extensions::url_request_util
|