hurl.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:28k
源码类别:

Symbian

开发平台:

Visual C++

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