Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: chrome/renderer/plugins/blocked_plugin.cc

Issue 8461011: Clean up plug-in placeholders: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: cleanup Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/renderer/blocked_plugin.h" 5 #include "chrome/renderer/plugins/blocked_plugin.h"
6 6
7 #include "base/string_piece.h" 7 #include "base/string_piece.h"
8 #include "base/string_util.h" 8 #include "base/string_util.h"
9 #include "base/values.h" 9 #include "base/values.h"
10 #include "chrome/common/jstemplate_builder.h" 10 #include "chrome/common/jstemplate_builder.h"
11 #include "chrome/common/render_messages.h" 11 #include "chrome/common/render_messages.h"
12 #include "chrome/renderer/plugin_uma.h" 12 #include "chrome/renderer/custom_menu_commands.h"
13 #include "content/public/renderer/render_thread.h" 13 #include "content/public/renderer/render_thread.h"
14 #include "content/public/renderer/render_view.h" 14 #include "content/public/renderer/render_view.h"
15 #include "grit/generated_resources.h" 15 #include "grit/generated_resources.h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h" 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMenuItemInfo.h" 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMenuItemInfo.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h" 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h"
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRegularExpression. h"
26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebTextCaseSensitivit y.h"
27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h" 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
29 #include "ui/base/l10n/l10n_util.h" 22 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/resource/resource_bundle.h" 23 #include "ui/base/resource/resource_bundle.h"
31 #include "webkit/glue/webpreferences.h" 24 #include "webkit/glue/webpreferences.h"
32 #include "webkit/plugins/npapi/plugin_group.h" 25 #include "webkit/plugins/npapi/plugin_group.h"
33 #include "webkit/plugins/npapi/webview_plugin.h" 26 #include "webkit/plugins/npapi/webview_plugin.h"
34 27
35 using WebKit::WebContextMenuData; 28 using WebKit::WebContextMenuData;
36 using WebKit::WebElement;
37 using WebKit::WebFrame; 29 using WebKit::WebFrame;
38 using WebKit::WebMenuItemInfo; 30 using WebKit::WebMenuItemInfo;
39 using WebKit::WebNode;
40 using WebKit::WebPlugin; 31 using WebKit::WebPlugin;
41 using WebKit::WebPluginContainer;
42 using WebKit::WebPluginParams; 32 using WebKit::WebPluginParams;
43 using WebKit::WebPoint; 33 using WebKit::WebPoint;
44 using WebKit::WebRegularExpression;
45 using WebKit::WebString; 34 using WebKit::WebString;
46 using WebKit::WebURLRequest; 35 using WebKit::WebURLRequest;
47 using WebKit::WebVector; 36 using WebKit::WebVector;
48 using content::RenderThread; 37 using content::RenderThread;
49 38
50 static const char* const kBlockedPluginDataURL = "chrome://blockedplugindata/";
51 // TODO(cevans) - move these to a shared header file so that there are no 39 // TODO(cevans) - move these to a shared header file so that there are no
52 // collisions in the longer term. Currently, blocked_plugin.cc is the only 40 // collisions in the longer term. Currently, blocked_plugin.cc is the only
53 // user of custom menu commands (extension menu items have their own range). 41 // user of custom menu commands (extension menu items have their own range).
54 static const unsigned kMenuActionLoad = 1; 42 static const unsigned kMenuActionLoad = 1;
55 static const unsigned kMenuActionRemove = 2; 43 static const unsigned kMenuActionRemove = 2;
56 44
57 static const BlockedPlugin* g_last_active_menu; 45 namespace {
46 const BlockedPlugin* g_last_active_menu = NULL;
47 }
58 48
59 BlockedPlugin::BlockedPlugin(content::RenderView* render_view, 49 // static
60 WebFrame* frame, 50
battre 2011/11/22 09:57:15 nit: -empty line
Bernhard Bauer 2011/11/22 17:04:49 gone.
61 const webkit::WebPluginInfo& info, 51 webkit::npapi::WebViewPlugin* BlockedPlugin::Create(
62 const WebPluginParams& params, 52 content::RenderView* render_view,
63 const WebPreferences& preferences, 53 WebFrame* frame,
64 int template_id, 54 const WebPluginParams& params,
65 const string16& name, 55 const webkit::WebPluginInfo& plugin,
66 const string16& message, 56 const webkit::npapi::PluginGroup* group,
67 bool is_blocked_for_prerendering, 57 int template_id,
68 bool allow_loading) 58 int message_id,
69 : content::RenderViewObserver(render_view), 59 bool is_blocked_for_prerendering,
70 frame_(frame), 60 bool allow_loading) {
71 plugin_info_(info), 61 string16 name = group->GetGroupName();
72 plugin_params_(params), 62 string16 message = l10n_util::GetStringFUTF16(message_id, name);
73 name_(name), 63
74 is_blocked_for_prerendering_(is_blocked_for_prerendering), 64 DictionaryValue values;
75 hidden_(false), 65 values.SetString("message", message);
76 allow_loading_(allow_loading) { 66 values.SetString("name", name);
67 values.SetString("hide", l10n_util::GetStringUTF8(IDS_PLUGIN_HIDE));
68
77 const base::StringPiece template_html( 69 const base::StringPiece template_html(
78 ResourceBundle::GetSharedInstance().GetRawDataResource(template_id)); 70 ResourceBundle::GetSharedInstance().GetRawDataResource(template_id));
79 71
80 DCHECK(!template_html.empty()) << "unable to load template. ID: " 72 DCHECK(!template_html.empty()) << "unable to load template. ID: "
81 << template_id; 73 << template_id;
82
83 DictionaryValue values;
84 values.SetString("message", message);
85 values.SetString("name", name_);
86 values.SetString("hide", l10n_util::GetStringUTF8(IDS_PLUGIN_HIDE));
87
88 // "t" is the id of the templates root node. 74 // "t" is the id of the templates root node.
89 std::string html_data = jstemplate_builder::GetI18nTemplateHtml( 75 std::string html_data = jstemplate_builder::GetI18nTemplateHtml(
90 template_html, &values); 76 template_html, &values);
91 77
92 plugin_ = webkit::npapi::WebViewPlugin::Create(this, 78 BlockedPlugin* blocked_plugin = new BlockedPlugin(
93 preferences, 79 render_view, frame, params, html_data, plugin, name,
94 html_data, 80 is_blocked_for_prerendering, allow_loading);
95 GURL(kBlockedPluginDataURL)); 81 return blocked_plugin->plugin();
battre 2011/11/22 09:57:15 This looks like a memory leak.
Bernhard Bauer 2011/11/22 17:04:49 BlockedPlugin is a WebViewPluginDelegate. WebViewP
82 }
83
84 BlockedPlugin::BlockedPlugin(content::RenderView* render_view,
85 WebFrame* frame,
86 const WebPluginParams& params,
87 const std::string& html_data,
88 const webkit::WebPluginInfo& info,
89 const string16& name,
90 bool is_blocked_for_prerendering,
91 bool allow_loading)
92 : PluginPlaceholder(render_view, frame, params, html_data),
93 plugin_info_(info),
94 name_(name),
95 is_blocked_for_prerendering_(is_blocked_for_prerendering),
96 hidden_(false),
97 allow_loading_(allow_loading) {
96 } 98 }
97 99
98 BlockedPlugin::~BlockedPlugin() { 100 BlockedPlugin::~BlockedPlugin() {
99 } 101 }
100 102
101 void BlockedPlugin::BindWebFrame(WebFrame* frame) { 103 void BlockedPlugin::BindWebFrame(WebFrame* frame) {
102 BindToJavascript(frame, "plugin"); 104 PluginPlaceholder::BindWebFrame(frame);
103 BindMethod("load", &BlockedPlugin::LoadCallback); 105 BindMethod("load", &BlockedPlugin::LoadCallback);
104 BindMethod("hide", &BlockedPlugin::HideCallback); 106 BindMethod("hide", &BlockedPlugin::HideCallback);
105 BindMethod("openURL", &BlockedPlugin::OpenUrlCallback); 107 BindMethod("openURL", &BlockedPlugin::OpenUrlCallback);
106 } 108 }
107 109
108 void BlockedPlugin::WillDestroyPlugin() {
109 delete this;
110 }
111
112 void BlockedPlugin::ShowContextMenu(const WebKit::WebMouseEvent& event) { 110 void BlockedPlugin::ShowContextMenu(const WebKit::WebMouseEvent& event) {
113 WebContextMenuData menu_data; 111 WebContextMenuData menu_data;
114 112
115 size_t num_items = name_.empty() ? 2u : 4u; 113 size_t num_items = name_.empty() ? 2u : 4u;
116 WebVector<WebMenuItemInfo> custom_items(num_items); 114 WebVector<WebMenuItemInfo> custom_items(num_items);
117 115
118 size_t i = 0; 116 size_t i = 0;
119 if (!name_.empty()) { 117 if (!name_.empty()) {
120 WebMenuItemInfo name_item; 118 WebMenuItemInfo name_item;
121 name_item.label = name_; 119 name_item.label = name_;
122 name_item.hasTextDirectionOverride = false; 120 name_item.hasTextDirectionOverride = false;
123 name_item.textDirection = WebKit::WebTextDirectionDefault; 121 name_item.textDirection = WebKit::WebTextDirectionDefault;
124 custom_items[i++] = name_item; 122 custom_items[i++] = name_item;
125 123
126 WebMenuItemInfo separator_item; 124 WebMenuItemInfo separator_item;
127 separator_item.type = WebMenuItemInfo::Separator; 125 separator_item.type = WebMenuItemInfo::Separator;
128 custom_items[i++] = separator_item; 126 custom_items[i++] = separator_item;
129 } 127 }
130 128
131 WebMenuItemInfo run_item; 129 WebMenuItemInfo run_item;
132 run_item.action = kMenuActionLoad; 130 run_item.action = chrome::MENU_COMMAND_PLUGIN_RUN;
133 // Disable this menu item if the plugin is blocked by policy. 131 // Disable this menu item if the plugin is blocked by policy.
134 run_item.enabled = allow_loading_; 132 run_item.enabled = allow_loading_;
135 run_item.label = WebString::fromUTF8( 133 run_item.label = WebString::fromUTF8(
136 l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_PLUGIN_RUN).c_str()); 134 l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_PLUGIN_RUN).c_str());
137 run_item.hasTextDirectionOverride = false; 135 run_item.hasTextDirectionOverride = false;
138 run_item.textDirection = WebKit::WebTextDirectionDefault; 136 run_item.textDirection = WebKit::WebTextDirectionDefault;
139 custom_items[i++] = run_item; 137 custom_items[i++] = run_item;
140 138
141 WebMenuItemInfo hide_item; 139 WebMenuItemInfo hide_item;
142 hide_item.action = kMenuActionRemove; 140 hide_item.action = chrome::MENU_COMMAND_PLUGIN_HIDE;
143 hide_item.enabled = true; 141 hide_item.enabled = true;
144 hide_item.label = WebString::fromUTF8( 142 hide_item.label = WebString::fromUTF8(
145 l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_PLUGIN_HIDE).c_str()); 143 l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_PLUGIN_HIDE).c_str());
146 hide_item.hasTextDirectionOverride = false; 144 hide_item.hasTextDirectionOverride = false;
147 hide_item.textDirection = WebKit::WebTextDirectionDefault; 145 hide_item.textDirection = WebKit::WebTextDirectionDefault;
148 custom_items[i++] = hide_item; 146 custom_items[i++] = hide_item;
149 147
150 menu_data.customItems.swap(custom_items); 148 menu_data.customItems.swap(custom_items);
151 menu_data.mousePosition = WebPoint(event.windowX, event.windowY); 149 menu_data.mousePosition = WebPoint(event.windowX, event.windowY);
152 render_view()->ShowContextMenu(NULL, menu_data); 150 render_view()->ShowContextMenu(NULL, menu_data);
153 g_last_active_menu = this; 151 g_last_active_menu = this;
154 } 152 }
155 153
156 bool BlockedPlugin::OnMessageReceived(const IPC::Message& message) { 154 bool BlockedPlugin::OnMessageReceived(const IPC::Message& message) {
157 // We don't swallow ViewMsg_CustomContextMenuAction because we listen for all 155 // We don't swallow ViewMsg_CustomContextMenuAction because we listen for all
158 // custom menu IDs, and not just our own. We don't swallow 156 // custom menu IDs, and not just our own. We don't swallow
159 // ViewMsg_LoadBlockedPlugins because multiple blocked plugins have an 157 // ViewMsg_LoadBlockedPlugins because multiple blocked plugins have an
160 // interest in it. 158 // interest in it.
161 IPC_BEGIN_MESSAGE_MAP(BlockedPlugin, message) 159 IPC_BEGIN_MESSAGE_MAP(BlockedPlugin, message)
162 IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins) 160 IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins)
163 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsPrerendering, OnSetIsPrerendering) 161 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsPrerendering, OnSetIsPrerendering)
164 IPC_END_MESSAGE_MAP() 162 IPC_END_MESSAGE_MAP()
165 163
166 return false; 164 return false;
167 } 165 }
168 166
169 void BlockedPlugin::ContextMenuAction(unsigned id) { 167 void BlockedPlugin::ContextMenuAction(unsigned id) {
170 if (g_last_active_menu != this) 168 if (g_last_active_menu != this)
171 return; 169 return;
172 if (id == kMenuActionLoad) { 170 switch (id) {
173 RenderThread::Get()->RecordUserMetrics("Plugin_Load_Menu"); 171 case chrome::MENU_COMMAND_PLUGIN_RUN: {
174 LoadPlugin(); 172 RenderThread::Get()->RecordUserMetrics("Plugin_Load_Menu");
175 } else if (id == kMenuActionRemove) { 173 LoadPlugin();
176 RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Menu"); 174 break;
177 HidePlugin(); 175 }
176 case chrome::MENU_COMMAND_PLUGIN_HIDE: {
177 RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Menu");
178 HidePlugin();
179 break;
180 }
181 default:
182 NOTREACHED();
178 } 183 }
179 } 184 }
180 185
181 void BlockedPlugin::OnLoadBlockedPlugins() { 186 void BlockedPlugin::OnLoadBlockedPlugins() {
182 RenderThread::Get()->RecordUserMetrics("Plugin_Load_UI"); 187 RenderThread::Get()->RecordUserMetrics("Plugin_Load_UI");
183 LoadPlugin(); 188 LoadPlugin();
184 } 189 }
185 190
186 void BlockedPlugin::OnSetIsPrerendering(bool is_prerendering) { 191 void BlockedPlugin::OnSetIsPrerendering(bool is_prerendering) {
187 // Prerendering can only be enabled prior to a RenderView's first navigation, 192 // Prerendering can only be enabled prior to a RenderView's first navigation,
188 // so no BlockedPlugin should see the notification that enables prerendering. 193 // so no BlockedPlugin should see the notification that enables prerendering.
189 DCHECK(!is_prerendering); 194 DCHECK(!is_prerendering);
190 if (is_blocked_for_prerendering_ && !is_prerendering) 195 if (is_blocked_for_prerendering_ && !is_prerendering)
191 LoadPlugin(); 196 LoadPlugin();
192 } 197 }
193 198
194 void BlockedPlugin::LoadPlugin() { 199 void BlockedPlugin::LoadPlugin() {
195 CHECK(plugin_);
196 // This is not strictly necessary but is an important defense in case the 200 // This is not strictly necessary but is an important defense in case the
197 // event propagation changes between "close" vs. "click-to-play". 201 // event propagation changes between "close" vs. "click-to-play".
198 if (hidden_) 202 if (hidden_)
199 return; 203 return;
200 if (!allow_loading_) 204 if (!allow_loading_)
201 return; 205 return;
202 WebPluginContainer* container = plugin_->container(); 206 PluginPlaceholder::LoadPlugin(plugin_info_);
203 WebPlugin* new_plugin =
204 render_view()->CreatePlugin(frame_, plugin_info_, plugin_params_);
205 if (new_plugin && new_plugin->initialize(container)) {
206 plugin_->RestoreTitleText();
207 container->setPlugin(new_plugin);
208 container->invalidate();
209 container->reportGeometry();
210 plugin_->ReplayReceivedData(new_plugin);
211 plugin_->destroy();
212 } else {
213 MissingPluginReporter::GetInstance()->ReportPluginMissing(
214 plugin_params_.mimeType.utf8(),
215 plugin_params_.url);
216 }
217 } 207 }
218 208
219 void BlockedPlugin::LoadCallback(const CppArgumentList& args, 209 void BlockedPlugin::LoadCallback(const CppArgumentList& args,
220 CppVariant* result) { 210 CppVariant* result) {
221 RenderThread::Get()->RecordUserMetrics("Plugin_Load_Click"); 211 RenderThread::Get()->RecordUserMetrics("Plugin_Load_Click");
222 LoadPlugin(); 212 LoadPlugin();
223 } 213 }
224 214
225 void BlockedPlugin::HideCallback(const CppArgumentList& args, 215 void BlockedPlugin::HideCallback(const CppArgumentList& args,
226 CppVariant* result) { 216 CppVariant* result) {
(...skipping 10 matching lines...) Expand all
237 if (!args[0].isString()) { 227 if (!args[0].isString()) {
238 NOTREACHED(); 228 NOTREACHED();
239 return; 229 return;
240 } 230 }
241 231
242 GURL url(args[0].ToString()); 232 GURL url(args[0].ToString());
243 WebURLRequest request; 233 WebURLRequest request;
244 request.initialize(); 234 request.initialize();
245 request.setURL(url); 235 request.setURL(url);
246 render_view()->LoadURLExternally( 236 render_view()->LoadURLExternally(
247 frame_, request, WebKit::WebNavigationPolicyNewForegroundTab); 237 frame(), request, WebKit::WebNavigationPolicyNewForegroundTab);
248 } 238 }
249 239
250 void BlockedPlugin::HidePlugin() { 240 void BlockedPlugin::HidePlugin() {
251 CHECK(plugin_);
252 hidden_ = true; 241 hidden_ = true;
253 WebPluginContainer* container = plugin_->container(); 242 PluginPlaceholder::HidePlugin();
254 WebElement element = container->element();
255 element.setAttribute("style", "display: none;");
256 // If we have a width and height, search for a parent (often <div>) with the
257 // same dimensions. If we find such a parent, hide that as well.
258 // This makes much more uncovered page content usable (including clickable)
259 // as opposed to merely visible.
260 // TODO(cevans) -- it's a foul heurisitc but we're going to tolerate it for
261 // now for these reasons:
262 // 1) Makes the user experience better.
263 // 2) Foulness is encapsulated within this single function.
264 // 3) Confidence in no fasle positives.
265 // 4) Seems to have a good / low false negative rate at this time.
266 if (element.hasAttribute("width") && element.hasAttribute("height")) {
267 std::string width_str("width:[\\s]*");
268 width_str += element.getAttribute("width").utf8().data();
269 if (EndsWith(width_str, "px", false)) {
270 width_str = width_str.substr(0, width_str.length() - 2);
271 }
272 TrimWhitespace(width_str, TRIM_TRAILING, &width_str);
273 width_str += "[\\s]*px";
274 WebRegularExpression width_regex(WebString::fromUTF8(width_str.c_str()),
275 WebKit::WebTextCaseSensitive);
276 std::string height_str("height:[\\s]*");
277 height_str += element.getAttribute("height").utf8().data();
278 if (EndsWith(height_str, "px", false)) {
279 height_str = height_str.substr(0, height_str.length() - 2);
280 }
281 TrimWhitespace(height_str, TRIM_TRAILING, &height_str);
282 height_str += "[\\s]*px";
283 WebRegularExpression height_regex(WebString::fromUTF8(height_str.c_str()),
284 WebKit::WebTextCaseSensitive);
285 WebNode parent = element;
286 while (!parent.parentNode().isNull()) {
287 parent = parent.parentNode();
288 if (!parent.isElementNode())
289 continue;
290 element = parent.toConst<WebElement>();
291 if (element.hasAttribute("style")) {
292 WebString style_str = element.getAttribute("style");
293 if (width_regex.match(style_str) >= 0 &&
294 height_regex.match(style_str) >= 0)
295 element.setAttribute("style", "display: none;");
296 }
297 }
298 }
299 } 243 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698