diff options
77 files changed, 1071 insertions, 1051 deletions
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc index 91f5c76..7904696 100644 --- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc +++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc @@ -17,6 +17,7 @@ #include "chrome/browser/ui/host_desktop.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/api/tabs.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" @@ -52,9 +53,7 @@ void DesktopCaptureChooseDesktopMediaFunction::SetPickerFactoryForTests( } DesktopCaptureChooseDesktopMediaFunction:: - DesktopCaptureChooseDesktopMediaFunction() - : render_process_id_(0), - render_view_id_(0) { + DesktopCaptureChooseDesktopMediaFunction() { } DesktopCaptureChooseDesktopMediaFunction:: @@ -90,8 +89,8 @@ bool DesktopCaptureChooseDesktopMediaFunction::RunAsync() { DesktopCaptureRequestsRegistry::GetInstance()->AddRequest( render_view_host()->GetProcess()->GetID(), request_id_, this); - gfx::NativeWindow parent_window = NULL; - content::RenderViewHost* render_view = NULL; + // |web_contents| is the WebContents for which the stream is created, and will + // also be used to determine where to show the picker's UI. content::WebContents* web_contents = NULL; base::string16 target_name; if (params->target_tab) { @@ -120,37 +119,21 @@ bool DesktopCaptureChooseDesktopMediaFunction::RunAsync() { error_ = kInvalidTabIdError; return false; } + DCHECK(web_contents); - GURL current_origin_ = - web_contents->GetLastCommittedURL().GetOrigin(); - if (current_origin_ != origin_) { + if (origin_ != web_contents->GetLastCommittedURL().GetOrigin()) { error_ = kTabUrlChangedError; return false; } - - // Register to be notified when the tab is closed. - Observe(web_contents); - - render_view = web_contents->GetRenderViewHost(); - parent_window = web_contents->GetTopLevelNativeWindow(); } else { origin_ = GetExtension()->url(); target_name = base::UTF8ToUTF16(GetExtension()->name()); - render_view = render_view_host(); - - web_contents = GetAssociatedWebContents(); - if (web_contents) { - parent_window = web_contents->GetTopLevelNativeWindow(); - } else { -#if defined(USE_ASH) - if (chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH) - parent_window = ash::Shell::GetPrimaryRootWindow(); -#endif - } + web_contents = content::WebContents::FromRenderViewHost(render_view_host()); + DCHECK(web_contents); } - render_process_id_ = render_view->GetProcess()->GetID(); - render_view_id_ = render_view->GetRoutingID(); + // Register to be notified when the tab is closed. + Observe(web_contents); bool show_screens = false; bool show_windows = false; @@ -181,6 +164,8 @@ bool DesktopCaptureChooseDesktopMediaFunction::RunAsync() { return false; } + const gfx::NativeWindow parent_window = + web_contents->GetTopLevelNativeWindow(); scoped_ptr<DesktopMediaList> media_list; if (g_picker_factory) { media_list = g_picker_factory->CreateModel( @@ -234,13 +219,20 @@ void DesktopCaptureChooseDesktopMediaFunction::WebContentsDestroyed() { void DesktopCaptureChooseDesktopMediaFunction::OnPickerDialogResults( content::DesktopMediaID source) { std::string result; - if (source.type != content::DesktopMediaID::TYPE_NONE) { + if (source.type != content::DesktopMediaID::TYPE_NONE && + web_contents()) { DesktopStreamsRegistry* registry = MediaCaptureDevicesDispatcher::GetInstance()-> GetDesktopStreamsRegistry(); + // TODO(miu): Once render_frame_host() is being set, we should register the + // exact RenderFrame requesting the stream, not the main RenderFrame. With + // that change, also update + // MediaCaptureDevicesDispatcher::ProcessDesktopCaptureAccessRequest(). + // http://crbug.com/304341 + content::RenderFrameHost* const main_frame = web_contents()->GetMainFrame(); result = registry->RegisterStream( - render_process_id_, - render_view_id_, + main_frame->GetProcess()->GetID(), + main_frame->GetRoutingID(), origin_, source, GetExtension()->name()); diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h index 7c3af4b..475edf9 100644 --- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h +++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h @@ -58,9 +58,7 @@ class DesktopCaptureChooseDesktopMediaFunction int request_id_; - // Parameters of the tab the stream is requested for. - int render_process_id_; - int render_view_id_; + // URL of page that desktop capture was requested for. GURL origin_; scoped_ptr<DesktopMediaPicker> picker_; diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc index c88fbc9..82f528d 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc @@ -16,12 +16,12 @@ #include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h" #include "chrome/browser/extensions/extension_renderer_state.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sessions/session_tab_helper.h" +#include "chrome/browser/sessions/session_id.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" -#include "content/public/browser/render_view_host.h" #include "extensions/common/features/feature.h" #include "extensions/common/features/feature_provider.h" #include "extensions/common/features/simple_feature.h" @@ -85,12 +85,11 @@ bool TabCaptureCaptureFunction::RunSync() { const Extension* extension = GetExtension(); const std::string& extension_id = extension->id(); - const int tab_id = SessionID::IdForTab(target_contents); - // Make sure either we have been granted permission to capture through an // extension icon click or our extension is whitelisted. if (!extension->permissions_data()->HasAPIPermissionForTab( - tab_id, APIPermission::kTabCaptureForTab) && + SessionID::IdForTab(target_contents), + APIPermission::kTabCaptureForTab) && CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kWhitelistedExtensionID) != extension_id && !SimpleFeature::IsIdInList( @@ -102,10 +101,6 @@ bool TabCaptureCaptureFunction::RunSync() { return false; } - content::RenderViewHost* const rvh = target_contents->GetRenderViewHost(); - int render_process_id = rvh->GetProcess()->GetID(); - int routing_id = rvh->GetRoutingID(); - // Create a constraints vector. We will modify all the constraints in this // vector to append our chrome specific constraints. std::vector<MediaStreamConstraint*> constraints; @@ -131,8 +126,13 @@ bool TabCaptureCaptureFunction::RunSync() { } // Device id we use for Tab Capture. - std::string device_id = - base::StringPrintf("%i:%i", render_process_id, routing_id); + content::RenderFrameHost* const main_frame = target_contents->GetMainFrame(); + // TODO(miu): We should instead use a "randomly generated device ID" scheme, + // like that employed by the desktop capture API. http://crbug.com/163100 + const std::string device_id = base::StringPrintf( + "web-contents-media-stream://%i:%i", + main_frame->GetProcess()->GetID(), + main_frame->GetRoutingID()); // Append chrome specific tab constraints. for (std::vector<MediaStreamConstraint*>::iterator it = constraints.begin(); @@ -144,11 +144,7 @@ bool TabCaptureCaptureFunction::RunSync() { extensions::TabCaptureRegistry* registry = extensions::TabCaptureRegistry::Get(GetProfile()); - if (!registry->AddRequest(render_process_id, - routing_id, - extension_id, - tab_id, - tab_capture::TAB_CAPTURE_STATE_NONE)) { + if (!registry->AddRequest(target_contents, extension_id)) { error_ = kCapturingSameTab; return false; } @@ -166,19 +162,9 @@ bool TabCaptureCaptureFunction::RunSync() { bool TabCaptureGetCapturedTabsFunction::RunSync() { extensions::TabCaptureRegistry* registry = extensions::TabCaptureRegistry::Get(GetProfile()); - - const TabCaptureRegistry::RegistryCaptureInfo& captured_tabs = - registry->GetCapturedTabs(GetExtension()->id()); - - base::ListValue *list = new base::ListValue(); - for (TabCaptureRegistry::RegistryCaptureInfo::const_iterator it = - captured_tabs.begin(); it != captured_tabs.end(); ++it) { - scoped_ptr<tab_capture::CaptureInfo> info(new tab_capture::CaptureInfo()); - info->tab_id = it->first; - info->status = it->second; - list->Append(info->ToValue().release()); - } - + base::ListValue* const list = new base::ListValue(); + if (registry) + registry->GetCapturedTabs(GetExtension()->id(), list); SetResult(list); return true; } diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc index 9af7934..bbca11a 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc @@ -11,8 +11,8 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/fullscreen/fullscreen_controller.h" #include "chrome/common/chrome_version_info.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" -#include "content/public/browser/render_view_host.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/switches.h" @@ -119,11 +119,11 @@ IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, MAYBE_GetUserMediaTest) { content::PAGE_TRANSITION_LINK, false); content::WebContents* web_contents = browser()->OpenURL(params); - content::RenderViewHost* const rvh = web_contents->GetRenderViewHost(); - int render_process_id = rvh->GetProcess()->GetID(); - int routing_id = rvh->GetRoutingID(); - - listener.Reply(base::StringPrintf("%i:%i", render_process_id, routing_id)); + content::RenderFrameHost* const main_frame = web_contents->GetMainFrame(); + ASSERT_TRUE(main_frame); + listener.Reply(base::StringPrintf("web-contents-media-stream://%i:%i", + main_frame->GetProcess()->GetID(), + main_frame->GetRoutingID())); ResultCatcher catcher; catcher.RestrictToProfile(browser()->profile()); diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc index 2159f52..c76694c 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc @@ -21,8 +21,6 @@ #include "chrome/test/base/test_launcher_utils.h" #include "chrome/test/base/test_switches.h" #include "chrome/test/base/tracing.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/render_view_host.h" #include "content/public/common/content_switches.h" #include "extensions/common/feature_switch.h" #include "extensions/common/features/base_feature_provider.h" diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc index 1526b7d..fa2cc8b 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc @@ -5,14 +5,11 @@ #include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h" #include "base/lazy_instance.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/ui/fullscreen/fullscreen_controller.h" +#include "base/values.h" +#include "chrome/browser/sessions/session_id.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/notification_details.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" -#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "extensions/browser/event_router.h" @@ -26,89 +23,123 @@ namespace extensions { namespace tab_capture = api::tab_capture; -class FullscreenObserver : public content::WebContentsObserver { +// Stores values associated with a tab capture request, maintains lifecycle +// state, and monitors WebContents for fullscreen transition events and +// destruction. +class TabCaptureRegistry::LiveRequest : public content::WebContentsObserver { public: - FullscreenObserver(TabCaptureRequest* request, - const TabCaptureRegistry* registry); - virtual ~FullscreenObserver() {} + LiveRequest(content::WebContents* target_contents, + const std::string& extension_id, + TabCaptureRegistry* registry) + : content::WebContentsObserver(target_contents), + extension_id_(extension_id), + registry_(registry), + capture_state_(tab_capture::TAB_CAPTURE_STATE_NONE), + is_verified_(false), + // TODO(miu): This initial value for |is_fullscreened_| is a faulty + // assumption. http://crbug.com/350491 + is_fullscreened_(false), + render_process_id_(-1), + render_frame_id_(-1) { + DCHECK(web_contents()); + DCHECK(registry_); + } - private: - // content::WebContentsObserver implementation. - virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE; - virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE; + virtual ~LiveRequest() {} - TabCaptureRequest* request_; - const TabCaptureRegistry* registry_; + // Accessors. + const content::WebContents* target_contents() const { + return content::WebContentsObserver::web_contents(); + } + const std::string& extension_id() const { + return extension_id_; + } + TabCaptureState capture_state() const { + return capture_state_; + } + bool is_verified() const { + return is_verified_; + } - DISALLOW_COPY_AND_ASSIGN(FullscreenObserver); -}; + void SetIsVerified() { + DCHECK(!is_verified_); + is_verified_ = true; + } -// Holds all the state related to a tab capture stream. -struct TabCaptureRequest { - TabCaptureRequest(int render_process_id, - int render_view_id, - const std::string& extension_id, - int tab_id, - TabCaptureState status); - ~TabCaptureRequest(); - - const int render_process_id; - const int render_view_id; - const std::string extension_id; - const int tab_id; - TabCaptureState status; - TabCaptureState last_status; - bool fullscreen; - scoped_ptr<FullscreenObserver> fullscreen_observer; -}; + // TODO(miu): See TODO(miu) in VerifyRequest() below. + void SetOriginallyTargettedRenderFrameID(int render_process_id, + int render_frame_id) { + DCHECK_GT(render_frame_id, 0); + DCHECK_EQ(render_frame_id_, -1); // Setting ID only once. + render_process_id_ = render_process_id; + render_frame_id_ = render_frame_id; + } -FullscreenObserver::FullscreenObserver( - TabCaptureRequest* request, - const TabCaptureRegistry* registry) - : request_(request), - registry_(registry) { - content::RenderViewHost* const rvh = - content::RenderViewHost::FromID(request->render_process_id, - request->render_view_id); - Observe(rvh ? content::WebContents::FromRenderViewHost(rvh) : NULL); -} + bool WasOriginallyTargettingRenderFrameID(int render_process_id, + int render_frame_id) const { + return render_process_id_ == render_process_id && + render_frame_id_ == render_frame_id; + } -void FullscreenObserver::DidShowFullscreenWidget( - int routing_id) { - request_->fullscreen = true; - registry_->DispatchStatusChangeEvent(request_); -} + void UpdateCaptureState(TabCaptureState next_capture_state) { + // This method can get duplicate calls if both audio and video were + // requested, so return early to avoid duplicate dispatching of status + // change events. + if (capture_state_ == next_capture_state) + return; -void FullscreenObserver::DidDestroyFullscreenWidget( - int routing_id) { - request_->fullscreen = false; - registry_->DispatchStatusChangeEvent(request_); -} + capture_state_ = next_capture_state; + registry_->DispatchStatusChangeEvent(this); + } -TabCaptureRequest::TabCaptureRequest( - int render_process_id, - int render_view_id, - const std::string& extension_id, - const int tab_id, - TabCaptureState status) - : render_process_id(render_process_id), - render_view_id(render_view_id), - extension_id(extension_id), - tab_id(tab_id), - status(status), - last_status(status), - fullscreen(false) { -} + void GetCaptureInfo(tab_capture::CaptureInfo* info) const { + info->tab_id = SessionID::IdForTab(web_contents()); + info->status = capture_state_; + info->fullscreen = is_fullscreened_; + } -TabCaptureRequest::~TabCaptureRequest() { -} + protected: + virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE { + is_fullscreened_ = true; + if (capture_state_ == tab_capture::TAB_CAPTURE_STATE_ACTIVE) + registry_->DispatchStatusChangeEvent(this); + } + + virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE { + is_fullscreened_ = false; + if (capture_state_ == tab_capture::TAB_CAPTURE_STATE_ACTIVE) + registry_->DispatchStatusChangeEvent(this); + } + + virtual void DidToggleFullscreenModeForTab(bool entered_fullscreen) OVERRIDE { + is_fullscreened_ = entered_fullscreen; + if (capture_state_ == tab_capture::TAB_CAPTURE_STATE_ACTIVE) + registry_->DispatchStatusChangeEvent(this); + } + + virtual void WebContentsDestroyed() OVERRIDE { + registry_->KillRequest(this); // Deletes |this|. + } + + private: + const std::string extension_id_; + TabCaptureRegistry* const registry_; + TabCaptureState capture_state_; + bool is_verified_; + bool is_fullscreened_; + + // These reference the originally targetted RenderFrameHost by its ID. The + // RenderFrameHost may have gone away long before a LiveRequest closes, but + // calls to OnRequestUpdate() will always refer to this request by this ID. + int render_process_id_; + int render_frame_id_; + + DISALLOW_COPY_AND_ASSIGN(LiveRequest); +}; TabCaptureRegistry::TabCaptureRegistry(content::BrowserContext* context) : browser_context_(context), extension_registry_observer_(this) { MediaCaptureDevicesDispatcher::GetInstance()->AddObserver(this); - registrar_.Add(this, - chrome::NOTIFICATION_FULLSCREEN_CHANGED, - content::NotificationService::AllSources()); extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); } @@ -130,53 +161,18 @@ TabCaptureRegistry::GetFactoryInstance() { return g_factory.Pointer(); } -const TabCaptureRegistry::RegistryCaptureInfo - TabCaptureRegistry::GetCapturedTabs(const std::string& extension_id) const { +void TabCaptureRegistry::GetCapturedTabs( + const std::string& extension_id, + base::ListValue* list_of_capture_info) const { DCHECK_CURRENTLY_ON(BrowserThread::UI); - RegistryCaptureInfo list; - for (ScopedVector<TabCaptureRequest>::const_iterator it = requests_.begin(); + DCHECK(list_of_capture_info); + list_of_capture_info->Clear(); + for (ScopedVector<LiveRequest>::const_iterator it = requests_.begin(); it != requests_.end(); ++it) { - if ((*it)->extension_id == extension_id) { - list.push_back(std::make_pair((*it)->tab_id, (*it)->status)); - } - } - return list; -} - -void TabCaptureRegistry::Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK_EQ(chrome::NOTIFICATION_FULLSCREEN_CHANGED, type); - FullscreenController* fullscreen_controller = - content::Source<FullscreenController>(source).ptr(); - const bool is_fullscreen = *content::Details<bool>(details).ptr(); - for (ScopedVector<TabCaptureRequest>::iterator it = requests_.begin(); - it != requests_.end(); - ++it) { - // If we are exiting fullscreen mode, we only need to check if any of - // the requests had the fullscreen flag toggled previously. The - // fullscreen controller no longer has the reference to the fullscreen - // web_contents here. - if (!is_fullscreen) { - if ((*it)->fullscreen) { - (*it)->fullscreen = false; - DispatchStatusChangeEvent(*it); - break; - } - continue; - } - - // If we are entering fullscreen mode, find whether the web_contents we - // are capturing entered fullscreen mode. - content::RenderViewHost* const rvh = content::RenderViewHost::FromID( - (*it)->render_process_id, (*it)->render_view_id); - if (rvh && - fullscreen_controller->IsFullscreenForTabOrPending( - content::WebContents::FromRenderViewHost(rvh))) { - (*it)->fullscreen = true; - DispatchStatusChangeEvent(*it); - break; + if ((*it)->is_verified() && (*it)->extension_id() == extension_id) { + tab_capture::CaptureInfo info; + (*it)->GetCaptureInfo(&info); + list_of_capture_info->Append(info.ToValue().release()); } } } @@ -186,9 +182,9 @@ void TabCaptureRegistry::OnExtensionUnloaded( const Extension* extension, UnloadedExtensionInfo::Reason reason) { // Cleanup all the requested media streams for this extension. - for (ScopedVector<TabCaptureRequest>::iterator it = requests_.begin(); + for (ScopedVector<LiveRequest>::iterator it = requests_.begin(); it != requests_.end();) { - if ((*it)->extension_id == extension->id()) { + if ((*it)->extension_id() == extension->id()) { it = requests_.erase(it); } else { ++it; @@ -196,78 +192,96 @@ void TabCaptureRegistry::OnExtensionUnloaded( } } -bool TabCaptureRegistry::AddRequest(int render_process_id, - int render_view_id, - const std::string& extension_id, - int tab_id, - TabCaptureState status) { - TabCaptureRequest* request = FindCaptureRequest(render_process_id, - render_view_id); +bool TabCaptureRegistry::AddRequest(content::WebContents* target_contents, + const std::string& extension_id) { + LiveRequest* const request = FindRequest(target_contents); + // Currently, we do not allow multiple active captures for same tab. if (request != NULL) { - if (request->status != tab_capture::TAB_CAPTURE_STATE_STOPPED && - request->status != tab_capture::TAB_CAPTURE_STATE_ERROR) { + if (request->capture_state() != tab_capture::TAB_CAPTURE_STATE_STOPPED && + request->capture_state() != tab_capture::TAB_CAPTURE_STATE_ERROR) { return false; } else { - DeleteCaptureRequest(render_process_id, render_view_id); + // Delete the request before creating its replacement (below). + KillRequest(request); } } - requests_.push_back(new TabCaptureRequest(render_process_id, - render_view_id, - extension_id, - tab_id, - status)); + requests_.push_back(new LiveRequest(target_contents, extension_id, this)); return true; } -bool TabCaptureRegistry::VerifyRequest(int render_process_id, - int render_view_id) { +bool TabCaptureRegistry::VerifyRequest( + int render_process_id, + int render_frame_id, + const std::string& extension_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DVLOG(1) << "Verifying tabCapture request for " - << render_process_id << ":" << render_view_id; - // TODO(justinlin): Verify extension too. - return (FindCaptureRequest(render_process_id, render_view_id) != NULL); + + LiveRequest* const request = FindRequest( + content::WebContents::FromRenderFrameHost( + content::RenderFrameHost::FromID( + render_process_id, render_frame_id))); + if (!request) + return false; // Unknown RenderFrameHost ID, or frame has gone away. + + // TODO(miu): We should probably also verify the origin URL, like the desktop + // capture API. http://crbug.com/163100 + if (request->is_verified() || + request->extension_id() != extension_id || + (request->capture_state() != tab_capture::TAB_CAPTURE_STATE_NONE && + request->capture_state() != tab_capture::TAB_CAPTURE_STATE_PENDING)) + return false; + + // TODO(miu): The RenderFrameHost IDs should be set when LiveRequest is + // constructed, but ExtensionFunction does not yet support use of + // render_frame_host() to determine the exact RenderFrameHost for the call to + // AddRequest() above. Fix tab_capture_api.cc, and then fix this ugly hack. + // http://crbug.com/304341 + request->SetOriginallyTargettedRenderFrameID( + render_process_id, render_frame_id); + + request->SetIsVerified(); + return true; } void TabCaptureRegistry::OnRequestUpdate( - int render_process_id, - int render_view_id, - const content::MediaStreamDevice& device, + int original_target_render_process_id, + int original_target_render_frame_id, + content::MediaStreamType stream_type, const content::MediaRequestState new_state) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (device.type != content::MEDIA_TAB_VIDEO_CAPTURE && - device.type != content::MEDIA_TAB_AUDIO_CAPTURE) { + if (stream_type != content::MEDIA_TAB_VIDEO_CAPTURE && + stream_type != content::MEDIA_TAB_AUDIO_CAPTURE) { return; } - TabCaptureRequest* request = FindCaptureRequest(render_process_id, - render_view_id); - if (request == NULL) { - // TODO(justinlin): This can happen because the extension's renderer does - // not seem to always cleanup streams correctly. - LOG(ERROR) << "Receiving updates for deleted capture request."; - return; + LiveRequest* request = FindRequest(original_target_render_process_id, + original_target_render_frame_id); + if (!request) { + // Fall-back: Search again using WebContents since this method may have been + // called before VerifyRequest() set the RenderFrameHost ID. If the + // RenderFrameHost has gone away, that's okay since the upcoming call to + // VerifyRequest() will fail, and that means the tracking of request updates + // doesn't matter anymore. + request = FindRequest(content::WebContents::FromRenderFrameHost( + content::RenderFrameHost::FromID(original_target_render_process_id, + original_target_render_frame_id))); + if (!request) + return; // Stale or invalid request update. } - bool opening_stream = false; - bool stopping_stream = false; - TabCaptureState next_state = tab_capture::TAB_CAPTURE_STATE_NONE; switch (new_state) { case content::MEDIA_REQUEST_STATE_PENDING_APPROVAL: next_state = tab_capture::TAB_CAPTURE_STATE_PENDING; break; case content::MEDIA_REQUEST_STATE_DONE: - opening_stream = true; next_state = tab_capture::TAB_CAPTURE_STATE_ACTIVE; break; case content::MEDIA_REQUEST_STATE_CLOSING: - stopping_stream = true; next_state = tab_capture::TAB_CAPTURE_STATE_STOPPED; break; case content::MEDIA_REQUEST_STATE_ERROR: - stopping_stream = true; next_state = tab_capture::TAB_CAPTURE_STATE_ERROR; break; case content::MEDIA_REQUEST_STATE_OPENING: @@ -279,76 +293,68 @@ void TabCaptureRegistry::OnRequestUpdate( } if (next_state == tab_capture::TAB_CAPTURE_STATE_PENDING && - request->status != tab_capture::TAB_CAPTURE_STATE_PENDING && - request->status != tab_capture::TAB_CAPTURE_STATE_NONE && - request->status != tab_capture::TAB_CAPTURE_STATE_STOPPED && - request->status != tab_capture::TAB_CAPTURE_STATE_ERROR) { + request->capture_state() != tab_capture::TAB_CAPTURE_STATE_PENDING && + request->capture_state() != tab_capture::TAB_CAPTURE_STATE_NONE && + request->capture_state() != tab_capture::TAB_CAPTURE_STATE_STOPPED && + request->capture_state() != tab_capture::TAB_CAPTURE_STATE_ERROR) { // If we end up trying to grab a new stream while the previous one was never // terminated, then something fishy is going on. NOTREACHED() << "Trying to capture tab with existing stream."; return; } - if (opening_stream) { - request->fullscreen_observer.reset(new FullscreenObserver(request, this)); - } - - if (stopping_stream) { - request->fullscreen_observer.reset(); - } - - request->last_status = request->status; - request->status = next_state; - - // We will get duplicate events if we requested both audio and video, so only - // send new events. - if (request->last_status != request->status) { - DispatchStatusChangeEvent(request); - } + request->UpdateCaptureState(next_state); } void TabCaptureRegistry::DispatchStatusChangeEvent( - const TabCaptureRequest* request) const { + const LiveRequest* request) const { EventRouter* router = EventRouter::Get(browser_context_); if (!router) return; - scoped_ptr<tab_capture::CaptureInfo> info(new tab_capture::CaptureInfo()); - info->tab_id = request->tab_id; - info->status = request->status; - info->fullscreen = request->fullscreen; - scoped_ptr<base::ListValue> args(new base::ListValue()); - args->Append(info->ToValue().release()); + tab_capture::CaptureInfo info; + request->GetCaptureInfo(&info); + args->Append(info.ToValue().release()); scoped_ptr<Event> event(new Event(tab_capture::OnStatusChanged::kEventName, args.Pass())); event->restrict_to_browser_context = browser_context_; - router->DispatchEventToExtension(request->extension_id, event.Pass()); + router->DispatchEventToExtension(request->extension_id(), event.Pass()); } -TabCaptureRequest* TabCaptureRegistry::FindCaptureRequest( - int render_process_id, int render_view_id) const { - for (ScopedVector<TabCaptureRequest>::const_iterator it = requests_.begin(); +TabCaptureRegistry::LiveRequest* TabCaptureRegistry::FindRequest( + const content::WebContents* target_contents) const { + for (ScopedVector<LiveRequest>::const_iterator it = requests_.begin(); it != requests_.end(); ++it) { - if ((*it)->render_process_id == render_process_id && - (*it)->render_view_id == render_view_id) { + if ((*it)->target_contents() == target_contents) + return *it; + } + return NULL; +} + +TabCaptureRegistry::LiveRequest* TabCaptureRegistry::FindRequest( + int original_target_render_process_id, + int original_target_render_frame_id) const { + for (ScopedVector<LiveRequest>::const_iterator it = requests_.begin(); + it != requests_.end(); ++it) { + if ((*it)->WasOriginallyTargettingRenderFrameID( + original_target_render_process_id, + original_target_render_frame_id)) return *it; - } } return NULL; } -void TabCaptureRegistry::DeleteCaptureRequest(int render_process_id, - int render_view_id) { - for (ScopedVector<TabCaptureRequest>::iterator it = requests_.begin(); +void TabCaptureRegistry::KillRequest(LiveRequest* request) { + for (ScopedVector<LiveRequest>::iterator it = requests_.begin(); it != requests_.end(); ++it) { - if ((*it)->render_process_id == render_process_id && - (*it)->render_view_id == render_view_id) { + if ((*it) == request) { requests_.erase(it); return; } } + NOTREACHED(); } } // namespace extensions diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.h b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.h index 54fd9e6..49f7379 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.h +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.h @@ -14,31 +14,28 @@ #include "chrome/browser/media/media_capture_devices_dispatcher.h" #include "chrome/common/extensions/api/tab_capture.h" #include "content/public/browser/media_request_state.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" #include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/extension_registry_observer.h" +namespace base { +class ListValue; +} + namespace content { class BrowserContext; +class WebContents; } namespace extensions { -struct TabCaptureRequest; class ExtensionRegistry; -class FullscreenObserver; namespace tab_capture = api::tab_capture; class TabCaptureRegistry : public BrowserContextKeyedAPI, - public content::NotificationObserver, public ExtensionRegistryObserver, public MediaCaptureDevicesDispatcher::Observer { public: - typedef std::vector<std::pair<int, tab_capture::TabCaptureState> > - RegistryCaptureInfo; - static TabCaptureRegistry* Get(content::BrowserContext* context); // Used by BrowserContextKeyedAPI. @@ -46,24 +43,29 @@ class TabCaptureRegistry : public BrowserContextKeyedAPI, GetFactoryInstance(); // List all pending, active and stopped capture requests. - const RegistryCaptureInfo GetCapturedTabs( - const std::string& extension_id) const; + void GetCapturedTabs(const std::string& extension_id, + base::ListValue* list_of_capture_info) const; // Add a tab capture request to the registry when a stream is requested - // through the API. - bool AddRequest(int render_process_id, - int render_view_id, - const std::string& extension_id, - int tab_id, - tab_capture::TabCaptureState status); - - // The MediaStreamDevicesController will verify the request before creating - // the stream by checking the registry here. - bool VerifyRequest(int render_process_id, int render_view_id); + // through the API. |target_contents| refers to the WebContents associated + // with the tab to be captured. |extension_id| refers to the Extension + // initiating the request. + bool AddRequest(content::WebContents* target_contents, + const std::string& extension_id); + + // Called by MediaStreamDevicesController to verify the request before + // creating the stream. |render_process_id| and |render_frame_id| are used to + // look-up a WebContents instance, which should match the |target_contents| + // from the prior call to AddRequest(). In addition, a request is not + // verified unless the |extension_id| also matches AND the request itself is + // in the PENDING state. + bool VerifyRequest(int render_process_id, + int render_frame_id, + const std::string& extension_id); private: friend class BrowserContextKeyedAPIFactory<TabCaptureRegistry>; - friend class FullscreenObserver; + class LiveRequest; explicit TabCaptureRegistry(content::BrowserContext* context); virtual ~TabCaptureRegistry(); @@ -76,11 +78,6 @@ class TabCaptureRegistry : public BrowserContextKeyedAPI, static const bool kServiceIsCreatedWithBrowserContext = false; static const bool kServiceRedirectedInIncognito = true; - // content::NotificationObserver implementation. - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE; - // ExtensionRegistryObserver implementation. virtual void OnExtensionUnloaded( content::BrowserContext* browser_context, @@ -89,21 +86,25 @@ class TabCaptureRegistry : public BrowserContextKeyedAPI, // MediaCaptureDevicesDispatcher::Observer implementation. virtual void OnRequestUpdate( - int render_process_id, - int render_view_id, - const content::MediaStreamDevice& device, + int original_target_render_process_id, + int original_target_render_frame_id, + content::MediaStreamType stream_type, const content::MediaRequestState state) OVERRIDE; - void DispatchStatusChangeEvent(const TabCaptureRequest* request) const; + // Send a StatusChanged event containing the current state of |request|. + void DispatchStatusChangeEvent(const LiveRequest* request) const; - TabCaptureRequest* FindCaptureRequest(int render_process_id, - int render_view_id) const; + // Look-up a LiveRequest associated with the given |target_contents| (or + // the originally targetted RenderFrameHost), if any. + LiveRequest* FindRequest(const content::WebContents* target_contents) const; + LiveRequest* FindRequest(int original_target_render_process_id, + int original_target_render_frame_id) const; - void DeleteCaptureRequest(int render_process_id, int render_view_id); + // Removes the |request| from |requests_|, thus causing its destruction. + void KillRequest(LiveRequest* request); - content::NotificationRegistrar registrar_; content::BrowserContext* const browser_context_; - ScopedVector<TabCaptureRequest> requests_; + ScopedVector<LiveRequest> requests_; ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> extension_registry_observer_; diff --git a/chrome/browser/media/desktop_streams_registry.cc b/chrome/browser/media/desktop_streams_registry.cc index f2e2607..9f6a0eb 100644 --- a/chrome/browser/media/desktop_streams_registry.cc +++ b/chrome/browser/media/desktop_streams_registry.cc @@ -32,16 +32,17 @@ DesktopStreamsRegistry::~DesktopStreamsRegistry() {} std::string DesktopStreamsRegistry::RegisterStream( int render_process_id, - int render_view_id, + int render_frame_id, const GURL& origin, const content::DesktopMediaID& source, const std::string& extension_name) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); std::string id = GenerateRandomStreamId(); + DCHECK(approved_streams_.find(id) == approved_streams_.end()); ApprovedDesktopMediaStream& stream = approved_streams_[id]; stream.render_process_id = render_process_id; - stream.render_view_id = render_view_id; + stream.render_frame_id = render_frame_id; stream.origin = origin; stream.source = source; stream.extension_name = extension_name; @@ -58,7 +59,7 @@ std::string DesktopStreamsRegistry::RegisterStream( content::DesktopMediaID DesktopStreamsRegistry::RequestMediaForStreamId( const std::string& id, int render_process_id, - int render_view_id, + int render_frame_id, const GURL& origin, std::string* extension_name) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); @@ -69,7 +70,7 @@ content::DesktopMediaID DesktopStreamsRegistry::RequestMediaForStreamId( // the same origin and the same renderer. if (it == approved_streams_.end() || render_process_id != it->second.render_process_id || - render_view_id != it->second.render_view_id || + render_frame_id != it->second.render_frame_id || origin != it->second.origin) { return content::DesktopMediaID(); } @@ -86,4 +87,4 @@ void DesktopStreamsRegistry::CleanupStream(const std::string& id) { } DesktopStreamsRegistry::ApprovedDesktopMediaStream::ApprovedDesktopMediaStream() - : render_process_id(-1), render_view_id(-1) {} + : render_process_id(-1), render_frame_id(-1) {} diff --git a/chrome/browser/media/desktop_streams_registry.h b/chrome/browser/media/desktop_streams_registry.h index 90fb365..c497bd6 100644 --- a/chrome/browser/media/desktop_streams_registry.h +++ b/chrome/browser/media/desktop_streams_registry.h @@ -22,19 +22,21 @@ class DesktopStreamsRegistry { // Adds new stream to the registry. Called by the implementation of // desktopCapture.chooseDesktopMedia() API after user has approved access to // |source| for the |origin|. Returns identifier of the new stream. + // |render_frame_id| refers to the RenderFrame requesting the stream. std::string RegisterStream(int render_process_id, - int render_view_id, + int render_frame_id, const GURL& origin, const content::DesktopMediaID& source, const std::string& extension_name); // Validates stream identifier specified in getUserMedia(). Returns null // DesktopMediaID if the specified |id| is invalid, i.e. wasn't generated - // using RegisterStream() or if it was generated for a different origin. - // Otherwise returns ID of the source and removes it from the registry. + // using RegisterStream() or if it was generated for a different + // RenderFrame/origin. Otherwise returns ID of the source and removes it from + // the registry. content::DesktopMediaID RequestMediaForStreamId(const std::string& id, int render_process_id, - int render_view_id, + int render_frame_id, const GURL& origin, std::string* extension_name); @@ -44,7 +46,7 @@ class DesktopStreamsRegistry { ApprovedDesktopMediaStream(); int render_process_id; - int render_view_id; + int render_frame_id; GURL origin; content::DesktopMediaID source; std::string extension_name; diff --git a/chrome/browser/media/media_capture_devices_dispatcher.cc b/chrome/browser/media/media_capture_devices_dispatcher.cc index 136139a..7806eb9 100644 --- a/chrome/browser/media/media_capture_devices_dispatcher.cc +++ b/chrome/browser/media/media_capture_devices_dispatcher.cc @@ -36,6 +36,7 @@ #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/media_stream_request.h" #include "extensions/common/constants.h" @@ -394,11 +395,24 @@ void MediaCaptureDevicesDispatcher::ProcessDesktopCaptureAccessRequest( // The extension name that the stream is registered with. std::string original_extension_name; // Resolve DesktopMediaID for the specified device id. - content::DesktopMediaID media_id = - GetDesktopStreamsRegistry()->RequestMediaForStreamId( - request.requested_video_device_id, request.render_process_id, - request.render_view_id, request.security_origin, - &original_extension_name); + content::DesktopMediaID media_id; + // TODO(miu): Replace "main RenderFrame" IDs with the request's actual + // RenderFrame IDs once the desktop capture extension API implementation is + // fixed. http://crbug.com/304341 + content::WebContents* const web_contents_for_stream = + content::WebContents::FromRenderFrameHost( + content::RenderFrameHost::FromID(request.render_process_id, + request.render_frame_id)); + content::RenderFrameHost* const main_frame = web_contents_for_stream ? + web_contents_for_stream->GetMainFrame() : NULL; + if (main_frame) { + media_id = GetDesktopStreamsRegistry()->RequestMediaForStreamId( + request.requested_video_device_id, + main_frame->GetProcess()->GetID(), + main_frame->GetRoutingID(), + request.security_origin, + &original_extension_name); + } // Received invalid device id. if (media_id.type == content::DesktopMediaID::TYPE_NONE) { @@ -545,9 +559,8 @@ void MediaCaptureDevicesDispatcher::ProcessTabCaptureAccessRequest( callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, ui.Pass()); return; } - bool tab_capture_allowed = - tab_capture_registry->VerifyRequest(request.render_process_id, - request.render_view_id); + const bool tab_capture_allowed = tab_capture_registry->VerifyRequest( + request.render_process_id, request.render_frame_id, extension->id()); if (request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE && tab_capture_allowed && @@ -576,7 +589,7 @@ void MediaCaptureDevicesDispatcher::ProcessTabCaptureAccessRequest( ui.Pass()); #else // defined(ENABLE_EXTENSIONS) callback.Run(devices, content::MEDIA_DEVICE_TAB_CAPTURE_FAILURE, ui.Pass()); -#endif // !defined(OS_ANDROID) +#endif // defined(ENABLE_EXTENSIONS) } void MediaCaptureDevicesDispatcher:: @@ -804,18 +817,18 @@ void MediaCaptureDevicesDispatcher::OnVideoCaptureDevicesChanged() { void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged( int render_process_id, - int render_view_id, + int render_frame_id, int page_request_id, const GURL& security_origin, - const content::MediaStreamDevice& device, + content::MediaStreamType stream_type, content::MediaRequestState state) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind( &MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread, - base::Unretained(this), render_process_id, render_view_id, - page_request_id, security_origin, device, state)); + base::Unretained(this), render_process_id, render_frame_id, + page_request_id, security_origin, stream_type, state)); } void MediaCaptureDevicesDispatcher::OnAudioStreamPlaying( @@ -877,17 +890,17 @@ void MediaCaptureDevicesDispatcher::NotifyVideoDevicesChangedOnUIThread() { void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread( int render_process_id, - int render_view_id, + int render_frame_id, int page_request_id, const GURL& security_origin, - const content::MediaStreamDevice& device, + content::MediaStreamType stream_type, content::MediaRequestState state) { // Track desktop capture sessions. Tracking is necessary to avoid unbalanced // session counts since not all requests will reach MEDIA_REQUEST_STATE_DONE, // but they will all reach MEDIA_REQUEST_STATE_CLOSING. - if (device.type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) { + if (stream_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) { if (state == content::MEDIA_REQUEST_STATE_DONE) { - DesktopCaptureSession session = { render_process_id, render_view_id, + DesktopCaptureSession session = { render_process_id, render_frame_id, page_request_id }; desktop_capture_sessions_.push_back(session); } else if (state == content::MEDIA_REQUEST_STATE_CLOSING) { @@ -896,7 +909,7 @@ void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread( it != desktop_capture_sessions_.end(); ++it) { if (it->render_process_id == render_process_id && - it->render_view_id == render_view_id && + it->render_frame_id == render_frame_id && it->page_request_id == page_request_id) { desktop_capture_sessions_.erase(it); break; @@ -914,7 +927,7 @@ void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread( for (RequestsQueue::iterator it = queue.begin(); it != queue.end(); ++it) { if (it->request.render_process_id == render_process_id && - it->request.render_view_id == render_view_id && + it->request.render_frame_id == render_frame_id && it->request.page_request_id == page_request_id) { queue.erase(it); found = true; @@ -927,7 +940,7 @@ void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread( } #if defined(OS_CHROMEOS) - if (IsOriginForCasting(security_origin) && IsVideoMediaType(device.type)) { + if (IsOriginForCasting(security_origin) && IsVideoMediaType(stream_type)) { // Notify ash that casting state has changed. if (state == content::MEDIA_REQUEST_STATE_DONE) { ash::Shell::GetInstance()->OnCastingSessionStartedOrStopped(true); @@ -939,8 +952,8 @@ void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread( FOR_EACH_OBSERVER(Observer, observers_, OnRequestUpdate(render_process_id, - render_view_id, - device, + render_frame_id, + stream_type, state)); } diff --git a/chrome/browser/media/media_capture_devices_dispatcher.h b/chrome/browser/media/media_capture_devices_dispatcher.h index 0c16f3b..6c71661 100644 --- a/chrome/browser/media/media_capture_devices_dispatcher.h +++ b/chrome/browser/media/media_capture_devices_dispatcher.h @@ -51,8 +51,8 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver, // Handle an information update related to a media stream request. virtual void OnRequestUpdate( int render_process_id, - int render_view_id, - const content::MediaStreamDevice& device, + int render_frame_id, + content::MediaStreamType stream_type, const content::MediaRequestState state) {} // Handle an information update that a new stream is being created. @@ -116,10 +116,10 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver, virtual void OnVideoCaptureDevicesChanged() OVERRIDE; virtual void OnMediaRequestStateChanged( int render_process_id, - int render_view_id, + int render_frame_id, int page_request_id, const GURL& security_origin, - const content::MediaStreamDevice& device, + content::MediaStreamType stream_type, content::MediaRequestState state) OVERRIDE; virtual void OnCreatingAudioStream(int render_process_id, int render_frame_id) OVERRIDE; @@ -203,10 +203,10 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver, void NotifyVideoDevicesChangedOnUIThread(); void UpdateMediaRequestStateOnUIThread( int render_process_id, - int render_view_id, + int render_frame_id, int page_request_id, const GURL& security_origin, - const content::MediaStreamDevice& device, + content::MediaStreamType stream_type, content::MediaRequestState state); void OnCreatingAudioStreamOnUIThread(int render_process_id, int render_frame_id); @@ -236,7 +236,7 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver, // MEDIA_REQUEST_STATE_CLOSING is encountered. struct DesktopCaptureSession { int render_process_id; - int render_view_id; + int render_frame_id; int page_request_id; }; typedef std::list<DesktopCaptureSession> DesktopCaptureSessions; diff --git a/chrome/browser/ui/ash/media_delegate_chromeos.cc b/chrome/browser/ui/ash/media_delegate_chromeos.cc index ff92c70..6e0d151 100644 --- a/chrome/browser/ui/ash/media_delegate_chromeos.cc +++ b/chrome/browser/ui/ash/media_delegate_chromeos.cc @@ -157,8 +157,8 @@ ash::MediaCaptureState MediaDelegateChromeOS::GetMediaCaptureState( void MediaDelegateChromeOS::OnRequestUpdate( int render_process_id, - int render_view_id, - const content::MediaStreamDevice& device, + int render_frame_id, + content::MediaStreamType stream_type, const content::MediaRequestState state) { base::MessageLoopForUI::current()->PostTask( FROM_HERE, diff --git a/chrome/browser/ui/ash/media_delegate_chromeos.h b/chrome/browser/ui/ash/media_delegate_chromeos.h index 7370432..f8d8317 100644 --- a/chrome/browser/ui/ash/media_delegate_chromeos.h +++ b/chrome/browser/ui/ash/media_delegate_chromeos.h @@ -24,8 +24,8 @@ class MediaDelegateChromeOS : public ash::MediaDelegate, // MediaCaptureDevicesDispatcher::Observer: virtual void OnRequestUpdate(int render_process_id, - int render_view_id, - const content::MediaStreamDevice& device, + int render_frame_id, + content::MediaStreamType stream_type, const content::MediaRequestState state) OVERRIDE; private: diff --git a/chrome/test/data/extensions/api_test/tab_capture/api_tests.js b/chrome/test/data/extensions/api_test/tab_capture/api_tests.js index a100d25..06e5022 100644 --- a/chrome/test/data/extensions/api_test/tab_capture/api_tests.js +++ b/chrome/test/data/extensions/api_test/tab_capture/api_tests.js @@ -29,25 +29,53 @@ chrome.test.runTests([ }, function getCapturedTabs() { - var activeStream = null; + chrome.tabs.create({active:true}, function(secondTab) { + // chrome.tabCapture.capture() will only capture the active tab. + chrome.test.assertTrue(secondTab.active); - var capturedTabsAfterClose = function(infos) { - chrome.test.assertEq(1, infos.length); - chrome.test.assertEq('stopped', infos[0].status); - chrome.test.succeed(); - }; + function checkInfoForSecondTabHasStatus(infos, status) { + for (var i = 0; i < infos.length; ++i) { + if (infos[i].tabId == secondTab) { + chrome.test.assertNe(null, status); + chrome.test.assertEq(status, infos[i].status); + chrome.test.assertEq(false, infos[i].fullscreen); + return; + } + } + } - var capturedTabsAfterOpen = function(infos) { - chrome.test.assertEq(1, infos.length); - chrome.test.assertEq('active', infos[0].status); - activeStream.stop(); - tabCapture.getCapturedTabs(capturedTabsAfterClose); - }; + // Step 4: After the second tab is closed, check that getCapturedTabs() + // returns no info at all about the second tab. http://crbug.com/338445 + chrome.tabs.onRemoved.addListener(function() { + tabCapture.getCapturedTabs(function checkNoInfos(infos) { + checkInfoForSecondTabHasStatus(infos, null); + chrome.test.succeed(); + }); + }); - tabCapture.capture({audio: true, video: true}, function(stream) { - chrome.test.assertTrue(!!stream); - activeStream = stream; - tabCapture.getCapturedTabs(capturedTabsAfterOpen); + var activeStream = null; + + // Step 3: After the stream is stopped, check that getCapturedTabs() + // returns 'stopped' capturing status for the second tab. + var capturedTabsAfterStopCapture = function(infos) { + checkInfoForSecondTabHasStatus(infos, 'stopped'); + chrome.tabs.remove(secondTab.id); + }; + + // Step 2: After the stream is started, check that getCapturedTabs() + // returns 'active' capturing status for the second tab. + var capturedTabsAfterStartCapture = function(infos) { + checkInfoForSecondTabHasStatus(infos, 'active'); + activeStream.stop(); + tabCapture.getCapturedTabs(capturedTabsAfterStopCapture); + }; + + // Step 1: Start capturing the second tab (the currently active tab). + tabCapture.capture({audio: true, video: true}, function(stream) { + chrome.test.assertTrue(!!stream); + activeStream = stream; + tabCapture.getCapturedTabs(capturedTabsAfterStartCapture); + }); }); }, diff --git a/chrome/test/data/extensions/api_test/tab_capture/manifest.json b/chrome/test/data/extensions/api_test/tab_capture/manifest.json index 56d761c..991b2e5 100644 --- a/chrome/test/data/extensions/api_test/tab_capture/manifest.json +++ b/chrome/test/data/extensions/api_test/tab_capture/manifest.json @@ -5,5 +5,5 @@ "manifest_version": 2, "description": "Tab Capture API Test Extension", "incognito": "split", - "permissions": ["tabCapture"] + "permissions": ["tabCapture","tabs"] } diff --git a/content/browser/frame_host/render_frame_host_delegate.cc b/content/browser/frame_host/render_frame_host_delegate.cc index 3b7fad1..d333185 100644 --- a/content/browser/frame_host/render_frame_host_delegate.cc +++ b/content/browser/frame_host/render_frame_host_delegate.cc @@ -4,6 +4,7 @@ #include <stddef.h> +#include "base/callback.h" #include "base/strings/string16.h" #include "content/browser/frame_host/render_frame_host_delegate.h" #include "url/gurl.h" @@ -34,4 +35,12 @@ WebContents* RenderFrameHostDelegate::GetAsWebContents() { return NULL; } +void RenderFrameHostDelegate::RequestMediaAccessPermission( + const MediaStreamRequest& request, + const MediaResponseCallback& callback) { + callback.Run(MediaStreamDevices(), + MEDIA_DEVICE_INVALID_STATE, + scoped_ptr<MediaStreamUI>()); +} + } // namespace content diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h index a49e22c..4d53936 100644 --- a/content/browser/frame_host/render_frame_host_delegate.h +++ b/content/browser/frame_host/render_frame_host_delegate.h @@ -9,6 +9,7 @@ #include "base/i18n/rtl.h" #include "content/common/content_export.h" #include "content/public/common/javascript_message_type.h" +#include "content/public/common/media_stream_request.h" class GURL; @@ -111,6 +112,13 @@ class CONTENT_EXPORT RenderFrameHostDelegate { // not a WebContents, returns NULL. virtual WebContents* GetAsWebContents(); + // The render frame has requested access to media devices listed in + // |request|, and the client should grant or deny that permission by + // calling |callback|. + virtual void RequestMediaAccessPermission( + const MediaStreamRequest& request, + const MediaResponseCallback& callback); + protected: virtual ~RenderFrameHostDelegate() {} }; diff --git a/content/browser/media/capture/web_contents_audio_input_stream.cc b/content/browser/media/capture/web_contents_audio_input_stream.cc index ad5a33f..9d42c2d 100644 --- a/content/browser/media/capture/web_contents_audio_input_stream.cc +++ b/content/browser/media/capture/web_contents_audio_input_stream.cc @@ -25,7 +25,7 @@ class WebContentsAudioInputStream::Impl public AudioMirroringManager::MirroringDestination { public: // Takes ownership of |mixer_stream|. The rest outlive this instance. - Impl(int render_process_id, int render_view_id, + Impl(int render_process_id, int main_render_frame_id, AudioMirroringManager* mirroring_manager, const scoped_refptr<WebContentsTracker>& tracker, media::VirtualAudioInputStream* mixer_stream); @@ -84,6 +84,8 @@ class WebContentsAudioInputStream::Impl void OnTargetChanged(int render_process_id, int render_view_id); // Injected dependencies. + const int initial_render_process_id_; + const int initial_main_render_frame_id_; AudioMirroringManager* const mirroring_manager_; const scoped_refptr<WebContentsTracker> tracker_; // The AudioInputStream implementation that handles the audio conversion and @@ -93,6 +95,7 @@ class WebContentsAudioInputStream::Impl State state_; // Current audio mirroring target. + bool target_identified_; int target_render_process_id_; int target_render_view_id_; @@ -105,14 +108,19 @@ class WebContentsAudioInputStream::Impl }; WebContentsAudioInputStream::Impl::Impl( - int render_process_id, int render_view_id, + int render_process_id, int main_render_frame_id, AudioMirroringManager* mirroring_manager, const scoped_refptr<WebContentsTracker>& tracker, media::VirtualAudioInputStream* mixer_stream) - : mirroring_manager_(mirroring_manager), - tracker_(tracker), mixer_stream_(mixer_stream), state_(CONSTRUCTED), - target_render_process_id_(render_process_id), - target_render_view_id_(render_view_id), + : initial_render_process_id_(render_process_id), + initial_main_render_frame_id_(main_render_frame_id), + mirroring_manager_(mirroring_manager), + tracker_(tracker), + mixer_stream_(mixer_stream), + state_(CONSTRUCTED), + target_identified_(false), + target_render_process_id_(-1), + target_render_view_id_(-1), callback_(NULL) { DCHECK(mirroring_manager_); DCHECK(tracker_.get()); @@ -138,7 +146,7 @@ bool WebContentsAudioInputStream::Impl::Open() { state_ = OPENED; tracker_->Start( - target_render_process_id_, target_render_view_id_, + initial_render_process_id_, initial_main_render_frame_id_, base::Bind(&Impl::OnTargetChanged, this)); return true; @@ -196,7 +204,8 @@ void WebContentsAudioInputStream::Impl::Close() { bool WebContentsAudioInputStream::Impl::IsTargetLost() const { DCHECK(thread_checker_.CalledOnValidThread()); - + if (!target_identified_) + return false; return target_render_process_id_ <= 0 || target_render_view_id_ <= 0; } @@ -252,7 +261,8 @@ void WebContentsAudioInputStream::Impl::OnTargetChanged(int render_process_id, int render_view_id) { DCHECK(thread_checker_.CalledOnValidThread()); - if (target_render_process_id_ == render_process_id && + if (target_identified_ && + target_render_process_id_ == render_process_id && target_render_view_id_ == render_view_id) { return; } @@ -264,6 +274,7 @@ void WebContentsAudioInputStream::Impl::OnTargetChanged(int render_process_id, if (state_ == MIRRORING) StopMirroring(); + target_identified_ = true; target_render_process_id_ = render_process_id; target_render_view_id_ = render_view_id; @@ -284,14 +295,14 @@ WebContentsAudioInputStream* WebContentsAudioInputStream::Create( const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner, AudioMirroringManager* audio_mirroring_manager) { int render_process_id; - int render_view_id; + int main_render_frame_id; if (!WebContentsCaptureUtil::ExtractTabCaptureTarget( - device_id, &render_process_id, &render_view_id)) { + device_id, &render_process_id, &main_render_frame_id)) { return NULL; } return new WebContentsAudioInputStream( - render_process_id, render_view_id, + render_process_id, main_render_frame_id, audio_mirroring_manager, new WebContentsTracker(), new media::VirtualAudioInputStream( @@ -300,11 +311,11 @@ WebContentsAudioInputStream* WebContentsAudioInputStream::Create( } WebContentsAudioInputStream::WebContentsAudioInputStream( - int render_process_id, int render_view_id, + int render_process_id, int main_render_frame_id, AudioMirroringManager* mirroring_manager, const scoped_refptr<WebContentsTracker>& tracker, media::VirtualAudioInputStream* mixer_stream) - : impl_(new Impl(render_process_id, render_view_id, + : impl_(new Impl(render_process_id, main_render_frame_id, mirroring_manager, tracker, mixer_stream)) {} WebContentsAudioInputStream::~WebContentsAudioInputStream() {} diff --git a/content/browser/media/capture/web_contents_audio_input_stream.h b/content/browser/media/capture/web_contents_audio_input_stream.h index c0a2c6a..9bdc914 100644 --- a/content/browser/media/capture/web_contents_audio_input_stream.h +++ b/content/browser/media/capture/web_contents_audio_input_stream.h @@ -75,7 +75,7 @@ class CONTENT_EXPORT WebContentsAudioInputStream class Impl; WebContentsAudioInputStream( - int render_process_id, int render_view_id, + int render_process_id, int main_render_frame_id, AudioMirroringManager* mirroring_manager, const scoped_refptr<WebContentsTracker>& tracker, media::VirtualAudioInputStream* mixer_stream); diff --git a/content/browser/media/capture/web_contents_capture_util.cc b/content/browser/media/capture/web_contents_capture_util.cc index 57b636a..e1c5d52 100644 --- a/content/browser/media/capture/web_contents_capture_util.cc +++ b/content/browser/media/capture/web_contents_capture_util.cc @@ -9,40 +9,24 @@ #include "base/strings/string_piece.h" #include "base/strings/string_util.h" -namespace { - -const char kVirtualDeviceScheme[] = "virtual-media-stream://"; - -} // namespace - namespace content { -std::string WebContentsCaptureUtil::AppendWebContentsDeviceScheme( - const std::string& device_id) { - return kVirtualDeviceScheme + device_id; -} - -std::string WebContentsCaptureUtil::StripWebContentsDeviceScheme( - const std::string& device_id) { - return (IsWebContentsDeviceId(device_id) ? - device_id.substr(arraysize(kVirtualDeviceScheme) - 1) : - device_id); -} - bool WebContentsCaptureUtil::IsWebContentsDeviceId( const std::string& device_id) { - return StartsWithASCII(device_id, kVirtualDeviceScheme, true); + int ignored; + return ExtractTabCaptureTarget(device_id, &ignored, &ignored); } bool WebContentsCaptureUtil::ExtractTabCaptureTarget( const std::string& device_id_param, int* render_process_id, - int* render_view_id) { - if (!IsWebContentsDeviceId(device_id_param)) + int* main_render_frame_id) { + static const char kDeviceScheme[] = "web-contents-media-stream://"; + if (!StartsWithASCII(device_id_param, kDeviceScheme, true)) return false; const std::string device_id = device_id_param.substr( - arraysize(kVirtualDeviceScheme) - 1); + arraysize(kDeviceScheme) - 1); const size_t sep_pos = device_id.find(':'); if (sep_pos == std::string::npos) @@ -53,7 +37,7 @@ bool WebContentsCaptureUtil::ExtractTabCaptureTarget( device_id.length() - sep_pos - 1); return (base::StringToInt(component1, render_process_id) && - base::StringToInt(component2, render_view_id)); + base::StringToInt(component2, main_render_frame_id)); } } // namespace content diff --git a/content/browser/media/capture/web_contents_capture_util.h b/content/browser/media/capture/web_contents_capture_util.h index 5f43f42..60a9113 100644 --- a/content/browser/media/capture/web_contents_capture_util.h +++ b/content/browser/media/capture/web_contents_capture_util.h @@ -13,21 +13,14 @@ namespace content { class CONTENT_EXPORT WebContentsCaptureUtil { public: - // Returns a new id after appending the device id scheme for virtual streams. - static std::string AppendWebContentsDeviceScheme( - const std::string& device_id_param); - - static std::string StripWebContentsDeviceScheme( - const std::string& device_id_param); - // Check whether the device id indicates that this is a web contents stream. static bool IsWebContentsDeviceId(const std::string& device_id); - // Function to extract the target renderer id's from a tab media stream + // Function to extract the target render frame id's from a media stream // request's device id. static bool ExtractTabCaptureTarget(const std::string& device_id, int* render_process_id, - int* render_view_id); + int* main_render_frame_id); }; } // namespace content diff --git a/content/browser/media/capture/web_contents_tracker.cc b/content/browser/media/capture/web_contents_tracker.cc index 0765331..5bfdf4e 100644 --- a/content/browser/media/capture/web_contents_tracker.cc +++ b/content/browser/media/capture/web_contents_tracker.cc @@ -6,6 +6,7 @@ #include "base/message_loop/message_loop_proxy.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" @@ -18,7 +19,7 @@ WebContentsTracker::~WebContentsTracker() { DCHECK(!web_contents()) << "BUG: Still observering!"; } -void WebContentsTracker::Start(int render_process_id, int render_view_id, +void WebContentsTracker::Start(int render_process_id, int main_render_frame_id, const ChangeCallback& callback) { DCHECK(!message_loop_.get() || message_loop_->BelongsToCurrentThread()); @@ -29,7 +30,7 @@ void WebContentsTracker::Start(int render_process_id, int render_view_id, BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&WebContentsTracker::LookUpAndObserveWebContents, this, - render_process_id, render_view_id)); + render_process_id, main_render_frame_id)); } void WebContentsTracker::Stop() { @@ -67,17 +68,15 @@ void WebContentsTracker::MaybeDoCallback(int render_process_id, } void WebContentsTracker::LookUpAndObserveWebContents(int render_process_id, - int render_view_id) { + int main_render_frame_id) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - RenderViewHost* const rvh = - RenderViewHost::FromID(render_process_id, render_view_id); - DVLOG_IF(1, !rvh) << "RenderViewHost::FromID(" - << render_process_id << ", " << render_view_id - << ") returned NULL."; - Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL); + Observe(WebContents::FromRenderFrameHost(RenderFrameHost::FromID( + render_process_id, main_render_frame_id))); DVLOG_IF(1, !web_contents()) - << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL."; + << "Could not find WebContents associated with main RenderFrameHost " + << "referenced by render_process_id=" << render_process_id + << ", routing_id=" << main_render_frame_id; OnWebContentsChangeEvent(); } diff --git a/content/browser/media/capture/web_contents_tracker.h b/content/browser/media/capture/web_contents_tracker.h index f8957f3..bd551ca 100644 --- a/content/browser/media/capture/web_contents_tracker.h +++ b/content/browser/media/capture/web_contents_tracker.h @@ -2,11 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Given a starting render_process_id and render_view_id, the WebContentsTracker -// tracks RenderViewHost instance swapping during the lifetime of a WebContents -// instance. This is used when mirroring tab video and audio so that user -// navigations, crashes, etc., during a tab's lifetime allow the capturing code -// to remain active on the current/latest RenderView. +// Given a starting render_process_id and main_render_frame_id, the +// WebContentsTracker tracks RenderViewHost instance swapping during the +// lifetime of a WebContents instance. This is used when mirroring tab video +// and audio so that user navigations, crashes, etc., during a tab's lifetime +// allow the capturing code to remain active on the current/latest RenderView. +// +// TODO(miu): In a soon upcoming change, the cross-site isolation migration of +// this code will be completed such that the main RenderFrameHost is tracked +// instead of the RenderViewHost. // // Threading issues: Start(), Stop() and the ChangeCallback are invoked on the // same thread. This can be any thread, and the decision is locked-in by @@ -39,10 +43,11 @@ class CONTENT_EXPORT WebContentsTracker typedef base::Callback<void(int render_process_id, int render_view_id)> ChangeCallback; - // Start tracking. The last-known |render_process_id| and |render_view_id| - // are provided, and the given callback is invoked asynchronously one or more - // times. The callback will be invoked on the same thread calling Start(). - virtual void Start(int render_process_id, int render_view_id, + // Start tracking. The last-known |render_process_id| and + // |main_render_frame_id| are provided, and the given callback is invoked + // asynchronously one or more times. The callback will be invoked on the same + // thread calling Start(). + virtual void Start(int render_process_id, int main_render_frame_id, const ChangeCallback& callback); // Stop tracking. Once this method returns, the callback is guaranteed not to @@ -63,9 +68,9 @@ class CONTENT_EXPORT WebContentsTracker void MaybeDoCallback(int render_process_id, int render_view_id); // Look-up the current WebContents instance associated with the given - // |render_process_id| and |render_view_id| and begin observing it. + // |render_process_id| and |main_render_frame_id| and begin observing it. void LookUpAndObserveWebContents(int render_process_id, - int render_view_id); + int main_render_frame_id); // WebContentsObserver overrides to react to events of interest. virtual void RenderViewReady() OVERRIDE; diff --git a/content/browser/media/capture/web_contents_video_capture_device.cc b/content/browser/media/capture/web_contents_video_capture_device.cc index 47993b2..7eb2d94 100644 --- a/content/browser/media/capture/web_contents_video_capture_device.cc +++ b/content/browser/media/capture/web_contents_video_capture_device.cc @@ -225,7 +225,7 @@ class WebContentsCaptureMachine : public VideoCaptureMachine, public WebContentsObserver { public: - WebContentsCaptureMachine(int render_process_id, int render_view_id); + WebContentsCaptureMachine(int render_process_id, int main_render_frame_id); virtual ~WebContentsCaptureMachine(); // VideoCaptureMachine overrides. @@ -301,7 +301,7 @@ class WebContentsCaptureMachine // Parameters saved in constructor. const int initial_render_process_id_; - const int initial_render_view_id_; + const int initial_main_render_frame_id_; // A dedicated worker thread on which SkBitmap->VideoFrame conversion will // occur. Only used when this activity cannot be done on the GPU. @@ -558,9 +558,9 @@ void VideoFrameDeliveryLog::ChronicleFrameDelivery(base::TimeTicks frame_time) { } WebContentsCaptureMachine::WebContentsCaptureMachine(int render_process_id, - int render_view_id) + int main_render_frame_id) : initial_render_process_id_(render_process_id), - initial_render_view_id_(render_view_id), + initial_main_render_frame_id_(main_render_frame_id), fullscreen_widget_id_(MSG_ROUTING_NONE), weak_ptr_factory_(this) {} @@ -672,22 +672,21 @@ void WebContentsCaptureMachine::Capture( } bool WebContentsCaptureMachine::StartObservingWebContents() { - // Look-up the RenderViewHost and, from that, the WebContents that wraps it. + // Look-up the RenderFrameHost and, from that, the WebContents that wraps it. // If successful, begin observing the WebContents instance. // // Why this can be unsuccessful: The request for mirroring originates in a - // render process, and this request is based on the current RenderView + // render process, and this request is based on the current main RenderFrame // associated with a tab. However, by the time we get up-and-running here, // there have been multiple back-and-forth IPCs between processes, as well as // a bit of indirection across threads. It's easily possible that, in the - // meantime, the original RenderView may have gone away. - RenderViewHost* const rvh = - RenderViewHost::FromID(initial_render_process_id_, - initial_render_view_id_); - DVLOG_IF(1, !rvh) << "RenderViewHost::FromID(" - << initial_render_process_id_ << ", " - << initial_render_view_id_ << ") returned NULL."; - Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL); + // meantime, the original RenderFrame may have gone away. + Observe(WebContents::FromRenderFrameHost(RenderFrameHost::FromID( + initial_render_process_id_, initial_main_render_frame_id_))); + DVLOG_IF(1, !web_contents()) + << "Could not find WebContents associated with main RenderFrameHost " + << "referenced by render_process_id=" << initial_render_process_id_ + << ", routing_id=" << initial_main_render_frame_id_; WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents()); if (contents) { @@ -696,8 +695,6 @@ bool WebContentsCaptureMachine::StartObservingWebContents() { RenewFrameSubscription(); return true; } - - DVLOG(1) << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL."; return false; } @@ -786,9 +783,10 @@ void WebContentsCaptureMachine::RenewFrameSubscription() { } // namespace WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( - int render_process_id, int render_view_id) + int render_process_id, int main_render_frame_id) : core_(new ContentVideoCaptureDeviceCore(scoped_ptr<VideoCaptureMachine>( - new WebContentsCaptureMachine(render_process_id, render_view_id)))) {} + new WebContentsCaptureMachine( + render_process_id, main_render_frame_id)))) {} WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() { DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying."; @@ -799,13 +797,14 @@ media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create( const std::string& device_id) { // Parse device_id into render_process_id and render_view_id. int render_process_id = -1; - int render_view_id = -1; + int main_render_frame_id = -1; if (!WebContentsCaptureUtil::ExtractTabCaptureTarget( - device_id, &render_process_id, &render_view_id)) { + device_id, &render_process_id, &main_render_frame_id)) { return NULL; } - return new WebContentsVideoCaptureDevice(render_process_id, render_view_id); + return new WebContentsVideoCaptureDevice( + render_process_id, main_render_frame_id); } void WebContentsVideoCaptureDevice::AllocateAndStart( diff --git a/content/browser/media/capture/web_contents_video_capture_device.h b/content/browser/media/capture/web_contents_video_capture_device.h index 16c7b09..e7d31f6 100644 --- a/content/browser/media/capture/web_contents_video_capture_device.h +++ b/content/browser/media/capture/web_contents_video_capture_device.h @@ -19,22 +19,21 @@ class ContentVideoCaptureDeviceCore; // tab (accessed via its associated WebContents instance), producing a stream of // video frames. // -// An instance is created by providing a device_id. The device_id contains the -// routing ID for a RenderViewHost, and from the RenderViewHost instance, a -// reference to its associated WebContents instance is acquired. From then on, +// An instance is created by providing a device_id. The device_id contains +// information necessary for finding a WebContents instance. From then on, // WebContentsVideoCaptureDevice will capture from whatever render view is // currently associated with that WebContents instance. This allows the // underlying render view to be swapped out (e.g., due to navigation or // crashes/reloads), without any interruption in capturing. +// +// TODO(miu): In a soon upcoming change, the cross-site isolation migration of +// this code will be completed such that the main RenderFrameHost is tracked +// instead of the RenderViewHost. class CONTENT_EXPORT WebContentsVideoCaptureDevice : public media::VideoCaptureDevice { public: - // Construct from a |device_id| string of the form: - // "virtual-media-stream://render_process_id:render_view_id", where - // |render_process_id| and |render_view_id| are decimal integers. - // |destroy_cb| is invoked on an outside thread once all outstanding objects - // are completely destroyed -- this will be some time after the - // WebContentsVideoCaptureDevice is itself deleted. + // Create a WebContentsVideoCaptureDevice instance from the given + // |device_id|. Returns NULL if |device_id| is invalid. static media::VideoCaptureDevice* Create(const std::string& device_id); virtual ~WebContentsVideoCaptureDevice(); @@ -45,7 +44,8 @@ class CONTENT_EXPORT WebContentsVideoCaptureDevice virtual void StopAndDeAllocate() OVERRIDE; private: - WebContentsVideoCaptureDevice(int render_process_id, int render_view_id); + WebContentsVideoCaptureDevice( + int render_process_id, int main_render_frame_id); const scoped_ptr<ContentVideoCaptureDeviceCore> core_; diff --git a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc index fde3706..f9557b6 100644 --- a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc +++ b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc @@ -499,17 +499,11 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test { render_process_host_factory_.get()); web_contents_.reset( TestWebContents::Create(browser_context_.get(), site_instance.get())); - - // This is actually a CaptureTestRenderViewHost. - RenderWidgetHostImpl* rwh = - RenderWidgetHostImpl::From(web_contents_->GetRenderViewHost()); - - std::string device_id = - WebContentsCaptureUtil::AppendWebContentsDeviceScheme( - base::StringPrintf("%d:%d", rwh->GetProcess()->GetID(), - rwh->GetRoutingID())); - - device_.reset(WebContentsVideoCaptureDevice::Create(device_id)); + RenderFrameHost* const main_frame = web_contents_->GetMainFrame(); + device_.reset(WebContentsVideoCaptureDevice::Create( + base::StringPrintf("web-contents-media-stream://%d:%d", + main_frame->GetProcess()->GetID(), + main_frame->GetRoutingID()))); base::RunLoop().RunUntilIdle(); } diff --git a/content/browser/renderer_host/media/DEPS b/content/browser/renderer_host/media/DEPS index c3a5b96..21fd0fd9 100644 --- a/content/browser/renderer_host/media/DEPS +++ b/content/browser/renderer_host/media/DEPS @@ -1,3 +1,11 @@ include_rules = [ "+media", ] + +specific_include_rules = { + # TODO(miu): Need to relocate MediaStreamManager/DispatcherHost/UIProxy and + # friends to somewhere more appropriate. Perhaps content/browser/media? + "media_stream_ui_proxy(_unittest)?\.cc": [ + "+content/browser/frame_host", + ], +} diff --git a/content/browser/renderer_host/media/device_request_message_filter.cc b/content/browser/renderer_host/media/device_request_message_filter.cc index db0d175..d15039d 100644 --- a/content/browser/renderer_host/media/device_request_message_filter.cc +++ b/content/browser/renderer_host/media/device_request_message_filter.cc @@ -53,7 +53,7 @@ struct DeviceRequestMessageFilter::DeviceRequest { }; void DeviceRequestMessageFilter::DevicesEnumerated( - int render_view_id, + int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfoArray& new_devices) { diff --git a/content/browser/renderer_host/media/device_request_message_filter.h b/content/browser/renderer_host/media/device_request_message_filter.h index 2ec54cc..4bf30aa 100644 --- a/content/browser/renderer_host/media/device_request_message_filter.h +++ b/content/browser/renderer_host/media/device_request_message_filter.h @@ -32,22 +32,22 @@ class CONTENT_EXPORT DeviceRequestMessageFilter : public BrowserMessageFilter, // we don't have to override all these callbacks we don't care about. // (crbug.com/249476) virtual void StreamGenerated( - int render_view_id, int page_request_id, const std::string& label, + int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfoArray& audio_devices, const StreamDeviceInfoArray& video_devices) OVERRIDE {} virtual void StreamGenerationFailed( - int render_view_id, + int render_frame_id, int page_request_id, content::MediaStreamRequestResult result) OVERRIDE {} - virtual void DeviceStopped(int render_view_id, + virtual void DeviceStopped(int render_frame_id, const std::string& label, const StreamDeviceInfo& device) OVERRIDE {} - virtual void DeviceOpened(int render_view_id, + virtual void DeviceOpened(int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfo& video_device) OVERRIDE {} // DevicesEnumerated() is the only callback we're interested in. - virtual void DevicesEnumerated(int render_view_id, + virtual void DevicesEnumerated(int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfoArray& devices) OVERRIDE; diff --git a/content/browser/renderer_host/media/device_request_message_filter_unittest.cc b/content/browser/renderer_host/media/device_request_message_filter_unittest.cc index 6d6a9e3..628bd19 100644 --- a/content/browser/renderer_host/media/device_request_message_filter_unittest.cc +++ b/content/browser/renderer_host/media/device_request_message_filter_unittest.cc @@ -28,7 +28,7 @@ class MockMediaStreamManager : public MediaStreamManager { MOCK_METHOD8(EnumerateDevices, std::string(MediaStreamRequester* requester, int render_process_id, - int render_view_id, + int render_frame_id, const ResourceContext::SaltCallback& rc, int page_request_id, MediaStreamType type, @@ -37,7 +37,7 @@ class MockMediaStreamManager : public MediaStreamManager { std::string DoEnumerateDevices(MediaStreamRequester* requester, int render_process_id, - int render_view_id, + int render_frame_id, const ResourceContext::SaltCallback& rc, int page_request_id, MediaStreamType type, diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc index 91fad34..327efce 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc @@ -26,7 +26,7 @@ MediaStreamDispatcherHost::MediaStreamDispatcherHost( } void MediaStreamDispatcherHost::StreamGenerated( - int render_view_id, + int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfoArray& audio_devices, @@ -36,12 +36,11 @@ void MediaStreamDispatcherHost::StreamGenerated( << ", {label = " << label << "})"; Send(new MediaStreamMsg_StreamGenerated( - render_view_id, page_request_id, label, audio_devices, - video_devices)); + render_frame_id, page_request_id, label, audio_devices, video_devices)); } void MediaStreamDispatcherHost::StreamGenerationFailed( - int render_view_id, + int render_frame_id, int page_request_id, content::MediaStreamRequestResult result) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -50,12 +49,12 @@ void MediaStreamDispatcherHost::StreamGenerationFailed( << ", { result= " << result << "})"; - Send(new MediaStreamMsg_StreamGenerationFailed(render_view_id, + Send(new MediaStreamMsg_StreamGenerationFailed(render_frame_id, page_request_id, result)); } -void MediaStreamDispatcherHost::DeviceStopped(int render_view_id, +void MediaStreamDispatcherHost::DeviceStopped(int render_frame_id, const std::string& label, const StreamDeviceInfo& device) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -64,11 +63,11 @@ void MediaStreamDispatcherHost::DeviceStopped(int render_view_id, << "{type = " << device.device.type << "}, " << "{device_id = " << device.device.id << "})"; - Send(new MediaStreamMsg_DeviceStopped(render_view_id, label, device)); + Send(new MediaStreamMsg_DeviceStopped(render_frame_id, label, device)); } void MediaStreamDispatcherHost::DevicesEnumerated( - int render_view_id, + int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfoArray& devices) { @@ -76,12 +75,12 @@ void MediaStreamDispatcherHost::DevicesEnumerated( DVLOG(1) << "MediaStreamDispatcherHost::DevicesEnumerated(" << ", {page_request_id = " << page_request_id << "})"; - Send(new MediaStreamMsg_DevicesEnumerated(render_view_id, page_request_id, + Send(new MediaStreamMsg_DevicesEnumerated(render_frame_id, page_request_id, devices)); } void MediaStreamDispatcherHost::DeviceOpened( - int render_view_id, + int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfo& video_device) { @@ -90,7 +89,7 @@ void MediaStreamDispatcherHost::DeviceOpened( << ", {page_request_id = " << page_request_id << "})"; Send(new MediaStreamMsg_DeviceOpened( - render_view_id, page_request_id, label, video_device)); + render_frame_id, page_request_id, label, video_device)); } bool MediaStreamDispatcherHost::OnMessageReceived(const IPC::Message& message) { @@ -125,13 +124,13 @@ MediaStreamDispatcherHost::~MediaStreamDispatcherHost() { } void MediaStreamDispatcherHost::OnGenerateStream( - int render_view_id, + int render_frame_id, int page_request_id, const StreamOptions& components, const GURL& security_origin, bool user_gesture) { DVLOG(1) << "MediaStreamDispatcherHost::OnGenerateStream(" - << render_view_id << ", " + << render_frame_id << ", " << page_request_id << ", [" << " audio:" << components.audio_requested << " video:" << components.video_requested @@ -143,37 +142,37 @@ void MediaStreamDispatcherHost::OnGenerateStream( return; media_stream_manager_->GenerateStream( - this, render_process_id_, render_view_id, salt_callback_, + this, render_process_id_, render_frame_id, salt_callback_, page_request_id, components, security_origin, user_gesture); } -void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_view_id, +void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_frame_id, int page_request_id) { DVLOG(1) << "MediaStreamDispatcherHost::OnCancelGenerateStream(" - << render_view_id << ", " + << render_frame_id << ", " << page_request_id << ")"; - media_stream_manager_->CancelRequest(render_process_id_, render_view_id, + media_stream_manager_->CancelRequest(render_process_id_, render_frame_id, page_request_id); } void MediaStreamDispatcherHost::OnStopStreamDevice( - int render_view_id, + int render_frame_id, const std::string& device_id) { DVLOG(1) << "MediaStreamDispatcherHost::OnStopStreamDevice(" - << render_view_id << ", " + << render_frame_id << ", " << device_id << ")"; - media_stream_manager_->StopStreamDevice(render_process_id_, render_view_id, + media_stream_manager_->StopStreamDevice(render_process_id_, render_frame_id, device_id); } void MediaStreamDispatcherHost::OnEnumerateDevices( - int render_view_id, + int render_frame_id, int page_request_id, MediaStreamType type, const GURL& security_origin, bool hide_labels_if_no_access) { DVLOG(1) << "MediaStreamDispatcherHost::OnEnumerateDevices(" - << render_view_id << ", " + << render_frame_id << ", " << page_request_id << ", " << type << ", " << security_origin.spec() << ")"; @@ -194,28 +193,28 @@ void MediaStreamDispatcherHost::OnEnumerateDevices( } media_stream_manager_->EnumerateDevices( - this, render_process_id_, render_view_id, salt_callback_, + this, render_process_id_, render_frame_id, salt_callback_, page_request_id, type, security_origin, have_permission); } void MediaStreamDispatcherHost::OnCancelEnumerateDevices( - int render_view_id, + int render_frame_id, int page_request_id) { DVLOG(1) << "MediaStreamDispatcherHost::OnCancelEnumerateDevices(" - << render_view_id << ", " + << render_frame_id << ", " << page_request_id << ")"; - media_stream_manager_->CancelRequest(render_process_id_, render_view_id, + media_stream_manager_->CancelRequest(render_process_id_, render_frame_id, page_request_id); } void MediaStreamDispatcherHost::OnOpenDevice( - int render_view_id, + int render_frame_id, int page_request_id, const std::string& device_id, MediaStreamType type, const GURL& security_origin) { DVLOG(1) << "MediaStreamDispatcherHost::OnOpenDevice(" - << render_view_id << ", " + << render_frame_id << ", " << page_request_id << ", device_id: " << device_id.c_str() << ", type: " << type << ", " @@ -225,15 +224,15 @@ void MediaStreamDispatcherHost::OnOpenDevice( return; media_stream_manager_->OpenDevice( - this, render_process_id_, render_view_id, salt_callback_, + this, render_process_id_, render_frame_id, salt_callback_, page_request_id, device_id, type, security_origin); } void MediaStreamDispatcherHost::OnCloseDevice( - int render_view_id, + int render_frame_id, const std::string& label) { DVLOG(1) << "MediaStreamDispatcherHost::OnCloseDevice(" - << render_view_id << ", " + << render_frame_id << ", " << label << ")"; media_stream_manager_->CancelRequest(label); diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.h b/content/browser/renderer_host/media/media_stream_dispatcher_host.h index b599c39..d467718 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host.h +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.h @@ -22,8 +22,8 @@ class MediaStreamManager; class ResourceContext; // MediaStreamDispatcherHost is a delegate for Media Stream API messages used by -// MediaStreamImpl. It's the complement of MediaStreamDispatcher -// (owned by RenderView). +// MediaStreamImpl. There is one MediaStreamDispatcherHost per +// RenderProcessHost, the former owned by the latter. class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter, public MediaStreamRequester { public: @@ -35,23 +35,23 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter, // MediaStreamRequester implementation. virtual void StreamGenerated( - int render_view_id, + int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfoArray& audio_devices, const StreamDeviceInfoArray& video_devices) OVERRIDE; virtual void StreamGenerationFailed( - int render_view_id, + int render_frame_id, int page_request_id, content::MediaStreamRequestResult result) OVERRIDE; - virtual void DeviceStopped(int render_view_id, + virtual void DeviceStopped(int render_frame_id, const std::string& label, const StreamDeviceInfo& device) OVERRIDE; - virtual void DevicesEnumerated(int render_view_id, + virtual void DevicesEnumerated(int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfoArray& devices) OVERRIDE; - virtual void DeviceOpened(int render_view_id, + virtual void DeviceOpened(int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfo& video_device) OVERRIDE; @@ -66,35 +66,35 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter, private: friend class MockMediaStreamDispatcherHost; - void OnGenerateStream(int render_view_id, + void OnGenerateStream(int render_frame_id, int page_request_id, const StreamOptions& components, const GURL& security_origin, bool user_gesture); - void OnCancelGenerateStream(int render_view_id, + void OnCancelGenerateStream(int render_frame_id, int page_request_id); - void OnStopStreamDevice(int render_view_id, + void OnStopStreamDevice(int render_frame_id, const std::string& device_id); - void OnEnumerateDevices(int render_view_id, + void OnEnumerateDevices(int render_frame_id, int page_request_id, MediaStreamType type, const GURL& security_origin, bool hide_labels_if_no_access); - void OnCancelEnumerateDevices(int render_view_id, + void OnCancelEnumerateDevices(int render_frame_id, int page_request_id); - void OnOpenDevice(int render_view_id, + void OnOpenDevice(int render_frame_id, int page_request_id, const std::string& device_id, MediaStreamType type, const GURL& security_origin); - void OnCloseDevice(int render_view_id, + void OnCloseDevice(int render_frame_id, const std::string& label); - void StoreRequest(int render_view_id, + void StoreRequest(int render_frame_id, int page_request_id, const std::string& label); diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc index a7edd38..24366a5 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc @@ -70,22 +70,22 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, MOCK_METHOD2(OnDeviceOpened, void(int routing_id, int request_id)); // Accessor to private functions. - void OnGenerateStream(int render_view_id, + void OnGenerateStream(int render_frame_id, int page_request_id, const StreamOptions& components, const GURL& security_origin, const base::Closure& quit_closure) { quit_closures_.push(quit_closure); MediaStreamDispatcherHost::OnGenerateStream( - render_view_id, page_request_id, components, security_origin, false); + render_frame_id, page_request_id, components, security_origin, false); } - void OnStopStreamDevice(int render_view_id, + void OnStopStreamDevice(int render_frame_id, const std::string& device_id) { - MediaStreamDispatcherHost::OnStopStreamDevice(render_view_id, device_id); + MediaStreamDispatcherHost::OnStopStreamDevice(render_frame_id, device_id); } - void OnOpenDevice(int render_view_id, + void OnOpenDevice(int render_frame_id, int page_request_id, const std::string& device_id, MediaStreamType type, @@ -93,10 +93,10 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, const base::Closure& quit_closure) { quit_closures_.push(quit_closure); MediaStreamDispatcherHost::OnOpenDevice( - render_view_id, page_request_id, device_id, type, security_origin); + render_frame_id, page_request_id, device_id, type, security_origin); } - void OnEnumerateDevices(int render_view_id, + void OnEnumerateDevices(int render_frame_id, int page_request_id, MediaStreamType type, const GURL& security_origin, @@ -104,7 +104,7 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, const base::Closure& quit_closure) { quit_closures_.push(quit_closure); MediaStreamDispatcherHost::OnEnumerateDevices( - render_view_id, page_request_id, type, security_origin, + render_frame_id, page_request_id, type, security_origin, hide_labels_if_no_access); } @@ -279,7 +279,7 @@ class MediaStreamDispatcherHostTest : public testing::Test { stream_ui.PassAs<FakeMediaStreamUIProxy>()); } - void GenerateStreamAndWaitForResult(int render_view_id, + void GenerateStreamAndWaitForResult(int render_frame_id, int page_request_id, const StreamOptions& options) { base::RunLoop run_loop; @@ -289,10 +289,11 @@ class MediaStreamDispatcherHostTest : public testing::Test { int expected_video_array_size = (options.video_requested && physical_video_devices_.size() > 0) ? 1 : 0; - EXPECT_CALL(*host_.get(), OnStreamGenerated(render_view_id, page_request_id, + EXPECT_CALL(*host_.get(), OnStreamGenerated(render_frame_id, + page_request_id, expected_audio_array_size, expected_video_array_size)); - host_->OnGenerateStream(render_view_id, page_request_id, options, origin_, + host_->OnGenerateStream(render_frame_id, page_request_id, options, origin_, run_loop.QuitClosure()); run_loop.Run(); EXPECT_FALSE(DoesContainRawIds(host_->audio_devices_)); @@ -302,25 +303,25 @@ class MediaStreamDispatcherHostTest : public testing::Test { } void GenerateStreamAndWaitForFailure( - int render_view_id, + int render_frame_id, int page_request_id, const StreamOptions& options, MediaStreamRequestResult expected_result) { base::RunLoop run_loop; EXPECT_CALL(*host_.get(), - OnStreamGenerationFailed(render_view_id, + OnStreamGenerationFailed(render_frame_id, page_request_id, expected_result)); - host_->OnGenerateStream(render_view_id, page_request_id, options, origin_, - run_loop.QuitClosure()); + host_->OnGenerateStream(render_frame_id, page_request_id, options, + origin_, run_loop.QuitClosure()); run_loop.Run(); } - void OpenVideoDeviceAndWaitForResult(int render_view_id, + void OpenVideoDeviceAndWaitForResult(int render_frame_id, int page_request_id, const std::string& device_id) { base::RunLoop run_loop; - host_->OnOpenDevice(render_view_id, page_request_id, device_id, + host_->OnOpenDevice(render_frame_id, page_request_id, device_id, MEDIA_DEVICE_VIDEO_CAPTURE, origin_, run_loop.QuitClosure()); run_loop.Run(); @@ -328,12 +329,12 @@ class MediaStreamDispatcherHostTest : public testing::Test { EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_)); } - void EnumerateDevicesAndWaitForResult(int render_view_id, + void EnumerateDevicesAndWaitForResult(int render_frame_id, int page_request_id, MediaStreamType type, bool hide_labels_if_no_access) { base::RunLoop run_loop; - host_->OnEnumerateDevices(render_view_id, page_request_id, type, origin_, + host_->OnEnumerateDevices(render_frame_id, page_request_id, type, origin_, hide_labels_if_no_access, run_loop.QuitClosure()); run_loop.Run(); ASSERT_FALSE(host_->enumerated_devices_.empty()); @@ -470,8 +471,8 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioAndVideo) { EXPECT_EQ(host_->video_devices_.size(), 1u); } -// This test generates two streams with video only using the same render view -// id. The same capture device with the same device and session id is expected +// This test generates two streams with video only using the same render frame +// id. The same capture device with the same device and session id is expected // to be used. TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsFromSameRenderId) { StreamOptions options(false, true); @@ -530,7 +531,7 @@ TEST_F(MediaStreamDispatcherHostTest, // This test generates two streams with video only using two separate render -// view ids. The same device id but different session ids are expected. +// frame ids. The same device id but different session ids are expected. TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) { StreamOptions options(false, true); @@ -545,7 +546,7 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) { const std::string device_id1 = host_->video_devices_.front().device.id; const int session_id1 = host_->video_devices_.front().session_id; - // Generate second stream from another render view. + // Generate second stream from another render frame. SetupFakeUI(true); GenerateStreamAndWaitForResult(kRenderId+1, kPageRequestId + 1, options); diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index 2b337ca..21d2aa4 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc @@ -183,7 +183,7 @@ class MediaStreamManager::DeviceRequest { public: DeviceRequest(MediaStreamRequester* requester, int requesting_process_id, - int requesting_view_id, + int requesting_frame_id, int page_request_id, const GURL& security_origin, bool have_permission, @@ -193,7 +193,7 @@ class MediaStreamManager::DeviceRequest { const ResourceContext::SaltCallback& salt_callback) : requester(requester), requesting_process_id(requesting_process_id), - requesting_view_id(requesting_view_id), + requesting_frame_id(requesting_frame_id), page_request_id(page_request_id), security_origin(security_origin), have_permission(have_permission), @@ -230,7 +230,7 @@ class MediaStreamManager::DeviceRequest { const std::string& requested_video_device_id) { DCHECK(!ui_request_); ui_request_.reset(new MediaStreamRequest(requesting_process_id, - requesting_view_id, + requesting_frame_id, page_request_id, security_origin, user_gesture, @@ -243,12 +243,12 @@ class MediaStreamManager::DeviceRequest { // Creates a tab capture specific MediaStreamRequest object that is used by // this request when UI is asked for permission and device selection. - void CreateTabCatureUIRequest(int target_render_process_id, - int target_render_view_id, - const std::string& tab_capture_id) { + void CreateTabCaptureUIRequest(int target_render_process_id, + int target_render_frame_id, + const std::string& tab_capture_id) { DCHECK(!ui_request_); ui_request_.reset(new MediaStreamRequest(target_render_process_id, - target_render_view_id, + target_render_frame_id, page_request_id, security_origin, user_gesture, @@ -283,17 +283,10 @@ class MediaStreamManager::DeviceRequest { if (!ui_request_) return; - // If we appended a device_id scheme, we want to remove it when notifying - // observers which may be in different modules since this scheme is only - // used internally within the content module. - std::string device_id = - WebContentsCaptureUtil::StripWebContentsDeviceScheme( - ui_request_->tab_capture_device_id); - media_observer->OnMediaRequestStateChanged( - ui_request_->render_process_id, ui_request_->render_view_id, + ui_request_->render_process_id, ui_request_->render_frame_id, ui_request_->page_request_id, ui_request_->security_origin, - MediaStreamDevice(stream_type, device_id, device_id), new_state); + stream_type, new_state); } MediaRequestState state(MediaStreamType stream_type) const { @@ -309,13 +302,13 @@ class MediaStreamManager::DeviceRequest { // specifies the target renderer from which audio and video is captured. const int requesting_process_id; - // The render view id that requested this stream to be generated and that + // The render frame id that requested this stream to be generated and that // will receive a handle to the MediaStream. This may be different from - // MediaStreamRequest::render_view_id which in the tab capture case + // MediaStreamRequest::render_frame_id which in the tab capture case // specifies the target renderer from which audio and video is captured. - const int requesting_view_id; + const int requesting_frame_id; - // An ID the render view provided to identify this request. + // An ID the render frame provided to identify this request. const int page_request_id; const GURL security_origin; @@ -414,7 +407,7 @@ AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() { std::string MediaStreamManager::MakeMediaAccessRequest( int render_process_id, - int render_view_id, + int render_frame_id, int page_request_id, const StreamOptions& options, const GURL& security_origin, @@ -425,7 +418,7 @@ std::string MediaStreamManager::MakeMediaAccessRequest( // suggests that this is the wrong design. Can this be refactored? DeviceRequest* request = new DeviceRequest(NULL, render_process_id, - render_view_id, + render_frame_id, page_request_id, security_origin, true, @@ -451,7 +444,7 @@ std::string MediaStreamManager::MakeMediaAccessRequest( void MediaStreamManager::GenerateStream(MediaStreamRequester* requester, int render_process_id, - int render_view_id, + int render_frame_id, const ResourceContext::SaltCallback& sc, int page_request_id, const StreamOptions& options, @@ -466,7 +459,7 @@ void MediaStreamManager::GenerateStream(MediaStreamRequester* requester, DeviceRequest* request = new DeviceRequest(requester, render_process_id, - render_view_id, + render_frame_id, page_request_id, security_origin, true, @@ -489,13 +482,13 @@ void MediaStreamManager::GenerateStream(MediaStreamRequester* requester, } void MediaStreamManager::CancelRequest(int render_process_id, - int render_view_id, + int render_frame_id, int page_request_id) { for (DeviceRequests::const_iterator request_it = requests_.begin(); request_it != requests_.end(); ++request_it) { const DeviceRequest* request = request_it->second; if (request->requesting_process_id == render_process_id && - request->requesting_view_id == render_view_id && + request->requesting_frame_id == render_frame_id && request->page_request_id == page_request_id) { CancelRequest(request_it->first); return; @@ -557,19 +550,19 @@ void MediaStreamManager::CancelAllRequests(int render_process_id) { } void MediaStreamManager::StopStreamDevice(int render_process_id, - int render_view_id, + int render_frame_id, const std::string& device_id) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DVLOG(1) << "StopStreamDevice({render_view_id = " << render_view_id << "} " + DVLOG(1) << "StopStreamDevice({render_frame_id = " << render_frame_id << "} " << ", {device_id = " << device_id << "})"; - // Find the first request for this |render_process_id| and |render_view_id| + // Find the first request for this |render_process_id| and |render_frame_id| // of type MEDIA_GENERATE_STREAM that has requested to use |device_id| and // stop it. for (DeviceRequests::iterator request_it = requests_.begin(); - request_it != requests_.end(); ++request_it) { + request_it != requests_.end(); ++request_it) { DeviceRequest* request = request_it->second; if (request->requesting_process_id != render_process_id || - request->requesting_view_id != render_view_id || + request->requesting_frame_id != render_frame_id || request->request_type != MEDIA_GENERATE_STREAM) { continue; } @@ -648,7 +641,7 @@ void MediaStreamManager::CloseDevice(MediaStreamType type, int session_id) { std::string MediaStreamManager::EnumerateDevices( MediaStreamRequester* requester, int render_process_id, - int render_view_id, + int render_frame_id, const ResourceContext::SaltCallback& sc, int page_request_id, MediaStreamType type, @@ -662,7 +655,7 @@ std::string MediaStreamManager::EnumerateDevices( DeviceRequest* request = new DeviceRequest(requester, render_process_id, - render_view_id, + render_frame_id, page_request_id, security_origin, have_permission, @@ -733,8 +726,7 @@ void MediaStreamManager::DoEnumerateDevices(const std::string& label) { DVLOG(1) << "Enumerate Devices ({label = " << label << "})"; } -void MediaStreamManager::EnumerateAudioOutputDevices( - const std::string& label) { +void MediaStreamManager::EnumerateAudioOutputDevices(const std::string& label) { DCHECK(device_task_runner_->BelongsToCurrentThread()); scoped_ptr<media::AudioDeviceNames> device_names( @@ -786,7 +778,7 @@ void MediaStreamManager::AudioOutputDevicesEnumerated( void MediaStreamManager::OpenDevice(MediaStreamRequester* requester, int render_process_id, - int render_view_id, + int render_frame_id, const ResourceContext::SaltCallback& sc, int page_request_id, const std::string& device_id, @@ -810,7 +802,7 @@ void MediaStreamManager::OpenDevice(MediaStreamRequester* requester, } DeviceRequest* request = new DeviceRequest(requester, render_process_id, - render_view_id, + render_frame_id, page_request_id, security_origin, true, @@ -910,7 +902,7 @@ void MediaStreamManager::StopRemovedDevice(const MediaStreamDevice& device) { session_ids.push_back(device_it->session_id); if (it->second->requester) { it->second->requester->DeviceStopped( - it->second->requesting_view_id, + it->second->requesting_frame_id, it->first, *device_it); } @@ -1295,17 +1287,10 @@ bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) { // Customize options for a WebContents based capture. int target_render_process_id = 0; - int target_render_view_id = 0; - - // TODO(justinlin): Can't plumb audio mirroring using stream type right - // now, so plumbing by device_id. Will revisit once it's refactored. - // http://crbug.com/163100 - std::string tab_capture_device_id = - WebContentsCaptureUtil::AppendWebContentsDeviceScheme(capture_device_id); + int target_render_frame_id = 0; bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget( - tab_capture_device_id, &target_render_process_id, - &target_render_view_id); + capture_device_id, &target_render_process_id, &target_render_frame_id); if (!has_valid_device_id || (request->audio_type() != MEDIA_TAB_AUDIO_CAPTURE && request->audio_type() != MEDIA_NO_SERVICE) || @@ -1314,15 +1299,15 @@ bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) { return false; } - request->CreateTabCatureUIRequest(target_render_process_id, - target_render_view_id, - tab_capture_device_id); + request->CreateTabCaptureUIRequest(target_render_process_id, + target_render_frame_id, + capture_device_id); DVLOG(3) << "SetupTabCaptureRequest " - << ", {tab_capture_device_id = " << tab_capture_device_id << "}" + << ", {capture_device_id = " << capture_device_id << "}" << ", {target_render_process_id = " << target_render_process_id << "}" - << ", {target_render_view_id = " << target_render_view_id << "}"; + << ", {target_render_frame_id = " << target_render_frame_id << "}"; return true; } @@ -1394,7 +1379,7 @@ bool MediaStreamManager::FindExistingRequestedDeviceInfo( it != requests_.end() ; ++it) { const DeviceRequest* request = it->second; if (request->requesting_process_id == new_request.requesting_process_id && - request->requesting_view_id == new_request.requesting_view_id && + request->requesting_frame_id == new_request.requesting_frame_id && request->request_type == new_request.request_type) { for (StreamDeviceInfoArray::const_iterator device_it = request->devices.begin(); @@ -1431,7 +1416,7 @@ void MediaStreamManager::FinalizeGenerateStream(const std::string& label, } request->requester->StreamGenerated( - request->requesting_view_id, + request->requesting_frame_id, request->page_request_id, label, audio_devices, video_devices); } @@ -1442,7 +1427,7 @@ void MediaStreamManager::FinalizeRequestFailed( content::MediaStreamRequestResult result) { if (request->requester) request->requester->StreamGenerationFailed( - request->requesting_view_id, + request->requesting_frame_id, request->page_request_id, result); @@ -1457,7 +1442,7 @@ void MediaStreamManager::FinalizeRequestFailed( void MediaStreamManager::FinalizeOpenDevice(const std::string& label, DeviceRequest* request) { const StreamDeviceInfoArray& requested_devices = request->devices; - request->requester->DeviceOpened(request->requesting_view_id, + request->requester->DeviceOpened(request->requesting_frame_id, request->page_request_id, label, requested_devices.front()); } @@ -1480,7 +1465,7 @@ void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label, ClearDeviceLabels(&request->devices); request->requester->DevicesEnumerated( - request->requesting_view_id, + request->requesting_frame_id, request->page_request_id, label, request->devices); @@ -1817,8 +1802,6 @@ void MediaStreamManager::HandleAccessRequestResponse( StreamDeviceInfo device_info; device_info.device = *device_it; - // TODO(justinlin): Nicer way to do this? - // Re-append the device's id since we lost it when posting request to UI. if (device_info.device.type == content::MEDIA_TAB_VIDEO_CAPTURE || device_info.device.type == content::MEDIA_TAB_AUDIO_CAPTURE) { device_info.device.id = request->UIRequest()->tab_capture_device_id; @@ -1847,7 +1830,7 @@ void MediaStreamManager::HandleAccessRequestResponse( } // If this is request for a new MediaStream, a device is only opened once - // per render view. This is so that the permission to use a device can be + // per render frame. This is so that the permission to use a device can be // revoked by a single call to StopStreamDevice regardless of how many // MediaStreams it is being used in. if (request->request_type == MEDIA_GENERATE_STREAM) { @@ -1900,7 +1883,7 @@ void MediaStreamManager::StopMediaStreamFromBrowser(const std::string& label) { if (request->requester) { for (StreamDeviceInfoArray::iterator device_it = request->devices.begin(); device_it != request->devices.end(); ++device_it) { - request->requester->DeviceStopped(request->requesting_view_id, + request->requester->DeviceStopped(request->requesting_frame_id, label, *device_it); } diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h index 1de659c..4125b39 100644 --- a/content/browser/renderer_host/media/media_stream_manager.h +++ b/content/browser/renderer_host/media/media_stream_manager.h @@ -81,13 +81,13 @@ class CONTENT_EXPORT MediaStreamManager // Creates a new media access request which is identified by a unique string // that's returned to the caller. This will trigger the infobar and ask users - // for access to the device. |render_process_id| and |render_view_id| refer - // to the view where the infobar will appear to the user. |callback| is + // for access to the device. |render_process_id| and |render_frame_id| are + // used to determine where the infobar will appear to the user. |callback| is // used to send the selected device to the clients. An empty list of device // will be returned if the users deny the access. std::string MakeMediaAccessRequest( int render_process_id, - int render_view_id, + int render_frame_id, int page_request_id, const StreamOptions& options, const GURL& security_origin, @@ -95,11 +95,11 @@ class CONTENT_EXPORT MediaStreamManager // GenerateStream opens new media devices according to |components|. It // creates a new request which is identified by a unique string that's - // returned to the caller. |render_process_id| and |render_view_id| refer to - // the view where the infobar will appear to the user. + // returned to the caller. |render_process_id| and |render_frame_id| are used + // to determine where the infobar will appear to the user. void GenerateStream(MediaStreamRequester* requester, int render_process_id, - int render_view_id, + int render_frame_id, const ResourceContext::SaltCallback& sc, int page_request_id, const StreamOptions& components, @@ -107,7 +107,7 @@ class CONTENT_EXPORT MediaStreamManager bool user_gesture); void CancelRequest(int render_process_id, - int render_view_id, + int render_frame_id, int page_request_id); // Cancel an open request identified by |label|. @@ -116,10 +116,10 @@ class CONTENT_EXPORT MediaStreamManager // Cancel all requests for the given |render_process_id|. void CancelAllRequests(int render_process_id); - // Closes the stream device for a certain render view. The stream must have + // Closes the stream device for a certain render frame. The stream must have // been opened by a call to GenerateStream. void StopStreamDevice(int render_process_id, - int render_view_id, + int render_frame_id, const std::string& device_id); // Gets a list of devices of |type|, which must be MEDIA_DEVICE_AUDIO_CAPTURE @@ -132,7 +132,7 @@ class CONTENT_EXPORT MediaStreamManager // If |have_permission| is false, we remove the device label from the result. virtual std::string EnumerateDevices(MediaStreamRequester* requester, int render_process_id, - int render_view_id, + int render_frame_id, const ResourceContext::SaltCallback& sc, int page_request_id, MediaStreamType type, @@ -144,7 +144,7 @@ class CONTENT_EXPORT MediaStreamManager // The request is identified using string returned to the caller. void OpenDevice(MediaStreamRequester* requester, int render_process_id, - int render_view_id, + int render_frame_id, const ResourceContext::SaltCallback& sc, int page_request_id, const std::string& device_id, @@ -301,7 +301,7 @@ class CONTENT_EXPORT MediaStreamManager // needed. void PostRequestToUI(const std::string& label, DeviceRequest* request); // Returns true if a device with |device_id| has already been requested with - // a render procecss_id and render_view_id and type equal to the the values + // a render procecss_id and render_frame_id and type equal to the the values // in |request|. If it has been requested, |device_info| contain information // about the device. bool FindExistingRequestedDeviceInfo( diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc index e01b945..cc19af2 100644 --- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc @@ -99,7 +99,7 @@ class MediaStreamManagerTest : public ::testing::Test { protected: std::string MakeMediaAccessRequest(int index) { const int render_process_id = 1; - const int render_view_id = 1; + const int render_frame_id = 1; const int page_request_id = 1; const GURL security_origin; MediaStreamManager::MediaRequestResponseCallback callback = @@ -107,7 +107,7 @@ class MediaStreamManagerTest : public ::testing::Test { base::Unretained(this), index); StreamOptions options(true, true); return media_stream_manager_->MakeMediaAccessRequest(render_process_id, - render_view_id, + render_frame_id, page_request_id, options, security_origin, @@ -146,7 +146,7 @@ TEST_F(MediaStreamManagerTest, MakeMultipleRequests) { // Second request. int render_process_id = 2; - int render_view_id = 2; + int render_frame_id = 2; int page_request_id = 2; GURL security_origin; StreamOptions options(true, true); @@ -155,7 +155,7 @@ TEST_F(MediaStreamManagerTest, MakeMultipleRequests) { base::Unretained(this), 1); std::string label2 = media_stream_manager_->MakeMediaAccessRequest( render_process_id, - render_view_id, + render_frame_id, page_request_id, options, security_origin, diff --git a/content/browser/renderer_host/media/media_stream_requester.h b/content/browser/renderer_host/media/media_stream_requester.h index 337effa..c36f166 100644 --- a/content/browser/renderer_host/media/media_stream_requester.h +++ b/content/browser/renderer_host/media/media_stream_requester.h @@ -18,29 +18,29 @@ namespace content { class CONTENT_EXPORT MediaStreamRequester { public: // Called as a reply of a successful call to GenerateStream. - virtual void StreamGenerated(int render_view_id, + virtual void StreamGenerated(int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfoArray& audio_devices, const StreamDeviceInfoArray& video_devices) = 0; // Called if GenerateStream failed. virtual void StreamGenerationFailed( - int render_view_id, + int render_frame_id, int page_request_id, content::MediaStreamRequestResult result) = 0; // Called if a device has been stopped by a user from UI or the device - // has become unavailable. |render_view_id| is the render view that requested - // the device and |label| is the label of the request|. - virtual void DeviceStopped(int render_view_id, + // has become unavailable. |render_frame_id| is the render frame that + // requested the device and |label| is the label of the request. + virtual void DeviceStopped(int render_frame_id, const std::string& label, const StreamDeviceInfo& device) = 0; // Called as a reply of a successful call to EnumerateDevices. - virtual void DevicesEnumerated(int render_view_id, + virtual void DevicesEnumerated(int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfoArray& devices) = 0; // Called as a reply of a successful call to OpenDevice. - virtual void DeviceOpened(int render_view_id, + virtual void DeviceOpened(int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfo& device_info) = 0; diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy.cc b/content/browser/renderer_host/media/media_stream_ui_proxy.cc index 1c92424..122bfa2 100644 --- a/content/browser/renderer_host/media/media_stream_ui_proxy.cc +++ b/content/browser/renderer_host/media/media_stream_ui_proxy.cc @@ -5,8 +5,8 @@ #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" #include "base/command_line.h" -#include "content/browser/renderer_host/render_view_host_delegate.h" -#include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/frame_host/render_frame_host_delegate.h" +#include "content/browser/frame_host/render_frame_host_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/content_switches.h" #include "media/video/capture/fake_video_capture_device.h" @@ -16,7 +16,7 @@ namespace content { class MediaStreamUIProxy::Core { public: explicit Core(const base::WeakPtr<MediaStreamUIProxy>& proxy, - RenderViewHostDelegate* test_render_delegate); + RenderFrameHostDelegate* test_render_delegate); ~Core(); void RequestAccess(const MediaStreamRequest& request); @@ -31,7 +31,7 @@ class MediaStreamUIProxy::Core { base::WeakPtr<MediaStreamUIProxy> proxy_; scoped_ptr<MediaStreamUI> ui_; - RenderViewHostDelegate* const test_render_delegate_; + RenderFrameHostDelegate* const test_render_delegate_; // WeakPtr<> is used to RequestMediaAccessPermission() because there is no way // cancel media requests. @@ -41,7 +41,7 @@ class MediaStreamUIProxy::Core { }; MediaStreamUIProxy::Core::Core(const base::WeakPtr<MediaStreamUIProxy>& proxy, - RenderViewHostDelegate* test_render_delegate) + RenderFrameHostDelegate* test_render_delegate) : proxy_(proxy), test_render_delegate_(test_render_delegate), weak_factory_(this) { @@ -55,24 +55,22 @@ void MediaStreamUIProxy::Core::RequestAccess( const MediaStreamRequest& request) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - RenderViewHostDelegate* render_delegate; - + RenderFrameHostDelegate* render_delegate; if (test_render_delegate_) { render_delegate = test_render_delegate_; } else { - RenderViewHostImpl* host = RenderViewHostImpl::FromID( - request.render_process_id, request.render_view_id); - - // Tab may have gone away. - if (!host || !host->GetDelegate()) { - ProcessAccessRequestResponse( - MediaStreamDevices(), - MEDIA_DEVICE_INVALID_STATE, - scoped_ptr<MediaStreamUI>()); - return; - } + RenderFrameHostImpl* const host = RenderFrameHostImpl::FromID( + request.render_process_id, request.render_frame_id); + render_delegate = host ? host->delegate() : NULL; + } - render_delegate = host->GetDelegate(); + // Tab may have gone away, or has no delegate from which to request access. + if (!render_delegate) { + ProcessAccessRequestResponse( + MediaStreamDevices(), + MEDIA_DEVICE_INVALID_STATE, + scoped_ptr<MediaStreamUI>()); + return; } render_delegate->RequestMediaAccessPermission( @@ -116,13 +114,13 @@ scoped_ptr<MediaStreamUIProxy> MediaStreamUIProxy::Create() { // static scoped_ptr<MediaStreamUIProxy> MediaStreamUIProxy::CreateForTests( - RenderViewHostDelegate* render_delegate) { + RenderFrameHostDelegate* render_delegate) { return scoped_ptr<MediaStreamUIProxy>( new MediaStreamUIProxy(render_delegate)); } MediaStreamUIProxy::MediaStreamUIProxy( - RenderViewHostDelegate* test_render_delegate) + RenderFrameHostDelegate* test_render_delegate) : weak_factory_(this) { DCHECK_CURRENTLY_ON(BrowserThread::IO); core_.reset(new Core(weak_factory_.GetWeakPtr(), test_render_delegate)); diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy.h b/content/browser/renderer_host/media/media_stream_ui_proxy.h index 01be166..fe1dde5 100644 --- a/content/browser/renderer_host/media/media_stream_ui_proxy.h +++ b/content/browser/renderer_host/media/media_stream_ui_proxy.h @@ -13,11 +13,11 @@ namespace content { -class RenderViewHostDelegate; +class RenderFrameHostDelegate; // MediaStreamUIProxy proxies calls to media stream UI between IO thread and UI // thread. One instance of this class is create per MediaStream object. It must -// be create, used and destroyed on IO thread. +// be created, used and destroyed on IO thread. class CONTENT_EXPORT MediaStreamUIProxy { public: typedef base::Callback< @@ -29,7 +29,7 @@ class CONTENT_EXPORT MediaStreamUIProxy { static scoped_ptr<MediaStreamUIProxy> Create(); static scoped_ptr<MediaStreamUIProxy> CreateForTests( - RenderViewHostDelegate* render_delegate); + RenderFrameHostDelegate* render_delegate); virtual ~MediaStreamUIProxy(); @@ -48,10 +48,10 @@ class CONTENT_EXPORT MediaStreamUIProxy { virtual void OnStarted(const base::Closure& stop_callback, const WindowIdCallback& window_id_callback); - void SetRenderViewHostDelegateForTests(RenderViewHostDelegate* delegate); + void SetRenderFrameHostDelegateForTests(RenderFrameHostDelegate* delegate); protected: - MediaStreamUIProxy(RenderViewHostDelegate* test_render_delegate); + explicit MediaStreamUIProxy(RenderFrameHostDelegate* test_render_delegate); private: class Core; diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc index 4529b49..3bc1b06 100644 --- a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc @@ -5,7 +5,7 @@ #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" #include "base/message_loop/message_loop.h" -#include "content/browser/renderer_host/render_view_host_delegate.h" +#include "content/browser/frame_host/render_frame_host_delegate.h" #include "content/public/common/renderer_preferences.h" #include "content/public/test/test_browser_thread.h" #include "testing/gmock/include/gmock/gmock.h" @@ -19,22 +19,11 @@ using testing::SaveArg; namespace content { namespace { -class MockRenderViewHostDelegate : public RenderViewHostDelegate { +class MockRenderFrameHostDelegate : public RenderFrameHostDelegate { public: MOCK_METHOD2(RequestMediaAccessPermission, void(const MediaStreamRequest& request, const MediaResponseCallback& callback)); - - // Stubs for pure virtual methods we don't care about. - virtual gfx::Rect GetRootWindowResizerRect() const OVERRIDE { - NOTREACHED(); - return gfx::Rect(); - } - virtual RendererPreferences GetRendererPrefs( - BrowserContext* browser_context) const OVERRIDE { - NOTREACHED(); - return RendererPreferences(); - } }; class MockResponseCallback { @@ -76,7 +65,7 @@ class MediaStreamUIProxyTest : public testing::Test { TestBrowserThread ui_thread_; TestBrowserThread io_thread_; - MockRenderViewHostDelegate delegate_; + MockRenderFrameHostDelegate delegate_; MockResponseCallback response_callback_; scoped_ptr<MediaStreamUIProxy> proxy_; }; @@ -84,7 +73,7 @@ class MediaStreamUIProxyTest : public testing::Test { MATCHER_P(SameRequest, expected, "") { return expected.render_process_id == arg.render_process_id && - expected.render_view_id == arg.render_view_id && + expected.render_frame_id == arg.render_frame_id && expected.tab_capture_device_id == arg.tab_capture_device_id && expected.security_origin == arg.security_origin && expected.request_type == arg.request_type && diff --git a/content/browser/renderer_host/media/mock_media_observer.h b/content/browser/renderer_host/media/mock_media_observer.h index 04678c9..ae4e7e6 100644 --- a/content/browser/renderer_host/media/mock_media_observer.h +++ b/content/browser/renderer_host/media/mock_media_observer.h @@ -21,9 +21,9 @@ class MockMediaObserver : public MediaObserver { virtual ~MockMediaObserver(); MOCK_METHOD6(OnMediaRequestStateChanged, - void(int render_process_id, int render_view_id, + void(int render_process_id, int render_frame_id, int page_request_id, const GURL& security_origin, - const MediaStreamDevice& device, + MediaStreamType stream_type, const MediaRequestState state)); }; diff --git a/content/browser/renderer_host/media/video_capture_host_unittest.cc b/content/browser/renderer_host/media/video_capture_host_unittest.cc index 6088081..1df72ba 100644 --- a/content/browser/renderer_host/media/video_capture_host_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_host_unittest.cc @@ -86,23 +86,23 @@ class MockMediaStreamRequester : public MediaStreamRequester { // MediaStreamRequester implementation. MOCK_METHOD5(StreamGenerated, - void(int render_view_id, + void(int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfoArray& audio_devices, const StreamDeviceInfoArray& video_devices)); MOCK_METHOD3(StreamGenerationFailed, - void(int render_view_id, + void(int render_frame_id, int page_request_id, content::MediaStreamRequestResult result)); - MOCK_METHOD3(DeviceStopped, void(int render_view_id, + MOCK_METHOD3(DeviceStopped, void(int render_frame_id, const std::string& label, const StreamDeviceInfo& device)); - MOCK_METHOD4(DevicesEnumerated, void(int render_view_id, + MOCK_METHOD4(DevicesEnumerated, void(int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfoArray& devices)); - MOCK_METHOD4(DeviceOpened, void(int render_view_id, + MOCK_METHOD4(DeviceOpened, void(int render_frame_id, int page_request_id, const std::string& label, const StreamDeviceInfo& device_info)); @@ -319,7 +319,7 @@ class VideoCaptureHostTest : public testing::Test { void OpenSession() { const int render_process_id = 1; - const int render_view_id = 1; + const int render_frame_id = 1; const int page_request_id = 1; const GURL security_origin("http://test.com"); @@ -332,13 +332,13 @@ class VideoCaptureHostTest : public testing::Test { std::string label = media_stream_manager_->EnumerateDevices( &stream_requester_, render_process_id, - render_view_id, + render_frame_id, browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), page_request_id, MEDIA_DEVICE_VIDEO_CAPTURE, security_origin, true); - EXPECT_CALL(stream_requester_, DevicesEnumerated(render_view_id, + EXPECT_CALL(stream_requester_, DevicesEnumerated(render_frame_id, page_request_id, label, _)) @@ -359,13 +359,13 @@ class VideoCaptureHostTest : public testing::Test { media_stream_manager_->OpenDevice( &stream_requester_, render_process_id, - render_view_id, + render_frame_id, browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), page_request_id, devices[0].device.id, MEDIA_DEVICE_VIDEO_CAPTURE, security_origin); - EXPECT_CALL(stream_requester_, DeviceOpened(render_view_id, + EXPECT_CALL(stream_requester_, DeviceOpened(render_frame_id, page_request_id, _, _)) diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h index 6c87b7a..a9dea8b 100644 --- a/content/browser/renderer_host/render_view_host_delegate.h +++ b/content/browser/renderer_host/render_view_host_delegate.h @@ -13,7 +13,6 @@ #include "base/strings/string16.h" #include "content/browser/dom_storage/session_storage_namespace_impl.h" #include "content/common/content_export.h" -#include "content/public/common/media_stream_request.h" #include "content/public/common/page_transition_types.h" #include "net/base/load_states.h" #include "third_party/WebKit/public/web/WebPopupType.h" @@ -266,13 +265,6 @@ class CONTENT_EXPORT RenderViewHostDelegate { // Show the newly created full screen widget. Similar to above. virtual void ShowCreatedFullscreenWidget(int route_id) {} - // The render view has requested access to media devices listed in - // |request|, and the client should grant or deny that permission by - // calling |callback|. - virtual void RequestMediaAccessPermission( - const MediaStreamRequest& request, - const MediaResponseCallback& callback) {} - // Returns the SessionStorageNamespace the render view should use. Might // create the SessionStorageNamespace on the fly. virtual SessionStorageNamespace* GetSessionStorageNamespace( diff --git a/content/browser/speech/speech_recognition_dispatcher_host.cc b/content/browser/speech/speech_recognition_dispatcher_host.cc index 0197bcf..f18ad7d 100644 --- a/content/browser/speech/speech_recognition_dispatcher_host.cc +++ b/content/browser/speech/speech_recognition_dispatcher_host.cc @@ -108,6 +108,12 @@ void SpeechRecognitionDispatcherHost::OnStartRequest( SpeechRecognitionManagerImpl::GetInstance()->delegate()-> FilterProfanities(render_process_id_); + // TODO(miu): This is a hack to allow SpeechRecognition to operate with the + // MediaStreamManager, which partitions requests per RenderFrame, not per + // RenderView. http://crbug.com/390749 + const int params_render_frame_id = render_view_host ? + render_view_host->GetMainFrame()->GetRoutingID() : MSG_ROUTING_NONE; + BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, @@ -116,6 +122,7 @@ void SpeechRecognitionDispatcherHost::OnStartRequest( embedder_render_process_id, embedder_render_view_id, input_params, + params_render_frame_id, filter_profanities)); } @@ -123,11 +130,13 @@ void SpeechRecognitionDispatcherHost::OnStartRequestOnIO( int embedder_render_process_id, int embedder_render_view_id, const SpeechRecognitionHostMsg_StartRequest_Params& params, + int params_render_frame_id, bool filter_profanities) { SpeechRecognitionSessionContext context; context.context_name = params.origin_url; context.render_process_id = render_process_id_; context.render_view_id = params.render_view_id; + context.render_frame_id = params_render_frame_id; context.embedder_render_process_id = embedder_render_process_id; context.embedder_render_view_id = embedder_render_view_id; if (embedder_render_process_id) diff --git a/content/browser/speech/speech_recognition_dispatcher_host.h b/content/browser/speech/speech_recognition_dispatcher_host.h index f8853f1..bd1f2a43 100644 --- a/content/browser/speech/speech_recognition_dispatcher_host.h +++ b/content/browser/speech/speech_recognition_dispatcher_host.h @@ -68,6 +68,7 @@ class CONTENT_EXPORT SpeechRecognitionDispatcherHost int embedder_render_process_id, int embedder_render_view_id, const SpeechRecognitionHostMsg_StartRequest_Params& params, + int params_render_frame_id, bool filter_profanities); void OnAbortRequest(int render_view_id, int request_id); void OnStopCaptureRequest(int render_view_id, int request_id); diff --git a/content/browser/speech/speech_recognition_manager_impl.cc b/content/browser/speech/speech_recognition_manager_impl.cc index 4b0827a..1a05420 100644 --- a/content/browser/speech/speech_recognition_manager_impl.cc +++ b/content/browser/speech/speech_recognition_manager_impl.cc @@ -196,7 +196,7 @@ void SpeechRecognitionManagerImpl::RecognitionAllowedCallback(int session_id, SpeechRecognitionSessionContext& context = session->context; context.label = media_stream_manager_->MakeMediaAccessRequest( context.render_process_id, - context.render_view_id, + context.render_frame_id, context.request_id, StreamOptions(true, false), GURL(context.context_name), diff --git a/content/common/media/media_stream_messages.h b/content/common/media/media_stream_messages.h index 0d33170..e88aeab 100644 --- a/content/common/media/media_stream_messages.h +++ b/content/common/media/media_stream_messages.h @@ -105,7 +105,7 @@ IPC_MESSAGE_CONTROL2(MediaStreamMsg_GetSourcesACK, // Request a new media stream. IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_GenerateStream, - int /* render view id */, + int /* render frame id */, int /* request id */, content::StreamOptions /* components */, GURL /* security origin */, @@ -113,12 +113,12 @@ IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_GenerateStream, // Request to cancel the request for a new media stream. IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_CancelGenerateStream, - int /* render view id */, + int /* render frame id */, int /* request id */) // Request to close a device that has been opened by GenerateStream. IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_StopStreamDevice, - int /* render view id */, + int /* render frame id */, std::string /*device_id*/) // Request to enumerate devices. @@ -129,7 +129,7 @@ IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_GetSources, // Request to enumerate devices. // Used by Pepper and WebRTC. IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_EnumerateDevices, - int /* render view id */, + int /* render frame id */, int /* request id */, content::MediaStreamType /* type */, GURL /* security origin */, @@ -137,12 +137,12 @@ IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_EnumerateDevices, // Request to stop enumerating devices. IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_CancelEnumerateDevices, - int /* render view id */, + int /* render frame id */, int /* request id */) // Request to open the device. IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_OpenDevice, - int /* render view id */, + int /* render frame id */, int /* request id */, std::string /* device_id */, content::MediaStreamType /* type */, @@ -150,5 +150,5 @@ IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_OpenDevice, // Request to close a device. IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_CloseDevice, - int /* render view id */, + int /* render frame id */, std::string /*label*/) diff --git a/content/common/media/media_stream_options.cc b/content/common/media/media_stream_options.cc index c727b63..83add2a 100644 --- a/content/common/media/media_stream_options.cc +++ b/content/common/media/media_stream_options.cc @@ -42,13 +42,13 @@ bool GetFirstConstraintByName(const StreamOptions::Constraints& mandatory, std::string* value, bool* is_mandatory) { if (GetFirstConstraintByName(mandatory, name, value)) { - if (is_mandatory) - *is_mandatory = true; - return true; - } if (is_mandatory) - *is_mandatory = false; - return GetFirstConstraintByName(optional, name, value); + *is_mandatory = true; + return true; + } + if (is_mandatory) + *is_mandatory = false; + return GetFirstConstraintByName(optional, name, value); } } // namespace diff --git a/content/public/browser/media_observer.h b/content/public/browser/media_observer.h index dca5b85..321e7d0 100644 --- a/content/public/browser/media_observer.h +++ b/content/public/browser/media_observer.h @@ -24,10 +24,10 @@ class MediaObserver { // Called when a media request changes state. virtual void OnMediaRequestStateChanged( int render_process_id, - int render_view_id, + int render_frame_id, int page_request_id, const GURL& security_origin, - const MediaStreamDevice& device, + MediaStreamType stream_type, MediaRequestState state) = 0; // Called when an audio stream is being created. diff --git a/content/public/browser/speech_recognition_session_context.cc b/content/public/browser/speech_recognition_session_context.cc index 9b6575b..b185be8 100644 --- a/content/public/browser/speech_recognition_session_context.cc +++ b/content/public/browser/speech_recognition_session_context.cc @@ -11,6 +11,7 @@ namespace content { SpeechRecognitionSessionContext::SpeechRecognitionSessionContext() : render_process_id(0), render_view_id(0), + render_frame_id(0), guest_render_view_id(MSG_ROUTING_NONE), embedder_render_process_id(0), embedder_render_view_id(MSG_ROUTING_NONE), diff --git a/content/public/browser/speech_recognition_session_context.h b/content/public/browser/speech_recognition_session_context.h index d092a5d..532a4e4 100644 --- a/content/public/browser/speech_recognition_session_context.h +++ b/content/public/browser/speech_recognition_session_context.h @@ -26,6 +26,7 @@ struct CONTENT_EXPORT SpeechRecognitionSessionContext { int render_process_id; int render_view_id; + int render_frame_id; // Browser plugin guest's render view id, if this context represents a speech // recognition request from an embedder on behalf of the guest. This is used diff --git a/content/public/common/media_stream_request.cc b/content/public/common/media_stream_request.cc index cb3b8ed8..dc5e156 100644 --- a/content/public/common/media_stream_request.cc +++ b/content/public/common/media_stream_request.cc @@ -85,7 +85,7 @@ const MediaStreamDevice* MediaStreamDevices::FindById( MediaStreamRequest::MediaStreamRequest( int render_process_id, - int render_view_id, + int render_frame_id, int page_request_id, const GURL& security_origin, bool user_gesture, @@ -95,7 +95,7 @@ MediaStreamRequest::MediaStreamRequest( MediaStreamType audio_type, MediaStreamType video_type) : render_process_id(render_process_id), - render_view_id(render_view_id), + render_frame_id(render_frame_id), page_request_id(page_request_id), security_origin(security_origin), user_gesture(user_gesture), diff --git a/content/public/common/media_stream_request.h b/content/public/common/media_stream_request.h index 5a91fd1..6d882ea 100644 --- a/content/public/common/media_stream_request.h +++ b/content/public/common/media_stream_request.h @@ -192,7 +192,7 @@ typedef std::map<MediaStreamType, MediaStreamDevices> MediaStreamDeviceMap; struct CONTENT_EXPORT MediaStreamRequest { MediaStreamRequest( int render_process_id, - int render_view_id, + int render_frame_id, int page_request_id, const GURL& security_origin, bool user_gesture, @@ -209,12 +209,12 @@ struct CONTENT_EXPORT MediaStreamRequest { // displayed for this renderer. int render_process_id; - // This is the render view id for the renderer associated with generating + // This is the render frame id for the renderer associated with generating // frames for a MediaStream. Any indicators associated with a capture will be // displayed for this renderer. - int render_view_id; + int render_frame_id; - // The unique id combined with render_process_id and render_view_id for + // The unique id combined with render_process_id and render_frame_id for // identifying this request. This is used for cancelling request. int page_request_id; diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h index ac836bb..d298065 100644 --- a/content/public/renderer/render_frame_observer.h +++ b/content/public/renderer/render_frame_observer.h @@ -54,6 +54,10 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener, virtual void DidClearWindowObject() {} virtual void DidChangeName(const base::string16& name) {} + // Called when the frame will soon be closed. This is the last opportunity to + // send messages to the host (e.g., for clean-up, shutdown, etc.). + virtual void FrameWillClose() {} + // Called when we receive a console message from Blink for which we requested // extra details (like the stack trace). |message| is the error message, // |source| is the Blink-reported source of the error (either external or diff --git a/content/renderer/media/media_stream_audio_source.cc b/content/renderer/media/media_stream_audio_source.cc index 069f4e3..d988552 100644 --- a/content/renderer/media/media_stream_audio_source.cc +++ b/content/renderer/media/media_stream_audio_source.cc @@ -4,14 +4,28 @@ #include "content/renderer/media/media_stream_audio_source.h" +#include "content/renderer/render_frame_impl.h" +#include "content/renderer/render_view_impl.h" + namespace content { +namespace { +// TODO(miu): This is a temporary hack until the Chrome audio vertical is +// migrated for the Cross-Site Isolation project. http://crbug.com/392596 +int ToRenderViewId(int render_frame_id) { + RenderFrameImpl* const frame = + RenderFrameImpl::FromRoutingID(render_frame_id); + RenderViewImpl* const view = frame ? frame->render_view() : NULL; + return view ? view->GetRoutingID() : -1; +} +} // namespace + MediaStreamAudioSource::MediaStreamAudioSource( - int render_view_id, + int render_frame_id, const StreamDeviceInfo& device_info, const SourceStoppedCallback& stop_callback, PeerConnectionDependencyFactory* factory) - : render_view_id_(render_view_id), + : render_view_id_(ToRenderViewId(render_frame_id)), factory_(factory) { SetDeviceInfo(device_info); SetStopCallback(stop_callback); diff --git a/content/renderer/media/media_stream_audio_source.h b/content/renderer/media/media_stream_audio_source.h index 29f1d4c..7d49a43 100644 --- a/content/renderer/media/media_stream_audio_source.h +++ b/content/renderer/media/media_stream_audio_source.h @@ -17,7 +17,7 @@ namespace content { class CONTENT_EXPORT MediaStreamAudioSource : NON_EXPORTED_BASE(public MediaStreamSource) { public: - MediaStreamAudioSource(int render_view_id, + MediaStreamAudioSource(int render_frame_id, const StreamDeviceInfo& device_info, const SourceStoppedCallback& stop_callback, PeerConnectionDependencyFactory* factory); @@ -49,15 +49,15 @@ class CONTENT_EXPORT MediaStreamAudioSource virtual void DoStopSource() OVERRIDE; private: - int render_view_id_; // Render view ID that created this source. + const int render_view_id_; // Render view ID that created this source. + PeerConnectionDependencyFactory* const factory_; + // This member holds an instance of webrtc::LocalAudioSource. This is used // as a container for audio options. scoped_refptr<webrtc::AudioSourceInterface> local_audio_source_; scoped_refptr<WebRtcAudioCapturer> audio_capturer_; - PeerConnectionDependencyFactory* factory_; - DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioSource); }; diff --git a/content/renderer/media/media_stream_dispatcher.cc b/content/renderer/media/media_stream_dispatcher.cc index e2675a8..9903bdf 100644 --- a/content/renderer/media/media_stream_dispatcher.cc +++ b/content/renderer/media/media_stream_dispatcher.cc @@ -5,11 +5,9 @@ #include "content/renderer/media/media_stream_dispatcher.h" #include "base/logging.h" -#include "base/message_loop/message_loop_proxy.h" #include "content/common/media/media_stream_messages.h" #include "content/renderer/media/media_stream_dispatcher_eventhandler.h" #include "content/renderer/render_thread_impl.h" -#include "content/renderer/render_view_impl.h" #include "media/audio/audio_parameters.h" #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" #include "url/gurl.h" @@ -63,9 +61,8 @@ struct MediaStreamDispatcher::Stream { StreamDeviceInfoArray video_array; }; -MediaStreamDispatcher::MediaStreamDispatcher(RenderViewImpl* render_view) - : RenderViewObserver(render_view), - main_loop_(base::MessageLoopProxy::current()), +MediaStreamDispatcher::MediaStreamDispatcher(RenderFrame* render_frame) + : RenderFrameObserver(render_frame), next_ipc_id_(0) { } @@ -76,7 +73,7 @@ void MediaStreamDispatcher::GenerateStream( const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler, const StreamOptions& components, const GURL& security_origin) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); DVLOG(1) << "MediaStreamDispatcher::GenerateStream(" << request_id << ")"; requests_.push_back(Request(event_handler, request_id, next_ipc_id_)); @@ -88,7 +85,7 @@ void MediaStreamDispatcher::GenerateStream( void MediaStreamDispatcher::CancelGenerateStream( int request_id, const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); DVLOG(1) << "MediaStreamDispatcher::CancelGenerateStream" << ", {request_id = " << request_id << "}"; @@ -106,7 +103,7 @@ void MediaStreamDispatcher::CancelGenerateStream( void MediaStreamDispatcher::StopStreamDevice( const StreamDeviceInfo& device_info) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); DVLOG(1) << "MediaStreamDispatcher::StopStreamDevice" << ", {device_id = " << device_info.device.id << "}"; // Remove |device_info| from all streams in |label_stream_map_|. @@ -128,9 +125,10 @@ void MediaStreamDispatcher::StopStreamDevice( } if (!device_found) { - // TODO(perkj): This can currently happen since there is one - // MediaStreamDispatcher per RenderView but there is one MediaStreamImpl - // per RenderFrame. http://crbug/368030. + // TODO(perkj): Revisit this. It used to be true (but isn't anymore) that + // there was one MediaStreamDispatcher per RenderView, but one + // MediaStreamImpl per RenderFrame. Now both MediaStreamDispatcher and + // MediaStreamImpl are 1:1 per RenderFrame. http://crbug/368030. return; } @@ -144,7 +142,7 @@ void MediaStreamDispatcher::EnumerateDevices( MediaStreamType type, const GURL& security_origin, bool hide_labels_if_no_access) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE || type == MEDIA_DEVICE_VIDEO_CAPTURE || type == MEDIA_DEVICE_AUDIO_OUTPUT); @@ -167,7 +165,7 @@ void MediaStreamDispatcher::EnumerateDevices( void MediaStreamDispatcher::StopEnumerateDevices( int request_id, const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); DVLOG(1) << "MediaStreamDispatcher::StopEnumerateDevices(" << request_id << ")"; for (RequestList::iterator it = requests_.begin(); it != requests_.end(); @@ -187,7 +185,7 @@ void MediaStreamDispatcher::OpenDevice( const std::string& device_id, MediaStreamType type, const GURL& security_origin) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); DVLOG(1) << "MediaStreamDispatcher::OpenDevice(" << request_id << ")"; requests_.push_back(Request(event_handler, request_id, next_ipc_id_)); @@ -205,7 +203,7 @@ void MediaStreamDispatcher::CancelOpenDevice( } void MediaStreamDispatcher::CloseDevice(const std::string& label) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!label.empty()); DVLOG(1) << "MediaStreamDispatcher::CloseDevice" << ", {label = " << label << "}"; @@ -218,6 +216,10 @@ void MediaStreamDispatcher::CloseDevice(const std::string& label) { Send(new MediaStreamHostMsg_CloseDevice(routing_id(), label)); } +void MediaStreamDispatcher::OnDestruct() { + // Do not self-destruct. MediaStreamImpl owns |this|. +} + bool MediaStreamDispatcher::Send(IPC::Message* message) { if (!RenderThread::Get()) { delete message; @@ -252,7 +254,7 @@ void MediaStreamDispatcher::OnStreamGenerated( const std::string& label, const StreamDeviceInfoArray& audio_array, const StreamDeviceInfoArray& video_array) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); for (RequestList::iterator it = requests_.begin(); it != requests_.end(); ++it) { @@ -278,7 +280,7 @@ void MediaStreamDispatcher::OnStreamGenerated( void MediaStreamDispatcher::OnStreamGenerationFailed( int request_id, content::MediaStreamRequestResult result) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); for (RequestList::iterator it = requests_.begin(); it != requests_.end(); ++it) { Request& request = *it; @@ -297,7 +299,7 @@ void MediaStreamDispatcher::OnStreamGenerationFailed( void MediaStreamDispatcher::OnDeviceStopped( const std::string& label, const StreamDeviceInfo& device_info) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); DVLOG(1) << "MediaStreamDispatcher::OnDeviceStopped(" << "{label = " << label << "})" << ", {device_id = " << device_info.device.id << "})"; @@ -324,7 +326,7 @@ void MediaStreamDispatcher::OnDeviceStopped( void MediaStreamDispatcher::OnDevicesEnumerated( int request_id, const StreamDeviceInfoArray& device_array) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_GE(request_id, 0); for (RequestList::iterator it = requests_.begin(); it != requests_.end(); @@ -340,7 +342,7 @@ void MediaStreamDispatcher::OnDeviceOpened( int request_id, const std::string& label, const StreamDeviceInfo& device_info) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); for (RequestList::iterator it = requests_.begin(); it != requests_.end(); ++it) { Request& request = *it; @@ -367,7 +369,7 @@ void MediaStreamDispatcher::OnDeviceOpened( } void MediaStreamDispatcher::OnDeviceOpenFailed(int request_id) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); for (RequestList::iterator it = requests_.begin(); it != requests_.end(); ++it) { Request& request = *it; @@ -385,7 +387,7 @@ void MediaStreamDispatcher::OnDeviceOpenFailed(int request_id) { int MediaStreamDispatcher::audio_session_id(const std::string& label, int index) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); LabelStreamMap::iterator it = label_stream_map_.find(label); if (it == label_stream_map_.end() || it->second.audio_array.size() <= static_cast<size_t>(index)) { @@ -395,13 +397,13 @@ int MediaStreamDispatcher::audio_session_id(const std::string& label, } bool MediaStreamDispatcher::IsStream(const std::string& label) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); return label_stream_map_.find(label) != label_stream_map_.end(); } int MediaStreamDispatcher::video_session_id(const std::string& label, int index) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); LabelStreamMap::iterator it = label_stream_map_.find(label); if (it == label_stream_map_.end() || it->second.video_array.size() <= static_cast<size_t>(index)) { @@ -411,7 +413,7 @@ int MediaStreamDispatcher::video_session_id(const std::string& label, } bool MediaStreamDispatcher::IsAudioDuckingActive() const { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(thread_checker_.CalledOnValidThread()); LabelStreamMap::const_iterator stream_it = label_stream_map_.begin(); while (stream_it != label_stream_map_.end()) { const StreamDeviceInfoArray& audio_array = stream_it->second.audio_array; diff --git a/content/renderer/media/media_stream_dispatcher.h b/content/renderer/media/media_stream_dispatcher.h index 59363a3..c4e5136 100644 --- a/content/renderer/media/media_stream_dispatcher.h +++ b/content/renderer/media/media_stream_dispatcher.h @@ -13,9 +13,10 @@ #include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/threading/thread_checker.h" #include "content/common/content_export.h" #include "content/common/media/media_stream_options.h" -#include "content/public/renderer/render_view_observer.h" +#include "content/public/renderer/render_frame_observer.h" #include "content/renderer/media/media_stream_dispatcher_eventhandler.h" namespace base { @@ -24,18 +25,16 @@ class MessageLoopProxy; namespace content { -class RenderViewImpl; - // MediaStreamDispatcher is a delegate for the Media Stream API messages. // MediaStreams are used by WebKit to open media devices such as Video Capture // and Audio input devices. // It's the complement of MediaStreamDispatcherHost (owned by // BrowserRenderProcessHost). class CONTENT_EXPORT MediaStreamDispatcher - : public RenderViewObserver, + : public RenderFrameObserver, public base::SupportsWeakPtr<MediaStreamDispatcher> { public: - explicit MediaStreamDispatcher(RenderViewImpl* render_view); + explicit MediaStreamDispatcher(RenderFrame* render_frame); virtual ~MediaStreamDispatcher(); // Request a new media stream to be created. @@ -115,11 +114,12 @@ class CONTENT_EXPORT MediaStreamDispatcher // opened it. struct Stream; - // RenderViewObserver OVERRIDE. + // RenderFrameObserver OVERRIDE. + virtual void OnDestruct() OVERRIDE; virtual bool Send(IPC::Message* message) OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; // Messages from the browser. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; void OnStreamGenerated( int request_id, const std::string& label, @@ -140,7 +140,7 @@ class CONTENT_EXPORT MediaStreamDispatcher void OnDeviceOpenFailed(int request_id); // Used for DCHECKs so methods calls won't execute in the wrong thread. - scoped_refptr<base::MessageLoopProxy> main_loop_; + base::ThreadChecker thread_checker_; int next_ipc_id_; typedef std::map<std::string, Stream> LabelStreamMap; diff --git a/content/renderer/media/media_stream_dispatcher_unittest.cc b/content/renderer/media/media_stream_dispatcher_unittest.cc index 62a6f70..6e80f98 100644 --- a/content/renderer/media/media_stream_dispatcher_unittest.cc +++ b/content/renderer/media/media_stream_dispatcher_unittest.cc @@ -109,7 +109,7 @@ class MediaStreamDispatcherUnderTest : public MediaStreamDispatcher { MediaStreamDispatcherUnderTest() : MediaStreamDispatcher(NULL) {} using MediaStreamDispatcher::GetNextIpcIdForTest; - using RenderViewObserver::OnMessageReceived; + using RenderFrameObserver::OnMessageReceived; }; class MediaStreamDispatcherTest : public ::testing::Test { diff --git a/content/renderer/media/media_stream_impl.cc b/content/renderer/media/media_stream_impl.cc index 79f86a8..887b593 100644 --- a/content/renderer/media/media_stream_impl.cc +++ b/content/renderer/media/media_stream_impl.cc @@ -12,6 +12,7 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "content/public/renderer/render_frame.h" #include "content/renderer/media/media_stream.h" #include "content/renderer/media/media_stream_audio_source.h" #include "content/renderer/media/media_stream_dispatcher.h" @@ -82,15 +83,22 @@ struct MediaStreamImpl::MediaDevicesRequestInfo { }; MediaStreamImpl::MediaStreamImpl( - RenderView* render_view, - MediaStreamDispatcher* media_stream_dispatcher, - PeerConnectionDependencyFactory* dependency_factory) - : RenderViewObserver(render_view), + RenderFrame* render_frame, + PeerConnectionDependencyFactory* dependency_factory, + scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher) + : RenderFrameObserver(render_frame), dependency_factory_(dependency_factory), - media_stream_dispatcher_(media_stream_dispatcher) { + media_stream_dispatcher_(media_stream_dispatcher.Pass()), + weak_factory_(this) { + DCHECK(dependency_factory_); + DCHECK(media_stream_dispatcher_.get()); } MediaStreamImpl::~MediaStreamImpl() { + // Force-close all outstanding user media requests and local sources here, + // before the outstanding WeakPtrs are invalidated, to ensure a clean + // shutdown. + FrameWillClose(); } void MediaStreamImpl::requestUserMedia( @@ -108,7 +116,6 @@ void MediaStreamImpl::requestUserMedia( int request_id = g_next_request_id++; StreamOptions options; - blink::WebLocalFrame* frame = NULL; GURL security_origin; bool enable_automatic_output_device_selection = false; @@ -142,11 +149,9 @@ void MediaStreamImpl::requestUserMedia( } security_origin = GURL(user_media_request.securityOrigin().toString()); - // Get the WebFrame that requested a MediaStream. - // The frame is needed to tell the MediaStreamDispatcher when a stream goes - // out of scope. - frame = user_media_request.ownerDocument().frame(); - DCHECK(frame); + DCHECK(render_frame()->GetWebFrame() == + static_cast<blink::WebFrame*>( + user_media_request.ownerDocument().frame())); } DVLOG(1) << "MediaStreamImpl::requestUserMedia(" << request_id << ", [ " @@ -176,12 +181,12 @@ void MediaStreamImpl::requestUserMedia( mandatory_video ? "true":"false")); user_media_requests_.push_back( - new UserMediaRequestInfo(request_id, frame, user_media_request, - enable_automatic_output_device_selection)); + new UserMediaRequestInfo(request_id, user_media_request, + enable_automatic_output_device_selection)); media_stream_dispatcher_->GenerateStream( request_id, - AsWeakPtr(), + weak_factory_.GetWeakPtr(), options, security_origin); } @@ -226,21 +231,21 @@ void MediaStreamImpl::requestMediaDevices( media_stream_dispatcher_->EnumerateDevices( audio_input_request_id, - AsWeakPtr(), + weak_factory_.GetWeakPtr(), MEDIA_DEVICE_AUDIO_CAPTURE, security_origin, true); media_stream_dispatcher_->EnumerateDevices( video_input_request_id, - AsWeakPtr(), + weak_factory_.GetWeakPtr(), MEDIA_DEVICE_VIDEO_CAPTURE, security_origin, true); media_stream_dispatcher_->EnumerateDevices( audio_output_request_id, - AsWeakPtr(), + weak_factory_.GetWeakPtr(), MEDIA_DEVICE_AUDIO_OUTPUT, security_origin, true); @@ -253,18 +258,7 @@ void MediaStreamImpl::cancelMediaDevicesRequest( FindMediaDevicesRequestInfo(media_devices_request); if (!request) return; - - // Cancel device enumeration. - media_stream_dispatcher_->StopEnumerateDevices( - request->audio_input_request_id, - AsWeakPtr()); - media_stream_dispatcher_->StopEnumerateDevices( - request->video_input_request_id, - AsWeakPtr()); - media_stream_dispatcher_->StopEnumerateDevices( - request->audio_output_request_id, - AsWeakPtr()); - DeleteMediaDevicesRequestInfo(request); + CancelAndDeleteMediaDevicesRequest(request); } // Callback from MediaStreamDispatcher. @@ -334,7 +328,8 @@ void MediaStreamImpl::OnStreamGenerated( // Wait for the tracks to be started successfully or to fail. request_info->CallbackOnTracksStarted( - base::Bind(&MediaStreamImpl::OnCreateNativeTracksCompleted, AsWeakPtr())); + base::Bind(&MediaStreamImpl::OnCreateNativeTracksCompleted, + weak_factory_.GetWeakPtr())); } // Callback from MediaStreamDispatcher. @@ -380,7 +375,7 @@ void MediaStreamImpl::OnDeviceStopped( for (LocalStreamSources::iterator device_it = local_sources_.begin(); device_it != local_sources_.end(); ++device_it) { - if (device_it->source.id() == source.id()) { + if (device_it->id() == source.id()) { local_sources_.erase(device_it); break; } @@ -391,7 +386,6 @@ void MediaStreamImpl::InitializeSourceObject( const StreamDeviceInfo& device, blink::WebMediaStreamSource::Type type, const blink::WebMediaConstraints& constraints, - blink::WebFrame* frame, blink::WebMediaStreamSource* webkit_source) { const blink::WebMediaStreamSource* existing_source = FindLocalSource(device); @@ -415,18 +409,20 @@ void MediaStreamImpl::InitializeSourceObject( webkit_source->setExtraData( CreateVideoSource( device, - base::Bind(&MediaStreamImpl::OnLocalSourceStopped, AsWeakPtr()))); + base::Bind(&MediaStreamImpl::OnLocalSourceStopped, + weak_factory_.GetWeakPtr()))); } else { DCHECK_EQ(blink::WebMediaStreamSource::TypeAudio, type); MediaStreamAudioSource* audio_source( new MediaStreamAudioSource( - RenderViewObserver::routing_id(), + RenderFrameObserver::routing_id(), device, - base::Bind(&MediaStreamImpl::OnLocalSourceStopped, AsWeakPtr()), + base::Bind(&MediaStreamImpl::OnLocalSourceStopped, + weak_factory_.GetWeakPtr()), dependency_factory_)); webkit_source->setExtraData(audio_source); } - local_sources_.push_back(LocalStreamSource(frame, *webkit_source)); + local_sources_.push_back(*webkit_source); } MediaStreamVideoSource* MediaStreamImpl::CreateVideoSource( @@ -450,7 +446,6 @@ void MediaStreamImpl::CreateVideoTracks( InitializeSourceObject(devices[i], blink::WebMediaStreamSource::TypeVideo, constraints, - request->frame, &webkit_source); (*webkit_tracks)[i] = request->CreateAndStartVideoTrack(webkit_source, constraints); @@ -491,7 +486,6 @@ void MediaStreamImpl::CreateAudioTracks( InitializeSourceObject(overridden_audio_array[i], blink::WebMediaStreamSource::TypeAudio, constraints, - request->frame, &webkit_source); (*webkit_tracks)[i].initialize(webkit_source); request->StartAudioTrack((*webkit_tracks)[i], constraints); @@ -585,19 +579,7 @@ void MediaStreamImpl::OnDevicesEnumerated( } EnumerateDevicesSucceded(&request->request, devices); - - // Cancel device enumeration. - media_stream_dispatcher_->StopEnumerateDevices( - request->audio_input_request_id, - AsWeakPtr()); - media_stream_dispatcher_->StopEnumerateDevices( - request->video_input_request_id, - AsWeakPtr()); - media_stream_dispatcher_->StopEnumerateDevices( - request->audio_output_request_id, - AsWeakPtr()); - - DeleteMediaDevicesRequestInfo(request); + CancelAndDeleteMediaDevicesRequest(request); } void MediaStreamImpl::OnDeviceOpened( @@ -672,13 +654,13 @@ const blink::WebMediaStreamSource* MediaStreamImpl::FindLocalSource( const StreamDeviceInfo& device) const { for (LocalStreamSources::const_iterator it = local_sources_.begin(); it != local_sources_.end(); ++it) { - MediaStreamSource* source = - static_cast<MediaStreamSource*>(it->source.extraData()); + MediaStreamSource* const source = + static_cast<MediaStreamSource*>(it->extraData()); const StreamDeviceInfo& active_device = source->device_info(); if (active_device.device.id == device.device.id && active_device.device.type == device.device.type && active_device.session_id == device.session_id) { - return &it->source; + return &(*it); } } return NULL; @@ -742,11 +724,19 @@ MediaStreamImpl::FindMediaDevicesRequestInfo( return NULL; } -void MediaStreamImpl::DeleteMediaDevicesRequestInfo( +void MediaStreamImpl::CancelAndDeleteMediaDevicesRequest( MediaDevicesRequestInfo* request) { MediaDevicesRequests::iterator it = media_devices_requests_.begin(); for (; it != media_devices_requests_.end(); ++it) { if ((*it) == request) { + // Cancel device enumeration. + media_stream_dispatcher_->StopEnumerateDevices( + request->audio_input_request_id, weak_factory_.GetWeakPtr()); + media_stream_dispatcher_->StopEnumerateDevices( + request->video_input_request_id, weak_factory_.GetWeakPtr()); + media_stream_dispatcher_->StopEnumerateDevices( + request->audio_output_request_id, weak_factory_.GetWeakPtr()); + media_devices_requests_.erase(it); return; } @@ -754,43 +744,28 @@ void MediaStreamImpl::DeleteMediaDevicesRequestInfo( NOTREACHED(); } -void MediaStreamImpl::FrameDetached(blink::WebFrame* frame) { - // Do same thing as FrameWillClose. - FrameWillClose(frame); -} - -void MediaStreamImpl::FrameWillClose(blink::WebFrame* frame) { - // Loop through all UserMediaRequests and find the requests that belong to the - // frame that is being closed. +void MediaStreamImpl::FrameWillClose() { + // Cancel all outstanding UserMediaRequests. UserMediaRequests::iterator request_it = user_media_requests_.begin(); while (request_it != user_media_requests_.end()) { - if ((*request_it)->frame == frame) { - DVLOG(1) << "MediaStreamImpl::FrameWillClose: " - << "Cancel user media request " << (*request_it)->request_id; - // If the request is not generated, it means that a request - // has been sent to the MediaStreamDispatcher to generate a stream - // but MediaStreamDispatcher has not yet responded and we need to cancel - // the request. - if (!(*request_it)->generated) { - media_stream_dispatcher_->CancelGenerateStream( - (*request_it)->request_id, AsWeakPtr()); - } - request_it = user_media_requests_.erase(request_it); - } else { - ++request_it; + DVLOG(1) << "MediaStreamImpl@" << this << "::FrameWillClose: " + << "Cancel user media request " << (*request_it)->request_id; + // If the request is not generated, it means that a request + // has been sent to the MediaStreamDispatcher to generate a stream + // but MediaStreamDispatcher has not yet responded and we need to cancel + // the request. + if (!(*request_it)->generated) { + media_stream_dispatcher_->CancelGenerateStream( + (*request_it)->request_id, weak_factory_.GetWeakPtr()); } + request_it = user_media_requests_.erase(request_it); } - // Loop through all current local sources and stop the sources that were - // created by the frame that will be closed. + // Loop through all current local sources and stop the sources. LocalStreamSources::iterator sources_it = local_sources_.begin(); while (sources_it != local_sources_.end()) { - if (sources_it->frame == frame) { - StopLocalSource(sources_it->source, true); - sources_it = local_sources_.erase(sources_it); - } else { - ++sources_it; - } + StopLocalSource(*sources_it, true); + sources_it = local_sources_.erase(sources_it); } } @@ -802,7 +777,7 @@ void MediaStreamImpl::OnLocalSourceStopped( bool device_found = false; for (LocalStreamSources::iterator device_it = local_sources_.begin(); device_it != local_sources_.end(); ++device_it) { - if (device_it->source.id() == source.id()) { + if (device_it->id() == source.id()) { device_found = true; local_sources_.erase(device_it); break; @@ -811,7 +786,7 @@ void MediaStreamImpl::OnLocalSourceStopped( CHECK(device_found); MediaStreamSource* source_impl = - static_cast<MediaStreamSource*> (source.extraData()); + static_cast<MediaStreamSource*>(source.extraData()); media_stream_dispatcher_->StopStreamDevice(source_impl->device_info()); } @@ -819,7 +794,7 @@ void MediaStreamImpl::StopLocalSource( const blink::WebMediaStreamSource& source, bool notify_dispatcher) { MediaStreamSource* source_impl = - static_cast<MediaStreamSource*> (source.extraData()); + static_cast<MediaStreamSource*>(source.extraData()); DVLOG(1) << "MediaStreamImpl::StopLocalSource(" << "{device_id = " << source_impl->device_info().device.id << "})"; @@ -832,14 +807,12 @@ void MediaStreamImpl::StopLocalSource( MediaStreamImpl::UserMediaRequestInfo::UserMediaRequestInfo( int request_id, - blink::WebFrame* frame, const blink::WebUserMediaRequest& request, bool enable_automatic_output_device_selection) : request_id(request_id), generated(false), enable_automatic_output_device_selection( enable_automatic_output_device_selection), - frame(frame), request(request), request_failed_(false) { } diff --git a/content/renderer/media/media_stream_impl.h b/content/renderer/media/media_stream_impl.h index ad96020..0effc2a 100644 --- a/content/renderer/media/media_stream_impl.h +++ b/content/renderer/media/media_stream_impl.h @@ -16,7 +16,7 @@ #include "base/memory/weak_ptr.h" #include "base/threading/non_thread_safe.h" #include "content/common/content_export.h" -#include "content/public/renderer/render_view_observer.h" +#include "content/public/renderer/render_frame_observer.h" #include "content/renderer/media/media_stream_dispatcher_eventhandler.h" #include "content/renderer/media/media_stream_source.h" #include "third_party/WebKit/public/platform/WebMediaStream.h" @@ -38,20 +38,23 @@ class VideoCapturerDelegate; // (via MediaStreamDispatcher and MediaStreamDispatcherHost) // in the browser process. It must be created, called and destroyed on the // render thread. -// MediaStreamImpl have weak pointers to a MediaStreamDispatcher. class CONTENT_EXPORT MediaStreamImpl - : public RenderViewObserver, + : public RenderFrameObserver, NON_EXPORTED_BASE(public blink::WebUserMediaClient), public MediaStreamDispatcherEventHandler, - public base::SupportsWeakPtr<MediaStreamImpl>, NON_EXPORTED_BASE(public base::NonThreadSafe) { public: + // |render_frame| and |dependency_factory| must outlive this instance. MediaStreamImpl( - RenderView* render_view, - MediaStreamDispatcher* media_stream_dispatcher, - PeerConnectionDependencyFactory* dependency_factory); + RenderFrame* render_frame, + PeerConnectionDependencyFactory* dependency_factory, + scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher); virtual ~MediaStreamImpl(); + MediaStreamDispatcher* media_stream_dispatcher() const { + return media_stream_dispatcher_.get(); + } + // blink::WebUserMediaClient implementation virtual void requestUserMedia( const blink::WebUserMediaRequest& user_media_request); @@ -82,9 +85,8 @@ class CONTENT_EXPORT MediaStreamImpl const StreamDeviceInfo& device_info) OVERRIDE; virtual void OnDeviceOpenFailed(int request_id) OVERRIDE; - // RenderViewObserver OVERRIDE - virtual void FrameDetached(blink::WebFrame* frame) OVERRIDE; - virtual void FrameWillClose(blink::WebFrame* frame) OVERRIDE; + // RenderFrameObserver OVERRIDE + virtual void FrameWillClose() OVERRIDE; protected: // Called when |source| has been stopped from JavaScript. @@ -119,7 +121,6 @@ class CONTENT_EXPORT MediaStreamImpl ResourcesReady; UserMediaRequestInfo(int request_id, - blink::WebFrame* frame, const blink::WebUserMediaRequest& request, bool enable_automatic_output_device_selection); ~UserMediaRequestInfo(); @@ -128,7 +129,6 @@ class CONTENT_EXPORT MediaStreamImpl // OnStreamGenerated. bool generated; const bool enable_automatic_output_device_selection; - blink::WebFrame* frame; // WebFrame that requested the MediaStream. blink::WebMediaStream web_stream; blink::WebUserMediaRequest request; @@ -160,17 +160,7 @@ class CONTENT_EXPORT MediaStreamImpl }; typedef ScopedVector<UserMediaRequestInfo> UserMediaRequests; - struct LocalStreamSource { - LocalStreamSource(blink::WebFrame* frame, - const blink::WebMediaStreamSource& source) - : frame(frame), source(source) { - } - // |frame| is the WebFrame that requested |source|. NULL in unit tests. - // TODO(perkj): Change so that |frame| is not NULL in unit tests. - blink::WebFrame* frame; - blink::WebMediaStreamSource source; - }; - typedef std::vector<LocalStreamSource> LocalStreamSources; + typedef std::vector<blink::WebMediaStreamSource> LocalStreamSources; struct MediaDevicesRequestInfo; typedef ScopedVector<MediaDevicesRequestInfo> MediaDevicesRequests; @@ -181,7 +171,6 @@ class CONTENT_EXPORT MediaStreamImpl const StreamDeviceInfo& device, blink::WebMediaStreamSource::Type type, const blink::WebMediaConstraints& constraints, - blink::WebFrame* frame, blink::WebMediaStreamSource* webkit_source); void CreateVideoTracks( @@ -210,7 +199,7 @@ class CONTENT_EXPORT MediaStreamImpl MediaDevicesRequestInfo* FindMediaDevicesRequestInfo(int request_id); MediaDevicesRequestInfo* FindMediaDevicesRequestInfo( const blink::WebMediaDevicesRequest& request); - void DeleteMediaDevicesRequestInfo(MediaDevicesRequestInfo* request); + void CancelAndDeleteMediaDevicesRequest(MediaDevicesRequestInfo* request); // Returns the source that use a device with |device.session_id| // and |device.device.id|. NULL if such source doesn't exist. @@ -224,11 +213,11 @@ class CONTENT_EXPORT MediaStreamImpl // It's valid for the lifetime of RenderThread. // TODO(xians): Remove this dependency once audio do not need it for local // audio. - PeerConnectionDependencyFactory* dependency_factory_; + PeerConnectionDependencyFactory* const dependency_factory_; - // media_stream_dispatcher_ is a weak reference, owned by RenderView. It's - // valid for the lifetime of RenderView. - MediaStreamDispatcher* media_stream_dispatcher_; + // MediaStreamImpl owns MediaStreamDispatcher instead of RenderFrameImpl + // (or RenderFrameObserver) to ensure tear-down occurs in the right order. + const scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher_; LocalStreamSources local_sources_; @@ -237,6 +226,10 @@ class CONTENT_EXPORT MediaStreamImpl // Requests to enumerate media devices. MediaDevicesRequests media_devices_requests_; + // Note: This member must be the last to ensure all outstanding weak pointers + // are invalidated first. + base::WeakPtrFactory<MediaStreamImpl> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(MediaStreamImpl); }; diff --git a/content/renderer/media/media_stream_impl_unittest.cc b/content/renderer/media/media_stream_impl_unittest.cc index cddf119..997340a 100644 --- a/content/renderer/media/media_stream_impl_unittest.cc +++ b/content/renderer/media/media_stream_impl_unittest.cc @@ -43,9 +43,11 @@ class MediaStreamImplUnderTest : public MediaStreamImpl { REQUEST_FAILED, }; - MediaStreamImplUnderTest(MediaStreamDispatcher* media_stream_dispatcher, - PeerConnectionDependencyFactory* dependency_factory) - : MediaStreamImpl(NULL, media_stream_dispatcher, dependency_factory), + MediaStreamImplUnderTest( + PeerConnectionDependencyFactory* dependency_factory, + scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher) + : MediaStreamImpl( + NULL, dependency_factory, media_stream_dispatcher.Pass()), state_(REQUEST_NOT_STARTED), result_(NUM_MEDIA_REQUEST_RESULTS), factory_(dependency_factory), @@ -128,10 +130,11 @@ class MediaStreamImplTest : public ::testing::Test { virtual void SetUp() { // Create our test object. child_process_.reset(new ChildProcess()); - ms_dispatcher_.reset(new MockMediaStreamDispatcher()); dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); - ms_impl_.reset(new MediaStreamImplUnderTest(ms_dispatcher_.get(), - dependency_factory_.get())); + ms_dispatcher_ = new MockMediaStreamDispatcher(); + ms_impl_.reset(new MediaStreamImplUnderTest( + dependency_factory_.get(), + scoped_ptr<MediaStreamDispatcher>(ms_dispatcher_).Pass())); } blink::WebMediaStream RequestLocalMediaStream() { @@ -199,7 +202,7 @@ class MediaStreamImplTest : public ::testing::Test { protected: base::MessageLoop message_loop_; scoped_ptr<ChildProcess> child_process_; - scoped_ptr<MockMediaStreamDispatcher> ms_dispatcher_; + MockMediaStreamDispatcher* ms_dispatcher_; // Owned my |ms_impl_|. scoped_ptr<MediaStreamImplUnderTest> ms_impl_; scoped_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; }; @@ -329,16 +332,13 @@ TEST_F(MediaStreamImplTest, StopSourceWhenMediaStreamGoesOutOfScope) { EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); } -// Test that the MediaStreams are deleted if the owning WebFrame is deleted. +// Test that the MediaStreams are deleted if the owning WebFrame is closing. // In the unit test the owning frame is NULL. TEST_F(MediaStreamImplTest, FrameWillClose) { // Test a stream with both audio and video. blink::WebMediaStream mixed_desc = RequestLocalMediaStream(); blink::WebMediaStream desc2 = RequestLocalMediaStream(); - - // Test that the MediaStreams are deleted if the owning WebFrame is deleted. - // In the unit test the owning frame is NULL. - ms_impl_->FrameWillClose(NULL); + ms_impl_->FrameWillClose(); EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); } @@ -387,7 +387,7 @@ TEST_F(MediaStreamImplTest, MediaStreamImplShutDown) { // being generated by the MediaStreamDispatcher. TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingStream) { ms_impl_->RequestUserMedia(); - ms_impl_->FrameWillClose(NULL); + ms_impl_->FrameWillClose(); EXPECT_EQ(1, ms_dispatcher_->request_stream_counter()); EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter()); EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter()); @@ -401,7 +401,7 @@ TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingSources) { ms_impl_->RequestUserMedia(); FakeMediaStreamDispatcherRequestUserMediaComplete(); EXPECT_EQ(1, ms_dispatcher_->request_stream_counter()); - ms_impl_->FrameWillClose(NULL); + ms_impl_->FrameWillClose(); EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE, @@ -413,7 +413,7 @@ TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingSources) { TEST_F(MediaStreamImplTest, StopTrackAfterReload) { blink::WebMediaStream mixed_desc = RequestLocalMediaStream(); EXPECT_EQ(1, ms_dispatcher_->request_stream_counter()); - ms_impl_->FrameWillClose(NULL); + ms_impl_->FrameWillClose(); EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); diff --git a/content/renderer/media/webrtc_audio_renderer.cc b/content/renderer/media/webrtc_audio_renderer.cc index 3193dba..006f12f 100644 --- a/content/renderer/media/webrtc_audio_renderer.cc +++ b/content/renderer/media/webrtc_audio_renderer.cc @@ -12,7 +12,7 @@ #include "content/renderer/media/media_stream_dispatcher.h" #include "content/renderer/media/webrtc_audio_device_impl.h" #include "content/renderer/media/webrtc_logging.h" -#include "content/renderer/render_view_impl.h" +#include "content/renderer/render_frame_impl.h" #include "media/audio/audio_output_device.h" #include "media/audio/audio_parameters.h" #include "media/audio/sample_rates.h" @@ -186,10 +186,12 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer { // Returns either AudioParameters::NO_EFFECTS or AudioParameters::DUCKING // depending on whether or not an input element is currently open with // ducking enabled. -int GetCurrentDuckingFlag(int render_view_id) { - RenderViewImpl* render_view = RenderViewImpl::FromRoutingID(render_view_id); - if (render_view && render_view->media_stream_dispatcher() && - render_view->media_stream_dispatcher()->IsAudioDuckingActive()) { +int GetCurrentDuckingFlag(int render_frame_id) { + RenderFrameImpl* const frame = + RenderFrameImpl::FromRoutingID(render_frame_id); + MediaStreamDispatcher* const dispatcher = frame ? + frame->GetMediaStreamDispatcher() : NULL; + if (dispatcher && dispatcher->IsAudioDuckingActive()) { return media::AudioParameters::DUCKING; } @@ -218,7 +220,7 @@ WebRtcAudioRenderer::WebRtcAudioRenderer( sink_params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_STEREO, 0, sample_rate, 16, frames_per_buffer, - GetCurrentDuckingFlag(source_render_view_id)) { + GetCurrentDuckingFlag(source_render_frame_id)) { WebRtcLogMessage(base::StringPrintf( "WAR::WAR. source_render_view_id=%d" ", session_id=%d, sample_rate=%d, frames_per_buffer=%d, effects=%i", diff --git a/content/renderer/media/webrtc_local_audio_renderer.cc b/content/renderer/media/webrtc_local_audio_renderer.cc index ed98b28..f13e7b0 100644 --- a/content/renderer/media/webrtc_local_audio_renderer.cc +++ b/content/renderer/media/webrtc_local_audio_renderer.cc @@ -12,7 +12,7 @@ #include "content/renderer/media/audio_device_factory.h" #include "content/renderer/media/media_stream_dispatcher.h" #include "content/renderer/media/webrtc_audio_capturer.h" -#include "content/renderer/render_view_impl.h" +#include "content/renderer/render_frame_impl.h" #include "media/audio/audio_output_device.h" #include "media/base/audio_bus.h" #include "media/base/audio_fifo.h" @@ -266,11 +266,11 @@ void WebRtcLocalAudioRenderer::ReconfigureSink( DVLOG(1) << "WebRtcLocalAudioRenderer::ReconfigureSink()"; int implicit_ducking_effect = 0; - RenderViewImpl* render_view = - RenderViewImpl::FromRoutingID(source_render_view_id_); - if (render_view && - render_view->media_stream_dispatcher() && - render_view->media_stream_dispatcher()->IsAudioDuckingActive()) { + RenderFrameImpl* const frame = + RenderFrameImpl::FromRoutingID(source_render_frame_id_); + MediaStreamDispatcher* const dispatcher = frame ? + frame->GetMediaStreamDispatcher() : NULL; + if (dispatcher && dispatcher->IsAudioDuckingActive()) { DVLOG(1) << "Forcing DUCKING to be ON for output"; implicit_ducking_effect = media::AudioParameters::DUCKING; } else { diff --git a/content/renderer/pepper/pepper_audio_input_host.cc b/content/renderer/pepper/pepper_audio_input_host.cc index a86e177..0da9cd1 100644 --- a/content/renderer/pepper/pepper_audio_input_host.cc +++ b/content/renderer/pepper/pepper_audio_input_host.cc @@ -10,7 +10,7 @@ #include "content/renderer/pepper/pepper_platform_audio_input.h" #include "content/renderer/pepper/pepper_plugin_instance_impl.h" #include "content/renderer/pepper/renderer_ppapi_host_impl.h" -#include "content/renderer/render_view_impl.h" +#include "content/renderer/render_frame_impl.h" #include "ipc/ipc_message.h" #include "ppapi/c/pp_errors.h" #include "ppapi/host/dispatch_host_message.h" @@ -46,8 +46,8 @@ PepperAudioInputHost::PepperAudioInputHost(RendererPpapiHostImpl* host, renderer_ppapi_host_(host), audio_input_(NULL), enumeration_helper_(this, - PepperMediaDeviceManager::GetForRenderView( - host->GetRenderViewForInstance(pp_instance())), + PepperMediaDeviceManager::GetForRenderFrame( + host->GetRenderFrameForInstance(pp_instance())), PP_DEVICETYPE_DEV_AUDIOCAPTURE, host->GetDocumentURL(instance)) {} @@ -98,16 +98,14 @@ int32_t PepperAudioInputHost::OnOpen(ppapi::host::HostMessageContext* context, // When it is done, we'll get called back on StreamCreated() or // StreamCreationFailed(). - RenderViewImpl* render_view = static_cast<RenderViewImpl*>( - renderer_ppapi_host_->GetRenderViewForInstance(pp_instance())); - - audio_input_ = - PepperPlatformAudioInput::Create(render_view->AsWeakPtr(), - device_id, - document_url, - static_cast<int>(sample_rate), - static_cast<int>(sample_frame_count), - this); + audio_input_ = PepperPlatformAudioInput::Create( + renderer_ppapi_host_->GetRenderFrameForInstance(pp_instance())-> + GetRoutingID(), + device_id, + document_url, + static_cast<int>(sample_rate), + static_cast<int>(sample_frame_count), + this); if (audio_input_) { open_context_ = context->MakeReplyMessageContext(); return PP_OK_COMPLETIONPENDING; diff --git a/content/renderer/pepper/pepper_media_device_manager.cc b/content/renderer/pepper/pepper_media_device_manager.cc index b36df31..3c5abdc 100644 --- a/content/renderer/pepper/pepper_media_device_manager.cc +++ b/content/renderer/pepper/pepper_media_device_manager.cc @@ -6,7 +6,7 @@ #include "base/logging.h" #include "content/renderer/media/media_stream_dispatcher.h" -#include "content/renderer/render_view_impl.h" +#include "content/renderer/render_frame_impl.h" #include "ppapi/shared_impl/ppb_device_ref_shared.h" namespace content { @@ -23,18 +23,18 @@ ppapi::DeviceRefData FromStreamDeviceInfo(const StreamDeviceInfo& info) { } // namespace -PepperMediaDeviceManager* PepperMediaDeviceManager::GetForRenderView( - RenderView* render_view) { +PepperMediaDeviceManager* PepperMediaDeviceManager::GetForRenderFrame( + RenderFrame* render_frame) { PepperMediaDeviceManager* handler = - PepperMediaDeviceManager::Get(render_view); + PepperMediaDeviceManager::Get(render_frame); if (!handler) - handler = new PepperMediaDeviceManager(render_view); + handler = new PepperMediaDeviceManager(render_frame); return handler; } -PepperMediaDeviceManager::PepperMediaDeviceManager(RenderView* render_view) - : RenderViewObserver(render_view), - RenderViewObserverTracker<PepperMediaDeviceManager>(render_view), +PepperMediaDeviceManager::PepperMediaDeviceManager(RenderFrame* render_frame) + : RenderFrameObserver(render_frame), + RenderFrameObserverTracker<PepperMediaDeviceManager>(render_frame), next_id_(1) {} PepperMediaDeviceManager::~PepperMediaDeviceManager() { @@ -50,7 +50,7 @@ int PepperMediaDeviceManager::EnumerateDevices( int request_id = next_id_++; #if defined(ENABLE_WEBRTC) - GetRenderViewImpl()->media_stream_dispatcher()->EnumerateDevices( + GetMediaStreamDispatcher()->EnumerateDevices( request_id, AsWeakPtr(), PepperMediaDeviceManager::FromPepperDeviceType(type), @@ -76,10 +76,20 @@ void PepperMediaDeviceManager::StopEnumerateDevices(int request_id) { // of EnumerateDevices. base::MessageLoop::current()->PostTask( FROM_HERE, - base::Bind(&MediaStreamDispatcher::StopEnumerateDevices, - GetRenderViewImpl()->media_stream_dispatcher()->AsWeakPtr(), - request_id, - AsWeakPtr())); + base::Bind(&PepperMediaDeviceManager::StopEnumerateDevicesDelayed, + AsWeakPtr(), + request_id)); +#endif +} + +void PepperMediaDeviceManager::StopEnumerateDevicesDelayed(int request_id) { +#if defined(ENABLE_WEBRTC) + // This method is being invoked by the message loop at some unknown + // point-in-time after StopEnumerateDevices(). Therefore, check that + // render_frame() is not NULL, in order to guarantee + // GetMediaStreamDispatcher() won't return NULL. + if (render_frame()) + GetMediaStreamDispatcher()->StopEnumerateDevices(request_id, AsWeakPtr()); #endif } @@ -91,7 +101,7 @@ int PepperMediaDeviceManager::OpenDevice(PP_DeviceType_Dev type, int request_id = next_id_++; #if defined(ENABLE_WEBRTC) - GetRenderViewImpl()->media_stream_dispatcher()->OpenDevice( + GetMediaStreamDispatcher()->OpenDevice( request_id, AsWeakPtr(), device_id, @@ -112,14 +122,13 @@ void PepperMediaDeviceManager::CancelOpenDevice(int request_id) { open_callbacks_.erase(request_id); #if defined(ENABLE_WEBRTC) - GetRenderViewImpl()->media_stream_dispatcher()->CancelOpenDevice(request_id, - AsWeakPtr()); + GetMediaStreamDispatcher()->CancelOpenDevice(request_id, AsWeakPtr()); #endif } void PepperMediaDeviceManager::CloseDevice(const std::string& label) { #if defined(ENABLE_WEBRTC) - GetRenderViewImpl()->media_stream_dispatcher()->CloseDevice(label); + GetMediaStreamDispatcher()->CloseDevice(label); #endif } @@ -128,11 +137,9 @@ int PepperMediaDeviceManager::GetSessionID(PP_DeviceType_Dev type, #if defined(ENABLE_WEBRTC) switch (type) { case PP_DEVICETYPE_DEV_AUDIOCAPTURE: - return GetRenderViewImpl()->media_stream_dispatcher()->audio_session_id( - label, 0); + return GetMediaStreamDispatcher()->audio_session_id(label, 0); case PP_DEVICETYPE_DEV_VIDEOCAPTURE: - return GetRenderViewImpl()->media_stream_dispatcher()->video_session_id( - label, 0); + return GetMediaStreamDispatcher()->video_session_id(label, 0); default: NOTREACHED(); return 0; @@ -236,8 +243,13 @@ void PepperMediaDeviceManager::NotifyDeviceOpened(int request_id, callback.Run(request_id, succeeded, label); } -RenderViewImpl* PepperMediaDeviceManager::GetRenderViewImpl() { - return static_cast<RenderViewImpl*>(render_view()); +MediaStreamDispatcher* PepperMediaDeviceManager::GetMediaStreamDispatcher() + const { + DCHECK(render_frame()); + MediaStreamDispatcher* const dispatcher = + static_cast<RenderFrameImpl*>(render_frame())->GetMediaStreamDispatcher(); + DCHECK(dispatcher); + return dispatcher; } } // namespace content diff --git a/content/renderer/pepper/pepper_media_device_manager.h b/content/renderer/pepper/pepper_media_device_manager.h index 6fa7d7a..b3d94e0 100644 --- a/content/renderer/pepper/pepper_media_device_manager.h +++ b/content/renderer/pepper/pepper_media_device_manager.h @@ -8,22 +8,22 @@ #include <map> #include "base/memory/weak_ptr.h" +#include "content/public/renderer/render_frame_observer.h" +#include "content/public/renderer/render_frame_observer_tracker.h" #include "content/renderer/media/media_stream_dispatcher_eventhandler.h" #include "content/renderer/pepper/pepper_device_enumeration_host_helper.h" -#include "content/public/renderer/render_view_observer_tracker.h" -#include "content/public/renderer/render_view_observer.h" namespace content { -class RenderViewImpl; +class MediaStreamDispatcher; class PepperMediaDeviceManager : public MediaStreamDispatcherEventHandler, public PepperDeviceEnumerationHostHelper::Delegate, - public RenderViewObserver, - public RenderViewObserverTracker<PepperMediaDeviceManager>, + public RenderFrameObserver, + public RenderFrameObserverTracker<PepperMediaDeviceManager>, public base::SupportsWeakPtr<PepperMediaDeviceManager> { public: - static PepperMediaDeviceManager* GetForRenderView(RenderView* render_view); + static PepperMediaDeviceManager* GetForRenderFrame(RenderFrame* render_frame); virtual ~PepperMediaDeviceManager(); // PepperDeviceEnumerationHostHelper::Delegate implementation: @@ -78,13 +78,18 @@ class PepperMediaDeviceManager static PP_DeviceType_Dev FromMediaStreamType(MediaStreamType type); private: - PepperMediaDeviceManager(RenderView* render_view); + explicit PepperMediaDeviceManager(RenderFrame* render_frame); + + // Called by StopEnumerateDevices() after returing to the event loop, to avoid + // a reentrancy problem. + void StopEnumerateDevicesDelayed(int request_id); void NotifyDeviceOpened(int request_id, bool succeeded, const std::string& label); - RenderViewImpl* GetRenderViewImpl(); + + MediaStreamDispatcher* GetMediaStreamDispatcher() const; int next_id_; diff --git a/content/renderer/pepper/pepper_platform_audio_input.cc b/content/renderer/pepper/pepper_platform_audio_input.cc index ed2bbcf..fafff22 100644 --- a/content/renderer/pepper/pepper_platform_audio_input.cc +++ b/content/renderer/pepper/pepper_platform_audio_input.cc @@ -12,6 +12,7 @@ #include "content/renderer/media/audio_input_message_filter.h" #include "content/renderer/pepper/pepper_audio_input_host.h" #include "content/renderer/pepper/pepper_media_device_manager.h" +#include "content/renderer/render_frame_impl.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_view_impl.h" #include "media/audio/audio_manager_base.h" @@ -22,7 +23,7 @@ namespace content { // static PepperPlatformAudioInput* PepperPlatformAudioInput::Create( - const base::WeakPtr<RenderViewImpl>& render_view, + int render_frame_id, const std::string& device_id, const GURL& document_url, int sample_rate, @@ -30,7 +31,7 @@ PepperPlatformAudioInput* PepperPlatformAudioInput::Create( PepperAudioInputHost* client) { scoped_refptr<PepperPlatformAudioInput> audio_input( new PepperPlatformAudioInput()); - if (audio_input->Initialize(render_view, + if (audio_input->Initialize(render_frame_id, device_id, document_url, sample_rate, @@ -139,12 +140,13 @@ PepperPlatformAudioInput::PepperPlatformAudioInput() : client_(NULL), main_message_loop_proxy_(base::MessageLoopProxy::current()), io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()), + render_frame_id_(MSG_ROUTING_NONE), create_stream_sent_(false), pending_open_device_(false), pending_open_device_id_(-1) {} bool PepperPlatformAudioInput::Initialize( - const base::WeakPtr<RenderViewImpl>& render_view, + int render_frame_id, const std::string& device_id, const GURL& document_url, int sample_rate, @@ -152,15 +154,20 @@ bool PepperPlatformAudioInput::Initialize( PepperAudioInputHost* client) { DCHECK(main_message_loop_proxy_->BelongsToCurrentThread()); - if (!render_view.get() || !client) + RenderFrameImpl* const render_frame = + RenderFrameImpl::FromRoutingID(render_frame_id); + if (!render_frame || !client) + return false; + + render_frame_id_ = render_frame_id; + client_ = client; + + if (!GetMediaDeviceManager()) return false; ipc_ = RenderThreadImpl::current() ->audio_input_message_filter() - ->CreateAudioInputIPC(render_view->GetRoutingID()); - - render_view_ = render_view; - client_ = client; + ->CreateAudioInputIPC(render_frame->render_view()->GetRoutingID()); params_.Reset(media::AudioParameters::AUDIO_PCM_LINEAR, media::CHANNEL_LAYOUT_MONO, @@ -230,12 +237,13 @@ void PepperPlatformAudioInput::OnDeviceOpened(int request_id, pending_open_device_ = false; pending_open_device_id_ = -1; - if (succeeded && render_view_.get()) { + PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); + if (succeeded && device_manager) { DCHECK(!label.empty()); label_ = label; if (client_) { - int session_id = GetMediaDeviceManager()->GetSessionID( + int session_id = device_manager->GetSessionID( PP_DEVICETYPE_DEV_AUDIOCAPTURE, label); io_message_loop_proxy_->PostTask( FROM_HERE, @@ -254,16 +262,18 @@ void PepperPlatformAudioInput::OnDeviceOpened(int request_id, void PepperPlatformAudioInput::CloseDevice() { DCHECK(main_message_loop_proxy_->BelongsToCurrentThread()); - if (render_view_.get()) { - if (!label_.empty()) { - GetMediaDeviceManager()->CloseDevice(label_); - label_.clear(); - } - if (pending_open_device_) { - GetMediaDeviceManager()->CancelOpenDevice(pending_open_device_id_); - pending_open_device_ = false; - pending_open_device_id_ = -1; - } + if (!label_.empty()) { + PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); + if (device_manager) + device_manager->CloseDevice(label_); + label_.clear(); + } + if (pending_open_device_) { + PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); + if (device_manager) + device_manager->CancelOpenDevice(pending_open_device_id_); + pending_open_device_ = false; + pending_open_device_id_ = -1; } } @@ -275,7 +285,12 @@ void PepperPlatformAudioInput::NotifyStreamCreationFailed() { } PepperMediaDeviceManager* PepperPlatformAudioInput::GetMediaDeviceManager() { - return PepperMediaDeviceManager::GetForRenderView(render_view_.get()); + DCHECK(main_message_loop_proxy_->BelongsToCurrentThread()); + + RenderFrameImpl* const render_frame = + RenderFrameImpl::FromRoutingID(render_frame_id_); + return render_frame ? + PepperMediaDeviceManager::GetForRenderFrame(render_frame) : NULL; } } // namespace content diff --git a/content/renderer/pepper/pepper_platform_audio_input.h b/content/renderer/pepper/pepper_platform_audio_input.h index 56a701a..e443577 100644 --- a/content/renderer/pepper/pepper_platform_audio_input.h +++ b/content/renderer/pepper/pepper_platform_audio_input.h @@ -29,7 +29,6 @@ namespace content { class PepperAudioInputHost; class PepperMediaDeviceManager; -class RenderViewImpl; // PepperPlatformAudioInput is operated on two threads: the main thread (the // thread on which objects are created) and the I/O thread. All public methods, @@ -45,7 +44,7 @@ class PepperPlatformAudioInput // Factory function, returns NULL on failure. StreamCreated() will be called // when the stream is created. static PepperPlatformAudioInput* Create( - const base::WeakPtr<RenderViewImpl>& render_view, + int render_frame_id, const std::string& device_id, const GURL& document_url, int sample_rate, @@ -76,7 +75,7 @@ class PepperPlatformAudioInput PepperPlatformAudioInput(); - bool Initialize(const base::WeakPtr<RenderViewImpl>& render_view, + bool Initialize(int render_frame_id, const std::string& device_id, const GURL& document_url, int sample_rate, @@ -93,6 +92,8 @@ class PepperPlatformAudioInput void CloseDevice(); void NotifyStreamCreationFailed(); + // Can return NULL if the RenderFrame referenced by |render_frame_id_| has + // gone away. PepperMediaDeviceManager* GetMediaDeviceManager(); // The client to notify when the stream is created. THIS MUST ONLY BE @@ -106,8 +107,8 @@ class PepperPlatformAudioInput scoped_refptr<base::MessageLoopProxy> main_message_loop_proxy_; scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; - // THIS MUST ONLY BE ACCESSED ON THE MAIN THREAD. - base::WeakPtr<RenderViewImpl> render_view_; + // The frame containing the Pepper widget. + int render_frame_id_; // The unique ID to identify the opened device. THIS MUST ONLY BE ACCESSED ON // THE MAIN THREAD. diff --git a/content/renderer/pepper/pepper_platform_video_capture.cc b/content/renderer/pepper/pepper_platform_video_capture.cc index 74eea87..f883d1b 100644 --- a/content/renderer/pepper/pepper_platform_video_capture.cc +++ b/content/renderer/pepper/pepper_platform_video_capture.cc @@ -10,19 +10,19 @@ #include "content/renderer/media/video_capture_impl_manager.h" #include "content/renderer/pepper/pepper_media_device_manager.h" #include "content/renderer/pepper/pepper_video_capture_host.h" +#include "content/renderer/render_frame_impl.h" #include "content/renderer/render_thread_impl.h" -#include "content/renderer/render_view_impl.h" #include "media/base/bind_to_current_loop.h" #include "url/gurl.h" namespace content { PepperPlatformVideoCapture::PepperPlatformVideoCapture( - const base::WeakPtr<RenderViewImpl>& render_view, + int render_frame_id, const std::string& device_id, const GURL& document_url, PepperVideoCaptureHost* handler) - : render_view_(render_view), + : render_frame_id_(render_frame_id), device_id_(device_id), session_id_(0), handler_(handler), @@ -31,8 +31,9 @@ PepperPlatformVideoCapture::PepperPlatformVideoCapture( weak_factory_(this) { // We need to open the device and obtain the label and session ID before // initializing. - if (render_view_.get()) { - pending_open_device_id_ = GetMediaDeviceManager()->OpenDevice( + PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); + if (device_manager) { + pending_open_device_id_ = device_manager->OpenDevice( PP_DEVICETYPE_DEV_VIDEOCAPTURE, device_id, document_url, @@ -75,16 +76,18 @@ void PepperPlatformVideoCapture::DetachEventHandler() { release_device_cb_.Run(); release_device_cb_.Reset(); } - if (render_view_.get()) { - if (!label_.empty()) { - GetMediaDeviceManager()->CloseDevice(label_); - label_.clear(); - } - if (pending_open_device_) { - GetMediaDeviceManager()->CancelOpenDevice(pending_open_device_id_); - pending_open_device_ = false; - pending_open_device_id_ = -1; - } + if (!label_.empty()) { + PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); + if (device_manager) + device_manager->CloseDevice(label_); + label_.clear(); + } + if (pending_open_device_) { + PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); + if (device_manager) + device_manager->CancelOpenDevice(pending_open_device_id_); + pending_open_device_ = false; + pending_open_device_id_ = -1; } } @@ -101,10 +104,11 @@ void PepperPlatformVideoCapture::OnDeviceOpened(int request_id, pending_open_device_ = false; pending_open_device_id_ = -1; - succeeded = succeeded && render_view_.get(); + PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); + succeeded = succeeded && device_manager; if (succeeded) { label_ = label; - session_id_ = GetMediaDeviceManager()->GetSessionID( + session_id_ = device_manager->GetSessionID( PP_DEVICETYPE_DEV_VIDEOCAPTURE, label); VideoCaptureImplManager* manager = RenderThreadImpl::current()->video_capture_impl_manager(); @@ -145,7 +149,10 @@ void PepperPlatformVideoCapture::OnFrameReady( } PepperMediaDeviceManager* PepperPlatformVideoCapture::GetMediaDeviceManager() { - return PepperMediaDeviceManager::GetForRenderView(render_view_.get()); + RenderFrameImpl* const render_frame = + RenderFrameImpl::FromRoutingID(render_frame_id_); + return render_frame ? + PepperMediaDeviceManager::GetForRenderFrame(render_frame) : NULL; } } // namespace content diff --git a/content/renderer/pepper/pepper_platform_video_capture.h b/content/renderer/pepper/pepper_platform_video_capture.h index e31b8c7..2412f49 100644 --- a/content/renderer/pepper/pepper_platform_video_capture.h +++ b/content/renderer/pepper/pepper_platform_video_capture.h @@ -22,12 +22,11 @@ class GURL; namespace content { class PepperMediaDeviceManager; class PepperVideoCaptureHost; -class RenderViewImpl; // This object must only be used on the thread it's constructed on. class PepperPlatformVideoCapture { public: - PepperPlatformVideoCapture(const base::WeakPtr<RenderViewImpl>& render_view, + PepperPlatformVideoCapture(int render_frame_id, const std::string& device_id, const GURL& document_url, PepperVideoCaptureHost* handler); @@ -46,11 +45,13 @@ class PepperPlatformVideoCapture { const media::VideoCaptureFormat& format, const base::TimeTicks& estimated_capture_time); + // Can return NULL if the RenderFrame referenced by |render_frame_id_| has + // gone away. PepperMediaDeviceManager* GetMediaDeviceManager(); - base::WeakPtr<RenderViewImpl> render_view_; + const int render_frame_id_; + const std::string device_id_; - std::string device_id_; std::string label_; int session_id_; base::Closure release_device_cb_; diff --git a/content/renderer/pepper/pepper_video_capture_host.cc b/content/renderer/pepper/pepper_video_capture_host.cc index 3981785..d28813b 100644 --- a/content/renderer/pepper/pepper_video_capture_host.cc +++ b/content/renderer/pepper/pepper_video_capture_host.cc @@ -9,7 +9,7 @@ #include "content/renderer/pepper/pepper_platform_video_capture.h" #include "content/renderer/pepper/pepper_plugin_instance_impl.h" #include "content/renderer/pepper/renderer_ppapi_host_impl.h" -#include "content/renderer/render_view_impl.h" +#include "content/renderer/render_frame_impl.h" #include "media/base/limits.h" #include "media/base/video_frame.h" #include "ppapi/host/dispatch_host_message.h" @@ -42,8 +42,8 @@ PepperVideoCaptureHost::PepperVideoCaptureHost(RendererPpapiHostImpl* host, buffer_count_hint_(0), status_(PP_VIDEO_CAPTURE_STATUS_STOPPED), enumeration_helper_(this, - PepperMediaDeviceManager::GetForRenderView( - host->GetRenderViewForInstance(pp_instance())), + PepperMediaDeviceManager::GetForRenderFrame( + host->GetRenderFrameForInstance(pp_instance())), PP_DEVICETYPE_DEV_VIDEOCAPTURE, host->GetDocumentURL(instance)) { } @@ -261,11 +261,12 @@ int32_t PepperVideoCaptureHost::OnOpen( if (!document_url.is_valid()) return PP_ERROR_FAILED; - RenderViewImpl* render_view = static_cast<RenderViewImpl*>( - renderer_ppapi_host_->GetRenderViewForInstance(pp_instance())); - platform_video_capture_.reset(new PepperPlatformVideoCapture( - render_view->AsWeakPtr(), device_id, document_url, this)); + renderer_ppapi_host_->GetRenderFrameForInstance(pp_instance())-> + GetRoutingID(), + device_id, + document_url, + this)); open_reply_context_ = context->MakeReplyMessageContext(); diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index fd5708e..eb7370c 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc @@ -652,6 +652,13 @@ void RenderFrameImpl::OnImeConfirmComposition( #endif // ENABLE_PLUGINS +MediaStreamDispatcher* RenderFrameImpl::GetMediaStreamDispatcher() { + if (!web_user_media_client_) + InitializeUserMediaClient(); + return web_user_media_client_ ? + web_user_media_client_->media_stream_dispatcher() : NULL; +} + bool RenderFrameImpl::Send(IPC::Message* message) { if (is_detaching_) { delete message; @@ -1569,6 +1576,7 @@ void RenderFrameImpl::frameFocused() { void RenderFrameImpl::willClose(blink::WebFrame* frame) { DCHECK(!frame_ || frame_ == frame); + FOR_EACH_OBSERVER(RenderFrameObserver, observers_, FrameWillClose()); FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(), FrameWillClose(frame)); } @@ -2757,10 +2765,8 @@ void RenderFrameImpl::willStartUsingPeerConnectionHandler( } blink::WebUserMediaClient* RenderFrameImpl::userMediaClient() { - // This can happen in tests, in which case it's OK to return NULL. - if (!InitializeUserMediaClient()) - return NULL; - + if (!web_user_media_client_) + InitializeUserMediaClient(); return web_user_media_client_; } @@ -3443,32 +3449,21 @@ void RenderFrameImpl::SyncSelectionIfRequired() { GetRenderWidget()->UpdateSelectionBounds(); } -bool RenderFrameImpl::InitializeUserMediaClient() { - if (web_user_media_client_) - return true; - +void RenderFrameImpl::InitializeUserMediaClient() { if (!RenderThreadImpl::current()) // Will be NULL during unit tests. - return false; + return; #if defined(OS_ANDROID) if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebRTC)) - return false; + return; #endif #if defined(ENABLE_WEBRTC) - if (!render_view_->media_stream_dispatcher_) { - render_view_->media_stream_dispatcher_ = - new MediaStreamDispatcher(render_view_.get()); - } - - MediaStreamImpl* media_stream_impl = new MediaStreamImpl( - render_view_.get(), - render_view_->media_stream_dispatcher_, - RenderThreadImpl::current()->GetPeerConnectionDependencyFactory()); - web_user_media_client_ = media_stream_impl; - return true; -#else - return false; + DCHECK(!web_user_media_client_); + web_user_media_client_ = new MediaStreamImpl( + this, + RenderThreadImpl::current()->GetPeerConnectionDependencyFactory(), + make_scoped_ptr(new MediaStreamDispatcher(this)).Pass()); #endif } diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 0a7dda7..d1a3303 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h @@ -58,6 +58,8 @@ namespace content { class ChildFrameCompositingHelper; class GeolocationDispatcher; +class MediaStreamDispatcher; +class MediaStreamImpl; class MediaStreamRendererFactory; class MidiDispatcher; class NotificationProvider; @@ -201,6 +203,10 @@ class CONTENT_EXPORT RenderFrameImpl bool keep_selection); #endif // ENABLE_PLUGINS + // May return NULL in some cases, especially if userMediaClient() returns + // NULL. + MediaStreamDispatcher* GetMediaStreamDispatcher(); + // IPC::Sender virtual bool Send(IPC::Message* msg) OVERRIDE; @@ -526,10 +532,10 @@ class CONTENT_EXPORT RenderFrameImpl const blink::WebURLError& error, bool replace); - // Initializes |web_user_media_client_|, returning true if successful. Returns - // false if it wasn't possible to create a MediaStreamClient (e.g., WebRTC is - // disabled) in which case |web_user_media_client_| is NULL. - bool InitializeUserMediaClient(); + // Initializes |web_user_media_client_|. If this fails, because it wasn't + // possible to create a MediaStreamClient (e.g., WebRTC is disabled), then + // |web_user_media_client_| will remain NULL. + void InitializeUserMediaClient(); blink::WebMediaPlayer* CreateWebMediaPlayerForMediaStream( const blink::WebURL& url, @@ -617,7 +623,8 @@ class CONTENT_EXPORT RenderFrameImpl // Holds a reference to the service which provides desktop notifications. NotificationProvider* notification_provider_; - blink::WebUserMediaClient* web_user_media_client_; + // Destroyed via the RenderFrameObserver::OnDestruct() mechanism. + MediaStreamImpl* web_user_media_client_; // MidiClient attached to this frame; lazily initialized. MidiDispatcher* midi_dispatcher_; diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 64f1fa3..95c11b4 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -87,7 +87,6 @@ #include "content/renderer/input/input_handler_manager.h" #include "content/renderer/internal_document_state_data.h" #include "content/renderer/media/audio_device_factory.h" -#include "content/renderer/media/media_stream_dispatcher.h" #include "content/renderer/media/video_capture_impl_manager.h" #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" #include "content/renderer/memory_benchmarking_extension.h" @@ -726,7 +725,6 @@ RenderViewImpl::RenderViewImpl(RenderViewImplParams* params) #endif has_scrolled_focused_editable_node_into_rect_(false), speech_recognition_dispatcher_(NULL), - media_stream_dispatcher_(NULL), browser_plugin_manager_(NULL), devtools_agent_(NULL), accessibility_mode_(AccessibilityModeOff), @@ -849,11 +847,6 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) { OnSetRendererPrefs(params->renderer_prefs); -#if defined(ENABLE_WEBRTC) - if (!media_stream_dispatcher_) - media_stream_dispatcher_ = new MediaStreamDispatcher(this); -#endif - new MHTMLGenerator(this); #if defined(OS_MACOSX) new TextInputClientObserver(this); diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 0bc24bd..6efc709 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h @@ -133,7 +133,6 @@ class FaviconHelper; class HistoryController; class HistoryEntry; class ImageResourceFetcher; -class MediaStreamDispatcher; class MouseLockDispatcher; class NavigationState; class PepperPluginInstanceImpl; @@ -221,11 +220,6 @@ class CONTENT_EXPORT RenderViewImpl RenderFrameImpl* main_render_frame() { return main_render_frame_.get(); } - // TODO(jam): move to RenderFrameImpl - MediaStreamDispatcher* media_stream_dispatcher() { - return media_stream_dispatcher_; - } - AccessibilityMode accessibility_mode() { return accessibility_mode_; } @@ -1046,9 +1040,6 @@ class CONTENT_EXPORT RenderViewImpl // initialized. SpeechRecognitionDispatcher* speech_recognition_dispatcher_; - // MediaStream dispatcher attached to this view; lazily initialized. - MediaStreamDispatcher* media_stream_dispatcher_; - // BrowserPluginManager attached to this view; lazily initialized. scoped_refptr<BrowserPluginManager> browser_plugin_manager_; diff --git a/content/shell/renderer/test_runner/web_test_proxy.h b/content/shell/renderer/test_runner/web_test_proxy.h index f4c7f70..a11ceb7 100644 --- a/content/shell/renderer/test_runner/web_test_proxy.h +++ b/content/shell/renderer/test_runner/web_test_proxy.h @@ -347,9 +347,6 @@ class WebTestProxy : public Base, public WebTestProxyBase { WebTestProxyBase::SetStatusText(text); Base::setStatusText(text); } - virtual blink::WebUserMediaClient* userMediaClient() { - return WebTestProxyBase::GetUserMediaClient(); - } virtual void printPage(blink::WebLocalFrame* frame) { WebTestProxyBase::PrintPage(frame); } |