Commit e354a6c1 authored by Marijn Kruisselbrink's avatar Marijn Kruisselbrink Committed by Commit Bot

Fix blob url loading in <webview> in guest mode.

As it turns out Chrome OS guest mode is violating the assumption
<webview> made that a chrome app's storage partition is always on disk.
Because of this, before the change that added the blob url fallback
mechanism a <webview> with no explicit partition name set would
(incorrectly) share the storage partition with the app that embeds it.
Adding the blob url fallback flag fixed that (by making them separate
configs only differing in the fallback flag), but the fallback mechanism
also assumed that a chrome app's storage partition always was on disk.

This CL fixes loading blob URLs in a <webview> in guest mode by changing
StoragePartitionConfig to store a tri-state enum rather than a simple
bool for its blob url fallback mode. This way we can support fallback
regardless of if the chrome app's storage is in memory or on disk.

Bug: 1128330
Change-Id: I518cd5d1e89491eaf1cc6e2ed9ddb5cd3f0b9e87
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2439110Reviewed-by: default avatarDavid Roger <droger@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarLucas Gadani <lfg@chromium.org>
Reviewed-by: default avatarLuciano Pacheco <lucmult@chromium.org>
Reviewed-by: default avatarAaron Colwell <acolwell@chromium.org>
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812313}
parent 074492a9
...@@ -494,6 +494,7 @@ WRAPPED_INSTANTIATE_TEST_SUITE_P( ...@@ -494,6 +494,7 @@ WRAPPED_INSTANTIATE_TEST_SUITE_P(
TestCase("openQuickViewAudioWithImageMetadata"), TestCase("openQuickViewAudioWithImageMetadata"),
TestCase("openQuickViewImageJpg"), TestCase("openQuickViewImageJpg"),
TestCase("openQuickViewImageJpeg"), TestCase("openQuickViewImageJpeg"),
TestCase("openQuickViewImageJpeg").InGuestMode(),
TestCase("openQuickViewImageExif"), TestCase("openQuickViewImageExif"),
TestCase("openQuickViewImageRaw"), TestCase("openQuickViewImageRaw"),
TestCase("openQuickViewImageRawWithOrientation"), TestCase("openQuickViewImageRawWithOrientation"),
......
...@@ -140,7 +140,7 @@ void WebAuthFlow::DetachDelegateAndDelete() { ...@@ -140,7 +140,7 @@ void WebAuthFlow::DetachDelegateAndDelete() {
content::StoragePartition* WebAuthFlow::GetGuestPartition() { content::StoragePartition* WebAuthFlow::GetGuestPartition() {
return content::BrowserContext::GetStoragePartition( return content::BrowserContext::GetStoragePartition(
profile_, GetWebViewPartitionConfig(partition_)); profile_, GetWebViewPartitionConfig(partition_, profile_));
} }
const std::string& WebAuthFlow::GetAppWindowKey() const { const std::string& WebAuthFlow::GetAppWindowKey() const {
...@@ -149,13 +149,19 @@ const std::string& WebAuthFlow::GetAppWindowKey() const { ...@@ -149,13 +149,19 @@ const std::string& WebAuthFlow::GetAppWindowKey() const {
// static // static
content::StoragePartitionConfig WebAuthFlow::GetWebViewPartitionConfig( content::StoragePartitionConfig WebAuthFlow::GetWebViewPartitionConfig(
Partition partition) { Partition partition,
content::BrowserContext* browser_context) {
// This has to mirror the logic in WebViewGuest::CreateWebContents for // This has to mirror the logic in WebViewGuest::CreateWebContents for
// creating the correct StoragePartitionConfig. // creating the correct StoragePartitionConfig.
auto result = content::StoragePartitionConfig::Create( auto result = content::StoragePartitionConfig::Create(
extension_misc::kIdentityApiUiAppId, GetPartitionName(partition), extension_misc::kIdentityApiUiAppId, GetPartitionName(partition),
/*in_memory=*/true); /*in_memory=*/true);
result.set_fallback_to_partition_domain_for_blob_urls(true); result.set_fallback_to_partition_domain_for_blob_urls(
browser_context->IsOffTheRecord()
? content::StoragePartitionConfig::FallbackMode::
kFallbackPartitionInMemory
: content::StoragePartitionConfig::FallbackMode::
kFallbackPartitionOnDisk);
return result; return result;
} }
......
...@@ -105,7 +105,8 @@ class WebAuthFlow : public content::NotificationObserver, ...@@ -105,7 +105,8 @@ class WebAuthFlow : public content::NotificationObserver,
// Returns the StoragePartitionConfig for a given |partition| used in the // Returns the StoragePartitionConfig for a given |partition| used in the
// WebAuthFlow. // WebAuthFlow.
static content::StoragePartitionConfig GetWebViewPartitionConfig( static content::StoragePartitionConfig GetWebViewPartitionConfig(
Partition partition); Partition partition,
content::BrowserContext* browser_context);
private: private:
friend class ::WebAuthFlowTest; friend class ::WebAuthFlowTest;
......
...@@ -109,7 +109,8 @@ bool HeaderModificationDelegateImpl::ShouldIgnoreGuestWebViewRequest( ...@@ -109,7 +109,8 @@ bool HeaderModificationDelegateImpl::ShouldIgnoreGuestWebViewRequest(
GURL identity_api_site = GURL identity_api_site =
extensions::WebViewGuest::GetSiteForGuestPartitionConfig( extensions::WebViewGuest::GetSiteForGuestPartitionConfig(
extensions::WebAuthFlow::GetWebViewPartitionConfig( extensions::WebAuthFlow::GetWebViewPartitionConfig(
extensions::WebAuthFlow::GET_AUTH_TOKEN)); extensions::WebAuthFlow::GET_AUTH_TOKEN,
contents->GetBrowserContext()));
if (contents->GetSiteInstance()->GetSiteURL() != identity_api_site) if (contents->GetSiteInstance()->GetSiteURL() != identity_api_site)
return true; return true;
......
...@@ -51,16 +51,13 @@ StoragePartitionConfig StoragePartitionConfig::CopyWithInMemorySet() const { ...@@ -51,16 +51,13 @@ StoragePartitionConfig StoragePartitionConfig::CopyWithInMemorySet() const {
base::Optional<StoragePartitionConfig> base::Optional<StoragePartitionConfig>
StoragePartitionConfig::GetFallbackForBlobUrls() const { StoragePartitionConfig::GetFallbackForBlobUrls() const {
if (!fallback_to_partition_domain_for_blob_urls_) if (fallback_to_partition_domain_for_blob_urls_ == FallbackMode::kNone)
return base::nullopt; return base::nullopt;
// Currently this fallback mechanism is only used in cases where the fallback return StoragePartitionConfig(
// partition is not in memory. If we ever need to support falling back to a partition_domain_, "",
// in memory storage partition, we could change the fallback flag from the /*in_memory=*/fallback_to_partition_domain_for_blob_urls_ ==
// boolean it is today to some kind of enum. FallbackMode::kFallbackPartitionInMemory);
// TODO(acolwell): Make this a little more robust.
return StoragePartitionConfig(partition_domain_, "",
/*in_memory=*/false);
} }
bool StoragePartitionConfig::operator<( bool StoragePartitionConfig::operator<(
......
...@@ -50,18 +50,27 @@ class CONTENT_EXPORT StoragePartitionConfig { ...@@ -50,18 +50,27 @@ class CONTENT_EXPORT StoragePartitionConfig {
// In some cases we want a "child" storage partition to resolve blob URLs that // In some cases we want a "child" storage partition to resolve blob URLs that
// were created by their "parent", while not allowing the reverse. To enable // were created by their "parent", while not allowing the reverse. To enable
// this, set this flag to true, which will result in the storage partition // this, set this flag to a value other than kNone, which will result in the
// with the same partition_domain but empty partition_name being used as // storage partition with the same partition_domain but empty partition_name
// fallback for the purpose of resolving blob URLs. // being used as fallback for the purpose of resolving blob URLs.
void set_fallback_to_partition_domain_for_blob_urls(bool fallback) { enum class FallbackMode {
if (fallback) { kNone,
kFallbackPartitionOnDisk,
kFallbackPartitionInMemory,
};
void set_fallback_to_partition_domain_for_blob_urls(FallbackMode fallback) {
if (fallback != FallbackMode::kNone) {
DCHECK(!is_default()); DCHECK(!is_default());
DCHECK(!partition_domain_.empty()); DCHECK(!partition_domain_.empty());
DCHECK(!partition_name_.empty() || in_memory_); // TODO(acollwell): Ideally we shouldn't have storage partition configs
// that differ only in their fallback mode, but unfortunately that isn't
// true. When that is fixed this can be made more robust by disallowing
// fallback from storage partitions with an empty partition name.
// DCHECK(!partition_name_.empty());
} }
fallback_to_partition_domain_for_blob_urls_ = fallback; fallback_to_partition_domain_for_blob_urls_ = fallback;
} }
bool fallback_to_partition_domain_for_blob_urls() const { FallbackMode fallback_to_partition_domain_for_blob_urls() const {
return fallback_to_partition_domain_for_blob_urls_; return fallback_to_partition_domain_for_blob_urls_;
} }
base::Optional<StoragePartitionConfig> GetFallbackForBlobUrls() const; base::Optional<StoragePartitionConfig> GetFallbackForBlobUrls() const;
...@@ -80,7 +89,8 @@ class CONTENT_EXPORT StoragePartitionConfig { ...@@ -80,7 +89,8 @@ class CONTENT_EXPORT StoragePartitionConfig {
std::string partition_domain_; std::string partition_domain_;
std::string partition_name_; std::string partition_name_;
bool in_memory_ = false; bool in_memory_ = false;
bool fallback_to_partition_domain_for_blob_urls_ = false; FallbackMode fallback_to_partition_domain_for_blob_urls_ =
FallbackMode::kNone;
}; };
} // namespace content } // namespace content
......
...@@ -90,6 +90,11 @@ namespace extensions { ...@@ -90,6 +90,11 @@ namespace extensions {
namespace { namespace {
// Strings used to encode blob url fallback mode in site URLs.
constexpr char kNoFallback[] = "nofallback";
constexpr char kInMemoryFallback[] = "inmemoryfallback";
constexpr char kOnDiskFallback[] = "ondiskfallback";
// Returns storage partition removal mask from web_view clearData mask. Note // Returns storage partition removal mask from web_view clearData mask. Note
// that storage partition mask is a subset of webview's data removal mask. // that storage partition mask is a subset of webview's data removal mask.
uint32_t GetStoragePartitionRemovalMask(uint32_t web_view_removal_mask) { uint32_t GetStoragePartitionRemovalMask(uint32_t web_view_removal_mask) {
...@@ -296,9 +301,24 @@ bool WebViewGuest::GetGuestPartitionConfigForSite( ...@@ -296,9 +301,24 @@ bool WebViewGuest::GetGuestPartitionConfigForSite(
// partition_domain but empty partition_name. Setting this flag on the // partition_domain but empty partition_name. Setting this flag on the
// partition config causes it to be used as fallback for the purpose of // partition config causes it to be used as fallback for the purpose of
// resolving blob URLs. // resolving blob URLs.
bool use_fallback = site.ref() != "nofallback";
// Default to having the fallback partition on disk, as that matches most
// closely what we would have done before fallback behavior started being
// encoded in the site URL.
content::StoragePartitionConfig::FallbackMode fallback_mode =
content::StoragePartitionConfig::FallbackMode::kFallbackPartitionOnDisk;
if (site.ref() == kNoFallback) {
fallback_mode = content::StoragePartitionConfig::FallbackMode::kNone;
} else if (site.ref() == kInMemoryFallback) {
fallback_mode = content::StoragePartitionConfig::FallbackMode::
kFallbackPartitionInMemory;
} else if (site.ref() == kOnDiskFallback) {
fallback_mode =
content::StoragePartitionConfig::FallbackMode::kFallbackPartitionOnDisk;
}
storage_partition_config->set_fallback_to_partition_domain_for_blob_urls( storage_partition_config->set_fallback_to_partition_domain_for_blob_urls(
use_fallback); fallback_mode);
return true; return true;
} }
...@@ -307,14 +327,26 @@ GURL WebViewGuest::GetSiteForGuestPartitionConfig( ...@@ -307,14 +327,26 @@ GURL WebViewGuest::GetSiteForGuestPartitionConfig(
const content::StoragePartitionConfig& storage_partition_config) { const content::StoragePartitionConfig& storage_partition_config) {
std::string url_encoded_partition = net::EscapeQueryParamValue( std::string url_encoded_partition = net::EscapeQueryParamValue(
storage_partition_config.partition_name(), false); storage_partition_config.partition_name(), false);
return GURL(base::StringPrintf( const char* fallback = "";
"%s://%s/%s?%s%s", content::kGuestScheme, switch (
storage_partition_config.fallback_to_partition_domain_for_blob_urls()) {
case content::StoragePartitionConfig::FallbackMode::kNone:
fallback = kNoFallback;
break;
case content::StoragePartitionConfig::FallbackMode::
kFallbackPartitionOnDisk:
fallback = kOnDiskFallback;
break;
case content::StoragePartitionConfig::FallbackMode::
kFallbackPartitionInMemory:
fallback = kInMemoryFallback;
break;
}
return GURL(
base::StringPrintf("%s://%s/%s?%s#%s", content::kGuestScheme,
storage_partition_config.partition_domain().c_str(), storage_partition_config.partition_domain().c_str(),
storage_partition_config.in_memory() ? "" : "persist", storage_partition_config.in_memory() ? "" : "persist",
url_encoded_partition.c_str(), url_encoded_partition.c_str(), fallback));
storage_partition_config.fallback_to_partition_domain_for_blob_urls()
? ""
: "#nofallback"));
} }
// static // static
...@@ -379,8 +411,16 @@ void WebViewGuest::CreateWebContents(const base::DictionaryValue& create_params, ...@@ -379,8 +411,16 @@ void WebViewGuest::CreateWebContents(const base::DictionaryValue& create_params,
extensions::util::GetStoragePartitionConfigForExtensionId( extensions::util::GetStoragePartitionConfigForExtensionId(
GetOwnerSiteURL().host(), GetOwnerSiteURL().host(),
owner_render_process_host->GetBrowserContext()); owner_render_process_host->GetBrowserContext());
if (!owner_config.is_default() && !owner_config.in_memory()) { if (owner_render_process_host->GetBrowserContext()->IsOffTheRecord()) {
partition_config.set_fallback_to_partition_domain_for_blob_urls(true); owner_config = owner_config.CopyWithInMemorySet();
}
if (!owner_config.is_default()) {
partition_config.set_fallback_to_partition_domain_for_blob_urls(
owner_config.in_memory()
? content::StoragePartitionConfig::FallbackMode::
kFallbackPartitionInMemory
: content::StoragePartitionConfig::FallbackMode::
kFallbackPartitionOnDisk);
DCHECK(owner_config == partition_config.GetFallbackForBlobUrls().value()); DCHECK(owner_config == partition_config.GetFallbackForBlobUrls().value());
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment