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

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

Issue 23606022: Move renderer plugin code into a new component. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Move renderer plugin code into a new component - split off youtube plugin, and respond to other cod… Created 7 years, 3 months 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/plugins/plugin_placeholder.h" 5 #include "chrome/renderer/plugins/chrome_plugin_placeholder.h"
6 6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/json/string_escape.h"
10 #include "base/strings/string_piece.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h" 7 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h" 8 #include "base/values.h"
14 #include "chrome/common/prerender_messages.h" 9 #include "chrome/common/prerender_messages.h"
15 #include "chrome/common/render_messages.h" 10 #include "chrome/common/render_messages.h"
16 #include "chrome/renderer/chrome_content_renderer_client.h" 11 #include "chrome/renderer/chrome_content_renderer_client.h"
17 #include "chrome/renderer/custom_menu_commands.h" 12 #include "chrome/renderer/custom_menu_commands.h"
18 #include "chrome/renderer/plugins/plugin_uma.h"
19 #include "content/public/common/content_constants.h"
20 #include "content/public/common/context_menu_params.h" 13 #include "content/public/common/context_menu_params.h"
21 #include "content/public/renderer/render_thread.h" 14 #include "content/public/renderer/render_thread.h"
22 #include "content/public/renderer/render_view.h" 15 #include "content/public/renderer/render_view.h"
23 #include "grit/generated_resources.h" 16 #include "grit/generated_resources.h"
24 #include "grit/renderer_resources.h" 17 #include "grit/renderer_resources.h"
25 #include "grit/webkit_strings.h" 18 #include "grit/webkit_strings.h"
26 #include "third_party/WebKit/public/platform/WebData.h"
27 #include "third_party/WebKit/public/platform/WebPoint.h"
28 #include "third_party/WebKit/public/platform/WebURLRequest.h"
29 #include "third_party/WebKit/public/platform/WebVector.h"
30 #include "third_party/WebKit/public/web/WebContextMenuData.h"
31 #include "third_party/WebKit/public/web/WebDocument.h" 19 #include "third_party/WebKit/public/web/WebDocument.h"
32 #include "third_party/WebKit/public/web/WebElement.h"
33 #include "third_party/WebKit/public/web/WebFrame.h" 20 #include "third_party/WebKit/public/web/WebFrame.h"
34 #include "third_party/WebKit/public/web/WebInputEvent.h" 21 #include "third_party/WebKit/public/web/WebInputEvent.h"
35 #include "third_party/WebKit/public/web/WebPluginContainer.h"
36 #include "third_party/WebKit/public/web/WebScriptSource.h" 22 #include "third_party/WebKit/public/web/WebScriptSource.h"
37 #include "third_party/WebKit/public/web/WebView.h"
38 #include "third_party/re2/re2/re2.h"
39 #include "ui/base/l10n/l10n_util.h" 23 #include "ui/base/l10n/l10n_util.h"
40 #include "ui/base/resource/resource_bundle.h" 24 #include "ui/base/resource/resource_bundle.h"
41 #include "ui/webui/jstemplate_builder.h" 25 #include "ui/webui/jstemplate_builder.h"
42 26
43 using content::RenderThread; 27 using content::RenderThread;
44 using content::RenderView; 28 using content::RenderView;
45 using WebKit::WebContextMenuData;
46 using WebKit::WebDocument; 29 using WebKit::WebDocument;
47 using WebKit::WebElement; 30 using WebKit::WebElement;
48 using WebKit::WebFrame; 31 using WebKit::WebFrame;
49 using WebKit::WebMouseEvent; 32 using WebKit::WebMouseEvent;
50 using WebKit::WebNode; 33 using WebKit::WebNode;
51 using WebKit::WebPlugin; 34 using WebKit::WebPlugin;
52 using WebKit::WebPluginContainer; 35 using WebKit::WebPluginContainer;
53 using WebKit::WebPluginParams; 36 using WebKit::WebPluginParams;
54 using WebKit::WebPoint;
55 using WebKit::WebScriptSource;
56 using WebKit::WebString;
57 using WebKit::WebURLRequest;
58 using WebKit::WebVector;
59 using webkit_glue::CppArgumentList; 37 using webkit_glue::CppArgumentList;
60 using webkit_glue::CppVariant; 38 using webkit_glue::CppVariant;
61 39
62 const char* const kPluginPlaceholderDataURL =
63 "chrome://pluginplaceholderdata/";
64
65 #if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN)
66 // Strings we used to parse the youtube plugin url.
67 const char* const kSlashVSlash = "/v/";
68 const char* const kSlashESlash = "/e/";
69 #endif
70
71 namespace { 40 namespace {
72 const PluginPlaceholder* g_last_active_menu = NULL; 41 const PluginPlaceholder* g_last_active_menu = NULL;
73
74 #if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN)
75 // Helper function to get the youtube id from plugin params for old style
76 // embedded youtube video.
77 std::string GetYoutubeVideoId(const WebPluginParams& params) {
78 GURL url(params.url);
79 std::string video_id = url.path().substr(strlen(kSlashVSlash));
80
81 // Extract just the video id
82 size_t video_id_end = video_id.find('&');
83 if (video_id_end != std::string::npos)
84 video_id = video_id.substr(0, video_id_end);
85 return video_id;
86 }
87 #endif
88 } // namespace 42 } // namespace
89 43
44 ChromePluginPlaceholder::ChromePluginPlaceholder(
45 content::RenderView* render_view,
46 WebKit::WebFrame* frame,
47 const WebKit::WebPluginParams& params,
48 const std::string& html_data,
49 const string16& title)
50 : PluginPlaceholder(render_view, frame, params, html_data),
51 status_(new ChromeViewHostMsg_GetPluginInfo_Status),
52 title_(title),
53 #if defined(ENABLE_PLUGIN_INSTALLATION)
54 placeholder_routing_id_(MSG_ROUTING_NONE),
55 #endif
56 has_host_(false),
57 context_menu_request_id_(0) {
58 RenderThread::Get()->AddObserver(this);
59 }
60
61 ChromePluginPlaceholder::~ChromePluginPlaceholder() {
62 #if defined(ENABLE_PLUGIN_INSTALLATION)
63 if (placeholder_routing_id_ == MSG_ROUTING_NONE)
64 return;
65 RenderThread::Get()->RemoveRoute(placeholder_routing_id_);
66 if (has_host_) {
67 RenderThread::Get()->Send(new ChromeViewHostMsg_RemovePluginPlaceholderHost(
68 routing_id(), placeholder_routing_id_));
69 }
70 #endif
71 RenderThread::Get()->RemoveObserver(this);
72 if (context_menu_request_id_)
73 render_view()->CancelContextMenu(context_menu_request_id_);
74 }
75
90 // static 76 // static
91 PluginPlaceholder* PluginPlaceholder::CreateMissingPlugin( 77 ChromePluginPlaceholder* ChromePluginPlaceholder::CreateMissingPlugin(
92 RenderView* render_view, 78 RenderView* render_view,
93 WebFrame* frame, 79 WebFrame* frame,
94 const WebPluginParams& params) { 80 const WebPluginParams& params) {
95 const base::StringPiece template_html( 81 const base::StringPiece template_html(
96 ResourceBundle::GetSharedInstance().GetRawDataResource( 82 ResourceBundle::GetSharedInstance()
97 IDR_BLOCKED_PLUGIN_HTML)); 83 .GetRawDataResource(IDR_BLOCKED_PLUGIN_HTML));
98 84
99 base::DictionaryValue values; 85 base::DictionaryValue values;
100 #if defined(ENABLE_PLUGIN_INSTALLATION) 86 #if defined(ENABLE_PLUGIN_INSTALLATION)
101 values.SetString("message", l10n_util::GetStringUTF8(IDS_PLUGIN_SEARCHING)); 87 values.SetString("message", l10n_util::GetStringUTF8(IDS_PLUGIN_SEARCHING));
102 #else 88 #else
103 values.SetString("message", 89 values.SetString("message",
104 l10n_util::GetStringUTF8(IDS_PLUGIN_NOT_SUPPORTED)); 90 l10n_util::GetStringUTF8(IDS_PLUGIN_NOT_SUPPORTED));
105 #endif 91 #endif
106 92
107 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values); 93 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values);
108 94
109 // |missing_plugin| will destroy itself when its WebViewPlugin is going away. 95 // |missing_plugin| will destroy itself when its WebViewPlugin is going away.
110 PluginPlaceholder* missing_plugin = new PluginPlaceholder( 96 ChromePluginPlaceholder* missing_plugin = new ChromePluginPlaceholder(
111 render_view, frame, params, html_data, params.mimeType); 97 render_view, frame, params, html_data, params.mimeType);
112 missing_plugin->set_allow_loading(true); 98 missing_plugin->set_allow_loading(true);
113 #if defined(ENABLE_PLUGIN_INSTALLATION) 99 #if defined(ENABLE_PLUGIN_INSTALLATION)
114 RenderThread::Get()->Send(new ChromeViewHostMsg_FindMissingPlugin( 100 RenderThread::Get()->Send(
115 missing_plugin->routing_id(), missing_plugin->CreateRoutingId(), 101 new ChromeViewHostMsg_FindMissingPlugin(missing_plugin->routing_id(),
116 params.mimeType.utf8())); 102 missing_plugin->CreateRoutingId(),
103 params.mimeType.utf8()));
117 #endif 104 #endif
118 return missing_plugin; 105 return missing_plugin;
119 } 106 }
120 107
121 PluginPlaceholder* PluginPlaceholder::CreateErrorPlugin( 108 // static
109 ChromePluginPlaceholder* ChromePluginPlaceholder::CreateErrorPlugin(
122 RenderView* render_view, 110 RenderView* render_view,
123 const base::FilePath& file_path) { 111 const base::FilePath& file_path) {
124 base::DictionaryValue values; 112 base::DictionaryValue values;
125 values.SetString("message", 113 values.SetString("message",
126 l10n_util::GetStringUTF8(IDS_PLUGIN_INITIALIZATION_ERROR)); 114 l10n_util::GetStringUTF8(IDS_PLUGIN_INITIALIZATION_ERROR));
127 115
128 const base::StringPiece template_html( 116 const base::StringPiece template_html(
129 ResourceBundle::GetSharedInstance().GetRawDataResource( 117 ResourceBundle::GetSharedInstance()
130 IDR_BLOCKED_PLUGIN_HTML)); 118 .GetRawDataResource(IDR_BLOCKED_PLUGIN_HTML));
131 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values); 119 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values);
132 120
133 WebPluginParams params; 121 WebPluginParams params;
134 // |missing_plugin| will destroy itself when its WebViewPlugin is going away. 122 // |missing_plugin| will destroy itself when its WebViewPlugin is going away.
135 PluginPlaceholder* plugin = new PluginPlaceholder( 123 ChromePluginPlaceholder* plugin = new ChromePluginPlaceholder(
136 render_view, NULL, params, html_data, params.mimeType); 124 render_view, NULL, params, html_data, params.mimeType);
137 125
138 RenderThread::Get()->Send( 126 RenderThread::Get()->Send(new ChromeViewHostMsg_CouldNotLoadPlugin(
139 new ChromeViewHostMsg_CouldNotLoadPlugin(plugin->routing_id(), 127 plugin->routing_id(), file_path));
140 file_path));
141 return plugin; 128 return plugin;
142 } 129 }
143 130
144 // static 131 // static
145 PluginPlaceholder* PluginPlaceholder::CreateBlockedPlugin( 132 ChromePluginPlaceholder* ChromePluginPlaceholder::CreateBlockedPlugin(
146 RenderView* render_view, 133 RenderView* render_view,
147 WebFrame* frame, 134 WebFrame* frame,
148 const WebPluginParams& params, 135 const WebPluginParams& params,
149 const content::WebPluginInfo& plugin, 136 const content::WebPluginInfo& plugin,
150 const std::string& identifier, 137 const std::string& identifier,
151 const string16& name, 138 const string16& name,
152 int template_id, 139 int template_id,
153 const string16& message) { 140 const string16& message) {
154 base::DictionaryValue values; 141 base::DictionaryValue values;
155 values.SetString("message", message); 142 values.SetString("message", message);
156 values.SetString("name", name); 143 values.SetString("name", name);
157 values.SetString("hide", l10n_util::GetStringUTF8(IDS_PLUGIN_HIDE)); 144 values.SetString("hide", l10n_util::GetStringUTF8(IDS_PLUGIN_HIDE));
158 145
159 const base::StringPiece template_html( 146 const base::StringPiece template_html(
160 ResourceBundle::GetSharedInstance().GetRawDataResource( 147 ResourceBundle::GetSharedInstance().GetRawDataResource(template_id));
161 template_id));
162 148
163 DCHECK(!template_html.empty()) << "unable to load template. ID: " 149 DCHECK(!template_html.empty()) << "unable to load template. ID: "
164 << template_id; 150 << template_id;
165 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values); 151 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values);
166 152
167 // |blocked_plugin| will destroy itself when its WebViewPlugin is going away. 153 // |blocked_plugin| will destroy itself when its WebViewPlugin is going away.
168 PluginPlaceholder* blocked_plugin = new PluginPlaceholder( 154 ChromePluginPlaceholder* blocked_plugin =
169 render_view, frame, params, html_data, name); 155 new ChromePluginPlaceholder(render_view, frame, params, html_data, name);
170 blocked_plugin->plugin_info_ = plugin; 156 blocked_plugin->SetPluginInfo(plugin);
171 blocked_plugin->identifier_ = identifier; 157 blocked_plugin->SetIdentifier(identifier);
172 return blocked_plugin; 158 return blocked_plugin;
173 } 159 }
174 160
175 #if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN) 161 void ChromePluginPlaceholder::SetStatus(
176 // static 162 const ChromeViewHostMsg_GetPluginInfo_Status& status) {
177 PluginPlaceholder* PluginPlaceholder::CreateMobileYoutubePlugin( 163 status_->value = status.value;
178 content::RenderView* render_view,
179 WebFrame* frame,
180 const WebPluginParams& params) {
181 const base::StringPiece template_html(
182 ResourceBundle::GetSharedInstance().GetRawDataResource(
183 IDR_MOBILE_YOUTUBE_PLUGIN_HTML));
184
185 base::DictionaryValue values;
186 values.SetString("video_id", GetYoutubeVideoId(params));
187 std::string html_data = webui::GetI18nTemplateHtml(template_html, &values);
188
189 // |youtube_plugin| will destroy itself when its WebViewPlugin is going away.
190 PluginPlaceholder* youtube_plugin = new PluginPlaceholder(
191 render_view, frame, params, html_data, params.mimeType);
192 return youtube_plugin;
193 }
194 #endif
195
196 PluginPlaceholder::PluginPlaceholder(content::RenderView* render_view,
197 WebFrame* frame,
198 const WebPluginParams& params,
199 const std::string& html_data,
200 const string16& title)
201 : content::RenderViewObserver(render_view),
202 frame_(frame),
203 plugin_params_(params),
204 plugin_(WebViewPlugin::Create(
205 this, render_view->GetWebkitPreferences(), html_data,
206 GURL(kPluginPlaceholderDataURL))),
207 title_(title),
208 status_(new ChromeViewHostMsg_GetPluginInfo_Status),
209 is_blocked_for_prerendering_(false),
210 allow_loading_(false),
211 #if defined(ENABLE_PLUGIN_INSTALLATION)
212 placeholder_routing_id_(MSG_ROUTING_NONE),
213 #endif
214 hidden_(false),
215 has_host_(false),
216 finished_loading_(false),
217 context_menu_request_id_(0) {
218 RenderThread::Get()->AddObserver(this);
219 }
220
221 PluginPlaceholder::~PluginPlaceholder() {
222 RenderThread::Get()->RemoveObserver(this);
223 if (context_menu_request_id_)
224 render_view()->CancelContextMenu(context_menu_request_id_);
225
226 #if defined(ENABLE_PLUGIN_INSTALLATION)
227 if (placeholder_routing_id_ == MSG_ROUTING_NONE)
228 return;
229 RenderThread::Get()->RemoveRoute(placeholder_routing_id_);
230 if (has_host_) {
231 RenderThread::Get()->Send(
232 new ChromeViewHostMsg_RemovePluginPlaceholderHost(
233 routing_id(), placeholder_routing_id_));
234 }
235 #endif
236 } 164 }
237 165
238 #if defined(ENABLE_PLUGIN_INSTALLATION) 166 #if defined(ENABLE_PLUGIN_INSTALLATION)
239 int32 PluginPlaceholder::CreateRoutingId() { 167 int32 ChromePluginPlaceholder::CreateRoutingId() {
240 placeholder_routing_id_ = RenderThread::Get()->GenerateRoutingID(); 168 placeholder_routing_id_ = RenderThread::Get()->GenerateRoutingID();
241 RenderThread::Get()->AddRoute(placeholder_routing_id_, this); 169 RenderThread::Get()->AddRoute(placeholder_routing_id_, this);
242 return placeholder_routing_id_; 170 return placeholder_routing_id_;
243 } 171 }
244 #endif 172 #endif
245 173
246 void PluginPlaceholder::SetStatus( 174 bool ChromePluginPlaceholder::OnMessageReceived(const IPC::Message& message) {
247 const ChromeViewHostMsg_GetPluginInfo_Status& status) {
248 status_->value = status.value;
249 }
250
251 void PluginPlaceholder::BindWebFrame(WebFrame* frame) {
252 BindToJavascript(frame, "plugin");
253 BindCallback("load", base::Bind(&PluginPlaceholder::LoadCallback,
254 base::Unretained(this)));
255 BindCallback("hide", base::Bind(&PluginPlaceholder::HideCallback,
256 base::Unretained(this)));
257 BindCallback("openAboutPlugins",
258 base::Bind(&PluginPlaceholder::OpenAboutPluginsCallback,
259 base::Unretained(this)));
260 BindCallback("didFinishLoading",
261 base::Bind(&PluginPlaceholder::DidFinishLoadingCallback,
262 base::Unretained(this)));
263 #if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN)
264 BindCallback("openYoutubeURL",
265 base::Bind(&PluginPlaceholder::OpenYoutubeUrlCallback,
266 base::Unretained(this)));
267 #endif
268 }
269
270 bool PluginPlaceholder::OnMessageReceived(const IPC::Message& message) {
271 #if defined(ENABLE_PLUGIN_INSTALLATION) 175 #if defined(ENABLE_PLUGIN_INSTALLATION)
272 bool handled = true; 176 bool handled = true;
273 IPC_BEGIN_MESSAGE_MAP(PluginPlaceholder, message) 177 IPC_BEGIN_MESSAGE_MAP(ChromePluginPlaceholder, message)
274 IPC_MESSAGE_HANDLER(ChromeViewMsg_FoundMissingPlugin, 178 IPC_MESSAGE_HANDLER(ChromeViewMsg_FoundMissingPlugin, OnFoundMissingPlugin)
275 OnFoundMissingPlugin) 179 IPC_MESSAGE_HANDLER(ChromeViewMsg_DidNotFindMissingPlugin,
276 IPC_MESSAGE_HANDLER(ChromeViewMsg_DidNotFindMissingPlugin, 180 OnDidNotFindMissingPlugin)
277 OnDidNotFindMissingPlugin) 181 IPC_MESSAGE_HANDLER(ChromeViewMsg_StartedDownloadingPlugin,
278 IPC_MESSAGE_HANDLER(ChromeViewMsg_StartedDownloadingPlugin, 182 OnStartedDownloadingPlugin)
279 OnStartedDownloadingPlugin) 183 IPC_MESSAGE_HANDLER(ChromeViewMsg_FinishedDownloadingPlugin,
280 IPC_MESSAGE_HANDLER(ChromeViewMsg_FinishedDownloadingPlugin, 184 OnFinishedDownloadingPlugin)
281 OnFinishedDownloadingPlugin) 185 IPC_MESSAGE_HANDLER(ChromeViewMsg_ErrorDownloadingPlugin,
282 IPC_MESSAGE_HANDLER(ChromeViewMsg_ErrorDownloadingPlugin, 186 OnErrorDownloadingPlugin)
283 OnErrorDownloadingPlugin) 187 IPC_MESSAGE_HANDLER(ChromeViewMsg_CancelledDownloadingPlugin,
284 IPC_MESSAGE_HANDLER(ChromeViewMsg_CancelledDownloadingPlugin, 188 OnCancelledDownloadingPlugin)
285 OnCancelledDownloadingPlugin) 189 IPC_MESSAGE_UNHANDLED(handled = false)
286 IPC_MESSAGE_UNHANDLED(handled = false)
287 IPC_END_MESSAGE_MAP() 190 IPC_END_MESSAGE_MAP()
288 191
289 if (handled) 192 if (handled)
290 return true; 193 return true;
291 #endif 194 #endif
292 195
293 // We don't swallow these messages because multiple blocked plugins have an 196 // We don't swallow these messages because multiple blocked plugins have an
294 // interest in them. 197 // interest in them.
295 IPC_BEGIN_MESSAGE_MAP(PluginPlaceholder, message) 198 IPC_BEGIN_MESSAGE_MAP(ChromePluginPlaceholder, message)
296 IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins) 199 IPC_MESSAGE_HANDLER(ChromeViewMsg_LoadBlockedPlugins, OnLoadBlockedPlugins)
297 IPC_MESSAGE_HANDLER(PrerenderMsg_SetIsPrerendering, OnSetIsPrerendering) 200 IPC_MESSAGE_HANDLER(PrerenderMsg_SetIsPrerendering, OnSetIsPrerendering)
298 IPC_END_MESSAGE_MAP() 201 IPC_END_MESSAGE_MAP()
299 202
300 return false; 203 return false;
301 } 204 }
302 205
303 void PluginPlaceholder::ReplacePlugin(WebPlugin* new_plugin) { 206 void ChromePluginPlaceholder::OnLoadBlockedPlugins(
304 CHECK(plugin_); 207 const std::string& identifier) {
305 if (!new_plugin) { 208 PluginPlaceholder::OnLoadBlockedPlugins(identifier);
306 PluginUMAReporter::GetInstance()->ReportPluginMissing(
307 plugin_params_.mimeType.utf8(),
308 plugin_params_.url);
309 return;
310 }
311
312 WebPluginContainer* container = plugin_->container();
313 // Set the new plug-in on the container before initializing it.
314 container->setPlugin(new_plugin);
315 // Save the element in case the plug-in is removed from the page during
316 // initialization.
317 WebElement element = container->element();
318 if (!new_plugin->initialize(container)) {
319 // We couldn't initialize the new plug-in. Restore the old one and abort.
320 container->setPlugin(plugin_);
321 return;
322 }
323
324 // The plug-in has been removed from the page. Destroy the old plug-in
325 // (which will destroy us).
326 if (!element.pluginContainer()) {
327 plugin_->destroy();
328 return;
329 }
330
331 // During initialization, the new plug-in might have replaced itself in turn
332 // with another plug-in. Make sure not to use the passed in |new_plugin| after
333 // this point.
334 new_plugin = container->plugin();
335
336 plugin_->RestoreTitleText();
337 container->invalidate();
338 container->reportGeometry();
339 plugin_->ReplayReceivedData(new_plugin);
340 plugin_->destroy();
341 } 209 }
342 210
343 void PluginPlaceholder::HidePlugin() { 211 void ChromePluginPlaceholder::OpenAboutPluginsCallback(
344 hidden_ = true; 212 const CppArgumentList& args,
345 WebPluginContainer* container = plugin_->container(); 213 CppVariant* result) {
346 WebElement element = container->element(); 214 RenderThread::Get()
347 element.setAttribute("style", "display: none;"); 215 ->Send(new ChromeViewHostMsg_OpenAboutPlugins(routing_id()));
348 // If we have a width and height, search for a parent (often <div>) with the
349 // same dimensions. If we find such a parent, hide that as well.
350 // This makes much more uncovered page content usable (including clickable)
351 // as opposed to merely visible.
352 // TODO(cevans) -- it's a foul heurisitc but we're going to tolerate it for
353 // now for these reasons:
354 // 1) Makes the user experience better.
355 // 2) Foulness is encapsulated within this single function.
356 // 3) Confidence in no fasle positives.
357 // 4) Seems to have a good / low false negative rate at this time.
358 if (element.hasAttribute("width") && element.hasAttribute("height")) {
359 std::string width_str("width:[\\s]*");
360 width_str += element.getAttribute("width").utf8().data();
361 if (EndsWith(width_str, "px", false)) {
362 width_str = width_str.substr(0, width_str.length() - 2);
363 }
364 TrimWhitespace(width_str, TRIM_TRAILING, &width_str);
365 width_str += "[\\s]*px";
366 std::string height_str("height:[\\s]*");
367 height_str += element.getAttribute("height").utf8().data();
368 if (EndsWith(height_str, "px", false)) {
369 height_str = height_str.substr(0, height_str.length() - 2);
370 }
371 TrimWhitespace(height_str, TRIM_TRAILING, &height_str);
372 height_str += "[\\s]*px";
373 WebNode parent = element;
374 while (!parent.parentNode().isNull()) {
375 parent = parent.parentNode();
376 if (!parent.isElementNode())
377 continue;
378 element = parent.toConst<WebElement>();
379 if (element.hasAttribute("style")) {
380 std::string style_str = element.getAttribute("style").utf8();
381 if (RE2::PartialMatch(style_str, width_str) &&
382 RE2::PartialMatch(style_str, height_str))
383 element.setAttribute("style", "display: none;");
384 }
385 }
386 }
387 } 216 }
388 217
389 void PluginPlaceholder::WillDestroyPlugin() { 218 void ChromePluginPlaceholder::OnSetIsPrerendering(bool is_prerendering) {
390 delete this; 219 PluginPlaceholder::OnSetIsPrerendering(is_prerendering);
391 } 220 }
392 221
393 #if defined(ENABLE_PLUGIN_INSTALLATION) 222 #if defined(ENABLE_PLUGIN_INSTALLATION)
394 void PluginPlaceholder::OnDidNotFindMissingPlugin() { 223 void ChromePluginPlaceholder::OnDidNotFindMissingPlugin() {
395 SetMessage(l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_FOUND)); 224 SetMessage(l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_FOUND));
396 } 225 }
397 226
398 void PluginPlaceholder::OnFoundMissingPlugin(const string16& plugin_name) { 227 void ChromePluginPlaceholder::OnFoundMissingPlugin(
228 const string16& plugin_name) {
399 if (status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound) 229 if (status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound)
400 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_FOUND, plugin_name)); 230 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_FOUND, plugin_name));
401 has_host_ = true; 231 has_host_ = true;
402 plugin_name_ = plugin_name; 232 plugin_name_ = plugin_name;
403 } 233 }
404 234
405 void PluginPlaceholder::OnStartedDownloadingPlugin() { 235 void ChromePluginPlaceholder::OnStartedDownloadingPlugin() {
406 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING, plugin_name_)); 236 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING, plugin_name_));
407 } 237 }
408 238
409 void PluginPlaceholder::OnFinishedDownloadingPlugin() { 239 void ChromePluginPlaceholder::OnFinishedDownloadingPlugin() {
410 bool is_installing = 240 bool is_installing =
411 status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound; 241 status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound;
412 SetMessage(l10n_util::GetStringFUTF16( 242 SetMessage(l10n_util::GetStringFUTF16(
413 is_installing ? IDS_PLUGIN_INSTALLING : IDS_PLUGIN_UPDATING, 243 is_installing ? IDS_PLUGIN_INSTALLING : IDS_PLUGIN_UPDATING,
414 plugin_name_)); 244 plugin_name_));
415 } 245 }
416 246
417 void PluginPlaceholder::OnErrorDownloadingPlugin(const std::string& error) { 247 void ChromePluginPlaceholder::OnErrorDownloadingPlugin(
248 const std::string& error) {
418 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR, 249 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR,
419 UTF8ToUTF16(error))); 250 UTF8ToUTF16(error)));
420 } 251 }
421 252
422 void PluginPlaceholder::OnCancelledDownloadingPlugin() { 253 void ChromePluginPlaceholder::OnCancelledDownloadingPlugin() {
423 SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED, 254 SetMessage(
424 plugin_name_)); 255 l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED, plugin_name_));
425 } 256 }
426 #endif // defined(ENABLE_PLUGIN_INSTALLATION) 257 #endif // defined(ENABLE_PLUGIN_INSTALLATION)
427 258
428 void PluginPlaceholder::PluginListChanged() { 259 void ChromePluginPlaceholder::PluginListChanged() {
429 if (!frame_) 260 if (!GetFrame())
430 return; 261 return;
431 WebDocument document = frame_->top()->document(); 262 WebDocument document = GetFrame()->top()->document();
432 if (document.isNull()) 263 if (document.isNull())
433 return; 264 return;
434 265
435 ChromeViewHostMsg_GetPluginInfo_Output output; 266 ChromeViewHostMsg_GetPluginInfo_Output output;
436 std::string mime_type(plugin_params_.mimeType.utf8()); 267 std::string mime_type(GetPluginParams().mimeType.utf8());
437 render_view()->Send(new ChromeViewHostMsg_GetPluginInfo( 268 render_view()
438 routing_id(), GURL(plugin_params_.url), document.url(), 269 ->Send(new ChromeViewHostMsg_GetPluginInfo(routing_id(),
439 mime_type, &output)); 270 GURL(GetPluginParams().url),
271 document.url(),
272 mime_type,
273 &output));
440 if (output.status.value == status_->value) 274 if (output.status.value == status_->value)
441 return; 275 return;
442 WebPlugin* new_plugin = chrome::ChromeContentRendererClient::CreatePlugin( 276 WebPlugin* new_plugin = chrome::ChromeContentRendererClient::CreatePlugin(
443 render_view(), frame_, plugin_params_, output); 277 render_view(), GetFrame(), GetPluginParams(), output);
444 ReplacePlugin(new_plugin); 278 ReplacePlugin(new_plugin);
445 } 279 }
446 280
447 void PluginPlaceholder::OnMenuAction(int request_id, unsigned action) { 281 void ChromePluginPlaceholder::OnMenuAction(int request_id, unsigned action) {
448 DCHECK_EQ(context_menu_request_id_, request_id); 282 DCHECK_EQ(context_menu_request_id_, request_id);
449 if (g_last_active_menu != this) 283 if (g_last_active_menu != this)
450 return; 284 return;
451 switch (action) { 285 switch (action) {
452 case chrome::MENU_COMMAND_PLUGIN_RUN: { 286 case chrome::MENU_COMMAND_PLUGIN_RUN: {
453 RenderThread::Get()->RecordUserMetrics("Plugin_Load_Menu"); 287 RenderThread::Get()->RecordUserMetrics("Plugin_Load_Menu");
454 LoadPlugin(); 288 LoadPlugin();
455 break; 289 break;
456 } 290 }
457 case chrome::MENU_COMMAND_PLUGIN_HIDE: { 291 case chrome::MENU_COMMAND_PLUGIN_HIDE: {
458 RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Menu"); 292 RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Menu");
459 HidePlugin(); 293 HidePlugin();
460 break; 294 break;
461 } 295 }
462 default: 296 default:
463 NOTREACHED(); 297 NOTREACHED();
464 } 298 }
465 } 299 }
466 300
467 void PluginPlaceholder::OnMenuClosed(int request_id) { 301 void ChromePluginPlaceholder::OnMenuClosed(int request_id) {
468 DCHECK_EQ(context_menu_request_id_, request_id); 302 DCHECK_EQ(context_menu_request_id_, request_id);
469 context_menu_request_id_ = 0; 303 context_menu_request_id_ = 0;
470 } 304 }
471 305
472 void PluginPlaceholder::SetMessage(const string16& message) { 306 void ChromePluginPlaceholder::ShowContextMenu(const WebMouseEvent& event) {
473 message_ = message;
474 if (finished_loading_)
475 UpdateMessage();
476 }
477
478 void PluginPlaceholder::UpdateMessage() {
479 std::string script = "window.setMessage(" +
480 base::GetDoubleQuotedJson(message_) + ")";
481 plugin_->web_view()->mainFrame()->executeScript(
482 WebScriptSource(ASCIIToUTF16(script)));
483 }
484
485 void PluginPlaceholder::ShowContextMenu(const WebMouseEvent& event) {
486 if (context_menu_request_id_) 307 if (context_menu_request_id_)
487 return; // Don't allow nested context menu requests. 308 return; // Don't allow nested context menu requests.
488 309
489 content::ContextMenuParams params; 310 content::ContextMenuParams params;
490 311
491 content::MenuItem name_item; 312 content::MenuItem name_item;
492 name_item.label = title_; 313 name_item.label = title_;
493 params.custom_items.push_back(name_item); 314 params.custom_items.push_back(name_item);
494 315
495 content::MenuItem separator_item; 316 content::MenuItem separator_item;
496 separator_item.type = content::MenuItem::SEPARATOR; 317 separator_item.type = content::MenuItem::SEPARATOR;
497 params.custom_items.push_back(separator_item); 318 params.custom_items.push_back(separator_item);
498 319
499 if (!plugin_info_.path.value().empty()) { 320 if (!GetPluginInfo().path.value().empty()) {
500 content::MenuItem run_item; 321 content::MenuItem run_item;
501 run_item.action = chrome::MENU_COMMAND_PLUGIN_RUN; 322 run_item.action = chrome::MENU_COMMAND_PLUGIN_RUN;
502 // Disable this menu item if the plugin is blocked by policy. 323 // Disable this menu item if the plugin is blocked by policy.
503 run_item.enabled = allow_loading_; 324 run_item.enabled = LoadingAllowed();
504 run_item.label = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PLUGIN_RUN); 325 run_item.label = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PLUGIN_RUN);
505 params.custom_items.push_back(run_item); 326 params.custom_items.push_back(run_item);
506 } 327 }
507 328
508 content::MenuItem hide_item; 329 content::MenuItem hide_item;
509 hide_item.action = chrome::MENU_COMMAND_PLUGIN_HIDE; 330 hide_item.action = chrome::MENU_COMMAND_PLUGIN_HIDE;
510 hide_item.enabled = true; 331 hide_item.enabled = true;
511 hide_item.label = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PLUGIN_HIDE); 332 hide_item.label = l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_PLUGIN_HIDE);
512 params.custom_items.push_back(hide_item); 333 params.custom_items.push_back(hide_item);
513 334
514 params.x = event.windowX; 335 params.x = event.windowX;
515 params.y = event.windowY; 336 params.y = event.windowY;
516 337
517 context_menu_request_id_ = render_view()->ShowContextMenu(this, params); 338 context_menu_request_id_ = render_view()->ShowContextMenu(this, params);
518 g_last_active_menu = this; 339 g_last_active_menu = this;
519 } 340 }
520 341
521 void PluginPlaceholder::OnLoadBlockedPlugins(const std::string& identifier) { 342 void ChromePluginPlaceholder::BindWebFrame(WebKit::WebFrame* frame) {
522 if (!identifier.empty() && identifier != identifier_) 343 PluginPlaceholder::BindWebFrame(frame);
523 return; 344 BindCallback("openAboutPlugins",
524 345 base::Bind(&ChromePluginPlaceholder::OpenAboutPluginsCallback,
525 RenderThread::Get()->RecordUserMetrics("Plugin_Load_UI"); 346 base::Unretained(this)));
526 LoadPlugin();
527 } 347 }
528
529 void PluginPlaceholder::OnSetIsPrerendering(bool is_prerendering) {
530 // Prerendering can only be enabled prior to a RenderView's first navigation,
531 // so no BlockedPlugin should see the notification that enables prerendering.
532 DCHECK(!is_prerendering);
533 if (is_blocked_for_prerendering_ && !is_prerendering)
534 LoadPlugin();
535 }
536
537 void PluginPlaceholder::LoadPlugin() {
538 // This is not strictly necessary but is an important defense in case the
539 // event propagation changes between "close" vs. "click-to-play".
540 if (hidden_)
541 return;
542 if (!allow_loading_) {
543 NOTREACHED();
544 return;
545 }
546
547 // TODO(mmenke): In the case of prerendering, feed into
548 // ChromeContentRendererClient::CreatePlugin instead, to
549 // reduce the chance of future regressions.
550 WebPlugin* plugin =
551 render_view()->CreatePlugin(frame_, plugin_info_, plugin_params_);
552 ReplacePlugin(plugin);
553 }
554
555 void PluginPlaceholder::LoadCallback(const CppArgumentList& args,
556 CppVariant* result) {
557 RenderThread::Get()->RecordUserMetrics("Plugin_Load_Click");
558 LoadPlugin();
559 }
560
561 void PluginPlaceholder::HideCallback(const CppArgumentList& args,
562 CppVariant* result) {
563 RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Click");
564 HidePlugin();
565 }
566
567 void PluginPlaceholder::OpenAboutPluginsCallback(const CppArgumentList& args,
568 CppVariant* result) {
569 RenderThread::Get()->Send(
570 new ChromeViewHostMsg_OpenAboutPlugins(routing_id()));
571 }
572
573 void PluginPlaceholder::DidFinishLoadingCallback(const CppArgumentList& args,
574 CppVariant* result) {
575 finished_loading_ = true;
576 if (message_.length() > 0)
577 UpdateMessage();
578 }
579
580 #if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN)
581 void PluginPlaceholder::OpenYoutubeUrlCallback(const CppArgumentList& args,
582 CppVariant* result) {
583 std::string youtube("vnd.youtube:");
584 GURL url(youtube.append(GetYoutubeVideoId(plugin_params_)));
585 WebURLRequest request;
586 request.initialize();
587 request.setURL(url);
588 render_view()->LoadURLExternally(
589 frame_, request, WebKit::WebNavigationPolicyNewForegroundTab);
590 }
591
592 bool PluginPlaceholder::IsValidYouTubeVideo(const std::string& path) {
593 unsigned len = strlen(kSlashVSlash);
594
595 // check for more than just /v/ or /e/.
596 if (path.length() <= len)
597 return false;
598
599 std::string str = StringToLowerASCII(path);
600 // Youtube flash url can start with /v/ or /e/.
601 if (strncmp(str.data(), kSlashVSlash, len) != 0 &&
602 strncmp(str.data(), kSlashESlash, len) != 0)
603 return false;
604
605 // Start after /v/
606 for (unsigned i = len; i < path.length(); i++) {
607 char c = str[i];
608 if (isalpha(c) || isdigit(c) || c == '_' || c == '-')
609 continue;
610 // The url can have more parameters such as &hl=en after the video id.
611 // Once we start seeing extra parameters we can return true.
612 return c == '&' && i > len;
613 }
614 return true;
615 }
616
617 bool PluginPlaceholder::IsYouTubeURL(const GURL& url,
618 const std::string& mime_type) {
619 std::string host = url.host();
620 bool is_youtube = EndsWith(host, "youtube.com", true) ||
621 EndsWith(host, "youtube-nocookie.com", true);
622
623 return is_youtube && IsValidYouTubeVideo(url.path()) &&
624 LowerCaseEqualsASCII(mime_type, content::kFlashPluginSwfMimeType);
625 }
626 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698