Home | History | Annotate | Download | only in media
      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 "content/browser/media/media_internals_proxy.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "content/browser/media/media_internals_handler.h"
     10 #include "content/public/browser/content_browser_client.h"
     11 #include "content/public/browser/notification_service.h"
     12 #include "content/public/browser/notification_types.h"
     13 #include "content/public/browser/render_process_host.h"
     14 #include "content/public/browser/web_ui.h"
     15 
     16 namespace content {
     17 
     18 static const int kMediaInternalsProxyEventDelayMilliseconds = 100;
     19 
     20 static const net::NetLog::EventType kNetEventTypeFilter[] = {
     21   net::NetLog::TYPE_DISK_CACHE_ENTRY_IMPL,
     22   net::NetLog::TYPE_SPARSE_READ,
     23   net::NetLog::TYPE_SPARSE_WRITE,
     24   net::NetLog::TYPE_URL_REQUEST_START_JOB,
     25   net::NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
     26 };
     27 
     28 MediaInternalsProxy::MediaInternalsProxy() {
     29   registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
     30                  NotificationService::AllBrowserContextsAndSources());
     31 }
     32 
     33 void MediaInternalsProxy::Observe(int type,
     34                                   const NotificationSource& source,
     35                                   const NotificationDetails& details) {
     36   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     37   DCHECK_EQ(type, NOTIFICATION_RENDERER_PROCESS_TERMINATED);
     38   RenderProcessHost* process = Source<RenderProcessHost>(source).ptr();
     39   CallJavaScriptFunctionOnUIThread("media.onRendererTerminated",
     40       new base::FundamentalValue(process->GetID()));
     41 }
     42 
     43 void MediaInternalsProxy::Attach(MediaInternalsMessageHandler* handler) {
     44   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     45   handler_ = handler;
     46   BrowserThread::PostTask(
     47       BrowserThread::IO, FROM_HERE,
     48       base::Bind(&MediaInternalsProxy::ObserveMediaInternalsOnIOThread, this));
     49 }
     50 
     51 void MediaInternalsProxy::Detach() {
     52   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     53   handler_ = NULL;
     54   BrowserThread::PostTask(
     55       BrowserThread::IO, FROM_HERE,
     56       base::Bind(
     57           &MediaInternalsProxy::StopObservingMediaInternalsOnIOThread, this));
     58 }
     59 
     60 void MediaInternalsProxy::GetEverything() {
     61   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     62 
     63   // Ask MediaInternals for all its data.
     64   BrowserThread::PostTask(
     65       BrowserThread::IO, FROM_HERE,
     66       base::Bind(&MediaInternalsProxy::GetEverythingOnIOThread, this));
     67 
     68   // Send the page names for constants.
     69   CallJavaScriptFunctionOnUIThread("media.onReceiveConstants", GetConstants());
     70 }
     71 
     72 void MediaInternalsProxy::OnUpdate(const base::string16& update) {
     73   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     74   BrowserThread::PostTask(
     75       BrowserThread::UI, FROM_HERE,
     76       base::Bind(&MediaInternalsProxy::UpdateUIOnUIThread, this, update));
     77 }
     78 
     79 void MediaInternalsProxy::OnAddEntry(const net::NetLog::Entry& entry) {
     80   bool is_event_interesting = false;
     81   for (size_t i = 0; i < arraysize(kNetEventTypeFilter); i++) {
     82     if (entry.type() == kNetEventTypeFilter[i]) {
     83       is_event_interesting = true;
     84       break;
     85     }
     86   }
     87 
     88   if (!is_event_interesting)
     89     return;
     90 
     91   BrowserThread::PostTask(
     92       BrowserThread::UI, FROM_HERE,
     93       base::Bind(&MediaInternalsProxy::AddNetEventOnUIThread, this,
     94                  entry.ToValue()));
     95 }
     96 
     97 MediaInternalsProxy::~MediaInternalsProxy() {}
     98 
     99 base::Value* MediaInternalsProxy::GetConstants() {
    100   base::DictionaryValue* event_phases = new base::DictionaryValue();
    101   event_phases->SetInteger(
    102       net::NetLog::EventPhaseToString(net::NetLog::PHASE_NONE),
    103       net::NetLog::PHASE_NONE);
    104   event_phases->SetInteger(
    105       net::NetLog::EventPhaseToString(net::NetLog::PHASE_BEGIN),
    106       net::NetLog::PHASE_BEGIN);
    107   event_phases->SetInteger(
    108       net::NetLog::EventPhaseToString(net::NetLog::PHASE_END),
    109       net::NetLog::PHASE_END);
    110 
    111   base::DictionaryValue* constants = new base::DictionaryValue();
    112   constants->Set("eventTypes", net::NetLog::GetEventTypesAsValue());
    113   constants->Set("eventPhases", event_phases);
    114 
    115   return constants;
    116 }
    117 
    118 void MediaInternalsProxy::ObserveMediaInternalsOnIOThread() {
    119   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    120   update_callback_ = base::Bind(&MediaInternalsProxy::OnUpdate,
    121                                 base::Unretained(this));
    122   MediaInternals::GetInstance()->AddUpdateCallback(update_callback_);
    123   if (GetContentClient()->browser()->GetNetLog()) {
    124     net::NetLog* net_log = GetContentClient()->browser()->GetNetLog();
    125     net_log->AddThreadSafeObserver(this, net::NetLog::LOG_ALL_BUT_BYTES);
    126   }
    127 }
    128 
    129 void MediaInternalsProxy::StopObservingMediaInternalsOnIOThread() {
    130   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    131   MediaInternals::GetInstance()->RemoveUpdateCallback(update_callback_);
    132   if (GetContentClient()->browser()->GetNetLog()) {
    133     net::NetLog* net_log = GetContentClient()->browser()->GetNetLog();
    134     net_log->RemoveThreadSafeObserver(this);
    135   }
    136 }
    137 
    138 void MediaInternalsProxy::GetEverythingOnIOThread() {
    139   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    140   MediaInternals::GetInstance()->SendEverything();
    141 }
    142 
    143 void MediaInternalsProxy::UpdateUIOnUIThread(const base::string16& update) {
    144   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    145   // Don't forward updates to a destructed UI.
    146   if (handler_)
    147     handler_->OnUpdate(update);
    148 }
    149 
    150 void MediaInternalsProxy::AddNetEventOnUIThread(base::Value* entry) {
    151   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    152 
    153   // Send the updates to the page in kMediaInternalsProxyEventDelayMilliseconds
    154   // if an update is not already pending.
    155   if (!pending_net_updates_) {
    156     pending_net_updates_.reset(new base::ListValue());
    157     base::MessageLoop::current()->PostDelayedTask(
    158         FROM_HERE,
    159         base::Bind(&MediaInternalsProxy::SendNetEventsOnUIThread, this),
    160         base::TimeDelta::FromMilliseconds(
    161             kMediaInternalsProxyEventDelayMilliseconds));
    162   }
    163   pending_net_updates_->Append(entry);
    164 }
    165 
    166 void MediaInternalsProxy::SendNetEventsOnUIThread() {
    167   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    168   CallJavaScriptFunctionOnUIThread("media.onNetUpdate",
    169                                    pending_net_updates_.release());
    170 }
    171 
    172 void MediaInternalsProxy::CallJavaScriptFunctionOnUIThread(
    173     const std::string& function, base::Value* args) {
    174   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    175   scoped_ptr<base::Value> args_value(args);
    176   std::vector<const base::Value*> args_vector;
    177   args_vector.push_back(args_value.get());
    178   base::string16 update = WebUI::GetJavascriptCall(function, args_vector);
    179   UpdateUIOnUIThread(update);
    180 }
    181 
    182 }  // namespace content
    183