summaryrefslogtreecommitdiffstats
path: root/src/core/extensions/extensions_browser_client_qt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/extensions/extensions_browser_client_qt.cpp')
-rw-r--r--src/core/extensions/extensions_browser_client_qt.cpp241
1 files changed, 161 insertions, 80 deletions
diff --git a/src/core/extensions/extensions_browser_client_qt.cpp b/src/core/extensions/extensions_browser_client_qt.cpp
index 59c15d2f5..8b5da3d60 100644
--- a/src/core/extensions/extensions_browser_client_qt.cpp
+++ b/src/core/extensions/extensions_browser_client_qt.cpp
@@ -63,13 +63,16 @@
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_host_delegate.h"
#include "extensions/browser/extension_protocols.h"
+#include "extensions/browser/extensions_browser_interface_binders.h"
#include "extensions/browser/mojo/interface_registration.h"
#include "extensions/browser/url_request_util.h"
#include "extensions/common/file_util.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/base/completion_once_callback.h"
#include "net/base/mime_util.h"
-#include "net/url_request/url_request_simple_job.h"
+#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/mojom/url_loader.mojom.h"
+#include "third_party/zlib/google/compression_utils.h"
#include "ui/base/resource/resource_bundle.h"
#include "component_extension_resource_manager_qt.h"
@@ -102,67 +105,164 @@ void DetermineCharset(const std::string &mime_type,
}
}
-// A request for an extension resource in a Chrome .pak file. These are used
-// by component extensions.
-class URLRequestResourceBundleJob : public net::URLRequestSimpleJob
+scoped_refptr<base::RefCountedMemory> GetResource(int resource_id, const std::string &extension_id)
+{
+ const ui::ResourceBundle &rb = ui::ResourceBundle::GetSharedInstance();
+ scoped_refptr<base::RefCountedMemory> bytes = rb.LoadDataResourceBytes(resource_id);
+ auto *replacements = extensions::ExtensionsBrowserClient::Get()->GetComponentExtensionResourceManager()
+ ? extensions::ExtensionsBrowserClient::Get()->GetComponentExtensionResourceManager()->GetTemplateReplacementsForExtension(
+ extension_id)
+ : nullptr;
+
+ bool is_gzipped = rb.IsGzipped(resource_id);
+ if (!bytes->size() || (!replacements && !is_gzipped)) {
+ return bytes;
+ }
+
+ base::StringPiece input(reinterpret_cast<const char *>(bytes->front()), bytes->size());
+
+ std::string temp_str;
+
+ base::StringPiece source = input;
+ if (is_gzipped) {
+ temp_str.resize(compression::GetUncompressedSize(input));
+ source = temp_str;
+ CHECK(compression::GzipUncompress(input, source));
+ }
+
+ if (replacements) {
+ temp_str = ui::ReplaceTemplateExpressions(source, *replacements);
+ }
+
+ DCHECK(!temp_str.empty());
+
+ return base::RefCountedString::TakeString(&temp_str);
+}
+
+// Loads an extension resource in a Chrome .pak file. These are used by
+// component extensions.
+class ResourceBundleFileLoader : public network::mojom::URLLoader
{
public:
- URLRequestResourceBundleJob(net::URLRequest *request, net::NetworkDelegate *network_delegate,
- const base::FilePath &filename, int resource_id,
- const std::string &content_security_policy, bool send_cors_header)
- : net::URLRequestSimpleJob(request, network_delegate)
- , filename_(filename)
- , resource_id_(resource_id)
- , weak_factory_(this)
+ static void CreateAndStart(const network::ResourceRequest &request,
+ mojo::PendingReceiver<network::mojom::URLLoader> loader,
+ mojo::PendingRemote<network::mojom::URLLoaderClient> client_info,
+ const base::FilePath &filename, int resource_id,
+ const std::string &content_security_policy, bool send_cors_header)
{
- // Leave cache headers out of resource bundle requests.
- response_info_.headers = extensions::BuildHttpHeaders(content_security_policy, send_cors_header, base::Time());
+ // Owns itself. Will live as long as its URLLoader and URLLoaderClientPtr
+ // bindings are alive - essentially until either the client gives up or all
+ // file data has been sent to it.
+ auto *bundle_loader = new ResourceBundleFileLoader(content_security_policy, send_cors_header);
+ bundle_loader->Start(request, std::move(loader), std::move(client_info), filename, resource_id);
}
- int GetRefCountedData(std::string *mime_type, std::string *charset, scoped_refptr<base::RefCountedMemory> *data,
- net::CompletionOnceCallback callback) const override
+
+ // mojom::URLLoader implementation:
+ void FollowRedirect(const std::vector<std::string> &removed_headers,
+ const net::HttpRequestHeaders &modified_headers, const base::Optional<GURL> &new_url) override
{
- const ui::ResourceBundle &rb = ui::ResourceBundle::GetSharedInstance();
- *data = rb.LoadDataResourceBytes(resource_id_);
+ NOTREACHED() << "No redirects for local file loads.";
+ }
+ // Current implementation reads all resource data at start of resource
+ // load, so priority, and pausing is not currently implemented.
+ void SetPriority(net::RequestPriority priority, int32_t intra_priority_value) override {}
+ void PauseReadingBodyFromNet() override {}
+ void ResumeReadingBodyFromNet() override {}
- // Add the Content-Length header now that we know the resource length.
- response_info_.headers->AddHeader(base::StringPrintf("%s: %s", net::HttpRequestHeaders::kContentLength,
- base::NumberToString((*data)->size()).c_str()));
+private:
+ ResourceBundleFileLoader(const std::string &content_security_policy, bool send_cors_header) : binding_(this)
+ {
+ response_headers_ = extensions::BuildHttpHeaders(content_security_policy, send_cors_header, base::Time());
+ }
+ ~ResourceBundleFileLoader() override = default;
- std::string *read_mime_type = new std::string;
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, { base::MayBlock() },
- base::BindOnce(&net::GetMimeTypeFromFile, filename_, base::Unretained(read_mime_type)),
- base::BindOnce(&URLRequestResourceBundleJob::OnMimeTypeRead, weak_factory_.GetWeakPtr(), mime_type,
- charset, *data, base::Owned(read_mime_type), std::move(callback)));
+ void Start(const network::ResourceRequest &request,
+ mojo::PendingReceiver<network::mojom::URLLoader> loader,
+ mojo::PendingRemote<network::mojom::URLLoaderClient> client_info_remote,
+ const base::FilePath &filename, int resource_id)
+ {
+ client_.Bind(std::move(client_info_remote));
+ binding_.Bind(std::move(loader));
+ binding_.set_connection_error_handler(
+ base::BindOnce(&ResourceBundleFileLoader::OnBindingError, base::Unretained(this)));
+ client_.set_connection_error_handler(
+ base::BindOnce(&ResourceBundleFileLoader::OnConnectionError, base::Unretained(this)));
+ auto data = GetResource(resource_id, request.url.host());
- return net::ERR_IO_PENDING;
+ std::string *read_mime_type = new std::string;
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE, { base::ThreadPool(), base::MayBlock() },
+ base::BindOnce(&net::GetMimeTypeFromFile, filename, base::Unretained(read_mime_type)),
+ base::BindOnce(&ResourceBundleFileLoader::OnMimeTypeRead, weak_factory_.GetWeakPtr(), std::move(data),
+ base::Owned(read_mime_type)));
}
- void GetResponseInfo(net::HttpResponseInfo *info) override { *info = response_info_; }
+ void OnMimeTypeRead(scoped_refptr<base::RefCountedMemory> data, std::string *read_mime_type, bool read_result)
+ {
+ network::ResourceResponseHead head;
+ head.request_start = base::TimeTicks::Now();
+ head.response_start = base::TimeTicks::Now();
+ head.content_length = data->size();
+ head.mime_type = *read_mime_type;
+ DetermineCharset(head.mime_type, data.get(), &head.charset);
+ mojo::DataPipe pipe(data->size());
+ if (!pipe.consumer_handle.is_valid()) {
+ client_->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED));
+ client_.reset();
+ MaybeDeleteSelf();
+ return;
+ }
+ head.headers = response_headers_;
+ head.headers->AddHeader(base::StringPrintf("%s: %s", net::HttpRequestHeaders::kContentLength,
+ base::NumberToString(head.content_length).c_str()));
+ if (!head.mime_type.empty()) {
+ head.headers->AddHeader(
+ base::StringPrintf("%s: %s", net::HttpRequestHeaders::kContentType, head.mime_type.c_str()));
+ }
+ client_->OnReceiveResponse(head);
+ client_->OnStartLoadingResponseBody(std::move(pipe.consumer_handle));
-private:
- ~URLRequestResourceBundleJob() override {}
+ uint32_t write_size = data->size();
+ MojoResult result = pipe.producer_handle->WriteData(data->front(), &write_size, MOJO_WRITE_DATA_FLAG_NONE);
+ OnFileWritten(result);
+ }
- void OnMimeTypeRead(std::string *out_mime_type, std::string *charset, scoped_refptr<base::RefCountedMemory> data,
- std::string *read_mime_type, net::CompletionOnceCallback callback, bool read_result)
+ void OnConnectionError()
{
- response_info_.headers->AddHeader(
- base::StringPrintf("%s: %s", net::HttpRequestHeaders::kContentType, read_mime_type->c_str()));
- *out_mime_type = *read_mime_type;
- DetermineCharset(*read_mime_type, data.get(), charset);
- int result = read_result ? net::OK : net::ERR_INVALID_URL;
- std::move(callback).Run(result);
+ client_.reset();
+ MaybeDeleteSelf();
}
- // We need the filename of the resource to determine the mime type.
- base::FilePath filename_;
+ void OnBindingError()
+ {
+ binding_.Close();
+ MaybeDeleteSelf();
+ }
- // The resource to load.
- int resource_id_;
+ void MaybeDeleteSelf()
+ {
+ if (!binding_.is_bound() && !client_.is_bound())
+ delete this;
+ }
- net::HttpResponseInfo response_info_;
+ void OnFileWritten(MojoResult result)
+ {
+ // All the data has been written now. The consumer will be notified that
+ // there will be no more data to read from now.
+ if (result == MOJO_RESULT_OK)
+ client_->OnComplete(network::URLLoaderCompletionStatus(net::OK));
+ else
+ client_->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED));
+ client_.reset();
+ MaybeDeleteSelf();
+ }
- mutable base::WeakPtrFactory<URLRequestResourceBundleJob> weak_factory_;
+ mojo::Binding<network::mojom::URLLoader> binding_;
+ network::mojom::URLLoaderClientPtr client_;
+ scoped_refptr<net::HttpResponseHeaders> response_headers_;
+ base::WeakPtrFactory<ResourceBundleFileLoader> weak_factory_{ this };
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceBundleFileLoader);
};
} // namespace
@@ -235,38 +335,6 @@ bool ExtensionsBrowserClientQt::CanExtensionCrossIncognito(const Extension *exte
return false;
}
-net::URLRequestJob *ExtensionsBrowserClientQt::MaybeCreateResourceBundleRequestJob(net::URLRequest *request,
- net::NetworkDelegate *network_delegate,
- const base::FilePath &directory_path,
- const std::string &content_security_policy,
- bool send_cors_header)
-{
- base::FilePath resources_path;
- base::FilePath relative_path;
- // Try to load extension resources from chrome resource file if
- // directory_path is a descendant of resources_path. resources_path
- // corresponds to src/chrome/browser/resources in source tree.
- if (base::PathService::Get(base::DIR_QT_LIBRARY_DATA, &resources_path) &&
- // Since component extension resources are included in
- // component_extension_resources.pak file in resources_path, calculate
- // extension relative path against resources_path.
- resources_path.AppendRelativePath(directory_path, &relative_path)) {
- base::FilePath request_path = extensions::file_util::ExtensionURLToRelativeFilePath(request->url());
- int resource_id = 0;
- if (GetComponentExtensionResourceManager()->IsComponentExtensionResource(directory_path, request_path, &resource_id)) {
- relative_path = relative_path.Append(request_path);
- relative_path = relative_path.NormalizePathSeparators();
- return new URLRequestResourceBundleJob(request,
- network_delegate,
- relative_path,
- resource_id,
- content_security_policy,
- send_cors_header);
- }
- }
- return nullptr;
-}
-
// Return the resource relative path and id for the given request.
base::FilePath ExtensionsBrowserClientQt::GetBundleResourcePath(const network::ResourceRequest &request,
const base::FilePath &extension_resources_path,
@@ -300,14 +368,15 @@ base::FilePath ExtensionsBrowserClientQt::GetBundleResourcePath(const network::R
// Creates and starts a URLLoader to load an extension resource from the
// embedder's resource bundle (.pak) files. Used for component extensions.
void ExtensionsBrowserClientQt::LoadResourceFromResourceBundle(const network::ResourceRequest &request,
- network::mojom::URLLoaderRequest loader,
+ mojo::PendingReceiver<network::mojom::URLLoader> loader,
const base::FilePath &resource_relative_path,
int resource_id,
const std::string &content_security_policy,
- network::mojom::URLLoaderClientPtr client,
+ mojo::PendingRemote<network::mojom::URLLoaderClient> client,
bool send_cors_header)
{
- NOTIMPLEMENTED();
+ ResourceBundleFileLoader::CreateAndStart(request, std::move(loader), std::move(client), resource_relative_path,
+ resource_id, content_security_policy, send_cors_header);
}
@@ -395,6 +464,18 @@ void ExtensionsBrowserClientQt::RegisterExtensionInterfaces(service_manager::Bin
RegisterInterfacesForExtension(registry, render_frame_host, extension);
}
+void ExtensionsBrowserClientQt::RegisterBrowserInterfaceBindersForFrame(
+ service_manager::BinderMapWithContext<content::RenderFrameHost*> *binder_map,
+ content::RenderFrameHost* render_frame_host,
+ const Extension* extension) const
+{
+ PopulateExtensionFrameBinders(binder_map, render_frame_host, extension);
+
+ // FIXME Do we need something from here?
+ // PopulateChromeFrameBindersForExtension(binder_map, render_frame_host,
+ // extension);
+}
+
std::unique_ptr<RuntimeAPIDelegate> ExtensionsBrowserClientQt::CreateRuntimeAPIDelegate(content::BrowserContext *context) const
{
// TODO(extensions): Implement to support Apps.
@@ -409,7 +490,7 @@ const ComponentExtensionResourceManager *ExtensionsBrowserClientQt::GetComponent
void ExtensionsBrowserClientQt::BroadcastEventToRenderers(events::HistogramValue histogram_value,
const std::string &event_name,
- std::unique_ptr<base::ListValue> args)
+ std::unique_ptr<base::ListValue> args, bool dispatch_to_off_the_record_profiles)
{
NOTIMPLEMENTED();
// TODO : do the event routing