PageRenderTime 41ms CodeModel.GetById 9ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/newview/llfloaterwebcontent.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 467 lines | 335 code | 66 blank | 66 comment | 61 complexity | 9858c8e846365f1e75fe44f9dd61be05 MD5 | raw file
  1/**
  2 * @file llfloaterwebcontent.cpp
  3 * @brief floater for displaying web content - e.g. profiles and search (eventually)
  4 *
  5 * $LicenseInfo:firstyear=2006&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
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "llcombobox.h"
 30#include "lliconctrl.h"
 31#include "llfloaterreg.h"
 32#include "lllayoutstack.h"
 33#include "llpluginclassmedia.h"
 34#include "llprogressbar.h"
 35#include "lltextbox.h"
 36#include "llurlhistory.h"
 37#include "llviewercontrol.h"
 38#include "llweb.h"
 39#include "llwindow.h"
 40
 41#include "llfloaterwebcontent.h"
 42
 43LLFloaterWebContent::_Params::_Params()
 44:	url("url"),
 45	target("target"),
 46	id("id"),
 47	window_class("window_class", "web_content"),
 48	show_chrome("show_chrome", true),
 49	allow_address_entry("allow_address_entry", true),
 50	preferred_media_size("preferred_media_size"),
 51	trusted_content("trusted_content", false),
 52	show_page_title("show_page_title", true)
 53{}
 54
 55LLFloaterWebContent::LLFloaterWebContent( const Params& params )
 56:	LLFloater( params ),
 57	LLInstanceTracker<LLFloaterWebContent, std::string>(params.id()),
 58	mWebBrowser(NULL),
 59	mAddressCombo(NULL),
 60	mSecureLockIcon(NULL),
 61	mStatusBarText(NULL),
 62	mStatusBarProgress(NULL),
 63	mBtnBack(NULL),
 64	mBtnForward(NULL),
 65	mBtnReload(NULL),
 66	mBtnStop(NULL),
 67	mUUID(params.id()),
 68	mShowPageTitle(params.show_page_title)
 69{
 70	mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this ));
 71	mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this ));
 72	mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this ));
 73	mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this ));
 74	mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this ));
 75	mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this ));
 76}
 77
 78BOOL LLFloaterWebContent::postBuild()
 79{
 80	// these are used in a bunch of places so cache them
 81	mWebBrowser        = getChild< LLMediaCtrl >( "webbrowser" );
 82	mAddressCombo      = getChild< LLComboBox >( "address" );
 83	mStatusBarText     = getChild< LLTextBox >( "statusbartext" );
 84	mStatusBarProgress = getChild<LLProgressBar>("statusbarprogress" );
 85
 86	mBtnBack           = getChildView( "back" );
 87	mBtnForward        = getChildView( "forward" );
 88	mBtnReload         = getChildView( "reload" );
 89	mBtnStop           = getChildView( "stop" );
 90
 91	// observe browser events
 92	mWebBrowser->addObserver( this );
 93
 94	// these buttons are always enabled
 95	mBtnReload->setEnabled( true );
 96	getChildView("popexternal")->setEnabled( true );
 97
 98	// cache image for secure browsing
 99	mSecureLockIcon = getChild< LLIconCtrl >("media_secure_lock_flag");
100
101	// initialize the URL history using the system URL History manager
102	initializeURLHistory();
103
104	return TRUE;
105}
106
107void LLFloaterWebContent::initializeURLHistory()
108{
109	// start with an empty list
110	LLCtrlListInterface* url_list = childGetListInterface("address");
111	if (url_list)
112	{
113		url_list->operateOnAll(LLCtrlListInterface::OP_DELETE);
114	}
115
116	// Get all of the entries in the "browser" collection
117	LLSD browser_history = LLURLHistory::getURLHistory("browser");
118	LLSD::array_iterator iter_history = browser_history.beginArray();
119	LLSD::array_iterator end_history = browser_history.endArray();
120	for(; iter_history != end_history; ++iter_history)
121	{
122		std::string url = (*iter_history).asString();
123		if(! url.empty())
124			url_list->addSimpleElement(url);
125	}
126}
127
128bool LLFloaterWebContent::matchesKey(const LLSD& key)
129{
130	Params p(mKey);
131	Params other_p(key);
132	if (!other_p.target().empty() && other_p.target() != "_blank")
133	{
134		return other_p.target() == p.target();
135	}
136	else
137	{
138		return other_p.id() == p.id();
139	}
140}
141
142//static
143LLFloater* LLFloaterWebContent::create( Params p)
144{
145	preCreate(p);
146	return new LLFloaterWebContent(p);
147}
148
149//static
150void LLFloaterWebContent::closeRequest(const std::string &uuid)
151{
152	LLFloaterWebContent* floaterp = instance_tracker_t::getInstance(uuid);
153	if (floaterp)
154	{
155		floaterp->closeFloater(false);
156	}
157}
158
159//static
160void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height)
161{
162	LLFloaterWebContent* floaterp = instance_tracker_t::getInstance(uuid);
163	if (floaterp)
164	{
165		floaterp->geometryChanged(x, y, width, height);
166	}
167}
168
169void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
170{
171	// Make sure the layout of the browser control is updated, so this calculation is correct.
172	LLLayoutStack::updateClass();
173
174	// TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc.
175	LLCoordWindow window_size;
176	getWindow()->getSize(&window_size);
177
178	// Adjust width and height for the size of the chrome on the web Browser window.
179	LLRect browser_rect;
180	mWebBrowser->localRectToOtherView(mWebBrowser->getLocalRect(), &browser_rect, this);
181
182	S32 requested_browser_bottom = window_size.mY - (y + height);
183	LLRect geom;
184	geom.setOriginAndSize(x - browser_rect.mLeft, 
185						requested_browser_bottom - browser_rect.mBottom, 
186						width + getRect().getWidth() - browser_rect.getWidth(), 
187						height + getRect().getHeight() - browser_rect.getHeight());
188
189	lldebugs << "geometry change: " << geom << llendl;
190	
191	LLRect new_rect;
192	getParent()->screenRectToLocal(geom, &new_rect);
193	setShape(new_rect);	
194}
195
196// static
197void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)
198{
199	lldebugs << "url = " << p.url() << ", target = " << p.target() << ", uuid = " << p.id() << llendl;
200
201	if (!p.id.isProvided())
202	{
203		p.id = LLUUID::generateNewID().asString();
204	}
205
206	if(p.target().empty() || p.target() == "_blank")
207	{
208		p.target = p.id();
209	}
210
211	S32 browser_window_limit = gSavedSettings.getS32("WebContentWindowLimit");
212	if(browser_window_limit != 0)
213	{
214		// showInstance will open a new window.  Figure out how many web browsers are already open,
215		// and close the least recently opened one if this will put us over the limit.
216
217		LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList(p.window_class);
218		lldebugs << "total instance count is " << instances.size() << llendl;
219
220		for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++)
221		{
222			lldebugs << "    " << (*iter)->getKey()["target"] << llendl;
223		}
224
225		if(instances.size() >= (size_t)browser_window_limit)
226		{
227			// Destroy the least recently opened instance
228			(*instances.begin())->closeFloater();
229		}
230	}
231}
232
233void LLFloaterWebContent::open_media(const Params& p)
234{
235	// Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.
236	LLViewerMedia::proxyWindowOpened(p.target(), p.id());
237	mWebBrowser->setHomePageUrl(p.url, "text/html");
238	mWebBrowser->setTarget(p.target);
239	mWebBrowser->navigateTo(p.url, "text/html");
240	
241	set_current_url(p.url);
242
243	getChild<LLLayoutPanel>("status_bar")->setVisible(p.show_chrome);
244	getChild<LLLayoutPanel>("nav_controls")->setVisible(p.show_chrome);
245	bool address_entry_enabled = p.allow_address_entry && !p.trusted_content;
246	getChildView("address")->setEnabled(address_entry_enabled);
247	getChildView("popexternal")->setEnabled(address_entry_enabled);
248
249	if (!address_entry_enabled)
250	{
251		mWebBrowser->setFocus(TRUE);
252	}
253
254	if (!p.show_chrome)
255	{
256		setResizeLimits(100, 100);
257	}
258
259	if (!p.preferred_media_size().isEmpty())
260	{
261		LLLayoutStack::updateClass();
262		LLRect browser_rect = mWebBrowser->calcScreenRect();
263		LLCoordWindow window_size;
264		getWindow()->getSize(&window_size);
265		
266		geometryChanged(browser_rect.mLeft, window_size.mY - browser_rect.mTop, p.preferred_media_size().getWidth(), p.preferred_media_size().getHeight());
267	}
268
269}
270
271void LLFloaterWebContent::onOpen(const LLSD& key)
272{
273	Params params(key);
274
275	if (!params.validateBlock())
276	{
277		closeFloater();
278		return;
279	}
280
281	mWebBrowser->setTrustedContent(params.trusted_content);
282
283	// tell the browser instance to load the specified URL
284	open_media(params);
285}
286
287//virtual
288void LLFloaterWebContent::onClose(bool app_quitting)
289{
290	LLViewerMedia::proxyWindowClosed(mUUID);
291	destroy();
292}
293
294// virtual
295void LLFloaterWebContent::draw()
296{
297	// this is asynchronous so we need to keep checking
298	mBtnBack->setEnabled( mWebBrowser->canNavigateBack() );
299	mBtnForward->setEnabled( mWebBrowser->canNavigateForward() );
300
301	LLFloater::draw();
302}
303
304// virtual
305void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
306{
307	if(event == MEDIA_EVENT_LOCATION_CHANGED)
308	{
309		const std::string url = self->getLocation();
310
311		if ( url.length() )
312			mStatusBarText->setText( url );
313
314		set_current_url( url );
315	}
316	else if(event == MEDIA_EVENT_NAVIGATE_BEGIN)
317	{
318		// flags are sent with this event
319		mBtnBack->setEnabled( self->getHistoryBackAvailable() );
320		mBtnForward->setEnabled( self->getHistoryForwardAvailable() );
321
322		// toggle visibility of these buttons based on browser state
323		mBtnReload->setVisible( false );
324		mBtnStop->setVisible( true );
325
326		// turn "on" progress bar now we're about to start loading
327		mStatusBarProgress->setVisible( true );
328	}
329	else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE)
330	{
331		// flags are sent with this event
332		mBtnBack->setEnabled( self->getHistoryBackAvailable() );
333		mBtnForward->setEnabled( self->getHistoryForwardAvailable() );
334
335		// toggle visibility of these buttons based on browser state
336		mBtnReload->setVisible( true );
337		mBtnStop->setVisible( false );
338
339		// turn "off" progress bar now we're loaded
340		mStatusBarProgress->setVisible( false );
341
342		// we populate the status bar with URLs as they change so clear it now we're done
343		const std::string end_str = "";
344		mStatusBarText->setText( end_str );
345
346		// decide if secure browsing icon should be displayed
347		std::string prefix =  std::string("https://");
348		std::string test_prefix = mCurrentURL.substr(0, prefix.length());
349		LLStringUtil::toLower(test_prefix);
350		if(test_prefix == prefix)
351		{
352			mSecureLockIcon->setVisible(true);
353		}
354		else
355		{
356			mSecureLockIcon->setVisible(false);
357		}
358	}
359	else if(event == MEDIA_EVENT_CLOSE_REQUEST)
360	{
361		// The browser instance wants its window closed.
362		closeFloater();
363	}
364	else if(event == MEDIA_EVENT_GEOMETRY_CHANGE)
365	{
366		geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight());
367	}
368	else if(event == MEDIA_EVENT_STATUS_TEXT_CHANGED )
369	{
370		const std::string text = self->getStatusText();
371		if ( text.length() )
372			mStatusBarText->setText( text );
373	}
374	else if(event == MEDIA_EVENT_PROGRESS_UPDATED )
375	{
376		int percent = (int)self->getProgressPercent();
377		mStatusBarProgress->setValue( percent );
378	}
379	else if(event == MEDIA_EVENT_NAME_CHANGED )
380	{
381		std::string page_title = self->getMediaName();
382		// simulate browser behavior - title is empty, use the current URL
383		if (mShowPageTitle)
384		{
385			if ( page_title.length() > 0 )
386				setTitle( page_title );
387			else
388				setTitle( mCurrentURL );
389		}
390	}
391	else if(event == MEDIA_EVENT_LINK_HOVERED )
392	{
393		const std::string link = self->getHoverLink();
394		mStatusBarText->setText( link );
395	}
396}
397
398void LLFloaterWebContent::set_current_url(const std::string& url)
399{
400	mCurrentURL = url;
401
402	// serialize url history into the system URL History manager
403	LLURLHistory::removeURL("browser", mCurrentURL);
404	LLURLHistory::addURL("browser", mCurrentURL);
405
406	mAddressCombo->remove( mCurrentURL );
407	mAddressCombo->add( mCurrentURL );
408	mAddressCombo->selectByValue( mCurrentURL );
409}
410
411void LLFloaterWebContent::onClickForward()
412{
413	mWebBrowser->navigateForward();
414}
415
416void LLFloaterWebContent::onClickBack()
417{
418	mWebBrowser->navigateBack();
419}
420
421void LLFloaterWebContent::onClickReload()
422{
423
424	if( mWebBrowser->getMediaPlugin() )
425	{
426		bool ignore_cache = true;
427		mWebBrowser->getMediaPlugin()->browse_reload( ignore_cache );
428	}
429	else
430	{
431		mWebBrowser->navigateTo(mCurrentURL);
432	}
433}
434
435void LLFloaterWebContent::onClickStop()
436{
437	if( mWebBrowser->getMediaPlugin() )
438		mWebBrowser->getMediaPlugin()->browse_stop();
439
440	// still should happen when we catch the navigate complete event
441	// but sometimes (don't know why) that event isn't sent from Qt
442	// and we ghetto a point where the stop button stays active.
443	mBtnReload->setVisible( true );
444	mBtnStop->setVisible( false );
445}
446
447void LLFloaterWebContent::onEnterAddress()
448{
449	// make sure there is at least something there.
450	// (perhaps this test should be for minimum length of a URL)
451	std::string url = mAddressCombo->getValue().asString();
452	if ( url.length() > 0 )
453	{
454		mWebBrowser->navigateTo( url, "text/html");
455	};
456}
457
458void LLFloaterWebContent::onPopExternal()
459{
460	// make sure there is at least something there.
461	// (perhaps this test should be for minimum length of a URL)
462	std::string url = mAddressCombo->getValue().asString();
463	if ( url.length() > 0 )
464	{
465		LLWeb::loadURLExternal( url );
466	};
467}