shdocvw: Implement IWebBrowser::ExecWB and IWebBrowser::QueryStatusWB.
authorErich Hoover <ehoover@mines.edu>
Tue, 1 Mar 2011 20:25:41 +0000 (13:25 -0700)
committerAlexandre Julliard <julliard@winehq.org>
Thu, 3 Mar 2011 16:47:15 +0000 (17:47 +0100)
dlls/shdocvw/tests/webbrowser.c
dlls/shdocvw/webbrowser.c

index afde2e1d52799e32b730f26b9a0be215048b6dab..10880651a7bc824662f1590ce1ce3fc68016ae74 100644 (file)
@@ -122,7 +122,10 @@ DEFINE_EXPECT(Exec_SETPROGRESSPOS);
 DEFINE_EXPECT(Exec_UPDATECOMMANDS);
 DEFINE_EXPECT(Exec_SETTITLE);
 DEFINE_EXPECT(QueryStatus_SETPROGRESSTEXT);
+DEFINE_EXPECT(Exec_STOP);
+DEFINE_EXPECT(Exec_IDM_STOP);
 DEFINE_EXPECT(QueryStatus_STOP);
+DEFINE_EXPECT(QueryStatus_IDM_STOP);
 DEFINE_EXPECT(DocHost_EnableModeless_TRUE);
 DEFINE_EXPECT(DocHost_EnableModeless_FALSE);
 DEFINE_EXPECT(DocHost_TranslateAccelerator);
@@ -138,10 +141,11 @@ static const WCHAR wszItem[] = {'i','t','e','m',0};
 static const WCHAR emptyW[] = {0};
 
 static VARIANT_BOOL exvb;
+
 static IWebBrowser2 *wb;
 
 static HWND container_hwnd, shell_embedding_hwnd;
-static BOOL is_downloading, is_first_load;
+static BOOL is_downloading, is_first_load, use_container_olecmd;
 static HRESULT hr_dochost_TranslateAccelerator = E_NOTIMPL;
 static HRESULT hr_site_TranslateAccelerator = E_NOTIMPL;
 static const char *current_url;
@@ -197,6 +201,17 @@ static BSTR a2bstr(const char *str)
     return ret;
 }
 
+#define create_WebBrowser(a) _create_WebBrowser(__LINE__,a)
+static HRESULT _create_WebBrowser(unsigned line, IUnknown **unk)
+{
+    HRESULT hres;
+
+    hres = CoCreateInstance(&CLSID_WebBrowser, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
+            &IID_IUnknown, (void**)unk);
+    ok_(__FILE__,line)(hres == S_OK, "Creating WebBrowser object failed: %08x\n", hres);
+    return hres;
+}
+
 #define test_LocationURL(a,b) _test_LocationURL(__LINE__,a,b)
 static void _test_LocationURL(unsigned line, IUnknown *unk, const char *exurl)
 {
@@ -308,6 +323,15 @@ static HRESULT WINAPI OleCommandTarget_QueryStatus(IOleCommandTarget *iface, con
         CHECK_EXPECT(QueryStatus_SETPROGRESSTEXT);
         prgCmds[0].cmdf = OLECMDF_ENABLED;
         return S_OK;
+    case IDM_STOP:
+        /* Note:
+         *  IDM_STOP is a command specific to CGID_MSHTML (not an OLECMDID command).
+         *  This command appears here for the ExecWB and QueryStatusWB tests in order
+         *  to help demonstrate that these routines use a NULL pguidCmdGroup.
+         */
+        CHECK_EXPECT(QueryStatus_IDM_STOP);
+        prgCmds[0].cmdf = 0;
+        return S_OK;
     default:
         ok(0, "unexpected command %d\n", prgCmds[0].cmdID);
     }
@@ -366,6 +390,17 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID
             CHECK_EXPECT(Exec_SETTITLE);
             /* TODO: test args */
             return S_OK;
+        case OLECMDID_STOP:
+            CHECK_EXPECT(Exec_STOP);
+            return S_OK;
+        case IDM_STOP:
+            /* Note:
+             *  IDM_STOP is a command specific to CGID_MSHTML (not an OLECMDID command).
+             *  This command appears here for the ExecWB and QueryStatusWB tests in order
+             *  to help demonstrate that these routines use a NULL pguidCmdGroup.
+             */
+            CHECK_EXPECT(Exec_IDM_STOP);
+            return OLECMDERR_E_NOTSUPPORTED;
         default:
             ok(0, "unexpected nsCmdID %d\n", nCmdID);
         }
