Refactor UI interface to allow dynamically adding tabs

An example of how this is done is in `org.apache.spark.ui.FooTab`, which should be deleted before we merge this into master.