plugin_placeholder.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Copyright 2013 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 "components/plugins/renderer/plugin_placeholder.h"
  5. #include "base/metrics/user_metrics_action.h"
  6. #include "base/strings/string_util.h"
  7. #include "content/public/renderer/render_frame.h"
  8. #include "content/public/renderer/render_thread.h"
  9. #include "content/public/renderer/v8_value_converter.h"
  10. #include "gin/object_template_builder.h"
  11. #include "third_party/blink/public/common/web_preferences/web_preferences.h"
  12. #include "third_party/blink/public/web/blink.h"
  13. #include "third_party/blink/public/web/web_dom_message_event.h"
  14. #include "third_party/blink/public/web/web_element.h"
  15. #include "third_party/blink/public/web/web_local_frame.h"
  16. #include "third_party/blink/public/web/web_plugin_container.h"
  17. #include "third_party/blink/public/web/web_script_source.h"
  18. #include "third_party/blink/public/web/web_serialized_script_value.h"
  19. #include "third_party/re2/src/re2/re2.h"
  20. namespace plugins {
  21. // The placeholder is loaded in normal web renderer processes, so it should not
  22. // have a chrome:// scheme that might let it be confused with a WebUI page.
  23. const char kPluginPlaceholderDataURL[] = "data:text/html,pluginplaceholderdata";
  24. PluginPlaceholderBase::PluginPlaceholderBase(
  25. content::RenderFrame* render_frame,
  26. const blink::WebPluginParams& params,
  27. const std::string& html_data)
  28. : content::RenderFrameObserver(render_frame),
  29. plugin_params_(params),
  30. plugin_(WebViewPlugin::Create(render_frame->GetWebFrame()->View(),
  31. this,
  32. render_frame
  33. ? render_frame->GetBlinkPreferences()
  34. : blink::web_pref::WebPreferences(),
  35. html_data,
  36. GURL(kPluginPlaceholderDataURL))),
  37. hidden_(false) {}
  38. PluginPlaceholderBase::~PluginPlaceholderBase() {
  39. }
  40. const blink::WebPluginParams& PluginPlaceholderBase::GetPluginParams() const {
  41. return plugin_params_;
  42. }
  43. void PluginPlaceholderBase::ShowContextMenu(const blink::WebMouseEvent& event) {
  44. // Does nothing by default. Will be overridden if a specific browser wants
  45. // a context menu.
  46. return;
  47. }
  48. void PluginPlaceholderBase::PluginDestroyed() {
  49. plugin_ = nullptr;
  50. }
  51. v8::Local<v8::Object> PluginPlaceholderBase::GetV8ScriptableObject(
  52. v8::Isolate* isolate) const {
  53. return v8::Local<v8::Object>();
  54. }
  55. void PluginPlaceholderBase::HidePlugin() {
  56. hidden_ = true;
  57. if (!plugin())
  58. return;
  59. blink::WebPluginContainer* container = plugin()->Container();
  60. blink::WebElement element = container->GetElement();
  61. element.SetAttribute("style", "display: none;");
  62. // If we have a width and height, search for a parent (often <div>) with the
  63. // same dimensions. If we find such a parent, hide that as well.
  64. // This makes much more uncovered page content usable (including clickable)
  65. // as opposed to merely visible.
  66. // TODO(cevans) -- it's a foul heuristic but we're going to tolerate it for
  67. // now for these reasons:
  68. // 1) Makes the user experience better.
  69. // 2) Foulness is encapsulated within this single function.
  70. // 3) Confidence in no fasle positives.
  71. // 4) Seems to have a good / low false negative rate at this time.
  72. if (element.HasAttribute("width") && element.HasAttribute("height")) {
  73. std::string width_str("width:[\\s]*");
  74. width_str += element.GetAttribute("width").Utf8();
  75. if (base::EndsWith(width_str, "px", base::CompareCase::INSENSITIVE_ASCII)) {
  76. width_str = width_str.substr(0, width_str.length() - 2);
  77. }
  78. base::TrimWhitespaceASCII(width_str, base::TRIM_TRAILING, &width_str);
  79. width_str += "[\\s]*px";
  80. std::string height_str("height:[\\s]*");
  81. height_str += element.GetAttribute("height").Utf8();
  82. if (base::EndsWith(height_str, "px",
  83. base::CompareCase::INSENSITIVE_ASCII)) {
  84. height_str = height_str.substr(0, height_str.length() - 2);
  85. }
  86. base::TrimWhitespaceASCII(height_str, base::TRIM_TRAILING, &height_str);
  87. height_str += "[\\s]*px";
  88. blink::WebNode parent = element;
  89. while (!parent.ParentNode().IsNull()) {
  90. parent = parent.ParentNode();
  91. if (!parent.IsElementNode())
  92. continue;
  93. element = parent.To<blink::WebElement>();
  94. if (element.HasAttribute("style")) {
  95. std::string style_str = element.GetAttribute("style").Utf8();
  96. if (RE2::PartialMatch(style_str, width_str) &&
  97. RE2::PartialMatch(style_str, height_str))
  98. element.SetAttribute("style", "display: none;");
  99. }
  100. }
  101. }
  102. }
  103. void PluginPlaceholderBase::HideCallback() {
  104. content::RenderThread::Get()->RecordAction(
  105. base::UserMetricsAction("Plugin_Hide_Click"));
  106. HidePlugin();
  107. }
  108. void PluginPlaceholderBase::NotifyPlaceholderReadyForTestingCallback() {
  109. if (!plugin())
  110. return;
  111. // Set an attribute and post an event, so browser tests can wait for the
  112. // placeholder to be ready to receive simulated user input.
  113. blink::WebElement element = plugin()->Container()->GetElement();
  114. element.SetAttribute("placeholderReady", "true");
  115. base::Value value("placeholderReady");
  116. blink::WebSerializedScriptValue message_data =
  117. blink::WebSerializedScriptValue::Serialize(
  118. blink::MainThreadIsolate(),
  119. content::V8ValueConverter::Create()->ToV8Value(
  120. value,
  121. element.GetDocument().GetFrame()->MainWorldScriptContext()));
  122. blink::WebDOMMessageEvent msg_event(message_data);
  123. plugin()->Container()->EnqueueMessageEvent(msg_event);
  124. }
  125. void PluginPlaceholderBase::OnDestruct() {}
  126. // static
  127. gin::WrapperInfo PluginPlaceholder::kWrapperInfo = {gin::kEmbedderNativeGin};
  128. PluginPlaceholder::PluginPlaceholder(content::RenderFrame* render_frame,
  129. const blink::WebPluginParams& params,
  130. const std::string& html_data)
  131. : PluginPlaceholderBase(render_frame, params, html_data) {}
  132. PluginPlaceholder::~PluginPlaceholder() {
  133. }
  134. v8::Local<v8::Value> PluginPlaceholder::GetV8Handle(v8::Isolate* isolate) {
  135. return gin::CreateHandle(isolate, this).ToV8();
  136. }
  137. bool PluginPlaceholderBase::IsErrorPlaceholder() {
  138. return false;
  139. }
  140. gin::ObjectTemplateBuilder PluginPlaceholder::GetObjectTemplateBuilder(
  141. v8::Isolate* isolate) {
  142. return gin::Wrappable<PluginPlaceholder>::GetObjectTemplateBuilder(isolate)
  143. .SetMethod<void (plugins::PluginPlaceholder::*)()>(
  144. "hide", &PluginPlaceholder::HideCallback);
  145. }
  146. } // namespace plugins