summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhshi@chromium.org <hshi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-17 23:45:33 +0000
committerhshi@chromium.org <hshi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-17 23:45:33 +0000
commit58868abfc1fe2a7f40e661daab83b0e09e560cbb (patch)
treeefc399a8d3251d7d2badd5847297b027bc7067c4
parent1ac72d4dd82a9abfa9185b18089ca9442a6c977a (diff)
downloadchromium_src-58868abfc1fe2a7f40e661daab83b0e09e560cbb.zip
chromium_src-58868abfc1fe2a7f40e661daab83b0e09e560cbb.tar.gz
chromium_src-58868abfc1fe2a7f40e661daab83b0e09e560cbb.tar.bz2
Chrome OS: avoid suspending on lid close when casting is active.
Treat casting (both tab casting and screen casting) the same as external display to avoid suspending on lid close. BUG=268615 TEST=verify that device is not suspended on lid close with casting is active. Review URL: https://codereview.chromium.org/139053003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245659 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ash/shell.cc7
-rw-r--r--ash/shell.h3
-rw-r--r--chrome/browser/media/media_capture_devices_dispatcher.cc47
-rw-r--r--chrome/browser/media/media_capture_devices_dispatcher.h2
-rw-r--r--chromeos/display/output_configurator.cc49
-rw-r--r--chromeos/display/output_configurator.h9
-rw-r--r--chromeos/display/output_configurator_unittest.cc41
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.cc2
-rw-r--r--content/browser/renderer_host/media/mock_media_observer.h4
-rw-r--r--content/public/browser/media_observer.h1
10 files changed, 141 insertions, 24 deletions
diff --git a/ash/shell.cc b/ash/shell.cc
index 5e81698..68b3d38 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -389,6 +389,13 @@ void Shell::OnLockStateChanged(bool locked) {
#endif
}
+void Shell::OnCastingSessionStartedOrStopped(bool started) {
+#if defined(OS_CHROMEOS) && defined(USE_X11)
+ if (output_configurator_)
+ output_configurator_->OnCastingSessionStartedOrStopped(started);
+#endif
+}
+
void Shell::CreateShelf() {
RootWindowControllerList controllers = GetAllRootWindowControllers();
for (RootWindowControllerList::iterator iter = controllers.begin();
diff --git a/ash/shell.h b/ash/shell.h
index d2019f9..1d9dee7 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -286,6 +286,9 @@ class ASH_EXPORT Shell
// unlocked.
void OnLockStateChanged(bool locked);
+ // Called when a casting session is started or stopped.
+ void OnCastingSessionStartedOrStopped(bool started);
+
// Initializes |shelf_|. Does nothing if it's already initialized.
void CreateShelf();
diff --git a/chrome/browser/media/media_capture_devices_dispatcher.cc b/chrome/browser/media/media_capture_devices_dispatcher.cc
index 29c7afb..5bdc499 100644
--- a/chrome/browser/media/media_capture_devices_dispatcher.cc
+++ b/chrome/browser/media/media_capture_devices_dispatcher.cc
@@ -89,22 +89,48 @@ bool IsOriginWhitelistedForScreenCapture(const GURL& origin) {
origin.spec() == "chrome-extension://pkedcjkdefgpdelpbcmbmeomcjbeemfm/" ||
origin.spec() == "chrome-extension://fmfcbgogabcbclcofgocippekhfcmgfj/" ||
origin.spec() == "chrome-extension://hfaagokkkhdbgiakmmlclaapfelnkoah/" ||
+ origin.spec() == "chrome-extension://boadgeojelhgndaghljhdicfkmllpafd/" ||
origin.spec() == "chrome-extension://gfdkimpbcpahaombhbimeihdjnejgicl/") {
return true;
}
// Check against hashed origins.
+ // TODO(hshi): remove this when trusted tester becomes public.
const std::string origin_hash = base::SHA1HashString(origin.spec());
DCHECK_EQ(origin_hash.length(), base::kSHA1Length);
const std::string hexencoded_origin_hash =
base::HexEncode(origin_hash.data(), origin_hash.length());
return
- hexencoded_origin_hash == "3C2705BC432E7C51CA8553FDC5BEE873FF2468EE" ||
- hexencoded_origin_hash == "50F02B8A668CAB274527D58356F07C2143080FCC";
+ hexencoded_origin_hash == "3C2705BC432E7C51CA8553FDC5BEE873FF2468EE";
#else
return false;
#endif
}
+#if defined(OS_CHROMEOS)
+// Returns true of the security origin is associated with casting.
+bool IsOriginForCasting(const GURL& origin) {
+#if defined(OFFICIAL_BUILD)
+ // Whitelisted tab casting extensions.
+ if (origin.spec() == "chrome-extension://pkedcjkdefgpdelpbcmbmeomcjbeemfm/" ||
+ origin.spec() == "chrome-extension://fmfcbgogabcbclcofgocippekhfcmgfj/" ||
+ origin.spec() == "chrome-extension://hfaagokkkhdbgiakmmlclaapfelnkoah/" ||
+ origin.spec() == "chrome-extension://boadgeojelhgndaghljhdicfkmllpafd/") {
+ return true;
+ }
+ // Check against hashed origins.
+ // TODO(hshi): remove this when trusted tester becomes public.
+ const std::string origin_hash = base::SHA1HashString(origin.spec());
+ DCHECK_EQ(origin_hash.length(), base::kSHA1Length);
+ const std::string hexencoded_origin_hash =
+ base::HexEncode(origin_hash.data(), origin_hash.length());
+ return
+ hexencoded_origin_hash == "3C2705BC432E7C51CA8553FDC5BEE873FF2468EE";
+#else
+ return false;
+#endif
+}
+#endif
+
// Helper to get title of the calling application shown in the screen capture
// notification.
base::string16 GetApplicationTitle(content::WebContents* web_contents,
@@ -395,7 +421,7 @@ void MediaCaptureDevicesDispatcher::ProcessScreenCaptureAccessRequest(
// display the notification for stream capture.
bool display_notification = !component_extension;
- ui = GetDevicesForDesktopCapture(devices, screen_id, capture_audio,
+ ui = GetDevicesForDesktopCapture(devices, screen_id, capture_audio,
display_notification, application_title);
}
}
@@ -657,6 +683,7 @@ void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged(
int render_process_id,
int render_view_id,
int page_request_id,
+ const GURL& security_origin,
const content::MediaStreamDevice& device,
content::MediaRequestState state) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -665,7 +692,7 @@ void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged(
base::Bind(
&MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread,
base::Unretained(this), render_process_id, render_view_id,
- page_request_id, device, state));
+ page_request_id, security_origin, device, state));
}
void MediaCaptureDevicesDispatcher::OnAudioStreamPlayingChanged(
@@ -709,6 +736,7 @@ void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread(
int render_process_id,
int render_view_id,
int page_request_id,
+ const GURL& security_origin,
const content::MediaStreamDevice& device,
content::MediaRequestState state) {
// Track desktop capture sessions. Tracking is necessary to avoid unbalanced
@@ -755,6 +783,17 @@ void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread(
}
}
+#if defined(OS_CHROMEOS)
+ if (IsOriginForCasting(security_origin) && IsVideoMediaType(device.type)) {
+ // Notify ash that casting state has changed.
+ if (state == content::MEDIA_REQUEST_STATE_DONE) {
+ ash::Shell::GetInstance()->OnCastingSessionStartedOrStopped(true);
+ } else if (state == content::MEDIA_REQUEST_STATE_CLOSING) {
+ ash::Shell::GetInstance()->OnCastingSessionStartedOrStopped(false);
+ }
+ }
+#endif
+
FOR_EACH_OBSERVER(Observer, observers_,
OnRequestUpdate(render_process_id,
render_view_id,
diff --git a/chrome/browser/media/media_capture_devices_dispatcher.h b/chrome/browser/media/media_capture_devices_dispatcher.h
index 2b65ab2..b86d525 100644
--- a/chrome/browser/media/media_capture_devices_dispatcher.h
+++ b/chrome/browser/media/media_capture_devices_dispatcher.h
@@ -121,6 +121,7 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver,
int render_process_id,
int render_view_id,
int page_request_id,
+ const GURL& security_origin,
const content::MediaStreamDevice& device,
content::MediaRequestState state) OVERRIDE;
virtual void OnAudioStreamPlayingChanged(
@@ -200,6 +201,7 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver,
int render_process_id,
int render_view_id,
int page_request_id,
+ const GURL& security_origin,
const content::MediaStreamDevice& device,
content::MediaRequestState state);
void OnCreatingAudioStreamOnUIThread(int render_process_id,
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc
index fb545aa..852b794 100644
--- a/chromeos/display/output_configurator.cc
+++ b/chromeos/display/output_configurator.cc
@@ -106,20 +106,6 @@ int GetOutputPower(
return num_on_outputs;
}
-// Determine if there is an "internal" output and how many outputs are
-// connected.
-bool IsProjecting(
- const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
- bool has_internal_output = false;
- int connected_output_count = outputs.size();
- for (size_t i = 0; i < outputs.size(); ++i)
- has_internal_output |= outputs[i].type == OUTPUT_TYPE_INTERNAL;
-
- // "Projecting" is defined as having more than 1 output connected while at
- // least one of them is an internal output.
- return has_internal_output && (connected_output_count > 1);
-}
-
} // namespace
OutputConfigurator::ModeInfo::ModeInfo()
@@ -252,7 +238,8 @@ OutputConfigurator::OutputConfigurator()
xrandr_event_base_(0),
output_state_(STATE_INVALID),
power_state_(DISPLAY_POWER_ALL_ON),
- next_output_protection_client_id_(1) {
+ next_output_protection_client_id_(1),
+ casting_session_count_(0) {
}
OutputConfigurator::~OutputConfigurator() {}
@@ -294,7 +281,7 @@ void OutputConfigurator::Start(uint32 background_color_argb) {
// that all displays are on when signing out.
delegate_->ForceDPMSOn();
delegate_->UngrabServer();
- delegate_->SendProjectingStateToPowerManager(IsProjecting(cached_outputs_));
+ SendProjectingStateToPowerManager();
NotifyObservers(success, new_state);
}
@@ -335,6 +322,22 @@ bool OutputConfigurator::ApplyProtections(const DisplayProtections& requests) {
return true;
}
+void OutputConfigurator::SendProjectingStateToPowerManager() {
+ bool has_internal_output = false;
+ int connected_output_count = cached_outputs_.size() + casting_session_count_;
+ for (size_t i = 0; i < cached_outputs_.size(); ++i) {
+ if (cached_outputs_[i].type == OUTPUT_TYPE_INTERNAL) {
+ has_internal_output = true;
+ break;
+ }
+ }
+
+ // "Projecting" is defined as having more than 1 output connected while at
+ // least one of them is an internal output.
+ bool is_projecting = has_internal_output && (connected_output_count > 1);
+ delegate_->SendProjectingStateToPowerManager(is_projecting);
+}
+
OutputConfigurator::OutputProtectionClientId
OutputConfigurator::RegisterOutputProtectionClient() {
if (!configure_display_)
@@ -599,6 +602,18 @@ base::EventStatus OutputConfigurator::WillProcessEvent(
void OutputConfigurator::DidProcessEvent(const base::NativeEvent& event) {
}
+void OutputConfigurator::OnCastingSessionStartedOrStopped(bool started) {
+ if (started) {
+ ++casting_session_count_;
+ } else {
+ DCHECK_GT(casting_session_count_, 0);
+ --casting_session_count_;
+ if (casting_session_count_ < 0)
+ casting_session_count_ = 0;
+ }
+ SendProjectingStateToPowerManager();
+}
+
void OutputConfigurator::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
@@ -777,7 +792,7 @@ void OutputConfigurator::ConfigureOutputs() {
delegate_->UngrabServer();
NotifyObservers(success, new_state);
- delegate_->SendProjectingStateToPowerManager(IsProjecting(cached_outputs_));
+ SendProjectingStateToPowerManager();
}
void OutputConfigurator::NotifyObservers(bool success,
diff --git a/chromeos/display/output_configurator.h b/chromeos/display/output_configurator.h
index 7144d2a..8a8b36d 100644
--- a/chromeos/display/output_configurator.h
+++ b/chromeos/display/output_configurator.h
@@ -379,6 +379,9 @@ class CHROMEOS_EXPORT OutputConfigurator
const base::NativeEvent& event) OVERRIDE;
virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE;
+ // Called when a casting session is started or stopped.
+ void OnCastingSessionStartedOrStopped(bool started);
+
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
@@ -503,6 +506,9 @@ class CHROMEOS_EXPORT OutputConfigurator
// Applies output protections according to requests.
bool ApplyProtections(const DisplayProtections& requests);
+ // Sends the current projecting state to power manager.
+ void SendProjectingStateToPowerManager();
+
StateController* state_controller_;
SoftwareMirroringController* mirroring_controller_;
scoped_ptr<Delegate> delegate_;
@@ -551,6 +557,9 @@ class CHROMEOS_EXPORT OutputConfigurator
// Output protection requests of each client.
ProtectionRequests client_protection_requests_;
+ // Number of outstanding casting sessions.
+ int casting_session_count_;
+
DISALLOW_COPY_AND_ASSIGN(OutputConfigurator);
};
diff --git a/chromeos/display/output_configurator_unittest.cc b/chromeos/display/output_configurator_unittest.cc
index c253270a..7c74bd3 100644
--- a/chromeos/display/output_configurator_unittest.cc
+++ b/chromeos/display/output_configurator_unittest.cc
@@ -787,6 +787,47 @@ TEST_F(OutputConfiguratorTest, SetDisplayPower) {
EXPECT_EQ(1, observer_.num_changes());
}
+TEST_F(OutputConfiguratorTest, Casting) {
+ InitWithSingleOutput();
+
+ // Notify configurator that casting session is started.
+ configurator_.OnCastingSessionStartedOrStopped(true);
+ EXPECT_EQ(kProjectingOn, delegate_->GetActionsAndClear());
+
+ // Verify that the configurator keeps a count of active casting sessions
+ // instead of treating it as a single global state.
+ configurator_.OnCastingSessionStartedOrStopped(true);
+ EXPECT_EQ(kProjectingOn, delegate_->GetActionsAndClear());
+ configurator_.OnCastingSessionStartedOrStopped(false);
+ EXPECT_EQ(kProjectingOn, delegate_->GetActionsAndClear());
+
+ // Turn all displays off and check that projecting is not turned off.
+ configurator_.SetDisplayPower(DISPLAY_POWER_ALL_OFF,
+ OutputConfigurator::kSetDisplayPowerNoFlags);
+ EXPECT_EQ(JoinActions(kGrab,
+ GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
+ outputs_[0].crtc, 0).c_str(),
+ GetCrtcAction(outputs_[0].crtc, 0, 0, 0,
+ outputs_[0].output).c_str(),
+ kUngrab, NULL),
+ delegate_->GetActionsAndClear());
+
+ // Turn all displays back on.
+ configurator_.SetDisplayPower(DISPLAY_POWER_ALL_ON,
+ OutputConfigurator::kSetDisplayPowerNoFlags);
+ EXPECT_EQ(JoinActions(kGrab,
+ GetFramebufferAction(kSmallModeWidth, kSmallModeHeight,
+ outputs_[0].crtc, 0).c_str(),
+ GetCrtcAction(outputs_[0].crtc, 0, 0, kSmallModeId,
+ outputs_[0].output).c_str(),
+ kForceDPMS, kUngrab, NULL),
+ delegate_->GetActionsAndClear());
+
+ // Notify configurator that casting session is ended.
+ configurator_.OnCastingSessionStartedOrStopped(false);
+ EXPECT_EQ(kProjectingOff, delegate_->GetActionsAndClear());
+}
+
TEST_F(OutputConfiguratorTest, SuspendAndResume) {
InitWithSingleOutput();
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index 8a865fc..4b1ea25 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -217,7 +217,7 @@ class MediaStreamManager::DeviceRequest {
media_observer->OnMediaRequestStateChanged(
ui_request_->render_process_id, ui_request_->render_view_id,
- ui_request_->page_request_id,
+ ui_request_->page_request_id, ui_request_->security_origin,
MediaStreamDevice(stream_type, device_id, device_id), new_state);
}
diff --git a/content/browser/renderer_host/media/mock_media_observer.h b/content/browser/renderer_host/media/mock_media_observer.h
index c3543f3..e59352f 100644
--- a/content/browser/renderer_host/media/mock_media_observer.h
+++ b/content/browser/renderer_host/media/mock_media_observer.h
@@ -24,9 +24,9 @@ class MockMediaObserver : public MediaObserver {
void(const MediaStreamDevices& devices));
MOCK_METHOD1(OnVideoCaptureDevicesChanged,
void(const MediaStreamDevices& devices));
- MOCK_METHOD5(OnMediaRequestStateChanged,
+ MOCK_METHOD6(OnMediaRequestStateChanged,
void(int render_process_id, int render_view_id,
- int page_request_id,
+ int page_request_id, const GURL& security_origin,
const MediaStreamDevice& device,
const MediaRequestState state));
MOCK_METHOD6(OnAudioStreamPlayingChanged,
diff --git a/content/public/browser/media_observer.h b/content/public/browser/media_observer.h
index 1c264aa..c5185ba 100644
--- a/content/public/browser/media_observer.h
+++ b/content/public/browser/media_observer.h
@@ -27,6 +27,7 @@ class MediaObserver {
int render_process_id,
int render_view_id,
int page_request_id,
+ const GURL& security_origin,
const MediaStreamDevice& device,
MediaRequestState state) = 0;