Commit 73b2202e authored by Pavel Feldman's avatar Pavel Feldman Committed by Commit Bot

DevTools: respect permission overrides on the chrome level.

This is a follow up to the content-side change, we need chrome
to respect these overrides as well when the check originates
outside of the web platform.

Bug: 631464
Change-Id: I8300a17d6b2b65140aef8232a58a694e56a709e3
Reviewed-on: https://chromium-review.googlesource.com/c/1308935
Commit-Queue: Pavel Feldman <pfeldman@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#604815}
parent 6d232c64
...@@ -49,6 +49,9 @@ class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate { ...@@ -49,6 +49,9 @@ class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate {
// Resets |device_manager_|. // Resets |device_manager_|.
void ResetAndroidDeviceManagerForTesting(); void ResetAndroidDeviceManagerForTesting();
std::vector<content::BrowserContext*> GetBrowserContexts() override;
content::BrowserContext* GetDefaultBrowserContext() override;
private: private:
friend class DevToolsManagerDelegateTest; friend class DevToolsManagerDelegateTest;
...@@ -62,8 +65,6 @@ class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate { ...@@ -62,8 +65,6 @@ class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate {
std::string GetTargetType(content::WebContents* web_contents) override; std::string GetTargetType(content::WebContents* web_contents) override;
std::string GetTargetTitle(content::WebContents* web_contents) override; std::string GetTargetTitle(content::WebContents* web_contents) override;
std::vector<content::BrowserContext*> GetBrowserContexts() override;
content::BrowserContext* GetDefaultBrowserContext() override;
content::BrowserContext* CreateBrowserContext() override; content::BrowserContext* CreateBrowserContext() override;
void DisposeBrowserContext(content::BrowserContext*, void DisposeBrowserContext(content::BrowserContext*,
DisposeCallback callback) override; DisposeCallback callback) override;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
}, },
{ {
"domain": "Browser", "domain": "Browser",
"include": [ "getWindowForTarget", "getWindowBounds", "setWindowBounds", "close" ], "include": [ "getWindowForTarget", "getWindowBounds", "setWindowBounds", "close", "grantPermissions", "resetPermissions" ],
"include_events": [] "include_events": []
}, },
{ {
......
...@@ -4,8 +4,13 @@ ...@@ -4,8 +4,13 @@
#include "chrome/browser/devtools/protocol/browser_handler.h" #include "chrome/browser/devtools/protocol/browser_handler.h"
#include <set>
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "chrome/browser/devtools/chrome_devtools_manager_delegate.h"
#include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/permissions/permission_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h"
...@@ -14,6 +19,10 @@ ...@@ -14,6 +19,10 @@
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_agent_host.h"
using PermissionOverrides = std::set<content::PermissionType>;
using protocol::Maybe;
using protocol::Response;
namespace { namespace {
BrowserWindow* GetBrowserWindow(int window_id) { BrowserWindow* GetBrowserWindow(int window_id) {
...@@ -48,6 +57,49 @@ std::unique_ptr<protocol::Browser::Bounds> GetBrowserWindowBounds( ...@@ -48,6 +57,49 @@ std::unique_ptr<protocol::Browser::Bounds> GetBrowserWindowBounds(
.Build(); .Build();
} }
Response FromProtocolPermissionType(
const protocol::Browser::PermissionType& type,
content::PermissionType* out_type) {
if (type == protocol::Browser::PermissionTypeEnum::Notifications) {
*out_type = content::PermissionType::NOTIFICATIONS;
} else if (type == protocol::Browser::PermissionTypeEnum::Geolocation) {
*out_type = content::PermissionType::GEOLOCATION;
} else if (type ==
protocol::Browser::PermissionTypeEnum::ProtectedMediaIdentifier) {
*out_type = content::PermissionType::PROTECTED_MEDIA_IDENTIFIER;
} else if (type == protocol::Browser::PermissionTypeEnum::Midi) {
*out_type = content::PermissionType::MIDI;
} else if (type == protocol::Browser::PermissionTypeEnum::MidiSysex) {
*out_type = content::PermissionType::MIDI_SYSEX;
} else if (type == protocol::Browser::PermissionTypeEnum::DurableStorage) {
*out_type = content::PermissionType::DURABLE_STORAGE;
} else if (type == protocol::Browser::PermissionTypeEnum::AudioCapture) {
*out_type = content::PermissionType::AUDIO_CAPTURE;
} else if (type == protocol::Browser::PermissionTypeEnum::VideoCapture) {
*out_type = content::PermissionType::VIDEO_CAPTURE;
} else if (type == protocol::Browser::PermissionTypeEnum::BackgroundSync) {
*out_type = content::PermissionType::BACKGROUND_SYNC;
} else if (type == protocol::Browser::PermissionTypeEnum::Flash) {
*out_type = content::PermissionType::FLASH;
} else if (type == protocol::Browser::PermissionTypeEnum::Sensors) {
*out_type = content::PermissionType::SENSORS;
} else if (type ==
protocol::Browser::PermissionTypeEnum::AccessibilityEvents) {
*out_type = content::PermissionType::ACCESSIBILITY_EVENTS;
} else if (type == protocol::Browser::PermissionTypeEnum::ClipboardRead) {
*out_type = content::PermissionType::CLIPBOARD_READ;
} else if (type == protocol::Browser::PermissionTypeEnum::ClipboardWrite) {
*out_type = content::PermissionType::CLIPBOARD_WRITE;
} else if (type == protocol::Browser::PermissionTypeEnum::PaymentHandler) {
*out_type = content::PermissionType::PAYMENT_HANDLER;
} else if (type == protocol::Browser::PermissionTypeEnum::BackgroundFetch) {
*out_type = content::PermissionType::BACKGROUND_FETCH;
} else {
return Response::InvalidParams("Unknown permission type: " + type);
}
return Response::OK();
}
} // namespace } // namespace
BrowserHandler::BrowserHandler(protocol::UberDispatcher* dispatcher) { BrowserHandler::BrowserHandler(protocol::UberDispatcher* dispatcher) {
...@@ -58,16 +110,16 @@ BrowserHandler::BrowserHandler(protocol::UberDispatcher* dispatcher) { ...@@ -58,16 +110,16 @@ BrowserHandler::BrowserHandler(protocol::UberDispatcher* dispatcher) {
BrowserHandler::~BrowserHandler() = default; BrowserHandler::~BrowserHandler() = default;
protocol::Response BrowserHandler::GetWindowForTarget( Response BrowserHandler::GetWindowForTarget(
const std::string& target_id, const std::string& target_id,
int* out_window_id, int* out_window_id,
std::unique_ptr<protocol::Browser::Bounds>* out_bounds) { std::unique_ptr<protocol::Browser::Bounds>* out_bounds) {
auto host = content::DevToolsAgentHost::GetForId(target_id); auto host = content::DevToolsAgentHost::GetForId(target_id);
if (!host) if (!host)
return protocol::Response::Error("No target with given id"); return Response::Error("No target with given id");
content::WebContents* web_contents = host->GetWebContents(); content::WebContents* web_contents = host->GetWebContents();
if (!web_contents) if (!web_contents)
return protocol::Response::Error("No web contents in the target"); return Response::Error("No web contents in the target");
Browser* browser = nullptr; Browser* browser = nullptr;
for (auto* b : *BrowserList::GetInstance()) { for (auto* b : *BrowserList::GetInstance()) {
...@@ -76,37 +128,37 @@ protocol::Response BrowserHandler::GetWindowForTarget( ...@@ -76,37 +128,37 @@ protocol::Response BrowserHandler::GetWindowForTarget(
browser = b; browser = b;
} }
if (!browser) if (!browser)
return protocol::Response::Error("Browser window not found"); return Response::Error("Browser window not found");
BrowserWindow* window = browser->window(); BrowserWindow* window = browser->window();
*out_window_id = browser->session_id().id(); *out_window_id = browser->session_id().id();
*out_bounds = GetBrowserWindowBounds(window); *out_bounds = GetBrowserWindowBounds(window);
return protocol::Response::OK(); return Response::OK();
} }
protocol::Response BrowserHandler::GetWindowBounds( Response BrowserHandler::GetWindowBounds(
int window_id, int window_id,
std::unique_ptr<protocol::Browser::Bounds>* out_bounds) { std::unique_ptr<protocol::Browser::Bounds>* out_bounds) {
BrowserWindow* window = GetBrowserWindow(window_id); BrowserWindow* window = GetBrowserWindow(window_id);
if (!window) if (!window)
return protocol::Response::Error("Browser window not found"); return Response::Error("Browser window not found");
*out_bounds = GetBrowserWindowBounds(window); *out_bounds = GetBrowserWindowBounds(window);
return protocol::Response::OK(); return Response::OK();
} }
protocol::Response BrowserHandler::Close() { Response BrowserHandler::Close() {
base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
base::BindOnce([]() { chrome::AttemptExit(); })); base::BindOnce([]() { chrome::AttemptExit(); }));
return protocol::Response::OK(); return Response::OK();
} }
protocol::Response BrowserHandler::SetWindowBounds( Response BrowserHandler::SetWindowBounds(
int window_id, int window_id,
std::unique_ptr<protocol::Browser::Bounds> window_bounds) { std::unique_ptr<protocol::Browser::Bounds> window_bounds) {
BrowserWindow* window = GetBrowserWindow(window_id); BrowserWindow* window = GetBrowserWindow(window_id);
if (!window) if (!window)
return protocol::Response::Error("Browser window not found"); return Response::Error("Browser window not found");
gfx::Rect bounds = window->GetBounds(); gfx::Rect bounds = window->GetBounds();
const bool set_bounds = window_bounds->HasLeft() || window_bounds->HasTop() || const bool set_bounds = window_bounds->HasLeft() || window_bounds->HasTop() ||
window_bounds->HasWidth() || window_bounds->HasWidth() ||
...@@ -120,14 +172,14 @@ protocol::Response BrowserHandler::SetWindowBounds( ...@@ -120,14 +172,14 @@ protocol::Response BrowserHandler::SetWindowBounds(
const std::string window_state = window_bounds->GetWindowState("normal"); const std::string window_state = window_bounds->GetWindowState("normal");
if (set_bounds && window_state != "normal") { if (set_bounds && window_state != "normal") {
return protocol::Response::Error( return Response::Error(
"The 'minimized', 'maximized' and 'fullscreen' states cannot be " "The 'minimized', 'maximized' and 'fullscreen' states cannot be "
"combined with 'left', 'top', 'width' or 'height'"); "combined with 'left', 'top', 'width' or 'height'");
} }
if (window_state == "fullscreen") { if (window_state == "fullscreen") {
if (window->IsMinimized()) { if (window->IsMinimized()) {
return protocol::Response::Error( return Response::Error(
"To make minimized window fullscreen, " "To make minimized window fullscreen, "
"restore it to normal state first."); "restore it to normal state first.");
} }
...@@ -135,14 +187,14 @@ protocol::Response BrowserHandler::SetWindowBounds( ...@@ -135,14 +187,14 @@ protocol::Response BrowserHandler::SetWindowBounds(
GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE); GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE);
} else if (window_state == "maximized") { } else if (window_state == "maximized") {
if (window->IsMinimized() || window->IsFullscreen()) { if (window->IsMinimized() || window->IsFullscreen()) {
return protocol::Response::Error( return Response::Error(
"To maximize a minimized or fullscreen " "To maximize a minimized or fullscreen "
"window, restore it to normal state first."); "window, restore it to normal state first.");
} }
window->Maximize(); window->Maximize();
} else if (window_state == "minimized") { } else if (window_state == "minimized") {
if (window->IsFullscreen()) { if (window->IsFullscreen()) {
return protocol::Response::Error( return Response::Error(
"To minimize a fullscreen window, restore it to normal " "To minimize a fullscreen window, restore it to normal "
"state first."); "state first.");
} }
...@@ -160,5 +212,85 @@ protocol::Response BrowserHandler::SetWindowBounds( ...@@ -160,5 +212,85 @@ protocol::Response BrowserHandler::SetWindowBounds(
NOTREACHED(); NOTREACHED();
} }
return protocol::Response::OK(); return Response::OK();
}
Response BrowserHandler::Disable() {
for (auto& browser_context_id : contexts_with_overridden_permissions_) {
Profile* profile = nullptr;
Maybe<std::string> context_id =
browser_context_id == "" ? Maybe<std::string>()
: Maybe<std::string>(browser_context_id);
FindProfile(context_id, &profile);
if (profile) {
PermissionManager* permission_manager = PermissionManager::Get(profile);
permission_manager->ResetPermissionOverridesForDevTools();
}
}
contexts_with_overridden_permissions_.clear();
return Response::OK();
}
Response BrowserHandler::GrantPermissions(
const std::string& origin,
std::unique_ptr<protocol::Array<protocol::Browser::PermissionType>>
permissions,
Maybe<std::string> browser_context_id) {
Profile* profile = nullptr;
Response response = FindProfile(browser_context_id, &profile);
if (!response.isSuccess())
return response;
PermissionOverrides overrides;
for (size_t i = 0; i < permissions->length(); ++i) {
content::PermissionType type;
Response type_response =
FromProtocolPermissionType(permissions->get(i), &type);
if (!type_response.isSuccess())
return type_response;
overrides.insert(type);
}
PermissionManager* permission_manager = PermissionManager::Get(profile);
GURL url = GURL(origin).GetOrigin();
permission_manager->SetPermissionOverridesForDevTools(url,
std::move(overrides));
contexts_with_overridden_permissions_.insert(
browser_context_id.fromMaybe(""));
return Response::FallThrough();
}
Response BrowserHandler::ResetPermissions(
Maybe<std::string> browser_context_id) {
Profile* profile = nullptr;
Response response = FindProfile(browser_context_id, &profile);
if (!response.isSuccess())
return response;
PermissionManager* permission_manager = PermissionManager::Get(profile);
permission_manager->ResetPermissionOverridesForDevTools();
contexts_with_overridden_permissions_.erase(browser_context_id.fromMaybe(""));
return Response::FallThrough();
}
Response BrowserHandler::FindProfile(
const Maybe<std::string>& browser_context_id,
Profile** profile) {
auto* delegate = ChromeDevToolsManagerDelegate::GetInstance();
if (!browser_context_id.isJust()) {
*profile =
Profile::FromBrowserContext(delegate->GetDefaultBrowserContext());
if (*profile == nullptr)
return Response::Error("Browser context management is not supported.");
return Response::OK();
}
std::string context_id = browser_context_id.fromJust();
for (auto* context : delegate->GetBrowserContexts()) {
if (context->UniqueId() == context_id) {
*profile = Profile::FromBrowserContext(context);
return Response::OK();
}
}
return Response::InvalidParams("Failed to find browser context for id " +
context_id);
} }
...@@ -5,8 +5,11 @@ ...@@ -5,8 +5,11 @@
#ifndef CHROME_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_ #ifndef CHROME_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_
#define CHROME_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_ #define CHROME_BROWSER_DEVTOOLS_PROTOCOL_BROWSER_HANDLER_H_
#include "base/containers/flat_set.h"
#include "chrome/browser/devtools/protocol/browser.h" #include "chrome/browser/devtools/protocol/browser.h"
class Profile;
class BrowserHandler : public protocol::Browser::Backend { class BrowserHandler : public protocol::Browser::Backend {
public: public:
explicit BrowserHandler(protocol::UberDispatcher* dispatcher); explicit BrowserHandler(protocol::UberDispatcher* dispatcher);
...@@ -24,8 +27,22 @@ class BrowserHandler : public protocol::Browser::Backend { ...@@ -24,8 +27,22 @@ class BrowserHandler : public protocol::Browser::Backend {
protocol::Response SetWindowBounds( protocol::Response SetWindowBounds(
int window_id, int window_id,
std::unique_ptr<protocol::Browser::Bounds> out_bounds) override; std::unique_ptr<protocol::Browser::Bounds> out_bounds) override;
protocol::Response Disable() override;
protocol::Response GrantPermissions(
const std::string& origin,
std::unique_ptr<protocol::Array<protocol::Browser::PermissionType>>
permissions,
protocol::Maybe<std::string> browser_context_id) override;
protocol::Response ResetPermissions(
protocol::Maybe<std::string> browser_context_id) override;
private: private:
protocol::Response FindProfile(
const protocol::Maybe<std::string>& browser_context_id,
Profile** profile);
base::flat_set<std::string> contexts_with_overridden_permissions_;
DISALLOW_COPY_AND_ASSIGN(BrowserHandler); DISALLOW_COPY_AND_ASSIGN(BrowserHandler);
}; };
......
...@@ -396,10 +396,18 @@ int PermissionManager::RequestPermissions( ...@@ -396,10 +396,18 @@ int PermissionManager::RequestPermissions(
for (size_t i = 0; i < permissions.size(); ++i) { for (size_t i = 0; i < permissions.size(); ++i) {
const ContentSettingsType permission = permissions[i]; const ContentSettingsType permission = permissions[i];
PermissionContextBase* context = GetPermissionContext(permission);
DCHECK(context);
auto callback = auto callback =
std::make_unique<PermissionResponseCallback>(this, request_id, i); std::make_unique<PermissionResponseCallback>(this, request_id, i);
auto status = GetPermissionOverrideForDevTools(canonical_requesting_origin,
permission);
if (status != CONTENT_SETTING_DEFAULT) {
callback->OnPermissionsRequestResponseStatus(CONTENT_SETTING_ALLOW);
continue;
}
PermissionContextBase* context = GetPermissionContext(permission);
DCHECK(context);
context->RequestPermission( context->RequestPermission(
web_contents, request, canonical_requesting_origin, user_gesture, web_contents, request, canonical_requesting_origin, user_gesture,
base::Bind( base::Bind(
...@@ -676,6 +684,10 @@ PermissionResult PermissionManager::GetPermissionStatusHelper( ...@@ -676,6 +684,10 @@ PermissionResult PermissionManager::GetPermissionStatusHelper(
const GURL& embedding_origin) { const GURL& embedding_origin) {
GURL canonical_requesting_origin = GURL canonical_requesting_origin =
GetCanonicalOrigin(requesting_origin, embedding_origin); GetCanonicalOrigin(requesting_origin, embedding_origin);
auto status =
GetPermissionOverrideForDevTools(canonical_requesting_origin, permission);
if (status != CONTENT_SETTING_DEFAULT)
return PermissionResult(status, PermissionStatusSource::UNSPECIFIED);
PermissionContextBase* context = GetPermissionContext(permission); PermissionContextBase* context = GetPermissionContext(permission);
PermissionResult result = context->GetPermissionStatus( PermissionResult result = context->GetPermissionStatus(
render_frame_host, canonical_requesting_origin.GetOrigin(), render_frame_host, canonical_requesting_origin.GetOrigin(),
...@@ -685,3 +697,26 @@ PermissionResult PermissionManager::GetPermissionStatusHelper( ...@@ -685,3 +697,26 @@ PermissionResult PermissionManager::GetPermissionStatusHelper(
result.content_setting == CONTENT_SETTING_BLOCK); result.content_setting == CONTENT_SETTING_BLOCK);
return result; return result;
} }
void PermissionManager::SetPermissionOverridesForDevTools(
const GURL& origin,
const PermissionOverrides& overrides) {
ContentSettingsTypeOverrides result;
for (const auto& item : overrides)
result.insert(PermissionTypeToContentSetting(item));
devtools_permission_overrides_[origin] = std::move(result);
}
void PermissionManager::ResetPermissionOverridesForDevTools() {
devtools_permission_overrides_.clear();
}
ContentSetting PermissionManager::GetPermissionOverrideForDevTools(
const GURL& origin,
ContentSettingsType permission) {
auto it = devtools_permission_overrides_.find(origin);
if (it == devtools_permission_overrides_.end())
return CONTENT_SETTING_DEFAULT;
return it->second.count(permission) ? CONTENT_SETTING_ALLOW
: CONTENT_SETTING_BLOCK;
}
...@@ -15,15 +15,12 @@ ...@@ -15,15 +15,12 @@
#include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings.h"
#include "components/keyed_service/core/keyed_service.h" #include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/permission_controller_delegate.h" #include "content/public/browser/permission_controller_delegate.h"
#include "content/public/browser/permission_type.h"
class PermissionContextBase; class PermissionContextBase;
struct PermissionResult; struct PermissionResult;
class Profile; class Profile;
namespace content {
enum class PermissionType;
}; // namespace content
class PermissionManager : public KeyedService, class PermissionManager : public KeyedService,
public content::PermissionControllerDelegate, public content::PermissionControllerDelegate,
public content_settings::Observer { public content_settings::Observer {
...@@ -119,6 +116,14 @@ class PermissionManager : public KeyedService, ...@@ -119,6 +116,14 @@ class PermissionManager : public KeyedService,
// denied due to the kill switch. // denied due to the kill switch.
bool IsPermissionKillSwitchOn(ContentSettingsType); bool IsPermissionKillSwitchOn(ContentSettingsType);
using PermissionOverrides = std::set<content::PermissionType>;
// For the given |origin|, grant permissions that belong to |overrides|
// and reject all others.
void SetPermissionOverridesForDevTools(const GURL& origin,
const PermissionOverrides& overrides);
void ResetPermissionOverridesForDevTools();
private: private:
friend class PermissionManagerTest; friend class PermissionManagerTest;
friend class GeolocationPermissionContextTests; friend class GeolocationPermissionContextTests;
...@@ -158,6 +163,10 @@ class PermissionManager : public KeyedService, ...@@ -158,6 +163,10 @@ class PermissionManager : public KeyedService,
const GURL& requesting_origin, const GURL& requesting_origin,
const GURL& embedding_origin); const GURL& embedding_origin);
ContentSetting GetPermissionOverrideForDevTools(
const GURL& origin,
ContentSettingsType permission);
Profile* profile_; Profile* profile_;
PendingRequestsMap pending_requests_; PendingRequestsMap pending_requests_;
SubscriptionsMap subscriptions_; SubscriptionsMap subscriptions_;
...@@ -166,6 +175,8 @@ class PermissionManager : public KeyedService, ...@@ -166,6 +175,8 @@ class PermissionManager : public KeyedService,
std::unique_ptr<PermissionContextBase>, std::unique_ptr<PermissionContextBase>,
ContentSettingsTypeHash> ContentSettingsTypeHash>
permission_contexts_; permission_contexts_;
using ContentSettingsTypeOverrides = std::set<ContentSettingsType>;
std::map<GURL, ContentSettingsTypeOverrides> devtools_permission_overrides_;
DISALLOW_COPY_AND_ASSIGN(PermissionManager); DISALLOW_COPY_AND_ASSIGN(PermissionManager);
}; };
......
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