f316b073536a3438c53923cd42b6ee83608ce9ed
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / components / HandlerRegistry.js
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.save(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
158         if (contentProvider instanceof WebInspector.UISourceCode) {
159             var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (contentProvider);
160             if (uiSourceCode.project().type() !== WebInspector.projectTypes.FileSystem && uiSourceCode.project().type() !== WebInspector.projectTypes.Snippets)
161                 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as..." : "Save As..."), save.bind(null, true));
162         }
163     },
164
165     /**
166      * @param {!WebInspector.ContextMenu} contextMenu
167      * @param {!Object} target
168      */
169     _appendHrefItems: function(contextMenu, target)
170     {
171         if (!(target instanceof Node))
172             return;
173         var targetNode = /** @type {!Node} */ (target);
174
175         var anchorElement = targetNode.enclosingNodeOrSelfWithClass("webkit-html-resource-link") || targetNode.enclosingNodeOrSelfWithClass("webkit-html-external-link");
176         if (!anchorElement)
177             return;
178
179         var resourceURL = anchorElement.href;
180         if (!resourceURL)
181             return;
182
183         // Add resource-related actions.
184         contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), this._openInNewTab.bind(this, resourceURL));
185
186         function openInResourcesPanel(resourceURL)
187         {
188             var resource = WebInspector.resourceForURL(resourceURL);
189             if (resource)
190                 WebInspector.Revealer.reveal(resource);
191             else
192                 InspectorFrontendHost.openInNewTab(resourceURL);
193         }
194         if (WebInspector.resourceForURL(resourceURL))
195             contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open link in Resources panel" : "Open Link in Resources Panel"), openInResourcesPanel.bind(null, resourceURL));
196         contextMenu.appendItem(WebInspector.copyLinkAddressLabel(), InspectorFrontendHost.copyText.bind(InspectorFrontendHost, resourceURL));
197     },
198
199     __proto__: WebInspector.Object.prototype
200 }
201
202
203 WebInspector.HandlerRegistry.EventTypes = {
204     HandlersUpdated: "HandlersUpdated"
205 }
206
207 /**
208  * @constructor
209  */
210 WebInspector.HandlerSelector = function(handlerRegistry)
211 {
212     this._handlerRegistry = handlerRegistry;
213     this.element = createElementWithClass("select", "chrome-select");
214     this.element.addEventListener("change", this._onChange.bind(this), false);
215     this._update();
216     this._handlerRegistry.addEventListener(WebInspector.HandlerRegistry.EventTypes.HandlersUpdated, this._update.bind(this));
217 }
218
219 WebInspector.HandlerSelector.prototype =
220 {
221     _update: function()
222     {
223         this.element.removeChildren();
224         var names = this._handlerRegistry.handlerNames;
225         var activeHandler = this._handlerRegistry.activeHandler;
226
227         for (var i = 0; i < names.length; ++i) {
228             var option = createElement("option");
229             option.textContent = names[i];
230             option.selected = activeHandler === names[i];
231             this.element.appendChild(option);
232         }
233         this.element.disabled = names.length <= 1;
234     },
235
236     _onChange: function(event)
237     {
238         var value = event.target.value;
239         this._handlerRegistry.activeHandler = value;
240     }
241 }
242
243 /**
244  * @constructor
245  * @implements {WebInspector.ContextMenu.Provider}
246  */
247 WebInspector.HandlerRegistry.ContextMenuProvider = function()
248 {
249 }
250
251 WebInspector.HandlerRegistry.ContextMenuProvider.prototype = {
252     /**
253      * @param {!Event} event
254      * @param {!WebInspector.ContextMenu} contextMenu
255      * @param {!Object} target
256      */
257     appendApplicableItems: function(event, contextMenu, target)
258     {
259         WebInspector.openAnchorLocationRegistry._appendContentProviderItems(contextMenu, target);
260         WebInspector.openAnchorLocationRegistry._appendHrefItems(contextMenu, target);
261     }
262 }
263
264 /**
265  * @constructor
266  * @implements {WebInspector.Linkifier.LinkHandler}
267  */
268 WebInspector.HandlerRegistry.LinkHandler = function()
269 {
270 }
271
272 WebInspector.HandlerRegistry.LinkHandler.prototype = {
273     /**
274      * @param {string} url
275      * @param {number=} lineNumber
276      * @return {boolean}
277      */
278     handleLink: function(url, lineNumber)
279     {
280         return WebInspector.openAnchorLocationRegistry.dispatch({ url: url, lineNumber: lineNumber});
281     }
282 }
283
284 /**
285  * @constructor
286  * @extends {WebInspector.UISettingDelegate}
287  */
288 WebInspector.HandlerRegistry.OpenAnchorLocationSettingDelegate = function()
289 {
290     WebInspector.UISettingDelegate.call(this);
291 }
292
293 WebInspector.HandlerRegistry.OpenAnchorLocationSettingDelegate.prototype = {
294     /**
295      * @override
296      * @return {?Element}
297      */
298     settingElement: function()
299     {
300         if (!WebInspector.openAnchorLocationRegistry.handlerNames.length)
301             return null;
302
303         var handlerSelector = new WebInspector.HandlerSelector(WebInspector.openAnchorLocationRegistry);
304         return WebInspector.SettingsUI.createCustomSetting(WebInspector.UIString("Open links in"), handlerSelector.element);
305     },
306
307     __proto__: WebInspector.UISettingDelegate.prototype
308 }
309
310 /**
311  * @type {!WebInspector.HandlerRegistry}
312  */
313 WebInspector.openAnchorLocationRegistry;