(function() {
    /*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

function defineCommonExtensionSymbols(apiPrivate)
{
    if (!apiPrivate.audits)
        apiPrivate.audits = {};
    apiPrivate.audits.Severity = {
        Info: "info",
        Warning: "warning",
        Severe: "severe"
    };

    if (!apiPrivate.panels)
        apiPrivate.panels = {};
    apiPrivate.panels.SearchAction = {
        CancelSearch: "cancelSearch",
        PerformSearch: "performSearch",
        NextSearchResult: "nextSearchResult",
        PreviousSearchResult: "previousSearchResult"
    };

    apiPrivate.Events = {
        AuditStarted: "audit-started-",
        ButtonClicked: "button-clicked-",
        PanelObjectSelected: "panel-objectSelected-",
        NetworkRequestFinished: "network-request-finished",
        OpenResource: "open-resource",
        PanelSearch: "panel-search-",
        ResourceAdded: "resource-added",
        ResourceContentCommitted: "resource-content-committed",
        ViewShown: "view-shown-",
        ViewHidden: "view-hidden-"
    };

    apiPrivate.Commands = {
        AddAuditCategory: "addAuditCategory",
        AddAuditResult: "addAuditResult",
        AddRequestHeaders: "addRequestHeaders",
        ApplyStyleSheet: "applyStyleSheet",
        CreatePanel: "createPanel",
        CreateSidebarPane: "createSidebarPane",
        CreateToolbarButton: "createToolbarButton",
        EvaluateOnInspectedPage: "evaluateOnInspectedPage",
        ForwardKeyboardEvent: "_forwardKeyboardEvent",
        GetHAR: "getHAR",
        GetPageResources: "getPageResources",
        GetRequestContent: "getRequestContent",
        GetResourceContent: "getResourceContent",
        InspectedURLChanged: "inspectedURLChanged",
        OpenResource: "openResource",
        Reload: "Reload",
        Subscribe: "subscribe",
        SetOpenResourceHandler: "setOpenResourceHandler",
        SetResourceContent: "setResourceContent",
        SetSidebarContent: "setSidebarContent",
        SetSidebarHeight: "setSidebarHeight",
        SetSidebarPage: "setSidebarPage",
        ShowPanel: "showPanel",
        StopAuditCategoryRun: "stopAuditCategoryRun",
        Unsubscribe: "unsubscribe",
        UpdateAuditProgress: "updateAuditProgress",
        UpdateButton: "updateButton"
    };
}

/**
 * @param {number} injectedScriptId
 * @return {!Object}
 * @suppressGlobalPropertiesCheck
 */
function injectedExtensionAPI(injectedScriptId)
{

var apiPrivate = {};

defineCommonExtensionSymbols(apiPrivate);

var commands = apiPrivate.Commands;
var events = apiPrivate.Events;
var userAction = false;

// Here and below, all constructors are private to API implementation.
// For a public type Foo, if internal fields are present, these are on
// a private FooImpl type, an instance of FooImpl is used in a closure
// by Foo consutrctor to re-bind publicly exported members to an instance
// of Foo.

/**
 * @constructor
 */
function EventSinkImpl(type, customDispatch)
{
    this._type = type;
    this._listeners = [];
    this._customDispatch = customDispatch;
}

EventSinkImpl.prototype = {
    addListener: function(callback)
    {
        if (typeof callback !== "function")
            throw "addListener: callback is not a function";
        if (this._listeners.length === 0)
            extensionServer.sendRequest({ command: commands.Subscribe, type: this._type });
        this._listeners.push(callback);
        extensionServer.registerHandler("notify-" + this._type, this._dispatch.bind(this));
    },

    removeListener: function(callback)
    {
        var listeners = this._listeners;

        for (var i = 0; i < listeners.length; ++i) {
            if (listeners[i] === callback) {
                listeners.splice(i, 1);
                break;
            }
        }
        if (this._listeners.length === 0)
            extensionServer.sendRequest({ command: commands.Unsubscribe, type: this._type });
    },

    /**
     * @param {...} vararg
     */
    _fire: function(vararg)
    {
        var listeners = this._listeners.slice();
        for (var i = 0; i < listeners.length; ++i)
            listeners[i].apply(null, arguments);
    },

    _dispatch: function(request)
    {
         if (this._customDispatch)
             this._customDispatch.call(this, request);
         else
             this._fire.apply(this, request.arguments);
    }
}

/**
 * @constructor
 */
function InspectorExtensionAPI()
{
    this.audits = new Audits();
    this.inspectedWindow = new InspectedWindow();
    this.panels = new Panels();
    this.network = new Network();
    defineDeprecatedProperty(this, "webInspector", "resources", "network");
}

/**
 * @constructor
 */
function Network()
{
    /**
     * @this {EventSinkImpl}
     */
    function dispatchRequestEvent(message)
    {
        var request = message.arguments[1];
        request.__proto__ = new Request(message.arguments[0]);
        this._fire(request);
    }
    this.onRequestFinished = new EventSink(events.NetworkRequestFinished, dispatchRequestEvent);
    defineDeprecatedProperty(this, "network", "onFinished", "onRequestFinished");
    this.onNavigated = new EventSink(events.InspectedURLChanged);
}

Network.prototype = {
    getHAR: function(callback)
    {
        function callbackWrapper(result)
        {
            var entries = (result && result.entries) || [];
            for (var i = 0; i < entries.length; ++i) {
                entries[i].__proto__ = new Request(entries[i]._requestId);
                delete entries[i]._requestId;
            }
            callback(result);
        }
        extensionServer.sendRequest({ command: commands.GetHAR }, callback && callbackWrapper);
    },

    addRequestHeaders: function(headers)
    {
        extensionServer.sendRequest({ command: commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname });
    }
}

/**
 * @constructor
 */
function RequestImpl(id)
{
    this._id = id;
}

RequestImpl.prototype = {
    getContent: function(callback)
    {
        function callbackWrapper(response)
        {
            callback(response.content, response.encoding);
        }
        extensionServer.sendRequest({ command: commands.GetRequestContent, id: this._id }, callback && callbackWrapper);
    }
}

/**
 * @constructor
 */
function Panels()
{
    var panels = {
        elements: new ElementsPanel(),
        sources: new SourcesPanel(),
    };

    function panelGetter(name)
    {
        return panels[name];
    }
    for (var panel in panels)
        this.__defineGetter__(panel, panelGetter.bind(null, panel));
    this.applyStyleSheet = function(styleSheet) { extensionServer.sendRequest({ command: commands.ApplyStyleSheet, styleSheet: styleSheet }); };
}

Panels.prototype = {
    create: function(title, icon, page, callback)
    {
        var id = "extension-panel-" + extensionServer.nextObjectId();
        var request = {
            command: commands.CreatePanel,
            id: id,
            title: title,
            icon: icon,
            page: page
        };
        extensionServer.sendRequest(request, callback && callback.bind(this, new ExtensionPanel(id)));
    },

    setOpenResourceHandler: function(callback)
    {
        var hadHandler = extensionServer.hasHandler(events.OpenResource);

        function callbackWrapper(message)
        {
            // Allow the panel to show itself when handling the event.
            userAction = true;
            try {
                callback.call(null, new Resource(message.resource), message.lineNumber);
            } finally {
                userAction = false;
            }
        }

        if (!callback)
            extensionServer.unregisterHandler(events.OpenResource);
        else
            extensionServer.registerHandler(events.OpenResource, callbackWrapper);

        // Only send command if we either removed an existing handler or added handler and had none before.
        if (hadHandler === !callback)
            extensionServer.sendRequest({ command: commands.SetOpenResourceHandler, "handlerPresent": !!callback });
    },

    openResource: function(url, lineNumber, callback)
    {
        extensionServer.sendRequest({ command: commands.OpenResource, "url": url, "lineNumber": lineNumber }, callback);
    },

    get SearchAction()
    {
        return apiPrivate.panels.SearchAction;
    }
}

/**
 * @constructor
 */
function ExtensionViewImpl(id)
{
    this._id = id;

    /**
     * @this {EventSinkImpl}
     */
    function dispatchShowEvent(message)
    {
        var frameIndex = message.arguments[0];
        if (typeof frameIndex === "number")
            this._fire(window.parent.frames[frameIndex]);
        else
            this._fire();
    }

    if (id) {
        this.onShown = new EventSink(events.ViewShown + id, dispatchShowEvent);
        this.onHidden = new EventSink(events.ViewHidden + id);
    }
}

/**
 * @constructor
 * @extends {ExtensionViewImpl}
 * @param {string} hostPanelName
 */
function PanelWithSidebarImpl(hostPanelName)
{
    ExtensionViewImpl.call(this, null);
    this._hostPanelName = hostPanelName;
    this.onSelectionChanged = new EventSink(events.PanelObjectSelected + hostPanelName);
}

PanelWithSidebarImpl.prototype = {
    createSidebarPane: function(title, callback)
    {
        var id = "extension-sidebar-" + extensionServer.nextObjectId();
        var request = {
            command: commands.CreateSidebarPane,
            panel: this._hostPanelName,
            id: id,
            title: title
        };
        function callbackWrapper()
        {
            callback(new ExtensionSidebarPane(id));
        }
        extensionServer.sendRequest(request, callback && callbackWrapper);
    },

    __proto__: ExtensionViewImpl.prototype
}

function declareInterfaceClass(implConstructor)
{
    return function()
    {
        var impl = { __proto__: implConstructor.prototype };
        implConstructor.apply(impl, arguments);
        populateInterfaceClass(this, impl);
    };
}

function defineDeprecatedProperty(object, className, oldName, newName)
{
    var warningGiven = false;
    function getter()
    {
        if (!warningGiven) {
            console.warn(className + "." + oldName + " is deprecated. Use " + className + "." + newName + " instead");
            warningGiven = true;
        }
        return object[newName];
    }
    object.__defineGetter__(oldName, getter);
}

function extractCallbackArgument(args)
{
    var lastArgument = args[args.length - 1];
    return typeof lastArgument === "function" ? lastArgument : undefined;
}

var AuditCategory = declareInterfaceClass(AuditCategoryImpl);
var AuditResult = declareInterfaceClass(AuditResultImpl);
var Button = declareInterfaceClass(ButtonImpl);
var EventSink = declareInterfaceClass(EventSinkImpl);
var ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
var ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
var PanelWithSidebar = declareInterfaceClass(PanelWithSidebarImpl);
var Request = declareInterfaceClass(RequestImpl);
var Resource = declareInterfaceClass(ResourceImpl);

/**
 * @constructor
 * @extends {PanelWithSidebar}
 */
function ElementsPanel()
{
    PanelWithSidebar.call(this, "elements");
}

ElementsPanel.prototype = {
    __proto__: PanelWithSidebar.prototype
}

/**
 * @constructor
 * @extends {PanelWithSidebar}
 */
function SourcesPanel()
{
    PanelWithSidebar.call(this, "sources");
}

SourcesPanel.prototype = {
    __proto__: PanelWithSidebar.prototype
}

/**
 * @constructor
 * @extends {ExtensionViewImpl}
 */
function ExtensionPanelImpl(id)
{
    ExtensionViewImpl.call(this, id);
    this.onSearch = new EventSink(events.PanelSearch + id);
}

ExtensionPanelImpl.prototype = {
    /**
     * @return {!Object}
     */
    createStatusBarButton: function(iconPath, tooltipText, disabled)
    {
        var id = "button-" + extensionServer.nextObjectId();
        var request = {
            command: commands.CreateToolbarButton,
            panel: this._id,
            id: id,
            icon: iconPath,
            tooltip: tooltipText,
            disabled: !!disabled
        };
        extensionServer.sendRequest(request);
        return new Button(id);
    },

    show: function()
    {
        if (!userAction)
            return;

        var request = {
            command: commands.ShowPanel,
            id: this._id
        };
        extensionServer.sendRequest(request);
    },

    __proto__: ExtensionViewImpl.prototype
}

/**
 * @constructor
 * @extends {ExtensionViewImpl}
 */
function ExtensionSidebarPaneImpl(id)
{
    ExtensionViewImpl.call(this, id);
}

ExtensionSidebarPaneImpl.prototype = {
    setHeight: function(height)
    {
        extensionServer.sendRequest({ command: commands.SetSidebarHeight, id: this._id, height: height });
    },

    setExpression: function(expression, rootTitle, evaluateOptions)
    {
        var request = {
            command: commands.SetSidebarContent,
            id: this._id,
            expression: expression,
            rootTitle: rootTitle,
            evaluateOnPage: true,
        };
        if (typeof evaluateOptions === "object")
            request.evaluateOptions = evaluateOptions;
        extensionServer.sendRequest(request, extractCallbackArgument(arguments));
    },

    setObject: function(jsonObject, rootTitle, callback)
    {
        extensionServer.sendRequest({ command: commands.SetSidebarContent, id: this._id, expression: jsonObject, rootTitle: rootTitle }, callback);
    },

    setPage: function(page)
    {
        extensionServer.sendRequest({ command: commands.SetSidebarPage, id: this._id, page: page });
    },

    __proto__: ExtensionViewImpl.prototype
}

/**
 * @constructor
 */
function ButtonImpl(id)
{
    this._id = id;
    this.onClicked = new EventSink(events.ButtonClicked + id);
}

ButtonImpl.prototype = {
    update: function(iconPath, tooltipText, disabled)
    {
        var request = {
            command: commands.UpdateButton,
            id: this._id,
            icon: iconPath,
            tooltip: tooltipText,
            disabled: !!disabled
        };
        extensionServer.sendRequest(request);
    }
};

/**
 * @constructor
 */
function Audits()
{
}

Audits.prototype = {
    /**
     * @return {!AuditCategory}
     */
    addCategory: function(displayName, resultCount)
    {
        var id = "extension-audit-category-" + extensionServer.nextObjectId();
        if (typeof resultCount !== "undefined")
            console.warn("Passing resultCount to audits.addCategory() is deprecated. Use AuditResult.updateProgress() instead.");
        extensionServer.sendRequest({ command: commands.AddAuditCategory, id: id, displayName: displayName, resultCount: resultCount });
        return new AuditCategory(id);
    }
}

/**
 * @constructor
 */
function AuditCategoryImpl(id)
{
    /**
     * @this {EventSinkImpl}
     */
    function dispatchAuditEvent(request)
    {
        var auditResult = new AuditResult(request.arguments[0]);
        try {
            this._fire(auditResult);
        } catch (e) {
            console.error("Uncaught exception in extension audit event handler: " + e);
            auditResult.done();
        }
    }
    this._id = id;
    this.onAuditStarted = new EventSink(events.AuditStarted + id, dispatchAuditEvent);
}

/**
 * @constructor
 */
function AuditResultImpl(id)
{
    this._id = id;

    this.createURL = this._nodeFactory.bind(this, "url");
    this.createSnippet = this._nodeFactory.bind(this, "snippet");
    this.createText = this._nodeFactory.bind(this, "text");
    this.createObject = this._nodeFactory.bind(this, "object");
    this.createNode = this._nodeFactory.bind(this, "node");
}

AuditResultImpl.prototype = {
    addResult: function(displayName, description, severity, details)
    {
        // shorthand for specifying details directly in addResult().
        if (details && !(details instanceof AuditResultNode))
            details = new AuditResultNode(Array.isArray(details) ? details : [details]);

        var request = {
            command: commands.AddAuditResult,
            resultId: this._id,
            displayName: displayName,
            description: description,
            severity: severity,
            details: details
        };
        extensionServer.sendRequest(request);
    },

    /**
     * @return {!Object}
     */
    createResult: function()
    {
        return new AuditResultNode(Array.prototype.slice.call(arguments));
    },

    updateProgress: function(worked, totalWork)
    {
        extensionServer.sendRequest({ command: commands.UpdateAuditProgress, resultId: this._id, progress: worked / totalWork });
    },

    done: function()
    {
        extensionServer.sendRequest({ command: commands.StopAuditCategoryRun, resultId: this._id });
    },

    /**
     * @type {!Object.<string, string>}
     */
    get Severity()
    {
        return apiPrivate.audits.Severity;
    },

    /**
     * @return {!{type: string, arguments: !Array.<string|number>}}
     */
    createResourceLink: function(url, lineNumber)
    {
        return {
            type: "resourceLink",
            arguments: [url, lineNumber && lineNumber - 1]
        };
    },

    /**
     * @return {!{type: string, arguments: !Array.<string|number>}}
     */
    _nodeFactory: function(type)
    {
        return {
            type: type,
            arguments: Array.prototype.slice.call(arguments, 1)
        };
    }
}

/**
 * @constructor
 */
function AuditResultNode(contents)
{
    this.contents = contents;
    this.children = [];
    this.expanded = false;
}

AuditResultNode.prototype = {
    /**
     * @return {!Object}
     */
    addChild: function()
    {
        var node = new AuditResultNode(Array.prototype.slice.call(arguments));
        this.children.push(node);
        return node;
    }
};

/**
 * @constructor
 */
function InspectedWindow()
{
    /**
     * @this {EventSinkImpl}
     */
    function dispatchResourceEvent(message)
    {
        this._fire(new Resource(message.arguments[0]));
    }

    /**
     * @this {EventSinkImpl}
     */
    function dispatchResourceContentEvent(message)
    {
        this._fire(new Resource(message.arguments[0]), message.arguments[1]);
    }

    this.onResourceAdded = new EventSink(events.ResourceAdded, dispatchResourceEvent);
    this.onResourceContentCommitted = new EventSink(events.ResourceContentCommitted, dispatchResourceContentEvent);
}

InspectedWindow.prototype = {
    reload: function(optionsOrUserAgent)
    {
        var options = null;
        if (typeof optionsOrUserAgent === "object") {
            options = optionsOrUserAgent;
        } else if (typeof optionsOrUserAgent === "string") {
            options = { userAgent: optionsOrUserAgent };
            console.warn("Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. " +
                         "Use inspectedWindow.reload({ userAgent: value}) instead.");
        }
        extensionServer.sendRequest({ command: commands.Reload, options: options });
    },

    /**
     * @return {?Object}
     */
    eval: function(expression, evaluateOptions)
    {
        var callback = extractCallbackArgument(arguments);
        function callbackWrapper(result)
        {
            if (result.isError || result.isException)
                callback(undefined, result);
            else
                callback(result.value);
        }
        var request = {
            command: commands.EvaluateOnInspectedPage,
            expression: expression
        };
        if (typeof evaluateOptions === "object")
            request.evaluateOptions = evaluateOptions;
        extensionServer.sendRequest(request, callback && callbackWrapper);
        return null;
    },

    getResources: function(callback)
    {
        function wrapResource(resourceData)
        {
            return new Resource(resourceData);
        }
        function callbackWrapper(resources)
        {
            callback(resources.map(wrapResource));
        }
        extensionServer.sendRequest({ command: commands.GetPageResources }, callback && callbackWrapper);
    }
}

/**
 * @constructor
 */
function ResourceImpl(resourceData)
{
    this._url = resourceData.url;
    this._type = resourceData.type;
}

ResourceImpl.prototype = {
    get url()
    {
        return this._url;
    },

    get type()
    {
        return this._type;
    },

    getContent: function(callback)
    {
        function callbackWrapper(response)
        {
            callback(response.content, response.encoding);
        }

        extensionServer.sendRequest({ command: commands.GetResourceContent, url: this._url }, callback && callbackWrapper);
    },

    setContent: function(content, commit, callback)
    {
        extensionServer.sendRequest({ command: commands.SetResourceContent, url: this._url, content: content, commit: commit }, callback);
    }
}

var keyboardEventRequestQueue = [];
var forwardTimer = null;

function forwardKeyboardEvent(event)
{
    const Esc = "U+001B";
    // We only care about global hotkeys, not about random text
    if (!event.ctrlKey && !event.altKey && !event.metaKey && !/^F\d+$/.test(event.key) && event.key !== Esc)
        return;
    var requestPayload = {
        eventType: event.type,
        ctrlKey: event.ctrlKey,
        altKey: event.altKey,
        metaKey: event.metaKey,
        key: event.key,
        location: event.location,
        keyCode: event.keyCode
    };
    keyboardEventRequestQueue.push(requestPayload);
    if (!forwardTimer)
        forwardTimer = setTimeout(forwardEventQueue, 0);
}

function forwardEventQueue()
{
    forwardTimer = null;
    var request = {
        command: commands.ForwardKeyboardEvent,
        entries: keyboardEventRequestQueue
    };
    extensionServer.sendRequest(request);
    keyboardEventRequestQueue = [];
}

document.addEventListener("keydown", forwardKeyboardEvent, false);
document.addEventListener("keypress", forwardKeyboardEvent, false);

/**
 * @constructor
 */
function ExtensionServerClient()
{
    this._callbacks = {};
    this._handlers = {};
    this._lastRequestId = 0;
    this._lastObjectId = 0;

    this.registerHandler("callback", this._onCallback.bind(this));

    var channel = new MessageChannel();
    this._port = channel.port1;
    this._port.addEventListener("message", this._onMessage.bind(this), false);
    this._port.start();

    window.parent.postMessage("registerExtension", [ channel.port2 ], "*");
}

ExtensionServerClient.prototype = {
    /**
     * @param {!Object} message
     * @param {function()=} callback
     */
    sendRequest: function(message, callback)
    {
        if (typeof callback === "function")
            message.requestId = this._registerCallback(callback);
        this._port.postMessage(message);
    },

    /**
     * @return {boolean}
     */
    hasHandler: function(command)
    {
        return !!this._handlers[command];
    },

    registerHandler: function(command, handler)
    {
        this._handlers[command] = handler;
    },

    unregisterHandler: function(command)
    {
        delete this._handlers[command];
    },

    /**
     * @return {string}
     */
    nextObjectId: function()
    {
        return injectedScriptId.toString() + "_" + ++this._lastObjectId;
    },

    _registerCallback: function(callback)
    {
        var id = ++this._lastRequestId;
        this._callbacks[id] = callback;
        return id;
    },

    _onCallback: function(request)
    {
        if (request.requestId in this._callbacks) {
            var callback = this._callbacks[request.requestId];
            delete this._callbacks[request.requestId];
            callback(request.result);
        }
    },

    _onMessage: function(event)
    {
        var request = event.data;
        var handler = this._handlers[request.command];
        if (handler)
            handler.call(this, request);
    }
}

function populateInterfaceClass(interfaze, implementation)
{
    for (var member in implementation) {
        if (member.charAt(0) === "_")
            continue;
        var descriptor = null;
        // Traverse prototype chain until we find the owner.
        for (var owner = implementation; owner && !descriptor; owner = owner.__proto__)
            descriptor = Object.getOwnPropertyDescriptor(owner, member);
        if (!descriptor)
            continue;
        if (typeof descriptor.value === "function")
            interfaze[member] = descriptor.value.bind(implementation);
        else if (typeof descriptor.get === "function")
            interfaze.__defineGetter__(member, descriptor.get.bind(implementation));
        else
            Object.defineProperty(interfaze, member, descriptor);
    }
}

// extensionServer is a closure variable defined by the glue below -- make sure we fail if it's not there.
if (!extensionServer)
    extensionServer = new ExtensionServerClient();

return new InspectorExtensionAPI();
}

/**
 * @suppress {checkVars, checkTypes}
 */
function platformExtensionAPI(coreAPI)
{
    function getTabId()
    {
        return tabId;
    }
    chrome = window.chrome || {};
    // Override chrome.devtools as a workaround for a error-throwing getter being exposed
    // in extension pages loaded into a non-extension process (only happens for remote client
    // extensions)
    var devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, "devtools");
    if (!devtools_descriptor || devtools_descriptor.get)
        Object.defineProperty(chrome, "devtools", { value: {}, enumerable: true });
    // Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.inspectedWindow.
    chrome.devtools.inspectedWindow = {};
    chrome.devtools.inspectedWindow.__defineGetter__("tabId", getTabId);
    chrome.devtools.inspectedWindow.__proto__ = coreAPI.inspectedWindow;
    chrome.devtools.network = coreAPI.network;
    chrome.devtools.panels = coreAPI.panels;

    // default to expose experimental APIs for now.
    if (extensionInfo.exposeExperimentalAPIs !== false) {
        chrome.experimental = chrome.experimental || {};
        chrome.experimental.devtools = chrome.experimental.devtools || {};

        var properties = Object.getOwnPropertyNames(coreAPI);
        for (var i = 0; i < properties.length; ++i) {
            var descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i]);
            Object.defineProperty(chrome.experimental.devtools, properties[i], descriptor);
        }
        chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWindow;
    }
    if (extensionInfo.exposeWebInspectorNamespace)
        window.webInspector = coreAPI;
}

/**
 * @param {!ExtensionDescriptor} extensionInfo
 * @param {string} inspectedTabId
 * @return {string}
 */
function buildPlatformExtensionAPI(extensionInfo, inspectedTabId)
{
    return "var extensionInfo = " + JSON.stringify(extensionInfo) + ";" +
       "var tabId = " + inspectedTabId + ";" +
       platformExtensionAPI.toString();
}

/**
 * @param {!ExtensionDescriptor} extensionInfo
 * @param {string} inspectedTabId
 * @return {string}
 */
function buildExtensionAPIInjectedScript(extensionInfo, inspectedTabId)
{
    return "(function(injectedScriptId){ " +
        "var extensionServer;" +
        defineCommonExtensionSymbols.toString() + ";" +
        injectedExtensionAPI.toString() + ";" +
        buildPlatformExtensionAPI(extensionInfo, inspectedTabId) + ";" +
        "platformExtensionAPI(injectedExtensionAPI(injectedScriptId));" +
        "return {};" +
        "})";
}

        var tabId;
        var extensionInfo = {};
        var extensionServer;
        platformExtensionAPI(injectedExtensionAPI("remote-" + window.parent.frames.length));
    })();