blob: 42586d50f7c9a3778f6b6c3a497a44667983205b [file] [log] [blame]
// Copyright 2020 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.
#import <Cocoa/Cocoa.h>
#include "base/command_line.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/cocoa/screentime/fake_webpage_controller.h"
#include "chrome/browser/ui/cocoa/screentime/screentime_features.h"
#include "chrome/browser/ui/cocoa/screentime/screentime_policy.h"
#include "chrome/browser/ui/cocoa/screentime/tab_helper.h"
#include "chrome/browser/ui/cocoa/screentime/webpage_controller.h"
#include "chrome/browser/ui/cocoa/screentime/webpage_controller_impl.h"
#include "content/public/browser/media_session.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
namespace screentime {
namespace {
bool g_use_fake_webpage_controller = false;
}
// static
void TabHelper::UseFakeWebpageControllerForTesting() {
g_use_fake_webpage_controller = true;
}
// static
bool TabHelper::IsScreentimeEnabledForProfile(Profile* profile) {
if (profile->IsOffTheRecord())
return false;
return IsScreenTimeEnabled();
}
TabHelper::TabHelper(content::WebContents* contents)
: WebContentsObserver(contents), page_controller_(MakeWebpageController()) {
NSView* contents_view = contents->GetNativeView().GetNativeNSView();
[contents_view addSubview:page_controller_->GetView()];
}
TabHelper::~TabHelper() = default;
void TabHelper::DidFinishNavigation(content::NavigationHandle* handle) {
Profile* profile = Profile::FromBrowserContext(
handle->GetWebContents()->GetBrowserContext());
// Absolutely ensure that we never record a navigation for an OTR profile.
CHECK(!profile->IsOffTheRecord());
// TODO(ellyjones): Some defensive programming around chrome:// URLs would
// probably be a good idea here. It's not unimaginable that ScreenTime would
// misbehave and end up occluding those URLs, which would be very bad.
if (handle->IsInMainFrame() && handle->HasCommitted())
page_controller_->PageURLChangedTo(URLForReporting(handle->GetURL()));
}
std::unique_ptr<WebpageController> TabHelper::MakeWebpageController() {
const bool use_fake =
g_use_fake_webpage_controller ||
base::CommandLine::ForCurrentProcess()->HasSwitch("fake-screentime");
// The callback is owned by the WebpageController instance, which is in turn
// owned by this object, so it can't outlive us.
auto callback =
base::BindRepeating(&TabHelper::OnBlockedChanged, base::Unretained(this));
std::unique_ptr<WebpageController> controller;
if (use_fake)
controller = std::make_unique<FakeWebpageController>(callback);
else
controller = std::make_unique<WebpageControllerImpl>(callback);
return controller;
}
void TabHelper::OnBlockedChanged(bool blocked) {
// TODO: Update occlusion state on the WebContents, and so on.
// Getting this behavior right will probably require some care.
auto* media_session = content::MediaSession::Get(web_contents());
if (blocked)
media_session->Suspend(content::MediaSession::SuspendType::kSystem);
else
media_session->Resume(content::MediaSession::SuspendType::kSystem);
}
WEB_CONTENTS_USER_DATA_KEY_IMPL(TabHelper)
} // namespace screentime