// Copyright 2019 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/public/browser/device_service.h" #include "base/memory/scoped_refptr.h" #include "base/task/single_thread_task_runner.h" #include "base/task/thread_pool.h" #include "base/threading/sequence_local_storage_slot.h" #include "build/build_config.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/network_service_instance.h" #include "content/public/common/content_client.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/device/device_service.h" #include "services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h" #include "services/network/public/mojom/network_service_test.mojom.h" #include "services/network/public/mojom/url_loader.mojom.h" #if BUILDFLAG(IS_ANDROID) #include "base/android/jni_android.h" #include "base/android/scoped_java_ref.h" #include "content/browser/wake_lock/wake_lock_context_host.h" #include "content/public/android/content_jni_headers/ContentNfcDelegate_jni.h" #endif namespace content { namespace { // SharedURLLoaderFactory for device service, backed by // GetContentClient()->browser()->GetSystemSharedURLLoaderFactory(). class DeviceServiceURLLoaderFactory : public network::SharedURLLoaderFactory { public: DeviceServiceURLLoaderFactory() = default; DeviceServiceURLLoaderFactory(const DeviceServiceURLLoaderFactory&) = delete; DeviceServiceURLLoaderFactory& operator=( const DeviceServiceURLLoaderFactory&) = delete; // mojom::URLLoaderFactory implementation: void CreateLoaderAndStart( mojo::PendingReceiver receiver, int32_t request_id, uint32_t options, const network::ResourceRequest& url_request, mojo::PendingRemote client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) override { auto factory = GetContentClient()->browser()->GetSystemSharedURLLoaderFactory(); if (!factory) return; factory->CreateLoaderAndStart(std::move(receiver), request_id, options, url_request, std::move(client), traffic_annotation); } // SharedURLLoaderFactory implementation: void Clone(mojo::PendingReceiver receiver) override { GetContentClient()->browser()->GetSystemSharedURLLoaderFactory()->Clone( std::move(receiver)); } std::unique_ptr Clone() override { return std::make_unique( this); } private: friend class base::RefCounted; ~DeviceServiceURLLoaderFactory() override = default; }; void BindDeviceServiceReceiver( mojo::PendingReceiver receiver) { // Bind the lifetime of the service instance to that of the sequence it's // running on. static base::SequenceLocalStorageSlot> service_slot; auto& service = service_slot.GetOrCreateValue(); if (service) { service->AddReceiver(std::move(receiver)); return; } auto params = std::make_unique(); // This task runner may be used by some device service implementation bits // to interface with dbus client code, which in turn imposes some subtle // thread affinity on the clients. We therefore require a single-thread // runner. params->file_task_runner = base::ThreadPool::CreateSingleThreadTaskRunner( {base::MayBlock(), base::TaskPriority::BEST_EFFORT}); params->io_task_runner = GetIOThreadTaskRunner({}); params->url_loader_factory = base::MakeRefCounted(); params->network_connection_tracker = content::GetNetworkConnectionTracker(); params->geolocation_api_key = GetContentClient()->browser()->GetGeolocationApiKey(); params->custom_location_provider_callback = base::BindRepeating(&ContentBrowserClient::OverrideSystemLocationProvider, base::Unretained(GetContentClient()->browser())); params->geolocation_manager = GetContentClient()->browser()->GetGeolocationManager(); #if BUILDFLAG(IS_ANDROID) JNIEnv* env = base::android::AttachCurrentThread(); params->java_nfc_delegate = Java_ContentNfcDelegate_create(env); DCHECK(!params->java_nfc_delegate.is_null()); params->wake_lock_context_callback = base::BindRepeating(&WakeLockContextHost::GetNativeViewForContext); params->use_gms_core_location_provider = GetContentClient()->browser()->ShouldUseGmsCoreGeolocationProvider(); #endif service = device::CreateDeviceService(std::move(params), std::move(receiver)); } } // namespace device::mojom::DeviceService& GetDeviceService() { static base::SequenceLocalStorageSlot< mojo::Remote> remote_slot; mojo::Remote& remote = remote_slot.GetOrCreateValue(); if (!remote) { // This may be called very early in startup, too early for some Device // Service initialization steps (for example, in browser test environments, // the Device Service's connection to the Network Service could deadlock). // We post a task to defer until the main message loop has started, when // initialization is reliably safe. GetUIThreadTaskRunner({})->PostTask( FROM_HERE, base::BindOnce(&BindDeviceServiceReceiver, remote.BindNewPipeAndPassReceiver())); } return *remote.get(); } } // namespace content