summaryrefslogtreecommitdiffstats
path: root/webkit/glue
diff options
context:
space:
mode:
authorananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-23 00:34:27 +0000
committerananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-23 00:34:27 +0000
commit65e82a56b3f1ca882db8c53f07781ecdc6cb7ece (patch)
treee224abcb3aa50320f55bf7a35bbf2e72ee0e0270 /webkit/glue
parent52426e4c3b775666fa9fd52e1c52f8dbbbaadd49 (diff)
downloadchromium_src-65e82a56b3f1ca882db8c53f07781ecdc6cb7ece.zip
chromium_src-65e82a56b3f1ca882db8c53f07781ecdc6cb7ece.tar.gz
chromium_src-65e82a56b3f1ca882db8c53f07781ecdc6cb7ece.tar.bz2
Implement NPAPI HTTP Redirect handling. This basically supports the NPAPI URL redirect
notifications which are sent out from the browser while processing URL requests issued by the plugin via the NPN_GetURLNotify and NPN_PostURLNotify APIs. For more info please see https://wiki.mozilla.org/NPAPI:HTTPRedirectHandling As part of this CL we also block cross origin 307 POST url redirects. Test=Covered by NPAPI UI test GetURLRedirectNotification Bug=63030,63698 Review URL: http://codereview.chromium.org/5228007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67029 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue')
-rw-r--r--webkit/glue/plugins/plugin_host.cc8
-rw-r--r--webkit/glue/plugins/plugin_instance.cc39
-rw-r--r--webkit/glue/plugins/plugin_instance.h11
-rw-r--r--webkit/glue/plugins/plugin_stream.h7
-rw-r--r--webkit/glue/plugins/plugin_stream_url.cc14
-rw-r--r--webkit/glue/plugins/plugin_stream_url.h6
-rw-r--r--webkit/glue/plugins/plugin_stream_win.cc1
-rw-r--r--webkit/glue/plugins/test/plugin_client.cc46
-rw-r--r--webkit/glue/plugins/test/plugin_geturl_test.cc40
-rw-r--r--webkit/glue/plugins/test/plugin_geturl_test.h6
-rw-r--r--webkit/glue/plugins/test/plugin_test.cc5
-rw-r--r--webkit/glue/plugins/test/plugin_test.h2
-rw-r--r--webkit/glue/plugins/test/plugin_test_factory.cc3
-rw-r--r--webkit/glue/plugins/webplugin.h10
-rw-r--r--webkit/glue/plugins/webplugin_impl.cc68
-rw-r--r--webkit/glue/plugins/webplugin_impl.h13
16 files changed, 236 insertions, 43 deletions
diff --git a/webkit/glue/plugins/plugin_host.cc b/webkit/glue/plugins/plugin_host.cc
index 4cee55d..27caf6c 100644
--- a/webkit/glue/plugins/plugin_host.cc
+++ b/webkit/glue/plugins/plugin_host.cc
@@ -137,7 +137,7 @@ void PluginHost::InitializeHostFuncs() {
host_funcs_.handleevent = NPN_HandleEvent;
host_funcs_.unfocusinstance = NPN_UnfocusInstance;
// TODO: Implement redirect handling: http://crbug.com/63030
- host_funcs_.urlredirectresponse = NULL;
+ host_funcs_.urlredirectresponse = NPN_URLRedirectResponse;
}
void PluginHost::PatchNPNetscapeFuncs(NPNetscapeFuncs* overrides) {
@@ -1102,5 +1102,11 @@ NPBool NPN_UnfocusInstance(NPP id, NPFocusDirection direction) {
return false;
}
+void NPN_URLRedirectResponse(NPP instance, void* notify_data, NPBool allow) {
+ scoped_refptr<NPAPI::PluginInstance> plugin(FindInstance(instance));
+ if (plugin.get()) {
+ plugin->URLRedirectResponse(!!allow, notify_data);
+ }
+}
} // extern "C"
diff --git a/webkit/glue/plugins/plugin_instance.cc b/webkit/glue/plugins/plugin_instance.cc
index 65ae0b6..4ccbadf 100644
--- a/webkit/glue/plugins/plugin_instance.cc
+++ b/webkit/glue/plugins/plugin_instance.cc
@@ -54,7 +54,8 @@ PluginInstance::PluginInstance(PluginLib *plugin, const std::string &mime_type)
in_close_streams_(false),
next_timer_id_(1),
next_notify_id_(0),
- next_range_request_id_(0) {
+ next_range_request_id_(0),
+ handles_url_redirects_(false) {
npp_ = new NPP_t();
npp_->ndata = 0;
npp_->pdata = 0;
@@ -153,6 +154,12 @@ bool PluginInstance::Start(const GURL& url,
NPError err = NPP_New(mode, param_count,
const_cast<char **>(param_names), const_cast<char **>(param_values));
+
+ if (err == NPERR_NO_ERROR) {
+ handles_url_redirects_ =
+ ((npp_functions_->version >= NPVERS_HAS_URL_REDIRECT_HANDLING) &&
+ (npp_functions_->urlredirectnotify));
+ }
return err == NPERR_NO_ERROR;
}
@@ -350,6 +357,14 @@ NPError PluginInstance::NPP_ClearSiteData(uint64 flags,
return NPERR_NO_ERROR;
}
+void PluginInstance::NPP_URLRedirectNotify(const char* url, int32_t status,
+ void* notify_data) {
+ DCHECK(npp_functions_ != 0);
+ if (npp_functions_->urlredirectnotify != 0) {
+ npp_functions_->urlredirectnotify(npp_, url, status, notify_data);
+ }
+}
+
void PluginInstance::SendJavaScriptStream(const GURL& url,
const std::string& result,
bool success,
@@ -556,7 +571,8 @@ void PluginInstance::RequestURL(const char* url,
}
webplugin_->HandleURLRequest(
- url, method, target, buf, len, notify_id, popups_allowed());
+ url, method, target, buf, len, notify_id, popups_allowed(),
+ notify ? handles_url_redirects_ : false);
}
bool PluginInstance::ConvertPoint(double source_x, double source_y,
@@ -642,4 +658,23 @@ void PluginInstance::GetNotifyData(
}
}
+void PluginInstance::URLRedirectResponse(bool allow, void* notify_data) {
+ // The notify_data passed in allows us to identify the matching stream.
+ std::vector<scoped_refptr<PluginStream> >::iterator stream_index;
+ for (stream_index = open_streams_.begin();
+ stream_index != open_streams_.end(); ++stream_index) {
+ PluginStream* plugin_stream = *stream_index;
+ if (plugin_stream->notify_data() == notify_data) {
+ webkit_glue::WebPluginResourceClient* resource_client =
+ plugin_stream->AsResourceClient();
+ webplugin_->URLRedirectResponse(allow, resource_client->ResourceId());
+ if (allow) {
+ plugin_stream->UpdateUrl(
+ plugin_stream->pending_redirect_url().c_str());
+ }
+ break;
+ }
+ }
+}
+
} // namespace NPAPI
diff --git a/webkit/glue/plugins/plugin_instance.h b/webkit/glue/plugins/plugin_instance.h
index 3d4d8b0..fa0320e 100644
--- a/webkit/glue/plugins/plugin_instance.h
+++ b/webkit/glue/plugins/plugin_instance.h
@@ -199,6 +199,8 @@ class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> {
void NPP_Destroy();
bool NPP_Print(NPPrint* platform_print);
NPError NPP_ClearSiteData(uint64, const char*, uint64);
+ void NPP_URLRedirectNotify(const char* url, int32_t status,
+ void* notify_data);
void SendJavaScriptStream(const GURL& url,
const std::string& result,
@@ -234,6 +236,12 @@ class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> {
bool notify,
void* notify_data);
+ // Handles NPN_URLRedirectResponse calls issued by plugins in response to
+ // HTTP URL redirect notifications.
+ void URLRedirectResponse(bool allow, void* notify_data);
+
+ bool handles_url_redirects() const { return handles_url_redirects_; }
+
private:
friend class base::RefCountedThreadSafe<PluginInstance>;
@@ -336,6 +344,9 @@ class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> {
typedef std::map<int, scoped_refptr<PluginStream> > PendingRangeRequestMap;
PendingRangeRequestMap pending_range_requests_;
int next_range_request_id_;
+ // The plugin handles the NPAPI URL redirect notification API.
+ // See here https://wiki.mozilla.org/NPAPI:HTTPRedirectHandling
+ bool handles_url_redirects_;
DISALLOW_COPY_AND_ASSIGN(PluginInstance);
};
diff --git a/webkit/glue/plugins/plugin_stream.h b/webkit/glue/plugins/plugin_stream.h
index c17faaf..b277465 100644
--- a/webkit/glue/plugins/plugin_stream.h
+++ b/webkit/glue/plugins/plugin_stream.h
@@ -83,6 +83,8 @@ class PluginStream : public base::RefCounted<PluginStream> {
void* notify_data() const { return notify_data_; }
+ std::string pending_redirect_url() const { return pending_redirect_url_; }
+
protected:
friend class base::RefCounted<PluginStream>;
@@ -92,6 +94,11 @@ class PluginStream : public base::RefCounted<PluginStream> {
// Check if the stream is open.
bool open() { return opened_; }
+ // If the plugin participates in HTTP URL redirect handling then this member
+ // holds the url being redirected to while we wait for the plugin to make a
+ // decision on whether to allow or deny the redirect.
+ std::string pending_redirect_url_;
+
private:
// Open a temporary file for this stream.
diff --git a/webkit/glue/plugins/plugin_stream_url.cc b/webkit/glue/plugins/plugin_stream_url.cc
index 6694139..1af4485 100644
--- a/webkit/glue/plugins/plugin_stream_url.cc
+++ b/webkit/glue/plugins/plugin_stream_url.cc
@@ -4,8 +4,10 @@
#include "webkit/glue/plugins/plugin_stream_url.h"
+#include "net/http/http_response_headers.h"
#include "webkit/glue/plugins/plugin_host.h"
#include "webkit/glue/plugins/plugin_instance.h"
+#include "webkit/glue/plugins/plugin_lib.h"
#include "webkit/glue/plugins/webplugin.h"
namespace NPAPI {
@@ -37,7 +39,17 @@ bool PluginStreamUrl::Close(NPReason reason) {
return result;
}
-void PluginStreamUrl::WillSendRequest(const GURL& url) {
+void PluginStreamUrl::WillSendRequest(const GURL& url, int http_status_code) {
+ if (notify_needed()) {
+ // If the plugin participates in HTTP url redirect handling then notify it.
+ if (net::HttpResponseHeaders::IsRedirectResponseCode(http_status_code) &&
+ instance()->handles_url_redirects()) {
+ pending_redirect_url_ = url.spec();
+ instance()->NPP_URLRedirectNotify(url.spec().c_str(), http_status_code,
+ notify_data());
+ return;
+ }
+ }
url_ = url;
UpdateUrl(url.spec().c_str());
}
diff --git a/webkit/glue/plugins/plugin_stream_url.h b/webkit/glue/plugins/plugin_stream_url.h
index 01a6da9..8c03edc 100644
--- a/webkit/glue/plugins/plugin_stream_url.h
+++ b/webkit/glue/plugins/plugin_stream_url.h
@@ -43,7 +43,7 @@ class PluginStreamUrl : public PluginStream,
//
// WebPluginResourceClient methods
//
- void WillSendRequest(const GURL& url);
+ void WillSendRequest(const GURL& url, int http_status_code);
void DidReceiveResponse(const std::string& mime_type,
const std::string& headers,
uint32 expected_length,
@@ -55,7 +55,9 @@ class PluginStreamUrl : public PluginStream,
bool IsMultiByteResponseExpected() {
return seekable();
}
-
+ int ResourceId() {
+ return id_;
+ }
private:
GURL url_;
diff --git a/webkit/glue/plugins/plugin_stream_win.cc b/webkit/glue/plugins/plugin_stream_win.cc
index fffa6fe..0b6fcbd 100644
--- a/webkit/glue/plugins/plugin_stream_win.cc
+++ b/webkit/glue/plugins/plugin_stream_win.cc
@@ -32,6 +32,7 @@ void PluginStream::UpdateUrl(const char* url) {
DCHECK(!opened_);
free(const_cast<char*>(stream_.url));
stream_.url = _strdup(url);
+ pending_redirect_url_.clear();
}
void PluginStream::WriteAsFile() {
diff --git a/webkit/glue/plugins/test/plugin_client.cc b/webkit/glue/plugins/test/plugin_client.cc
index d617e16..8358340 100644
--- a/webkit/glue/plugins/test/plugin_client.cc
+++ b/webkit/glue/plugins/test/plugin_client.cc
@@ -34,6 +34,7 @@ NPError PluginClient::GetEntryPoints(NPPluginFuncs* pFuncs) {
pFuncs->getvalue = NPP_GetValue;
pFuncs->setvalue = NPP_SetValue;
pFuncs->javaClass = NULL;
+ pFuncs->urlredirectnotify = NPP_URLRedirectNotify;
return NPERR_NO_ERROR;
}
@@ -114,8 +115,8 @@ NPError NPP_Destroy(NPP instance, NPSavedData** save) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
- NPAPIClient::PluginTest *plugin =
- (NPAPIClient::PluginTest*)instance->pdata;
+ NPAPIClient::PluginTest* plugin =
+ reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
NPError rv = plugin->Destroy();
delete plugin;
@@ -126,8 +127,8 @@ NPError NPP_SetWindow(NPP instance, NPWindow* pNPWindow) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
- NPAPIClient::PluginTest *plugin =
- (NPAPIClient::PluginTest*)instance->pdata;
+ NPAPIClient::PluginTest* plugin =
+ reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->SetWindow(pNPWindow);
}
@@ -137,8 +138,8 @@ NPError NPP_NewStream(NPP instance, NPMIMEType type,
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
- NPAPIClient::PluginTest *plugin =
- (NPAPIClient::PluginTest*)instance->pdata;
+ NPAPIClient::PluginTest* plugin =
+ reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->NewStream(type, stream, seekable, stype);
}
@@ -147,8 +148,8 @@ int32 NPP_WriteReady(NPP instance, NPStream *stream) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
- NPAPIClient::PluginTest *plugin =
- (NPAPIClient::PluginTest*)instance->pdata;
+ NPAPIClient::PluginTest* plugin =
+ reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->WriteReady(stream);
}
@@ -158,8 +159,8 @@ int32 NPP_Write(NPP instance, NPStream *stream, int32 offset,
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
- NPAPIClient::PluginTest *plugin =
- (NPAPIClient::PluginTest*)instance->pdata;
+ NPAPIClient::PluginTest* plugin =
+ reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->Write(stream, offset, len, buffer);
}
@@ -168,8 +169,8 @@ NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
- NPAPIClient::PluginTest *plugin =
- (NPAPIClient::PluginTest*)instance->pdata;
+ NPAPIClient::PluginTest* plugin =
+ reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->DestroyStream(stream, reason);
}
@@ -178,8 +179,8 @@ void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) {
if (instance == NULL)
return;
- NPAPIClient::PluginTest *plugin =
- (NPAPIClient::PluginTest*)instance->pdata;
+ NPAPIClient::PluginTest* plugin =
+ reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->StreamAsFile(stream, fname);
}
@@ -196,8 +197,8 @@ void NPP_URLNotify(NPP instance, const char* url, NPReason reason,
if (instance == NULL)
return;
- NPAPIClient::PluginTest *plugin =
- (NPAPIClient::PluginTest*)instance->pdata;
+ NPAPIClient::PluginTest* plugin =
+ reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->URLNotify(url, reason, notifyData);
}
@@ -222,9 +223,18 @@ int16 NPP_HandleEvent(NPP instance, void* event) {
if (instance == NULL)
return 0;
- NPAPIClient::PluginTest *plugin =
- (NPAPIClient::PluginTest*)instance->pdata;
+ NPAPIClient::PluginTest* plugin =
+ reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->HandleEvent(event);
}
+
+void NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status,
+ void* notify_data) {
+ if (instance) {
+ NPAPIClient::PluginTest* plugin =
+ reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
+ plugin->URLRedirectNotify(url, status, notify_data);
+ }
+}
} // extern "C"
diff --git a/webkit/glue/plugins/test/plugin_geturl_test.cc b/webkit/glue/plugins/test/plugin_geturl_test.cc
index aedf582..5363a66 100644
--- a/webkit/glue/plugins/test/plugin_geturl_test.cc
+++ b/webkit/glue/plugins/test/plugin_geturl_test.cc
@@ -24,6 +24,13 @@
// url for testing GetURL with a bogus URL.
#define BOGUS_URL "bogoproto:///x:/asdf.xysdhffieasdf.asdhj/"
+// url for testing redirect notifications sent to plugins.
+#define REDIRECT_SRC_URL \
+ "http://mock.http/npapi/plugin_read_page_redirect_src.html"
+
+// The notification id for the redirect notification url.
+#define REDIRECT_SRC_URL_NOTIFICATION_ID 4
+
// The identifier for the bogus url stream.
#define BOGUS_URL_STREAM_ID 3
@@ -38,7 +45,9 @@ PluginGetURLTest::PluginGetURLTest(NPP id, NPNetscapeFuncs *host_functions)
tests_in_progress_(0),
test_file_(NULL),
expect_404_response_(false),
- npn_evaluate_context_(false) {
+ npn_evaluate_context_(false),
+ handle_url_redirects_(false),
+ received_url_redirect_notification_(false) {
}
NPError PluginGetURLTest::New(uint16 mode, int16 argc, const char* argn[],
@@ -62,6 +71,10 @@ NPError PluginGetURLTest::New(uint16 mode, int16 argc, const char* argn[],
referrer_target_url_ = referrer_target_url;
}
+ if (!base::strcasecmp(GetArgValue("name", argc, argn, argv),
+ "geturlredirectnotify")) {
+ handle_url_redirects_ = true;
+ }
return PluginTest::New(mode, argc, argn, argv, saved);
}
@@ -85,6 +98,11 @@ NPError PluginGetURLTest::SetWindow(NPWindow* pNPWindow) {
HostFunctions()->geturl(id(), referrer_target_url_.c_str(), "_blank");
HostFunctions()->poppopupsenabledstate(id());
return NPERR_NO_ERROR;
+ } else if (handle_url_redirects_) {
+ HostFunctions()->geturlnotify(
+ id(), REDIRECT_SRC_URL, NULL,
+ reinterpret_cast<void*>(REDIRECT_SRC_URL_NOTIFICATION_ID));
+ return NPERR_NO_ERROR;
}
std::string url = SELF_URL;
@@ -179,6 +197,9 @@ NPError PluginGetURLTest::NewStream(NPMIMEType type, NPStream* stream,
case BOGUS_URL_STREAM_ID:
SetError("Unexpected NewStream for BOGUS_URL");
break;
+ case REDIRECT_SRC_URL_NOTIFICATION_ID:
+ SetError("Should not redirect to URL when plugin denied it.");
+ break;
default:
SetError("Unexpected NewStream callback");
break;
@@ -364,6 +385,13 @@ void PluginGetURLTest::URLNotify(const char* url, NPReason reason, void* data) {
}
tests_in_progress_--;
break;
+ case REDIRECT_SRC_URL_NOTIFICATION_ID: {
+ if (!received_url_redirect_notification_) {
+ SetError("Failed to receive URLRedirect notification");
+ }
+ tests_in_progress_--;
+ break;
+ }
default:
SetError("Unexpected NewStream callback");
break;
@@ -373,4 +401,14 @@ void PluginGetURLTest::URLNotify(const char* url, NPReason reason, void* data) {
SignalTestCompleted();
}
+void PluginGetURLTest::URLRedirectNotify(const char* url,
+ int32_t status,
+ void* notify_data) {
+ if (!base::strcasecmp(url, "http://mock.http/npapi/plugin_read_page.html")) {
+ received_url_redirect_notification_ = true;
+ // Disallow redirect notification.
+ HostFunctions()->urlredirectresponse(id(), notify_data, false);
+ }
+}
+
} // namespace NPAPIClient
diff --git a/webkit/glue/plugins/test/plugin_geturl_test.h b/webkit/glue/plugins/test/plugin_geturl_test.h
index 9d5b826..df8d741 100644
--- a/webkit/glue/plugins/test/plugin_geturl_test.h
+++ b/webkit/glue/plugins/test/plugin_geturl_test.h
@@ -36,6 +36,8 @@ class PluginGetURLTest : public PluginTest {
virtual NPError DestroyStream(NPStream *stream, NPError reason);
virtual void StreamAsFile(NPStream* stream, const char* fname);
virtual void URLNotify(const char* url, NPReason reason, void* data);
+ virtual void URLRedirectNotify(const char* url, int32_t status,
+ void* notify_data);
private:
bool tests_started_;
@@ -45,6 +47,10 @@ class PluginGetURLTest : public PluginTest {
bool expect_404_response_;
// This flag is set to true in the context of the NPN_Evaluate call.
bool npn_evaluate_context_;
+ // The following two flags handle URL redirect notifications received by
+ // plugins.
+ bool handle_url_redirects_;
+ bool received_url_redirect_notification_;
std::string page_not_found_url_;
std::string fail_write_url_;
std::string referrer_target_url_;
diff --git a/webkit/glue/plugins/test/plugin_test.cc b/webkit/glue/plugins/test/plugin_test.cc
index 141c91a..6717e4b 100644
--- a/webkit/glue/plugins/test/plugin_test.cc
+++ b/webkit/glue/plugins/test/plugin_test.cc
@@ -147,4 +147,9 @@ int16 PluginTest::HandleEvent(void* event) {
return 0;
}
+void PluginTest::URLRedirectNotify(const char* url, int32_t status,
+ void* notify_data) {
+ // There is no default action
+}
+
} // namespace NPAPIClient
diff --git a/webkit/glue/plugins/test/plugin_test.h b/webkit/glue/plugins/test/plugin_test.h
index eed6e3f..f3f8937 100644
--- a/webkit/glue/plugins/test/plugin_test.h
+++ b/webkit/glue/plugins/test/plugin_test.h
@@ -43,6 +43,8 @@ class PluginTest {
virtual void StreamAsFile(NPStream* stream, const char* fname);
virtual void URLNotify(const char* url, NPReason reason, void* data);
virtual int16 HandleEvent(void* event);
+ virtual void URLRedirectNotify(const char* url, int32_t status,
+ void* notify_data);
// Returns true if the test has not had any errors.
bool Succeeded() { return test_status_.length() == 0; }
diff --git a/webkit/glue/plugins/test/plugin_test_factory.cc b/webkit/glue/plugins/test/plugin_test_factory.cc
index ea9b290..b4ae4f1 100644
--- a/webkit/glue/plugins/test/plugin_test_factory.cc
+++ b/webkit/glue/plugins/test/plugin_test_factory.cc
@@ -34,7 +34,8 @@ PluginTest* CreatePluginTest(const std::string& test_name,
new_test = new PluginArgumentsTest(instance, host_functions);
} else if (test_name == "geturl" || test_name == "geturl_404_response" ||
test_name == "geturl_fail_write" ||
- test_name == "plugin_referrer_test") {
+ test_name == "plugin_referrer_test" ||
+ test_name == "geturlredirectnotify") {
new_test = new PluginGetURLTest(instance, host_functions);
} else if (test_name == "npobject_proxy") {
new_test = new NPObjectProxyTest(instance, host_functions);
diff --git a/webkit/glue/plugins/webplugin.h b/webkit/glue/plugins/webplugin.h
index 36426fa..5fbef1f 100644
--- a/webkit/glue/plugins/webplugin.h
+++ b/webkit/glue/plugins/webplugin.h
@@ -126,7 +126,8 @@ class WebPlugin {
const char* buf,
unsigned int len,
int notify_id,
- bool popups_allowed) = 0;
+ bool popups_allowed,
+ bool notify_redirects) = 0;
// Cancels document load.
virtual void CancelDocumentLoad() = 0;
@@ -168,13 +169,17 @@ class WebPlugin {
// This API is only for use with Pepper, and is only overridden
// by in-renderer implementations.
virtual WebPluginDelegate* delegate() { return NULL; }
+
+ // Handles NPN_URLRedirectResponse calls issued by plugins in response to
+ // HTTP URL redirect notifications.
+ virtual void URLRedirectResponse(bool allow, int resource_id) = 0;
};
// Simpler version of ResourceHandleClient that lends itself to proxying.
class WebPluginResourceClient {
public:
virtual ~WebPluginResourceClient() {}
- virtual void WillSendRequest(const GURL& url) = 0;
+ virtual void WillSendRequest(const GURL& url, int http_status_code) = 0;
// The request_is_seekable parameter indicates whether byte range requests
// can be issued for the underlying stream.
virtual void DidReceiveResponse(const std::string& mime_type,
@@ -187,6 +192,7 @@ class WebPluginResourceClient {
virtual void DidFinishLoading() = 0;
virtual void DidFail() = 0;
virtual bool IsMultiByteResponseExpected() = 0;
+ virtual int ResourceId() = 0;
};
} // namespace webkit_glue
diff --git a/webkit/glue/plugins/webplugin_impl.cc b/webkit/glue/plugins/webplugin_impl.cc
index 80774ff..cd91744 100644
--- a/webkit/glue/plugins/webplugin_impl.cc
+++ b/webkit/glue/plugins/webplugin_impl.cc
@@ -14,6 +14,7 @@
#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"
@@ -216,6 +217,7 @@ struct WebPluginImpl::ClientInfo {
WebKit::WebURLRequest request;
bool pending_failure_notification;
linked_ptr<WebKit::WebURLLoader> loader;
+ bool notify_redirects;
};
bool WebPluginImpl::initialize(WebPluginContainer* container) {
@@ -770,6 +772,22 @@ 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();
@@ -782,7 +800,8 @@ void WebPluginImpl::InvalidateRect(const gfx::Rect& rect) {
void WebPluginImpl::OnDownloadPluginSrcUrl() {
HandleURLRequestInternal(
- plugin_url_.spec().c_str(), "GET", NULL, NULL, 0, 0, false, DOCUMENT_URL);
+ plugin_url_.spec().c_str(), "GET", NULL, NULL, 0, 0, false, DOCUMENT_URL,
+ false);
}
WebPluginResourceClient* WebPluginImpl::GetClientFromLoader(
@@ -806,10 +825,32 @@ WebPluginImpl::ClientInfo* WebPluginImpl::GetClientInfoFromLoader(
void WebPluginImpl::willSendRequest(WebURLLoader* loader,
WebURLRequest& request,
- const WebURLResponse&) {
- WebPluginResourceClient* client = GetClientFromLoader(loader);
- if (client)
- client->WillSendRequest(request.url());
+ 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,
@@ -998,11 +1039,13 @@ void WebPluginImpl::HandleURLRequest(const char* url,
const char* buf,
unsigned int len,
int notify_id,
- bool popups_allowed) {
+ 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);
+ url, method, target, buf, len, notify_id, popups_allowed, PLUGIN_SRC,
+ notify_redirects);
}
void WebPluginImpl::HandleURLRequestInternal(const char* url,
@@ -1012,7 +1055,8 @@ void WebPluginImpl::HandleURLRequestInternal(const char* url,
unsigned int len,
int notify_id,
bool popups_allowed,
- Referrer referrer_flag) {
+ 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
@@ -1070,7 +1114,7 @@ void WebPluginImpl::HandleURLRequestInternal(const char* url,
return;
InitiateHTTPRequest(resource_id, resource_client, complete_url, method, buf,
- len, NULL, referrer_flag);
+ len, NULL, referrer_flag, notify_redirects);
}
unsigned long WebPluginImpl::GetNextResourceId() {
@@ -1089,7 +1133,8 @@ bool WebPluginImpl::InitiateHTTPRequest(unsigned long resource_id,
const char* buf,
int buf_len,
const char* range_info,
- Referrer referrer_flag) {
+ Referrer referrer_flag,
+ bool notify_redirects) {
if (!client) {
NOTREACHED();
return false;
@@ -1106,6 +1151,7 @@ bool WebPluginImpl::InitiateHTTPRequest(unsigned long resource_id,
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"),
@@ -1167,7 +1213,7 @@ void WebPluginImpl::InitiateHTTPRangeRequest(
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);
+ load_manually_ ? NO_REFERRER : PLUGIN_SRC, false);
}
void WebPluginImpl::SetDeferResourceLoading(unsigned long resource_id,
diff --git a/webkit/glue/plugins/webplugin_impl.h b/webkit/glue/plugins/webplugin_impl.h
index 58289d6..4f3b6c7 100644
--- a/webkit/glue/plugins/webplugin_impl.h
+++ b/webkit/glue/plugins/webplugin_impl.h
@@ -127,6 +127,8 @@ class WebPluginImpl : public WebPlugin,
std::string* json_retval);
virtual void OnMissingPluginStatus(int status);
+ virtual void URLRedirectResponse(bool allow, int resource_id);
+
// Given a (maybe partial) url, completes using the base url.
GURL CompleteURL(const char* url);
@@ -179,7 +181,8 @@ class WebPluginImpl : public WebPlugin,
const char* buf,
int len,
const char* range_info,
- Referrer referrer_flag);
+ Referrer referrer_flag,
+ bool notify_redirects);
gfx::Rect GetWindowClipRect(const gfx::Rect& rect);
@@ -196,7 +199,7 @@ class WebPluginImpl : public WebPlugin,
// to relay the callbacks to the plugin.
virtual void willSendRequest(WebKit::WebURLLoader* loader,
WebKit::WebURLRequest& request,
- const WebKit::WebURLResponse&);
+ const WebKit::WebURLResponse& response);
virtual void didSendData(WebKit::WebURLLoader* loader,
unsigned long long bytes_sent,
unsigned long long total_bytes_to_be_sent);
@@ -223,7 +226,8 @@ class WebPluginImpl : public WebPlugin,
const char* buf,
unsigned int len,
int notify_id,
- bool popups_allowed);
+ bool popups_allowed,
+ bool notify_redirects);
void CancelDocumentLoad();
@@ -247,7 +251,8 @@ class WebPluginImpl : public WebPlugin,
unsigned int len,
int notify_id,
bool popups_allowed,
- Referrer referrer_flag);
+ Referrer referrer_flag,
+ bool notify_redirects);
// Tears down the existing plugin instance and creates a new plugin instance
// to handle the response identified by the loader parameter.