Commit f108f025 authored by Jeffrey Kardatzke's avatar Jeffrey Kardatzke Committed by Commit Bot

Reland: Add ash D-Bus framework & service for opening URLs with Chrome

This adds a small D-Bus service framework to ash and then adds an
initial service that has one call "OpenUrl" which will then
open a new tab in Chrome with that URL. This is intended to be used by
Chrome OS clients that want to open a URL with Chrome; initial usage
will be from VMs.

Relanding crrev.com/c/998081, fixed missing D-Bus .conf file
TBR=stevenjb@chromium.org,dominickn@chromium.org,hashimoto@chromium.org,mkwst@chromium.org

Bug: 822496
Bug: 831333
Test: Verified with dbus-send that links open properly
Change-Id: I5e6d9c716ef6da88b184e8e05582825d9547946e
Reviewed-on: https://chromium-review.googlesource.com/1014424
Commit-Queue: Jeffrey Kardatzke <jkardatzke@google.com>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarDan Erat <derat@chromium.org>
Cr-Commit-Position: refs/heads/master@{#551383}
parent a42a629f
......@@ -104,6 +104,10 @@ component("ash") {
"cancel_mode.h",
"cast_config_controller.cc",
"cast_config_controller.h",
"dbus/ash_dbus_services.cc",
"dbus/ash_dbus_services.h",
"dbus/url_handler_service_provider.cc",
"dbus/url_handler_service_provider.h",
"debug.cc",
"debug.h",
"detachable_base/detachable_base_handler.cc",
......@@ -1256,6 +1260,7 @@ component("ash") {
data_deps = [
"//ash/components/autoclick:autoclick_app",
"//ash/components/touch_hud:touch_hud_app",
":dbus_service_files",
]
# Usage of content should be in ash_content_unittests.
......@@ -1407,6 +1412,15 @@ static_library("ash_shell_lib_with_content") {
]
}
copy("dbus_service_files") {
sources = [
"dbus/org.chromium.UrlHandlerService.conf",
]
outputs = [
"$root_out_dir/dbus/{{source_file_part}}",
]
}
# This target is intended for tests that use content. In general very few tests
# need or use content and should be placed in |ash_unittests| instead.
test("ash_content_unittests") {
......
......@@ -66,6 +66,7 @@ include_rules = [
"+chromeos/dbus/power_manager",
"+chromeos/dbus/power_manager_client.h",
"+chromeos/dbus/power_policy_controller.h",
"+chromeos/dbus/services/cros_dbus_service.h",
"+chromeos/dbus/session_manager_client.h",
"+chromeos/dbus/shill_device_client.h",
"+chromeos/dbus/system_clock_client.h",
......
include_rules = [
"+dbus",
]
// Copyright 2018 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 "ash/dbus/ash_dbus_services.h"
#include "ash/dbus/url_handler_service_provider.h"
#include "ash/public/cpp/config.h"
#include "ash/shell.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/services/cros_dbus_service.h"
#include "chromeos/dbus/session_manager_client.h"
#include "dbus/object_path.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace ash {
AshDBusServices::AshDBusServices() {
// TODO(stevenjb): Figure out where else the D-Bus thread is getting
// initialized and then always init it here when we have the MASH
// config after the contention is sorted out.
if (!chromeos::DBusThreadManager::IsInitialized()) {
chromeos::DBusThreadManager::Initialize(
chromeos::DBusThreadManager::kShared);
initialized_dbus_thread_ = true;
}
url_handler_service_ = chromeos::CrosDBusService::Create(
chromeos::kUrlHandlerServiceName,
dbus::ObjectPath(chromeos::kUrlHandlerServicePath),
chromeos::CrosDBusService::CreateServiceProviderList(
std::make_unique<UrlHandlerServiceProvider>()));
}
void AshDBusServices::EmitAshInitialized() {
chromeos::DBusThreadManager::Get()
->GetSessionManagerClient()
->EmitAshInitialized();
}
AshDBusServices::~AshDBusServices() {
url_handler_service_.reset();
if (initialized_dbus_thread_) {
chromeos::DBusThreadManager::Shutdown();
}
}
} // namespace ash
// Copyright 2018 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.
#ifndef ASH_DBUS_ASH_DBUS_SERVICES_H_
#define ASH_DBUS_ASH_DBUS_SERVICES_H_
#include <memory>
#include "base/macros.h"
namespace chromeos {
class CrosDBusService;
} // namespace chromeos
namespace ash {
// Handles starting/stopping the D-Bus thread for ash services and also
// manages the liftime of the ash D-Bus services.
class AshDBusServices {
public:
AshDBusServices();
~AshDBusServices();
// Emit ash-initialized upstart signal to start Chrome OS tasks that expect
// that ash is listening to D-Bus signals they emit.
void EmitAshInitialized();
private:
bool initialized_dbus_thread_{false};
std::unique_ptr<chromeos::CrosDBusService> url_handler_service_;
DISALLOW_COPY_AND_ASSIGN(AshDBusServices);
};
} // namespace ash
#endif // ASH_DBUS_ASH_DBUS_SERVICES_H_
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<!--
Copyright 2018 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.
-->
<busconfig>
<policy user="chronos">
<allow own="org.chromium.UrlHandlerService"/>
</policy>
<policy user="crosvm">
<!-- methods allowed -->
<allow send_destination="org.chromium.UrlHandlerService"
send_interface="org.chromium.UrlHandlerServiceInterface"
send_member="OpenUrl"/>
</policy>
</busconfig>
// Copyright 2018 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 "ash/dbus/url_handler_service_provider.h"
#include <utility>
#include "ash/new_window_controller.h"
#include "ash/shell.h"
#include "base/bind.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "extensions/common/constants.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "url/gurl.h"
#include "url/url_constants.h"
namespace ash {
namespace {
constexpr const char* kUrlSchemes[] = {url::kFtpScheme, url::kHttpScheme,
url::kHttpsScheme, url::kMailToScheme};
// Called from ExportedObject when OpenUrl() is exported as a D-Bus method or
// failed to be exported.
void OnExported(const std::string& interface_name,
const std::string& method_name,
bool success) {
if (!success) {
LOG(ERROR) << "Failed to export " << interface_name << "." << method_name;
}
}
} // namespace
UrlHandlerServiceProvider::UrlHandlerServiceProvider()
: allowed_url_schemes_(std::cbegin(kUrlSchemes), std::cend(kUrlSchemes)),
weak_ptr_factory_(this) {}
UrlHandlerServiceProvider::~UrlHandlerServiceProvider() = default;
void UrlHandlerServiceProvider::Start(
scoped_refptr<dbus::ExportedObject> exported_object) {
exported_object->ExportMethod(
chromeos::kUrlHandlerServiceInterface,
chromeos::kUrlHandlerServiceOpenUrlMethod,
base::BindRepeating(&UrlHandlerServiceProvider::OpenUrl,
weak_ptr_factory_.GetWeakPtr()),
base::BindRepeating(&OnExported));
}
void UrlHandlerServiceProvider::OpenUrl(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
dbus::MessageReader reader(method_call);
std::string url;
if (!reader.PopString(&url)) {
LOG(ERROR) << "Method call lacks URL: " << method_call->ToString();
response_sender.Run(dbus::ErrorResponse::FromMethodCall(
method_call, DBUS_ERROR_INVALID_ARGS, "No URL string arg"));
return;
}
const GURL gurl(url);
if (!gurl.is_valid() ||
allowed_url_schemes_.find(gurl.scheme()) == allowed_url_schemes_.end()) {
response_sender.Run(dbus::ErrorResponse::FromMethodCall(
method_call, DBUS_ERROR_FAILED, "Invalid URL"));
return;
}
ash::Shell::Get()->new_window_controller()->NewTabWithUrl(gurl);
response_sender.Run(dbus::Response::FromMethodCall(method_call));
}
} // namespace ash
// Copyright 2018 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.
#ifndef ASH_DBUS_URL_HANDLER_SERVICE_PROVIDER_H_
#define ASH_DBUS_URL_HANDLER_SERVICE_PROVIDER_H_
#include <memory>
#include <set>
#include <string>
#include "ash/ash_export.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/dbus/services/cros_dbus_service.h"
#include "dbus/exported_object.h"
namespace dbus {
class MethodCall;
}
namespace ash {
// This class exports D-Bus methods for asking Chrome to open a URL.
//
// OpenUrl:
// % dbus-send --system --type=method_call --print-reply
// --dest=org.chromium.UrlHandlerService
// /org/chromium/UrlHandlerService
// org.chromium.UrlHandlerServiceInterface.OpenUrl
// "string:|url|"
//
// % (returns true on success, otherwise returns false)
class ASH_EXPORT UrlHandlerServiceProvider
: public chromeos::CrosDBusService::ServiceProviderInterface {
public:
UrlHandlerServiceProvider();
~UrlHandlerServiceProvider() override;
// CrosDBusService::ServiceProviderInterface overrides:
void Start(scoped_refptr<dbus::ExportedObject> exported_object) override;
private:
// Called on UI thread in response to a D-Bus request.
void OpenUrl(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Schemes that we allow to be sent via OpenUrl.
const std::set<std::string> allowed_url_schemes_;
// Keep this last so that all weak pointers will be invalidated at the
// beginning of destruction.
base::WeakPtrFactory<UrlHandlerServiceProvider> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(UrlHandlerServiceProvider);
};
} // namespace ash
#endif // ASH_DBUS_URL_HANDLER_SERVICE_PROVIDER_H_
......@@ -29,6 +29,11 @@ void NewWindowController::ShowKeyboardOverlay() {
client_->ShowKeyboardOverlay();
}
void NewWindowController::NewTabWithUrl(const GURL& url) {
if (client_)
client_->NewTabWithUrl(url);
}
void NewWindowController::NewTab() {
if (client_)
client_->NewTab();
......
......@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "url/gurl.h"
namespace ash {
......@@ -26,6 +27,7 @@ class ASH_EXPORT NewWindowController : public mojom::NewWindowController {
// NewWindowController:
void SetClient(mojom::NewWindowClientAssociatedPtrInfo client) override;
void ShowKeyboardOverlay() override;
void NewTabWithUrl(const GURL& url) override;
// Pass throughs for methods of the same name on |client_|.
void NewTab();
......
......@@ -4,6 +4,9 @@
module ash.mojom;
// For GURL.
import "url/mojom/url.mojom";
// An exported object in ash which lets an ash consumer set a client interface.
interface NewWindowController {
SetClient(associated NewWindowClient client);
......@@ -13,6 +16,9 @@ interface NewWindowController {
// Shows the keyboard shortcut overlay. TODO(mash): this calls the client
// function of the same name below, but it should be implemented inside ash.
ShowKeyboardOverlay();
// Opens a new tab with the specified URL.
NewTabWithUrl(url.mojom.Url url);
};
// A delegate interface that an ash user sends to ash to handle certain window
......@@ -21,6 +27,9 @@ interface NewWindowClient {
// Invoked when the user uses Ctrl+T to open a new tab.
NewTab();
// Opens a new tab with the specified URL.
NewTabWithUrl(url.mojom.Url url);
// Invoked when the user uses Ctrl-N or Ctrl-Shift-N to open a new window.
NewWindow(bool incognito);
......
......@@ -22,6 +22,7 @@
#include "ash/assistant/ash_assistant_controller.h"
#include "ash/autoclick/autoclick_controller.h"
#include "ash/cast_config_controller.h"
#include "ash/dbus/ash_dbus_services.h"
#include "ash/detachable_base/detachable_base_handler.h"
#include "ash/detachable_base/detachable_base_notification_controller.h"
#include "ash/display/ash_display_controller.h"
......@@ -155,7 +156,6 @@
#include "base/trace_event/trace_event.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power_policy_controller.h"
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/system/devicemode.h"
#include "components/exo/file_helper.h"
#include "components/prefs/pref_registry_simple.h"
......@@ -1238,6 +1238,8 @@ void Shell::Init(ui::ContextFactory* context_factory,
user_metrics_recorder_->OnShellInitialized();
// Initialize the D-Bus thread and services for ash.
ash_dbus_services_ = std::make_unique<AshDBusServices>();
// By this point ash shell should have initialized its D-Bus signal
// listeners, so emit ash-initialized upstart signal to start Chrome OS tasks
// that expect that ash is listening to D-Bus signals they emit. For example,
......@@ -1245,9 +1247,8 @@ void Shell::Init(ui::ContextFactory* context_factory,
// purely by emitting D-Bus signals, and thus has to be run whenever ash is
// started so ash (DetachableBaseHandler in particular) gets the proper view
// of the current detachable base state.
chromeos::DBusThreadManager::Get()
->GetSessionManagerClient()
->EmitAshInitialized();
// TODO(stevenjb): Move this and other D-Bus dependencies to AshDBusServices.
ash_dbus_services_->EmitAshInitialized();
}
void Shell::InitializeDisplayManager() {
......
......@@ -85,6 +85,7 @@ class AccessibilityController;
class AccessibilityDelegate;
class AccessibilityFocusRingController;
class AshAssistantController;
class AshDBusServices;
class AshDisplayController;
class AppListControllerImpl;
class NativeCursorManagerAsh;
......@@ -687,6 +688,7 @@ class ASH_EXPORT Shell : public SessionObserver,
accessibility_focus_ring_controller_;
std::unique_ptr<AppListControllerImpl> app_list_controller_;
std::unique_ptr<AshAssistantController> ash_assistant_controller_;
std::unique_ptr<AshDBusServices> ash_dbus_services_;
std::unique_ptr<AshDisplayController> ash_display_controller_;
std::unique_ptr<BacklightsForcedOffSetter> backlights_forced_off_setter_;
std::unique_ptr<BrightnessControlDelegate> brightness_control_delegate_;
......
......@@ -19,6 +19,8 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/extensions/app_launch_params.h"
......@@ -28,6 +30,7 @@
#include "chrome/common/url_constants.h"
#include "components/sessions/core/tab_restore_service.h"
#include "components/sessions/core/tab_restore_service_observer.h"
#include "components/url_formatter/url_fixer.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/service_manager_connection.h"
#include "extensions/browser/extension_system.h"
......@@ -139,6 +142,14 @@ void ChromeNewWindowClient::NewTab() {
browser->SetFocusToLocationBar(false);
}
void ChromeNewWindowClient::NewTabWithUrl(const GURL& url) {
NavigateParams navigate_params(
ProfileManager::GetActiveUserProfile(), url,
ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
ui::PAGE_TRANSITION_FROM_API));
Navigate(&navigate_params);
}
void ChromeNewWindowClient::NewWindow(bool is_incognito) {
if (is_incognito && !IsIncognitoAllowed())
return;
......
......@@ -10,6 +10,7 @@
#include "ash/public/interfaces/new_window.mojom.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "url/gurl.h"
class ChromeNewWindowClient : public ash::mojom::NewWindowClient {
public:
......@@ -20,6 +21,7 @@ class ChromeNewWindowClient : public ash::mojom::NewWindowClient {
// Overridden from ash::mojom::NewWindowClient:
void NewTab() override;
void NewTabWithUrl(const GURL& url) override;
void NewWindow(bool incognito) override;
void OpenFileManager() override;
void OpenCrosh() override;
......
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