@@ -428,8 +463,13 @@ static HRESULT WINAPI OleContainer_QueryInterface(IOleContainer *iface, REFIID r
         return E_NOINTERFACE; /* TODO */
 
     if(IsEqualGUID(&IID_IOleCommandTarget, riid)) {
-        *ppv = &OleCommandTarget;
-        return S_OK;
+        if(use_container_olecmd)
+        {
+            *ppv = &OleCommandTarget;
+            return S_OK;
+        }
+        else
+            return E_NOINTERFACE;
     }
 
     ok(0, "unexpected call\n");
@@ -1729,7 +1769,7 @@ static void test_ClientSite(IUnknown *unk, IOleClientSite *client, BOOL stop_dow
         SET_EXPECT(Invoke_AMBIENT_SILENT);
     }else if(stop_download) {
         SET_EXPECT(Invoke_DOWNLOADCOMPLETE);
-        SET_EXPECT(Exec_SETDOWNLOADSTATE_0);
+        if (use_container_olecmd) SET_EXPECT(Exec_SETDOWNLOADSTATE_0);
         SET_EXPECT(Invoke_COMMANDSTATECHANGE);
     }
 
@@ -1743,7 +1783,7 @@ static void test_ClientSite(IUnknown *unk, IOleClientSite *client, BOOL stop_dow
         CHECK_CALLED(Invoke_AMBIENT_SILENT);
     }else if(stop_download) {
         todo_wine CHECK_CALLED(Invoke_DOWNLOADCOMPLETE);
-        todo_wine CHECK_CALLED(Exec_SETDOWNLOADSTATE_0);
+        if (use_container_olecmd) todo_wine CHECK_CALLED(Exec_SETDOWNLOADSTATE_0);
         todo_wine CHECK_CALLED(Invoke_COMMANDSTATECHANGE);
    }
 
@@ -2343,7 +2383,7 @@ static void test_Navigate2(IUnknown *unk)
         SET_EXPECT(Invoke_PROPERTYCHANGE);
         SET_EXPECT(Invoke_BEFORENAVIGATE2);
         SET_EXPECT(Invoke_DOWNLOADBEGIN);
-        SET_EXPECT(Exec_SETDOWNLOADSTATE_1);
+        if (use_container_olecmd) SET_EXPECT(Exec_SETDOWNLOADSTATE_1);
         SET_EXPECT(EnableModeless_FALSE);
         SET_EXPECT(Invoke_STATUSTEXTCHANGE);
         SET_EXPECT(SetStatusText);
@@ -2353,14 +2393,15 @@ static void test_Navigate2(IUnknown *unk)
         SET_EXPECT(Invoke_AMBIENT_PALETTE);
         SET_EXPECT(GetOptionKeyPath);
         SET_EXPECT(GetOverridesKeyPath);
-        SET_EXPECT(QueryStatus_SETPROGRESSTEXT);
-        SET_EXPECT(Exec_SETPROGRESSMAX);
-        SET_EXPECT(Exec_SETPROGRESSPOS);
+        if (use_container_olecmd) SET_EXPECT(QueryStatus_SETPROGRESSTEXT);
+        if (use_container_olecmd) SET_EXPECT(Exec_SETPROGRESSMAX);
+        if (use_container_olecmd) SET_EXPECT(Exec_SETPROGRESSPOS);
         SET_EXPECT(Invoke_SETSECURELOCKICON);
         SET_EXPECT(Invoke_FILEDOWNLOAD);
-        SET_EXPECT(Exec_SETDOWNLOADSTATE_0);
+        if (use_container_olecmd) SET_EXPECT(Exec_SETDOWNLOADSTATE_0);
         SET_EXPECT(Invoke_COMMANDSTATECHANGE);
         SET_EXPECT(EnableModeless_TRUE);
+        if (!use_container_olecmd) SET_EXPECT(Invoke_DOWNLOADCOMPLETE);
     }
 
     hres = IWebBrowser2_Navigate2(webbrowser, &url, NULL, NULL, NULL, NULL);
@@ -2371,7 +2412,7 @@ static void test_Navigate2(IUnknown *unk)
         todo_wine CHECK_CALLED(Invoke_PROPERTYCHANGE);
         CHECK_CALLED(Invoke_BEFORENAVIGATE2);
         todo_wine CHECK_CALLED(Invoke_DOWNLOADBEGIN);
