PageRenderTime 52ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llviewermedia.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2092 lines | 1447 code | 290 blank | 355 comment | 267 complexity | 6c863bb92bbd6d18258348eca7b38dc3 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llviewermedia.cpp
  3. * @brief Client interface to the media engine
  4. *
  5. * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llviewermedia.h"
  28. #include "llagent.h"
  29. #include "llagentcamera.h"
  30. #include "llappviewer.h"
  31. #include "llaudioengine.h" // for gAudiop
  32. #include "llcallbacklist.h"
  33. #include "lldir.h"
  34. #include "lldiriterator.h"
  35. #include "llevent.h" // LLSimpleListener
  36. #include "llfilepicker.h"
  37. #include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows.
  38. #include "llfocusmgr.h"
  39. #include "llkeyboard.h"
  40. #include "lllogininstance.h"
  41. #include "llmarketplacefunctions.h"
  42. #include "llmediaentry.h"
  43. #include "llmimetypes.h"
  44. #include "llmutelist.h"
  45. #include "llnotifications.h"
  46. #include "llnotificationsutil.h"
  47. #include "llpanelprofile.h"
  48. #include "llparcel.h"
  49. #include "llpluginclassmedia.h"
  50. #include "llplugincookiestore.h"
  51. #include "llurldispatcher.h"
  52. #include "lluuid.h"
  53. #include "llversioninfo.h"
  54. #include "llviewermediafocus.h"
  55. #include "llviewercontrol.h"
  56. #include "llviewernetwork.h"
  57. #include "llviewerparcelmedia.h"
  58. #include "llviewerparcelmgr.h"
  59. #include "llviewerregion.h"
  60. #include "llviewertexture.h"
  61. #include "llviewertexturelist.h"
  62. #include "llviewerwindow.h"
  63. #include "llvoavatar.h"
  64. #include "llvoavatarself.h"
  65. #include "llvovolume.h"
  66. #include "llwebprofile.h"
  67. #include "llwebsharing.h" // For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this!
  68. #include "llwindow.h"
  69. #include "llvieweraudio.h"
  70. #include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows.
  71. #include <boost/bind.hpp> // for SkinFolder listener
  72. #include <boost/signals2.hpp>
  73. /*static*/ const char* LLViewerMedia::AUTO_PLAY_MEDIA_SETTING = "ParcelMediaAutoPlayEnable";
  74. /*static*/ const char* LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING = "MediaShowOnOthers";
  75. /*static*/ const char* LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING = "MediaShowWithinParcel";
  76. /*static*/ const char* LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING = "MediaShowOutsideParcel";
  77. // Move this to its own file.
  78. LLViewerMediaEventEmitter::~LLViewerMediaEventEmitter()
  79. {
  80. observerListType::iterator iter = mObservers.begin();
  81. while( iter != mObservers.end() )
  82. {
  83. LLViewerMediaObserver *self = *iter;
  84. iter++;
  85. remObserver(self);
  86. }
  87. }
  88. ///////////////////////////////////////////////////////////////////////////////
  89. //
  90. bool LLViewerMediaEventEmitter::addObserver( LLViewerMediaObserver* observer )
  91. {
  92. if ( ! observer )
  93. return false;
  94. if ( std::find( mObservers.begin(), mObservers.end(), observer ) != mObservers.end() )
  95. return false;
  96. mObservers.push_back( observer );
  97. observer->mEmitters.push_back( this );
  98. return true;
  99. }
  100. ///////////////////////////////////////////////////////////////////////////////
  101. //
  102. bool LLViewerMediaEventEmitter::remObserver( LLViewerMediaObserver* observer )
  103. {
  104. if ( ! observer )
  105. return false;
  106. mObservers.remove( observer );
  107. observer->mEmitters.remove(this);
  108. return true;
  109. }
  110. ///////////////////////////////////////////////////////////////////////////////
  111. //
  112. void LLViewerMediaEventEmitter::emitEvent( LLPluginClassMedia* media, LLViewerMediaObserver::EMediaEvent event )
  113. {
  114. // Broadcast the event to any observers.
  115. observerListType::iterator iter = mObservers.begin();
  116. while( iter != mObservers.end() )
  117. {
  118. LLViewerMediaObserver *self = *iter;
  119. ++iter;
  120. self->handleMediaEvent( media, event );
  121. }
  122. }
  123. // Move this to its own file.
  124. LLViewerMediaObserver::~LLViewerMediaObserver()
  125. {
  126. std::list<LLViewerMediaEventEmitter *>::iterator iter = mEmitters.begin();
  127. while( iter != mEmitters.end() )
  128. {
  129. LLViewerMediaEventEmitter *self = *iter;
  130. iter++;
  131. self->remObserver( this );
  132. }
  133. }
  134. // Move this to its own file.
  135. // helper class that tries to download a URL from a web site and calls a method
  136. // on the Panel Land Media and to discover the MIME type
  137. class LLMimeDiscoveryResponder : public LLHTTPClient::Responder
  138. {
  139. LOG_CLASS(LLMimeDiscoveryResponder);
  140. public:
  141. LLMimeDiscoveryResponder( viewer_media_t media_impl)
  142. : mMediaImpl(media_impl),
  143. mInitialized(false)
  144. {
  145. if(mMediaImpl->mMimeTypeProbe != NULL)
  146. {
  147. llerrs << "impl already has an outstanding responder" << llendl;
  148. }
  149. mMediaImpl->mMimeTypeProbe = this;
  150. }
  151. ~LLMimeDiscoveryResponder()
  152. {
  153. disconnectOwner();
  154. }
  155. virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content)
  156. {
  157. std::string media_type = content["content-type"].asString();
  158. std::string::size_type idx1 = media_type.find_first_of(";");
  159. std::string mime_type = media_type.substr(0, idx1);
  160. lldebugs << "status is " << status << ", media type \"" << media_type << "\"" << llendl;
  161. // 2xx status codes indicate success.
  162. // Most 4xx status codes are successful enough for our purposes.
  163. // 499 is the error code for host not found, timeout, etc.
  164. // 500 means "Internal Server error" but we decided it's okay to
  165. // accept this and go past it in the MIME type probe
  166. // 302 means the resource can be found temporarily in a different place - added this for join.secondlife.com
  167. // 499 is a code specifc to join.secondlife.com (????) apparently safe to ignore
  168. // if( ((status >= 200) && (status < 300)) ||
  169. // ((status >= 400) && (status < 499)) ||
  170. // (status == 500) ||
  171. // (status == 302) ||
  172. // (status == 499)
  173. // )
  174. // We now no longer check the error code returned from the probe.
  175. // If we have a mime type, use it. If not, default to the web plugin and let it handle error reporting.
  176. if(1)
  177. {
  178. // The probe was successful.
  179. if(mime_type.empty())
  180. {
  181. // Some sites don't return any content-type header at all.
  182. // Treat an empty mime type as text/html.
  183. mime_type = "text/html";
  184. }
  185. completeAny(status, mime_type);
  186. }
  187. else
  188. {
  189. llwarns << "responder failed with status " << status << ", reason " << reason << llendl;
  190. if(mMediaImpl)
  191. {
  192. mMediaImpl->mMediaSourceFailed = true;
  193. }
  194. }
  195. }
  196. void completeAny(U32 status, const std::string& mime_type)
  197. {
  198. // the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.
  199. // Make a local copy so we can call loadURI() afterwards.
  200. LLViewerMediaImpl *impl = mMediaImpl;
  201. if(impl && !mInitialized && ! mime_type.empty())
  202. {
  203. if(impl->initializeMedia(mime_type))
  204. {
  205. mInitialized = true;
  206. impl->loadURI();
  207. disconnectOwner();
  208. }
  209. }
  210. }
  211. void cancelRequest()
  212. {
  213. disconnectOwner();
  214. }
  215. private:
  216. void disconnectOwner()
  217. {
  218. if(mMediaImpl)
  219. {
  220. if(mMediaImpl->mMimeTypeProbe != this)
  221. {
  222. llerrs << "internal error: mMediaImpl->mMimeTypeProbe != this" << llendl;
  223. }
  224. mMediaImpl->mMimeTypeProbe = NULL;
  225. }
  226. mMediaImpl = NULL;
  227. }
  228. public:
  229. LLViewerMediaImpl *mMediaImpl;
  230. bool mInitialized;
  231. };
  232. class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder
  233. {
  234. LOG_CLASS(LLViewerMediaOpenIDResponder);
  235. public:
  236. LLViewerMediaOpenIDResponder( )
  237. {
  238. }
  239. ~LLViewerMediaOpenIDResponder()
  240. {
  241. }
  242. /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
  243. {
  244. LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
  245. LL_DEBUGS("MediaAuth") << content << LL_ENDL;
  246. std::string cookie = content["set-cookie"].asString();
  247. LLViewerMedia::openIDCookieResponse(cookie);
  248. }
  249. /* virtual */ void completedRaw(
  250. U32 status,
  251. const std::string& reason,
  252. const LLChannelDescriptors& channels,
  253. const LLIOPipe::buffer_ptr_t& buffer)
  254. {
  255. // This is just here to disable the default behavior (attempting to parse the response as llsd).
  256. // We don't care about the content of the response, only the set-cookie header.
  257. }
  258. };
  259. class LLViewerMediaWebProfileResponder : public LLHTTPClient::Responder
  260. {
  261. LOG_CLASS(LLViewerMediaWebProfileResponder);
  262. public:
  263. LLViewerMediaWebProfileResponder(std::string host)
  264. {
  265. mHost = host;
  266. }
  267. ~LLViewerMediaWebProfileResponder()
  268. {
  269. }
  270. /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
  271. {
  272. LL_WARNS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
  273. LL_WARNS("MediaAuth") << content << LL_ENDL;
  274. std::string cookie = content["set-cookie"].asString();
  275. LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost);
  276. // Set cookie for snapshot publishing.
  277. std::string auth_cookie = cookie.substr(0, cookie.find(";")); // strip path
  278. LLWebProfile::setAuthCookie(auth_cookie);
  279. }
  280. void completedRaw(
  281. U32 status,
  282. const std::string& reason,
  283. const LLChannelDescriptors& channels,
  284. const LLIOPipe::buffer_ptr_t& buffer)
  285. {
  286. // This is just here to disable the default behavior (attempting to parse the response as llsd).
  287. // We don't care about the content of the response, only the set-cookie header.
  288. }
  289. std::string mHost;
  290. };
  291. LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL;
  292. LLURL LLViewerMedia::sOpenIDURL;
  293. std::string LLViewerMedia::sOpenIDCookie;
  294. LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = NULL;
  295. static LLViewerMedia::impl_list sViewerMediaImplList;
  296. static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap;
  297. static LLTimer sMediaCreateTimer;
  298. static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f;
  299. static F32 sGlobalVolume = 1.0f;
  300. static bool sForceUpdate = false;
  301. static LLUUID sOnlyAudibleTextureID = LLUUID::null;
  302. static F64 sLowestLoadableImplInterest = 0.0f;
  303. static bool sAnyMediaShowing = false;
  304. static boost::signals2::connection sTeleportFinishConnection;
  305. static std::string sUpdatedCookies;
  306. static const char *PLUGIN_COOKIE_FILE_NAME = "plugin_cookies.txt";
  307. //////////////////////////////////////////////////////////////////////////////////////////
  308. static void add_media_impl(LLViewerMediaImpl* media)
  309. {
  310. sViewerMediaImplList.push_back(media);
  311. }
  312. //////////////////////////////////////////////////////////////////////////////////////////
  313. static void remove_media_impl(LLViewerMediaImpl* media)
  314. {
  315. LLViewerMedia::impl_list::iterator iter = sViewerMediaImplList.begin();
  316. LLViewerMedia::impl_list::iterator end = sViewerMediaImplList.end();
  317. for(; iter != end; iter++)
  318. {
  319. if(media == *iter)
  320. {
  321. sViewerMediaImplList.erase(iter);
  322. return;
  323. }
  324. }
  325. }
  326. class LLViewerMediaMuteListObserver : public LLMuteListObserver
  327. {
  328. /* virtual */ void onChange() { LLViewerMedia::muteListChanged();}
  329. };
  330. static LLViewerMediaMuteListObserver sViewerMediaMuteListObserver;
  331. static bool sViewerMediaMuteListObserverInitialized = false;
  332. static bool sInWorldMediaDisabled = false;
  333. //////////////////////////////////////////////////////////////////////////////////////////
  334. // LLViewerMedia
  335. //////////////////////////////////////////////////////////////////////////////////////////
  336. // static
  337. viewer_media_t LLViewerMedia::newMediaImpl(
  338. const LLUUID& texture_id,
  339. S32 media_width,
  340. S32 media_height,
  341. U8 media_auto_scale,
  342. U8 media_loop)
  343. {
  344. LLViewerMediaImpl* media_impl = getMediaImplFromTextureID(texture_id);
  345. if(media_impl == NULL || texture_id.isNull())
  346. {
  347. // Create the media impl
  348. media_impl = new LLViewerMediaImpl(texture_id, media_width, media_height, media_auto_scale, media_loop);
  349. }
  350. else
  351. {
  352. media_impl->unload();
  353. media_impl->setTextureID(texture_id);
  354. media_impl->mMediaWidth = media_width;
  355. media_impl->mMediaHeight = media_height;
  356. media_impl->mMediaAutoScale = media_auto_scale;
  357. media_impl->mMediaLoop = media_loop;
  358. }
  359. return media_impl;
  360. }
  361. viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const std::string& previous_url, bool update_from_self)
  362. {
  363. // Try to find media with the same media ID
  364. viewer_media_t media_impl = getMediaImplFromTextureID(media_entry->getMediaID());
  365. lldebugs << "called, current URL is \"" << media_entry->getCurrentURL()
  366. << "\", previous URL is \"" << previous_url
  367. << "\", update_from_self is " << (update_from_self?"true":"false")
  368. << llendl;
  369. bool was_loaded = false;
  370. bool needs_navigate = false;
  371. if(media_impl)
  372. {
  373. was_loaded = media_impl->hasMedia();
  374. media_impl->setHomeURL(media_entry->getHomeURL());
  375. media_impl->mMediaAutoScale = media_entry->getAutoScale();
  376. media_impl->mMediaLoop = media_entry->getAutoLoop();
  377. media_impl->mMediaWidth = media_entry->getWidthPixels();
  378. media_impl->mMediaHeight = media_entry->getHeightPixels();
  379. media_impl->mMediaAutoPlay = media_entry->getAutoPlay();
  380. media_impl->mMediaEntryURL = media_entry->getCurrentURL();
  381. if (media_impl->mMediaSource)
  382. {
  383. media_impl->mMediaSource->setAutoScale(media_impl->mMediaAutoScale);
  384. media_impl->mMediaSource->setLoop(media_impl->mMediaLoop);
  385. media_impl->mMediaSource->setSize(media_entry->getWidthPixels(), media_entry->getHeightPixels());
  386. }
  387. bool url_changed = (media_impl->mMediaEntryURL != previous_url);
  388. if(media_impl->mMediaEntryURL.empty())
  389. {
  390. if(url_changed)
  391. {
  392. // The current media URL is now empty. Unload the media source.
  393. media_impl->unload();
  394. lldebugs << "Unloading media instance (new current URL is empty)." << llendl;
  395. }
  396. }
  397. else
  398. {
  399. // The current media URL is not empty.
  400. // If (the media was already loaded OR the media was set to autoplay) AND this update didn't come from this agent,
  401. // do a navigate.
  402. bool auto_play = media_impl->isAutoPlayable();
  403. if((was_loaded || auto_play) && !update_from_self)
  404. {
  405. needs_navigate = url_changed;
  406. }
  407. lldebugs << "was_loaded is " << (was_loaded?"true":"false")
  408. << ", auto_play is " << (auto_play?"true":"false")
  409. << ", needs_navigate is " << (needs_navigate?"true":"false") << llendl;
  410. }
  411. }
  412. else
  413. {
  414. media_impl = newMediaImpl(
  415. media_entry->getMediaID(),
  416. media_entry->getWidthPixels(),
  417. media_entry->getHeightPixels(),
  418. media_entry->getAutoScale(),
  419. media_entry->getAutoLoop());
  420. media_impl->setHomeURL(media_entry->getHomeURL());
  421. media_impl->mMediaAutoPlay = media_entry->getAutoPlay();
  422. media_impl->mMediaEntryURL = media_entry->getCurrentURL();
  423. if(media_impl->isAutoPlayable())
  424. {
  425. needs_navigate = true;
  426. }
  427. }
  428. if(media_impl)
  429. {
  430. if(needs_navigate)
  431. {
  432. media_impl->navigateTo(media_impl->mMediaEntryURL, "", true, true);
  433. lldebugs << "navigating to URL " << media_impl->mMediaEntryURL << llendl;
  434. }
  435. else if(!media_impl->mMediaURL.empty() && (media_impl->mMediaURL != media_impl->mMediaEntryURL))
  436. {
  437. // If we already have a non-empty media URL set and we aren't doing a navigate, update the media URL to match the media entry.
  438. media_impl->mMediaURL = media_impl->mMediaEntryURL;
  439. // If this causes a navigate at some point (such as after a reload), it should be considered server-driven so it isn't broadcast.
  440. media_impl->mNavigateServerRequest = true;
  441. lldebugs << "updating URL in the media impl to " << media_impl->mMediaEntryURL << llendl;
  442. }
  443. }
  444. return media_impl;
  445. }
  446. //////////////////////////////////////////////////////////////////////////////////////////
  447. // static
  448. LLViewerMediaImpl* LLViewerMedia::getMediaImplFromTextureID(const LLUUID& texture_id)
  449. {
  450. LLViewerMediaImpl* result = NULL;
  451. // Look up the texture ID in the texture id->impl map.
  452. impl_id_map::iterator iter = sViewerMediaTextureIDMap.find(texture_id);
  453. if(iter != sViewerMediaTextureIDMap.end())
  454. {
  455. result = iter->second;
  456. }
  457. return result;
  458. }
  459. //////////////////////////////////////////////////////////////////////////////////////////
  460. // static
  461. std::string LLViewerMedia::getCurrentUserAgent()
  462. {
  463. // Don't use user-visible string to avoid
  464. // punctuation and strange characters.
  465. std::string skin_name = gSavedSettings.getString("SkinCurrent");
  466. // Just in case we need to check browser differences in A/B test
  467. // builds.
  468. std::string channel = LLVersionInfo::getChannel();
  469. // append our magic version number string to the browser user agent id
  470. // See the HTTP 1.0 and 1.1 specifications for allowed formats:
  471. // http://www.ietf.org/rfc/rfc1945.txt section 10.15
  472. // http://www.ietf.org/rfc/rfc2068.txt section 3.8
  473. // This was also helpful:
  474. // http://www.mozilla.org/build/revised-user-agent-strings.html
  475. std::ostringstream codec;
  476. codec << "SecondLife/";
  477. codec << LLVersionInfo::getVersion();
  478. codec << " (" << channel << "; " << skin_name << " skin)";
  479. llinfos << codec.str() << llendl;
  480. return codec.str();
  481. }
  482. //////////////////////////////////////////////////////////////////////////////////////////
  483. // static
  484. void LLViewerMedia::updateBrowserUserAgent()
  485. {
  486. std::string user_agent = getCurrentUserAgent();
  487. impl_list::iterator iter = sViewerMediaImplList.begin();
  488. impl_list::iterator end = sViewerMediaImplList.end();
  489. for(; iter != end; iter++)
  490. {
  491. LLViewerMediaImpl* pimpl = *iter;
  492. if(pimpl->mMediaSource && pimpl->mMediaSource->pluginSupportsMediaBrowser())
  493. {
  494. pimpl->mMediaSource->setBrowserUserAgent(user_agent);
  495. }
  496. }
  497. }
  498. //////////////////////////////////////////////////////////////////////////////////////////
  499. // static
  500. bool LLViewerMedia::handleSkinCurrentChanged(const LLSD& /*newvalue*/)
  501. {
  502. // gSavedSettings is already updated when this function is called.
  503. updateBrowserUserAgent();
  504. return true;
  505. }
  506. //////////////////////////////////////////////////////////////////////////////////////////
  507. // static
  508. bool LLViewerMedia::textureHasMedia(const LLUUID& texture_id)
  509. {
  510. impl_list::iterator iter = sViewerMediaImplList.begin();
  511. impl_list::iterator end = sViewerMediaImplList.end();
  512. for(; iter != end; iter++)
  513. {
  514. LLViewerMediaImpl* pimpl = *iter;
  515. if(pimpl->getMediaTextureID() == texture_id)
  516. {
  517. return true;
  518. }
  519. }
  520. return false;
  521. }
  522. //////////////////////////////////////////////////////////////////////////////////////////
  523. // static
  524. void LLViewerMedia::setVolume(F32 volume)
  525. {
  526. if(volume != sGlobalVolume || sForceUpdate)
  527. {
  528. sGlobalVolume = volume;
  529. impl_list::iterator iter = sViewerMediaImplList.begin();
  530. impl_list::iterator end = sViewerMediaImplList.end();
  531. for(; iter != end; iter++)
  532. {
  533. LLViewerMediaImpl* pimpl = *iter;
  534. pimpl->updateVolume();
  535. }
  536. sForceUpdate = false;
  537. }
  538. }
  539. //////////////////////////////////////////////////////////////////////////////////////////
  540. // static
  541. F32 LLViewerMedia::getVolume()
  542. {
  543. return sGlobalVolume;
  544. }
  545. //////////////////////////////////////////////////////////////////////////////////////////
  546. // static
  547. void LLViewerMedia::muteListChanged()
  548. {
  549. // When the mute list changes, we need to check mute status on all impls.
  550. impl_list::iterator iter = sViewerMediaImplList.begin();
  551. impl_list::iterator end = sViewerMediaImplList.end();
  552. for(; iter != end; iter++)
  553. {
  554. LLViewerMediaImpl* pimpl = *iter;
  555. pimpl->mNeedsMuteCheck = true;
  556. }
  557. }
  558. //////////////////////////////////////////////////////////////////////////////////////////
  559. // static
  560. void LLViewerMedia::setInWorldMediaDisabled(bool disabled)
  561. {
  562. sInWorldMediaDisabled = disabled;
  563. }
  564. //////////////////////////////////////////////////////////////////////////////////////////
  565. // static
  566. bool LLViewerMedia::getInWorldMediaDisabled()
  567. {
  568. return sInWorldMediaDisabled;
  569. }
  570. //////////////////////////////////////////////////////////////////////////////////////////
  571. // static
  572. bool LLViewerMedia::isInterestingEnough(const LLVOVolume *object, const F64 &object_interest)
  573. {
  574. bool result = false;
  575. if (NULL == object)
  576. {
  577. result = false;
  578. }
  579. // Focused? Then it is interesting!
  580. else if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == object->getID())
  581. {
  582. result = true;
  583. }
  584. // Selected? Then it is interesting!
  585. // XXX Sadly, 'contains()' doesn't take a const :(
  586. else if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(object)))
  587. {
  588. result = true;
  589. }
  590. else
  591. {
  592. lldebugs << "object interest = " << object_interest << ", lowest loadable = " << sLowestLoadableImplInterest << llendl;
  593. if(object_interest >= sLowestLoadableImplInterest)
  594. result = true;
  595. }
  596. return result;
  597. }
  598. LLViewerMedia::impl_list &LLViewerMedia::getPriorityList()
  599. {
  600. return sViewerMediaImplList;
  601. }
  602. // This is the predicate function used to sort sViewerMediaImplList by priority.
  603. bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
  604. {
  605. if(i1->isForcedUnloaded() && !i2->isForcedUnloaded())
  606. {
  607. // Muted or failed items always go to the end of the list, period.
  608. return false;
  609. }
  610. else if(i2->isForcedUnloaded() && !i1->isForcedUnloaded())
  611. {
  612. // Muted or failed items always go to the end of the list, period.
  613. return true;
  614. }
  615. else if(i1->hasFocus())
  616. {
  617. // The item with user focus always comes to the front of the list, period.
  618. return true;
  619. }
  620. else if(i2->hasFocus())
  621. {
  622. // The item with user focus always comes to the front of the list, period.
  623. return false;
  624. }
  625. else if(i1->isParcelMedia())
  626. {
  627. // The parcel media impl sorts above all other inworld media, unless one has focus.
  628. return true;
  629. }
  630. else if(i2->isParcelMedia())
  631. {
  632. // The parcel media impl sorts above all other inworld media, unless one has focus.
  633. return false;
  634. }
  635. else if(i1->getUsedInUI() && !i2->getUsedInUI())
  636. {
  637. // i1 is a UI element, i2 is not. This makes i1 "less than" i2, so it sorts earlier in our list.
  638. return true;
  639. }
  640. else if(i2->getUsedInUI() && !i1->getUsedInUI())
  641. {
  642. // i2 is a UI element, i1 is not. This makes i2 "less than" i1, so it sorts earlier in our list.
  643. return false;
  644. }
  645. else if(i1->isPlayable() && !i2->isPlayable())
  646. {
  647. // Playable items sort above ones that wouldn't play even if they got high enough priority
  648. return true;
  649. }
  650. else if(!i1->isPlayable() && i2->isPlayable())
  651. {
  652. // Playable items sort above ones that wouldn't play even if they got high enough priority
  653. return false;
  654. }
  655. else if(i1->getInterest() == i2->getInterest())
  656. {
  657. // Generally this will mean both objects have zero interest. In this case, sort on distance.
  658. return (i1->getProximityDistance() < i2->getProximityDistance());
  659. }
  660. else
  661. {
  662. // The object with the larger interest value should be earlier in the list, so we reverse the sense of the comparison here.
  663. return (i1->getInterest() > i2->getInterest());
  664. }
  665. }
  666. static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
  667. {
  668. if(i1->getProximityDistance() < i2->getProximityDistance())
  669. {
  670. return true;
  671. }
  672. else if(i1->getProximityDistance() > i2->getProximityDistance())
  673. {
  674. return false;
  675. }
  676. else
  677. {
  678. // Both objects have the same distance. This most likely means they're two faces of the same object.
  679. // They may also be faces on different objects with exactly the same distance (like HUD objects).
  680. // We don't actually care what the sort order is for this case, as long as it's stable and doesn't change when you enable/disable media.
  681. // Comparing the impl pointers gives a completely arbitrary ordering, but it will be stable.
  682. return (i1 < i2);
  683. }
  684. }
  685. static LLFastTimer::DeclareTimer FTM_MEDIA_UPDATE("Update Media");
  686. static LLFastTimer::DeclareTimer FTM_MEDIA_SPARE_IDLE("Spare Idle");
  687. static LLFastTimer::DeclareTimer FTM_MEDIA_UPDATE_INTEREST("Update/Interest");
  688. static LLFastTimer::DeclareTimer FTM_MEDIA_SORT("Sort");
  689. static LLFastTimer::DeclareTimer FTM_MEDIA_SORT2("Sort 2");
  690. static LLFastTimer::DeclareTimer FTM_MEDIA_MISC("Misc");
  691. //////////////////////////////////////////////////////////////////////////////////////////
  692. // static
  693. void LLViewerMedia::updateMedia(void *dummy_arg)
  694. {
  695. LLFastTimer t1(FTM_MEDIA_UPDATE);
  696. // Enable/disable the plugin read thread
  697. LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread"));
  698. // HACK: we always try to keep a spare running webkit plugin around to improve launch times.
  699. createSpareBrowserMediaSource();
  700. sAnyMediaShowing = false;
  701. sUpdatedCookies = getCookieStore()->getChangedCookies();
  702. if(!sUpdatedCookies.empty())
  703. {
  704. lldebugs << "updated cookies will be sent to all loaded plugins: " << llendl;
  705. lldebugs << sUpdatedCookies << llendl;
  706. }
  707. impl_list::iterator iter = sViewerMediaImplList.begin();
  708. impl_list::iterator end = sViewerMediaImplList.end();
  709. {
  710. LLFastTimer t(FTM_MEDIA_UPDATE_INTEREST);
  711. for(; iter != end;)
  712. {
  713. LLViewerMediaImpl* pimpl = *iter++;
  714. pimpl->update();
  715. pimpl->calculateInterest();
  716. }
  717. }
  718. // Let the spare media source actually launch
  719. if(sSpareBrowserMediaSource)
  720. {
  721. LLFastTimer t(FTM_MEDIA_SPARE_IDLE);
  722. sSpareBrowserMediaSource->idle();
  723. }
  724. {
  725. LLFastTimer t(FTM_MEDIA_SORT);
  726. // Sort the static instance list using our interest criteria
  727. sViewerMediaImplList.sort(priorityComparitor);
  728. }
  729. // Go through the list again and adjust according to priority.
  730. iter = sViewerMediaImplList.begin();
  731. end = sViewerMediaImplList.end();
  732. F64 total_cpu = 0.0f;
  733. int impl_count_total = 0;
  734. int impl_count_interest_low = 0;
  735. int impl_count_interest_normal = 0;
  736. std::vector<LLViewerMediaImpl*> proximity_order;
  737. bool inworld_media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia");
  738. bool inworld_audio_enabled = gSavedSettings.getBOOL("AudioStreamingMusic");
  739. U32 max_instances = gSavedSettings.getU32("PluginInstancesTotal");
  740. U32 max_normal = gSavedSettings.getU32("PluginInstancesNormal");
  741. U32 max_low = gSavedSettings.getU32("PluginInstancesLow");
  742. F32 max_cpu = gSavedSettings.getF32("PluginInstancesCPULimit");
  743. // Setting max_cpu to 0.0 disables CPU usage checking.
  744. bool check_cpu_usage = (max_cpu != 0.0f);
  745. LLViewerMediaImpl* lowest_interest_loadable = NULL;
  746. // Notes on tweakable params:
  747. // max_instances must be set high enough to allow the various instances used in the UI (for the help browser, search, etc.) to be loaded.
  748. // If max_normal + max_low is less than max_instances, things will tend to get unloaded instead of being set to slideshow.
  749. {
  750. LLFastTimer t(FTM_MEDIA_MISC);
  751. for(; iter != end; iter++)
  752. {
  753. LLViewerMediaImpl* pimpl = *iter;
  754. LLPluginClassMedia::EPriority new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
  755. if(pimpl->isForcedUnloaded() || (impl_count_total >= (int)max_instances))
  756. {
  757. // Never load muted or failed impls.
  758. // Hard limit on the number of instances that will be loaded at one time
  759. new_priority = LLPluginClassMedia::PRIORITY_UNLOADED;
  760. }
  761. else if(!pimpl->getVisible())
  762. {
  763. new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
  764. }
  765. else if(pimpl->hasFocus())
  766. {
  767. new_priority = LLPluginClassMedia::PRIORITY_HIGH;
  768. impl_count_interest_normal++; // count this against the count of "normal" instances for priority purposes
  769. }
  770. else if(pimpl->getUsedInUI())
  771. {
  772. new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
  773. impl_count_interest_normal++;
  774. }
  775. else if(pimpl->isParcelMedia())
  776. {
  777. new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
  778. impl_count_interest_normal++;
  779. }
  780. else
  781. {
  782. // Look at interest and CPU usage for instances that aren't in any of the above states.
  783. // Heuristic -- if the media texture's approximate screen area is less than 1/4 of the native area of the texture,
  784. // turn it down to low instead of normal. This may downsample for plugins that support it.
  785. bool media_is_small = false;
  786. F64 approximate_interest = pimpl->getApproximateTextureInterest();
  787. if(approximate_interest == 0.0f)
  788. {
  789. // this media has no current size, which probably means it's not loaded.
  790. media_is_small = true;
  791. }
  792. else if(pimpl->getInterest() < (approximate_interest / 4))
  793. {
  794. media_is_small = true;
  795. }
  796. if(pimpl->getInterest() == 0.0f)
  797. {
  798. // This media is completely invisible, due to being outside the view frustrum or out of range.
  799. new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
  800. }
  801. else if(check_cpu_usage && (total_cpu > max_cpu))
  802. {
  803. // Higher priority plugins have already used up the CPU budget. Set remaining ones to slideshow priority.
  804. new_priority = LLPluginClassMedia::PRIORITY_SLIDESHOW;
  805. }
  806. else if((impl_count_interest_normal < (int)max_normal) && !media_is_small)
  807. {
  808. // Up to max_normal inworld get normal priority
  809. new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
  810. impl_count_interest_normal++;
  811. }
  812. else if (impl_count_interest_low + impl_count_interest_normal < (int)max_low + (int)max_normal)
  813. {
  814. // The next max_low inworld get turned down
  815. new_priority = LLPluginClassMedia::PRIORITY_LOW;
  816. impl_count_interest_low++;
  817. // Set the low priority size for downsampling to approximately the size the texture is displayed at.
  818. {
  819. F32 approximate_interest_dimension = (F32) sqrt(pimpl->getInterest());
  820. pimpl->setLowPrioritySizeLimit(llround(approximate_interest_dimension));
  821. }
  822. }
  823. else
  824. {
  825. // Any additional impls (up to max_instances) get very infrequent time
  826. new_priority = LLPluginClassMedia::PRIORITY_SLIDESHOW;
  827. }
  828. }
  829. if(!pimpl->getUsedInUI() && (new_priority != LLPluginClassMedia::PRIORITY_UNLOADED))
  830. {
  831. // This is a loadable inworld impl -- the last one in the list in this class defines the lowest loadable interest.
  832. lowest_interest_loadable = pimpl;
  833. impl_count_total++;
  834. }
  835. // Overrides if the window is minimized or we lost focus (taking care
  836. // not to accidentally "raise" the priority either)
  837. if (!gViewerWindow->getActive() /* viewer window minimized? */
  838. && new_priority > LLPluginClassMedia::PRIORITY_HIDDEN)
  839. {
  840. new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
  841. }
  842. else if (!gFocusMgr.getAppHasFocus() /* viewer window lost focus? */
  843. && new_priority > LLPluginClassMedia::PRIORITY_LOW)
  844. {
  845. new_priority = LLPluginClassMedia::PRIORITY_LOW;
  846. }
  847. if(!inworld_media_enabled)
  848. {
  849. // If inworld media is locked out, force all inworld media to stay unloaded.
  850. if(!pimpl->getUsedInUI())
  851. {
  852. new_priority = LLPluginClassMedia::PRIORITY_UNLOADED;
  853. }
  854. }
  855. // update the audio stream here as well
  856. if( !inworld_audio_enabled)
  857. {
  858. if(LLViewerMedia::isParcelAudioPlaying() && gAudiop && LLViewerMedia::hasParcelAudio())
  859. {
  860. LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade();
  861. }
  862. }
  863. pimpl->setPriority(new_priority);
  864. if(pimpl->getUsedInUI())
  865. {
  866. // Any impls used in the UI should not be in the proximity list.
  867. pimpl->mProximity = -1;
  868. }
  869. else
  870. {
  871. proximity_order.push_back(pimpl);
  872. }
  873. total_cpu += pimpl->getCPUUsage();
  874. if (!pimpl->getUsedInUI() && pimpl->hasMedia())
  875. {
  876. sAnyMediaShowing = true;
  877. }
  878. }
  879. }
  880. // Re-calculate this every time.
  881. sLowestLoadableImplInterest = 0.0f;
  882. // Only do this calculation if we've hit the impl count limit -- up until that point we always need to load media data.
  883. if(lowest_interest_loadable && (impl_count_total >= (int)max_instances))
  884. {
  885. // Get the interest value of this impl's object for use by isInterestingEnough
  886. LLVOVolume *object = lowest_interest_loadable->getSomeObject();
  887. if(object)
  888. {
  889. // NOTE: Don't use getMediaInterest() here. We want the pixel area, not the total media interest,
  890. // so that we match up with the calculation done in LLMediaDataClient.
  891. sLowestLoadableImplInterest = object->getPixelArea();
  892. }
  893. }
  894. if(gSavedSettings.getBOOL("MediaPerformanceManagerDebug"))
  895. {
  896. // Give impls the same ordering as the priority list
  897. // they're already in the right order for this.
  898. }
  899. else
  900. {
  901. LLFastTimer t(FTM_MEDIA_SORT2);
  902. // Use a distance-based sort for proximity values.
  903. std::stable_sort(proximity_order.begin(), proximity_order.end(), proximity_comparitor);
  904. }
  905. // Transfer the proximity order to the proximity fields in the objects.
  906. for(int i = 0; i < (int)proximity_order.size(); i++)
  907. {
  908. proximity_order[i]->mProximity = i;
  909. }
  910. LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << llendl;
  911. }
  912. //////////////////////////////////////////////////////////////////////////////////////////
  913. // static
  914. bool LLViewerMedia::isAnyMediaShowing()
  915. {
  916. return sAnyMediaShowing;
  917. }
  918. //////////////////////////////////////////////////////////////////////////////////////////
  919. // static
  920. void LLViewerMedia::setAllMediaEnabled(bool val)
  921. {
  922. // Set "tentative" autoplay first. We need to do this here or else
  923. // re-enabling won't start up the media below.
  924. gSavedSettings.setBOOL("MediaTentativeAutoPlay", val);
  925. // Then
  926. impl_list::iterator iter = sViewerMediaImplList.begin();
  927. impl_list::iterator end = sViewerMediaImplList.end();
  928. for(; iter != end; iter++)
  929. {
  930. LLViewerMediaImpl* pimpl = *iter;
  931. if (!pimpl->getUsedInUI())
  932. {
  933. pimpl->setDisabled(!val);
  934. }
  935. }
  936. // Also do Parcel Media and Parcel Audio
  937. if (val)
  938. {
  939. if (!LLViewerMedia::isParcelMediaPlaying() && LLViewerMedia::hasParcelMedia())
  940. {
  941. LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
  942. }
  943. if (gSavedSettings.getBOOL("AudioStreamingMusic") &&
  944. !LLViewerMedia::isParcelAudioPlaying() &&
  945. gAudiop &&
  946. LLViewerMedia::hasParcelAudio())
  947. {
  948. if (LLAudioEngine::AUDIO_PAUSED == gAudiop->isInternetStreamPlaying())
  949. {
  950. // 'false' means unpause
  951. gAudiop->pauseInternetStream(false);
  952. }
  953. else
  954. {
  955. LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLViewerMedia::getParcelAudioURL());
  956. }
  957. }
  958. }
  959. else {
  960. // This actually unloads the impl, as opposed to "stop"ping the media
  961. LLViewerParcelMedia::stop();
  962. if (gAudiop)
  963. {
  964. LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade();
  965. }
  966. }
  967. }
  968. //////////////////////////////////////////////////////////////////////////////////////////
  969. // static
  970. bool LLViewerMedia::isParcelMediaPlaying()
  971. {
  972. return (LLViewerMedia::hasParcelMedia() && LLViewerParcelMedia::getParcelMedia() && LLViewerParcelMedia::getParcelMedia()->hasMedia());
  973. }
  974. /////////////////////////////////////////////////////////////////////////////////////////
  975. // static
  976. bool LLViewerMedia::isParcelAudioPlaying()
  977. {
  978. return (LLViewerMedia::hasParcelAudio() && gAudiop && LLAudioEngine::AUDIO_PLAYING == gAudiop->isInternetStreamPlaying());
  979. }
  980. void LLViewerMedia::onAuthSubmit(const LLSD& notification, const LLSD& response)
  981. {
  982. LLViewerMediaImpl *impl = LLViewerMedia::getMediaImplFromTextureID(notification["payload"]["media_id"]);
  983. if(impl)
  984. {
  985. LLPluginClassMedia* media = impl->getMediaPlugin();
  986. if(media)
  987. {
  988. if (response["ok"])
  989. {
  990. media->sendAuthResponse(true, response["username"], response["password"]);
  991. }
  992. else
  993. {
  994. media->sendAuthResponse(false, "", "");
  995. }
  996. }
  997. }
  998. }
  999. /////////////////////////////////////////////////////////////////////////////////////////
  1000. // static
  1001. void LLViewerMedia::clearAllCookies()
  1002. {
  1003. // Clear all cookies for all plugins
  1004. impl_list::iterator iter = sViewerMediaImplList.begin();
  1005. impl_list::iterator end = sViewerMediaImplList.end();
  1006. for (; iter != end; iter++)
  1007. {
  1008. LLViewerMediaImpl* pimpl = *iter;
  1009. if(pimpl->mMediaSource)
  1010. {
  1011. pimpl->mMediaSource->clear_cookies();
  1012. }
  1013. }
  1014. // Clear all cookies from the cookie store
  1015. getCookieStore()->setAllCookies("");
  1016. // FIXME: this may not be sufficient, since the on-disk cookie file won't get written until some browser instance exits cleanly.
  1017. // It also won't clear cookies for other accounts, or for any account if we're not logged in, and won't do anything at all if there are no webkit plugins loaded.
  1018. // Until such time as we can centralize cookie storage, the following hack should cover these cases:
  1019. // HACK: Look for cookie files in all possible places and delete them.
  1020. // NOTE: this assumes knowledge of what happens inside the webkit plugin (it's what adds 'browser_profile' to the path and names the cookie file)
  1021. // Places that cookie files can be:
  1022. // <getOSUserAppDir>/browser_profile/cookies
  1023. // <getOSUserAppDir>/first_last/browser_profile/cookies (note that there may be any number of these!)
  1024. // <getOSUserAppDir>/first_last/plugin_cookies.txt (note that there may be any number of these!)
  1025. std::string base_dir = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter();
  1026. std::string target;
  1027. std::string filename;
  1028. lldebugs << "base dir = " << base_dir << llendl;
  1029. // The non-logged-in version is easy
  1030. target = base_dir;
  1031. target += "browser_profile";
  1032. target += gDirUtilp->getDirDelimiter();
  1033. target += "cookies";
  1034. lldebugs << "target = " << target << llendl;
  1035. if(LLFile::isfile(target))
  1036. {
  1037. LLFile::remove(target);
  1038. }
  1039. // the hard part: iterate over all user directories and delete the cookie file from each one
  1040. LLDirIterator dir_iter(base_dir, "*_*");
  1041. while (dir_iter.next(filename))
  1042. {
  1043. target = base_dir;
  1044. target += filename;
  1045. target += gDirUtilp->getDirDelimiter();
  1046. target += "browser_profile";
  1047. target += gDirUtilp->getDirDelimiter();
  1048. target += "cookies";
  1049. lldebugs << "target = " << target << llendl;
  1050. if(LLFile::isfile(target))
  1051. {
  1052. LLFile::remove(target);
  1053. }
  1054. // Other accounts may have new-style cookie files too -- delete them as well
  1055. target = base_dir;
  1056. target += filename;
  1057. target += gDirUtilp->getDirDelimiter();
  1058. target += PLUGIN_COOKIE_FILE_NAME;
  1059. lldebugs << "target = " << target << llendl;
  1060. if(LLFile::isfile(target))
  1061. {
  1062. LLFile::remove(target);
  1063. }
  1064. }
  1065. // If we have an OpenID cookie, re-add it to the cookie store.
  1066. setOpenIDCookie();
  1067. }
  1068. /////////////////////////////////////////////////////////////////////////////////////////
  1069. // static
  1070. void LLViewerMedia::clearAllCaches()
  1071. {
  1072. // Clear all plugins' caches
  1073. impl_list::iterator iter = sViewerMediaImplList.begin();
  1074. impl_list::iterator end = sViewerMediaImplList.end();
  1075. for (; iter != end; iter++)
  1076. {
  1077. LLViewerMediaImpl* pimpl = *iter;
  1078. pimpl->clearCache();
  1079. }
  1080. }
  1081. /////////////////////////////////////////////////////////////////////////////////////////
  1082. // static
  1083. void LLViewerMedia::setCookiesEnabled(bool enabled)
  1084. {
  1085. // Set the "cookies enabled" flag for all loaded plugins
  1086. impl_list::iterator iter = sViewerMediaImplList.begin();
  1087. impl_list::iterator end = sViewerMediaImplList.end();
  1088. for (; iter != end; iter++)
  1089. {
  1090. LLViewerMediaImpl* pimpl = *iter;
  1091. if(pimpl->mMediaSource)
  1092. {
  1093. pimpl->mMediaSource->enable_cookies(enabled);
  1094. }
  1095. }
  1096. }
  1097. /////////////////////////////////////////////////////////////////////////////////////////
  1098. // static
  1099. void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int port)
  1100. {
  1101. // Set the proxy config for all loaded plugins
  1102. impl_list::iterator iter = sViewerMediaImplList.begin();
  1103. impl_list::iterator end = sViewerMediaImplList.end();
  1104. for (; iter != end; iter++)
  1105. {
  1106. LLViewerMediaImpl* pimpl = *iter;
  1107. if(pimpl->mMediaSource)
  1108. {
  1109. pimpl->mMediaSource->proxy_setup(enable, host, port);
  1110. }
  1111. }
  1112. }
  1113. /////////////////////////////////////////////////////////////////////////////////////////
  1114. // static
  1115. /////////////////////////////////////////////////////////////////////////////////////////
  1116. // static
  1117. LLPluginCookieStore *LLViewerMedia::getCookieStore()
  1118. {
  1119. if(sCookieStore == NULL)
  1120. {
  1121. sCookieStore = new LLPluginCookieStore;
  1122. }
  1123. return sCookieStore;
  1124. }
  1125. /////////////////////////////////////////////////////////////////////////////////////////
  1126. // static
  1127. void LLViewerMedia::loadCookieFile()
  1128. {
  1129. // build filename for each user
  1130. std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME);
  1131. if (resolved_filename.empty())
  1132. {
  1133. llinfos << "can't get path to plugin cookie file - probably not logged in yet." << llendl;
  1134. return;
  1135. }
  1136. // open the file for reading
  1137. llifstream file(resolved_filename);
  1138. if (!file.is_open())
  1139. {
  1140. llwarns << "can't load plugin cookies from file \"" << PLUGIN_COOKIE_FILE_NAME << "\"" << llendl;
  1141. return;
  1142. }
  1143. getCookieStore()->readAllCookies(file, true);
  1144. file.close();
  1145. // send the clear_cookies message to all loaded plugins
  1146. impl_list::iterator iter = sViewerMediaImplList.begin();
  1147. impl_list::iterator end = sViewerMediaImplList.end();
  1148. for (; iter != end; iter++)
  1149. {
  1150. LLViewerMediaImpl* pimpl = *iter;
  1151. if(pimpl->mMediaSource)
  1152. {
  1153. pimpl->mMediaSource->clear_cookies();
  1154. }
  1155. }
  1156. // If we have an OpenID cookie, re-add it to the cookie store.
  1157. setOpenIDCookie();
  1158. }
  1159. /////////////////////////////////////////////////////////////////////////////////////////
  1160. // static
  1161. void LLViewerMedia::saveCookieFile()
  1162. {
  1163. // build filename for each user
  1164. std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME);
  1165. if (resolved_filename.empty())
  1166. {
  1167. llinfos << "can't get path to plugin cookie file - probably not logged in yet." << llendl;
  1168. return;
  1169. }
  1170. // open a file for writing
  1171. llofstream file (resolved_filename);
  1172. if (!file.is_open())
  1173. {
  1174. llwarns << "can't open plugin cookie file \"" << PLUGIN_COOKIE_FILE_NAME << "\" for writing" << llendl;
  1175. return;
  1176. }
  1177. getCookieStore()->writePersistentCookies(file);
  1178. file.close();
  1179. }
  1180. /////////////////////////////////////////////////////////////////////////////////////////
  1181. // static
  1182. void LLViewerMedia::addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path, bool secure)
  1183. {
  1184. std::stringstream cookie;
  1185. cookie << name << "=" << LLPluginCookieStore::quoteString(value);
  1186. if(expires.notNull())
  1187. {
  1188. cookie << "; expires=" << expires.asRFC1123();
  1189. }
  1190. cookie << "; domain=" << domain;
  1191. cookie << "; path=" << path;
  1192. if(secure)
  1193. {
  1194. cookie << "; secure";
  1195. }
  1196. getCookieStore()->setCookies(cookie.str());
  1197. }
  1198. /////////////////////////////////////////////////////////////////////////////////////////
  1199. // static
  1200. void LLViewerMedia::addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path, bool secure)
  1201. {
  1202. // A session cookie just has a NULL date.
  1203. addCookie(name, value, domain, LLDate(), path, secure);
  1204. }
  1205. /////////////////////////////////////////////////////////////////////////////////////////
  1206. // static
  1207. void LLViewerMedia::removeCookie(const std::string &name, const std::string &domain, const std::string &path )
  1208. {
  1209. // To remove a cookie, add one with the same name, domain, and path that expires in the past.
  1210. addCookie(name, "", domain, LLDate(LLDate::now().secondsSinceEpoch() - 1.0), path);
  1211. }
  1212. LLSD LLViewerMedia::getHeaders()
  1213. {
  1214. LLSD headers = LLSD::emptyMap();
  1215. headers["Accept"] = "*/*";
  1216. headers["Content-Type"] = "application/xml";
  1217. headers["Cookie"] = sOpenIDCookie;
  1218. headers["User-Agent"] = getCurrentUserAgent();
  1219. return headers;
  1220. }
  1221. /////////////////////////////////////////////////////////////////////////////////////////
  1222. // static
  1223. void LLViewerMedia::setOpenIDCookie()
  1224. {
  1225. if(!sOpenIDCookie.empty())
  1226. {
  1227. // The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port]
  1228. // We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that.
  1229. // We therefore do it here.
  1230. std::string authority = sOpenIDURL.mAuthority;
  1231. std::string::size_type host_start = authority.find('@');
  1232. if(host_start == std::string::npos)
  1233. {
  1234. // no username/password
  1235. host_start = 0;
  1236. }
  1237. else
  1238. {
  1239. // Hostname starts after the @.
  1240. // (If the hostname part is empty, this may put host_start at the end of the string. In that case, it will end up passing through an empty hostname, which is correct.)
  1241. ++host_start;
  1242. }
  1243. std::string::size_type host_end = authority.rfind(':');
  1244. if((host_end == std::string::npos) || (host_end < host_start))
  1245. {
  1246. // no port
  1247. host_end = authority.size();
  1248. }
  1249. getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(host_start, host_end - host_start));
  1250. // *HACK: Doing this here is nasty, find a better way.
  1251. LLWebSharing::instance().setOpenIDCookie(sOpenIDCookie);
  1252. // Do a web profile get so we can store the cookie
  1253. LLSD headers = LLSD::emptyMap();
  1254. headers["Accept"] = "*/*";
  1255. headers["Cookie"] = sOpenIDCookie;
  1256. headers["User-Agent"] = getCurrentUserAgent();
  1257. std::string profile_url = getProfileURL("");
  1258. LLURL raw_profile_url( profile_url.c_str() );
  1259. LL_DEBUGS("MediaAuth") << "Requesting " << profile_url << llendl;
  1260. LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << llendl;
  1261. LLHTTPClient::get(profile_url,
  1262. new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()),
  1263. headers);
  1264. }
  1265. }
  1266. /////////////////////////////////////////////////////////////////////////////////////////
  1267. // static
  1268. void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string &openid_token)
  1269. {
  1270. LL_DEBUGS("MediaAuth") << "url = \"" << openid_url << "\", token = \"" << openid_token << "\"" << LL_ENDL;
  1271. // post the token to the url
  1272. // the responder will need to extract the cookie(s).
  1273. // Save the OpenID URL for later -- we may need the host when adding the cookie.
  1274. sOpenIDURL.init(openid_url.c_str());
  1275. // We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies.
  1276. sOpenIDCookie.clear();
  1277. LLSD headers = LLSD::emptyMap();
  1278. // Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header
  1279. headers["Accept"] = "*/*";
  1280. // and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream"
  1281. headers["Content-Type"] = "application/x-www-form-urlencoded";
  1282. // postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here.
  1283. size_t size = openid_token.size();
  1284. U8 *data = new U8[size];
  1285. memcpy(data, openid_token.data(), size);
  1286. LLHTTPClient::postRaw(
  1287. openid_url,
  1288. data,
  1289. size,
  1290. new LLViewerMediaOpenIDResponder(),
  1291. headers);
  1292. }
  1293. /////////////////////////////////////////////////////////////////////////////////////////
  1294. // static
  1295. void LLViewerMedia::openIDCookieResponse(const std::string &cookie)
  1296. {
  1297. LL_DEBUGS("MediaAuth") << "Cookie received: \"" << cookie << "\"" << LL_ENDL;
  1298. sOpenIDCookie += cookie;
  1299. setOpenIDCookie();
  1300. }
  1301. /////////////////////////////////////////////////////////////////////////////////////////
  1302. // static
  1303. void LLViewerMedia::proxyWindowOpened(const std::string &target, const std::string &uuid)
  1304. {
  1305. if(uuid.empty())
  1306. return;
  1307. for (impl_list::iterator iter = sViewerMediaImplList.begin(); iter != sViewerMediaImplList.end(); iter++)
  1308. {
  1309. if((*iter)->mMediaSource && (*iter)->mMediaSource->pluginSupportsMediaBrowser())
  1310. {
  1311. (*iter)->mMediaSource->proxyWindowOpened(target, uuid);
  1312. }
  1313. }
  1314. }
  1315. /////////////////////////////////////////////////////////////////////////////////////////
  1316. // static
  1317. void LLViewerMedia::proxyWindowClosed(const std::string &uuid)
  1318. {
  1319. if(uuid.empty())
  1320. return;
  1321. for (impl_list::iterator iter = sViewerMediaImplList.begin(); iter != sViewerMediaImplList.end(); iter++)
  1322. {
  1323. if((*iter)->mMediaSource && (*iter)->mMediaSource->pluginSupportsMediaBrowser())
  1324. {
  1325. (*iter)->mMediaSource->proxyWindowClosed(uuid);
  1326. }
  1327. }
  1328. }
  1329. /////////////////////////////////////////////////////////////////////////////////////////
  1330. // static
  1331. void LLViewerMedia::createSpareBrowserMediaSource()
  1332. {
  1333. // If we don't have a spare browser media source, create one.
  1334. // However, if PluginAttachDebuggerToPlugins is set then don't spawn a spare
  1335. // SLPlugin process in order to not be confused by an unrelated gdb terminal
  1336. // popping up at the moment we start a media plugin.
  1337. if (!sSpareBrowserMediaSource && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
  1338. {
  1339. // The null owner will keep the browser plugin from fully initializing
  1340. // (specifically, it keeps LLPluginClassMedia from negotiating a size change,
  1341. // which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color)
  1342. sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0);
  1343. }
  1344. }
  1345. /////////////////////////////////////////////////////////////////////////////////////////
  1346. // static
  1347. LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource()
  1348. {
  1349. LLPluginClassMedia* result = sSpareBrowserMediaSource;
  1350. sSpareBrowserMediaSource = NULL;
  1351. return result;
  1352. };
  1353. bool LLViewerMedia::hasInWorldMedia()
  1354. {
  1355. if (sInWorldMediaDisabled) return false;
  1356. impl_list::iterator iter = sViewerMediaImplList.begin();
  1357. impl_list::iterator end = sViewerMediaImplList.end();
  1358. // This should be quick, because there should be very few non-in-world-media impls
  1359. for (; iter != end; iter++)
  1360. {
  1361. LLViewerMediaImpl* pimpl = *iter;
  1362. if (!pimpl->getUsedInUI() && !pimpl->isParcelMedia())
  1363. {
  1364. // Found an in-world media impl
  1365. return true;
  1366. }
  1367. }
  1368. return false;
  1369. }
  1370. //////////////////////////////////////////////////////////////////////////////////////////
  1371. // static
  1372. bool LLViewerMedia::hasParcelMedia()
  1373. {
  1374. return !LLViewerParcelMedia::getURL().empty();
  1375. }
  1376. //////////////////////////////////////////////////////////////////////////////////////////
  1377. // static
  1378. bool LLViewerMedia::hasParcelAudio()
  1379. {
  1380. return !LLViewerMedia::getParcelAudioURL().empty();
  1381. }
  1382. //////////////////////////////////////////////////////////////////////////////////////////
  1383. // static
  1384. std::string LLViewerMedia::getParcelAudioURL()
  1385. {
  1386. return LLViewerParcelMgr::getInstance()->getAgentParcel()->getMusicURL();
  1387. }
  1388. //////////////////////////////////////////////////////////////////////////////////////////
  1389. // static
  1390. void LLViewerMedia::initClass()
  1391. {
  1392. gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL);
  1393. sTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
  1394. setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished));
  1395. }
  1396. //////////////////////////////////////////////////////////////////////////////////////////
  1397. // static
  1398. void LLViewerMedia::cleanupClass()
  1399. {
  1400. gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL);
  1401. sTeleportFinishConnection.disconnect();
  1402. }
  1403. //////////////////////////////////////////////////////////////////////////////////////////
  1404. // static
  1405. void LLViewerMedia::onTeleportFinished()
  1406. {
  1407. // On teleport, clear this setting (i.e. set it to true)
  1408. gSavedSettings.setBOOL("MediaTentativeAutoPlay", true);
  1409. }
  1410. //////////////////////////////////////////////////////////////////////////////////////////
  1411. // static
  1412. void LLViewerMedia::setOnlyAudibleMediaTextureID(const LLUUID& texture_id)
  1413. {
  1414. sOnlyAudibleTextureID = texture_id;
  1415. sForceUpdate = true;
  1416. }
  1417. //////////////////////////////////////////////////////////////////////////////////////////
  1418. // LLViewerMediaImpl
  1419. //////////////////////////////////////////////////////////////////////////////////////////
  1420. LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
  1421. S32 media_width,
  1422. S32 media_height,
  1423. U8 media_auto_scale,
  1424. U8 media_loop)
  1425. :
  1426. mMediaSource( NULL ),
  1427. mMovieImageHasMips(false),
  1428. mMediaWidth(media_width),
  1429. mMediaHeight(media_height),
  1430. mMediaAutoScale(media_auto_scale),
  1431. mMediaLoop(media_loop),
  1432. mNeedsNewTexture(true),
  1433. mTextureUsedWidth(0),
  1434. mTextureUsedHeight(0),
  1435. mSuspendUpdates(false),
  1436. mVisible(true),
  1437. mLastSetCursor( UI_CURSOR_ARROW ),
  1438. mMediaNavState( MEDIANAVSTATE_NONE ),
  1439. mInterest(0.0f),
  1440. mUsedInUI(false),
  1441. mHasFocus(false),
  1442. mPriority(LLPluginClassMedia::PRIORITY_UNLOADED),
  1443. mNavigateRediscoverType(false),
  1444. mNavigateServerRequest(false),
  1445. mMediaSourceFailed(false),
  1446. mRequestedVolume(1.0f),
  1447. mIsMuted(false),
  1448. mNeedsMuteCheck(false),
  1449. mPreviousMediaState(MEDIA_NONE),
  1450. mPreviousMediaTime(0.0f),
  1451. mIsDisabled(false),
  1452. mIsParcelMedia(false),
  1453. mProximity(-1),
  1454. mProximityDistance(0.0f),
  1455. mMimeTypeProbe(NULL),
  1456. mMediaAutoPlay(false),
  1457. mInNearbyMediaList(false),
  1458. mClearCache(false),
  1459. mBackgroundColor(LLColor4::white),
  1460. mNavigateSuspended(false),
  1461. mNavigateSuspendedDeferred(false),
  1462. mIsUpdated(false),
  1463. mTrustedBrowser(false),
  1464. mZoomFactor(1.0)
  1465. {
  1466. // Set up the mute list observer if it hasn't been set up already.
  1467. if(!sViewerMediaMuteListObserverInitialized)
  1468. {
  1469. LLMuteList::getInstance()->addObserver(&sViewerMediaMuteListObserver);
  1470. sViewerMediaMuteListObserverInitialized = true;
  1471. }
  1472. add_media_impl(this);
  1473. setTextureID(texture_id);
  1474. // connect this media_impl to the media texture, creating it if it doesn't exist.0
  1475. // This is necessary because we need to be able to use getMaxVirtualSize() even if the media plugin is not loaded.
  1476. LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture(mTextureId);
  1477. if(media_tex)
  1478. {
  1479. media_tex->setMediaImpl();
  1480. }
  1481. }
  1482. //////////////////////////////////////////////////////////////////////////////////////////
  1483. LLViewerMediaImpl::~LLViewerMediaImpl()
  1484. {
  1485. destroyMediaSource();
  1486. LLViewerMediaTexture::removeMediaImplFromTexture(mTextureId) ;
  1487. setTextureID();
  1488. remove_media_impl(this);
  1489. }
  1490. //////////////////////////////////////////////////////////////////////////////////////////
  1491. void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event)
  1492. {
  1493. // Broadcast to observers using the superclass version
  1494. LLViewerMediaEventEmitter::emitEvent(plugin, event);
  1495. // If this media is on one or more LLVOVolume objects, tell them about the event as well.
  1496. std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
  1497. while(iter != mObjectList.end())
  1498. {
  1499. LLVOVolume *self = *iter;
  1500. ++iter;
  1501. self->mediaEvent(this, plugin, event);
  1502. }
  1503. }
  1504. //////////////////////////////////////////////////////////////////////////////////////////
  1505. bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type)
  1506. {
  1507. bool mimeTypeChanged = (mMimeType != mime_type);
  1508. bool pluginChanged = (LLMIMETypes::implType(mCurrentMimeType) != LLMIMETypes::implType(mime_type));
  1509. if(!mMediaSource || pluginChanged)
  1510. {
  1511. // We don't have a plugin at all, or the new mime type is handled by a different plugin than the old mime type.
  1512. (void)initializePlugin(mime_type);
  1513. }
  1514. else if(mimeTypeChanged)
  1515. {
  1516. // The same plugin should be able to handle the new media -- just update the stored mime type.
  1517. mMimeType = mime_type;
  1518. }
  1519. return (mMediaSource != NULL);
  1520. }
  1521. //////////////////////////////////////////////////////////////////////////////////////////
  1522. void LLViewerMediaImpl::createMediaSource()
  1523. {
  1524. if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
  1525. {
  1526. // This media shouldn't be created yet.
  1527. return;
  1528. }
  1529. if(! mMediaURL.empty())
  1530. {
  1531. navigateInternal();
  1532. }
  1533. else if(! mMimeType.empty())
  1534. {
  1535. if (!initializeMedia(mMimeType))
  1536. {
  1537. LL_WARNS("Media") << "Failed to initialize media for mime type " << mMimeType << LL_ENDL;
  1538. }
  1539. }
  1540. }
  1541. //////////////////////////////////////////////////////////////////////////////////////////
  1542. void LLViewerMediaImpl::destroyMediaSource()
  1543. {
  1544. mNeedsNewTexture = true;
  1545. // Tell the viewer media texture it's no longer active
  1546. LLViewerMediaTexture* oldImage = LLViewerTextureManager::findMediaTexture( mTextureId );
  1547. if (oldImage)
  1548. {
  1549. oldImage->setPlaying(FALSE) ;
  1550. }
  1551. cancelMimeTypeProbe();
  1552. if(mMediaSource)
  1553. {
  1554. mMediaSource->setDeleteOK(true) ;
  1555. delete mMediaSource;
  1556. mMediaSource = NULL;
  1557. }
  1558. }
  1559. //////////////////////////////////////////////////////////////////////////////////////////
  1560. void LLViewerMediaImpl::setMediaType(const std::string& media_type)
  1561. {
  1562. mMimeType = media_type;
  1563. }
  1564. //////////////////////////////////////////////////////////////////////////////////////////
  1565. /*static*/
  1566. LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target)
  1567. {
  1568. std::string plugin_basename = LLMIMETypes::implType(media_type);
  1569. LLPluginClassMedia* media_source = NULL;
  1570. // HACK: we always try to keep a spare running webkit plugin around to improve launch times.
  1571. // If a spare was already created before PluginAttachDebuggerToPlugins was set, don't use it.
  1572. if(plugin_basename == "media_plugin_webkit" && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
  1573. {
  1574. media_source = LLViewerMedia::getSpareBrowserMediaSource();
  1575. if(media_source)
  1576. {
  1577. media_source->setOwner(owner);
  1578. media_source->setTarget(target);
  1579. media_source->setSize(default_width, default_height);
  1580. return media_source;
  1581. }
  1582. }
  1583. if(plugin_basename.empty())
  1584. {
  1585. LL_WARNS_ONCE("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL;
  1586. }
  1587. else
  1588. {
  1589. std::string launcher_name = gDirUtilp->getLLPluginLauncher();
  1590. std::string plugin_name = gDirUtilp->getLLPluginFilename(plugin_basename);
  1591. std::string user_data_path = gDirUtilp->getOSUserAppDir();
  1592. user_data_path += gDirUtilp->getDirDelimiter();
  1593. // Fix for EXT-5960 - make browser profile specific to user (cache, cookies etc.)
  1594. // If the linden username returned is blank, that can only mean we are
  1595. // at the login page displaying login Web page or Web browser test via Develop menu.
  1596. // In this case we just use whatever gDirUtilp->getOSUserAppDir() gives us (this
  1597. // is what we always used before this change)
  1598. std::string linden_user_dir = gDirUtilp->getLindenUserDir();
  1599. if ( ! linden_user_dir.empty() )
  1600. {
  1601. // gDirUtilp->getLindenUserDir() is whole path, not just Linden name
  1602. user_data_path = linden_user_dir;
  1603. user_data_path += gDirUtilp->getDirDelimiter();
  1604. };
  1605. // See if the plugin executable exists
  1606. llstat s;
  1607. if(LLFile::stat(launcher_name, &s))
  1608. {
  1609. LL_WARNS_ONCE("Media") << "Couldn't find launcher at " << launcher_name << LL_ENDL;
  1610. }
  1611. else if(LLFile::stat(plugin_name, &s))
  1612. {
  1613. LL_WARNS_ONCE("Media") << "Couldn't find plugin at " << plugin_name << LL_ENDL;
  1614. }
  1615. else
  1616. {
  1617. media_source = new LLPluginClassMedia(owner);
  1618. media_source->setSize(default_width, default_height);
  1619. media_source->setUserDataPath(user_data_path);
  1620. media_source->setLanguageCode(LLUI::getLanguage());
  1621. // collect 'cookies enabled' setting from prefs and send to embedded browser
  1622. bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" );
  1623. media_source->enable_cookies( cookies_enabled );
  1624. // collect 'plugins enabled' setting from prefs and send to embedded browser
  1625. bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" );
  1626. media_source->setPluginsEnabled( plugins_enabled );
  1627. // collect 'javascript enabled' setting from prefs and send to embedded browser
  1628. bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" );
  1629. media_source->setJavascriptEnabled( javascript_enabled );
  1630. bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging");
  1631. media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled );
  1632. media_source->setTarget(target);
  1633. const std::string plugin_dir = gDirUtilp->getLLPluginDir();
  1634. if (media_source->init(launcher_name, plugin_dir, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")))
  1635. {
  1636. return media_source;
  1637. }
  1638. else
  1639. {
  1640. LL_WARNS("Media") << "Failed to init plugin. Destroying." << LL_ENDL;
  1641. delete media_source;
  1642. }
  1643. }
  1644. }
  1645. LL_WARNS_ONCE("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL;
  1646. LLSD args;
  1647. args["MIME_TYPE"] = media_type;
  1648. LLNotificationsUtil::add("NoPlugin", args);
  1649. return NULL;
  1650. }
  1651. //////////////////////////////////////////////////////////////////////////////////////////
  1652. bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
  1653. {
  1654. if(mMediaSource)
  1655. {
  1656. // Save the previous media source's last set size before destroying it.
  1657. mMediaWidth = mMediaSource->getSetWidth();
  1658. mMediaHeight = mMediaSource->getSetHeight();
  1659. }
  1660. // Always delete the old media impl first.
  1661. destroyMediaSource();
  1662. // and unconditionally set the mime type
  1663. mMimeType = media_type;
  1664. if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
  1665. {
  1666. // This impl should not be loaded at this time.
  1667. LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
  1668. return false;
  1669. }
  1670. // If we got here, we want to ignore previous init failures.
  1671. mMediaSourceFailed = false;
  1672. // Save the MIME type that really caused the plugin to load
  1673. mCurrentMimeType = mMimeType;
  1674. LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget);
  1675. if (media_source)
  1676. {
  1677. media_source->setDisableTimeout(gSavedSettings.getBOOL("DebugPluginDisableTimeout"));
  1678. media_source->setLoop(mMediaLoop);
  1679. media_source->setAutoScale(mMediaAutoScale);
  1680. media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent());
  1681. media_source->focus(mHasFocus);
  1682. media_source->setBackgroundColor(mBackgroundColor);
  1683. if(gSavedSettings.getBOOL("BrowserIgnoreSSLCertErrors"))
  1684. {
  1685. media_source->ignore_ssl_cert_errors(true);
  1686. }
  1687. // the correct way to deal with certs it to load ours from CA.pem and append them to the ones
  1688. // Qt/WebKit loads from your system location.
  1689. // Note: This needs the new CA.pem file with the Equifax Secure Certificate Authority
  1690. // cert at the bottom: (MIIDIDCCAomgAwIBAgIENd70zzANBg)
  1691. std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "CA.pem" );
  1692. media_source->addCertificateFilePath( ca_path );
  1693. media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort"));
  1694. if(mClearCache)
  1695. {
  1696. mClearCache = false;
  1697. media_source->clear_cache();
  1698. }
  1699. // TODO: Only send cookies to plugins that need them
  1700. // Ideally, the plugin should tell us whether it handles cookies or not -- either via the init response or through a separate message.
  1701. // Due to the ordering of messages, it's possible we wouldn't get that information back in time to send cookies before sending a navigate message,
  1702. // which could cause odd race conditions.
  1703. std::string all_cookies = LLViewerMedia::getCookieStore()->getAllCookies();
  1704. lldebugs << "setting cookies: " << all_cookies << llendl;
  1705. if(!all_cookies.empty())
  1706. {
  1707. media_source->set_cookies(all_cookies);
  1708. }
  1709. mMediaSource = media_source;
  1710. mMediaSource->setDeleteOK(false) ;
  1711. updateVolume();
  1712. return true;
  1713. }
  1714. // Make sure the timer doesn't try re-initing this plugin repeatedly until something else changes.
  1715. mMediaSourceFailed = true;
  1716. return false;
  1717. }
  1718. //////////////////////////////////////////////////////////////////////////////////////////
  1719. void LLViewerMediaImpl::loadURI()
  1720. {
  1721. if(mMediaSource)
  1722. {
  1723. // trim whitespace from front and back of URL - fixes EXT-5363
  1724. LLStringUtil::trim( mMediaURL );
  1725. // *HACK: we don't know if the URI coming in is properly escaped
  1726. // (the contract doesn't specify whether it is escaped or not.
  1727. // but LLQtWebKit expects it to be, so we do our best to encode
  1728. // special characters)
  1729. // The strings below were taken right from http://www.ietf.org/rfc/rfc1738.txt
  1730. // Note especially that '%' and '/' are there.
  1731. std::string uri = LLURI::escape(mMediaURL,
  1732. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  1733. "0123456789"
  1734. "$-_.+"
  1735. "!*'(),"
  1736. "{}|\\^~[]`"
  1737. "<>#%"
  1738. ";/?:@&=",
  1739. false);
  1740. llinfos << "Asking media source to load URI: " << uri << llendl;
  1741. mMediaSource->loadURI( uri );
  1742. // A non-zero mPreviousMediaTime means that either this media was previously unloaded by the priority code while playing/paused,
  1743. // or a seek happened before the media loaded. In either case, seek to the saved time.
  1744. if(mPreviousMediaTime != 0.0f)
  1745. {
  1746. seek(mPreviousMediaTime);
  1747. }
  1748. if(mPreviousMediaState == MEDIA_PLAYING)
  1749. {
  1750. // This media was playing before this instance was unloaded.
  1751. start();
  1752. }
  1753. else if(mPreviousMediaState == MEDIA_PAUSED)
  1754. {
  1755. // This media was paused before this instance was unloaded.
  1756. pause();
  1757. }
  1758. else
  1759. {
  1760. // No relevant previous media play state -- if we're loading the URL, we want to start playing.
  1761. start();
  1762. }
  1763. }
  1764. }
  1765. //////////////////////////////////////////////////////////////////////////////////////////
  1766. void LLViewerMediaImpl::setSize(int width, int height)
  1767. {
  1768. mMediaWidth = width;
  1769. mMediaHeight = height;
  1770. if(mMediaSource)
  1771. {
  1772. mMediaSource->setSize(width, height);
  1773. }
  1774. }
  1775. //////////////////////////////////////////////////////////////////////////////////////////
  1776. void LLViewerMediaImpl::showNotification(LLNotificationPtr notify)
  1777. {
  1778. mNotification = notify;
  1779. }
  1780. //////////////////////////////////////////////////////////////////////////////////////////
  1781. void LLViewerMediaImpl::hideNotification()
  1782. {
  1783. mNotification.reset();
  1784. }
  1785. //////////////////////////////////////////////////////////////////////////////////////////
  1786. void LLViewerMediaImpl::play()
  1787. {
  1788. // If the media source isn't there, try to initialize it and load an URL.
  1789. if(mMediaSource == NULL)
  1790. {
  1791. if(!initializeMedia(mMimeType))
  1792. {
  1793. // This may be the case where the plugin's priority is PRIORITY_UNLOADED
  1794. return;
  1795. }
  1796. // Only do this if the media source was just loaded.
  1797. loadURI();
  1798. }
  1799. // always start the media
  1800. start();
  1801. }
  1802. ////////////////////////////////////////////////////