blob: 2b223a1fcf23474ecb17ac849375d84a79a11cd1 [file] [log] [blame]
// Copyright 2013 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 "chrome/browser/chromeos/display/output_protection_delegate.h"
#include "ash/shell.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
namespace chromeos {
namespace {
bool GetCurrentDisplayId(content::RenderFrameHost* rfh, int64_t* display_id) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(rfh);
DCHECK(display_id);
display::Screen* screen = display::Screen::GetScreen();
if (!screen)
return false;
display::Display display =
screen->GetDisplayNearestWindow(rfh->GetNativeView());
*display_id = display.id();
return true;
}
void DoNothing(bool status) {
}
} // namespace
OutputProtectionDelegate::OutputProtectionDelegate(int render_process_id,
int render_frame_id)
: render_process_id_(render_process_id),
render_frame_id_(render_frame_id),
window_(nullptr),
client_id_(ui::DisplayConfigurator::kInvalidClientId),
display_id_(0),
weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
}
OutputProtectionDelegate::~OutputProtectionDelegate() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
ui::DisplayConfigurator* configurator =
ash::Shell::GetInstance()->display_configurator();
configurator->UnregisterContentProtectionClient(client_id_);
if (window_)
window_->RemoveObserver(this);
}
ui::DisplayConfigurator::ContentProtectionClientId
OutputProtectionDelegate::GetClientId() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (client_id_ == ui::DisplayConfigurator::kInvalidClientId) {
content::RenderFrameHost* rfh =
content::RenderFrameHost::FromID(render_process_id_, render_frame_id_);
if (!rfh || !GetCurrentDisplayId(rfh, &display_id_))
return ui::DisplayConfigurator::kInvalidClientId;
aura::Window* window = rfh->GetNativeView();
if (!window)
return ui::DisplayConfigurator::kInvalidClientId;
ui::DisplayConfigurator* configurator =
ash::Shell::GetInstance()->display_configurator();
client_id_ = configurator->RegisterContentProtectionClient();
if (client_id_ != ui::DisplayConfigurator::kInvalidClientId) {
window->AddObserver(this);
window_ = window;
}
}
return client_id_;
}
void OutputProtectionDelegate::QueryStatus(
const QueryStatusCallback& callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::RenderFrameHost* rfh =
content::RenderFrameHost::FromID(render_process_id_, render_frame_id_);
if (!rfh) {
LOG(WARNING) << "RenderFrameHost is not alive.";
callback.Run(false, 0, 0);
return;
}
ui::DisplayConfigurator* configurator =
ash::Shell::GetInstance()->display_configurator();
configurator->QueryContentProtectionStatus(
GetClientId(), display_id_,
base::Bind(&OutputProtectionDelegate::QueryStatusComplete,
weak_ptr_factory_.GetWeakPtr(), callback));
}
void OutputProtectionDelegate::EnableProtection(
uint32_t desired_method_mask,
const EnableProtectionCallback& callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
ui::DisplayConfigurator* configurator =
ash::Shell::GetInstance()->display_configurator();
configurator->EnableContentProtection(
GetClientId(), display_id_, desired_method_mask,
base::Bind(&OutputProtectionDelegate::EnableProtectionComplete,
weak_ptr_factory_.GetWeakPtr(), callback));
desired_method_mask_ = desired_method_mask;
}
void OutputProtectionDelegate::QueryStatusComplete(
const QueryStatusCallback& callback,
const ui::DisplayConfigurator::QueryProtectionResponse& response) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::RenderFrameHost* rfh =
content::RenderFrameHost::FromID(render_process_id_, render_frame_id_);
// TODO(xjz): Investigate whether this check (and the other one above) should
// be removed.
if (!rfh) {
LOG(WARNING) << "RenderFrameHost is not alive.";
callback.Run(false, 0, 0);
return;
}
callback.Run(response.success, response.link_mask, response.protection_mask);
}
void OutputProtectionDelegate::EnableProtectionComplete(
const EnableProtectionCallback& callback,
bool success) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
callback.Run(success);
}
void OutputProtectionDelegate::OnWindowHierarchyChanged(
const aura::WindowObserver::HierarchyChangeParams& params) {
content::RenderFrameHost* rfh =
content::RenderFrameHost::FromID(render_process_id_, render_frame_id_);
if (!rfh) {
LOG(WARNING) << "RenderFrameHost is not alive.";
return;
}
int64_t new_display_id = 0;
if (!GetCurrentDisplayId(rfh, &new_display_id))
return;
if (display_id_ == new_display_id)
return;
if (desired_method_mask_ != ui::CONTENT_PROTECTION_METHOD_NONE) {
// Display changed and should enable output protections on new display.
ui::DisplayConfigurator* configurator =
ash::Shell::GetInstance()->display_configurator();
configurator->EnableContentProtection(GetClientId(), new_display_id,
desired_method_mask_,
base::Bind(&DoNothing));
configurator->EnableContentProtection(GetClientId(), display_id_,
ui::CONTENT_PROTECTION_METHOD_NONE,
base::Bind(&DoNothing));
}
display_id_ = new_display_id;
}
void OutputProtectionDelegate::OnWindowDestroying(aura::Window* window) {
DCHECK_EQ(window, window_);
window_->RemoveObserver(this);
window_ = nullptr;
}
} // namespace chromeos