15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_BROWSER_UI_WEBUI_NTP_APP_LAUNCHER_HANDLER_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_UI_WEBUI_NTP_APP_LAUNCHER_HANDLER_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <set>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "apps/metrics_names.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_change_registrar.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/task/cancelable_task_tracker.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_uninstall_dialog.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_observer.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui_message_handler.h"
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/api/string_ordinal.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ExtensionEnableFlow;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionService;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PrefChangeRegistrar;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Profile;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace favicon_base {
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)struct FaviconImageResult;
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The handler for Javascript messages related to the "apps" view.
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class AppLauncherHandler
3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : public content::WebUIMessageHandler,
3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      public extensions::ExtensionUninstallDialog::Delegate,
3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      public ExtensionEnableFlowDelegate,
3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      public content::NotificationObserver {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit AppLauncherHandler(ExtensionService* extension_service);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~AppLauncherHandler();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Populate a dictionary with the information from an extension.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void CreateAppInfo(
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const extensions::Extension* extension,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionService* service,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::DictionaryValue* value);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebUIMessageHandler implementation.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RegisterMessages() OVERRIDE;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // content::NotificationObserver
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Observe(int type,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationSource& source,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationDetails& details) OVERRIDE;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Populate the given dictionary with all installed app info.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FillAppDictionary(base::DictionaryValue* value);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a dictionary value for the given extension. May return NULL, e.g. if
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the given extension is not an app. If non-NULL, the caller assumes
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ownership of the pointer.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::DictionaryValue* GetAppInfo(const extensions::Extension* extension);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Populate the given dictionary with the web store promo content.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FillPromoDictionary(base::DictionaryValue* value);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Handles the "launchApp" message with unused |args|.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleGetApps(const base::ListValue* args);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Handles the "launchApp" message with |args| containing [extension_id,
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // source] with optional [url, disposition], |disposition| defaulting to
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // CURRENT_TAB.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleLaunchApp(const base::ListValue* args);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Handles the "setLaunchType" message with args containing [extension_id,
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // launch_type].
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleSetLaunchType(const base::ListValue* args);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Handles the "uninstallApp" message with |args| containing [extension_id]
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // and an optional bool to not confirm the uninstall when true, defaults to
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // false.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleUninstallApp(const base::ListValue* args);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Handles the "createAppShortcut" message with |args| containing
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // [extension_id].
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleCreateAppShortcut(const base::ListValue* args);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Handles the "reorderApps" message with |args| containing [dragged_app_id,
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // app_order].
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleReorderApps(const base::ListValue* args);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Handles the "setPageIndex" message with |args| containing [extension_id,
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // page_index].
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleSetPageIndex(const base::ListValue* args);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Handles "saveAppPageName" message with |args| containing [name,
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // page_index].
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleSaveAppPageName(const base::ListValue* args);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Handles "generateAppForLink" message with |args| containing [url, title,
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // page_index].
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleGenerateAppForLink(const base::ListValue* args);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Other registered message callbacks with unused |args|.
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StopShowingAppLauncherPromo(const base::ListValue* args);
108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void OnLearnMore(const base::ListValue* args);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct AppInstallInfo {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppInstallInfo();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~AppInstallInfo();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 title;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL app_url;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::StringOrdinal page_ordinal;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset some instance flags we use to track the currently uninstalling app.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CleanupAfterUninstall();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prompts the user to re-enable the app for |extension_id|.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PromptToEnableApp(const std::string& extension_id);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ExtensionUninstallDialog::Delegate:
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ExtensionUninstallAccepted() OVERRIDE;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ExtensionUninstallCanceled() OVERRIDE;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ExtensionEnableFlowDelegate:
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void ExtensionEnableFlowFinished() OVERRIDE;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void ExtensionEnableFlowAborted(bool user_initiated) OVERRIDE;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the ExtensionUninstallDialog object for this class, creating it if
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // needed.
13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  extensions::ExtensionUninstallDialog* GetExtensionUninstallDialog();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Continuation for installing a bookmark app after favicon lookup.
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnFaviconForApp(scoped_ptr<AppInstallInfo> install_info,
1400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                       const favicon_base::FaviconImageResult& image_result);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sends |highlight_app_id_| to the js.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetAppToBeHighlighted();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnExtensionPreferenceChanged();
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnLocalStatePreferenceChanged();
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The apps are represented in the extensions model, which
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // outlives us since it's owned by our containing profile.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionService* const extension_service_;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We monitor changes to the extension system so that we can reload the apps
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // when necessary.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationRegistrar registrar_;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Monitor extension preference changes so that the Web UI can be notified.
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PrefChangeRegistrar extension_pref_change_registrar_;
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Monitor the local state pref to control the app launcher promo.
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PrefChangeRegistrar local_state_pref_change_registrar_;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used to show confirmation UI for uninstalling extensions in incognito mode.
16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<extensions::ExtensionUninstallDialog> extension_uninstall_dialog_;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Used to show confirmation UI for enabling extensions.
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ExtensionEnableFlow> extension_enable_flow_;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The ids of apps to show on the NTP.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> visible_apps_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The id of the extension we are prompting the user about (either enable or
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // uninstall).
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extension_id_prompting_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When true, we ignore changes to the underlying data rather than immediately
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // refreshing. This is useful when making many batch updates to avoid flicker.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ignore_changes_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When true, we have attempted to install a bookmark app, and are still
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // waiting to hear about success or failure from the extensions system.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool attempted_bookmark_app_install_;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if we have executed HandleGetApps() at least once.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_loaded_apps_;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The ID of the app to be highlighted on the NTP (i.e. shown on the page
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and pulsed). This is done for new installs. The actual higlighting occurs
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // when the app is added to the page (via getAppsCallback or appAdded).
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string highlight_app_id_;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Used for favicon loading tasks.
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::CancelableTaskTracker cancelable_task_tracker_;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AppLauncherHandler);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // CHROME_BROWSER_UI_WEBUI_NTP_APP_LAUNCHER_HANDLER_H_
199