diff options
author | robliao <robliao@chromium.org> | 2015-11-10 17:39:50 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-11 01:40:38 +0000 |
commit | 8ed7e286df82468f631e3788155ff0a517f80af9 (patch) | |
tree | 16a58d13d009aff8775024bc4b69780360f336c8 | |
parent | 7608e2ac26c40c2d299f9b1641a4578a45fde4c2 (diff) | |
download | chromium_src-8ed7e286df82468f631e3788155ff0a517f80af9.zip chromium_src-8ed7e286df82468f631e3788155ff0a517f80af9.tar.gz chromium_src-8ed7e286df82468f631e3788155ff0a517f80af9.tar.bz2 |
Revert of [Presentation API / Media Router] Clean up default pres URL logic. (patchset #16 id:300001 of https://codereview.chromium.org/1406013003/ )
Reason for revert:
Prime suspect in causing
mojo_runner_unittests mojo_runner_unittests
failures:
BackgroundApplicationLoaderTest.Load
NativeApplicationLoaderTest.DoesNotExist
https://build.chromium.org/p/chromium.linux/builders/Android%20GN/builds/32013
Original issue's description:
> [Presentation API / Media Router] Clean up default pres URL logic.
>
> 1. In presentation_service.mojom, there were 2 methods for default
> presentation: ListenForDefaultSessionStart and SetDefaultPresentationURL.
> There is no reason they should be called separately. Furthermore,
> ListenForDefaultSessionStart is called after connecting to
> PresentationService, which is not optimal. This CL removes the former
> method.
>
> 2. Remove OnDefaultSessionStarted from PSD::Observer and replace it
> with callbacks. The purpose of PSD::Observer is to notify
> PresentationServiceImpl that PresentationServiceDelegate is being
> destroyed and shouldn't include specific Pres API logic.
>
> 3. Fix default request matching logic in PSDImpl to account for all
> of (frame, frame url, presentation url). Previously it was only
> checking presentation url and always assumes it came from the
> current main frame. This is a problem because the main frame of a
> WebContents can change over time, i.e. main frame at time of setting
> DPU and time of route response could be different). Now we create
> a PresentationRequest object to hold all info needed to match default
> request and pass it to MRUI, who then binds the request to the route
> response callback in PSDImpl/PresentationFrameManager to perform the
> matching.
>
> BUG=544259
>
> Committed: https://crrev.com/6104fb062821e3e8584ed2e40cdb3f77502d88f0
> Cr-Commit-Position: refs/heads/master@{#358935}
TBR=mfoltz@chromium.org,avayvod@chromium.org,mlamouri@chromium.org,imcheng@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=544259
Review URL: https://codereview.chromium.org/1436703002
Cr-Commit-Position: refs/heads/master@{#359007}
25 files changed, 591 insertions, 755 deletions
diff --git a/chrome/browser/media/android/router/media_router_dialog_controller_android.cc b/chrome/browser/media/android/router/media_router_dialog_controller_android.cc index df69aee..53ee2ea4 100644 --- a/chrome/browser/media/android/router/media_router_dialog_controller_android.cc +++ b/chrome/browser/media/android/router/media_router_dialog_controller_android.cc @@ -10,7 +10,6 @@ #include "chrome/browser/media/router/media_router.h" #include "chrome/browser/media/router/media_router_factory.h" #include "chrome/browser/media/router/media_source.h" -#include "chrome/browser/media/router/presentation_request.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" @@ -36,17 +35,16 @@ MediaRouterDialogControllerAndroid::GetOrCreateForWebContents( void MediaRouterDialogControllerAndroid::OnSinkSelected( JNIEnv* env, jobject obj, jstring jsink_id) { - scoped_ptr<CreatePresentationConnectionRequest> create_connection_request = - TakeCreateConnectionRequest(); - const PresentationRequest& presentation_request = - create_connection_request->presentation_request(); - const MediaSource::Id source_id = presentation_request.GetMediaSource().id(); - const GURL origin = presentation_request.frame_url().GetOrigin(); + scoped_ptr<CreatePresentationSessionRequest> + request(TakePresentationRequest()); + + const std::string& source_id = request->media_source().id(); + const GURL& origin = request->frame_url().GetOrigin(); std::vector<MediaRouteResponseCallback> route_response_callbacks; route_response_callbacks.push_back( - base::Bind(&CreatePresentationConnectionRequest::HandleRouteResponse, - base::Passed(&create_connection_request))); + base::Bind(&CreatePresentationSessionRequest::HandleRouteResponse, + base::Passed(&request))); MediaRouter* router = MediaRouterFactory::GetApiForBrowserContext( initiator()->GetBrowserContext()); @@ -78,8 +76,9 @@ void MediaRouterDialogControllerAndroid::OnDialogCancelled( } void MediaRouterDialogControllerAndroid::CancelPresentationRequest() { - scoped_ptr<CreatePresentationConnectionRequest> request = - TakeCreateConnectionRequest(); + scoped_ptr<CreatePresentationSessionRequest> request( + TakePresentationRequest()); + DCHECK(request); request->InvokeErrorCallback(content::PresentationError( @@ -110,10 +109,10 @@ MediaRouterDialogControllerAndroid::~MediaRouterDialogControllerAndroid() { void MediaRouterDialogControllerAndroid::CreateMediaRouterDialog() { JNIEnv* env = base::android::AttachCurrentThread(); - const MediaSource::Id source_id = - create_connection_request()->presentation_request().GetMediaSource().id(); + const MediaSource::Id& media_source_id = + presentation_request()->media_source().id(); ScopedJavaLocalRef<jstring> jsource_urn = - base::android::ConvertUTF8ToJavaString(env, source_id); + base::android::ConvertUTF8ToJavaString(env, media_source_id); // If it's a single route with the same source, show the controller dialog // instead of the device picker. @@ -121,7 +120,7 @@ void MediaRouterDialogControllerAndroid::CreateMediaRouterDialog() { // PresentationServiceDelegateImpl: if the route exists for the same frame // and tab, show the route controller dialog, if not, show the device picker. if (single_existing_route_.get() && - single_existing_route_->media_source().id() == source_id) { + single_existing_route_->media_source().id() == media_source_id) { ScopedJavaLocalRef<jstring> jmedia_route_id = base::android::ConvertUTF8ToJavaString( env, single_existing_route_->media_route_id()); diff --git a/chrome/browser/media/router/create_presentation_connection_request.cc b/chrome/browser/media/router/create_presentation_session_request.cc index 984f676..b3b4bc8 100644 --- a/chrome/browser/media/router/create_presentation_connection_request.cc +++ b/chrome/browser/media/router/create_presentation_session_request.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/media/router/create_presentation_connection_request.h" +#include "chrome/browser/media/router/create_presentation_session_request.h" #include "chrome/browser/media/router/media_source_helper.h" @@ -11,13 +11,13 @@ using content::PresentationError; namespace media_router { -CreatePresentationConnectionRequest::CreatePresentationConnectionRequest( - const RenderFrameHostId& render_frame_host_id, +CreatePresentationSessionRequest::CreatePresentationSessionRequest( const std::string& presentation_url, const GURL& frame_url, const PresentationSessionSuccessCallback& success_cb, const PresentationSessionErrorCallback& error_cb) - : presentation_request_(render_frame_host_id, presentation_url, frame_url), + : media_source_(MediaSourceForPresentationUrl(presentation_url)), + frame_url_(frame_url), success_cb_(success_cb), error_cb_(error_cb), cb_invoked_(false) { @@ -25,27 +25,28 @@ CreatePresentationConnectionRequest::CreatePresentationConnectionRequest( DCHECK(!error_cb.is_null()); } -CreatePresentationConnectionRequest::~CreatePresentationConnectionRequest() { +CreatePresentationSessionRequest::~CreatePresentationSessionRequest() { if (!cb_invoked_) { error_cb_.Run(content::PresentationError( content::PRESENTATION_ERROR_UNKNOWN, "Unknown error.")); } } -void CreatePresentationConnectionRequest::InvokeSuccessCallback( +void CreatePresentationSessionRequest::InvokeSuccessCallback( const std::string& presentation_id, const MediaRoute::Id& route_id) { DCHECK(!cb_invoked_); if (!cb_invoked_) { + // Overwrite presentation ID. success_cb_.Run( content::PresentationSessionInfo( - presentation_request_.presentation_url(), presentation_id), + PresentationUrlFromMediaSource(media_source_), presentation_id), route_id); cb_invoked_ = true; } } -void CreatePresentationConnectionRequest::InvokeErrorCallback( +void CreatePresentationSessionRequest::InvokeErrorCallback( const content::PresentationError& error) { DCHECK(!cb_invoked_); if (!cb_invoked_) { @@ -55,8 +56,8 @@ void CreatePresentationConnectionRequest::InvokeErrorCallback( } // static -void CreatePresentationConnectionRequest::HandleRouteResponse( - scoped_ptr<CreatePresentationConnectionRequest> presentation_request, +void CreatePresentationSessionRequest::HandleRouteResponse( + scoped_ptr<CreatePresentationSessionRequest> presentation_request, const MediaRoute* route, const std::string& presentation_id, const std::string& error) { diff --git a/chrome/browser/media/router/create_presentation_connection_request.h b/chrome/browser/media/router/create_presentation_session_request.h index 024dd1b..9cebcb9 100644 --- a/chrome/browser/media/router/create_presentation_connection_request.h +++ b/chrome/browser/media/router/create_presentation_session_request.h @@ -2,16 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_MEDIA_ROUTER_CREATE_PRESENTATION_CONNECTION_REQUEST_H_ -#define CHROME_BROWSER_MEDIA_ROUTER_CREATE_PRESENTATION_CONNECTION_REQUEST_H_ +#ifndef CHROME_BROWSER_MEDIA_ROUTER_CREATE_PRESENTATION_SESSION_REQUEST_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_CREATE_PRESENTATION_SESSION_REQUEST_H_ #include <string> -#include "base/macros.h" #include "chrome/browser/media/router/media_route.h" #include "chrome/browser/media/router/media_source.h" -#include "chrome/browser/media/router/presentation_request.h" -#include "chrome/browser/media/router/render_frame_host_id.h" #include "content/public/browser/presentation_service_delegate.h" #include "url/gurl.h" @@ -28,29 +25,28 @@ namespace media_router { // MediaRouterUI. |success_cb| will be invoked when create-session // succeeds, or |error_cb| will be invoked when create-session fails or // the UI closes. -class CreatePresentationConnectionRequest { +class CreatePresentationSessionRequest { public: using PresentationSessionSuccessCallback = base::Callback<void(const content::PresentationSessionInfo&, const MediaRoute::Id&)>; using PresentationSessionErrorCallback = - content::PresentationSessionErrorCallback; + content::PresentationServiceDelegate::PresentationSessionErrorCallback; + // |presentation_url|: The presentation URL of the request. Must be a valid // URL. // |frame_url|: The URL of the frame that initiated the presentation request. // |success_cb|: Callback to invoke when the request succeeds. Must be valid. // |erorr_cb|: Callback to invoke when the request fails. Must be valid. - CreatePresentationConnectionRequest( - const RenderFrameHostId& render_frame_host_id, + CreatePresentationSessionRequest( const std::string& presentation_url, const GURL& frame_url, const PresentationSessionSuccessCallback& success_cb, const PresentationSessionErrorCallback& error_cb); - ~CreatePresentationConnectionRequest(); + ~CreatePresentationSessionRequest(); - const PresentationRequest& presentation_request() const { - return presentation_request_; - } + const MediaSource& media_source() const { return media_source_; } + const GURL& frame_url() const { return frame_url_; } // Invokes |success_cb_| or |error_cb_| with the given arguments. // These functions can only be invoked once per instance. It is an error @@ -61,20 +57,21 @@ class CreatePresentationConnectionRequest { // Handle route creation/joining response by invoking the right callback. static void HandleRouteResponse( - scoped_ptr<CreatePresentationConnectionRequest> presentation_request, + scoped_ptr<CreatePresentationSessionRequest> presentation_request, const MediaRoute* route, const std::string& presentation_id, const std::string& error); private: - const PresentationRequest presentation_request_; + const MediaSource media_source_; + const GURL frame_url_; PresentationSessionSuccessCallback success_cb_; PresentationSessionErrorCallback error_cb_; bool cb_invoked_; - DISALLOW_COPY_AND_ASSIGN(CreatePresentationConnectionRequest); + DISALLOW_COPY_AND_ASSIGN(CreatePresentationSessionRequest); }; } // namespace media_router -#endif // CHROME_BROWSER_MEDIA_ROUTER_CREATE_PRESENTATION_CONNECTION_REQUEST_H_ +#endif // CHROME_BROWSER_MEDIA_ROUTER_CREATE_PRESENTATION_SESSION_REQUEST_H_ diff --git a/chrome/browser/media/router/create_presentation_connection_request_unittest.cc b/chrome/browser/media/router/create_presentation_session_request_unittest.cc index 7532529..98614c6 100644 --- a/chrome/browser/media/router/create_presentation_connection_request_unittest.cc +++ b/chrome/browser/media/router/create_presentation_session_request_unittest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/bind.h" -#include "chrome/browser/media/router/create_presentation_connection_request.h" +#include "chrome/browser/media/router/create_presentation_session_request.h" #include "chrome/browser/media/router/media_source_helper.h" #include "content/public/browser/presentation_service_delegate.h" #include "testing/gtest/include/gtest/gtest.h" @@ -13,18 +13,16 @@ namespace media_router { namespace { const char kPresentationUrl[] = "http://foo.com"; -const char kFrameUrl[] = "http://google.com"; const char kPresentationId[] = "presentationId"; const char kRouteId[] = "urn:x-org.chromium:media:route:presentationId/cast-sink1/http://foo.com"; } // namespace -class CreatePresentationConnectionRequestTest : public ::testing::Test { +class CreatePresentationSessionRequestTest : public ::testing::Test { public: - CreatePresentationConnectionRequestTest() - : cb_invoked_(false), render_frame_host_id_(1, 2) {} - ~CreatePresentationConnectionRequestTest() override {} + CreatePresentationSessionRequestTest() : cb_invoked_(false) {} + ~CreatePresentationSessionRequestTest() override {} void OnSuccess(const content::PresentationSessionInfo& expected_info, const content::PresentationSessionInfo& actual_info, @@ -51,49 +49,52 @@ class CreatePresentationConnectionRequestTest : public ::testing::Test { } bool cb_invoked_; - const RenderFrameHostId render_frame_host_id_; }; // Test that the object's getters match the constructor parameters. -TEST_F(CreatePresentationConnectionRequestTest, Getters) { +TEST_F(CreatePresentationSessionRequestTest, Getters) { + GURL frame_url("http://frameUrl"); content::PresentationError error(content::PRESENTATION_ERROR_UNKNOWN, "Unknown error."); - CreatePresentationConnectionRequest request( - render_frame_host_id_, kPresentationUrl, GURL(kFrameUrl), - base::Bind(&CreatePresentationConnectionRequestTest::FailOnSuccess, + CreatePresentationSessionRequest request( + kPresentationUrl, frame_url, + base::Bind(&CreatePresentationSessionRequestTest::FailOnSuccess, base::Unretained(this)), - base::Bind(&CreatePresentationConnectionRequestTest::OnError, + base::Bind(&CreatePresentationSessionRequestTest::OnError, base::Unretained(this), error)); - - PresentationRequest presentation_request(render_frame_host_id_, - kPresentationUrl, GURL(kFrameUrl)); - EXPECT_TRUE(request.presentation_request().Equals(presentation_request)); + EXPECT_EQ(frame_url, request.frame_url()); + EXPECT_EQ(kPresentationUrl, + PresentationUrlFromMediaSource(request.media_source())); // Since we didn't explicitly call Invoke*, the error callback will be // invoked when |request| is destroyed. } -TEST_F(CreatePresentationConnectionRequestTest, SuccessCallback) { +TEST_F(CreatePresentationSessionRequestTest, SuccessCallback) { + GURL frame_url("http://frameUrl"); content::PresentationSessionInfo session_info(kPresentationUrl, kPresentationId); - CreatePresentationConnectionRequest request( - render_frame_host_id_, kPresentationUrl, GURL(kFrameUrl), - base::Bind(&CreatePresentationConnectionRequestTest::OnSuccess, + CreatePresentationSessionRequest request( + kPresentationUrl, frame_url, + base::Bind(&CreatePresentationSessionRequestTest::OnSuccess, base::Unretained(this), session_info), - base::Bind(&CreatePresentationConnectionRequestTest::FailOnError, + base::Bind(&CreatePresentationSessionRequestTest::FailOnError, base::Unretained(this))); request.InvokeSuccessCallback(kPresentationId, kRouteId); EXPECT_TRUE(cb_invoked_); } -TEST_F(CreatePresentationConnectionRequestTest, ErrorCallback) { +TEST_F(CreatePresentationSessionRequestTest, ErrorCallback) { + GURL frame_url("http://frameUrl"); + content::PresentationSessionInfo session_info(kPresentationUrl, + kPresentationId); content::PresentationError error( content::PRESENTATION_ERROR_SESSION_REQUEST_CANCELLED, "This is an error message"); - CreatePresentationConnectionRequest request( - render_frame_host_id_, kPresentationUrl, GURL(kFrameUrl), - base::Bind(&CreatePresentationConnectionRequestTest::FailOnSuccess, + CreatePresentationSessionRequest request( + kPresentationUrl, frame_url, + base::Bind(&CreatePresentationSessionRequestTest::FailOnSuccess, base::Unretained(this)), - base::Bind(&CreatePresentationConnectionRequestTest::OnError, + base::Bind(&CreatePresentationSessionRequestTest::OnError, base::Unretained(this), error)); request.InvokeErrorCallback(error); EXPECT_TRUE(cb_invoked_); diff --git a/chrome/browser/media/router/media_router.gypi b/chrome/browser/media/router/media_router.gypi index 5e27de5..32089b1 100644 --- a/chrome/browser/media/router/media_router.gypi +++ b/chrome/browser/media/router/media_router.gypi @@ -6,8 +6,8 @@ 'variables': { # File lists shared with GN build. 'media_router_sources': [ - 'create_presentation_connection_request.cc', - 'create_presentation_connection_request.h', + 'create_presentation_session_request.cc', + 'create_presentation_session_request.h', 'issue.cc', 'issue.h', 'issue_manager.cc', @@ -39,15 +39,12 @@ 'presentation_connection_state_observer.h', 'presentation_media_sinks_observer.cc', 'presentation_media_sinks_observer.h', - 'presentation_request.cc', - 'presentation_request.h', 'presentation_service_delegate_impl.cc', 'presentation_service_delegate_impl.h', 'presentation_session_messages_observer.cc', 'presentation_session_messages_observer.h', 'presentation_session_state_observer.cc', 'presentation_session_state_observer.h', - 'render_frame_host_id.h', ], # Files that are only needed on desktop builds 'media_router_non_android_sources': [ diff --git a/chrome/browser/media/router/media_router_dialog_controller.cc b/chrome/browser/media/router/media_router_dialog_controller.cc index 2f0583d..f363730 100644 --- a/chrome/browser/media/router/media_router_dialog_controller.cc +++ b/chrome/browser/media/router/media_router_dialog_controller.cc @@ -73,14 +73,14 @@ MediaRouterDialogController::~MediaRouterDialogController() { } bool MediaRouterDialogController::ShowMediaRouterDialogForPresentation( - scoped_ptr<CreatePresentationConnectionRequest> request) { + scoped_ptr<CreatePresentationSessionRequest> request) { DCHECK(thread_checker_.CalledOnValidThread()); // Check if the media router dialog exists for |initiator| and return if so. if (IsShowingMediaRouterDialog()) return false; - create_connection_request_ = request.Pass(); + presentation_request_ = request.Pass(); CreateMediaRouterDialog(); // Show the initiator holding the existing media router dialog. @@ -114,14 +114,14 @@ void MediaRouterDialogController::ActivateInitiatorWebContents() { initiator_->GetDelegate()->ActivateContents(initiator_); } -scoped_ptr<CreatePresentationConnectionRequest> -MediaRouterDialogController::TakeCreateConnectionRequest() { - return create_connection_request_.Pass(); +scoped_ptr<CreatePresentationSessionRequest> +MediaRouterDialogController::TakePresentationRequest() { + return presentation_request_.Pass(); } void MediaRouterDialogController::Reset() { initiator_observer_.reset(); - create_connection_request_.reset(); + presentation_request_.reset(); } } // namespace media_router diff --git a/chrome/browser/media/router/media_router_dialog_controller.h b/chrome/browser/media/router/media_router_dialog_controller.h index 4c6b26c..40dce80 100644 --- a/chrome/browser/media/router/media_router_dialog_controller.h +++ b/chrome/browser/media/router/media_router_dialog_controller.h @@ -10,7 +10,7 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/threading/thread_checker.h" -#include "chrome/browser/media/router/create_presentation_connection_request.h" +#include "chrome/browser/media/router/create_presentation_session_request.h" #include "content/public/browser/web_contents_observer.h" namespace content { @@ -40,7 +40,7 @@ class MediaRouterDialogController { // If the dialog already exists, brings it to the front but doesn't change the // dialog with |request|, returns false and |request| is deleted. bool ShowMediaRouterDialogForPresentation( - scoped_ptr<CreatePresentationConnectionRequest> request); + scoped_ptr<CreatePresentationSessionRequest> request); // Shows the media router dialog modal to |initiator_|. // Creates the dialog if it did not exist prior to this call, returns true. @@ -62,14 +62,13 @@ class MediaRouterDialogController { // Activates the WebContents that initiated the dialog, e.g. focuses the tab. void ActivateInitiatorWebContents(); - // Passes the ownership of the CreatePresentationConnectionRequest to the - // caller. - scoped_ptr<CreatePresentationConnectionRequest> TakeCreateConnectionRequest(); + // Passes the ownership of the CreatePresentationSessionRequest to the caller. + scoped_ptr<CreatePresentationSessionRequest> TakePresentationRequest(); - // Returns the CreatePresentationConnectionRequest to the caller but keeps the + // Returns the CreatePresentationSessionRequest to the caller but keeps the // ownership with the MediaRouterDialogController. - const CreatePresentationConnectionRequest* create_connection_request() const { - return create_connection_request_.get(); + const CreatePresentationSessionRequest* presentation_request() const { + return presentation_request_.get(); } // Returns the WebContents that initiated showing the dialog. @@ -95,7 +94,7 @@ class MediaRouterDialogController { // Data for dialogs created at the request of the Presentation API. // Passed from the caller via ShowMediaRouterDialogForPresentation to the // dialog when it is initialized. - scoped_ptr<CreatePresentationConnectionRequest> create_connection_request_; + scoped_ptr<CreatePresentationSessionRequest> presentation_request_; DISALLOW_COPY_AND_ASSIGN(MediaRouterDialogController); }; diff --git a/chrome/browser/media/router/presentation_request.cc b/chrome/browser/media/router/presentation_request.cc deleted file mode 100644 index 1c6df55..0000000 --- a/chrome/browser/media/router/presentation_request.cc +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2015 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/media/router/presentation_request.h" - -#include "chrome/browser/media/router/media_source_helper.h" - -namespace media_router { - -PresentationRequest::PresentationRequest( - const RenderFrameHostId& render_frame_host_id, - const std::string& presentation_url, - const GURL& frame_url) - : render_frame_host_id_(render_frame_host_id), - presentation_url_(presentation_url), - frame_url_(frame_url) {} - -PresentationRequest::~PresentationRequest() = default; - -bool PresentationRequest::Equals(const PresentationRequest& other) const { - return render_frame_host_id_ == other.render_frame_host_id_ && - presentation_url_ == other.presentation_url_ && - frame_url_ == other.frame_url_; -} - -MediaSource PresentationRequest::GetMediaSource() const { - return MediaSourceForPresentationUrl(presentation_url_); -} - -} // namespace media_router diff --git a/chrome/browser/media/router/presentation_request.h b/chrome/browser/media/router/presentation_request.h deleted file mode 100644 index a37189f..0000000 --- a/chrome/browser/media/router/presentation_request.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2015 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. - -#ifndef CHROME_BROWSER_MEDIA_ROUTER_PRESENTATION_REQUEST_H_ -#define CHROME_BROWSER_MEDIA_ROUTER_PRESENTATION_REQUEST_H_ - -#include <string> - -#include "chrome/browser/media/router/media_source.h" -#include "chrome/browser/media/router/render_frame_host_id.h" -#include "url/gurl.h" - -namespace media_router { - -// Represents a presentation request made from a render frame. Contains the -// presentation URL of the request, and information on the originating frame. -class PresentationRequest { - public: - PresentationRequest(const RenderFrameHostId& render_frame_host_id, - const std::string& presentation_url, - const GURL& frame_url); - ~PresentationRequest(); - - bool Equals(const PresentationRequest& other) const; - - // Helper method to get the MediaSource for |presentation_url_|. - MediaSource GetMediaSource() const; - - const RenderFrameHostId& render_frame_host_id() const { - return render_frame_host_id_; - } - const std::string& presentation_url() const { return presentation_url_; } - const GURL& frame_url() const { return frame_url_; } - - private: - // ID of RenderFrameHost that initiated the request. - const RenderFrameHostId render_frame_host_id_; - - // URL of presentation. - const std::string presentation_url_; - - // URL of frame from which the request was initiated. - const GURL frame_url_; -}; - -} // namespace media_router - -#endif // CHROME_BROWSER_MEDIA_ROUTER_PRESENTATION_REQUEST_H_ diff --git a/chrome/browser/media/router/presentation_request_unittest.cc b/chrome/browser/media/router/presentation_request_unittest.cc deleted file mode 100644 index 7d21a5e..0000000 --- a/chrome/browser/media/router/presentation_request_unittest.cc +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2015 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/media/router/presentation_request.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace media_router { - -TEST(PresentationRequestTest, Equals) { - PresentationRequest request1(RenderFrameHostId(1, 2), - "http://presentationUrl", - GURL("http://frameUrl")); - - // Frame IDs are different. - PresentationRequest request2(RenderFrameHostId(3, 4), - "http://presentationUrl", - GURL("http://frameUrl")); - EXPECT_FALSE(request1.Equals(request2)); - - // Presentation URLs are different. - PresentationRequest request3(RenderFrameHostId(1, 2), - "http://anotherPresentationUrl", - GURL("http://frameUrl")); - EXPECT_FALSE(request1.Equals(request3)); - - // Frame URLs are different. - PresentationRequest request4(RenderFrameHostId(1, 2), - "http://presentationUrl", - GURL("http://anotherFrameUrl")); - EXPECT_FALSE(request1.Equals(request4)); - - PresentationRequest request5(RenderFrameHostId(1, 2), - "http://presentationUrl", - GURL("http://frameUrl")); - EXPECT_TRUE(request1.Equals(request5)); -} - -} // namespace media_router diff --git a/chrome/browser/media/router/presentation_service_delegate_impl.cc b/chrome/browser/media/router/presentation_service_delegate_impl.cc index d2228e5..e45b394 100644 --- a/chrome/browser/media/router/presentation_service_delegate_impl.cc +++ b/chrome/browser/media/router/presentation_service_delegate_impl.cc @@ -11,7 +11,7 @@ #include "base/guid.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" -#include "chrome/browser/media/router/create_presentation_connection_request.h" +#include "chrome/browser/media/router/create_presentation_session_request.h" #include "chrome/browser/media/router/media_route.h" #include "chrome/browser/media/router/media_router.h" #include "chrome/browser/media/router/media_router_dialog_controller.h" @@ -37,6 +37,10 @@ namespace media_router { namespace { using DelegateObserver = content::PresentationServiceDelegate::Observer; +using PresentationSessionErrorCallback = + content::PresentationServiceDelegate::PresentationSessionErrorCallback; +using PresentationSessionSuccessCallback = + content::PresentationServiceDelegate::PresentationSessionSuccessCallback; // Returns the unique identifier for the supplied RenderFrameHost. RenderFrameHostId GetRenderFrameHostId(RenderFrameHost* render_frame_host) { @@ -80,7 +84,6 @@ class PresentationFrame { void ListenForSessionMessages( const content::PresentationSessionInfo& session, const content::PresentationSessionMessageCallback& message_cb); - void Reset(); const MediaRoute::Id GetRouteId(const std::string& presentation_id) const; @@ -88,6 +91,7 @@ class PresentationFrame { void OnPresentationSessionClosed(const std::string& presentation_id); void OnPresentationSessionStarted( + bool is_default_presentation, const content::PresentationSessionInfo& session, const MediaRoute::Id& route_id); void OnPresentationServiceDelegateDestroyed() const; @@ -131,12 +135,15 @@ void PresentationFrame::OnPresentationServiceDelegateDestroyed() const { } void PresentationFrame::OnPresentationSessionStarted( + bool is_default_presentation, const content::PresentationSessionInfo& session, const MediaRoute::Id& route_id) { presentation_id_to_route_id_[session.presentation_id] = route_id; route_id_to_presentation_.Add(route_id, session); if (session_state_observer_) session_state_observer_->OnPresentationSessionConnected(route_id); + if (is_default_presentation && delegate_observer_) + delegate_observer_->OnDefaultPresentationStarted(session); } void PresentationFrame::OnPresentationSessionClosed( @@ -204,7 +211,6 @@ void PresentationFrame::Reset() { sinks_observer_.reset(); if (session_state_observer_) session_state_observer_->Reset(); - session_messages_observers_.clear(); } @@ -259,23 +265,9 @@ class PresentationFrameManager { const RenderFrameHostId& render_frame_host_id, const content::PresentationSessionInfo& session, const content::PresentationSessionMessageCallback& message_cb); - - // Sets or clears the default presentation request and callback for the given - // frame. Also sets / clears the default presentation requests for the owning - // tab WebContents. - void SetDefaultPresentationUrl( - const RenderFrameHostId& render_frame_host_id, - const std::string& default_presentation_url, - const content::PresentationSessionStartedCallback& callback); void AddDelegateObserver(const RenderFrameHostId& render_frame_host_id, DelegateObserver* observer); void RemoveDelegateObserver(const RenderFrameHostId& render_frame_host_id); - void AddDefaultPresentationRequestObserver( - PresentationServiceDelegateImpl::DefaultPresentationRequestObserver* - observer); - void RemoveDefaultPresentationRequestObserver( - PresentationServiceDelegateImpl::DefaultPresentationRequestObserver* - observer); void Reset(const RenderFrameHostId& render_frame_host_id); bool HasScreenAvailabilityListenerForTest( const RenderFrameHostId& render_frame_host_id, @@ -284,10 +276,7 @@ class PresentationFrameManager { void OnPresentationSessionStarted( const RenderFrameHostId& render_frame_host_id, - const content::PresentationSessionInfo& session, - const MediaRoute::Id& route_id); - void OnDefaultPresentationSessionStarted( - const PresentationRequest& request, + bool is_default_presentation, const content::PresentationSessionInfo& session, const MediaRoute::Id& route_id); @@ -299,44 +288,15 @@ class PresentationFrameManager { const std::vector<MediaRoute::Id> GetRouteIds( const RenderFrameHostId& render_frame_host_id) const; - const PresentationRequest* default_presentation_request() const { - return default_presentation_request_.get(); - } - private: PresentationFrame* GetOrAddPresentationFrame( const RenderFrameHostId& render_frame_host_id); - // Sets the default presentation request for the owning WebContents and - // notifies observers of changes. - void SetDefaultPresentationRequest( - const PresentationRequest& default_presentation_request); - - // Clears the default presentation request for the owning WebContents and - // notifies observers of changes. Also resets - // |default_presentation_started_callback_|. - void ClearDefaultPresentationRequest(); - - bool IsMainFrame(const RenderFrameHostId& render_frame_host_id) const; - // Maps a frame identifier to a PresentationFrame object for frames // that are using presentation API. base::ScopedPtrHashMap<RenderFrameHostId, scoped_ptr<PresentationFrame>> presentation_frames_; - // Default presentation request for the owning tab WebContents. - scoped_ptr<PresentationRequest> default_presentation_request_; - - // Callback to invoke when default presentation has started. - content::PresentationSessionStartedCallback - default_presentation_started_callback_; - - // References to the observers listening for changes to this tab WebContent's - // default presentation. - base::ObserverList< - PresentationServiceDelegateImpl::DefaultPresentationRequestObserver> - default_presentation_request_observers_; - // References to the owning WebContents, and the corresponding MediaRouter. MediaRouter* router_; content::WebContents* web_contents_; @@ -357,26 +317,13 @@ PresentationFrameManager::~PresentationFrameManager() { void PresentationFrameManager::OnPresentationSessionStarted( const RenderFrameHostId& render_frame_host_id, + bool is_default_presentation, const content::PresentationSessionInfo& session, const MediaRoute::Id& route_id) { auto presentation_frame = presentation_frames_.get(render_frame_host_id); if (presentation_frame) - presentation_frame->OnPresentationSessionStarted(session, route_id); -} - -void PresentationFrameManager::OnDefaultPresentationSessionStarted( - const PresentationRequest& request, - const content::PresentationSessionInfo& session, - const MediaRoute::Id& route_id) { - auto presentation_frame = - presentation_frames_.get(request.render_frame_host_id()); - if (presentation_frame) - presentation_frame->OnPresentationSessionStarted(session, route_id); - - if (default_presentation_request_ && - default_presentation_request_->Equals(request)) { - default_presentation_started_callback_.Run(session); - } + presentation_frame->OnPresentationSessionStarted(is_default_presentation, + session, route_id); } void PresentationFrameManager::OnPresentationSessionClosed( @@ -450,25 +397,6 @@ void PresentationFrameManager::ListenForSessionMessages( presentation_frame->ListenForSessionMessages(session, message_cb); } -void PresentationFrameManager::SetDefaultPresentationUrl( - const RenderFrameHostId& render_frame_host_id, - const std::string& default_presentation_url, - const content::PresentationSessionStartedCallback& callback) { - if (!IsMainFrame(render_frame_host_id)) - return; - - if (default_presentation_url.empty()) { - ClearDefaultPresentationRequest(); - } else { - DCHECK(!callback.is_null()); - GURL frame_url(GetLastCommittedURLForFrame(render_frame_host_id)); - PresentationRequest request(render_frame_host_id, default_presentation_url, - frame_url); - default_presentation_started_callback_ = callback; - SetDefaultPresentationRequest(request); - } -} - void PresentationFrameManager::AddDelegateObserver( const RenderFrameHostId& render_frame_host_id, DelegateObserver* observer) { @@ -485,29 +413,11 @@ void PresentationFrameManager::RemoveDelegateObserver( } } -void PresentationFrameManager::AddDefaultPresentationRequestObserver( - PresentationServiceDelegateImpl::DefaultPresentationRequestObserver* - observer) { - default_presentation_request_observers_.AddObserver(observer); -} - -void PresentationFrameManager::RemoveDefaultPresentationRequestObserver( - PresentationServiceDelegateImpl::DefaultPresentationRequestObserver* - observer) { - default_presentation_request_observers_.RemoveObserver(observer); -} - void PresentationFrameManager::Reset( const RenderFrameHostId& render_frame_host_id) { auto presentation_frame = presentation_frames_.get(render_frame_host_id); if (presentation_frame) presentation_frame->Reset(); - - if (default_presentation_request_ && - render_frame_host_id == - default_presentation_request_->render_frame_host_id()) { - ClearDefaultPresentationRequest(); - } } PresentationFrame* PresentationFrameManager::GetOrAddPresentationFrame( @@ -521,37 +431,6 @@ PresentationFrame* PresentationFrameManager::GetOrAddPresentationFrame( return presentation_frames_.get(render_frame_host_id); } -void PresentationFrameManager::ClearDefaultPresentationRequest() { - default_presentation_started_callback_.Reset(); - if (!default_presentation_request_) - return; - - default_presentation_request_.reset(); - FOR_EACH_OBSERVER( - PresentationServiceDelegateImpl::DefaultPresentationRequestObserver, - default_presentation_request_observers_, OnDefaultPresentationRemoved()); -} - -bool PresentationFrameManager::IsMainFrame( - const RenderFrameHostId& render_frame_host_id) const { - RenderFrameHost* main_frame = web_contents_->GetMainFrame(); - return main_frame && GetRenderFrameHostId(main_frame) == render_frame_host_id; -} - -void PresentationFrameManager::SetDefaultPresentationRequest( - const PresentationRequest& default_presentation_request) { - if (default_presentation_request_ && - default_presentation_request_->Equals(default_presentation_request)) - return; - - default_presentation_request_.reset( - new PresentationRequest(default_presentation_request)); - FOR_EACH_OBSERVER( - PresentationServiceDelegateImpl::DefaultPresentationRequestObserver, - default_presentation_request_observers_, - OnDefaultPresentationChanged(*default_presentation_request_)); -} - void PresentationFrameManager::SetMediaRouterForTest(MediaRouter* router) { router_ = router; } @@ -615,24 +494,60 @@ void PresentationServiceDelegateImpl::Reset(int render_process_id, int render_frame_id) { RenderFrameHostId render_frame_host_id(render_process_id, render_frame_id); frame_manager_->Reset(render_frame_host_id); + if (render_frame_host_id == default_presentation_render_frame_host_id_) { + UpdateDefaultMediaSourceAndNotifyObservers(RenderFrameHostId(), + MediaSource(), GURL()); + } } void PresentationServiceDelegateImpl::SetDefaultPresentationUrl( int render_process_id, int render_frame_id, - const std::string& default_presentation_url, - const content::PresentationSessionStartedCallback& callback) { + const std::string& default_presentation_url) { RenderFrameHostId render_frame_host_id(render_process_id, render_frame_id); - frame_manager_->SetDefaultPresentationUrl(render_frame_host_id, - default_presentation_url, callback); + if (IsMainFrame(render_process_id, render_frame_id)) { + // This is the main frame, which means tab-level default presentation + // might have been updated. + MediaSource default_source; + if (!default_presentation_url.empty()) + default_source = MediaSourceForPresentationUrl(default_presentation_url); + + GURL default_frame_url = GetLastCommittedURLForFrame(render_frame_host_id); + UpdateDefaultMediaSourceAndNotifyObservers( + render_frame_host_id, default_source, default_frame_url); + } +} + +bool PresentationServiceDelegateImpl::IsMainFrame(int render_process_id, + int render_frame_id) const { + RenderFrameHost* main_frame = web_contents_->GetMainFrame(); + return main_frame && + GetRenderFrameHostId(main_frame) == + RenderFrameHostId(render_process_id, render_frame_id); +} + +void PresentationServiceDelegateImpl:: + UpdateDefaultMediaSourceAndNotifyObservers( + const RenderFrameHostId& render_frame_host_id, + const MediaSource& new_default_source, + const GURL& new_default_frame_url) { + default_presentation_render_frame_host_id_ = render_frame_host_id; + if (!new_default_source.Equals(default_source_) || + new_default_frame_url != default_frame_url_) { + default_source_ = new_default_source; + default_frame_url_ = new_default_frame_url; + FOR_EACH_OBSERVER( + DefaultMediaSourceObserver, default_media_source_observers_, + OnDefaultMediaSourceChanged(default_source_, default_frame_url_)); + } } void PresentationServiceDelegateImpl::OnJoinRouteResponse( int render_process_id, int render_frame_id, const content::PresentationSessionInfo& session, - const content::PresentationSessionStartedCallback& success_cb, - const content::PresentationSessionErrorCallback& error_cb, + const PresentationSessionSuccessCallback& success_cb, + const PresentationSessionErrorCallback& error_cb, const MediaRoute* route, const std::string& presentation_id, const std::string& error_text) { @@ -646,7 +561,7 @@ void PresentationServiceDelegateImpl::OnJoinRouteResponse( << ", presentation ID: " << session.presentation_id; DCHECK_EQ(session.presentation_id, presentation_id); frame_manager_->OnPresentationSessionStarted( - RenderFrameHostId(render_process_id, render_frame_id), session, + RenderFrameHostId(render_process_id, render_frame_id), false, session, route->media_route_id()); success_cb.Run(session); } @@ -655,7 +570,7 @@ void PresentationServiceDelegateImpl::OnJoinRouteResponse( void PresentationServiceDelegateImpl::OnStartSessionSucceeded( int render_process_id, int render_frame_id, - const content::PresentationSessionStartedCallback& success_cb, + const PresentationSessionSuccessCallback& success_cb, const content::PresentationSessionInfo& new_session, const MediaRoute::Id& route_id) { DVLOG(1) << "OnStartSessionSucceeded: " @@ -663,7 +578,7 @@ void PresentationServiceDelegateImpl::OnStartSessionSucceeded( << ", presentation URL: " << new_session.presentation_url << ", presentation ID: " << new_session.presentation_id; frame_manager_->OnPresentationSessionStarted( - RenderFrameHostId(render_process_id, render_frame_id), new_session, + RenderFrameHostId(render_process_id, render_frame_id), false, new_session, route_id); success_cb.Run(new_session); } @@ -672,26 +587,25 @@ void PresentationServiceDelegateImpl::StartSession( int render_process_id, int render_frame_id, const std::string& presentation_url, - const content::PresentationSessionStartedCallback& success_cb, - const content::PresentationSessionErrorCallback& error_cb) { + const PresentationSessionSuccessCallback& success_cb, + const PresentationSessionErrorCallback& error_cb) { if (presentation_url.empty() || !IsValidPresentationUrl(presentation_url)) { error_cb.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN, "Invalid presentation arguments.")); return; } - RenderFrameHostId render_frame_host_id(render_process_id, render_frame_id); - scoped_ptr<CreatePresentationConnectionRequest> request( - new CreatePresentationConnectionRequest( - render_frame_host_id, presentation_url, - GetLastCommittedURLForFrame(render_frame_host_id), + + scoped_ptr<CreatePresentationSessionRequest> context( + new CreatePresentationSessionRequest( + presentation_url, GetLastCommittedURLForFrame(render_frame_host_id), base::Bind(&PresentationServiceDelegateImpl::OnStartSessionSucceeded, weak_factory_.GetWeakPtr(), render_process_id, render_frame_id, success_cb), error_cb)); MediaRouterDialogController* controller = MediaRouterDialogController::GetOrCreateForWebContents(web_contents_); - if (!controller->ShowMediaRouterDialogForPresentation(request.Pass())) { + if (!controller->ShowMediaRouterDialogForPresentation(context.Pass())) { LOG(ERROR) << "Media router dialog already exists. Ignoring StartSession."; error_cb.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN, "Unable to create dialog.")); @@ -704,8 +618,8 @@ void PresentationServiceDelegateImpl::JoinSession( int render_frame_id, const std::string& presentation_url, const std::string& presentation_id, - const content::PresentationSessionStartedCallback& success_cb, - const content::PresentationSessionErrorCallback& error_cb) { + const PresentationSessionSuccessCallback& success_cb, + const PresentationSessionErrorCallback& error_cb) { std::vector<MediaRouteResponseCallback> route_response_callbacks; route_response_callbacks.push_back(base::Bind( &PresentationServiceDelegateImpl::OnJoinRouteResponse, @@ -775,37 +689,34 @@ void PresentationServiceDelegateImpl::ListenForSessionStateChange( } void PresentationServiceDelegateImpl::OnRouteResponse( - const PresentationRequest& presentation_request, const MediaRoute* route, const std::string& presentation_id, const std::string& error) { if (!route) return; - - content::PresentationSessionInfo session_info( - presentation_request.presentation_url(), presentation_id); - frame_manager_->OnDefaultPresentationSessionStarted( - presentation_request, session_info, route->media_route_id()); -} - -void PresentationServiceDelegateImpl::AddDefaultPresentationRequestObserver( - DefaultPresentationRequestObserver* observer) { - frame_manager_->AddDefaultPresentationRequestObserver(observer); -} - -void PresentationServiceDelegateImpl::RemoveDefaultPresentationRequestObserver( - DefaultPresentationRequestObserver* observer) { - frame_manager_->RemoveDefaultPresentationRequestObserver(observer); + const MediaSource& source = route->media_source(); + DCHECK(!source.Empty()); + if (!default_source_.Equals(source)) + return; + RenderFrameHost* main_frame = web_contents_->GetMainFrame(); + if (!main_frame) + return; + RenderFrameHostId render_frame_host_id(GetRenderFrameHostId(main_frame)); + frame_manager_->OnPresentationSessionStarted( + render_frame_host_id, true, + content::PresentationSessionInfo(PresentationUrlFromMediaSource(source), + presentation_id), + route->media_route_id()); } -PresentationRequest -PresentationServiceDelegateImpl::GetDefaultPresentationRequest() const { - DCHECK(HasDefaultPresentationRequest()); - return *frame_manager_->default_presentation_request(); +void PresentationServiceDelegateImpl::AddDefaultMediaSourceObserver( + DefaultMediaSourceObserver* observer) { + default_media_source_observers_.AddObserver(observer); } -bool PresentationServiceDelegateImpl::HasDefaultPresentationRequest() const { - return frame_manager_->default_presentation_request() != nullptr; +void PresentationServiceDelegateImpl::RemoveDefaultMediaSourceObserver( + DefaultMediaSourceObserver* observer) { + default_media_source_observers_.RemoveObserver(observer); } base::WeakPtr<PresentationServiceDelegateImpl> diff --git a/chrome/browser/media/router/presentation_service_delegate_impl.h b/chrome/browser/media/router/presentation_service_delegate_impl.h index 0e6b633..03ad8c7 100644 --- a/chrome/browser/media/router/presentation_service_delegate_impl.h +++ b/chrome/browser/media/router/presentation_service_delegate_impl.h @@ -16,8 +16,6 @@ #include "base/observer_list.h" #include "chrome/browser/media/router/media_router.h" #include "chrome/browser/media/router/media_source.h" -#include "chrome/browser/media/router/presentation_request.h" -#include "chrome/browser/media/router/render_frame_host_id.h" #include "content/public/browser/presentation_service_delegate.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" @@ -37,6 +35,8 @@ class MediaSinksObserver; class PresentationFrameManager; class PresentationSessionStateObserver; +using RenderFrameHostId = std::pair<int, int>; + // Implementation of PresentationServiceDelegate that interfaces an // instance of WebContents with the Chrome Media Router. It uses the Media // Router to handle presentation API calls forwarded from @@ -49,23 +49,6 @@ class PresentationServiceDelegateImpl : public content::WebContentsUserData<PresentationServiceDelegateImpl>, public content::PresentationServiceDelegate { public: - // Observer interface for listening to default presentation request - // changes for the WebContents. - class DefaultPresentationRequestObserver { - public: - virtual ~DefaultPresentationRequestObserver() = default; - - // Called when default presentation request for the corresponding - // WebContents is set or changed. - // |default_presentation_info|: New default presentation request. - virtual void OnDefaultPresentationChanged( - const PresentationRequest& default_presentation_request) = 0; - - // Called when default presentation request for the corresponding - // WebContents has been removed. - virtual void OnDefaultPresentationRemoved() = 0; - }; - // Retrieves the instance of PresentationServiceDelegateImpl that was attached // to the specified WebContents. If no instance was attached, creates one, // and attaches it to the specified WebContents. @@ -92,21 +75,18 @@ class PresentationServiceDelegateImpl void SetDefaultPresentationUrl( int render_process_id, int render_frame_id, - const std::string& default_presentation_url, - const content::PresentationSessionStartedCallback& callback) override; - void StartSession( - int render_process_id, - int render_frame_id, - const std::string& presentation_url, - const content::PresentationSessionStartedCallback& success_cb, - const content::PresentationSessionErrorCallback& error_cb) override; - void JoinSession( - int render_process_id, - int render_frame_id, - const std::string& presentation_url, - const std::string& presentation_id, - const content::PresentationSessionStartedCallback& success_cb, - const content::PresentationSessionErrorCallback& error_cb) override; + const std::string& default_presentation_url) override; + void StartSession(int render_process_id, + int render_frame_id, + const std::string& presentation_url, + const PresentationSessionSuccessCallback& success_cb, + const PresentationSessionErrorCallback& error_cb) override; + void JoinSession(int render_process_id, + int render_frame_id, + const std::string& presentation_url, + const std::string& presentation_id, + const PresentationSessionSuccessCallback& success_cb, + const PresentationSessionErrorCallback& error_cb) override; void CloseSession(int render_process_id, int render_frame_id, const std::string& presentation_id) override; @@ -125,34 +105,39 @@ class PresentationServiceDelegateImpl int render_frame_id, const content::SessionStateChangedCallback& state_changed_cb) override; - // Callback invoked when a default PresentationRequest is started from a - // browser-initiated dialog. - void OnRouteResponse(const PresentationRequest& request, - const MediaRoute* route, + // Callback invoked when there is a route response from CreateRoute/JoinRoute + // outside of a Presentation API request. This could be due to + // browser action (e.g., browser initiated media router dialog) or + // a media route provider (e.g., autojoin). + void OnRouteResponse(const MediaRoute* route, const std::string& presentation_id, const std::string& error); - // Adds / removes an observer for listening to default PresentationRequest - // changes. This class does not own |observer|. When |observer| is about to - // be destroyed, |RemoveDefaultPresentationRequestObserver| must be called. - void AddDefaultPresentationRequestObserver( - DefaultPresentationRequestObserver* observer); - void RemoveDefaultPresentationRequestObserver( - DefaultPresentationRequestObserver* observer); + // Returns the default MediaSource for this tab if there is one. + // Returns an empty MediaSource otherwise. + MediaSource default_source() const { return default_source_; } - // Gets the default presentation request for the owning tab WebContents. It - // is an error to call this method if the default presentation request does - // not exist. - PresentationRequest GetDefaultPresentationRequest() const; + content::WebContents* web_contents() const { return web_contents_; } + const GURL& default_frame_url() const { return default_frame_url_; } - // Returns true if there is a default presentation request for the owning tab + // Observer interface for listening to default MediaSource changes for the // WebContents. - bool HasDefaultPresentationRequest() const; - - // Returns the WebContents that owns this instance. - content::WebContents* web_contents() const { return web_contents_; } + class DefaultMediaSourceObserver { + public: + virtual ~DefaultMediaSourceObserver() {} + + // Called when default media source for the corresponding WebContents has + // changed. + // |source|: New default MediaSource, or empty if default was removed. + // |frame_url|: URL of the frame that contains the default media + // source, or empty if there is no default media source. + virtual void OnDefaultMediaSourceChanged(const MediaSource& source, + const GURL& frame_url) = 0; + }; - base::WeakPtr<PresentationServiceDelegateImpl> GetWeakPtr(); + // Adds / removes an observer for listening to default MediaSource changes. + void AddDefaultMediaSourceObserver(DefaultMediaSourceObserver* observer); + void RemoveDefaultMediaSourceObserver(DefaultMediaSourceObserver* observer); void SetMediaRouterForTest(MediaRouter* router); bool HasScreenAvailabilityListenerForTest( @@ -160,16 +145,12 @@ class PresentationServiceDelegateImpl int render_frame_id, const MediaSource::Id& source_id) const; + base::WeakPtr<PresentationServiceDelegateImpl> GetWeakPtr(); + private: friend class content::WebContentsUserData<PresentationServiceDelegateImpl>; FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest, DelegateObservers); - FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest, - SetDefaultPresentationUrl); - FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest, - DefaultPresentationRequestObserver); - FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest, - DefaultPresentationUrlCallback); explicit PresentationServiceDelegateImpl(content::WebContents* web_contents); @@ -178,26 +159,47 @@ class PresentationServiceDelegateImpl MediaSource GetMediaSourceFromListener( content::PresentationScreenAvailabilityListener* listener); - void OnJoinRouteResponse( - int render_process_id, - int render_frame_id, - const content::PresentationSessionInfo& session, - const content::PresentationSessionStartedCallback& success_cb, - const content::PresentationSessionErrorCallback& error_cb, - const MediaRoute* route, - const std::string& presentation_id, - const std::string& error_text); + void OnJoinRouteResponse(int render_process_id, + int render_frame_id, + const content::PresentationSessionInfo& session, + const PresentationSessionSuccessCallback& success_cb, + const PresentationSessionErrorCallback& error_cb, + const MediaRoute* route, + const std::string& presentation_id, + const std::string& error_text); void OnStartSessionSucceeded( int render_process_id, int render_frame_id, - const content::PresentationSessionStartedCallback& success_cb, + const PresentationSessionSuccessCallback& success_cb, const content::PresentationSessionInfo& new_session, const MediaRoute::Id& route_id); + // Returns |true| if the frame is the main frame of |web_contents_|. + bool IsMainFrame(int render_process_id, int render_frame_id) const; + + // Updates tab-level default MediaSource, default frame URL, and the + // originating frame. If the source or frame URL changed, notify the + // observers. + void UpdateDefaultMediaSourceAndNotifyObservers( + const RenderFrameHostId& render_frame_host_id, + const MediaSource& new_default_source, + const GURL& new_default_frame_url); + + // ID of RenderFrameHost that contains the default presentation. + RenderFrameHostId default_presentation_render_frame_host_id_; + // Default MediaSource for the tab associated with this instance. + MediaSource default_source_; + // URL of the frame that contains the default MediaSource. + GURL default_frame_url_; + + // References to the observers listening for changes to default media source. + base::ObserverList< + DefaultMediaSourceObserver> default_media_source_observers_; + // References to the WebContents that owns this instance, and associated // browser profile's MediaRouter instance. - content::WebContents* const web_contents_; + content::WebContents* web_contents_; MediaRouter* router_; scoped_ptr<PresentationFrameManager> frame_manager_; diff --git a/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc b/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc index c3099aa..056f05d 100644 --- a/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc +++ b/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc @@ -24,7 +24,6 @@ using ::testing::_; using ::testing::Mock; using ::testing::Return; -using ::testing::SaveArg; using ::testing::StrictMock; namespace media_router { @@ -37,12 +36,11 @@ class MockDelegateObserver void(const content::PresentationSessionInfo&)); }; -class MockDefaultPresentationRequestObserver - : public PresentationServiceDelegateImpl:: - DefaultPresentationRequestObserver { +class MockDefaultMediaSourceObserver + : public PresentationServiceDelegateImpl::DefaultMediaSourceObserver { public: - MOCK_METHOD1(OnDefaultPresentationChanged, void(const PresentationRequest&)); - MOCK_METHOD0(OnDefaultPresentationRemoved, void()); + MOCK_METHOD2(OnDefaultMediaSourceChanged, + void(const MediaSource&, const GURL&)); }; class PresentationServiceDelegateImplTest @@ -57,9 +55,6 @@ class PresentationServiceDelegateImplTest delegate_impl_->SetMediaRouterForTest(&router_); } - MOCK_METHOD1(OnDefaultPresentationStarted, - void(const content::PresentationSessionInfo& session_info)); - PresentationServiceDelegateImpl* delegate_impl_; MockMediaRouter router_; }; @@ -67,8 +62,8 @@ class PresentationServiceDelegateImplTest TEST_F(PresentationServiceDelegateImplTest, AddScreenAvailabilityListener) { ON_CALL(router_, RegisterMediaSinksObserver(_)).WillByDefault(Return(true)); - std::string presentation_url1("http://url1.fakeUrl"); - std::string presentation_url2("http://url2.fakeUrl"); + std::string presentation_url1("http://url1"); + std::string presentation_url2("http://url2"); MediaSource source1 = MediaSourceForPresentationUrl(presentation_url1); MediaSource source2 = MediaSourceForPresentationUrl(presentation_url2); MockScreenAvailabilityListener listener1(presentation_url1); @@ -103,7 +98,7 @@ TEST_F(PresentationServiceDelegateImplTest, AddScreenAvailabilityListener) { TEST_F(PresentationServiceDelegateImplTest, AddSameListenerTwice) { ON_CALL(router_, RegisterMediaSinksObserver(_)).WillByDefault(Return(true)); - std::string presentation_url1("http://url1.fakeUrl"); + std::string presentation_url1("http://url1"); MediaSource source1(MediaSourceForPresentationUrl(presentation_url1)); MockScreenAvailabilityListener listener1(presentation_url1); int render_process_id = 1; @@ -124,144 +119,76 @@ TEST_F(PresentationServiceDelegateImplTest, AddSameListenerTwice) { render_process_id, render_frame_id, source1.id())); } -// TODO(imcheng): Add a test to set default presentation URL in a different -// RenderFrameHost and verify that it works. TEST_F(PresentationServiceDelegateImplTest, SetDefaultPresentationUrl) { - EXPECT_FALSE(delegate_impl_->HasDefaultPresentationRequest()); - - GURL frame_url("http://www.google.com"); - content::WebContentsTester::For(web_contents())->NavigateAndCommit(frame_url); + content::WebContentsTester::For(web_contents()) + ->NavigateAndCommit(GURL("http://www.google.com")); content::RenderFrameHost* main_frame = web_contents()->GetMainFrame(); ASSERT_TRUE(main_frame); int render_process_id = main_frame->GetProcess()->GetID(); int routing_id = main_frame->GetRoutingID(); - auto callback = base::Bind( - &PresentationServiceDelegateImplTest::OnDefaultPresentationStarted, - base::Unretained(this)); - std::string presentation_url1("http://foo.fakeUrl"); + std::string presentation_url1("http://foo"); delegate_impl_->SetDefaultPresentationUrl(render_process_id, routing_id, - presentation_url1, callback); - ASSERT_TRUE(delegate_impl_->HasDefaultPresentationRequest()); - PresentationRequest request1 = - delegate_impl_->GetDefaultPresentationRequest(); - EXPECT_EQ(presentation_url1, request1.presentation_url()); - EXPECT_EQ(RenderFrameHostId(render_process_id, routing_id), - request1.render_frame_host_id()); - EXPECT_EQ(frame_url, request1.frame_url()); - - // Set to a new default presentation URL - std::string presentation_url2("https://youtube.com"); - delegate_impl_->SetDefaultPresentationUrl(render_process_id, routing_id, - presentation_url2, callback); - ASSERT_TRUE(delegate_impl_->HasDefaultPresentationRequest()); - PresentationRequest request2 = - delegate_impl_->GetDefaultPresentationRequest(); - EXPECT_EQ(presentation_url2, request2.presentation_url()); - EXPECT_EQ(RenderFrameHostId(render_process_id, routing_id), - request2.render_frame_host_id()); - EXPECT_EQ(frame_url, request2.frame_url()); + presentation_url1); + EXPECT_TRUE(delegate_impl_->default_source().Equals( + MediaSourceForPresentationUrl(presentation_url1))); // Remove default presentation URL. - delegate_impl_->SetDefaultPresentationUrl(render_process_id, routing_id, "", - callback); - EXPECT_FALSE(delegate_impl_->HasDefaultPresentationRequest()); -} + delegate_impl_->SetDefaultPresentationUrl(render_process_id, routing_id, ""); + EXPECT_TRUE(delegate_impl_->default_source().Empty()); -TEST_F(PresentationServiceDelegateImplTest, DefaultPresentationUrlCallback) { - content::RenderFrameHost* main_frame = web_contents()->GetMainFrame(); - ASSERT_TRUE(main_frame); - int render_process_id = main_frame->GetProcess()->GetID(); - int routing_id = main_frame->GetRoutingID(); - - auto callback = base::Bind( - &PresentationServiceDelegateImplTest::OnDefaultPresentationStarted, - base::Unretained(this)); - std::string presentation_url1("http://foo.fakeUrl"); + // Set to a new default presentation URL + std::string presentation_url2("https://youtube.com"); delegate_impl_->SetDefaultPresentationUrl(render_process_id, routing_id, - presentation_url1, callback); - - ASSERT_TRUE(delegate_impl_->HasDefaultPresentationRequest()); - PresentationRequest request = delegate_impl_->GetDefaultPresentationRequest(); - - // Should not trigger callback since route response is error. - delegate_impl_->OnRouteResponse(request, nullptr, "", "Error"); - EXPECT_TRUE(Mock::VerifyAndClearExpectations(this)); - - // Should not trigger callback since request doesn't match. - std::string presentation_url2("http://bar.fakeUrl"); - PresentationRequest different_request(RenderFrameHostId(100, 200), - presentation_url2, - GURL("http://anotherFrameUrl.fakeUrl")); - MediaRoute different_route("differentRouteId", - MediaSourceForPresentationUrl(presentation_url2), - "mediaSinkId", "", true, "", true); - delegate_impl_->OnRouteResponse(different_request, &different_route, - "differentPresentationId", ""); - EXPECT_TRUE(Mock::VerifyAndClearExpectations(this)); - - // Should trigger callback since request matches. - MediaRoute route("routeId", MediaSourceForPresentationUrl(presentation_url1), - "mediaSinkId", "", true, "", true); - EXPECT_CALL(*this, OnDefaultPresentationStarted(_)).Times(1); - delegate_impl_->OnRouteResponse(request, &route, "presentationId", ""); + presentation_url2); + EXPECT_TRUE(delegate_impl_->default_source().Equals( + MediaSourceForPresentationUrl(presentation_url2))); } -TEST_F(PresentationServiceDelegateImplTest, - DefaultPresentationRequestObserver) { - auto callback = base::Bind( - &PresentationServiceDelegateImplTest::OnDefaultPresentationStarted, - base::Unretained(this)); - - StrictMock<MockDefaultPresentationRequestObserver> observer; - delegate_impl_->AddDefaultPresentationRequestObserver(&observer); - - GURL frame_url("http://www.google.com"); - content::WebContentsTester::For(web_contents())->NavigateAndCommit(frame_url); +TEST_F(PresentationServiceDelegateImplTest, DefaultMediaSourceObserver) { + content::WebContentsTester::For(web_contents()) + ->NavigateAndCommit(GURL("http://www.google.com")); content::RenderFrameHost* main_frame = web_contents()->GetMainFrame(); ASSERT_TRUE(main_frame); int render_process_id = main_frame->GetProcess()->GetID(); int routing_id = main_frame->GetRoutingID(); - - std::string url1("http://foo.fakeUrl"); - PresentationRequest observed_request1( - RenderFrameHostId(render_process_id, routing_id), url1, frame_url); - EXPECT_CALL(observer, OnDefaultPresentationChanged(Equals(observed_request1))) - .Times(1); - delegate_impl_->SetDefaultPresentationUrl(render_process_id, routing_id, url1, - callback); - - ASSERT_TRUE(delegate_impl_->HasDefaultPresentationRequest()); - PresentationRequest request1 = - delegate_impl_->GetDefaultPresentationRequest(); - EXPECT_TRUE(request1.Equals(observed_request1)); - - EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer)); - + StrictMock<MockDefaultMediaSourceObserver> observer1; + StrictMock<MockDefaultMediaSourceObserver> observer2; + delegate_impl_->AddDefaultMediaSourceObserver(&observer1); + delegate_impl_->AddDefaultMediaSourceObserver(&observer2); + std::string url1("http://foo"); + EXPECT_CALL(observer1, OnDefaultMediaSourceChanged( + Equals(MediaSourceForPresentationUrl(url1)), + GURL("http://www.google.com"))).Times(1); + EXPECT_CALL(observer2, OnDefaultMediaSourceChanged( + Equals(MediaSourceForPresentationUrl(url1)), + GURL("http://www.google.com"))).Times(1); + delegate_impl_->SetDefaultPresentationUrl(render_process_id, + routing_id, url1); + + EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1)); + EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2)); + + delegate_impl_->RemoveDefaultMediaSourceObserver(&observer2); std::string url2("http://youtube.com"); - PresentationRequest observed_request2( - RenderFrameHostId(render_process_id, routing_id), url2, frame_url); - EXPECT_CALL(observer, OnDefaultPresentationChanged(Equals(observed_request2))) - .Times(1); - delegate_impl_->SetDefaultPresentationUrl(render_process_id, routing_id, url2, - callback); - ASSERT_TRUE(delegate_impl_->HasDefaultPresentationRequest()); - PresentationRequest request2 = - delegate_impl_->GetDefaultPresentationRequest(); - EXPECT_TRUE(request2.Equals(observed_request2)); - - EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer)); + EXPECT_CALL(observer1, OnDefaultMediaSourceChanged( + Equals(MediaSourceForPresentationUrl(url2)), + GURL("http://www.google.com"))).Times(1); + delegate_impl_->SetDefaultPresentationUrl(render_process_id, + routing_id, url2); + EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1)); // Remove default presentation URL. - EXPECT_CALL(observer, OnDefaultPresentationRemoved()).Times(1); - delegate_impl_->SetDefaultPresentationUrl(render_process_id, routing_id, "", - callback); + EXPECT_CALL(observer1, OnDefaultMediaSourceChanged( + Equals(MediaSource()), + GURL("http://www.google.com"))).Times(1); + delegate_impl_->SetDefaultPresentationUrl(render_process_id, routing_id, ""); } TEST_F(PresentationServiceDelegateImplTest, Reset) { ON_CALL(router_, RegisterMediaSinksObserver(_)).WillByDefault(Return(true)); - std::string presentation_url1("http://url1.fakeUrl"); + std::string presentation_url1("http://url1"); MediaSource source = MediaSourceForPresentationUrl(presentation_url1); MockScreenAvailabilityListener listener1(presentation_url1); int render_process_id = 1; @@ -298,7 +225,7 @@ TEST_F(PresentationServiceDelegateImplTest, DelegateObservers) { TEST_F(PresentationServiceDelegateImplTest, SinksObserverCantRegister) { ON_CALL(router_, RegisterMediaSinksObserver(_)).WillByDefault(Return(false)); - const std::string presentation_url("http://url1.fakeUrl"); + const std::string presentation_url("http://url1"); MockScreenAvailabilityListener listener(presentation_url); const int render_process_id = 10; const int render_frame_id = 1; diff --git a/chrome/browser/media/router/render_frame_host_id.h b/chrome/browser/media/router/render_frame_host_id.h deleted file mode 100644 index d9fb005..0000000 --- a/chrome/browser/media/router/render_frame_host_id.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 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. - -#ifndef CHROME_BROWSER_MEDIA_ROUTER_RENDER_FRAME_HOST_ID_H_ -#define CHROME_BROWSER_MEDIA_ROUTER_RENDER_FRAME_HOST_ID_H_ - -#include <utility> - -namespace media_router { - -using RenderFrameHostId = std::pair<int, int>; - -} // namespace media_router - -#endif // CHROME_BROWSER_MEDIA_ROUTER_RENDER_FRAME_HOST_ID_H_ diff --git a/chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl.cc b/chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl.cc index d81c695..ffcecc2 100644 --- a/chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl.cc +++ b/chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl.cc @@ -274,18 +274,18 @@ void MediaRouterDialogControllerImpl::PopulateDialog( return; } - scoped_ptr<CreatePresentationConnectionRequest> create_connection_request( - TakeCreateConnectionRequest()); + scoped_ptr<CreatePresentationSessionRequest> presentation_request( + TakePresentationRequest()); // TODO(imcheng): Don't create PresentationServiceDelegateImpl if it doesn't // exist (crbug.com/508695). base::WeakPtr<PresentationServiceDelegateImpl> delegate = PresentationServiceDelegateImpl::GetOrCreateForWebContents(initiator()) ->GetWeakPtr(); - if (!create_connection_request.get()) { + if (!presentation_request.get()) { media_router_ui->InitWithDefaultMediaSource(delegate); } else { media_router_ui->InitWithPresentationSessionRequest( - initiator(), delegate, create_connection_request.Pass()); + initiator(), delegate, presentation_request.Pass()); } } diff --git a/chrome/browser/ui/webui/media_router/media_router_ui.cc b/chrome/browser/ui/webui/media_router/media_router_ui.cc index afb9c42..4d05a51 100644 --- a/chrome/browser/ui/webui/media_router/media_router_ui.cc +++ b/chrome/browser/ui/webui/media_router/media_router_ui.cc @@ -9,7 +9,7 @@ #include "base/guid.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/media/router/create_presentation_connection_request.h" +#include "chrome/browser/media/router/create_presentation_session_request.h" #include "chrome/browser/media/router/issue.h" #include "chrome/browser/media/router/issues_observer.h" #include "chrome/browser/media/router/media_route.h" @@ -163,12 +163,11 @@ MediaRouterUI::~MediaRouterUI() { if (query_result_manager_.get()) query_result_manager_->RemoveObserver(this); if (presentation_service_delegate_.get()) - presentation_service_delegate_->RemoveDefaultPresentationRequestObserver( - this); - // If |create_session_request_| still exists, then it means presentation route + presentation_service_delegate_->RemoveDefaultMediaSourceObserver(this); + // If |presentation_request_| still exists, then it means presentation route // request was never attempted. - if (create_session_request_) { - create_session_request_->InvokeErrorCallback(content::PresentationError( + if (presentation_request_) { + presentation_request_->InvokeErrorCallback(content::PresentationError( content::PRESENTATION_ERROR_SESSION_REQUEST_CANCELLED, "Dialog closed.")); } @@ -181,30 +180,30 @@ void MediaRouterUI::InitWithDefaultMediaSource( DCHECK(!query_result_manager_.get()); presentation_service_delegate_ = delegate; - presentation_service_delegate_->AddDefaultPresentationRequestObserver(this); - InitCommon(presentation_service_delegate_->web_contents()); - if (presentation_service_delegate_->HasDefaultPresentationRequest()) { - OnDefaultPresentationChanged( - presentation_service_delegate_->GetDefaultPresentationRequest()); - } + presentation_service_delegate_->AddDefaultMediaSourceObserver(this); + InitCommon(presentation_service_delegate_->web_contents(), + presentation_service_delegate_->default_source(), + presentation_service_delegate_->default_frame_url()); } void MediaRouterUI::InitWithPresentationSessionRequest( content::WebContents* initiator, const base::WeakPtr<PresentationServiceDelegateImpl>& delegate, - scoped_ptr<CreatePresentationConnectionRequest> create_session_request) { + scoped_ptr<CreatePresentationSessionRequest> presentation_request) { DCHECK(initiator); - DCHECK(create_session_request); - DCHECK(!create_session_request_); + DCHECK(presentation_request); + DCHECK(!presentation_request_); DCHECK(!query_result_manager_); - create_session_request_ = create_session_request.Pass(); + presentation_request_ = presentation_request.Pass(); presentation_service_delegate_ = delegate; - InitCommon(initiator); - OnDefaultPresentationChanged(create_session_request_->presentation_request()); + InitCommon(initiator, presentation_request_->media_source(), + presentation_request_->frame_url()); } -void MediaRouterUI::InitCommon(content::WebContents* initiator) { +void MediaRouterUI::InitCommon(content::WebContents* initiator, + const MediaSource& default_source, + const GURL& default_frame_url) { DCHECK(initiator); DCHECK(router_); @@ -224,31 +223,26 @@ void MediaRouterUI::InitCommon(content::WebContents* initiator) { MediaSourceForTab(SessionTabHelper::IdForTab(initiator))); query_result_manager_->StartSinksQuery( MediaCastMode::TAB_MIRROR, mirroring_source); -} -void MediaRouterUI::OnDefaultPresentationChanged( - const PresentationRequest& presentation_request) { - presentation_request_.reset(new PresentationRequest(presentation_request)); - query_result_manager_->StartSinksQuery( - MediaCastMode::DEFAULT, presentation_request_->GetMediaSource()); - UpdateCastModes(); + OnDefaultMediaSourceChanged(default_source, default_frame_url); } -void MediaRouterUI::OnDefaultPresentationRemoved() { - presentation_request_.reset(); - query_result_manager_->StopSinksQuery(MediaCastMode::DEFAULT); - UpdateCastModes(); +void MediaRouterUI::OnDefaultMediaSourceChanged(const MediaSource& source, + const GURL& frame_url) { + if (source.Empty()) { + query_result_manager_->StopSinksQuery(MediaCastMode::DEFAULT); + } else { + query_result_manager_->StartSinksQuery(MediaCastMode::DEFAULT, source); + } + UpdateSourceHostAndCastModes(frame_url); } -void MediaRouterUI::UpdateCastModes() { - // Gets updated cast modes from |query_result_manager_| and forwards it to UI. +void MediaRouterUI::UpdateSourceHostAndCastModes(const GURL& frame_url) { + DCHECK(query_result_manager_); + frame_url_ = frame_url; query_result_manager_->GetSupportedCastModes(&cast_modes_); - if (ui_initialized_) { - handler_->UpdateCastModes( - cast_modes_, presentation_request_ - ? GetHostFromURL(presentation_request_->frame_url()) - : std::string()); - } + if (ui_initialized_) + handler_->UpdateCastModes(cast_modes_, GetHostFromURL(frame_url_)); } void MediaRouterUI::Close() { @@ -274,11 +268,11 @@ bool MediaRouterUI::CreateRoute(const MediaSink::Id& sink_id, DCHECK(initiator_); // Note that there is a rarely-encountered bug, where the MediaCastMode to - // MediaSource mapping could have been updated, between when the user clicked - // on the UI to start a create route request, and when this function is - // called. However, since the user does not have visibility into the - // MediaSource, and that it occurs very rarely in practice, we leave it as-is - // for now. + // MediaSource mapping could have been updated, between when the user + // clicked on the UI to start a create route request, + // and when this function is called. + // However, since the user does not have visibility into the MediaSource, and + // that it occurs very rarely in practice, we leave it as-is for now. MediaSource source = query_result_manager_->GetSourceForCastMode(cast_mode); if (source.Empty()) { LOG(ERROR) << "No corresponding MediaSource for cast mode " << cast_mode; @@ -286,16 +280,11 @@ bool MediaRouterUI::CreateRoute(const MediaSink::Id& sink_id, } requesting_route_for_default_source_ = cast_mode == MediaCastMode::DEFAULT; - if (requesting_route_for_default_source_ && !presentation_request_) { - DLOG(ERROR) << "Requested to create a route for presentation, but " - << "presentation request is missing."; - return false; - } - current_route_request_id_ = ++route_request_counter_; GURL origin; + // TODO(imcheng): What is the origin if not creating route in DEFAULT mode? if (requesting_route_for_default_source_) { - origin = presentation_request_->frame_url().GetOrigin(); + origin = frame_url_.GetOrigin(); } else { // Requesting route for mirroring. Use a placeholder URL as origin. origin = GURL(chrome::kChromeUIMediaRouterURL); @@ -308,7 +297,7 @@ bool MediaRouterUI::CreateRoute(const MediaSink::Id& sink_id, // (1) Non-presentation route request (e.g., mirroring). No additional // notification necessary. // (2) Presentation route request for a Presentation API startSession call. - // The startSession (CreatePresentationConnectionRequest) will need to be + // The startSession (CreatePresentationSessionRequest) will need to be // answered with the // route response. // (3) Browser-initiated presentation route request. If successful, @@ -321,16 +310,16 @@ bool MediaRouterUI::CreateRoute(const MediaSink::Id& sink_id, weak_factory_.GetWeakPtr(), current_route_request_id_, sink_id)); if (requesting_route_for_default_source_) { - if (create_session_request_) { - // |create_session_request_| will be nullptr after this call, as the + if (presentation_request_) { + // |presentation_request_| will be nullptr after this call, as the // object will be transferred to the callback. route_response_callbacks.push_back( - base::Bind(&CreatePresentationConnectionRequest::HandleRouteResponse, - base::Passed(&create_session_request_))); + base::Bind(&CreatePresentationSessionRequest::HandleRouteResponse, + base::Passed(&presentation_request_))); } else if (presentation_service_delegate_) { route_response_callbacks.push_back( base::Bind(&PresentationServiceDelegateImpl::OnRouteResponse, - presentation_service_delegate_, *presentation_request_)); + presentation_service_delegate_)); } } diff --git a/chrome/browser/ui/webui/media_router/media_router_ui.h b/chrome/browser/ui/webui/media_router/media_router_ui.h index 4c8ef33..3d7859f 100644 --- a/chrome/browser/ui/webui/media_router/media_router_ui.h +++ b/chrome/browser/ui/webui/media_router/media_router_ui.h @@ -38,13 +38,13 @@ class MediaRouterWebUIMessageHandler; class MediaRoutesObserver; class MediaSink; class MediaSinksObserver; -class CreatePresentationConnectionRequest; +class CreatePresentationSessionRequest; // Implements the chrome://media-router user interface. -class MediaRouterUI : public ConstrainedWebDialogUI, - public QueryResultManager::Observer, - public PresentationServiceDelegateImpl:: - DefaultPresentationRequestObserver { +class MediaRouterUI + : public ConstrainedWebDialogUI, + public QueryResultManager::Observer, + public PresentationServiceDelegateImpl::DefaultMediaSourceObserver { public: // |web_ui| owns this object and is used to initialize the base class. explicit MediaRouterUI(content::WebUI* web_ui); @@ -79,7 +79,7 @@ class MediaRouterUI : public ConstrainedWebDialogUI, void InitWithPresentationSessionRequest( content::WebContents* initiator, const base::WeakPtr<PresentationServiceDelegateImpl>& delegate, - scoped_ptr<CreatePresentationConnectionRequest> presentation_request); + scoped_ptr<CreatePresentationSessionRequest> presentation_request); // Closes the media router UI. void Close(); @@ -163,17 +163,20 @@ class MediaRouterUI : public ConstrainedWebDialogUI, // Creates and sends an issue if route creation times out. void RouteCreationTimeout(); - // Initializes the dialog with mirroring sources derived from |initiator|. - void InitCommon(content::WebContents* initiator); + // Sets the source host name to be displayed in the UI. + // Gets cast modes from |query_result_manager_| and forwards it to UI. + // One of the Init* functions must have been called before. + void UpdateSourceHostAndCastModes(const GURL& frame_url); - // PresentationServiceDelegateImpl::DefaultPresentationObserver - void OnDefaultPresentationChanged( - const PresentationRequest& presentation_request) override; - void OnDefaultPresentationRemoved() override; + // Initializes the dialog with mirroring sources derived from |initiator|, + // and optional |default_source| and |default_frame_url| if any. + void InitCommon(content::WebContents* initiator, + const MediaSource& default_source, + const GURL& default_frame_url); - // Updates the set of supported cast modes and sends the updated set to - // |handler_|. - void UpdateCastModes(); + // PresentationServiceDelegateImpl::DefaultMediaSourceObserver + void OnDefaultMediaSourceChanged(const MediaSource& source, + const GURL& frame_url) override; // Owned by the |web_ui| passed in the ctor, and guaranteed to be deleted // only after it has deleted |this|. @@ -205,11 +208,7 @@ class MediaRouterUI : public ConstrainedWebDialogUI, // If set, then the result of the next presentation route request will // be handled by this object. - scoped_ptr<CreatePresentationConnectionRequest> create_session_request_; - - // Set to the presentation request corresponding to the presentation cast - // mode, if supported. Otherwise set to nullptr. - scoped_ptr<PresentationRequest> presentation_request_; + scoped_ptr<CreatePresentationSessionRequest> presentation_request_; // It's possible for PresentationServiceDelegateImpl to be destroyed before // this class. diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index cd0acad..7f6712f 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -1432,7 +1432,7 @@ 'browser/supervised_user/legacy/supervised_user_sync_service_unittest.cc', ], 'chrome_unit_tests_media_router_sources': [ - 'browser/media/router/create_presentation_connection_request_unittest.cc', + 'browser/media/router/create_presentation_session_request_unittest.cc', 'browser/media/router/issue_manager_unittest.cc', 'browser/media/router/issue_unittest.cc', 'browser/media/router/media_route_unittest.cc', @@ -1440,7 +1440,6 @@ 'browser/media/router/media_source_helper_unittest.cc', 'browser/media/router/media_source_unittest.cc', 'browser/media/router/presentation_media_sinks_observer_unittest.cc', - 'browser/media/router/presentation_request_unittest.cc', 'browser/media/router/presentation_service_delegate_impl_unittest.cc', 'browser/media/router/presentation_session_state_observer_unittest.cc', ], diff --git a/content/browser/presentation/presentation_service_impl.cc b/content/browser/presentation/presentation_service_impl.cc index 5d20a31..dd5203d 100644 --- a/content/browser/presentation/presentation_service_impl.cc +++ b/content/browser/presentation/presentation_service_impl.cc @@ -224,6 +224,13 @@ void PresentationServiceImpl::StopListeningForScreenAvailability( screen_availability_listeners_.erase(listener_it); } +void PresentationServiceImpl::ListenForDefaultSessionStart( + const DefaultSessionMojoCallback& callback) { + if (!default_session_start_context_.get()) + default_session_start_context_.reset(new DefaultSessionStartContext); + default_session_start_context_->AddCallback(callback); +} + void PresentationServiceImpl::StartSession( const mojo::String& presentation_url, const NewSessionMojoCallback& callback) { @@ -361,12 +368,11 @@ void PresentationServiceImpl::SetDefaultPresentationURL( const std::string& new_default_url = url.get(); if (default_presentation_url_ == new_default_url) return; - - default_presentation_url_ = new_default_url; delegate_->SetDefaultPresentationUrl( - render_process_id_, render_frame_id_, new_default_url, - base::Bind(&PresentationServiceImpl::OnDefaultPresentationStarted, - weak_factory_.GetWeakPtr())); + render_process_id_, + render_frame_id_, + new_default_url); + default_presentation_url_ = new_default_url; } void PresentationServiceImpl::SendSessionMessage( @@ -515,6 +521,8 @@ void PresentationServiceImpl::Reset() { pending_join_session_cbs_.clear(); + default_session_start_context_.reset(); + if (on_session_messages_callback_.get()) { on_session_messages_callback_->Run( mojo::Array<presentation::SessionMessagePtr>()); @@ -536,10 +544,9 @@ void PresentationServiceImpl::OnDelegateDestroyed() { } void PresentationServiceImpl::OnDefaultPresentationStarted( - const PresentationSessionInfo& session_info) { - DCHECK(client_.get()); - client_->OnDefaultSessionStarted( - presentation::PresentationSessionInfo::From(session_info)); + const PresentationSessionInfo& session) { + if (default_session_start_context_.get()) + default_session_start_context_->set_session(session); } PresentationServiceImpl::ScreenAvailabilityListenerImpl @@ -590,4 +597,45 @@ void PresentationServiceImpl::NewSessionMojoCallbackWrapper::Run( callback_.reset(); } +PresentationServiceImpl::DefaultSessionStartContext +::DefaultSessionStartContext() { +} + +PresentationServiceImpl::DefaultSessionStartContext +::~DefaultSessionStartContext() { + Reset(); +} + +void PresentationServiceImpl::DefaultSessionStartContext::AddCallback( + const DefaultSessionMojoCallback& callback) { + if (session_.get()) { + DCHECK(callbacks_.empty()); + callback.Run(presentation::PresentationSessionInfo::From(*session_)); + session_.reset(); + } else { + callbacks_.push_back(new DefaultSessionMojoCallback(callback)); + } +} + +void PresentationServiceImpl::DefaultSessionStartContext::set_session( + const PresentationSessionInfo& session) { + if (callbacks_.empty()) { + session_.reset(new PresentationSessionInfo(session)); + } else { + DCHECK(!session_.get()); + ScopedVector<DefaultSessionMojoCallback> callbacks; + callbacks.swap(callbacks_); + for (const auto& callback : callbacks) + callback->Run(presentation::PresentationSessionInfo::From(session)); + } +} + +void PresentationServiceImpl::DefaultSessionStartContext::Reset() { + ScopedVector<DefaultSessionMojoCallback> callbacks; + callbacks.swap(callbacks_); + for (const auto& callback : callbacks) + callback->Run(presentation::PresentationSessionInfoPtr()); + session_.reset(); +} + } // namespace content diff --git a/content/browser/presentation/presentation_service_impl.h b/content/browser/presentation/presentation_service_impl.h index 54e1a4c..220c256 100644 --- a/content/browser/presentation/presentation_service_impl.h +++ b/content/browser/presentation/presentation_service_impl.h @@ -94,7 +94,7 @@ class CONTENT_EXPORT PresentationServiceImpl // Maximum number of pending JoinSession requests at any given time. static const int kMaxNumQueuedSessionRequests = 10; - using PresentationSessionMojoCallback = + using DefaultSessionMojoCallback = mojo::Callback<void(presentation::PresentationSessionInfoPtr)>; using SessionStateCallback = mojo::Callback<void(presentation::PresentationSessionInfoPtr, @@ -125,6 +125,27 @@ class CONTENT_EXPORT PresentationServiceImpl PresentationServiceImpl* const service_; }; + class CONTENT_EXPORT DefaultSessionStartContext { + public: + DefaultSessionStartContext(); + ~DefaultSessionStartContext(); + + // Adds a callback. May invoke the callback immediately if |session| using + // default presentation URL was already started. + void AddCallback(const DefaultSessionMojoCallback& callback); + + // Sets the session info. Maybe invoke callbacks queued with AddCallback(). + void set_session(const PresentationSessionInfo& session); + + private: + // Flush all queued callbacks by invoking them with null + // PresentationSessionInfoPtr. + void Reset(); + + ScopedVector<DefaultSessionMojoCallback> callbacks_; + scoped_ptr<PresentationSessionInfo> session_; + }; + // Ensures the provided NewSessionMojoCallback is invoked exactly once // before it goes out of scope. class NewSessionMojoCallbackWrapper { @@ -156,6 +177,8 @@ class CONTENT_EXPORT PresentationServiceImpl void SetClient(presentation::PresentationServiceClientPtr client) override; void ListenForScreenAvailability(const mojo::String& url) override; void StopListeningForScreenAvailability(const mojo::String& url) override; + void ListenForDefaultSessionStart( + const DefaultSessionMojoCallback& callback) override; void StartSession( const mojo::String& presentation_url, const NewSessionMojoCallback& callback) override; @@ -185,11 +208,8 @@ class CONTENT_EXPORT PresentationServiceImpl // PresentationServiceDelegate::Observer void OnDelegateDestroyed() override; - - // Passed to embedder's implementation of PresentationServiceDelegate for - // later invocation when default presentation has started. - void OnDefaultPresentationStarted( - const PresentationSessionInfo& session_info); + void OnDefaultPresentationStarted(const PresentationSessionInfo& session) + override; // Finds the callback from |pending_join_session_cbs_| using // |request_session_id|. @@ -264,6 +284,8 @@ class CONTENT_EXPORT PresentationServiceImpl base::hash_map<int, linked_ptr<NewSessionMojoCallbackWrapper>> pending_join_session_cbs_; + scoped_ptr<DefaultSessionStartContext> default_session_start_context_; + // RAII binding of |this| to an Presentation interface request. // The binding is removed when binding_ is cleared or goes out of scope. scoped_ptr<mojo::Binding<presentation::PresentationService>> binding_; diff --git a/content/browser/presentation/presentation_service_impl_unittest.cc b/content/browser/presentation/presentation_service_impl_unittest.cc index b85fc84..3716586 100644 --- a/content/browser/presentation/presentation_service_impl_unittest.cc +++ b/content/browser/presentation/presentation_service_impl_unittest.cc @@ -41,6 +41,12 @@ MATCHER_P(Equals, expected, "") { const char *const kPresentationId = "presentationId"; const char *const kPresentationUrl = "http://foo.com/index.html"; +bool ArePresentationSessionsEqual( + const presentation::PresentationSessionInfo& expected, + const presentation::PresentationSessionInfo& actual) { + return expected.url == actual.url && expected.id == actual.id; +} + bool ArePresentationSessionMessagesEqual( const presentation::SessionMessage* expected, const presentation::SessionMessage* actual) { @@ -85,24 +91,26 @@ class MockPresentationServiceDelegate : public PresentationServiceDelegate { void( int render_process_id, int routing_id)); - MOCK_METHOD4(SetDefaultPresentationUrl, - void(int render_process_id, - int routing_id, - const std::string& default_presentation_url, - const PresentationSessionStartedCallback& callback)); + MOCK_METHOD3(SetDefaultPresentationUrl, + void( + int render_process_id, + int routing_id, + const std::string& default_presentation_url)); MOCK_METHOD5(StartSession, - void(int render_process_id, - int render_frame_id, - const std::string& presentation_url, - const PresentationSessionStartedCallback& success_cb, - const PresentationSessionErrorCallback& error_cb)); + void( + int render_process_id, + int render_frame_id, + const std::string& presentation_url, + const PresentationSessionSuccessCallback& success_cb, + const PresentationSessionErrorCallback& error_cb)); MOCK_METHOD6(JoinSession, - void(int render_process_id, - int render_frame_id, - const std::string& presentation_url, - const std::string& presentation_id, - const PresentationSessionStartedCallback& success_cb, - const PresentationSessionErrorCallback& error_cb)); + void( + int render_process_id, + int render_frame_id, + const std::string& presentation_url, + const std::string& presentation_id, + const PresentationSessionSuccessCallback& success_cb, + const PresentationSessionErrorCallback& error_cb)); MOCK_METHOD3(CloseSession, void(int render_process_id, int render_frame_id, @@ -164,13 +172,6 @@ class MockPresentationServiceClient : } MOCK_METHOD0(MessagesReceived, void()); - void OnDefaultSessionStarted( - presentation::PresentationSessionInfoPtr session_info) override { - OnDefaultSessionStarted(*session_info); - } - MOCK_METHOD1(OnDefaultSessionStarted, - void(const presentation::PresentationSessionInfo& session_info)); - mojo::Array<presentation::SessionMessagePtr> messages_received_; }; @@ -256,6 +257,7 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness { EXPECT_EQ( service_impl_->screen_availability_listeners_.find(kPresentationUrl), service_impl_->screen_availability_listeners_.end()); + EXPECT_FALSE(service_impl_->default_session_start_context_.get()); EXPECT_FALSE(service_impl_->on_session_messages_callback_.get()); } @@ -277,6 +279,25 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness { run_loop_quit_closure_.Run(); } + void ExpectDefaultSessionStarted( + const presentation::PresentationSessionInfo& expected_session, + presentation::PresentationSessionInfoPtr actual_session) { + ASSERT_TRUE(!actual_session.is_null()); + EXPECT_TRUE(ArePresentationSessionsEqual( + expected_session, *actual_session)); + ++default_session_started_count_; + if (!run_loop_quit_closure_.is_null()) + run_loop_quit_closure_.Run(); + } + + void ExpectDefaultSessionNull( + presentation::PresentationSessionInfoPtr actual_session) { + EXPECT_TRUE(actual_session.is_null()); + ++default_session_started_count_; + if (!run_loop_quit_closure_.is_null()) + run_loop_quit_closure_.Run(); + } + void ExpectSessionMessages( const mojo::Array<presentation::SessionMessagePtr>& expected_msgs, const mojo::Array<presentation::SessionMessagePtr>& actual_msgs) { @@ -429,30 +450,24 @@ TEST_F(PresentationServiceImplTest, DelegateFails) { TEST_F(PresentationServiceImplTest, SetDefaultPresentationUrl) { std::string url1("http://fooUrl"); - EXPECT_CALL(mock_delegate_, SetDefaultPresentationUrl(_, _, Eq(url1), _)) + EXPECT_CALL(mock_delegate_, + SetDefaultPresentationUrl(_, _, Eq(url1))) .Times(1); service_impl_->SetDefaultPresentationURL(url1); EXPECT_EQ(url1, service_impl_->default_presentation_url_); std::string url2("http://barUrl"); // Sets different DPU. - content::PresentationSessionStartedCallback callback; - EXPECT_CALL(mock_delegate_, SetDefaultPresentationUrl(_, _, Eq(url2), _)) - .WillOnce(SaveArg<3>(&callback)); + EXPECT_CALL(mock_delegate_, + SetDefaultPresentationUrl(_, _, Eq(url2))) + .Times(1); service_impl_->SetDefaultPresentationURL(url2); EXPECT_EQ(url2, service_impl_->default_presentation_url_); - - presentation::PresentationSessionInfo session_info; - session_info.url = url2; - session_info.id = kPresentationId; - EXPECT_CALL(mock_client_, OnDefaultSessionStarted(Equals(session_info))) - .Times(1); - callback.Run(content::PresentationSessionInfo(url2, kPresentationId)); } TEST_F(PresentationServiceImplTest, SetSameDefaultPresentationUrl) { EXPECT_CALL(mock_delegate_, - SetDefaultPresentationUrl(_, _, Eq(kPresentationUrl), _)) + SetDefaultPresentationUrl(_, _, Eq(kPresentationUrl))) .Times(1); service_impl_->SetDefaultPresentationURL(kPresentationUrl); EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_delegate_)); @@ -577,6 +592,59 @@ TEST_F(PresentationServiceImplTest, StartSessionInProgress) { SaveQuitClosureAndRunLoop(); } +TEST_F(PresentationServiceImplTest, ListenForDefaultSessionStart) { + presentation::PresentationSessionInfo expected_session; + expected_session.url = kPresentationUrl; + expected_session.id = kPresentationId; + service_ptr_->ListenForDefaultSessionStart( + base::Bind(&PresentationServiceImplTest::ExpectDefaultSessionStarted, + base::Unretained(this), + expected_session)); + RunLoopFor(base::TimeDelta::FromMilliseconds(50)); + service_impl_->OnDefaultPresentationStarted( + content::PresentationSessionInfo(kPresentationUrl, kPresentationId)); + SaveQuitClosureAndRunLoop(); + EXPECT_EQ(1, default_session_started_count_); +} + +TEST_F(PresentationServiceImplTest, ListenForDefaultSessionStartAfterSet) { + // Note that the callback will only pick up presentation_url2/id2 since + // ListenForDefaultSessionStart wasn't called yet when the DPU was still + // presentation_url1. + std::string presentation_url1("http://fooUrl1"); + std::string presentation_id1("presentationId1"); + std::string presentation_url2("http://fooUrl2"); + std::string presentation_id2("presentationId2"); + service_impl_->OnDefaultPresentationStarted( + content::PresentationSessionInfo(presentation_url1, presentation_id1)); + + presentation::PresentationSessionInfo expected_session; + expected_session.url = presentation_url2; + expected_session.id = presentation_id2; + service_ptr_->ListenForDefaultSessionStart( + base::Bind(&PresentationServiceImplTest::ExpectDefaultSessionStarted, + base::Unretained(this), + expected_session)); + RunLoopFor(base::TimeDelta::FromMilliseconds(50)); + service_impl_->OnDefaultPresentationStarted( + content::PresentationSessionInfo(presentation_url2, presentation_id2)); + SaveQuitClosureAndRunLoop(); + EXPECT_EQ(1, default_session_started_count_); +} + +TEST_F(PresentationServiceImplTest, DefaultSessionStartReset) { + service_ptr_->ListenForDefaultSessionStart( + base::Bind(&PresentationServiceImplTest::ExpectDefaultSessionNull, + base::Unretained(this))); + RunLoopFor(TestTimeouts::tiny_timeout()); + + ExpectReset(); + service_impl_->Reset(); + ExpectCleanState(); + SaveQuitClosureAndRunLoop(); + EXPECT_EQ(1, default_session_started_count_); +} + TEST_F(PresentationServiceImplTest, SendStringMessage) { std::string message("Test presentation session message"); diff --git a/content/common/presentation/presentation_service.mojom b/content/common/presentation/presentation_service.mojom index 422ae58..3256a96 100644 --- a/content/common/presentation/presentation_service.mojom +++ b/content/common/presentation/presentation_service.mojom @@ -42,14 +42,12 @@ struct SessionMessage { }; interface PresentationService { - // Sets the PresentationServiceClient. - SetClient(PresentationServiceClient client); - // Called when the frame sets or changes the default presentation URL. - // When the default presentation is started on this frame, - // PresentationServiceClient::OnDefaultSessionStarted will be invoked. SetDefaultPresentationURL(string url); + // Sets the PresentationServiceClient. + SetClient(PresentationServiceClient client); + // Starts listening for screen availability for presentation of // |url|. Availability results will be returned to the client via // PresentationServiceClient::OnScreenAvailabilityUpdated. @@ -60,6 +58,13 @@ interface PresentationService { // |url|. StopListeningForScreenAvailability(string url); + // Called when the renderer is ready to receive the browser initiated + // session. If the default session is started by the embedder before this + // call, the embedder may queue it and run the callback when the call is + // performed. + ListenForDefaultSessionStart() + => (PresentationSessionInfo? defaultSessionInfo); + // Called when startSession() is called by the frame. The result callback // will return a non-null and valid PresentationSessionInfo if starting the // session succeeded, or null with a PresentationError if starting the @@ -84,8 +89,7 @@ interface PresentationService { // The false in the result callback notifies the renderer to stop sending // the send requests and invalidate all pending requests. This occurs // for eg., when frame is deleted or navigated away. - SendSessionMessage(PresentationSessionInfo sessionInfo, - SessionMessage message_request) => (bool success); + SendSessionMessage(PresentationSessionInfo sessionInfo, SessionMessage message_request) => (bool success); // Called when closeSession() is called by the frame. CloseSession(string presentation_url, string presentation_id); @@ -121,9 +125,5 @@ interface PresentationServiceClient { PresentationConnectionState newState); // See PresentationService::ListenForSessionMessages. - OnSessionMessagesReceived(PresentationSessionInfo sessionInfo, - array<SessionMessage> messages); - - // See PresentationService::SetDefaultPresentationURL. - OnDefaultSessionStarted(PresentationSessionInfo sessionInfo); -}; + OnSessionMessagesReceived(PresentationSessionInfo sessionInfo, array<SessionMessage> messages); +}; diff --git a/content/public/browser/presentation_service_delegate.h b/content/public/browser/presentation_service_delegate.h index ba0bf99..5c4e5c8 100644 --- a/content/public/browser/presentation_service_delegate.h +++ b/content/public/browser/presentation_service_delegate.h @@ -19,10 +19,6 @@ namespace content { class PresentationScreenAvailabilityListener; -using PresentationSessionStartedCallback = - base::Callback<void(const PresentationSessionInfo&)>; -using PresentationSessionErrorCallback = - base::Callback<void(const PresentationError&)>; using SessionStateChangedCallback = base::Callback<void(const PresentationSessionInfo&, PresentationConnectionState)>; @@ -43,10 +39,21 @@ class CONTENT_EXPORT PresentationServiceDelegate { // Called when the PresentationServiceDelegate is being destroyed. virtual void OnDelegateDestroyed() = 0; + // Called when the default presentation has been started outside of a + // Presentation API context (e.g., browser action). This will not be called + // if the session was created as a result of Presentation API's + // StartSession()/JoinSession(). + virtual void OnDefaultPresentationStarted( + const PresentationSessionInfo& session) = 0; + protected: virtual ~Observer() {} }; + using PresentationSessionSuccessCallback = + base::Callback<void(const PresentationSessionInfo&)>; + using PresentationSessionErrorCallback = + base::Callback<void(const PresentationError&)>; using SendMessageCallback = base::Callback<void(bool)>; virtual ~PresentationServiceDelegate() {} @@ -94,16 +101,13 @@ class CONTENT_EXPORT PresentationServiceDelegate { int render_frame_id) = 0; // Sets the default presentation URL for frame given by |render_process_id| - // and |render_frame_id|. When the default presentation is started on this - // frame, |callback| will be invoked with the corresponding - // PresentationSessionInfo object. + // and |render_frame_id|. // If |default_presentation_url| is empty, the default presentation URL will - // be cleared and the previously registered callback (if any) will be removed. + // be cleared. virtual void SetDefaultPresentationUrl( int render_process_id, int render_frame_id, - const std::string& default_presentation_url, - const PresentationSessionStartedCallback& callback) = 0; + const std::string& default_presentation_url) = 0; // Starts a new presentation session. The presentation id of the session will // be the default presentation ID if any or a generated one otherwise. @@ -119,7 +123,7 @@ class CONTENT_EXPORT PresentationServiceDelegate { int render_process_id, int render_frame_id, const std::string& presentation_url, - const PresentationSessionStartedCallback& success_cb, + const PresentationSessionSuccessCallback& success_cb, const PresentationSessionErrorCallback& error_cb) = 0; // Joins an existing presentation session. Unlike StartSession(), this @@ -135,7 +139,7 @@ class CONTENT_EXPORT PresentationServiceDelegate { int render_frame_id, const std::string& presentation_url, const std::string& presentation_id, - const PresentationSessionStartedCallback& success_cb, + const PresentationSessionSuccessCallback& success_cb, const PresentationSessionErrorCallback& error_cb) = 0; // Close an existing presentation session. diff --git a/content/renderer/presentation/presentation_dispatcher.cc b/content/renderer/presentation/presentation_dispatcher.cc index 1a249e8..9eb9c67 100644 --- a/content/renderer/presentation/presentation_dispatcher.cc +++ b/content/renderer/presentation/presentation_dispatcher.cc @@ -337,6 +337,11 @@ void PresentationDispatcher::OnDefaultSessionStarted( if (!controller_) return; + // Reset the callback to get the next event. + presentation_service_->ListenForDefaultSessionStart(base::Bind( + &PresentationDispatcher::OnDefaultSessionStarted, + base::Unretained(this))); + if (!session_info.is_null()) { controller_->didStartDefaultSession( new PresentationConnectionClient(session_info.Clone())); @@ -421,6 +426,9 @@ void PresentationDispatcher::ConnectToPresentationServiceIfNeeded() { binding_.Bind(GetProxy(&client_ptr)); presentation_service_->SetClient(client_ptr.Pass()); + presentation_service_->ListenForDefaultSessionStart(base::Bind( + &PresentationDispatcher::OnDefaultSessionStarted, + base::Unretained(this))); presentation_service_->ListenForSessionStateChange(); } diff --git a/content/renderer/presentation/presentation_dispatcher.h b/content/renderer/presentation/presentation_dispatcher.h index 7311329..54c259b 100644 --- a/content/renderer/presentation/presentation_dispatcher.h +++ b/content/renderer/presentation/presentation_dispatcher.h @@ -100,13 +100,13 @@ class CONTENT_EXPORT PresentationDispatcher void OnSessionMessagesReceived( presentation::PresentationSessionInfoPtr session_info, mojo::Array<presentation::SessionMessagePtr> messages) override; - void OnDefaultSessionStarted( - presentation::PresentationSessionInfoPtr session_info) override; void OnSessionCreated( blink::WebPresentationConnectionClientCallbacks* callback, presentation::PresentationSessionInfoPtr session_info, presentation::PresentationErrorPtr error); + void OnDefaultSessionStarted( + presentation::PresentationSessionInfoPtr session_info); // Call to PresentationService to send the message in |request|. // |session_info| and |message| of |reuqest| will be consumed. |