hurl.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:27k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include <string.h>
  36. #include <stdio.h>
  37. #ifndef _MAC_MACHO
  38. #include <InternetConfig.h>
  39. #endif
  40. #include "hxtypes.h"
  41. #include "hxcom.h"     /* IUnknown */
  42. #include "ihxpckts.h"  /* IHXBuffer */
  43. #include "platform/mac/hurl.h"
  44. #include "hxwintyp.h"
  45. #if defined(_CARBON) || defined(_MAC_UNIX)
  46. #include "platform/mac/mac_pref_cf.h"
  47. #ifndef _MAC_UNIX
  48. #include "filespecutils.h"
  49. #include "MoreFilesX.h"
  50. #endif
  51. static BOOL LaunchMacBrowserCarbon(const char* pURL, IHXPreferences* pPrefs, BOOL bBringToFront, BOOL bNewWindow);
  52. static BOOL GetPreferredBrowser(IHXPreferences* pPrefs, FSRef *outBrowserFSRef, OSType *outBrowserSignature);
  53. static void MakeHurlJavascriptURL(const char * pszURL, const char * pszWindowName, 
  54. BOOL bSetPosition, const HXxPoint& ptWindowPos, const HXxSize& sizeWindow, CHXString& outStrURL, BOOL bUseNewJavascriptWindow);
  55. #else
  56. #include "mac_pref.h"
  57. #endif // _CARBON
  58. // Stuff for using ODOCs instead of OpenURL for Unicode UTF-8 URLs because IE 5.2 and Netscape can't
  59. // deal with UTF8 in URLs; we'll send ODOCs instead of OpenURL events in those cases
  60. Boolean IsLocalFileURLAPotentialProblemBecauseOfPercentEncodedUTF8Chars(const char *pURL);
  61. BOOL MakeOpenDocumentsEventFromURL(OSType appSignature, const char* pURL, AEDesc *theAppleEventPtr, Boolean bNewWindow);
  62. #include "platform/mac/hx_moreprocesses.h"
  63. #ifndef _MAC_UNIX
  64. #include "hx_morefiles.h"
  65. #include "fullpathname.h"
  66. #include "hxinternetconfigutils.h"
  67. #endif
  68. #include "hxresult.h"
  69. #include "hxprefs.h"
  70. const DescType kWebBrowserSuite = 'WWW!';
  71. const DescType kOpenUrlEventID = 'OURL';
  72. const DescType kOpenUrlWindowID = 'WIND';
  73. const DescType kCloseAllWindowsEventID = 'CLSA';
  74. const  OSType MSIE_CREATOR =  'MSIE';
  75. const  OSType NETSCAPE_CREATOR =  'MOSS';
  76. const  OSType MOZILLA_CREATOR =  'MOZZ';
  77. const  OSType AOL_CREATOR =  'AOp3';
  78. const  OSType OMNIWEB_CREATOR =  'OWEB';
  79. const OSType ICAB_CREATOR =  'iCAB';
  80. const OSType CHIMERA_CREATOR =  'CHIM';
  81. const OSType OPERA_CREATOR =  'OPRA';
  82. const OSType SAFARI_CREATOR =  'sfri';
  83.  
  84. const OSType MOSAIC_CREATOR =  'MOS!';
  85. const   OSType MOSAIC_BrowserSuite =  'mos!';
  86. const OSType MOSAIC_OpenUrlEventID =  'ourl';
  87. // if there's no default browser signature that we can determine from HX prefs or from InternetConfig,
  88. // we'll look for one in this list, in this order
  89. static OSType BrowserCreators[] 
  90. = { SAFARI_CREATOR, MSIE_CREATOR, NETSCAPE_CREATOR, MOZILLA_CREATOR, AOL_CREATOR,
  91. OMNIWEB_CREATOR, ICAB_CREATOR, CHIMERA_CREATOR, OPERA_CREATOR, 0 }; // what's Opera?  Any others?
  92. /********************************************************************
  93. LaunchMacBrowserWithURL
  94. ********************************************************************/
  95. BOOL LaunchMacBrowserWithURL(const char* pURL, IHXPreferences* pPrefs)
  96. {
  97. const BOOL bBringToFront = TRUE;
  98. return LaunchMacBrowserWithURLOrdered(pURL, pPrefs, bBringToFront);
  99. }
  100. BOOL LaunchMacBrowserWithURLOrdered(const char* pURL, IHXPreferences* pPrefs, BOOL bBringToFront)
  101. {
  102. const BOOL bExistingWindow = FALSE;
  103. return LaunchMacBrowserWithURLWindowParam(pURL, pPrefs, bBringToFront, bExistingWindow);
  104. }
  105. BOOL LaunchMacBrowserTargetingWindow(const char* pURL, IHXPreferences* pPrefs, BOOL bBringToFront, 
  106. const char* pTargetWindowName, BOOL bUseNewJavascriptWindow)
  107. {
  108. // if bUseNewJavascriptWindow is false, then we won't make a new window for the javascript to execute in;
  109. // on some browsers, this will make the javascript fail to execute if no windows are open.
  110. const BOOL kDontSetPosition = FALSE;
  111. HXxPoint ptUnset = { 0, 0 };
  112. HXxSize szUnset = { 0, 0 };
  113. CHXString strNewURL;
  114. MakeHurlJavascriptURL(pURL, pTargetWindowName, kDontSetPosition, ptUnset, szUnset, strNewURL, bUseNewJavascriptWindow);
  115. if (strNewURL.IsEmpty())
  116. {
  117. check(!"LaunchMacBrowserTargetingWindow could not make Javascript URL");
  118. strNewURL = pURL;
  119. }
  120. // we make a new window since the Javascript will blow away the existing window
  121. return LaunchMacBrowserWithURLWindowParam(strNewURL, pPrefs, bBringToFront, bUseNewJavascriptWindow);
  122. }
  123. BOOL LaunchMacBrowserWithURLWindowParam(const char* pURL, IHXPreferences* pPrefs, BOOL bBringToFront, BOOL bNewWindow)
  124. {
  125. #if defined(_CARBON) || defined(_MAC_UNIX)
  126. return LaunchMacBrowserCarbon(pURL, pPrefs, bBringToFront, bNewWindow);
  127. #else
  128.     OSErr theErr = noErr;
  129.     CPBusyCursor busyCursor;
  130.     
  131.     Size urlLen = ::strlen(pURL);
  132.     Boolean launched = FALSE;
  133.     // Check to see if the default browser is running, otherwise launch it.
  134.     // Then send it an openURL event.
  135.     OSType    defaultBrowser = 'PNst';
  136.     IHXBuffer* pBuffer = NULL;
  137.     Boolean bICStarted = HXInternetConfigMac::StartUsingIC();
  138. if (pPrefs)
  139. {
  140.     if (HXR_OK == pPrefs->ReadPref("PreferredBrowser", pBuffer))
  141.     {
  142.      const char* theBrowserFilePath = (const char*) pBuffer->GetBuffer();
  143.      if (theBrowserFilePath)
  144.      {
  145. FInfo  applFinderInfo;
  146. FSSpec  spec;
  147. if (noErr == FSSpecFromPathName(theBrowserFilePath, &spec))
  148. {
  149. if (noErr == FSpGetFInfo(&spec, &applFinderInfo))
  150. {
  151. defaultBrowser = applFinderInfo.fdCreator;
  152. }
  153. }
  154. }
  155.      pBuffer->Release();
  156.     }
  157. }    
  158.     /* get Preferred Browser from InternetConfig unless either
  159.        InternetConfig isn't linked in, System 8.1, OR
  160.        Preferences dictate a specific browser. */
  161.     if (defaultBrowser == 'PNst')
  162.     {
  163.     if (ICStart) // not linked with IC for some reason - pre Sys 8.1?
  164.     {
  165.      unsigned char *kDontCareBrowserName = NULL;
  166.     
  167.      OSStatus err = HXInternetConfigMac::GetHTTPHelper(&defaultBrowser, kDontCareBrowserName);
  168.     }
  169. else
  170. {
  171. defaultBrowser = NETSCAPE_CREATOR;
  172. }
  173. }
  174.     
  175.     OSType    openBrowser = 0;
  176.     FSSpec cachedDefaultBrowserSpec;
  177.     {
  178. // check if any browser is already running
  179. if (CheckForApplicationRunning(NETSCAPE_CREATOR))
  180.     openBrowser = NETSCAPE_CREATOR;
  181. else if (CheckForApplicationRunning(MSIE_CREATOR))
  182.     openBrowser = MSIE_CREATOR;
  183. else if (CheckForApplicationRunning(AOL_CREATOR))
  184.     openBrowser = AOL_CREATOR;
  185. if (!openBrowser)
  186. {
  187.     short volindex=1;
  188.     short vRefNum=0;
  189.     
  190.     // Look through all volumes for the default browser application.
  191.     while (GetVRefnumFromIndex(volindex,&vRefNum)) 
  192.     {
  193. short fileindex=0;
  194. while (noErr==HX_FSpGetAppSpecFromDesktop(defaultBrowser,fileindex,
  195. vRefNum,&cachedDefaultBrowserSpec))
  196. {
  197.     FInfo finfo;
  198.     FSpGetFInfo(&cachedDefaultBrowserSpec,&finfo);
  199.     if (finfo.fdType=='APPL') 
  200.     {
  201. AppleEvent theEvent;
  202. //do this at idle time! don't want to launch app at interrupt time
  203. if (MakeOpenURLEvent(defaultBrowser, pURL, &theEvent, bNewWindow))
  204. {
  205. ProcessSerialNumber* kDontCareAboutPSN = NULL;
  206. short launchFlags;
  207. if (bBringToFront) 
  208. {
  209. launchFlags = (launchContinue | launchNoFileFlags);
  210. }
  211. else
  212. {
  213. launchFlags = (launchContinue | launchNoFileFlags | launchDontSwitch);
  214. }
  215. theErr = FSpLaunchApplicationWithParamsAndFlags(&cachedDefaultBrowserSpec, &theEvent, 
  216. kDontCareAboutPSN, launchFlags);
  217. if (theErr == noErr)
  218. {
  219. launched = TRUE;
  220. }
  221. (void) AEDisposeDesc(&theEvent);
  222. }
  223.     }//if
  224.     else 
  225.     {
  226. fileindex++;
  227. continue;
  228.     }//else
  229. break;
  230. }//while
  231. if (launched) break;
  232. volindex++;
  233.     }//while
  234. }//if
  235. if( !launched && openBrowser)
  236. {
  237.   const BOOL bAsync = TRUE;
  238.     launched = SendOpenURLOrdered(openBrowser,pURL, bAsync, bBringToFront, bNewWindow);
  239. }
  240. if ( bICStarted && !launched )
  241. {
  242. theErr = HXInternetConfigMac::LaunchURL(pURL);
  243. launched = (theErr == noErr);
  244. }
  245. goto CleanUp;
  246.     }//if
  247. CleanUp:
  248. if (bICStarted)
  249. {
  250. HXInternetConfigMac::StopUsingIC();
  251. }
  252. return (launched);
  253. #endif // !defined _CARBON
  254. }
  255. BOOL SendOpenURL(OSType appSignature, const char* pURL, BOOL async) 
  256. {
  257. const BOOL bBringToFront = TRUE;
  258. return SendOpenURLOrdered(appSignature, pURL, async, bBringToFront);
  259. }
  260. BOOL SendOpenURLOrdered(OSType appSignature, const char* pURL, BOOL async, BOOL bBringToFront, BOOL bNewWindow) 
  261. {
  262. AEDesc theAppleEvent;
  263. AEDesc outAEReply;
  264. OSErr err;
  265. if (MakeOpenURLEvent(appSignature, pURL, &theAppleEvent, bNewWindow))
  266. {
  267. if (async)
  268. {
  269. err = AESend (&theAppleEvent, &outAEReply, 
  270.  kAENoReply + kAEDontRecord, kAEHighPriority, kNoTimeOut, nil, nil);
  271. }
  272. else
  273. {
  274. err = AESend (&theAppleEvent, &outAEReply,
  275. kAEWaitReply+kAEDontRecord, kAEHighPriority, kNoTimeOut,nil,nil);
  276. AEDisposeDesc(&outAEReply);
  277. }
  278. if (bBringToFront)
  279. {
  280. ActivateApplication(appSignature);
  281. }
  282. (void) AEDisposeDesc(&theAppleEvent);
  283. }
  284. else
  285. {
  286. err = -1;
  287. }
  288. return (err == noErr);
  289. }
  290. BOOL SendOpenURLSync(OSType appSignature, const char* pURL) 
  291. {
  292. return SendOpenURL(appSignature,pURL,false);
  293. }//SendOpenURLSync
  294. BOOL SendOpenURLAsync(OSType appSignature, const char* pURL) 
  295. {
  296. return SendOpenURL(appSignature,pURL,true);
  297. }//SendOpenURLASync
  298. // MakeOpenURLEvent
  299. //
  300. // The caller is responsible for disposing of theAppleEventPtr allocated by this routine
  301. BOOL MakeOpenURLEvent(OSType appSignature, const char* pURL, AEDesc *theAppleEventPtr, Boolean bNewWindow) 
  302. {
  303. if (IsLocalFileURLAPotentialProblemBecauseOfPercentEncodedUTF8Chars(pURL))
  304. {
  305. // for local file URLs which have UTF8 characters in them encoded as % hex,
  306. // we use an ODOC event instead of the OpenURL event since IE 5.2 and Netscape 6.?
  307. // can't handle the UTF8 URLs
  308. return MakeOpenDocumentsEventFromURL(appSignature, pURL, theAppleEventPtr, bNewWindow);
  309. }
  310. AEDesc target;
  311. OSErr err;
  312. AEEventClass eventClass;
  313. AEEventID eventID;
  314. if (MOSAIC_CREATOR == appSignature)
  315. {
  316. eventClass = MOSAIC_BrowserSuite;
  317. eventID = MOSAIC_OpenUrlEventID;
  318. else
  319. {
  320. eventClass = kWebBrowserSuite;
  321. eventID = kOpenUrlEventID;
  322. // Create an application signature address.
  323. err = AECreateDesc(typeApplSignature, &appSignature, sizeof(OSType), &target);
  324. require_noerr(err, CreateDescFailed);
  325. // Create the Apple event
  326. err = AECreateAppleEvent(eventClass, eventID, &target,
  327. kAutoGenerateReturnID, kAnyTransactionID, theAppleEventPtr);
  328. require_noerr(err, AECreateAppleEventFailed);
  329. // Add the URL as the direct object
  330. err = AEPutParamPtr(theAppleEventPtr, keyDirectObject, typeChar, pURL, strlen(pURL));
  331. require_noerr(err, CouldntPutDirectObject);
  332. {
  333.         // Add the targetted window parameter
  334. const long kSameWindow = -1, kNewWindow = 0;
  335. long window = bNewWindow ? kNewWindow : kSameWindow;
  336. err = AEPutParamPtr(theAppleEventPtr, kOpenUrlWindowID, typeLongInteger, &window, sizeof(window));
  337. require_noerr(err, CouldntPutWindow);
  338. (void) AEDisposeDesc(&target);
  339. return TRUE;
  340.         }
  341. // error handling: reverse-order cleanup
  342. CouldntPutWindow:
  343. CouldntPutDirectObject:
  344. (void) AEDisposeDesc(theAppleEventPtr);
  345. AECreateAppleEventFailed:
  346. (void) AEDisposeDesc(&target);
  347. CreateDescFailed:
  348. return FALSE;
  349. }
  350. BOOL MakeOpenDocumentsEventFromURL(OSType appSignature, const char* pURL, AEDesc *theAppleEventPtr, Boolean bNewWindow) 
  351. {
  352. #ifdef _MAC_UNIX
  353.     HX_ASSERT("unimplemented" == NULL);
  354. #else
  355. AEDesc target;
  356. OSErr err;
  357. AliasHandle  alias = NULL;
  358. CHXFileSpecifier  fileSpec;
  359. FSRef fileRef;
  360. theAppleEventPtr->dataHandle = NULL;
  361. target.dataHandle = NULL;
  362. fileSpec.SetFromURL(pURL);
  363. require(CHXFileSpecUtils::FileExists(fileSpec), bail);
  364. fileRef = (FSRef) fileSpec;
  365. // Create an application signature address.
  366. err = AECreateDesc(typeApplSignature, &appSignature, sizeof(OSType), &target);
  367. require_noerr(err, bail);
  368. // Create the Apple event
  369. err = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, &target,
  370. kAutoGenerateReturnID, kAnyTransactionID, theAppleEventPtr);
  371. require_noerr(err, bail);
  372. // Add an alias as the direct object
  373. err = FSNewAlias(NULL, &fileRef, &alias);
  374. require_noerr(err, bail);
  375. err = AEPutParamPtr(theAppleEventPtr, keyDirectObject, typeAlias, *alias, ::GetHandleSize((Handle) alias));
  376. require_noerr(err, bail);
  377. (void) AEDisposeDesc(&target);
  378. DisposeHandle((Handle) alias);
  379. return TRUE;
  380. // error handling: reverse-order cleanup
  381. bail:
  382. if (theAppleEventPtr->dataHandle) (void) AEDisposeDesc(theAppleEventPtr);
  383. if (target.dataHandle) (void) AEDisposeDesc(&target);
  384. if (alias) DisposeHandle((Handle) alias);
  385. return FALSE;
  386. #endif
  387. }
  388. #if defined(_CARBON) || defined(_MAC_UNIX)
  389. BOOL GetPreferredOrSystemBrowser(IHXPreferences* pPrefs, FSRef *outBrowserFSRef, OSType *outBrowserSignature)
  390. {
  391. #ifdef _MAC_UNIX
  392.     HX_ASSERT("GetPreferredOrSystemBrowser unimplemented" == NULL);
  393. #else
  394. FSRef browserFSRef;
  395. OSType defaultBrowserSignature;
  396. BOOL bSuccess;
  397. ZeroInit(&browserFSRef);
  398. bSuccess = GetPreferredBrowser(pPrefs, &browserFSRef, &defaultBrowserSignature);
  399. if (!bSuccess)
  400. {
  401. // there isn't a preferred browser in prefs; get one from InternetConfig, or else look
  402. // for any of our known browsers
  403. unsigned char *kDontCareBrowserName = NULL;
  404. OSErr err;
  405. err = HXInternetConfigMac::GetHTTPHelper(&defaultBrowserSignature, kDontCareBrowserName);
  406. if (err == noErr)
  407. {
  408. err = GetApplicationFSRefFromSignature(defaultBrowserSignature, &browserFSRef);
  409. }
  410. if (err != noErr)
  411. {
  412. defaultBrowserSignature = NETSCAPE_CREATOR;
  413. for (int idx = 0; BrowserCreators[idx] != 0; idx++)
  414. {
  415. if (noErr == GetApplicationFSRefFromSignature(BrowserCreators[idx], &browserFSRef))
  416. {
  417. defaultBrowserSignature = BrowserCreators[idx];
  418. break;
  419. }
  420. }
  421. }
  422. if (err == noErr)
  423. {
  424. bSuccess = TRUE;
  425. }
  426. }
  427. if (outBrowserSignature) *outBrowserSignature = defaultBrowserSignature;
  428. if (outBrowserFSRef) *outBrowserFSRef = browserFSRef;
  429. return bSuccess;
  430. #endif
  431. }
  432. BOOL GetPreferredBrowser(IHXPreferences* pPrefs, FSRef *outBrowserFSRef, OSType *outBrowserSignature)
  433. {
  434. #ifdef _MAC_UNIX
  435.     HX_ASSERT("GetPreferredBrowser unimplemented" == NULL);
  436. #else
  437. HX_RESULT res;
  438. OSStatus err;
  439. const char* theBrowserPref;
  440. FinderInfo fileInfo;
  441. IHXBuffer* pBuffer = NULL;
  442. check(outBrowserFSRef != NULL && outBrowserSignature != NULL);
  443. require_nonnull_quiet(pPrefs, NoPrefsAvailable);
  444. res = pPrefs->ReadPref("PreferredBrowser", pBuffer);
  445. require_quiet(SUCCEEDED(res), CantGetPreferredBrowser);
  446. theBrowserPref = (const char*) pBuffer->GetBuffer();
  447. require_nonnull(theBrowserPref, CantGetPrefFromBuffer);
  448. require_quiet(strlen(theBrowserPref) > 1, NoBrowserSet);
  449. if (strlen(theBrowserPref) == 4)
  450. {
  451. // the pref is an OSType
  452. *outBrowserSignature = *(OSType *) theBrowserPref;
  453. err = GetApplicationFSRefFromSignature(*outBrowserSignature, outBrowserFSRef);
  454. require_noerr_quiet(err, CantGetBrowserFSRef);
  455. }
  456. else
  457. {
  458. // the pref is a persistent file spec or a path
  459. CHXFileSpecifier browserSpec;
  460. (void) browserSpec.SetFromPersistentString(theBrowserPref);
  461. require(browserSpec.IsSet(), CantMakeBrowserSpec);
  462. *outBrowserFSRef = (FSRef) browserSpec;
  463. err = FSGetFinderInfo(outBrowserFSRef, &fileInfo, NULL, NULL);
  464. require_noerr_quiet(err, CantGetBrowserType);
  465. *outBrowserSignature = fileInfo.file.fileCreator;
  466. }
  467. HX_RELEASE(pBuffer);
  468. return TRUE;
  469. CantGetBrowserType:
  470. CantGetAppRef:
  471. CantMakeBrowserSpec:
  472. CantGetBrowserFSRef:
  473. NoBrowserSet:
  474. CantGetPrefFromBuffer:
  475. HX_RELEASE(pBuffer);
  476. CantGetPreferredBrowser:
  477. NoPrefsAvailable:
  478. return FALSE; 
  479. #endif
  480. }
  481. static BOOL LaunchMacBrowserCarbon(const char* pURL, IHXPreferences* pPrefs, BOOL bBringToFront, BOOL bNewWindow)
  482. {
  483. #ifdef _MAC_UNIX
  484.     HX_ASSERT("LaunchMacBrowserCarbon unimplemented" == NULL);
  485. #else
  486. FSRef browserFSRef;
  487. //BOOL bSuccess;
  488. OSType defaultBrowserSignature;
  489. OSType openBrowserSignature;
  490. OSStatus err;
  491. BOOL bLaunched;
  492. int idx;
  493. bLaunched = FALSE;
  494. // get the preferred browser from prefs, if it's available; otherwise, find some other browser
  495. // to default to
  496. defaultBrowserSignature = 0;
  497. ZeroInit(&browserFSRef);
  498. GetPreferredOrSystemBrowser(pPrefs, &browserFSRef, &defaultBrowserSignature);
  499. // see if the preferred browser, or any other, is running
  500. openBrowserSignature = 0;
  501. if (CheckForApplicationRunning(defaultBrowserSignature))
  502. {
  503. openBrowserSignature = defaultBrowserSignature;
  504. }
  505. else
  506. {
  507. for (idx = 0; BrowserCreators[idx] != 0; idx++)
  508. {
  509. if (CheckForApplicationRunning(BrowserCreators[idx]))
  510. {
  511. openBrowserSignature = BrowserCreators[idx];
  512. break;
  513. }
  514. }
  515. }
  516. // CZ 10/29/02 - if a browser is running and the current app is that browser
  517. // then we must be running the embedded player 
  518. // in this case don't force the browser to come to the front
  519. // ie. a hurl from the embedded player shouldn't bring the browser to the front
  520.      if (GetCurrentAppSignature() == openBrowserSignature)
  521.      {
  522. bBringToFront = FALSE; 
  523.      }
  524. // GR 10/1/02 Nasty hack: Netscape 6 and 7 can't deal with URLs in standard OS X format, so
  525. // for that browser and for local URLs only, we'll make a bogus old-style file:/// URL
  526. // by taking a full path and replacing colons with slashes
  527. CHXString strNetscapeLocalURL;
  528. if (openBrowserSignature == 'MOSS' || (openBrowserSignature == 0 && defaultBrowserSignature == 'MOSS'))
  529. {
  530. CHXFileSpecifier fileSpec;
  531. fileSpec.SetFromURL(pURL);
  532. if (fileSpec.IsSet())
  533. {
  534. CHXString strPathMunge = fileSpec.GetPathName();
  535. for (int idx = 0; idx < strPathMunge.GetLength(); idx++)
  536. {
  537. if      (strPathMunge[idx] == ':') strPathMunge.SetAt(idx, '/');
  538. else if (strPathMunge[idx] == '/') strPathMunge.SetAt(idx, ':');
  539. }
  540. strPathMunge.FindAndReplace(" ", "%20", TRUE);
  541. strNetscapeLocalURL = "file:///";
  542. strNetscapeLocalURL += strPathMunge;
  543. pURL = (const char *) strNetscapeLocalURL;
  544. }
  545. }
  546. // try to send the URL via an Apple event to an open browser
  547. if (openBrowserSignature)
  548. {
  549. const BOOL bAsync = TRUE;
  550. bLaunched = SendOpenURLOrdered(openBrowserSignature, pURL, bAsync, bBringToFront, bNewWindow);
  551. }
  552. // if necessary, launch a browser
  553. if (!bLaunched)
  554. {
  555. if (IsRunningNativeOnMacOSX())
  556. {
  557. CHXFileSpecifier tempSpec;
  558. if (IsLocalFileURLAPotentialProblemBecauseOfPercentEncodedUTF8Chars(pURL))
  559. {
  560. // we handle the UTF8 problem only with local files; avoid the problem
  561. // by opening file document directly instead of using a temp file
  562. tempSpec.SetFromURL(pURL);
  563. }
  564. else
  565. {
  566. // Is OS X we can't pass an Apple event with the launch (can we?), so we'll make a document to
  567. // open which redirects to the real page
  568. // make a temp file with the redirect to the real URL; we do this for network URLs
  569. // or for local URLs that don't have UTF-8
  570. CHXDirSpecifier tempDirSpec;
  571. CHXString strRedirect;
  572. const BOOL kReplaceExistingTempFile = TRUE;
  573. strRedirect = "<HEAD>n<META HTTP-EQUIV="refresh" CONTENT="0;URL=";
  574. strRedirect += pURL;
  575. strRedirect += "">n</HEAD>n";
  576. // make a file spec for a temp file, create the file and open it,
  577. // and write the redirect into the file
  578. tempDirSpec = CHXFileSpecUtils::MacFindFolder(kOnAppropriateDisk, kChewableItemsFolderType);
  579. tempSpec = CHXFileSpecUtils::GetUniqueTempFileSpec(tempDirSpec, "HX_hurl_%.html", "%");
  580. check(tempSpec.IsSet());
  581. err = CHXFileSpecUtils::WriteTextFile(tempSpec, strRedirect, kReplaceExistingTempFile);
  582. check_noerr(err);
  583. }
  584. // launch the browser with that temp file
  585. if (err == noErr)
  586. {
  587. LSLaunchFSRefSpec launchSpec;
  588. ZeroInit(&launchSpec);
  589. launchSpec.appRef = &browserFSRef;
  590. launchSpec.numDocs = 1;
  591. launchSpec.itemRefs = (FSRef *) tempSpec;
  592. launchSpec.launchFlags = kLSLaunchDefaults | (bBringToFront ? 0 : kLSLaunchDontSwitch);
  593. err = LSOpenFromRefSpec(&launchSpec, NULL); // NULL -> don't care about FSRef of launched app
  594. }
  595. if (err == noErr)
  596. {
  597. bLaunched = TRUE;
  598. }
  599. }
  600. else
  601. {
  602. // OS 9 launch
  603. AppleEvent theEvent;
  604. if (MakeOpenURLEvent(defaultBrowserSignature, pURL, &theEvent, bNewWindow))
  605. {
  606. ProcessSerialNumber* kDontCareAboutPSN = NULL;
  607. short launchFlags;
  608. FSSpec appSpec;
  609. launchFlags = (launchContinue | launchNoFileFlags);
  610. if (!bBringToFront) 
  611. {
  612. launchFlags |= launchDontSwitch;
  613. }
  614. err = FindApplicationBySignature(defaultBrowserSignature, &appSpec);
  615. if (err == noErr)
  616. {
  617. err = FSpLaunchApplicationWithParamsAndFlags(&appSpec, &theEvent, 
  618. kDontCareAboutPSN, launchFlags);
  619. }
  620. if (err == noErr)
  621. {
  622. bLaunched = TRUE;
  623. }
  624. (void) AEDisposeDesc(&theEvent);
  625. }
  626. }
  627. }
  628. // last ditch effort is to rely on InternetConfig
  629. if (!bLaunched)
  630. {
  631. err = HXInternetConfigMac::LaunchURL(pURL);
  632. if (err == noErr)
  633. {
  634. bLaunched = TRUE;
  635. }
  636. }
  637. return bLaunched;
  638. #endif
  639. }    
  640. Boolean IsLocalFileURLAPotentialProblemBecauseOfPercentEncodedUTF8Chars(const char *pURL)
  641. {
  642. // In Mac OS X, 8-bit characters become %-encoded Unicode in the URL, like
  643. // this:
  644. //  folder