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 */ 35 WebInspector.HandlerRegistry = function(setting) 36 { 37 WebInspector.Object.call(this); 38 this._handlers = {}; 39 this._setting = setting; 40 this._activeHandler = this._setting.get(); 41 } 42 43 WebInspector.HandlerRegistry.prototype = { 44 get handlerNames() 45 { 46 return Object.getOwnPropertyNames(this._handlers); 47 }, 48 49 get activeHandler() 50 { 51 return this._activeHandler; 52 }, 53 54 set activeHandler(value) 55 { 56 this._activeHandler = value; 57 this._setting.set(value); 58 }, 59 60 /** 61 * @param {!Object} data 62 * @return {boolean} 63 */ 64 dispatch: function(data) 65 { 66 return this.dispatchToHandler(this._activeHandler, data); 67 }, 68 69 /** 70 * @param {string} name 71 * @param {!Object} data 72 * @return {boolean} 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 {string} url 95 */ 96 _openInNewTab: function(url) 97 { 98 InspectorFrontendHost.openInNewTab(url); 99 }, 100 101 /** 102 * @param {!WebInspector.ContextMenu} contextMenu 103 * @param {!Object} target 104 */ 105 _appendContentProviderItems: function(contextMenu, target) 106 { 107 if (!(target instanceof WebInspector.UISourceCode || target instanceof WebInspector.Resource || target instanceof WebInspector.NetworkRequest)) 108 return; 109 var contentProvider = /** @type {!WebInspector.ContentProvider} */ (target); 110 if (!contentProvider.contentURL()) 111 return; 112 113 contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), this._openInNewTab.bind(this, contentProvider.contentURL())); 114 // Skip 0th handler, as it's 'Use default panel' one. 115 for (var i = 1; i < this.handlerNames.length; ++i) { 116 var handler = this.handlerNames[i]; 117 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open using %s" : "Open Using %s", handler), 118 this.dispatchToHandler.bind(this, handler, { url: contentProvider.contentURL() })); 119 } 120 contextMenu.appendItem(WebInspector.copyLinkAddressLabel(), InspectorFrontendHost.copyText.bind(InspectorFrontendHost, contentProvider.contentURL())); 121 122 if (!contentProvider.contentURL()) 123 return; 124 125 var contentType = contentProvider.contentType(); 126 if (contentType !== WebInspector.resourceTypes.Document && 127 contentType !== WebInspector.resourceTypes.Stylesheet && 128 contentType !== WebInspector.resourceTypes.Script) 129 return; 130 131 /** 132 * @param {boolean} forceSaveAs 133 * @param {?string} content 134 */ 135 function doSave(forceSaveAs, content) 136 { 137 var url = contentProvider.contentURL(); 138 WebInspector.fileManager.save(url, /** @type {string} */ (content), forceSaveAs); 139 WebInspector.fileManager.close(url); 140 } 141 142 /** 143 * @param {boolean} forceSaveAs 144 */ 145 function save(forceSaveAs) 146 { 147 if (contentProvider instanceof WebInspector.UISourceCode) { 148 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (contentProvider); 149 uiSourceCode.saveToFileSystem(forceSaveAs); 150 return; 151 } 152 contentProvider.requestContent(doSave.bind(null, forceSaveAs)); 153 } 154 155 contextMenu.appendSeparator(); 156 contextMenu.appendItem(WebInspector.UIString("Save"), save.bind(null, false)); 157 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as..." : "Save As..."), save.bind(null, true)); 158 }, 159 160 /** 161 * @param {!WebInspector.ContextMenu} contextMenu 162 * @param {!Object} target 163 */ 164 _appendHrefItems: function(contextMenu, target) 165 { 166 if (!(target instanceof Node)) 167 return; 168 var targetNode = /** @type {!Node} */ (target); 169 170 var anchorElement = targetNode.enclosingNodeOrSelfWithClass("webkit-html-resource-link") || targetNode.enclosingNodeOrSelfWithClass("webkit-html-external-link"); 171 if (!anchorElement) 172 return; 173 174 var resourceURL = anchorElement.href; 175 if (!resourceURL) 176 return; 177 178 // Add resource-related actions. 179 contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), this._openInNewTab.bind(this, resourceURL)); 180 181 function openInResourcesPanel(resourceURL) 182 { 183 var resource = WebInspector.resourceForURL(resourceURL); 184 if (resource) 185 WebInspector.Revealer.reveal(resource); 186 else 187 InspectorFrontendHost.openInNewTab(resourceURL); 188 } 189 if (WebInspector.resourceForURL(resourceURL)) 190 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open link in Resources panel" : "Open Link in Resources Panel"), openInResourcesPanel.bind(null, resourceURL)); 191 contextMenu.appendItem(WebInspector.copyLinkAddressLabel(), InspectorFrontendHost.copyText.bind(InspectorFrontendHost, resourceURL)); 192 }, 193 194 __proto__: WebInspector.Object.prototype 195 } 196 197 198 WebInspector.HandlerRegistry.EventTypes = { 199 HandlersUpdated: "HandlersUpdated" 200 } 201 202 /** 203 * @constructor 204 */ 205 WebInspector.HandlerSelector = function(handlerRegistry) 206 { 207 this._handlerRegistry = handlerRegistry; 208 this.element = document.createElement("select"); 209 this.element.addEventListener("change", this._onChange.bind(this), false); 210 this._update(); 211 this._handlerRegistry.addEventListener(WebInspector.HandlerRegistry.EventTypes.HandlersUpdated, this._update.bind(this)); 212 } 213 214 WebInspector.HandlerSelector.prototype = 215 { 216 _update: function() 217 { 218 this.element.removeChildren(); 219 var names = this._handlerRegistry.handlerNames; 220 var activeHandler = this._handlerRegistry.activeHandler; 221 222 for (var i = 0; i < names.length; ++i) { 223 var option = document.createElement("option"); 224 option.textContent = names[i]; 225 option.selected = activeHandler === names[i]; 226 this.element.appendChild(option); 227 } 228 this.element.disabled = names.length <= 1; 229 }, 230 231 _onChange: function(event) 232 { 233 var value = event.target.value; 234 this._handlerRegistry.activeHandler = value; 235 } 236 } 237 238 /** 239 * @constructor 240 * @implements {WebInspector.ContextMenu.Provider} 241 */ 242 WebInspector.HandlerRegistry.ContextMenuProvider = function() 243 { 244 } 245 246 WebInspector.HandlerRegistry.ContextMenuProvider.prototype = { 247 /** 248 * @param {!Event} event 249 * @param {!WebInspector.ContextMenu} contextMenu 250 * @param {!Object} target 251 */ 252 appendApplicableItems: function(event, contextMenu, target) 253 { 254 WebInspector.openAnchorLocationRegistry._appendContentProviderItems(contextMenu, target); 255 WebInspector.openAnchorLocationRegistry._appendHrefItems(contextMenu, target); 256 } 257 } 258 259 /** 260 * @constructor 261 * @implements {WebInspector.Linkifier.LinkHandler} 262 */ 263 WebInspector.HandlerRegistry.LinkHandler = function() 264 { 265 } 266 267 WebInspector.HandlerRegistry.LinkHandler.prototype = { 268 /** 269 * @param {string} url 270 * @param {number=} lineNumber 271 * @return {boolean} 272 */ 273 handleLink: function(url, lineNumber) 274 { 275 return WebInspector.openAnchorLocationRegistry.dispatch({ url: url, lineNumber: lineNumber}); 276 } 277 } 278 279 /** 280 * @constructor 281 * @extends {WebInspector.UISettingDelegate} 282 */ 283 WebInspector.HandlerRegistry.OpenAnchorLocationSettingDelegate = function() 284 { 285 WebInspector.UISettingDelegate.call(this); 286 } 287 288 WebInspector.HandlerRegistry.OpenAnchorLocationSettingDelegate.prototype = { 289 /** 290 * @override 291 * @return {?Element} 292 */ 293 settingElement: function() 294 { 295 if (!WebInspector.openAnchorLocationRegistry.handlerNames.length) 296 return null; 297 298 var handlerSelector = new WebInspector.HandlerSelector(WebInspector.openAnchorLocationRegistry); 299 return WebInspector.SettingsUI.createCustomSetting(WebInspector.UIString("Open links in"), handlerSelector.element); 300 }, 301 302 __proto__: WebInspector.UISettingDelegate.prototype 303 } 304 305 /** 306 * @type {!WebInspector.HandlerRegistry} 307 */ 308 WebInspector.openAnchorLocationRegistry; 309