15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/media/media_internals_proxy.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/media/media_internals_handler.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/content_browser_client.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMediaInternalsProxyEventDelayMilliseconds = 100;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const net::NetLog::EventType kNetEventTypeFilter[] = {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetLog::TYPE_DISK_CACHE_ENTRY_IMPL,
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetLog::TYPE_SPARSE_READ,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetLog::TYPE_SPARSE_WRITE,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetLog::TYPE_URL_REQUEST_START_JOB,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaInternalsProxy::MediaInternalsProxy() {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 NotificationService::AllBrowserContextsAndSources());
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaInternalsProxy::Observe(int type,
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const NotificationSource& source,
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const NotificationDetails& details) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(type, NOTIFICATION_RENDERER_PROCESS_TERMINATED);
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RenderProcessHost* process = Source<RenderProcessHost>(source).ptr();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallJavaScriptFunctionOnUIThread("media.onRendererTerminated",
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::FundamentalValue(process->GetID()));
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaInternalsProxy::Attach(MediaInternalsMessageHandler* handler) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_ = handler;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MediaInternalsProxy::ObserveMediaInternalsOnIOThread, this));
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaInternalsProxy::Detach() {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_ = NULL;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &MediaInternalsProxy::StopObservingMediaInternalsOnIOThread, this));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaInternalsProxy::GetEverything() {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ask MediaInternals for all its data.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MediaInternalsProxy::GetEverythingOnIOThread, this));
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send the page names for constants.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallJavaScriptFunctionOnUIThread("media.onReceiveConstants", GetConstants());
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaInternalsProxy::OnUpdate(const base::string16& update) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI, FROM_HERE,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MediaInternalsProxy::UpdateUIOnUIThread, this, update));
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaInternalsProxy::OnAddEntry(const net::NetLog::Entry& entry) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_event_interesting = false;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kNetEventTypeFilter); i++) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry.type() == kNetEventTypeFilter[i]) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_event_interesting = true;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_event_interesting)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI, FROM_HERE,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MediaInternalsProxy::AddNetEventOnUIThread, this,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 entry.ToValue()));
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaInternalsProxy::~MediaInternalsProxy() {}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* MediaInternalsProxy::GetConstants() {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* event_phases = new base::DictionaryValue();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_phases->SetInteger(
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::EventPhaseToString(net::NetLog::PHASE_NONE),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_NONE);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_phases->SetInteger(
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::EventPhaseToString(net::NetLog::PHASE_BEGIN),
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_BEGIN);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_phases->SetInteger(
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::EventPhaseToString(net::NetLog::PHASE_END),
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_END);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* constants = new base::DictionaryValue();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  constants->Set("eventTypes", net::NetLog::GetEventTypesAsValue());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  constants->Set("eventPhases", event_phases);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return constants;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaInternalsProxy::ObserveMediaInternalsOnIOThread() {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  update_callback_ = base::Bind(&MediaInternalsProxy::OnUpdate,
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                base::Unretained(this));
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaInternals::GetInstance()->AddUpdateCallback(update_callback_);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (GetContentClient()->browser()->GetNetLog()) {
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net::NetLog* net_log = GetContentClient()->browser()->GetNetLog();
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net_log->AddThreadSafeObserver(this, net::NetLog::LOG_ALL_BUT_BYTES);
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaInternalsProxy::StopObservingMediaInternalsOnIOThread() {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaInternals::GetInstance()->RemoveUpdateCallback(update_callback_);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (GetContentClient()->browser()->GetNetLog()) {
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net::NetLog* net_log = GetContentClient()->browser()->GetNetLog();
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net_log->RemoveThreadSafeObserver(this);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaInternalsProxy::GetEverythingOnIOThread() {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MediaInternals::GetInstance()->SendEverything();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaInternalsProxy::UpdateUIOnUIThread(const base::string16& update) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't forward updates to a destructed UI.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (handler_)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handler_->OnUpdate(update);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaInternalsProxy::AddNetEventOnUIThread(base::Value* entry) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send the updates to the page in kMediaInternalsProxyEventDelayMilliseconds
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if an update is not already pending.
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!pending_net_updates_) {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_net_updates_.reset(new base::ListValue());
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&MediaInternalsProxy::SendNetEventsOnUIThread, this),
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            kMediaInternalsProxyEventDelayMilliseconds));
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_net_updates_->Append(entry);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaInternalsProxy::SendNetEventsOnUIThread() {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallJavaScriptFunctionOnUIThread("media.onNetUpdate",
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   pending_net_updates_.release());
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaInternalsProxy::CallJavaScriptFunctionOnUIThread(
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& function, base::Value* args) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> args_value(args);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<const base::Value*> args_vector;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args_vector.push_back(args_value.get());
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 update = WebUI::GetJavascriptCall(function, args_vector);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateUIOnUIThread(update);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
183