cast_web_view_default.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. // Copyright 2017 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. #include "chromecast/browser/cast_web_view_default.h"
  5. #include <utility>
  6. #include "base/logging.h"
  7. #include "base/memory/ptr_util.h"
  8. #include "base/strings/string_util.h"
  9. #include "base/strings/utf_string_conversions.h"
  10. #include "base/threading/thread_task_runner_handle.h"
  11. #include "chromecast/base/cast_features.h"
  12. #include "chromecast/base/chromecast_switches.h"
  13. #include "chromecast/base/metrics/cast_metrics_helper.h"
  14. #include "chromecast/browser/cast_browser_process.h"
  15. #include "chromecast/browser/cast_web_service.h"
  16. #include "chromecast/browser/lru_renderer_cache.h"
  17. #include "chromecast/browser/renderer_prelauncher.h"
  18. #include "chromecast/chromecast_buildflags.h"
  19. #include "chromecast/graphics/cast_screen.h"
  20. #include "content/public/browser/media_capture_devices.h"
  21. #include "content/public/browser/media_session.h"
  22. #include "content/public/browser/render_frame_host.h"
  23. #include "content/public/browser/render_view_host.h"
  24. #include "content/public/browser/render_widget_host.h"
  25. #include "content/public/browser/render_widget_host_view.h"
  26. #include "content/public/browser/site_instance.h"
  27. #include "ipc/ipc_message.h"
  28. #include "net/base/net_errors.h"
  29. #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h"
  30. #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
  31. #include "ui/display/display.h"
  32. #include "ui/display/screen.h"
  33. #include "url/gurl.h"
  34. #if defined(USE_AURA)
  35. #include "ui/aura/window.h"
  36. #endif
  37. namespace chromecast {
  38. namespace {
  39. std::unique_ptr<content::WebContents> CreateWebContents(
  40. content::BrowserContext* browser_context,
  41. scoped_refptr<content::SiteInstance> site_instance,
  42. const mojom::CastWebViewParams& params) {
  43. DCHECK(browser_context);
  44. content::WebContents::CreateParams create_params(browser_context, nullptr);
  45. create_params.site_instance = site_instance;
  46. return content::WebContents::Create(create_params);
  47. }
  48. std::unique_ptr<RendererPrelauncher> TakeOrCreatePrelauncher(
  49. const GURL& prelaunch_url,
  50. mojom::RendererPool renderer_pool,
  51. CastWebService* web_service) {
  52. if (!prelaunch_url.is_valid()) {
  53. return nullptr;
  54. }
  55. if (renderer_pool == mojom::RendererPool::OVERLAY) {
  56. return web_service->overlay_renderer_cache()->TakeRendererPrelauncher(
  57. prelaunch_url);
  58. }
  59. return std::make_unique<RendererPrelauncher>(web_service->browser_context(),
  60. prelaunch_url);
  61. }
  62. scoped_refptr<content::SiteInstance> Prelaunch(
  63. RendererPrelauncher* prelauncher) {
  64. if (!prelauncher) {
  65. return nullptr;
  66. }
  67. prelauncher->Prelaunch();
  68. return prelauncher->site_instance();
  69. }
  70. #if defined(USE_AURA)
  71. constexpr gfx::Rect k720pDimensions(0, 0, 1280, 720);
  72. #endif
  73. } // namespace
  74. CastWebViewDefault::CastWebViewDefault(
  75. mojom::CastWebViewParamsPtr params,
  76. CastWebService* web_service,
  77. content::BrowserContext* browser_context,
  78. std::unique_ptr<CastContentWindow> cast_content_window)
  79. : params_(std::move(params)),
  80. web_service_(web_service),
  81. renderer_prelauncher_(TakeOrCreatePrelauncher(params_->prelaunch_url,
  82. params_->renderer_pool,
  83. web_service_)),
  84. site_instance_(Prelaunch(renderer_prelauncher_.get())),
  85. web_contents_(
  86. CreateWebContents(browser_context, site_instance_, *params_)),
  87. cast_web_contents_(web_contents_.get(), params_->Clone()),
  88. window_(cast_content_window
  89. ? std::move(cast_content_window)
  90. : web_service->CreateWindow(params_->Clone())) {
  91. DCHECK(web_service_);
  92. DCHECK(window_);
  93. window_->SetCastWebContents(&cast_web_contents_);
  94. web_contents_->SetDelegate(this);
  95. #if defined(USE_AURA)
  96. web_contents_->GetNativeView()->SetName(params_->activity_id);
  97. if (params_->force_720p_resolution) {
  98. const auto primary_display =
  99. display::Screen::GetScreen()->GetPrimaryDisplay();
  100. // Force scale factor to 1.0 and screen bounds to 720p.
  101. // When performed prior to the creation of the web view this causes blink to
  102. // render at a 1.0 pixel ratio but the compositor still scales out at 1.5,
  103. // increasing performance on 1080p displays (at the expense of visual
  104. // quality).
  105. shell::CastBrowserProcess::GetInstance()
  106. ->cast_screen()
  107. ->OverridePrimaryDisplaySettings(k720pDimensions, 1.0,
  108. primary_display.rotation());
  109. }
  110. #endif
  111. }
  112. CastWebViewDefault::~CastWebViewDefault() {
  113. if (renderer_prelauncher_ && params_->prelaunch_url.is_valid() &&
  114. params_->renderer_pool == mojom::RendererPool::OVERLAY) {
  115. web_service_->overlay_renderer_cache()->ReleaseRendererPrelauncher(
  116. params_->prelaunch_url);
  117. }
  118. }
  119. CastContentWindow* CastWebViewDefault::window() const {
  120. return window_.get();
  121. }
  122. content::WebContents* CastWebViewDefault::web_contents() const {
  123. return web_contents_.get();
  124. }
  125. CastWebContents* CastWebViewDefault::cast_web_contents() {
  126. return &cast_web_contents_;
  127. }
  128. base::TimeDelta CastWebViewDefault::shutdown_delay() const {
  129. return params_->shutdown_delay;
  130. }
  131. void CastWebViewDefault::OwnerDestroyed() {
  132. #if defined(USE_AURA)
  133. if (params_->force_720p_resolution) {
  134. shell::CastBrowserProcess::GetInstance()
  135. ->cast_screen()
  136. ->RestorePrimaryDisplaySettings();
  137. }
  138. #endif
  139. }
  140. void CastWebViewDefault::CloseContents(content::WebContents* source) {
  141. DCHECK_EQ(source, web_contents_.get());
  142. window_.reset(); // Window destructor requires live web_contents on Android.
  143. // This will signal to the owner that |web_contents_| is no longer in use,
  144. // permitting the owner to tear down.
  145. cast_web_contents_.Stop(net::OK);
  146. }
  147. content::WebContents* CastWebViewDefault::OpenURLFromTab(
  148. content::WebContents* source,
  149. const content::OpenURLParams& params) {
  150. LOG(INFO) << "Change url: " << params.url;
  151. // If source is NULL which means current tab, use web_contents_ of this class.
  152. if (!source)
  153. source = web_contents_.get();
  154. DCHECK_EQ(source, web_contents_.get());
  155. // We don't want to create another web_contents. Load url only when source is
  156. // specified.
  157. source->GetController().LoadURL(params.url, params.referrer,
  158. params.transition, params.extra_headers);
  159. return source;
  160. }
  161. void CastWebViewDefault::ActivateContents(content::WebContents* contents) {
  162. DCHECK_EQ(contents, web_contents_.get());
  163. contents->GetRenderViewHost()->GetWidget()->Focus();
  164. }
  165. bool CastWebViewDefault::CheckMediaAccessPermission(
  166. content::RenderFrameHost* render_frame_host,
  167. const GURL& security_origin,
  168. blink::mojom::MediaStreamType type) {
  169. if (!chromecast::IsFeatureEnabled(kAllowUserMediaAccess) &&
  170. !params_->allow_media_access) {
  171. LOG(WARNING) << __func__ << ": media access is disabled.";
  172. return false;
  173. }
  174. return true;
  175. }
  176. bool CastWebViewDefault::DidAddMessageToConsole(
  177. content::WebContents* source,
  178. blink::mojom::ConsoleMessageLevel log_level,
  179. const std::u16string& message,
  180. int32_t line_no,
  181. const std::u16string& source_id) {
  182. if (!params_->log_js_console_messages)
  183. return true;
  184. std::u16string single_line_message;
  185. // Mult-line message is not friendly to dumpstate redact.
  186. base::ReplaceChars(message, u"\n", u"\\n ", &single_line_message);
  187. logging::LogMessage("CONSOLE", line_no, ::logging::LOG_INFO).stream()
  188. << params_->log_prefix << ": \"" << single_line_message
  189. << "\", source: " << source_id << " (" << line_no << ")";
  190. return true;
  191. }
  192. const blink::MediaStreamDevice* GetRequestedDeviceOrDefault(
  193. const blink::MediaStreamDevices& devices,
  194. const std::string& requested_device_id) {
  195. if (!requested_device_id.empty()) {
  196. auto it = std::find_if(
  197. devices.begin(), devices.end(),
  198. [requested_device_id](const blink::MediaStreamDevice& device) {
  199. return device.id == requested_device_id;
  200. });
  201. return it != devices.end() ? &(*it) : nullptr;
  202. }
  203. if (!devices.empty())
  204. return &devices[0];
  205. return nullptr;
  206. }
  207. void CastWebViewDefault::RequestMediaAccessPermission(
  208. content::WebContents* web_contents,
  209. const content::MediaStreamRequest& request,
  210. content::MediaResponseCallback callback) {
  211. if (!chromecast::IsFeatureEnabled(kAllowUserMediaAccess) &&
  212. !params_->allow_media_access) {
  213. LOG(WARNING) << __func__ << ": media access is disabled.";
  214. std::move(callback).Run(
  215. blink::mojom::StreamDevicesSet(),
  216. blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
  217. std::unique_ptr<content::MediaStreamUI>());
  218. return;
  219. }
  220. auto audio_devices =
  221. content::MediaCaptureDevices::GetInstance()->GetAudioCaptureDevices();
  222. auto video_devices =
  223. content::MediaCaptureDevices::GetInstance()->GetVideoCaptureDevices();
  224. DVLOG(2) << __func__ << " audio_devices=" << audio_devices.size()
  225. << " video_devices=" << video_devices.size();
  226. blink::mojom::StreamDevicesSet stream_devices_set;
  227. stream_devices_set.stream_devices.emplace_back(
  228. blink::mojom::StreamDevices::New());
  229. blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0];
  230. if (request.audio_type ==
  231. blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
  232. const blink::MediaStreamDevice* device = GetRequestedDeviceOrDefault(
  233. audio_devices, request.requested_audio_device_id);
  234. if (device) {
  235. DVLOG(1) << __func__ << "Using audio device: id=" << device->id
  236. << " name=" << device->name;
  237. devices.audio_device = *device;
  238. }
  239. }
  240. if (request.video_type ==
  241. blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE) {
  242. const blink::MediaStreamDevice* device = GetRequestedDeviceOrDefault(
  243. video_devices, request.requested_video_device_id);
  244. if (device) {
  245. DVLOG(1) << __func__ << "Using video device: id=" << device->id
  246. << " name=" << device->name;
  247. devices.video_device = *device;
  248. }
  249. }
  250. std::move(callback).Run(stream_devices_set,
  251. blink::mojom::MediaStreamRequestResult::OK,
  252. std::unique_ptr<content::MediaStreamUI>());
  253. }
  254. bool CastWebViewDefault::ShouldAllowRunningInsecureContent(
  255. content::WebContents* /* web_contents */,
  256. bool allowed_per_prefs,
  257. const url::Origin& /* origin */,
  258. const GURL& /* resource_url */) {
  259. metrics::CastMetricsHelper::GetInstance()->RecordApplicationEvent(
  260. params_->activity_id, params_->session_id, params_->sdk_version,
  261. "Cast.Platform.AppRunningInsecureContent");
  262. return allowed_per_prefs;
  263. }
  264. } // namespace chromecast