1 /* |
|
2 * Copyright (c) 2000 - 2001 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 the License "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: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "nw_hypertext_aelementhandleri.h" |
|
20 |
|
21 #include "nw_xhtml_xhtmlcontenthandler.h" |
|
22 #include "nw_hed_hedeventhandler.h" |
|
23 #include "nw_hed_documentroot.h" |
|
24 #include "nw_lmgr_activecontainerbox.h" |
|
25 #include "nw_lmgr_textbox.h" |
|
26 #include "nw_evt_activateevent.h" |
|
27 #include "nw_evt_accesskeyevent.h" |
|
28 #include "nw_xhtml_savetophonebkevent.h" |
|
29 #include "nw_evt_focusevent.h" |
|
30 #include "nw_xhtml_xhtml_1_0_tokens.h" |
|
31 #include "nw_xhtml_telephonyservices.h" |
|
32 #include "nw_xhtml_textelementhandler.h" |
|
33 #include "nw_image_imgelementhandler.h" |
|
34 #include "nw_wmlscriptch_wmlscriptcontenthandler.h" /* to run Wml Scripts */ |
|
35 #include "nwx_url_utils.h" |
|
36 #include "nwx_http_defs.h" |
|
37 //#include "nw_ecma_contenthandler.h" |
|
38 #include "BrsrStatusCodes.h" |
|
39 #include "nwx_logger.h" |
|
40 |
|
41 /* ------------------------------------------------------------------------- */ |
|
42 static |
|
43 NW_LMgr_Box_t* |
|
44 NW_XHTML_aElementHandler_ImodeCreateBox(const NW_XHTML_ElementHandler_t* elementHandler, |
|
45 NW_XHTML_ContentHandler_t* contentHandler, |
|
46 NW_DOM_ElementNode_t* elementNode) |
|
47 { |
|
48 NW_Text_t* ctiVal = NULL; |
|
49 NW_Text_t* hrefVal = NULL; |
|
50 NW_Text_t* nameVal = NULL; |
|
51 NW_LMgr_ActiveContainerBox_t* box = NULL; |
|
52 NW_Bool validNumber = NW_FALSE; |
|
53 NW_Ucs2* storage = NULL; |
|
54 NW_Uint8 freeNeeded = NW_FALSE; |
|
55 NW_Text_Length_t charCount; |
|
56 NW_XHTML_TelephonyServices_t* telServices = NULL; |
|
57 NW_HED_EventHandler_t* eventHandler = NULL; |
|
58 NW_Ucs2* newUrl = NULL; |
|
59 NW_Ucs2 *chReturns = NULL; |
|
60 NW_Bool createBox = NW_FALSE; |
|
61 NW_LMgr_ActiveContainerBox_ActionType_t actionType = NW_LMgr_ActionType_OpenLink; |
|
62 |
|
63 NW_REQUIRED_PARAM(elementHandler); |
|
64 |
|
65 telServices = (NW_XHTML_TelephonyServices_t*)(&NW_XHTML_TelephonyServices); |
|
66 |
|
67 // Find the 'name' attribute and get its string value. The name is used below |
|
68 // if HREF is not specified and it is also used for ECMA script processing. |
|
69 NW_XHTML_GetDOMAttribute (contentHandler, elementNode, NW_XHTML_AttributeToken_name, &nameVal); |
|
70 |
|
71 /* find the 'cti' attribute and get its string value */ |
|
72 NW_XHTML_GetDOMAttribute(contentHandler, elementNode, |
|
73 NW_XHTML_AttributeToken_cti, &ctiVal); |
|
74 if (ctiVal) |
|
75 { |
|
76 storage = (NW_Ucs2*) NW_Text_GetUCS2Buffer(ctiVal, NW_Text_Flags_Aligned,&charCount, |
|
77 &freeNeeded); |
|
78 if (!storage) |
|
79 { |
|
80 goto cleanup; |
|
81 } |
|
82 |
|
83 validNumber = NW_XHTML_TelephonyServices_ParseNumber(telServices, storage, NW_TRUE); |
|
84 |
|
85 if (storage && freeNeeded) |
|
86 { |
|
87 NW_Str_Delete(storage); |
|
88 storage = NULL; |
|
89 } |
|
90 |
|
91 if (validNumber) |
|
92 { |
|
93 eventHandler = NW_HED_EventHandler_New(NW_HED_DocumentNodeOf (contentHandler), elementNode); |
|
94 box = NW_LMgr_ActiveContainerBox_New(0, NW_LMgr_EventHandlerOf (eventHandler), NW_LMgr_ActionType_DialNumber); |
|
95 if (box) |
|
96 { |
|
97 NW_LMgr_ActiveContainerBox_SetName(box, nameVal, NW_TRUE); |
|
98 nameVal = NULL; // ownership of name object was transferred to box |
|
99 } |
|
100 goto cleanup; |
|
101 } |
|
102 } |
|
103 |
|
104 /* find the 'href' attribute and get its string value */ |
|
105 NW_XHTML_GetDOMAttribute (contentHandler, elementNode, NW_XHTML_AttributeToken_href, &hrefVal); |
|
106 if (hrefVal == NULL) |
|
107 { |
|
108 /* if href is not specified in <a>, use base tag url, unless a name attribute is specified. |
|
109 Because if a name tag is specifed but not an href, this <a> element means to be only a fragment |
|
110 identifier. */ |
|
111 if (nameVal == NULL) |
|
112 { |
|
113 NW_XHTML_aElementHandler_getBaseTagUrl (contentHandler, &hrefVal); |
|
114 } |
|
115 } |
|
116 |
|
117 if (hrefVal) |
|
118 { |
|
119 NW_Url_Schema_t scheme = NW_SCHEMA_INVALID; |
|
120 NW_Ucs2* number; |
|
121 |
|
122 storage = (NW_Ucs2*) NW_Text_GetUCS2Buffer(hrefVal, NW_Text_Flags_Aligned, &charCount, |
|
123 &freeNeeded); |
|
124 if (!storage) |
|
125 { |
|
126 goto cleanup; |
|
127 } |
|
128 |
|
129 /* At this point, only interested if a scheme is present, not if the URL |
|
130 complies with RFC2396. If there is a problem with the URL, it will be |
|
131 caught later, when the anchor is selected. The philosophy is to present |
|
132 everything to the user, except scheme=NW_SCHEMA_INVALID for TEL: and MAILTO: |
|
133 */ |
|
134 NW_Url_GetSchemeNoValidation(storage, &scheme); |
|
135 |
|
136 // remove cariage return and new line from url |
|
137 chReturns = NW_Str_New (2); |
|
138 chReturns[0] = 0x0D; |
|
139 chReturns[1] = 0x0A; |
|
140 chReturns[2] = '\0'; |
|
141 |
|
142 NW_LOG1( NW_LOG_OFF, "before removing, storage: %s", storage ); |
|
143 newUrl = NW_Str_New(NW_Url_RemoveCharsLen(storage, chReturns)); |
|
144 if (!newUrl) |
|
145 { |
|
146 goto cleanup; |
|
147 } |
|
148 NW_Url_RemoveChars(storage, newUrl, chReturns); |
|
149 |
|
150 // Validate the TEL:, WTAI:, MAILTO: schemes, all other schemes just get created. |
|
151 // Also, set the corresponding action type for the shemes. |
|
152 if (scheme == NW_SCHEMA_TEL) |
|
153 { |
|
154 // For "TEL:" scheme, verify the number, i.e. "TEL:8005551234" |
|
155 number = newUrl + 4; |
|
156 validNumber = NW_XHTML_TelephonyServices_ParseNumber(telServices, number, NW_FALSE); |
|
157 actionType = NW_LMgr_ActionType_DialNumber; |
|
158 // Create box for the anchor <a> link if and only if "TEL:" number format is valid. |
|
159 createBox = validNumber; |
|
160 } |
|
161 else if (scheme == NW_SCHEMA_WTAI) |
|
162 { |
|
163 // For "WTAI:" scheme, verify the number, i.e. "WTAI://wp/mc;8005551234" |
|
164 number = newUrl + 13; |
|
165 validNumber = NW_XHTML_TelephonyServices_ParseNumber(telServices, number, NW_FALSE); |
|
166 actionType = NW_LMgr_ActionType_DialNumber; |
|
167 // Create the box for the anchor <a> link if and only if "WTAI://wp/mc" number format is valid. |
|
168 createBox = validNumber; |
|
169 } |
|
170 else if (scheme == NW_SCHEMA_MAILTO) |
|
171 { |
|
172 // For "MAILTO" scheme, no verification. Assume it is valid. |
|
173 actionType = NW_LMgr_ActionType_SendMail; |
|
174 // Since there is no validation, always create the box. |
|
175 createBox = NW_TRUE; |
|
176 } |
|
177 else |
|
178 { |
|
179 // Create an anchor for all other schemas (http, https, file, |
|
180 // etc...), including: |
|
181 // NW_SCHEMA_UNKNOWN - Unknown schemes contain a colon, but aren't |
|
182 // in the limited supported list. They need to be displayed |
|
183 // anyhow, because some application might support it (plugin, |
|
184 // sms, mms, etc...). |
|
185 // NW_SCHEMA_INVALID - Probably a relative link. |
|
186 actionType = NW_LMgr_ActionType_OpenLink; |
|
187 // Always create the box. |
|
188 createBox = NW_TRUE; |
|
189 } |
|
190 |
|
191 if (createBox) |
|
192 { |
|
193 // Create the box for the anchor <a> link. |
|
194 eventHandler = NW_HED_EventHandler_New (NW_HED_DocumentNodeOf (contentHandler), elementNode); |
|
195 box = NW_LMgr_ActiveContainerBox_New(0, NW_LMgr_EventHandlerOf (eventHandler), actionType); |
|
196 if (box) |
|
197 { |
|
198 NW_LMgr_ActiveContainerBox_SetName(box, nameVal, NW_TRUE); |
|
199 nameVal = NULL; // ownership of name object was transferred to box |
|
200 } |
|
201 } |
|
202 |
|
203 } // end of if (hrefVal) |
|
204 |
|
205 if (box) |
|
206 { |
|
207 box->hrefAttr = NW_Text_New( HTTP_iso_10646_ucs_2, (void*)newUrl, NW_Str_Strlen(newUrl), |
|
208 NW_Text_Flags_NullTerminated | NW_Text_Flags_Aligned | NW_Text_Flags_Copy ); |
|
209 if (!box->hrefAttr) |
|
210 { |
|
211 NW_Object_Delete(box); |
|
212 box = NULL; |
|
213 } |
|
214 } |
|
215 |
|
216 cleanup: |
|
217 if (hrefVal) |
|
218 { |
|
219 NW_Object_Delete(hrefVal); |
|
220 } |
|
221 if (storage && freeNeeded) |
|
222 { |
|
223 NW_Str_Delete(storage); |
|
224 } |
|
225 if (newUrl) |
|
226 { |
|
227 NW_Str_Delete(newUrl); |
|
228 } |
|
229 if (chReturns) |
|
230 { |
|
231 NW_Str_Delete(chReturns); |
|
232 } |
|
233 if (nameVal) |
|
234 { |
|
235 NW_Object_Delete(nameVal); |
|
236 } |
|
237 if (ctiVal) |
|
238 { |
|
239 NW_Object_Delete(ctiVal); |
|
240 } |
|
241 |
|
242 return (box) ? NW_LMgr_BoxOf(box) : NULL; |
|
243 } |
|
244 |
|
245 /* ------------------------------------------------------------------------- |
|
246 ------------------------------------------------------------------------- */ |
|
247 static |
|
248 NW_LMgr_Box_t* |
|
249 NW_XHTML_aElementHandler_CreateBox(const NW_XHTML_ElementHandler_t* elementHandler, |
|
250 NW_XHTML_ContentHandler_t* contentHandler, |
|
251 NW_DOM_ElementNode_t* elementNode) |
|
252 { |
|
253 NW_Text_t* hrefVal = NULL; |
|
254 NW_Text_t* nameVal = NULL; |
|
255 NW_LMgr_ActiveContainerBox_t* box = NULL; |
|
256 NW_HED_EventHandler_t* eventHandler = NULL; |
|
257 NW_Ucs2* storage = NULL; |
|
258 NW_Uint8 freeNeeded = NW_FALSE; |
|
259 |
|
260 NW_REQUIRED_PARAM(elementHandler); |
|
261 |
|
262 // find the 'name' attribute. |
|
263 NW_XHTML_GetDOMAttribute (contentHandler, elementNode, |
|
264 NW_XHTML_AttributeToken_name, &nameVal); |
|
265 |
|
266 /* find the 'href' attribute. */ |
|
267 NW_XHTML_GetDOMAttribute (contentHandler, elementNode, |
|
268 NW_XHTML_AttributeToken_href, &hrefVal); |
|
269 if (hrefVal == NULL) |
|
270 { |
|
271 NW_XHTML_aElementHandler_getBaseTagUrl(contentHandler, &hrefVal); |
|
272 } |
|
273 if (hrefVal != NULL) |
|
274 { |
|
275 NW_Url_Schema_t scheme = NW_SCHEMA_INVALID; |
|
276 TBrowserStatusCode schemeStatus = KBrsrSuccess; |
|
277 NW_Text_Length_t charCount; |
|
278 |
|
279 /* There is an href attribute, so make it an active box. */ |
|
280 |
|
281 storage = (NW_Ucs2*) |
|
282 NW_Text_GetUCS2Buffer (hrefVal, NW_Text_Flags_Aligned, &charCount, |
|
283 &freeNeeded); |
|
284 if (!storage) |
|
285 { |
|
286 goto cleanup; |
|
287 } |
|
288 |
|
289 /* At this point, only interested if a scheme is present, not that the URL does not |
|
290 comply with RFC2396. If there is a problem with the URL, it will be caught later |
|
291 when the anchor is selected/used. The philosophy is to present everything to the user. */ |
|
292 schemeStatus = NW_Url_GetScheme(storage, &scheme); |
|
293 |
|
294 if (scheme == NW_SCHEMA_INVALID && schemeStatus == KBrsrMalformedUrl) |
|
295 { |
|
296 goto cleanup; |
|
297 } |
|
298 |
|
299 eventHandler = |
|
300 NW_HED_EventHandler_New (NW_HED_DocumentNodeOf (contentHandler), elementNode); |
|
301 box = NW_LMgr_ActiveContainerBox_New(0, |
|
302 NW_LMgr_EventHandlerOf(eventHandler), |
|
303 NW_LMgr_ActionType_OpenLink); |
|
304 if (box) |
|
305 { |
|
306 NW_LMgr_ActiveContainerBox_SetName(box, nameVal, NW_TRUE); |
|
307 nameVal = NULL; // ownership of name object was transferred to box |
|
308 } |
|
309 } |
|
310 |
|
311 cleanup: |
|
312 if (hrefVal) |
|
313 { |
|
314 NW_Object_Delete(hrefVal); |
|
315 } |
|
316 if (storage && freeNeeded) |
|
317 { |
|
318 NW_Str_Delete(storage); |
|
319 } |
|
320 if (nameVal) |
|
321 { |
|
322 NW_Object_Delete(nameVal); |
|
323 } |
|
324 |
|
325 return (box) ? NW_LMgr_BoxOf(box) : NULL; |
|
326 } |
|
327 |
|
328 /* ------------------------------------------------------------------------- |
|
329 NW_XHTML_aElementHandler_HandleIModeEvents |
|
330 ------------------------------------------------------------------------- */ |
|
331 static |
|
332 NW_Uint8 |
|
333 NW_XHTML_aElementHandler_HandleIModeEvents(const NW_XHTML_ElementHandler_t* elementHandler, |
|
334 NW_XHTML_ContentHandler_t* contentHandler, |
|
335 NW_DOM_ElementNode_t* elementNode, |
|
336 NW_Evt_Event_t* event) |
|
337 { |
|
338 NW_Text_t* url = NULL; |
|
339 NW_Text_t* cti = NULL; |
|
340 NW_Bool isCti = NW_FALSE; |
|
341 TBrowserStatusCode status = KBrsrFailure; |
|
342 NW_Url_Schema_t scheme = NW_SCHEMA_INVALID; |
|
343 NW_Ucs2* storage = NULL; |
|
344 NW_Uint8 freeNeeded = 0; |
|
345 NW_Text_Length_t charCount = 0; |
|
346 NW_XHTML_TelephonyServices_t* telServices; |
|
347 |
|
348 NW_REQUIRED_PARAM(elementHandler); |
|
349 |
|
350 telServices = (NW_XHTML_TelephonyServices_t*)(&NW_XHTML_TelephonyServices); |
|
351 |
|
352 /* find the 'cti' attribute and get its string value */ |
|
353 NW_XHTML_GetDOMAttribute (contentHandler, elementNode, |
|
354 NW_XHTML_AttributeToken_cti, &cti); |
|
355 |
|
356 /*In models that support this function, the cti attribute takes |
|
357 precedence over the href attribute. Models that do not support this |
|
358 tag will not understand the cti attribute and will therefore use the |
|
359 href attribute. */ |
|
360 if (cti == NULL) |
|
361 { |
|
362 /* find the 'href' attribute and get its string value */ |
|
363 NW_XHTML_GetDOMAttribute (contentHandler, elementNode, |
|
364 NW_XHTML_AttributeToken_href, &url); |
|
365 if (url == NULL) |
|
366 { |
|
367 NW_XHTML_aElementHandler_getBaseTagUrl(contentHandler, &url); |
|
368 } |
|
369 if (url == NULL) |
|
370 { |
|
371 return NW_LMgr_EventAbsorbed; |
|
372 } |
|
373 storage = (NW_Ucs2*)NW_Text_GetUCS2Buffer(url, NW_Text_Flags_Aligned, |
|
374 &charCount, &freeNeeded); |
|
375 NW_Url_GetSchemeNoValidation(storage, &scheme); |
|
376 } |
|
377 |
|
378 /* handle Save To Phonebook event */ |
|
379 if (NW_Object_Core_GetClass (event) == &NW_XHTML_SaveToPhoneBkEvent_Class) |
|
380 { |
|
381 if (scheme == NW_SCHEMA_MAILTO) |
|
382 { |
|
383 NW_Text_t* email = NULL; |
|
384 NW_Text_t* name = NULL; |
|
385 NW_XHTML_GetDOMAttribute (contentHandler, elementNode, |
|
386 NW_XHTML_AttributeToken_email, &email); |
|
387 NW_XHTML_GetDOMAttribute (contentHandler, elementNode, |
|
388 NW_XHTML_AttributeToken_memoryname, &name); |
|
389 |
|
390 if (email == NULL) |
|
391 { |
|
392 status = NW_XHTML_TelephonyServices_Mailto_SaveToPhoneBook(telServices, contentHandler, |
|
393 url, name, NW_FALSE); |
|
394 } |
|
395 else |
|
396 { |
|
397 status = NW_XHTML_TelephonyServices_Mailto_SaveToPhoneBook(telServices, contentHandler, |
|
398 email, name, NW_TRUE); |
|
399 } |
|
400 NW_Object_Delete(url); |
|
401 NW_Object_Delete(email); |
|
402 NW_Object_Delete(name); |
|
403 |
|
404 return NW_LMgr_EventAbsorbed; |
|
405 } |
|
406 else |
|
407 /*if (NW_Object_Core_GetClass (event) == &NW_XHTML_SaveToPhoneBkEvent_Class)*/ |
|
408 { |
|
409 NW_Text_t* name = NULL; |
|
410 NW_Text_t* email = NULL; |
|
411 |
|
412 status = NW_XHTML_GetDOMAttribute(contentHandler, elementNode, |
|
413 NW_XHTML_AttributeToken_telbook, &name); |
|
414 |
|
415 if (status != KBrsrSuccess) |
|
416 { |
|
417 NW_XHTML_GetDOMAttribute(contentHandler, elementNode, |
|
418 NW_XHTML_AttributeToken_memoryname, &name); |
|
419 } |
|
420 |
|
421 NW_XHTML_GetDOMAttribute(contentHandler, elementNode, |
|
422 NW_XHTML_AttributeToken_email, &email); |
|
423 if (cti != NULL) |
|
424 { |
|
425 isCti = NW_TRUE; |
|
426 status = NW_XHTML_TelephonyServices_SaveToPhoneBook(telServices, contentHandler, |
|
427 cti, name, email, isCti); |
|
428 } |
|
429 else |
|
430 { |
|
431 status = NW_XHTML_TelephonyServices_SaveToPhoneBook(telServices, contentHandler, |
|
432 url, name, email, isCti); |
|
433 } |
|
434 |
|
435 NW_Object_Delete(cti); |
|
436 NW_Object_Delete(url); |
|
437 NW_Object_Delete(name); |
|
438 NW_Object_Delete(email); |
|
439 |
|
440 return NW_LMgr_EventAbsorbed; |
|
441 } |
|
442 } |
|
443 |
|
444 if (freeNeeded) |
|
445 { |
|
446 NW_Str_Delete(storage); |
|
447 } |
|
448 |
|
449 /* handle ActiveEvent/AccessKeyEvent */ |
|
450 if (cti != NULL) /* if cti attribute is specified use cti to make call */ |
|
451 { |
|
452 NW_Object_Delete(url); /* cti will be used. url is not needed. */ |
|
453 url = NULL; |
|
454 |
|
455 status = NW_XHTML_TelephonyServices_MakeCall(telServices, contentHandler, cti, NW_TRUE); |
|
456 if (status != KBrsrSuccess) |
|
457 { |
|
458 NW_HED_DocumentNode_HandleError(contentHandler, |
|
459 NW_HED_ContentHandler_GetUrlRequest(contentHandler), |
|
460 BRSR_STAT_CLASS_GENERAL, (NW_WaeError_t)status); |
|
461 } |
|
462 NW_Object_Delete(cti); |
|
463 |
|
464 return NW_LMgr_EventAbsorbed; |
|
465 } |
|
466 |
|
467 /* handle tel:// scheme */ |
|
468 if (scheme == NW_SCHEMA_TEL) |
|
469 { |
|
470 status = NW_XHTML_TelephonyServices_MakeCall(telServices, contentHandler, url, NW_FALSE); |
|
471 if (status != KBrsrSuccess) |
|
472 { |
|
473 NW_HED_DocumentNode_HandleError(contentHandler, |
|
474 NW_HED_ContentHandler_GetUrlRequest(contentHandler), |
|
475 BRSR_STAT_CLASS_GENERAL, (NW_WaeError_t)status); |
|
476 } |
|
477 NW_Object_Delete(url); |
|
478 |
|
479 return NW_LMgr_EventAbsorbed; |
|
480 } |
|
481 |
|
482 NW_Object_Delete(url); |
|
483 |
|
484 return NW_LMgr_EventNotAbsorbed; |
|
485 } |
|
486 |
|
487 /* ------------------------------------------------------------------------- * |
|
488 class definition |
|
489 * ------------------------------------------------------------------------- */ |
|
490 |
|
491 /* ------------------------------------------------------------------------- */ |
|
492 const |
|
493 NW_XHTML_aElementHandler_Class_t NW_XHTML_aElementHandler_Class = { |
|
494 { /* NW_Object_Core */ |
|
495 /* super */ &NW_XHTML_ElementHandler_Class, |
|
496 /* queryInterface */ _NW_Object_Core_QueryInterface |
|
497 }, |
|
498 { /* NW_XHTML_ElementHandler */ |
|
499 /* initialize */ _NW_XHTML_aElementHandler_Initialize, |
|
500 /* createBoxTree */ _NW_XHTML_aElementHandler_CreateBoxTree, |
|
501 /* processEvent */ _NW_XHTML_aElementHandler_ProcessEvent |
|
502 }, |
|
503 { /* NW_XHTML_aElementHandler */ |
|
504 /* unused */ NW_Object_Unused |
|
505 } |
|
506 }; |
|
507 |
|
508 /* ------------------------------------------------------------------------- * |
|
509 singleton definition |
|
510 * ------------------------------------------------------------------------- */ |
|
511 |
|
512 /* ------------------------------------------------------------------------- */ |
|
513 const NW_XHTML_aElementHandler_t NW_XHTML_aElementHandler = { |
|
514 { { &NW_XHTML_aElementHandler_Class } } |
|
515 }; |
|
516 |
|
517 /* ------------------------------------------------------------------------- * |
|
518 virtual methods |
|
519 * ------------------------------------------------------------------------- */ |
|
520 |
|
521 /* ------------------------------------------------------------------------- */ |
|
522 TBrowserStatusCode |
|
523 _NW_XHTML_aElementHandler_Initialize (const NW_XHTML_ElementHandler_t* elementHandler, |
|
524 NW_XHTML_ContentHandler_t* contentHandler, |
|
525 NW_DOM_ElementNode_t* elementNode) |
|
526 { |
|
527 NW_REQUIRED_PARAM(elementHandler); |
|
528 |
|
529 // special handling if a is the last part of the chunk: |
|
530 // leave select to be processed in the next chunk |
|
531 // in case this is the last chunk, we need to process a in this chunk |
|
532 NW_XHTML_ElementHandler_NextSiblingExists (contentHandler, elementNode, NW_TRUE); |
|
533 |
|
534 return KBrsrSuccess; |
|
535 } |
|
536 |
|
537 /* ------------------------------------------------------------------------- */ |
|
538 TBrowserStatusCode |
|
539 _NW_XHTML_aElementHandler_CreateBoxTree (const NW_XHTML_ElementHandler_t* elementHandler, |
|
540 NW_XHTML_ContentHandler_t* contentHandler, |
|
541 NW_DOM_ElementNode_t* elementNode, |
|
542 NW_LMgr_ContainerBox_t* parentBox) |
|
543 { |
|
544 NW_LMgr_Box_t* box = NULL; |
|
545 NW_Text_t* url = NULL; |
|
546 NW_LMgr_TextBox_t* textBox = NULL; |
|
547 |
|
548 NW_TRY (status) |
|
549 { |
|
550 // special handling if a is the last node of the chunck: |
|
551 // leave it to be processed in the next chunck |
|
552 if (!NW_XHTML_ElementHandler_NextSiblingExists (contentHandler, elementNode, NW_FALSE)) |
|
553 { |
|
554 NW_THROW_SUCCESS (status); |
|
555 } |
|
556 |
|
557 if ( NW_XHTML_ContentHandler_GetHtmlSubset(contentHandler) == |
|
558 NW_XHTML_CONTENTHANDLER_IMODEHTMLEXT) |
|
559 { |
|
560 box = NW_XHTML_aElementHandler_ImodeCreateBox(elementHandler, contentHandler, |
|
561 elementNode); |
|
562 } |
|
563 else |
|
564 { |
|
565 box = NW_XHTML_aElementHandler_CreateBox(elementHandler, contentHandler, |
|
566 elementNode); |
|
567 } |
|
568 if (box == NULL) |
|
569 { |
|
570 /* either tel was invalid or there was no href attribute */ |
|
571 box = (NW_LMgr_Box_t*)NW_LMgr_ContainerBox_New(0); |
|
572 NW_THROW_OOM_ON_NULL (box, status); |
|
573 } |
|
574 |
|
575 /* Add the box to the tree */ |
|
576 status = NW_LMgr_ContainerBox_AddChild (parentBox, box); |
|
577 _NW_THROW_ON_ERROR (status); |
|
578 |
|
579 /* apply common attributes and styles */ |
|
580 status = NW_XHTML_ElementHandler_ApplyStyles (elementHandler, contentHandler, elementNode, &box, NULL); |
|
581 |
|
582 NW_THROW_ON (status, KBrsrOutOfMemory); |
|
583 |
|
584 // Apply Styles will take care of replacing container box if display was block, list-item or marquee. |
|
585 // In case of 'display:none' or an error it removes the container box. That's why we check box |
|
586 if (box == NULL) |
|
587 { |
|
588 NW_THROW_SUCCESS (status); |
|
589 } |
|
590 |
|
591 parentBox = NW_LMgr_ContainerBoxOf (box); |
|
592 |
|
593 /* invoke our superclass for completion */ |
|
594 status = _NW_XHTML_ElementHandler_CreateBoxTree(elementHandler, contentHandler, elementNode, parentBox); |
|
595 |
|
596 // if the <a href="foo.html"></a> is empty, then add the href as link text. |
|
597 if( parentBox && NW_Object_IsInstanceOf( parentBox, &NW_LMgr_ActiveContainerBox_Class ) ) |
|
598 { |
|
599 // child count = 0 means that we have not added any textbox to this container yet. add the href then. |
|
600 if( NW_LMgr_ContainerBox_GetChildCount( parentBox ) == 0 && NW_LMgr_ActiveContainerBoxOf( parentBox )->hrefAttr ) |
|
601 { |
|
602 url = NW_Text_Copy( NW_LMgr_ActiveContainerBoxOf( parentBox )->hrefAttr, NW_TRUE ); |
|
603 NW_THROW_OOM_ON_NULL( url, status ); |
|
604 // |
|
605 // create the TextBox and insert it into our parent |
|
606 textBox = (NW_LMgr_TextBox_t*)NW_LMgr_TextBox_New( 0, url ); |
|
607 NW_THROW_OOM_ON_NULL( textBox, status ); |
|
608 url = NULL; |
|
609 |
|
610 status = NW_LMgr_ContainerBox_AddChild( parentBox, NW_LMgr_BoxOf( textBox ) ); |
|
611 _NW_THROW_ON_ERROR( status ); |
|
612 textBox = NULL; |
|
613 } |
|
614 } |
|
615 } |
|
616 NW_CATCH (status) |
|
617 { |
|
618 if(box) |
|
619 { |
|
620 NW_Object_Delete(box); |
|
621 } |
|
622 NW_Object_Delete( url ); |
|
623 NW_Object_Delete( textBox ); |
|
624 } |
|
625 NW_FINALLY |
|
626 { |
|
627 return status; |
|
628 } NW_END_TRY |
|
629 } |
|
630 |
|
631 /* ------------------------------------------------------------------------- */ |
|
632 |
|
633 NW_Uint8 |
|
634 _NW_XHTML_aElementHandler_ProcessEvent (const NW_XHTML_ElementHandler_t* elementHandler, |
|
635 NW_XHTML_ContentHandler_t* contentHandler, |
|
636 NW_DOM_ElementNode_t* elementNode, |
|
637 NW_LMgr_Box_t* box, |
|
638 NW_Evt_Event_t* event) |
|
639 { |
|
640 NW_Text_t* url = NULL; |
|
641 TBrowserStatusCode status = KBrsrNotFound; |
|
642 NW_HED_DocumentRoot_t* documentRoot = |
|
643 (NW_HED_DocumentRoot_t*)NW_HED_DocumentNode_GetRootNode (contentHandler); |
|
644 |
|
645 NW_REQUIRED_PARAM(box); |
|
646 |
|
647 /* we are really only interested in the following list of events */ |
|
648 if ((NW_Object_Core_GetClass (event) != &NW_Evt_ActivateEvent_Class) && |
|
649 (NW_Object_Core_GetClass (event) != &NW_Evt_AccessKeyEvent_Class) && |
|
650 (NW_Object_Core_GetClass (event) != &NW_Evt_FocusEvent_Class) && |
|
651 (NW_Object_Core_GetClass (event) != &NW_XHTML_SaveToPhoneBkEvent_Class)) |
|
652 { |
|
653 return NW_LMgr_EventNotAbsorbed; |
|
654 } |
|
655 |
|
656 if(NW_Object_Core_GetClass (event) == &NW_Evt_FocusEvent_Class) { |
|
657 return NW_LMgr_EventAbsorbed; |
|
658 } |
|
659 |
|
660 /* Process IMODE events */ |
|
661 if (NW_XHTML_ContentHandler_GetHtmlSubset(contentHandler) == |
|
662 NW_XHTML_CONTENTHANDLER_IMODEHTMLEXT) |
|
663 { |
|
664 if(NW_XHTML_aElementHandler_HandleIModeEvents(elementHandler, contentHandler, |
|
665 elementNode, event) == NW_LMgr_EventAbsorbed) |
|
666 return NW_LMgr_EventAbsorbed; |
|
667 } |
|
668 |
|
669 if(NW_LMgr_ActiveContainerBoxOf(box)->hrefAttr != NULL) |
|
670 { |
|
671 url = NW_Text_Copy(NW_LMgr_ActiveContainerBoxOf(box)->hrefAttr, NW_TRUE); |
|
672 } |
|
673 else |
|
674 { |
|
675 /* find the 'href' attribute and get its string value */ |
|
676 NW_XHTML_GetDOMAttribute (contentHandler, |
|
677 elementNode, |
|
678 NW_XHTML_AttributeToken_href, &url); |
|
679 } |
|
680 |
|
681 if (url == NULL) |
|
682 { |
|
683 NW_XHTML_aElementHandler_getBaseTagUrl(contentHandler, &url); |
|
684 } |
|
685 if (url == NULL) { |
|
686 return NW_LMgr_EventAbsorbed; |
|
687 } |
|
688 |
|
689 |
|
690 if(status == KBrsrNotFound) |
|
691 { |
|
692 // if the url starts with javascript: then delegate the activate event to ecmaengine |
|
693 if(NW_Str_Strnicmp((const NW_Ucs2*) url->storage, (const NW_Ucs2*) NW_STR("javascript:"), 11) == 0) { |
|
694 NW_Bool urlTextFreeNeeded; |
|
695 NW_Text_Length_t urlTextLength; |
|
696 NW_Ucs2* urlStorage; |
|
697 urlStorage = NW_Text_GetUCS2Buffer (url, 0, &urlTextLength, &urlTextFreeNeeded); |
|
698 if(urlTextFreeNeeded){ |
|
699 NW_Mem_Free ((NW_Ucs2*) urlStorage); |
|
700 } |
|
701 } |
|
702 else |
|
703 { |
|
704 #if !defined(__SERIES60_28__) && !defined(__SERIES60_27__) |
|
705 NW_Text_t* target = NULL; |
|
706 NW_XHTML_GetDOMAttribute (contentHandler, elementNode, NW_XHTML_AttributeToken_target, &target); |
|
707 TBool newWindow = EFalse; |
|
708 if (target != NULL && target->characterCount == 0) |
|
709 { |
|
710 NW_Object_Delete(target); |
|
711 target = NULL; |
|
712 } |
|
713 if (target == NULL) |
|
714 { |
|
715 NW_XHTML_ContentHandler_GetBaseTagTarget (contentHandler, &target); |
|
716 } |
|
717 if (target != NULL) |
|
718 { |
|
719 // If the target attribute exists, and it is not an empty string, and |
|
720 // it is not "_self", open the url in a new window |
|
721 NW_Bool targetTextFreeNeeded = NW_FALSE;; |
|
722 NW_Ucs2* targetStorage; |
|
723 NW_Text_Length_t targetTextLength; |
|
724 _LIT(KSelf, "_self"); |
|
725 targetStorage = NW_Text_GetUCS2Buffer (target, NW_Text_Flags_NullTerminated, |
|
726 &targetTextLength, &targetTextFreeNeeded); |
|
727 // Check that the target attribute is not empty |
|
728 TPtrC targetPtr(targetStorage, targetTextLength); |
|
729 if (targetTextLength > 0 && targetPtr.CompareF(KSelf) != 0) |
|
730 { |
|
731 status = NW_XHTML_ContentHandler_WindowOpen(contentHandler, url, target); |
|
732 newWindow = ETrue; |
|
733 } |
|
734 if (targetTextFreeNeeded) |
|
735 { |
|
736 NW_Mem_Free(targetStorage); |
|
737 } |
|
738 NW_Object_Delete(target); |
|
739 } |
|
740 if (!newWindow) |
|
741 #endif |
|
742 { |
|
743 // copy the Url on to the content handler |
|
744 NW_XHTML_ContentHandler_SetReferrerUrl(contentHandler); |
|
745 // mailto and wtai scheme are now being processed by the default scheme dispatcher |
|
746 /* load the content */ |
|
747 status = NW_XHTML_ContentHandler_StartLoad (contentHandler, NW_TextOf (url), |
|
748 NW_HED_UrlRequest_Reason_DocLoad, (void *) &NW_WmlScript_ContentHandler_Class, |
|
749 NW_UrlRequest_Type_Any); |
|
750 } |
|
751 } |
|
752 } |
|
753 |
|
754 NW_Object_Delete(url); |
|
755 |
|
756 if (status != KBrsrSuccess && status != KBrsrHedContentDispatched) { |
|
757 NW_HED_DocumentNode_HandleError (contentHandler, |
|
758 NW_HED_ContentHandler_GetUrlRequest (contentHandler), |
|
759 BRSR_STAT_CLASS_GENERAL, (NW_WaeError_t) status); |
|
760 } |
|
761 |
|
762 /* we absorbed the event! */ |
|
763 return NW_LMgr_EventAbsorbed; |
|
764 } |
|
765 |
|
766 /* |
|
767 Get the URL in base tag defined in header, this value can be used to combine with |
|
768 relative URL to figure out the absolute URL. |
|
769 */ |
|
770 TBrowserStatusCode |
|
771 NW_XHTML_aElementHandler_getBaseTagUrl (NW_XHTML_ContentHandler_t* contentHandler, |
|
772 NW_Text_t** hrefVal) |
|
773 { |
|
774 NW_DOM_Node_t* baseElement; |
|
775 NW_String_t href; |
|
776 |
|
777 NW_ASSERT (hrefVal); |
|
778 |
|
779 /* get the base url as found in the "base" element */ |
|
780 baseElement = NW_HED_DomHelper_FindElement (&contentHandler->domHelper, NW_HED_DomTree_GetRootNode ( |
|
781 contentHandler->domTree), 3, NW_XHTML_ElementToken_base, 0, NULL); |
|
782 |
|
783 if (baseElement != NULL) { |
|
784 TBrowserStatusCode status = NW_HED_DomHelper_GetAttributeValue (&contentHandler->domHelper, baseElement, |
|
785 NW_XHTML_AttributeToken_href, &href); |
|
786 |
|
787 if (status == KBrsrSuccess) { |
|
788 *hrefVal = (NW_Text_t*) NW_Text_UCS2_New (href.storage, 0, NW_Text_Flags_TakeOwnership); |
|
789 } |
|
790 } |
|
791 return KBrsrSuccess; |
|
792 } |
|