diff options
Diffstat (limited to 'chrome/browser/chromeos')
5 files changed, 610 insertions, 0 deletions
diff --git a/chrome/browser/chromeos/extensions/media_player_event_router.cc b/chrome/browser/chromeos/extensions/media_player_event_router.cc new file mode 100644 index 0000000..ea8f70b --- /dev/null +++ b/chrome/browser/chromeos/extensions/media_player_event_router.cc @@ -0,0 +1,29 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/extensions/media_player_event_router.h" + +#include "base/memory/singleton.h" +#include "chrome/browser/extensions/extension_event_router.h" +#include "chrome/browser/profiles/profile.h" + +ExtensionMediaPlayerEventRouter::ExtensionMediaPlayerEventRouter() + : profile_(NULL) { +} + +ExtensionMediaPlayerEventRouter* + ExtensionMediaPlayerEventRouter::GetInstance() { + return Singleton<ExtensionMediaPlayerEventRouter>::get(); +} + +void ExtensionMediaPlayerEventRouter::Init(Profile* profile) { + profile_ = profile; +} + +void ExtensionMediaPlayerEventRouter::NotifyPlaylistChanged() { + if (profile_ && profile_->GetExtensionEventRouter()) { + profile_->GetExtensionEventRouter()->DispatchEventToRenderers( + "mediaPlayerPrivate.onPlaylistChanged", "[]", NULL, GURL()); + } +} diff --git a/chrome/browser/chromeos/extensions/media_player_event_router.h b/chrome/browser/chromeos/extensions/media_player_event_router.h new file mode 100644 index 0000000..5095de1 --- /dev/null +++ b/chrome/browser/chromeos/extensions/media_player_event_router.h @@ -0,0 +1,31 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_MEDIA_PLAYER_EVENT_ROUTER_H_ +#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_MEDIA_PLAYER_EVENT_ROUTER_H_ +#pragma once + +#include "base/basictypes.h" + +class Profile; +template <typename T> struct DefaultSingletonTraits; + +// Event router class for events related to Mediaplayer. +class ExtensionMediaPlayerEventRouter { + public: + static ExtensionMediaPlayerEventRouter* GetInstance(); + + void Init(Profile* profile); + + void NotifyPlaylistChanged(); + + private: + Profile* profile_; + + ExtensionMediaPlayerEventRouter(); + friend struct DefaultSingletonTraits<ExtensionMediaPlayerEventRouter>; + DISALLOW_COPY_AND_ASSIGN(ExtensionMediaPlayerEventRouter); +}; + +#endif // CHROME_BROWSER_CHROMEOS_EXTENSIONS_MEDIA_PLAYER_EVENT_ROUTER_H_ diff --git a/chrome/browser/chromeos/media/media_player.cc b/chrome/browser/chromeos/media/media_player.cc new file mode 100644 index 0000000..d320cfa --- /dev/null +++ b/chrome/browser/chromeos/media/media_player.cc @@ -0,0 +1,311 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/media/media_player.h" + +#include "base/command_line.h" +#include "base/logging.h" +#include "base/memory/singleton.h" +#include "base/memory/weak_ptr.h" +#include "base/message_loop.h" +#include "base/path_service.h" +#include "base/string_piece.h" +#include "base/string_util.h" +#include "base/threading/thread.h" +#include "base/time.h" +#include "base/values.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/chromeos/extensions/media_player_event_router.h" +#include "chrome/browser/download/download_manager.h" +#include "chrome/browser/download/download_util.h" +#include "chrome/browser/extensions/file_manager_util.h" +#include "chrome/browser/history/history_types.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/webui/favicon_source.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/jstemplate_builder.h" +#include "chrome/common/net/url_fetcher.h" +#include "chrome/common/time_format.h" +#include "chrome/common/url_constants.h" +#include "content/browser/browser_thread.h" +#include "content/browser/tab_contents/tab_contents.h" +#include "content/browser/user_metrics.h" +#include "grit/browser_resources.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" +#include "grit/locale_settings.h" +#include "net/base/escape.h" +#include "net/base/load_flags.h" +#include "net/url_request/url_request_job.h" +#include "ui/base/resource/resource_bundle.h" + +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/frame/panel_browser_view.h" +#endif + +static const char* kMediaPlayerAppName = "mediaplayer"; +static const int kPopupLeft = 0; +static const int kPopupTop = 0; +static const int kPopupWidth = 350; +static const int kPopupHeight = 300; + +const MediaPlayer::UrlVector& MediaPlayer::GetPlaylist() const { + return current_playlist_; +} + +int MediaPlayer::GetPlaylistPosition() const { + return current_position_; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Mediaplayer +// +//////////////////////////////////////////////////////////////////////////////// + +// Allows InvokeLater without adding refcounting. This class is a Singleton and +// won't be deleted until it's last InvokeLater is run. +DISABLE_RUNNABLE_METHOD_REFCOUNT(MediaPlayer); + +MediaPlayer::~MediaPlayer() { +} + +// static +MediaPlayer* MediaPlayer::GetInstance() { + return Singleton<MediaPlayer>::get(); +} + +void MediaPlayer::EnqueueMediaFile(Profile* profile, const FilePath& file_path, + Browser* creator) { + GURL url; + if (!FileManagerUtil::ConvertFileToFileSystemUrl(profile, file_path, + GetOriginUrl(), &url)) { + } + EnqueueMediaFileUrl(url, creator); +} + +void MediaPlayer::EnqueueMediaFileUrl(const GURL& url, Browser* creator) { + if (mediaplayer_browser_ == NULL) { + PopupMediaPlayer(creator); + } + EnqueueMediaFileUrl(url); +} + +void MediaPlayer::EnqueueMediaFileUrl(const GURL& url) { + current_playlist_.push_back(MediaUrl(url)); + NotifyPlaylistChanged(); +} + +void MediaPlayer::ForcePlayMediaFile(Profile* profile, + const FilePath& file_path, + Browser* creator) { + GURL url; + if (!FileManagerUtil::ConvertFileToFileSystemUrl(profile, file_path, + GetOriginUrl(), &url)) { + return; + } + ForcePlayMediaURL(url, creator); +} + +void MediaPlayer::ForcePlayMediaURL(const GURL& url, Browser* creator) { + if (mediaplayer_browser_ == NULL) { + PopupMediaPlayer(creator); + } + current_playlist_.push_back(MediaUrl(url)); + current_position_ = current_playlist_.size() - 1; + pending_playback_request_ = true; + NotifyPlaylistChanged(); +} + +void MediaPlayer::TogglePlaylistWindowVisible() { + if (playlist_browser_) { + ClosePlaylistWindow(); + } else { + ShowPlaylistWindow(); + } +} + +void MediaPlayer::ShowPlaylistWindow() { + if (playlist_browser_ == NULL) { + PopupPlaylist(NULL); + } +} + +void MediaPlayer::ClosePlaylistWindow() { + if (playlist_browser_ != NULL) { + playlist_browser_->window()->Close(); + } +} + +void MediaPlayer::SetPlaylistPosition(int position) { + const int playlist_size = current_playlist_.size(); + if (current_position_ < 0 || current_position_ > playlist_size) + position = current_playlist_.size(); + if (current_position_ != position) { + current_position_ = position; + NotifyPlaylistChanged(); + } +} + +void MediaPlayer::SetPlaybackError(GURL const& url) { + for (size_t x = 0; x < current_playlist_.size(); x++) { + if (current_playlist_[x].url == url) { + current_playlist_[x].haderror = true; + } + } + NotifyPlaylistChanged(); +} + +void MediaPlayer::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(type == NotificationType::BROWSER_CLOSING); + registrar_.Remove(this, + NotificationType::BROWSER_CLOSING, + source); + if (Source<Browser>(source).ptr() == mediaplayer_browser_) { + mediaplayer_browser_ = NULL; + } else if (Source<Browser>(source).ptr() == playlist_browser_) { + playlist_browser_ = NULL; + } +} + +void MediaPlayer::NotifyPlaylistChanged() { + ExtensionMediaPlayerEventRouter::GetInstance()->NotifyPlaylistChanged(); +} + +bool MediaPlayer::GetPendingPlayRequestAndReset() { + bool result = pending_playback_request_; + pending_playback_request_ = false; + return result; +} + +void MediaPlayer::SetPlaybackRequest() { + pending_playback_request_ = true; +} + +void MediaPlayer::ToggleFullscreen() { + if (mediaplayer_browser_) { + mediaplayer_browser_->ToggleFullscreenMode(); + } +} + +void MediaPlayer::PopupPlaylist(Browser* creator) { + Profile* profile = BrowserList::GetLastActive()->profile(); + playlist_browser_ = Browser::CreateForApp(Browser::TYPE_PANEL, + kMediaPlayerAppName, + gfx::Size(), + profile); + registrar_.Add(this, + NotificationType::BROWSER_CLOSING, + Source<Browser>(playlist_browser_)); + playlist_browser_->AddSelectedTabWithURL(GetMediaplayerPlaylistUrl(), + PageTransition::LINK); + playlist_browser_->window()->SetBounds(gfx::Rect(kPopupLeft, + kPopupTop, + kPopupWidth, + kPopupHeight)); + playlist_browser_->window()->Show(); +} + +void MediaPlayer::PopupMediaPlayer(Browser* creator) { + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + NewRunnableMethod(this, &MediaPlayer::PopupMediaPlayer, + static_cast<Browser*>(NULL))); + return; + } + Profile* profile = BrowserList::GetLastActive()->profile(); + mediaplayer_browser_ = Browser::CreateForApp(Browser::TYPE_PANEL, + kMediaPlayerAppName, + gfx::Size(), + profile); + registrar_.Add(this, + NotificationType::BROWSER_CLOSING, + Source<Browser>(mediaplayer_browser_)); + +#if defined(OS_CHROMEOS) + // Since we are on chromeos, popups should be a PanelBrowserView, + // so we can just cast it. + if (creator) { + chromeos::PanelBrowserView* creatorview = + static_cast<chromeos::PanelBrowserView*>(creator->window()); + chromeos::PanelBrowserView* view = + static_cast<chromeos::PanelBrowserView*>( + mediaplayer_browser_->window()); + view->SetCreatorView(creatorview); + } +#endif + mediaplayer_browser_->AddSelectedTabWithURL(GetMediaPlayerUrl(), + PageTransition::LINK); + mediaplayer_browser_->window()->SetBounds(gfx::Rect(kPopupLeft, + kPopupTop, + kPopupWidth, + kPopupHeight)); + mediaplayer_browser_->window()->Show(); +} + +net::URLRequestJob* MediaPlayer::MaybeIntercept(net::URLRequest* request) { + // Don't attempt to intercept here as we want to wait until the mime + // type is fully determined. + return NULL; +} + +// This is the list of mime types currently supported by the Google +// Document Viewer. +static const char* const supported_mime_type_list[] = { + "audio/mpeg", + "video/mp4", + "audio/mp3" +}; + +net::URLRequestJob* MediaPlayer::MaybeInterceptResponse( + net::URLRequest* request) { + // Do not intercept this request if it is a download. + if (request->load_flags() & net::LOAD_IS_DOWNLOAD) { + return NULL; + } + + std::string mime_type; + request->GetMimeType(&mime_type); + // If it is in our list of known URLs, enqueue the url then + // Cancel the request so the mediaplayer can handle it when + // it hits it in the playlist. + if (supported_mime_types_.find(mime_type) != supported_mime_types_.end()) { + if (request->referrer() != chrome::kChromeUIMediaplayerURL && + !request->referrer().empty()) { + EnqueueMediaFileUrl(request->url(), NULL); + request->Cancel(); + } + } + return NULL; +} + +GURL MediaPlayer::GetOriginUrl() const { + return FileManagerUtil::GetMediaPlayerUrl().GetOrigin(); +} + +GURL MediaPlayer::GetMediaplayerPlaylistUrl() const { + return FileManagerUtil::GetMediaPlayerPlaylistUrl(); +} + +GURL MediaPlayer::GetMediaPlayerUrl() const { + return FileManagerUtil::GetMediaPlayerUrl(); +} + +MediaPlayer::MediaPlayer() + : current_position_(0), + pending_playback_request_(false), + playlist_browser_(NULL), + mediaplayer_browser_(NULL) { + for (size_t i = 0; i < arraysize(supported_mime_type_list); ++i) { + supported_mime_types_.insert(supported_mime_type_list[i]); + } +}; diff --git a/chrome/browser/chromeos/media/media_player.h b/chrome/browser/chromeos/media/media_player.h new file mode 100644 index 0000000..e916ea2 --- /dev/null +++ b/chrome/browser/chromeos/media/media_player.h @@ -0,0 +1,161 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_MEDIA_MEDIA_PLAYER_H_ +#define CHROME_BROWSER_CHROMEOS_MEDIA_MEDIA_PLAYER_H_ +#pragma once + +#include <set> +#include <vector> + +#include "base/memory/singleton.h" +#include "content/common/notification_observer.h" +#include "content/common/notification_registrar.h" +#include "content/common/notification_source.h" +#include "content/common/notification_type.h" + +#include "net/url_request/url_request.h" + +template <typename T> struct DefaultSingletonTraits; + +class Browser; +class GURL; +class Profile; + +class MediaPlayer : public NotificationObserver, + public net::URLRequest::Interceptor { + public: + struct MediaUrl; + typedef std::vector<MediaUrl> UrlVector; + + virtual ~MediaPlayer(); + + // Enqueues this file into the current playlist. If the mediaplayer is + // not currently visible, show it, and play the given url. + void EnqueueMediaFile(Profile* profile, const FilePath& file_path, + Browser* creator); + + // Enqueues this fileschema url into the current playlist. If the mediaplayer + // is not currently visible, show it, and play the given url. + void EnqueueMediaFileUrl(const GURL& url, Browser* creator); + + // Clears out the current playlist, and start playback of the given + // |file_path|. If there is no mediaplayer currently, show it, and play the + // given |file_path|. + void ForcePlayMediaFile(Profile* profile, const FilePath& file_path, + Browser* creator); + + // Clears out the current playlist, and start playback of the given url. + // If there is no mediaplayer currently, show it, and play the given url. + void ForcePlayMediaURL(const GURL& url, Browser* creator); + + // Toggle the visibility of the playlist window. + void TogglePlaylistWindowVisible(); + + // Force the playlist window to be shown. + void ShowPlaylistWindow(); + + // Toggle the mediaplayer between fullscreen and windowed. + void ToggleFullscreen(); + + // Force the playlist window to be closed. + void ClosePlaylistWindow(); + + // Sets the currently playing element to the given positions. + void SetPlaylistPosition(int position); + + // Returns current playlist. + const UrlVector& GetPlaylist() const; + + // Returns current playlist position. + int GetPlaylistPosition() const; + + // Set flag that error occuires while playing the url. + void SetPlaybackError(GURL const& url); + + // Notfies the mediaplayer that the playlist changed. This could be + // called from the mediaplayer itself for example. + void NotifyPlaylistChanged(); + + // Retuen true if playback requested. Resets this flag. + bool GetPendingPlayRequestAndReset(); + + // Requests starting playback of the current playlist item when the + // mediaplayer get the playlist updated. + void SetPlaybackRequest(); + + // Always returns NULL because we don't want to attempt a redirect + // before seeing the detected mime type of the request. + // Implementation of net::URLRequest::Interceptor. + virtual net::URLRequestJob* MaybeIntercept(net::URLRequest* request); + + // Determines if the requested document can be viewed by the + // MediaPlayer. If it can, returns a net::URLRequestJob that + // redirects the browser to the view URL. + // Implementation of net::URLRequest::Interceptor. + virtual net::URLRequestJob* MaybeInterceptResponse(net::URLRequest* request); + + // Used to detect when the mediaplayer is closed. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // Getter for the singleton. + static MediaPlayer* GetInstance(); + + private: + friend struct DefaultSingletonTraits<MediaPlayer>; + + // The current playlist of urls. + UrlVector current_playlist_; + // The position into the current_playlist_ of the currently playing item. + int current_position_; + + bool pending_playback_request_; + + MediaPlayer(); + + GURL GetOriginUrl() const; + GURL GetMediaplayerPlaylistUrl() const; + GURL GetMediaPlayerUrl() const; + + // Popup the mediaplayer, this shows the browser, and sets up its + // locations correctly. + void PopupMediaPlayer(Browser* creator); + + // Popup the playlist. Shows the browser, sets it up to point at + // chrome://mediaplayer#playlist + void PopupPlaylist(Browser* creator); + + void EnqueueMediaFileUrl(const GURL& url); + + // Browser containing the playlist. Used to force closes. This is created + // By the PopupPlaylist call, and is NULLed out when the window is closed. + Browser* playlist_browser_; + + // Browser containing the Mediaplayer. Used to force closes. This is + // created by the PopupMediaplayer call, and is NULLed out when the window + // is closed. + Browser* mediaplayer_browser_; + + // Used to register for events on the windows, like to listen for closes. + NotificationRegistrar registrar_; + + // List of mimetypes that the mediaplayer should listen to. Used for + // interceptions of url GETs. + std::set<std::string> supported_mime_types_; + friend class MediaPlayerBrowserTest; + DISALLOW_COPY_AND_ASSIGN(MediaPlayer); +}; + +struct MediaPlayer::MediaUrl { + MediaUrl() {} + explicit MediaUrl(const GURL& newurl) + : url(newurl), + haderror(false) {} + GURL url; + bool haderror; +}; + +#endif // CHROME_BROWSER_CHROMEOS_MEDIA_MEDIA_PLAYER_H_ diff --git a/chrome/browser/chromeos/media/media_player_browsertest.cc b/chrome/browser/chromeos/media/media_player_browsertest.cc new file mode 100644 index 0000000..9afaff3 --- /dev/null +++ b/chrome/browser/chromeos/media/media_player_browsertest.cc @@ -0,0 +1,78 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "base/memory/ref_counted.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/chromeos/media/media_player.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/automation/dom_element_proxy.h" +#include "chrome/test/in_process_browser_test.h" +#include "chrome/test/ui_test_utils.h" +#include "content/browser/tab_contents/tab_contents.h" + +class MediaPlayerBrowserTest : public InProcessBrowserTest { + public: + MediaPlayerBrowserTest() {} + + GURL GetMusicTestURL() { + return GURL("http://localhost:1337/files/plugin/sample_mp3.mp3"); + } + + bool IsBrowserVisible(Browser* browser) { + if (browser == NULL) + return false; + for (BrowserList::const_iterator it = BrowserList::begin(); + it != BrowserList::end(); ++it) { + if ((*it)->is_type_panel() && (*it)->is_app() && (*it) == browser) + return true; + } + return false; + } + + bool IsPlayerVisible() { + return IsBrowserVisible(MediaPlayer::GetInstance()->mediaplayer_browser_); + } + + bool IsPlaylistVisible() { + return IsBrowserVisible(MediaPlayer::GetInstance()->playlist_browser_); + } +}; + +IN_PROC_BROWSER_TEST_F(MediaPlayerBrowserTest, Popup) { + ASSERT_TRUE(test_server()->Start()); + // Doing this so we have a valid profile. + ui_test_utils::NavigateToURL(browser(), + GURL("chrome://downloads")); + + MediaPlayer* player = MediaPlayer::GetInstance(); + // Check that its not currently visible + ASSERT_FALSE(IsPlayerVisible()); + + player->EnqueueMediaFileUrl(GetMusicTestURL(), NULL); + + ASSERT_TRUE(IsPlayerVisible()); +} + +IN_PROC_BROWSER_TEST_F(MediaPlayerBrowserTest, PopupPlaylist) { + ASSERT_TRUE(test_server()->Start()); + // Doing this so we have a valid profile. + ui_test_utils::NavigateToURL(browser(), + GURL("chrome://downloads")); + + + MediaPlayer* player = MediaPlayer::GetInstance(); + + player->EnqueueMediaFileUrl(GetMusicTestURL(), NULL); + + EXPECT_FALSE(IsPlaylistVisible()); + + player->TogglePlaylistWindowVisible(); + + EXPECT_TRUE(IsPlaylistVisible()); +} + |