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

Side by Side Diff: webkit/glue/plugins/webplugin_impl.cc

Issue 6012002: Move the NPAPI files from webkit/glue/plugins to webkit/plugins/npapi and put... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 10 years 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
« no previous file with comments | « webkit/glue/plugins/webplugin_impl.h ('k') | webkit/glue/plugins/webplugin_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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
5 #include "webkit/glue/plugins/webplugin_impl.h"
6
7 #include "base/linked_ptr.h"
8 #include "base/logging.h"
9 #include "base/message_loop.h"
10 #include "base/string_util.h"
11 #include "base/stringprintf.h"
12 #include "base/utf_string_conversions.h"
13 #include "gfx/rect.h"
14 #include "googleurl/src/gurl.h"
15 #include "net/base/escape.h"
16 #include "net/base/net_errors.h"
17 #include "net/http/http_response_headers.h"
18 #include "skia/ext/platform_canvas.h"
19 #include "third_party/WebKit/WebKit/chromium/public/WebConsoleMessage.h"
20 #include "third_party/WebKit/WebKit/chromium/public/WebCookieJar.h"
21 #include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
22 #include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h"
23 #include "third_party/WebKit/WebKit/chromium/public/WebDevToolsAgent.h"
24 #include "third_party/WebKit/WebKit/chromium/public/WebData.h"
25 #include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
26 #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
27 #include "third_party/WebKit/WebKit/chromium/public/WebHTTPBody.h"
28 #include "third_party/WebKit/WebKit/chromium/public/WebHTTPHeaderVisitor.h"
29 #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
30 #include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
31 #include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h"
32 #include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h"
33 #include "third_party/WebKit/WebKit/chromium/public/WebPluginParams.h"
34 #include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
35 #include "third_party/WebKit/WebKit/chromium/public/WebURLError.h"
36 #include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h"
37 #include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h"
38 #include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
39 #include "third_party/WebKit/WebKit/chromium/public/WebView.h"
40 #include "webkit/appcache/web_application_cache_host_impl.h"
41 #include "webkit/glue/multipart_response_delegate.h"
42 #include "webkit/glue/plugins/plugin_host.h"
43 #include "webkit/glue/plugins/plugin_instance.h"
44 #include "webkit/glue/plugins/webplugin_delegate.h"
45 #include "webkit/glue/plugins/webplugin_page_delegate.h"
46
47 using appcache::WebApplicationCacheHostImpl;
48 using WebKit::WebCanvas;
49 using WebKit::WebConsoleMessage;
50 using WebKit::WebCookieJar;
51 using WebKit::WebCString;
52 using WebKit::WebCursorInfo;
53 using WebKit::WebData;
54 using WebKit::WebDataSource;
55 using WebKit::WebDevToolsAgent;
56 using WebKit::WebFrame;
57 using WebKit::WebHTTPBody;
58 using WebKit::WebHTTPHeaderVisitor;
59 using WebKit::WebInputEvent;
60 using WebKit::WebKeyboardEvent;
61 using WebKit::WebMouseEvent;
62 using WebKit::WebPluginContainer;
63 using WebKit::WebPluginParams;
64 using WebKit::WebRect;
65 using WebKit::WebString;
66 using WebKit::WebURL;
67 using WebKit::WebURLError;
68 using WebKit::WebURLLoader;
69 using WebKit::WebURLLoaderClient;
70 using WebKit::WebURLRequest;
71 using WebKit::WebURLResponse;
72 using WebKit::WebVector;
73 using WebKit::WebView;
74 using webkit_glue::MultipartResponseDelegate;
75
76 namespace webkit_glue {
77 namespace {
78
79 // This class handles individual multipart responses. It is instantiated when
80 // we receive HTTP status code 206 in the HTTP response. This indicates
81 // that the response could have multiple parts each separated by a boundary
82 // specified in the response header.
83 class MultiPartResponseClient : public WebURLLoaderClient {
84 public:
85 explicit MultiPartResponseClient(WebPluginResourceClient* resource_client)
86 : resource_client_(resource_client) {
87 Clear();
88 }
89
90 virtual void willSendRequest(
91 WebURLLoader*, WebURLRequest&, const WebURLResponse&) {}
92 virtual void didSendData(
93 WebURLLoader*, unsigned long long, unsigned long long) {}
94
95 // Called when the multipart parser encounters an embedded multipart
96 // response.
97 virtual void didReceiveResponse(
98 WebURLLoader*, const WebURLResponse& response) {
99 int instance_size;
100 if (!MultipartResponseDelegate::ReadContentRanges(
101 response,
102 &byte_range_lower_bound_,
103 &byte_range_upper_bound_,
104 &instance_size)) {
105 NOTREACHED();
106 return;
107 }
108
109 resource_response_ = response;
110 }
111
112 // Receives individual part data from a multipart response.
113 virtual void didReceiveData(
114 WebURLLoader*, const char* data, int data_size) {
115 // TODO(ananta)
116 // We should defer further loads on multipart resources on the same lines
117 // as regular resources requested by plugins to prevent reentrancy.
118 resource_client_->DidReceiveData(
119 data, data_size, byte_range_lower_bound_);
120 byte_range_lower_bound_ += data_size;
121 }
122
123 virtual void didFinishLoading(WebURLLoader*, double finishTime) {}
124 virtual void didFail(WebURLLoader*, const WebURLError&) {}
125
126 void Clear() {
127 resource_response_.reset();
128 byte_range_lower_bound_ = 0;
129 byte_range_upper_bound_ = 0;
130 }
131
132 private:
133 WebURLResponse resource_response_;
134 // The lower bound of the byte range.
135 int byte_range_lower_bound_;
136 // The upper bound of the byte range.
137 int byte_range_upper_bound_;
138 // The handler for the data.
139 WebPluginResourceClient* resource_client_;
140 };
141
142 class HeaderFlattener : public WebHTTPHeaderVisitor {
143 public:
144 HeaderFlattener(std::string* buf) : buf_(buf) {
145 }
146
147 virtual void visitHeader(const WebString& name, const WebString& value) {
148 // TODO(darin): Should we really exclude headers with an empty value?
149 if (!name.isEmpty() && !value.isEmpty()) {
150 buf_->append(name.utf8());
151 buf_->append(": ");
152 buf_->append(value.utf8());
153 buf_->append("\n");
154 }
155 }
156
157 private:
158 std::string* buf_;
159 };
160
161 std::string GetAllHeaders(const WebURLResponse& response) {
162 // TODO(darin): It is possible for httpStatusText to be empty and still have
163 // an interesting response, so this check seems wrong.
164 std::string result;
165 const WebString& status = response.httpStatusText();
166 if (status.isEmpty())
167 return result;
168
169 // TODO(darin): Shouldn't we also report HTTP version numbers?
170 result = base::StringPrintf("HTTP %d ", response.httpStatusCode());
171 result.append(status.utf8());
172 result.append("\n");
173
174 HeaderFlattener flattener(&result);
175 response.visitHTTPHeaderFields(&flattener);
176
177 return result;
178 }
179
180 struct ResponseInfo {
181 GURL url;
182 std::string mime_type;
183 uint32 last_modified;
184 uint32 expected_length;
185 };
186
187 void GetResponseInfo(const WebURLResponse& response,
188 ResponseInfo* response_info) {
189 response_info->url = response.url();
190 response_info->mime_type = response.mimeType().utf8();
191
192 // Measured in seconds since 12:00 midnight GMT, January 1, 1970.
193 response_info->last_modified =
194 static_cast<uint32>(response.lastModifiedDate());
195
196 // If the length comes in as -1, then it indicates that it was not
197 // read off the HTTP headers. We replicate Safari webkit behavior here,
198 // which is to set it to 0.
199 response_info->expected_length =
200 static_cast<uint32>(std::max(response.expectedContentLength(), 0LL));
201
202 WebString content_encoding =
203 response.httpHeaderField(WebString::fromUTF8("Content-Encoding"));
204 if (!content_encoding.isNull() &&
205 !EqualsASCII(content_encoding, "identity")) {
206 // Don't send the compressed content length to the plugin, which only
207 // cares about the decoded length.
208 response_info->expected_length = 0;
209 }
210 }
211
212 } // namespace
213
214 // WebKit::WebPlugin ----------------------------------------------------------
215
216 struct WebPluginImpl::ClientInfo {
217 unsigned long id;
218 WebPluginResourceClient* client;
219 WebKit::WebURLRequest request;
220 bool pending_failure_notification;
221 linked_ptr<WebKit::WebURLLoader> loader;
222 bool notify_redirects;
223 };
224
225 bool WebPluginImpl::initialize(WebPluginContainer* container) {
226 if (!page_delegate_)
227 return false;
228
229 WebPluginDelegate* plugin_delegate = page_delegate_->CreatePluginDelegate(
230 file_path_, mime_type_);
231 if (!plugin_delegate)
232 return false;
233
234 // Set the container before Initialize because the plugin may
235 // synchronously call NPN_GetValue to get its container during its
236 // initialization.
237 SetContainer(container);
238 bool ok = plugin_delegate->Initialize(
239 plugin_url_, arg_names_, arg_values_, this, load_manually_);
240 if (!ok) {
241 plugin_delegate->PluginDestroyed();
242 return false;
243 }
244
245 delegate_ = plugin_delegate;
246
247 return true;
248 }
249
250 void WebPluginImpl::destroy() {
251 SetContainer(NULL);
252 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
253 }
254
255 NPObject* WebPluginImpl::scriptableObject() {
256 return delegate_->GetPluginScriptableObject();
257 }
258
259 void WebPluginImpl::paint(WebCanvas* canvas, const WebRect& paint_rect) {
260 if (!delegate_ || !container_)
261 return;
262
263 #if defined(OS_WIN)
264 // Force a geometry update if needed to allow plugins like media player
265 // which defer the initial geometry update to work.
266 container_->reportGeometry();
267 #endif // OS_WIN
268
269 // Note that |canvas| is only used when in windowless mode.
270 delegate_->Paint(canvas, paint_rect);
271 }
272
273 void WebPluginImpl::updateGeometry(
274 const WebRect& window_rect, const WebRect& clip_rect,
275 const WebVector<WebRect>& cutout_rects, bool is_visible) {
276 WebPluginGeometry new_geometry;
277 new_geometry.window = window_;
278 new_geometry.window_rect = window_rect;
279 new_geometry.clip_rect = clip_rect;
280 new_geometry.visible = is_visible;
281 new_geometry.rects_valid = true;
282 for (size_t i = 0; i < cutout_rects.size(); ++i)
283 new_geometry.cutout_rects.push_back(cutout_rects[i]);
284
285 // Only send DidMovePlugin if the geometry changed in some way.
286 if (window_ &&
287 page_delegate_ &&
288 (first_geometry_update_ || !new_geometry.Equals(geometry_))) {
289 page_delegate_->DidMovePlugin(new_geometry);
290 }
291
292 // Only UpdateGeometry if either the window or clip rects have changed.
293 if (first_geometry_update_ ||
294 new_geometry.window_rect != geometry_.window_rect ||
295 new_geometry.clip_rect != geometry_.clip_rect) {
296 // Notify the plugin that its parameters have changed.
297 delegate_->UpdateGeometry(new_geometry.window_rect, new_geometry.clip_rect);
298 }
299
300 // Initiate a download on the plugin url. This should be done for the
301 // first update geometry sequence. We need to ensure that the plugin
302 // receives the geometry update before it starts receiving data.
303 if (first_geometry_update_) {
304 // An empty url corresponds to an EMBED tag with no src attribute.
305 if (!load_manually_ && plugin_url_.is_valid()) {
306 // The Flash plugin hangs for a while if it receives data before
307 // receiving valid plugin geometry. By valid geometry we mean the
308 // geometry received by a call to setFrameRect in the Webkit
309 // layout code path. To workaround this issue we download the
310 // plugin source url on a timer.
311 MessageLoop::current()->PostDelayedTask(
312 FROM_HERE, method_factory_.NewRunnableMethod(
313 &WebPluginImpl::OnDownloadPluginSrcUrl), 0);
314 }
315 }
316
317 #if defined(OS_WIN)
318 // Don't cache the geometry during the first geometry update. The first
319 // geometry update sequence is received when Widget::setParent is called.
320 // For plugins like media player which have a bug where they only honor
321 // the first geometry update, we have a quirk which ignores the first
322 // geometry update. To ensure that these plugins work correctly in cases
323 // where we receive only one geometry update from webkit, we also force
324 // a geometry update during paint which should go out correctly as the
325 // initial geometry update was not cached.
326 if (!first_geometry_update_)
327 geometry_ = new_geometry;
328 #else // OS_WIN
329 geometry_ = new_geometry;
330 #endif // OS_WIN
331 first_geometry_update_ = false;
332 }
333
334 unsigned WebPluginImpl::getBackingTextureId() {
335 // Regular plugins do not have a backing texture.
336 return 0;
337 }
338
339 void WebPluginImpl::updateFocus(bool focused) {
340 if (accepts_input_events_)
341 delegate_->SetFocus(focused);
342 }
343
344 void WebPluginImpl::updateVisibility(bool visible) {
345 if (!window_ || !page_delegate_)
346 return;
347
348 WebPluginGeometry move;
349 move.window = window_;
350 move.window_rect = gfx::Rect();
351 move.clip_rect = gfx::Rect();
352 move.rects_valid = false;
353 move.visible = visible;
354
355 page_delegate_->DidMovePlugin(move);
356 }
357
358 bool WebPluginImpl::acceptsInputEvents() {
359 return accepts_input_events_;
360 }
361
362 bool WebPluginImpl::handleInputEvent(
363 const WebInputEvent& event, WebCursorInfo& cursor_info) {
364 // Swallow context menu events in order to suppress the default context menu.
365 if (event.type == WebInputEvent::ContextMenu)
366 return true;
367
368 return delegate_->HandleInputEvent(event, &cursor_info);
369 }
370
371 void WebPluginImpl::didReceiveResponse(const WebURLResponse& response) {
372 ignore_response_error_ = false;
373
374 ResponseInfo response_info;
375 GetResponseInfo(response, &response_info);
376
377 delegate_->DidReceiveManualResponse(
378 response_info.url,
379 response_info.mime_type,
380 GetAllHeaders(response),
381 response_info.expected_length,
382 response_info.last_modified);
383 }
384
385 void WebPluginImpl::didReceiveData(const char* data, int data_length) {
386 delegate_->DidReceiveManualData(data, data_length);
387 }
388
389 void WebPluginImpl::didFinishLoading() {
390 delegate_->DidFinishManualLoading();
391 }
392
393 void WebPluginImpl::didFailLoading(const WebURLError& error) {
394 if (!ignore_response_error_)
395 delegate_->DidManualLoadFail();
396 }
397
398 void WebPluginImpl::didFinishLoadingFrameRequest(
399 const WebURL& url, void* notify_data) {
400 if (delegate_) {
401 // We're converting a void* into an arbitrary int id. Though
402 // these types are the same size on all the platforms we support,
403 // the compiler may complain as though they are different, so to
404 // make the casting gods happy go through an intptr_t (the union
405 // of void* and int) rather than converting straight across.
406 delegate_->DidFinishLoadWithReason(
407 url, NPRES_DONE, reinterpret_cast<intptr_t>(notify_data));
408 }
409 }
410
411 void WebPluginImpl::didFailLoadingFrameRequest(
412 const WebURL& url, void* notify_data, const WebURLError& error) {
413 if (!delegate_)
414 return;
415
416 NPReason reason =
417 error.reason == net::ERR_ABORTED ? NPRES_USER_BREAK : NPRES_NETWORK_ERR;
418 // See comment in didFinishLoadingFrameRequest about the cast here.
419 delegate_->DidFinishLoadWithReason(
420 url, reason, reinterpret_cast<intptr_t>(notify_data));
421 }
422
423 bool WebPluginImpl::supportsPaginatedPrint() {
424 if (!delegate_)
425 return false;
426 return delegate_->PrintSupportsPrintExtension();
427 }
428
429 int WebPluginImpl::printBegin(const WebRect& printable_area, int printer_dpi) {
430 if (!delegate_)
431 return 0;
432
433 if (!supportsPaginatedPrint())
434 return 0;
435
436 return delegate_->PrintBegin(printable_area, printer_dpi);
437 }
438
439 bool WebPluginImpl::printPage(int page_number, WebCanvas* canvas) {
440 if (!delegate_)
441 return false;
442
443 return delegate_->PrintPage(page_number, canvas);
444 }
445
446 void WebPluginImpl::printEnd() {
447 if (delegate_)
448 delegate_->PrintEnd();
449 }
450
451 bool WebPluginImpl::hasSelection() const {
452 if (!delegate_)
453 return false;
454
455 return delegate_->HasSelection();
456 }
457
458 WebKit::WebString WebPluginImpl::selectionAsText() const {
459 if (!delegate_)
460 return WebString();
461
462 return delegate_->GetSelectionAsText();
463 }
464
465 WebKit::WebString WebPluginImpl::selectionAsMarkup() const {
466 if (!delegate_)
467 return WebString();
468
469 return delegate_->GetSelectionAsMarkup();
470 }
471
472 void WebPluginImpl::setZoomFactor(float scale, bool text_only) {
473 if (delegate_)
474 delegate_->SetZoomFactor(scale, text_only);
475 }
476
477 bool WebPluginImpl::startFind(const WebKit::WebString& search_text,
478 bool case_sensitive,
479 int identifier) {
480 if (!delegate_)
481 return false;
482 return delegate_->StartFind(search_text, case_sensitive, identifier);
483 }
484
485 void WebPluginImpl::selectFindResult(bool forward) {
486 if (delegate_)
487 delegate_->SelectFindResult(forward);
488 }
489
490 void WebPluginImpl::stopFind() {
491 if (delegate_)
492 delegate_->StopFind();
493 }
494
495
496 // -----------------------------------------------------------------------------
497
498 WebPluginImpl::WebPluginImpl(
499 WebFrame* webframe,
500 const WebPluginParams& params,
501 const FilePath& file_path,
502 const std::string& mime_type,
503 const base::WeakPtr<WebPluginPageDelegate>& page_delegate)
504 : windowless_(false),
505 window_(gfx::kNullPluginWindow),
506 accepts_input_events_(false),
507 page_delegate_(page_delegate),
508 webframe_(webframe),
509 delegate_(NULL),
510 container_(NULL),
511 plugin_url_(params.url),
512 load_manually_(params.loadManually),
513 first_geometry_update_(true),
514 ignore_response_error_(false),
515 file_path_(file_path),
516 mime_type_(mime_type),
517 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
518 DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size());
519 StringToLowerASCII(&mime_type_);
520
521 for (size_t i = 0; i < params.attributeNames.size(); ++i) {
522 arg_names_.push_back(params.attributeNames[i].utf8());
523 arg_values_.push_back(params.attributeValues[i].utf8());
524 }
525 }
526
527 WebPluginImpl::~WebPluginImpl() {
528 }
529
530 void WebPluginImpl::SetWindow(gfx::PluginWindowHandle window) {
531 #if defined(OS_MACOSX)
532 // The only time this is called twice, and the second time with a
533 // non-zero PluginWindowHandle, is the case when this WebPluginImpl
534 // is created on behalf of the GPU plugin. This entire code path
535 // will go away soon, as soon as the GPU plugin becomes the GPU
536 // process, so it is being separated out for easy deletion.
537
538 // The logic we want here is: if (window) DCHECK(!window_);
539 DCHECK(!(window_ && window));
540 window_ = window;
541 // Lie to ourselves about being windowless even if we got a fake
542 // plugin window handle, so we continue to get input events.
543 windowless_ = true;
544 accepts_input_events_ = true;
545 // We do not really need to notify the page delegate that a plugin
546 // window was created -- so don't.
547 #else
548 if (window) {
549 DCHECK(!windowless_);
550 window_ = window;
551 accepts_input_events_ = false;
552 if (page_delegate_) {
553 // Tell the view delegate that the plugin window was created, so that it
554 // can create necessary container widgets.
555 page_delegate_->CreatedPluginWindow(window);
556 }
557 } else {
558 DCHECK(!window_); // Make sure not called twice.
559 windowless_ = true;
560 accepts_input_events_ = true;
561 }
562 #endif
563 }
564
565 void WebPluginImpl::SetAcceptsInputEvents(bool accepts) {
566 accepts_input_events_ = accepts;
567 }
568
569 void WebPluginImpl::WillDestroyWindow(gfx::PluginWindowHandle window) {
570 DCHECK_EQ(window, window_);
571 window_ = gfx::kNullPluginWindow;
572 if (page_delegate_)
573 page_delegate_->WillDestroyPluginWindow(window);
574 }
575
576 GURL WebPluginImpl::CompleteURL(const char* url) {
577 if (!webframe_) {
578 NOTREACHED();
579 return GURL();
580 }
581 // TODO(darin): Is conversion from UTF8 correct here?
582 return webframe_->document().completeURL(WebString::fromUTF8(url));
583 }
584
585 void WebPluginImpl::CancelResource(unsigned long id) {
586 for (size_t i = 0; i < clients_.size(); ++i) {
587 if (clients_[i].id == id) {
588 if (clients_[i].loader.get()) {
589 clients_[i].loader->setDefersLoading(false);
590 clients_[i].loader->cancel();
591 RemoveClient(i);
592 }
593 return;
594 }
595 }
596 }
597
598 bool WebPluginImpl::SetPostData(WebURLRequest* request,
599 const char *buf,
600 uint32 length) {
601 std::vector<std::string> names;
602 std::vector<std::string> values;
603 std::vector<char> body;
604 bool rv = NPAPI::PluginHost::SetPostData(buf, length, &names, &values, &body);
605
606 for (size_t i = 0; i < names.size(); ++i) {
607 request->addHTTPHeaderField(WebString::fromUTF8(names[i]),
608 WebString::fromUTF8(values[i]));
609 }
610
611 WebString content_type_header = WebString::fromUTF8("Content-Type");
612 const WebString& content_type =
613 request->httpHeaderField(content_type_header);
614 if (content_type.isEmpty()) {
615 request->setHTTPHeaderField(
616 content_type_header,
617 WebString::fromUTF8("application/x-www-form-urlencoded"));
618 }
619
620 WebHTTPBody http_body;
621 if (body.size()) {
622 http_body.initialize();
623 http_body.appendData(WebData(&body[0], body.size()));
624 }
625 request->setHTTPBody(http_body);
626
627 return rv;
628 }
629
630 WebPluginDelegate* WebPluginImpl::delegate() {
631 return delegate_;
632 }
633
634 bool WebPluginImpl::IsValidUrl(const GURL& url, Referrer referrer_flag) {
635 if (referrer_flag == PLUGIN_SRC &&
636 mime_type_ == "application/x-shockwave-flash" &&
637 url.GetOrigin() != plugin_url_.GetOrigin()) {
638 // Do url check to make sure that there are no @, ;, \ chars in between url
639 // scheme and url path.
640 const char* url_to_check(url.spec().data());
641 url_parse::Parsed parsed;
642 url_parse::ParseStandardURL(url_to_check, strlen(url_to_check), &parsed);
643 if (parsed.path.begin <= parsed.scheme.end())
644 return true;
645 std::string string_to_search;
646 string_to_search.assign(url_to_check + parsed.scheme.end(),
647 parsed.path.begin - parsed.scheme.end());
648 if (string_to_search.find("@") != std::string::npos ||
649 string_to_search.find(";") != std::string::npos ||
650 string_to_search.find("\\") != std::string::npos)
651 return false;
652 }
653
654 return true;
655 }
656
657 WebPluginImpl::RoutingStatus WebPluginImpl::RouteToFrame(
658 const char* url,
659 bool is_javascript_url,
660 const char* method,
661 const char* target,
662 const char* buf,
663 unsigned int len,
664 int notify_id,
665 Referrer referrer_flag) {
666 // If there is no target, there is nothing to do
667 if (!target)
668 return NOT_ROUTED;
669
670 // This could happen if the WebPluginContainer was already deleted.
671 if (!webframe_)
672 return NOT_ROUTED;
673
674 WebString target_str = WebString::fromUTF8(target);
675
676 // Take special action for JavaScript URLs
677 if (is_javascript_url) {
678 WebFrame* target_frame =
679 webframe_->view()->findFrameByName(target_str, webframe_);
680 // For security reasons, do not allow JavaScript on frames
681 // other than this frame.
682 if (target_frame != webframe_) {
683 // TODO(darin): Localize this message.
684 const char kMessage[] =
685 "Ignoring cross-frame javascript URL load requested by plugin.";
686 webframe_->addMessageToConsole(
687 WebConsoleMessage(WebConsoleMessage::LevelError,
688 WebString::fromUTF8(kMessage)));
689 return ROUTED;
690 }
691
692 // Route javascript calls back to the plugin.
693 return NOT_ROUTED;
694 }
695
696 // If we got this far, we're routing content to a target frame.
697 // Go fetch the URL.
698
699 GURL complete_url = CompleteURL(url);
700 // Remove when flash bug is fixed. http://crbug.com/40016.
701 if (!WebPluginImpl::IsValidUrl(complete_url, referrer_flag))
702 return INVALID_URL;
703
704 if (strcmp(method, "GET") != 0) {
705 // We're only going to route HTTP/HTTPS requests
706 if (!(complete_url.SchemeIs("http") || complete_url.SchemeIs("https")))
707 return INVALID_URL;
708 }
709
710 WebURLRequest request(complete_url);
711 SetReferrer(&request, referrer_flag);
712
713 request.setHTTPMethod(WebString::fromUTF8(method));
714 request.setFirstPartyForCookies(
715 webframe_->document().firstPartyForCookies());
716 if (len > 0) {
717 if (!SetPostData(&request, buf, len)) {
718 // Uhoh - we're in trouble. There isn't a good way
719 // to recover at this point. Break out.
720 NOTREACHED();
721 return ROUTED;
722 }
723 }
724
725 container_->loadFrameRequest(
726 request, target_str, notify_id != 0, reinterpret_cast<void*>(notify_id));
727 return ROUTED;
728 }
729
730 NPObject* WebPluginImpl::GetWindowScriptNPObject() {
731 if (!webframe_) {
732 NOTREACHED();
733 return NULL;
734 }
735 return webframe_->windowObject();
736 }
737
738 NPObject* WebPluginImpl::GetPluginElement() {
739 return container_->scriptableObjectForElement();
740 }
741
742 void WebPluginImpl::SetCookie(const GURL& url,
743 const GURL& first_party_for_cookies,
744 const std::string& cookie) {
745 if (!page_delegate_)
746 return;
747
748 WebCookieJar* cookie_jar = page_delegate_->GetCookieJar();
749 if (!cookie_jar) {
750 DLOG(WARNING) << "No cookie jar!";
751 return;
752 }
753
754 cookie_jar->setCookie(
755 url, first_party_for_cookies, WebString::fromUTF8(cookie));
756 }
757
758 std::string WebPluginImpl::GetCookies(const GURL& url,
759 const GURL& first_party_for_cookies) {
760 if (!page_delegate_)
761 return std::string();
762
763 WebCookieJar* cookie_jar = page_delegate_->GetCookieJar();
764 if (!cookie_jar) {
765 DLOG(WARNING) << "No cookie jar!";
766 return std::string();
767 }
768
769 return UTF16ToUTF8(cookie_jar->cookies(url, first_party_for_cookies));
770 }
771
772 void WebPluginImpl::ShowModalHTMLDialog(const GURL& url, int width, int height,
773 const std::string& json_arguments,
774 std::string* json_retval) {
775 if (page_delegate_) {
776 page_delegate_->ShowModalHTMLDialogForPlugin(
777 url, gfx::Size(width, height), json_arguments, json_retval);
778 }
779 }
780
781 void WebPluginImpl::OnMissingPluginStatus(int status) {
782 NOTREACHED();
783 }
784
785 void WebPluginImpl::URLRedirectResponse(bool allow, int resource_id) {
786 for (size_t i = 0; i < clients_.size(); ++i) {
787 if (clients_[i].id == static_cast<unsigned long>(resource_id)) {
788 if (clients_[i].loader.get()) {
789 if (allow) {
790 clients_[i].loader->setDefersLoading(false);
791 } else {
792 clients_[i].loader->cancel();
793 clients_[i].client->DidFail();
794 }
795 }
796 break;
797 }
798 }
799 }
800
801 void WebPluginImpl::Invalidate() {
802 if (container_)
803 container_->invalidate();
804 }
805
806 void WebPluginImpl::InvalidateRect(const gfx::Rect& rect) {
807 if (container_)
808 container_->invalidateRect(rect);
809 }
810
811 void WebPluginImpl::OnDownloadPluginSrcUrl() {
812 HandleURLRequestInternal(
813 plugin_url_.spec().c_str(), "GET", NULL, NULL, 0, 0, false, DOCUMENT_URL,
814 false);
815 }
816
817 WebPluginResourceClient* WebPluginImpl::GetClientFromLoader(
818 WebURLLoader* loader) {
819 ClientInfo* client_info = GetClientInfoFromLoader(loader);
820 if (client_info)
821 return client_info->client;
822 return NULL;
823 }
824
825 WebPluginImpl::ClientInfo* WebPluginImpl::GetClientInfoFromLoader(
826 WebURLLoader* loader) {
827 for (size_t i = 0; i < clients_.size(); ++i) {
828 if (clients_[i].loader.get() == loader)
829 return &clients_[i];
830 }
831
832 NOTREACHED();
833 return 0;
834 }
835
836 void WebPluginImpl::willSendRequest(WebURLLoader* loader,
837 WebURLRequest& request,
838 const WebURLResponse& response) {
839 WebPluginImpl::ClientInfo* client_info = GetClientInfoFromLoader(loader);
840 if (client_info) {
841 if (net::HttpResponseHeaders::IsRedirectResponseCode(
842 response.httpStatusCode())) {
843 // If the plugin does not participate in url redirect notifications then
844 // just block cross origin 307 POST redirects.
845 if (!client_info->notify_redirects) {
846 if (response.httpStatusCode() == 307 &&
847 LowerCaseEqualsASCII(request.httpMethod().utf8(), "post")) {
848 GURL original_request_url(response.url());
849 GURL response_url(request.url());
850 if (original_request_url.GetOrigin() != response_url.GetOrigin()) {
851 loader->setDefersLoading(true);
852 loader->cancel();
853 client_info->client->DidFail();
854 return;
855 }
856 }
857 } else {
858 loader->setDefersLoading(true);
859 }
860 }
861 client_info->client->WillSendRequest(request.url(),
862 response.httpStatusCode());
863 }
864 }
865
866 void WebPluginImpl::didSendData(WebURLLoader* loader,
867 unsigned long long bytes_sent,
868 unsigned long long total_bytes_to_be_sent) {
869 }
870
871 void WebPluginImpl::didReceiveResponse(WebURLLoader* loader,
872 const WebURLResponse& response) {
873 static const int kHttpPartialResponseStatusCode = 206;
874 static const int kHttpResponseSuccessStatusCode = 200;
875
876 WebPluginResourceClient* client = GetClientFromLoader(loader);
877 if (!client)
878 return;
879
880 ResponseInfo response_info;
881 GetResponseInfo(response, &response_info);
882
883 bool request_is_seekable = true;
884 if (client->IsMultiByteResponseExpected()) {
885 if (response.httpStatusCode() == kHttpPartialResponseStatusCode) {
886 HandleHttpMultipartResponse(response, client);
887 return;
888 } else if (response.httpStatusCode() == kHttpResponseSuccessStatusCode) {
889 // If the client issued a byte range request and the server responds with
890 // HTTP 200 OK, it indicates that the server does not support byte range
891 // requests.
892 // We need to emulate Firefox behavior by doing the following:-
893 // 1. Destroy the plugin instance in the plugin process. Ensure that
894 // existing resource requests initiated for the plugin instance
895 // continue to remain valid.
896 // 2. Create a new plugin instance and notify it about the response
897 // received here.
898 if (!ReinitializePluginForResponse(loader)) {
899 NOTREACHED();
900 return;
901 }
902
903 // The server does not support byte range requests. No point in creating
904 // seekable streams.
905 request_is_seekable = false;
906
907 delete client;
908 client = NULL;
909
910 // Create a new resource client for this request.
911 for (size_t i = 0; i < clients_.size(); ++i) {
912 if (clients_[i].loader.get() == loader) {
913 WebPluginResourceClient* resource_client =
914 delegate_->CreateResourceClient(clients_[i].id, plugin_url_, 0);
915 clients_[i].client = resource_client;
916 client = resource_client;
917 break;
918 }
919 }
920
921 DCHECK(client != NULL);
922 }
923 }
924
925 // Calling into a plugin could result in reentrancy if the plugin yields
926 // control to the OS like entering a modal loop etc. Prevent this by
927 // stopping further loading until the plugin notifies us that it is ready to
928 // accept data
929 loader->setDefersLoading(true);
930
931 client->DidReceiveResponse(
932 response_info.mime_type,
933 GetAllHeaders(response),
934 response_info.expected_length,
935 response_info.last_modified,
936 request_is_seekable);
937
938 if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) {
939 ClientInfo* client_info = GetClientInfoFromLoader(loader);
940 if (client_info)
941 devtools_agent->didReceiveResponse(client_info->id, response);
942 }
943
944 // Bug http://b/issue?id=925559. The flash plugin would not handle the HTTP
945 // error codes in the stream header and as a result, was unaware of the
946 // fate of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF
947 // destroy the stream and invoke the NPP_DestroyStream function on the
948 // plugin if the HTTP request fails.
949 const GURL& url = response.url();
950 if (url.SchemeIs("http") || url.SchemeIs("https")) {
951 if (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400) {
952 // The plugin instance could be in the process of deletion here.
953 // Verify if the WebPluginResourceClient instance still exists before
954 // use.
955 ClientInfo* client_info = GetClientInfoFromLoader(loader);
956 if (client_info) {
957 client_info->pending_failure_notification = true;
958 }
959 }
960 }
961 }
962
963 void WebPluginImpl::didReceiveData(WebURLLoader* loader,
964 const char *buffer,
965 int length) {
966 WebPluginResourceClient* client = GetClientFromLoader(loader);
967 if (!client)
968 return;
969
970 // ClientInfo can be removed from clients_ vector by next statements.
971 if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) {
972 ClientInfo* client_info = GetClientInfoFromLoader(loader);
973 if (client_info)
974 devtools_agent->didReceiveData(client_info->id, length);
975 }
976 MultiPartResponseHandlerMap::iterator index =
977 multi_part_response_map_.find(client);
978 if (index != multi_part_response_map_.end()) {
979 MultipartResponseDelegate* multi_part_handler = (*index).second;
980 DCHECK(multi_part_handler != NULL);
981 multi_part_handler->OnReceivedData(buffer, length);
982 } else {
983 loader->setDefersLoading(true);
984 client->DidReceiveData(buffer, length, 0);
985 }
986 }
987
988 void WebPluginImpl::didFinishLoading(WebURLLoader* loader, double finishTime) {
989 ClientInfo* client_info = GetClientInfoFromLoader(loader);
990 if (client_info && client_info->client) {
991 MultiPartResponseHandlerMap::iterator index =
992 multi_part_response_map_.find(client_info->client);
993 if (index != multi_part_response_map_.end()) {
994 delete (*index).second;
995 multi_part_response_map_.erase(index);
996 if (page_delegate_)
997 page_delegate_->DidStopLoadingForPlugin();
998 }
999 loader->setDefersLoading(true);
1000 WebPluginResourceClient* resource_client = client_info->client;
1001 // The ClientInfo can get deleted in the call to DidFinishLoading below.
1002 // It is not safe to access this structure after that.
1003 client_info->client = NULL;
1004 resource_client->DidFinishLoading();
1005
1006 if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent())
1007 devtools_agent->didFinishLoading(client_info->id);
1008 }
1009 }
1010
1011 void WebPluginImpl::didFail(WebURLLoader* loader,
1012 const WebURLError& error) {
1013 ClientInfo* client_info = GetClientInfoFromLoader(loader);
1014 if (client_info && client_info->client) {
1015 loader->setDefersLoading(true);
1016 WebPluginResourceClient* resource_client = client_info->client;
1017 // The ClientInfo can get deleted in the call to DidFail below.
1018 // It is not safe to access this structure after that.
1019 client_info->client = NULL;
1020 resource_client->DidFail();
1021
1022 if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent())
1023 devtools_agent->didFailLoading(client_info->id, error);
1024 }
1025 }
1026
1027 void WebPluginImpl::RemoveClient(size_t i) {
1028 clients_.erase(clients_.begin() + i);
1029 }
1030
1031 void WebPluginImpl::RemoveClient(WebURLLoader* loader) {
1032 for (size_t i = 0; i < clients_.size(); ++i) {
1033 if (clients_[i].loader.get() == loader) {
1034 RemoveClient(i);
1035 return;
1036 }
1037 }
1038 }
1039
1040 void WebPluginImpl::SetContainer(WebPluginContainer* container) {
1041 if (!container)
1042 TearDownPluginInstance(NULL);
1043 container_ = container;
1044 }
1045
1046 void WebPluginImpl::HandleURLRequest(const char* url,
1047 const char* method,
1048 const char* target,
1049 const char* buf,
1050 unsigned int len,
1051 int notify_id,
1052 bool popups_allowed,
1053 bool notify_redirects) {
1054 // GetURL/PostURL requests initiated explicitly by plugins should specify the
1055 // plugin SRC url as the referrer if it is available.
1056 HandleURLRequestInternal(
1057 url, method, target, buf, len, notify_id, popups_allowed, PLUGIN_SRC,
1058 notify_redirects);
1059 }
1060
1061 void WebPluginImpl::HandleURLRequestInternal(const char* url,
1062 const char* method,
1063 const char* target,
1064 const char* buf,
1065 unsigned int len,
1066 int notify_id,
1067 bool popups_allowed,
1068 Referrer referrer_flag,
1069 bool notify_redirects) {
1070 // For this request, we either route the output to a frame
1071 // because a target has been specified, or we handle the request
1072 // here, i.e. by executing the script if it is a javascript url
1073 // or by initiating a download on the URL, etc. There is one special
1074 // case in that the request is a javascript url and the target is "_self",
1075 // in which case we route the output to the plugin rather than routing it
1076 // to the plugin's frame.
1077 bool is_javascript_url = StartsWithASCII(url, "javascript:", false);
1078 RoutingStatus routing_status = RouteToFrame(
1079 url, is_javascript_url, method, target, buf, len, notify_id,
1080 referrer_flag);
1081 if (routing_status == ROUTED)
1082 return;
1083
1084 if (is_javascript_url) {
1085 GURL gurl(url);
1086 WebString result = container_->executeScriptURL(gurl, popups_allowed);
1087
1088 // delegate_ could be NULL because executeScript caused the container to
1089 // be deleted.
1090 if (delegate_) {
1091 delegate_->SendJavaScriptStream(
1092 gurl, result.utf8(), !result.isNull(), notify_id);
1093 }
1094
1095 return;
1096 }
1097
1098 unsigned long resource_id = GetNextResourceId();
1099 if (!resource_id)
1100 return;
1101
1102 GURL complete_url = CompleteURL(url);
1103 // Remove when flash bug is fixed. http://crbug.com/40016.
1104 if (!WebPluginImpl::IsValidUrl(complete_url, referrer_flag))
1105 return;
1106
1107 WebPluginResourceClient* resource_client = delegate_->CreateResourceClient(
1108 resource_id, complete_url, notify_id);
1109 if (!resource_client)
1110 return;
1111
1112 // If the RouteToFrame call returned a failure then inform the result
1113 // back to the plugin asynchronously.
1114 if ((routing_status == INVALID_URL) ||
1115 (routing_status == GENERAL_FAILURE)) {
1116 resource_client->DidFail();
1117 return;
1118 }
1119
1120 // CreateResourceClient() sends a synchronous IPC message so it's possible
1121 // that TearDownPluginInstance() may have been called in the nested
1122 // message loop. If so, don't start the request.
1123 if (!delegate_)
1124 return;
1125
1126 InitiateHTTPRequest(resource_id, resource_client, complete_url, method, buf,
1127 len, NULL, referrer_flag, notify_redirects);
1128 }
1129
1130 unsigned long WebPluginImpl::GetNextResourceId() {
1131 if (!webframe_)
1132 return 0;
1133 WebView* view = webframe_->view();
1134 if (!view)
1135 return 0;
1136 return view->createUniqueIdentifierForRequest();
1137 }
1138
1139 bool WebPluginImpl::InitiateHTTPRequest(unsigned long resource_id,
1140 WebPluginResourceClient* client,
1141 const GURL& url,
1142 const char* method,
1143 const char* buf,
1144 int buf_len,
1145 const char* range_info,
1146 Referrer referrer_flag,
1147 bool notify_redirects) {
1148 if (!client) {
1149 NOTREACHED();
1150 return false;
1151 }
1152
1153 ClientInfo info;
1154 info.id = resource_id;
1155 info.client = client;
1156 info.request.initialize();
1157 info.request.setURL(url);
1158 info.request.setFirstPartyForCookies(
1159 webframe_->document().firstPartyForCookies());
1160 info.request.setRequestorProcessID(delegate_->GetProcessId());
1161 info.request.setTargetType(WebURLRequest::TargetIsObject);
1162 info.request.setHTTPMethod(WebString::fromUTF8(method));
1163 info.pending_failure_notification = false;
1164 info.notify_redirects = notify_redirects;
1165
1166 if (range_info) {
1167 info.request.addHTTPHeaderField(WebString::fromUTF8("Range"),
1168 WebString::fromUTF8(range_info));
1169 }
1170
1171 if (strcmp(method, "POST") == 0) {
1172 // Adds headers or form data to a request. This must be called before
1173 // we initiate the actual request.
1174 SetPostData(&info.request, buf, buf_len);
1175 }
1176
1177 SetReferrer(&info.request, referrer_flag);
1178
1179 // Sets the routing id to associate the ResourceRequest with the RenderView.
1180 webframe_->dispatchWillSendRequest(info.request);
1181
1182 // Sets the appcache host id to allow retrieval from the appcache.
1183 if (WebApplicationCacheHostImpl* appcache_host =
1184 WebApplicationCacheHostImpl::FromFrame(webframe_)) {
1185 appcache_host->willStartSubResourceRequest(info.request);
1186 }
1187
1188 if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) {
1189 devtools_agent->identifierForInitialRequest(resource_id, webframe_,
1190 info.request);
1191 devtools_agent->willSendRequest(resource_id, info.request);
1192 }
1193
1194 info.loader.reset(WebKit::webKitClient()->createURLLoader());
1195 if (!info.loader.get())
1196 return false;
1197 info.loader->loadAsynchronously(info.request, this);
1198
1199 clients_.push_back(info);
1200 return true;
1201 }
1202
1203 void WebPluginImpl::CancelDocumentLoad() {
1204 if (webframe_) {
1205 ignore_response_error_ = true;
1206 webframe_->stopLoading();
1207 }
1208 }
1209
1210 void WebPluginImpl::InitiateHTTPRangeRequest(
1211 const char* url, const char* range_info, int range_request_id) {
1212 unsigned long resource_id = GetNextResourceId();
1213 if (!resource_id)
1214 return;
1215
1216 GURL complete_url = CompleteURL(url);
1217 // Remove when flash bug is fixed. http://crbug.com/40016.
1218 if (!WebPluginImpl::IsValidUrl(complete_url,
1219 load_manually_ ? NO_REFERRER : PLUGIN_SRC))
1220 return;
1221
1222 WebPluginResourceClient* resource_client =
1223 delegate_->CreateSeekableResourceClient(resource_id, range_request_id);
1224 InitiateHTTPRequest(
1225 resource_id, resource_client, complete_url, "GET", NULL, 0, range_info,
1226 load_manually_ ? NO_REFERRER : PLUGIN_SRC, false);
1227 }
1228
1229 void WebPluginImpl::SetDeferResourceLoading(unsigned long resource_id,
1230 bool defer) {
1231 std::vector<ClientInfo>::iterator client_index = clients_.begin();
1232 while (client_index != clients_.end()) {
1233 ClientInfo& client_info = *client_index;
1234
1235 if (client_info.id == resource_id) {
1236 client_info.loader->setDefersLoading(defer);
1237
1238 // If we determined that the request had failed via the HTTP headers
1239 // in the response then we send out a failure notification to the
1240 // plugin process, as certain plugins don't handle HTTP failure codes
1241 // correctly.
1242 if (!defer && client_info.client &&
1243 client_info.pending_failure_notification) {
1244 // The ClientInfo and the iterator can become invalid due to the call
1245 // to DidFail below.
1246 WebPluginResourceClient* resource_client = client_info.client;
1247 client_info.loader->cancel();
1248 clients_.erase(client_index++);
1249 resource_client->DidFail();
1250
1251 // Report that resource loading finished.
1252 if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent())
1253 devtools_agent->didFinishLoading(resource_id);
1254 }
1255 break;
1256 }
1257 client_index++;
1258 }
1259 }
1260
1261 bool WebPluginImpl::IsOffTheRecord() {
1262 return false;
1263 }
1264
1265 void WebPluginImpl::HandleHttpMultipartResponse(
1266 const WebURLResponse& response, WebPluginResourceClient* client) {
1267 std::string multipart_boundary;
1268 if (!MultipartResponseDelegate::ReadMultipartBoundary(
1269 response, &multipart_boundary)) {
1270 NOTREACHED();
1271 return;
1272 }
1273
1274 if (page_delegate_)
1275 page_delegate_->DidStartLoadingForPlugin();
1276
1277 MultiPartResponseClient* multi_part_response_client =
1278 new MultiPartResponseClient(client);
1279
1280 MultipartResponseDelegate* multi_part_response_handler =
1281 new MultipartResponseDelegate(multi_part_response_client, NULL,
1282 response,
1283 multipart_boundary);
1284 multi_part_response_map_[client] = multi_part_response_handler;
1285 }
1286
1287 bool WebPluginImpl::ReinitializePluginForResponse(
1288 WebURLLoader* loader) {
1289 WebFrame* webframe = webframe_;
1290 if (!webframe)
1291 return false;
1292
1293 WebView* webview = webframe->view();
1294 if (!webview)
1295 return false;
1296
1297 WebPluginContainer* container_widget = container_;
1298
1299 // Destroy the current plugin instance.
1300 TearDownPluginInstance(loader);
1301
1302 container_ = container_widget;
1303 webframe_ = webframe;
1304
1305 WebPluginDelegate* plugin_delegate = page_delegate_->CreatePluginDelegate(
1306 file_path_, mime_type_);
1307
1308 bool ok = plugin_delegate && plugin_delegate->Initialize(
1309 plugin_url_, arg_names_, arg_values_, this, load_manually_);
1310
1311 if (!ok) {
1312 container_ = NULL;
1313 // TODO(iyengar) Should we delete the current plugin instance here?
1314 return false;
1315 }
1316
1317 delegate_ = plugin_delegate;
1318
1319 // Force a geometry update to occur to ensure that the plugin becomes
1320 // visible.
1321 container_->reportGeometry();
1322
1323 // The plugin move sequences accumulated via DidMove are sent to the browser
1324 // whenever the renderer paints. Force a paint here to ensure that changes
1325 // to the plugin window are propagated to the browser.
1326 container_->invalidate();
1327 return true;
1328 }
1329
1330 void WebPluginImpl::TearDownPluginInstance(
1331 WebURLLoader* loader_to_ignore) {
1332 // The container maintains a list of JSObjects which are related to this
1333 // plugin. Tell the frame we're gone so that it can invalidate all of
1334 // those sub JSObjects.
1335 if (container_)
1336 container_->clearScriptObjects();
1337
1338 if (delegate_) {
1339 // Call PluginDestroyed() first to prevent the plugin from calling us back
1340 // in the middle of tearing down the render tree.
1341 delegate_->PluginDestroyed();
1342 delegate_ = NULL;
1343 }
1344
1345 // Cancel any pending requests because otherwise this deleted object will
1346 // be called by the ResourceDispatcher.
1347 std::vector<ClientInfo>::iterator client_index = clients_.begin();
1348 while (client_index != clients_.end()) {
1349 ClientInfo& client_info = *client_index;
1350
1351 if (loader_to_ignore == client_info.loader) {
1352 client_index++;
1353 continue;
1354 }
1355
1356 if (client_info.loader.get())
1357 client_info.loader->cancel();
1358
1359 client_index = clients_.erase(client_index);
1360 }
1361
1362 // This needs to be called now and not in the destructor since the
1363 // webframe_ might not be valid anymore.
1364 webframe_ = NULL;
1365 method_factory_.RevokeAll();
1366 }
1367
1368 void WebPluginImpl::SetReferrer(WebKit::WebURLRequest* request,
1369 Referrer referrer_flag) {
1370 switch (referrer_flag) {
1371 case DOCUMENT_URL:
1372 webframe_->setReferrerForRequest(*request, GURL());
1373 break;
1374
1375 case PLUGIN_SRC:
1376 webframe_->setReferrerForRequest(*request, plugin_url_);
1377 break;
1378
1379 default:
1380 break;
1381 }
1382 }
1383
1384 WebDevToolsAgent* WebPluginImpl::GetDevToolsAgent() {
1385 if (!webframe_)
1386 return NULL;
1387 WebView* view = webframe_->view();
1388 if (!view)
1389 return NULL;
1390 return view->devToolsAgent();
1391 }
1392
1393 } // namespace webkit_glue
OLDNEW
« no previous file with comments | « webkit/glue/plugins/webplugin_impl.h ('k') | webkit/glue/plugins/webplugin_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698