172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSIONS_UI_H_ 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CHROME_BROWSER_EXTENSIONS_EXTENSIONS_UI_H_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_uninstall_dialog.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/pack_extension_job.h" 1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/shell_dialogs.h" 16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/webui/chrome_url_data_manager.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension_resource.h" 18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/webui/web_ui.h" 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_observer.h" 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_registrar.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass DictionaryValue; 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass Extension; 2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass ExtensionService; 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass FilePath; 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass ListValue; 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass PrefService; 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass RenderProcessHost; 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass UserScript; 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Information about a page running in an extension, for example a toolstrip, 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a background page, or a tab contents. 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct ExtensionPage { 353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ExtensionPage(const GURL& url, int render_process_id, int render_view_id, 363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool incognito) 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : url(url), render_process_id(render_process_id), 383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick render_view_id(render_view_id), incognito(incognito) {} 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url; 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int render_process_id; 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int render_view_id; 423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool incognito; 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ExtensionsUIHTMLSource : public ChromeURLDataManager::DataSource { 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionsUIHTMLSource(); 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called when the network layer has requested a resource underneath 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the path we registered. 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void StartDataRequest(const std::string& path, 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool is_incognito, 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int request_id); 5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual std::string GetMimeType(const std::string&) const; 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~ExtensionsUIHTMLSource() {} 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(ExtensionsUIHTMLSource); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The handler for JavaScript messages related to the "extensions" view. 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass ExtensionsDOMHandler : public WebUIMessageHandler, 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public NotificationObserver, 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public PackExtensionJob::Client, 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public SelectFileDialog::Listener, 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public ExtensionUninstallDialog::Delegate { 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen explicit ExtensionsDOMHandler(ExtensionService* extension_service); 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~ExtensionsDOMHandler(); 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // WebUIMessageHandler implementation. 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void RegisterMessages(); 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Extension Detail JSON Struct for page. (static for ease of testing). 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note: service can be NULL in unit tests. 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static DictionaryValue* CreateExtensionDetailValue( 7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ExtensionService* service, 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const Extension* extension, 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<ExtensionPage>& pages, 8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool enabled, 8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool terminated); 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ExtensionPackJob::Client 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnPackSuccess(const FilePath& crx_file, 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const FilePath& key_file); 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void OnPackFailure(const std::string& error); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // ExtensionUninstallDialog::Delegate: 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void ExtensionDialogAccepted(); 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void ExtensionDialogCanceled(); 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback for "requestExtensionsData" message. 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void HandleRequestExtensionsData(const ListValue* args); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback for "toggleDeveloperMode" message. 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void HandleToggleDeveloperMode(const ListValue* args); 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback for "inspect" message. 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void HandleInspectMessage(const ListValue* args); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback for "reload" message. 1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void HandleReloadMessage(const ListValue* args); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback for "enable" message. 1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void HandleEnableMessage(const ListValue* args); 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback for "enableIncognito" message. 1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void HandleEnableIncognitoMessage(const ListValue* args); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback for "allowFileAcces" message. 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void HandleAllowFileAccessMessage(const ListValue* args); 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback for "uninstall" message. 1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void HandleUninstallMessage(const ListValue* args); 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback for "options" message. 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void HandleOptionsMessage(const ListValue* args); 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 122201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Callback for "showButton" message. 123201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch void HandleShowButtonMessage(const ListValue* args); 124201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback for "load" message. 1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void HandleLoadMessage(const ListValue* args); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback for "pack" message. 1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void HandlePackMessage(const ListValue* args); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback for "autoupdate" message. 1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void HandleAutoUpdateMessage(const ListValue* args); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Utility for calling javascript window.alert in the page. 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ShowAlert(const std::string& message); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback for "selectFilePath" message. 1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void HandleSelectFilePathMessage(const ListValue* args); 1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Utility for callbacks that get an extension ID as the sole argument. 141513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* GetExtension(const ListValue* args); 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Forces a UI update if appropriate after a notification is received. 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void MaybeUpdateAfterNotification(); 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Register for notifications that we need to reload the page. 147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen void RegisterForNotifications(); 148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SelectFileDialog::Listener 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void FileSelected(const FilePath& path, 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index, void* params); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void MultiFilesSelected( 15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::vector<FilePath>& files, void* params); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void FileSelectionCanceled(void* params) {} 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NotificationObserver 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Observe(NotificationType type, 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Helper that lists the current active html pages for an extension. 162513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::vector<ExtensionPage> GetActivePagesForExtension( 163513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension); 1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void GetActivePagesForExtensionProcess( 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RenderProcessHost* process, 166513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension, 1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::vector<ExtensionPage> *result); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Returns the ExtensionUninstallDialog object for this class, creating it if 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // needed. 171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExtensionUninstallDialog* GetExtensionUninstallDialog(); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Our model. 17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_refptr<ExtensionService> extensions_service_; 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Used to pick the directory when loading an extension. 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<SelectFileDialog> load_extension_dialog_; 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Used to package the extension. 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<PackExtensionJob> pack_job_; 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Used to show confirmation UI for uninstalling extensions in incognito mode. 183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<ExtensionUninstallDialog> extension_uninstall_dialog_; 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The id of the extension we are prompting the user about. 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string extension_id_prompting_; 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We monitor changes to the extension system so that we can reload when 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // necessary. 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationRegistrar registrar_; 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If true, we will ignore notifications in ::Observe(). This is needed 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to prevent reloading the page when we were the cause of the 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // notification. 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool ignore_notifications_; 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The page may be refreshed in response to a RENDER_VIEW_HOST_DELETED, 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // but the iteration over RenderViewHosts will include the host because the 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // notification is sent when it is in the process of being deleted (and before 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // it is removed from the process). Keep a pointer to it so we can exclude 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // it from the active views. 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RenderViewHost* deleting_rvh_; 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(ExtensionsDOMHandler); 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass ExtensionsUI : public WebUI { 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit ExtensionsUI(TabContents* contents); 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static RefCountedMemory* GetFaviconResourceBytes(); 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static void RegisterUserPrefs(PrefService* prefs); 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(ExtensionsUI); 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // CHROME_BROWSER_EXTENSIONS_EXTENSIONS_UI_H_ 220