| Index: webkit/glue/plugins/webplugin_impl.cc
|
| ===================================================================
|
| --- webkit/glue/plugins/webplugin_impl.cc (revision 69426)
|
| +++ webkit/glue/plugins/webplugin_impl.cc (working copy)
|
| @@ -1,1393 +0,0 @@
|
| -// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "webkit/glue/plugins/webplugin_impl.h"
|
| -
|
| -#include "base/linked_ptr.h"
|
| -#include "base/logging.h"
|
| -#include "base/message_loop.h"
|
| -#include "base/string_util.h"
|
| -#include "base/stringprintf.h"
|
| -#include "base/utf_string_conversions.h"
|
| -#include "gfx/rect.h"
|
| -#include "googleurl/src/gurl.h"
|
| -#include "net/base/escape.h"
|
| -#include "net/base/net_errors.h"
|
| -#include "net/http/http_response_headers.h"
|
| -#include "skia/ext/platform_canvas.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebConsoleMessage.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebCookieJar.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebDevToolsAgent.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebHTTPBody.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebHTTPHeaderVisitor.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebPluginParams.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebURLError.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebURLLoader.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebURLLoaderClient.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
|
| -#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
|
| -#include "webkit/appcache/web_application_cache_host_impl.h"
|
| -#include "webkit/glue/multipart_response_delegate.h"
|
| -#include "webkit/glue/plugins/plugin_host.h"
|
| -#include "webkit/glue/plugins/plugin_instance.h"
|
| -#include "webkit/glue/plugins/webplugin_delegate.h"
|
| -#include "webkit/glue/plugins/webplugin_page_delegate.h"
|
| -
|
| -using appcache::WebApplicationCacheHostImpl;
|
| -using WebKit::WebCanvas;
|
| -using WebKit::WebConsoleMessage;
|
| -using WebKit::WebCookieJar;
|
| -using WebKit::WebCString;
|
| -using WebKit::WebCursorInfo;
|
| -using WebKit::WebData;
|
| -using WebKit::WebDataSource;
|
| -using WebKit::WebDevToolsAgent;
|
| -using WebKit::WebFrame;
|
| -using WebKit::WebHTTPBody;
|
| -using WebKit::WebHTTPHeaderVisitor;
|
| -using WebKit::WebInputEvent;
|
| -using WebKit::WebKeyboardEvent;
|
| -using WebKit::WebMouseEvent;
|
| -using WebKit::WebPluginContainer;
|
| -using WebKit::WebPluginParams;
|
| -using WebKit::WebRect;
|
| -using WebKit::WebString;
|
| -using WebKit::WebURL;
|
| -using WebKit::WebURLError;
|
| -using WebKit::WebURLLoader;
|
| -using WebKit::WebURLLoaderClient;
|
| -using WebKit::WebURLRequest;
|
| -using WebKit::WebURLResponse;
|
| -using WebKit::WebVector;
|
| -using WebKit::WebView;
|
| -using webkit_glue::MultipartResponseDelegate;
|
| -
|
| -namespace webkit_glue {
|
| -namespace {
|
| -
|
| -// This class handles individual multipart responses. It is instantiated when
|
| -// we receive HTTP status code 206 in the HTTP response. This indicates
|
| -// that the response could have multiple parts each separated by a boundary
|
| -// specified in the response header.
|
| -class MultiPartResponseClient : public WebURLLoaderClient {
|
| - public:
|
| - explicit MultiPartResponseClient(WebPluginResourceClient* resource_client)
|
| - : resource_client_(resource_client) {
|
| - Clear();
|
| - }
|
| -
|
| - virtual void willSendRequest(
|
| - WebURLLoader*, WebURLRequest&, const WebURLResponse&) {}
|
| - virtual void didSendData(
|
| - WebURLLoader*, unsigned long long, unsigned long long) {}
|
| -
|
| - // Called when the multipart parser encounters an embedded multipart
|
| - // response.
|
| - virtual void didReceiveResponse(
|
| - WebURLLoader*, const WebURLResponse& response) {
|
| - int instance_size;
|
| - if (!MultipartResponseDelegate::ReadContentRanges(
|
| - response,
|
| - &byte_range_lower_bound_,
|
| - &byte_range_upper_bound_,
|
| - &instance_size)) {
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| -
|
| - resource_response_ = response;
|
| - }
|
| -
|
| - // Receives individual part data from a multipart response.
|
| - virtual void didReceiveData(
|
| - WebURLLoader*, const char* data, int data_size) {
|
| - // TODO(ananta)
|
| - // We should defer further loads on multipart resources on the same lines
|
| - // as regular resources requested by plugins to prevent reentrancy.
|
| - resource_client_->DidReceiveData(
|
| - data, data_size, byte_range_lower_bound_);
|
| - byte_range_lower_bound_ += data_size;
|
| - }
|
| -
|
| - virtual void didFinishLoading(WebURLLoader*, double finishTime) {}
|
| - virtual void didFail(WebURLLoader*, const WebURLError&) {}
|
| -
|
| - void Clear() {
|
| - resource_response_.reset();
|
| - byte_range_lower_bound_ = 0;
|
| - byte_range_upper_bound_ = 0;
|
| - }
|
| -
|
| - private:
|
| - WebURLResponse resource_response_;
|
| - // The lower bound of the byte range.
|
| - int byte_range_lower_bound_;
|
| - // The upper bound of the byte range.
|
| - int byte_range_upper_bound_;
|
| - // The handler for the data.
|
| - WebPluginResourceClient* resource_client_;
|
| -};
|
| -
|
| -class HeaderFlattener : public WebHTTPHeaderVisitor {
|
| - public:
|
| - HeaderFlattener(std::string* buf) : buf_(buf) {
|
| - }
|
| -
|
| - virtual void visitHeader(const WebString& name, const WebString& value) {
|
| - // TODO(darin): Should we really exclude headers with an empty value?
|
| - if (!name.isEmpty() && !value.isEmpty()) {
|
| - buf_->append(name.utf8());
|
| - buf_->append(": ");
|
| - buf_->append(value.utf8());
|
| - buf_->append("\n");
|
| - }
|
| - }
|
| -
|
| - private:
|
| - std::string* buf_;
|
| -};
|
| -
|
| -std::string GetAllHeaders(const WebURLResponse& response) {
|
| - // TODO(darin): It is possible for httpStatusText to be empty and still have
|
| - // an interesting response, so this check seems wrong.
|
| - std::string result;
|
| - const WebString& status = response.httpStatusText();
|
| - if (status.isEmpty())
|
| - return result;
|
| -
|
| - // TODO(darin): Shouldn't we also report HTTP version numbers?
|
| - result = base::StringPrintf("HTTP %d ", response.httpStatusCode());
|
| - result.append(status.utf8());
|
| - result.append("\n");
|
| -
|
| - HeaderFlattener flattener(&result);
|
| - response.visitHTTPHeaderFields(&flattener);
|
| -
|
| - return result;
|
| -}
|
| -
|
| -struct ResponseInfo {
|
| - GURL url;
|
| - std::string mime_type;
|
| - uint32 last_modified;
|
| - uint32 expected_length;
|
| -};
|
| -
|
| -void GetResponseInfo(const WebURLResponse& response,
|
| - ResponseInfo* response_info) {
|
| - response_info->url = response.url();
|
| - response_info->mime_type = response.mimeType().utf8();
|
| -
|
| - // Measured in seconds since 12:00 midnight GMT, January 1, 1970.
|
| - response_info->last_modified =
|
| - static_cast<uint32>(response.lastModifiedDate());
|
| -
|
| - // If the length comes in as -1, then it indicates that it was not
|
| - // read off the HTTP headers. We replicate Safari webkit behavior here,
|
| - // which is to set it to 0.
|
| - response_info->expected_length =
|
| - static_cast<uint32>(std::max(response.expectedContentLength(), 0LL));
|
| -
|
| - WebString content_encoding =
|
| - response.httpHeaderField(WebString::fromUTF8("Content-Encoding"));
|
| - if (!content_encoding.isNull() &&
|
| - !EqualsASCII(content_encoding, "identity")) {
|
| - // Don't send the compressed content length to the plugin, which only
|
| - // cares about the decoded length.
|
| - response_info->expected_length = 0;
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -// WebKit::WebPlugin ----------------------------------------------------------
|
| -
|
| -struct WebPluginImpl::ClientInfo {
|
| - unsigned long id;
|
| - WebPluginResourceClient* client;
|
| - WebKit::WebURLRequest request;
|
| - bool pending_failure_notification;
|
| - linked_ptr<WebKit::WebURLLoader> loader;
|
| - bool notify_redirects;
|
| -};
|
| -
|
| -bool WebPluginImpl::initialize(WebPluginContainer* container) {
|
| - if (!page_delegate_)
|
| - return false;
|
| -
|
| - WebPluginDelegate* plugin_delegate = page_delegate_->CreatePluginDelegate(
|
| - file_path_, mime_type_);
|
| - if (!plugin_delegate)
|
| - return false;
|
| -
|
| - // Set the container before Initialize because the plugin may
|
| - // synchronously call NPN_GetValue to get its container during its
|
| - // initialization.
|
| - SetContainer(container);
|
| - bool ok = plugin_delegate->Initialize(
|
| - plugin_url_, arg_names_, arg_values_, this, load_manually_);
|
| - if (!ok) {
|
| - plugin_delegate->PluginDestroyed();
|
| - return false;
|
| - }
|
| -
|
| - delegate_ = plugin_delegate;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void WebPluginImpl::destroy() {
|
| - SetContainer(NULL);
|
| - MessageLoop::current()->DeleteSoon(FROM_HERE, this);
|
| -}
|
| -
|
| -NPObject* WebPluginImpl::scriptableObject() {
|
| - return delegate_->GetPluginScriptableObject();
|
| -}
|
| -
|
| -void WebPluginImpl::paint(WebCanvas* canvas, const WebRect& paint_rect) {
|
| - if (!delegate_ || !container_)
|
| - return;
|
| -
|
| -#if defined(OS_WIN)
|
| - // Force a geometry update if needed to allow plugins like media player
|
| - // which defer the initial geometry update to work.
|
| - container_->reportGeometry();
|
| -#endif // OS_WIN
|
| -
|
| - // Note that |canvas| is only used when in windowless mode.
|
| - delegate_->Paint(canvas, paint_rect);
|
| -}
|
| -
|
| -void WebPluginImpl::updateGeometry(
|
| - const WebRect& window_rect, const WebRect& clip_rect,
|
| - const WebVector<WebRect>& cutout_rects, bool is_visible) {
|
| - WebPluginGeometry new_geometry;
|
| - new_geometry.window = window_;
|
| - new_geometry.window_rect = window_rect;
|
| - new_geometry.clip_rect = clip_rect;
|
| - new_geometry.visible = is_visible;
|
| - new_geometry.rects_valid = true;
|
| - for (size_t i = 0; i < cutout_rects.size(); ++i)
|
| - new_geometry.cutout_rects.push_back(cutout_rects[i]);
|
| -
|
| - // Only send DidMovePlugin if the geometry changed in some way.
|
| - if (window_ &&
|
| - page_delegate_ &&
|
| - (first_geometry_update_ || !new_geometry.Equals(geometry_))) {
|
| - page_delegate_->DidMovePlugin(new_geometry);
|
| - }
|
| -
|
| - // Only UpdateGeometry if either the window or clip rects have changed.
|
| - if (first_geometry_update_ ||
|
| - new_geometry.window_rect != geometry_.window_rect ||
|
| - new_geometry.clip_rect != geometry_.clip_rect) {
|
| - // Notify the plugin that its parameters have changed.
|
| - delegate_->UpdateGeometry(new_geometry.window_rect, new_geometry.clip_rect);
|
| - }
|
| -
|
| - // Initiate a download on the plugin url. This should be done for the
|
| - // first update geometry sequence. We need to ensure that the plugin
|
| - // receives the geometry update before it starts receiving data.
|
| - if (first_geometry_update_) {
|
| - // An empty url corresponds to an EMBED tag with no src attribute.
|
| - if (!load_manually_ && plugin_url_.is_valid()) {
|
| - // The Flash plugin hangs for a while if it receives data before
|
| - // receiving valid plugin geometry. By valid geometry we mean the
|
| - // geometry received by a call to setFrameRect in the Webkit
|
| - // layout code path. To workaround this issue we download the
|
| - // plugin source url on a timer.
|
| - MessageLoop::current()->PostDelayedTask(
|
| - FROM_HERE, method_factory_.NewRunnableMethod(
|
| - &WebPluginImpl::OnDownloadPluginSrcUrl), 0);
|
| - }
|
| - }
|
| -
|
| -#if defined(OS_WIN)
|
| - // Don't cache the geometry during the first geometry update. The first
|
| - // geometry update sequence is received when Widget::setParent is called.
|
| - // For plugins like media player which have a bug where they only honor
|
| - // the first geometry update, we have a quirk which ignores the first
|
| - // geometry update. To ensure that these plugins work correctly in cases
|
| - // where we receive only one geometry update from webkit, we also force
|
| - // a geometry update during paint which should go out correctly as the
|
| - // initial geometry update was not cached.
|
| - if (!first_geometry_update_)
|
| - geometry_ = new_geometry;
|
| -#else // OS_WIN
|
| - geometry_ = new_geometry;
|
| -#endif // OS_WIN
|
| - first_geometry_update_ = false;
|
| -}
|
| -
|
| -unsigned WebPluginImpl::getBackingTextureId() {
|
| - // Regular plugins do not have a backing texture.
|
| - return 0;
|
| -}
|
| -
|
| -void WebPluginImpl::updateFocus(bool focused) {
|
| - if (accepts_input_events_)
|
| - delegate_->SetFocus(focused);
|
| -}
|
| -
|
| -void WebPluginImpl::updateVisibility(bool visible) {
|
| - if (!window_ || !page_delegate_)
|
| - return;
|
| -
|
| - WebPluginGeometry move;
|
| - move.window = window_;
|
| - move.window_rect = gfx::Rect();
|
| - move.clip_rect = gfx::Rect();
|
| - move.rects_valid = false;
|
| - move.visible = visible;
|
| -
|
| - page_delegate_->DidMovePlugin(move);
|
| -}
|
| -
|
| -bool WebPluginImpl::acceptsInputEvents() {
|
| - return accepts_input_events_;
|
| -}
|
| -
|
| -bool WebPluginImpl::handleInputEvent(
|
| - const WebInputEvent& event, WebCursorInfo& cursor_info) {
|
| - // Swallow context menu events in order to suppress the default context menu.
|
| - if (event.type == WebInputEvent::ContextMenu)
|
| - return true;
|
| -
|
| - return delegate_->HandleInputEvent(event, &cursor_info);
|
| -}
|
| -
|
| -void WebPluginImpl::didReceiveResponse(const WebURLResponse& response) {
|
| - ignore_response_error_ = false;
|
| -
|
| - ResponseInfo response_info;
|
| - GetResponseInfo(response, &response_info);
|
| -
|
| - delegate_->DidReceiveManualResponse(
|
| - response_info.url,
|
| - response_info.mime_type,
|
| - GetAllHeaders(response),
|
| - response_info.expected_length,
|
| - response_info.last_modified);
|
| -}
|
| -
|
| -void WebPluginImpl::didReceiveData(const char* data, int data_length) {
|
| - delegate_->DidReceiveManualData(data, data_length);
|
| -}
|
| -
|
| -void WebPluginImpl::didFinishLoading() {
|
| - delegate_->DidFinishManualLoading();
|
| -}
|
| -
|
| -void WebPluginImpl::didFailLoading(const WebURLError& error) {
|
| - if (!ignore_response_error_)
|
| - delegate_->DidManualLoadFail();
|
| -}
|
| -
|
| -void WebPluginImpl::didFinishLoadingFrameRequest(
|
| - const WebURL& url, void* notify_data) {
|
| - if (delegate_) {
|
| - // We're converting a void* into an arbitrary int id. Though
|
| - // these types are the same size on all the platforms we support,
|
| - // the compiler may complain as though they are different, so to
|
| - // make the casting gods happy go through an intptr_t (the union
|
| - // of void* and int) rather than converting straight across.
|
| - delegate_->DidFinishLoadWithReason(
|
| - url, NPRES_DONE, reinterpret_cast<intptr_t>(notify_data));
|
| - }
|
| -}
|
| -
|
| -void WebPluginImpl::didFailLoadingFrameRequest(
|
| - const WebURL& url, void* notify_data, const WebURLError& error) {
|
| - if (!delegate_)
|
| - return;
|
| -
|
| - NPReason reason =
|
| - error.reason == net::ERR_ABORTED ? NPRES_USER_BREAK : NPRES_NETWORK_ERR;
|
| - // See comment in didFinishLoadingFrameRequest about the cast here.
|
| - delegate_->DidFinishLoadWithReason(
|
| - url, reason, reinterpret_cast<intptr_t>(notify_data));
|
| -}
|
| -
|
| -bool WebPluginImpl::supportsPaginatedPrint() {
|
| - if (!delegate_)
|
| - return false;
|
| - return delegate_->PrintSupportsPrintExtension();
|
| -}
|
| -
|
| -int WebPluginImpl::printBegin(const WebRect& printable_area, int printer_dpi) {
|
| - if (!delegate_)
|
| - return 0;
|
| -
|
| - if (!supportsPaginatedPrint())
|
| - return 0;
|
| -
|
| - return delegate_->PrintBegin(printable_area, printer_dpi);
|
| -}
|
| -
|
| -bool WebPluginImpl::printPage(int page_number, WebCanvas* canvas) {
|
| - if (!delegate_)
|
| - return false;
|
| -
|
| - return delegate_->PrintPage(page_number, canvas);
|
| -}
|
| -
|
| -void WebPluginImpl::printEnd() {
|
| - if (delegate_)
|
| - delegate_->PrintEnd();
|
| -}
|
| -
|
| -bool WebPluginImpl::hasSelection() const {
|
| - if (!delegate_)
|
| - return false;
|
| -
|
| - return delegate_->HasSelection();
|
| -}
|
| -
|
| -WebKit::WebString WebPluginImpl::selectionAsText() const {
|
| - if (!delegate_)
|
| - return WebString();
|
| -
|
| - return delegate_->GetSelectionAsText();
|
| -}
|
| -
|
| -WebKit::WebString WebPluginImpl::selectionAsMarkup() const {
|
| - if (!delegate_)
|
| - return WebString();
|
| -
|
| - return delegate_->GetSelectionAsMarkup();
|
| -}
|
| -
|
| -void WebPluginImpl::setZoomFactor(float scale, bool text_only) {
|
| - if (delegate_)
|
| - delegate_->SetZoomFactor(scale, text_only);
|
| -}
|
| -
|
| -bool WebPluginImpl::startFind(const WebKit::WebString& search_text,
|
| - bool case_sensitive,
|
| - int identifier) {
|
| - if (!delegate_)
|
| - return false;
|
| - return delegate_->StartFind(search_text, case_sensitive, identifier);
|
| -}
|
| -
|
| -void WebPluginImpl::selectFindResult(bool forward) {
|
| - if (delegate_)
|
| - delegate_->SelectFindResult(forward);
|
| -}
|
| -
|
| -void WebPluginImpl::stopFind() {
|
| - if (delegate_)
|
| - delegate_->StopFind();
|
| -}
|
| -
|
| -
|
| -// -----------------------------------------------------------------------------
|
| -
|
| -WebPluginImpl::WebPluginImpl(
|
| - WebFrame* webframe,
|
| - const WebPluginParams& params,
|
| - const FilePath& file_path,
|
| - const std::string& mime_type,
|
| - const base::WeakPtr<WebPluginPageDelegate>& page_delegate)
|
| - : windowless_(false),
|
| - window_(gfx::kNullPluginWindow),
|
| - accepts_input_events_(false),
|
| - page_delegate_(page_delegate),
|
| - webframe_(webframe),
|
| - delegate_(NULL),
|
| - container_(NULL),
|
| - plugin_url_(params.url),
|
| - load_manually_(params.loadManually),
|
| - first_geometry_update_(true),
|
| - ignore_response_error_(false),
|
| - file_path_(file_path),
|
| - mime_type_(mime_type),
|
| - ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
|
| - DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size());
|
| - StringToLowerASCII(&mime_type_);
|
| -
|
| - for (size_t i = 0; i < params.attributeNames.size(); ++i) {
|
| - arg_names_.push_back(params.attributeNames[i].utf8());
|
| - arg_values_.push_back(params.attributeValues[i].utf8());
|
| - }
|
| -}
|
| -
|
| -WebPluginImpl::~WebPluginImpl() {
|
| -}
|
| -
|
| -void WebPluginImpl::SetWindow(gfx::PluginWindowHandle window) {
|
| -#if defined(OS_MACOSX)
|
| - // The only time this is called twice, and the second time with a
|
| - // non-zero PluginWindowHandle, is the case when this WebPluginImpl
|
| - // is created on behalf of the GPU plugin. This entire code path
|
| - // will go away soon, as soon as the GPU plugin becomes the GPU
|
| - // process, so it is being separated out for easy deletion.
|
| -
|
| - // The logic we want here is: if (window) DCHECK(!window_);
|
| - DCHECK(!(window_ && window));
|
| - window_ = window;
|
| - // Lie to ourselves about being windowless even if we got a fake
|
| - // plugin window handle, so we continue to get input events.
|
| - windowless_ = true;
|
| - accepts_input_events_ = true;
|
| - // We do not really need to notify the page delegate that a plugin
|
| - // window was created -- so don't.
|
| -#else
|
| - if (window) {
|
| - DCHECK(!windowless_);
|
| - window_ = window;
|
| - accepts_input_events_ = false;
|
| - if (page_delegate_) {
|
| - // Tell the view delegate that the plugin window was created, so that it
|
| - // can create necessary container widgets.
|
| - page_delegate_->CreatedPluginWindow(window);
|
| - }
|
| - } else {
|
| - DCHECK(!window_); // Make sure not called twice.
|
| - windowless_ = true;
|
| - accepts_input_events_ = true;
|
| - }
|
| -#endif
|
| -}
|
| -
|
| -void WebPluginImpl::SetAcceptsInputEvents(bool accepts) {
|
| - accepts_input_events_ = accepts;
|
| -}
|
| -
|
| -void WebPluginImpl::WillDestroyWindow(gfx::PluginWindowHandle window) {
|
| - DCHECK_EQ(window, window_);
|
| - window_ = gfx::kNullPluginWindow;
|
| - if (page_delegate_)
|
| - page_delegate_->WillDestroyPluginWindow(window);
|
| -}
|
| -
|
| -GURL WebPluginImpl::CompleteURL(const char* url) {
|
| - if (!webframe_) {
|
| - NOTREACHED();
|
| - return GURL();
|
| - }
|
| - // TODO(darin): Is conversion from UTF8 correct here?
|
| - return webframe_->document().completeURL(WebString::fromUTF8(url));
|
| -}
|
| -
|
| -void WebPluginImpl::CancelResource(unsigned long id) {
|
| - for (size_t i = 0; i < clients_.size(); ++i) {
|
| - if (clients_[i].id == id) {
|
| - if (clients_[i].loader.get()) {
|
| - clients_[i].loader->setDefersLoading(false);
|
| - clients_[i].loader->cancel();
|
| - RemoveClient(i);
|
| - }
|
| - return;
|
| - }
|
| - }
|
| -}
|
| -
|
| -bool WebPluginImpl::SetPostData(WebURLRequest* request,
|
| - const char *buf,
|
| - uint32 length) {
|
| - std::vector<std::string> names;
|
| - std::vector<std::string> values;
|
| - std::vector<char> body;
|
| - bool rv = NPAPI::PluginHost::SetPostData(buf, length, &names, &values, &body);
|
| -
|
| - for (size_t i = 0; i < names.size(); ++i) {
|
| - request->addHTTPHeaderField(WebString::fromUTF8(names[i]),
|
| - WebString::fromUTF8(values[i]));
|
| - }
|
| -
|
| - WebString content_type_header = WebString::fromUTF8("Content-Type");
|
| - const WebString& content_type =
|
| - request->httpHeaderField(content_type_header);
|
| - if (content_type.isEmpty()) {
|
| - request->setHTTPHeaderField(
|
| - content_type_header,
|
| - WebString::fromUTF8("application/x-www-form-urlencoded"));
|
| - }
|
| -
|
| - WebHTTPBody http_body;
|
| - if (body.size()) {
|
| - http_body.initialize();
|
| - http_body.appendData(WebData(&body[0], body.size()));
|
| - }
|
| - request->setHTTPBody(http_body);
|
| -
|
| - return rv;
|
| -}
|
| -
|
| -WebPluginDelegate* WebPluginImpl::delegate() {
|
| - return delegate_;
|
| -}
|
| -
|
| -bool WebPluginImpl::IsValidUrl(const GURL& url, Referrer referrer_flag) {
|
| - if (referrer_flag == PLUGIN_SRC &&
|
| - mime_type_ == "application/x-shockwave-flash" &&
|
| - url.GetOrigin() != plugin_url_.GetOrigin()) {
|
| - // Do url check to make sure that there are no @, ;, \ chars in between url
|
| - // scheme and url path.
|
| - const char* url_to_check(url.spec().data());
|
| - url_parse::Parsed parsed;
|
| - url_parse::ParseStandardURL(url_to_check, strlen(url_to_check), &parsed);
|
| - if (parsed.path.begin <= parsed.scheme.end())
|
| - return true;
|
| - std::string string_to_search;
|
| - string_to_search.assign(url_to_check + parsed.scheme.end(),
|
| - parsed.path.begin - parsed.scheme.end());
|
| - if (string_to_search.find("@") != std::string::npos ||
|
| - string_to_search.find(";") != std::string::npos ||
|
| - string_to_search.find("\\") != std::string::npos)
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -WebPluginImpl::RoutingStatus WebPluginImpl::RouteToFrame(
|
| - const char* url,
|
| - bool is_javascript_url,
|
| - const char* method,
|
| - const char* target,
|
| - const char* buf,
|
| - unsigned int len,
|
| - int notify_id,
|
| - Referrer referrer_flag) {
|
| - // If there is no target, there is nothing to do
|
| - if (!target)
|
| - return NOT_ROUTED;
|
| -
|
| - // This could happen if the WebPluginContainer was already deleted.
|
| - if (!webframe_)
|
| - return NOT_ROUTED;
|
| -
|
| - WebString target_str = WebString::fromUTF8(target);
|
| -
|
| - // Take special action for JavaScript URLs
|
| - if (is_javascript_url) {
|
| - WebFrame* target_frame =
|
| - webframe_->view()->findFrameByName(target_str, webframe_);
|
| - // For security reasons, do not allow JavaScript on frames
|
| - // other than this frame.
|
| - if (target_frame != webframe_) {
|
| - // TODO(darin): Localize this message.
|
| - const char kMessage[] =
|
| - "Ignoring cross-frame javascript URL load requested by plugin.";
|
| - webframe_->addMessageToConsole(
|
| - WebConsoleMessage(WebConsoleMessage::LevelError,
|
| - WebString::fromUTF8(kMessage)));
|
| - return ROUTED;
|
| - }
|
| -
|
| - // Route javascript calls back to the plugin.
|
| - return NOT_ROUTED;
|
| - }
|
| -
|
| - // If we got this far, we're routing content to a target frame.
|
| - // Go fetch the URL.
|
| -
|
| - GURL complete_url = CompleteURL(url);
|
| - // Remove when flash bug is fixed. http://crbug.com/40016.
|
| - if (!WebPluginImpl::IsValidUrl(complete_url, referrer_flag))
|
| - return INVALID_URL;
|
| -
|
| - if (strcmp(method, "GET") != 0) {
|
| - // We're only going to route HTTP/HTTPS requests
|
| - if (!(complete_url.SchemeIs("http") || complete_url.SchemeIs("https")))
|
| - return INVALID_URL;
|
| - }
|
| -
|
| - WebURLRequest request(complete_url);
|
| - SetReferrer(&request, referrer_flag);
|
| -
|
| - request.setHTTPMethod(WebString::fromUTF8(method));
|
| - request.setFirstPartyForCookies(
|
| - webframe_->document().firstPartyForCookies());
|
| - if (len > 0) {
|
| - if (!SetPostData(&request, buf, len)) {
|
| - // Uhoh - we're in trouble. There isn't a good way
|
| - // to recover at this point. Break out.
|
| - NOTREACHED();
|
| - return ROUTED;
|
| - }
|
| - }
|
| -
|
| - container_->loadFrameRequest(
|
| - request, target_str, notify_id != 0, reinterpret_cast<void*>(notify_id));
|
| - return ROUTED;
|
| -}
|
| -
|
| -NPObject* WebPluginImpl::GetWindowScriptNPObject() {
|
| - if (!webframe_) {
|
| - NOTREACHED();
|
| - return NULL;
|
| - }
|
| - return webframe_->windowObject();
|
| -}
|
| -
|
| -NPObject* WebPluginImpl::GetPluginElement() {
|
| - return container_->scriptableObjectForElement();
|
| -}
|
| -
|
| -void WebPluginImpl::SetCookie(const GURL& url,
|
| - const GURL& first_party_for_cookies,
|
| - const std::string& cookie) {
|
| - if (!page_delegate_)
|
| - return;
|
| -
|
| - WebCookieJar* cookie_jar = page_delegate_->GetCookieJar();
|
| - if (!cookie_jar) {
|
| - DLOG(WARNING) << "No cookie jar!";
|
| - return;
|
| - }
|
| -
|
| - cookie_jar->setCookie(
|
| - url, first_party_for_cookies, WebString::fromUTF8(cookie));
|
| -}
|
| -
|
| -std::string WebPluginImpl::GetCookies(const GURL& url,
|
| - const GURL& first_party_for_cookies) {
|
| - if (!page_delegate_)
|
| - return std::string();
|
| -
|
| - WebCookieJar* cookie_jar = page_delegate_->GetCookieJar();
|
| - if (!cookie_jar) {
|
| - DLOG(WARNING) << "No cookie jar!";
|
| - return std::string();
|
| - }
|
| -
|
| - return UTF16ToUTF8(cookie_jar->cookies(url, first_party_for_cookies));
|
| -}
|
| -
|
| -void WebPluginImpl::ShowModalHTMLDialog(const GURL& url, int width, int height,
|
| - const std::string& json_arguments,
|
| - std::string* json_retval) {
|
| - if (page_delegate_) {
|
| - page_delegate_->ShowModalHTMLDialogForPlugin(
|
| - url, gfx::Size(width, height), json_arguments, json_retval);
|
| - }
|
| -}
|
| -
|
| -void WebPluginImpl::OnMissingPluginStatus(int status) {
|
| - NOTREACHED();
|
| -}
|
| -
|
| -void WebPluginImpl::URLRedirectResponse(bool allow, int resource_id) {
|
| - for (size_t i = 0; i < clients_.size(); ++i) {
|
| - if (clients_[i].id == static_cast<unsigned long>(resource_id)) {
|
| - if (clients_[i].loader.get()) {
|
| - if (allow) {
|
| - clients_[i].loader->setDefersLoading(false);
|
| - } else {
|
| - clients_[i].loader->cancel();
|
| - clients_[i].client->DidFail();
|
| - }
|
| - }
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void WebPluginImpl::Invalidate() {
|
| - if (container_)
|
| - container_->invalidate();
|
| -}
|
| -
|
| -void WebPluginImpl::InvalidateRect(const gfx::Rect& rect) {
|
| - if (container_)
|
| - container_->invalidateRect(rect);
|
| -}
|
| -
|
| -void WebPluginImpl::OnDownloadPluginSrcUrl() {
|
| - HandleURLRequestInternal(
|
| - plugin_url_.spec().c_str(), "GET", NULL, NULL, 0, 0, false, DOCUMENT_URL,
|
| - false);
|
| -}
|
| -
|
| -WebPluginResourceClient* WebPluginImpl::GetClientFromLoader(
|
| - WebURLLoader* loader) {
|
| - ClientInfo* client_info = GetClientInfoFromLoader(loader);
|
| - if (client_info)
|
| - return client_info->client;
|
| - return NULL;
|
| -}
|
| -
|
| -WebPluginImpl::ClientInfo* WebPluginImpl::GetClientInfoFromLoader(
|
| - WebURLLoader* loader) {
|
| - for (size_t i = 0; i < clients_.size(); ++i) {
|
| - if (clients_[i].loader.get() == loader)
|
| - return &clients_[i];
|
| - }
|
| -
|
| - NOTREACHED();
|
| - return 0;
|
| -}
|
| -
|
| -void WebPluginImpl::willSendRequest(WebURLLoader* loader,
|
| - WebURLRequest& request,
|
| - const WebURLResponse& response) {
|
| - WebPluginImpl::ClientInfo* client_info = GetClientInfoFromLoader(loader);
|
| - if (client_info) {
|
| - if (net::HttpResponseHeaders::IsRedirectResponseCode(
|
| - response.httpStatusCode())) {
|
| - // If the plugin does not participate in url redirect notifications then
|
| - // just block cross origin 307 POST redirects.
|
| - if (!client_info->notify_redirects) {
|
| - if (response.httpStatusCode() == 307 &&
|
| - LowerCaseEqualsASCII(request.httpMethod().utf8(), "post")) {
|
| - GURL original_request_url(response.url());
|
| - GURL response_url(request.url());
|
| - if (original_request_url.GetOrigin() != response_url.GetOrigin()) {
|
| - loader->setDefersLoading(true);
|
| - loader->cancel();
|
| - client_info->client->DidFail();
|
| - return;
|
| - }
|
| - }
|
| - } else {
|
| - loader->setDefersLoading(true);
|
| - }
|
| - }
|
| - client_info->client->WillSendRequest(request.url(),
|
| - response.httpStatusCode());
|
| - }
|
| -}
|
| -
|
| -void WebPluginImpl::didSendData(WebURLLoader* loader,
|
| - unsigned long long bytes_sent,
|
| - unsigned long long total_bytes_to_be_sent) {
|
| -}
|
| -
|
| -void WebPluginImpl::didReceiveResponse(WebURLLoader* loader,
|
| - const WebURLResponse& response) {
|
| - static const int kHttpPartialResponseStatusCode = 206;
|
| - static const int kHttpResponseSuccessStatusCode = 200;
|
| -
|
| - WebPluginResourceClient* client = GetClientFromLoader(loader);
|
| - if (!client)
|
| - return;
|
| -
|
| - ResponseInfo response_info;
|
| - GetResponseInfo(response, &response_info);
|
| -
|
| - bool request_is_seekable = true;
|
| - if (client->IsMultiByteResponseExpected()) {
|
| - if (response.httpStatusCode() == kHttpPartialResponseStatusCode) {
|
| - HandleHttpMultipartResponse(response, client);
|
| - return;
|
| - } else if (response.httpStatusCode() == kHttpResponseSuccessStatusCode) {
|
| - // If the client issued a byte range request and the server responds with
|
| - // HTTP 200 OK, it indicates that the server does not support byte range
|
| - // requests.
|
| - // We need to emulate Firefox behavior by doing the following:-
|
| - // 1. Destroy the plugin instance in the plugin process. Ensure that
|
| - // existing resource requests initiated for the plugin instance
|
| - // continue to remain valid.
|
| - // 2. Create a new plugin instance and notify it about the response
|
| - // received here.
|
| - if (!ReinitializePluginForResponse(loader)) {
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| -
|
| - // The server does not support byte range requests. No point in creating
|
| - // seekable streams.
|
| - request_is_seekable = false;
|
| -
|
| - delete client;
|
| - client = NULL;
|
| -
|
| - // Create a new resource client for this request.
|
| - for (size_t i = 0; i < clients_.size(); ++i) {
|
| - if (clients_[i].loader.get() == loader) {
|
| - WebPluginResourceClient* resource_client =
|
| - delegate_->CreateResourceClient(clients_[i].id, plugin_url_, 0);
|
| - clients_[i].client = resource_client;
|
| - client = resource_client;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - DCHECK(client != NULL);
|
| - }
|
| - }
|
| -
|
| - // Calling into a plugin could result in reentrancy if the plugin yields
|
| - // control to the OS like entering a modal loop etc. Prevent this by
|
| - // stopping further loading until the plugin notifies us that it is ready to
|
| - // accept data
|
| - loader->setDefersLoading(true);
|
| -
|
| - client->DidReceiveResponse(
|
| - response_info.mime_type,
|
| - GetAllHeaders(response),
|
| - response_info.expected_length,
|
| - response_info.last_modified,
|
| - request_is_seekable);
|
| -
|
| - if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) {
|
| - ClientInfo* client_info = GetClientInfoFromLoader(loader);
|
| - if (client_info)
|
| - devtools_agent->didReceiveResponse(client_info->id, response);
|
| - }
|
| -
|
| - // Bug http://b/issue?id=925559. The flash plugin would not handle the HTTP
|
| - // error codes in the stream header and as a result, was unaware of the
|
| - // fate of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF
|
| - // destroy the stream and invoke the NPP_DestroyStream function on the
|
| - // plugin if the HTTP request fails.
|
| - const GURL& url = response.url();
|
| - if (url.SchemeIs("http") || url.SchemeIs("https")) {
|
| - if (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400) {
|
| - // The plugin instance could be in the process of deletion here.
|
| - // Verify if the WebPluginResourceClient instance still exists before
|
| - // use.
|
| - ClientInfo* client_info = GetClientInfoFromLoader(loader);
|
| - if (client_info) {
|
| - client_info->pending_failure_notification = true;
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void WebPluginImpl::didReceiveData(WebURLLoader* loader,
|
| - const char *buffer,
|
| - int length) {
|
| - WebPluginResourceClient* client = GetClientFromLoader(loader);
|
| - if (!client)
|
| - return;
|
| -
|
| - // ClientInfo can be removed from clients_ vector by next statements.
|
| - if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) {
|
| - ClientInfo* client_info = GetClientInfoFromLoader(loader);
|
| - if (client_info)
|
| - devtools_agent->didReceiveData(client_info->id, length);
|
| - }
|
| - MultiPartResponseHandlerMap::iterator index =
|
| - multi_part_response_map_.find(client);
|
| - if (index != multi_part_response_map_.end()) {
|
| - MultipartResponseDelegate* multi_part_handler = (*index).second;
|
| - DCHECK(multi_part_handler != NULL);
|
| - multi_part_handler->OnReceivedData(buffer, length);
|
| - } else {
|
| - loader->setDefersLoading(true);
|
| - client->DidReceiveData(buffer, length, 0);
|
| - }
|
| -}
|
| -
|
| -void WebPluginImpl::didFinishLoading(WebURLLoader* loader, double finishTime) {
|
| - ClientInfo* client_info = GetClientInfoFromLoader(loader);
|
| - if (client_info && client_info->client) {
|
| - MultiPartResponseHandlerMap::iterator index =
|
| - multi_part_response_map_.find(client_info->client);
|
| - if (index != multi_part_response_map_.end()) {
|
| - delete (*index).second;
|
| - multi_part_response_map_.erase(index);
|
| - if (page_delegate_)
|
| - page_delegate_->DidStopLoadingForPlugin();
|
| - }
|
| - loader->setDefersLoading(true);
|
| - WebPluginResourceClient* resource_client = client_info->client;
|
| - // The ClientInfo can get deleted in the call to DidFinishLoading below.
|
| - // It is not safe to access this structure after that.
|
| - client_info->client = NULL;
|
| - resource_client->DidFinishLoading();
|
| -
|
| - if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent())
|
| - devtools_agent->didFinishLoading(client_info->id);
|
| - }
|
| -}
|
| -
|
| -void WebPluginImpl::didFail(WebURLLoader* loader,
|
| - const WebURLError& error) {
|
| - ClientInfo* client_info = GetClientInfoFromLoader(loader);
|
| - if (client_info && client_info->client) {
|
| - loader->setDefersLoading(true);
|
| - WebPluginResourceClient* resource_client = client_info->client;
|
| - // The ClientInfo can get deleted in the call to DidFail below.
|
| - // It is not safe to access this structure after that.
|
| - client_info->client = NULL;
|
| - resource_client->DidFail();
|
| -
|
| - if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent())
|
| - devtools_agent->didFailLoading(client_info->id, error);
|
| - }
|
| -}
|
| -
|
| -void WebPluginImpl::RemoveClient(size_t i) {
|
| - clients_.erase(clients_.begin() + i);
|
| -}
|
| -
|
| -void WebPluginImpl::RemoveClient(WebURLLoader* loader) {
|
| - for (size_t i = 0; i < clients_.size(); ++i) {
|
| - if (clients_[i].loader.get() == loader) {
|
| - RemoveClient(i);
|
| - return;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void WebPluginImpl::SetContainer(WebPluginContainer* container) {
|
| - if (!container)
|
| - TearDownPluginInstance(NULL);
|
| - container_ = container;
|
| -}
|
| -
|
| -void WebPluginImpl::HandleURLRequest(const char* url,
|
| - const char* method,
|
| - const char* target,
|
| - const char* buf,
|
| - unsigned int len,
|
| - int notify_id,
|
| - bool popups_allowed,
|
| - bool notify_redirects) {
|
| - // GetURL/PostURL requests initiated explicitly by plugins should specify the
|
| - // plugin SRC url as the referrer if it is available.
|
| - HandleURLRequestInternal(
|
| - url, method, target, buf, len, notify_id, popups_allowed, PLUGIN_SRC,
|
| - notify_redirects);
|
| -}
|
| -
|
| -void WebPluginImpl::HandleURLRequestInternal(const char* url,
|
| - const char* method,
|
| - const char* target,
|
| - const char* buf,
|
| - unsigned int len,
|
| - int notify_id,
|
| - bool popups_allowed,
|
| - Referrer referrer_flag,
|
| - bool notify_redirects) {
|
| - // For this request, we either route the output to a frame
|
| - // because a target has been specified, or we handle the request
|
| - // here, i.e. by executing the script if it is a javascript url
|
| - // or by initiating a download on the URL, etc. There is one special
|
| - // case in that the request is a javascript url and the target is "_self",
|
| - // in which case we route the output to the plugin rather than routing it
|
| - // to the plugin's frame.
|
| - bool is_javascript_url = StartsWithASCII(url, "javascript:", false);
|
| - RoutingStatus routing_status = RouteToFrame(
|
| - url, is_javascript_url, method, target, buf, len, notify_id,
|
| - referrer_flag);
|
| - if (routing_status == ROUTED)
|
| - return;
|
| -
|
| - if (is_javascript_url) {
|
| - GURL gurl(url);
|
| - WebString result = container_->executeScriptURL(gurl, popups_allowed);
|
| -
|
| - // delegate_ could be NULL because executeScript caused the container to
|
| - // be deleted.
|
| - if (delegate_) {
|
| - delegate_->SendJavaScriptStream(
|
| - gurl, result.utf8(), !result.isNull(), notify_id);
|
| - }
|
| -
|
| - return;
|
| - }
|
| -
|
| - unsigned long resource_id = GetNextResourceId();
|
| - if (!resource_id)
|
| - return;
|
| -
|
| - GURL complete_url = CompleteURL(url);
|
| - // Remove when flash bug is fixed. http://crbug.com/40016.
|
| - if (!WebPluginImpl::IsValidUrl(complete_url, referrer_flag))
|
| - return;
|
| -
|
| - WebPluginResourceClient* resource_client = delegate_->CreateResourceClient(
|
| - resource_id, complete_url, notify_id);
|
| - if (!resource_client)
|
| - return;
|
| -
|
| - // If the RouteToFrame call returned a failure then inform the result
|
| - // back to the plugin asynchronously.
|
| - if ((routing_status == INVALID_URL) ||
|
| - (routing_status == GENERAL_FAILURE)) {
|
| - resource_client->DidFail();
|
| - return;
|
| - }
|
| -
|
| - // CreateResourceClient() sends a synchronous IPC message so it's possible
|
| - // that TearDownPluginInstance() may have been called in the nested
|
| - // message loop. If so, don't start the request.
|
| - if (!delegate_)
|
| - return;
|
| -
|
| - InitiateHTTPRequest(resource_id, resource_client, complete_url, method, buf,
|
| - len, NULL, referrer_flag, notify_redirects);
|
| -}
|
| -
|
| -unsigned long WebPluginImpl::GetNextResourceId() {
|
| - if (!webframe_)
|
| - return 0;
|
| - WebView* view = webframe_->view();
|
| - if (!view)
|
| - return 0;
|
| - return view->createUniqueIdentifierForRequest();
|
| -}
|
| -
|
| -bool WebPluginImpl::InitiateHTTPRequest(unsigned long resource_id,
|
| - WebPluginResourceClient* client,
|
| - const GURL& url,
|
| - const char* method,
|
| - const char* buf,
|
| - int buf_len,
|
| - const char* range_info,
|
| - Referrer referrer_flag,
|
| - bool notify_redirects) {
|
| - if (!client) {
|
| - NOTREACHED();
|
| - return false;
|
| - }
|
| -
|
| - ClientInfo info;
|
| - info.id = resource_id;
|
| - info.client = client;
|
| - info.request.initialize();
|
| - info.request.setURL(url);
|
| - info.request.setFirstPartyForCookies(
|
| - webframe_->document().firstPartyForCookies());
|
| - info.request.setRequestorProcessID(delegate_->GetProcessId());
|
| - info.request.setTargetType(WebURLRequest::TargetIsObject);
|
| - info.request.setHTTPMethod(WebString::fromUTF8(method));
|
| - info.pending_failure_notification = false;
|
| - info.notify_redirects = notify_redirects;
|
| -
|
| - if (range_info) {
|
| - info.request.addHTTPHeaderField(WebString::fromUTF8("Range"),
|
| - WebString::fromUTF8(range_info));
|
| - }
|
| -
|
| - if (strcmp(method, "POST") == 0) {
|
| - // Adds headers or form data to a request. This must be called before
|
| - // we initiate the actual request.
|
| - SetPostData(&info.request, buf, buf_len);
|
| - }
|
| -
|
| - SetReferrer(&info.request, referrer_flag);
|
| -
|
| - // Sets the routing id to associate the ResourceRequest with the RenderView.
|
| - webframe_->dispatchWillSendRequest(info.request);
|
| -
|
| - // Sets the appcache host id to allow retrieval from the appcache.
|
| - if (WebApplicationCacheHostImpl* appcache_host =
|
| - WebApplicationCacheHostImpl::FromFrame(webframe_)) {
|
| - appcache_host->willStartSubResourceRequest(info.request);
|
| - }
|
| -
|
| - if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent()) {
|
| - devtools_agent->identifierForInitialRequest(resource_id, webframe_,
|
| - info.request);
|
| - devtools_agent->willSendRequest(resource_id, info.request);
|
| - }
|
| -
|
| - info.loader.reset(WebKit::webKitClient()->createURLLoader());
|
| - if (!info.loader.get())
|
| - return false;
|
| - info.loader->loadAsynchronously(info.request, this);
|
| -
|
| - clients_.push_back(info);
|
| - return true;
|
| -}
|
| -
|
| -void WebPluginImpl::CancelDocumentLoad() {
|
| - if (webframe_) {
|
| - ignore_response_error_ = true;
|
| - webframe_->stopLoading();
|
| - }
|
| -}
|
| -
|
| -void WebPluginImpl::InitiateHTTPRangeRequest(
|
| - const char* url, const char* range_info, int range_request_id) {
|
| - unsigned long resource_id = GetNextResourceId();
|
| - if (!resource_id)
|
| - return;
|
| -
|
| - GURL complete_url = CompleteURL(url);
|
| - // Remove when flash bug is fixed. http://crbug.com/40016.
|
| - if (!WebPluginImpl::IsValidUrl(complete_url,
|
| - load_manually_ ? NO_REFERRER : PLUGIN_SRC))
|
| - return;
|
| -
|
| - WebPluginResourceClient* resource_client =
|
| - delegate_->CreateSeekableResourceClient(resource_id, range_request_id);
|
| - InitiateHTTPRequest(
|
| - resource_id, resource_client, complete_url, "GET", NULL, 0, range_info,
|
| - load_manually_ ? NO_REFERRER : PLUGIN_SRC, false);
|
| -}
|
| -
|
| -void WebPluginImpl::SetDeferResourceLoading(unsigned long resource_id,
|
| - bool defer) {
|
| - std::vector<ClientInfo>::iterator client_index = clients_.begin();
|
| - while (client_index != clients_.end()) {
|
| - ClientInfo& client_info = *client_index;
|
| -
|
| - if (client_info.id == resource_id) {
|
| - client_info.loader->setDefersLoading(defer);
|
| -
|
| - // If we determined that the request had failed via the HTTP headers
|
| - // in the response then we send out a failure notification to the
|
| - // plugin process, as certain plugins don't handle HTTP failure codes
|
| - // correctly.
|
| - if (!defer && client_info.client &&
|
| - client_info.pending_failure_notification) {
|
| - // The ClientInfo and the iterator can become invalid due to the call
|
| - // to DidFail below.
|
| - WebPluginResourceClient* resource_client = client_info.client;
|
| - client_info.loader->cancel();
|
| - clients_.erase(client_index++);
|
| - resource_client->DidFail();
|
| -
|
| - // Report that resource loading finished.
|
| - if (WebDevToolsAgent* devtools_agent = GetDevToolsAgent())
|
| - devtools_agent->didFinishLoading(resource_id);
|
| - }
|
| - break;
|
| - }
|
| - client_index++;
|
| - }
|
| -}
|
| -
|
| -bool WebPluginImpl::IsOffTheRecord() {
|
| - return false;
|
| -}
|
| -
|
| -void WebPluginImpl::HandleHttpMultipartResponse(
|
| - const WebURLResponse& response, WebPluginResourceClient* client) {
|
| - std::string multipart_boundary;
|
| - if (!MultipartResponseDelegate::ReadMultipartBoundary(
|
| - response, &multipart_boundary)) {
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| -
|
| - if (page_delegate_)
|
| - page_delegate_->DidStartLoadingForPlugin();
|
| -
|
| - MultiPartResponseClient* multi_part_response_client =
|
| - new MultiPartResponseClient(client);
|
| -
|
| - MultipartResponseDelegate* multi_part_response_handler =
|
| - new MultipartResponseDelegate(multi_part_response_client, NULL,
|
| - response,
|
| - multipart_boundary);
|
| - multi_part_response_map_[client] = multi_part_response_handler;
|
| -}
|
| -
|
| -bool WebPluginImpl::ReinitializePluginForResponse(
|
| - WebURLLoader* loader) {
|
| - WebFrame* webframe = webframe_;
|
| - if (!webframe)
|
| - return false;
|
| -
|
| - WebView* webview = webframe->view();
|
| - if (!webview)
|
| - return false;
|
| -
|
| - WebPluginContainer* container_widget = container_;
|
| -
|
| - // Destroy the current plugin instance.
|
| - TearDownPluginInstance(loader);
|
| -
|
| - container_ = container_widget;
|
| - webframe_ = webframe;
|
| -
|
| - WebPluginDelegate* plugin_delegate = page_delegate_->CreatePluginDelegate(
|
| - file_path_, mime_type_);
|
| -
|
| - bool ok = plugin_delegate && plugin_delegate->Initialize(
|
| - plugin_url_, arg_names_, arg_values_, this, load_manually_);
|
| -
|
| - if (!ok) {
|
| - container_ = NULL;
|
| - // TODO(iyengar) Should we delete the current plugin instance here?
|
| - return false;
|
| - }
|
| -
|
| - delegate_ = plugin_delegate;
|
| -
|
| - // Force a geometry update to occur to ensure that the plugin becomes
|
| - // visible.
|
| - container_->reportGeometry();
|
| -
|
| - // The plugin move sequences accumulated via DidMove are sent to the browser
|
| - // whenever the renderer paints. Force a paint here to ensure that changes
|
| - // to the plugin window are propagated to the browser.
|
| - container_->invalidate();
|
| - return true;
|
| -}
|
| -
|
| -void WebPluginImpl::TearDownPluginInstance(
|
| - WebURLLoader* loader_to_ignore) {
|
| - // The container maintains a list of JSObjects which are related to this
|
| - // plugin. Tell the frame we're gone so that it can invalidate all of
|
| - // those sub JSObjects.
|
| - if (container_)
|
| - container_->clearScriptObjects();
|
| -
|
| - if (delegate_) {
|
| - // Call PluginDestroyed() first to prevent the plugin from calling us back
|
| - // in the middle of tearing down the render tree.
|
| - delegate_->PluginDestroyed();
|
| - delegate_ = NULL;
|
| - }
|
| -
|
| - // Cancel any pending requests because otherwise this deleted object will
|
| - // be called by the ResourceDispatcher.
|
| - std::vector<ClientInfo>::iterator client_index = clients_.begin();
|
| - while (client_index != clients_.end()) {
|
| - ClientInfo& client_info = *client_index;
|
| -
|
| - if (loader_to_ignore == client_info.loader) {
|
| - client_index++;
|
| - continue;
|
| - }
|
| -
|
| - if (client_info.loader.get())
|
| - client_info.loader->cancel();
|
| -
|
| - client_index = clients_.erase(client_index);
|
| - }
|
| -
|
| - // This needs to be called now and not in the destructor since the
|
| - // webframe_ might not be valid anymore.
|
| - webframe_ = NULL;
|
| - method_factory_.RevokeAll();
|
| -}
|
| -
|
| -void WebPluginImpl::SetReferrer(WebKit::WebURLRequest* request,
|
| - Referrer referrer_flag) {
|
| - switch (referrer_flag) {
|
| - case DOCUMENT_URL:
|
| - webframe_->setReferrerForRequest(*request, GURL());
|
| - break;
|
| -
|
| - case PLUGIN_SRC:
|
| - webframe_->setReferrerForRequest(*request, plugin_url_);
|
| - break;
|
| -
|
| - default:
|
| - break;
|
| - }
|
| -}
|
| -
|
| -WebDevToolsAgent* WebPluginImpl::GetDevToolsAgent() {
|
| - if (!webframe_)
|
| - return NULL;
|
| - WebView* view = webframe_->view();
|
| - if (!view)
|
| - return NULL;
|
| - return view->devToolsAgent();
|
| -}
|
| -
|
| -} // namespace webkit_glue
|
|
|