2
* Miro - an RSS based video player application
3
* Copyright (C) 2005-2010 Participatory Culture Foundation
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
* In addition, as a special exception, the copyright holders give
20
* permission to link the code of portions of this program with the OpenSSL
23
* You must obey the GNU General Public License in all respects for all of
24
* the code used other than OpenSSL. If you modify file(s) with this
25
* exception, you may extend this exception to your version of the file(s),
26
* but you are not obligated to do so. If you do not wish to do so, delete
27
* this exception statement from your version. If you delete this exception
28
* statement from all source files in the program, then also delete it here.
32
* MiroBrowserEmbed.cpp
34
* Implementation of our embedded xulrunner browser.
40
#include "nsComponentManagerUtils.h"
41
#include "nsEmbedCID.h"
42
#include "nsEmbedString.h"
43
#include "nsIDOMWindow.h"
44
#include "nsIInterfaceRequestorUtils.h"
45
#include "nsISupportsImpl.h"
46
#include "nsIWebBrowser.h"
47
#include "nsIWebBrowserFocus.h"
48
#include "docshell/nsDocShellCID.h"
49
#include "docshell/nsIDocShellTreeItem.h"
50
#include "docshell/nsIWebNavigationInfo.h"
51
#include "necko/nsIURI.h"
52
#include "xpcom/nsServiceManagerUtils.h"
54
#include "MiroBrowserEmbed.h"
55
#include "xulrunnerbrowser.h"
61
MiroBrowserEmbed::MiroBrowserEmbed()
64
mFocusCallback = nsnull;
67
MiroBrowserEmbed::~MiroBrowserEmbed()
69
log_info("destroying MiroBrowserEmbed");
72
nsresult MiroBrowserEmbed::init(unsigned long parentWindow, int x,
73
int y, int width, int height)
77
mWebBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID, &rv);
78
NS_ENSURE_SUCCESS(rv, rv);
79
mWindow = reinterpret_cast<nativeWindow>(parentWindow);
81
mWebBrowser->SetContainerWindow(static_cast<nsIWebBrowserChrome*>(this));
83
nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(mWebBrowser);
84
dsti->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
86
nsCOMPtr<nsIBaseWindow> browserBaseWindow(do_QueryInterface(mWebBrowser));
87
browserBaseWindow->InitWindow(mWindow, nsnull, x, y, width, height);
88
browserBaseWindow->Create();
89
browserBaseWindow->SetVisibility(PR_TRUE);
90
browserBaseWindow->SetEnabled(PR_TRUE);
92
install_focus_fixes((HWND)mWindow);
93
rv = mWebBrowser->GetParentURIContentListener(
94
getter_AddRefs(mParentContentListener));
95
NS_ENSURE_SUCCESS(rv, rv);
96
rv = mWebBrowser->SetParentURIContentListener(
97
static_cast<nsIURIContentListener *>(this));
98
NS_ENSURE_SUCCESS(rv, rv);
100
nsCOMPtr<nsIWeakReference> weakRef;
101
rv = GetWeakReference(getter_AddRefs(weakRef));
102
NS_ENSURE_SUCCESS(rv, rv);
104
rv = mWebBrowser->AddWebBrowserListener(weakRef,
105
NS_GET_IID(nsIWebProgressListener));
106
NS_ENSURE_SUCCESS(rv, rv);
107
mWebNavigation = do_QueryInterface(mWebBrowser);
111
nsresult MiroBrowserEmbed::disable()
114
nsCOMPtr<nsIBaseWindow> browserBaseWindow(do_QueryInterface(mWebBrowser));
116
rv = browserBaseWindow->SetVisibility(PR_FALSE);
117
NS_ENSURE_SUCCESS(rv, rv);
118
rv = browserBaseWindow->SetEnabled(PR_FALSE);
119
NS_ENSURE_SUCCESS(rv, rv);
123
nsresult MiroBrowserEmbed::enable()
126
nsCOMPtr<nsIBaseWindow> browserBaseWindow(do_QueryInterface(mWebBrowser));
128
rv = browserBaseWindow->SetVisibility(PR_TRUE);
129
NS_ENSURE_SUCCESS(rv, rv);
130
rv = browserBaseWindow->SetEnabled(PR_TRUE);
131
NS_ENSURE_SUCCESS(rv, rv);
132
rv = browserBaseWindow->Repaint(PR_FALSE);
133
NS_ENSURE_SUCCESS(rv, rv);
137
void MiroBrowserEmbed::destroy()
139
nsCOMPtr<nsIBaseWindow> browserBaseWindow(do_QueryInterface(mWebBrowser));
140
browserBaseWindow->Destroy();
143
PRBool MiroBrowserEmbed::is_enabled()
146
nsCOMPtr<nsIBaseWindow> browserBaseWindow(do_QueryInterface(mWebBrowser));
147
browserBaseWindow->GetEnabled(&enabled);
151
// Load a URI into the browser
152
nsresult MiroBrowserEmbed::loadURI(const char* uri)
154
mWebNavigation->LoadURI(NS_ConvertASCIItoUTF16(uri).get(),
155
nsIWebNavigation::LOAD_FLAGS_NONE, 0, 0, 0);
159
nsresult MiroBrowserEmbed::getCurrentURI(char ** uri)
162
nsCAutoString specString;
165
rv = mWebNavigation->GetCurrentURI(&aURI);
166
NS_ENSURE_SUCCESS(rv, rv);
168
rv = aURI->GetSpec(specString);
169
NS_ENSURE_SUCCESS(rv, rv);
171
*uri = (char *) specString.get();
175
nsresult MiroBrowserEmbed::getCurrentTitle(char ** aTitle, int* length)
178
nsISHistory *history;
179
nsIHistoryEntry *historyentry;
183
rv = mWebNavigation->GetSessionHistory(&history);
184
NS_ENSURE_SUCCESS(rv, rv);
186
rv = history->GetIndex(&index);
187
NS_ENSURE_SUCCESS(rv, rv);
189
rv = history->GetEntryAtIndex(index, PR_FALSE, &historyentry);
190
NS_ENSURE_SUCCESS(rv, rv);
192
rv = historyentry->GetTitle(&title);
193
NS_ENSURE_SUCCESS(rv, rv);
195
*aTitle = (char *)title;
196
*length = (wcslen(title) + 1) * 2;
200
// Called when the parent window changes size
201
nsresult MiroBrowserEmbed::resize(int x, int y, int width, int height)
203
nsCOMPtr<nsIBaseWindow>browserBaseWindow(
204
do_QueryInterface(mWebBrowser));
205
if(!browserBaseWindow) return NS_ERROR_FAILURE;
206
return browserBaseWindow->SetPositionAndSize(x, y, width, height,
210
// Give the browser keyboard focus
211
nsresult MiroBrowserEmbed::focus()
213
nsCOMPtr<nsIWebBrowserFocus> browserFocus(
214
do_GetInterface(mWebBrowser));
215
if(!browserFocus) return NS_ERROR_FAILURE;
216
return browserFocus->Activate();
219
// Set the focus callback. This will be called when the user tabs through all
220
// the elements in the browser and the next Widget should be given focus.
221
void MiroBrowserEmbed::SetFocusCallback(focusCallback callback, void* data)
223
mFocusCallback = callback;
224
mFocusCallbackData = data;
227
void MiroBrowserEmbed::SetURICallback(uriCallback callback, void* data)
229
mURICallback = callback;
230
mURICallbackData = data;
233
void MiroBrowserEmbed::SetNetworkCallback(networkCallback callback, void* data)
235
mNetworkCallback = callback;
236
mNetworkCallbackData = data;
239
int MiroBrowserEmbed::canGoBack()
242
mWebNavigation->GetCanGoBack(&retval);
246
int MiroBrowserEmbed::canGoForward()
249
mWebNavigation->GetCanGoForward(&retval);
253
void MiroBrowserEmbed::goBack()
255
mWebNavigation->GoBack();
258
void MiroBrowserEmbed::goForward()
260
mWebNavigation->GoForward();
263
void MiroBrowserEmbed::stop()
265
mWebNavigation->Stop(nsIWebNavigation::STOP_ALL);
268
void MiroBrowserEmbed::reload()
270
mWebNavigation->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);
273
//*****************************************************************************
274
// MiroBrowserEmbed::nsISupports
275
//*****************************************************************************
277
NS_IMPL_ADDREF(MiroBrowserEmbed)
278
NS_IMPL_RELEASE(MiroBrowserEmbed)
280
NS_INTERFACE_MAP_BEGIN(MiroBrowserEmbed)
281
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
282
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
283
NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
284
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
285
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus)
286
NS_INTERFACE_MAP_ENTRY(nsIURIContentListener)
287
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
288
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
292
//*****************************************************************************
293
// MiroBrowserEmbed::nsIWebBrowserChrome
294
//*****************************************************************************
296
NS_IMETHODIMP MiroBrowserEmbed::SetStatus(PRUint32 aType, const PRUnichar* aStatus)
302
NS_IMETHODIMP MiroBrowserEmbed::GetWebBrowser(nsIWebBrowser** aWebBrowser)
304
NS_ENSURE_ARG_POINTER(aWebBrowser);
305
*aWebBrowser = mWebBrowser;
306
NS_IF_ADDREF(*aWebBrowser);
310
NS_IMETHODIMP MiroBrowserEmbed::SetWebBrowser(nsIWebBrowser* aWebBrowser)
312
mWebBrowser = aWebBrowser;
316
NS_IMETHODIMP MiroBrowserEmbed::GetChromeFlags(PRUint32* aChromeMask)
318
*aChromeMask = mChromeFlags;
322
NS_IMETHODIMP MiroBrowserEmbed::SetChromeFlags(PRUint32 aChromeMask)
324
mChromeFlags = aChromeMask;
328
NS_IMETHODIMP MiroBrowserEmbed::DestroyBrowserWindow(void)
330
log_warning("DestroyBrowserWindow() not implemented");
335
// IN: The desired browser client area dimensions.
336
NS_IMETHODIMP MiroBrowserEmbed::SizeBrowserTo(PRInt32 aWidth, PRInt32 aHeight)
342
NS_IMETHODIMP MiroBrowserEmbed::ShowAsModal(void)
344
mContinueModalLoop = PR_TRUE;
345
//AppCallbacks::RunEventLoop(mContinueModalLoop);
350
NS_IMETHODIMP MiroBrowserEmbed::IsWindowModal(PRBool *_retval)
353
return NS_ERROR_NOT_IMPLEMENTED;
356
NS_IMETHODIMP MiroBrowserEmbed::ExitModalEventLoop(nsresult aStatus)
358
mContinueModalLoop = PR_FALSE;
363
//*****************************************************************************
364
// MiroBrowserEmbed::nsIWebBrowserChromeFocus
365
//*****************************************************************************
366
NS_IMETHODIMP MiroBrowserEmbed::FocusNextElement()
368
if(mFocusCallback && is_enabled())
369
mFocusCallback(PR_TRUE, mFocusCallbackData);
373
NS_IMETHODIMP MiroBrowserEmbed::FocusPrevElement()
375
if(mFocusCallback && is_enabled())
376
mFocusCallback(PR_FALSE, mFocusCallbackData);
381
//*****************************************************************************
382
// MiroBrowserEmbed::nsIEmbeddingSiteWindow
383
//*****************************************************************************
385
NS_IMETHODIMP MiroBrowserEmbed::SetDimensions(PRUint32 aFlags, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy)
387
return NS_ERROR_NOT_IMPLEMENTED;
390
NS_IMETHODIMP MiroBrowserEmbed::GetDimensions(PRUint32 aFlags, PRInt32 *x, PRInt32 *y, PRInt32 *cx, PRInt32 *cy)
392
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION)
397
if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER ||
398
aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER)
403
return NS_ERROR_NOT_IMPLEMENTED;
406
/* void setFocus (); */
407
NS_IMETHODIMP MiroBrowserEmbed::SetFocus()
412
/* attribute wstring title; */
413
NS_IMETHODIMP MiroBrowserEmbed::GetTitle(PRUnichar * *aTitle)
415
NS_ENSURE_ARG_POINTER(aTitle);
419
return NS_ERROR_NOT_IMPLEMENTED;
421
NS_IMETHODIMP MiroBrowserEmbed::SetTitle(const PRUnichar * aTitle)
423
return NS_ERROR_NOT_IMPLEMENTED;
426
/* attribute boolean visibility; */
427
NS_IMETHODIMP MiroBrowserEmbed::GetVisibility(PRBool * aVisibility)
429
NS_ENSURE_ARG_POINTER(aVisibility);
430
*aVisibility = PR_TRUE;
433
NS_IMETHODIMP MiroBrowserEmbed::SetVisibility(PRBool aVisibility)
438
/* attribute nativeSiteWindow siteWindow */
439
NS_IMETHODIMP MiroBrowserEmbed::GetSiteWindow(void * *aSiteWindow)
441
NS_ENSURE_ARG_POINTER(aSiteWindow);
443
*aSiteWindow = mWindow;
447
//*****************************************************************************
448
// MiroBrowserEmbed::nsIURIContentListener
449
//*****************************************************************************
450
/* boolean onStartURIOpen (in nsIURI aURI); */
451
NS_IMETHODIMP MiroBrowserEmbed::OnStartURIOpen(nsIURI *aURI, PRBool *_retval)
454
nsCAutoString specString;
457
rv = aURI->GetSpec(specString);
458
NS_ENSURE_SUCCESS(rv, rv);
460
// Hmm, the docs seem to suggest that retval should be TRUE if we want to
461
// continue the load. However, it seems like the opposite is actually the
463
if(mURICallback && is_enabled()) {
464
if(mURICallback((char*)specString.get(), mURICallbackData) == 0) {
471
/* boolean doContent (in string aContentType, in boolean aIsContentPreferred, in nsIRequest aRequest, out nsIStreamListener aContentHandler); */
472
NS_IMETHODIMP MiroBrowserEmbed::DoContent(const char *aContentType, PRBool aIsContentPreferred, nsIRequest *aRequest, nsIStreamListener **aContentHandler, PRBool *_retval)
474
return NS_ERROR_NOT_IMPLEMENTED;
477
/* boolean isPreferred (in string aContentType, out string aDesiredContentType); */
478
NS_IMETHODIMP MiroBrowserEmbed::IsPreferred(const char *aContentType, char **aDesiredContentType, PRBool *_retval)
480
// This method was pretty much copied from GtkMozEmbed
482
*aDesiredContentType = nsnull;
485
nsCOMPtr<nsIWebNavigationInfo> webNavInfo(
486
do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID));
490
webNavInfo->IsTypeSupported(nsDependentCString(aContentType),
491
mWebNavigation, &canHandle);
492
NS_ENSURE_SUCCESS(rv, rv);
493
*_retval = (canHandle != nsIWebNavigationInfo::UNSUPPORTED);
499
/* boolean canHandleContent (in string aContentType, in boolean aIsContentPreferred, out string aDesiredContentType); */
500
NS_IMETHODIMP MiroBrowserEmbed::CanHandleContent(const char *aContentType, PRBool aIsContentPreferred, char **aDesiredContentType, PRBool *_retval)
506
/* attribute nsISupports loadCookie; */
507
NS_IMETHODIMP MiroBrowserEmbed::GetLoadCookie(nsISupports * *aLoadCookie)
509
return NS_ERROR_NOT_IMPLEMENTED;
511
NS_IMETHODIMP MiroBrowserEmbed::SetLoadCookie(nsISupports * aLoadCookie)
513
return NS_ERROR_NOT_IMPLEMENTED;
516
/* attribute nsIURIContentListener parentContentListener; */
517
NS_IMETHODIMP MiroBrowserEmbed::GetParentContentListener(nsIURIContentListener * *aParentContentListener)
519
*aParentContentListener = mParentContentListener;
520
(*aParentContentListener)->AddRef();
523
NS_IMETHODIMP MiroBrowserEmbed::SetParentContentListener(nsIURIContentListener * aParentContentListener)
525
mParentContentListener = aParentContentListener;
529
//*****************************************************************************
530
// MiroBrowserEmbed::nsIWebProgressListener
531
//*****************************************************************************
533
/* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */
534
NS_IMETHODIMP MiroBrowserEmbed::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus)
536
if((aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK) &&
537
mNetworkCallback && is_enabled()) {
538
if(aStateFlags & nsIWebProgressListener::STATE_START) {
539
mNetworkCallback(PR_TRUE, mNetworkCallbackData);
540
} else if(aStateFlags & nsIWebProgressListener::STATE_STOP) {
541
mNetworkCallback(PR_FALSE, mNetworkCallbackData);
547
/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
548
NS_IMETHODIMP MiroBrowserEmbed::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
553
/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI aLocation); */
554
NS_IMETHODIMP MiroBrowserEmbed::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *aLocation)
559
/* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
560
NS_IMETHODIMP MiroBrowserEmbed::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
565
/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aState); */
566
NS_IMETHODIMP MiroBrowserEmbed::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aState)
572
//*****************************************************************************
573
// MiroBrowserEmbed::nsIInterfaceRequestor
574
//*****************************************************************************
576
NS_IMETHODIMP MiroBrowserEmbed::GetInterface(const nsIID &aIID, void** aInstancePtr)
578
NS_ENSURE_ARG_POINTER(aInstancePtr);
581
if (aIID.Equals(NS_GET_IID(nsIDOMWindow)))
585
return mWebBrowser->GetContentDOMWindow((nsIDOMWindow **) aInstancePtr);
587
return NS_ERROR_NOT_INITIALIZED;
589
return QueryInterface(aIID, aInstancePtr);
592
void addref(MiroBrowserEmbed* browser)
596
void release(MiroBrowserEmbed* browser)