1// Copyright (C) 2023 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import m from 'mithril'; 16 17import {pluginManager, pluginRegistry} from '../common/plugins'; 18import {raf} from '../core/raf_scheduler'; 19import {Button} from '../widgets/button'; 20 21import {exists} from '../base/utils'; 22import {PluginDescriptor} from '../public'; 23import {createPage} from './pages'; 24import {defaultPlugins} from '../core/default_plugins'; 25import {Intent} from '../widgets/common'; 26 27export const PluginsPage = createPage({ 28 view() { 29 return m( 30 '.pf-plugins-page', 31 m('h1', 'Plugins'), 32 m( 33 '.pf-plugins-topbar', 34 m(Button, { 35 intent: Intent.Primary, 36 label: 'Disable All', 37 onclick: async () => { 38 for (const plugin of pluginRegistry.values()) { 39 await pluginManager.disablePlugin(plugin.pluginId, true); 40 raf.scheduleFullRedraw(); 41 } 42 }, 43 }), 44 m(Button, { 45 intent: Intent.Primary, 46 label: 'Enable All', 47 onclick: async () => { 48 for (const plugin of pluginRegistry.values()) { 49 await pluginManager.enablePlugin(plugin.pluginId, true); 50 raf.scheduleFullRedraw(); 51 } 52 }, 53 }), 54 m(Button, { 55 intent: Intent.Primary, 56 label: 'Restore Defaults', 57 onclick: async () => { 58 await pluginManager.restoreDefaults(true); 59 raf.scheduleFullRedraw(); 60 }, 61 }), 62 ), 63 m( 64 '.pf-plugins-grid', 65 [ 66 m('span', 'Plugin'), 67 m('span', 'Default?'), 68 m('span', 'Enabled?'), 69 m('span', 'Active?'), 70 m('span', 'Control'), 71 m('span', 'Load Time'), 72 ], 73 Array.from(pluginRegistry.values()).map((plugin) => { 74 return renderPluginRow(plugin); 75 }), 76 ), 77 ); 78 }, 79}); 80 81function renderPluginRow(plugin: PluginDescriptor): m.Children { 82 const pluginId = plugin.pluginId; 83 const isDefault = defaultPlugins.includes(pluginId); 84 const pluginDetails = pluginManager.plugins.get(pluginId); 85 const isActive = pluginManager.isActive(pluginId); 86 const isEnabled = pluginManager.isEnabled(pluginId); 87 const loadTime = pluginDetails?.previousOnTraceLoadTimeMillis; 88 return [ 89 m('span', pluginId), 90 m('span', isDefault ? 'Yes' : 'No'), 91 isEnabled 92 ? m('.pf-tag.pf-active', 'Enabled') 93 : m('.pf-tag.pf-inactive', 'Disabled'), 94 isActive 95 ? m('.pf-tag.pf-active', 'Active') 96 : m('.pf-tag.pf-inactive', 'Inactive'), 97 m(Button, { 98 label: isActive ? 'Disable' : 'Enable', 99 intent: Intent.Primary, 100 onclick: async () => { 101 if (isActive) { 102 await pluginManager.disablePlugin(pluginId, true); 103 } else { 104 await pluginManager.enablePlugin(pluginId, true); 105 } 106 raf.scheduleFullRedraw(); 107 }, 108 }), 109 exists(loadTime) ? m('span', `${loadTime.toFixed(1)} ms`) : m('span', `-`), 110 ]; 111} 112