150 likes | 161 Views
This article explores the flaws in current approaches to web browser extensions and proposes using programming language techniques, such as declarative compositional overlays, to overcome these limitations. It describes the benefits of browser extensions, the trade-offs in their design, and presents potential solutions for better programming models in popular browsers like Firefox and Chrome.
E N D
Language Support for Extensible Web Browsers Benjamin Lerner and Dan Grossman
Position • Browser extensions are a good thing • What are extensions? • Why use them? • Current approaches have important flaws • False design tradeoffs • Languages used are poor • PL techniques can help • UI: declarative compositional overlays • Behavior: aspects
What are web-browser extensions? • Downloadable code to customize the browser • Different from plugins
Why extensions? • Extensions avoid bloat • Pick and choose the features you want • Extensions can experiment • Provide new features after products ship • Wildly popular: • 6,000+ extensions • 1.5 Billion downloads
What’s wrong with extensions today? • Two browser designs: Firefox and Chrome • The designs force a trade-off: • Huge flexibility, or • Robustness • For both, the programming model is very poor • Why can’t we do better?
Programming example: Mouse Gestures • “Right-click-and-drag” gestures • Shape of gesture browser command • Work-alike versions for Chrome and Firefox
Firefox: flexible but brittle • Firebug + YSlow, Firefinder, FireCookie… • Deliberately extend another extension • http://sixrevisions.com/web-development/10-useful-firefox-extensions-to-supercharge-firebug/ • AdBlock Plus + NoScript • Deliberately break another extension • http://hackademix.net/2009/05/04/dear-adblock-plus-and-noscript-users-dear-mozilla-community/ • Currently no way to distinguish these cases
aioContent = document.getElementById("content"); aioContent.aioNativeRemoveTab = aioContent.removeTab; eval("aioContent.aioNativeRemoveTab = " + aioContent.aioNativeRemoveTab.toString().replace( 'this.selectedTab', '…various replacement code…')); aioContent.removeTab = function(aTab) { …various preprocessing… aioContent.aioNativeRemoveTab(aTab); } Firefox: free-form code injection Get a reference to the main window Alias the removeTab function Modify the function at that alias Replace the original with a call to the modified version
Chrome: robust but limited • StumbleUpon • Provides a “toolbar” in the page, • …but it’s not a true chrome toolbar • http://www.stumbleupon.com/sublog/su_chrome_extension/ • Currently no fix without new APIs
In the background page: close_tab:function(tab){ chrome.tabs.remove(tab.id); }, Injected into the main page: var ACTION = { … "close this tab" : function(){ connection.postMessage('close_tab'); }, … } Chrome: tightly-constrained Predefined object to manipulate tabs Page communicates to background via postMessage API
Towards a middle ground • Goal: flexibility and robustness • Free-form UI extension • Benign extensions can extend each other • Malicious extensions can’t hurt each other • Separate techniques for UI and code: • UI: Declarative, compositional overlays • Code: aspects
Overlays • Intuition: “Tree-structured patch” • When are overlays successfully applied? • When are overlays in conflict? • When should overlays be prohibited? <overlay> <div id=“greeting”> <p><b>World</b></p> </div> </overlay> <div id=“greeting”> <p>Hello</p> </div> <div id=“greeting”> <p>Hello</p> <p><b>World</b></p> </div>
Compositional overlays • The tree-patching part is fine, but need to: • Declare expectations of the base document • Declare invariants asserted by the overlay • Can now detect conflicting assertions Require “greeting” Last “greeting” (“greeting”, <p><b>World</b></p>) Last “greeting” Require “greeting” Last “greeting” (“greeting”, <p><b>Toronto</b></p>) Last “greeting”
aioContent = document.getElementById("content"); aioContent.aioNativeRemoveTab = aioContent.removeTab; eval("aioContent.aioNativeRemoveTab = " + aioContent.aioNativeRemoveTab.toString().replace( 'this.selectedTab', '…various replacement code…')); aioContent.removeTab = function(aTab) { …various preprocessing… aioContent.aioNativeRemoveTab(aTab); } Programming redux: using aspects aioContent = document.getElementById("content"); aioContent.aioNativeRemoveTab = aioContent.removeTab; at pointcut(field(this.selectedTab) && within(aioContent.removeTab)) around { get { …various replacement code… } }; at pointcut(callee(aioContent.removeTab)) before (aTab) { …various preprocessing… } Get a reference to the main window • When are aspects successfully woven? • When should aspects be prohibited? Alias the removeTab function Advise field accesses explicitly Add before advice to the function Come to OOPSLA for more details
Conclusion • Browser extensions are here to stay • Programming them needs our help • Two potential techniques: • UI: compositional overlays • Code: aspects