1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file.
4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/browser/media/media_web_contents_observer.h"
6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/stl_util.h"
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/browser/media/cdm/browser_cdm_manager.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/renderer_host/render_process_host_impl.h"
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/browser/render_frame_host.h"
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/browser/web_contents.h"
13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ipc/ipc_message_macros.h"
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(OS_ANDROID)
16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/browser/media/android/browser_media_player_manager.h"
17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/common/media/media_player_messages_android.h"
18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "media/base/android/media_player_android.h"
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif  // defined(OS_ANDROID)
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace content {
22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)MediaWebContentsObserver::MediaWebContentsObserver(
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    RenderViewHost* render_view_host)
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : WebContentsObserver(WebContents::FromRenderViewHost(render_view_host)) {
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)MediaWebContentsObserver::~MediaWebContentsObserver() {
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void MediaWebContentsObserver::RenderFrameDeleted(
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    RenderFrameHost* render_frame_host) {
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  uintptr_t key = reinterpret_cast<uintptr_t>(render_frame_host);
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Always destroy the media players before CDMs because we do not support
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // detaching CDMs from media players yet. See http://crbug.com/330324
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(OS_ANDROID)
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  media_player_managers_.erase(key);
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(xhwang): Currently MediaWebContentsObserver, BrowserMediaPlayerManager
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // and BrowserCdmManager all run on browser UI thread. So this call is okay.
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // In the future we need to support the case where MediaWebContentsObserver
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // get notified on browser UI thread, but BrowserMediaPlayerManager and
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // BrowserCdmManager run on a different thread.
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BrowserCdmManager* browser_cdm_manager =
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      BrowserCdmManager::FromProcess(render_frame_host->GetProcess()->GetID());
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (browser_cdm_manager)
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    browser_cdm_manager->RenderFrameDeleted(render_frame_host->GetRoutingID());
48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_ANDROID)
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool MediaWebContentsObserver::OnMessageReceived(
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const IPC::Message& msg,
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    RenderFrameHost* render_frame_host) {
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (OnMediaPlayerMessageReceived(msg, render_frame_host))
56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return true;
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (OnMediaPlayerSetCdmMessageReceived(msg, render_frame_host))
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return true;
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return false;
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool MediaWebContentsObserver::OnMediaPlayerMessageReceived(
65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const IPC::Message& msg,
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    RenderFrameHost* render_frame_host) {
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool handled = true;
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(MediaWebContentsObserver, msg)
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_EnterFullscreen,
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        GetMediaPlayerManager(render_frame_host),
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        BrowserMediaPlayerManager::OnEnterFullscreen)
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_ExitFullscreen,
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        GetMediaPlayerManager(render_frame_host),
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        BrowserMediaPlayerManager::OnExitFullscreen)
75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Initialize,
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        GetMediaPlayerManager(render_frame_host),
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        BrowserMediaPlayerManager::OnInitialize)
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Start,
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        GetMediaPlayerManager(render_frame_host),
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        BrowserMediaPlayerManager::OnStart)
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Seek,
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        GetMediaPlayerManager(render_frame_host),
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        BrowserMediaPlayerManager::OnSeek)
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Pause,
85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        GetMediaPlayerManager(render_frame_host),
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        BrowserMediaPlayerManager::OnPause)
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_SetVolume,
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        GetMediaPlayerManager(render_frame_host),
89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        BrowserMediaPlayerManager::OnSetVolume)
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_SetPoster,
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        GetMediaPlayerManager(render_frame_host),
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        BrowserMediaPlayerManager::OnSetPoster)
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Release,
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        GetMediaPlayerManager(render_frame_host),
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        BrowserMediaPlayerManager::OnReleaseResources)
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_DestroyMediaPlayer,
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        GetMediaPlayerManager(render_frame_host),
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        BrowserMediaPlayerManager::OnDestroyPlayer)
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_RequestRemotePlayback,
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        GetMediaPlayerManager(render_frame_host),
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        BrowserMediaPlayerManager::OnRequestRemotePlayback)
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    IPC_MESSAGE_FORWARD(
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        MediaPlayerHostMsg_RequestRemotePlaybackControl,
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        GetMediaPlayerManager(render_frame_host),
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        BrowserMediaPlayerManager::OnRequestRemotePlaybackControl)
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(VIDEO_HOLE)
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_NotifyExternalSurface,
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        GetMediaPlayerManager(render_frame_host),
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        BrowserMediaPlayerManager::OnNotifyExternalSurface)
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return handled;
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool MediaWebContentsObserver::OnMediaPlayerSetCdmMessageReceived(
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const IPC::Message& msg,
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    RenderFrameHost* render_frame_host) {
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool handled = true;
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MediaWebContentsObserver, msg, render_frame_host)
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_SetCdm, OnSetCdm)
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return handled;
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void MediaWebContentsObserver::OnSetCdm(RenderFrameHost* render_frame_host,
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                        int player_id,
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                        int cdm_id) {
131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  media::MediaPlayerAndroid* media_player =
132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      GetMediaPlayerManager(render_frame_host)->GetPlayer(player_id);
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!media_player) {
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    NOTREACHED() << "OnSetCdm: MediaPlayer not found for " << player_id;
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // MediaPlayerAndroid runs on the same thread as BrowserCdmManager.
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BrowserCdmManager* browser_cdm_manager =
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      BrowserCdmManager::FromProcess(render_frame_host->GetProcess()->GetID());
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!browser_cdm_manager) {
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NOTREACHED() << "OnSetCdm: CDM not found for " << cdm_id;
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  media::BrowserCdm* cdm =
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      browser_cdm_manager->GetCdm(render_frame_host->GetRoutingID(), cdm_id);
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!cdm) {
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    NOTREACHED() << "OnSetCdm: CDM not found for " << cdm_id;
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // TODO(xhwang): This could possibly fail. In that case we should reject the
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // promise.
155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  media_player->SetCdm(cdm);
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)BrowserMediaPlayerManager* MediaWebContentsObserver::GetMediaPlayerManager(
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    RenderFrameHost* render_frame_host) {
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  uintptr_t key = reinterpret_cast<uintptr_t>(render_frame_host);
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!media_player_managers_.contains(key)) {
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    media_player_managers_.set(
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        key,
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        make_scoped_ptr(BrowserMediaPlayerManager::Create(render_frame_host)));
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return media_player_managers_.get(key);
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(VIDEO_HOLE)
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void MediaWebContentsObserver::OnFrameInfoUpdated() {
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (MediaPlayerManagerMap::iterator iter = media_player_managers_.begin();
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      iter != media_player_managers_.end(); ++iter) {
173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    BrowserMediaPlayerManager* manager = iter->second;
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    manager->OnFrameInfoUpdated();
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif  // defined(OS_ANDROID)
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace content
182