summaryrefslogtreecommitdiffstats
path: root/chrome_frame
diff options
context:
space:
mode:
authoramit@chromium.org <amit@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-27 17:32:51 +0000
committeramit@chromium.org <amit@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-27 17:32:51 +0000
commit2f1793eafae6419d8f0e776f441bcbe262e207d3 (patch)
treec5286986c7fa7bd007eaf2d3e1bcca57141c20c6 /chrome_frame
parent6f1dbc0060967d9ad7c214315f1ca843777d5c7f (diff)
downloadchromium_src-2f1793eafae6419d8f0e776f441bcbe262e207d3.zip
chromium_src-2f1793eafae6419d8f0e776f441bcbe262e207d3.tar.gz
chromium_src-2f1793eafae6419d8f0e776f441bcbe262e207d3.tar.bz2
Add support for OnClose event in ActiveX and NPAPI
Provide event notification for window.close called within ActiveX and NPAPI. Currently this is handled in ActiveDocument to close the popups. In ActiveX and NPAPI plugin we just fire an event as it is upto the container to decide what's the right thing to do. BUG=59664 TEST=New tests ChromeFrameTestWithWebServer.FullTabModeIE_WindowClose, ChromeFrameTestWithWebServer.FullTabModeFF_WindowClose Review URL: http://codereview.chromium.org/4152005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64092 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame')
-rw-r--r--chrome_frame/chrome_active_document.cc4
-rw-r--r--chrome_frame/chrome_frame_activex_base.h10
-rw-r--r--chrome_frame/chrome_frame_npapi.cc23
-rw-r--r--chrome_frame/chrome_frame_npapi.h3
-rw-r--r--chrome_frame/chrome_tab.idl7
-rw-r--r--chrome_frame/test/data/window_close.html48
-rw-r--r--chrome_frame/test/data/window_close_frame.html20
-rw-r--r--chrome_frame/test/test_with_web_server.cc11
8 files changed, 124 insertions, 2 deletions
diff --git a/chrome_frame/chrome_active_document.cc b/chrome_frame/chrome_active_document.cc
index c949c21..9dfe739 100644
--- a/chrome_frame/chrome_active_document.cc
+++ b/chrome_frame/chrome_active_document.cc
@@ -683,6 +683,10 @@ void ChromeActiveDocument::OnDidNavigate(int tab_handle,
}
void ChromeActiveDocument::OnCloseTab(int tab_handle) {
+ // Base class will fire DIChromeFrameEvents::onclose.
+ BaseActiveX::OnCloseTab(tab_handle);
+
+ // Close the container window.
ScopedComPtr<IWebBrowser2> web_browser2;
DoQueryService(SID_SWebBrowserApp, m_spClientSite, web_browser2.Receive());
if (web_browser2)
diff --git a/chrome_frame/chrome_frame_activex_base.h b/chrome_frame/chrome_frame_activex_base.h
index 4c0879b..def29b8 100644
--- a/chrome_frame/chrome_frame_activex_base.h
+++ b/chrome_frame/chrome_frame_activex_base.h
@@ -140,6 +140,10 @@ class ATL_NO_VTABLE ProxyDIChromeFrameEvents
void Fire_onchannelerror() { // NOLINT
FireMethodWithParams(CF_EVENT_DISPID_ONCHANNELERROR, NULL, 0);
}
+
+ void Fire_onclose() { // NOLINT
+ FireMethodWithParams(CF_EVENT_DISPID_ONCLOSE, NULL, 0);
+ }
};
extern bool g_first_launch_by_process_;
@@ -337,7 +341,6 @@ END_MSG_MAP()
return S_OK;
}
-
// Used to setup the document_url_ member needed for completing navigation.
// Create external tab (possibly in incognito mode).
HRESULT IOleObject_SetClientSite(IOleClientSite* client_site) {
@@ -415,7 +418,6 @@ END_MSG_MAP()
DVLOG(1) << __FUNCTION__ << ": " << profile_path->value();
}
-
void OnLoad(int tab_handle, const GURL& url) {
if (ready_state_ < READYSTATE_COMPLETE) {
ready_state_ = READYSTATE_COMPLETE;
@@ -567,6 +569,10 @@ END_MSG_MAP()
FireOnChanged(DISPID_READYSTATE);
}
+ virtual void OnCloseTab(int tab_handle) {
+ Fire_onclose();
+ }
+
// Overridden to take advantage of readystate prop changes and send those
// to potential listeners.
HRESULT FireOnChanged(DISPID dispid) {
diff --git a/chrome_frame/chrome_frame_npapi.cc b/chrome_frame/chrome_frame_npapi.cc
index 267516f..9ea07df 100644
--- a/chrome_frame/chrome_frame_npapi.cc
+++ b/chrome_frame/chrome_frame_npapi.cc
@@ -54,6 +54,7 @@ const NPUTF8* ChromeFrameNPAPI::plugin_property_identifier_names_[] = {
"readystate",
"onprivatemessage",
"usechromenetwork",
+ "onclose",
};
const NPUTF8* ChromeFrameNPAPI::plugin_method_identifier_names_[] = {
@@ -97,6 +98,8 @@ static const char kPluginOnloadAttribute[] = "onload";
static const char kPluginOnErrorAttribute[] = "onloaderror";
static const char kPluginOnMessageAttribute[] = "onmessage";
static const char kPluginOnPrivateMessageAttribute[] = "onprivatemessage";
+static const char kPluginOnCloseAttribute[] = "onclose";
+
// These properties can only be set in arguments at control instantiation.
// When the privileged_mode property is provided and set to true, the control
// will probe for whether its hosting document has the system principal, in
@@ -197,6 +200,8 @@ bool ChromeFrameNPAPI::Initialize(NPMIMEType mime_type, NPP instance,
onerror_handler_ = JavascriptToNPObject(argv[i]);
} else if (LowerCaseEqualsASCII(argn[i], kPluginOnMessageAttribute)) {
onmessage_handler_ = JavascriptToNPObject(argv[i]);
+ } else if (LowerCaseEqualsASCII(argn[i], kPluginOnCloseAttribute)) {
+ onclose_handler_ = JavascriptToNPObject(argv[i]);
} else if (LowerCaseEqualsASCII(argn[i],
kPluginPrivilegedModeAttribute)) {
// Test for the FireFox privileged mode if the user requests it
@@ -300,6 +305,7 @@ void ChromeFrameNPAPI::Uninitialize() {
onerror_handler_.Free();
onmessage_handler_.Free();
onprivatemessage_handler_.Free();
+ onclose_handler_.Free();
Base::Uninitialize();
}
@@ -641,6 +647,12 @@ bool ChromeFrameNPAPI::GetProperty(NPIdentifier name,
return true;
}
}
+ } else if (name == plugin_property_identifiers_[PLUGIN_PROPERTY_ONCLOSE]) {
+ if (onclose_handler_) {
+ variant->type = NPVariantType_Object;
+ variant->value.objectValue = onclose_handler_.Copy();
+ return true;
+ }
} else if (name == plugin_property_identifiers_[PLUGIN_PROPERTY_SRC]) {
AllocateStringVariant(src_, variant);
return true;
@@ -698,6 +710,10 @@ bool ChromeFrameNPAPI::SetProperty(NPIdentifier name,
onprivatemessage_handler_ = variant->value.objectValue;
return true;
}
+ } else if (name == plugin_property_identifiers_[PLUGIN_PROPERTY_ONCLOSE]) {
+ onclose_handler_.Free();
+ onclose_handler_ = variant->value.objectValue;
+ return true;
}
} else if (NPVARIANT_IS_STRING(*variant) || NPVARIANT_IS_NULL(*variant)) {
if (name == plugin_property_identifiers_[PLUGIN_PROPERTY_SRC]) {
@@ -873,6 +889,13 @@ void ChromeFrameNPAPI::OnAutomationServerLaunchFailed(
}
}
+void ChromeFrameNPAPI::OnCloseTab(int tab_handle) {
+ std::string arg;
+ FireEvent("close", arg);
+ ScopedNpVariant result;
+ InvokeDefault(onclose_handler_, arg, &result);
+}
+
bool ChromeFrameNPAPI::InvokeDefault(NPObject* object,
unsigned param_count,
const NPVariant* params,
diff --git a/chrome_frame/chrome_frame_npapi.h b/chrome_frame/chrome_frame_npapi.h
index 45ee1b9..5101592 100644
--- a/chrome_frame/chrome_frame_npapi.h
+++ b/chrome_frame/chrome_frame_npapi.h
@@ -46,6 +46,7 @@ class ChromeFrameNPAPI
PLUGIN_PROPERTY_READYSTATE,
PLUGIN_PROPERTY_ONPRIVATEMESSAGE,
PLUGIN_PROPERTY_USECHROMENETWORK,
+ PLUGIN_PROPERTY_ONCLOSE,
PLUGIN_PROPERTY_COUNT // must be last
} PluginPropertyId;
@@ -150,6 +151,7 @@ END_MSG_MAP()
virtual void OnGetEnabledExtensionsComplete(
void* user_data,
const std::vector<FilePath>& extension_directories);
+ virtual void OnCloseTab(int tab_handle);
private:
void SubscribeToFocusEvents();
@@ -318,6 +320,7 @@ END_MSG_MAP()
ScopedNpObject<NPObject> onerror_handler_;
ScopedNpObject<NPObject> onmessage_handler_;
ScopedNpObject<NPObject> onprivatemessage_handler_;
+ ScopedNpObject<NPObject> onclose_handler_;
// As a workaround for a problem in Opera we cache the window object.
// The problem stems from two things: window messages aren't always removed
diff --git a/chrome_frame/chrome_tab.idl b/chrome_frame/chrome_tab.idl
index d2181ac..f934673 100644
--- a/chrome_frame/chrome_tab.idl
+++ b/chrome_frame/chrome_tab.idl
@@ -118,6 +118,7 @@ typedef enum {
CF_EVENT_DISPID_ONEXTENSIONREADY,
CF_EVENT_DISPID_ONGETENABLEDEXTENSIONSCOMPLETE,
CF_EVENT_DISPID_ONCHANNELERROR,
+ CF_EVENT_DISPID_ONCLOSE,
CF_EVENT_DISPID_ONREADYSTATECHANGED = DISPID_READYSTATECHANGE,
} ChromeFrameEventDispId;
@@ -166,6 +167,12 @@ library ChromeTabLib {
// This event is fired when there is an error in communication channel with
// Chrome and Automation must be reconnected to continue.
void onchannelerror();
+
+ [id(CF_EVENT_DISPID_ONCLOSE)]
+ // This event is fired when the script inside the page wants to close it.
+ // This is just a notification, there is no way to prevent the script from
+ // closing.
+ void onclose();
};
[uuid(BB1176EE-20DD-41DC-9D1E-AC1335C7BBB0)]
diff --git a/chrome_frame/test/data/window_close.html b/chrome_frame/test/data/window_close.html
new file mode 100644
index 0000000..e7f0718
--- /dev/null
+++ b/chrome_frame/test/data/window_close.html
@@ -0,0 +1,48 @@
+<html>
+ <head><title>window.close test</title>
+ <script type="text/javascript" src="chrome_frame_tester_helpers.js">
+ </script>
+ <script type="text/javascript">
+ function OnNavigationFailed() {
+ onFailure("WindowCloseTest", 1, "ChromeFrame Navigation failed");
+ }
+
+ function OnChromeFrameLoaded(url) {
+ appendStatus("Loaded URL: " + url.data);
+ var cf = window.document.ChromeFrame;
+ if (cf.attachEvent) { // Special case for IE
+ appendStatus("Attaching close event handler");
+ cf.attachEvent("onclose", OnCloseWindow);
+ }
+ }
+
+ function OnCloseWindow() {
+ appendStatus("Received window close event.");
+ return onSuccess("WindowCloseTest", 1);
+ }
+
+ </script>
+ </head>
+ <body>
+ <div id="statusPanel" style="border: 1px solid red; width: 100%">
+ Test running....
+ </div>
+
+ <object id="ChromeFrame" width="500" height="500"
+ codebase="http://www.google.com"
+ classid="CLSID:E0A900DF-9611-4446-86BD-4B1D47E7DB2A">
+ <param name="src" value="window_close_frame.html">
+ <param name="onload" value="return OnChromeFrameLoaded(arguments[0]);">
+ <param name="onloaderror" value="return OnNavigationFailed(arguments[0]);">
+ <param name="onclose" value="return OnCloseWindow();">
+ <embed id="ChromeFramePlugin" width="500" height="500" name="ChromeFrame"
+ src="window_close_frame.html"
+ type="application/chromeframe"
+ onload="return OnChromeFrameLoaded(arguments[0]);"
+ onloaderror="return OnNavigationFailed(arguments[0]);"
+ onclose="return OnCloseWindow();">
+ </embed>
+ </object>
+ <p>Tests window.close notification from ChromeFrame to its container</p>
+ </body>
+</html>
diff --git a/chrome_frame/test/data/window_close_frame.html b/chrome_frame/test/data/window_close_frame.html
new file mode 100644
index 0000000..c8a1d53
--- /dev/null
+++ b/chrome_frame/test/data/window_close_frame.html
@@ -0,0 +1,20 @@
+<html>
+ <head><title>window.close test</title>
+ <script type="text/javascript" src="chrome_frame_tester_helpers.js">
+ </script>
+ <script type="text/javascript">
+ function close_window() {
+ if (!isRunningInChrome()) {
+ onFailure("WindowCloseTest", 1,
+ "window_close_frame.html should load in Chrome");
+ return;
+ }
+ window.close();
+ }
+ </script>
+ </head>
+ <body onLoad="setTimeout(close_window, 100);">
+ <h2>Prepare close!</h2>
+ <p>Content closing the window...</p>
+ </body>
+</html> \ No newline at end of file
diff --git a/chrome_frame/test/test_with_web_server.cc b/chrome_frame/test/test_with_web_server.cc
index 35784a4..99643e0 100644
--- a/chrome_frame/test/test_with_web_server.cc
+++ b/chrome_frame/test/test_with_web_server.cc
@@ -1018,6 +1018,17 @@ TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_XHRConditionalHeaderTest) {
SimpleBrowserTest(IE, kXHRConditionalHeaderTestUrl);
}
+const wchar_t kWindowCloseTestUrl[] =
+ L"window_close.html";
+
+TEST_F(ChromeFrameTestWithWebServer, FullTabModeIE_WindowClose) {
+ SimpleBrowserTest(IE, kWindowCloseTestUrl);
+}
+
+TEST_F(ChromeFrameTestWithWebServer, FullTabModeFF_WindowClose) {
+ SimpleBrowserTest(FIREFOX, kWindowCloseTestUrl);
+}
+
std::string GetHeaderValue(const std::string& headers,
const char* header_name) {
net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(),