|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Implementation of the CVCommandRunnable class |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include <vcommandapi.h> |
|
21 #include "rubydebug.h" |
|
22 |
|
23 #include <apaid.h> |
|
24 #include <apgcli.h> |
|
25 #include <apacmdln.h> |
|
26 #include <apgtask.h> |
|
27 #include <eikappui.h> |
|
28 |
|
29 /** |
|
30 * The version of the streamed data protocol |
|
31 * It is rather likely, that the format of the data streamed changes in the future. |
|
32 * Using the protocol version, the code can check if it knows how to parse the |
|
33 * input stream |
|
34 */ |
|
35 const TInt32 KVCRunnableProtocolVersion = 2; |
|
36 |
|
37 /** |
|
38 * @leave KErrOverflow if aArguments is longer, than KMaxVCArgumentLength |
|
39 * @leave KErrArgument if aAppUid is KNullUidValue |
|
40 */ |
|
41 EXPORT_C CVCRunnable* CVCRunnable::NewL( TUid aAppUid, const TDesC8& aArguments ) |
|
42 { |
|
43 CVCRunnable* self = new ( ELeave ) CVCRunnable; |
|
44 CleanupStack::PushL( self ); |
|
45 self->ConstructL( aAppUid, aArguments ); |
|
46 CleanupStack::Pop( self ); |
|
47 return self; |
|
48 } |
|
49 |
|
50 /** |
|
51 * Factory function |
|
52 * @param aExeName Exe-file to start. Can be full or partical name according to |
|
53 * the RProcess::Create rules. Cannot be KNullDesC |
|
54 * @param aArguments Command line to pass to the application. This object makes |
|
55 * a copy of the passed string |
|
56 * @leave KErrOverflow if aArguments is longer, than KMaxVCArgumentLength or |
|
57 * aExeName is longer, than KMaxOsName |
|
58 * @leave KErrUndeflow if aExeName is empty |
|
59 */ |
|
60 EXPORT_C CVCRunnable* CVCRunnable::NewL( const TDesC& aExeName, const TDesC8& aArguments ) |
|
61 { |
|
62 CVCRunnable* self = new( ELeave ) CVCRunnable; |
|
63 CleanupStack::PushL( self ); |
|
64 self->ConstructL( aExeName, aArguments); |
|
65 CleanupStack::Pop( self ); |
|
66 return self; |
|
67 } |
|
68 |
|
69 /** |
|
70 * Copy the existing CVRunnable |
|
71 */ |
|
72 EXPORT_C CVCRunnable* CVCRunnable::NewL( const CVCRunnable& aOriginal ) |
|
73 { |
|
74 CVCRunnable* self = new (ELeave) CVCRunnable; |
|
75 CleanupStack::PushL( self ); |
|
76 if( aOriginal.Uid() == KNullUid ) |
|
77 { |
|
78 self->ConstructL( aOriginal.ExeName(), aOriginal.Arguments() ); |
|
79 } |
|
80 else |
|
81 { |
|
82 self->ConstructL( aOriginal.Uid(), aOriginal.Arguments() ); |
|
83 } |
|
84 CleanupStack::Pop( self ); |
|
85 return self; |
|
86 } |
|
87 |
|
88 /** |
|
89 * Internalizes from stream |
|
90 * values are read in the same order as ExternalizeL wrote them |
|
91 */ |
|
92 EXPORT_C CVCRunnable* CVCRunnable::NewL( RReadStream &aStream ) |
|
93 { |
|
94 CVCRunnable* self = new (ELeave) CVCRunnable; |
|
95 CleanupStack::PushL( self ); |
|
96 self->ConstructL( aStream ); |
|
97 CleanupStack::Pop( self ); |
|
98 return self; |
|
99 } |
|
100 |
|
101 void CVCRunnable::ConstructL( RReadStream &aStream ) |
|
102 { |
|
103 TInt32 ver; |
|
104 aStream >> ver; |
|
105 __ASSERT_ALWAYS( ver == KVCRunnableProtocolVersion, User::Leave( KErrNotSupported ) ); |
|
106 iExeUid = TUid::Uid( aStream.ReadInt32L() ); |
|
107 iArguments = HBufC8::NewL( aStream.ReadInt32L() ); |
|
108 TPtr8 pArguments = iArguments->Des(); |
|
109 aStream >> pArguments; |
|
110 TInt exeNameLength = aStream.ReadInt32L(); |
|
111 if( exeNameLength > 0 ) |
|
112 { |
|
113 iExeName = HBufC::NewL( exeNameLength ); |
|
114 TPtr pExeName = iExeName->Des(); |
|
115 aStream >> pExeName; |
|
116 } |
|
117 } |
|
118 |
|
119 void CVCRunnable::ConstructL( TUid aAppUid, const TDesC8& aArguments ) |
|
120 { |
|
121 __ASSERT_ALWAYS( aArguments.Length() <= KMaxVCArgumentLength, User::Leave( KErrOverflow) ); |
|
122 __ASSERT_ALWAYS( aAppUid != KNullUid, User::Leave( KErrArgument ) ); |
|
123 iExeUid = TUid::Uid( aAppUid.iUid ); |
|
124 iArguments = HBufC8::NewL( aArguments.Length() ); |
|
125 *iArguments = aArguments; |
|
126 } |
|
127 |
|
128 void CVCRunnable::ConstructL( const TDesC& aExeName, const TDesC8& aArguments ) |
|
129 { |
|
130 __ASSERT_ALWAYS( aArguments.Length() <= KMaxVCArgumentLength, User::Leave( KErrOverflow) ); |
|
131 __ASSERT_ALWAYS( aExeName.Length() <= KMaxFileName, User::Leave( KErrOverflow ) ); |
|
132 __ASSERT_ALWAYS( aExeName.Length() > 0, User::Leave( KErrUnderflow ) ); |
|
133 iExeName = HBufC::NewL( aExeName.Length() ); |
|
134 *iExeName = aExeName; |
|
135 iArguments = HBufC8::NewL( aArguments.Length() ); |
|
136 *iArguments = aArguments; |
|
137 } |
|
138 |
|
139 EXPORT_C CVCRunnable::~CVCRunnable() |
|
140 { |
|
141 delete iExeName; |
|
142 delete iArguments; |
|
143 } |
|
144 |
|
145 /** |
|
146 * Saves the object to stream. |
|
147 * The current format is as follows: |
|
148 * <protocol version: int32><uid: int32; KNullUidValue if no><argument length: int32> |
|
149 * <argument descriptor streamed by the default descriptor ExternalizeL> |
|
150 * <exe filename length><exe filename descriptor only if filename length is not 0> |
|
151 */ |
|
152 EXPORT_C void CVCRunnable::ExternalizeL( RWriteStream &aStream ) const |
|
153 { |
|
154 aStream << KVCRunnableProtocolVersion; |
|
155 aStream << iExeUid.iUid; |
|
156 aStream << static_cast<TInt32>( iArguments->Length() ); |
|
157 aStream << *iArguments; |
|
158 if( iExeName ) |
|
159 { |
|
160 aStream << static_cast<TInt32>( iExeName->Length() ); |
|
161 aStream << *iExeName; |
|
162 } |
|
163 else |
|
164 { |
|
165 aStream << static_cast<TInt32>( 0 ); |
|
166 } |
|
167 } |
|
168 |
|
169 EXPORT_C TBool CVCRunnable::operator==( const CVCRunnable& aRunnable ) const |
|
170 { |
|
171 return ( |
|
172 ( Uid() == aRunnable.Uid()) && |
|
173 ( Arguments() == aRunnable.Arguments() ) && |
|
174 ( ExeName() == aRunnable.ExeName() ) |
|
175 ); |
|
176 } |
|
177 |
|
178 |
|
179 /** |
|
180 * @return The uid of the application to be started |
|
181 */ |
|
182 EXPORT_C const TUid CVCRunnable::Uid() const |
|
183 { |
|
184 return iExeUid; |
|
185 } |
|
186 |
|
187 /** |
|
188 * @return The filename of the application to be started. KNullDesC if there is none |
|
189 */ |
|
190 EXPORT_C const TDesC& CVCRunnable::ExeName() const |
|
191 { |
|
192 if( iExeName ) |
|
193 { |
|
194 return *iExeName; |
|
195 } |
|
196 else |
|
197 { |
|
198 return KNullDesC; |
|
199 } |
|
200 } |
|
201 |
|
202 /** |
|
203 * The arguments to be passed to the application |
|
204 */ |
|
205 EXPORT_C const TDesC8& CVCRunnable::Arguments() const |
|
206 { |
|
207 return *iArguments; |
|
208 } |
|
209 |
|
210 /** |
|
211 * Run the command. In case of aAppUid specified during the construction |
|
212 * application is started via the RApaLsSession::StartApp, otherwise |
|
213 * via the RProcess::Create |
|
214 * @leave System-wide error code. In particular KErrNotFound if there is |
|
215 * no such app in the system |
|
216 */ |
|
217 EXPORT_C void CVCRunnable::ExecuteL() const |
|
218 { |
|
219 RUBY_DEBUG_BLOCK( "CVCRunnable::ExecuteL" ); |
|
220 if( iExeName ) |
|
221 { |
|
222 RProcess process; |
|
223 CleanupClosePushL( process ); |
|
224 // Convert arguments into system_number_of_bits-bit descriptor |
|
225 // (needed for exe, not needed for GUI apps) |
|
226 HBufC* arguments = HBufC::NewLC( iArguments->Length() ); |
|
227 arguments->Des().Copy( *iArguments ); |
|
228 |
|
229 User::LeaveIfError( process.Create( *iExeName, *arguments) ); |
|
230 process.Resume(); |
|
231 |
|
232 CleanupStack::PopAndDestroy( arguments ); |
|
233 CleanupStack::PopAndDestroy( &process ); |
|
234 } |
|
235 else |
|
236 { |
|
237 const TUid KLogsUID3 = { 270486741 };//101F4CD5 |
|
238 //In case logs.exe run in background [EDCN-84B68Q] |
|
239 //todo: General support for this kind of case, |
|
240 // eg, add "view" keyworkd in defaultvoicecommands.xml... |
|
241 if ( iExeUid == KLogsUID3 ) |
|
242 { |
|
243 TApaTaskList taskList( CCoeEnv::Static()->WsSession() ); |
|
244 TApaTask task = taskList.FindApp( iExeUid ); |
|
245 if( task.Exists() ) //Logs already open. Request it to |
|
246 { //activate the correct view |
|
247 task.SendMessage( iExeUid, *iArguments ); |
|
248 return; |
|
249 } |
|
250 } |
|
251 |
|
252 TApaAppInfo appInfo; |
|
253 RApaLsSession apaLsSession; |
|
254 CleanupClosePushL( apaLsSession ); |
|
255 User::LeaveIfError( apaLsSession.Connect() ); |
|
256 User::LeaveIfError( apaLsSession.GetAppInfo( appInfo, iExeUid ) ); |
|
257 |
|
258 CApaCommandLine* apaCommandLine = CApaCommandLine::NewLC(); |
|
259 apaCommandLine->SetExecutableNameL( appInfo.iFullName ); |
|
260 apaCommandLine->SetTailEndL( *iArguments ); |
|
261 User::LeaveIfError( apaLsSession.StartApp( *apaCommandLine ) ); |
|
262 |
|
263 CleanupStack::PopAndDestroy( apaCommandLine ); |
|
264 CleanupStack::PopAndDestroy( &apaLsSession ); |
|
265 } |
|
266 } |
|
267 |
|
268 //End of file |