btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / apps / webpositive / BrowserApp.cpp
blobd6253c0cf6ec3aadd821b0f60cb47a89821043df
1 /*
2 * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
3 * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "BrowserApp.h"
31 #include <AboutWindow.h>
32 #include <Alert.h>
33 #include <Autolock.h>
34 #include <Catalog.h>
35 #include <Directory.h>
36 #include <Entry.h>
37 #include <FindDirectory.h>
38 #include <Locale.h>
39 #include <Path.h>
40 #include <Screen.h>
41 #include <UrlContext.h>
42 #include <debugger.h>
44 #include <stdio.h>
46 #include "BrowserWindow.h"
47 #include "BrowsingHistory.h"
48 #include "DownloadWindow.h"
49 #include "SettingsMessage.h"
50 #include "SettingsWindow.h"
51 #include "ConsoleWindow.h"
52 #include "CookieWindow.h"
53 #include "NetworkCookieJar.h"
54 #include "WebKitInfo.h"
55 #include "WebPage.h"
56 #include "WebSettings.h"
57 #include "WebView.h"
58 #include "WebViewConstants.h"
61 #undef B_TRANSLATION_CONTEXT
62 #define B_TRANSLATION_CONTEXT "WebPositive"
64 const char* kApplicationSignature = "application/x-vnd.Haiku-WebPositive";
65 const char* kApplicationName = B_TRANSLATE_SYSTEM_NAME("WebPositive");
66 static const uint32 PRELOAD_BROWSING_HISTORY = 'plbh';
68 #define ENABLE_NATIVE_COOKIES 1
71 BrowserApp::BrowserApp()
73 BApplication(kApplicationSignature),
74 fWindowCount(0),
75 fLastWindowFrame(50, 50, 950, 750),
76 fLaunchRefsMessage(0),
77 fInitialized(false),
78 fSettings(NULL),
79 fCookies(NULL),
80 fSession(NULL),
81 fContext(NULL),
82 fDownloadWindow(NULL),
83 fSettingsWindow(NULL),
84 fConsoleWindow(NULL),
85 fCookieWindow(NULL)
87 #if ENABLE_NATIVE_COOKIES
88 BString cookieStorePath = kApplicationName;
89 cookieStorePath << "/Cookies";
90 fCookies = new SettingsMessage(B_USER_SETTINGS_DIRECTORY,
91 cookieStorePath.String());
92 fContext = new BUrlContext();
93 if (fCookies->InitCheck() == B_OK) {
94 BMessage cookieArchive = fCookies->GetValue("cookies", cookieArchive);
95 fContext->SetCookieJar(BNetworkCookieJar(&cookieArchive));
97 #endif
99 BString sessionStorePath = kApplicationName;
100 sessionStorePath << "/Session";
101 fSession = new SettingsMessage(B_USER_SETTINGS_DIRECTORY,
102 sessionStorePath.String());
106 BrowserApp::~BrowserApp()
108 delete fLaunchRefsMessage;
109 delete fSettings;
110 delete fCookies;
111 delete fSession;
112 delete fContext;
116 void
117 BrowserApp::AboutRequested()
119 BAboutWindow* window = new BAboutWindow(kApplicationName,
120 kApplicationSignature);
122 // create the about window
124 const char* authors[] = {
125 "Andrea Anzani",
126 "Stephan Aßmus",
127 "Alexandre Deckner",
128 "Rene Gollent",
129 "Ryan Leavengood",
130 "Michael Lotz",
131 "Maxime Simon",
132 NULL
135 BString aboutText("");
136 aboutText << "HaikuWebKit " << WebKitInfo::HaikuWebKitVersion();
137 aboutText << "\nWebKit " << WebKitInfo::WebKitVersion();
139 window->AddCopyright(2007, "Haiku, Inc.");
140 window->AddAuthors(authors);
141 window->AddExtraInfo(aboutText.String());
143 window->Show();
147 void
148 BrowserApp::ArgvReceived(int32 argc, char** argv)
150 BMessage message(B_REFS_RECEIVED);
151 for (int i = 1; i < argc; i++) {
152 if (strcmp("-f", argv[i]) == 0
153 || strcmp("--fullscreen", argv[i]) == 0) {
154 message.AddBool("fullscreen", true);
155 continue;
157 const char* url = argv[i];
158 BEntry entry(argv[i], true);
159 BPath path;
160 if (entry.Exists() && entry.GetPath(&path) == B_OK)
161 url = path.Path();
162 message.AddString("url", url);
164 // Upon program launch, it will buffer a copy of the message, since
165 // ArgReceived() is called before ReadyToRun().
166 RefsReceived(&message);
170 void
171 BrowserApp::ReadyToRun()
173 // Since we will essentially run the GUI...
174 set_thread_priority(Thread(), B_DISPLAY_PRIORITY);
176 BWebPage::InitializeOnce();
177 BWebPage::SetCacheModel(B_WEBKIT_CACHE_MODEL_WEB_BROWSER);
179 BPath path;
180 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK
181 && path.Append(kApplicationName) == B_OK
182 && create_directory(path.Path(), 0777) == B_OK) {
184 BWebSettings::SetPersistentStoragePath(path.Path());
187 BString mainSettingsPath(kApplicationName);
188 mainSettingsPath << "/Application";
189 fSettings = new SettingsMessage(B_USER_SETTINGS_DIRECTORY,
190 mainSettingsPath.String());
192 fLastWindowFrame = fSettings->GetValue("window frame", fLastWindowFrame);
193 BRect defaultDownloadWindowFrame(-10, -10, 365, 265);
194 BRect downloadWindowFrame = fSettings->GetValue("downloads window frame",
195 defaultDownloadWindowFrame);
196 BRect settingsWindowFrame = fSettings->GetValue("settings window frame",
197 BRect());
198 BRect consoleWindowFrame = fSettings->GetValue("console window frame",
199 BRect(50, 50, 400, 300));
200 BRect cookieWindowFrame = fSettings->GetValue("cookie window frame",
201 BRect(50, 50, 400, 300));
202 bool showDownloads = fSettings->GetValue("show downloads", false);
204 fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads,
205 fSettings);
206 if (downloadWindowFrame == defaultDownloadWindowFrame) {
207 // Initially put download window in lower right of screen.
208 BRect screenFrame = BScreen().Frame();
209 BMessage decoratorSettings;
210 fDownloadWindow->GetDecoratorSettings(&decoratorSettings);
211 float borderWidth = 0;
212 if (decoratorSettings.FindFloat("border width", &borderWidth) != B_OK)
213 borderWidth = 5;
214 fDownloadWindow->MoveTo(screenFrame.Width()
215 - fDownloadWindow->Frame().Width() - borderWidth,
216 screenFrame.Height() - fDownloadWindow->Frame().Height()
217 - borderWidth);
219 fSettingsWindow = new SettingsWindow(settingsWindowFrame, fSettings);
221 BWebPage::SetDownloadListener(BMessenger(fDownloadWindow));
223 fConsoleWindow = new ConsoleWindow(consoleWindowFrame);
224 fCookieWindow = new CookieWindow(cookieWindowFrame, fContext->GetCookieJar());
226 fInitialized = true;
228 int32 pagesCreated = 0;
229 bool fullscreen = false;
230 if (fLaunchRefsMessage) {
231 _RefsReceived(fLaunchRefsMessage, &pagesCreated, &fullscreen);
232 delete fLaunchRefsMessage;
233 fLaunchRefsMessage = NULL;
236 // If no refs led to a new open page, restore previous session.
237 if (fSession->InitCheck() == B_OK && pagesCreated == 0) {
238 BMessage archivedWindow;
239 for (int i = 0; fSession->FindMessage("window", i, &archivedWindow) == B_OK;
240 i++) {
241 BRect frame = archivedWindow.FindRect("window frame");
242 BString url;
243 archivedWindow.FindString("tab", 0, &url);
244 BrowserWindow* window = new(std::nothrow) BrowserWindow(frame,
245 fSettings, url, fContext);
247 if (window != NULL) {
248 window->Show();
249 pagesCreated++;
251 for (int j = 1; archivedWindow.FindString("tab", j, &url) == B_OK;
252 j++) {
253 printf("Create %d:%d\n", i, j);
254 _CreateNewTab(window, url, false);
255 pagesCreated++;
261 // If previous session did not contain any window, create a new empty one.
262 if (pagesCreated == 0)
263 _CreateNewWindow("", fullscreen);
265 PostMessage(PRELOAD_BROWSING_HISTORY);
269 void
270 BrowserApp::MessageReceived(BMessage* message)
272 switch (message->what) {
273 case PRELOAD_BROWSING_HISTORY:
274 // Accessing the default instance will load the history from disk.
275 BrowsingHistory::DefaultInstance();
276 break;
277 case B_SILENT_RELAUNCH:
278 _CreateNewPage("");
279 break;
280 case NEW_WINDOW: {
281 BString url;
282 if (message->FindString("url", &url) != B_OK)
283 break;
284 _CreateNewWindow(url);
285 break;
287 case NEW_TAB: {
288 BrowserWindow* window;
289 if (message->FindPointer("window",
290 reinterpret_cast<void**>(&window)) != B_OK)
291 break;
292 BString url;
293 message->FindString("url", &url);
294 bool select = false;
295 message->FindBool("select", &select);
296 _CreateNewTab(window, url, select);
297 break;
299 case WINDOW_OPENED:
300 fWindowCount++;
301 fDownloadWindow->SetMinimizeOnClose(false);
302 break;
303 case WINDOW_CLOSED:
304 fWindowCount--;
305 message->FindRect("window frame", &fLastWindowFrame);
306 if (fWindowCount <= 0) {
307 BMessage* message = new BMessage(B_QUIT_REQUESTED);
308 message->AddMessage("window", DetachCurrentMessage());
309 PostMessage(message);
311 break;
313 case SHOW_DOWNLOAD_WINDOW:
314 _ShowWindow(message, fDownloadWindow);
315 break;
316 case SHOW_SETTINGS_WINDOW:
317 _ShowWindow(message, fSettingsWindow);
318 break;
319 case SHOW_CONSOLE_WINDOW:
320 _ShowWindow(message, fConsoleWindow);
321 break;
322 case SHOW_COOKIE_WINDOW:
323 _ShowWindow(message, fCookieWindow);
324 break;
325 case ADD_CONSOLE_MESSAGE:
326 fConsoleWindow->PostMessage(message);
327 break;
329 default:
330 BApplication::MessageReceived(message);
331 break;
336 void
337 BrowserApp::RefsReceived(BMessage* message)
339 if (!fInitialized) {
340 delete fLaunchRefsMessage;
341 fLaunchRefsMessage = new BMessage(*message);
342 return;
345 _RefsReceived(message);
349 bool
350 BrowserApp::QuitRequested()
352 if (fDownloadWindow->DownloadsInProgress()) {
353 BAlert* alert = new BAlert(B_TRANSLATE("Downloads in progress"),
354 B_TRANSLATE("There are still downloads in progress, do you really "
355 "want to quit WebPositive now?"), B_TRANSLATE("Quit"),
356 B_TRANSLATE("Continue downloads"));
357 int32 choice = alert->Go();
358 if (choice == 1) {
359 if (fWindowCount == 0) {
360 if (fDownloadWindow->Lock()) {
361 fDownloadWindow->SetWorkspaces(1 << current_workspace());
362 if (fDownloadWindow->IsHidden())
363 fDownloadWindow->Show();
364 else
365 fDownloadWindow->Activate();
366 fDownloadWindow->SetMinimizeOnClose(true);
367 fDownloadWindow->Unlock();
368 return false;
370 } else
371 return false;
375 fSession->MakeEmpty();
377 /* See if we got here because the last window is already closed.
378 * In that case we only need to save that one, which is already archived */
379 BMessage* message = CurrentMessage();
380 BMessage windowMessage;
382 status_t ret = message->FindMessage("window", &windowMessage);
383 if (ret == B_OK) {
384 fSession->AddMessage("window", &windowMessage);
385 } else {
386 for (int i = 0; BWindow* window = WindowAt(i); i++) {
387 BrowserWindow* webWindow = dynamic_cast<BrowserWindow*>(window);
388 if (!webWindow)
389 continue;
390 if (!webWindow->Lock())
391 continue;
393 BMessage windowArchive;
394 webWindow->Archive(&windowArchive, true);
395 fSession->AddMessage("window", &windowArchive);
397 if (webWindow->QuitRequested()) {
398 fLastWindowFrame = webWindow->WindowFrame();
399 webWindow->Quit();
400 i--;
401 } else {
402 webWindow->Unlock();
403 return false;
408 BWebPage::ShutdownOnce();
410 fSettings->SetValue("window frame", fLastWindowFrame);
411 if (fDownloadWindow->Lock()) {
412 fSettings->SetValue("downloads window frame", fDownloadWindow->Frame());
413 fSettings->SetValue("show downloads", !fDownloadWindow->IsHidden());
414 fDownloadWindow->Unlock();
416 if (fSettingsWindow->Lock()) {
417 fSettings->SetValue("settings window frame", fSettingsWindow->Frame());
418 fSettingsWindow->Unlock();
420 if (fConsoleWindow->Lock()) {
421 fSettings->SetValue("console window frame", fConsoleWindow->Frame());
422 fConsoleWindow->Unlock();
424 if (fCookieWindow->Lock()) {
425 fSettings->SetValue("cookie window frame", fCookieWindow->Frame());
426 fCookieWindow->Unlock();
429 BMessage cookieArchive;
430 BNetworkCookieJar& cookieJar = fContext->GetCookieJar();
431 cookieJar.PurgeForExit();
432 if (cookieJar.Archive(&cookieArchive) == B_OK)
433 fCookies->SetValue("cookies", cookieArchive);
435 return true;
439 void
440 BrowserApp::_RefsReceived(BMessage* message, int32* _pagesCreated,
441 bool* _fullscreen)
443 int32 pagesCreated = 0;
445 BrowserWindow* window = NULL;
446 if (message->FindPointer("window", (void**)&window) != B_OK)
447 window = NULL;
449 bool fullscreen;
450 if (message->FindBool("fullscreen", &fullscreen) != B_OK)
451 fullscreen = false;
453 entry_ref ref;
454 for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) {
455 BEntry entry(&ref, true);
456 if (!entry.Exists())
457 continue;
458 BPath path;
459 if (entry.GetPath(&path) != B_OK)
460 continue;
461 BUrl url(path);
462 window = _CreateNewPage(url.UrlString(), window, fullscreen,
463 pagesCreated == 0);
464 pagesCreated++;
467 BString url;
468 for (int32 i = 0; message->FindString("url", i, &url) == B_OK; i++) {
469 window = _CreateNewPage(url, window, fullscreen, pagesCreated == 0);
470 pagesCreated++;
473 if (_pagesCreated != NULL)
474 *_pagesCreated = pagesCreated;
475 if (_fullscreen != NULL)
476 *_fullscreen = fullscreen;
480 BrowserWindow*
481 BrowserApp::_CreateNewPage(const BString& url, BrowserWindow* webWindow,
482 bool fullscreen, bool useBlankTab)
484 // Let's first see if we must target a specific window...
485 if (webWindow && webWindow->Lock()) {
486 if (useBlankTab && webWindow->IsBlankTab()) {
487 if (url.Length() != 0)
488 webWindow->CurrentWebView()->LoadURL(url);
489 } else
490 webWindow->CreateNewTab(url, true);
491 webWindow->Activate();
492 webWindow->CurrentWebView()->MakeFocus(true);
493 webWindow->Unlock();
494 return webWindow;
497 // Otherwise, try to find one in the current workspace
498 uint32 workspace = 1 << current_workspace();
500 bool loadedInWindowOnCurrentWorkspace = false;
501 for (int i = 0; BWindow* window = WindowAt(i); i++) {
502 webWindow = dynamic_cast<BrowserWindow*>(window);
503 if (!webWindow)
504 continue;
506 if (webWindow->Lock()) {
507 if (webWindow->Workspaces() & workspace) {
508 if (useBlankTab && webWindow->IsBlankTab()) {
509 if (url.Length() != 0)
510 webWindow->CurrentWebView()->LoadURL(url);
511 } else
512 webWindow->CreateNewTab(url, true);
513 webWindow->Activate();
514 webWindow->CurrentWebView()->MakeFocus(true);
515 loadedInWindowOnCurrentWorkspace = true;
517 webWindow->Unlock();
519 if (loadedInWindowOnCurrentWorkspace)
520 return webWindow;
523 // Finally, if no window is available, let's create one.
524 return _CreateNewWindow(url, fullscreen);
528 BrowserWindow*
529 BrowserApp::_CreateNewWindow(const BString& url, bool fullscreen)
531 // Offset the window frame unless this is the first window created in the
532 // session.
533 if (fWindowCount > 0)
534 fLastWindowFrame.OffsetBy(20, 20);
535 if (!BScreen().Frame().Contains(fLastWindowFrame))
536 fLastWindowFrame.OffsetTo(50, 50);
538 BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings,
539 url, fContext);
540 if (fullscreen)
541 window->ToggleFullscreen();
542 window->Show();
543 return window;
547 void
548 BrowserApp::_CreateNewTab(BrowserWindow* window, const BString& url,
549 bool select)
551 if (!window->Lock())
552 return;
553 window->CreateNewTab(url, select);
554 window->Unlock();
558 void
559 BrowserApp::_ShowWindow(const BMessage* message, BWindow* window)
561 BAutolock _(window);
562 uint32 workspaces;
563 if (message->FindUInt32("workspaces", &workspaces) == B_OK)
564 window->SetWorkspaces(workspaces);
565 if (window->IsHidden())
566 window->Show();
567 else
568 window->Activate();
572 // #pragma mark -
576 main(int, char**)
578 try {
579 new BrowserApp();
580 be_app->Run();
581 delete be_app;
582 } catch (...) {
583 debugger("Exception caught.");
586 return 0;