summaryrefslogtreecommitdiffstats
path: root/src/core/extensions/extension_system_qt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/extensions/extension_system_qt.cpp')
-rw-r--r--src/core/extensions/extension_system_qt.cpp447
1 files changed, 447 insertions, 0 deletions
diff --git a/src/core/extensions/extension_system_qt.cpp b/src/core/extensions/extension_system_qt.cpp
new file mode 100644
index 000000000..4ca407421
--- /dev/null
+++ b/src/core/extensions/extension_system_qt.cpp
@@ -0,0 +1,447 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extension_system_qt.h"
+
+#include <algorithm>
+
+#include "base/base_paths.h"
+#include "base/base_switches.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/json/json_string_value_serializer.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
+#include "base/path_service.h"
+#include "base/strings/string_tokenizer.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
+#include "components/crx_file/id_util.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/plugin_service.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/url_data_source.h"
+#include "content/public/common/webplugininfo.h"
+#include "extensions/browser/content_verifier.h"
+#include "extensions/browser/content_verifier_delegate.h"
+#include "extensions/browser/extension_pref_store.h"
+#include "extensions/browser/extension_pref_value_map.h"
+#include "extensions/browser/extension_pref_value_map_factory.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/info_map.h"
+#include "extensions/browser/notification_types.h"
+#include "extensions/browser/null_app_sorting.h"
+#include "extensions/browser/quota_service.h"
+#include "extensions/browser/renderer_startup_helper.h"
+#include "extensions/browser/runtime_data.h"
+#include "extensions/browser/shared_user_script_master.h"
+#include "extensions/browser/service_worker_manager.h"
+#include "extensions/browser/value_store/value_store_factory_impl.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/extension_messages.h"
+#include "extensions/common/manifest_constants.h"
+#include "extensions/common/manifest_handlers/mime_types_handler.h"
+#include "extensions/common/manifest_url_handlers.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "chrome/grit/component_extension_resources.h"
+#include "chrome/grit/browser_resources.h"
+#include "net/base/mime_util.h"
+
+using content::BrowserThread;
+
+namespace extensions {
+
+namespace {
+
+std::string GenerateId(const base::DictionaryValue *manifest,
+ const base::FilePath &path)
+{
+ std::string raw_key;
+ std::string id_input;
+ CHECK(manifest->GetString(manifest_keys::kPublicKey, &raw_key));
+ CHECK(Extension::ParsePEMKeyBytes(raw_key, &id_input));
+ std::string id = crx_file::id_util::GenerateId(id_input);
+ return id;
+}
+
+// Implementation based on ComponentLoader::ParseManifest.
+std::unique_ptr<base::DictionaryValue> ParseManifest(const std::string &manifest_contents)
+{
+ JSONStringValueDeserializer deserializer(manifest_contents);
+ std::unique_ptr<base::Value> manifest(deserializer.Deserialize(NULL, NULL));
+
+ if (!manifest.get() || !manifest->is_dict()) {
+ LOG(ERROR) << "Failed to parse extension manifest.";
+ return NULL;
+ }
+ // Transfer ownership to the caller.
+ return base::DictionaryValue::From(std::move(manifest));
+}
+
+} // namespace
+
+// Dummy Content Verifier Delegate. Added to prevent crashes.
+class ContentVerifierDelegateQt
+ : public ContentVerifierDelegate {
+ public:
+ ~ContentVerifierDelegateQt() override {}
+
+ // This should return what verification mode is appropriate for the given
+ // extension, if any.
+ Mode ShouldBeVerified(const Extension& extension) override {
+ return NONE;
+ }
+
+ // Should return the public key to use for validating signatures via the two
+ // out parameters.
+ ContentVerifierKey GetPublicKey() override {
+ return ContentVerifierKey();
+ }
+ // This should return a URL that can be used to fetch the
+ // verified_contents.json containing signatures for the given extension
+ // id/version pair.
+ GURL GetSignatureFetchUrl(const std::string& extension_id,
+ const base::Version& version) override {
+ return GURL();
+ }
+
+ // This should return the set of file paths for images used within the
+ // browser process. (These may get transcoded during the install process).
+ std::set<base::FilePath> GetBrowserImagePaths(
+ const extensions::Extension* extension) override {
+ return std::set<base::FilePath>();
+ }
+
+ // Called when the content verifier detects that a read of a file inside
+ // an extension did not match its expected hash.
+ void VerifyFailed(const std::string& extension_id,
+ ContentVerifyJob::FailureReason reason) override {
+
+ }
+
+ // Called when ExtensionSystem is shutting down.
+ void Shutdown() override {
+
+ }
+};
+
+void ExtensionSystemQt::LoadExtension(std::string extension_id, std::unique_ptr<base::DictionaryValue> manifest, const base::FilePath &directory)
+{
+ int flags = Extension::REQUIRE_KEY;
+ std::string error;
+ scoped_refptr<const Extension> extension = Extension::Create(
+ directory,
+ Manifest::COMPONENT,
+ *manifest,
+ flags,
+ &error);
+ if (!extension.get())
+ LOG(ERROR) << error;
+
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::Bind(&InfoMap::AddExtension,
+ base::Unretained(info_map()),
+ base::RetainedRef(extension),
+ base::Time::Now(),
+ true,
+ false));
+ extension_registry_->AddEnabled(extension.get());
+
+ NotifyExtensionLoaded(extension.get());
+}
+
+void ExtensionSystemQt::OnExtensionRegisteredWithRequestContexts(scoped_refptr<const extensions::Extension> extension)
+{
+ extension_registry_->AddReady(extension);
+ if (extension_registry_->enabled_extensions().Contains(extension->id()))
+ extension_registry_->TriggerOnReady(extension.get());
+}
+
+// Implementation based on ExtensionService::NotifyExtensionLoaded.
+void ExtensionSystemQt::NotifyExtensionLoaded(const Extension *extension)
+{
+ // The URLRequestContexts need to be first to know that the extension
+ // was loaded, otherwise a race can arise where a renderer that is created
+ // for the extension may try to load an extension URL with an extension id
+ // that the request context doesn't yet know about. The profile is responsible
+ // for ensuring its URLRequestContexts appropriately discover the loaded
+ // extension.
+ RegisterExtensionWithRequestContexts(
+ extension,
+ base::Bind(&ExtensionSystemQt::OnExtensionRegisteredWithRequestContexts,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::WrapRefCounted(extension)));
+
+ // Tell renderers about the loaded extension.
+ renderer_helper_->OnExtensionLoaded(*extension);
+
+ // Tell subsystems that use the ExtensionRegistryObserver::OnExtensionLoaded
+ // about the new extension.
+ //
+ // NOTE: It is important that this happen after notifying the renderers about
+ // the new extensions so that if we navigate to an extension URL in
+ // ExtensionRegistryObserver::OnExtensionLoaded the renderer is guaranteed to
+ // know about it.
+ extension_registry_->TriggerOnLoaded(extension);
+
+ // Register plugins included with the extension.
+ // Implementation based on PluginManager::OnExtensionLoaded.
+ const MimeTypesHandler *handler = MimeTypesHandler::GetHandler(extension);
+ if (handler && !handler->handler_url().empty()) {
+ content::WebPluginInfo info;
+ info.type = content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN;
+ info.name = base::UTF8ToUTF16(extension->name());
+ info.path = base::FilePath::FromUTF8Unsafe(extension->url().spec());
+ for (std::set<std::string>::const_iterator mime_type = handler->mime_type_set().begin();
+ mime_type != handler->mime_type_set().end(); ++mime_type) {
+ content::WebPluginMimeType mime_type_info;
+ mime_type_info.mime_type = *mime_type;
+ base::FilePath::StringType file_extension;
+ if (net::GetPreferredExtensionForMimeType(*mime_type, &file_extension)) {
+ mime_type_info.file_extensions.push_back(
+ base::FilePath(file_extension).AsUTF8Unsafe());
+ }
+ info.mime_types.push_back(mime_type_info);
+ }
+ content::PluginService *plugin_service =
+ content::PluginService::GetInstance();
+ plugin_service->RefreshPlugins();
+ plugin_service->RegisterInternalPlugin(info, true);
+ }
+}
+
+bool ExtensionSystemQt::FinishDelayedInstallationIfReady(const std::string &extension_id, bool install_immediately)
+{
+ // TODO mibrunin
+ return false;
+}
+
+void ExtensionSystemQt::Shutdown()
+{
+ if (content_verifier_.get())
+ content_verifier_->Shutdown();
+}
+
+ServiceWorkerManager *ExtensionSystemQt::service_worker_manager()
+{
+ return service_worker_manager_.get();
+}
+
+ExtensionService *ExtensionSystemQt::extension_service()
+{
+ return nullptr;
+}
+
+RuntimeData *ExtensionSystemQt::runtime_data()
+{
+ return runtime_data_.get();
+}
+
+ManagementPolicy *ExtensionSystemQt::management_policy()
+{
+ return nullptr;
+}
+
+SharedUserScriptMaster *ExtensionSystemQt::shared_user_script_master()
+{
+ return shared_user_script_master_.get();
+}
+
+StateStore *ExtensionSystemQt::state_store()
+{
+ return nullptr;
+}
+
+StateStore *ExtensionSystemQt::rules_store()
+{
+ return nullptr;
+}
+
+scoped_refptr<ValueStoreFactory> ExtensionSystemQt::store_factory()
+{
+ return store_factory_;
+}
+
+InfoMap *ExtensionSystemQt::info_map()
+{
+ if (!info_map_.get())
+ info_map_ = new InfoMap;
+ return info_map_.get();
+}
+
+QuotaService *ExtensionSystemQt::quota_service()
+{
+ return quota_service_.get();
+}
+
+AppSorting *ExtensionSystemQt::app_sorting()
+{
+ return app_sorting_.get();
+}
+
+ContentVerifier *ExtensionSystemQt::content_verifier()
+{
+ if (!content_verifier_.get()) {
+ content_verifier_ = new ContentVerifier(browser_context_, std::make_unique<ContentVerifierDelegateQt>());
+ }
+ return content_verifier_.get();
+}
+
+ExtensionSystemQt::ExtensionSystemQt(content::BrowserContext *browserContext)
+ : browser_context_(browserContext)
+ , store_factory_(new ValueStoreFactoryImpl(browserContext->GetPath()))
+ , extension_registry_(ExtensionRegistry::Get(browserContext))
+ , renderer_helper_(extensions::RendererStartupHelperFactory::GetForBrowserContext(browserContext))
+ , initialized_(false)
+ , weak_ptr_factory_(this)
+{
+}
+
+ExtensionSystemQt::~ExtensionSystemQt()
+{
+}
+
+void ExtensionSystemQt::Init(bool extensions_enabled)
+{
+ if (initialized_)
+ return;
+
+ initialized_ = true;
+
+ service_worker_manager_.reset(new ServiceWorkerManager(browser_context_));
+ runtime_data_.reset(new RuntimeData(extension_registry_));
+ quota_service_.reset(new QuotaService);
+ app_sorting_.reset(new NullAppSorting);
+
+ shared_user_script_master_ =
+ std::make_unique<SharedUserScriptMaster>(browser_context_);
+
+ // Make the chrome://extension-icon/ resource available.
+ // content::URLDataSource::Add(browser_context_, new ExtensionIconSource(browser_context_));
+
+ if (extensions_enabled) {
+ // Inform the rest of the extensions system to start.
+ ready_.Signal();
+ content::NotificationService::current()->Notify(
+ NOTIFICATION_EXTENSIONS_READY_DEPRECATED,
+ content::Source<content::BrowserContext>(browser_context_),
+ content::NotificationService::NoDetails());
+
+ std::string pdf_manifest = ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_PDF_MANIFEST).as_string();
+ base::ReplaceFirstSubstringAfterOffset(&pdf_manifest, 0, "<NAME>", "chromium-pdf");
+
+ std::unique_ptr<base::DictionaryValue> pdfManifestDict = ParseManifest(pdf_manifest);
+ base::FilePath path;
+ base::PathService::Get(base::DIR_QT_LIBRARY_DATA, &path);
+ path = path.Append(base::FilePath(FILE_PATH_LITERAL("pdf")));
+ std::string id = GenerateId(pdfManifestDict.get(), path);
+ LoadExtension(id, std::move(pdfManifestDict), path);
+ }
+}
+
+void ExtensionSystemQt::InitForRegularProfile(bool extensions_enabled)
+{
+ if (initialized_)
+ return; // Already initialized.
+ // The InfoMap needs to be created before the ProcessManager.
+ info_map();
+
+ Init(extensions_enabled);
+}
+
+void ExtensionSystemQt::InitForIncognitoProfile()
+{
+ NOTIMPLEMENTED();
+}
+
+std::unique_ptr<ExtensionSet> ExtensionSystemQt::GetDependentExtensions(const Extension *extension)
+{
+ return base::WrapUnique(new ExtensionSet());
+}
+
+#if !defined(TOOLKIT_QT)
+void ExtensionSystemQt::InstallUpdate(const std::string &extension_id,
+ const std::string &public_key,
+ const base::FilePath &unpacked_dir,
+ bool install_immediately,
+ InstallUpdateCallback install_update_callback)
+{
+ NOTREACHED() << "Not yet implemented";
+ base::DeleteFile(unpacked_dir, true /* recursive */);
+ std::move(install_update_callback).Run(CrxInstallError(CrxInstallErrorType::DECLINED, CrxInstallErrorDetail::DISALLOWED_BY_POLICY));
+}
+#endif
+
+void ExtensionSystemQt::RegisterExtensionWithRequestContexts(const Extension *extension,
+ const base::Closure &callback)
+{
+ base::Time install_time = base::Time::Now();
+
+ bool incognito_enabled = false;
+ bool notifications_disabled = false;
+
+ base::PostTaskWithTraitsAndReply(
+ FROM_HERE, {BrowserThread::IO},
+ base::Bind(&InfoMap::AddExtension, info_map(),
+ base::RetainedRef(extension), install_time, incognito_enabled,
+ notifications_disabled),
+ callback);
+}
+
+void ExtensionSystemQt::UnregisterExtensionWithRequestContexts(const std::string &extension_id,
+ const UnloadedExtensionReason reason)
+{
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::IO},
+ base::Bind(&InfoMap::RemoveExtension, info_map(), extension_id, reason));
+}
+} // namespace extensions