1/* 2 * Copyright (C) 2011 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31/** 32 * @constructor 33 * @extends {WebInspector.Object} 34 * @implements {WebInspector.ContextMenu.Provider} 35 */ 36WebInspector.HandlerRegistry = function(setting) 37{ 38 WebInspector.Object.call(this); 39 this._handlers = {}; 40 this._setting = setting; 41 this._activeHandler = this._setting.get(); 42 WebInspector.ContextMenu.registerProvider(this); 43} 44 45WebInspector.HandlerRegistry.prototype = { 46 get handlerNames() 47 { 48 return Object.getOwnPropertyNames(this._handlers); 49 }, 50 51 get activeHandler() 52 { 53 return this._activeHandler; 54 }, 55 56 set activeHandler(value) 57 { 58 this._activeHandler = value; 59 this._setting.set(value); 60 }, 61 62 /** 63 * @param {Object} data 64 */ 65 dispatch: function(data) 66 { 67 return this.dispatchToHandler(this._activeHandler, data); 68 }, 69 70 /** 71 * @param {string} name 72 * @param {Object} data 73 */ 74 dispatchToHandler: function(name, data) 75 { 76 var handler = this._handlers[name]; 77 var result = handler && handler(data); 78 return !!result; 79 }, 80 81 registerHandler: function(name, handler) 82 { 83 this._handlers[name] = handler; 84 this.dispatchEventToListeners(WebInspector.HandlerRegistry.EventTypes.HandlersUpdated); 85 }, 86 87 unregisterHandler: function(name) 88 { 89 delete this._handlers[name]; 90 this.dispatchEventToListeners(WebInspector.HandlerRegistry.EventTypes.HandlersUpdated); 91 }, 92 93 /** 94 * @param {WebInspector.ContextMenu} contextMenu 95 * @param {Object} target 96 */ 97 appendApplicableItems: function(event, contextMenu, target) 98 { 99 if (event.hasBeenHandledByHandlerRegistry) 100 return; 101 event.hasBeenHandledByHandlerRegistry = true; 102 this._appendContentProviderItems(contextMenu, target); 103 this._appendHrefItems(contextMenu, target); 104 }, 105 106 /** 107 * @param {WebInspector.ContextMenu} contextMenu 108 * @param {Object} target 109 */ 110 _appendContentProviderItems: function(contextMenu, target) 111 { 112 if (!(target instanceof WebInspector.UISourceCode || target instanceof WebInspector.Resource || target instanceof WebInspector.NetworkRequest)) 113 return; 114 var contentProvider = /** @type {WebInspector.ContentProvider} */ (target); 115 if (!contentProvider.contentURL()) 116 return; 117 118 contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), WebInspector.openResource.bind(WebInspector, contentProvider.contentURL(), false)); 119 // Skip 0th handler, as it's 'Use default panel' one. 120 for (var i = 1; i < this.handlerNames.length; ++i) { 121 var handler = this.handlerNames[i]; 122 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open using %s" : "Open Using %s", handler), 123 this.dispatchToHandler.bind(this, handler, { url: contentProvider.contentURL() })); 124 } 125 contextMenu.appendItem(WebInspector.copyLinkAddressLabel(), InspectorFrontendHost.copyText.bind(InspectorFrontendHost, contentProvider.contentURL())); 126 127 if (!InspectorFrontendHost.canSave() || !contentProvider.contentURL()) 128 return; 129 130 var contentType = contentProvider.contentType(); 131 if (contentType !== WebInspector.resourceTypes.Document && 132 contentType !== WebInspector.resourceTypes.Stylesheet && 133 contentType !== WebInspector.resourceTypes.Script) 134 return; 135 136 function doSave(forceSaveAs, content) 137 { 138 var url = contentProvider.contentURL(); 139 WebInspector.fileManager.save(url, content, forceSaveAs); 140 WebInspector.fileManager.close(url); 141 } 142 143 function save(forceSaveAs) 144 { 145 if (contentProvider instanceof WebInspector.UISourceCode) { 146 var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (contentProvider); 147 if (uiSourceCode.isDirty()) { 148 doSave(forceSaveAs, uiSourceCode.workingCopy()); 149 uiSourceCode.commitWorkingCopy(function() { }); 150 return; 151 } 152 } 153 contentProvider.requestContent(doSave.bind(this, forceSaveAs)); 154 } 155 156 contextMenu.appendSeparator(); 157 contextMenu.appendItem(WebInspector.UIString("Save"), save.bind(this, false)); 158 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as..." : "Save As..."), save.bind(this, true)); 159 }, 160 161 /** 162 * @param {WebInspector.ContextMenu} contextMenu 163 * @param {Object} target 164 */ 165 _appendHrefItems: function(contextMenu, target) 166 { 167 if (!(target instanceof Node)) 168 return; 169 var targetNode = /** @type {Node} */ (target); 170 171 var anchorElement = targetNode.enclosingNodeOrSelfWithClass("webkit-html-resource-link") || targetNode.enclosingNodeOrSelfWithClass("webkit-html-external-link"); 172 if (!anchorElement) 173 return; 174 175 var resourceURL = anchorElement.href; 176 if (!resourceURL) 177 return; 178 179 // Add resource-related actions. 180 contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), WebInspector.openResource.bind(WebInspector, resourceURL, false)); 181 if (WebInspector.resourceForURL(resourceURL)) 182 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open link in Resources panel" : "Open Link in Resources Panel"), WebInspector.openResource.bind(null, resourceURL, true)); 183 contextMenu.appendItem(WebInspector.copyLinkAddressLabel(), InspectorFrontendHost.copyText.bind(InspectorFrontendHost, resourceURL)); 184 }, 185 186 __proto__: WebInspector.Object.prototype 187} 188 189 190WebInspector.HandlerRegistry.EventTypes = { 191 HandlersUpdated: "HandlersUpdated" 192} 193 194/** 195 * @constructor 196 */ 197WebInspector.HandlerSelector = function(handlerRegistry) 198{ 199 this._handlerRegistry = handlerRegistry; 200 this.element = document.createElement("select"); 201 this.element.addEventListener("change", this._onChange.bind(this), false); 202 this._update(); 203 this._handlerRegistry.addEventListener(WebInspector.HandlerRegistry.EventTypes.HandlersUpdated, this._update.bind(this)); 204} 205 206WebInspector.HandlerSelector.prototype = 207{ 208 _update: function() 209 { 210 this.element.removeChildren(); 211 var names = this._handlerRegistry.handlerNames; 212 var activeHandler = this._handlerRegistry.activeHandler; 213 214 for (var i = 0; i < names.length; ++i) { 215 var option = document.createElement("option"); 216 option.textContent = names[i]; 217 option.selected = activeHandler === names[i]; 218 this.element.appendChild(option); 219 } 220 this.element.disabled = names.length <= 1; 221 }, 222 223 _onChange: function(event) 224 { 225 var value = event.target.value; 226 this._handlerRegistry.activeHandler = value; 227 } 228} 229 230 231/** 232 * @type {WebInspector.HandlerRegistry} 233 */ 234WebInspector.openAnchorLocationRegistry = null; 235