-        todo_wine CHECK_CALLED(Exec_SETDOWNLOADSTATE_1);
+        if (use_container_olecmd) todo_wine CHECK_CALLED(Exec_SETDOWNLOADSTATE_1);
         CHECK_CALLED(EnableModeless_FALSE);
         CHECK_CALLED(Invoke_STATUSTEXTCHANGE);
         CHECK_CALLED(SetStatusText);
@@ -2381,13 +2422,13 @@ static void test_Navigate2(IUnknown *unk)
         CHECK_CALLED(Invoke_AMBIENT_PALETTE);
         CHECK_CALLED(GetOptionKeyPath);
         CHECK_CALLED(GetOverridesKeyPath);
-        todo_wine CHECK_CALLED(QueryStatus_SETPROGRESSTEXT);
-        todo_wine CHECK_CALLED(Exec_SETPROGRESSMAX);
-        todo_wine CHECK_CALLED(Exec_SETPROGRESSPOS);
+        if (use_container_olecmd) todo_wine CHECK_CALLED(QueryStatus_SETPROGRESSTEXT);
+        if (use_container_olecmd) todo_wine CHECK_CALLED(Exec_SETPROGRESSMAX);
+        if (use_container_olecmd) todo_wine CHECK_CALLED(Exec_SETPROGRESSPOS);
         todo_wine CHECK_CALLED(Invoke_SETSECURELOCKICON);
         todo_wine CHECK_CALLED(Invoke_FILEDOWNLOAD);
         todo_wine CHECK_CALLED(Invoke_COMMANDSTATECHANGE);
-        todo_wine CHECK_CALLED(Exec_SETDOWNLOADSTATE_0);
+        if (use_container_olecmd) todo_wine CHECK_CALLED(Exec_SETDOWNLOADSTATE_0);
         CHECK_CALLED(EnableModeless_TRUE);
     }
 
@@ -2397,6 +2438,84 @@ static void test_Navigate2(IUnknown *unk)
     test_ready_state(READYSTATE_LOADING);
 }
 
