summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-08 02:57:03 +0000
committerananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-08 02:57:03 +0000
commit4c3046b09abd049562d543fa8dba1cba63c62b5a (patch)
tree4d7e7c087ee541234f0d550856959ee499eb931a
parent067b9286c41061489ed97167d69cbe6801cd09ef (diff)
downloadchromium_src-4c3046b09abd049562d543fa8dba1cba63c62b5a.zip
chromium_src-4c3046b09abd049562d543fa8dba1cba63c62b5a.tar.gz
chromium_src-4c3046b09abd049562d543fa8dba1cba63c62b5a.tar.bz2
Deleting cookies by setting the expires attribute on them with an empty value would not work in ChromeFrame
with the host network stack enabled. When we receive a response in the host browser (IE) we send over the response headers which include the Set-Cookie header and a list of cookies retreived via the InternetGetCookie API. We call this API to retrieve the persistent cookies and send them over to Chrome. However this API returns session cookies as well as persistent cookies. There is no documented way to return only persistent cookies from IE. As a result we would end up setting duplicate cookies in Chrome, which caused this issu.e. To workaround this issue when we receive the response in the url request automation job which handles ChromeFrame network requests, we strip out duplicate cookies sent via InternetGetCookie. When a script deletes a cookie we now handle it correctly in IE and set the data to an empty string. However this does not delete the cookie. When such cookies show up in Chrome, we strip them out as well. Fixes bug http://code.google.com/p/chromium/issues/detail?id=30786 The changes to chrome_frame_npapi.cc/.h are to move the NPAPI functions to the chrome_frame namespace as they conflict with similar functions in NACL. Added the DeleteCookie function to the CookieStore interface, which I think missed out by oversight. Bug=30786 Test=Covered by ChromeFrame unit tests. I also added a unit test to test the newly added URLRequestAutomationJob::IsCookiePresentInCookieHeader function Review URL: http://codereview.chromium.org/518054 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35769 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/automation/automation_profile_impl.cc5
-rw-r--r--chrome/browser/automation/url_request_automation_job.cc37
-rw-r--r--chrome/browser/automation/url_request_automation_job.h7
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc7
-rw-r--r--chrome_frame/chrome_frame.gyp5
-rw-r--r--chrome_frame/chrome_frame_activex_base.h12
-rw-r--r--chrome_frame/chrome_frame_npapi.cc150
-rw-r--r--chrome_frame/chrome_frame_npapi_entrypoints.cc176
-rw-r--r--chrome_frame/chrome_frame_npapi_entrypoints.h39
-rw-r--r--chrome_frame/test/chrome_frame_unittests.cc21
-rw-r--r--chrome_frame/test/data/fulltab_delete_cookie_test.html47
-rw-r--r--chrome_frame/test/data/fulltab_delete_cookie_test.html.mock-http-headers3
-rw-r--r--chrome_frame/test/html_util_unittests.cc24
-rw-r--r--net/base/cookie_store.h4
14 files changed, 360 insertions, 177 deletions
diff --git a/chrome/browser/automation/automation_profile_impl.cc b/chrome/browser/automation/automation_profile_impl.cc
index 0acd37d..b8685be 100644
--- a/chrome/browser/automation/automation_profile_impl.cc
+++ b/chrome/browser/automation/automation_profile_impl.cc
@@ -105,6 +105,11 @@ class AutomationCookieStore : public net::CookieStore {
return original_cookie_store_->GetCookiesWithOptions(url, options);
}
+ virtual void DeleteCookie(const GURL& url,
+ const std::string& cookie_name) {
+ return original_cookie_store_->DeleteCookie(url, cookie_name);
+ }
+
protected:
void SendIPCMessageOnIOThread(IPC::Message* m) {
if (ChromeThread::CurrentlyOn(ChromeThread::IO)) {
diff --git a/chrome/browser/automation/url_request_automation_job.cc b/chrome/browser/automation/url_request_automation_job.cc
index 5433ca7..576743e 100644
--- a/chrome/browser/automation/url_request_automation_job.cc
+++ b/chrome/browser/automation/url_request_automation_job.cc
@@ -12,6 +12,7 @@
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
#include "chrome/test/automation/automation_messages.h"
+#include "net/base/cookie_monster.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/http/http_util.h"
@@ -256,6 +257,7 @@ void URLRequestAutomationJob::OnRequestStarted(int tab, int id,
redirect_url_.c_str());
URLRequestContext* ctx = request_->context();
+ std::vector<std::string> response_cookies;
if (!response.headers.empty()) {
headers_ = new net::HttpResponseHeaders(
@@ -264,7 +266,6 @@ void URLRequestAutomationJob::OnRequestStarted(int tab, int id,
// Parse and set HTTP cookies.
const std::string name = "Set-Cookie";
std::string value;
- std::vector<std::string> response_cookies;
void* iter = NULL;
while (headers_->EnumerateHeader(&iter, name, &value)) {
@@ -291,10 +292,20 @@ void URLRequestAutomationJob::OnRequestStarted(int tab, int id,
StringTokenizer cookie_parser(response.persistent_cookies, ";");
while (cookie_parser.GetNext()) {
- net::CookieOptions options;
- ctx->cookie_store()->SetCookieWithOptions(url_for_cookies,
- cookie_parser.token(),
- options);
+ std::string cookie_string = cookie_parser.token();
+ // Only allow cookies with valid name value pairs.
+ if (cookie_string.find('=') != std::string::npos) {
+ TrimWhitespace(cookie_string, TRIM_ALL, &cookie_string);
+ // Ignore duplicate cookies, i.e. cookies passed in from the host
+ // browser which also exist in the response header.
+ if (!IsCookiePresentInCookieHeader(cookie_string,
+ response_cookies)) {
+ net::CookieOptions options;
+ ctx->cookie_store()->SetCookieWithOptions(url_for_cookies,
+ cookie_string,
+ options);
+ }
+ }
}
}
@@ -436,3 +447,19 @@ void URLRequestAutomationJob::DisconnectFromMessageFilter() {
message_filter_ = NULL;
}
}
+
+bool URLRequestAutomationJob::IsCookiePresentInCookieHeader(
+ const std::string& cookie_line,
+ const std::vector<std::string>& header_cookies) {
+ net::CookieMonster::ParsedCookie parsed_current_cookie(cookie_line);
+ for (size_t index = 0; index < header_cookies.size(); index++) {
+ net::CookieMonster::ParsedCookie parsed_header_cookie(
+ header_cookies[index]);
+
+ if (parsed_header_cookie.Name() == parsed_current_cookie.Name())
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/chrome/browser/automation/url_request_automation_job.h b/chrome/browser/automation/url_request_automation_job.h
index 824b80c..0b6a2f1 100644
--- a/chrome/browser/automation/url_request_automation_job.h
+++ b/chrome/browser/automation/url_request_automation_job.h
@@ -6,6 +6,7 @@
#ifndef CHROME_BROWSER_AUTOMATION_URL_REQUEST_AUTOMATION_JOB_H_
#define CHROME_BROWSER_AUTOMATION_URL_REQUEST_AUTOMATION_JOB_H_
+#include <vector>
#include "chrome/common/ref_counted_util.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
@@ -51,6 +52,12 @@ class URLRequestAutomationJob : public URLRequestJob {
return request_id_;
}
+ // Returns true if the cookie passed in exists in the list of cookies
+ // parsed from the HTTP response header.
+ static bool IsCookiePresentInCookieHeader(
+ const std::string& cookie_name,
+ const std::vector<std::string>& header_cookies);
+
protected:
// Protected URLRequestJob override.
virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read);
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index bde98fd..61a25d8 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -538,12 +538,7 @@ void ResourceMessageFilter::OnGetRawCookies(
void ResourceMessageFilter::OnDeleteCookie(const GURL& url,
const std::string& cookie_name) {
URLRequestContext* context = GetRequestContextForURL(url);
- net::CookieMonster* cookie_monster = context->cookie_store()->
- GetCookieMonster();
- if (!cookie_monster)
- return;
-
- cookie_monster->DeleteCookie(url, cookie_name);
+ context->cookie_store()->DeleteCookie(url, cookie_name);
}
#if defined(OS_WIN) // This hack is Windows-specific.
diff --git a/chrome_frame/chrome_frame.gyp b/chrome_frame/chrome_frame.gyp
index 33f4a4a..764ec79 100644
--- a/chrome_frame/chrome_frame.gyp
+++ b/chrome_frame/chrome_frame.gyp
@@ -108,7 +108,11 @@
'type': 'executable',
'dependencies': [
'../build/temp_gyp/googleurl.gyp:googleurl',
+ '../chrome/chrome.gyp:browser',
'../chrome/chrome.gyp:common',
+ '../chrome/chrome.gyp:debugger',
+ '../chrome/chrome.gyp:nacl',
+ '../chrome/chrome.gyp:renderer',
'../chrome/chrome.gyp:utility',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
@@ -617,6 +621,7 @@
'sources': [
'chrome_frame_npapi.rgs',
'chrome_frame_npapi_entrypoints.cc',
+ 'chrome_frame_npapi_entrypoints.h',
'chrome_tab.cc',
'chrome_tab.def',
'chrome_tab.h',
diff --git a/chrome_frame/chrome_frame_activex_base.h b/chrome_frame/chrome_frame_activex_base.h
index 077fa11..a7fd6a0 100644
--- a/chrome_frame/chrome_frame_activex_base.h
+++ b/chrome_frame/chrome_frame_activex_base.h
@@ -42,6 +42,7 @@
#include "chrome_frame/com_type_info_holder.h"
#include "chrome_frame/urlmon_url_request.h"
#include "grit/generated_resources.h"
+#include "net/base/cookie_monster.h"
// Include without path to make GYP build see it.
#include "chrome_tab.h" // NOLINT
@@ -523,10 +524,17 @@ END_MSG_MAP()
const std::string& cookie) {
std::string name;
std::string data;
+
size_t name_end = cookie.find('=');
if (std::string::npos != name_end) {
- name = cookie.substr(0, name_end);
- data = cookie.substr(name_end + 1);
+ net::CookieMonster::ParsedCookie parsed_cookie = cookie;
+ name = parsed_cookie.Name();
+ // Verify if the cookie is being deleted. The cookie format is as below
+ // value[; expires=date][; domain=domain][; path=path][; secure]
+ // If the first semicolon appears immediately after the name= string,
+ // it means that the cookie is being deleted.
+ if (!parsed_cookie.Value().empty())
+ data = cookie.substr(name_end + 1);
} else {
data = cookie;
}
diff --git a/chrome_frame/chrome_frame_npapi.cc b/chrome_frame/chrome_frame_npapi.cc
index d3e1f91..2dd3145 100644
--- a/chrome_frame/chrome_frame_npapi.cc
+++ b/chrome_frame/chrome_frame_npapi.cc
@@ -85,8 +85,6 @@ void ChromeFrameNPAPI::CompileAsserts() {
you_must_add_both_plugin_property_and_name);
}
-static const int kMaxBytesForPluginConsumption = 0x7FFFFFFF;
-
static const char kPluginSrcAttribute[] = "src";
static const char kPluginForceFullPageAttribute[] = "force_full_page";
static const char kPluginOnloadAttribute[] = "onload";
@@ -111,154 +109,6 @@ static const char kPluginChromeFunctionsAutomatedAttribute[] =
// If chrome network stack is to be used
static const char kPluginUseChromeNetwork[] = "usechromenetwork";
-
-NPError NPP_New(NPMIMEType plugin_type, NPP instance, uint16 mode, int16 argc,
- char* argn[], char* argv[], NPSavedData* saved) {
- if (instance == NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
-
- ChromeFrameNPAPI::ChromeFrameNPObject* chrome_frame_npapi_obj =
- reinterpret_cast<ChromeFrameNPAPI::ChromeFrameNPObject*>(
- npapi::CreateObject(instance, ChromeFrameNPAPI::PluginClass()));
- DCHECK(chrome_frame_npapi_obj != NULL);
-
- ChromeFrameNPAPI* plugin_instance =
- chrome_frame_npapi_obj->chrome_frame_plugin_instance;
- DCHECK(plugin_instance != NULL);
-
- // Note that we MUST set instance->pdata BEFORE calling Initialize. This is
- // because Initialize can call back into the NPAPI host which will need the
- // pdata field to be set.
- chrome_frame_npapi_obj->chrome_frame_plugin_instance =
- plugin_instance;
- instance->pdata = chrome_frame_npapi_obj;
-
- bool init = plugin_instance->Initialize(plugin_type, instance,
- mode, argc, argn, argv);
- DCHECK(init);
-
- return NPERR_NO_ERROR;
-}
-
-NPError NPP_Destroy(NPP instance, NPSavedData** save) {
- // Takes ownership and releases the object at the end of scope.
- ScopedNpObject<ChromeFrameNPAPI::ChromeFrameNPObject> chrome_frame_npapi_obj(
- reinterpret_cast<ChromeFrameNPAPI::ChromeFrameNPObject*>(
- instance->pdata));
-
- if (chrome_frame_npapi_obj.get()) {
- ChromeFrameNPAPI* plugin_instance =
- ChromeFrameNPAPI::ChromeFrameInstanceFromPluginInstance(instance);
-
- plugin_instance->Uninitialize();
- instance->pdata = NULL;
- }
-
- return NPERR_NO_ERROR;
-}
-
-NPError NPP_SetWindow(NPP instance, NPWindow* window_info) {
- if (window_info == NULL) {
- NOTREACHED();
- return NPERR_GENERIC_ERROR;
- }
-
- ChromeFrameNPAPI* plugin_instance =
- ChromeFrameNPAPI::ChromeFrameInstanceFromPluginInstance(instance);
-
- if (plugin_instance == NULL) {
- return NPERR_INVALID_INSTANCE_ERROR;
- }
-
- plugin_instance->SetWindow(window_info);
- return NPERR_NO_ERROR;
-}
-
-NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream,
- NPBool seekable, uint16* stream_type) {
- NPAPIUrlRequest* url_request = ChromeFrameNPAPI::ValidateRequest(
- instance, stream->notifyData);
- if (url_request) {
- if (!url_request->OnStreamCreated(type, stream))
- return NPERR_GENERIC_ERROR;
- }
-
- // We need to return the requested stream mode if we are returning a success
- // code. If we don't do this it causes Opera to blow up.
- *stream_type = NP_NORMAL;
- return NPERR_NO_ERROR;
-}
-
-NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) {
- NPAPIUrlRequest* url_request = ChromeFrameNPAPI::ValidateRequest(
- instance, stream->notifyData);
- if (url_request) {
- url_request->OnStreamDestroyed(reason);
- }
-
- return NPERR_NO_ERROR;
-}
-
-NPError NPP_GetValue(NPP instance, NPPVariable variable, void* value) {
- if (variable == NPPVpluginScriptableNPObject) {
- void** plugin = reinterpret_cast<void**>(value);
- ChromeFrameNPAPI::ChromeFrameNPObject* chrome_frame_npapi_obj =
- reinterpret_cast<ChromeFrameNPAPI::ChromeFrameNPObject*>(
- instance->pdata);
- // Return value is expected to be retained
- npapi::RetainObject(reinterpret_cast<NPObject*>(chrome_frame_npapi_obj));
- *plugin = chrome_frame_npapi_obj;
- return NPERR_NO_ERROR;
- }
- return NPERR_GENERIC_ERROR;
-}
-
-NPError NPP_SetValue(NPP instance, NPNVariable variable, void* value) {
- return NPERR_GENERIC_ERROR;
-}
-
-int32 NPP_WriteReady(NPP instance, NPStream* stream) {
- NPAPIUrlRequest* url_request = ChromeFrameNPAPI::ValidateRequest(
- instance, stream->notifyData);
- if (url_request) {
- return url_request->OnWriteReady();
- }
-
- return kMaxBytesForPluginConsumption;
-}
-
-int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len,
- void* buffer) {
- NPAPIUrlRequest* url_request = ChromeFrameNPAPI::ValidateRequest(
- instance, stream->notifyData);
- if (url_request) {
- return url_request->OnWrite(buffer, len);
- }
-
- return len;
-}
-
-void NPP_URLNotify(NPP instance, const char* url, NPReason reason,
- void* notifyData) {
- ChromeFrameNPAPI* plugin_instance =
- ChromeFrameNPAPI::ChromeFrameInstanceFromPluginInstance(instance);
- if (plugin_instance) {
- plugin_instance->UrlNotify(url, reason, notifyData);
- }
-}
-
-void NPP_Print(NPP instance, NPPrint* print_info) {
- ChromeFrameNPAPI* plugin_instance =
- ChromeFrameNPAPI::ChromeFrameInstanceFromPluginInstance(instance);
-
- if (plugin_instance == NULL) {
- NOTREACHED();
- return;
- }
-
- plugin_instance->Print(print_info);
-}
-
// ChromeFrameNPAPI member defines.
// TODO(tommi): remove ignore_setfocus_ since that's not how focus is
diff --git a/chrome_frame/chrome_frame_npapi_entrypoints.cc b/chrome_frame/chrome_frame_npapi_entrypoints.cc
index f1eec1c..17a0953 100644
--- a/chrome_frame/chrome_frame_npapi_entrypoints.cc
+++ b/chrome_frame/chrome_frame_npapi_entrypoints.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "chrome_frame/chrome_frame_npapi_entrypoints.h"
#include "chrome_frame/chrome_frame_npapi.h"
#define NPAPI WINAPI
@@ -23,19 +24,19 @@ NPError NPAPI NP_Initialize(NPNetscapeFuncs* browser_funcs) {
NPError NPAPI NP_GetEntryPoints(NPPluginFuncs* plugin_funcs) {
plugin_funcs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
plugin_funcs->size = sizeof(plugin_funcs);
- plugin_funcs->newp = NPP_New;
- plugin_funcs->destroy = NPP_Destroy;
- plugin_funcs->setwindow = NPP_SetWindow;
- plugin_funcs->newstream = NPP_NewStream;
- plugin_funcs->destroystream = NPP_DestroyStream;
+ plugin_funcs->newp = chrome_frame::NPP_New;
+ plugin_funcs->destroy = chrome_frame::NPP_Destroy;
+ plugin_funcs->setwindow = chrome_frame::NPP_SetWindow;
+ plugin_funcs->newstream = chrome_frame::NPP_NewStream;
+ plugin_funcs->destroystream = chrome_frame::NPP_DestroyStream;
plugin_funcs->asfile = NULL;
- plugin_funcs->writeready = NPP_WriteReady;
- plugin_funcs->write = NPP_Write;
- plugin_funcs->print = NPP_Print;
+ plugin_funcs->writeready = chrome_frame::NPP_WriteReady;
+ plugin_funcs->write = chrome_frame::NPP_Write;
+ plugin_funcs->print = chrome_frame::NPP_Print;
plugin_funcs->event = NULL;
- plugin_funcs->urlnotify = NPP_URLNotify;
- plugin_funcs->getvalue = NPP_GetValue;
- plugin_funcs->setvalue = NPP_SetValue;
+ plugin_funcs->urlnotify = chrome_frame::NPP_URLNotify;
+ plugin_funcs->getvalue = chrome_frame::NPP_GetValue;
+ plugin_funcs->setvalue = chrome_frame::NPP_SetValue;
return NPERR_NO_ERROR;
}
@@ -51,3 +52,156 @@ void NPAPI NP_Shutdown() {
<< " living objects";
}
+
+namespace chrome_frame {
+
+NPError NPP_New(NPMIMEType plugin_type, NPP instance, uint16 mode, int16 argc,
+ char* argn[], char* argv[], NPSavedData* saved) {
+ if (instance == NULL)
+ return NPERR_INVALID_INSTANCE_ERROR;
+
+ ChromeFrameNPAPI::ChromeFrameNPObject* chrome_frame_npapi_obj =
+ reinterpret_cast<ChromeFrameNPAPI::ChromeFrameNPObject*>(
+ npapi::CreateObject(instance, ChromeFrameNPAPI::PluginClass()));
+ DCHECK(chrome_frame_npapi_obj != NULL);
+
+ ChromeFrameNPAPI* plugin_instance =
+ chrome_frame_npapi_obj->chrome_frame_plugin_instance;
+ DCHECK(plugin_instance != NULL);
+
+ // Note that we MUST set instance->pdata BEFORE calling Initialize. This is
+ // because Initialize can call back into the NPAPI host which will need the
+ // pdata field to be set.
+ chrome_frame_npapi_obj->chrome_frame_plugin_instance =
+ plugin_instance;
+ instance->pdata = chrome_frame_npapi_obj;
+
+ bool init = plugin_instance->Initialize(plugin_type, instance,
+ mode, argc, argn, argv);
+ DCHECK(init);
+
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_Destroy(NPP instance, NPSavedData** save) {
+ // Takes ownership and releases the object at the end of scope.
+ ScopedNpObject<ChromeFrameNPAPI::ChromeFrameNPObject> chrome_frame_npapi_obj(
+ reinterpret_cast<ChromeFrameNPAPI::ChromeFrameNPObject*>(
+ instance->pdata));
+
+ if (chrome_frame_npapi_obj.get()) {
+ ChromeFrameNPAPI* plugin_instance =
+ ChromeFrameNPAPI::ChromeFrameInstanceFromPluginInstance(instance);
+
+ plugin_instance->Uninitialize();
+ instance->pdata = NULL;
+ }
+
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_SetWindow(NPP instance, NPWindow* window_info) {
+ if (window_info == NULL) {
+ NOTREACHED();
+ return NPERR_GENERIC_ERROR;
+ }
+
+ ChromeFrameNPAPI* plugin_instance =
+ ChromeFrameNPAPI::ChromeFrameInstanceFromPluginInstance(instance);
+
+ if (plugin_instance == NULL) {
+ return NPERR_INVALID_INSTANCE_ERROR;
+ }
+
+ plugin_instance->SetWindow(window_info);
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream,
+ NPBool seekable, uint16* stream_type) {
+ NPAPIUrlRequest* url_request = ChromeFrameNPAPI::ValidateRequest(
+ instance, stream->notifyData);
+ if (url_request) {
+ if (!url_request->OnStreamCreated(type, stream))
+ return NPERR_GENERIC_ERROR;
+ }
+
+ // We need to return the requested stream mode if we are returning a success
+ // code. If we don't do this it causes Opera to blow up.
+ *stream_type = NP_NORMAL;
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) {
+ NPAPIUrlRequest* url_request = ChromeFrameNPAPI::ValidateRequest(
+ instance, stream->notifyData);
+ if (url_request) {
+ url_request->OnStreamDestroyed(reason);
+ }
+
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_GetValue(NPP instance, NPPVariable variable, void* value) {
+ if (variable == NPPVpluginScriptableNPObject) {
+ void** plugin = reinterpret_cast<void**>(value);
+ ChromeFrameNPAPI::ChromeFrameNPObject* chrome_frame_npapi_obj =
+ reinterpret_cast<ChromeFrameNPAPI::ChromeFrameNPObject*>(
+ instance->pdata);
+ // Return value is expected to be retained
+ npapi::RetainObject(reinterpret_cast<NPObject*>(chrome_frame_npapi_obj));
+ *plugin = chrome_frame_npapi_obj;
+ return NPERR_NO_ERROR;
+ }
+ return NPERR_GENERIC_ERROR;
+}
+
+NPError NPP_SetValue(NPP instance, NPNVariable variable, void* value) {
+ return NPERR_GENERIC_ERROR;
+}
+
+int32 NPP_WriteReady(NPP instance, NPStream* stream) {
+ static const int kMaxBytesForPluginConsumption = 0x7FFFFFFF;
+
+ NPAPIUrlRequest* url_request = ChromeFrameNPAPI::ValidateRequest(
+ instance, stream->notifyData);
+ if (url_request) {
+ return url_request->OnWriteReady();
+ }
+
+ return kMaxBytesForPluginConsumption;
+}
+
+int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len,
+ void* buffer) {
+ NPAPIUrlRequest* url_request = ChromeFrameNPAPI::ValidateRequest(
+ instance, stream->notifyData);
+ if (url_request) {
+ return url_request->OnWrite(buffer, len);
+ }
+
+ return len;
+}
+
+void NPP_URLNotify(NPP instance, const char* url, NPReason reason,
+ void* notifyData) {
+ ChromeFrameNPAPI* plugin_instance =
+ ChromeFrameNPAPI::ChromeFrameInstanceFromPluginInstance(instance);
+ if (plugin_instance) {
+ plugin_instance->UrlNotify(url, reason, notifyData);
+ }
+}
+
+void NPP_Print(NPP instance, NPPrint* print_info) {
+ ChromeFrameNPAPI* plugin_instance =
+ ChromeFrameNPAPI::ChromeFrameInstanceFromPluginInstance(instance);
+
+ if (plugin_instance == NULL) {
+ NOTREACHED();
+ return;
+ }
+
+ plugin_instance->Print(print_info);
+}
+
+} // namespace chrome_frame
diff --git a/chrome_frame/chrome_frame_npapi_entrypoints.h b/chrome_frame/chrome_frame_npapi_entrypoints.h
new file mode 100644
index 0000000..00b34fd
--- /dev/null
+++ b/chrome_frame/chrome_frame_npapi_entrypoints.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2009 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.
+
+#ifndef CHROME_FRAME_CHROME_FRAME_NPAPI_ENTRYPOINTS_H_
+#define CHROME_FRAME_CHROME_FRAME_NPAPI_ENTRYPOINTS_H_
+
+#include "chrome_frame/np_browser_functions.h"
+
+namespace chrome_frame {
+
+NPError NPP_New(NPMIMEType plugin_type, NPP instance, uint16 mode, int16 argc,
+ char* argn[], char* argv[], NPSavedData* saved);
+
+NPError NPP_Destroy(NPP instance, NPSavedData** save);
+
+NPError NPP_SetWindow(NPP instance, NPWindow* window_info);
+
+NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream,
+ NPBool seekable, uint16* stream_type);
+
+NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason);
+
+NPError NPP_GetValue(NPP instance, NPPVariable variable, void* value);
+
+NPError NPP_SetValue(NPP instance, NPNVariable variable, void* value);
+
+int32 NPP_WriteReady(NPP instance, NPStream* stream);
+
+int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len,
+ void* buffer);
+void NPP_URLNotify(NPP instance, const char* url, NPReason reason,
+ void* notifyData);
+
+void NPP_Print(NPP instance, NPPrint* print_info);
+
+} // namespace chrome_frame
+
+#endif // CHROME_FRAME_CHROME_FRAME_NPAPI_ENTRYPOINTS_H_
diff --git a/chrome_frame/test/chrome_frame_unittests.cc b/chrome_frame/test/chrome_frame_unittests.cc
index bfd863b..9497162 100644
--- a/chrome_frame/test/chrome_frame_unittests.cc
+++ b/chrome_frame/test/chrome_frame_unittests.cc
@@ -1745,9 +1745,8 @@ TEST_F(ChromeFrameTestWithWebServer,
FullTabModeIE_ChromeFrameXHRAuthHeaderTest) {
chrome_frame_test::TimedMsgLoop loop;
- ASSERT_TRUE(
- LaunchBrowser(IE,
- kChromeFrameFullTabModeXMLHttpRequestAuthHeaderTestUrl));
+ ASSERT_TRUE(LaunchBrowser(
+ IE, kChromeFrameFullTabModeXMLHttpRequestAuthHeaderTestUrl));
loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
@@ -1755,3 +1754,19 @@ TEST_F(ChromeFrameTestWithWebServer,
ASSERT_TRUE(
CheckResultFile(L"FullTab_XMLHttpRequestAuthorizationHeaderTest", "OK"));
}
+
+const wchar_t kChromeFrameFullTabModeDeleteCookieTest[] =
+ L"files/fulltab_delete_cookie_test.html";
+
+TEST_F(ChromeFrameTestWithWebServer,
+ FullTabModeIE_ChromeFrameDeleteCookieTest) {
+ chrome_frame_test::TimedMsgLoop loop;
+
+ ASSERT_TRUE(LaunchBrowser(IE, kChromeFrameFullTabModeDeleteCookieTest));
+
+ loop.RunFor(kChromeFrameLongNavigationTimeoutInSeconds);
+
+ chrome_frame_test::CloseAllIEWindows();
+ ASSERT_TRUE(CheckResultFile(L"FullTab_DeleteCookieTest", "OK"));
+}
+
diff --git a/chrome_frame/test/data/fulltab_delete_cookie_test.html b/chrome_frame/test/data/fulltab_delete_cookie_test.html
new file mode 100644
index 0000000..62c5df0
--- /dev/null
+++ b/chrome_frame/test/data/fulltab_delete_cookie_test.html
@@ -0,0 +1,47 @@
+<html>
+ <head>
+ <meta http-equiv="x-ua-compatible" content="chrome=1" />
+ <title>FullTab mode cookie deletion test</title>
+ </head>
+
+ <script type="text/javascript"
+ src="chrome_frame_tester_helpers.js"></script>
+
+ <script type="text/javascript">
+ function onLoad() {
+ if (!isRunningInChrome()) {
+ onFailure("FullTab_DeleteCookieTest", 1, "Not running in Chrome");
+ return;
+ }
+
+ // The path of the cookie in this test is set to "/." As a result it
+ // is set twice, once for the original URL and once for the
+ // chrome_frame_tester_helpers.js script. We attempt to delete
+ // the cookie twice and validate that the end result is null.
+ // First validate that the document cookie contains the substring
+ // CF_FullTabDeleteCookie=1; CF_FullTabDeleteCookie=1
+ // Then erase the first cookie and validate that it no longer contains
+ // this string.
+ var cookie_found =
+ /CF_FullTabDeleteCookie=1; CF_FullTabDeleteCookie=1/.test(
+ document.cookie);
+ if (cookie_found) {
+ eraseCookie("CF_FullTabDeleteCookie");
+ cookie_found =
+ /CF_FullTabDeleteCookie=1; CF_FullTabDeleteCookie=1/.test(
+ document.cookie);
+ if (!cookie_found) {
+ onSuccess("FullTab_DeleteCookieTest", 1);
+ } else {
+ onFailure("FullTab_DeleteCookieTest", 1, "Delete cookie failed");
+ }
+ } else {
+ onFailure("FullTab_DeleteCookieTest", 1, "Expected cookies not set");
+ }
+ }
+ </script>
+
+ <body onload="onLoad();">
+ This tests whether cookies get deleted correctly in full tab mode
+ </body>
+</html>
diff --git a/chrome_frame/test/data/fulltab_delete_cookie_test.html.mock-http-headers b/chrome_frame/test/data/fulltab_delete_cookie_test.html.mock-http-headers
new file mode 100644
index 0000000..53edac0
--- /dev/null
+++ b/chrome_frame/test/data/fulltab_delete_cookie_test.html.mock-http-headers
@@ -0,0 +1,3 @@
+HTTP/1.0 200 OK
+Content-type: text/html
+Set-Cookie: CF_FullTabDeleteCookie=1;path=/
diff --git a/chrome_frame/test/html_util_unittests.cc b/chrome_frame/test/html_util_unittests.cc
index 969e680..7884638 100644
--- a/chrome_frame/test/html_util_unittests.cc
+++ b/chrome_frame/test/html_util_unittests.cc
@@ -5,6 +5,8 @@
#include <windows.h>
#include <atlsecurity.h>
#include <shellapi.h>
+#include <string>
+#include <vector>
#include "base/basictypes.h"
#include "base/file_util.h"
@@ -22,6 +24,7 @@
#include "chrome_frame/chrome_frame_delegate.h"
#include "chrome_frame/html_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "chrome/browser/automation/url_request_automation_job.h"
const char kChromeFrameUserAgent[] = "chromeframe";
@@ -360,4 +363,25 @@ TEST(HttpUtils, HasFrameBustingHeader) {
"X-Frame-Options: ALLOWall\r\n"));
}
+TEST(HttpCookieTest, IdentifyDuplicateCookieTest) {
+ std::vector<std::string> header_cookies;
+ header_cookies.push_back("BLAHHH; Path=/;");
+
+ EXPECT_FALSE(URLRequestAutomationJob::IsCookiePresentInCookieHeader(
+ "BLAHHH=1", header_cookies));
+
+ header_cookies.clear();
+
+ header_cookies.push_back("BLAHHH=1; Path=/;");
+
+ EXPECT_TRUE(URLRequestAutomationJob::IsCookiePresentInCookieHeader(
+ "BLAHHH=1", header_cookies));
+
+ header_cookies.clear();
+
+ header_cookies.push_back("BLAH=1; Path=/blah;");
+
+ EXPECT_FALSE(URLRequestAutomationJob::IsCookiePresentInCookieHeader(
+ "BLAH", header_cookies));
+}
diff --git a/net/base/cookie_store.h b/net/base/cookie_store.h
index e4d9b5d..1ea3fa2 100644
--- a/net/base/cookie_store.h
+++ b/net/base/cookie_store.h
@@ -59,6 +59,10 @@ class CookieStore : public base::RefCountedThreadSafe<CookieStore> {
return NULL;
};
+ // Deletes the passed in cookie for the specified URL.
+ virtual void DeleteCookie(const GURL& url,
+ const std::string& cookie_name) = 0;
+
protected:
friend class base::RefCountedThreadSafe<CookieStore>;
virtual ~CookieStore() {}