Commit 9eb09ede authored by Sergey Poromov's avatar Sergey Poromov Committed by Commit Bot

DLP: Enforce screenshot restrictions in extensions API.

"tabs.captureVisibleTab" extensions API should respect the current Data Leak Prevention content restrictions on Chrome OS.

Bug: 1109723
Change-Id: I7d4fc2f3bcac466db3fbc0fc0f7fb35be25e8188
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2323357
Commit-Queue: Sergey Poromov <poromov@chromium.org>
Reviewed-by: default avatarKaran Bhatia <karandeepb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796230}
parent d91344f9
...@@ -1698,12 +1698,13 @@ TabsCaptureVisibleTabFunction::TabsCaptureVisibleTabFunction() ...@@ -1698,12 +1698,13 @@ TabsCaptureVisibleTabFunction::TabsCaptureVisibleTabFunction()
: chrome_details_(this) { : chrome_details_(this) {
} }
bool TabsCaptureVisibleTabFunction::IsScreenshotEnabled() const { bool TabsCaptureVisibleTabFunction::IsScreenshotEnabled(
content::WebContents* web_contents) const {
PrefService* service = chrome_details_.GetProfile()->GetPrefs(); PrefService* service = chrome_details_.GetProfile()->GetPrefs();
if (service->GetBoolean(prefs::kDisableScreenshots)) { if (service->GetBoolean(prefs::kDisableScreenshots)) {
return false; return false;
} }
return true; return !tabs_util::IsScreenshotRestricted(web_contents);
} }
bool TabsCaptureVisibleTabFunction::ClientAllowsTransparency() { bool TabsCaptureVisibleTabFunction::ClientAllowsTransparency() {
......
...@@ -236,7 +236,7 @@ class TabsCaptureVisibleTabFunction ...@@ -236,7 +236,7 @@ class TabsCaptureVisibleTabFunction
content::WebContents* GetWebContentsForID(int window_id, std::string* error); content::WebContents* GetWebContentsForID(int window_id, std::string* error);
// extensions::WebContentsCaptureClient: // extensions::WebContentsCaptureClient:
bool IsScreenshotEnabled() const override; bool IsScreenshotEnabled(content::WebContents* web_contents) const override;
bool ClientAllowsTransparency() override; bool ClientAllowsTransparency() override;
void OnCaptureSuccess(const SkBitmap& bitmap) override; void OnCaptureSuccess(const SkBitmap& bitmap) override;
void OnCaptureFailure(CaptureResult result) override; void OnCaptureFailure(CaptureResult result) override;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
#include "ash/public/cpp/window_pin_type.h" #include "ash/public/cpp/window_pin_type.h"
#include "ash/public/cpp/window_properties.h" #include "ash/public/cpp/window_properties.h"
#include "chrome/browser/chromeos/policy/dlp/mock_dlp_content_manager.h"
#endif #endif
namespace extensions { namespace extensions {
...@@ -601,6 +602,44 @@ TEST_F(TabsApiUnitTest, DontCreateTabsInLockedFullscreenMode) { ...@@ -601,6 +602,44 @@ TEST_F(TabsApiUnitTest, DontCreateTabsInLockedFullscreenMode) {
extension_function_test_utils::RunFunctionAndReturnError( extension_function_test_utils::RunFunctionAndReturnError(
function.get(), "[{}]", browser(), api_test_utils::NONE)); function.get(), "[{}]", browser(), api_test_utils::NONE));
} }
// Ensure tabs.captureVisibleTab respects any Data Leak Prevention restrictions.
TEST_F(TabsApiUnitTest, ScreenshotsRestricted) {
// Setup the function and extension.
scoped_refptr<const Extension> extension = ExtensionBuilder("Screenshot")
.AddPermission("tabs")
.AddPermission("<all_urls>")
.Build();
auto function = base::MakeRefCounted<TabsCaptureVisibleTabFunction>();
function->set_extension(extension.get());
// Add a visible tab.
std::unique_ptr<content::WebContents> web_contents =
content::WebContentsTester::CreateTestWebContents(profile(), nullptr);
content::WebContentsTester* web_contents_tester =
content::WebContentsTester::For(web_contents.get());
const GURL kGoogle("http://www.google.com");
web_contents_tester->NavigateAndCommit(kGoogle);
browser()->tab_strip_model()->AppendWebContents(std::move(web_contents),
/*foreground=*/true);
// Setup Data Leak Prevention restriction.
policy::MockDlpContentManager mock_dlp_content_manager;
policy::DlpContentManager::SetDlpContentManagerForTesting(
&mock_dlp_content_manager);
EXPECT_CALL(mock_dlp_content_manager, IsScreenshotRestricted(testing::_))
.Times(1)
.WillOnce(testing::Return(true));
// Run the function and check result.
std::string error = extension_function_test_utils::RunFunctionAndReturnError(
function.get(), "[{}]", browser(), api_test_utils::NONE);
EXPECT_EQ(tabs_constants::kScreenshotsDisabled, error);
// Clean up.
browser()->tab_strip_model()->CloseAllTabs();
policy::DlpContentManager::ResetDlpContentManagerForTesting();
}
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
} // namespace extensions } // namespace extensions
...@@ -9,5 +9,9 @@ namespace tabs_util { ...@@ -9,5 +9,9 @@ namespace tabs_util {
void SetLockedFullscreenState(Browser* browser, bool locked) {} void SetLockedFullscreenState(Browser* browser, bool locked) {}
bool IsScreenshotRestricted(content::WebContents* web_contents) {
return false;
}
} // namespace tabs_util } // namespace tabs_util
} // namespace extensions } // namespace extensions
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
class Browser; class Browser;
namespace content {
class WebContents;
}
namespace extensions { namespace extensions {
namespace tabs_util { namespace tabs_util {
...@@ -18,6 +22,10 @@ namespace tabs_util { ...@@ -18,6 +22,10 @@ namespace tabs_util {
// necessary adjustments. // necessary adjustments.
void SetLockedFullscreenState(Browser* browser, bool locked); void SetLockedFullscreenState(Browser* browser, bool locked);
// Checks whether screenshot of |web_contents| is restricted due to Data Leak
// Prevention policy.
bool IsScreenshotRestricted(content::WebContents* web_contents);
} // namespace tabs_util } // namespace tabs_util
} // namespace extensions } // namespace extensions
......
...@@ -12,11 +12,13 @@ ...@@ -12,11 +12,13 @@
#include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/chromeos/arc/session/arc_session_manager.h" #include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
#include "chrome/browser/chromeos/assistant/assistant_util.h" #include "chrome/browser/chromeos/assistant/assistant_util.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager.h"
#include "chrome/browser/ui/ash/chrome_screenshot_grabber.h" #include "chrome/browser/ui/ash/chrome_screenshot_grabber.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_command_controller.h" #include "chrome/browser/ui/browser_command_controller.h"
#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/browser_window.h"
#include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/web_contents.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/clipboard_buffer.h" #include "ui/base/clipboard/clipboard_buffer.h"
...@@ -66,5 +68,10 @@ void SetLockedFullscreenState(Browser* browser, bool locked) { ...@@ -66,5 +68,10 @@ void SetLockedFullscreenState(Browser* browser, bool locked) {
} }
} }
bool IsScreenshotRestricted(content::WebContents* web_contents) {
return policy::DlpContentManager::Get()->IsScreenshotRestricted(
ScreenshotArea::CreateForWindow(web_contents->GetNativeView()));
}
} // namespace tabs_util } // namespace tabs_util
} // namespace extensions } // namespace extensions
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "chrome/browser/extensions/api/chrome_extensions_api_client.h" #include "chrome/browser/extensions/api/chrome_extensions_api_client.h"
#include "chrome/browser/extensions/api/content_settings/content_settings_service.h" #include "chrome/browser/extensions/api/content_settings/content_settings_service.h"
#include "chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.h" #include "chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.h"
#include "chrome/browser/extensions/api/tabs/tabs_util.h"
#include "chrome/browser/extensions/chrome_component_extension_resource_manager.h" #include "chrome/browser/extensions/chrome_component_extension_resource_manager.h"
#include "chrome/browser/extensions/chrome_extension_host_delegate.h" #include "chrome/browser/extensions/chrome_extension_host_delegate.h"
#include "chrome/browser/extensions/chrome_extension_web_contents_observer.h" #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
...@@ -590,6 +591,11 @@ bool ChromeExtensionsBrowserClient::HasIsolatedStorage( ...@@ -590,6 +591,11 @@ bool ChromeExtensionsBrowserClient::HasIsolatedStorage(
return extensions::util::HasIsolatedStorage(extension_id, context); return extensions::util::HasIsolatedStorage(extension_id, context);
} }
bool ChromeExtensionsBrowserClient::IsScreenshotRestricted(
content::WebContents* web_contents) const {
return tabs_util::IsScreenshotRestricted(web_contents);
}
// static // static
void ChromeExtensionsBrowserClient::SetMediaRouterAccessLoggerForTesting( void ChromeExtensionsBrowserClient::SetMediaRouterAccessLoggerForTesting(
MediaRouterExtensionAccessLogger* media_router_access_logger) { MediaRouterExtensionAccessLogger* media_router_access_logger) {
......
...@@ -158,6 +158,8 @@ class ChromeExtensionsBrowserClient : public ExtensionsBrowserClient { ...@@ -158,6 +158,8 @@ class ChromeExtensionsBrowserClient : public ExtensionsBrowserClient {
const override; const override;
bool HasIsolatedStorage(const std::string& extension_id, bool HasIsolatedStorage(const std::string& extension_id,
content::BrowserContext* context) override; content::BrowserContext* context) override;
bool IsScreenshotRestricted(
content::WebContents* web_contents) const override;
static void set_did_chrome_update_for_testing(bool did_update); static void set_did_chrome_update_for_testing(bool did_update);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/stop_find_action.h" #include "content/public/common/stop_find_action.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/guest_view/web_view/web_view_constants.h" #include "extensions/browser/guest_view/web_view/web_view_constants.h"
#include "extensions/browser/guest_view/web_view/web_view_content_script_manager.h" #include "extensions/browser/guest_view/web_view/web_view_content_script_manager.h"
#include "extensions/common/api/web_view_internal.h" #include "extensions/common/api/web_view_internal.h"
...@@ -314,9 +315,9 @@ WebViewInternalCaptureVisibleRegionFunction::Run() { ...@@ -314,9 +315,9 @@ WebViewInternalCaptureVisibleRegionFunction::Run() {
return RespondNow(Error(GetErrorMessage(capture_result))); return RespondNow(Error(GetErrorMessage(capture_result)));
} }
bool WebViewInternalCaptureVisibleRegionFunction::IsScreenshotEnabled() const { bool WebViewInternalCaptureVisibleRegionFunction::IsScreenshotEnabled(
// TODO(wjmaclean): Is it ok to always return true here? content::WebContents* web_contents) const {
return true; return !ExtensionsBrowserClient::Get()->IsScreenshotRestricted(web_contents);
} }
bool WebViewInternalCaptureVisibleRegionFunction::ClientAllowsTransparency() { bool WebViewInternalCaptureVisibleRegionFunction::ClientAllowsTransparency() {
...@@ -353,8 +354,7 @@ std::string WebViewInternalCaptureVisibleRegionFunction::GetErrorMessage( ...@@ -353,8 +354,7 @@ std::string WebViewInternalCaptureVisibleRegionFunction::GetErrorMessage(
reason_description = "view is invisible"; reason_description = "view is invisible";
break; break;
case FAILURE_REASON_SCREEN_SHOTS_DISABLED: case FAILURE_REASON_SCREEN_SHOTS_DISABLED:
NOTREACHED() << "WebViewInternalCaptureVisibleRegionFunction always have " reason_description = "screenshot has been disabled";
"screenshots enabled";
break; break;
case OK: case OK:
NOTREACHED() NOTREACHED()
......
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
#include "extensions/browser/guest_view/web_view/web_ui/web_ui_url_fetcher.h" #include "extensions/browser/guest_view/web_view/web_ui/web_ui_url_fetcher.h"
#include "extensions/browser/guest_view/web_view/web_view_guest.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h"
namespace content {
class WebContents;
}
// WARNING: WebViewInternal could be loaded in an unblessed context, thus any // WARNING: WebViewInternal could be loaded in an unblessed context, thus any
// new APIs must extend WebViewInternalExtensionFunction or // new APIs must extend WebViewInternalExtensionFunction or
// WebViewInternalExecuteCodeFunction which do a process ID check to prevent // WebViewInternalExecuteCodeFunction which do a process ID check to prevent
...@@ -47,7 +51,7 @@ class WebViewInternalCaptureVisibleRegionFunction ...@@ -47,7 +51,7 @@ class WebViewInternalCaptureVisibleRegionFunction
private: private:
// extensions::WebContentsCaptureClient: // extensions::WebContentsCaptureClient:
bool IsScreenshotEnabled() const override; bool IsScreenshotEnabled(content::WebContents* web_contents) const override;
bool ClientAllowsTransparency() override; bool ClientAllowsTransparency() override;
void OnCaptureSuccess(const SkBitmap& bitmap) override; void OnCaptureSuccess(const SkBitmap& bitmap) override;
void OnCaptureFailure(CaptureResult result) override; void OnCaptureFailure(CaptureResult result) override;
......
...@@ -34,7 +34,7 @@ WebContentsCaptureClient::CaptureResult WebContentsCaptureClient::CaptureAsync( ...@@ -34,7 +34,7 @@ WebContentsCaptureClient::CaptureResult WebContentsCaptureClient::CaptureAsync(
if (!view) if (!view)
return FAILURE_REASON_VIEW_INVISIBLE; return FAILURE_REASON_VIEW_INVISIBLE;
if (!IsScreenshotEnabled()) if (!IsScreenshotEnabled(web_contents))
return FAILURE_REASON_SCREEN_SHOTS_DISABLED; return FAILURE_REASON_SCREEN_SHOTS_DISABLED;
// The default format and quality setting used when encoding jpegs. // The default format and quality setting used when encoding jpegs.
......
...@@ -26,7 +26,8 @@ class WebContentsCaptureClient { ...@@ -26,7 +26,8 @@ class WebContentsCaptureClient {
protected: protected:
virtual ~WebContentsCaptureClient() {} virtual ~WebContentsCaptureClient() {}
virtual bool IsScreenshotEnabled() const = 0; virtual bool IsScreenshotEnabled(
content::WebContents* web_contents) const = 0;
virtual bool ClientAllowsTransparency() = 0; virtual bool ClientAllowsTransparency() = 0;
enum CaptureResult { enum CaptureResult {
......
...@@ -124,4 +124,9 @@ bool ExtensionsBrowserClient::HasIsolatedStorage( ...@@ -124,4 +124,9 @@ bool ExtensionsBrowserClient::HasIsolatedStorage(
return false; return false;
} }
bool ExtensionsBrowserClient::IsScreenshotRestricted(
content::WebContents* web_contents) const {
return false;
}
} // namespace extensions } // namespace extensions
...@@ -364,6 +364,10 @@ class ExtensionsBrowserClient { ...@@ -364,6 +364,10 @@ class ExtensionsBrowserClient {
virtual bool HasIsolatedStorage(const std::string& extension_id, virtual bool HasIsolatedStorage(const std::string& extension_id,
content::BrowserContext* context); content::BrowserContext* context);
// Returns whether screenshot of |web_contents| is restricted due to Data Leak
// Protection policy.
virtual bool IsScreenshotRestricted(content::WebContents* web_contents) const;
private: private:
std::vector<std::unique_ptr<ExtensionsBrowserAPIProvider>> providers_; std::vector<std::unique_ptr<ExtensionsBrowserAPIProvider>> providers_;
......
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