+static void test_QueryStatusWB(IWebBrowser2 *webbrowser, BOOL use_custom_target, BOOL has_document)
+{
+    HRESULT hres, success_state;
+    OLECMDF success_flags;
+    enum OLECMDF status;
+
+    /*
+     * We can tell the difference between the custom container target and the built-in target
+     * since the custom target returns OLECMDF_SUPPORTED instead of OLECMDF_ENABLED.
+     */
+    if (use_custom_target)
+        success_flags = OLECMDF_SUPPORTED;
+    else
+        success_flags = OLECMDF_ENABLED;
+
+    /* When no target is available (no document or custom target) an error is returned */
+    if (has_document)
+        success_state = S_OK;
+    else
+        success_state = E_UNEXPECTED;
+
+    /*
+     * Test a safe operation that exists as both a high-numbered MSHTML id and an OLECMDID.
+     * These tests show that QueryStatusWB uses a NULL pguidCmdGroup, since OLECMDID_STOP
+     * is enabled and IDM_STOP is not.
+     */
+    status = 0xdeadbeef;
+    if (use_custom_target) SET_EXPECT(QueryStatus_STOP);
+    hres = IWebBrowser2_QueryStatusWB(webbrowser, OLECMDID_STOP, &status);
+    ok(hres == success_state, "QueryStatusWB failed: %08x %08x\n", hres, success_state);
+    if (!use_custom_target && has_document)
+        todo_wine ok((has_document && status == success_flags) || (!has_document && status == 0xdeadbeef),
+                     "OLECMDID_STOP not enabled/supported: %08x %08x\n", status, success_flags);
+    else
+        ok((has_document && status == success_flags) || (!has_document && status == 0xdeadbeef),
+           "OLECMDID_STOP not enabled/supported: %08x %08x\n", status, success_flags);
+    status = 0xdeadbeef;
+    if (use_custom_target) SET_EXPECT(QueryStatus_IDM_STOP);
+    hres = IWebBrowser2_QueryStatusWB(webbrowser, IDM_STOP, &status);
+    ok(hres == success_state, "QueryStatusWB failed: %08x %08x\n", hres, success_state);
+    ok((has_document && status == 0) || (!has_document && status == 0xdeadbeef),
+       "IDM_STOP is enabled/supported: %08x %d\n", status, has_document);
+}
+
+static void test_ExecWB(IWebBrowser2 *webbrowser, BOOL use_custom_target, BOOL has_document)
+{
+    HRESULT hres, olecmdid_state, idm_state;
+
+    /* When no target is available (no document or custom target) an error is returned */
+    if (has_document)
+    {
+        olecmdid_state = S_OK;
+        idm_state = OLECMDERR_E_NOTSUPPORTED;
+    }
+    else
+    {
+        olecmdid_state = E_UNEXPECTED;
+        idm_state = E_UNEXPECTED;
+    }
+
+    /*
+     * Test a safe operation that exists as both a high-numbered MSHTML id and an OLECMDID.
+     * These tests show that QueryStatusWB uses a NULL pguidCmdGroup, since OLECMDID_STOP
+     * succeeds (S_OK) and IDM_STOP does not (OLECMDERR_E_NOTSUPPORTED).
+     */
+    if (use_custom_target)
+        SET_EXPECT(Exec_STOP);
+    hres = IWebBrowser2_ExecWB(webbrowser, OLECMDID_STOP, OLECMDEXECOPT_DONTPROMPTUSER, 0, 0);
+    if (!use_custom_target && has_document)
+        todo_wine ok(hres == olecmdid_state, "ExecWB failed: %08x %08x\n", hres, olecmdid_state);
+    else
+        ok(hres == olecmdid_state, "ExecWB failed: %08x %08x\n", hres, olecmdid_state);
+    if (use_custom_target)
+        SET_EXPECT(Exec_IDM_STOP);
+    hres = IWebBrowser2_ExecWB(webbrowser, IDM_STOP, OLECMDEXECOPT_DONTPROMPTUSER, 0, 0);
+    ok(hres == idm_state, "ExecWB failed: %08x %08x\n", hres, idm_state);
+}
+
 static void test_download(DWORD flags)
 {
     MSG msg;
@@ -2854,16 +2973,18 @@ static void test_WebBrowser(BOOL do_download)
     ULONG ref;
     HRESULT hres;
 
-    hres = CoCreateInstance(&CLSID_WebBrowser, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
-            &IID_IUnknown, (void**)&unk);
-    ok(hres == S_OK, "Creating WebBrowser object failed: %08x\n", hres);
+    if (FAILED(create_WebBrowser(&unk)))
+        return;
 
     is_downloading = FALSE;
     is_first_load = TRUE;
+    use_container_olecmd = TRUE;
 
     hres = IUnknown_QueryInterface(unk, &IID_IWebBrowser2, (void**)&wb);
     ok(hres == S_OK, "Could not get IWebBrowser2 iface: %08x\n", hres);
 
+    test_QueryStatusWB(wb, FALSE, FALSE);
+    test_ExecWB(wb, FALSE, FALSE);
     test_QueryInterface(unk);
     test_ready_state(READYSTATE_UNINITIALIZED);
     test_ClassInfo(unk);
@@ -2875,6 +2996,8 @@ static void test_WebBrowser(BOOL do_download)
     test_DoVerb(unk);
     test_olecmd(unk, FALSE);
     test_Navigate2(unk);
+    test_QueryStatusWB(wb, TRUE, TRUE);
+    test_ExecWB(wb, TRUE, TRUE);
 
     if(do_download) {
         IDispatch *doc, *doc2;
@@ -2912,6 +3035,40 @@ static void test_WebBrowser(BOOL do_download)
     ok(ref == 0, "ref=%d, expected 0\n", ref);
 }
 
+static void test_WebBrowser_NoContainerOlecmd(void)
+{
+    IUnknown *unk = NULL;
+    HRESULT hres;
+    ULONG ref;
+
+    is_downloading = FALSE;
+    is_first_load = TRUE;
+    use_container_olecmd = FALSE;
+
+    /* Setup stage */
+    if (FAILED(create_WebBrowser(&unk)))
+        return;
+    hres = IUnknown_QueryInterface(unk, &IID_IWebBrowser2, (void**)&wb);
+    ok(hres == S_OK, "QueryInterface(IID_IWebBrowser) failed: %08x\n", hres);
+    if(FAILED(hres))
+        return;
+    test_ConnectionPoint(unk, TRUE);
+    test_ClientSite(unk, &ClientSite, TRUE);
+    test_DoVerb(unk);
+    test_Navigate2(unk);
+
+    /* Tests of interest */
+    test_QueryStatusWB(wb, FALSE, TRUE);
+    test_ExecWB(wb, FALSE, TRUE);
+
+    /* Cleanup stage */
+    IWebBrowser2_Release(wb);
+    test_ClientSite(unk, NULL, TRUE);
+    test_ConnectionPoint(unk, FALSE);
+    ref = IUnknown_Release(unk);
+    ok(ref == 0, "ref=%d, expected 0\n", ref);
+}
+
 static BOOL check_ie(void)
 {
     IHTMLDocument5 *doc;
@@ -2937,6 +3094,8 @@ START_TEST(webbrowser)
       test_WebBrowser(FALSE);
       trace("Testing WebBrowser...\n");
       test_WebBrowser(TRUE);
+      trace("Testing WebBrowser w/o container-based olecmd...\n");
+      test_WebBrowser_NoContainerOlecmd();
     }else {
       win_skip("Skipping tests on too old IE\n");
     }
index 1a0e189d02b66ba05c0753b9193badf4fe248dc9..a0a8020719d1d9257c5d6a1bf796e88a92b3e962 100644 (file)
@@ -780,16 +780,75 @@ static HRESULT WINAPI WebBrowser_Navigate2(IWebBrowser2 *iface, VARIANT *URL, VA
 static HRESULT WINAPI WebBrowser_QueryStatusWB(IWebBrowser2 *iface, OLECMDID cmdID, OLECMDF *pcmdf)
 {
     WebBrowser *This = impl_from_IWebBrowser2(iface);
-    FIXME("(%p)->(%d %p)\n", This, cmdID, pcmdf);
-    return E_NOTIMPL;
+    IOleCommandTarget *target = NULL;
+    OLECMD ole_command[1];
+    HRESULT hres;
+
+    TRACE("(%p)->(%d %p)\n", This, cmdID, pcmdf);
+
+    if (!pcmdf)
+        return E_POINTER;
+    ole_command[0].cmdID = cmdID;
+    ole_command[0].cmdf = *pcmdf;
+
+    if (This->container)
+    {
+        hres = IOleContainer_QueryInterface(This->container, &IID_IOleCommandTarget, (LPVOID*)&target);
+        if(FAILED(hres))
+            target = NULL;
+    }
+    if (!target && This->doc_host.document)
+    {
+        hres = IOleContainer_QueryInterface(This->doc_host.document, &IID_IOleCommandTarget, (LPVOID*)&target);
+        if(FAILED(hres))
+            target = NULL;
+    }
+
+    if (!target)
+        return E_UNEXPECTED;
+
+    hres = IOleCommandTarget_QueryStatus(target, NULL, 1, ole_command, NULL);
+    if (SUCCEEDED(hres))
+        *pcmdf = ole_command[0].cmdf;
+    if (hres == OLECMDERR_E_NOTSUPPORTED)
+    {
+        *pcmdf = 0;
+        hres = S_OK;
+    }
+    IOleCommandTarget_Release(target);
+
+    return hres;
 }
 
 static HRESULT WINAPI WebBrowser_ExecWB(IWebBrowser2 *iface, OLECMDID cmdID,
         OLECMDEXECOPT cmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
 {
     WebBrowser *This = impl_from_IWebBrowser2(iface);
-    FIXME("(%p)->(%d %d %s %p)\n", This, cmdID, cmdexecopt, debugstr_variant(pvaIn), pvaOut);
-    return E_NOTIMPL;
+    IOleCommandTarget *target = NULL;
+    HRESULT hres;
+
+    TRACE("(%p)->(%d %d %s %p)\n", This, cmdID, cmdexecopt, debugstr_variant(pvaIn), pvaOut);
+
+    if(This->container)
+    {
+        hres = IOleContainer_QueryInterface(This->container, &IID_IOleCommandTarget, (LPVOID*)&target);
+        if(FAILED(hres))
+            target = NULL;
+    }
+    if(!target && This->doc_host.document)
+    {
+        hres = IOleContainer_QueryInterface(This->doc_host.document, &IID_IOleCommandTarget, (LPVOID*)&target);
+        if(FAILED(hres))
+            target = NULL;
+    }
+
+    if(!target)
+        return E_UNEXPECTED;
+
+    hres = IOleCommandTarget_Exec(target, NULL, cmdID, cmdexecopt, pvaIn, pvaOut);
+    IOleCommandTarget_Release(target);
+
+    return hres;
 }
 
 static HRESULT WINAPI WebBrowser_ShowBrowserBar(IWebBrowser2 *iface, VARIANT *pvaClsid,