1 // This may look like C code, but it's really -*- C++ -*- 2 /* 3 * Copyright (C) 2008 Emweb bv, Herent, Belgium. 4 * 5 * See the LICENSE file for terms of use. 6 */ 7 #ifndef WAPPLICATION_ 8 #define WAPPLICATION_ 9 10 #include <chrono> 11 #include <vector> 12 #include <string> 13 #include <set> 14 15 // even boost/poolfwd.hpp includes <windows.h> ... 16 namespace boost { 17 struct default_user_allocator_new_delete; 18 19 template <typename UserAllocator> 20 class pool; 21 } 22 23 #include <Wt/WObject.h> 24 #include <Wt/WCssStyleSheet.h> 25 #include <Wt/WEvent.h> 26 #include <Wt/WJavaScriptPreamble.h> 27 #include <Wt/WJavaScriptSlot.h> 28 #include <Wt/WLocale.h> 29 #include <Wt/WMessageResourceBundle.h> 30 #include <Wt/WSignal.h> 31 #include <Wt/WString.h> 32 33 namespace Wt { 34 35 #ifndef WT_TARGET_JAVA 36 /* 37 * Symbols used to check that included version matches library version 38 * against which you link. 39 */ 40 struct WtLibVersion { }; 41 extern WT_API const WtLibVersion WT_INCLUDED_VERSION; 42 #endif 43 44 class WApplication; 45 class WCombinedLocalizedStrings; 46 class WContainerWidget; 47 class WEnvironment; 48 class WEvent; 49 class WLoadingIndicator; 50 class WLogEntry; 51 class WResource; 52 class WText; 53 54 class WebSession; 55 class RootContainer; 56 class UpdateLockImpl; 57 class SoundManager; 58 59 /*! \brief Typedef for a function that creates WApplication objects. 60 * 61 * \sa WRun() 62 * 63 * \relates WApplication 64 */ 65 typedef std::function<std::unique_ptr<WApplication> (const WEnvironment&)> ApplicationCreator; 66 67 #ifdef WT_TARGET_JAVA 68 /*! \brief An HTML Meta Header 69 */ 70 #endif // WT_TARGET_JAVA 71 class MetaHeader { 72 public: 73 /*! \brief Constructor 74 * 75 * Creates a meta header. The lang and user agents are optional, and should 76 * be an empty string if not used. 77 */ 78 MetaHeader(MetaHeaderType type, const std::string& name, 79 const WString& content, const std::string& lang, 80 const std::string& userAgent); 81 82 MetaHeaderType type; 83 std::string name, lang, userAgent; 84 WString content; 85 }; 86 87 /*! \class WApplication Wt/WApplication.h Wt/WApplication.h 88 * \brief Represents an application instance for a single session. 89 * 90 * \if cpp 91 * 92 * Each user session of your application has a corresponding 93 * %WApplication instance. You need to create a new instance and return 94 * it as the result of the callback function passed to WRun(). The 95 * instance is the main entry point to session information, and holds 96 * a reference to the root() of the widget tree. 97 * 98 * \elseif java 99 * 100 * Each user session of your application has a corresponding 101 * %WApplication instance. You need to create a new instance and return 102 * it as the result of {javadoclink WtServlet#createApplication(WEnvironment)}. 103 * The instance is the main entry point to session information, 104 * and holds a reference to the root() of the widget tree. 105 * 106 * \endif 107 * 108 * The recipe for a %Wt web application, which allocates new 109 * WApplication instances for every user visiting the application is 110 * thus: 111 * 112 * \if cpp 113 * \code 114 * std::unique_ptr<WApplication> createApplication(const WEnvironment& env) 115 * { 116 * // 117 * // Optionally, check the environment and redirect to an error page. 118 * // 119 * bool valid = ...; 120 * 121 * std::unique_ptr<WApplication> app; 122 * if (!valid) { 123 * app = std::make_unique<WApplication>(env); 124 * app->redirect("error.html"); 125 * app->quit(); 126 * } else { 127 * // usually you will specialize your application class 128 * app = std::make_unique<WApplication>(env); 129 * 130 * // 131 * // Add widgets to app->root() and return the application object. 132 * // 133 * } 134 * 135 * return app; 136 * } 137 * \endcode 138 * \elseif java 139 * \code 140 * public class HelloServlet extends WtServlet { 141 * public HelloServlet() { 142 * super(); 143 * } 144 * 145 * public WApplication createApplication(WEnvironment env) { 146 * // In practice, you will specialize WApplication and simply 147 * // return a new instance. 148 * WApplication app = new WApplication(env); 149 * app.getRoot().addWidget(new WText("Hello world.")); 150 * return app; 151 * } 152 * } 153 * \endcode 154 * \endif 155 * 156 * \if cpp 157 * 158 * Throughout the session, the instance is available through 159 * WApplication::instance() (or through #wApp). The application may be 160 * exited either using the method quit(), or because of a timeout 161 * after the user has closed the window, but not because the user does 162 * not interact: keep-alive messages in the background will keep the 163 * session around as long as the user has the page opened. In either 164 * case, the application object is deleted, allowing for cleanup of 165 * the entire widget tree, and any other resources. 166 * 167 * \elseif java 168 * 169 * Throughout the session, the instance is available through the 170 * static method WApplication::instance(), which uses thread-specific 171 * storage to keep track of the current session. The application may 172 * be exited either using the method quit(), or because of a timeout 173 * after the user has closed the window, but not because the user does 174 * not interact: keep-alive messages in the background will keep the 175 * session around as long as the user has the page opened. 176 * 177 * \endif 178 * 179 * The %WApplication object provides access to session-wide settings, including: 180 * 181 * - circumstantial information through environment(), which gives 182 * details about the user, start-up arguments, and user agent 183 * capabilities. 184 * - the application title with setTitle(). 185 * - inline and external style sheets using styleSheet() and 186 * useStyleSheet(). 187 * - inline and external JavaScript using doJavaScript() and require(). 188 * - the top-level widget in root(), representing the entire browser window, 189 * or multiple top-level widgets using bindWidget() when deployed in 190 * EntryPointType::WidgetSet mode to manage a number of widgets within a 3rd party page. 191 * - definition of cookies using setCookie() to persist information across 192 * sessions, which may be read using WEnvironment::getCookie() in a future 193 * session. 194 * - management of the internal path (that enables browser history and 195 * bookmarks) using setInternalPath() and related methods. 196 * - support for server-initiated updates with enableUpdates() 197 * \if cpp 198 * - localization information and message resources bundles using setLocale() 199 * and messageResourceBundle(). 200 * \elseif java 201 * - localization information and message resources bundles, with 202 * setLocale() and setLocalizedStrings() 203 * \endif 204 */ 205 class WT_API WApplication : public WObject 206 { 207 public: 208 /*! \brief Typedef for a function that creates WApplication objects. 209 * 210 * \sa WRun() 211 */ 212 typedef Wt::ApplicationCreator ApplicationCreator; 213 214 /*! \brief Creates a new application instance. 215 * 216 * The \p environment provides information on the initial request, 217 * user agent, and deployment-related information. 218 */ 219 #if defined(DOXYGEN_ONLY) || defined(WT_TARGET_JAVA) 220 WApplication(const WEnvironment& environment); 221 #else 222 WApplication(const WEnvironment& environment, 223 WtLibVersion version = WT_INCLUDED_VERSION); 224 #endif 225 226 #ifndef WT_TARGET_JAVA 227 /*! \brief Destructor. 228 * 229 * The destructor deletes the root() container, and as a consequence 230 * the entire widget tree. 231 */ 232 ~WApplication(); 233 #endif // WT_TARGET_JAVA 234 235 /*! \brief Returns the current application instance. 236 * 237 * \if cpp 238 * This is the same as the global define #wApp. In a multi-threaded server, 239 * this method uses thread-specific storage to fetch the current session. 240 * \elseif java 241 * This method uses thread-specific storage to fetch the current session. 242 * \endif 243 */ 244 static WApplication *instance(); 245 246 /*! \brief Returns the environment information. 247 * 248 * This method returns the environment object that was used when 249 * constructing the application. The environment provides 250 * information on the initial request, user agent, and 251 * deployment-related information. 252 * 253 * \sa url(), sessionId() 254 */ 255 const WEnvironment& environment() const; 256 257 /*! \brief Returns the root container. 258 * 259 * This is the top-level widget container of the application, and 260 * corresponds to entire browser window. The user interface of your 261 * application is represented by the content of this container. 262 * 263 * \if cpp 264 * 265 * The %root() widget is only defined when the application manages 266 * the entire window. When deployed as a \link Wt::EntryPointType::WidgetSet 267 * EntryPointType::WidgetSet\endlink application, there is no %root() container, and 268 * \c 0 is returned. Instead, use bindWidget() to bind one or more 269 * root widgets to existing HTML <div> (or other) elements on 270 * the page. 271 * 272 * \elseif java 273 * 274 * The root() widget is only defined when the application manages 275 * the entire window. When deployed as a \link Wt::EntryPointType::WidgetSet 276 * EntryPointType::WidgetSet\endlink application, there is no %root() container, and 277 * <code>null</code> is returned. Instead, use bindWidget() to bind 278 * one or more root widgets to existing HTML <div> (or other) 279 * elements on the page. 280 * 281 * \endif 282 */ root()283 WContainerWidget *root() const { return widgetRoot_; } 284 285 /*! \brief Finds a widget by name. 286 * 287 * This finds a widget in the application's widget hierarchy. It 288 * does not only consider widgets in the root(), but also widgets 289 * that are placed outside this root, such as in dialogs, or other 290 * "roots" such as all the bound widgets in a widgetset application. 291 * 292 * \sa WWidget::setObjectName(), WWidget::find() 293 */ 294 WWidget *findWidget(const std::string& name); 295 296 /** @name Style sheets and CSS 297 */ 298 //!@{ 299 /*! \brief Returns a reference to the inline style sheet. 300 * 301 * Widgets may allow configuration of their look and feel through 302 * style classes. These may be defined in this inline stylesheet, or 303 * in external style sheets. 304 * 305 * It is usually preferable to use external stylesheets (and 306 * consider more accessible). Still, the internal stylesheet has as 307 * benefit that style rules may be dynamically updated, and it is 308 * easier to manage logistically. 309 * 310 * \sa useStyleSheet() 311 * \sa WWidget::setStyleClass() 312 */ styleSheet()313 WCssStyleSheet& styleSheet() { return styleSheet_; } 314 315 /*! \brief Adds an external style sheet. 316 * 317 * The \p link is a link to a stylesheet. 318 * 319 * The \p media indicates the CSS media to which this stylesheet 320 * applies. This may be a comma separated list of media. The default 321 * value is "all" indicating all media. 322 * 323 * This is an overloaded method for convenience, equivalent to: 324 * \code 325 * useStyleSheet(Wt::WCssStyleSheet(link, media)) 326 * \endcode 327 */ 328 void useStyleSheet(const WLink& link, const std::string& media = "all"); 329 330 /*! \brief Conditionally adds an external style sheet. 331 * 332 * This is an overloaded method for convenience, equivalent to: 333 * \code 334 * useStyleSheet(Wt::WLinkedCssStyleSheet(link, media), condition) 335 * \endcode 336 */ 337 void useStyleSheet(const WLink& link, const std::string& condition, 338 const std::string& media); 339 340 /*! \brief Adds an external stylesheet. 341 * 342 * Widgets may allow configuration of their look and feel through 343 * style classes. These may be defined in an inline stylesheet, 344 * or in external style sheets. 345 * 346 * External stylesheets are inserted after the internal style sheet, 347 * and can therefore override default styles set by widgets in the 348 * internal style sheet. 349 * External stylesheets must have valid link. 350 * 351 * If not empty, \p condition is a string that is used to apply the 352 * stylesheet to specific versions of IE. Only a limited subset of 353 * the IE conditional comments syntax is supported (since these are 354 * in fact interpreted server-side instead of client-side). Examples 355 * are: 356 * 357 * - "IE gte 6": only for IE version 6 or later. 358 * - "!IE gte 6": only for IE versions prior to IE6. 359 * - "IE lte 7": only for IE versions prior to IE7. 360 * 361 * \sa styleSheet(), useStyleSheet(const std::string&, const std::string&), 362 * removeStyleSheet(const WLink& link) 363 * \sa WWidget::setStyleClass() 364 */ 365 void useStyleSheet(const WLinkedCssStyleSheet& styleSheet, 366 const std::string& condition = ""); 367 368 /*! \brief Removes an external stylesheet. 369 * 370 * \sa styleSheet(), useStyleSheet(const std::string&, const std::string&) 371 * \sa WWidget::setStyleClass() 372 */ 373 void removeStyleSheet(const WLink& link); 374 375 /*! \brief Sets the theme. 376 * 377 * The theme provides the look and feel of several built-in widgets, 378 * using CSS style rules. Rules for each theme are defined in the 379 * <tt>resources/themes/</tt><i>theme</i><tt>/</tt> folder. 380 * 381 * The default theme is "default" CSS theme. 382 */ 383 void setTheme(const std::shared_ptr<WTheme>& theme); 384 385 /*! \brief Returns the theme. 386 */ theme()387 std::shared_ptr<WTheme> theme() const { return theme_; } 388 389 /*! \brief Sets a CSS theme. 390 * 391 * This sets a WCssTheme as theme. 392 * 393 * The theme provides the look and feel of several built-in widgets, 394 * using CSS style rules. Rules for each CSS theme are defined in 395 * the <tt>resources/themes/</tt><i>name</i><tt>/</tt> folder. 396 * 397 * The default theme is "default". Setting an empty theme "" will 398 * result in a stub CSS theme that does not load any stylesheets. 399 */ 400 void setCssTheme(const std::string& name); 401 402 /*! \brief Sets the layout direction. 403 * 404 * The default direction is LayoutDirection::LeftToRight. 405 * 406 * This sets the language text direction, which by itself sets the 407 * default text alignment and reverse the column orders of <table> 408 * elements. 409 * 410 * In addition, %Wt will take this setting into account in 411 * WTextEdit, WTableView and WTreeView (so that columns are 412 * reverted), and swap the behaviour of WWidget::setFloatSide() and 413 * WWidget::setOffsets() for LayoutDirection::RightToLeft 414 * languages. Note that CSS settings themselves are not affected by 415 * this setting, and thus for example <tt>"float: right"</tt> will 416 * move a box to the right, irrespective of the layout direction. 417 * 418 * The library sets <tt>"Wt-ltr"</tt> or <tt>"Wt-rtl"</tt> as style 419 * classes for the document body. You may use this if to override 420 * certain style rules for a Right-to-Left document. 421 * 422 * The only valid values are LayoutDirection::LeftToRight or 423 * LayoutDirection::RightToLeft. 424 * 425 * For example: 426 * \code 427 * body .sidebar { float: right; } 428 * body.Wt-rtl .sidebar { float: left; } 429 * \endcode 430 * 431 * \note The layout direction can be set only at application startup 432 * and does not have the effect of rerendering the entire UI. 433 */ 434 void setLayoutDirection(LayoutDirection direction); 435 436 /*! \brief Returns the layout direction. 437 * 438 * \sa setLayoutDirection() 439 */ layoutDirection()440 LayoutDirection layoutDirection() const { return layoutDirection_; } 441 442 /*! \brief Sets a style class to the entire page <body>. 443 * 444 * \sa setHtmlClass() 445 */ 446 void setBodyClass(const std::string& styleClass); 447 448 /*! \brief Returns the style class set for the entire page <body>. 449 * 450 * \sa setBodyClass() 451 */ bodyClass()452 std::string bodyClass() const { return bodyClass_; } 453 454 /*! \brief Sets a style class to the entire page <html>. 455 * 456 * \sa setBodyClass() 457 */ 458 void setHtmlClass(const std::string& styleClass); 459 460 /*! \brief Returns the style class set for the entire page <html>. 461 * 462 * \sa setHtmlClass() 463 */ htmlClass()464 std::string htmlClass() const { return htmlClass_; } 465 //!@} 466 467 /*! \brief Sets the window title. 468 * 469 * Sets the browser window title to \p title. 470 * 471 * The default title is "". 472 * 473 * \sa title() 474 */ 475 void setTitle(const WString& title); 476 477 /*! \brief Returns the window title. 478 * 479 * \sa setTitle(const WString&) 480 */ title()481 const WString& title() const { return title_; } 482 483 /*! \brief Returns the close message. 484 * 485 * \sa setConfirmCloseMessage() 486 */ closeMessage()487 const WString& closeMessage() const { return closeMessage_; } 488 489 /*! \brief Returns the resource object that provides localized strings. 490 * 491 * \if cpp 492 * The default value is a WMessageResourceBundle instance, which 493 * uses XML files to resolve localized strings, but you can set a 494 * custom class using setLocalizedStrings(). 495 * \elseif java 496 * This returns the object previously set using setLocalizedStrings(). 497 * \endif 498 * 499 * WString::tr() is used to create localized strings, whose 500 * localized translation is looked up through this object, using a 501 * key. 502 * 503 * \if cpp 504 * \sa WString::tr(), messageResourceBundle() 505 * \elseif java 506 * \sa WString::tr() 507 * \endif 508 */ 509 std::shared_ptr<WLocalizedStrings> localizedStrings(); 510 511 #ifdef WT_TARGET_JAVA 512 /*! \brief Accesses the built-in resource bundle. 513 * 514 * This is an internal function and should not be called directly. 515 * 516 * \sa localizedStrings() 517 */ 518 #endif // WT_TARGET_JAVA 519 WMessageResourceBundle& builtinLocalizedStrings(); 520 521 /*! \brief Sets the resource object that provides localized strings. 522 * 523 * The \p translator resolves localized strings within the current 524 * application locale. 525 * 526 * \sa localizedStrings(), WString::tr(const char *key) 527 */ 528 void setLocalizedStrings(const std::shared_ptr<WLocalizedStrings>& 529 stringResolver); 530 531 #ifndef WT_TARGET_JAVA 532 /*! \brief Returns the message resource bundle. 533 * 534 * The message resource bundle defines the list of external XML 535 * files that are used to lookup localized strings. 536 * 537 * The default localizedStrings() is a WMessageResourceBundle 538 * object, and this method returns localizedStrings() downcasted to 539 * this type. 540 * 541 * \throws WException when localizedStrings() is not a WMessageResourceBundle 542 * 543 * \sa WString::tr(const char *key) 544 */ 545 WMessageResourceBundle& messageResourceBundle(); 546 #endif // WT_TARGET_JAVA 547 548 /*! \brief Changes the locale. 549 * 550 * The locale is used by the localized strings resource to resolve 551 * localized strings. 552 * 553 * By passing an empty \p locale, the default locale is 554 * chosen. 555 * 556 * When the locale is changed, refresh() is called, which will 557 * resolve the strings of the current user-interface in the new 558 * locale. 559 * 560 * At construction, the locale is copied from the environment 561 * (WEnvironment::locale()), and this is the locale that was 562 * configured by the user in his browser preferences, and passed 563 * using an HTTP request header. 564 * 565 * \sa localizedStrings(), WString::tr() 566 */ 567 void setLocale(const WLocale& locale); 568 569 /*! \brief Returns the current locale. 570 * 571 * \sa setLocale(const WLocale&) 572 */ locale()573 const WLocale& locale() const { return locale_; } 574 575 /*! \brief Refreshes the application. 576 * 577 * This lets the application refresh its data, including strings 578 * from message resource bundles. This is done by propagating 579 * WWidget::refresh() through the widget hierarchy. 580 * 581 * This method is also called when the user hits the refresh (or 582 * reload) button, if this can be caught within the current session. 583 * 584 * \if cpp 585 * 586 * The reload button may only be caught when %Wt is configured so that 587 * reload should not spawn a new session. When URL rewriting is used for 588 * session tracking, this will cause an ugly session ID to be added to the 589 * URL. See \ref config_session for configuring the reload 590 * behavior ("<reload-is-new-session>"). 591 * 592 * \elseif java 593 * 594 * The reload button may only be caught when cookies for session 595 * tracking are configured in the servlet container. 596 * 597 * \endif 598 * 599 * \sa WWidget::refresh() 600 */ 601 virtual void refresh(); 602 603 /*! \brief Binds a top-level widget for a EntryPointType::WidgetSet deployment. 604 * 605 * This method binds a \p widget to an existing element with DOM id 606 * \p domId on the page. The element type should correspond with 607 * the widget type (e.g. it should be a <div> for a 608 * WContainerWidget, or a <table> for a WTable). 609 * 610 * \sa root() 611 * \sa Wt::EntryPointType::WidgetSet 612 */ 613 void bindWidget(std::unique_ptr<WWidget> widget, const std::string& domId); 614 615 /** @name URLs and internal paths 616 */ 617 //!@{ 618 /*! \brief Returns a URL for the current session 619 * 620 * Returns the (relative) URL for this application session 621 * (including the session ID if necessary). The URL includes the 622 * full application path, and is expanded by the browser into a full 623 * URL. 624 * 625 * For example, for an application deployed at \code 626 * http://www.mydomain.com/stuff/app.wt \endcode this method might 627 * return <tt>"/stuff/app.wt?wtd=AbCdEf"</tt>. Additional query 628 * parameters can be appended in the form of 629 * <tt>"¶m1=value¶m2=value"</tt>. 630 * 631 * To obtain a URL that is suitable for bookmarking the current 632 * application state, to be used across sessions, use bookmarkUrl() 633 * instead. 634 * 635 * \sa redirect(), WEnvironment::hostName(), WEnvironment::urlScheme() 636 * \sa bookmarkUrl() 637 */ 638 std::string url(const std::string& internalPath = std::string()) const; 639 640 /*! \brief Makes an absolute URL. 641 * 642 * Returns an absolute URL for a given (relative url) by including 643 * the schema, hostname, and deployment path. 644 * 645 * If \p url is "", then the absolute base URL is returned. This is 646 * the absolute URL at which the application is deployed, up to the 647 * last '/'. 648 * 649 * The default implementation is not complete: it does not handle relative 650 * URL path segments with '..'. It just handles the cases that are necessary for 651 * %Wt. 652 * 653 * This is not used in the library, except when a public URL is 654 * needed, e.g. for inclusion in an email. 655 * 656 * You may want to reimplement this method when the application is 657 * hosted behind a reverse proxy or in general the public URL of the 658 * application cannot be guessed correctly by the application. 659 */ 660 virtual std::string makeAbsoluteUrl(const std::string& url) const; 661 662 /*! \brief "Resolves" a relative URL taking into account internal paths. 663 * 664 * This resolves the relative URL against the base path of the application, 665 * so that it will point to the correct path regardless of the current internal 666 * path, e.g. if the application is deployed at <tt>%http://example.com/one</tt> 667 * and we're at the internal path <tt>/two/</tt>, so that the full URL is 668 * <tt>%http://example.com/one/two/</tt>, the output of the input URL <tt>three</tt> 669 * will point to <tt>%http://example.com/three</tt>, and not 670 * <tt>%http://example.com/one/two/three</tt>. 671 * 672 * If the given url is the empty string, the result will point to the base path 673 * of the application. 674 * 675 * See the table below for more examples. 676 * 677 * <h3>When you would want to use resolveRelativeUrl:</h3> 678 * 679 * Using HTML5 History API or in a plain HTML session (without ugly 680 * internal paths), the internal path is present as a full part of 681 * the URL. This has a consequence that relative URLs, if not dealt 682 * with, would be resolved against the last 'folder' name of the 683 * internal path, rather than against the application deployment 684 * path (which is what you probably want). 685 * 686 * When using a widgetset mode deployment, or when configuring a 687 * baseURL property in the configuration, this method will make an 688 * absolute URL so that the property is fetched from the right 689 * server. 690 * 691 * Otherwise, this method will fixup a relative URL so that it 692 * resolves correctly against the base path of an application. This 693 * does not necessarily mean that the URL is resolved into an 694 * absolute URL. In fact, %Wt will simply prepend a sequence of "../" 695 * path elements to correct for the internal path. When passed an 696 * absolute URL (i.e. starting with '/'), the url is returned 697 * unchanged. 698 * 699 * For URLs passed to the %Wt API (and of which the library knows it 700 * represents a URL) this method is called internally by the 701 * library. But it may be useful for URLs which are set e.g. inside 702 * a WTemplate. 703 * 704 * <h3>Examples</h3> 705 * 706 * Note that whether the deployment path and entry point ends with a slash is significant. 707 * Below are some examples with the 708 * <span style="color:red;">deployment path</span> in <span style="color:red;">red</span> 709 * and the <span style="color:blue;">internal path</span> in <span style="color:blue;">blue</span>. 710 * 711 * <table> 712 * <tr><th>Current full path</th><th>url argument</th><th>Result points to</th></tr> 713 * <tr><td rowspan="4"><tt>%http://example.com</tt><tt style="color:red;">/foo/bar</tt><tt style="color:blue;">/internal/path</tt><br />Deployment path: <tt style="color:red;">/foo/bar</tt> (no slash at the end)<br />Internal path: <tt style="color:blue;">/internal/path</tt></td> 714 * <td><i>(empty string)</i></td><td><tt>%http://example.com/foo/bar</tt></tr> 715 * <tr><td><tt>.</tt></td><td><tt>%http://example.com/foo/</tt></td></tr> 716 * <tr><td><tt>./</tt></td><td><tt>%http://example.com/foo/</tt></td></tr> 717 * <tr><td><tt>../</tt></td><td><tt>%http://example.com/</tt></td></tr> 718 * <tr><td rowspan="4"><tt>%http://example.com</tt><tt style="color:red;">/foo/bar</tt><tt style="color:magenta;font-weight:bold;">/</tt><tt style="color:blue;">internal/path</tt><br />Deployment path: <tt style="color:red;">/foo/bar/</tt> (with slash at the end)<br />Internal path: <tt style="color:blue;">/internal/path</tt><br />Note that the slash between the deployment path and the internal path is shared</td> 719 * <td><i>(empty string)</i></td><td><tt>%http://example.com/foo/bar/</tt></tr> 720 * <tr><td><tt>.</tt></td><td><tt>%http://example.com/foo/bar/</tt></td></tr> 721 * <tr><td><tt>./</tt></td><td><tt>%http://example.com/foo/bar/</tt></td></tr> 722 * <tr><td><tt>../</tt></td><td><tt>%http://example.com/foo/</tt></td></tr> 723 * </table> 724 */ 725 std::string resolveRelativeUrl(const std::string& url) const; 726 727 /*! \brief Returns a bookmarkable URL for the current internal path. 728 * 729 * Is equivalent to <tt>bookmarkUrl(internalPath())</tt>, see 730 * bookmarkUrl(const std::string&) const. 731 * 732 * To obtain a URL that is refers to the current session of the 733 * application, use url() instead. 734 * 735 * \sa url(), bookmarkUrl(const std::string&) const 736 */ 737 std::string bookmarkUrl() const; 738 739 /*! \brief Returns a bookmarkable URL for a given internal path. 740 * 741 * Returns the (relative) URL for this application that includes the 742 * internal path \p internalPath, usable across sessions. 743 * 744 * The returned URL concatenates the internal path to the application 745 * base URL, and when no JavaScript is available and URL rewriting is used 746 * for session-tracking, a session Id is appended to reuse an existing 747 * session if available. 748 * 749 * \if cpp 750 * See also \ref config_session for configuring the session-tracking 751 * method. 752 * 753 * For the built-in httpd, when the application is deployed at a folder 754 * (ending with '/'), only an exact matching path is routed to 755 * the application (this can be changed since Wt 3.1.9, see 756 * \ref wthttpd ), making clean URLs impossible. Returned URLs then 757 * include a <tt>"?_="</tt> encoding for the internal path. 758 * \endif 759 * 760 * You can use bookmarkUrl() as the destination for a WAnchor, and 761 * listen to a click event is attached to a slot that switches to 762 * the internal path \p internalPath (see 763 * WAnchor::setRefInternalPath()). In this way, an anchor can be 764 * used to switch between internal paths within an application 765 * regardless of the situation (browser with or without Ajax 766 * support, or a web spider bot), but still generates suitable URLs 767 * across sessions, which can be used for bookmarking, opening in a 768 * new window/tab, or indexing. 769 * 770 * To obtain a URL that refers to the current session of the 771 * application, use url() instead. 772 * 773 * \sa url(), bookmarkUrl() 774 * 775 * \if cpp 776 * \note the \p internalPath should be CharEncoding::UTF8 encoded (we may fix the API 777 * to use WString in the future). 778 * \endif 779 */ 780 std::string bookmarkUrl(const std::string& internalPath) const; 781 782 /*! \brief Changes the internal path. 783 * 784 * A %Wt application may manage multiple virtual paths. The virtual 785 * path is appended to the application URL. Depending on the 786 * situation, the path is directly appended to the application URL 787 * or it is appended using a name anchor (#). 788 * 789 * For example, for an application deployed at: 790 * \code 791 * http://www.mydomain.com/stuff/app.wt 792 * \endcode 793 * for which an \p internalPath <tt>"/project/z3cbc/details/"</tt> is 794 * set, the two forms for the application URL are: 795 * <ul> 796 * <li> in an AJAX session (HTML5): 797 * \code 798 * http://www.mydomain.com/stuff/app.wt/project/z3cbc/details/ 799 * \endcode 800 * </li><li> in an AJAX session (HTML4): 801 * \code 802 * http://www.mydomain.com/stuff/app.wt#/project/z3cbc/details/ 803 * \endcode 804 * </li><li> 805 * in a plain HTML session: 806 * \code 807 * http://www.mydomain.com/stuff/app.wt/project/z3cbc/details/ 808 * \endcode 809 * </li></ul> 810 * 811 * Note, since %Wt 3.1.9, the actual form of the URL no longer 812 * affects relative URL resolution, since now %Wt includes an HTML 813 * <tt>meta base</tt> tag which points to the deployment path, 814 * regardless of the current internal path. This does break 815 * deployments behind a reverse proxy which changes paths. 816 * 817 * \if cpp 818 * For the built-in httpd, when the application is deployed 819 * at a folder (ending with '/'), only an exact matching path is 820 * routed to the application (this can be changed since Wt 3.1.9, 821 * see \ref wthttpd ), making clean URLs impossible. Returned 822 * URLs then include a <tt>"?_="</tt> encoding for the internal 823 * path: 824 * 825 * \code 826 * http://www.mydomain.com/stuff/?_=/project/z3cbc/details/ 827 * \endcode 828 * \endif 829 * 830 * When the internal path is changed, an entry is added to the 831 * browser history. When the user navigates back and forward through 832 * this history (using the browser back/forward buttons), an 833 * internalPathChanged() event is emitted. You should listen to this 834 * signal to switch the application to the corresponding state. When 835 * \p emitChange is \c true, this signal is also emitted by setting 836 * the path (but only if the path is actually changed). 837 * 838 * A url that includes the internal path may be obtained using 839 * bookmarkUrl(). 840 * 841 * The \p internalPath must start with a '/'. In this way, you 842 * can still use normal anchors in your HTML. Internal path changes 843 * initiated in the browser to paths that do not start with a '/' 844 * are ignored. 845 * 846 * The \p emitChange parameter determines whether calling this 847 * method causes the internalPathChanged() signal to be emitted. 848 * 849 * \sa bookmarkUrl(), internalPath(), internalPathChanged() 850 * 851 * \if cpp 852 * \note the \p path should be CharEncoding::UTF8 encoded (we may fix the API 853 * to use WString in the future). 854 * \endif 855 */ 856 void setInternalPath(const std::string& path, bool emitChange = false); 857 858 /*! \brief Sets whether an internal path is valid by default. 859 * 860 * This configures how you treat (invalid) internal paths. If an 861 * internal path is treated valid by default then you need to call 862 * setInternalPath(false) for an invalid path. If on the other hand 863 * you treat an internal path as invalid by default, then you need 864 * to call setInternalPath(true) for a valid path. 865 * 866 * A user which opens an invalid internal path will receive a HTTP 867 * 404-Not Found response code (if sent an HTML response). 868 * 869 * The default value is \c true. 870 */ 871 void setInternalPathDefaultValid(bool valid); 872 873 /*! \brief Returns whether an internal path is valid by default. 874 * 875 * \sa setInternalPathDefaultValid() 876 */ internalPathDefaultValid()877 bool internalPathDefaultValid() const { return internalPathDefaultValid_; } 878 879 /*! \brief Sets whether the current internal path is valid. 880 * 881 * You can use this function in response to an internal path change 882 * event (or at application startup) to indicate whether the new (or 883 * initial) internal path is valid. This has only an effect on plain 884 * HTML sessions, or on the first response in an application 885 * deployed with progressive bootstrap settings, as this generates 886 * then a 404 Not-Found response. 887 * 888 * \sa internalPathChanged(), setInternalPathDefaultValid() 889 */ 890 void setInternalPathValid(bool valid); 891 892 /*! \brief Returns whether the current internal path is valid. 893 * 894 * \sa setInternalPathValid() 895 */ internalPathValid()896 bool internalPathValid() const { return internalPathValid_; } 897 898 /*! \brief Returns the current internal path. 899 * 900 * When the application is just created, this is equal to 901 * WEnvironment::internalPath(). 902 * 903 * \sa setInternalPath(), internalPathNextPart(), internalPathMatches() 904 * 905 * \if cpp 906 * \note the \p returned path is CharEncoding::UTF8 (we may fix the API 907 * to use WString in the future). 908 * \endif 909 */ 910 std::string internalPath() const; 911 912 /*! \brief Returns a part of the current internal path. 913 * 914 * This is a convenience method which returns the next \p folder 915 * in the internal path, after the given \p path. 916 * 917 * For example, when the current internal path is 918 * <tt>"/project/z3cbc/details"</tt>, this method returns 919 * <tt>"details"</tt> when called with <tt>"/project/z3cbc/"</tt> as 920 * \p path argument. 921 * 922 * The \p path must start with a '/', and internalPathMatches() 923 * should evaluate to \c true for the given \p path. If not, 924 * an empty string is returned and an error message is logged. 925 * 926 * \sa internalPath(), internalPathChanged() 927 * 928 * \if cpp 929 * \note the \p internal path is CharEncoding::UTF8 encoded (we may fix the API 930 * to use WString in the future). 931 * \endif 932 */ 933 std::string internalPathNextPart(const std::string& path) const; 934 935 std::string internalSubPath(const std::string& path) const; 936 937 /*! \brief Checks if the internal path matches a given path. 938 * 939 * Returns whether the current internalPath() starts with 940 * \p path (or is equal to \p path). You will typically use 941 * this method within a slot conneted to the internalPathChanged() 942 * signal, to check that an internal path change affects the 943 * widget. It may also be useful before changing \p path using 944 * setInternalPath() if you do not intend to remove sub paths when 945 * the current internal path already matches \p path. 946 * 947 * The \p path must start with a '/'. 948 * 949 * \sa setInternalPath(), internalPath() 950 * 951 * \if cpp 952 * \note the \p internal path is CharEncoding::UTF8 encoded (we may fix the API 953 * to use WString in the future). 954 * \endif 955 */ 956 bool internalPathMatches(const std::string& path) const; 957 958 /*! \brief %Signal which indicates that the user changes the internal path. 959 * 960 * This signal indicates a change to the internal path, which is 961 * usually triggered by the user using the browser back/forward 962 * buttons. 963 * 964 * The argument contains the new internal path. 965 * 966 * \sa setInternalPath() 967 * 968 * \if cpp 969 * \note the \p internal path is CharEncoding::UTF8 encoded (we may fix the API 970 * to use WString in the future). 971 * \endif 972 */ 973 Signal<std::string>& internalPathChanged(); 974 975 /*! \brief %Signal which indicates that an invalid internal path is navigated. 976 */ internalPathInvalid()977 Signal<std::string>& internalPathInvalid() { return internalPathInvalid_; } 978 979 /*! \brief Redirects the application to another location. 980 * 981 * The client will be redirected to a new location identified by \p 982 * url. Use this in conjunction with quit() if you want the 983 * application to be terminated as well. 984 * 985 * Calling %redirect() does not imply %quit() since it may be useful 986 * to switch between a non-secure and secure (SSL) transport 987 * connection. 988 */ 989 void redirect(const std::string& url); 990 //!@} 991 992 /*! \brief Returns the URL at which the resources are deployed. 993 * 994 * Returns resolveRelativeUrl(relativeResourcesUrl()) 995 */ 996 static std::string resourcesUrl(); 997 998 /*! \brief Returns the URL at which the resources are deployed. 999 * 1000 * \if cpp 1001 * This returns the value of the 'resources' property set in the 1002 * configuration file, and may thus be a URL relative to the deployment 1003 * path. 1004 * \endif 1005 * 1006 * \sa resolveRelativeUrl() 1007 */ 1008 static std::string relativeResourcesUrl(); 1009 1010 #ifndef WT_TARGET_JAVA 1011 /*! \brief Returns the appRoot special property 1012 * 1013 * This returns the "appRoot" property, with a trailing slash added 1014 * to the end if it was not yet present. 1015 * 1016 * The property "appRoot" was introduced as a generalization of the 1017 * working directory for the location of files that do not need to 1018 * be served over http to the client, but are required by the 1019 * program to run properly. Typically, these are message resource 1020 * bundles (xml), CSV files, database files (e.g. SQLite files for 1021 * Wt::Dbo), ... 1022 * 1023 * Some connectors do not allow you to control what the current 1024 * working directory (CWD) is set to (fcgi, isapi). Instead of 1025 * referring to files assuming a sensible CWD, it is therefore 1026 * better to refer to them relative to the application root. 1027 * 1028 * The appRoot property is special in the sense that it can be set 1029 * implicitly by the connector (see the connector documentation for 1030 * more info). If it was not set by the connector, it can be set as 1031 * a normal property in the configuration file (the default 1032 * wt_config.xml describes how to set properties). If the property 1033 * is not set at all, it is assumed that the appRoot is CWD and this 1034 * function will return an empty string. 1035 * 1036 * \if cpp 1037 * Usage example: 1038 * \code 1039 * messageResourceBundle().use(appRoot() + "text"); 1040 * messageResourceBundle().use(appRoot() + "charts"); 1041 * 1042 * auto sqlite3_ = std::make_unique<Wt::Dbo::backend::Sqlite3>(appRoot() + "planner.db"); 1043 * \endcode 1044 * \endif 1045 * 1046 * \sa WServer::appRoot(), docRoot() 1047 */ 1048 static std::string appRoot(); 1049 1050 /*! \brief Returns the server document root. 1051 * 1052 * This returns the filesystem path that corresponds to the document root 1053 * of the webserver. 1054 * 1055 * \note This does not work reliably for complex webserver configurations 1056 * (e.g. using FastCGI with Apache and rewrite rules). See also the 1057 * <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=26052"> 1058 * discussion here</a>. 1059 * 1060 * \sa appRoot() 1061 */ 1062 std::string docRoot() const; 1063 1064 /*! \brief Sets a client-side connection monitor 1065 * 1066 * This can be used to be notified, in the browser, of changes in 1067 * connection state between the browser and the server. The passed 1068 * \p jsObject should be an object that has the following prototype: 1069 * \code 1070 * { 1071 * onChange: function(type, oldValue, newValue) { ... } 1072 * } 1073 * \endcode 1074 * 1075 * The 'onChange' function will be called on an connection status change 1076 * event. The following types are defined: 1077 * - "connectionStatus": 0 = disconnected, 1 = connected 1078 * - "websocket": true = websocket is used, false = websocket is not used 1079 * 1080 * The current state is also stored in a 'status' object inside the 1081 * connection monitor. 1082 * 1083 * Example usage: 1084 * \code 1085 * app.setConnectionMonitor("{ onChange: function(type, ov, nv) { console.log(type, ov, nv); } }"); 1086 * \endcode 1087 */ 1088 void setConnectionMonitor(const std::string& jsObject); 1089 1090 #else 1091 static std::string appRoot(); 1092 #endif // WT_TARGET_JAVA 1093 1094 /*! \brief Returns the unique identifier for the current session. 1095 * 1096 * The session id is a string that uniquely identifies the current session. 1097 * Note that the actual contents has no particular meaning and client 1098 * applications should in no way try to interpret its value. 1099 */ 1100 std::string sessionId() const; 1101 1102 #ifndef WT_TARGET_JAVA 1103 /*! \brief Changes the session id. 1104 * 1105 * To mitigate session ID fixation attacks, you should use this 1106 * method to change the session ID to a new random value after a 1107 * user has authenticated himself. 1108 * 1109 * \sa sessionId() 1110 */ 1111 void changeSessionId(); 1112 #endif // WT_TARGET_JAVA 1113 session()1114 WebSession *session() const { return session_; } 1115 1116 /** @name Manipulation outside the main event loop 1117 */ 1118 //!@{ 1119 /*! \brief Enables server-initiated updates. 1120 * 1121 * By default, updates to the user interface are possible only at 1122 * startup, during any event (in a slot), or at regular time points 1123 * using WTimer. This is the normal %Wt event loop. 1124 * 1125 * In some cases, one may want to modify the user interface from a 1126 * second thread, outside the event loop. While this may be worked 1127 * around by the WTimer, in some cases, there are bandwidth and 1128 * processing overheads associated which may be unnecessary, and 1129 * which create a trade-off with time resolution of the updates. 1130 * 1131 * When \p enabled is \c true, this enables "server push" (what is 1132 * called 'comet' in AJAX terminology). Widgets may then be 1133 * modified, created or deleted outside of the event loop (e.g. in 1134 * response to execution of another thread), and these changes are 1135 * propagated by calling triggerUpdate(). 1136 * 1137 * \if cpp 1138 * There are two ways for safely manipulating a session's UI, with 1139 * respect to thread-safety and application life-time (the library 1140 * can decide to terminate an application if it lost connectivity 1141 * with the browser). 1142 * 1143 * <h3>WServer::post()</h3> 1144 * 1145 * The easiest and less error-prone solution is to post an event, 1146 * represented by a function/method call, to a session using 1147 * WServer::post(). 1148 * 1149 * The method is non-blocking: it returns immediately, avoiding 1150 * dead-lock scenarios. The function is called from within a thread 1151 * of the server's thread pool, and not if the session has been or 1152 * is being terminated. The function is called in the context of the 1153 * targeted application session, and with exclusive access to the 1154 * session. 1155 * 1156 * <h3>WApplication::UpdateLock</h3> 1157 * 1158 * A more direct approach is to grab the application's update lock and 1159 * manipulate the application's state directly from another thread. 1160 * 1161 * At any time, the application may be deleted (e.g. because of a 1162 * time out or because the user closes the application window). You 1163 * should thus make sure you do no longer reference an application 1164 * after it has been deleted. When %Wt decides to delete an 1165 * application, it first runs WApplication::finalize() and then 1166 * invokes the destructor. While doing this, any other thread trying 1167 * to grab the update lock will unblock, but the lock will return \c 1168 * false. You should therefore always check whether the lock is 1169 * valid. 1170 * 1171 * \elseif java 1172 * 1173 * Note that you need to grab the application's update lock to avoid 1174 * concurrency problems, whenever you modify the application's state 1175 * from another thread. 1176 * 1177 * \endif 1178 * 1179 * An example of how to modify the widget tree outside the event loop 1180 * and propagate changes is: 1181 * \if cpp 1182 * \code 1183 * // You need to have a reference to the application whose state 1184 * // you are about to manipulate. 1185 * // You should prevent the application from being deleted somehow, 1186 * // before you could grab the application lock. 1187 * Wt::WApplication *app = ...; 1188 * 1189 * { 1190 * // Grab the application lock. It is a scoped lock. 1191 * Wt::WApplication::UpdateLock lock(app); 1192 * 1193 * if (lock) { 1194 * // We now have exclusive access to the application: we can safely modify the widget tree for example. 1195 * app->root()->addWidget(std::make_unique<Wt::WText>("Something happened!")); 1196 * 1197 * // Push the changes to the browser 1198 * app->triggerUpdate(); 1199 * } 1200 * } 1201 * \endcode 1202 * \elseif java 1203 * \code 1204 * // You need to have a reference to the application whose state 1205 * // you are about to manipulate. 1206 * WApplication app = ...; 1207 * 1208 * // Grab the application lock 1209 * WApplication.UpdateLock lock = app.getUpdateLock(); 1210 * 1211 * try { 1212 * // We now have exclusive access to the application: 1213 * // we can safely modify the widget tree for example. 1214 * app.getRoot().addWidget(new WText("Something happened!")); 1215 * 1216 * // Push the changes to the browser 1217 * app.triggerUpdate(); 1218 * } finally { 1219 * lock.release(); 1220 * } 1221 * \endcode 1222 * \endif 1223 * 1224 * \if java 1225 * This works only if your servlet container supports the Servlet 3.0 1226 * API. If you try to invoke this function on a servlet container with 1227 * no such support, an exception will be thrown. 1228 * \endif 1229 * 1230 * \note This works only if JavaScript is available on the client. 1231 * 1232 * \sa triggerUpdate() 1233 */ 1234 void enableUpdates(bool enabled = true); 1235 1236 /*! \brief Returns whether server-initiated updates are enabled. 1237 * 1238 * \sa enableUpdates() 1239 */ updatesEnabled()1240 bool updatesEnabled() const { return serverPush_ > 0; } 1241 1242 /*! \brief Propagates server-initiated updates. 1243 * 1244 * When the lock to the application is released, changes will 1245 * propagate to the user interface. This call only has an effect 1246 * after updates have been enabled from within the normal event loop 1247 * using enableUpdates(). 1248 * 1249 * This is typically used only outside of the main event loop, 1250 * e.g. from another thread or from within a method posted to an 1251 * application using WServer::post(), since changes always propagate 1252 * within the event loop at the end of the event. 1253 * 1254 * The update is not immediate, and thus changes that happen after this 1255 * call will equally be pushed to the client. 1256 * 1257 * \sa enableUpdates() 1258 */ 1259 void triggerUpdate(); 1260 1261 #ifndef WT_TARGET_JAVA 1262 /*! \brief A RAII lock for manipulating and updating the 1263 * application and its widgets outside of the event loop. 1264 * 1265 * You can use this lock to manipulate widgets outside of the event 1266 * loop. Inside the event loop (including events posted using 1267 * WServer::post()), this lock is already held by the library itself. 1268 * 1269 * The lock is recursive, so trying to take a lock, while already 1270 * holding a lock, will not block. 1271 */ 1272 #else 1273 /*! \brief A synchronization lock for manipulating and updating the 1274 * application and its widgets outside of the event loop. 1275 * 1276 * You need to take this lock only when you want to manipulate 1277 * widgets outside of the event loop. LabelOption::Inside the event loop, this 1278 * lock is already held by the library itself. 1279 * 1280 * \sa getUpdateLock() 1281 */ 1282 #endif // WT_TARGET_JAVA 1283 class WT_API UpdateLock 1284 #ifdef WT_TARGET_JAVA 1285 : public AutoCloseable 1286 #endif // WT_TARGET_JAVA 1287 { 1288 public: 1289 #ifndef WT_TARGET_JAVA 1290 /*! \brief Creates and locks the given application. 1291 * 1292 * The lock guarantees exclusive access to modify the 1293 * application's state. 1294 * 1295 * You should also consider WServer::post() for lock-free 1296 * communication between different application sessions. 1297 * 1298 * As soon as the library decides to destroy the application, the 1299 * lock will no longer succeed in taking the application lock. You 1300 * can need to detect this by checking that after the lock is taken, 1301 * the lock is taken: 1302 * \code 1303 * WApplication::UpdateLock lock(app); 1304 * if (lock) { 1305 * // exclusive access to app state 1306 * } 1307 * \endcode 1308 */ 1309 UpdateLock(WApplication *app); 1310 1311 /*! \brief Tests whether the update lock was succesfully taken. 1312 * 1313 * This may return \c false when the library has already decided 1314 * to destroy the session (but before your application 1315 * finalizer/destructor has run to notify helper threads that the 1316 * application is destroyed). 1317 */ 1318 explicit operator bool() const { return ok_; } 1319 1320 /*! \brief Releases the lock. 1321 */ 1322 ~UpdateLock(); 1323 1324 #else 1325 /*! \brief Releases the lock. 1326 */ 1327 void release(); 1328 #endif 1329 1330 #ifdef WT_TARGET_JAVA 1331 /*! \brief Releases the lock. 1332 * 1333 * Calls release() 1334 * 1335 * Implemented in order to support the AutoCloseable interface. 1336 */ 1337 virtual void close(); 1338 #endif // WT_TARGET_JAVA 1339 1340 private: 1341 #ifdef WT_TARGET_JAVA 1342 UpdateLock(WApplication *app); 1343 bool createdHandler_; 1344 #endif // WT_TARGET_JAVA 1345 1346 #ifndef WT_TARGET_JAVA 1347 mutable std::unique_ptr<UpdateLockImpl> impl_; 1348 bool ok_; 1349 #endif // !WT_TARGET_JAVA 1350 1351 friend class WApplication; 1352 }; 1353 1354 #ifdef WT_TARGET_JAVA 1355 /*! \brief Grabs and returns the lock for manipulating widgets outside 1356 * the event loop. 1357 * 1358 * You need to keep this lock in scope while manipulating widgets 1359 * outside of the event loop. In normal cases, inside the %Wt event 1360 * loop, you do not need to care about it. 1361 * 1362 * \sa enableUpdates(), triggerUpdate() 1363 */ 1364 UpdateLock getUpdateLock(); 1365 #endif // WT_TARGET_JAVA 1366 1367 /*! \brief Attach an auxiliary thread to this application. 1368 * 1369 * In a multi-threaded environment, WApplication::instance() uses 1370 * thread-local data to retrieve the application object that 1371 * corresponds to the session currently being handled by the 1372 * thread. This is set automatically by the library whenever an 1373 * event is delivered to the application, or when you use the 1374 * UpdateLock to modify the application from an auxiliary thread 1375 * outside the normal event loop. 1376 * 1377 * When you want to manipulate the widget tree inside the main event 1378 * loop, but from within an auxiliary thread, then you cannot use 1379 * the UpdateLock since this will create an immediate dead 1380 * lock. Instead, you may attach the auxiliary thread to the 1381 * application, by calling this method from the auxiliary thread, 1382 * and in this way you can modify the application from within that 1383 * thread without needing the update lock. 1384 * 1385 * Calling attachThread() with \p attach = \c false, detaches the 1386 * current thread. 1387 */ 1388 void attachThread(bool attach = true); 1389 //!@} 1390 1391 /** @name Invoking JavaScript or including scripts 1392 */ 1393 //!@{ 1394 /*! \brief Executes some JavaScript code. 1395 * 1396 * This method may be used to call some custom \p javaScript code as 1397 * part of an event response. 1398 * 1399 * This function does not wait until the JavaScript is run, but 1400 * returns immediately. The JavaScript will be run after the normal 1401 * event handling, unless \p afterLoaded is set to \c false. 1402 * 1403 * In most situations, it's more robust to use 1404 * WWidget::doJavaScript() however. 1405 * 1406 * \sa WWidget::doJavaScript(), declareJavaScriptFunction() 1407 */ 1408 void doJavaScript(const std::string& javascript, bool afterLoaded = true); 1409 1410 /*! \brief Adds JavaScript statements that should be run continuously. 1411 * 1412 * This is an internal method. 1413 * 1414 * It is used by for example layout managers to adjust the layout 1415 * whenever the DOM tree is manipulated. 1416 * 1417 * \sa doJavaScript() 1418 */ 1419 void addAutoJavaScript(const std::string& javascript); 1420 1421 /*! \brief Declares an application-wide JavaScript function. 1422 * 1423 * The function is stored in WApplication::javaScriptClass(). 1424 * 1425 * The next code snippet declares and invokes function foo: 1426 * \if cpp 1427 * \code 1428 * app->declareJavaScriptFunction("foo", 1429 * "function(id) { ... }"); 1430 * ... 1431 * std::string id("myId"); 1432 * app->doJavaScript(app->javaScriptClass() + ".foo('" + id + "');"); 1433 * \endcode 1434 * \endif 1435 */ 1436 void declareJavaScriptFunction(const std::string& name, 1437 const std::string& function); 1438 1439 /*! \brief Loads a JavaScript library. 1440 * 1441 * Loads a JavaScript library located at the URL \p url. %Wt keeps 1442 * track of libraries (with the same URL) that already have been 1443 * loaded, and will load a library only once. In addition, you may 1444 * provide a \p symbol which if already defined will also indicate 1445 * that the library was already loaded (possibly outside of %Wt when 1446 * in EntryPointType::WidgetSet mode). 1447 * 1448 * This method returns \c true only when the library is loaded 1449 * for the first time. 1450 * 1451 * JavaScript libraries may be loaded at any point in time. Any 1452 * JavaScript code is deferred until the library is loaded, except 1453 * for JavaScript that was defined to load before, passing \c false 1454 * as second parameter to doJavaScript(). 1455 * 1456 * Although %Wt includes an off-the-shelf JQuery version (which can 1457 * also be used by your own JavaScript code), you can override the 1458 * one used by %Wt and load another JQuery version instead, but this 1459 * needs to be done using requireJQuery(). 1460 */ 1461 bool require(const std::string& url, 1462 const std::string& symbol = std::string()); 1463 1464 /*! \brief Loads a custom JQuery library. 1465 * 1466 * %Wt ships with a rather old version of JQuery (1.4.1) which is 1467 * sufficient for its needs and is many times smaller than more recent 1468 * JQuery releases (about 50% smaller). 1469 * 1470 * Using this function, you can replace Wt's JQuery version with another 1471 * version of JQuery. 1472 * 1473 * \code 1474 * requireJQuery("jquery/jquery-1.7.2.min.js"); 1475 * \endcode 1476 */ 1477 bool requireJQuery(const std::string& url); 1478 1479 /*! \brief Returns whether a custom JQuery library is used. 1480 * 1481 * \sa requireJQuery(const std::string& url) 1482 */ customJQuery()1483 bool customJQuery() const { return customJQuery_; } 1484 1485 /*! \brief Sets the name of the application JavaScript class. 1486 * 1487 * This should be called right after construction of the application, and 1488 * changing the JavaScript class is only supported for EntryPointType::WidgetSet mode 1489 * applications. The \p className should be a valid JavaScript identifier, and 1490 * should also be unique in a single page. 1491 */ 1492 void setJavaScriptClass(const std::string& className); 1493 1494 /*! \brief Returns the name of the application JavaScript class. 1495 * 1496 * This JavaScript class encapsulates all JavaScript methods 1497 * specific to this application instance. The method is foreseen to 1498 * allow multiple applications to run simultaneously on the same 1499 * page in Wt::WidgtSet mode, without interfering. 1500 */ javaScriptClass()1501 std::string javaScriptClass() { return javaScriptClass_; } 1502 //!@} 1503 1504 /*! \brief Processes UI events. 1505 * 1506 * You may call this method during a long operation to: 1507 * - propagate widget changes to the client. 1508 * - process UI events. 1509 * 1510 * This method starts a recursive event loop, blocking the current 1511 * thread, and resumes when all pending user interface events have been 1512 * processed. 1513 * 1514 * Because a thread is blocked, this may affect your application 1515 * scalability. 1516 */ 1517 void processEvents(); 1518 1519 /*! \brief Blocks the thread, waiting for an UI event. 1520 * 1521 * This function is used by functions like WDialog::exec() or 1522 * WPopupMenu::exec(), to block the current thread waiting for a new 1523 * event. 1524 * 1525 * This requires that at least one additional thread is available to 1526 * process incoming requests, and is not scalable when working with 1527 * a fixed size thread pools. 1528 */ 1529 virtual void waitForEvent(); 1530 1531 #ifndef WT_TARGET_JAVA 1532 /*! \brief Reads a configuration property. 1533 * 1534 * Tries to read a configured value for the property 1535 * \p name. The method returns whether a value is defined for 1536 * the property, and sets it to \p value. 1537 * 1538 * \sa WServer::readConfigurationProperty() 1539 */ 1540 static bool readConfigurationProperty(const std::string& name, 1541 std::string& value); 1542 #else 1543 /*! \brief Reads a configuration property. 1544 * 1545 * Tries to read a configured value for the property 1546 * \p name. If no value was configured, the default \p value 1547 * is returned. 1548 */ 1549 static std::string *readConfigurationProperty(const std::string& name, 1550 const std::string& value); 1551 #endif // WT_TARGET_JAVA 1552 1553 /* 1554 * The DOM root object. This contains not only the application root but 1555 * also other invisible objects (timers, dialog covers, ...). 1556 */ 1557 WWebWidget *domRoot() const; 1558 1559 /* 1560 * A phony DOM root object, used to logically contain all widgets bound 1561 * in widgetset mode. 1562 */ domRoot2()1563 WContainerWidget *domRoot2() const { return domRoot2_.get(); } 1564 1565 /* 1566 * Encode an object to a string, to make it referencable from JavaScript. 1567 * Currently only used to encode the drag object in drag & drop. 1568 * 1569 * FIXME: provide a way to remove the encoding! 1570 * 1571 * \see decodeObject() 1572 */ 1573 std::string encodeObject(WObject *object); 1574 1575 /* 1576 * Decode an object. 1577 * 1578 * \see encodeObject() 1579 */ 1580 WObject *decodeObject(const std::string& objectId) const; 1581 1582 #ifndef WT_TARGET_JAVA 1583 /*! \brief Initializes the application, post-construction. 1584 * 1585 * This method is invoked by the %Wt library after construction of a 1586 * new application. You may reimplement this method to do additional 1587 * initialization that is not possible from the constructor 1588 * (e.g. which uses virtual methods). 1589 */ 1590 virtual void initialize(); 1591 1592 /*! \brief Finalizes the application, pre-destruction. 1593 * 1594 * This method is invoked by the %Wt library before destruction of a 1595 * new application. You may reimplement this method to do additional 1596 * finalization that is not possible from the destructor (e.g. which 1597 * uses virtual methods). 1598 */ 1599 virtual void finalize(); 1600 #else 1601 /*! \brief Destroys the application session. 1602 * 1603 * The application is destroyed when the session is invalidated. You 1604 * should put here any logic which is needed to cleanup the 1605 * application session. 1606 * 1607 * The default implementation does nothing. 1608 */ 1609 virtual void destroy(); 1610 #endif //WT_TARGET_JAVA 1611 1612 /*! \brief Changes the threshold for two-phase rendering. 1613 * 1614 * This changes the threshold for the \p size of a JavaScript 1615 * response (in bytes) to render invisible changes in one go. If the 1616 * bandwidth for rendering the invisible changes exceed the 1617 * threshold, they will be fetched in a second communication, after 1618 * the visible changes have been rendered. 1619 * 1620 * The value is a trade-off: setting it smaller will always use 1621 * two-phase rendering, increasing the total render time but 1622 * reducing the latency for the visible changes. Setting it too 1623 * large will increase the latency to render the visible changes, 1624 * since first also all invisible changes need to be computed and 1625 * received in the browser. 1626 * 1627 * \if cpp 1628 * The initial value is read from the configuration file, see \ref 1629 * config_general. 1630 * \endif 1631 */ 1632 void setTwoPhaseRenderingThreshold(int size); 1633 1634 /*! \brief Sets a new cookie. 1635 * 1636 * Use cookies to transfer information across different sessions 1637 * (e.g. a user name). In a subsequent session you will be able to 1638 * read this cookie using WEnvironment::getCookie(). You cannot use 1639 * a cookie to store information in the current session. 1640 * 1641 * The name must be a valid cookie name (of type 'token': no special 1642 * characters or separators, see RFC2616 page 16). The value may be 1643 * anything. Specify the maximum age (in seconds) after which the 1644 * client must discard the cookie. To delete a cookie, use a value of '0'. 1645 * 1646 * By default the cookie only applies to the application deployment 1647 * path (WEnvironment::deploymentPath()) in the current domain. To 1648 * set a proper value for domain, see also RFC2109. 1649 * 1650 * \if cpp 1651 * \note %Wt provides session tracking automatically, and may be configured 1652 * to use a cookie for this. You only need to use cookies yourself 1653 * if you want to remember some information (like a logged in identity) 1654 * <i>across sessions</i>. 1655 * \endif 1656 * 1657 * \sa WEnvironment::supportsCookies(), WEnvironment::getCookie() 1658 */ 1659 void setCookie(const std::string& name, const std::string& value, 1660 int maxAge, const std::string& domain = "", 1661 const std::string& path = "", bool secure = false); 1662 1663 #ifndef WT_TARGET_JAVA 1664 void setCookie(const std::string& name, const std::string& value, 1665 const WDateTime& expires, const std::string& domain = "", 1666 const std::string& path = "", bool secure = false); 1667 #endif // WT_TARGET_JAVA 1668 1669 /*! \brief Removes a cookie. 1670 * 1671 * \sa setCookie() 1672 */ 1673 void removeCookie(const std::string& name, const std::string& domain = "", 1674 const std::string& path = ""); 1675 1676 /*! \brief Adds an HTML meta link. 1677 * 1678 * When a link was previously set for the same \p href, its contents 1679 * are replaced. 1680 * When an empty string is used for the arguments \p media, \p hreflang, 1681 * \p type or \p sizes, they will be ignored. 1682 * 1683 * \sa removeMetaLink() 1684 */ 1685 void addMetaLink(const std::string &href, 1686 const std::string &rel, 1687 const std::string &media, 1688 const std::string &hreflang, 1689 const std::string &type, 1690 const std::string &sizes, 1691 bool disabled); 1692 1693 /*! \brief Removes the HTML meta link. 1694 * 1695 * \sa addMetaLink() 1696 */ 1697 void removeMetaLink(const std::string &href); 1698 1699 /*! \brief Adds a "name" HTML meta header. 1700 * 1701 * \sa addMetaHeader(MetaHeaderType, const std::string&, const WString&, const std::string&) 1702 */ 1703 void addMetaHeader(const std::string& name, const WString& content, 1704 const std::string& lang = ""); 1705 1706 /*! \brief Adds an HTML meta header. 1707 * 1708 * This method sets either a "name" meta headers, which configures a 1709 * document property, or a "http-equiv" meta headers, which defines 1710 * a HTTP headers (but these latter headers are being deprecated). 1711 * 1712 * A meta header can however only be added in the following situations: 1713 * 1714 * - when a plain HTML session is used (including when the user agent is a 1715 * bot), you can add meta headers at any time. 1716 * - or, when \ref progressive_bootstrap "progressive bootstrap" is 1717 * used, you can set meta headers for any type of session, from 1718 * within the application constructor (which corresponds to the 1719 * initial request). 1720 * - but never for a Wt::EntryPointType::WidgetSet mode application since then the 1721 * application is hosted within a foreign HTML page. 1722 * 1723 * These situations coincide with WEnvironment::ajax() returning \c 1724 * false (see environment()). The reason that it other cases the 1725 * HTML page has already been rendered, and will not be rerendered 1726 * since all updates are done dynamically. 1727 * 1728 * As an alternative, you can use the <meta-headers> 1729 * configuration property in the configuration file, which will be 1730 * applied in all circumstances. 1731 * 1732 * \sa removeMetaHeader() 1733 */ 1734 void addMetaHeader(MetaHeaderType type, const std::string& name, 1735 const WString& content, const std::string& lang = ""); 1736 1737 /*! \brief Returns a meta header value. 1738 * 1739 * \sa addMetaHeader() 1740 */ 1741 WString metaHeader(MetaHeaderType type, const std::string& name) const; 1742 1743 /*! \brief Removes one or all meta headers. 1744 * 1745 * Removes the meta header with given type and name (if it is present). 1746 * If name is empty, all meta headers of the given type are removed. 1747 * 1748 * \sa addMetaHeader() 1749 */ 1750 void removeMetaHeader(MetaHeaderType type, const std::string& name = ""); 1751 1752 #ifndef WT_TARGET_JAVA 1753 /*! \brief Adds an entry to the application log. 1754 * 1755 * Starts a new log entry of the given \p type in the %Wt 1756 * application log file. This method returns a stream-like object to 1757 * which the message may be streamed. 1758 * 1759 * \if cpp 1760 * A typical usage would be: 1761 * \code 1762 * wApp->log("notice") << "User " << userName << " logged in successfully."; 1763 * \endcode 1764 * 1765 * This would create a log entry that looks like: 1766 * \verbatim 1767 [2008-Jul-13 14:01:17.817348] 16879 [/app.wt Z2gCmSxIGjLHD73L] [notice] "User bart logged in successfully." 1768 * \endverbatim 1769 * \endif 1770 * 1771 * \if cpp 1772 * \sa \ref config_general 1773 * \endif 1774 */ 1775 WLogEntry log(const std::string& type) const; 1776 #endif // WT_TARGET_JAVA 1777 1778 /*! \brief Sets the loading indicator. 1779 * 1780 * The loading indicator is shown to indicate that a response from 1781 * the server is pending or JavaScript is being evaluated. 1782 * 1783 * The default loading indicator is a WDefaultLoadingIndicator. 1784 */ 1785 void setLoadingIndicator(std::unique_ptr<WLoadingIndicator> indicator); 1786 1787 /*! \brief Returns the loading indicator. 1788 * 1789 * \sa setLoadingIndicator() 1790 */ loadingIndicator()1791 WLoadingIndicator *loadingIndicator() const { return loadingIndicator_; } 1792 1793 /* 1794 * A url to a resource that provides a one pixel gif. This is sometimes 1795 * useful for CSS hackery to make IE behave. 1796 */ 1797 std::string onePixelGifUrl(); 1798 1799 /* 1800 * The doctype used to deliver the application. 1801 */ 1802 std::string docType() const; 1803 1804 /*! \brief Quits the application. 1805 * 1806 * This quits the application with a default restart message resolved 1807 * as WString::tr("Wt.QuittedMessage"). 1808 * 1809 * \sa quit(const WString&) 1810 */ 1811 void quit(); 1812 1813 /*! \brief Quits the application. 1814 * 1815 * The method returns immediately, but has as effect that the 1816 * application will be terminated after the current event is 1817 * completed. 1818 * 1819 * The current widget tree (including any modifications still 1820 * pending and applied during the current event handling) will still 1821 * be rendered, after which the application is terminated. 1822 * 1823 * If the restart message is not empty, then the user will be 1824 * offered to restart the application (using the provided message) 1825 * when further interacting with the application. 1826 * 1827 * \sa redirect() 1828 */ 1829 void quit(const WString& restartMessage); 1830 1831 /*! \brief Returns whether the application has quit. 1832 * 1833 * \sa quit() 1834 */ hasQuit()1835 bool hasQuit() const { return quitted_; } 1836 1837 /*! \brief Returns the current maximum size of a request to the 1838 * application. 1839 * 1840 * The returned value is the maximum request size in bytes. 1841 * 1842 * \if cpp 1843 * The maximum request size is configured in the configuration file, 1844 * see \ref config_general. 1845 * \endif 1846 * 1847 * \sa requestTooLarge() 1848 */ 1849 ::int64_t maximumRequestSize() const; 1850 1851 /*! \brief %Signal which indicates that too a large request was received. 1852 * 1853 * The integer parameter is the request size that was received in bytes. 1854 */ requestTooLarge()1855 Signal< ::int64_t>& requestTooLarge() { return requestTooLarge_; } 1856 1857 /** @name Global keyboard and mouse events 1858 */ 1859 //!@{ 1860 /*! \brief Event signal emitted when a keyboard key is pushed down. 1861 * 1862 * The application receives key events when no widget currently 1863 * has focus. Otherwise, key events are handled by the widget in focus, 1864 * and its ancestors. 1865 * 1866 * \sa See WInteractWidget::keyWentDown() 1867 */ 1868 EventSignal<WKeyEvent>& globalKeyWentDown(); 1869 1870 /*! \brief Event signal emitted when a "character" was entered. 1871 * 1872 * The application receives key events when no widget currently 1873 * has focus. Otherwise, key events are handled by the widget in focus, 1874 * and its ancestors. 1875 * 1876 * \sa See WInteractWidget::keyPressed() 1877 */ 1878 EventSignal<WKeyEvent>& globalKeyPressed(); 1879 1880 /*! \brief Event signal emitted when a keyboard key is released. 1881 * 1882 * The application receives key events when no widget currently 1883 * has focus. Otherwise, key events are handled by the widget in focus, 1884 * and its ancestors. 1885 * 1886 * \sa See WInteractWidget::keyWentUp() 1887 */ 1888 EventSignal<WKeyEvent>& globalKeyWentUp(); 1889 1890 /*! \brief Event signal emitted when enter was pressed. 1891 * 1892 * The application receives key events when no widget currently 1893 * has focus. Otherwise, key events are handled by the widget in focus, 1894 * and its ancestors. 1895 * 1896 * \sa See WInteractWidget::enterPressed() 1897 */ 1898 EventSignal<>& globalEnterPressed(); 1899 1900 /*! \brief Event signal emitted when escape was pressed. 1901 * 1902 * The application receives key events when no widget currently 1903 * has focus. Otherwise, key events are handled by the widget in focus, 1904 * and its ancestors. 1905 * 1906 * \sa See WInteractWidget::escapePressed() 1907 */ 1908 EventSignal<>& globalEscapePressed(); 1909 //!@} 1910 1911 /* 1912 * Returns whether debug was configured. 1913 * (should be public API ?) 1914 */ 1915 bool debug() const; 1916 1917 /* 1918 * Methods for client-side focus 1919 */ 1920 void setFocus(const std::string& id, int selectionStart, int selectionEnd); 1921 1922 #ifdef WT_DEBUG_JS 1923 void loadJavaScript(const char *jsFile); 1924 #else 1925 #ifdef WT_TARGET_JAVA 1926 /*! \brief Loads an internal JavaScript file. 1927 * 1928 * This is an internal function and should not be called directly. 1929 * 1930 * \sa require(), doJavaScript() 1931 */ 1932 #endif 1933 void loadJavaScript(const char *jsFile, const WJavaScriptPreamble& preamble); 1934 #endif 1935 1936 bool javaScriptLoaded(const char *jsFile) const; 1937 1938 /*! \brief Sets the message for the user to confirm closing of the 1939 * application window/tab. 1940 * 1941 * If the message is empty, then the user may navigate away from the page 1942 * without confirmation. 1943 * 1944 * Otherwise the user will be prompted with a browser-specific 1945 * dialog asking him to confirm leaving the page. This \p message is 1946 * added to the page. 1947 * 1948 * \sa unload() 1949 */ 1950 void setConfirmCloseMessage(const WString& message); 1951 1952 void enableInternalPaths(); 1953 1954 // should we move this into an InternalPaths utility class / namespace ? 1955 #ifdef WT_TARGET_JAVA 1956 /*! \brief Utility function to check if one path falls under another path. 1957 * 1958 * This returns whether the \p query path matches the given \p path, 1959 * meaning that it is equal to that path or it specifies a more 1960 * specific sub path of that path. 1961 */ 1962 #endif // WT_TARGET_JAVA 1963 static bool pathMatches(const std::string& path, const std::string& query); 1964 1965 #ifndef WT_TARGET_JAVA 1966 /*! \brief Defers rendering of the current event response. 1967 * 1968 * This method defers the rendering of the current event response 1969 * until resumeRendering() is called. This may be used if you do not 1970 * want to actively block the current thread while waiting for an 1971 * event which is needed to complete the current event 1972 * response. Note that this effectively freezes the user interface, 1973 * and thus you should only do this if you know that the event you 1974 * are waiting for will arrive shortly, or there is really nothing more 1975 * useful for the user to do than wait for the action to complete. 1976 * 1977 * A typical use case is in conjunction with the Http::Client, to 1978 * defer the rendering while waiting for the Http::Client to 1979 * complete. 1980 * 1981 * The function may be called multiple times and the number of deferral 1982 * requests is counted. The current response is deferred until as 1983 * many calls to resumeRendering() have been performed. 1984 * 1985 * \sa resumeRendering() 1986 */ 1987 void deferRendering(); 1988 1989 /*! \brief Resumes rendering of a deferred event response. 1990 * 1991 * \sa deferRendering() 1992 */ 1993 void resumeRendering(); 1994 #endif 1995 1996 /*! \brief Encodes an untrusted URL to prevent referer leaks. 1997 * 1998 * This encodes an URL so that in case the session ID is present 1999 * in the current URL, this session ID does not leak to the refenced 2000 * URL. 2001 * 2002 * %Wt will safely handle URLs in the API (in WImage and WAnchor) but 2003 * you may want to use this function to encode URLs which you use in 2004 * WTemplate texts. 2005 */ 2006 std::string encodeUntrustedUrl(const std::string& url) const; 2007 2008 /*! \brief Pushes a (modal) widget onto the expose stack. 2009 * 2010 * This defines a new context of widgets that are currently visible. 2011 */ 2012 void pushExposedConstraint(WWidget *w); 2013 void popExposedConstraint(WWidget *w); 2014 2015 void addGlobalWidget(WWidget *w); // from within constructor 2016 void removeGlobalWidget(WWidget *w); // from within destructor 2017 2018 /*! \brief Suspend the application. 2019 * 2020 * Keep this application alive for a certain amount of time, while 2021 * allowing the user to navigate away from the page. This can be 2022 * useful when using 3rd party login or payment providers. 2023 * You can later return to the application with a url that includes 2024 * the session ID as query parameter (see WApplication::url()). 2025 */ 2026 void suspend(std::chrono::seconds duration); 2027 2028 /*! \brief Signal that is emitted when the application is no longer suspended. 2029 * 2030 * This can be used to apply changes which were difficult to do as a result of 2031 * the application not being rendered. 2032 * Eg. Wt uses this to trigger a login as a result of single sign-on. 2033 */ unsuspended()2034 Signal<>& unsuspended() { return unsuspended_; } 2035 2036 protected: 2037 /*! \brief Notifies an event to the application. 2038 * 2039 * This method is called by the event loop for propagating an event 2040 * to the application. It provides a single point of entry for 2041 * events to the application, besides the application constructor. 2042 * 2043 * You may want to reimplement this method for two reasons: 2044 * 2045 * - for having a single point for exception handling: while you may want 2046 * to catch recoverable exceptions in a more appropriate place, general 2047 * (usually fatal) exceptions may be caught here. You will probably 2048 * want to catch the same exceptions in the application constructor 2049 * in the same way. 2050 * - you want to manage resource usage during requests. For example, at 2051 * the end of request handling, you want to return a database session 2052 * back to the pool. Since %notify() is also used for rendering right after 2053 * the application is created, this will also clean up resources after 2054 * application construction. 2055 * 2056 * In either case, you will need to call the base class 2057 * implementation of %notify(), as otherwise no events will be 2058 * delivered to your application. 2059 * 2060 * The following shows a generic template for reimplementhing this 2061 * method for both managing request resources and generic exception 2062 * handling. 2063 * 2064 * \if cpp 2065 * \code 2066 * MyApplication::notify(const WEvent& event) 2067 * { 2068 * // Grab resources for during request handling 2069 * try { 2070 * WApplication::notify(event); 2071 * } catch (MyException& exception) { 2072 * // handle this exception in a central place 2073 * } 2074 * // Free resources used during request handling 2075 * } 2076 * \endcode 2077 * \elseif java 2078 * \code 2079 * void notify(WEvent event) { 2080 * // Grab resources for during request handling 2081 * try { 2082 * super.notify(event); 2083 * } catch (MyException exception) { 2084 * // handle this exception in a central place 2085 * } 2086 * // Free resources used during request handling 2087 * } 2088 * \endcode 2089 * \endif 2090 * 2091 * Note that any uncaught exception throw during event handling 2092 * terminates the session. 2093 */ 2094 virtual void notify(const WEvent& e); 2095 2096 /*! \brief Returns whether a widget is exposed in the interface. 2097 * 2098 * The default implementation simply returns \c true, unless a modal 2099 * dialog is active, in which case it returns \c true only for widgets 2100 * that are inside the dialog. 2101 * 2102 * You may want to reimplement this method if you wish to disallow 2103 * events from certain widgets even when they are inserted in the 2104 * widget hierachy. 2105 */ 2106 virtual bool isExposed(WWidget *w) const; 2107 2108 /*! \brief Progresses to an Ajax-enabled user interface. 2109 * 2110 * This method is called when the progressive bootstrap method is used, and 2111 * support for AJAX has been detected. The default behavior will propagate 2112 * the WWidget::enableAjax() method through the widget hierarchy. 2113 * 2114 * You may want to reimplement this method if you want to make 2115 * changes to the user-interface when AJAX is enabled. You should 2116 * always call the base implementation. 2117 * 2118 * \sa WWidget::enableAjax() 2119 */ 2120 virtual void enableAjax(); 2121 2122 /*! \brief Handles a browser unload event. 2123 * 2124 * The browser unloads the application when the user navigates away or 2125 * when he closes the window or tab. 2126 * 2127 * When <tt>reload-is-new-session</tt> is set to \c true, then the 2128 * default implementation of this method terminates this session by 2129 * calling quit(), otherwise the session is scheduled to expire within 2130 * seconds (since it may be a refresh). 2131 * 2132 * You may want to reimplement this if you want to keep the 2133 * application running until it times out (as was the behaviour 2134 * before %Wt 3.1.6). 2135 */ 2136 virtual void unload(); 2137 2138 /*! \brief Idle timeout handler 2139 * 2140 * \if cpp 2141 * If <tt>idle-timeout</tt> is set in the configuration, this method is called when 2142 * the user seems idle for the number of seconds set in <tt>idle-timeout</tt>. 2143 * \elseif java 2144 * If idle timeout is set in the configuration 2145 * ({@link Configuration#setIdleTimeout(int)}), this 2146 * method is called when the user seems idle for the number of seconds set as the 2147 * idle timeout. 2148 * \endif 2149 * 2150 * This feature can be useful in security sensitive applications 2151 * to prevent unauthorized users from taking over the session 2152 * of a user that has moved away from or left behind 2153 * the device from which they are accessing the %Wt application. 2154 * 2155 * The default implementation logs that a timeout has occurred, 2156 * and calls quit(). 2157 * 2158 * This method can be overridden to specify different timeout behaviour, 2159 * e.g. to show a dialog that a user's session has expired, or that 2160 * the session is about to expire. 2161 * 2162 * \if cpp 2163 * 2164 * Example for an expiration dialog: 2165 * 2166 * \code 2167 * class MyApplication : public Wt::WApplication { 2168 * public: 2169 * MyApplication(Wt::WEnvironment &env) 2170 * : WApplication(env) 2171 * { } 2172 * 2173 * protected: 2174 * virtual void idleTimeout() override 2175 * { 2176 * if (idleTimeoutDialog_) 2177 * return; // Prevent multiple dialogs 2178 * 2179 * idleTimeoutDialog_ = addChild(std::make_unique<Wt::WDialog>("Idle timeout")); 2180 * idleTimeoutDialog_->contents()->addNew<Wt::WText>("This session will automatically quit in 1 minute, " 2181 * "press 'abort' to continue using the application"); 2182 * auto btn = idleTimeoutDialog_->footer()->addNew<Wt::WPushButton>("abort"); 2183 * btn->clicked().connect([this]{ 2184 * removeChild(idleTimeoutDialog_.get()); 2185 * }); 2186 * auto timer = idleTimeoutDialog_->addChild(std::make_unique<Wt::WTimer>()); 2187 * timer->setInterval(std::chrono::seconds{60}); 2188 * timer->setSingleShot(true); 2189 * timer->timeout().connect([this]{ 2190 * quit(); 2191 * }); 2192 * timer->start(); 2193 * idleTimeoutDialog_->show(); 2194 * } 2195 * 2196 * private: 2197 * Wt::Core::observing_ptr<Wt::WDialog> idleTimeoutDialog_; 2198 * }; 2199 * \endcode 2200 * 2201 * \endif 2202 * 2203 * \note The events currently counted as user activity are: 2204 * - mousedown 2205 * - mouseup 2206 * - wheel 2207 * - keydown 2208 * - keyup 2209 * - touchstart 2210 * - touchend 2211 * - pointerdown 2212 * - pointerup 2213 */ 2214 virtual void idleTimeout(); 2215 2216 /** 2217 * @brief handleJavaScriptError print javaScript errors to log file. 2218 * You may want to overwrite it to render error page for example. 2219 * 2220 * @param errorText the error will usually be in json format. 2221 */ 2222 virtual void handleJavaScriptError(const std::string& errorText); 2223 private: 2224 Signal< ::int64_t > requestTooLarge_; 2225 Signal<> unsuspended_; 2226 2227 struct ScriptLibrary { 2228 ScriptLibrary(const std::string& uri, const std::string& symbol); 2229 2230 std::string uri, symbol, beforeLoadJS; 2231 bool operator< (const ScriptLibrary& other) const; 2232 bool operator== (const ScriptLibrary& other) const; 2233 }; 2234 2235 struct MetaLink { 2236 MetaLink(const std::string &href, 2237 const std::string &rel, 2238 const std::string &media, 2239 const std::string &hreflang, 2240 const std::string &type, 2241 const std::string &sizes, 2242 bool disabled); 2243 2244 std::string href; 2245 std::string rel; 2246 std::string media; 2247 std::string hreflang; 2248 std::string type; 2249 std::string sizes; 2250 bool disabled; 2251 }; 2252 2253 #ifndef WT_TARGET_JAVA 2254 typedef std::map<std::string, EventSignalBase *> SignalMap; 2255 typedef std::map<std::string, WResource*> ResourceMap; 2256 #else 2257 typedef std::weak_value_map<std::string, EventSignalBase *> SignalMap; 2258 typedef std::weak_value_map<std::string, WResource*> ResourceMap; 2259 #endif 2260 typedef std::map<std::string, WObject *> ObjectMap; 2261 2262 /* 2263 * Basic application stuff 2264 */ 2265 WebSession *session_; // session owning this application 2266 #ifndef WT_CNOR 2267 std::weak_ptr<WebSession> weakSession_; // used to sense destruction 2268 #endif // WT_CNOR 2269 WString title_, closeMessage_; 2270 bool titleChanged_, closeMessageChanged_, localeChanged_; 2271 std::unique_ptr<WContainerWidget> domRoot_; // main DOM root 2272 WContainerWidget *widgetRoot_; // widgets in main DOM root 2273 WContainerWidget *timerRoot_; // timers in main DOM root 2274 std::unique_ptr<WContainerWidget> domRoot2_; // other virtual root 2275 WCssStyleSheet styleSheet_; // internal stylesheet 2276 std::unique_ptr<WCombinedLocalizedStrings> localizedStrings_; 2277 WLocale locale_; 2278 std::string renderedInternalPath_, newInternalPath_; 2279 Signal<std::string> internalPathChanged_, internalPathInvalid_; 2280 bool internalPathIsChanged_, internalPathDefaultValid_, internalPathValid_; 2281 int serverPush_; 2282 bool serverPushChanged_; 2283 #ifndef WT_TARGET_JAVA 2284 boost::pool<boost::default_user_allocator_new_delete> *eventSignalPool_; 2285 #endif // WT_TARGET_JAVA 2286 std::string javaScriptClass_; 2287 bool quitted_; 2288 WString quittedMessage_; 2289 std::unique_ptr<WResource> onePixelGifR_; 2290 bool internalPathsEnabled_; 2291 WWidget *exposedOnly_; 2292 WLoadingIndicator *loadingIndicator_; 2293 std::string htmlClass_, bodyClass_; 2294 bool bodyHtmlClassChanged_, enableAjax_; 2295 #ifndef WT_TARGET_JAVA 2296 bool initialized_; 2297 #endif // WT_TARGET_JAVA 2298 std::string focusId_; 2299 int selectionStart_, selectionEnd_; 2300 LayoutDirection layoutDirection_; 2301 2302 std::vector<ScriptLibrary> scriptLibraries_; 2303 int scriptLibrariesAdded_; 2304 2305 std::shared_ptr<WTheme> theme_; 2306 std::vector<WLinkedCssStyleSheet> styleSheets_; 2307 std::vector<WLinkedCssStyleSheet> styleSheetsToRemove_; 2308 2309 int styleSheetsAdded_; 2310 2311 std::vector<MetaHeader> metaHeaders_; 2312 std::vector<MetaLink> metaLinks_; 2313 2314 SignalMap exposedSignals_; // signals that may be accessed 2315 ResourceMap exposedResources_; // resources that may be accessed 2316 ObjectMap encodedObjects_; // objects encoded for internal purposes 2317 // like 'virtual pointers' (see D&D) 2318 std::set<std::string> justRemovedSignals_; 2319 2320 bool exposeSignals_; // if we are currently exposing signals (see WViewWidget) 2321 2322 std::string afterLoadJavaScript_, beforeLoadJavaScript_; 2323 int newBeforeLoadJavaScript_; 2324 std::string autoJavaScript_; 2325 bool autoJavaScriptChanged_; 2326 2327 #ifndef WT_DEBUG_JS 2328 std::vector<WJavaScriptPreamble> javaScriptPreamble_; 2329 int newJavaScriptPreamble_; 2330 #else 2331 std::vector<const char *> newJavaScriptToLoad_; 2332 #endif // WT_DEBUG_JS 2333 std::set<const char *> javaScriptLoaded_; 2334 bool customJQuery_; 2335 2336 EventSignal<> showLoadingIndicator_, hideLoadingIndicator_; 2337 JSignal<> unloaded_; 2338 JSignal<> idleTimeout_; 2339 timerRoot()2340 WContainerWidget *timerRoot() const { return timerRoot_; } 2341 WEnvironment& env(); // short-hand for session_->env() 2342 2343 /* 2344 * Functions for exposed signals, resources, and objects 2345 */ 2346 void addExposedSignal(EventSignalBase* signal); 2347 void removeExposedSignal(EventSignalBase* signal); 2348 EventSignalBase *decodeExposedSignal(const std::string& signalName) const; 2349 std::string encodeSignal(const std::string& objectId, 2350 const std::string& name) const; 2351 exposedSignals()2352 SignalMap& exposedSignals() { return exposedSignals_; } justRemovedSignals()2353 std::set<std::string>& justRemovedSignals() { return justRemovedSignals_; } 2354 2355 std::string resourceMapKey(WResource *resource); 2356 std::string addExposedResource(WResource *resource); 2357 bool removeExposedResource(WResource *resource); 2358 WResource *decodeExposedResource(const std::string& resourceMapKey) const; 2359 WResource *decodeExposedResource(const std::string& resourceMapKey, 2360 unsigned long rand) const; 2361 2362 /* 2363 * Methods for application state handling 2364 */ 2365 bool changeInternalPath(const std::string& path); 2366 bool changedInternalPath(const std::string& path); 2367 2368 /* 2369 * Methods for accessing javaScript, which may have erase-on-read 2370 * semantics 2371 */ 2372 void streamAfterLoadJavaScript(WStringStream& out); 2373 void streamBeforeLoadJavaScript(WStringStream& out, bool all); 2374 void streamJavaScriptPreamble(WStringStream& out, bool all); 2375 #ifdef WT_DEBUG_JS 2376 void loadJavaScriptFile(WStringStream& out, const char *jsFile); 2377 #endif // WT_DEBUG_JS 2378 2379 /* 2380 * Methods that control exposing of signals 2381 */ setExposeSignals(bool how)2382 void setExposeSignals(bool how) { exposeSignals_ = how; } exposeSignals()2383 bool exposeSignals() const { return exposeSignals_; } 2384 void doUnload(); 2385 void doIdleTimeout(); 2386 2387 #ifndef WT_TARGET_JAVA 2388 int startWaitingAtLock(); 2389 void endWaitingAtLock(int id); 2390 #endif // WT_TARGET_JAVA 2391 focus()2392 std::string focus() const { return focusId_; } selectionStart()2393 int selectionStart() const { return selectionStart_; } selectionEnd()2394 int selectionEnd() const { return selectionEnd_; } 2395 2396 WLocalizedStrings *localizedStringsPack(); 2397 2398 /* 2399 * Methods for audio handling 2400 */ 2401 SoundManager *getSoundManager(); 2402 SoundManager *soundManager_; 2403 2404 static const char *RESOURCES_URL; 2405 2406 #ifdef WT_TARGET_JAVA 2407 JSlot showLoadJS; 2408 JSlot hideLoadJS; 2409 #endif 2410 2411 friend class WCssStyleSheet; 2412 friend class WebRenderer; 2413 friend class WebSession; 2414 friend class WebController; 2415 friend class EventSignalBase; 2416 friend class JavaScriptEvent; 2417 friend class UpdateLockImpl; 2418 friend class WContainerWidget; 2419 friend class WDialog; 2420 friend class WFileUpload; 2421 friend class WInteractWidget; 2422 friend class WLineEdit; 2423 friend class WMenu; 2424 friend class WResource; 2425 friend class WSound; 2426 friend class WString; 2427 friend class WTextArea; 2428 friend class WTimer; 2429 friend class WViewWidget; 2430 friend class WWidget; 2431 friend class WWebWidget; 2432 }; 2433 2434 #ifndef WT_TARGET_JAVA 2435 #ifdef DOXYGEN_ONLY 2436 /*! \brief Runs the %Wt application server. 2437 * 2438 * This function runs the application server, and should be called 2439 * only once (e.g. from within your main function). 2440 * 2441 * The \p createApplication parameter is a <tt>std::function</tt> 2442 * object that should create a new application instance for a new user 2443 * visiting the application. It is of type: 2444 * <tt>std::function<Wt::WApplication* (const 2445 * Wt::WEnvironment&)></tt>, and thus you can pass to it a function 2446 * like: 2447 * 2448 * <pre> 2449 * Wt::WApplication *createApplication(const Wt::WEnvironment& env) 2450 * { 2451 * // ... 2452 * } 2453 * </pre> 2454 * 2455 * When using the built-in httpd, the implementation listens for POSIX 2456 * termination signals (or console CTRL-C) event. You can use the 2457 * WServer class for more flexible control on starting and stopping 2458 * the server. 2459 * 2460 * \relates WServer 2461 * \sa WApplication 2462 */ 2463 extern int WRun(int argc, char** argv, 2464 ApplicationCreator createApplication = 0); 2465 #else // DOXYGEN_ONLY 2466 extern int WTCONNECTOR_API 2467 WRun(int argc, char** argv, 2468 ApplicationCreator createApplication = ApplicationCreator()); 2469 2470 #endif // DOXYGEN_ONLY 2471 2472 #ifdef DOXYGEN_ONLY 2473 /*! \brief Runs the %Wt application server. 2474 * 2475 * This function runs the application server, and should be called 2476 * only once (e.g. from within your main function). 2477 * 2478 * The \p createApplication parameter is a <tt>std::function</tt> 2479 * object that should create a new application instance for a new user 2480 * visiting the application. It is of type: 2481 * <tt>std::function<Wt::WApplication* (const 2482 * Wt::WEnvironment&)></tt>, and thus you can pass to it a function 2483 * like: 2484 * 2485 * <pre> 2486 * Wt::WApplication *createApplication(const Wt::WEnvironment& env) 2487 * { 2488 * // ... 2489 * } 2490 * </pre> 2491 * 2492 * When using the built-in httpd, the implementation listens for POSIX 2493 * termination signals (or console CTRL-C) event. You can use the 2494 * WServer class for more flexible control on starting and stopping 2495 * the server. 2496 * 2497 * This version of WRun() takes a std::string 2498 * for the application path, and a vector of arguments (not including 2499 * argv[0], the application path) instead of argc and argv, 2500 * for better convenience when arguments are not provided via 2501 * the command line. 2502 * 2503 * \relates WServer 2504 * \sa WApplication 2505 */ 2506 extern int WRun(const std::string &applicationPath, 2507 const std::vector<std::string> &args, 2508 ApplicationCreator createApplication = 0); 2509 #else // DOXYGEN_ONLY 2510 extern int WTCONNECTOR_API 2511 WRun(const std::string &applicationPath, 2512 const std::vector<std::string> &args, 2513 ApplicationCreator createApplication = ApplicationCreator()); 2514 2515 #endif // DOXYGEN_ONLY 2516 #endif // WT_TARGET_JAVA 2517 2518 /*! \def wApp 2519 * \brief Global constant for accessing the application instance. 2520 * 2521 * This is equivalent to WApplication::instance() 2522 * 2523 * \relates WApplication 2524 */ 2525 #define wApp Wt::WApplication::instance() 2526 2527 } 2528 2529 #endif // WAPPLICATION_ 2530