1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "sal/config.h"
25 
26 #include "boost/noncopyable.hpp"
27 #include "com/sun/star/awt/AsyncCallback.hpp"
28 #include "com/sun/star/awt/XCallback.hpp"
29 #include "com/sun/star/beans/PropertyState.hpp"
30 #include "com/sun/star/beans/PropertyValue.hpp"
31 #include "com/sun/star/document/MacroExecMode.hpp"
32 #include "com/sun/star/frame/DispatchResultEvent.hpp"
33 #include "com/sun/star/frame/DispatchResultState.hpp"
34 #include "com/sun/star/frame/XComponentLoader.hpp"
35 #include "com/sun/star/frame/XController.hpp"
36 #include "com/sun/star/frame/XDispatchProvider.hpp"
37 #include "com/sun/star/frame/XDispatchResultListener.hpp"
38 #include "com/sun/star/frame/XModel.hpp"
39 #include "com/sun/star/frame/XNotifyingDispatch.hpp"
40 #include "com/sun/star/lang/EventObject.hpp"
41 #include "com/sun/star/uno/Any.hxx"
42 #include "com/sun/star/uno/Reference.hxx"
43 #include "com/sun/star/uno/RuntimeException.hpp"
44 #include "com/sun/star/uno/Sequence.hxx"
45 #include "com/sun/star/util/URL.hpp"
46 #include <preextstl.h>
47 #include "cppuhelper/implbase1.hxx"
48 #include "cppunit/TestAssert.h"
49 #include "cppunit/TestFixture.h"
50 #include "cppunit/extensions/HelperMacros.h"
51 #include "cppunit/plugin/TestPlugIn.h"
52 #include <postextstl.h>
53 #include "osl/conditn.hxx"
54 #include "osl/diagnose.h"
55 #include "rtl/ustring.h"
56 #include "rtl/ustring.hxx"
57 #include "test/gettestargument.hxx"
58 #include "test/officeconnection.hxx"
59 #include "test/oustringostreaminserter.hxx"
60 #include "test/toabsolutefileurl.hxx"
61 
62 namespace {
63 
64 namespace css = com::sun::star;
65 
66 struct Result: private boost::noncopyable {
67     osl::Condition condition;
68     bool success;
69     rtl::OUString result;
70 };
71 
72 class Listener:
73     public cppu::WeakImplHelper1< css::frame::XDispatchResultListener >
74 {
75 public:
76     Listener(Result * result): result_(result) { OSL_ASSERT(result != 0); }
77 
78 private:
79     virtual void SAL_CALL disposing(css::lang::EventObject const &)
80         throw (css::uno::RuntimeException) {}
81 
82     virtual void SAL_CALL dispatchFinished(
83         css::frame::DispatchResultEvent const & Result)
84         throw (css::uno::RuntimeException);
85 
86     Result * result_;
87 };
88 
89 void Listener::dispatchFinished(css::frame::DispatchResultEvent const & Result)
90     throw (css::uno::RuntimeException)
91 {
92     result_->success =
93         (Result.State == css::frame::DispatchResultState::SUCCESS) &&
94         (Result.Result >>= result_->result);
95     result_->condition.set();
96 }
97 
98 class Callback: public cppu::WeakImplHelper1< css::awt::XCallback > {
99 public:
100     Callback(
101         css::uno::Reference< css::frame::XNotifyingDispatch > const & dispatch,
102         css::util::URL const & url,
103         css::uno::Sequence< css::beans::PropertyValue > const & arguments,
104         css::uno::Reference< css::frame::XDispatchResultListener > const &
105             listener):
106         dispatch_(dispatch), url_(url), arguments_(arguments),
107         listener_(listener)
108     { OSL_ASSERT(dispatch.is()); }
109 
110 private:
111     virtual void SAL_CALL notify(css::uno::Any const &)
112         throw (css::uno::RuntimeException)
113     { dispatch_->dispatchWithNotification(url_, arguments_, listener_); }
114 
115     css::uno::Reference< css::frame::XNotifyingDispatch > dispatch_;
116     css::util::URL url_;
117     css::uno::Sequence< css::beans::PropertyValue > arguments_;
118     css::uno::Reference< css::frame::XDispatchResultListener > listener_;
119 };
120 
121 class Test: public CppUnit::TestFixture {
122 public:
123     virtual void setUp();
124 
125     virtual void tearDown();
126 
127 private:
128     CPPUNIT_TEST_SUITE(Test);
129     CPPUNIT_TEST(test);
130     CPPUNIT_TEST_SUITE_END();
131 
132     void test();
133 
134     test::OfficeConnection connection_;
135 };
136 
137 void Test::setUp() {
138     connection_.setUp();
139 }
140 
141 void Test::tearDown() {
142     connection_.tearDown();
143 }
144 
145 void Test::test() {
146     rtl::OUString doc;
147     CPPUNIT_ASSERT(
148         test::getTestArgument(
149             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("smoketest.doc")), &doc));
150     css::uno::Sequence< css::beans::PropertyValue > args(2);
151     args[0].Name = rtl::OUString(
152         RTL_CONSTASCII_USTRINGPARAM("MacroExecutionMode"));
153     args[0].Handle = -1;
154     args[0].Value <<=
155         com::sun::star::document::MacroExecMode::ALWAYS_EXECUTE_NO_WARN;
156     args[0].State = css::beans::PropertyState_DIRECT_VALUE;
157     args[1].Name = rtl::OUString(
158         RTL_CONSTASCII_USTRINGPARAM("ReadOnly"));
159     args[1].Handle = -1;
160     args[1].Value <<= sal_True;
161     args[1].State = css::beans::PropertyState_DIRECT_VALUE;
162     css::util::URL url;
163     url.Complete = rtl::OUString(
164         RTL_CONSTASCII_USTRINGPARAM(
165             "vnd.sun.star.script:Standard.Global.StartTestWithDefaultOptions?"
166             "language=Basic&location=document"));
167     css::uno::Reference< css::frame::XNotifyingDispatch > disp(
168         css::uno::Reference< css::frame::XDispatchProvider >(
169             css::uno::Reference< css::frame::XController >(
170                 css::uno::Reference< css::frame::XModel >(
171                     css::uno::Reference< css::frame::XComponentLoader >(
172                         (connection_.getComponentContext()->
173                          getServiceManager()->createInstanceWithContext(
174                              rtl::OUString(
175                                  RTL_CONSTASCII_USTRINGPARAM(
176                                      "com.sun.star.frame.Desktop")),
177                              connection_.getComponentContext())),
178                         css::uno::UNO_QUERY_THROW)->loadComponentFromURL(
179                             test::toAbsoluteFileUrl(doc),
180                             rtl::OUString(
181                                 RTL_CONSTASCII_USTRINGPARAM("_default")),
182                             0, args),
183                     css::uno::UNO_QUERY_THROW)->getCurrentController(),
184                 css::uno::UNO_SET_THROW)->getFrame(),
185             css::uno::UNO_QUERY_THROW)->queryDispatch(
186                 url, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_self")), 0),
187         css::uno::UNO_QUERY_THROW);
188     Result result;
189     // Shifted to main thread to work around potential deadlocks (i112867):
190     com::sun::star::awt::AsyncCallback::create(
191         connection_.getComponentContext())->addCallback(
192             new Callback(
193                 disp, url, css::uno::Sequence< css::beans::PropertyValue >(),
194                 new Listener(&result)),
195             css::uno::Any());
196     result.condition.wait();
197     CPPUNIT_ASSERT(result.success);
198     CPPUNIT_ASSERT_EQUAL(rtl::OUString(), result.result);
199 }
200 
201 CPPUNIT_TEST_SUITE_REGISTRATION(Test);
202 
203 }
204 
205 CPPUNIT_PLUGIN_IMPLEMENT();
206