1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/media/media_player.h"
6
7#include <string>
8
9#include "ash/shell.h"
10#include "base/bind.h"
11#include "chrome/browser/chrome_notification_types.h"
12#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
13#include "chrome/browser/chromeos/extensions/media_player_api.h"
14#include "chrome/browser/chromeos/extensions/media_player_event_router.h"
15#include "chrome/browser/profiles/profile.h"
16#include "chrome/browser/profiles/profile_manager.h"
17#include "chrome/browser/ui/browser.h"
18#include "chrome/browser/ui/browser_iterator.h"
19#include "chrome/browser/ui/browser_tabstrip.h"
20#include "chrome/browser/ui/browser_window.h"
21#include "chrome/browser/ui/host_desktop.h"
22#include "chrome/browser/ui/tabs/tab_strip_model.h"
23#include "content/public/browser/browser_thread.h"
24#include "content/public/browser/web_contents.h"
25#include "ui/gfx/screen.h"
26
27using content::BrowserThread;
28
29namespace {
30
31const char kMediaPlayerAppName[] = "mediaplayer";
32const int kPopupRight = 20;
33const int kPopupBottom = 80;
34const int kPopupWidth = 280;
35
36// Set the initial height to the minimum possible height. Keep the constants
37// in sync with chrome/browser/resources/file_manager/css/audio_player.css.
38// SetWindowHeight will be called soon after the popup creation with the correct
39// height which will cause a nice slide-up animation.
40// TODO(kaznacheev): Remove kTitleHeight when MediaPlayer becomes chromeless.
41// kTitleHeight is an approximate value. May be different for touch-enabled UI.
42const int kTitleHeight = 35;
43const int kTrackHeight = 58;
44const int kControlsHeight = 35;
45const int kPopupHeight = kTitleHeight + kTrackHeight + kControlsHeight;
46
47}  // namespace
48
49const MediaPlayer::UrlVector& MediaPlayer::GetPlaylist() const {
50  return current_playlist_;
51}
52
53int MediaPlayer::GetPlaylistPosition() const {
54  return current_position_;
55}
56
57////////////////////////////////////////////////////////////////////////////////
58//
59// Mediaplayer
60//
61////////////////////////////////////////////////////////////////////////////////
62
63MediaPlayer::~MediaPlayer() {
64}
65
66// static
67MediaPlayer* MediaPlayer::GetInstance() {
68  return Singleton<MediaPlayer>::get();
69}
70
71// The client knows how high the client part of the window should be but
72// cannot translate it to the window height (because the window title bar height
73// is unknown). Instead it passes the height difference which this method
74// applies to the window height.
75void MediaPlayer::AdjustWindowHeight(int height_diff) {
76  Browser* browser = GetBrowser();
77  if (browser != NULL) {
78    gfx::Rect bounds = browser->window()->GetBounds();
79    int window_height = bounds.height() + height_diff;
80    browser->window()->SetBounds(gfx::Rect(
81        bounds.x(),
82        std::max(0, bounds.bottom() - window_height),
83        bounds.width(),
84        window_height));
85  }
86}
87
88void MediaPlayer::CloseWindow() {
89  Browser* browser = GetBrowser();
90  if (browser != NULL) {
91    browser->window()->Close();
92  }
93}
94
95void MediaPlayer::ClearPlaylist() {
96  current_playlist_.clear();
97}
98
99void MediaPlayer::EnqueueMediaFileUrl(const GURL& url) {
100  current_playlist_.push_back(url);
101}
102
103void MediaPlayer::ForcePlayMediaURL(const GURL& url) {
104  ClearPlaylist();
105  EnqueueMediaFileUrl(url);
106  SetPlaylistPosition(0);
107  NotifyPlaylistChanged();
108}
109
110void MediaPlayer::SetPlaylistPosition(int position) {
111  current_position_ = position;
112}
113
114void MediaPlayer::NotifyPlaylistChanged() {
115  Browser* browser = GetBrowser();
116  if (browser) {
117    extensions::MediaPlayerAPI::Get(browser->profile())->
118        media_player_event_router()->NotifyPlaylistChanged();
119  }
120}
121
122void MediaPlayer::PopupMediaPlayer() {
123  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
124    BrowserThread::PostTask(
125        BrowserThread::UI, FROM_HERE,
126        base::Bind(&MediaPlayer::PopupMediaPlayer,
127                   base::Unretained(this) /*this class is a singleton*/));
128    return;
129  }
130
131  Browser* browser = GetBrowser();
132  if (!browser) {
133    const gfx::Size screen =
134        ash::Shell::GetScreen()->GetPrimaryDisplay().size();
135    const gfx::Rect bounds(screen.width() - kPopupRight - kPopupWidth,
136                           screen.height() - kPopupBottom - kPopupHeight,
137                           kPopupWidth,
138                           kPopupHeight);
139
140    Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
141    Browser::CreateParams params(Browser::TYPE_POPUP, profile,
142                                 chrome::HOST_DESKTOP_TYPE_ASH);
143    params.app_name = kMediaPlayerAppName;
144    params.initial_bounds = bounds;
145    browser = new Browser(params);
146
147    chrome::AddSelectedTabWithURL(browser, GetMediaPlayerUrl(),
148                                  content::PAGE_TRANSITION_LINK);
149  }
150  browser->window()->Show();
151}
152
153GURL MediaPlayer::GetMediaPlayerUrl() {
154  return file_manager::util::GetMediaPlayerUrl();
155}
156
157Browser* MediaPlayer::GetBrowser() {
158  for (chrome::BrowserIterator it; !it.done(); it.Next()) {
159    Browser* browser = *it;
160    TabStripModel* tab_strip = browser->tab_strip_model();
161    for (int idx = 0; idx < tab_strip->count(); idx++) {
162      const GURL& url = tab_strip->GetWebContentsAt(idx)->GetVisibleURL();
163      GURL base_url(url.GetOrigin().spec() + url.path().substr(1));
164      if (base_url == GetMediaPlayerUrl())
165        return browser;
166    }
167  }
168  return NULL;
169}
170
171MediaPlayer::MediaPlayer()
172    : current_position_(0) {
173};
174