You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1944 lines
60 KiB

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: Mozilla-sample-code 1.0
*
* Copyright (c) 2002 Netscape Communications Corporation and
* other contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this Mozilla sample software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Contributor(s):
* Chak Nanga <chak@netscape.com>
* Conrad Carlen <ccarlen@netscape.com>
*
* ***** END LICENSE BLOCK ***** */
// File Overview....
//
// The typical MFC app, frame creation code
//
// NS_InitEmbedding() is called in InitInstance()
//
// NS_TermEmbedding() is called in ExitInstance()
// ExitInstance() also takes care of cleaning up of
// multiple browser frame windows on app exit
//
// NS_DoIdleEmbeddingStuff(); is called in the overridden
// OnIdle() method
//
// Code to handle the creation of a new browser window
// Next suggested file to look at : BrowserFrm.cpp
// Local Includes
#include "stdafx.h"
#include "nsXPCOM.h"
#include "nsXPCOMGlue.h"
#include "MfcEmbed.h"
#include "HiddenWnd.h"
#include "BrowserFrm.h"
#include "BrowserFrmTab.h"
#include "KmFileLocProvider.h"
#include "ProfileMgr.h"
#include "ProfilesDlg.h"
#include "BrowserImpl.h"
#include "kmeleonConst.h"
#include "UnknownContentTypeHandler.h"
#include "MenuParser.h"
#include "kmeleon_plugin.h"
#include <io.h>
#include <fcntl.h>
#include "nsXULAppAPI.h"
#include "nsXPCOMGlue.h"
#include "nsIIOService.h"
#include "nsIWindowWatcher.h"
#include "nsIChromeRegistry.h"
#include "nsIAppStartup.h"
#include "nsToolkitCompsCID.h"
#include "nsIObserverService.h"
#include "nsICommandLineRunner.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include <locale.h>
static UINT WM_POSTEVENT = RegisterWindowMessage(_T("XPCOM_PostEvent"));
static UINT WM_FLASHRELAY = RegisterWindowMessage(_T("MozFlashUserRelay"));
static UINT WM_NSEVENTID = RegisterWindowMessage(_T("nsAppShell:EventID"));
XRE_InitEmbedding2Type XRE_InitEmbedding2 = 0;
XRE_TermEmbeddingType XRE_TermEmbedding = 0;
XRE_NotifyProfileType XRE_NotifyProfile = 0;
XRE_LockProfileDirectoryType XRE_LockProfileDirectory = 0;
XRE_AddManifestLocationType XRE_AddManifestLocation = 0;
XRE_GetProcessTypeType XRE_GetProcessType = 0;
XRE_AddStaticComponentType XRE_AddStaticComponent = 0;
#ifdef MOZ_PROFILESHARING
#include "nsIProfileSharingSetup.h"
#endif
#ifdef _BUILD_STATIC_BIN
#include "nsStaticComponents.h"
nsresult PR_CALLBACK
app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
#endif
#ifdef NS_TRACE_MALLOC
#include "nsTraceMalloc.h"
#endif
#ifdef _DEBUG
/*#include "StackWalker.h"
static struct _test
{
_test() { InitAllocCheck(); }
~_test(){ DeInitAllocCheck(); }
} _myLeakFinder;*/
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define LANG_CONFIG_FILE _T("language.cfg")
#define MENU_CONFIG_FILE _T("menus.cfg")
#define ACCEL_CONFIG_FILE _T("accel.cfg")
extern CString GetMozDirectory(char* dirName);
BEGIN_MESSAGE_MAP(CMfcEmbedApp, CWinApp)
//{{AFX_MSG_MAP(CMfcEmbedApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
ON_COMMAND(ID_NEW_BROWSER, OnNewBrowser)
ON_COMMAND(ID_MANAGE_PROFILES, OnManageProfiles)
ON_COMMAND(ID_PREFERENCES, OnPreferences)
ON_COMMAND(ID_OFFLINE, OnToggleOffline)
ON_COMMAND(ID_TOGGLE_JS, OnToggleJS)
ON_COMMAND(ID_APP_RESTART, OnAppRestart)
ON_UPDATE_COMMAND_UI(ID_APP_RESTART, OnUpdateAppRestart)
ON_UPDATE_COMMAND_UI(ID_TOGGLE_JS, OnUpdateToggleJS)
ON_UPDATE_COMMAND_UI(ID_OFFLINE, OnUpdateToggleOffline)
ON_UPDATE_COMMAND_UI_RANGE(WINDOW_MENU_START_ID, WINDOW_MENU_STOP_ID, OnUpdateWindows)
ON_COMMAND_RANGE(WINDOW_MENU_START_ID, WINDOW_MENU_STOP_ID, OnWindowSelect)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#include <Iads.h>
#include <activeds.h>
#include <comdef.h>
#include <initguid.h>
#include <accctrl.h>
BOOL RestartAsRestricted()
{
HANDLE hProcessToken = NULL;
HANDLE hRestrictedToken = NULL;
PTOKEN_USER pstructUserToken = NULL;
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_READ, &hProcessToken))
return FALSE;
DWORD dwLen = 0;
DWORD dwInertFlag;
if (!GetTokenInformation(hProcessToken, TokenSandBoxInert, &dwInertFlag, sizeof(dwInertFlag), &dwLen) || dwInertFlag!=0){
CloseHandle(hProcessToken);
return FALSE;
}
// XXX : Bad check using privilege count to be compatible with sandboxie
BYTE buf[1024];
if (!GetTokenInformation(hProcessToken, TokenPrivileges, &buf, 1024, &dwLen))
{
CloseHandle(hProcessToken);
return FALSE;
}
TOKEN_PRIVILEGES *tp = (TOKEN_PRIVILEGES*)buf;
if (tp->PrivilegeCount < 2) return FALSE;
if(!CreateRestrictedToken(hProcessToken, DISABLE_MAX_PRIVILEGE | SANDBOX_INERT, 0, &pstructUserToken->User, 0, NULL, 0, NULL, &hRestrictedToken ) ){
CloseHandle(hProcessToken);
return FALSE;
}
PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_NORMAL;
HANDLE hMutexOneInstance = CreateMutex( NULL, TRUE, _T("K-Meleon Instance Mutex") );
ReleaseMutex(hMutexOneInstance);
BOOL res = CreateProcessAsUser(hRestrictedToken, NULL, ::GetCommandLine(), NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
HeapFree(GetProcessHeap(), 0, (LPVOID)pstructUserToken);
pstructUserToken = NULL;
CloseHandle(hRestrictedToken);
CloseHandle(hProcessToken);
if (!res) return FALSE;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return TRUE;
}
CMfcEmbedApp::CMfcEmbedApp()
{
mRefCnt = 1; // Start at one - nothing is going to addref this object
m_ProfileMgr = NULL;
m_bSwitchingProfiles = FALSE;
m_bFirstWindowCreated = FALSE;
m_pMostRecentBrowserFrame = NULL;
m_hResDll = NULL;
m_MRUList = NULL;
m_bRestart = FALSE;
}
CMfcEmbedApp theApp;
static NS_IMETHODIMP
RefreshPlugins(PRBool aReloadPages)
{
return NS_OK;
}
nsresult CMfcEmbedApp::SetOffline(BOOL offline)
{
nsresult result;
nsCOMPtr<nsIIOService> io = do_GetService(NS_IOSERVICE_CONTRACTID, &result);
if (NS_SUCCEEDED(result)) {
result = io->SetOffline(offline);
if (NS_SUCCEEDED(result))
theApp.preferences.bOffline = offline;
}
return result;
}
void CMfcEmbedApp::ShowDebugConsole()
{
// Show console only in debug mode
if(! AllocConsole())
return;
// Redirect stdout to the console
int hCrtOut = _open_osfhandle(
(long) GetStdHandle(STD_OUTPUT_HANDLE),
_O_TEXT);
if(hCrtOut == -1)
return;
FILE *hfOut = _fdopen(hCrtOut, "w");
if(hfOut != NULL)
{
// Setup for unbuffered I/O so the console
// output shows up right away
*stdout = *hfOut;
setvbuf(stdout, NULL, _IONBF, 0);
}
// Redirect stderr to the console
int hCrtErr = _open_osfhandle(
(long) GetStdHandle(STD_ERROR_HANDLE),
_O_TEXT);
if(hCrtErr == -1)
return;
FILE *hfErr = _fdopen(hCrtErr, "w");
if(hfErr != NULL)
{
// Setup for unbuffered I/O so the console
// output shows up right away
*stderr = *hfErr;
setvbuf(stderr, NULL, _IONBF, 0);
}
}
#define FIREFOX_CHROME
#ifdef FIREFOX_CHROME
BOOL CMfcEmbedApp::LoadLanguage()
{
CString locale = preferences.GetLocaleString("general.useragent.locale", _T(""));
if (locale.IsEmpty())
return FALSE;
if (_tcsncmp(locale, _T("en"), 2) == 0) {
if (m_hResDll) {
FreeLibrary(m_hResDll);
m_hResDll = NULL;
}
lang.Reset();
AfxSetResourceHandle(m_hInstance);
#if _MSC_VER >= 1300
_AtlBaseModule.SetResourceInstance(m_hInstance);
#endif
return TRUE;
}
CString localeFolder = GetFolder(LocaleFolder) + _T("\\") + locale + _T("\\");
CString resDll = localeFolder + CString("kmeleon.dll");
HINSTANCE hInstResDll = ::LoadLibrary(resDll);
if (!hInstResDll) return FALSE;
// Check dll version
CString version, versiondll;
version.LoadString(IDS_LANG_VERSION);
#if _MSC_VER >= 1300
versiondll.LoadString(hInstResDll, IDS_LANG_VERSION);
#else
LoadString(hInstResDll, IDS_LANG_VERSION, versiondll.GetBuffer(10), 10);
versiondll.ReleaseBuffer();
#endif
if (version.Compare(versiondll) != 0) {
::FreeLibrary(hInstResDll);
return FALSE;
}
CFile file;
if (!file.Open(localeFolder + CString("kmeleon.kml"), CFile::modeRead, NULL)) {
::FreeLibrary(hInstResDll);
return FALSE;
}
file.Close();
CFileFind finder;
CString langFile, pattern = localeFolder + CString("*.kml");
BOOL bWorking = finder.FindFile(pattern);
while (bWorking) {
bWorking = finder.FindNextFile();
langFile = finder.GetFilePath();
lang.Load(langFile);
}
AfxSetResourceHandle(hInstResDll);
#if _MSC_VER >= 1300
_AtlBaseModule.SetResourceInstance(hInstResDll);
#endif
if (m_hResDll && m_hResDll!=hInstResDll)
FreeLibrary(m_hResDll);
m_hResDll = hInstResDll;
return TRUE;
}
#else
BOOL CMfcEmbedApp::LoadLanguage()
{
TCHAR resDll[MAX_PATH], *extension;
// Look for dll resources
::GetModuleFileName(m_hInstance, resDll, MAX_PATH);
extension = _tcsrchr(resDll, _T('.'));//::PathFindExtension(resDll);
if ((extension + 7) - resDll > MAX_PATH)
return FALSE;
lstrcpy(extension, _T("loc.dll"));
HINSTANCE hInstResDll = ::LoadLibrary(resDll);
if (!hInstResDll) return FALSE;
// Check dll version
CString version, versiondll;
version.LoadString(IDS_LANG_VERSION);
#if _MSC_VER >= 1300
versiondll.LoadString(hInstResDll, IDS_LANG_VERSION);
#else
LoadString(hInstResDll, IDS_LANG_VERSION, versiondll.GetBuffer(10), 10);
versiondll.ReleaseBuffer();
#endif
if (version.Compare(versiondll) != 0) {
::FreeLibrary(hInstResDll);
return FALSE;
}
// Look for language file
TCHAR* langFile = resDll;
TCHAR* lastSlash = _tcsrchr(resDll, _T('\\'));
if (!lastSlash) {
::FreeLibrary(hInstResDll);
ASSERT(FALSE);
return FALSE;
}
lastSlash++;
TCHAR locale[10];
::LoadString(hInstResDll, IDS_LOCALE_ID, locale, 10);
lstrcpy(lastSlash, _T("kmeleon."));
lstrcat(lastSlash, locale);
lstrcat(lastSlash, _T(".kml"));
if (!lang.Load(langFile)) {
lstrcpy(lastSlash, LANG_CONFIG_FILE);
if (!lang.Load(langFile)) {
::FreeLibrary(hInstResDll);
return FALSE;
}
}
AfxSetResourceHandle(hInstResDll);
#if _MSC_VER >= 1300
_AtlBaseModule.SetResourceInstance(hInstResDll);
#endif
return TRUE;
}
#endif
// Initialize our MFC application and also init
// the Gecko embedding APIs
// Note that we're also init'ng the profile switching
// code here
// Then, create a new BrowserFrame and load our
// default homepage
//
BOOL CMfcEmbedApp::CheckInstance()
{
HANDLE hMutexOneInstance = CreateMutex( NULL, FALSE, _T("K-Meleon Instance Mutex") );
DWORD dwWaitResult = WaitForSingleObject( hMutexOneInstance, 0);
if (dwWaitResult == WAIT_OBJECT_0)
return TRUE;
// if another instance is already running, pass it our command line paramaters,
// and ask it to open a new window
// eventually, we should handle this through DDE
// find the hidden window
if (HWND hwndPrev = ::FindWindowEx(NULL, NULL, HIDDEN_WINDOW_CLASS, NULL) ) {
if(*m_lpCmdLine) {
COPYDATASTRUCT copyData;
copyData.dwData = 0;
copyData.cbData = (strlen(cmdline.m_sCmdLine)+1)*sizeof(char);
copyData.lpData = (void *) cmdline.m_sCmdLine;
SendMessage(hwndPrev, WM_COPYDATA, NULL, (LPARAM) &copyData);
}
else
SendMessage(hwndPrev, UWM_NEWWINDOW, NULL, NULL);
}
return FALSE;
}
#define PROCESS_DEP_ENABLE 0x00000001
#define PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION 0x00000002
extern mozilla::Module kBrowserModule;
extern mozilla::Module kBrowserModuleApp;
BOOL CMfcEmbedApp::InitEmbedding(const char* profile)
{
CString xul = GetFolder(RootFolder)+_T("\\xul.dll");
int len = WideCharToMultiByte(CP_UTF8, 0, xul, -1, NULL, 0, NULL, NULL);
char* gnah = new char[len+1];
WideCharToMultiByte(CP_UTF8, 0, xul, -1, gnah, len, NULL, NULL);
if (NS_FAILED(XPCOMGlueStartup(gnah))) {
AfxMessageBox(IDS_START_FAILED, MB_OK | MB_ICONERROR);
return FALSE;
}
delete [] gnah;
NS_LogInit();
// load XUL functions
nsDynamicFunctionLoad nsFuncs[] = {
{"XRE_InitEmbedding2", (NSFuncPtr*)&XRE_InitEmbedding2},
{"XRE_TermEmbedding", (NSFuncPtr*)&XRE_TermEmbedding},
{"XRE_NotifyProfile", (NSFuncPtr*)&XRE_NotifyProfile},
{"XRE_LockProfileDirectory", (NSFuncPtr*)&XRE_LockProfileDirectory},
{"XRE_AddManifestLocation", (NSFuncPtr*)&XRE_AddManifestLocation},
{"XRE_GetProcessType", (NSFuncPtr*)&XRE_GetProcessType},
{"XRE_AddStaticComponent", (NSFuncPtr*)&XRE_AddStaticComponent},
{0, 0}
};
nsresult rv = XPCOMGlueLoadXULFunctions(nsFuncs);
NS_ENSURE_SUCCESS(rv, FALSE);
// Set provider
CString strRes;
strRes.LoadString(IDS_PROFILES_FOLDER_NAME);
KmFileLocProvider *provider = new KmFileLocProvider(nsDependentString(T2W(strRes.GetBuffer(0))));
if(!provider) return FALSE;
// Set app directory
nsCOMPtr<nsIFile> mreAppDir;
rv = NS_NewLocalFile(nsDependentString(theApp.GetFolder(RootFolder)), TRUE, getter_AddRefs(mreAppDir));
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create mreAppDir file");
nsCOMPtr<nsIFile> appSubdir;
rv = NS_NewLocalFile(nsDependentString(theApp.GetFolder(AppFolder)), TRUE, getter_AddRefs(appSubdir));
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create appSubdir file");
// Set Profile
m_ProfileMgr = new CProfileMgr;
if (!m_ProfileMgr) return FALSE;
BOOL result;
USES_CONVERSION;
result = m_ProfileMgr->StartUp(provider, profile ? A2CT(profile) : nullptr);
if (profile) delete [] profile;
ASSERT(result);
if (!result) return FALSE;
// Init XRE
rv = XRE_AddStaticComponent(&kBrowserModuleApp);
NS_ENSURE_SUCCESS(rv, FALSE);
rv = XRE_InitEmbedding2(mreAppDir, appSubdir, provider);
NS_ENSURE_SUCCESS(rv, FALSE);
rv = XRE_AddStaticComponent(&kBrowserModule);
NS_ENSURE_SUCCESS(rv, FALSE);
rv = InitializeWindowCreator();
if (NS_FAILED(rv))
{
ASSERT(FALSE);
XRE_TermEmbedding();
return FALSE;
}
// Register chrome language
CString localesFolder = GetFolder(LocaleFolder) + _T("\\*");
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile(localesFolder.GetBuffer(0), &ffd);
localesFolder.Truncate(localesFolder.GetLength()-1);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
ffd.cFileName[0]!='.') {
nsCOMPtr<nsIFile> mFile;
NS_NewLocalFile(CStringToNSString(localesFolder + ffd.cFileName + _T("\\") + ffd.cFileName + _T(".manifest")), false, getter_AddRefs(mFile));
XRE_AddManifestLocation(NS_COMPONENT_LOCATION, mFile);
}
} while ( FindNextFile(hFind, &ffd) );
FindClose(hFind);
}
XRE_NotifyProfile();
nsCOMPtr<nsIAppStartup> appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID));
if (appStartup) {
appStartup->CreateHiddenWindow();
}
NS_LogTerm();
nsCOMPtr<nsICommandLineRunner> cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
if (cmdLine) {
nsCOMPtr<nsIFile> workingDir;
NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));
int argc;
LPWSTR* argv16 = CommandLineToArgvW(GetCommandLineW(), &argc);
int l = 0;
for (int i = 0; i < argc; i++) {
l += wcslen(argv16[i]) + 1;
}
char *_argv = new char[l * 3];
char** argv = new char*[argc];
for (int i = 0; i < argc; i++) {
argv[i] = _argv;
int x = WideCharToMultiByte(CP_UTF8, 0, argv16[i], -1, _argv, l, NULL, NULL);
_argv += x;
l -= x;
}
LocalFree(argv16);
cmdLine->Init(argc, argv, workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
delete[] argv[0];
delete[] argv;
nsCOMPtr<nsIObserverService> observer(do_GetService("@mozilla.org/observer-service;1"));
if (observer) observer->NotifyObservers(cmdLine, "command-line-startup", nullptr);
}
return TRUE;
}
BOOL CMfcEmbedApp::InitInstance()
{
USES_CONVERSION;
cmdline.Initialize(T2A(m_lpCmdLine));
// check for prior instances
m_bAlreadyRunning = FALSE;
if (cmdline.GetSwitch("-new", NULL, TRUE)<0 && !CheckInstance()) {
m_bAlreadyRunning = TRUE;
return FALSE;
}
// Security
#ifdef _UNICODE
if (cmdline.GetSwitch("-norestrict", NULL, TRUE)<0 && RestartAsRestricted())
{
m_bAlreadyRunning = TRUE;
return FALSE;
}
#endif
#ifdef _DEBUG
ShowDebugConsole();
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
#endif
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
AfxOleInit();
// Profile selection
int len = cmdline.GetSwitch("-P", NULL, FALSE);
char *profile = NULL;
if (len == 0) {
cmdline.GetSwitch("-P", NULL, TRUE); // remove the flag from the command line
}
else if (len > 0) {
profile = new char[len+1];
cmdline.GetSwitch("-P", profile, TRUE);
}
m_hMutex = CreateMutex(NULL, FALSE, NULL);
// Minimal unicode support
#ifndef _UNICODE
OSVERSIONINFO osinfo;
osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osinfo);
m_bUnicode = (osinfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
#endif
// Register the hidden window class
WNDCLASS wc = { 0 };
#ifdef _UNICODE
wc.lpfnWndProc = DefWindowProc; // MSLU incompatibility
#else
wc.lpfnWndProc = AfxWndProc;
#endif
wc.hInstance = AfxGetInstanceHandle();
wc.lpszClassName = HIDDEN_WINDOW_CLASS;
wc.hIcon=m_hMainIcon;
AfxRegisterClass( &wc );
// Register the browser window class
wc.lpszClassName = BROWSER_WINDOW_CLASS;
AfxRegisterClass( &wc );
//plugins.Load(GetFolder(RootFolder)+_T("\\kplugins\\jsbridge.dll"));
if (!InitEmbedding(profile))
return FALSE;
// These have to be done in this order!
InitializeDefineMap();
InitializePrefs();
SetOffline(theApp.preferences.bOffline);
LoadLanguage();
CheckProfileVersion();
m_MRUList = new CMostRecentUrls();
// Initialize plugins
plugins.FindAndLoad();
plugins.SendMessage("*", "* Plugin Manager", "Init2");
skin.Init(theApp.preferences.skinsCurrent);
// Retrieve the default icon
CString sSkinIcon;
if (skin.FindSkinFile(sSkinIcon, _T("main.ico")))
{
m_hMainIcon = (HICON)LoadImage( NULL, sSkinIcon, IMAGE_ICON, 0,0, LR_DEFAULTSIZE | LR_LOADFROMFILE );
m_hSmallIcon = (HICON)LoadImage( NULL, sSkinIcon, IMAGE_ICON, 16,16, LR_LOADFROMFILE );
}
else
{
m_hMainIcon = LoadIcon( IDR_MAINFRAME );
m_hSmallIcon = LoadIcon( IDR_MAINFRAME );
}
#ifdef INTERNAL_SITEICONS
// Create the favicon list
float scale = 1;
/* CString _scale = theApp.preferences.GetString("layout.css.devPixelsPerPx", _T("-1.0"));
float scale = _tstof_l((LPCTSTR)_scale, _create_locale(LC_ALL, "ENU"));
if (scale<=0) {
HDC dc = ::GetDC(NULL);
scale = GetDeviceCaps(dc, LOGPIXELSY) / 96.0;
::ReleaseDC(NULL, dc);
}
*/
if (preferences.bSiteIcons)
favicons.Create(skin.GetUserWidth(),skin.GetUserWidth(),ILC_COLOR32|ILC_MASK,25,100);
#endif
InitializeMenusAccels();
// the hidden window will take care of creating the first
// browser window for us
if(!CreateHiddenWindow()){
ASSERT(FALSE);
XRE_TermEmbedding();
//NS_TermEmbedding();
return FALSE;
}
return TRUE;
}
// add new download dialogs to the internal window list so we won't exit
// the app while downloads are in progress
void CMfcEmbedApp::RegisterWindow(CDialog *window) {
m_MiscWndLst.AddHead(window);
}
void CMfcEmbedApp::UnregisterWindow(CDialog *window) {
POSITION pos = m_MiscWndLst.Find(window);
m_MiscWndLst.RemoveAt(pos);
// See comment in RemoveFrameFromList()
if ((m_MiscWndLst.GetCount() == 0) && (m_FrameWndLst.GetCount() == 0)) {
if (m_pMainWnd) {
// if we're staying resident, create the hidden browser window
if (((CHiddenWnd*) m_pMainWnd)->Persisting() == PERSIST_STATE_ENABLED)
((CHiddenWnd*) m_pMainWnd)->StayResident();
// otherwise we're exiting, close the Evil Hidden Window
else
m_pMainWnd->DestroyWindow();
}
}
}
CBrowserFrame* CMfcEmbedApp::CreateNewBrowserFrameWithUrl(LPCTSTR pUrl, LPCTSTR refferer,
BOOL bBackground,
CWnd* pParent)
{
if (!pUrl) return NULL;
CBrowserFrame* pFrame;
const TCHAR* ext = _tcschr(pUrl, L'.');
if (ext && (_tcsstr(ext, _T(".xul")) == ext) &&
(_tcsncmp(pUrl, _T("chrome:"), 7) == 0)) {
pFrame = CreateNewChromeDialog(pUrl, pParent);
}
else {
pFrame = CreateNewBrowserFrame(nsIWebBrowserChrome::CHROME_ALL, bBackground, pParent);
pFrame->OpenURL(pUrl, refferer, FALSE);
pFrame->ShowWindow(SW_SHOW);
}
return pFrame;
}
/*
CDialog* diag = new CDialog();
diag->CreateIndirect((LPCDLGTEMPLATE)tplGenericDlg, pParent);
CBrowserView* view = new CBrowserView();
if (!view->CreateEx(0, NULL, NULL, WS_CHILD|WS_VISIBLE,
CRect(0, 0, 0, 0), diag, AFX_IDW_PANE_FIRST, NULL)) return 0;
view->OpenURL(url);
diag->ShowWindow(SW_SHOW);
return diag;
*/
CBrowserFrame* CMfcEmbedApp::CreateNewChromeDialog(LPCTSTR url, CWnd* pParent)
{
// Check if it's not already open
POSITION pos = theApp.m_FrameWndLst.GetHeadPosition();
CBrowserFrame* pBrowserFrame = NULL;
while( pos != NULL ) {
pBrowserFrame = (CBrowserFrame *) theApp.m_FrameWndLst.GetNext(pos);
if(pBrowserFrame->IsDialog() && pBrowserFrame->GetActiveView()->GetCurrentURI().Compare(url) == 0) {
pBrowserFrame->ActivateFrame();
return pBrowserFrame;
}
}
//XXXX We have to make a real Dialog!
PRUint32 chromeMask = nsIWebBrowserChrome::CHROME_WINDOW_RESIZE |
nsIWebBrowserChrome::CHROME_WINDOW_CLOSE |
nsIWebBrowserChrome::CHROME_TITLEBAR |
nsIWebBrowserChrome::CHROME_OPENAS_CHROME|
nsIWebBrowserChrome::CHROME_WINDOW_MIN;
CBrowserFrame* pFrame = CreateNewBrowserFrame(chromeMask, FALSE, pParent);
pFrame->OpenURL(url);
return pFrame;
}
CBrowserFrame* CMfcEmbedApp::CreateNewBrowserFrame(PRUint32 chromeMask,
BOOL inBackground,
CWnd* pParent)
{
DWORD dwWaitResult;
dwWaitResult = WaitForSingleObject( m_hMutex, 1000L);
if (dwWaitResult != WAIT_OBJECT_0) {
return NULL;
}
// Load the window title from the string resource table
CString strTitle;
strTitle.LoadString(IDR_MAINFRAME);
BOOL isPopupOrDialog = FALSE;
// XXX Chrome dialogs shouldn't have thoses.
if (chromeMask & nsIWebBrowserChrome::CHROME_OPENAS_CHROME) {
chromeMask &= ~nsIWebBrowserChrome::CHROME_MENUBAR
&~nsIWebBrowserChrome::CHROME_TOOLBAR
&~nsIWebBrowserChrome::CHROME_LOCATIONBAR
&~nsIWebBrowserChrome::CHROME_STATUSBAR
&~nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR;
isPopupOrDialog = TRUE;
}
LONG style, styleEx = 0L;
if (chromeMask & nsIWebBrowserChrome::CHROME_WINDOW_POPUP) {
style = WS_POPUPWINDOW | WS_CAPTION;
styleEx = WS_EX_TOPMOST | WS_EX_TOOLWINDOW;
}
else if (chromeMask & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG) {
style = WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_DLGFRAME;
//| DS_3DLOOK | DS_MODALFRAME;
styleEx = WS_EX_DLGMODALFRAME;
}
else {
style = WS_OVERLAPPEDWINDOW;
if (pParent && (chromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT))
style |= WS_POPUP;
}
if ( !(chromeMask & nsIWebBrowserChrome::CHROME_DEFAULT) &&
((chromeMask & nsIWebBrowserChrome::CHROME_ALL) != nsIWebBrowserChrome::CHROME_ALL)) {
if( !(chromeMask & nsIWebBrowserChrome::CHROME_TITLEBAR) )
style &= ~WS_CAPTION; // No caption
if (!theApp.preferences.bDisableResize) {
if( !(chromeMask & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE) ) {
// Can't resize this window
style &= ~WS_THICKFRAME;
style &= ~WS_MAXIMIZEBOX;
}
}
if ( !(chromeMask & nsIWebBrowserChrome::CHROME_WINDOW_CLOSE) &&
!(chromeMask & nsIWebBrowserChrome::CHROME_MENUBAR) )
style &= ~WS_SYSMENU;
if (chromeMask & nsIWebBrowserChrome::CHROME_WINDOW_MIN)
style |= WS_MINIMIZEBOX;
}
if ( (chromeMask & (nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) ||
(!(chromeMask & nsIWebBrowserChrome::CHROME_DEFAULT) &&
!(chromeMask & nsIWebBrowserChrome::CHROME_TOOLBAR)) ) {
isPopupOrDialog = TRUE;
style |= WS_POPUP; // XXX
}
if (!isPopupOrDialog && (preferences.bMaximized ||
(m_pMostRecentBrowserFrame && m_pMostRecentBrowserFrame->IsZoomed())) &&
((chromeMask & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE) || (chromeMask & nsIWebBrowserChrome::CHROME_ALL)))
style |= WS_MAXIMIZE;
RECT screen, winSize = {0};
SystemParametersInfo(SPI_GETWORKAREA, NULL, &screen, 0);
int screenWidth = screen.right - screen.left;
int screenHeight = screen.bottom - screen.top;
/*
if (x>0 && y>0 && cx>0 && cy>0) {
winSize.left = x;
winSize.top = y;
winSize.right = x + cx;
winSize.bottom = y + cy;
AdjustWindowRectEx(&winSize, style, chromeMask & (nsIWebBrowserChrome::CHROME_MENUBAR), 0);
}
else {*/
// If the last active window is not a popup use cascading placement
if (!(chromeMask & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) {
CBrowserFrame* pCascadeWnd = NULL;
if (inBackground && !m_FrameWndLst.IsEmpty()) {
pCascadeWnd = (CBrowserFrame*)m_FrameWndLst.GetHead();
if (pCascadeWnd->IsPopup() || pCascadeWnd->IsDialog())
pCascadeWnd = NULL;
}
if (!pCascadeWnd && m_pMostRecentBrowserFrame) {
pCascadeWnd = m_pMostRecentBrowserFrame;
if (pCascadeWnd->IsPopup() || pCascadeWnd->IsDialog())
pCascadeWnd = NULL;
}
if (pCascadeWnd)
{
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
pCascadeWnd->GetWindowPlacement(&wp);
// if the window is not maximized, let's use use GetWindowRect, which works
if (wp.showCmd == SW_SHOWNORMAL)
pCascadeWnd->GetWindowRect(&wp.rcNormalPosition);
int offset = GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CXBORDER);
winSize.left = wp.rcNormalPosition.left + offset;
winSize.top = wp.rcNormalPosition.top + offset;
winSize.right = wp.rcNormalPosition.right + offset;
winSize.bottom = wp.rcNormalPosition.bottom + offset;
// Put the window to the top corner if we're too far in
// the bottom left.
if ( (screen.right - winSize.right) < offset
&& (screen.bottom - winSize.bottom) < offset)
{
winSize.left = screen.left;
winSize.top = screen.top;
winSize.right = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
winSize.bottom = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
}
}
else {
// Use default position
winSize.left = screen.left + screenWidth / 20;
winSize.top = screen.top + screenHeight / 20;
winSize.right = winSize.left + 15*screenWidth / 20;
winSize.bottom = winSize.top + 18*screenHeight/20;
// Use user preference position if any
if (preferences.windowXPos >= 0)
winSize.left = preferences.windowXPos;
if (preferences.windowYPos >=0)
winSize.top = preferences.windowYPos;
if (preferences.windowWidth > 0)
winSize.right = winSize.left + preferences.windowWidth;
if (preferences.windowHeight > 0)
winSize.bottom = winSize.top + preferences.windowHeight;
}
} else {
// XXX
// this is a chrome window, let set some generic size in the hope
// the xul dialog will be sized correctly (with persist properties
// which are currently not working).
int w = preferences.GetInt("kmeleon.display.xulwidth", 0);
int h = preferences.GetInt("kmeleon.display.xulheight", 0);
if (w>1) {
winSize.left = (screenWidth - w) / 2 + screen.left;
winSize.right = winSize.left + w;
} else {
winSize.left = screen.left + screenWidth / 20;
winSize.right = winSize.left + 12*screenWidth / 20;
}
if (h>1) {
winSize.top = (screenHeight - h) / 2 + screen.top;
winSize.bottom = winSize.top + h;
} else {
winSize.top = screen.top + screenHeight / 20;
winSize.bottom = winSize.top + 15*screenHeight / 20;
}
}
// don't create windows larger than the screen
if ((winSize.right - winSize.left) > screenWidth)
winSize.right = screenWidth - winSize.left;
if ((winSize.bottom - winSize.top) > screenHeight)
winSize.bottom = screenHeight - winSize.top;
// make sure the window isn't going to run off the screen
if ((screen.right - winSize.right) < 0) {
winSize.left = screen.right - (winSize.right - winSize.left);
winSize.right = screen.right;
}
if ((screen.bottom - winSize.bottom) < 0) {
winSize.top = screen.bottom - (winSize.bottom - winSize.top);
winSize.bottom = screen.bottom;
}
// Now, create the browser frame
CBrowserFrame* pFrame = NULL;
if (isPopupOrDialog || preferences.GetBool("kmeleon.notab", FALSE))
pFrame = new CBrowserFrame(chromeMask, style);
else
pFrame = (CBrowserFrame*)new CBrowserFrmTab(chromeMask, style);
// this backup is made as part of a bad workaround:
// m_pMostRecentBrowserFrame needs to be this frame for the life of this function so that
// things like plugins and the rebar sizes can access it, but
// m_pMostRecentBrowserFrame should not stay set to this if this window
// is hidden (usually meaning that it is created using the open link in background option)
// so the backup is made, and m_pMostRecentBrowserFrame will be restored
// at the end of this function
CBrowserFrame* pOldRecentFrame = m_pMostRecentBrowserFrame;
m_pMostRecentBrowserFrame = pFrame;
if (!pOldRecentFrame)
pOldRecentFrame = pFrame;
CMenu *menu = theApp.menus.GetMenu(_T("Main"));
if (!pFrame->CreateEx(styleEx, BROWSER_WINDOW_CLASS, strTitle, style,
winSize, chromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT ? pParent : NULL,
(UINT)menu->GetSafeHmenu(), NULL))
{
TRACE0("Warning: failed to create CFrameWnd.\n");
ReleaseMutex(theApp.m_hMutex);
m_pMostRecentBrowserFrame = pOldRecentFrame;
delete pFrame;
return FALSE;
}
pFrame->SetIcon(m_hMainIcon, true);
pFrame->SetIcon(m_hSmallIcon, false);
// this only needs to be called once
if (!m_bFirstWindowCreated) {
KmMenu* menu = menus.GetKMenu(_T("@Toolbars"));
if (menu) menu->Invalidate();
#ifdef INTERNAL_SIDEBAR
menu = menus.GetKMenu(_T("@Sidebars"));
if (menu) menu->Invalidate();
#endif
m_bFirstWindowCreated = TRUE;
}
if (!preferences.bHideTaskBarButtons)
pFrame->ModifyStyleEx(0, WS_EX_APPWINDOW);
if (preferences.GetBool("kmeleon.display.hideTitleBar", FALSE) && !isPopupOrDialog) {
pFrame->ModifyStyle(WS_CAPTION, 0 , SWP_DRAWFRAME);
if (pFrame->IsZoomed())
pFrame->ModifyStyle(WS_THICKFRAME, 0);
}
if (inBackground) {
pFrame->SetWindowPos((CWnd*)theApp.m_FrameWndLst.GetHead(),
0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
theApp.m_pMostRecentBrowserFrame = pOldRecentFrame;
} else if (!isPopupOrDialog) {
theApp.m_pMostRecentBrowserFrame = pOldRecentFrame;
}
// Add to the list of BrowserFrame windows
m_FrameWndLst.AddHead(pFrame);
ReleaseMutex(m_hMutex);
return pFrame;
}
void CMfcEmbedApp::OnAppAbout()
{
CBrowserFrame* pFrm = CreateNewBrowserFrame(
nsIWebBrowserChrome::CHROME_WINDOW_RESIZE |
nsIWebBrowserChrome::CHROME_WINDOW_CLOSE |
nsIWebBrowserChrome::CHROME_TITLEBAR |
nsIWebBrowserChrome::CHROME_SCROLLBARS,
FALSE);
if (!pFrm) return;
pFrm->OpenURL(_T("about:"));
pFrm->ShowWindow(SW_SHOW);
}