Merge from Chromium at DEPS revision r198571

This commit was generated by merge_to_master.py.

Change-Id: I3a7f89ea6b8c017335bd52739166aed708cad1e5
diff --git a/Source/core/inspector/BindingVisitors.h b/Source/core/inspector/BindingVisitors.h
new file mode 100644
index 0000000..c885703
--- /dev/null
+++ b/Source/core/inspector/BindingVisitors.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2011 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef BindingVisitors_h
+#define BindingVisitors_h
+
+namespace WTF {
+class ArrayBufferView;
+class StringImpl;
+}
+
+namespace WebCore {
+
+class Node;
+
+class WrappedNodeVisitor {
+public:
+    virtual void visitNode(Node*) = 0;
+protected:
+    virtual ~WrappedNodeVisitor() { }
+};
+
+class ExternalStringVisitor {
+public:
+    virtual void visitJSExternalString(WTF::StringImpl*) = 0;
+protected:
+    virtual ~ExternalStringVisitor() { }
+};
+
+
+class ExternalArrayVisitor {
+public:
+    virtual void visitJSExternalArray(WTF::ArrayBufferView*) = 0;
+protected:
+    virtual ~ExternalArrayVisitor() { }
+};
+
+} // namespace WebCore
+
+#endif // BindingVisitors_h
diff --git a/Source/core/inspector/CodeGeneratorInspector.py b/Source/core/inspector/CodeGeneratorInspector.py
new file mode 100755
index 0000000..481682b
--- /dev/null
+++ b/Source/core/inspector/CodeGeneratorInspector.py
@@ -0,0 +1,2268 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Copyright (c) 2012 Intel Corporation. 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.
+
+import os.path
+import sys
+import string
+import optparse
+import re
+try:
+    import json
+except ImportError:
+    import simplejson as json
+
+import CodeGeneratorInspectorStrings
+
+# Manually-filled map of type name replacements.
+TYPE_NAME_FIX_MAP = {
+    "RGBA": "Rgba",  # RGBA is reported to be conflicting with a define name in Windows CE.
+    "": "Empty",
+}
+
+
+TYPES_WITH_RUNTIME_CAST_SET = frozenset(["Runtime.RemoteObject", "Runtime.PropertyDescriptor", "Runtime.InternalPropertyDescriptor",
+                                         "Debugger.FunctionDetails", "Debugger.CallFrame",
+                                         "Canvas.TraceLog", "Canvas.ResourceInfo", "Canvas.ResourceState",
+                                         # This should be a temporary hack. TimelineEvent should be created via generated C++ API.
+                                         "Timeline.TimelineEvent"])
+
+TYPES_WITH_OPEN_FIELD_LIST_SET = frozenset(["Timeline.TimelineEvent",
+                                            # InspectorStyleSheet not only creates this property but wants to read it and modify it.
+                                            "CSS.CSSProperty",
+                                            # InspectorResourceAgent needs to update mime-type.
+                                            "Network.Response"])
+
+EXACTLY_INT_SUPPORTED = False
+
+cmdline_parser = optparse.OptionParser()
+cmdline_parser.add_option("--output_h_dir")
+cmdline_parser.add_option("--output_cpp_dir")
+
+try:
+    arg_options, arg_values = cmdline_parser.parse_args()
+    if (len(arg_values) != 1):
+        raise Exception("Exactly one plain argument expected (found %s)" % len(arg_values))
+    input_json_filename = arg_values[0]
+    output_header_dirname = arg_options.output_h_dir
+    output_cpp_dirname = arg_options.output_cpp_dir
+    if not output_header_dirname:
+        raise Exception("Output .h directory must be specified")
+    if not output_cpp_dirname:
+        raise Exception("Output .cpp directory must be specified")
+except Exception:
+    # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html
+    exc = sys.exc_info()[1]
+    sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc)
+    sys.stderr.write("Usage: <script> protocol.json --output_h_dir <output_header_dir> --output_cpp_dir <output_cpp_dir>\n")
+    exit(1)
+
+
+# FIXME: move this methods under Capitalizer class below and remove duplications.
+def dash_to_camelcase(word):
+    return ''.join(x.capitalize() or '-' for x in word.split('-'))
+
+
+def fix_camel_case(name):
+    refined = re.sub(r'-(\w)', lambda pat: pat.group(1).upper(), name)
+    refined = to_title_case(refined)
+    return re.sub(r'(?i)HTML|XML|WML|API', lambda pat: pat.group(0).upper(), refined)
+
+
+def to_title_case(name):
+    return name[:1].upper() + name[1:]
+
+
+class Capitalizer:
+    @staticmethod
+    def lower_camel_case_to_upper(str):
+        if len(str) > 0 and str[0].islower():
+            str = str[0].upper() + str[1:]
+        return str
+
+    @staticmethod
+    def upper_camel_case_to_lower(str):
+        pos = 0
+        while pos < len(str) and str[pos].isupper():
+            pos += 1
+        if pos == 0:
+            return str
+        if pos == 1:
+            return str[0].lower() + str[1:]
+        if pos < len(str):
+            pos -= 1
+        possible_abbreviation = str[0:pos]
+        if possible_abbreviation not in Capitalizer.ABBREVIATION:
+            raise Exception("Unknown abbreviation %s" % possible_abbreviation)
+        str = possible_abbreviation.lower() + str[pos:]
+        return str
+
+    @staticmethod
+    def camel_case_to_capitalized_with_underscores(str):
+        if len(str) == 0:
+            return str
+        output = Capitalizer.split_camel_case_(str)
+        return "_".join(output).upper()
+
+    @staticmethod
+    def split_camel_case_(str):
+        output = []
+        pos_being = 0
+        pos = 1
+        has_oneletter = False
+        while pos < len(str):
+            if str[pos].isupper():
+                output.append(str[pos_being:pos].upper())
+                if pos - pos_being == 1:
+                    has_oneletter = True
+                pos_being = pos
+            pos += 1
+        output.append(str[pos_being:])
+        if has_oneletter:
+            array_pos = 0
+            while array_pos < len(output) - 1:
+                if len(output[array_pos]) == 1:
+                    array_pos_end = array_pos + 1
+                    while array_pos_end < len(output) and len(output[array_pos_end]) == 1:
+                        array_pos_end += 1
+                    if array_pos_end - array_pos > 1:
+                        possible_abbreviation = "".join(output[array_pos:array_pos_end])
+                        if possible_abbreviation.upper() in Capitalizer.ABBREVIATION:
+                            output[array_pos:array_pos_end] = [possible_abbreviation]
+                        else:
+                            array_pos = array_pos_end - 1
+                array_pos += 1
+        return output
+
+    ABBREVIATION = frozenset(["XHR", "DOM", "CSS"])
+
+VALIDATOR_IFDEF_NAME = "!ASSERT_DISABLED"
+
+
+class DomainNameFixes:
+    @classmethod
+    def get_fixed_data(cls, domain_name):
+        field_name_res = Capitalizer.upper_camel_case_to_lower(domain_name) + "Agent"
+
+        class Res(object):
+            agent_field_name = field_name_res
+
+        return Res
+
+
+class RawTypes(object):
+    @staticmethod
+    def get(json_type):
+        if json_type == "boolean":
+            return RawTypes.Bool
+        elif json_type == "string":
+            return RawTypes.String
+        elif json_type == "array":
+            return RawTypes.Array
+        elif json_type == "object":
+            return RawTypes.Object
+        elif json_type == "integer":
+            return RawTypes.Int
+        elif json_type == "number":
+            return RawTypes.Number
+        elif json_type == "any":
+            return RawTypes.Any
+        else:
+            raise Exception("Unknown type: %s" % json_type)
+
+    # For output parameter all values are passed by pointer except RefPtr-based types.
+    class OutputPassModel:
+        class ByPointer:
+            @staticmethod
+            def get_argument_prefix():
+                return "&"
+
+            @staticmethod
+            def get_parameter_type_suffix():
+                return "*"
+
+        class ByReference:
+            @staticmethod
+            def get_argument_prefix():
+                return ""
+
+            @staticmethod
+            def get_parameter_type_suffix():
+                return "&"
+
+    class BaseType(object):
+        need_internal_runtime_cast_ = False
+
+        @classmethod
+        def request_raw_internal_runtime_cast(cls):
+            if not cls.need_internal_runtime_cast_:
+                cls.need_internal_runtime_cast_ = True
+
+        @classmethod
+        def get_raw_validator_call_text(cls):
+            return "RuntimeCastHelper::assertType<InspectorValue::Type%s>" % cls.get_validate_method_params().template_type
+
+    class String(BaseType):
+        @staticmethod
+        def get_getter_name():
+            return "String"
+
+        get_setter_name = get_getter_name
+
+        @staticmethod
+        def get_c_initializer():
+            return "\"\""
+
+        @staticmethod
+        def get_validate_method_params():
+            class ValidateMethodParams:
+                template_type = "String"
+            return ValidateMethodParams
+
+        @staticmethod
+        def get_output_pass_model():
+            return RawTypes.OutputPassModel.ByPointer
+
+        @staticmethod
+        def is_heavy_value():
+            return True
+
+        @staticmethod
+        def get_array_item_raw_c_type_text():
+            return "String"
+
+        @staticmethod
+        def get_raw_type_model():
+            return TypeModel.String
+
+    class Int(BaseType):
+        @staticmethod
+        def get_getter_name():
+            return "Int"
+
+        @staticmethod
+        def get_setter_name():
+            return "Number"
+
+        @staticmethod
+        def get_c_initializer():
+            return "0"
+
+        @classmethod
+        def get_raw_validator_call_text(cls):
+            return "RuntimeCastHelper::assertInt"
+
+        @staticmethod
+        def get_output_pass_model():
+            return RawTypes.OutputPassModel.ByPointer
+
+        @staticmethod
+        def is_heavy_value():
+            return False
+
+        @staticmethod
+        def get_array_item_raw_c_type_text():
+            return "int"
+
+        @staticmethod
+        def get_raw_type_model():
+            return TypeModel.Int
+
+    class Number(BaseType):
+        @staticmethod
+        def get_getter_name():
+            return "Double"
+
+        @staticmethod
+        def get_setter_name():
+            return "Number"
+
+        @staticmethod
+        def get_c_initializer():
+            return "0"
+
+        @staticmethod
+        def get_validate_method_params():
+            class ValidateMethodParams:
+                template_type = "Number"
+            return ValidateMethodParams
+
+        @staticmethod
+        def get_output_pass_model():
+            return RawTypes.OutputPassModel.ByPointer
+
+        @staticmethod
+        def is_heavy_value():
+            return False
+
+        @staticmethod
+        def get_array_item_raw_c_type_text():
+            return "double"
+
+        @staticmethod
+        def get_raw_type_model():
+            return TypeModel.Number
+
+    class Bool(BaseType):
+        @staticmethod
+        def get_getter_name():
+            return "Boolean"
+
+        get_setter_name = get_getter_name
+
+        @staticmethod
+        def get_c_initializer():
+            return "false"
+
+        @staticmethod
+        def get_validate_method_params():
+            class ValidateMethodParams:
+                template_type = "Boolean"
+            return ValidateMethodParams
+
+        @staticmethod
+        def get_output_pass_model():
+            return RawTypes.OutputPassModel.ByPointer
+
+        @staticmethod
+        def is_heavy_value():
+            return False
+
+        @staticmethod
+        def get_array_item_raw_c_type_text():
+            return "bool"
+
+        @staticmethod
+        def get_raw_type_model():
+            return TypeModel.Bool
+
+    class Object(BaseType):
+        @staticmethod
+        def get_getter_name():
+            return "Object"
+
+        @staticmethod
+        def get_setter_name():
+            return "Value"
+
+        @staticmethod
+        def get_c_initializer():
+            return "InspectorObject::create()"
+
+        @staticmethod
+        def get_output_argument_prefix():
+            return ""
+
+        @staticmethod
+        def get_validate_method_params():
+            class ValidateMethodParams:
+                template_type = "Object"
+            return ValidateMethodParams
+
+        @staticmethod
+        def get_output_pass_model():
+            return RawTypes.OutputPassModel.ByReference
+
+        @staticmethod
+        def is_heavy_value():
+            return True
+
+        @staticmethod
+        def get_array_item_raw_c_type_text():
+            return "InspectorObject"
+
+        @staticmethod
+        def get_raw_type_model():
+            return TypeModel.Object
+
+    class Any(BaseType):
+        @staticmethod
+        def get_getter_name():
+            return "Value"
+
+        get_setter_name = get_getter_name
+
+        @staticmethod
+        def get_c_initializer():
+            raise Exception("Unsupported")
+
+        @staticmethod
+        def get_raw_validator_call_text():
+            return "RuntimeCastHelper::assertAny"
+
+        @staticmethod
+        def get_output_pass_model():
+            return RawTypes.OutputPassModel.ByReference
+
+        @staticmethod
+        def is_heavy_value():
+            return True
+
+        @staticmethod
+        def get_array_item_raw_c_type_text():
+            return "InspectorValue"
+
+        @staticmethod
+        def get_raw_type_model():
+            return TypeModel.Any
+
+    class Array(BaseType):
+        @staticmethod
+        def get_getter_name():
+            return "Array"
+
+        @staticmethod
+        def get_setter_name():
+            return "Value"
+
+        @staticmethod
+        def get_c_initializer():
+            return "InspectorArray::create()"
+
+        @staticmethod
+        def get_output_argument_prefix():
+            return ""
+
+        @staticmethod
+        def get_validate_method_params():
+            class ValidateMethodParams:
+                template_type = "Array"
+            return ValidateMethodParams
+
+        @staticmethod
+        def get_output_pass_model():
+            return RawTypes.OutputPassModel.ByReference
+
+        @staticmethod
+        def is_heavy_value():
+            return True
+
+        @staticmethod
+        def get_array_item_raw_c_type_text():
+            return "InspectorArray"
+
+        @staticmethod
+        def get_raw_type_model():
+            return TypeModel.Array
+
+
+def replace_right_shift(input_str):
+    return input_str.replace(">>", "> >")
+
+
+class CommandReturnPassModel:
+    class ByReference:
+        def __init__(self, var_type, set_condition):
+            self.var_type = var_type
+            self.set_condition = set_condition
+
+        def get_return_var_type(self):
+            return self.var_type
+
+        @staticmethod
+        def get_output_argument_prefix():
+            return ""
+
+        @staticmethod
+        def get_output_to_raw_expression():
+            return "%s"
+
+        def get_output_parameter_type(self):
+            return self.var_type + "&"
+
+        def get_set_return_condition(self):
+            return self.set_condition
+
+    class ByPointer:
+        def __init__(self, var_type):
+            self.var_type = var_type
+
+        def get_return_var_type(self):
+            return self.var_type
+
+        @staticmethod
+        def get_output_argument_prefix():
+            return "&"
+
+        @staticmethod
+        def get_output_to_raw_expression():
+            return "%s"
+
+        def get_output_parameter_type(self):
+            return self.var_type + "*"
+
+        @staticmethod
+        def get_set_return_condition():
+            return None
+
+    class OptOutput:
+        def __init__(self, var_type):
+            self.var_type = var_type
+
+        def get_return_var_type(self):
+            return "TypeBuilder::OptOutput<%s>" % self.var_type
+
+        @staticmethod
+        def get_output_argument_prefix():
+            return "&"
+
+        @staticmethod
+        def get_output_to_raw_expression():
+            return "%s.getValue()"
+
+        def get_output_parameter_type(self):
+            return "TypeBuilder::OptOutput<%s>*" % self.var_type
+
+        @staticmethod
+        def get_set_return_condition():
+            return "%s.isAssigned()"
+
+
+class TypeModel:
+    class RefPtrBased(object):
+        def __init__(self, class_name):
+            self.class_name = class_name
+            self.optional = False
+
+        def get_optional(self):
+            result = TypeModel.RefPtrBased(self.class_name)
+            result.optional = True
+            return result
+
+        def get_command_return_pass_model(self):
+            if self.optional:
+                set_condition = "%s"
+            else:
+                set_condition = None
+            return CommandReturnPassModel.ByReference(replace_right_shift("RefPtr<%s>" % self.class_name), set_condition)
+
+        def get_input_param_type_text(self):
+            return replace_right_shift("PassRefPtr<%s>" % self.class_name)
+
+        @staticmethod
+        def get_event_setter_expression_pattern():
+            return "%s"
+
+    class Enum(object):
+        def __init__(self, base_type_name):
+            self.type_name = base_type_name + "::Enum"
+
+        def get_optional(base_self):
+            class EnumOptional:
+                @classmethod
+                def get_optional(cls):
+                    return cls
+
+                @staticmethod
+                def get_command_return_pass_model():
+                    return CommandReturnPassModel.OptOutput(base_self.type_name)
+
+                @staticmethod
+                def get_input_param_type_text():
+                    return base_self.type_name + "*"
+
+                @staticmethod
+                def get_event_setter_expression_pattern():
+                    raise Exception("TODO")
+            return EnumOptional
+
+        def get_command_return_pass_model(self):
+            return CommandReturnPassModel.ByPointer(self.type_name)
+
+        def get_input_param_type_text(self):
+            return self.type_name
+
+        @staticmethod
+        def get_event_setter_expression_pattern():
+            return "%s"
+
+    class ValueType(object):
+        def __init__(self, type_name, is_heavy):
+            self.type_name = type_name
+            self.is_heavy = is_heavy
+
+        def get_optional(self):
+            return self.ValueOptional(self)
+
+        def get_command_return_pass_model(self):
+            return CommandReturnPassModel.ByPointer(self.type_name)
+
+        def get_input_param_type_text(self):
+            if self.is_heavy:
+                return "const %s&" % self.type_name
+            else:
+                return self.type_name
+
+        def get_opt_output_type_(self):
+            return self.type_name
+
+        @staticmethod
+        def get_event_setter_expression_pattern():
+            return "%s"
+
+        class ValueOptional:
+            def __init__(self, base):
+                self.base = base
+
+            def get_optional(self):
+                return self
+
+            def get_command_return_pass_model(self):
+                return CommandReturnPassModel.OptOutput(self.base.get_opt_output_type_())
+
+            def get_input_param_type_text(self):
+                return "const %s* const" % self.base.type_name
+
+            @staticmethod
+            def get_event_setter_expression_pattern():
+                return "*%s"
+
+    class ExactlyInt(ValueType):
+        def __init__(self):
+            TypeModel.ValueType.__init__(self, "int", False)
+
+        def get_input_param_type_text(self):
+            return "TypeBuilder::ExactlyInt"
+
+        def get_opt_output_type_(self):
+            return "TypeBuilder::ExactlyInt"
+
+    @classmethod
+    def init_class(cls):
+        cls.Bool = cls.ValueType("bool", False)
+        if EXACTLY_INT_SUPPORTED:
+            cls.Int = cls.ExactlyInt()
+        else:
+            cls.Int = cls.ValueType("int", False)
+        cls.Number = cls.ValueType("double", False)
+        cls.String = cls.ValueType("String", True,)
+        cls.Object = cls.RefPtrBased("InspectorObject")
+        cls.Array = cls.RefPtrBased("InspectorArray")
+        cls.Any = cls.RefPtrBased("InspectorValue")
+
+TypeModel.init_class()
+
+
+# Collection of InspectorObject class methods that are likely to be overloaded in generated class.
+# We must explicitly import all overloaded methods or they won't be available to user.
+INSPECTOR_OBJECT_SETTER_NAMES = frozenset(["setValue", "setBoolean", "setNumber", "setString", "setValue", "setObject", "setArray"])
+
+
+def fix_type_name(json_name):
+    if json_name in TYPE_NAME_FIX_MAP:
+        fixed = TYPE_NAME_FIX_MAP[json_name]
+
+        class Result(object):
+            class_name = fixed
+
+            @staticmethod
+            def output_comment(writer):
+                writer.newline("// Type originally was named '%s'.\n" % json_name)
+    else:
+
+        class Result(object):
+            class_name = json_name
+
+            @staticmethod
+            def output_comment(writer):
+                pass
+
+    return Result
+
+
+class Writer:
+    def __init__(self, output, indent):
+        self.output = output
+        self.indent = indent
+
+    def newline(self, str):
+        if (self.indent):
+            self.output.append(self.indent)
+        self.output.append(str)
+
+    def append(self, str):
+        self.output.append(str)
+
+    def newline_multiline(self, str):
+        parts = str.split('\n')
+        self.newline(parts[0])
+        for p in parts[1:]:
+            self.output.append('\n')
+            if p:
+                self.newline(p)
+
+    def append_multiline(self, str):
+        parts = str.split('\n')
+        self.append(parts[0])
+        for p in parts[1:]:
+            self.output.append('\n')
+            if p:
+                self.newline(p)
+
+    def get_indent(self):
+        return self.indent
+
+    def get_indented(self, additional_indent):
+        return Writer(self.output, self.indent + additional_indent)
+
+    def insert_writer(self, additional_indent):
+        new_output = []
+        self.output.append(new_output)
+        return Writer(new_output, self.indent + additional_indent)
+
+
+class EnumConstants:
+    map_ = {}
+    constants_ = []
+
+    @classmethod
+    def add_constant(cls, value):
+        if value in cls.map_:
+            return cls.map_[value]
+        else:
+            pos = len(cls.map_)
+            cls.map_[value] = pos
+            cls.constants_.append(value)
+            return pos
+
+    @classmethod
+    def get_enum_constant_code(cls):
+        output = []
+        for item in cls.constants_:
+            output.append("    \"" + item + "\"")
+        return ",\n".join(output) + "\n"
+
+
+# Typebuilder code is generated in several passes: first typedefs, then other classes.
+# Manual pass management is needed because we cannot have forward declarations for typedefs.
+class TypeBuilderPass:
+    TYPEDEF = "typedef"
+    MAIN = "main"
+
+
+class TypeBindings:
+    @staticmethod
+    def create_named_type_declaration(json_typable, context_domain_name, type_data):
+        json_type = type_data.get_json_type()
+
+        class Helper:
+            is_ad_hoc = False
+            full_name_prefix_for_use = "TypeBuilder::" + context_domain_name + "::"
+            full_name_prefix_for_impl = "TypeBuilder::" + context_domain_name + "::"
+
+            @staticmethod
+            def write_doc(writer):
+                if "description" in json_type:
+                    writer.newline("/* ")
+                    writer.append(json_type["description"])
+                    writer.append(" */\n")
+
+            @staticmethod
+            def add_to_forward_listener(forward_listener):
+                forward_listener.add_type_data(type_data)
+
+
+        fixed_type_name = fix_type_name(json_type["id"])
+        return TypeBindings.create_type_declaration_(json_typable, context_domain_name, fixed_type_name, Helper)
+
+    @staticmethod
+    def create_ad_hoc_type_declaration(json_typable, context_domain_name, ad_hoc_type_context):
+        class Helper:
+            is_ad_hoc = True
+            full_name_prefix_for_use = ad_hoc_type_context.container_relative_name_prefix
+            full_name_prefix_for_impl = ad_hoc_type_context.container_full_name_prefix
+
+            @staticmethod
+            def write_doc(writer):
+                pass
+
+            @staticmethod
+            def add_to_forward_listener(forward_listener):
+                pass
+        fixed_type_name = ad_hoc_type_context.get_type_name_fix()
+        return TypeBindings.create_type_declaration_(json_typable, context_domain_name, fixed_type_name, Helper)
+
+    @staticmethod
+    def create_type_declaration_(json_typable, context_domain_name, fixed_type_name, helper):
+        if json_typable["type"] == "string":
+            if "enum" in json_typable:
+
+                class EnumBinding:
+                    need_user_runtime_cast_ = False
+                    need_internal_runtime_cast_ = False
+
+                    @classmethod
+                    def resolve_inner(cls, resolve_context):
+                        pass
+
+                    @classmethod
+                    def request_user_runtime_cast(cls, request):
+                        if request:
+                            cls.need_user_runtime_cast_ = True
+                            request.acknowledge()
+
+                    @classmethod
+                    def request_internal_runtime_cast(cls):
+                        cls.need_internal_runtime_cast_ = True
+
+                    @classmethod
+                    def get_code_generator(enum_binding_cls):
+                        #FIXME: generate ad-hoc enums too once we figure out how to better implement them in C++.
+                        comment_out = helper.is_ad_hoc
+
+                        class CodeGenerator:
+                            @staticmethod
+                            def generate_type_builder(writer, generate_context):
+                                enum = json_typable["enum"]
+                                helper.write_doc(writer)
+                                enum_name = fixed_type_name.class_name
+                                fixed_type_name.output_comment(writer)
+                                writer.newline("struct ")
+                                writer.append(enum_name)
+                                writer.append(" {\n")
+                                writer.newline("    enum Enum {\n")
+                                for enum_item in enum:
+                                    enum_pos = EnumConstants.add_constant(enum_item)
+
+                                    item_c_name = enum_item.replace('-', '_')
+                                    item_c_name = Capitalizer.lower_camel_case_to_upper(item_c_name)
+                                    if item_c_name in TYPE_NAME_FIX_MAP:
+                                        item_c_name = TYPE_NAME_FIX_MAP[item_c_name]
+                                    writer.newline("        ")
+                                    writer.append(item_c_name)
+                                    writer.append(" = ")
+                                    writer.append("%s" % enum_pos)
+                                    writer.append(",\n")
+                                writer.newline("    };\n")
+                                if enum_binding_cls.need_user_runtime_cast_:
+                                    raise Exception("Not yet implemented")
+
+                                if enum_binding_cls.need_internal_runtime_cast_:
+                                    writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME)
+                                    writer.newline("    static void assertCorrectValue(InspectorValue* value);\n")
+                                    writer.append("#endif  // %s\n" % VALIDATOR_IFDEF_NAME)
+
+                                    validator_writer = generate_context.validator_writer
+
+                                    domain_fixes = DomainNameFixes.get_fixed_data(context_domain_name)
+
+                                    validator_writer.newline("void %s%s::assertCorrectValue(InspectorValue* value)\n" % (helper.full_name_prefix_for_impl, enum_name))
+                                    validator_writer.newline("{\n")
+                                    validator_writer.newline("    WTF::String s;\n")
+                                    validator_writer.newline("    bool cast_res = value->asString(&s);\n")
+                                    validator_writer.newline("    ASSERT(cast_res);\n")
+                                    if len(enum) > 0:
+                                        condition_list = []
+                                        for enum_item in enum:
+                                            enum_pos = EnumConstants.add_constant(enum_item)
+                                            condition_list.append("s == \"%s\"" % enum_item)
+                                        validator_writer.newline("    ASSERT(%s);\n" % " || ".join(condition_list))
+                                    validator_writer.newline("}\n")
+
+                                    validator_writer.newline("\n\n")
+
+                                writer.newline("}; // struct ")
+                                writer.append(enum_name)
+                                writer.append("\n\n")
+
+                            @staticmethod
+                            def register_use(forward_listener):
+                                pass
+
+                            @staticmethod
+                            def get_generate_pass_id():
+                                return TypeBuilderPass.MAIN
+
+                        return CodeGenerator
+
+                    @classmethod
+                    def get_validator_call_text(cls):
+                        return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::assertCorrectValue"
+
+                    @classmethod
+                    def get_array_item_c_type_text(cls):
+                        return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::Enum"
+
+                    @staticmethod
+                    def get_setter_value_expression_pattern():
+                        return "TypeBuilder::getEnumConstantValue(%s)"
+
+                    @staticmethod
+                    def reduce_to_raw_type():
+                        return RawTypes.String
+
+                    @staticmethod
+                    def get_type_model():
+                        return TypeModel.Enum(helper.full_name_prefix_for_use + fixed_type_name.class_name)
+
+                return EnumBinding
+            else:
+                if helper.is_ad_hoc:
+
+                    class PlainString:
+                        @classmethod
+                        def resolve_inner(cls, resolve_context):
+                            pass
+
+                        @staticmethod
+                        def request_user_runtime_cast(request):
+                            raise Exception("Unsupported")
+
+                        @staticmethod
+                        def request_internal_runtime_cast():
+                            pass
+
+                        @staticmethod
+                        def get_code_generator():
+                            return None
+
+                        @classmethod
+                        def get_validator_call_text(cls):
+                            return RawTypes.String.get_raw_validator_call_text()
+
+                        @staticmethod
+                        def reduce_to_raw_type():
+                            return RawTypes.String
+
+                        @staticmethod
+                        def get_type_model():
+                            return TypeModel.String
+
+                        @staticmethod
+                        def get_setter_value_expression_pattern():
+                            return None
+
+                        @classmethod
+                        def get_array_item_c_type_text(cls):
+                            return cls.reduce_to_raw_type().get_array_item_raw_c_type_text()
+
+                    return PlainString
+
+                else:
+
+                    class TypedefString:
+                        @classmethod
+                        def resolve_inner(cls, resolve_context):
+                            pass
+
+                        @staticmethod
+                        def request_user_runtime_cast(request):
+                            raise Exception("Unsupported")
+
+                        @staticmethod
+                        def request_internal_runtime_cast():
+                            RawTypes.String.request_raw_internal_runtime_cast()
+
+                        @staticmethod
+                        def get_code_generator():
+                            class CodeGenerator:
+                                @staticmethod
+                                def generate_type_builder(writer, generate_context):
+                                    helper.write_doc(writer)
+                                    fixed_type_name.output_comment(writer)
+                                    writer.newline("typedef String ")
+                                    writer.append(fixed_type_name.class_name)
+                                    writer.append(";\n\n")
+
+                                @staticmethod
+                                def register_use(forward_listener):
+                                    pass
+
+                                @staticmethod
+                                def get_generate_pass_id():
+                                    return TypeBuilderPass.TYPEDEF
+
+                            return CodeGenerator
+
+                        @classmethod
+                        def get_validator_call_text(cls):
+                            return RawTypes.String.get_raw_validator_call_text()
+
+                        @staticmethod
+                        def reduce_to_raw_type():
+                            return RawTypes.String
+
+                        @staticmethod
+                        def get_type_model():
+                            return TypeModel.ValueType("%s%s" % (helper.full_name_prefix_for_use, fixed_type_name.class_name), True)
+
+                        @staticmethod
+                        def get_setter_value_expression_pattern():
+                            return None
+
+                        @classmethod
+                        def get_array_item_c_type_text(cls):
+                            return "const %s%s&" % (helper.full_name_prefix_for_use, fixed_type_name.class_name)
+
+                    return TypedefString
+
+        elif json_typable["type"] == "object":
+            if "properties" in json_typable:
+
+                class ClassBinding:
+                    resolve_data_ = None
+                    need_user_runtime_cast_ = False
+                    need_internal_runtime_cast_ = False
+
+                    @classmethod
+                    def resolve_inner(cls, resolve_context):
+                        if cls.resolve_data_:
+                            return
+
+                        properties = json_typable["properties"]
+                        main = []
+                        optional = []
+
+                        ad_hoc_type_list = []
+
+                        for prop in properties:
+                            prop_name = prop["name"]
+                            ad_hoc_type_context = cls.AdHocTypeContextImpl(prop_name, fixed_type_name.class_name, resolve_context, ad_hoc_type_list, helper.full_name_prefix_for_impl)
+                            binding = resolve_param_type(prop, context_domain_name, ad_hoc_type_context)
+
+                            code_generator = binding.get_code_generator()
+                            if code_generator:
+                                code_generator.register_use(resolve_context.forward_listener)
+
+                            class PropertyData:
+                                param_type_binding = binding
+                                p = prop
+
+                            if prop.get("optional"):
+                                optional.append(PropertyData)
+                            else:
+                                main.append(PropertyData)
+
+                        class ResolveData:
+                            main_properties = main
+                            optional_properties = optional
+                            ad_hoc_types = ad_hoc_type_list
+
+                        cls.resolve_data_ = ResolveData
+
+                        for ad_hoc in ad_hoc_type_list:
+                            ad_hoc.resolve_inner(resolve_context)
+
+                    @classmethod
+                    def request_user_runtime_cast(cls, request):
+                        if not request:
+                            return
+                        cls.need_user_runtime_cast_ = True
+                        request.acknowledge()
+                        cls.request_internal_runtime_cast()
+
+                    @classmethod
+                    def request_internal_runtime_cast(cls):
+                        if cls.need_internal_runtime_cast_:
+                            return
+                        cls.need_internal_runtime_cast_ = True
+                        for p in cls.resolve_data_.main_properties:
+                            p.param_type_binding.request_internal_runtime_cast()
+                        for p in cls.resolve_data_.optional_properties:
+                            p.param_type_binding.request_internal_runtime_cast()
+
+                    @classmethod
+                    def get_code_generator(class_binding_cls):
+                        class CodeGenerator:
+                            @classmethod
+                            def generate_type_builder(cls, writer, generate_context):
+                                resolve_data = class_binding_cls.resolve_data_
+                                helper.write_doc(writer)
+                                class_name = fixed_type_name.class_name
+
+                                is_open_type = (context_domain_name + "." + class_name) in TYPES_WITH_OPEN_FIELD_LIST_SET
+
+                                fixed_type_name.output_comment(writer)
+                                writer.newline("class ")
+                                writer.append(class_name)
+                                writer.append(" : public ")
+                                if is_open_type:
+                                    writer.append("InspectorObject")
+                                else:
+                                    writer.append("InspectorObjectBase")
+                                writer.append(" {\n")
+                                writer.newline("public:\n")
+                                ad_hoc_type_writer = writer.insert_writer("    ")
+
+                                for ad_hoc_type in resolve_data.ad_hoc_types:
+                                    code_generator = ad_hoc_type.get_code_generator()
+                                    if code_generator:
+                                        code_generator.generate_type_builder(ad_hoc_type_writer, generate_context)
+
+                                writer.newline_multiline(
+"""    enum {
+        NoFieldsSet = 0,
+""")
+
+                                state_enum_items = []
+                                if len(resolve_data.main_properties) > 0:
+                                    pos = 0
+                                    for prop_data in resolve_data.main_properties:
+                                        item_name = Capitalizer.lower_camel_case_to_upper(prop_data.p["name"]) + "Set"
+                                        state_enum_items.append(item_name)
+                                        writer.newline("        %s = 1 << %s,\n" % (item_name, pos))
+                                        pos += 1
+                                    all_fields_set_value = "(" + (" | ".join(state_enum_items)) + ")"
+                                else:
+                                    all_fields_set_value = "0"
+
+                                writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_1
+                                                         % (all_fields_set_value, class_name, class_name))
+
+                                pos = 0
+                                for prop_data in resolve_data.main_properties:
+                                    prop_name = prop_data.p["name"]
+
+                                    param_type_binding = prop_data.param_type_binding
+                                    param_raw_type = param_type_binding.reduce_to_raw_type()
+
+                                    writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_2
+                                        % (state_enum_items[pos],
+                                           Capitalizer.lower_camel_case_to_upper(prop_name),
+                                           param_type_binding.get_type_model().get_input_param_type_text(),
+                                           state_enum_items[pos], prop_name,
+                                           param_raw_type.get_setter_name(), prop_name,
+                                           format_setter_value_expression(param_type_binding, "value"),
+                                           state_enum_items[pos]))
+
+                                    pos += 1
+
+                                writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_3
+                                                         % (class_name, class_name, class_name, class_name, class_name))
+
+                                writer.newline("    /*\n")
+                                writer.newline("     * Synthetic constructor:\n")
+                                writer.newline("     * RefPtr<%s> result = %s::create()" % (class_name, class_name))
+                                for prop_data in resolve_data.main_properties:
+                                    writer.append_multiline("\n     *     .set%s(...)" % Capitalizer.lower_camel_case_to_upper(prop_data.p["name"]))
+                                writer.append_multiline(";\n     */\n")
+
+                                writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_4)
+
+                                writer.newline("    typedef TypeBuilder::StructItemTraits ItemTraits;\n")
+
+                                for prop_data in resolve_data.optional_properties:
+                                    prop_name = prop_data.p["name"]
+                                    param_type_binding = prop_data.param_type_binding
+                                    setter_name = "set%s" % Capitalizer.lower_camel_case_to_upper(prop_name)
+
+                                    writer.append_multiline("\n    void %s" % setter_name)
+                                    writer.append("(%s value)\n" % param_type_binding.get_type_model().get_input_param_type_text())
+                                    writer.newline("    {\n")
+                                    writer.newline("        this->set%s(\"%s\", %s);\n"
+                                        % (param_type_binding.reduce_to_raw_type().get_setter_name(), prop_data.p["name"],
+                                           format_setter_value_expression(param_type_binding, "value")))
+                                    writer.newline("    }\n")
+
+
+                                    if setter_name in INSPECTOR_OBJECT_SETTER_NAMES:
+                                        writer.newline("    using InspectorObjectBase::%s;\n\n" % setter_name)
+
+                                if class_binding_cls.need_user_runtime_cast_:
+                                    writer.newline("    static PassRefPtr<%s> runtimeCast(PassRefPtr<InspectorValue> value)\n" % class_name)
+                                    writer.newline("    {\n")
+                                    writer.newline("        RefPtr<InspectorObject> object;\n")
+                                    writer.newline("        bool castRes = value->asObject(&object);\n")
+                                    writer.newline("        ASSERT_UNUSED(castRes, castRes);\n")
+                                    writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME)
+                                    writer.newline("        assertCorrectValue(object.get());\n")
+                                    writer.append("#endif  // %s\n" % VALIDATOR_IFDEF_NAME)
+                                    writer.newline("        COMPILE_ASSERT(sizeof(%s) == sizeof(InspectorObjectBase), type_cast_problem);\n" % class_name)
+                                    writer.newline("        return static_cast<%s*>(static_cast<InspectorObjectBase*>(object.get()));\n" % class_name)
+                                    writer.newline("    }\n")
+                                    writer.append("\n")
+
+                                if class_binding_cls.need_internal_runtime_cast_:
+                                    writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME)
+                                    writer.newline("    static void assertCorrectValue(InspectorValue* value);\n")
+                                    writer.append("#endif  // %s\n" % VALIDATOR_IFDEF_NAME)
+
+                                    closed_field_set = (context_domain_name + "." + class_name) not in TYPES_WITH_OPEN_FIELD_LIST_SET
+
+                                    validator_writer = generate_context.validator_writer
+
+                                    domain_fixes = DomainNameFixes.get_fixed_data(context_domain_name)
+
+                                    validator_writer.newline("void %s%s::assertCorrectValue(InspectorValue* value)\n" % (helper.full_name_prefix_for_impl, class_name))
+                                    validator_writer.newline("{\n")
+                                    validator_writer.newline("    RefPtr<InspectorObject> object;\n")
+                                    validator_writer.newline("    bool castRes = value->asObject(&object);\n")
+                                    validator_writer.newline("    ASSERT_UNUSED(castRes, castRes);\n")
+                                    for prop_data in resolve_data.main_properties:
+                                        validator_writer.newline("    {\n")
+                                        it_name = "%sPos" % prop_data.p["name"]
+                                        validator_writer.newline("        InspectorObject::iterator %s;\n" % it_name)
+                                        validator_writer.newline("        %s = object->find(\"%s\");\n" % (it_name, prop_data.p["name"]))
+                                        validator_writer.newline("        ASSERT(%s != object->end());\n" % it_name)
+                                        validator_writer.newline("        %s(%s->value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(), it_name))
+                                        validator_writer.newline("    }\n")
+
+                                    if closed_field_set:
+                                        validator_writer.newline("    int foundPropertiesCount = %s;\n" % len(resolve_data.main_properties))
+
+                                    for prop_data in resolve_data.optional_properties:
+                                        validator_writer.newline("    {\n")
+                                        it_name = "%sPos" % prop_data.p["name"]
+                                        validator_writer.newline("        InspectorObject::iterator %s;\n" % it_name)
+                                        validator_writer.newline("        %s = object->find(\"%s\");\n" % (it_name, prop_data.p["name"]))
+                                        validator_writer.newline("        if (%s != object->end()) {\n" % it_name)
+                                        validator_writer.newline("            %s(%s->value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(), it_name))
+                                        if closed_field_set:
+                                            validator_writer.newline("            ++foundPropertiesCount;\n")
+                                        validator_writer.newline("        }\n")
+                                        validator_writer.newline("    }\n")
+
+                                    if closed_field_set:
+                                        validator_writer.newline("    if (foundPropertiesCount != object->size()) {\n")
+                                        validator_writer.newline("      FATAL(\"Unexpected properties in object: %s\\n\", object->toJSONString().ascii().data());\n")
+                                        validator_writer.newline("    }\n")
+                                    validator_writer.newline("}\n")
+
+                                    validator_writer.newline("\n\n")
+
+                                if is_open_type:
+                                    cpp_writer = generate_context.cpp_writer
+                                    writer.append("\n")
+                                    writer.newline("    // Property names for type generated as open.\n")
+                                    for prop_data in resolve_data.main_properties + resolve_data.optional_properties:
+                                        prop_name = prop_data.p["name"]
+                                        prop_field_name = Capitalizer.lower_camel_case_to_upper(prop_name)
+                                        writer.newline("    static const char* %s;\n" % (prop_field_name))
+                                        cpp_writer.newline("const char* %s%s::%s = \"%s\";\n" % (helper.full_name_prefix_for_impl, class_name, prop_field_name, prop_name))
+
+
+                                writer.newline("};\n\n")
+
+                            @staticmethod
+                            def generate_forward_declaration(writer):
+                                class_name = fixed_type_name.class_name
+                                writer.newline("class ")
+                                writer.append(class_name)
+                                writer.append(";\n")
+
+                            @staticmethod
+                            def register_use(forward_listener):
+                                helper.add_to_forward_listener(forward_listener)
+
+                            @staticmethod
+                            def get_generate_pass_id():
+                                return TypeBuilderPass.MAIN
+
+                        return CodeGenerator
+
+                    @staticmethod
+                    def get_validator_call_text():
+                        return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::assertCorrectValue"
+
+                    @classmethod
+                    def get_array_item_c_type_text(cls):
+                        return helper.full_name_prefix_for_use + fixed_type_name.class_name
+
+                    @staticmethod
+                    def get_setter_value_expression_pattern():
+                        return None
+
+                    @staticmethod
+                    def reduce_to_raw_type():
+                        return RawTypes.Object
+
+                    @staticmethod
+                    def get_type_model():
+                        return TypeModel.RefPtrBased(helper.full_name_prefix_for_use + fixed_type_name.class_name)
+
+                    class AdHocTypeContextImpl:
+                        def __init__(self, property_name, class_name, resolve_context, ad_hoc_type_list, parent_full_name_prefix):
+                            self.property_name = property_name
+                            self.class_name = class_name
+                            self.resolve_context = resolve_context
+                            self.ad_hoc_type_list = ad_hoc_type_list
+                            self.container_full_name_prefix = parent_full_name_prefix + class_name + "::"
+                            self.container_relative_name_prefix = ""
+
+                        def get_type_name_fix(self):
+                            class NameFix:
+                                class_name = Capitalizer.lower_camel_case_to_upper(self.property_name)
+
+                                @staticmethod
+                                def output_comment(writer):
+                                    writer.newline("// Named after property name '%s' while generating %s.\n" % (self.property_name, self.class_name))
+
+                            return NameFix
+
+                        def add_type(self, binding):
+                            self.ad_hoc_type_list.append(binding)
+
+                return ClassBinding
+            else:
+
+                class PlainObjectBinding:
+                    @classmethod
+                    def resolve_inner(cls, resolve_context):
+                        pass
+
+                    @staticmethod
+                    def request_user_runtime_cast(request):
+                        pass
+
+                    @staticmethod
+                    def request_internal_runtime_cast():
+                        RawTypes.Object.request_raw_internal_runtime_cast()
+
+                    @staticmethod
+                    def get_code_generator():
+                        pass
+
+                    @staticmethod
+                    def get_validator_call_text():
+                        return "RuntimeCastHelper::assertType<InspectorValue::TypeObject>"
+
+                    @classmethod
+                    def get_array_item_c_type_text(cls):
+                        return cls.reduce_to_raw_type().get_array_item_raw_c_type_text()
+
+                    @staticmethod
+                    def get_setter_value_expression_pattern():
+                        return None
+
+                    @staticmethod
+                    def reduce_to_raw_type():
+                        return RawTypes.Object
+
+                    @staticmethod
+                    def get_type_model():
+                        return TypeModel.Object
+
+                return PlainObjectBinding
+        elif json_typable["type"] == "array":
+            if "items" in json_typable:
+
+                ad_hoc_types = []
+
+                class AdHocTypeContext:
+                    container_full_name_prefix = "<not yet defined>"
+                    container_relative_name_prefix = ""
+
+                    @staticmethod
+                    def get_type_name_fix():
+                        return fixed_type_name
+
+                    @staticmethod
+                    def add_type(binding):
+                        ad_hoc_types.append(binding)
+
+                item_binding = resolve_param_type(json_typable["items"], context_domain_name, AdHocTypeContext)
+
+                class ArrayBinding:
+                    resolve_data_ = None
+                    need_internal_runtime_cast_ = False
+
+                    @classmethod
+                    def resolve_inner(cls, resolve_context):
+                        if cls.resolve_data_:
+                            return
+
+                        class ResolveData:
+                            item_type_binding = item_binding
+                            ad_hoc_type_list = ad_hoc_types
+
+                        cls.resolve_data_ = ResolveData
+
+                        for t in ad_hoc_types:
+                            t.resolve_inner(resolve_context)
+
+                    @classmethod
+                    def request_user_runtime_cast(cls, request):
+                        raise Exception("Not implemented yet")
+
+                    @classmethod
+                    def request_internal_runtime_cast(cls):
+                        if cls.need_internal_runtime_cast_:
+                            return
+                        cls.need_internal_runtime_cast_ = True
+                        cls.resolve_data_.item_type_binding.request_internal_runtime_cast()
+
+                    @classmethod
+                    def get_code_generator(array_binding_cls):
+
+                        class CodeGenerator:
+                            @staticmethod
+                            def generate_type_builder(writer, generate_context):
+                                ad_hoc_type_writer = writer
+
+                                resolve_data = array_binding_cls.resolve_data_
+
+                                for ad_hoc_type in resolve_data.ad_hoc_type_list:
+                                    code_generator = ad_hoc_type.get_code_generator()
+                                    if code_generator:
+                                        code_generator.generate_type_builder(ad_hoc_type_writer, generate_context)
+
+                            @staticmethod
+                            def generate_forward_declaration(writer):
+                                pass
+
+                            @staticmethod
+                            def register_use(forward_listener):
+                                item_code_generator = item_binding.get_code_generator()
+                                if item_code_generator:
+                                    item_code_generator.register_use(forward_listener)
+
+                            @staticmethod
+                            def get_generate_pass_id():
+                                return TypeBuilderPass.MAIN
+
+                        return CodeGenerator
+
+                    @classmethod
+                    def get_validator_call_text(cls):
+                        return cls.get_array_item_c_type_text() + "::assertCorrectValue"
+
+                    @classmethod
+                    def get_array_item_c_type_text(cls):
+                        return replace_right_shift("TypeBuilder::Array<%s>" % cls.resolve_data_.item_type_binding.get_array_item_c_type_text())
+
+                    @staticmethod
+                    def get_setter_value_expression_pattern():
+                        return None
+
+                    @staticmethod
+                    def reduce_to_raw_type():
+                        return RawTypes.Array
+
+                    @classmethod
+                    def get_type_model(cls):
+                        return TypeModel.RefPtrBased(cls.get_array_item_c_type_text())
+
+                return ArrayBinding
+            else:
+                # Fall-through to raw type.
+                pass
+
+        raw_type = RawTypes.get(json_typable["type"])
+
+        return RawTypeBinding(raw_type)
+
+
+class RawTypeBinding:
+    def __init__(self, raw_type):
+        self.raw_type_ = raw_type
+
+    def resolve_inner(self, resolve_context):
+        pass
+
+    def request_user_runtime_cast(self, request):
+        raise Exception("Unsupported")
+
+    def request_internal_runtime_cast(self):
+        self.raw_type_.request_raw_internal_runtime_cast()
+
+    def get_code_generator(self):
+        return None
+
+    def get_validator_call_text(self):
+        return self.raw_type_.get_raw_validator_call_text()
+
+    def get_array_item_c_type_text(self):
+        return self.raw_type_.get_array_item_raw_c_type_text()
+
+    def get_setter_value_expression_pattern(self):
+        return None
+
+    def reduce_to_raw_type(self):
+        return self.raw_type_
+
+    def get_type_model(self):
+        return self.raw_type_.get_raw_type_model()
+
+
+class TypeData(object):
+    def __init__(self, json_type, json_domain, domain_data):
+        self.json_type_ = json_type
+        self.json_domain_ = json_domain
+        self.domain_data_ = domain_data
+
+        if "type" not in json_type:
+            raise Exception("Unknown type")
+
+        json_type_name = json_type["type"]
+        raw_type = RawTypes.get(json_type_name)
+        self.raw_type_ = raw_type
+        self.binding_being_resolved_ = False
+        self.binding_ = None
+
+    def get_raw_type(self):
+        return self.raw_type_
+
+    def get_binding(self):
+        if not self.binding_:
+            if self.binding_being_resolved_:
+                raise Error("Type %s is already being resolved" % self.json_type_["type"])
+            # Resolve only lazily, because resolving one named type may require resolving some other named type.
+            self.binding_being_resolved_ = True
+            try:
+                self.binding_ = TypeBindings.create_named_type_declaration(self.json_type_, self.json_domain_["domain"], self)
+            finally:
+                self.binding_being_resolved_ = False
+
+        return self.binding_
+
+    def get_json_type(self):
+        return self.json_type_
+
+    def get_name(self):
+        return self.json_type_["id"]
+
+    def get_domain_name(self):
+        return self.json_domain_["domain"]
+
+
+class DomainData:
+    def __init__(self, json_domain):
+        self.json_domain = json_domain
+        self.types_ = []
+
+    def add_type(self, type_data):
+        self.types_.append(type_data)
+
+    def name(self):
+        return self.json_domain["domain"]
+
+    def types(self):
+        return self.types_
+
+
+class TypeMap:
+    def __init__(self, api):
+        self.map_ = {}
+        self.domains_ = []
+        for json_domain in api["domains"]:
+            domain_name = json_domain["domain"]
+
+            domain_map = {}
+            self.map_[domain_name] = domain_map
+
+            domain_data = DomainData(json_domain)
+            self.domains_.append(domain_data)
+
+            if "types" in json_domain:
+                for json_type in json_domain["types"]:
+                    type_name = json_type["id"]
+                    type_data = TypeData(json_type, json_domain, domain_data)
+                    domain_map[type_name] = type_data
+                    domain_data.add_type(type_data)
+
+    def domains(self):
+        return self.domains_
+
+    def get(self, domain_name, type_name):
+        return self.map_[domain_name][type_name]
+
+
+def resolve_param_type(json_parameter, scope_domain_name, ad_hoc_type_context):
+    if "$ref" in json_parameter:
+        json_ref = json_parameter["$ref"]
+        type_data = get_ref_data(json_ref, scope_domain_name)
+        return type_data.get_binding()
+    elif "type" in json_parameter:
+        result = TypeBindings.create_ad_hoc_type_declaration(json_parameter, scope_domain_name, ad_hoc_type_context)
+        ad_hoc_type_context.add_type(result)
+        return result
+    else:
+        raise Exception("Unknown type")
+
+def resolve_param_raw_type(json_parameter, scope_domain_name):
+    if "$ref" in json_parameter:
+        json_ref = json_parameter["$ref"]
+        type_data = get_ref_data(json_ref, scope_domain_name)
+        return type_data.get_raw_type()
+    elif "type" in json_parameter:
+        json_type = json_parameter["type"]
+        return RawTypes.get(json_type)
+    else:
+        raise Exception("Unknown type")
+
+
+def get_ref_data(json_ref, scope_domain_name):
+    dot_pos = json_ref.find(".")
+    if dot_pos == -1:
+        domain_name = scope_domain_name
+        type_name = json_ref
+    else:
+        domain_name = json_ref[:dot_pos]
+        type_name = json_ref[dot_pos + 1:]
+
+    return type_map.get(domain_name, type_name)
+
+
+input_file = open(input_json_filename, "r")
+json_string = input_file.read()
+json_api = json.loads(json_string)
+
+
+class Templates:
+    def get_this_script_path_(absolute_path):
+        absolute_path = os.path.abspath(absolute_path)
+        components = []
+
+        def fill_recursive(path_part, depth):
+            if depth <= 0 or path_part == '/':
+                return
+            fill_recursive(os.path.dirname(path_part), depth - 1)
+            components.append(os.path.basename(path_part))
+
+        # Typical path is /Source/WebCore/inspector/CodeGeneratorInspector.py
+        # Let's take 4 components from the real path then.
+        fill_recursive(absolute_path, 4)
+
+        return "/".join(components)
+
+    file_header_ = ("// File is generated by %s\n\n" % get_this_script_path_(sys.argv[0]) +
+"""// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+""")
+
+    frontend_domain_class = string.Template(CodeGeneratorInspectorStrings.frontend_domain_class)
+    backend_method = string.Template(CodeGeneratorInspectorStrings.backend_method)
+    frontend_method = string.Template(CodeGeneratorInspectorStrings.frontend_method)
+    callback_method = string.Template(CodeGeneratorInspectorStrings.callback_method)
+    frontend_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.frontend_h)
+    backend_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.backend_h)
+    backend_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.backend_cpp)
+    frontend_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.frontend_cpp)
+    typebuilder_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.typebuilder_h)
+    typebuilder_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.typebuilder_cpp)
+    param_container_access_code = CodeGeneratorInspectorStrings.param_container_access_code
+
+
+
+
+
+type_map = TypeMap(json_api)
+
+
+class NeedRuntimeCastRequest:
+    def __init__(self):
+        self.ack_ = None
+
+    def acknowledge(self):
+        self.ack_ = True
+
+    def is_acknowledged(self):
+        return self.ack_
+
+
+def resolve_all_types():
+    runtime_cast_generate_requests = {}
+    for type_name in TYPES_WITH_RUNTIME_CAST_SET:
+        runtime_cast_generate_requests[type_name] = NeedRuntimeCastRequest()
+
+    class ForwardListener:
+        type_data_set = set()
+        already_declared_set = set()
+
+        @classmethod
+        def add_type_data(cls, type_data):
+            if type_data not in cls.already_declared_set:
+                cls.type_data_set.add(type_data)
+
+    class ResolveContext:
+        forward_listener = ForwardListener
+
+    for domain_data in type_map.domains():
+        for type_data in domain_data.types():
+            # Do not generate forwards for this type any longer.
+            ForwardListener.already_declared_set.add(type_data)
+
+            binding = type_data.get_binding()
+            binding.resolve_inner(ResolveContext)
+
+    for domain_data in type_map.domains():
+        for type_data in domain_data.types():
+            full_type_name = "%s.%s" % (type_data.get_domain_name(), type_data.get_name())
+            request = runtime_cast_generate_requests.pop(full_type_name, None)
+            binding = type_data.get_binding()
+            if request:
+                binding.request_user_runtime_cast(request)
+
+            if request and not request.is_acknowledged():
+                raise Exception("Failed to generate runtimeCast in " + full_type_name)
+
+    for full_type_name in runtime_cast_generate_requests:
+        raise Exception("Failed to generate runtimeCast. Type " + full_type_name + " not found")
+
+    return ForwardListener
+
+
+global_forward_listener = resolve_all_types()
+
+
+def get_annotated_type_text(raw_type, annotated_type):
+    if annotated_type != raw_type:
+        return "/*%s*/ %s" % (annotated_type, raw_type)
+    else:
+        return raw_type
+
+
+def format_setter_value_expression(param_type_binding, value_ref):
+    pattern = param_type_binding.get_setter_value_expression_pattern()
+    if pattern:
+        return pattern % value_ref
+    else:
+        return value_ref
+
+class Generator:
+    frontend_class_field_lines = []
+    frontend_domain_class_lines = []
+
+    method_name_enum_list = []
+    backend_method_declaration_list = []
+    backend_method_implementation_list = []
+    backend_method_name_declaration_list = []
+    method_handler_list = []
+    frontend_method_list = []
+
+    backend_virtual_setters_list = []
+    backend_agent_interface_list = []
+    backend_setters_list = []
+    backend_constructor_init_list = []
+    backend_field_list = []
+    frontend_constructor_init_list = []
+    type_builder_fragments = []
+    type_builder_forwards = []
+    validator_impl_list = []
+    type_builder_impl_list = []
+
+
+    @staticmethod
+    def go():
+        Generator.process_types(type_map)
+
+        first_cycle_guardable_list_list = [
+            Generator.backend_method_declaration_list,
+            Generator.backend_method_implementation_list,
+            Generator.backend_method_name_declaration_list,
+            Generator.backend_agent_interface_list,
+            Generator.frontend_class_field_lines,
+            Generator.frontend_constructor_init_list,
+            Generator.frontend_domain_class_lines,
+            Generator.frontend_method_list,
+            Generator.method_handler_list,
+            Generator.method_name_enum_list,
+            Generator.backend_constructor_init_list,
+            Generator.backend_virtual_setters_list,
+            Generator.backend_setters_list,
+            Generator.backend_field_list]
+
+        for json_domain in json_api["domains"]:
+            domain_name = json_domain["domain"]
+            domain_name_lower = domain_name.lower()
+
+            domain_fixes = DomainNameFixes.get_fixed_data(domain_name)
+
+            agent_field_name = domain_fixes.agent_field_name
+
+            frontend_method_declaration_lines = []
+
+            if "events" in json_domain:
+                for json_event in json_domain["events"]:
+                    Generator.process_event(json_event, domain_name, frontend_method_declaration_lines)
+
+            Generator.frontend_class_field_lines.append("    %s m_%s;\n" % (domain_name, domain_name_lower))
+            if Generator.frontend_constructor_init_list:
+                Generator.frontend_constructor_init_list.append("    , ")
+            Generator.frontend_constructor_init_list.append("m_%s(inspectorFrontendChannel)\n" % domain_name_lower)
+            Generator.frontend_domain_class_lines.append(Templates.frontend_domain_class.substitute(None,
+                domainClassName=domain_name,
+                domainFieldName=domain_name_lower,
+                frontendDomainMethodDeclarations="".join(flatten_list(frontend_method_declaration_lines))))
+
+            agent_interface_name = Capitalizer.lower_camel_case_to_upper(domain_name) + "CommandHandler"
+            Generator.backend_agent_interface_list.append("    class %s {\n" % agent_interface_name)
+            Generator.backend_agent_interface_list.append("    public:\n")
+            if "commands" in json_domain:
+                for json_command in json_domain["commands"]:
+                    Generator.process_command(json_command, domain_name, agent_field_name, agent_interface_name)
+            Generator.backend_agent_interface_list.append("\n    protected:\n")
+            Generator.backend_agent_interface_list.append("        virtual ~%s() { }\n" % agent_interface_name)
+            Generator.backend_agent_interface_list.append("    };\n\n")
+
+            Generator.backend_constructor_init_list.append("        , m_%s(0)" % agent_field_name)
+            Generator.backend_virtual_setters_list.append("    virtual void registerAgent(%s* %s) = 0;" % (agent_interface_name, agent_field_name))
+            Generator.backend_setters_list.append("    virtual void registerAgent(%s* %s) { ASSERT(!m_%s); m_%s = %s; }" % (agent_interface_name, agent_field_name, agent_field_name, agent_field_name, agent_field_name))
+            Generator.backend_field_list.append("    %s* m_%s;" % (agent_interface_name, agent_field_name))
+
+    @staticmethod
+    def process_event(json_event, domain_name, frontend_method_declaration_lines):
+        event_name = json_event["name"]
+
+        ad_hoc_type_output = []
+        frontend_method_declaration_lines.append(ad_hoc_type_output)
+        ad_hoc_type_writer = Writer(ad_hoc_type_output, "        ")
+
+        decl_parameter_list = []
+
+        json_parameters = json_event.get("parameters")
+        Generator.generate_send_method(json_parameters, event_name, domain_name, ad_hoc_type_writer,
+                                       decl_parameter_list,
+                                       Generator.EventMethodStructTemplate,
+                                       Generator.frontend_method_list, Templates.frontend_method, {"eventName": event_name})
+
+        frontend_method_declaration_lines.append(
+            "        void %s(%s);\n" % (event_name, ", ".join(decl_parameter_list)))
+
+    class EventMethodStructTemplate:
+        @staticmethod
+        def append_prolog(line_list):
+            line_list.append("    RefPtr<InspectorObject> paramsObject = InspectorObject::create();\n")
+
+        @staticmethod
+        def append_epilog(line_list):
+            line_list.append("    jsonMessage->setObject(\"params\", paramsObject);\n")
+
+        container_name = "paramsObject"
+
+    @staticmethod
+    def process_command(json_command, domain_name, agent_field_name, agent_interface_name):
+        json_command_name = json_command["name"]
+
+        cmd_enum_name = "k%s_%sCmd" % (domain_name, json_command["name"])
+
+        Generator.method_name_enum_list.append("        %s," % cmd_enum_name)
+        Generator.method_handler_list.append("            &InspectorBackendDispatcherImpl::%s_%s," % (domain_name, json_command_name))
+        Generator.backend_method_declaration_list.append("    void %s_%s(long callId, InspectorObject* requestMessageObject);" % (domain_name, json_command_name))
+
+        ad_hoc_type_output = []
+        Generator.backend_agent_interface_list.append(ad_hoc_type_output)
+        ad_hoc_type_writer = Writer(ad_hoc_type_output, "        ")
+
+        Generator.backend_agent_interface_list.append("        virtual void %s(ErrorString*" % json_command_name)
+
+        method_in_code = ""
+        method_out_code = ""
+        agent_call_param_list = []
+        response_cook_list = []
+        request_message_param = ""
+        if "parameters" in json_command:
+            json_params = json_command["parameters"]
+            method_in_code += Templates.param_container_access_code
+            request_message_param = " requestMessageObject"
+            js_param_list = []
+
+            for json_parameter in json_params:
+                json_param_name = json_parameter["name"]
+                param_raw_type = resolve_param_raw_type(json_parameter, domain_name)
+
+                getter_name = param_raw_type.get_getter_name()
+
+                optional = json_parameter.get("optional")
+
+                non_optional_type_model = param_raw_type.get_raw_type_model()
+                if optional:
+                    type_model = non_optional_type_model.get_optional()
+                else:
+                    type_model = non_optional_type_model
+
+                if optional:
+                    code = ("    bool %s_valueFound = false;\n"
+                            "    %s in_%s = get%s(paramsContainerPtr, \"%s\", &%s_valueFound, protocolErrorsPtr);\n" %
+                           (json_param_name, non_optional_type_model.get_command_return_pass_model().get_return_var_type(), json_param_name, getter_name, json_param_name, json_param_name))
+                    param = ", %s_valueFound ? &in_%s : 0" % (json_param_name, json_param_name)
+                    # FIXME: pass optional refptr-values as PassRefPtr
+                    formal_param_type_pattern = "const %s*"
+                else:
+                    code = ("    %s in_%s = get%s(paramsContainerPtr, \"%s\", 0, protocolErrorsPtr);\n" %
+                            (non_optional_type_model.get_command_return_pass_model().get_return_var_type(), json_param_name, getter_name, json_param_name))
+                    param = ", in_%s" % json_param_name
+                    # FIXME: pass not-optional refptr-values as NonNullPassRefPtr
+                    if param_raw_type.is_heavy_value():
+                        formal_param_type_pattern = "const %s&"
+                    else:
+                        formal_param_type_pattern = "%s"
+
+                method_in_code += code
+                agent_call_param_list.append(param)
+                Generator.backend_agent_interface_list.append(", %s in_%s" % (formal_param_type_pattern % non_optional_type_model.get_command_return_pass_model().get_return_var_type(), json_param_name))
+
+        response_cook_text = ""
+        if json_command.get("async") == True:
+            callback_name = Capitalizer.lower_camel_case_to_upper(json_command_name) + "Callback"
+
+            callback_output = []
+            callback_writer = Writer(callback_output, ad_hoc_type_writer.get_indent())
+
+            decl_parameter_list = []
+            Generator.generate_send_method(json_command.get("returns"), json_command_name, domain_name, ad_hoc_type_writer,
+                                           decl_parameter_list,
+                                           Generator.CallbackMethodStructTemplate,
+                                           Generator.backend_method_implementation_list, Templates.callback_method,
+                                           {"callbackName": callback_name, "agentName": agent_interface_name})
+
+            callback_writer.newline("class " + callback_name + " : public CallbackBase {\n")
+            callback_writer.newline("public:\n")
+            callback_writer.newline("    " + callback_name + "(PassRefPtr<InspectorBackendDispatcherImpl>, int id);\n")
+            callback_writer.newline("    void sendSuccess(" + ", ".join(decl_parameter_list) + ");\n")
+            callback_writer.newline("};\n")
+
+            ad_hoc_type_output.append(callback_output)
+
+            method_out_code += "    RefPtr<" + agent_interface_name + "::" + callback_name + "> callback = adoptRef(new " + agent_interface_name + "::" + callback_name + "(this, callId));\n"
+            agent_call_param_list.append(", callback")
+            response_cook_text += "        if (!error.length()) \n"
+            response_cook_text += "            return;\n"
+            response_cook_text += "        callback->disable();\n"
+            Generator.backend_agent_interface_list.append(", PassRefPtr<%s> callback" % callback_name)
+        else:
+            if "returns" in json_command:
+                method_out_code += "\n"
+                for json_return in json_command["returns"]:
+
+                    json_return_name = json_return["name"]
+
+                    optional = bool(json_return.get("optional"))
+
+                    return_type_binding = Generator.resolve_type_and_generate_ad_hoc(json_return, json_command_name, domain_name, ad_hoc_type_writer, agent_interface_name + "::")
+
+                    raw_type = return_type_binding.reduce_to_raw_type()
+                    setter_type = raw_type.get_setter_name()
+                    initializer = raw_type.get_c_initializer()
+
+                    type_model = return_type_binding.get_type_model()
+                    if optional:
+                        type_model = type_model.get_optional()
+
+                    code = "    %s out_%s;\n" % (type_model.get_command_return_pass_model().get_return_var_type(), json_return_name)
+                    param = ", %sout_%s" % (type_model.get_command_return_pass_model().get_output_argument_prefix(), json_return_name)
+                    var_name = "out_%s" % json_return_name
+                    setter_argument = type_model.get_command_return_pass_model().get_output_to_raw_expression() % var_name
+                    if return_type_binding.get_setter_value_expression_pattern():
+                        setter_argument = return_type_binding.get_setter_value_expression_pattern() % setter_argument
+
+                    cook = "            result->set%s(\"%s\", %s);\n" % (setter_type, json_return_name,
+                                                                         setter_argument)
+
+                    set_condition_pattern = type_model.get_command_return_pass_model().get_set_return_condition()
+                    if set_condition_pattern:
+                        cook = ("            if (%s)\n    " % (set_condition_pattern % var_name)) + cook
+                    annotated_type = type_model.get_command_return_pass_model().get_output_parameter_type()
+
+                    param_name = "out_%s" % json_return_name
+                    if optional:
+                        param_name = "opt_" + param_name
+
+                    Generator.backend_agent_interface_list.append(", %s %s" % (annotated_type, param_name))
+                    response_cook_list.append(cook)
+
+                    method_out_code += code
+                    agent_call_param_list.append(param)
+
+                response_cook_text = "".join(response_cook_list)
+
+                if len(response_cook_text) != 0:
+                    response_cook_text = "        if (!error.length()) {\n" + response_cook_text + "        }"
+
+        Generator.backend_method_implementation_list.append(Templates.backend_method.substitute(None,
+            domainName=domain_name, methodName=json_command_name,
+            agentField="m_" + agent_field_name,
+            methodInCode=method_in_code,
+            methodOutCode=method_out_code,
+            agentCallParams="".join(agent_call_param_list),
+            requestMessageObject=request_message_param,
+            responseCook=response_cook_text,
+            commandNameIndex=cmd_enum_name))
+        Generator.backend_method_name_declaration_list.append("    \"%s.%s\"," % (domain_name, json_command_name))
+
+        Generator.backend_agent_interface_list.append(") = 0;\n")
+
+    class CallbackMethodStructTemplate:
+        @staticmethod
+        def append_prolog(line_list):
+            pass
+
+        @staticmethod
+        def append_epilog(line_list):
+            pass
+
+        container_name = "jsonMessage"
+
+    # Generates common code for event sending and callback response data sending.
+    @staticmethod
+    def generate_send_method(parameters, event_name, domain_name, ad_hoc_type_writer, decl_parameter_list,
+                             method_struct_template,
+                             generator_method_list, method_template, template_params):
+        method_line_list = []
+        if parameters:
+            method_struct_template.append_prolog(method_line_list)
+            for json_parameter in parameters:
+                parameter_name = json_parameter["name"]
+
+                param_type_binding = Generator.resolve_type_and_generate_ad_hoc(json_parameter, event_name, domain_name, ad_hoc_type_writer, "")
+
+                raw_type = param_type_binding.reduce_to_raw_type()
+                raw_type_binding = RawTypeBinding(raw_type)
+
+                optional = bool(json_parameter.get("optional"))
+
+                setter_type = raw_type.get_setter_name()
+
+                type_model = param_type_binding.get_type_model()
+                raw_type_model = raw_type_binding.get_type_model()
+                if optional:
+                    type_model = type_model.get_optional()
+                    raw_type_model = raw_type_model.get_optional()
+
+                annotated_type = type_model.get_input_param_type_text()
+                mode_type_binding = param_type_binding
+
+                decl_parameter_list.append("%s %s" % (annotated_type, parameter_name))
+
+                setter_argument = raw_type_model.get_event_setter_expression_pattern() % parameter_name
+                if mode_type_binding.get_setter_value_expression_pattern():
+                    setter_argument = mode_type_binding.get_setter_value_expression_pattern() % setter_argument
+
+                setter_code = "    %s->set%s(\"%s\", %s);\n" % (method_struct_template.container_name, setter_type, parameter_name, setter_argument)
+                if optional:
+                    setter_code = ("    if (%s)\n    " % parameter_name) + setter_code
+                method_line_list.append(setter_code)
+
+            method_struct_template.append_epilog(method_line_list)
+
+        generator_method_list.append(method_template.substitute(None,
+            domainName=domain_name,
+            parameters=", ".join(decl_parameter_list),
+            code="".join(method_line_list), **template_params))
+
+    @staticmethod
+    def resolve_type_and_generate_ad_hoc(json_param, method_name, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param):
+        param_name = json_param["name"]
+        ad_hoc_type_list = []
+
+        class AdHocTypeContext:
+            container_full_name_prefix = "<not yet defined>"
+            container_relative_name_prefix = container_relative_name_prefix_param
+
+            @staticmethod
+            def get_type_name_fix():
+                class NameFix:
+                    class_name = Capitalizer.lower_camel_case_to_upper(param_name)
+
+                    @staticmethod
+                    def output_comment(writer):
+                        writer.newline("// Named after parameter '%s' while generating command/event %s.\n" % (param_name, method_name))
+
+                return NameFix
+
+            @staticmethod
+            def add_type(binding):
+                ad_hoc_type_list.append(binding)
+
+        type_binding = resolve_param_type(json_param, domain_name, AdHocTypeContext)
+
+        class InterfaceForwardListener:
+            @staticmethod
+            def add_type_data(type_data):
+                pass
+
+        class InterfaceResolveContext:
+            forward_listener = InterfaceForwardListener
+
+        for type in ad_hoc_type_list:
+            type.resolve_inner(InterfaceResolveContext)
+
+        class InterfaceGenerateContext:
+            validator_writer = "not supported in InterfaceGenerateContext"
+            cpp_writer = validator_writer
+
+        for type in ad_hoc_type_list:
+            generator = type.get_code_generator()
+            if generator:
+                generator.generate_type_builder(ad_hoc_type_writer, InterfaceGenerateContext)
+
+        return type_binding
+
+    @staticmethod
+    def process_types(type_map):
+        output = Generator.type_builder_fragments
+
+        class GenerateContext:
+            validator_writer = Writer(Generator.validator_impl_list, "")
+            cpp_writer = Writer(Generator.type_builder_impl_list, "")
+
+        def generate_all_domains_code(out, type_data_callback):
+            writer = Writer(out, "")
+            for domain_data in type_map.domains():
+                domain_fixes = DomainNameFixes.get_fixed_data(domain_data.name())
+
+                namespace_declared = []
+
+                def namespace_lazy_generator():
+                    if not namespace_declared:
+                        writer.newline("namespace ")
+                        writer.append(domain_data.name())
+                        writer.append(" {\n")
+                        # What is a better way to change value from outer scope?
+                        namespace_declared.append(True)
+                    return writer
+
+                for type_data in domain_data.types():
+                    type_data_callback(type_data, namespace_lazy_generator)
+
+                if namespace_declared:
+                    writer.append("} // ")
+                    writer.append(domain_data.name())
+                    writer.append("\n\n")
+
+        def create_type_builder_caller(generate_pass_id):
+            def call_type_builder(type_data, writer_getter):
+                code_generator = type_data.get_binding().get_code_generator()
+                if code_generator and generate_pass_id == code_generator.get_generate_pass_id():
+                    writer = writer_getter()
+
+                    code_generator.generate_type_builder(writer, GenerateContext)
+            return call_type_builder
+
+        generate_all_domains_code(output, create_type_builder_caller(TypeBuilderPass.MAIN))
+
+        Generator.type_builder_forwards.append("// Forward declarations.\n")
+
+        def generate_forward_callback(type_data, writer_getter):
+            if type_data in global_forward_listener.type_data_set:
+                binding = type_data.get_binding()
+                binding.get_code_generator().generate_forward_declaration(writer_getter())
+        generate_all_domains_code(Generator.type_builder_forwards, generate_forward_callback)
+
+        Generator.type_builder_forwards.append("// End of forward declarations.\n\n")
+
+        Generator.type_builder_forwards.append("// Typedefs.\n")
+
+        generate_all_domains_code(Generator.type_builder_forwards, create_type_builder_caller(TypeBuilderPass.TYPEDEF))
+
+        Generator.type_builder_forwards.append("// End of typedefs.\n\n")
+
+
+def flatten_list(input):
+    res = []
+
+    def fill_recursive(l):
+        for item in l:
+            if isinstance(item, list):
+                fill_recursive(item)
+            else:
+                res.append(item)
+    fill_recursive(input)
+    return res
+
+
+# A writer that only updates file if it actually changed to better support incremental build.
+class SmartOutput:
+    def __init__(self, file_name):
+        self.file_name_ = file_name
+        self.output_ = ""
+
+    def write(self, text):
+        self.output_ += text
+
+    def close(self):
+        text_changed = True
+
+        try:
+            read_file = open(self.file_name_, "r")
+            old_text = read_file.read()
+            read_file.close()
+            text_changed = old_text != self.output_
+        except:
+            # Ignore, just overwrite by default
+            pass
+
+        if text_changed:
+            out_file = open(self.file_name_, "w")
+            out_file.write(self.output_)
+            out_file.close()
+
+
+def output_file(file_name):
+    # For now, disable the incremental build optimisation in all cases.
+    if False:
+        return SmartOutput(file_name)
+    else:
+        return open(file_name, "w")
+
+
+Generator.go()
+
+backend_h_file = output_file(output_header_dirname + "/InspectorBackendDispatcher.h")
+backend_cpp_file = output_file(output_cpp_dirname + "/InspectorBackendDispatcher.cpp")
+
+frontend_h_file = output_file(output_header_dirname + "/InspectorFrontend.h")
+frontend_cpp_file = output_file(output_cpp_dirname + "/InspectorFrontend.cpp")
+
+typebuilder_h_file = output_file(output_header_dirname + "/InspectorTypeBuilder.h")
+typebuilder_cpp_file = output_file(output_cpp_dirname + "/InspectorTypeBuilder.cpp")
+
+
+backend_h_file.write(Templates.backend_h.substitute(None,
+    virtualSetters="\n".join(Generator.backend_virtual_setters_list),
+    agentInterfaces="".join(flatten_list(Generator.backend_agent_interface_list)),
+    methodNamesEnumContent="\n".join(Generator.method_name_enum_list)))
+
+backend_cpp_file.write(Templates.backend_cpp.substitute(None,
+    constructorInit="\n".join(Generator.backend_constructor_init_list),
+    setters="\n".join(Generator.backend_setters_list),
+    fieldDeclarations="\n".join(Generator.backend_field_list),
+    methodNameDeclarations="\n".join(Generator.backend_method_name_declaration_list),
+    methods="\n".join(Generator.backend_method_implementation_list),
+    methodDeclarations="\n".join(Generator.backend_method_declaration_list),
+    messageHandlers="\n".join(Generator.method_handler_list)))
+
+frontend_h_file.write(Templates.frontend_h.substitute(None,
+    fieldDeclarations="".join(Generator.frontend_class_field_lines),
+    domainClassList="".join(Generator.frontend_domain_class_lines)))
+
+frontend_cpp_file.write(Templates.frontend_cpp.substitute(None,
+    constructorInit="".join(Generator.frontend_constructor_init_list),
+    methods="\n".join(Generator.frontend_method_list)))
+
+typebuilder_h_file.write(Templates.typebuilder_h.substitute(None,
+    typeBuilders="".join(flatten_list(Generator.type_builder_fragments)),
+    forwards="".join(Generator.type_builder_forwards),
+    validatorIfdefName=VALIDATOR_IFDEF_NAME))
+
+typebuilder_cpp_file.write(Templates.typebuilder_cpp.substitute(None,
+    enumConstantValues=EnumConstants.get_enum_constant_code(),
+    implCode="".join(flatten_list(Generator.type_builder_impl_list)),
+    validatorCode="".join(flatten_list(Generator.validator_impl_list)),
+    validatorIfdefName=VALIDATOR_IFDEF_NAME))
+
+backend_h_file.close()
+backend_cpp_file.close()
+
+frontend_h_file.close()
+frontend_cpp_file.close()
+
+typebuilder_h_file.close()
+typebuilder_cpp_file.close()
diff --git a/Source/core/inspector/CodeGeneratorInspectorStrings.py b/Source/core/inspector/CodeGeneratorInspectorStrings.py
new file mode 100644
index 0000000..6c3fe05
--- /dev/null
+++ b/Source/core/inspector/CodeGeneratorInspectorStrings.py
@@ -0,0 +1,929 @@
+# Copyright (c) 2013 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.
+
+# THis file contains string resources for CodeGeneratorInspector.
+# Its syntax is a Python syntax subset, suitable for manual parsing.
+
+frontend_domain_class = (
+"""    class $domainClassName {
+    public:
+        $domainClassName(InspectorFrontendChannel* inspectorFrontendChannel) : m_inspectorFrontendChannel(inspectorFrontendChannel) { }
+${frontendDomainMethodDeclarations}        void setInspectorFrontendChannel(InspectorFrontendChannel* inspectorFrontendChannel) { m_inspectorFrontendChannel = inspectorFrontendChannel; }
+        InspectorFrontendChannel* getInspectorFrontendChannel() { return m_inspectorFrontendChannel; }
+    private:
+        InspectorFrontendChannel* m_inspectorFrontendChannel;
+    };
+
+    $domainClassName* $domainFieldName() { return &m_$domainFieldName; }
+
+""")
+
+backend_method = (
+"""void InspectorBackendDispatcherImpl::${domainName}_$methodName(long callId, InspectorObject*$requestMessageObject)
+{
+    RefPtr<InspectorArray> protocolErrors = InspectorArray::create();
+
+    if (!$agentField)
+        protocolErrors->pushString("${domainName} handler is not available.");
+$methodOutCode
+$methodInCode
+    RefPtr<InspectorObject> result = InspectorObject::create();
+    ErrorString error;
+    if (!protocolErrors->length()) {
+        $agentField->$methodName(&error$agentCallParams);
+
+${responseCook}
+    }
+    sendResponse(callId, result, commandNames[$commandNameIndex], protocolErrors, error);
+}
+""")
+
+frontend_method = ("""void InspectorFrontend::$domainName::$eventName($parameters)
+{
+    RefPtr<InspectorObject> jsonMessage = InspectorObject::create();
+    jsonMessage->setString("method", "$domainName.$eventName");
+$code    if (m_inspectorFrontendChannel)
+        m_inspectorFrontendChannel->sendMessageToFrontend(jsonMessage->toJSONString());
+}
+""")
+
+callback_method = (
+"""InspectorBackendDispatcher::$agentName::$callbackName::$callbackName(PassRefPtr<InspectorBackendDispatcherImpl> backendImpl, int id) : CallbackBase(backendImpl, id) {}
+
+void InspectorBackendDispatcher::$agentName::$callbackName::sendSuccess($parameters)
+{
+    RefPtr<InspectorObject> jsonMessage = InspectorObject::create();
+$code    sendIfActive(jsonMessage, ErrorString());
+}
+""")
+
+frontend_h = (
+"""#ifndef InspectorFrontend_h
+#define InspectorFrontend_h
+
+#include "InspectorTypeBuilder.h"
+#include "core/inspector/InspectorValues.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class InspectorFrontendChannel;
+
+typedef String ErrorString;
+
+class InspectorFrontend {
+public:
+    InspectorFrontend(InspectorFrontendChannel*);
+
+
+$domainClassList
+private:
+${fieldDeclarations}};
+
+} // namespace WebCore
+#endif // !defined(InspectorFrontend_h)
+""")
+
+backend_h = (
+"""#ifndef InspectorBackendDispatcher_h
+#define InspectorBackendDispatcher_h
+
+#include "InspectorTypeBuilder.h"
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class InspectorAgent;
+class InspectorObject;
+class InspectorArray;
+class InspectorFrontendChannel;
+
+typedef String ErrorString;
+
+class InspectorBackendDispatcherImpl;
+
+class InspectorBackendDispatcher: public RefCounted<InspectorBackendDispatcher> {
+public:
+    static PassRefPtr<InspectorBackendDispatcher> create(InspectorFrontendChannel* inspectorFrontendChannel);
+    virtual ~InspectorBackendDispatcher() { }
+
+    class CallbackBase: public RefCounted<CallbackBase> {
+    public:
+        CallbackBase(PassRefPtr<InspectorBackendDispatcherImpl> backendImpl, int id);
+        virtual ~CallbackBase();
+        void sendFailure(const ErrorString&);
+        bool isActive();
+
+    protected:
+        void sendIfActive(PassRefPtr<InspectorObject> partialMessage, const ErrorString& invocationError);
+
+    private:
+        void disable() { m_alreadySent = true; }
+
+        RefPtr<InspectorBackendDispatcherImpl> m_backendImpl;
+        int m_id;
+        bool m_alreadySent;
+
+        friend class InspectorBackendDispatcherImpl;
+    };
+
+$agentInterfaces
+$virtualSetters
+
+    virtual void clearFrontend() = 0;
+
+    enum CommonErrorCode {
+        ParseError = 0,
+        InvalidRequest,
+        MethodNotFound,
+        InvalidParams,
+        InternalError,
+        ServerError,
+        LastEntry,
+    };
+
+    void reportProtocolError(const long* const callId, CommonErrorCode, const String& errorMessage) const;
+    virtual void reportProtocolError(const long* const callId, CommonErrorCode, const String& errorMessage, PassRefPtr<InspectorArray> data) const = 0;
+    virtual void dispatch(const String& message) = 0;
+    static bool getCommandName(const String& message, String* result);
+
+    enum MethodNames {
+$methodNamesEnumContent
+
+        kMethodNamesEnumSize
+    };
+
+    static const char* commandNames[];
+};
+
+} // namespace WebCore
+#endif // !defined(InspectorBackendDispatcher_h)
+
+
+""")
+
+backend_cpp = (
+"""
+
+#include "config.h"
+#include "InspectorBackendDispatcher.h"
+
+
+#include "core/inspector/InspectorAgent.h"
+#include "core/inspector/InspectorFrontendChannel.h"
+#include "core/inspector/InspectorValues.h"
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+const char* InspectorBackendDispatcher::commandNames[] = {
+$methodNameDeclarations
+};
+
+
+class InspectorBackendDispatcherImpl : public InspectorBackendDispatcher {
+public:
+    InspectorBackendDispatcherImpl(InspectorFrontendChannel* inspectorFrontendChannel)
+        : m_inspectorFrontendChannel(inspectorFrontendChannel)
+$constructorInit
+    { }
+
+    virtual void clearFrontend() { m_inspectorFrontendChannel = 0; }
+    virtual void dispatch(const String& message);
+    virtual void reportProtocolError(const long* const callId, CommonErrorCode, const String& errorMessage, PassRefPtr<InspectorArray> data) const;
+    using InspectorBackendDispatcher::reportProtocolError;
+
+    void sendResponse(long callId, PassRefPtr<InspectorObject> result, const ErrorString& invocationError);
+    bool isActive() { return m_inspectorFrontendChannel; }
+
+$setters
+private:
+$methodDeclarations
+
+    InspectorFrontendChannel* m_inspectorFrontendChannel;
+$fieldDeclarations
+
+    template<typename R, typename V, typename V0>
+    static R getPropertyValueImpl(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors, V0 initial_value, bool (*as_method)(InspectorValue*, V*), const char* type_name);
+
+    static int getInt(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors);
+    static double getDouble(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors);
+    static String getString(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors);
+    static bool getBoolean(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors);
+    static PassRefPtr<InspectorObject> getObject(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors);
+    static PassRefPtr<InspectorArray> getArray(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors);
+
+    void sendResponse(long callId, PassRefPtr<InspectorObject> result, const char* commandName, PassRefPtr<InspectorArray> protocolErrors, ErrorString invocationError);
+
+};
+
+$methods
+
+PassRefPtr<InspectorBackendDispatcher> InspectorBackendDispatcher::create(InspectorFrontendChannel* inspectorFrontendChannel)
+{
+    return adoptRef(new InspectorBackendDispatcherImpl(inspectorFrontendChannel));
+}
+
+
+void InspectorBackendDispatcherImpl::dispatch(const String& message)
+{
+    RefPtr<InspectorBackendDispatcher> protect = this;
+    typedef void (InspectorBackendDispatcherImpl::*CallHandler)(long callId, InspectorObject* messageObject);
+    typedef HashMap<String, CallHandler> DispatchMap;
+    DEFINE_STATIC_LOCAL(DispatchMap, dispatchMap, );
+    long callId = 0;
+
+    if (dispatchMap.isEmpty()) {
+        static CallHandler handlers[] = {
+$messageHandlers
+        };
+        size_t length = WTF_ARRAY_LENGTH(commandNames);
+        for (size_t i = 0; i < length; ++i)
+            dispatchMap.add(commandNames[i], handlers[i]);
+    }
+
+    RefPtr<InspectorValue> parsedMessage = InspectorValue::parseJSON(message);
+    if (!parsedMessage) {
+        reportProtocolError(0, ParseError, "Message must be in JSON format");
+        return;
+    }
+
+    RefPtr<InspectorObject> messageObject = parsedMessage->asObject();
+    if (!messageObject) {
+        reportProtocolError(0, InvalidRequest, "Message must be a JSONified object");
+        return;
+    }
+
+    RefPtr<InspectorValue> callIdValue = messageObject->get("id");
+    if (!callIdValue) {
+        reportProtocolError(0, InvalidRequest, "'id' property was not found");
+        return;
+    }
+
+    if (!callIdValue->asNumber(&callId)) {
+        reportProtocolError(0, InvalidRequest, "The type of 'id' property must be number");
+        return;
+    }
+
+    RefPtr<InspectorValue> methodValue = messageObject->get("method");
+    if (!methodValue) {
+        reportProtocolError(&callId, InvalidRequest, "'method' property wasn't found");
+        return;
+    }
+
+    String method;
+    if (!methodValue->asString(&method)) {
+        reportProtocolError(&callId, InvalidRequest, "The type of 'method' property must be string");
+        return;
+    }
+
+    HashMap<String, CallHandler>::iterator it = dispatchMap.find(method);
+    if (it == dispatchMap.end()) {
+        reportProtocolError(&callId, MethodNotFound, "'" + method + "' wasn't found");
+        return;
+    }
+
+    ((*this).*it->value)(callId, messageObject.get());
+}
+
+void InspectorBackendDispatcherImpl::sendResponse(long callId, PassRefPtr<InspectorObject> result, const char* commandName, PassRefPtr<InspectorArray> protocolErrors, ErrorString invocationError)
+{
+    if (protocolErrors->length()) {
+        String errorMessage = String::format("Some arguments of method '%s' can't be processed", commandName);
+        reportProtocolError(&callId, InvalidParams, errorMessage, protocolErrors);
+        return;
+    }
+    sendResponse(callId, result, invocationError);
+}
+
+void InspectorBackendDispatcherImpl::sendResponse(long callId, PassRefPtr<InspectorObject> result, const ErrorString& invocationError)
+{
+    if (invocationError.length()) {
+        reportProtocolError(&callId, ServerError, invocationError);
+        return;
+    }
+
+    RefPtr<InspectorObject> responseMessage = InspectorObject::create();
+    responseMessage->setObject("result", result);
+    responseMessage->setNumber("id", callId);
+    if (m_inspectorFrontendChannel)
+        m_inspectorFrontendChannel->sendMessageToFrontend(responseMessage->toJSONString());
+}
+
+void InspectorBackendDispatcher::reportProtocolError(const long* const callId, CommonErrorCode code, const String& errorMessage) const
+{
+    reportProtocolError(callId, code, errorMessage, 0);
+}
+
+void InspectorBackendDispatcherImpl::reportProtocolError(const long* const callId, CommonErrorCode code, const String& errorMessage, PassRefPtr<InspectorArray> data) const
+{
+    DEFINE_STATIC_LOCAL(Vector<int>,s_commonErrors,);
+    if (!s_commonErrors.size()) {
+        s_commonErrors.insert(ParseError, -32700);
+        s_commonErrors.insert(InvalidRequest, -32600);
+        s_commonErrors.insert(MethodNotFound, -32601);
+        s_commonErrors.insert(InvalidParams, -32602);
+        s_commonErrors.insert(InternalError, -32603);
+        s_commonErrors.insert(ServerError, -32000);
+    }
+    ASSERT(code >=0);
+    ASSERT((unsigned)code < s_commonErrors.size());
+    ASSERT(s_commonErrors[code]);
+    RefPtr<InspectorObject> error = InspectorObject::create();
+    error->setNumber("code", s_commonErrors[code]);
+    error->setString("message", errorMessage);
+    ASSERT(error);
+    if (data)
+        error->setArray("data", data);
+    RefPtr<InspectorObject> message = InspectorObject::create();
+    message->setObject("error", error);
+    if (callId)
+        message->setNumber("id", *callId);
+    else
+        message->setValue("id", InspectorValue::null());
+    if (m_inspectorFrontendChannel)
+        m_inspectorFrontendChannel->sendMessageToFrontend(message->toJSONString());
+}
+
+template<typename R, typename V, typename V0>
+R InspectorBackendDispatcherImpl::getPropertyValueImpl(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors, V0 initial_value, bool (*as_method)(InspectorValue*, V*), const char* type_name)
+{
+    ASSERT(protocolErrors);
+
+    if (valueFound)
+        *valueFound = false;
+
+    V value = initial_value;
+
+    if (!object) {
+        if (!valueFound) {
+            // Required parameter in missing params container.
+            protocolErrors->pushString(String::format("'params' object must contain required parameter '%s' with type '%s'.", name.utf8().data(), type_name));
+        }
+        return value;
+    }
+
+    InspectorObject::const_iterator end = object->end();
+    InspectorObject::const_iterator valueIterator = object->find(name);
+
+    if (valueIterator == end) {
+        if (!valueFound)
+            protocolErrors->pushString(String::format("Parameter '%s' with type '%s' was not found.", name.utf8().data(), type_name));
+        return value;
+    }
+
+    if (!as_method(valueIterator->value.get(), &value))
+        protocolErrors->pushString(String::format("Parameter '%s' has wrong type. It must be '%s'.", name.utf8().data(), type_name));
+    else
+        if (valueFound)
+            *valueFound = true;
+    return value;
+}
+
+struct AsMethodBridges {
+    static bool asInt(InspectorValue* value, int* output) { return value->asNumber(output); }
+    static bool asDouble(InspectorValue* value, double* output) { return value->asNumber(output); }
+    static bool asString(InspectorValue* value, String* output) { return value->asString(output); }
+    static bool asBoolean(InspectorValue* value, bool* output) { return value->asBoolean(output); }
+    static bool asObject(InspectorValue* value, RefPtr<InspectorObject>* output) { return value->asObject(output); }
+    static bool asArray(InspectorValue* value, RefPtr<InspectorArray>* output) { return value->asArray(output); }
+};
+
+int InspectorBackendDispatcherImpl::getInt(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors)
+{
+    return getPropertyValueImpl<int, int, int>(object, name, valueFound, protocolErrors, 0, AsMethodBridges::asInt, "Number");
+}
+
+double InspectorBackendDispatcherImpl::getDouble(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors)
+{
+    return getPropertyValueImpl<double, double, double>(object, name, valueFound, protocolErrors, 0, AsMethodBridges::asDouble, "Number");
+}
+
+String InspectorBackendDispatcherImpl::getString(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors)
+{
+    return getPropertyValueImpl<String, String, String>(object, name, valueFound, protocolErrors, "", AsMethodBridges::asString, "String");
+}
+
+bool InspectorBackendDispatcherImpl::getBoolean(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors)
+{
+    return getPropertyValueImpl<bool, bool, bool>(object, name, valueFound, protocolErrors, false, AsMethodBridges::asBoolean, "Boolean");
+}
+
+PassRefPtr<InspectorObject> InspectorBackendDispatcherImpl::getObject(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors)
+{
+    return getPropertyValueImpl<PassRefPtr<InspectorObject>, RefPtr<InspectorObject>, InspectorObject*>(object, name, valueFound, protocolErrors, 0, AsMethodBridges::asObject, "Object");
+}
+
+PassRefPtr<InspectorArray> InspectorBackendDispatcherImpl::getArray(InspectorObject* object, const String& name, bool* valueFound, InspectorArray* protocolErrors)
+{
+    return getPropertyValueImpl<PassRefPtr<InspectorArray>, RefPtr<InspectorArray>, InspectorArray*>(object, name, valueFound, protocolErrors, 0, AsMethodBridges::asArray, "Array");
+}
+
+bool InspectorBackendDispatcher::getCommandName(const String& message, String* result)
+{
+    RefPtr<InspectorValue> value = InspectorValue::parseJSON(message);
+    if (!value)
+        return false;
+
+    RefPtr<InspectorObject> object = value->asObject();
+    if (!object)
+        return false;
+
+    if (!object->getString("method", result))
+        return false;
+
+    return true;
+}
+
+InspectorBackendDispatcher::CallbackBase::CallbackBase(PassRefPtr<InspectorBackendDispatcherImpl> backendImpl, int id)
+    : m_backendImpl(backendImpl), m_id(id), m_alreadySent(false) {}
+
+InspectorBackendDispatcher::CallbackBase::~CallbackBase() {}
+
+void InspectorBackendDispatcher::CallbackBase::sendFailure(const ErrorString& error)
+{
+    ASSERT(error.length());
+    sendIfActive(0, error);
+}
+
+bool InspectorBackendDispatcher::CallbackBase::isActive()
+{
+    return !m_alreadySent && m_backendImpl->isActive();
+}
+
+void InspectorBackendDispatcher::CallbackBase::sendIfActive(PassRefPtr<InspectorObject> partialMessage, const ErrorString& invocationError)
+{
+    if (m_alreadySent)
+        return;
+    m_backendImpl->sendResponse(m_id, partialMessage, invocationError);
+    m_alreadySent = true;
+}
+
+COMPILE_ASSERT(static_cast<int>(InspectorBackendDispatcher::kMethodNamesEnumSize) == WTF_ARRAY_LENGTH(InspectorBackendDispatcher::commandNames), command_name_array_problem);
+
+} // namespace WebCore
+
+""")
+
+frontend_cpp = (
+"""
+
+#include "config.h"
+
+#include "InspectorFrontend.h"
+#include "core/inspector/InspectorFrontendChannel.h"
+#include "core/inspector/InspectorValues.h"
+
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+InspectorFrontend::InspectorFrontend(InspectorFrontendChannel* inspectorFrontendChannel)
+    : $constructorInit{
+}
+
+$methods
+
+} // namespace WebCore
+
+""")
+
+typebuilder_h = (
+"""
+#ifndef InspectorTypeBuilder_h
+#define InspectorTypeBuilder_h
+
+#include "core/inspector/InspectorValues.h"
+
+#include <wtf/Assertions.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+namespace TypeBuilder {
+
+template<typename T>
+class OptOutput {
+public:
+    OptOutput() : m_assigned(false) { }
+
+    void operator=(T value)
+    {
+        m_value = value;
+        m_assigned = true;
+    }
+
+    bool isAssigned() { return m_assigned; }
+
+    T getValue()
+    {
+        ASSERT(isAssigned());
+        return m_value;
+    }
+
+private:
+    T m_value;
+    bool m_assigned;
+
+    WTF_MAKE_NONCOPYABLE(OptOutput);
+};
+
+
+// A small transient wrapper around int type, that can be used as a funciton parameter type
+// cleverly disallowing C++ implicit casts from float or double.
+class ExactlyInt {
+public:
+    template<typename T>
+    ExactlyInt(T t) : m_value(cast_to_int<T>(t)) {}
+
+    ExactlyInt() {}
+
+    operator int() { return m_value; }
+private:
+    int m_value;
+
+    template<typename T>
+    static int cast_to_int(T) { return T::default_case_cast_is_not_supported(); }
+};
+
+template<>
+inline int ExactlyInt::cast_to_int<int>(int i) { return i; }
+
+template<>
+inline int ExactlyInt::cast_to_int<unsigned int>(unsigned int i) { return i; }
+
+class RuntimeCastHelper {
+public:
+#if $validatorIfdefName
+    template<InspectorValue::Type TYPE>
+    static void assertType(InspectorValue* value)
+    {
+        ASSERT(value->type() == TYPE);
+    }
+    static void assertAny(InspectorValue*);
+    static void assertInt(InspectorValue* value);
+#endif
+};
+
+
+// This class provides "Traits" type for the input type T. It is programmed using C++ template specialization
+// technique. By default it simply takes "ItemTraits" type from T, but it doesn't work with the base types.
+template<typename T>
+struct ArrayItemHelper {
+    typedef typename T::ItemTraits Traits;
+};
+
+template<typename T>
+class Array : public InspectorArrayBase {
+private:
+    Array() { }
+
+    InspectorArray* openAccessors() {
+        COMPILE_ASSERT(sizeof(InspectorArray) == sizeof(Array<T>), cannot_cast);
+        return static_cast<InspectorArray*>(static_cast<InspectorArrayBase*>(this));
+    }
+
+public:
+    void addItem(PassRefPtr<T> value)
+    {
+        ArrayItemHelper<T>::Traits::pushRefPtr(this->openAccessors(), value);
+    }
+
+    void addItem(T value)
+    {
+        ArrayItemHelper<T>::Traits::pushRaw(this->openAccessors(), value);
+    }
+
+    static PassRefPtr<Array<T> > create()
+    {
+        return adoptRef(new Array<T>());
+    }
+
+    static PassRefPtr<Array<T> > runtimeCast(PassRefPtr<InspectorValue> value)
+    {
+        RefPtr<InspectorArray> array;
+        bool castRes = value->asArray(&array);
+        ASSERT_UNUSED(castRes, castRes);
+#if $validatorIfdefName
+        assertCorrectValue(array.get());
+#endif  // $validatorIfdefName
+        COMPILE_ASSERT(sizeof(Array<T>) == sizeof(InspectorArray), type_cast_problem);
+        return static_cast<Array<T>*>(static_cast<InspectorArrayBase*>(array.get()));
+    }
+
+#if $validatorIfdefName
+    static void assertCorrectValue(InspectorValue* value)
+    {
+        RefPtr<InspectorArray> array;
+        bool castRes = value->asArray(&array);
+        ASSERT_UNUSED(castRes, castRes);
+        for (unsigned i = 0; i < array->length(); i++)
+            ArrayItemHelper<T>::Traits::template assertCorrectValue<T>(array->get(i).get());
+    }
+
+#endif // $validatorIfdefName
+};
+
+struct StructItemTraits {
+    static void pushRefPtr(InspectorArray* array, PassRefPtr<InspectorValue> value)
+    {
+        array->pushValue(value);
+    }
+
+#if $validatorIfdefName
+    template<typename T>
+    static void assertCorrectValue(InspectorValue* value) {
+        T::assertCorrectValue(value);
+    }
+#endif  // $validatorIfdefName
+};
+
+template<>
+struct ArrayItemHelper<String> {
+    struct Traits {
+        static void pushRaw(InspectorArray* array, const String& value)
+        {
+            array->pushString(value);
+        }
+
+#if $validatorIfdefName
+        template<typename T>
+        static void assertCorrectValue(InspectorValue* value) {
+            RuntimeCastHelper::assertType<InspectorValue::TypeString>(value);
+        }
+#endif  // $validatorIfdefName
+    };
+};
+
+template<>
+struct ArrayItemHelper<int> {
+    struct Traits {
+        static void pushRaw(InspectorArray* array, int value)
+        {
+            array->pushInt(value);
+        }
+
+#if $validatorIfdefName
+        template<typename T>
+        static void assertCorrectValue(InspectorValue* value) {
+            RuntimeCastHelper::assertInt(value);
+        }
+#endif  // $validatorIfdefName
+    };
+};
+
+template<>
+struct ArrayItemHelper<double> {
+    struct Traits {
+        static void pushRaw(InspectorArray* array, double value)
+        {
+            array->pushNumber(value);
+        }
+
+#if $validatorIfdefName
+        template<typename T>
+        static void assertCorrectValue(InspectorValue* value) {
+            RuntimeCastHelper::assertType<InspectorValue::TypeNumber>(value);
+        }
+#endif  // $validatorIfdefName
+    };
+};
+
+template<>
+struct ArrayItemHelper<bool> {
+    struct Traits {
+        static void pushRaw(InspectorArray* array, bool value)
+        {
+            array->pushBoolean(value);
+        }
+
+#if $validatorIfdefName
+        template<typename T>
+        static void assertCorrectValue(InspectorValue* value) {
+            RuntimeCastHelper::assertType<InspectorValue::TypeBoolean>(value);
+        }
+#endif  // $validatorIfdefName
+    };
+};
+
+template<>
+struct ArrayItemHelper<InspectorValue> {
+    struct Traits {
+        static void pushRefPtr(InspectorArray* array, PassRefPtr<InspectorValue> value)
+        {
+            array->pushValue(value);
+        }
+
+#if $validatorIfdefName
+        template<typename T>
+        static void assertCorrectValue(InspectorValue* value) {
+            RuntimeCastHelper::assertAny(value);
+        }
+#endif  // $validatorIfdefName
+    };
+};
+
+template<>
+struct ArrayItemHelper<InspectorObject> {
+    struct Traits {
+        static void pushRefPtr(InspectorArray* array, PassRefPtr<InspectorValue> value)
+        {
+            array->pushValue(value);
+        }
+
+#if $validatorIfdefName
+        template<typename T>
+        static void assertCorrectValue(InspectorValue* value) {
+            RuntimeCastHelper::assertType<InspectorValue::TypeObject>(value);
+        }
+#endif  // $validatorIfdefName
+    };
+};
+
+template<>
+struct ArrayItemHelper<InspectorArray> {
+    struct Traits {
+        static void pushRefPtr(InspectorArray* array, PassRefPtr<InspectorArray> value)
+        {
+            array->pushArray(value);
+        }
+
+#if $validatorIfdefName
+        template<typename T>
+        static void assertCorrectValue(InspectorValue* value) {
+            RuntimeCastHelper::assertType<InspectorValue::TypeArray>(value);
+        }
+#endif  // $validatorIfdefName
+    };
+};
+
+template<typename T>
+struct ArrayItemHelper<TypeBuilder::Array<T> > {
+    struct Traits {
+        static void pushRefPtr(InspectorArray* array, PassRefPtr<TypeBuilder::Array<T> > value)
+        {
+            array->pushValue(value);
+        }
+
+#if $validatorIfdefName
+        template<typename S>
+        static void assertCorrectValue(InspectorValue* value) {
+            S::assertCorrectValue(value);
+        }
+#endif  // $validatorIfdefName
+    };
+};
+
+${forwards}
+
+String getEnumConstantValue(int code);
+
+${typeBuilders}
+} // namespace TypeBuilder
+
+
+} // namespace WebCore
+
+#endif // !defined(InspectorTypeBuilder_h)
+
+""")
+
+typebuilder_cpp = (
+"""
+
+#include "config.h"
+
+#include "InspectorTypeBuilder.h"
+
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+namespace TypeBuilder {
+
+const char* const enum_constant_values[] = {
+$enumConstantValues};
+
+String getEnumConstantValue(int code) {
+    return enum_constant_values[code];
+}
+
+} // namespace TypeBuilder
+
+$implCode
+
+#if $validatorIfdefName
+
+void TypeBuilder::RuntimeCastHelper::assertAny(InspectorValue*)
+{
+    // No-op.
+}
+
+
+void TypeBuilder::RuntimeCastHelper::assertInt(InspectorValue* value)
+{
+    double v;
+    bool castRes = value->asNumber(&v);
+    ASSERT_UNUSED(castRes, castRes);
+    ASSERT(static_cast<double>(static_cast<int>(v)) == v);
+}
+
+$validatorCode
+
+#endif // $validatorIfdefName
+
+} // namespace WebCore
+
+""")
+
+param_container_access_code = """
+    RefPtr<InspectorObject> paramsContainer = requestMessageObject->getObject("params");
+    InspectorObject* paramsContainerPtr = paramsContainer.get();
+    InspectorArray* protocolErrorsPtr = protocolErrors.get();
+"""
+
+class_binding_builder_part_1 = (
+"""        AllFieldsSet = %s
+    };
+
+    template<int STATE>
+    class Builder {
+    private:
+        RefPtr<InspectorObject> m_result;
+
+        template<int STEP> Builder<STATE | STEP>& castState()
+        {
+            return *reinterpret_cast<Builder<STATE | STEP>*>(this);
+        }
+
+        Builder(PassRefPtr</*%s*/InspectorObject> ptr)
+        {
+            COMPILE_ASSERT(STATE == NoFieldsSet, builder_created_in_non_init_state);
+            m_result = ptr;
+        }
+        friend class %s;
+    public:
+""")
+
+class_binding_builder_part_2 = ("""
+        Builder<STATE | %s>& set%s(%s value)
+        {
+            COMPILE_ASSERT(!(STATE & %s), property_%s_already_set);
+            m_result->set%s("%s", %s);
+            return castState<%s>();
+        }
+""")
+
+class_binding_builder_part_3 = ("""
+        operator RefPtr<%s>& ()
+        {
+            COMPILE_ASSERT(STATE == AllFieldsSet, result_is_not_ready);
+            COMPILE_ASSERT(sizeof(%s) == sizeof(InspectorObject), cannot_cast);
+            return *reinterpret_cast<RefPtr<%s>*>(&m_result);
+        }
+
+        PassRefPtr<%s> release()
+        {
+            return RefPtr<%s>(*this).release();
+        }
+    };
+
+""")
+
+class_binding_builder_part_4 = (
+"""    static Builder<NoFieldsSet> create()
+    {
+        return Builder<NoFieldsSet>(InspectorObject::create());
+    }
+""")
diff --git a/Source/core/inspector/ConsoleAPITypes.h b/Source/core/inspector/ConsoleAPITypes.h
new file mode 100644
index 0000000..11f65ec
--- /dev/null
+++ b/Source/core/inspector/ConsoleAPITypes.h
@@ -0,0 +1,48 @@
+/*
+ * 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:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#ifndef ConsoleAPITypes_h
+#define ConsoleAPITypes_h
+
+namespace WebCore {
+
+enum MessageType {
+    LogMessageType,
+    DirMessageType,
+    DirXMLMessageType,
+    TableMessageType,
+    TraceMessageType,
+    StartGroupMessageType,
+    StartGroupCollapsedMessageType,
+    EndGroupMessageType,
+    ClearMessageType,
+    AssertMessageType,
+    TimingMessageType,
+    ProfileMessageType,
+    ProfileEndMessageType
+};
+
+} // namespace WebCore
+
+#endif // ConsoleAPITypes_h
diff --git a/Source/core/inspector/ConsoleMessage.cpp b/Source/core/inspector/ConsoleMessage.cpp
new file mode 100644
index 0000000..d1f71b9
--- /dev/null
+++ b/Source/core/inspector/ConsoleMessage.cpp
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2009, 2010 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+
+
+#include "core/inspector/ConsoleMessage.h"
+
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptCallStackFactory.h"
+#include "bindings/v8/ScriptValue.h"
+#include "core/inspector/IdentifiersFactory.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/ScriptArguments.h"
+#include "core/inspector/ScriptCallFrame.h"
+#include "core/inspector/ScriptCallStack.h"
+#include "core/page/Console.h"
+#include <wtf/MainThread.h>
+
+namespace WebCore {
+
+ConsoleMessage::ConsoleMessage(bool canGenerateCallStack, MessageSource source, MessageType type, MessageLevel level, const String& message)
+    : m_source(source)
+    , m_type(type)
+    , m_level(level)
+    , m_message(message)
+    , m_url()
+    , m_line(0)
+    , m_repeatCount(1)
+    , m_requestId(IdentifiersFactory::requestId(0))
+{
+    autogenerateMetadata(canGenerateCallStack);
+}
+
+ConsoleMessage::ConsoleMessage(bool canGenerateCallStack, MessageSource source, MessageType type, MessageLevel level, const String& message, const String& url, unsigned line, ScriptState* state, unsigned long requestIdentifier)
+    : m_source(source)
+    , m_type(type)
+    , m_level(level)
+    , m_message(message)
+    , m_url(url)
+    , m_line(line)
+    , m_repeatCount(1)
+    , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
+{
+    autogenerateMetadata(canGenerateCallStack, state);
+}
+
+ConsoleMessage::ConsoleMessage(bool, MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptCallStack> callStack, unsigned long requestIdentifier)
+    : m_source(source)
+    , m_type(type)
+    , m_level(level)
+    , m_message(message)
+    , m_arguments(0)
+    , m_line(0)
+    , m_repeatCount(1)
+    , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
+{
+    if (callStack && callStack->size()) {
+        const ScriptCallFrame& frame = callStack->at(0);
+        m_url = frame.sourceURL();
+        m_line = frame.lineNumber();
+    }
+    m_callStack = callStack;
+}
+
+ConsoleMessage::ConsoleMessage(bool canGenerateCallStack, MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptArguments> arguments, ScriptState* state, unsigned long requestIdentifier)
+    : m_source(source)
+    , m_type(type)
+    , m_level(level)
+    , m_message(message)
+    , m_arguments(arguments)
+    , m_url()
+    , m_line(0)
+    , m_repeatCount(1)
+    , m_requestId(IdentifiersFactory::requestId(requestIdentifier))
+{
+    autogenerateMetadata(canGenerateCallStack, state);
+}
+
+ConsoleMessage::~ConsoleMessage()
+{
+}
+
+void ConsoleMessage::autogenerateMetadata(bool canGenerateCallStack, ScriptState* state)
+{
+    if (m_type == EndGroupMessageType)
+        return;
+
+    if (state)
+        m_callStack = createScriptCallStackForConsole(state);
+    else if (canGenerateCallStack)
+        m_callStack = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
+    else
+        return;
+
+    if (m_callStack && m_callStack->size()) {
+        const ScriptCallFrame& frame = m_callStack->at(0);
+        m_url = frame.sourceURL();
+        m_line = frame.lineNumber();
+        return;
+    }
+
+    m_callStack.clear();
+}
+
+static TypeBuilder::Console::ConsoleMessage::Source::Enum messageSourceValue(MessageSource source)
+{
+    switch (source) {
+    case XMLMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Xml;
+    case JSMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Javascript;
+    case NetworkMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Network;
+    case ConsoleAPIMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Console_api;
+    case StorageMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Storage;
+    case AppCacheMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Appcache;
+    case RenderingMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Rendering;
+    case CSSMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Css;
+    case SecurityMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Security;
+    case OtherMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Other;
+    case DeprecationMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Deprecation;
+    }
+    return TypeBuilder::Console::ConsoleMessage::Source::Other;
+}
+
+static TypeBuilder::Console::ConsoleMessage::Type::Enum messageTypeValue(MessageType type)
+{
+    switch (type) {
+    case LogMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Log;
+    case ClearMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Clear;
+    case DirMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Dir;
+    case DirXMLMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Dirxml;
+    case TableMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Table;
+    case TraceMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Trace;
+    case StartGroupMessageType: return TypeBuilder::Console::ConsoleMessage::Type::StartGroup;
+    case StartGroupCollapsedMessageType: return TypeBuilder::Console::ConsoleMessage::Type::StartGroupCollapsed;
+    case EndGroupMessageType: return TypeBuilder::Console::ConsoleMessage::Type::EndGroup;
+    case AssertMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Assert;
+    case TimingMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Timing;
+    case ProfileMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Profile;
+    case ProfileEndMessageType: return TypeBuilder::Console::ConsoleMessage::Type::ProfileEnd;
+    }
+    return TypeBuilder::Console::ConsoleMessage::Type::Log;
+}
+
+static TypeBuilder::Console::ConsoleMessage::Level::Enum messageLevelValue(MessageLevel level)
+{
+    switch (level) {
+    case DebugMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Debug;
+    case LogMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Log;
+    case WarningMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Warning;
+    case ErrorMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Error;
+    }
+    return TypeBuilder::Console::ConsoleMessage::Level::Log;
+}
+
+void ConsoleMessage::addToFrontend(InspectorFrontend::Console* frontend, InjectedScriptManager* injectedScriptManager, bool generatePreview)
+{
+    RefPtr<TypeBuilder::Console::ConsoleMessage> jsonObj = TypeBuilder::Console::ConsoleMessage::create()
+        .setSource(messageSourceValue(m_source))
+        .setLevel(messageLevelValue(m_level))
+        .setText(m_message);
+    // FIXME: only send out type for ConsoleAPI source messages.
+    jsonObj->setType(messageTypeValue(m_type));
+    jsonObj->setLine(static_cast<int>(m_line));
+    jsonObj->setUrl(m_url);
+    jsonObj->setRepeatCount(static_cast<int>(m_repeatCount));
+    if (m_source == NetworkMessageSource && !m_requestId.isEmpty())
+        jsonObj->setNetworkRequestId(m_requestId);
+    if (m_arguments && m_arguments->argumentCount()) {
+        InjectedScript injectedScript = injectedScriptManager->injectedScriptFor(m_arguments->globalState());
+        if (!injectedScript.hasNoValue()) {
+            RefPtr<TypeBuilder::Array<TypeBuilder::Runtime::RemoteObject> > jsonArgs = TypeBuilder::Array<TypeBuilder::Runtime::RemoteObject>::create();
+            if (m_type == TableMessageType && generatePreview && m_arguments->argumentCount()) {
+                ScriptValue table = m_arguments->argumentAt(0);
+                ScriptValue columns = m_arguments->argumentCount() > 1 ? m_arguments->argumentAt(1) : ScriptValue();
+                RefPtr<TypeBuilder::Runtime::RemoteObject> inspectorValue = injectedScript.wrapTable(table, columns);
+                if (!inspectorValue) {
+                    ASSERT_NOT_REACHED();
+                    return;
+                }
+                jsonArgs->addItem(inspectorValue);
+            } else {
+                for (unsigned i = 0; i < m_arguments->argumentCount(); ++i) {
+                    RefPtr<TypeBuilder::Runtime::RemoteObject> inspectorValue = injectedScript.wrapObject(m_arguments->argumentAt(i), "console", generatePreview);
+                    if (!inspectorValue) {
+                        ASSERT_NOT_REACHED();
+                        return;
+                    }
+                    jsonArgs->addItem(inspectorValue);
+                }
+            }
+            jsonObj->setParameters(jsonArgs);
+        }
+    }
+    if (m_callStack)
+        jsonObj->setStackTrace(m_callStack->buildInspectorArray());
+    frontend->messageAdded(jsonObj);
+}
+
+void ConsoleMessage::updateRepeatCountInConsole(InspectorFrontend::Console* frontend)
+{
+    frontend->messageRepeatCountUpdated(m_repeatCount);
+}
+
+bool ConsoleMessage::isEqual(ConsoleMessage* msg) const
+{
+    if (m_arguments) {
+        if (!m_arguments->isEqual(msg->m_arguments.get()))
+            return false;
+        // Never treat objects as equal - their properties might change over time.
+        for (size_t i = 0; i < m_arguments->argumentCount(); ++i) {
+            if (m_arguments->argumentAt(i).isObject())
+                return false;
+        }
+    } else if (msg->m_arguments)
+        return false;
+
+    if (m_callStack) {
+        if (!m_callStack->isEqual(msg->m_callStack.get()))
+            return false;
+    } else if (msg->m_callStack)
+        return false;
+
+    return msg->m_source == m_source
+        && msg->m_type == m_type
+        && msg->m_level == m_level
+        && msg->m_message == m_message
+        && msg->m_line == m_line
+        && msg->m_url == m_url
+        && msg->m_requestId == m_requestId;
+}
+
+void ConsoleMessage::windowCleared(DOMWindow* window)
+{
+    if (!m_arguments)
+        return;
+    if (domWindowFromScriptState(m_arguments->globalState()) != window)
+        return;
+    if (!m_message)
+        m_message = "<message collected>";
+    m_arguments.clear();
+}
+
+unsigned ConsoleMessage::argumentCount()
+{
+    if (m_arguments)
+        return m_arguments->argumentCount();
+    return 0;
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/ConsoleMessage.h b/Source/core/inspector/ConsoleMessage.h
new file mode 100644
index 0000000..1594df0
--- /dev/null
+++ b/Source/core/inspector/ConsoleMessage.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2009, 2010 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef ConsoleMessage_h
+#define ConsoleMessage_h
+
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptState.h"
+#include "core/inspector/ConsoleAPITypes.h"
+#include "core/page/ConsoleTypes.h"
+#include <wtf/Forward.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class DOMWindow;
+class InjectedScriptManager;
+class InspectorFrontend;
+class InspectorObject;
+class ScriptArguments;
+class ScriptCallFrame;
+class ScriptCallStack;
+class ScriptValue;
+
+class ConsoleMessage {
+    WTF_MAKE_NONCOPYABLE(ConsoleMessage); WTF_MAKE_FAST_ALLOCATED;
+public:
+    ConsoleMessage(bool canGenerateCallStack, MessageSource, MessageType, MessageLevel, const String& message);
+    ConsoleMessage(bool canGenerateCallStack, MessageSource, MessageType, MessageLevel, const String& message, const String& url, unsigned line, ScriptState*, unsigned long requestIdentifier);
+    ConsoleMessage(bool canGenerateCallStack, MessageSource, MessageType, MessageLevel, const String& message, PassRefPtr<ScriptCallStack>, unsigned long requestIdentifier);
+    ConsoleMessage(bool canGenerateCallStack, MessageSource, MessageType, MessageLevel, const String& message, PassRefPtr<ScriptArguments>, ScriptState*, unsigned long requestIdentifier);
+    ~ConsoleMessage();
+
+    void addToFrontend(InspectorFrontend::Console*, InjectedScriptManager*, bool generatePreview);
+    void updateRepeatCountInConsole(InspectorFrontend::Console*);
+    void incrementCount() { ++m_repeatCount; }
+    bool isEqual(ConsoleMessage* msg) const;
+
+    MessageSource source() const { return m_source; }
+    const String& message() const { return m_message; }
+    MessageType type() const { return m_type; }
+
+    void windowCleared(DOMWindow*);
+
+    unsigned argumentCount();
+
+private:
+    void autogenerateMetadata(bool canGenerateCallStack, ScriptState* = 0);
+
+    MessageSource m_source;
+    MessageType m_type;
+    MessageLevel m_level;
+    String m_message;
+    RefPtr<ScriptArguments> m_arguments;
+    RefPtr<ScriptCallStack> m_callStack;
+    String m_url;
+    unsigned m_line;
+    unsigned m_repeatCount;
+    String m_requestId;
+};
+
+} // namespace WebCore
+
+#endif // ConsoleMessage_h
diff --git a/Source/core/inspector/ContentSearchUtils.cpp b/Source/core/inspector/ContentSearchUtils.cpp
new file mode 100644
index 0000000..e294336
--- /dev/null
+++ b/Source/core/inspector/ContentSearchUtils.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2011 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:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS 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 GOOGLE INC.
+ * OR ITS 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.
+ */
+
+#include "config.h"
+
+#include "core/inspector/ContentSearchUtils.h"
+
+#include "core/inspector/InspectorValues.h"
+#include "core/platform/text/RegularExpression.h"
+#include <wtf/StdLibExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+namespace ContentSearchUtils {
+
+namespace {
+// This should be kept the same as the one in front-end/utilities.js
+static const char regexSpecialCharacters[] = "[](){}+-*.,?\\^$|";
+}
+
+static String createSearchRegexSource(const String& text)
+{
+    String result;
+    const UChar* characters = text.characters();
+    String specials(regexSpecialCharacters);
+
+    for (unsigned i = 0; i < text.length(); i++) {
+        if (specials.find(characters[i]) != notFound)
+            result.append("\\");
+        result.append(characters[i]);
+    }
+
+    return result;
+}
+
+static inline size_t sizetExtractor(const size_t* value)
+{
+    return *value;
+}
+
+TextPosition textPositionFromOffset(size_t offset, const Vector<size_t>& lineEndings)
+{
+    const size_t* foundLineEnding = approximateBinarySearch<size_t, size_t>(lineEndings, lineEndings.size(), offset, sizetExtractor);
+    size_t lineIndex = foundLineEnding - &lineEndings.at(0);
+    if (offset > *foundLineEnding)
+        ++lineIndex;
+    size_t lineStartOffset = lineIndex > 0 ? lineEndings.at(lineIndex - 1) + 1 : 0;
+    size_t column = offset - lineStartOffset;
+    return TextPosition(OrdinalNumber::fromZeroBasedInt(lineIndex), OrdinalNumber::fromZeroBasedInt(column));
+}
+
+static Vector<pair<int, String> > getRegularExpressionMatchesByLines(const RegularExpression* regex, const String& text)
+{
+    Vector<pair<int, String> > result;
+    if (text.isEmpty())
+        return result;
+
+    OwnPtr<Vector<size_t> > endings(lineEndings(text));
+    size_t size = endings->size();
+    unsigned start = 0;
+    for (size_t lineNumber = 0; lineNumber < size; ++lineNumber) {
+        size_t lineEnd = endings->at(lineNumber);
+        String line = text.substring(start, lineEnd - start);
+        if (line.endsWith('\r'))
+            line = line.left(line.length() - 1);
+
+        int matchLength;
+        if (regex->match(line, 0, &matchLength) != -1)
+            result.append(pair<int, String>(lineNumber, line));
+
+        start = lineEnd + 1;
+    }
+    return result;
+}
+
+PassOwnPtr<Vector<size_t> > lineEndings(const String& text)
+{
+    OwnPtr<Vector<size_t> > result(adoptPtr(new Vector<size_t>()));
+
+    unsigned start = 0;
+    while (start < text.length()) {
+        size_t lineEnd = text.find('\n', start);
+        if (lineEnd == notFound)
+            break;
+
+        result->append(lineEnd);
+        start = lineEnd + 1;
+    }
+    result->append(text.length());
+
+    return result.release();
+}
+
+static PassRefPtr<TypeBuilder::Page::SearchMatch> buildObjectForSearchMatch(int lineNumber, const String& lineContent)
+{
+    return TypeBuilder::Page::SearchMatch::create()
+        .setLineNumber(lineNumber)
+        .setLineContent(lineContent)
+        .release();
+}
+
+PassOwnPtr<RegularExpression> createSearchRegex(const String& query, bool caseSensitive, bool isRegex)
+{
+    String regexSource = isRegex ? query : createSearchRegexSource(query);
+    return adoptPtr(new RegularExpression(regexSource, caseSensitive ? TextCaseSensitive : TextCaseInsensitive));
+}
+
+int countRegularExpressionMatches(const RegularExpression* regex, const String& content)
+{
+    if (content.isEmpty())
+        return 0;
+
+    int result = 0;
+    int position;
+    unsigned start = 0;
+    int matchLength;
+    while ((position = regex->match(content, start, &matchLength)) != -1) {
+        if (start >= content.length())
+            break;
+        if (matchLength > 0)
+            ++result;
+        start = position + 1;
+    }
+    return result;
+}
+
+PassRefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchMatch> > searchInTextByLines(const String& text, const String& query, const bool caseSensitive, const bool isRegex)
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchMatch> > result = TypeBuilder::Array<TypeBuilder::Page::SearchMatch>::create();
+
+    OwnPtr<RegularExpression> regex = ContentSearchUtils::createSearchRegex(query, caseSensitive, isRegex);
+    Vector<pair<int, String> > matches = getRegularExpressionMatchesByLines(regex.get(), text);
+
+    for (Vector<pair<int, String> >::const_iterator it = matches.begin(); it != matches.end(); ++it)
+        result->addItem(buildObjectForSearchMatch(it->first, it->second));
+
+    return result;
+}
+
+static String findMagicComment(const String& content, const String& name)
+{
+    ASSERT(name.find("=") == notFound);
+    String pattern = "//@[\040\t]" + createSearchRegexSource(name) + "=[\040\t]*[^\\s\'\"]*[\040\t]*$";
+    RegularExpression regex(pattern, TextCaseSensitive, MultilineEnabled);
+
+    int matchLength;
+    int offset = regex.match(content, 0, &matchLength);
+    if (offset == -1)
+        return String();
+
+    String match = content.substring(offset, matchLength);
+    size_t separator = match.find("=");
+    ASSERT(separator != notFound);
+
+    return match.substring(separator + 1).stripWhiteSpace();
+}
+
+String findSourceURL(const String& content)
+{
+    return findMagicComment(content, "sourceURL");
+}
+
+String findSourceMapURL(const String& content)
+{
+    return findMagicComment(content, "sourceMappingURL");
+}
+
+} // namespace ContentSearchUtils
+} // namespace WebCore
+
diff --git a/Source/core/inspector/ContentSearchUtils.h b/Source/core/inspector/ContentSearchUtils.h
new file mode 100644
index 0000000..f7259de
--- /dev/null
+++ b/Source/core/inspector/ContentSearchUtils.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011 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:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS 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 GOOGLE INC.
+ * OR ITS 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.
+ */
+
+#ifndef ContentSearchUtils_h
+#define ContentSearchUtils_h
+
+
+#include "InspectorTypeBuilder.h"
+#include <wtf/Vector.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/TextPosition.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class InspectorArray;
+class RegularExpression;
+
+namespace ContentSearchUtils {
+
+PassOwnPtr<RegularExpression> createSearchRegex(const String& query, bool caseSensitive, bool isRegex);
+int countRegularExpressionMatches(const RegularExpression*, const String&);
+PassRefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchMatch> > searchInTextByLines(const String& text, const String& query, const bool caseSensitive, const bool isRegex);
+TextPosition textPositionFromOffset(size_t offset, const Vector<size_t>& lineEndings);
+PassOwnPtr<Vector<size_t> > lineEndings(const String&);
+
+String findSourceURL(const String& content);
+String findSourceMapURL(const String& content);
+
+} // namespace ContentSearchUtils
+} // namespace WebCore
+
+
+#endif // !defined(ContentSearchUtils_h)
diff --git a/Source/core/inspector/DOMEditor.cpp b/Source/core/inspector/DOMEditor.cpp
new file mode 100644
index 0000000..095e4b2
--- /dev/null
+++ b/Source/core/inspector/DOMEditor.cpp
@@ -0,0 +1,458 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+
+#include "core/inspector/DOMEditor.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/Node.h"
+#include "core/dom/Text.h"
+#include "core/inspector/DOMPatchSupport.h"
+#include "core/inspector/InspectorHistory.h"
+
+#include "core/editing/markup.h"
+
+#include <wtf/RefPtr.h>
+
+using namespace std;
+
+namespace WebCore {
+
+class DOMEditor::RemoveChildAction : public InspectorHistory::Action {
+    WTF_MAKE_NONCOPYABLE(RemoveChildAction);
+public:
+    RemoveChildAction(Node* parentNode, Node* node)
+        : InspectorHistory::Action("RemoveChild")
+        , m_parentNode(parentNode)
+        , m_node(node)
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        m_anchorNode = m_node->nextSibling();
+        return redo(ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        return m_parentNode->insertBefore(m_node.get(), m_anchorNode.get(), ec);
+    }
+
+    virtual bool redo(ExceptionCode& ec)
+    {
+        return m_parentNode->removeChild(m_node.get(), ec);
+    }
+
+private:
+    RefPtr<Node> m_parentNode;
+    RefPtr<Node> m_node;
+    RefPtr<Node> m_anchorNode;
+};
+
+class DOMEditor::InsertBeforeAction : public InspectorHistory::Action {
+    WTF_MAKE_NONCOPYABLE(InsertBeforeAction);
+public:
+    InsertBeforeAction(Node* parentNode, PassRefPtr<Node> node, Node* anchorNode)
+        : InspectorHistory::Action("InsertBefore")
+        , m_parentNode(parentNode)
+        , m_node(node)
+        , m_anchorNode(anchorNode)
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        if (m_node->parentNode()) {
+            m_removeChildAction = adoptPtr(new RemoveChildAction(m_node->parentNode(), m_node.get()));
+            if (!m_removeChildAction->perform(ec))
+                return false;
+        }
+        return m_parentNode->insertBefore(m_node.get(), m_anchorNode.get(), ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        if (!m_parentNode->removeChild(m_node.get(), ec))
+            return false;
+        if (m_removeChildAction)
+            return m_removeChildAction->undo(ec);
+        return true;
+    }
+
+    virtual bool redo(ExceptionCode& ec)
+    {
+        if (m_removeChildAction && !m_removeChildAction->redo(ec))
+            return false;
+        return m_parentNode->insertBefore(m_node.get(), m_anchorNode.get(), ec);
+    }
+
+private:
+    RefPtr<Node> m_parentNode;
+    RefPtr<Node> m_node;
+    RefPtr<Node> m_anchorNode;
+    OwnPtr<RemoveChildAction> m_removeChildAction;
+};
+
+class DOMEditor::RemoveAttributeAction : public InspectorHistory::Action {
+    WTF_MAKE_NONCOPYABLE(RemoveAttributeAction);
+public:
+    RemoveAttributeAction(Element* element, const String& name)
+        : InspectorHistory::Action("RemoveAttribute")
+        , m_element(element)
+        , m_name(name)
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        m_value = m_element->getAttribute(m_name);
+        return redo(ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        m_element->setAttribute(m_name, m_value, ec);
+        return true;
+    }
+
+    virtual bool redo(ExceptionCode&)
+    {
+        m_element->removeAttribute(m_name);
+        return true;
+    }
+
+private:
+    RefPtr<Element> m_element;
+    String m_name;
+    String m_value;
+};
+
+class DOMEditor::SetAttributeAction : public InspectorHistory::Action {
+    WTF_MAKE_NONCOPYABLE(SetAttributeAction);
+public:
+    SetAttributeAction(Element* element, const String& name, const String& value)
+        : InspectorHistory::Action("SetAttribute")
+        , m_element(element)
+        , m_name(name)
+        , m_value(value)
+        , m_hadAttribute(false)
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        m_hadAttribute = m_element->hasAttribute(m_name);
+        if (m_hadAttribute)
+            m_oldValue = m_element->getAttribute(m_name);
+        return redo(ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        if (m_hadAttribute)
+            m_element->setAttribute(m_name, m_oldValue, ec);
+        else
+            m_element->removeAttribute(m_name);
+        return true;
+    }
+
+    virtual bool redo(ExceptionCode& ec)
+    {
+        m_element->setAttribute(m_name, m_value, ec);
+        return true;
+    }
+
+private:
+    RefPtr<Element> m_element;
+    String m_name;
+    String m_value;
+    bool m_hadAttribute;
+    String m_oldValue;
+};
+
+class DOMEditor::SetOuterHTMLAction : public InspectorHistory::Action {
+    WTF_MAKE_NONCOPYABLE(SetOuterHTMLAction);
+public:
+    SetOuterHTMLAction(Node* node, const String& html)
+        : InspectorHistory::Action("SetOuterHTML")
+        , m_node(node)
+        , m_nextSibling(node->nextSibling())
+        , m_html(html)
+        , m_newNode(0)
+        , m_history(adoptPtr(new InspectorHistory()))
+        , m_domEditor(adoptPtr(new DOMEditor(m_history.get())))
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        m_oldHTML = createMarkup(m_node.get());
+        DOMPatchSupport domPatchSupport(m_domEditor.get(), m_node->ownerDocument());
+        m_newNode = domPatchSupport.patchNode(m_node.get(), m_html, ec);
+        return !ec;
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        return m_history->undo(ec);
+    }
+
+    virtual bool redo(ExceptionCode& ec)
+    {
+        return m_history->redo(ec);
+    }
+
+    Node* newNode()
+    {
+        return m_newNode;
+    }
+
+private:
+    RefPtr<Node> m_node;
+    RefPtr<Node> m_nextSibling;
+    String m_html;
+    String m_oldHTML;
+    Node* m_newNode;
+    OwnPtr<InspectorHistory> m_history;
+    OwnPtr<DOMEditor> m_domEditor;
+};
+
+class DOMEditor::ReplaceWholeTextAction : public InspectorHistory::Action {
+    WTF_MAKE_NONCOPYABLE(ReplaceWholeTextAction);
+public:
+    ReplaceWholeTextAction(Text* textNode, const String& text)
+        : InspectorHistory::Action("ReplaceWholeText")
+        , m_textNode(textNode)
+        , m_text(text)
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        m_oldText = m_textNode->wholeText();
+        return redo(ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        m_textNode->replaceWholeText(m_oldText, ec);
+        return true;
+    }
+
+    virtual bool redo(ExceptionCode& ec)
+    {
+        m_textNode->replaceWholeText(m_text, ec);
+        return true;
+    }
+
+private:
+    RefPtr<Text> m_textNode;
+    String m_text;
+    String m_oldText;
+};
+
+class DOMEditor::ReplaceChildNodeAction : public InspectorHistory::Action {
+    WTF_MAKE_NONCOPYABLE(ReplaceChildNodeAction);
+public:
+    ReplaceChildNodeAction(Node* parentNode, PassRefPtr<Node> newNode, Node* oldNode)
+        : InspectorHistory::Action("ReplaceChildNode")
+        , m_parentNode(parentNode)
+        , m_newNode(newNode)
+        , m_oldNode(oldNode)
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        return redo(ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        return m_parentNode->replaceChild(m_oldNode, m_newNode.get(), ec);
+    }
+
+    virtual bool redo(ExceptionCode& ec)
+    {
+        return m_parentNode->replaceChild(m_newNode, m_oldNode.get(), ec);
+    }
+
+private:
+    RefPtr<Node> m_parentNode;
+    RefPtr<Node> m_newNode;
+    RefPtr<Node> m_oldNode;
+};
+
+class DOMEditor::SetNodeValueAction : public InspectorHistory::Action {
+    WTF_MAKE_NONCOPYABLE(SetNodeValueAction);
+public:
+    SetNodeValueAction(Node* node, const String& value)
+        : InspectorHistory::Action("SetNodeValue")
+        , m_node(node)
+        , m_value(value)
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        m_oldValue = m_node->nodeValue();
+        return redo(ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        m_node->setNodeValue(m_oldValue, ec);
+        return !ec;
+    }
+
+    virtual bool redo(ExceptionCode& ec)
+    {
+        m_node->setNodeValue(m_value, ec);
+        return !ec;
+    }
+
+private:
+    RefPtr<Node> m_node;
+    String m_value;
+    String m_oldValue;
+};
+
+DOMEditor::DOMEditor(InspectorHistory* history) : m_history(history) { }
+
+DOMEditor::~DOMEditor() { }
+
+bool DOMEditor::insertBefore(Node* parentNode, PassRefPtr<Node> node, Node* anchorNode, ExceptionCode& ec)
+{
+    return m_history->perform(adoptPtr(new InsertBeforeAction(parentNode, node, anchorNode)), ec);
+}
+
+bool DOMEditor::removeChild(Node* parentNode, Node* node, ExceptionCode& ec)
+{
+    return m_history->perform(adoptPtr(new RemoveChildAction(parentNode, node)), ec);
+}
+
+bool DOMEditor::setAttribute(Element* element, const String& name, const String& value, ExceptionCode& ec)
+{
+    return m_history->perform(adoptPtr(new SetAttributeAction(element, name, value)), ec);
+}
+
+bool DOMEditor::removeAttribute(Element* element, const String& name, ExceptionCode& ec)
+{
+    return m_history->perform(adoptPtr(new RemoveAttributeAction(element, name)), ec);
+}
+
+bool DOMEditor::setOuterHTML(Node* node, const String& html, Node** newNode, ExceptionCode& ec)
+{
+    OwnPtr<SetOuterHTMLAction> action = adoptPtr(new SetOuterHTMLAction(node, html));
+    SetOuterHTMLAction* rawAction = action.get();
+    bool result = m_history->perform(action.release(), ec);
+    if (result)
+        *newNode = rawAction->newNode();
+    return result;
+}
+
+bool DOMEditor::replaceWholeText(Text* textNode, const String& text, ExceptionCode& ec)
+{
+    return m_history->perform(adoptPtr(new ReplaceWholeTextAction(textNode, text)), ec);
+}
+
+bool DOMEditor::replaceChild(Node* parentNode, PassRefPtr<Node> newNode, Node* oldNode, ExceptionCode& ec)
+{
+    return m_history->perform(adoptPtr(new ReplaceChildNodeAction(parentNode, newNode, oldNode)), ec);
+}
+
+bool DOMEditor::setNodeValue(Node* node, const String& value, ExceptionCode& ec)
+{
+    return m_history->perform(adoptPtr(new SetNodeValueAction(node, value)), ec);
+}
+
+static void populateErrorString(const ExceptionCode& ec, ErrorString* errorString)
+{
+    if (ec) {
+        ExceptionCodeDescription description(ec);
+        *errorString = description.name;
+    }
+}
+
+bool DOMEditor::insertBefore(Node* parentNode, PassRefPtr<Node> node, Node* anchorNode, ErrorString* errorString)
+{
+    ExceptionCode ec = 0;
+    bool result = insertBefore(parentNode, node, anchorNode, ec);
+    populateErrorString(ec, errorString);
+    return result;
+}
+
+bool DOMEditor::removeChild(Node* parentNode, Node* node, ErrorString* errorString)
+{
+    ExceptionCode ec = 0;
+    bool result = removeChild(parentNode, node, ec);
+    populateErrorString(ec, errorString);
+    return result;
+}
+
+bool DOMEditor::setAttribute(Element* element, const String& name, const String& value, ErrorString* errorString)
+{
+    ExceptionCode ec = 0;
+    bool result = setAttribute(element, name, value, ec);
+    populateErrorString(ec, errorString);
+    return result;
+}
+
+bool DOMEditor::removeAttribute(Element* element, const String& name, ErrorString* errorString)
+{
+    ExceptionCode ec = 0;
+    bool result = removeAttribute(element, name, ec);
+    populateErrorString(ec, errorString);
+    return result;
+}
+
+bool DOMEditor::setOuterHTML(Node* node, const String& html, Node** newNode, ErrorString* errorString)
+{
+    ExceptionCode ec = 0;
+    bool result = setOuterHTML(node, html, newNode, ec);
+    populateErrorString(ec, errorString);
+    return result;
+}
+
+bool DOMEditor::replaceWholeText(Text* textNode, const String& text, ErrorString* errorString)
+{
+    ExceptionCode ec = 0;
+    bool result = replaceWholeText(textNode, text, ec);
+    populateErrorString(ec, errorString);
+    return result;
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/DOMEditor.h b/Source/core/inspector/DOMEditor.h
new file mode 100644
index 0000000..7691588
--- /dev/null
+++ b/Source/core/inspector/DOMEditor.h
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#ifndef DOMEditor_h
+#define DOMEditor_h
+
+#include "core/dom/ExceptionCode.h"
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class Element;
+class InspectorHistory;
+class Node;
+class Text;
+
+
+typedef String ErrorString;
+
+class DOMEditor {
+    WTF_MAKE_NONCOPYABLE(DOMEditor); WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit DOMEditor(InspectorHistory*);
+    ~DOMEditor();
+
+    bool insertBefore(Node* parentNode, PassRefPtr<Node>, Node* anchorNode, ExceptionCode&);
+    bool removeChild(Node* parentNode, Node*, ExceptionCode&);
+    bool setAttribute(Element*, const String& name, const String& value, ExceptionCode&);
+    bool removeAttribute(Element*, const String& name, ExceptionCode&);
+    bool setOuterHTML(Node*, const String& html, Node** newNode, ExceptionCode&);
+    bool replaceWholeText(Text*, const String& text, ExceptionCode&);
+    bool replaceChild(Node* parentNode, PassRefPtr<Node> newNode, Node* oldNode, ExceptionCode&);
+    bool setNodeValue(Node* parentNode, const String& value, ExceptionCode&);
+
+    bool insertBefore(Node* parentNode, PassRefPtr<Node>, Node* anchorNode, ErrorString*);
+    bool removeChild(Node* parentNode, Node*, ErrorString*);
+    bool setAttribute(Element*, const String& name, const String& value, ErrorString*);
+    bool removeAttribute(Element*, const String& name, ErrorString*);
+    bool setOuterHTML(Node*, const String& html, Node** newNode, ErrorString*);
+    bool replaceWholeText(Text*, const String& text, ErrorString*);
+
+private:
+    class DOMAction;
+    class RemoveChildAction;
+    class InsertBeforeAction;
+    class RemoveAttributeAction;
+    class SetAttributeAction;
+    class SetOuterHTMLAction;
+    class ReplaceWholeTextAction;
+    class ReplaceChildNodeAction;
+    class SetNodeValueAction;
+
+    InspectorHistory* m_history;
+};
+
+
+} // namespace WebCore
+
+#endif // !defined(DOMEditor_h)
diff --git a/Source/core/inspector/DOMPatchSupport.cpp b/Source/core/inspector/DOMPatchSupport.cpp
new file mode 100644
index 0000000..12dc1b0
--- /dev/null
+++ b/Source/core/inspector/DOMPatchSupport.cpp
@@ -0,0 +1,527 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+
+#include "core/inspector/DOMPatchSupport.h"
+
+#include "HTMLNames.h"
+#include "core/dom/Attribute.h"
+#include "core/dom/ContextFeatures.h"
+#include "core/dom/Document.h"
+#include "core/dom/DocumentFragment.h"
+#include "core/dom/Node.h"
+#include "core/html/HTMLDocument.h"
+#include "core/html/HTMLElement.h"
+#include "core/html/HTMLHeadElement.h"
+#include "core/html/parser/HTMLDocumentParser.h"
+#include "core/inspector/DOMEditor.h"
+#include "core/inspector/InspectorHistory.h"
+#include "core/xml/parser/XMLDocumentParser.h"
+
+#include <wtf/Deque.h>
+#include <wtf/HashTraits.h>
+#include <wtf/RefPtr.h>
+#include <wtf/SHA1.h>
+#include <wtf/text/Base64.h>
+#include <wtf/text/CString.h>
+
+using namespace std;
+
+namespace WebCore {
+
+using HTMLNames::bodyTag;
+using HTMLNames::headTag;
+using HTMLNames::htmlTag;
+
+struct DOMPatchSupport::Digest {
+    explicit Digest(Node* node) : m_node(node) { }
+
+    String m_sha1;
+    String m_attrsSHA1;
+    Node* m_node;
+    Vector<OwnPtr<Digest> > m_children;
+};
+
+void DOMPatchSupport::patchDocument(Document* document, const String& markup)
+{
+    InspectorHistory history;
+    DOMEditor domEditor(&history);
+    DOMPatchSupport patchSupport(&domEditor, document);
+    patchSupport.patchDocument(markup);
+}
+
+DOMPatchSupport::DOMPatchSupport(DOMEditor* domEditor, Document* document)
+    : m_domEditor(domEditor)
+    , m_document(document)
+{
+}
+
+DOMPatchSupport::~DOMPatchSupport() { }
+
+void DOMPatchSupport::patchDocument(const String& markup)
+{
+    RefPtr<Document> newDocument;
+    if (m_document->isHTMLDocument())
+        newDocument = HTMLDocument::create(0, KURL());
+    else if (m_document->isXHTMLDocument())
+        newDocument = HTMLDocument::createXHTML(0, KURL());
+#if ENABLE(SVG)
+    else if (m_document->isSVGDocument())
+        newDocument = Document::create(0, KURL());
+#endif
+
+    ASSERT(newDocument);
+    newDocument->setContextFeatures(m_document->contextFeatures());
+    RefPtr<DocumentParser> parser;
+    if (m_document->isHTMLDocument())
+        parser = HTMLDocumentParser::create(static_cast<HTMLDocument*>(newDocument.get()), false);
+    else
+        parser = XMLDocumentParser::create(newDocument.get(), 0);
+    parser->insert(markup); // Use insert() so that the parser will not yield.
+    parser->finish();
+    parser->detach();
+
+    OwnPtr<Digest> oldInfo = createDigest(m_document->documentElement(), 0);
+    OwnPtr<Digest> newInfo = createDigest(newDocument->documentElement(), &m_unusedNodesMap);
+
+    if (!innerPatchNode(oldInfo.get(), newInfo.get(), IGNORE_EXCEPTION)) {
+        // Fall back to rewrite.
+        m_document->write(markup);
+        m_document->close();
+    }
+}
+
+Node* DOMPatchSupport::patchNode(Node* node, const String& markup, ExceptionCode& ec)
+{
+    // Don't parse <html> as a fragment.
+    if (node->isDocumentNode() || (node->parentNode() && node->parentNode()->isDocumentNode())) {
+        patchDocument(markup);
+        return 0;
+    }
+
+    Node* previousSibling = node->previousSibling();
+    // FIXME: This code should use one of createFragment* in markup.h
+    RefPtr<DocumentFragment> fragment = DocumentFragment::create(m_document);
+    if (m_document->isHTMLDocument())
+        fragment->parseHTML(markup, node->parentElement() ? node->parentElement() : m_document->documentElement());
+    else
+        fragment->parseXML(markup, node->parentElement() ? node->parentElement() : m_document->documentElement());
+
+    // Compose the old list.
+    ContainerNode* parentNode = node->parentNode();
+    Vector<OwnPtr<Digest> > oldList;
+    for (Node* child = parentNode->firstChild(); child; child = child->nextSibling())
+        oldList.append(createDigest(child, 0));
+
+    // Compose the new list.
+    String markupCopy = markup;
+    markupCopy.makeLower();
+    Vector<OwnPtr<Digest> > newList;
+    for (Node* child = parentNode->firstChild(); child != node; child = child->nextSibling())
+        newList.append(createDigest(child, 0));
+    for (Node* child = fragment->firstChild(); child; child = child->nextSibling()) {
+        if (child->hasTagName(headTag) && !child->firstChild() && markupCopy.find("</head>") == notFound)
+            continue; // HTML5 parser inserts empty <head> tag whenever it parses <body>
+        if (child->hasTagName(bodyTag) && !child->firstChild() && markupCopy.find("</body>") == notFound)
+            continue; // HTML5 parser inserts empty <body> tag whenever it parses </head>
+        newList.append(createDigest(child, &m_unusedNodesMap));
+    }
+    for (Node* child = node->nextSibling(); child; child = child->nextSibling())
+        newList.append(createDigest(child, 0));
+
+    if (!innerPatchChildren(parentNode, oldList, newList, ec)) {
+        // Fall back to total replace.
+        ec = 0;
+        if (!m_domEditor->replaceChild(parentNode, fragment.release(), node, ec))
+            return 0;
+    }
+    return previousSibling ? previousSibling->nextSibling() : parentNode->firstChild();
+}
+
+bool DOMPatchSupport::innerPatchNode(Digest* oldDigest, Digest* newDigest, ExceptionCode& ec)
+{
+    if (oldDigest->m_sha1 == newDigest->m_sha1)
+        return true;
+
+    Node* oldNode = oldDigest->m_node;
+    Node* newNode = newDigest->m_node;
+
+    if (newNode->nodeType() != oldNode->nodeType() || newNode->nodeName() != oldNode->nodeName())
+        return m_domEditor->replaceChild(oldNode->parentNode(), newNode, oldNode, ec);
+
+    if (oldNode->nodeValue() != newNode->nodeValue()) {
+        if (!m_domEditor->setNodeValue(oldNode, newNode->nodeValue(), ec))
+            return false;
+    }
+
+    if (oldNode->nodeType() != Node::ELEMENT_NODE)
+        return true;
+
+    // Patch attributes
+    Element* oldElement = toElement(oldNode);
+    Element* newElement = toElement(newNode);
+    if (oldDigest->m_attrsSHA1 != newDigest->m_attrsSHA1) {
+        // FIXME: Create a function in Element for removing all properties. Take in account whether did/willModifyAttribute are important.
+        if (oldElement->hasAttributesWithoutUpdate()) {
+            while (oldElement->attributeCount()) {
+                const Attribute* attribute = oldElement->attributeItem(0);
+                if (!m_domEditor->removeAttribute(oldElement, attribute->localName(), ec))
+                    return false;
+            }
+        }
+
+        // FIXME: Create a function in Element for copying properties. cloneDataFromElement() is close but not enough for this case.
+        if (newElement->hasAttributesWithoutUpdate()) {
+            size_t numAttrs = newElement->attributeCount();
+            for (size_t i = 0; i < numAttrs; ++i) {
+                const Attribute* attribute = newElement->attributeItem(i);
+                if (!m_domEditor->setAttribute(oldElement, attribute->name().localName(), attribute->value(), ec))
+                    return false;
+            }
+        }
+    }
+
+    bool result = innerPatchChildren(oldElement, oldDigest->m_children, newDigest->m_children, ec);
+    m_unusedNodesMap.remove(newDigest->m_sha1);
+    return result;
+}
+
+pair<DOMPatchSupport::ResultMap, DOMPatchSupport::ResultMap>
+DOMPatchSupport::diff(const Vector<OwnPtr<Digest> >& oldList, const Vector<OwnPtr<Digest> >& newList)
+{
+    ResultMap newMap(newList.size());
+    ResultMap oldMap(oldList.size());
+
+    for (size_t i = 0; i < oldMap.size(); ++i) {
+        oldMap[i].first = 0;
+        oldMap[i].second = 0;
+    }
+
+    for (size_t i = 0; i < newMap.size(); ++i) {
+        newMap[i].first = 0;
+        newMap[i].second = 0;
+    }
+
+    // Trim head and tail.
+    for (size_t i = 0; i < oldList.size() && i < newList.size() && oldList[i]->m_sha1 == newList[i]->m_sha1; ++i) {
+        oldMap[i].first = oldList[i].get();
+        oldMap[i].second = i;
+        newMap[i].first = newList[i].get();
+        newMap[i].second = i;
+    }
+    for (size_t i = 0; i < oldList.size() && i < newList.size() && oldList[oldList.size() - i - 1]->m_sha1 == newList[newList.size() - i - 1]->m_sha1; ++i) {
+        size_t oldIndex = oldList.size() - i - 1;
+        size_t newIndex = newList.size() - i - 1;
+        oldMap[oldIndex].first = oldList[oldIndex].get();
+        oldMap[oldIndex].second = newIndex;
+        newMap[newIndex].first = newList[newIndex].get();
+        newMap[newIndex].second = oldIndex;
+    }
+
+    typedef HashMap<String, Vector<size_t> > DiffTable;
+    DiffTable newTable;
+    DiffTable oldTable;
+
+    for (size_t i = 0; i < newList.size(); ++i) {
+        DiffTable::iterator it = newTable.add(newList[i]->m_sha1, Vector<size_t>()).iterator;
+        it->value.append(i);
+    }
+
+    for (size_t i = 0; i < oldList.size(); ++i) {
+        DiffTable::iterator it = oldTable.add(oldList[i]->m_sha1, Vector<size_t>()).iterator;
+        it->value.append(i);
+    }
+
+    for (DiffTable::iterator newIt = newTable.begin(); newIt != newTable.end(); ++newIt) {
+        if (newIt->value.size() != 1)
+            continue;
+
+        DiffTable::iterator oldIt = oldTable.find(newIt->key);
+        if (oldIt == oldTable.end() || oldIt->value.size() != 1)
+            continue;
+
+        newMap[newIt->value[0]] = make_pair(newList[newIt->value[0]].get(), oldIt->value[0]);
+        oldMap[oldIt->value[0]] = make_pair(oldList[oldIt->value[0]].get(), newIt->value[0]);
+    }
+
+    for (size_t i = 0; newList.size() > 0 && i < newList.size() - 1; ++i) {
+        if (!newMap[i].first || newMap[i + 1].first)
+            continue;
+
+        size_t j = newMap[i].second + 1;
+        if (j < oldMap.size() && !oldMap[j].first && newList[i + 1]->m_sha1 == oldList[j]->m_sha1) {
+            newMap[i + 1] = make_pair(newList[i + 1].get(), j);
+            oldMap[j] = make_pair(oldList[j].get(), i + 1);
+        }
+    }
+
+    for (size_t i = newList.size() - 1; newList.size() > 0 && i > 0; --i) {
+        if (!newMap[i].first || newMap[i - 1].first || newMap[i].second <= 0)
+            continue;
+
+        size_t j = newMap[i].second - 1;
+        if (!oldMap[j].first && newList[i - 1]->m_sha1 == oldList[j]->m_sha1) {
+            newMap[i - 1] = make_pair(newList[i - 1].get(), j);
+            oldMap[j] = make_pair(oldList[j].get(), i - 1);
+        }
+    }
+
+#ifdef DEBUG_DOM_PATCH_SUPPORT
+    dumpMap(oldMap, "OLD");
+    dumpMap(newMap, "NEW");
+#endif
+
+    return make_pair(oldMap, newMap);
+}
+
+bool DOMPatchSupport::innerPatchChildren(ContainerNode* parentNode, const Vector<OwnPtr<Digest> >& oldList, const Vector<OwnPtr<Digest> >& newList, ExceptionCode& ec)
+{
+    pair<ResultMap, ResultMap> resultMaps = diff(oldList, newList);
+    ResultMap& oldMap = resultMaps.first;
+    ResultMap& newMap = resultMaps.second;
+
+    Digest* oldHead = 0;
+    Digest* oldBody = 0;
+
+    // 1. First strip everything except for the nodes that retain. Collect pending merges.
+    HashMap<Digest*, Digest*> merges;
+    HashSet<size_t, WTF::IntHash<size_t>, WTF::UnsignedWithZeroKeyHashTraits<size_t> > usedNewOrdinals;
+    for (size_t i = 0; i < oldList.size(); ++i) {
+        if (oldMap[i].first) {
+            if (!usedNewOrdinals.contains(oldMap[i].second)) {
+                usedNewOrdinals.add(oldMap[i].second);
+                continue;
+            }
+            oldMap[i].first = 0;
+            oldMap[i].second = 0;
+        }
+
+        // Always match <head> and <body> tags with each other - we can't remove them from the DOM
+        // upon patching.
+        if (oldList[i]->m_node->hasTagName(headTag)) {
+            oldHead = oldList[i].get();
+            continue;
+        }
+        if (oldList[i]->m_node->hasTagName(bodyTag)) {
+            oldBody = oldList[i].get();
+            continue;
+        }
+
+        // Check if this change is between stable nodes. If it is, consider it as "modified".
+        if (!m_unusedNodesMap.contains(oldList[i]->m_sha1) && (!i || oldMap[i - 1].first) && (i == oldMap.size() - 1 || oldMap[i + 1].first)) {
+            size_t anchorCandidate = i ? oldMap[i - 1].second + 1 : 0;
+            size_t anchorAfter = i == oldMap.size() - 1 ? anchorCandidate + 1 : oldMap[i + 1].second;
+            if (anchorAfter - anchorCandidate == 1 && anchorCandidate < newList.size())
+                merges.set(newList[anchorCandidate].get(), oldList[i].get());
+            else {
+                if (!removeChildAndMoveToNew(oldList[i].get(), ec))
+                    return false;
+            }
+        } else {
+            if (!removeChildAndMoveToNew(oldList[i].get(), ec))
+                return false;
+        }
+    }
+
+    // Mark retained nodes as used, do not reuse node more than once.
+    HashSet<size_t, WTF::IntHash<size_t>, WTF::UnsignedWithZeroKeyHashTraits<size_t> >  usedOldOrdinals;
+    for (size_t i = 0; i < newList.size(); ++i) {
+        if (!newMap[i].first)
+            continue;
+        size_t oldOrdinal = newMap[i].second;
+        if (usedOldOrdinals.contains(oldOrdinal)) {
+            // Do not map node more than once
+            newMap[i].first = 0;
+            newMap[i].second = 0;
+            continue;
+        }
+        usedOldOrdinals.add(oldOrdinal);
+        markNodeAsUsed(newMap[i].first);
+    }
+
+    // Mark <head> and <body> nodes for merge.
+    if (oldHead || oldBody) {
+        for (size_t i = 0; i < newList.size(); ++i) {
+            if (oldHead && newList[i]->m_node->hasTagName(headTag))
+                merges.set(newList[i].get(), oldHead);
+            if (oldBody && newList[i]->m_node->hasTagName(bodyTag))
+                merges.set(newList[i].get(), oldBody);
+        }
+    }
+
+    // 2. Patch nodes marked for merge.
+    for (HashMap<Digest*, Digest*>::iterator it = merges.begin(); it != merges.end(); ++it) {
+        if (!innerPatchNode(it->value, it->key, ec))
+            return false;
+    }
+
+    // 3. Insert missing nodes.
+    for (size_t i = 0; i < newMap.size(); ++i) {
+        if (newMap[i].first || merges.contains(newList[i].get()))
+            continue;
+        if (!insertBeforeAndMarkAsUsed(parentNode, newList[i].get(), parentNode->childNode(i), ec))
+            return false;
+    }
+
+    // 4. Then put all nodes that retained into their slots (sort by new index).
+    for (size_t i = 0; i < oldMap.size(); ++i) {
+        if (!oldMap[i].first)
+            continue;
+        RefPtr<Node> node = oldMap[i].first->m_node;
+        Node* anchorNode = parentNode->childNode(oldMap[i].second);
+        if (node.get() == anchorNode)
+            continue;
+        if (node->hasTagName(bodyTag) || node->hasTagName(headTag))
+            continue; // Never move head or body, move the rest of the nodes around them.
+
+        if (!m_domEditor->insertBefore(parentNode, node.release(), anchorNode, ec))
+            return false;
+    }
+    return true;
+}
+
+static void addStringToSHA1(SHA1& sha1, const String& string)
+{
+    CString cString = string.utf8();
+    sha1.addBytes(reinterpret_cast<const uint8_t*>(cString.data()), cString.length());
+}
+
+PassOwnPtr<DOMPatchSupport::Digest> DOMPatchSupport::createDigest(Node* node, UnusedNodesMap* unusedNodesMap)
+{
+    Digest* digest = new Digest(node);
+
+    SHA1 sha1;
+
+    Node::NodeType nodeType = node->nodeType();
+    sha1.addBytes(reinterpret_cast<const uint8_t*>(&nodeType), sizeof(nodeType));
+    addStringToSHA1(sha1, node->nodeName());
+    addStringToSHA1(sha1, node->nodeValue());
+
+    if (node->nodeType() == Node::ELEMENT_NODE) {
+        Node* child = node->firstChild();
+        while (child) {
+            OwnPtr<Digest> childInfo = createDigest(child, unusedNodesMap);
+            addStringToSHA1(sha1, childInfo->m_sha1);
+            child = child->nextSibling();
+            digest->m_children.append(childInfo.release());
+        }
+        Element* element = toElement(node);
+
+        if (element->hasAttributesWithoutUpdate()) {
+            size_t numAttrs = element->attributeCount();
+            SHA1 attrsSHA1;
+            for (size_t i = 0; i < numAttrs; ++i) {
+                const Attribute* attribute = element->attributeItem(i);
+                addStringToSHA1(attrsSHA1, attribute->name().toString());
+                addStringToSHA1(attrsSHA1, attribute->value());
+            }
+            Vector<uint8_t, 20> attrsHash;
+            attrsSHA1.computeHash(attrsHash);
+            digest->m_attrsSHA1 = base64Encode(reinterpret_cast<const char*>(attrsHash.data()), 10);
+            addStringToSHA1(sha1, digest->m_attrsSHA1);
+        }
+    }
+
+    Vector<uint8_t, 20> hash;
+    sha1.computeHash(hash);
+    digest->m_sha1 = base64Encode(reinterpret_cast<const char*>(hash.data()), 10);
+    if (unusedNodesMap)
+        unusedNodesMap->add(digest->m_sha1, digest);
+    return adoptPtr(digest);
+}
+
+bool DOMPatchSupport::insertBeforeAndMarkAsUsed(ContainerNode* parentNode, Digest* digest, Node* anchor, ExceptionCode& ec)
+{
+    bool result = m_domEditor->insertBefore(parentNode, digest->m_node, anchor, ec);
+    markNodeAsUsed(digest);
+    return result;
+}
+
+bool DOMPatchSupport::removeChildAndMoveToNew(Digest* oldDigest, ExceptionCode& ec)
+{
+    RefPtr<Node> oldNode = oldDigest->m_node;
+    if (!m_domEditor->removeChild(oldNode->parentNode(), oldNode.get(), ec))
+        return false;
+
+    // Diff works within levels. In order not to lose the node identity when user
+    // prepends his HTML with "<div>" (i.e. all nodes are shifted to the next nested level),
+    // prior to dropping the original node on the floor, check whether new DOM has a digest
+    // with matching sha1. If it does, replace it with the original DOM chunk. Chances are
+    // high that it will get merged back into the original DOM during the further patching.
+    UnusedNodesMap::iterator it = m_unusedNodesMap.find(oldDigest->m_sha1);
+    if (it != m_unusedNodesMap.end()) {
+        Digest* newDigest = it->value;
+        Node* newNode = newDigest->m_node;
+        if (!m_domEditor->replaceChild(newNode->parentNode(), oldNode, newNode, ec))
+            return false;
+        newDigest->m_node = oldNode.get();
+        markNodeAsUsed(newDigest);
+        return true;
+    }
+
+    for (size_t i = 0; i < oldDigest->m_children.size(); ++i) {
+        if (!removeChildAndMoveToNew(oldDigest->m_children[i].get(), ec))
+            return false;
+    }
+    return true;
+}
+
+void DOMPatchSupport::markNodeAsUsed(Digest* digest)
+{
+    Deque<Digest*> queue;
+    queue.append(digest);
+    while (!queue.isEmpty()) {
+        Digest* first = queue.takeFirst();
+        m_unusedNodesMap.remove(first->m_sha1);
+        for (size_t i = 0; i < first->m_children.size(); ++i)
+            queue.append(first->m_children[i].get());
+    }
+}
+
+#ifdef DEBUG_DOM_PATCH_SUPPORT
+static String nodeName(Node* node)
+{
+    if (node->document()->isXHTMLDocument())
+         return node->nodeName();
+    return node->nodeName().lower();
+}
+
+void DOMPatchSupport::dumpMap(const ResultMap& map, const String& name)
+{
+    fprintf(stderr, "\n\n");
+    for (size_t i = 0; i < map.size(); ++i)
+        fprintf(stderr, "%s[%lu]: %s (%p) - [%lu]\n", name.utf8().data(), i, map[i].first ? nodeName(map[i].first->m_node).utf8().data() : "", map[i].first, map[i].second);
+}
+#endif
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/DOMPatchSupport.h b/Source/core/inspector/DOMPatchSupport.h
new file mode 100644
index 0000000..7e53a3e
--- /dev/null
+++ b/Source/core/inspector/DOMPatchSupport.h
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#ifndef DOMPatchSupport_h
+#define DOMPatchSupport_h
+
+#include "core/dom/ExceptionCode.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class ContainerNode;
+class DOMEditor;
+class Document;
+class Node;
+
+
+class DOMPatchSupport {
+    WTF_MAKE_NONCOPYABLE(DOMPatchSupport);
+public:
+    static void patchDocument(Document*, const String& markup);
+
+    DOMPatchSupport(DOMEditor*, Document*);
+    virtual ~DOMPatchSupport();
+
+    void patchDocument(const String& markup);
+    Node* patchNode(Node*, const String& markup, ExceptionCode&);
+
+private:
+    struct Digest;
+    typedef Vector<pair<Digest*, size_t> > ResultMap;
+    typedef HashMap<String, Digest*> UnusedNodesMap;
+
+    bool innerPatchNode(Digest* oldNode, Digest* newNode, ExceptionCode&);
+    std::pair<ResultMap, ResultMap> diff(const Vector<OwnPtr<Digest> >& oldChildren, const Vector<OwnPtr<Digest> >& newChildren);
+    bool innerPatchChildren(ContainerNode*, const Vector<OwnPtr<Digest> >& oldChildren, const Vector<OwnPtr<Digest> >& newChildren, ExceptionCode&);
+    PassOwnPtr<Digest> createDigest(Node*, UnusedNodesMap*);
+    bool insertBeforeAndMarkAsUsed(ContainerNode*, Digest*, Node* anchor, ExceptionCode&);
+    bool removeChildAndMoveToNew(Digest*, ExceptionCode&);
+    void markNodeAsUsed(Digest*);
+#ifdef DEBUG_DOM_PATCH_SUPPORT
+    void dumpMap(const ResultMap&, const String& name);
+#endif
+
+    DOMEditor* m_domEditor;
+    Document* m_document;
+
+    UnusedNodesMap m_unusedNodesMap;
+};
+
+
+} // namespace WebCore
+
+#endif // !defined(DOMPatchSupport_h)
diff --git a/Source/core/inspector/HeapGraphSerializer.cpp b/Source/core/inspector/HeapGraphSerializer.cpp
new file mode 100644
index 0000000..41d1824
--- /dev/null
+++ b/Source/core/inspector/HeapGraphSerializer.cpp
@@ -0,0 +1,253 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+
+#include "core/inspector/HeapGraphSerializer.h"
+
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/MemoryInstrumentationVector.h>
+#include <wtf/MemoryObjectInfo.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+HeapGraphSerializer::HeapGraphSerializer(Client* client)
+    : m_client(client)
+    , m_strings(Strings::create())
+    , m_edges(Edges::create())
+    , m_nodeEdgesCount(0)
+    , m_nodes(Nodes::create())
+    , m_baseToRealNodeIdMap(BaseToRealNodeIdMap::create())
+    , m_typeStrings(InspectorObject::create())
+    , m_leafCount(0)
+{
+    ASSERT(m_client);
+    m_strings->addItem(String()); // An empty string with 0 index.
+
+    memset(m_edgeTypes, 0, sizeof(m_edgeTypes));
+
+    m_edgeTypes[WTF::PointerMember] = registerTypeString("weak");
+    m_edgeTypes[WTF::RetainingPointer] = registerTypeString("property");
+
+    // FIXME: It is used as a magic constant for 'object' node type.
+    registerTypeString("object");
+
+    m_unknownClassNameId = registerString("unknown");
+}
+
+HeapGraphSerializer::~HeapGraphSerializer()
+{
+}
+
+void HeapGraphSerializer::pushUpdateIfNeeded()
+{
+    static const size_t chunkSize = 10000;
+    static const size_t averageEdgesPerNode = 5;
+
+    if (m_strings->length() <= chunkSize
+        && m_nodes->length() <= chunkSize * s_nodeFieldsCount
+        && m_edges->length() <= chunkSize * averageEdgesPerNode * s_edgeFieldsCount
+        && m_baseToRealNodeIdMap->length() <= chunkSize * s_idMapEntryFieldCount)
+        return;
+
+    pushUpdate();
+}
+
+void HeapGraphSerializer::pushUpdate()
+{
+    typedef TypeBuilder::Memory::HeapSnapshotChunk HeapSnapshotChunk;
+
+    RefPtr<HeapSnapshotChunk> chunk = HeapSnapshotChunk::create()
+        .setStrings(m_strings.release())
+        .setNodes(m_nodes.release())
+        .setEdges(m_edges.release())
+        .setBaseToRealNodeId(m_baseToRealNodeIdMap.release());
+
+    m_client->addNativeSnapshotChunk(chunk.release());
+
+    m_strings = Strings::create();
+    m_edges = Edges::create();
+    m_nodes = Nodes::create();
+    m_baseToRealNodeIdMap = BaseToRealNodeIdMap::create();
+}
+
+void HeapGraphSerializer::reportNode(const WTF::MemoryObjectInfo& info)
+{
+    ASSERT(info.reportedPointer());
+    reportNodeImpl(info, m_nodeEdgesCount);
+    m_nodeEdgesCount = 0;
+    if (info.isRoot())
+        m_roots.append(info.reportedPointer());
+    pushUpdateIfNeeded();
+}
+
+int HeapGraphSerializer::reportNodeImpl(const WTF::MemoryObjectInfo& info, int edgesCount)
+{
+    int nodeId = toNodeId(info.reportedPointer());
+    int classNameId = info.classNameId();
+    m_nodes->addItem(classNameId ? classNameId : m_unknownClassNameId);
+    m_nodes->addItem(info.nameId());
+    m_nodes->addItem(nodeId);
+    m_nodes->addItem(info.objectSize());
+    m_nodes->addItem(edgesCount);
+
+    return nodeId;
+}
+
+void HeapGraphSerializer::reportEdge(const void* to, const char* name, WTF::MemberType memberType)
+{
+    ASSERT(to);
+    reportEdgeImpl(toNodeId(to), name, m_edgeTypes[memberType]);
+    pushUpdateIfNeeded();
+}
+
+void HeapGraphSerializer::reportEdgeImpl(const int toNodeId, const char* name, int memberType)
+{
+    ASSERT(memberType >= 0);
+    ASSERT(memberType < WTF::LastMemberTypeEntry);
+
+    m_edges->addItem(memberType);
+    m_edges->addItem(registerString(name));
+    m_edges->addItem(toNodeId);
+
+    ++m_nodeEdgesCount;
+}
+
+void HeapGraphSerializer::reportLeaf(const WTF::MemoryObjectInfo& info, const char* edgeName)
+{
+    int nodeId = reportNodeImpl(info, 0);
+    reportEdgeImpl(nodeId, edgeName, m_edgeTypes[WTF::RetainingPointer]);
+    pushUpdateIfNeeded();
+}
+
+void HeapGraphSerializer::reportBaseAddress(const void* base, const void* real)
+{
+    m_baseToRealNodeIdMap->addItem(toNodeId(base));
+    m_baseToRealNodeIdMap->addItem(toNodeId(real));
+}
+
+PassRefPtr<InspectorObject> HeapGraphSerializer::finish()
+{
+    addRootNode();
+    pushUpdate();
+    String metaString =
+        "{"
+            "\"node_fields\":["
+                "\"type\","
+                "\"name\","
+                "\"id\","
+                "\"self_size\","
+                "\"edge_count\""
+            "],"
+            "\"node_types\":["
+                "[]," // FIXME: It is a fallback for Heap Snapshot parser. In case of Native Heap Snapshot it is a plain string id.
+                "\"string\","
+                "\"number\","
+                "\"number\","
+                "\"number\""
+            "],"
+            "\"edge_fields\":["
+                "\"type\","
+                "\"name_or_index\","
+                "\"to_node\""
+            "],"
+            "\"edge_types\":["
+                "[],"
+                "\"string_or_number\","
+                "\"node\""
+            "]"
+        "}";
+
+    RefPtr<InspectorValue> metaValue = InspectorValue::parseJSON(metaString);
+    RefPtr<InspectorObject> meta;
+    metaValue->asObject(&meta);
+    ASSERT(meta);
+    meta->setObject("type_strings", m_typeStrings);
+    return meta.release();
+}
+
+void HeapGraphSerializer::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Inspector);
+    info.ignoreMember(m_stringToIndex);
+    info.ignoreMember(m_strings);
+    info.ignoreMember(m_edges);
+    info.ignoreMember(m_nodes);
+    info.ignoreMember(m_baseToRealNodeIdMap);
+    info.ignoreMember(m_roots);
+}
+
+int HeapGraphSerializer::registerString(const char* string)
+{
+    if (!string)
+        return 0;
+    int length = strlen(string);
+    if (length > 256)
+        length = 256;
+    StringMap::AddResult result = m_stringToIndex.add(String(string, length), m_stringToIndex.size() + 1);
+    if (result.isNewEntry)
+        m_strings->addItem(string);
+    return result.iterator->value;
+}
+
+int HeapGraphSerializer::registerTypeString(const char* string)
+{
+    int stringId = registerString(string);
+    m_typeStrings->setNumber(string, stringId);
+    return stringId;
+}
+
+int HeapGraphSerializer::toNodeId(const void* to)
+{
+    if (!to)
+        return s_firstNodeId + m_address2NodeIdMap.size() + m_leafCount++;
+
+    Address2NodeId::AddResult result = m_address2NodeIdMap.add(to, s_firstNodeId + m_leafCount + m_address2NodeIdMap.size());
+    return result.iterator->value;
+}
+
+void HeapGraphSerializer::addRootNode()
+{
+    for (size_t i = 0; i < m_roots.size(); i++)
+        reportEdgeImpl(toNodeId(m_roots[i]), 0, m_edgeTypes[WTF::PointerMember]);
+
+    m_nodes->addItem(registerString("Root"));
+    m_nodes->addItem(0);
+    m_nodes->addItem(s_firstNodeId + m_address2NodeIdMap.size() + m_leafCount);
+    m_nodes->addItem(0);
+    m_nodes->addItem(m_roots.size());
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/HeapGraphSerializer.h b/Source/core/inspector/HeapGraphSerializer.h
new file mode 100644
index 0000000..6669805
--- /dev/null
+++ b/Source/core/inspector/HeapGraphSerializer.h
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+#ifndef HeapGraphSerializer_h
+#define HeapGraphSerializer_h
+
+
+#include "InspectorFrontend.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/MemoryInstrumentation.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+class HeapGraphSerializer {
+    WTF_MAKE_NONCOPYABLE(HeapGraphSerializer);
+public:
+
+    class Client {
+    public:
+        virtual ~Client() { }
+        virtual void addNativeSnapshotChunk(PassRefPtr<TypeBuilder::Memory::HeapSnapshotChunk>) = 0;
+    };
+
+    explicit HeapGraphSerializer(Client*);
+    ~HeapGraphSerializer();
+    void reportNode(const WTF::MemoryObjectInfo&);
+    void reportEdge(const void*, const char*, WTF::MemberType);
+    void reportLeaf(const WTF::MemoryObjectInfo&, const char*);
+    void reportBaseAddress(const void*, const void*);
+    int registerString(const char*);
+
+    PassRefPtr<InspectorObject> finish();
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+private:
+    void pushUpdateIfNeeded();
+    void pushUpdate();
+
+    int toNodeId(const void*);
+
+    void addRootNode();
+    int registerTypeString(const char*);
+
+    void reportEdgeImpl(const int toNodeId, const char* name, int memberType);
+    int reportNodeImpl(const WTF::MemoryObjectInfo&, int edgesCount);
+
+    Client* m_client;
+
+    typedef HashMap<String, int> StringMap;
+    StringMap m_stringToIndex;
+    typedef TypeBuilder::Array<String> Strings;
+    RefPtr<Strings> m_strings;
+
+    typedef TypeBuilder::Array<int> Edges;
+    RefPtr<Edges> m_edges;
+    int m_nodeEdgesCount;
+    static const size_t s_edgeFieldsCount = 3;
+
+    typedef TypeBuilder::Array<int> Nodes;
+    RefPtr<Nodes> m_nodes;
+    static const size_t s_nodeFieldsCount = 5;
+
+    typedef TypeBuilder::Array<int> BaseToRealNodeIdMap;
+    RefPtr<BaseToRealNodeIdMap> m_baseToRealNodeIdMap;
+    static const size_t s_idMapEntryFieldCount = 2;
+
+    typedef HashMap<const void*, int> Address2NodeId;
+    Address2NodeId m_address2NodeIdMap;
+
+    Vector<const void*> m_roots;
+    RefPtr<InspectorObject> m_typeStrings;
+
+    size_t m_edgeTypes[WTF::LastMemberTypeEntry];
+    int m_unknownClassNameId;
+    int m_leafCount;
+
+    static const int s_firstNodeId = 1;
+};
+
+} // namespace WebCore
+
+#endif // !defined(HeapGraphSerializer_h)
diff --git a/Source/core/inspector/IdentifiersFactory.cpp b/Source/core/inspector/IdentifiersFactory.cpp
new file mode 100644
index 0000000..f0c2b18
--- /dev/null
+++ b/Source/core/inspector/IdentifiersFactory.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+
+#include "config.h"
+
+
+#include "core/inspector/IdentifiersFactory.h"
+
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+namespace {
+static long s_lastUsedIdentifier = 0;
+}
+
+// static
+long IdentifiersFactory::s_processId;
+
+// static
+String IdentifiersFactory::createIdentifier()
+{
+    return addProcessIdPrefixTo(String::number(++s_lastUsedIdentifier));
+}
+
+// static
+String IdentifiersFactory::requestId(unsigned long identifier)
+{
+    if (identifier)
+        return addProcessIdPrefixTo(String::number(identifier));
+    return String();
+}
+
+// static
+String IdentifiersFactory::addProcessIdPrefixTo(const String& id)
+{
+    StringBuilder builder;
+    builder.appendNumber(s_processId);
+    builder.append('.');
+    builder.append(id);
+    return builder.toString();
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/IdentifiersFactory.h b/Source/core/inspector/IdentifiersFactory.h
new file mode 100644
index 0000000..6ec416c
--- /dev/null
+++ b/Source/core/inspector/IdentifiersFactory.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+
+#ifndef IdentifiersFactory_h
+#define IdentifiersFactory_h
+
+#include <wtf/text/WTFString.h>
+
+
+namespace WebCore {
+
+class IdentifiersFactory {
+public:
+    static void setProcessId(long processId) { s_processId = processId; }
+    static String createIdentifier();
+    static String requestId(unsigned long identifier);
+private:
+    static String addProcessIdPrefixTo(const String& id);
+
+    static long s_processId;
+};
+
+} // namespace WebCore
+
+
+#endif // IdentifiersFactory_h
diff --git a/Source/core/inspector/InjectedScript.cpp b/Source/core/inspector/InjectedScript.cpp
new file mode 100644
index 0000000..9b993d8
--- /dev/null
+++ b/Source/core/inspector/InjectedScript.cpp
@@ -0,0 +1,306 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+
+#include "core/inspector/InjectedScript.h"
+
+#include "bindings/v8/ScriptFunctionCall.h"
+#include "bindings/v8/SerializedScriptValue.h"
+#include "core/dom/Node.h"
+#include "core/inspector/InjectedScriptHost.h"
+#include "core/inspector/InjectedScriptModule.h"
+#include "core/inspector/InspectorValues.h"
+#include <wtf/text/WTFString.h>
+
+using WebCore::TypeBuilder::Array;
+using WebCore::TypeBuilder::Debugger::CallFrame;
+using WebCore::TypeBuilder::Runtime::PropertyDescriptor;
+using WebCore::TypeBuilder::Runtime::InternalPropertyDescriptor;
+using WebCore::TypeBuilder::Debugger::FunctionDetails;
+using WebCore::TypeBuilder::Runtime::RemoteObject;
+
+namespace WebCore {
+
+InjectedScript::InjectedScript()
+    : InjectedScriptBase("InjectedScript")
+{
+}
+
+InjectedScript::InjectedScript(ScriptObject injectedScriptObject, InspectedStateAccessCheck accessCheck)
+    : InjectedScriptBase("InjectedScript", injectedScriptObject, accessCheck)
+{
+}
+
+void InjectedScript::evaluate(ErrorString* errorString, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>* result, TypeBuilder::OptOutput<bool>* wasThrown)
+{
+    ScriptFunctionCall function(injectedScriptObject(), "evaluate");
+    function.appendArgument(expression);
+    function.appendArgument(objectGroup);
+    function.appendArgument(includeCommandLineAPI);
+    function.appendArgument(returnByValue);
+    function.appendArgument(generatePreview);
+    makeEvalCall(errorString, function, result, wasThrown);
+}
+
+void InjectedScript::callFunctionOn(ErrorString* errorString, const String& objectId, const String& expression, const String& arguments, bool returnByValue, bool generatePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>* result, TypeBuilder::OptOutput<bool>* wasThrown)
+{
+    ScriptFunctionCall function(injectedScriptObject(), "callFunctionOn");
+    function.appendArgument(objectId);
+    function.appendArgument(expression);
+    function.appendArgument(arguments);
+    function.appendArgument(returnByValue);
+    function.appendArgument(generatePreview);
+    makeEvalCall(errorString, function, result, wasThrown);
+}
+
+void InjectedScript::evaluateOnCallFrame(ErrorString* errorString, const ScriptValue& callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, RefPtr<RemoteObject>* result, TypeBuilder::OptOutput<bool>* wasThrown)
+{
+    ScriptFunctionCall function(injectedScriptObject(), "evaluateOnCallFrame");
+    function.appendArgument(callFrames);
+    function.appendArgument(callFrameId);
+    function.appendArgument(expression);
+    function.appendArgument(objectGroup);
+    function.appendArgument(includeCommandLineAPI);
+    function.appendArgument(returnByValue);
+    function.appendArgument(generatePreview);
+    makeEvalCall(errorString, function, result, wasThrown);
+}
+
+void InjectedScript::restartFrame(ErrorString* errorString, const ScriptValue& callFrames, const String& callFrameId, RefPtr<InspectorObject>* result)
+{
+    ScriptFunctionCall function(injectedScriptObject(), "restartFrame");
+    function.appendArgument(callFrames);
+    function.appendArgument(callFrameId);
+    RefPtr<InspectorValue> resultValue;
+    makeCall(function, &resultValue);
+    if (resultValue) {
+        if (resultValue->type() == InspectorValue::TypeString) {
+            resultValue->asString(errorString);
+            return;
+        }
+        if (resultValue->type() == InspectorValue::TypeObject) {
+            *result = resultValue->asObject();
+            return;
+        }
+    }
+    *errorString = "Internal error";
+}
+
+void InjectedScript::setVariableValue(ErrorString* errorString, const ScriptValue& callFrames, const String* callFrameIdOpt, const String* functionObjectIdOpt, int scopeNumber, const String& variableName, const String& newValueStr)
+{
+    ScriptFunctionCall function(injectedScriptObject(), "setVariableValue");
+    if (callFrameIdOpt) {
+        function.appendArgument(callFrames);
+        function.appendArgument(*callFrameIdOpt);
+    } else {
+        function.appendArgument(false);
+        function.appendArgument(false);
+    }
+    if (functionObjectIdOpt)
+        function.appendArgument(*functionObjectIdOpt);
+    else
+        function.appendArgument(false);
+    function.appendArgument(scopeNumber);
+    function.appendArgument(variableName);
+    function.appendArgument(newValueStr);
+    RefPtr<InspectorValue> resultValue;
+    makeCall(function, &resultValue);
+    if (!resultValue) {
+        *errorString = "Internal error";
+        return;
+    }
+    if (resultValue->type() == InspectorValue::TypeString) {
+        resultValue->asString(errorString);
+        return;
+    }
+    // Normal return.
+}
+
+void InjectedScript::getFunctionDetails(ErrorString* errorString, const String& functionId, RefPtr<FunctionDetails>* result)
+{
+    ScriptFunctionCall function(injectedScriptObject(), "getFunctionDetails");
+    function.appendArgument(functionId);
+    RefPtr<InspectorValue> resultValue;
+    makeCall(function, &resultValue);
+    if (!resultValue || resultValue->type() != InspectorValue::TypeObject) {
+        if (!resultValue->asString(errorString))
+            *errorString = "Internal error";
+        return;
+    }
+    *result = FunctionDetails::runtimeCast(resultValue);
+}
+
+void InjectedScript::getProperties(ErrorString* errorString, const String& objectId, bool ownProperties, RefPtr<Array<PropertyDescriptor> >* properties)
+{
+    ScriptFunctionCall function(injectedScriptObject(), "getProperties");
+    function.appendArgument(objectId);
+    function.appendArgument(ownProperties);
+
+    RefPtr<InspectorValue> result;
+    makeCall(function, &result);
+    if (!result || result->type() != InspectorValue::TypeArray) {
+        *errorString = "Internal error";
+        return;
+    }
+    *properties = Array<PropertyDescriptor>::runtimeCast(result);
+}
+
+void InjectedScript::getInternalProperties(ErrorString* errorString, const String& objectId, RefPtr<Array<InternalPropertyDescriptor> >* properties)
+{
+    ScriptFunctionCall function(injectedScriptObject(), "getInternalProperties");
+    function.appendArgument(objectId);
+
+    RefPtr<InspectorValue> result;
+    makeCall(function, &result);
+    if (!result || result->type() != InspectorValue::TypeArray) {
+        *errorString = "Internal error";
+        return;
+    }
+    RefPtr<Array<InternalPropertyDescriptor> > array = Array<InternalPropertyDescriptor>::runtimeCast(result);
+    if (array->length() > 0)
+        *properties = array;
+}
+
+Node* InjectedScript::nodeForObjectId(const String& objectId)
+{
+    if (hasNoValue() || !canAccessInspectedWindow())
+        return 0;
+
+    ScriptFunctionCall function(injectedScriptObject(), "nodeForObjectId");
+    function.appendArgument(objectId);
+
+    bool hadException = false;
+    ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException);
+    ASSERT(!hadException);
+
+    return InjectedScriptHost::scriptValueAsNode(resultValue);
+}
+
+void InjectedScript::releaseObject(const String& objectId)
+{
+    ScriptFunctionCall function(injectedScriptObject(), "releaseObject");
+    function.appendArgument(objectId);
+    RefPtr<InspectorValue> result;
+    makeCall(function, &result);
+}
+
+PassRefPtr<Array<CallFrame> > InjectedScript::wrapCallFrames(const ScriptValue& callFrames)
+{
+    ASSERT(!hasNoValue());
+    ScriptFunctionCall function(injectedScriptObject(), "wrapCallFrames");
+    function.appendArgument(callFrames);
+    bool hadException = false;
+    ScriptValue callFramesValue = callFunctionWithEvalEnabled(function, hadException);
+    ASSERT(!hadException);
+    RefPtr<InspectorValue> result = callFramesValue.toInspectorValue(scriptState());
+    if (result->type() == InspectorValue::TypeArray)
+        return Array<CallFrame>::runtimeCast(result);
+    return Array<CallFrame>::create();
+}
+
+PassRefPtr<TypeBuilder::Runtime::RemoteObject> InjectedScript::wrapObject(const ScriptValue& value, const String& groupName, bool generatePreview) const
+{
+    ASSERT(!hasNoValue());
+    ScriptFunctionCall wrapFunction(injectedScriptObject(), "wrapObject");
+    wrapFunction.appendArgument(value);
+    wrapFunction.appendArgument(groupName);
+    wrapFunction.appendArgument(canAccessInspectedWindow());
+    wrapFunction.appendArgument(generatePreview);
+    bool hadException = false;
+    ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException);
+    if (hadException)
+        return 0;
+    RefPtr<InspectorObject> rawResult = r.toInspectorValue(scriptState())->asObject();
+    return TypeBuilder::Runtime::RemoteObject::runtimeCast(rawResult);
+}
+
+PassRefPtr<TypeBuilder::Runtime::RemoteObject> InjectedScript::wrapTable(const ScriptValue& table, const ScriptValue& columns) const
+{
+    ASSERT(!hasNoValue());
+    ScriptFunctionCall wrapFunction(injectedScriptObject(), "wrapTable");
+    wrapFunction.appendArgument(canAccessInspectedWindow());
+    wrapFunction.appendArgument(table);
+    if (columns.hasNoValue())
+        wrapFunction.appendArgument(false);
+    else
+        wrapFunction.appendArgument(columns);
+    bool hadException = false;
+    ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException);
+    if (hadException)
+        return 0;
+    RefPtr<InspectorObject> rawResult = r.toInspectorValue(scriptState())->asObject();
+    return TypeBuilder::Runtime::RemoteObject::runtimeCast(rawResult);
+}
+
+PassRefPtr<TypeBuilder::Runtime::RemoteObject> InjectedScript::wrapNode(Node* node, const String& groupName)
+{
+    return wrapObject(nodeAsScriptValue(node), groupName);
+}
+
+ScriptValue InjectedScript::findObjectById(const String& objectId) const
+{
+    ASSERT(!hasNoValue());
+    ScriptFunctionCall function(injectedScriptObject(), "findObjectById");
+    function.appendArgument(objectId);
+
+    bool hadException = false;
+    ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException);
+    ASSERT(!hadException);
+    return resultValue;
+}
+
+void InjectedScript::inspectNode(Node* node)
+{
+    ASSERT(!hasNoValue());
+    ScriptFunctionCall function(injectedScriptObject(), "inspectNode");
+    function.appendArgument(nodeAsScriptValue(node));
+    RefPtr<InspectorValue> result;
+    makeCall(function, &result);
+}
+
+void InjectedScript::releaseObjectGroup(const String& objectGroup)
+{
+    ASSERT(!hasNoValue());
+    ScriptFunctionCall releaseFunction(injectedScriptObject(), "releaseObjectGroup");
+    releaseFunction.appendArgument(objectGroup);
+    bool hadException = false;
+    callFunctionWithEvalEnabled(releaseFunction, hadException);
+    ASSERT(!hadException);
+}
+
+ScriptValue InjectedScript::nodeAsScriptValue(Node* node)
+{
+    return InjectedScriptHost::nodeAsScriptValue(scriptState(), node);
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InjectedScript.h b/Source/core/inspector/InjectedScript.h
new file mode 100644
index 0000000..e3bbcc8
--- /dev/null
+++ b/Source/core/inspector/InjectedScript.h
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+#ifndef InjectedScript_h
+#define InjectedScript_h
+
+#include "InspectorTypeBuilder.h"
+#include "bindings/v8/ScriptObject.h"
+#include "core/inspector/InjectedScriptBase.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/ScriptArguments.h"
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class InjectedScriptModule;
+class Node;
+class SerializedScriptValue;
+
+
+class InjectedScript : public InjectedScriptBase {
+public:
+    InjectedScript();
+    ~InjectedScript() { }
+
+    void evaluate(ErrorString*,
+                  const String& expression,
+                  const String& objectGroup,
+                  bool includeCommandLineAPI,
+                  bool returnByValue,
+                  bool generatePreview,
+                  RefPtr<TypeBuilder::Runtime::RemoteObject>* result,
+                  TypeBuilder::OptOutput<bool>* wasThrown);
+    void callFunctionOn(ErrorString*,
+                        const String& objectId,
+                        const String& expression,
+                        const String& arguments,
+                        bool returnByValue,
+                        bool generatePreview,
+                        RefPtr<TypeBuilder::Runtime::RemoteObject>* result,
+                        TypeBuilder::OptOutput<bool>* wasThrown);
+    void evaluateOnCallFrame(ErrorString*,
+                             const ScriptValue& callFrames,
+                             const String& callFrameId,
+                             const String& expression,
+                             const String& objectGroup,
+                             bool includeCommandLineAPI,
+                             bool returnByValue,
+                             bool generatePreview,
+                             RefPtr<TypeBuilder::Runtime::RemoteObject>* result,
+                             TypeBuilder::OptOutput<bool>* wasThrown);
+    void restartFrame(ErrorString*, const ScriptValue& callFrames, const String& callFrameId, RefPtr<InspectorObject>* result);
+    void setVariableValue(ErrorString*, const ScriptValue& callFrames, const String* callFrameIdOpt, const String* functionObjectIdOpt, int scopeNumber, const String& variableName, const String& newValueStr);
+    void getFunctionDetails(ErrorString*, const String& functionId, RefPtr<TypeBuilder::Debugger::FunctionDetails>* result);
+    void getProperties(ErrorString*, const String& objectId, bool ownProperties, RefPtr<TypeBuilder::Array<TypeBuilder::Runtime::PropertyDescriptor> >* result);
+    void getInternalProperties(ErrorString*, const String& objectId, RefPtr<TypeBuilder::Array<TypeBuilder::Runtime::InternalPropertyDescriptor> >* result);
+    Node* nodeForObjectId(const String& objectId);
+    void releaseObject(const String& objectId);
+
+    PassRefPtr<TypeBuilder::Array<TypeBuilder::Debugger::CallFrame> > wrapCallFrames(const ScriptValue&);
+
+    PassRefPtr<TypeBuilder::Runtime::RemoteObject> wrapObject(const ScriptValue&, const String& groupName, bool generatePreview = false) const;
+    PassRefPtr<TypeBuilder::Runtime::RemoteObject> wrapTable(const ScriptValue& table, const ScriptValue& columns) const;
+    PassRefPtr<TypeBuilder::Runtime::RemoteObject> wrapNode(Node*, const String& groupName);
+    ScriptValue findObjectById(const String& objectId) const;
+
+    void inspectNode(Node*);
+    void releaseObjectGroup(const String&);
+
+private:
+    friend class InjectedScriptModule;
+    friend InjectedScript InjectedScriptManager::injectedScriptFor(ScriptState*);
+    InjectedScript(ScriptObject, InspectedStateAccessCheck);
+
+    ScriptValue nodeAsScriptValue(Node*);
+};
+
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/core/inspector/InjectedScriptBase.cpp b/Source/core/inspector/InjectedScriptBase.cpp
new file mode 100644
index 0000000..6da87cb
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptBase.cpp
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+
+#include "core/inspector/InjectedScriptBase.h"
+
+#include "bindings/v8/ScriptFunctionCall.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/InspectorValues.h"
+#include <wtf/text/WTFString.h>
+
+using WebCore::TypeBuilder::Runtime::RemoteObject;
+
+namespace WebCore {
+
+InjectedScriptBase::InjectedScriptBase(const String& name)
+    : m_name(name)
+    , m_inspectedStateAccessCheck(0)
+{
+}
+
+InjectedScriptBase::InjectedScriptBase(const String& name, ScriptObject injectedScriptObject, InspectedStateAccessCheck accessCheck)
+    : m_name(name)
+    , m_injectedScriptObject(injectedScriptObject)
+    , m_inspectedStateAccessCheck(accessCheck)
+{
+}
+
+void InjectedScriptBase::initialize(ScriptObject injectedScriptObject, InspectedStateAccessCheck accessCheck)
+{
+    m_injectedScriptObject = injectedScriptObject;
+    m_inspectedStateAccessCheck = accessCheck;
+}
+
+bool InjectedScriptBase::canAccessInspectedWindow() const
+{
+    return m_inspectedStateAccessCheck(m_injectedScriptObject.scriptState());
+}
+
+const ScriptObject& InjectedScriptBase::injectedScriptObject() const
+{
+    return m_injectedScriptObject;
+}
+
+ScriptValue InjectedScriptBase::callFunctionWithEvalEnabled(ScriptFunctionCall& function, bool& hadException) const
+{
+    ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromScriptState(m_injectedScriptObject.scriptState());
+    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willCallFunction(scriptExecutionContext, name(), 1);
+
+    ScriptState* scriptState = m_injectedScriptObject.scriptState();
+    bool evalIsDisabled = false;
+    if (scriptState) {
+        evalIsDisabled = !evalEnabled(scriptState);
+        // Temporarily enable allow evals for inspector.
+        if (evalIsDisabled)
+            setEvalEnabled(scriptState, true);
+    }
+
+    ScriptValue resultValue = function.call(hadException);
+
+    if (evalIsDisabled)
+        setEvalEnabled(scriptState, false);
+
+    InspectorInstrumentation::didCallFunction(cookie);
+    return resultValue;
+}
+
+void InjectedScriptBase::makeCall(ScriptFunctionCall& function, RefPtr<InspectorValue>* result)
+{
+    if (hasNoValue() || !canAccessInspectedWindow()) {
+        *result = InspectorValue::null();
+        return;
+    }
+
+    bool hadException = false;
+    ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException);
+
+    ASSERT(!hadException);
+    if (!hadException) {
+        *result = resultValue.toInspectorValue(m_injectedScriptObject.scriptState());
+        if (!*result)
+            *result = InspectorString::create(String::format("Object has too long reference chain(must not be longer than %d)", InspectorValue::maxDepth));
+    } else
+        *result = InspectorString::create("Exception while making a call.");
+}
+
+void InjectedScriptBase::makeEvalCall(ErrorString* errorString, ScriptFunctionCall& function, RefPtr<TypeBuilder::Runtime::RemoteObject>* objectResult, TypeBuilder::OptOutput<bool>* wasThrown)
+{
+    RefPtr<InspectorValue> result;
+    makeCall(function, &result);
+    if (!result) {
+        *errorString = "Internal error: result value is empty";
+        return;
+    }
+    if (result->type() == InspectorValue::TypeString) {
+        result->asString(errorString);
+        ASSERT(errorString->length());
+        return;
+    }
+    RefPtr<InspectorObject> resultPair = result->asObject();
+    if (!resultPair) {
+        *errorString = "Internal error: result is not an Object";
+        return;
+    }
+    RefPtr<InspectorObject> resultObj = resultPair->getObject("result");
+    bool wasThrownVal = false;
+    if (!resultObj || !resultPair->getBoolean("wasThrown", &wasThrownVal)) {
+        *errorString = "Internal error: result is not a pair of value and wasThrown flag";
+        return;
+    }
+    *objectResult = TypeBuilder::Runtime::RemoteObject::runtimeCast(resultObj);
+    *wasThrown = wasThrownVal;
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InjectedScriptBase.h b/Source/core/inspector/InjectedScriptBase.h
new file mode 100644
index 0000000..17b8ca3
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptBase.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#ifndef InjectedScriptBase_h
+#define InjectedScriptBase_h
+
+#include "InspectorTypeBuilder.h"
+#include "bindings/v8/ScriptObject.h"
+#include <wtf/Forward.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class InspectorValue;
+class ScriptFunctionCall;
+
+typedef String ErrorString;
+
+
+class InjectedScriptBase {
+public:
+    virtual ~InjectedScriptBase() { }
+
+    const String& name() const { return m_name; }
+    bool hasNoValue() const { return m_injectedScriptObject.hasNoValue(); }
+    ScriptState* scriptState() const { return m_injectedScriptObject.scriptState(); }
+
+protected:
+    typedef bool (*InspectedStateAccessCheck)(ScriptState*);
+    InjectedScriptBase(const String& name);
+    InjectedScriptBase(const String& name, ScriptObject, InspectedStateAccessCheck);
+
+    void initialize(ScriptObject, InspectedStateAccessCheck);
+    bool canAccessInspectedWindow() const;
+    const ScriptObject& injectedScriptObject() const;
+    ScriptValue callFunctionWithEvalEnabled(ScriptFunctionCall&, bool& hadException) const;
+    void makeCall(ScriptFunctionCall&, RefPtr<InspectorValue>* result);
+    void makeEvalCall(ErrorString*, ScriptFunctionCall&, RefPtr<TypeBuilder::Runtime::RemoteObject>* result, TypeBuilder::OptOutput<bool>* wasThrown);
+
+private:
+    String m_name;
+    ScriptObject m_injectedScriptObject;
+    InspectedStateAccessCheck m_inspectedStateAccessCheck;
+};
+
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/core/inspector/InjectedScriptCanvasModule.cpp b/Source/core/inspector/InjectedScriptCanvasModule.cpp
new file mode 100644
index 0000000..825f0aa
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptCanvasModule.cpp
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+
+#include "core/inspector/InjectedScriptCanvasModule.h"
+
+#include "InjectedScriptCanvasModuleSource.h"
+#include "bindings/v8/ScriptFunctionCall.h"
+#include "bindings/v8/ScriptObject.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InjectedScriptManager.h"
+
+using WebCore::TypeBuilder::Array;
+using WebCore::TypeBuilder::Canvas::ResourceId;
+using WebCore::TypeBuilder::Canvas::ResourceInfo;
+using WebCore::TypeBuilder::Canvas::ResourceState;
+using WebCore::TypeBuilder::Canvas::TraceLog;
+using WebCore::TypeBuilder::Canvas::TraceLogId;
+
+namespace WebCore {
+
+InjectedScriptCanvasModule::InjectedScriptCanvasModule()
+    : InjectedScriptModule("InjectedScriptCanvasModule")
+{
+}
+
+InjectedScriptCanvasModule InjectedScriptCanvasModule::moduleForState(InjectedScriptManager* injectedScriptManager, ScriptState* scriptState)
+{
+    InjectedScriptCanvasModule result;
+    result.ensureInjected(injectedScriptManager, scriptState);
+    return result;
+}
+
+String InjectedScriptCanvasModule::source() const
+{
+    return String(reinterpret_cast<const char*>(InjectedScriptCanvasModuleSource_js), sizeof(InjectedScriptCanvasModuleSource_js));
+}
+
+ScriptObject InjectedScriptCanvasModule::wrapCanvas2DContext(const ScriptObject& context)
+{
+    return callWrapContextFunction("wrapCanvas2DContext", context);
+}
+
+ScriptObject InjectedScriptCanvasModule::wrapWebGLContext(const ScriptObject& glContext)
+{
+    return callWrapContextFunction("wrapWebGLContext", glContext);
+}
+
+ScriptObject InjectedScriptCanvasModule::callWrapContextFunction(const String& functionName, const ScriptObject& context)
+{
+    ScriptFunctionCall function(injectedScriptObject(), functionName);
+    function.appendArgument(context);
+    bool hadException = false;
+    ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException);
+    if (hadException || resultValue.hasNoValue() || !resultValue.isObject()) {
+        ASSERT_NOT_REACHED();
+        return ScriptObject();
+    }
+    return ScriptObject(context.scriptState(), resultValue);
+}
+
+void InjectedScriptCanvasModule::markFrameEnd()
+{
+    ScriptFunctionCall function(injectedScriptObject(), "markFrameEnd");
+    RefPtr<InspectorValue> resultValue;
+    makeCall(function, &resultValue);
+    ASSERT(resultValue);
+}
+
+void InjectedScriptCanvasModule::captureFrame(ErrorString* errorString, TraceLogId* traceLogId)
+{
+    callStartCapturingFunction("captureFrame", errorString, traceLogId);
+}
+
+void InjectedScriptCanvasModule::startCapturing(ErrorString* errorString, TraceLogId* traceLogId)
+{
+    callStartCapturingFunction("startCapturing", errorString, traceLogId);
+}
+
+void InjectedScriptCanvasModule::callStartCapturingFunction(const String& functionName, ErrorString* errorString, TraceLogId* traceLogId)
+{
+    ScriptFunctionCall function(injectedScriptObject(), functionName);
+    RefPtr<InspectorValue> resultValue;
+    makeCall(function, &resultValue);
+    if (!resultValue || resultValue->type() != InspectorValue::TypeString || !resultValue->asString(traceLogId))
+        *errorString = "Internal error: " + functionName;
+}
+
+void InjectedScriptCanvasModule::stopCapturing(ErrorString* errorString, const TraceLogId& traceLogId)
+{
+    callVoidFunctionWithTraceLogIdArgument("stopCapturing", errorString, traceLogId);
+}
+
+void InjectedScriptCanvasModule::dropTraceLog(ErrorString* errorString, const TraceLogId& traceLogId)
+{
+    callVoidFunctionWithTraceLogIdArgument("dropTraceLog", errorString, traceLogId);
+}
+
+void InjectedScriptCanvasModule::callVoidFunctionWithTraceLogIdArgument(const String& functionName, ErrorString* errorString, const TraceLogId& traceLogId)
+{
+    ScriptFunctionCall function(injectedScriptObject(), functionName);
+    function.appendArgument(traceLogId);
+    bool hadException = false;
+    callFunctionWithEvalEnabled(function, hadException);
+    ASSERT(!hadException);
+    if (hadException)
+        *errorString = "Internal error: " + functionName;
+}
+
+void InjectedScriptCanvasModule::traceLog(ErrorString* errorString, const TraceLogId& traceLogId, const int* startOffset, const int* maxLength, RefPtr<TraceLog>* traceLog)
+{
+    ScriptFunctionCall function(injectedScriptObject(), "traceLog");
+    function.appendArgument(traceLogId);
+    if (startOffset)
+        function.appendArgument(*startOffset);
+    if (maxLength)
+        function.appendArgument(*maxLength);
+    RefPtr<InspectorValue> resultValue;
+    makeCall(function, &resultValue);
+    if (!resultValue || resultValue->type() != InspectorValue::TypeObject) {
+        if (!resultValue->asString(errorString))
+            *errorString = "Internal error: traceLog";
+        return;
+    }
+    *traceLog = TraceLog::runtimeCast(resultValue);
+}
+
+void InjectedScriptCanvasModule::replayTraceLog(ErrorString* errorString, const TraceLogId& traceLogId, int stepNo, RefPtr<ResourceState>* result)
+{
+    ScriptFunctionCall function(injectedScriptObject(), "replayTraceLog");
+    function.appendArgument(traceLogId);
+    function.appendArgument(stepNo);
+    RefPtr<InspectorValue> resultValue;
+    makeCall(function, &resultValue);
+    if (!resultValue || resultValue->type() != InspectorValue::TypeObject) {
+        if (!resultValue->asString(errorString))
+            *errorString = "Internal error: replayTraceLog";
+        return;
+    }
+    *result = ResourceState::runtimeCast(resultValue);
+}
+
+void InjectedScriptCanvasModule::resourceInfo(ErrorString* errorString, const ResourceId& resourceId, RefPtr<ResourceInfo>* result)
+{
+    ScriptFunctionCall function(injectedScriptObject(), "resourceInfo");
+    function.appendArgument(resourceId);
+    RefPtr<InspectorValue> resultValue;
+    makeCall(function, &resultValue);
+    if (!resultValue || resultValue->type() != InspectorValue::TypeObject) {
+        if (!resultValue->asString(errorString))
+            *errorString = "Internal error: resourceInfo";
+        return;
+    }
+    *result = ResourceInfo::runtimeCast(resultValue);
+}
+
+void InjectedScriptCanvasModule::resourceState(ErrorString* errorString, const TraceLogId& traceLogId, const ResourceId& resourceId, RefPtr<ResourceState>* result)
+{
+    ScriptFunctionCall function(injectedScriptObject(), "resourceState");
+    function.appendArgument(traceLogId);
+    function.appendArgument(resourceId);
+    RefPtr<InspectorValue> resultValue;
+    makeCall(function, &resultValue);
+    if (!resultValue || resultValue->type() != InspectorValue::TypeObject) {
+        if (!resultValue->asString(errorString))
+            *errorString = "Internal error: resourceState";
+        return;
+    }
+    *result = ResourceState::runtimeCast(resultValue);
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InjectedScriptCanvasModule.h b/Source/core/inspector/InjectedScriptCanvasModule.h
new file mode 100644
index 0000000..8999373
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptCanvasModule.h
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#ifndef InjectedScriptCanvasModule_h
+#define InjectedScriptCanvasModule_h
+
+#include "bindings/v8/ScriptState.h"
+#include "core/inspector/InjectedScriptModule.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class InjectedScriptManager;
+class ScriptObject;
+
+
+class InjectedScriptCanvasModule : public InjectedScriptModule {
+public:
+    InjectedScriptCanvasModule();
+    
+    virtual String source() const;
+
+    static InjectedScriptCanvasModule moduleForState(InjectedScriptManager*, ScriptState*);
+
+    ScriptObject wrapCanvas2DContext(const ScriptObject&);
+    ScriptObject wrapWebGLContext(const ScriptObject&);
+    void markFrameEnd();
+
+    void captureFrame(ErrorString*, TypeBuilder::Canvas::TraceLogId*);
+    void startCapturing(ErrorString*, TypeBuilder::Canvas::TraceLogId*);
+    void stopCapturing(ErrorString*, const TypeBuilder::Canvas::TraceLogId&);
+    void dropTraceLog(ErrorString*, const TypeBuilder::Canvas::TraceLogId&);
+    void traceLog(ErrorString*, const String&, const int*, const int*, RefPtr<TypeBuilder::Canvas::TraceLog>*);
+    void replayTraceLog(ErrorString*, const TypeBuilder::Canvas::TraceLogId&, int, RefPtr<TypeBuilder::Canvas::ResourceState>*);
+    void resourceInfo(ErrorString*, const TypeBuilder::Canvas::ResourceId&, RefPtr<TypeBuilder::Canvas::ResourceInfo>*);
+    void resourceState(ErrorString*, const TypeBuilder::Canvas::TraceLogId&, const TypeBuilder::Canvas::ResourceId&, RefPtr<TypeBuilder::Canvas::ResourceState>*);
+
+private:
+    ScriptObject callWrapContextFunction(const String&, const ScriptObject&);
+    void callStartCapturingFunction(const String&, ErrorString*, String*);
+    void callVoidFunctionWithTraceLogIdArgument(const String&, ErrorString*, const String&);
+};
+
+
+} // namespace WebCore
+
+#endif // !defined(InjectedScriptCanvasModule_h)
diff --git a/Source/core/inspector/InjectedScriptCanvasModuleSource.js b/Source/core/inspector/InjectedScriptCanvasModuleSource.js
new file mode 100644
index 0000000..115ad75
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptCanvasModuleSource.js
@@ -0,0 +1,3273 @@
+/*
+ * 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.
+ */
+
+/**
+ * @param {InjectedScriptHost} InjectedScriptHost
+ * @param {Window} inspectedWindow
+ * @param {number} injectedScriptId
+ */
+(function (InjectedScriptHost, inspectedWindow, injectedScriptId) {
+
+var TypeUtils = {
+    /**
+     * http://www.khronos.org/registry/typedarray/specs/latest/#7
+     * @const
+     * @type {!Array.<function(new:ArrayBufferView, ArrayBufferView)>}
+     */
+    _typedArrayClasses: (function(typeNames) {
+        var result = [];
+        for (var i = 0, n = typeNames.length; i < n; ++i) {
+            if (inspectedWindow[typeNames[i]])
+                result.push(inspectedWindow[typeNames[i]]);
+        }
+        return result;
+    })(["Int8Array", "Uint8Array", "Uint8ClampedArray", "Int16Array", "Uint16Array", "Int32Array", "Uint32Array", "Float32Array", "Float64Array"]),
+
+    /**
+     * @const
+     * @type {!Array.<string>}
+     */
+    _supportedPropertyPrefixes: ["webkit"],
+
+    /**
+     * @param {*} array
+     * @return {function(new:ArrayBufferView, ArrayBufferView)|null}
+     */
+    typedArrayClass: function(array)
+    {
+        var classes = TypeUtils._typedArrayClasses;
+        for (var i = 0, n = classes.length; i < n; ++i) {
+            if (array instanceof classes[i])
+                return classes[i];
+        }
+        return null;
+    },
+
+    /**
+     * @param {*} obj
+     * @return {*}
+     */
+    clone: function(obj)
+    {
+        if (!obj)
+            return obj;
+
+        var type = typeof obj;
+        if (type !== "object" && type !== "function")
+            return obj;
+
+        // Handle Array and ArrayBuffer instances.
+        if (typeof obj.slice === "function") {
+            console.assert(obj instanceof Array || obj instanceof ArrayBuffer);
+            return obj.slice(0);
+        }
+
+        var typedArrayClass = TypeUtils.typedArrayClass(obj);
+        if (typedArrayClass)
+            return new typedArrayClass(/** @type {ArrayBufferView} */ (obj));
+
+        if (obj instanceof HTMLImageElement) {
+            var img = /** @type {HTMLImageElement} */ (obj);
+            // Special case for Images with Blob URIs: cloneNode will fail if the Blob URI has already been revoked.
+            // FIXME: Maybe this is a bug in WebKit core?
+            if (/^blob:/.test(img.src))
+                return TypeUtils.cloneIntoCanvas(img);
+            return img.cloneNode(true);
+        }
+
+        if (obj instanceof HTMLCanvasElement)
+            return TypeUtils.cloneIntoCanvas(obj);
+
+        if (obj instanceof HTMLVideoElement)
+            return TypeUtils.cloneIntoCanvas(obj, obj.videoWidth, obj.videoHeight);
+
+        if (obj instanceof ImageData) {
+            var context = TypeUtils._dummyCanvas2dContext();
+            // FIXME: suppress type checks due to outdated builtin externs for createImageData.
+            var result = (/** @type {?} */ (context)).createImageData(obj);
+            for (var i = 0, n = obj.data.length; i < n; ++i)
+              result.data[i] = obj.data[i];
+            return result;
+        }
+
+        console.error("ASSERT_NOT_REACHED: failed to clone object: ", obj);
+        return obj;
+    },
+
+    /**
+     * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} obj
+     * @param {number=} width
+     * @param {number=} height
+     * @return {HTMLCanvasElement}
+     */
+    cloneIntoCanvas: function(obj, width, height)
+    {
+        var canvas = /** @type {HTMLCanvasElement} */ (inspectedWindow.document.createElement("canvas"));
+        canvas.width = width || +obj.width;
+        canvas.height = height || +obj.height;
+        var context = /** @type {CanvasRenderingContext2D} */ (Resource.wrappedObject(canvas.getContext("2d")));
+        context.drawImage(obj, 0, 0);
+        return canvas;
+    },
+
+    /**
+     * @param {Object=} obj
+     * @return {Object}
+     */
+    cloneObject: function(obj)
+    {
+        if (!obj)
+            return null;
+        var result = {};
+        for (var key in obj)
+            result[key] = obj[key];
+        return result;
+    },
+
+    /**
+     * @param {!Array.<string>} names
+     * @return {!Object.<string, boolean>}
+     */
+    createPrefixedPropertyNamesSet: function(names)
+    {
+        var result = Object.create(null);
+        for (var i = 0, name; name = names[i]; ++i) {
+            result[name] = true;
+            var suffix = name.substr(0, 1).toUpperCase() + name.substr(1);
+            for (var j = 0, prefix; prefix = TypeUtils._supportedPropertyPrefixes[j]; ++j)
+                result[prefix + suffix] = true;
+        }
+        return result;
+    },
+
+    /**
+     * @return {CanvasRenderingContext2D}
+     */
+    _dummyCanvas2dContext: function()
+    {
+        var context = TypeUtils._dummyCanvas2dContextInstance;
+        if (!context) {
+            var canvas = /** @type {HTMLCanvasElement} */ (inspectedWindow.document.createElement("canvas"));
+            context = /** @type {CanvasRenderingContext2D} */ (Resource.wrappedObject(canvas.getContext("2d")));
+            TypeUtils._dummyCanvas2dContextInstance = context;
+        }
+        return context;
+    }
+}
+
+/**
+ * @interface
+ */
+function StackTrace()
+{
+}
+
+StackTrace.prototype = {
+    /**
+     * @param {number} index
+     * @return {{sourceURL: string, lineNumber: number, columnNumber: number}|undefined}
+     */
+    callFrame: function(index)
+    {
+    }
+}
+
+/**
+ * @param {number=} stackTraceLimit
+ * @param {Function=} topMostFunctionToIgnore
+ * @return {StackTrace}
+ */
+StackTrace.create = function(stackTraceLimit, topMostFunctionToIgnore)
+{
+    if (typeof Error.captureStackTrace === "function")
+        return new StackTraceV8(stackTraceLimit, topMostFunctionToIgnore || arguments.callee);
+    // FIXME: Support JSC, and maybe other browsers.
+    return null;
+}
+
+/**
+ * @constructor
+ * @implements {StackTrace}
+ * @param {number=} stackTraceLimit
+ * @param {Function=} topMostFunctionToIgnore
+ * @see http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
+ */
+function StackTraceV8(stackTraceLimit, topMostFunctionToIgnore)
+{
+    StackTrace.call(this);
+
+    var oldPrepareStackTrace = Error.prepareStackTrace;
+    var oldStackTraceLimit = Error.stackTraceLimit;
+    if (typeof stackTraceLimit === "number")
+        Error.stackTraceLimit = stackTraceLimit;
+
+    /**
+     * @param {Object} error
+     * @param {Array.<CallSite>} structuredStackTrace
+     * @return {Array.<{sourceURL: string, lineNumber: number, columnNumber: number}>}
+     */
+    Error.prepareStackTrace = function(error, structuredStackTrace)
+    {
+        return structuredStackTrace.map(function(callSite) {
+            return {
+                sourceURL: callSite.getFileName(),
+                lineNumber: callSite.getLineNumber(),
+                columnNumber: callSite.getColumnNumber()
+            };
+        });
+    }
+
+    var holder = /** @type {{stack: Array.<{sourceURL: string, lineNumber: number, columnNumber: number}>}} */ ({});
+    Error.captureStackTrace(holder, topMostFunctionToIgnore || arguments.callee);
+    this._stackTrace = holder.stack;
+
+    Error.stackTraceLimit = oldStackTraceLimit;
+    Error.prepareStackTrace = oldPrepareStackTrace;
+}
+
+StackTraceV8.prototype = {
+    /**
+     * @override
+     * @param {number} index
+     * @return {{sourceURL: string, lineNumber: number, columnNumber: number}|undefined}
+     */
+    callFrame: function(index)
+    {
+        return this._stackTrace[index];
+    },
+
+    __proto__: StackTrace.prototype
+}
+
+/**
+ * @constructor
+ */
+function Cache()
+{
+    this.reset();
+}
+
+Cache.prototype = {
+    /**
+     * @return {number}
+     */
+    size: function()
+    {
+        return this._size;
+    },
+
+    reset: function()
+    {
+        /** @type {!Object.<number, Object>} */
+        this._items = Object.create(null);
+        /** @type {number} */
+        this._size = 0;
+    },
+
+    /**
+     * @param {number} key
+     * @return {boolean}
+     */
+    has: function(key)
+    {
+        return key in this._items;
+    },
+
+    /**
+     * @param {number} key
+     * @return {Object}
+     */
+    get: function(key)
+    {
+        return this._items[key];
+    },
+
+    /**
+     * @param {number} key
+     * @param {Object} item
+     */
+    put: function(key, item)
+    {
+        if (!this.has(key))
+            ++this._size;
+        this._items[key] = item;
+    }
+}
+
+/**
+ * @constructor
+ * @param {Resource|Object} thisObject
+ * @param {string} functionName
+ * @param {Array|Arguments} args
+ * @param {Resource|*=} result
+ * @param {StackTrace=} stackTrace
+ */
+function Call(thisObject, functionName, args, result, stackTrace)
+{
+    this._thisObject = thisObject;
+    this._functionName = functionName;
+    this._args = Array.prototype.slice.call(args, 0);
+    this._result = result;
+    this._stackTrace = stackTrace || null;
+
+    if (!this._functionName)
+        console.assert(this._args.length === 2 && typeof this._args[0] === "string");
+}
+
+Call.prototype = {
+    /**
+     * @return {Resource}
+     */
+    resource: function()
+    {
+        return Resource.forObject(this._thisObject);
+    },
+
+    /**
+     * @return {string}
+     */
+    functionName: function()
+    {
+        return this._functionName;
+    },
+
+    /**
+     * @return {boolean}
+     */
+    isPropertySetter: function()
+    {
+        return !this._functionName;
+    },
+    
+    /**
+     * @return {!Array}
+     */
+    args: function()
+    {
+        return this._args;
+    },
+
+    /**
+     * @return {*}
+     */
+    result: function()
+    {
+        return this._result;
+    },
+
+    /**
+     * @return {StackTrace}
+     */
+    stackTrace: function()
+    {
+        return this._stackTrace;
+    },
+
+    /**
+     * @param {StackTrace} stackTrace
+     */
+    setStackTrace: function(stackTrace)
+    {
+        this._stackTrace = stackTrace;
+    },
+
+    /**
+     * @param {*} result
+     */
+    setResult: function(result)
+    {
+        this._result = result;
+    },
+
+    /**
+     * @param {string} name
+     * @param {Object} attachment
+     */
+    setAttachment: function(name, attachment)
+    {
+        if (attachment) {
+            /** @type {Object.<string, Object>} */
+            this._attachments = this._attachments || Object.create(null);
+            this._attachments[name] = attachment;
+        } else if (this._attachments)
+            delete this._attachments[name];
+    },
+
+    /**
+     * @param {string} name
+     * @return {Object}
+     */
+    attachment: function(name)
+    {
+        return this._attachments && this._attachments[name];
+    },
+
+    freeze: function()
+    {
+        if (this._freezed)
+            return;
+        this._freezed = true;
+        for (var i = 0, n = this._args.length; i < n; ++i) {
+            // FIXME: freeze the Resources also!
+            if (!Resource.forObject(this._args[i]))
+                this._args[i] = TypeUtils.clone(this._args[i]);
+        }
+    },
+
+    /**
+     * @param {!Cache} cache
+     * @return {!ReplayableCall}
+     */
+    toReplayable: function(cache)
+    {
+        this.freeze();
+        var thisObject = /** @type {ReplayableResource} */ (Resource.toReplayable(this._thisObject, cache));
+        var result = Resource.toReplayable(this._result, cache);
+        var args = this._args.map(function(obj) {
+            return Resource.toReplayable(obj, cache);
+        });
+        var attachments = TypeUtils.cloneObject(this._attachments);
+        return new ReplayableCall(thisObject, this._functionName, args, result, this._stackTrace, attachments);
+    },
+
+    /**
+     * @param {!ReplayableCall} replayableCall
+     * @param {!Cache} cache
+     * @return {!Call}
+     */
+    replay: function(replayableCall, cache)
+    {
+        var replayObject = ReplayableResource.replay(replayableCall.replayableResource(), cache);
+        var replayArgs = replayableCall.args().map(function(obj) {
+            return ReplayableResource.replay(obj, cache);
+        });
+        var replayResult = undefined;
+
+        if (replayableCall.isPropertySetter())
+            replayObject[replayArgs[0]] = replayArgs[1];
+        else {
+            var replayFunction = replayObject[replayableCall.functionName()];
+            console.assert(typeof replayFunction === "function", "Expected a function to replay");
+            replayResult = replayFunction.apply(replayObject, replayArgs);
+            if (replayableCall.result() instanceof ReplayableResource) {
+                var resource = replayableCall.result().replay(cache);
+                if (!resource.wrappedObject())
+                    resource.setWrappedObject(replayResult);
+            }
+        }
+    
+        this._thisObject = replayObject;
+        this._functionName = replayableCall.functionName();
+        this._args = replayArgs;
+        this._result = replayResult;
+        this._stackTrace = replayableCall.stackTrace();
+        this._freezed = true;
+        var attachments = replayableCall.attachments();
+        if (attachments)
+            this._attachments = TypeUtils.cloneObject(attachments);
+        return this;
+    }
+}
+
+/**
+ * @constructor
+ * @param {ReplayableResource} thisObject
+ * @param {string} functionName
+ * @param {Array.<ReplayableResource|*>} args
+ * @param {ReplayableResource|*} result
+ * @param {StackTrace} stackTrace
+ * @param {Object.<string, Object>} attachments
+ */
+function ReplayableCall(thisObject, functionName, args, result, stackTrace, attachments)
+{
+    this._thisObject = thisObject;
+    this._functionName = functionName;
+    this._args = args;
+    this._result = result;
+    this._stackTrace = stackTrace;
+    if (attachments)
+        this._attachments = attachments;
+}
+
+ReplayableCall.prototype = {
+    /**
+     * @return {ReplayableResource}
+     */
+    replayableResource: function()
+    {
+        return this._thisObject;
+    },
+
+    /**
+     * @return {string}
+     */
+    functionName: function()
+    {
+        return this._functionName;
+    },
+
+    /**
+     * @return {boolean}
+     */
+    isPropertySetter: function()
+    {
+        return !this._functionName;
+    },
+
+    /**
+     * @return {Array.<ReplayableResource|*>}
+     */
+    args: function()
+    {
+        return this._args;
+    },
+
+    /**
+     * @return {ReplayableResource|*}
+     */
+    result: function()
+    {
+        return this._result;
+    },
+
+    /**
+     * @return {StackTrace}
+     */
+    stackTrace: function()
+    {
+        return this._stackTrace;
+    },
+
+    /**
+     * @return {Object.<string, Object>}
+     */
+    attachments: function()
+    {
+        return this._attachments;
+    },
+
+    /**
+     * @param {string} name
+     * @return {Object}
+     */
+    attachment: function(name)
+    {
+        return this._attachments && this._attachments[name];
+    },
+
+    /**
+     * @param {Cache} cache
+     * @return {!Call}
+     */
+    replay: function(cache)
+    {
+        var call = /** @type {!Call} */ (Object.create(Call.prototype));
+        return call.replay(this, cache);
+    }
+}
+
+/**
+ * @constructor
+ * @param {!Object} wrappedObject
+ * @param {string} name
+ */
+function Resource(wrappedObject, name)
+{
+    /** @type {number} */
+    this._id = ++Resource._uniqueId;
+    /** @type {string} */
+    this._name = name || "Resource";
+    /** @type {number} */
+    this._kindId = Resource._uniqueKindIds[this._name] = (Resource._uniqueKindIds[this._name] || 0) + 1;
+    /** @type {ResourceTrackingManager} */
+    this._resourceManager = null;
+    /** @type {!Array.<Call>} */
+    this._calls = [];
+    /**
+     * This is to prevent GC from collecting associated resources.
+     * Otherwise, for example in WebGL, subsequent calls to gl.getParameter()
+     * may return a recently created instance that is no longer bound to a
+     * Resource object (thus, no history to replay it later).
+     *
+     * @type {!Object.<string, Resource>}
+     */
+    this._boundResources = Object.create(null);
+    this.setWrappedObject(wrappedObject);
+}
+
+/**
+ * @type {number}
+ */
+Resource._uniqueId = 0;
+
+/**
+ * @type {!Object.<string, number>}
+ */
+Resource._uniqueKindIds = {};
+
+/**
+ * @param {*} obj
+ * @return {Resource}
+ */
+Resource.forObject = function(obj)
+{
+    if (!obj)
+        return null;
+    if (obj instanceof Resource)
+        return obj;
+    if (typeof obj === "object")
+        return obj["__resourceObject"];
+    return null;
+}
+
+/**
+ * @param {Resource|*} obj
+ * @return {*}
+ */
+Resource.wrappedObject = function(obj)
+{
+    var resource = Resource.forObject(obj);
+    return resource ? resource.wrappedObject() : obj;
+}
+
+/**
+ * @param {Resource|*} obj
+ * @param {!Cache} cache
+ * @return {ReplayableResource|*}
+ */
+Resource.toReplayable = function(obj, cache)
+{
+    var resource = Resource.forObject(obj);
+    return resource ? resource.toReplayable(cache) : obj;
+}
+
+Resource.prototype = {
+    /**
+     * @return {number}
+     */
+    id: function()
+    {
+        return this._id;
+    },
+
+    /**
+     * @return {Object}
+     */
+    wrappedObject: function()
+    {
+        return this._wrappedObject;
+    },
+
+    /**
+     * @param {!Object} value
+     */
+    setWrappedObject: function(value)
+    {
+        console.assert(value, "wrappedObject should not be NULL");
+        console.assert(!(value instanceof Resource), "Binding a Resource object to another Resource object?");
+        this._wrappedObject = value;
+        this._bindObjectToResource(value);
+    },
+
+    /**
+     * @return {Object}
+     */
+    proxyObject: function()
+    {
+        if (!this._proxyObject)
+            this._proxyObject = this._wrapObject();
+        return this._proxyObject;
+    },
+
+    /**
+     * @return {ResourceTrackingManager}
+     */
+    manager: function()
+    {
+        return this._resourceManager;
+    },
+
+    /**
+     * @param {ResourceTrackingManager} value
+     */
+    setManager: function(value)
+    {
+        this._resourceManager = value;
+    },
+
+    /**
+     * @return {!Array.<Call>}
+     */
+    calls: function()
+    {
+        return this._calls;
+    },
+
+    /**
+     * @return {ContextResource}
+     */
+    contextResource: function()
+    {
+        if (this instanceof ContextResource)
+            return /** @type {ContextResource} */ (this);
+
+        if (this._calculatingContextResource)
+            return null;
+
+        this._calculatingContextResource = true;
+        var result = null;
+        for (var i = 0, n = this._calls.length; i < n; ++i) {
+            result = this._calls[i].resource().contextResource();
+            if (result)
+                break;
+        }
+        delete this._calculatingContextResource;
+        console.assert(result, "Failed to find context resource for " + this._name + "@" + this._kindId);
+        return result;
+    },
+
+    /**
+     * @return {string}
+     */
+    toDataURL: function()
+    {
+        return "";
+    },
+
+    /**
+     * @param {!Cache} cache
+     * @return {!ReplayableResource}
+     */
+    toReplayable: function(cache)
+    {
+        var result = /** @type {ReplayableResource} */ (cache.get(this._id));
+        if (result)
+            return result;
+        var data = {
+            id: this._id,
+            name: this._name,
+            kindId: this._kindId
+        };
+        result = new ReplayableResource(this, data);
+        cache.put(this._id, result); // Put into the cache early to avoid loops.
+        data.calls = this._calls.map(function(call) {
+            return call.toReplayable(cache);
+        });
+        this._populateReplayableData(data, cache);
+        var contextResource = this.contextResource();
+        if (contextResource !== this)
+            data.contextResource = Resource.toReplayable(contextResource, cache);
+        return result;
+    },
+
+    /**
+     * @param {!Object} data
+     * @param {!Cache} cache
+     */
+    _populateReplayableData: function(data, cache)
+    {
+        // Do nothing. Should be overridden by subclasses.
+    },
+
+    /**
+     * @param {!Object} data
+     * @param {!Cache} cache
+     * @return {!Resource}
+     */
+    replay: function(data, cache)
+    {
+        var resource = /** @type {Resource} */ (cache.get(data.id));
+        if (resource)
+            return resource;
+        this._id = data.id;
+        this._name = data.name;
+        this._kindId = data.kindId;
+        this._resourceManager = null;
+        this._calls = [];
+        this._boundResources = Object.create(null);
+        this._wrappedObject = null;
+        cache.put(data.id, this); // Put into the cache early to avoid loops.
+        this._doReplayCalls(data, cache);
+        console.assert(this._wrappedObject, "Resource should be reconstructed!");
+        return this;
+    },
+
+    /**
+     * @param {!Object} data
+     * @param {!Cache} cache
+     */
+    _doReplayCalls: function(data, cache)
+    {
+        for (var i = 0, n = data.calls.length; i < n; ++i)
+            this._calls.push(data.calls[i].replay(cache));
+    },
+
+    /**
+     * @param {!Call} call
+     */
+    pushCall: function(call)
+    {
+        call.freeze();
+        this._calls.push(call);
+    },
+
+    /**
+     * @param {!Object} object
+     */
+    _bindObjectToResource: function(object)
+    {
+        Object.defineProperty(object, "__resourceObject", {
+            value: this,
+            writable: false,
+            enumerable: false,
+            configurable: true
+        });
+    },
+
+    /**
+     * @param {string} key
+     * @param {*} obj
+     */
+    _registerBoundResource: function(key, obj)
+    {
+        var resource = Resource.forObject(obj);
+        if (resource)
+            this._boundResources[key] = resource;
+        else
+            delete this._boundResources[key];
+    },
+
+    /**
+     * @return {Object}
+     */
+    _wrapObject: function()
+    {
+        var wrappedObject = this.wrappedObject();
+        if (!wrappedObject)
+            return null;
+        var proxy = Object.create(wrappedObject.__proto__); // In order to emulate "instanceof".
+
+        var self = this;
+        var customWrapFunctions = this._customWrapFunctions();
+        function processProperty(property)
+        {
+            if (typeof wrappedObject[property] === "function") {
+                var customWrapFunction = customWrapFunctions[property];
+                if (customWrapFunction)
+                    proxy[property] = self._wrapCustomFunction(self, wrappedObject, wrappedObject[property], property, customWrapFunction);
+                else
+                    proxy[property] = self._wrapFunction(self, wrappedObject, wrappedObject[property], property);
+            } else if (/^[A-Z0-9_]+$/.test(property) && typeof wrappedObject[property] === "number") {
+                // Fast access to enums and constants.
+                proxy[property] = wrappedObject[property];
+            } else {
+                Object.defineProperty(proxy, property, {
+                    get: function()
+                    {
+                        var obj = wrappedObject[property];
+                        var resource = Resource.forObject(obj);
+                        return resource ? resource : obj;
+                    },
+                    set: self._wrapPropertySetter(self, wrappedObject, property),
+                    enumerable: true
+                });
+            }
+        }
+
+        var isEmpty = true;
+        for (var property in wrappedObject) {
+            isEmpty = false;
+            processProperty(property);
+        }
+        if (isEmpty)
+            return wrappedObject; // Nothing to proxy.
+
+        this._bindObjectToResource(proxy);
+        return proxy;
+    },
+
+    /**
+     * @param {!Resource} resource
+     * @param {!Object} originalObject
+     * @param {!Function} originalFunction
+     * @param {string} functionName
+     * @param {!Function} customWrapFunction
+     * @return {!Function}
+     */
+    _wrapCustomFunction: function(resource, originalObject, originalFunction, functionName, customWrapFunction)
+    {
+        return function()
+        {
+            var manager = resource.manager();
+            var isCapturing = manager && manager.capturing();
+            if (isCapturing)
+                manager.captureArguments(resource, arguments);
+            var wrapFunction = new Resource.WrapFunction(originalObject, originalFunction, functionName, arguments);
+            customWrapFunction.apply(wrapFunction, arguments);
+            if (isCapturing) {
+                var call = wrapFunction.call();
+                call.setStackTrace(StackTrace.create(1, arguments.callee));
+                manager.captureCall(call);
+            }
+            return wrapFunction.result();
+        };
+    },
+
+    /**
+     * @param {!Resource} resource
+     * @param {!Object} originalObject
+     * @param {!Function} originalFunction
+     * @param {string} functionName
+     * @return {!Function}
+     */
+    _wrapFunction: function(resource, originalObject, originalFunction, functionName)
+    {
+        return function()
+        {
+            var manager = resource.manager();
+            if (!manager || !manager.capturing())
+                return originalFunction.apply(originalObject, arguments);
+            manager.captureArguments(resource, arguments);
+            var result = originalFunction.apply(originalObject, arguments);
+            var stackTrace = StackTrace.create(1, arguments.callee);
+            var call = new Call(resource, functionName, arguments, result, stackTrace);
+            manager.captureCall(call);
+            return result;
+        };
+    },
+
+    /**
+     * @param {!Resource} resource
+     * @param {!Object} originalObject
+     * @param {string} propertyName
+     * @return {function(*)}
+     */
+    _wrapPropertySetter: function(resource, originalObject, propertyName)
+    {
+        return function(value)
+        {
+            resource._registerBoundResource(propertyName, value);
+            var manager = resource.manager();
+            if (!manager || !manager.capturing()) {
+                originalObject[propertyName] = Resource.wrappedObject(value);
+                return;
+            }
+            var args = [propertyName, value];
+            manager.captureArguments(resource, args);
+            originalObject[propertyName] = Resource.wrappedObject(value);
+            var stackTrace = StackTrace.create(1, arguments.callee);
+            var call = new Call(resource, "", args, undefined, stackTrace);
+            manager.captureCall(call);
+        };
+    },
+
+    /**
+     * @return {!Object.<string, Function>}
+     */
+    _customWrapFunctions: function()
+    {
+        return Object.create(null); // May be overridden by subclasses.
+    }
+}
+
+/**
+ * @constructor
+ * @param {Object} originalObject
+ * @param {Function} originalFunction
+ * @param {string} functionName
+ * @param {Array|Arguments} args
+ */
+Resource.WrapFunction = function(originalObject, originalFunction, functionName, args)
+{
+    this._originalObject = originalObject;
+    this._originalFunction = originalFunction;
+    this._functionName = functionName;
+    this._args = args;
+    this._resource = Resource.forObject(originalObject);
+    console.assert(this._resource, "Expected a wrapped call on a Resource object.");
+}
+
+Resource.WrapFunction.prototype = {
+    /**
+     * @return {*}
+     */
+    result: function()
+    {
+        if (!this._executed) {
+            this._executed = true;
+            this._result = this._originalFunction.apply(this._originalObject, this._args);
+        }
+        return this._result;
+    },
+
+    /**
+     * @return {!Call}
+     */
+    call: function()
+    {
+        if (!this._call)
+            this._call = new Call(this._resource, this._functionName, this._args, this.result());
+        return this._call;
+    },
+
+    /**
+     * @param {*} result
+     */
+    overrideResult: function(result)
+    {
+        var call = this.call();
+        call.setResult(result);
+        this._result = result;
+    }
+}
+
+/**
+ * @param {function(new:Resource, !Object, string)} resourceConstructor
+ * @param {string} resourceName
+ * @return {function(this:Resource.WrapFunction)}
+ */
+Resource.WrapFunction.resourceFactoryMethod = function(resourceConstructor, resourceName)
+{
+    /** @this Resource.WrapFunction */
+    return function()
+    {
+        var wrappedObject = /** @type {Object} */ (this.result());
+        if (!wrappedObject)
+            return;
+        var resource = new resourceConstructor(wrappedObject, resourceName);
+        var manager = this._resource.manager();
+        if (manager)
+            manager.registerResource(resource);
+        this.overrideResult(resource.proxyObject());
+        resource.pushCall(this.call());
+    }
+}
+
+/**
+ * @constructor
+ * @param {!Resource} originalResource
+ * @param {!Object} data
+ */
+function ReplayableResource(originalResource, data)
+{
+    this._proto = originalResource.__proto__;
+    this._data = data;
+}
+
+ReplayableResource.prototype = {
+    /**
+     * @return {number}
+     */
+    id: function()
+    {
+        return this._data.id;
+    },
+
+    /**
+     * @return {string}
+     */
+    name: function()
+    {
+        return this._data.name;
+    },
+
+    /**
+     * @return {string}
+     */
+    description: function()
+    {
+        return this._data.name + "@" + this._data.kindId;
+    },
+
+    /**
+     * @return {!ReplayableResource}
+     */
+    replayableContextResource: function()
+    {
+        return this._data.contextResource || this;
+    },
+
+    /**
+     * @param {!Cache} cache
+     * @return {!Resource}
+     */
+    replay: function(cache)
+    {
+        var result = /** @type {!Resource} */ (Object.create(this._proto));
+        result = result.replay(this._data, cache)
+        console.assert(result.__proto__ === this._proto, "Wrong type of a replay result");
+        return result;
+    }
+}
+
+/**
+ * @param {ReplayableResource|*} obj
+ * @param {!Cache} cache
+ * @return {*}
+ */
+ReplayableResource.replay = function(obj, cache)
+{
+    return (obj instanceof ReplayableResource) ? obj.replay(cache).wrappedObject() : obj;
+}
+
+/**
+ * @constructor
+ * @extends {Resource}
+ * @param {!Object} wrappedObject
+ * @param {string} name
+ */
+function ContextResource(wrappedObject, name)
+{
+    Resource.call(this, wrappedObject, name);
+}
+
+ContextResource.prototype = {
+    __proto__: Resource.prototype
+}
+
+/**
+ * @constructor
+ * @extends {Resource}
+ * @param {!Object} wrappedObject
+ * @param {string} name
+ */
+function LogEverythingResource(wrappedObject, name)
+{
+    Resource.call(this, wrappedObject, name);
+}
+
+LogEverythingResource.prototype = {
+    /**
+     * @override
+     * @return {!Object.<string, Function>}
+     */
+    _customWrapFunctions: function()
+    {
+        var wrapFunctions = Object.create(null);
+        var wrappedObject = this.wrappedObject();
+        if (wrappedObject) {
+            for (var property in wrappedObject) {
+                /** @this Resource.WrapFunction */
+                wrapFunctions[property] = function()
+                {
+                    this._resource.pushCall(this.call());
+                }
+            }
+        }
+        return wrapFunctions;
+    },
+
+    __proto__: Resource.prototype
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WebGL
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * @constructor
+ * @extends {Resource}
+ * @param {!Object} wrappedObject
+ * @param {string} name
+ */
+function WebGLBoundResource(wrappedObject, name)
+{
+    Resource.call(this, wrappedObject, name);
+    /** @type {!Object.<string, *>} */
+    this._state = {};
+}
+
+WebGLBoundResource.prototype = {
+    /**
+     * @override
+     * @param {!Object} data
+     * @param {!Cache} cache
+     */
+    _populateReplayableData: function(data, cache)
+    {
+        var state = this._state;
+        data.state = {};
+        Object.keys(state).forEach(function(parameter) {
+            data.state[parameter] = Resource.toReplayable(state[parameter], cache);
+        });
+    },
+
+    /**
+     * @override
+     * @param {!Object} data
+     * @param {!Cache} cache
+     */
+    _doReplayCalls: function(data, cache)
+    {
+        var gl = this._replayContextResource(data, cache).wrappedObject();
+
+        /** @type {!Object.<string, Array.<string>>} */
+        var bindingsData = {
+            TEXTURE_2D: ["bindTexture", "TEXTURE_BINDING_2D"],
+            TEXTURE_CUBE_MAP: ["bindTexture", "TEXTURE_BINDING_CUBE_MAP"],
+            ARRAY_BUFFER: ["bindBuffer", "ARRAY_BUFFER_BINDING"],
+            ELEMENT_ARRAY_BUFFER: ["bindBuffer", "ELEMENT_ARRAY_BUFFER_BINDING"],
+            FRAMEBUFFER: ["bindFramebuffer", "FRAMEBUFFER_BINDING"],
+            RENDERBUFFER: ["bindRenderbuffer", "RENDERBUFFER_BINDING"]
+        };
+        var originalBindings = {};
+        Object.keys(bindingsData).forEach(function(bindingTarget) {
+            var bindingParameter = bindingsData[bindingTarget][1];
+            originalBindings[bindingTarget] = gl.getParameter(gl[bindingParameter]);
+        });
+
+        var state = {};
+        Object.keys(data.state).forEach(function(parameter) {
+            state[parameter] = ReplayableResource.replay(data.state[parameter], cache);
+        });
+        this._state = state;
+        Resource.prototype._doReplayCalls.call(this, data, cache);
+
+        Object.keys(bindingsData).forEach(function(bindingTarget) {
+            var bindMethodName = bindingsData[bindingTarget][0];
+            gl[bindMethodName].call(gl, gl[bindingTarget], originalBindings[bindingTarget]);
+        });
+    },
+
+    /**
+     * @param {!Object} data
+     * @param {!Cache} cache
+     * @return {WebGLRenderingContextResource}
+     */
+    _replayContextResource: function(data, cache)
+    {
+        var calls = /** @type {!Array.<ReplayableCall>} */ (data.calls);
+        for (var i = 0, n = calls.length; i < n; ++i) {
+            var resource = ReplayableResource.replay(calls[i].replayableResource(), cache);
+            var contextResource = WebGLRenderingContextResource.forObject(resource);
+            if (contextResource)
+                return contextResource;
+        }
+        return null;
+    },
+
+    /**
+     * @param {number} target
+     * @param {string} bindMethodName
+     */
+    pushBinding: function(target, bindMethodName)
+    {
+        if (this._state.BINDING !== target) {
+            this._state.BINDING = target;
+            this.pushCall(new Call(WebGLRenderingContextResource.forObject(this), bindMethodName, [target, this]));
+        }
+    },
+
+    __proto__: Resource.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebGLBoundResource}
+ * @param {!Object} wrappedObject
+ * @param {string} name
+ */
+function WebGLTextureResource(wrappedObject, name)
+{
+    WebGLBoundResource.call(this, wrappedObject, name);
+}
+
+WebGLTextureResource.prototype = {
+    /**
+     * @override
+     * @param {!Object} data
+     * @param {!Cache} cache
+     */
+    _doReplayCalls: function(data, cache)
+    {
+        var gl = this._replayContextResource(data, cache).wrappedObject();
+
+        var state = {};
+        WebGLRenderingContextResource.PixelStoreParameters.forEach(function(parameter) {
+            state[parameter] = gl.getParameter(gl[parameter]);
+        });
+
+        WebGLBoundResource.prototype._doReplayCalls.call(this, data, cache);
+
+        WebGLRenderingContextResource.PixelStoreParameters.forEach(function(parameter) {
+            gl.pixelStorei(gl[parameter], state[parameter]);
+        });
+    },
+
+    /**
+     * @override
+     * @param {!Call} call
+     */
+    pushCall: function(call)
+    {
+        var gl = WebGLRenderingContextResource.forObject(call.resource()).wrappedObject();
+        WebGLRenderingContextResource.PixelStoreParameters.forEach(function(parameter) {
+            var value = gl.getParameter(gl[parameter]);
+            if (this._state[parameter] !== value) {
+                this._state[parameter] = value;
+                var pixelStoreCall = new Call(gl, "pixelStorei", [gl[parameter], value]);
+                WebGLBoundResource.prototype.pushCall.call(this, pixelStoreCall);
+            }
+        }, this);
+
+        // FIXME: remove any older calls that no longer contribute to the resource state.
+        // FIXME: optimize memory usage: maybe it's more efficient to store one texImage2D call instead of many texSubImage2D.
+        WebGLBoundResource.prototype.pushCall.call(this, call);
+    },
+
+    /**
+     * Handles: texParameteri, texParameterf
+     * @param {!Call} call
+     */
+    pushCall_texParameter: function(call)
+    {
+        var args = call.args();
+        var pname = args[1];
+        var param = args[2];
+        if (this._state[pname] !== param) {
+            this._state[pname] = param;
+            WebGLBoundResource.prototype.pushCall.call(this, call);
+        }
+    },
+
+    /**
+     * Handles: copyTexImage2D, copyTexSubImage2D
+     * copyTexImage2D and copyTexSubImage2D define a texture image with pixels from the current framebuffer.
+     * @param {!Call} call
+     */
+    pushCall_copyTexImage2D: function(call)
+    {
+        var glResource = WebGLRenderingContextResource.forObject(call.resource());
+        var gl = glResource.wrappedObject();
+        var framebufferResource = /** @type {WebGLFramebufferResource} */ (glResource.currentBinding(gl.FRAMEBUFFER));
+        if (framebufferResource)
+            this.pushCall(new Call(glResource, "bindFramebuffer", [gl.FRAMEBUFFER, framebufferResource]));
+        else {
+            // FIXME: Implement this case.
+            console.error("ASSERT_NOT_REACHED: Could not properly process a gl." + call.functionName() + " call while the DRAWING BUFFER is bound.");
+        }
+        this.pushCall(call);
+    },
+
+    __proto__: WebGLBoundResource.prototype
+}
+
+/**
+ * @constructor
+ * @extends {Resource}
+ * @param {!Object} wrappedObject
+ * @param {string} name
+ */
+function WebGLProgramResource(wrappedObject, name)
+{
+    Resource.call(this, wrappedObject, name);
+}
+
+WebGLProgramResource.prototype = {
+    /**
+     * @override (overrides @return type)
+     * @return {WebGLProgram}
+     */
+    wrappedObject: function()
+    {
+        return this._wrappedObject;
+    },
+
+    /**
+     * @override
+     * @param {!Object} data
+     * @param {!Cache} cache
+     */
+    _populateReplayableData: function(data, cache)
+    {
+        var glResource = WebGLRenderingContextResource.forObject(this);
+        var gl = glResource.wrappedObject();
+        var program = this.wrappedObject();
+
+        var originalErrors = glResource.getAllErrors();
+
+        var uniforms = [];
+        var uniformsCount = /** @type {number} */ (gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS));
+        for (var i = 0; i < uniformsCount; ++i) {
+            var activeInfo = gl.getActiveUniform(program, i);
+            if (!activeInfo)
+                continue;
+            var uniformLocation = gl.getUniformLocation(program, activeInfo.name);
+            if (!uniformLocation)
+                continue;
+            var value = gl.getUniform(program, uniformLocation);
+            uniforms.push({
+                name: activeInfo.name,
+                type: activeInfo.type,
+                value: value
+            });
+        }
+        data.uniforms = uniforms;
+
+        glResource.restoreErrors(originalErrors);
+    },
+
+    /**
+     * @override
+     * @param {!Object} data
+     * @param {!Cache} cache
+     */
+    _doReplayCalls: function(data, cache)
+    {
+        Resource.prototype._doReplayCalls.call(this, data, cache);
+        var gl = WebGLRenderingContextResource.forObject(this).wrappedObject();
+        var program = this.wrappedObject();
+
+        var originalProgram = /** @type {WebGLProgram} */ (gl.getParameter(gl.CURRENT_PROGRAM));
+        var currentProgram = originalProgram;
+        
+        data.uniforms.forEach(function(uniform) {
+            var uniformLocation = gl.getUniformLocation(program, uniform.name);
+            if (!uniformLocation)
+                return;
+            if (currentProgram !== program) {
+                currentProgram = program;
+                gl.useProgram(program);
+            }
+            var methodName = this._uniformMethodNameByType(gl, uniform.type);
+            if (methodName.indexOf("Matrix") === -1)
+                gl[methodName].call(gl, uniformLocation, uniform.value);
+            else
+                gl[methodName].call(gl, uniformLocation, false, uniform.value);
+        }.bind(this));
+
+        if (currentProgram !== originalProgram)
+            gl.useProgram(originalProgram);
+    },
+
+    /**
+     * @param {WebGLRenderingContext} gl
+     * @param {number} type
+     * @return {string}
+     */
+    _uniformMethodNameByType: function(gl, type)
+    {
+        var uniformMethodNames = WebGLProgramResource._uniformMethodNames;
+        if (!uniformMethodNames) {
+            uniformMethodNames = {};
+            uniformMethodNames[gl.FLOAT] = "uniform1f";
+            uniformMethodNames[gl.FLOAT_VEC2] = "uniform2fv";
+            uniformMethodNames[gl.FLOAT_VEC3] = "uniform3fv";
+            uniformMethodNames[gl.FLOAT_VEC4] = "uniform4fv";
+            uniformMethodNames[gl.INT] = "uniform1i";
+            uniformMethodNames[gl.BOOL] = "uniform1i";
+            uniformMethodNames[gl.SAMPLER_2D] = "uniform1i";
+            uniformMethodNames[gl.SAMPLER_CUBE] = "uniform1i";
+            uniformMethodNames[gl.INT_VEC2] = "uniform2iv";
+            uniformMethodNames[gl.BOOL_VEC2] = "uniform2iv";
+            uniformMethodNames[gl.INT_VEC3] = "uniform3iv";
+            uniformMethodNames[gl.BOOL_VEC3] = "uniform3iv";
+            uniformMethodNames[gl.INT_VEC4] = "uniform4iv";
+            uniformMethodNames[gl.BOOL_VEC4] = "uniform4iv";
+            uniformMethodNames[gl.FLOAT_MAT2] = "uniformMatrix2fv";
+            uniformMethodNames[gl.FLOAT_MAT3] = "uniformMatrix3fv";
+            uniformMethodNames[gl.FLOAT_MAT4] = "uniformMatrix4fv";
+            WebGLProgramResource._uniformMethodNames = uniformMethodNames;
+        }
+        console.assert(uniformMethodNames[type], "Unknown uniform type " + type);
+        return uniformMethodNames[type];
+    },
+
+    /**
+     * @override
+     * @param {!Call} call
+     */
+    pushCall: function(call)
+    {
+        // FIXME: remove any older calls that no longer contribute to the resource state.
+        // FIXME: handle multiple attachShader && detachShader.
+        Resource.prototype.pushCall.call(this, call);
+    },
+
+    __proto__: Resource.prototype
+}
+
+/**
+ * @constructor
+ * @extends {Resource}
+ * @param {!Object} wrappedObject
+ * @param {string} name
+ */
+function WebGLShaderResource(wrappedObject, name)
+{
+    Resource.call(this, wrappedObject, name);
+}
+
+WebGLShaderResource.prototype = {
+    /**
+     * @return {number}
+     */
+    type: function()
+    {
+        var call = this._calls[0];
+        if (call && call.functionName() === "createShader")
+            return call.args()[0];
+        console.error("ASSERT_NOT_REACHED: Failed to restore shader type from the log.", call);
+        return 0;
+    },
+
+    /**
+     * @override
+     * @param {!Call} call
+     */
+    pushCall: function(call)
+    {
+        // FIXME: remove any older calls that no longer contribute to the resource state.
+        // FIXME: handle multiple shaderSource calls.
+        Resource.prototype.pushCall.call(this, call);
+    },
+
+    __proto__: Resource.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebGLBoundResource}
+ * @param {!Object} wrappedObject
+ * @param {string} name
+ */
+function WebGLBufferResource(wrappedObject, name)
+{
+    WebGLBoundResource.call(this, wrappedObject, name);
+}
+
+WebGLBufferResource.prototype = {
+    /**
+     * @override
+     * @param {!Call} call
+     */
+    pushCall: function(call)
+    {
+        // FIXME: remove any older calls that no longer contribute to the resource state.
+        // FIXME: Optimize memory for bufferSubData.
+        WebGLBoundResource.prototype.pushCall.call(this, call);
+    },
+
+    __proto__: WebGLBoundResource.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebGLBoundResource}
+ * @param {!Object} wrappedObject
+ * @param {string} name
+ */
+function WebGLFramebufferResource(wrappedObject, name)
+{
+    WebGLBoundResource.call(this, wrappedObject, name);
+}
+
+WebGLFramebufferResource.prototype = {
+    /**
+     * @override
+     * @param {!Call} call
+     */
+    pushCall: function(call)
+    {
+        // FIXME: remove any older calls that no longer contribute to the resource state.
+        WebGLBoundResource.prototype.pushCall.call(this, call);
+    },
+
+    __proto__: WebGLBoundResource.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebGLBoundResource}
+ * @param {!Object} wrappedObject
+ * @param {string} name
+ */
+function WebGLRenderbufferResource(wrappedObject, name)
+{
+    WebGLBoundResource.call(this, wrappedObject, name);
+}
+
+WebGLRenderbufferResource.prototype = {
+    /**
+     * @override
+     * @param {!Call} call
+     */
+    pushCall: function(call)
+    {
+        // FIXME: remove any older calls that no longer contribute to the resource state.
+        WebGLBoundResource.prototype.pushCall.call(this, call);
+    },
+
+    __proto__: WebGLBoundResource.prototype
+}
+
+/**
+ * @constructor
+ * @extends {ContextResource}
+ * @param {!WebGLRenderingContext} glContext
+ */
+function WebGLRenderingContextResource(glContext)
+{
+    ContextResource.call(this, glContext, "WebGLRenderingContext");
+    /** @type {Object.<number, boolean>} */
+    this._customErrors = null;
+    /** @type {!Object.<string, boolean>} */
+    this._extensions = {};
+}
+
+/**
+ * @const
+ * @type {!Array.<string>}
+ */
+WebGLRenderingContextResource.GLCapabilities = [
+    "BLEND",
+    "CULL_FACE",
+    "DEPTH_TEST",
+    "DITHER",
+    "POLYGON_OFFSET_FILL",
+    "SAMPLE_ALPHA_TO_COVERAGE",
+    "SAMPLE_COVERAGE",
+    "SCISSOR_TEST",
+    "STENCIL_TEST"
+];
+
+/**
+ * @const
+ * @type {!Array.<string>}
+ */
+WebGLRenderingContextResource.PixelStoreParameters = [
+    "PACK_ALIGNMENT",
+    "UNPACK_ALIGNMENT",
+    "UNPACK_COLORSPACE_CONVERSION_WEBGL",
+    "UNPACK_FLIP_Y_WEBGL",
+    "UNPACK_PREMULTIPLY_ALPHA_WEBGL"
+];
+
+/**
+ * @const
+ * @type {!Array.<string>}
+ */
+WebGLRenderingContextResource.StateParameters = [
+    "ACTIVE_TEXTURE",
+    "ARRAY_BUFFER_BINDING",
+    "BLEND_COLOR",
+    "BLEND_DST_ALPHA",
+    "BLEND_DST_RGB",
+    "BLEND_EQUATION_ALPHA",
+    "BLEND_EQUATION_RGB",
+    "BLEND_SRC_ALPHA",
+    "BLEND_SRC_RGB",
+    "COLOR_CLEAR_VALUE",
+    "COLOR_WRITEMASK",
+    "CULL_FACE_MODE",
+    "CURRENT_PROGRAM",
+    "DEPTH_CLEAR_VALUE",
+    "DEPTH_FUNC",
+    "DEPTH_RANGE",
+    "DEPTH_WRITEMASK",
+    "ELEMENT_ARRAY_BUFFER_BINDING",
+    "FRAMEBUFFER_BINDING",
+    "FRONT_FACE",
+    "GENERATE_MIPMAP_HINT",
+    "LINE_WIDTH",
+    "PACK_ALIGNMENT",
+    "POLYGON_OFFSET_FACTOR",
+    "POLYGON_OFFSET_UNITS",
+    "RENDERBUFFER_BINDING",
+    "SAMPLE_COVERAGE_INVERT",
+    "SAMPLE_COVERAGE_VALUE",
+    "SCISSOR_BOX",
+    "STENCIL_BACK_FAIL",
+    "STENCIL_BACK_FUNC",
+    "STENCIL_BACK_PASS_DEPTH_FAIL",
+    "STENCIL_BACK_PASS_DEPTH_PASS",
+    "STENCIL_BACK_REF",
+    "STENCIL_BACK_VALUE_MASK",
+    "STENCIL_BACK_WRITEMASK",
+    "STENCIL_CLEAR_VALUE",
+    "STENCIL_FAIL",
+    "STENCIL_FUNC",
+    "STENCIL_PASS_DEPTH_FAIL",
+    "STENCIL_PASS_DEPTH_PASS",
+    "STENCIL_REF",
+    "STENCIL_VALUE_MASK",
+    "STENCIL_WRITEMASK",
+    "UNPACK_ALIGNMENT",
+    "UNPACK_COLORSPACE_CONVERSION_WEBGL",
+    "UNPACK_FLIP_Y_WEBGL",
+    "UNPACK_PREMULTIPLY_ALPHA_WEBGL",
+    "VIEWPORT"
+];
+
+/**
+ * @const
+ * @type {!Object.<string, boolean>}
+ */
+WebGLRenderingContextResource.DrawingMethods = TypeUtils.createPrefixedPropertyNamesSet([
+    "clear",
+    "drawArrays",
+    "drawElements"
+]);
+
+/**
+ * @param {*} obj
+ * @return {WebGLRenderingContextResource}
+ */
+WebGLRenderingContextResource.forObject = function(obj)
+{
+    var resource = Resource.forObject(obj);
+    if (!resource)
+        return null;
+    resource = resource.contextResource();
+    return (resource instanceof WebGLRenderingContextResource) ? resource : null;
+}
+
+WebGLRenderingContextResource.prototype = {
+    /**
+     * @override (overrides @return type)
+     * @return {WebGLRenderingContext}
+     */
+    wrappedObject: function()
+    {
+        return this._wrappedObject;
+    },
+
+    /**
+     * @override
+     * @return {string}
+     */
+    toDataURL: function()
+    {
+        return this.wrappedObject().canvas.toDataURL();
+    },
+
+    /**
+     * @return {Array.<number>}
+     */
+    getAllErrors: function()
+    {
+        var errors = [];
+        var gl = this.wrappedObject();
+        if (gl) {
+            while (true) {
+                var error = gl.getError();
+                if (error === gl.NO_ERROR)
+                    break;
+                this.clearError(error);
+                errors.push(error);
+            }
+        }
+        if (this._customErrors) {
+            for (var key in this._customErrors) {
+                var error = Number(key);
+                errors.push(error);
+            }
+            delete this._customErrors;
+        }
+        return errors;
+    },
+
+    /**
+     * @param {Array.<number>} errors
+     */
+    restoreErrors: function(errors)
+    {
+        var gl = this.wrappedObject();
+        if (gl) {
+            var wasError = false;
+            while (gl.getError() !== gl.NO_ERROR)
+                wasError = true;
+            console.assert(!wasError, "Error(s) while capturing current WebGL state.");
+        }
+        if (!errors.length)
+            delete this._customErrors;
+        else {
+            this._customErrors = {};
+            for (var i = 0, n = errors.length; i < n; ++i)
+                this._customErrors[errors[i]] = true;
+        }
+    },
+
+    /**
+     * @param {number} error
+     */
+    clearError: function(error)
+    {
+        if (this._customErrors)
+            delete this._customErrors[error];
+    },
+
+    /**
+     * @return {number}
+     */
+    nextError: function()
+    {
+        if (this._customErrors) {
+            for (var key in this._customErrors) {
+                var error = Number(key);
+                delete this._customErrors[error];
+                return error;
+            }
+        }
+        delete this._customErrors;
+        var gl = this.wrappedObject();
+        return gl ? gl.NO_ERROR : 0;
+    },
+
+    /**
+     * @param {string} name
+     */
+    addExtension: function(name)
+    {
+        // FIXME: Wrap OES_vertex_array_object extension.
+        this._extensions[name.toLowerCase()] = true;
+    },
+
+    /**
+     * @override
+     * @param {!Object} data
+     * @param {!Cache} cache
+     */
+    _populateReplayableData: function(data, cache)
+    {
+        var gl = this.wrappedObject();
+        data.originalCanvas = gl.canvas;
+        data.originalContextAttributes = gl.getContextAttributes();
+        data.extensions = TypeUtils.cloneObject(this._extensions);
+
+        var originalErrors = this.getAllErrors();
+
+        // Take a full GL state snapshot.
+        var glState = {};
+        WebGLRenderingContextResource.GLCapabilities.forEach(function(parameter) {
+            glState[parameter] = gl.isEnabled(gl[parameter]);
+        });
+        WebGLRenderingContextResource.StateParameters.forEach(function(parameter) {
+            glState[parameter] = Resource.toReplayable(gl.getParameter(gl[parameter]), cache);
+        });
+
+        // VERTEX_ATTRIB_ARRAYS
+        var maxVertexAttribs = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+        var vertexAttribParameters = ["VERTEX_ATTRIB_ARRAY_BUFFER_BINDING", "VERTEX_ATTRIB_ARRAY_ENABLED", "VERTEX_ATTRIB_ARRAY_SIZE", "VERTEX_ATTRIB_ARRAY_STRIDE", "VERTEX_ATTRIB_ARRAY_TYPE", "VERTEX_ATTRIB_ARRAY_NORMALIZED", "CURRENT_VERTEX_ATTRIB"];
+        var vertexAttribStates = [];
+        for (var i = 0; i < maxVertexAttribs; ++i) {
+            var state = {};
+            vertexAttribParameters.forEach(function(attribParameter) {
+                state[attribParameter] = Resource.toReplayable(gl.getVertexAttrib(i, gl[attribParameter]), cache);
+            });
+            state.VERTEX_ATTRIB_ARRAY_POINTER = gl.getVertexAttribOffset(i, gl.VERTEX_ATTRIB_ARRAY_POINTER);
+            vertexAttribStates.push(state);
+        }
+        glState.vertexAttribStates = vertexAttribStates;
+
+        // TEXTURES
+        var currentTextureBinding = /** @type {number} */ (gl.getParameter(gl.ACTIVE_TEXTURE));
+        var maxTextureImageUnits = /** @type {number} */ (gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS));
+        var textureBindings = [];
+        for (var i = 0; i < maxTextureImageUnits; ++i) {
+            gl.activeTexture(gl.TEXTURE0 + i);
+            var state = {
+                TEXTURE_2D: Resource.toReplayable(gl.getParameter(gl.TEXTURE_BINDING_2D), cache),
+                TEXTURE_CUBE_MAP: Resource.toReplayable(gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP), cache)
+            };
+            textureBindings.push(state);
+        }
+        glState.textureBindings = textureBindings;
+        gl.activeTexture(currentTextureBinding);
+
+        data.glState = glState;
+
+        this.restoreErrors(originalErrors);
+    },
+
+    /**
+     * @override
+     * @param {!Object} data
+     * @param {!Cache} cache
+     */
+    _doReplayCalls: function(data, cache)
+    {
+        this._customErrors = null;
+        this._extensions = TypeUtils.cloneObject(data.extensions) || {};
+
+        var canvas = data.originalCanvas.cloneNode(true);
+        var replayContext = null;
+        var contextIds = ["experimental-webgl", "webkit-3d", "3d"];
+        for (var i = 0, contextId; contextId = contextIds[i]; ++i) {
+            replayContext = canvas.getContext(contextId, data.originalContextAttributes);
+            if (replayContext)
+                break;
+        }
+
+        console.assert(replayContext, "Failed to create a WebGLRenderingContext for the replay.");
+
+        var gl = /** @type {!WebGLRenderingContext} */ (Resource.wrappedObject(replayContext));
+        this.setWrappedObject(gl);
+
+        // Enable corresponding WebGL extensions.
+        for (var name in this._extensions)
+            gl.getExtension(name);
+
+        var glState = data.glState;
+        gl.bindFramebuffer(gl.FRAMEBUFFER, /** @type {WebGLFramebuffer} */ (ReplayableResource.replay(glState.FRAMEBUFFER_BINDING, cache)));
+        gl.bindRenderbuffer(gl.RENDERBUFFER, /** @type {WebGLRenderbuffer} */ (ReplayableResource.replay(glState.RENDERBUFFER_BINDING, cache)));
+
+        // Enable or disable server-side GL capabilities.
+        WebGLRenderingContextResource.GLCapabilities.forEach(function(parameter) {
+            console.assert(parameter in glState);
+            if (glState[parameter])
+                gl.enable(gl[parameter]);
+            else
+                gl.disable(gl[parameter]);
+        });
+
+        gl.blendColor(glState.BLEND_COLOR[0], glState.BLEND_COLOR[1], glState.BLEND_COLOR[2], glState.BLEND_COLOR[3]);
+        gl.blendEquationSeparate(glState.BLEND_EQUATION_RGB, glState.BLEND_EQUATION_ALPHA);
+        gl.blendFuncSeparate(glState.BLEND_SRC_RGB, glState.BLEND_DST_RGB, glState.BLEND_SRC_ALPHA, glState.BLEND_DST_ALPHA);
+        gl.clearColor(glState.COLOR_CLEAR_VALUE[0], glState.COLOR_CLEAR_VALUE[1], glState.COLOR_CLEAR_VALUE[2], glState.COLOR_CLEAR_VALUE[3]);
+        gl.clearDepth(glState.DEPTH_CLEAR_VALUE);
+        gl.clearStencil(glState.STENCIL_CLEAR_VALUE);
+        gl.colorMask(glState.COLOR_WRITEMASK[0], glState.COLOR_WRITEMASK[1], glState.COLOR_WRITEMASK[2], glState.COLOR_WRITEMASK[3]);
+        gl.cullFace(glState.CULL_FACE_MODE);
+        gl.depthFunc(glState.DEPTH_FUNC);
+        gl.depthMask(glState.DEPTH_WRITEMASK);
+        gl.depthRange(glState.DEPTH_RANGE[0], glState.DEPTH_RANGE[1]);
+        gl.frontFace(glState.FRONT_FACE);
+        gl.hint(gl.GENERATE_MIPMAP_HINT, glState.GENERATE_MIPMAP_HINT);
+        gl.lineWidth(glState.LINE_WIDTH);
+
+        WebGLRenderingContextResource.PixelStoreParameters.forEach(function(parameter) {
+            gl.pixelStorei(gl[parameter], glState[parameter]);
+        });
+
+        gl.polygonOffset(glState.POLYGON_OFFSET_FACTOR, glState.POLYGON_OFFSET_UNITS);
+        gl.sampleCoverage(glState.SAMPLE_COVERAGE_VALUE, glState.SAMPLE_COVERAGE_INVERT);
+        gl.stencilFuncSeparate(gl.FRONT, glState.STENCIL_FUNC, glState.STENCIL_REF, glState.STENCIL_VALUE_MASK);
+        gl.stencilFuncSeparate(gl.BACK, glState.STENCIL_BACK_FUNC, glState.STENCIL_BACK_REF, glState.STENCIL_BACK_VALUE_MASK);
+        gl.stencilOpSeparate(gl.FRONT, glState.STENCIL_FAIL, glState.STENCIL_PASS_DEPTH_FAIL, glState.STENCIL_PASS_DEPTH_PASS);
+        gl.stencilOpSeparate(gl.BACK, glState.STENCIL_BACK_FAIL, glState.STENCIL_BACK_PASS_DEPTH_FAIL, glState.STENCIL_BACK_PASS_DEPTH_PASS);
+        gl.stencilMaskSeparate(gl.FRONT, glState.STENCIL_WRITEMASK);
+        gl.stencilMaskSeparate(gl.BACK, glState.STENCIL_BACK_WRITEMASK);
+
+        gl.scissor(glState.SCISSOR_BOX[0], glState.SCISSOR_BOX[1], glState.SCISSOR_BOX[2], glState.SCISSOR_BOX[3]);
+        gl.viewport(glState.VIEWPORT[0], glState.VIEWPORT[1], glState.VIEWPORT[2], glState.VIEWPORT[3]);
+
+        gl.useProgram(/** @type {WebGLProgram} */ (ReplayableResource.replay(glState.CURRENT_PROGRAM, cache)));
+
+        // VERTEX_ATTRIB_ARRAYS
+        var maxVertexAttribs = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
+        for (var i = 0; i < maxVertexAttribs; ++i) {
+            var state = glState.vertexAttribStates[i] || {};
+            if (state.VERTEX_ATTRIB_ARRAY_ENABLED)
+                gl.enableVertexAttribArray(i);
+            else
+                gl.disableVertexAttribArray(i);
+            if (state.CURRENT_VERTEX_ATTRIB)
+                gl.vertexAttrib4fv(i, state.CURRENT_VERTEX_ATTRIB);
+            var buffer = /** @type {WebGLBuffer} */ (ReplayableResource.replay(state.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, cache));
+            if (buffer) {
+                gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+                gl.vertexAttribPointer(i, state.VERTEX_ATTRIB_ARRAY_SIZE, state.VERTEX_ATTRIB_ARRAY_TYPE, state.VERTEX_ATTRIB_ARRAY_NORMALIZED, state.VERTEX_ATTRIB_ARRAY_STRIDE, state.VERTEX_ATTRIB_ARRAY_POINTER);
+            }
+        }
+        gl.bindBuffer(gl.ARRAY_BUFFER, /** @type {WebGLBuffer} */ (ReplayableResource.replay(glState.ARRAY_BUFFER_BINDING, cache)));
+        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, /** @type {WebGLBuffer} */ (ReplayableResource.replay(glState.ELEMENT_ARRAY_BUFFER_BINDING, cache)));
+
+        // TEXTURES
+        var maxTextureImageUnits = /** @type {number} */ (gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS));
+        for (var i = 0; i < maxTextureImageUnits; ++i) {
+            gl.activeTexture(gl.TEXTURE0 + i);
+            var state = glState.textureBindings[i] || {};
+            gl.bindTexture(gl.TEXTURE_2D, /** @type {WebGLTexture} */ (ReplayableResource.replay(state.TEXTURE_2D, cache)));
+            gl.bindTexture(gl.TEXTURE_CUBE_MAP, /** @type {WebGLTexture} */ (ReplayableResource.replay(state.TEXTURE_CUBE_MAP, cache)));
+        }
+        gl.activeTexture(glState.ACTIVE_TEXTURE);
+
+        ContextResource.prototype._doReplayCalls.call(this, data, cache);
+    },
+
+    /**
+     * @param {Object|number} target
+     * @return {Resource}
+     */
+    currentBinding: function(target)
+    {
+        var resource = Resource.forObject(target);
+        if (resource)
+            return resource;
+        var gl = this.wrappedObject();
+        var bindingParameter;
+        var bindMethodName;
+        var bindMethodTarget = target;
+        switch (target) {
+        case gl.ARRAY_BUFFER:
+            bindingParameter = gl.ARRAY_BUFFER_BINDING;
+            bindMethodName = "bindBuffer";
+            break;
+        case gl.ELEMENT_ARRAY_BUFFER:
+            bindingParameter = gl.ELEMENT_ARRAY_BUFFER_BINDING;
+            bindMethodName = "bindBuffer";
+            break;
+        case gl.TEXTURE_2D:
+            bindingParameter = gl.TEXTURE_BINDING_2D;
+            bindMethodName = "bindTexture";
+            break;
+        case gl.TEXTURE_CUBE_MAP:
+        case gl.TEXTURE_CUBE_MAP_POSITIVE_X:
+        case gl.TEXTURE_CUBE_MAP_NEGATIVE_X:
+        case gl.TEXTURE_CUBE_MAP_POSITIVE_Y:
+        case gl.TEXTURE_CUBE_MAP_NEGATIVE_Y:
+        case gl.TEXTURE_CUBE_MAP_POSITIVE_Z:
+        case gl.TEXTURE_CUBE_MAP_NEGATIVE_Z:
+            bindingParameter = gl.TEXTURE_BINDING_CUBE_MAP;
+            bindMethodTarget = gl.TEXTURE_CUBE_MAP;
+            bindMethodName = "bindTexture";
+            break;
+        case gl.FRAMEBUFFER:
+            bindingParameter = gl.FRAMEBUFFER_BINDING;
+            bindMethodName = "bindFramebuffer";
+            break;
+        case gl.RENDERBUFFER:
+            bindingParameter = gl.RENDERBUFFER_BINDING;
+            bindMethodName = "bindRenderbuffer";
+            break;
+        default:
+            console.error("ASSERT_NOT_REACHED: unknown binding target " + target);
+            return null;
+        }
+        resource = Resource.forObject(gl.getParameter(bindingParameter));
+        if (resource)
+            resource.pushBinding(bindMethodTarget, bindMethodName);
+        return resource;
+    },
+
+    /**
+     * @override
+     * @return {!Object.<string, Function>}
+     */
+    _customWrapFunctions: function()
+    {
+        var wrapFunctions = WebGLRenderingContextResource._wrapFunctions;
+        if (!wrapFunctions) {
+            wrapFunctions = Object.create(null);
+
+            wrapFunctions["createBuffer"] = Resource.WrapFunction.resourceFactoryMethod(WebGLBufferResource, "WebGLBuffer");
+            wrapFunctions["createShader"] = Resource.WrapFunction.resourceFactoryMethod(WebGLShaderResource, "WebGLShader");
+            wrapFunctions["createProgram"] = Resource.WrapFunction.resourceFactoryMethod(WebGLProgramResource, "WebGLProgram");
+            wrapFunctions["createTexture"] = Resource.WrapFunction.resourceFactoryMethod(WebGLTextureResource, "WebGLTexture");
+            wrapFunctions["createFramebuffer"] = Resource.WrapFunction.resourceFactoryMethod(WebGLFramebufferResource, "WebGLFramebuffer");
+            wrapFunctions["createRenderbuffer"] = Resource.WrapFunction.resourceFactoryMethod(WebGLRenderbufferResource, "WebGLRenderbuffer");
+            wrapFunctions["getUniformLocation"] = Resource.WrapFunction.resourceFactoryMethod(Resource, "WebGLUniformLocation");
+
+            /**
+             * @param {string} methodName
+             * @param {function(this:Resource, !Call)=} pushCallFunc
+             */
+            function stateModifyingWrapFunction(methodName, pushCallFunc)
+            {
+                if (pushCallFunc) {
+                    /**
+                     * @param {Object|number} target
+                     * @this Resource.WrapFunction
+                     */
+                    wrapFunctions[methodName] = function(target)
+                    {
+                        var resource = this._resource.currentBinding(target);
+                        if (resource)
+                            pushCallFunc.call(resource, this.call());
+                    }
+                } else {
+                    /**
+                     * @param {Object|number} target
+                     * @this Resource.WrapFunction
+                     */
+                    wrapFunctions[methodName] = function(target)
+                    {
+                        var resource = this._resource.currentBinding(target);
+                        if (resource)
+                            resource.pushCall(this.call());
+                    }
+                }
+            }
+            stateModifyingWrapFunction("bindAttribLocation");
+            stateModifyingWrapFunction("compileShader");
+            stateModifyingWrapFunction("detachShader");
+            stateModifyingWrapFunction("linkProgram");
+            stateModifyingWrapFunction("shaderSource");
+            stateModifyingWrapFunction("bufferData");
+            stateModifyingWrapFunction("bufferSubData");
+            stateModifyingWrapFunction("compressedTexImage2D");
+            stateModifyingWrapFunction("compressedTexSubImage2D");
+            stateModifyingWrapFunction("copyTexImage2D", WebGLTextureResource.prototype.pushCall_copyTexImage2D);
+            stateModifyingWrapFunction("copyTexSubImage2D", WebGLTextureResource.prototype.pushCall_copyTexImage2D);
+            stateModifyingWrapFunction("generateMipmap");
+            stateModifyingWrapFunction("texImage2D");
+            stateModifyingWrapFunction("texSubImage2D");
+            stateModifyingWrapFunction("texParameterf", WebGLTextureResource.prototype.pushCall_texParameter);
+            stateModifyingWrapFunction("texParameteri", WebGLTextureResource.prototype.pushCall_texParameter);
+            stateModifyingWrapFunction("renderbufferStorage");
+
+            /** @this Resource.WrapFunction */
+            wrapFunctions["getError"] = function()
+            {
+                var gl = /** @type {WebGLRenderingContext} */ (this._originalObject);
+                var error = this.result();
+                if (error !== gl.NO_ERROR)
+                    this._resource.clearError(error);
+                else {
+                    error = this._resource.nextError();
+                    if (error !== gl.NO_ERROR)
+                        this.overrideResult(error);
+                }
+            }
+
+            /**
+             * @param {string} name
+             * @this Resource.WrapFunction
+             */
+            wrapFunctions["getExtension"] = function(name)
+            {
+                this._resource.addExtension(name);
+            }
+
+            //
+            // Register bound WebGL resources.
+            //
+
+            /**
+             * @param {WebGLProgram} program
+             * @param {WebGLShader} shader
+             * @this Resource.WrapFunction
+             */
+            wrapFunctions["attachShader"] = function(program, shader)
+            {
+                var resource = this._resource.currentBinding(program);
+                if (resource) {
+                    resource.pushCall(this.call());
+                    var shaderResource = /** @type {WebGLShaderResource} */ (Resource.forObject(shader));
+                    if (shaderResource) {
+                        var shaderType = shaderResource.type();
+                        resource._registerBoundResource("__attachShader_" + shaderType, shaderResource);
+                    }
+                }
+            }
+            /**
+             * @param {number} target
+             * @param {number} attachment
+             * @param {number} objectTarget
+             * @param {WebGLRenderbuffer|WebGLTexture} obj
+             * @this Resource.WrapFunction
+             */
+            wrapFunctions["framebufferRenderbuffer"] = wrapFunctions["framebufferTexture2D"] = function(target, attachment, objectTarget, obj)
+            {
+                var resource = this._resource.currentBinding(target);
+                if (resource) {
+                    resource.pushCall(this.call());
+                    resource._registerBoundResource("__framebufferAttachmentObjectName", obj);
+                }
+            }
+            /**
+             * @param {number} target
+             * @param {Object} obj
+             * @this Resource.WrapFunction
+             */
+            wrapFunctions["bindBuffer"] = wrapFunctions["bindFramebuffer"] = wrapFunctions["bindRenderbuffer"] = function(target, obj)
+            {
+                this._resource._registerBoundResource("__bindBuffer_" + target, obj);
+            }
+            /**
+             * @param {number} target
+             * @param {WebGLTexture} obj
+             * @this Resource.WrapFunction
+             */
+            wrapFunctions["bindTexture"] = function(target, obj)
+            {
+                var gl = /** @type {WebGLRenderingContext} */ (this._originalObject);
+                var currentTextureBinding = /** @type {number} */ (gl.getParameter(gl.ACTIVE_TEXTURE));
+                this._resource._registerBoundResource("__bindTexture_" + target + "_" + currentTextureBinding, obj);
+            }
+            /**
+             * @param {WebGLProgram} program
+             * @this Resource.WrapFunction
+             */
+            wrapFunctions["useProgram"] = function(program)
+            {
+                this._resource._registerBoundResource("__useProgram", program);
+            }
+            /**
+             * @param {number} index
+             * @this Resource.WrapFunction
+             */
+            wrapFunctions["vertexAttribPointer"] = function(index)
+            {
+                var gl = /** @type {WebGLRenderingContext} */ (this._originalObject);
+                this._resource._registerBoundResource("__vertexAttribPointer_" + index, gl.getParameter(gl.ARRAY_BUFFER_BINDING));
+            }
+
+            WebGLRenderingContextResource._wrapFunctions = wrapFunctions;
+        }
+        return wrapFunctions;
+    },
+
+    __proto__: ContextResource.prototype
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// 2D Canvas
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * @constructor
+ * @extends {ContextResource}
+ * @param {!CanvasRenderingContext2D} context
+ */
+function CanvasRenderingContext2DResource(context)
+{
+    ContextResource.call(this, context, "CanvasRenderingContext2D");
+}
+
+/**
+ * @const
+ * @type {!Array.<string>}
+ */
+CanvasRenderingContext2DResource.AttributeProperties = [
+    "strokeStyle",
+    "fillStyle",
+    "globalAlpha",
+    "lineWidth",
+    "lineCap",
+    "lineJoin",
+    "miterLimit",
+    "shadowOffsetX",
+    "shadowOffsetY",
+    "shadowBlur",
+    "shadowColor",
+    "globalCompositeOperation",
+    "font",
+    "textAlign",
+    "textBaseline",
+    "lineDashOffset",
+    // FIXME: Temporary properties implemented in JSC, but not in V8.
+    "webkitLineDash",
+    "webkitLineDashOffset"
+];
+
+/**
+ * @const
+ * @type {!Array.<string>}
+ */
+CanvasRenderingContext2DResource.PathMethods = [
+    "beginPath",
+    "moveTo",
+    "closePath",
+    "lineTo",
+    "quadraticCurveTo",
+    "bezierCurveTo",
+    "arcTo",
+    "arc",
+    "rect"
+];
+
+/**
+ * @const
+ * @type {!Array.<string>}
+ */
+CanvasRenderingContext2DResource.TransformationMatrixMethods = [
+    "scale",
+    "rotate",
+    "translate",
+    "transform",
+    "setTransform"
+];
+
+/**
+ * @const
+ * @type {!Object.<string, boolean>}
+ */
+CanvasRenderingContext2DResource.DrawingMethods = TypeUtils.createPrefixedPropertyNamesSet([
+    "clearRect",
+    "drawImage",
+    "drawImageFromRect",
+    "drawCustomFocusRing",
+    "drawSystemFocusRing",
+    "fill",
+    "fillRect",
+    "fillText",
+    "putImageData",
+    "putImageDataHD",
+    "stroke",
+    "strokeRect",
+    "strokeText"
+]);
+
+CanvasRenderingContext2DResource.prototype = {
+    /**
+     * @override (overrides @return type)
+     * @return {CanvasRenderingContext2D}
+     */
+    wrappedObject: function()
+    {
+        return this._wrappedObject;
+    },
+
+    /**
+     * @override
+     * @return {string}
+     */
+    toDataURL: function()
+    {
+        return this.wrappedObject().canvas.toDataURL();
+    },
+
+    /**
+     * @override
+     * @param {!Object} data
+     * @param {!Cache} cache
+     */
+    _populateReplayableData: function(data, cache)
+    {
+        data.currentAttributes = this._currentAttributesState();
+        data.originalCanvasCloned = TypeUtils.cloneIntoCanvas(this.wrappedObject().canvas);
+    },
+
+    /**
+     * @override
+     * @param {!Object} data
+     * @param {!Cache} cache
+     */
+    _doReplayCalls: function(data, cache)
+    {
+        var canvas = TypeUtils.cloneIntoCanvas(data.originalCanvasCloned);
+        var ctx = /** @type {!CanvasRenderingContext2D} */ (Resource.wrappedObject(canvas.getContext("2d")));
+        this.setWrappedObject(ctx);
+
+        for (var i = 0, n = data.calls.length; i < n; ++i) {
+            var replayableCall = /** @type {ReplayableCall} */ (data.calls[i]);
+            if (replayableCall.functionName() === "save")
+                this._applyAttributesState(replayableCall.attachment("canvas2dAttributesState"));
+            this._calls.push(replayableCall.replay(cache));
+        }
+        this._applyAttributesState(data.currentAttributes);
+    },
+
+    /**
+     * @param {!Call} call
+     */
+    pushCall_setTransform: function(call)
+    {
+        var saveCallIndex = this._lastIndexOfMatchingSaveCall();
+        var index = this._lastIndexOfAnyCall(CanvasRenderingContext2DResource.PathMethods);
+        index = Math.max(index, saveCallIndex);
+        if (this._removeCallsFromLog(CanvasRenderingContext2DResource.TransformationMatrixMethods, index + 1))
+            this._removeAllObsoleteCallsFromLog();
+        this.pushCall(call);
+    },
+
+    /**
+     * @param {!Call} call
+     */
+    pushCall_beginPath: function(call)
+    {
+        var index = this._lastIndexOfAnyCall(["clip"]);
+        if (this._removeCallsFromLog(CanvasRenderingContext2DResource.PathMethods, index + 1))
+            this._removeAllObsoleteCallsFromLog();
+        this.pushCall(call);
+    },
+
+    /**
+     * @param {!Call} call
+     */
+    pushCall_save: function(call)
+    {
+        call.setAttachment("canvas2dAttributesState", this._currentAttributesState());
+        this.pushCall(call);
+    },
+
+    /**
+     * @param {!Call} call
+     */
+    pushCall_restore: function(call)
+    {
+        var lastIndexOfSave = this._lastIndexOfMatchingSaveCall();
+        if (lastIndexOfSave === -1)
+            return;
+        this._calls[lastIndexOfSave].setAttachment("canvas2dAttributesState", null); // No longer needed, free memory.
+
+        var modified = false;
+        if (this._removeCallsFromLog(["clip"], lastIndexOfSave + 1))
+            modified = true;
+
+        var lastIndexOfAnyPathMethod = this._lastIndexOfAnyCall(CanvasRenderingContext2DResource.PathMethods);
+        var index = Math.max(lastIndexOfSave, lastIndexOfAnyPathMethod);
+        if (this._removeCallsFromLog(CanvasRenderingContext2DResource.TransformationMatrixMethods, index + 1))
+            modified = true;
+
+        if (modified)
+            this._removeAllObsoleteCallsFromLog();
+
+        var lastCall = this._calls[this._calls.length - 1];
+        if (lastCall && lastCall.functionName() === "save")
+            this._calls.pop();
+        else
+            this.pushCall(call);
+    },
+
+    /**
+     * @param {number=} fromIndex
+     * @return {number}
+     */
+    _lastIndexOfMatchingSaveCall: function(fromIndex)
+    {
+        if (typeof fromIndex !== "number")
+            fromIndex = this._calls.length - 1;
+        else
+            fromIndex = Math.min(fromIndex, this._calls.length - 1);
+        var stackDepth = 1;
+        for (var i = fromIndex; i >= 0; --i) {
+            var functionName = this._calls[i].functionName();
+            if (functionName === "restore")
+                ++stackDepth;
+            else if (functionName === "save") {
+                --stackDepth;
+                if (!stackDepth)
+                    return i;
+            }
+        }
+        return -1;
+    },
+
+    /**
+     * @param {!Array.<string>} functionNames
+     * @param {number=} fromIndex
+     * @return {number}
+     */
+    _lastIndexOfAnyCall: function(functionNames, fromIndex)
+    {
+        if (typeof fromIndex !== "number")
+            fromIndex = this._calls.length - 1;
+        else
+            fromIndex = Math.min(fromIndex, this._calls.length - 1);
+        for (var i = fromIndex; i >= 0; --i) {
+            if (functionNames.indexOf(this._calls[i].functionName()) !== -1)
+                return i;
+        }
+        return -1;
+    },
+
+    _removeAllObsoleteCallsFromLog: function()
+    {
+        // Remove all PATH methods between clip() and beginPath() calls.
+        var lastIndexOfBeginPath = this._lastIndexOfAnyCall(["beginPath"]);
+        while (lastIndexOfBeginPath !== -1) {
+            var index = this._lastIndexOfAnyCall(["clip"], lastIndexOfBeginPath - 1);
+            this._removeCallsFromLog(CanvasRenderingContext2DResource.PathMethods, index + 1, lastIndexOfBeginPath);
+            lastIndexOfBeginPath = this._lastIndexOfAnyCall(["beginPath"], index - 1);
+        }
+
+        // Remove all TRASFORMATION MATRIX methods before restore() or setTransform() but after any PATH or corresponding save() method.
+        var lastRestore = this._lastIndexOfAnyCall(["restore", "setTransform"]);
+        while (lastRestore !== -1) {
+            var saveCallIndex = this._lastIndexOfMatchingSaveCall(lastRestore - 1);
+            var index = this._lastIndexOfAnyCall(CanvasRenderingContext2DResource.PathMethods, lastRestore - 1);
+            index = Math.max(index, saveCallIndex);
+            this._removeCallsFromLog(CanvasRenderingContext2DResource.TransformationMatrixMethods, index + 1, lastRestore);
+            lastRestore = this._lastIndexOfAnyCall(["restore", "setTransform"], index - 1);
+        }
+
+        // Remove all save-restore consecutive pairs.
+        var restoreCalls = 0;
+        for (var i = this._calls.length - 1; i >= 0; --i) {
+            var functionName = this._calls[i].functionName();
+            if (functionName === "restore") {
+                ++restoreCalls;
+                continue;
+            }
+            if (functionName === "save" && restoreCalls > 0) {
+                var saveCallIndex = i;
+                for (var j = i - 1; j >= 0 && i - j < restoreCalls; --j) {
+                    if (this._calls[j].functionName() === "save")
+                        saveCallIndex = j;
+                    else
+                        break;
+                }
+                this._calls.splice(saveCallIndex, (i - saveCallIndex + 1) * 2);
+                i = saveCallIndex;
+            }
+            restoreCalls = 0;
+        }
+    },
+
+    /**
+     * @param {!Array.<string>} functionNames
+     * @param {number} fromIndex
+     * @param {number=} toIndex
+     * @return {boolean}
+     */
+    _removeCallsFromLog: function(functionNames, fromIndex, toIndex)
+    {
+        var oldLength = this._calls.length;
+        if (typeof toIndex !== "number")
+            toIndex = oldLength;
+        else
+            toIndex = Math.min(toIndex, oldLength);
+        var newIndex = Math.min(fromIndex, oldLength);
+        for (var i = newIndex; i < toIndex; ++i) {
+            var call = this._calls[i];
+            if (functionNames.indexOf(call.functionName()) === -1)
+                this._calls[newIndex++] = call;
+        }
+        if (newIndex >= toIndex)
+            return false;
+        this._calls.splice(newIndex, toIndex - newIndex);
+        return true;
+    },
+
+    /**
+     * @return {!Object.<string, string>}
+     */
+    _currentAttributesState: function()
+    {
+        var ctx = this.wrappedObject();
+        var state = {};
+        state.attributes = {};
+        CanvasRenderingContext2DResource.AttributeProperties.forEach(function(attribute) {
+            state.attributes[attribute] = ctx[attribute];
+        });
+        if (ctx.getLineDash)
+            state.lineDash = ctx.getLineDash();
+        return state;
+    },
+
+    /**
+     * @param {Object.<string, string>=} state
+     */
+    _applyAttributesState: function(state)
+    {
+        if (!state)
+            return;
+        var ctx = this.wrappedObject();
+        if (state.attributes) {
+            Object.keys(state.attributes).forEach(function(attribute) {
+                ctx[attribute] = state.attributes[attribute];
+            });
+        }
+        if (ctx.setLineDash)
+            ctx.setLineDash(state.lineDash);
+    },
+
+    /**
+     * @override
+     * @return {!Object.<string, Function>}
+     */
+    _customWrapFunctions: function()
+    {
+        var wrapFunctions = CanvasRenderingContext2DResource._wrapFunctions;
+        if (!wrapFunctions) {
+            wrapFunctions = Object.create(null);
+
+            wrapFunctions["createLinearGradient"] = Resource.WrapFunction.resourceFactoryMethod(LogEverythingResource, "CanvasGradient");
+            wrapFunctions["createRadialGradient"] = Resource.WrapFunction.resourceFactoryMethod(LogEverythingResource, "CanvasGradient");
+            wrapFunctions["createPattern"] = Resource.WrapFunction.resourceFactoryMethod(LogEverythingResource, "CanvasPattern");
+
+            /**
+             * @param {string} methodName
+             * @param {function(this:Resource, !Call)=} func
+             */
+            function stateModifyingWrapFunction(methodName, func)
+            {
+                if (func) {
+                    /** @this Resource.WrapFunction */
+                    wrapFunctions[methodName] = function()
+                    {
+                        func.call(this._resource, this.call());
+                    }
+                } else {
+                    /** @this Resource.WrapFunction */
+                    wrapFunctions[methodName] = function()
+                    {
+                        this._resource.pushCall(this.call());
+                    }
+                }
+            }
+
+            for (var i = 0, methodName; methodName = CanvasRenderingContext2DResource.TransformationMatrixMethods[i]; ++i)
+                stateModifyingWrapFunction(methodName, methodName === "setTransform" ? this.pushCall_setTransform : undefined);
+            for (var i = 0, methodName; methodName = CanvasRenderingContext2DResource.PathMethods[i]; ++i)
+                stateModifyingWrapFunction(methodName, methodName === "beginPath" ? this.pushCall_beginPath : undefined);
+
+            stateModifyingWrapFunction("save", this.pushCall_save);
+            stateModifyingWrapFunction("restore", this.pushCall_restore);
+            stateModifyingWrapFunction("clip");
+
+            CanvasRenderingContext2DResource._wrapFunctions = wrapFunctions;
+        }
+        return wrapFunctions;
+    },
+
+    __proto__: ContextResource.prototype
+}
+
+/**
+ * @constructor
+ * @param {!Object.<string, boolean>=} drawingMethodNames
+ */
+function CallFormatter(drawingMethodNames)
+{
+    this._drawingMethodNames = drawingMethodNames || Object.create(null);
+}
+
+CallFormatter.prototype = {
+    /**
+     * @param {!ReplayableCall} replayableCall
+     * @return {!Object}
+     */
+    formatCall: function(replayableCall)
+    {
+        var result = {};
+        var functionName = replayableCall.functionName();
+        if (functionName) {
+            result.functionName = functionName;
+            result.arguments = replayableCall.args().map(this.formatValue.bind(this));
+            if (replayableCall.result() !== undefined)
+                result.result = this.formatValue(replayableCall.result());
+            if (this._drawingMethodNames[functionName])
+                result.isDrawingCall = true;
+        } else {
+            result.property = replayableCall.args()[0];
+            result.value = this.formatValue(replayableCall.args()[1]);
+        }
+        return result;
+    },
+
+    /**
+     * @param {*} value
+     * @return {!Object}
+     */
+    formatValue: function(value)
+    {
+        if (value instanceof ReplayableResource)
+            var description = value.description();
+        else
+            var description = "" + value;
+        return { description: description };
+    }
+}
+
+/**
+ * @const
+ * @type {!Object.<string, !CallFormatter>}
+ */
+CallFormatter._formatters = {};
+
+/**
+ * @param {string} resourceName
+ * @param {!CallFormatter} callFormatter
+ */
+CallFormatter.register = function(resourceName, callFormatter)
+{
+    CallFormatter._formatters[resourceName] = callFormatter;
+}
+
+/**
+ * @param {!ReplayableCall} replayableCall
+ * @return {!Object}
+ */
+CallFormatter.formatCall = function(replayableCall)
+{
+    var resource = replayableCall.replayableResource();
+    var formatter = CallFormatter._formatters[resource.name()];
+    if (!formatter) {
+        var contextResource = resource.replayableContextResource();
+        formatter = CallFormatter._formatters[contextResource.name()] || new CallFormatter();
+    }
+    return formatter.formatCall(replayableCall);
+}
+
+CallFormatter.register("CanvasRenderingContext2D", new CallFormatter(CanvasRenderingContext2DResource.DrawingMethods));
+CallFormatter.register("WebGLRenderingContext", new CallFormatter(WebGLRenderingContextResource.DrawingMethods));
+
+/**
+ * @constructor
+ */
+function TraceLog()
+{
+    /** @type {!Array.<ReplayableCall>} */
+    this._replayableCalls = [];
+    /** @type {!Cache} */
+    this._replayablesCache = new Cache();
+    /** @type {!Object.<number, boolean>} */
+    this._frameEndCallIndexes = {};
+}
+
+TraceLog.prototype = {
+    /**
+     * @return {number}
+     */
+    size: function()
+    {
+        return this._replayableCalls.length;
+    },
+
+    /**
+     * @return {!Array.<ReplayableCall>}
+     */
+    replayableCalls: function()
+    {
+        return this._replayableCalls;
+    },
+
+    /**
+     * @param {number} id
+     * @return {ReplayableResource}
+     */
+    replayableResource: function(id)
+    {
+        return /** @type {ReplayableResource} */ (this._replayablesCache.get(id));
+    },
+
+    /**
+     * @param {!Resource} resource
+     */
+    captureResource: function(resource)
+    {
+        resource.toReplayable(this._replayablesCache);
+    },
+
+    /**
+     * @param {!Call} call
+     */
+    addCall: function(call)
+    {
+        this._replayableCalls.push(call.toReplayable(this._replayablesCache));
+    },
+
+    addFrameEndMark: function()
+    {
+        var index = this._replayableCalls.length - 1;
+        if (index >= 0)
+            this._frameEndCallIndexes[index] = true;
+    },
+
+    /**
+     * @param {number} index
+     * @return {boolean}
+     */
+    isFrameEndCallAt: function(index)
+    {
+        return !!this._frameEndCallIndexes[index];
+    }
+}
+
+/**
+ * @constructor
+ * @param {!TraceLog} traceLog
+ */
+function TraceLogPlayer(traceLog)
+{
+    /** @type {!TraceLog} */
+    this._traceLog = traceLog;
+    /** @type {number} */
+    this._nextReplayStep = 0;
+    /** @type {!Cache} */
+    this._replayWorldCache = new Cache();
+}
+
+TraceLogPlayer.prototype = {
+    /**
+     * @return {!TraceLog}
+     */
+    traceLog: function()
+    {
+        return this._traceLog;
+    },
+
+    /**
+     * @param {number} id
+     * @return {Resource}
+     */
+    replayWorldResource: function(id)
+    {
+        return /** @type {Resource} */ (this._replayWorldCache.get(id));
+    },
+
+    /**
+     * @return {number}
+     */
+    nextReplayStep: function()
+    {
+        return this._nextReplayStep;
+    },
+
+    reset: function()
+    {
+        this._nextReplayStep = 0;
+        this._replayWorldCache.reset();
+    },
+
+    /**
+     * @return {Call}
+     */
+    step: function()
+    {
+        return this.stepTo(this._nextReplayStep);
+    },
+
+    /**
+     * @param {number} stepNum
+     * @return {Call}
+     */
+    stepTo: function(stepNum)
+    {
+        stepNum = Math.min(stepNum, this._traceLog.size() - 1);
+        console.assert(stepNum >= 0);
+        if (this._nextReplayStep > stepNum)
+            this.reset();
+        // FIXME: Replay all the cached resources first to warm-up.
+        var lastCall = null;
+        var replayableCalls = this._traceLog.replayableCalls();
+        while (this._nextReplayStep <= stepNum)
+            lastCall = replayableCalls[this._nextReplayStep++].replay(this._replayWorldCache);
+        return lastCall;
+    },
+
+    /**
+     * @return {Call}
+     */
+    replay: function()
+    {
+        return this.stepTo(this._traceLog.size() - 1);
+    }
+}
+
+/**
+ * @constructor
+ */
+function ResourceTrackingManager()
+{
+    this._capturing = false;
+    this._stopCapturingOnFrameEnd = false;
+    this._lastTraceLog = null;
+}
+
+ResourceTrackingManager.prototype = {
+    /**
+     * @return {boolean}
+     */
+    capturing: function()
+    {
+        return this._capturing;
+    },
+
+    /**
+     * @return {TraceLog}
+     */
+    lastTraceLog: function()
+    {
+        return this._lastTraceLog;
+    },
+
+    /**
+     * @param {!Resource} resource
+     */
+    registerResource: function(resource)
+    {
+        resource.setManager(this);
+    },
+
+    startCapturing: function()
+    {
+        if (!this._capturing)
+            this._lastTraceLog = new TraceLog();
+        this._capturing = true;
+        this._stopCapturingOnFrameEnd = false;
+    },
+
+    /**
+     * @param {TraceLog=} traceLog
+     */
+    stopCapturing: function(traceLog)
+    {
+        if (traceLog && this._lastTraceLog !== traceLog)
+            return;
+        this._capturing = false;
+        this._stopCapturingOnFrameEnd = false;
+        if (this._lastTraceLog)
+            this._lastTraceLog.addFrameEndMark();
+    },
+
+    /**
+     * @param {!TraceLog} traceLog
+     */
+    dropTraceLog: function(traceLog)
+    {
+        this.stopCapturing(traceLog);
+        if (this._lastTraceLog === traceLog)
+            this._lastTraceLog = null;
+    },
+
+    captureFrame: function()
+    {
+        this._lastTraceLog = new TraceLog();
+        this._capturing = true;
+        this._stopCapturingOnFrameEnd = true;
+    },
+
+    /**
+     * @param {!Resource} resource
+     * @param {Array|Arguments} args
+     */
+    captureArguments: function(resource, args)
+    {
+        if (!this._capturing)
+            return;
+        this._lastTraceLog.captureResource(resource);
+        for (var i = 0, n = args.length; i < n; ++i) {
+            var res = Resource.forObject(args[i]);
+            if (res)
+                this._lastTraceLog.captureResource(res);
+        }
+    },
+
+    /**
+     * @param {!Call} call
+     */
+    captureCall: function(call)
+    {
+        if (!this._capturing)
+            return;
+        this._lastTraceLog.addCall(call);
+    },
+
+    markFrameEnd: function()
+    {
+        if (!this._lastTraceLog)
+            return;
+        this._lastTraceLog.addFrameEndMark();
+        if (this._stopCapturingOnFrameEnd && this._lastTraceLog.size())
+            this.stopCapturing(this._lastTraceLog);
+    }
+}
+
+/**
+ * @constructor
+ */
+var InjectedCanvasModule = function()
+{
+    /** @type {!ResourceTrackingManager} */
+    this._manager = new ResourceTrackingManager();
+    /** @type {number} */
+    this._lastTraceLogId = 0;
+    /** @type {!Object.<string, TraceLog>} */
+    this._traceLogs = {};
+    /** @type {!Object.<string, TraceLogPlayer>} */
+    this._traceLogPlayers = {};
+}
+
+InjectedCanvasModule.prototype = {
+    /**
+     * @param {!WebGLRenderingContext} glContext
+     * @return {Object}
+     */
+    wrapWebGLContext: function(glContext)
+    {
+        var resource = Resource.forObject(glContext) || new WebGLRenderingContextResource(glContext);
+        this._manager.registerResource(resource);
+        return resource.proxyObject();
+    },
+
+    /**
+     * @param {!CanvasRenderingContext2D} context
+     * @return {Object}
+     */
+    wrapCanvas2DContext: function(context)
+    {
+        var resource = Resource.forObject(context) || new CanvasRenderingContext2DResource(context);
+        this._manager.registerResource(resource);
+        return resource.proxyObject();
+    },
+
+    /**
+     * @return {CanvasAgent.TraceLogId}
+     */
+    captureFrame: function()
+    {
+        return this._callStartCapturingFunction(this._manager.captureFrame);
+    },
+
+    /**
+     * @return {CanvasAgent.TraceLogId}
+     */
+    startCapturing: function()
+    {
+        return this._callStartCapturingFunction(this._manager.startCapturing);
+    },
+
+    markFrameEnd: function()
+    {
+        this._manager.markFrameEnd();
+    },
+
+    /**
+     * @param {function(this:ResourceTrackingManager)} func
+     * @return {CanvasAgent.TraceLogId}
+     */
+    _callStartCapturingFunction: function(func)
+    {
+        var oldTraceLog = this._manager.lastTraceLog();
+        func.call(this._manager);
+        var traceLog = this._manager.lastTraceLog();
+        if (traceLog === oldTraceLog) {
+            for (var id in this._traceLogs) {
+                if (this._traceLogs[id] === traceLog)
+                    return id;
+            }
+        }
+        var id = this._makeTraceLogId();
+        this._traceLogs[id] = traceLog;
+        return id;
+    },
+
+    /**
+     * @param {CanvasAgent.TraceLogId} id
+     */
+    stopCapturing: function(id)
+    {
+        var traceLog = this._traceLogs[id];
+        if (traceLog)
+            this._manager.stopCapturing(traceLog);
+    },
+
+    /**
+     * @param {CanvasAgent.TraceLogId} id
+     */
+    dropTraceLog: function(id)
+    {
+        var traceLog = this._traceLogs[id];
+        if (traceLog)
+            this._manager.dropTraceLog(traceLog);
+        delete this._traceLogs[id];
+        delete this._traceLogPlayers[id];
+    },
+
+    /**
+     * @param {CanvasAgent.TraceLogId} id
+     * @param {number=} startOffset
+     * @param {number=} maxLength
+     * @return {!CanvasAgent.TraceLog|string}
+     */
+    traceLog: function(id, startOffset, maxLength)
+    {
+        var traceLog = this._traceLogs[id];
+        if (!traceLog)
+            return "Error: Trace log with the given ID not found.";
+
+        // Ensure last call ends a frame.
+        traceLog.addFrameEndMark();
+
+        var replayableCalls = traceLog.replayableCalls();
+        if (typeof startOffset !== "number")
+            startOffset = 0;
+        if (typeof maxLength !== "number")
+            maxLength = replayableCalls.length;
+
+        var fromIndex = Math.max(0, startOffset);
+        var toIndex = Math.min(replayableCalls.length - 1, fromIndex + maxLength - 1);
+
+        var alive = this._manager.capturing() && this._manager.lastTraceLog() === traceLog;
+        var result = {
+            id: id,
+            /** @type {Array.<CanvasAgent.Call>} */
+            calls: [],
+            alive: alive,
+            startOffset: fromIndex,
+            totalAvailableCalls: replayableCalls.length
+        };
+        for (var i = fromIndex; i <= toIndex; ++i) {
+            var call = replayableCalls[i];
+            var contextResource = call.replayableResource().replayableContextResource();
+            var stackTrace = call.stackTrace();
+            var callFrame = stackTrace ? stackTrace.callFrame(0) || {} : {};
+            var item = CallFormatter.formatCall(call);
+            item.contextId = this._makeStringResourceId(contextResource.id());
+            item.sourceURL = callFrame.sourceURL;
+            item.lineNumber = callFrame.lineNumber;
+            item.columnNumber = callFrame.columnNumber;
+            item.isFrameEndCall = traceLog.isFrameEndCallAt(i);
+            result.calls.push(item);
+        }
+        return result;
+    },
+
+    /**
+     * @param {*} obj
+     * @return {!CanvasAgent.CallArgument}
+     */
+    _makeCallArgument: function(obj)
+    {
+        if (obj instanceof ReplayableResource)
+            var description = obj.description();
+        else
+            var description = "" + obj;
+        return { description: description };
+    },
+
+    /**
+     * @param {CanvasAgent.TraceLogId} traceLogId
+     * @param {number} stepNo
+     * @return {!CanvasAgent.ResourceState|string}
+     */
+    replayTraceLog: function(traceLogId, stepNo)
+    {
+        var traceLog = this._traceLogs[traceLogId];
+        if (!traceLog)
+            return "Error: Trace log with the given ID not found.";
+        this._traceLogPlayers[traceLogId] = this._traceLogPlayers[traceLogId] || new TraceLogPlayer(traceLog);
+        var lastCall = this._traceLogPlayers[traceLogId].stepTo(stepNo);
+        var resource = lastCall.resource();
+        var dataURL = resource.toDataURL();
+        if (!dataURL) {
+            resource = resource.contextResource();
+            dataURL = resource.toDataURL();
+        }
+        return this._makeResourceState(this._makeStringResourceId(resource.id()), traceLogId, dataURL);
+    },
+
+    /**
+     * @param {CanvasAgent.ResourceId} stringResourceId
+     * @return {!CanvasAgent.ResourceInfo|string}
+     */
+    resourceInfo: function(stringResourceId)
+    {
+        var resourceId = this._parseStringId(stringResourceId).resourceId;
+        if (!resourceId)
+            return "Error: Wrong resource ID: " + stringResourceId;
+
+        var replayableResource = null;
+        for (var id in this._traceLogs) {
+            replayableResource = this._traceLogs[id].replayableResource(resourceId);
+            if (replayableResource)
+                break;
+        }
+        if (!replayableResource)
+            return "Error: Resource with the given ID not found.";
+
+        return this._makeResourceInfo(stringResourceId, replayableResource.description());
+    },
+
+    /**
+     * @param {CanvasAgent.TraceLogId} traceLogId
+     * @param {CanvasAgent.ResourceId} stringResourceId
+     * @return {!CanvasAgent.ResourceState|string}
+     */
+    resourceState: function(traceLogId, stringResourceId)
+    {
+        var traceLog = this._traceLogs[traceLogId];
+        if (!traceLog)
+            return "Error: Trace log with the given ID not found.";
+
+        var traceLogPlayer = this._traceLogPlayers[traceLogId];
+        if (!traceLogPlayer)
+            return "Error: Trace log replay has not started yet.";
+
+        var parsedStringId1 = this._parseStringId(traceLogId);
+        var parsedStringId2 = this._parseStringId(stringResourceId);
+        if (parsedStringId1.injectedScriptId !== parsedStringId2.injectedScriptId)
+            return "Error: Both IDs must point to the same injected script.";
+
+        var resourceId = parsedStringId2.resourceId;
+        if (!resourceId)
+            return "Error: Wrong resource ID: " + stringResourceId;
+
+        var resource = traceLogPlayer.replayWorldResource(resourceId);
+        if (!resource)
+            return "Error: Resource with the given ID has not been replayed yet.";
+
+        return this._makeResourceState(stringResourceId, traceLogId, resource.toDataURL());
+    },
+
+    /**
+     * @return {CanvasAgent.TraceLogId}
+     */
+    _makeTraceLogId: function()
+    {
+        return "{\"injectedScriptId\":" + injectedScriptId + ",\"traceLogId\":" + (++this._lastTraceLogId) + "}";
+    },
+
+    /**
+     * @param {number} resourceId
+     * @return {CanvasAgent.ResourceId}
+     */
+    _makeStringResourceId: function(resourceId)
+    {
+        return "{\"injectedScriptId\":" + injectedScriptId + ",\"resourceId\":" + resourceId + "}";
+    },
+
+    /**
+     * @param {CanvasAgent.ResourceId} stringResourceId
+     * @param {string} description
+     * @return {!CanvasAgent.ResourceInfo}
+     */
+    _makeResourceInfo: function(stringResourceId, description)
+    {
+        return {
+            id: stringResourceId,
+            description: description
+        };
+    },
+
+    /**
+     * @param {CanvasAgent.ResourceId} stringResourceId
+     * @param {CanvasAgent.TraceLogId} traceLogId
+     * @param {string} imageURL
+     * @return {!CanvasAgent.ResourceState}
+     */
+    _makeResourceState: function(stringResourceId, traceLogId, imageURL)
+    {
+        return {
+            id: stringResourceId,
+            traceLogId: traceLogId,
+            imageURL: imageURL
+        };
+    },
+
+    /**
+     * @param {string} stringId
+     * @return {{injectedScriptId: number, traceLogId: ?number, resourceId: ?number}}
+     */
+    _parseStringId: function(stringId)
+    {
+        return InjectedScriptHost.evaluate("(" + stringId + ")");
+    }
+}
+
+var injectedCanvasModule = new InjectedCanvasModule();
+return injectedCanvasModule;
+
+})
diff --git a/Source/core/inspector/InjectedScriptExterns.js b/Source/core/inspector/InjectedScriptExterns.js
new file mode 100644
index 0000000..d6d1a78
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptExterns.js
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+
+// WebKit Web Facing API
+var console = { }
+/** @param {...*} vararg */
+console.log = function(vararg) { }
+/** @param {...*} vararg */
+console.table = function(vararg) { }
+
+/**
+ * @constructor
+ */
+function InjectedScriptHost() { }
+InjectedScriptHost.prototype.storageId = function(object) { }
+InjectedScriptHost.prototype.getInternalProperties = function(object) { }
+/**
+ * @param {Function} func
+ */
+InjectedScriptHost.prototype.functionDetails = function(func) { }
+/**
+ * @param {*} object
+ */
+InjectedScriptHost.prototype.isHTMLAllCollection = function(object) { }
+/**
+ * @param {*} object
+ */
+InjectedScriptHost.prototype.internalConstructorName = function(object) { }
+/**
+ * @param {*} object
+ */
+InjectedScriptHost.prototype.copyText = function(object) { }
+InjectedScriptHost.prototype.clearConsoleMessages = function() { }
+/**
+ * @param {number} index
+ */
+InjectedScriptHost.prototype.inspectedObject = function(index) { }
+/**
+ * @param {*} object
+ * @return {number}
+ */
+InjectedScriptHost.prototype.objectId = function(object) { }
+/**
+ * @param {*} object
+ */
+InjectedScriptHost.prototype.releaseObjectId = function(object) { }
+/**
+ * @param {*} object
+ */
+InjectedScriptHost.prototype.databaseId = function(object) { }
+/**
+ * @param {*} object
+ * @param {Object} hints
+ */
+InjectedScriptHost.prototype.inspect = function(object, hints) { }
+/**
+ * @param {*} object
+ */
+InjectedScriptHost.prototype.type = function(object) { }
+/**
+ * @param {*} object
+ */
+InjectedScriptHost.prototype.getEventListeners = function(object) { }
+/**
+ * @param {string} expression
+ */
+InjectedScriptHost.prototype.evaluate = function(expression) { }
+
+/**
+ * @param {function(...)} fun
+ * @param {number} scopeNumber
+ * @param {string} variableName
+ * @param {*} newValue
+ */
+InjectedScriptHost.prototype.setFunctionVariableValue = function(fun, scopeNumber, variableName, newValue) { }
+
+/**
+ * @constructor
+ */
+function JavaScriptCallFrame()
+{
+    /** @type {number} */
+    this.sourceID;
+    /** @type {number} */
+    this.line;
+    /** @type {number} */
+    this.column;
+    /** @type {*} */
+    this.thisObject;
+}
+
+/**
+ * @param {number} index
+ */
+JavaScriptCallFrame.prototype.scopeType = function(index) { }
+
+JavaScriptCallFrame.prototype.restart = function() { }
+
+/**
+ * @param {number} scopeNumber
+ * @param {string} variableName
+ * @param {*} newValue
+ */
+JavaScriptCallFrame.prototype.setVariableValue = function(scopeNumber, variableName, newValue) {}
+
+/**
+ * @constructor
+ */
+function JavaScriptFunction()
+{
+    /** @type {Array} */
+    this.rawScopes;
+}
+
+var InspectorBackend = { };
+
+// http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
+/**
+ * @constructor
+ */
+function CallSite()
+{
+}
+/**
+ * @return {string}
+ */
+CallSite.prototype.getFileName = function() { }
+/**
+ * @return {number}
+ */
+CallSite.prototype.getLineNumber = function() { }
+/**
+ * @return {number}
+ */
+CallSite.prototype.getColumnNumber = function() { }
diff --git a/Source/core/inspector/InjectedScriptHost.cpp b/Source/core/inspector/InjectedScriptHost.cpp
new file mode 100644
index 0000000..b530f6a
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptHost.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2010 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InjectedScriptHost.h"
+
+#include "InspectorFrontend.h"
+#include "core/dom/Element.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InspectorAgent.h"
+#include "core/inspector/InspectorClient.h"
+#include "core/inspector/InspectorConsoleAgent.h"
+#include "core/inspector/InspectorDOMAgent.h"
+#include "core/inspector/InspectorDOMStorageAgent.h"
+#include "core/inspector/InspectorDatabaseAgent.h"
+#include "core/inspector/InspectorDebuggerAgent.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/loader/FrameLoader.h"
+#include "core/page/Frame.h"
+#include "core/platform/Pasteboard.h"
+#include "core/storage/Storage.h"
+#include "modules/webdatabase/Database.h"
+
+
+#include "core/editing/markup.h"
+
+#include <wtf/RefPtr.h>
+#include <wtf/StdLibExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+PassRefPtr<InjectedScriptHost> InjectedScriptHost::create()
+{
+    return adoptRef(new InjectedScriptHost());
+}
+
+InjectedScriptHost::InjectedScriptHost()
+    : m_inspectorAgent(0)
+    , m_consoleAgent(0)
+    , m_databaseAgent(0)
+    , m_domStorageAgent(0)
+    , m_domAgent(0)
+{
+    m_defaultInspectableObject = adoptPtr(new InspectableObject());
+}
+
+InjectedScriptHost::~InjectedScriptHost()
+{
+}
+
+void InjectedScriptHost::disconnect()
+{
+    m_inspectorAgent = 0;
+    m_consoleAgent = 0;
+    m_databaseAgent = 0;
+    m_domStorageAgent = 0;
+    m_domAgent = 0;
+}
+
+void InjectedScriptHost::inspectImpl(PassRefPtr<InspectorValue> object, PassRefPtr<InspectorValue> hints)
+{
+    if (m_inspectorAgent) {
+        RefPtr<TypeBuilder::Runtime::RemoteObject> remoteObject = TypeBuilder::Runtime::RemoteObject::runtimeCast(object);
+        m_inspectorAgent->inspect(remoteObject, hints->asObject());
+    }
+}
+
+void InjectedScriptHost::getEventListenersImpl(Node* node, Vector<EventListenerInfo>& listenersArray)
+{
+    if (m_domAgent)
+        m_domAgent->getEventListeners(node, listenersArray, false);
+}
+
+void InjectedScriptHost::clearConsoleMessages()
+{
+    if (m_consoleAgent) {
+        ErrorString error;
+        m_consoleAgent->clearMessages(&error);
+    }
+}
+
+void InjectedScriptHost::copyText(const String& text)
+{
+    Pasteboard::generalPasteboard()->writePlainText(text, Pasteboard::CannotSmartReplace);
+}
+
+ScriptValue InjectedScriptHost::InspectableObject::get(ScriptState*)
+{
+    return ScriptValue();
+};
+
+void InjectedScriptHost::addInspectedObject(PassOwnPtr<InjectedScriptHost::InspectableObject> object)
+{
+    m_inspectedObjects.prepend(object);
+    while (m_inspectedObjects.size() > 5)
+        m_inspectedObjects.removeLast();
+}
+
+void InjectedScriptHost::clearInspectedObjects()
+{
+    m_inspectedObjects.clear();
+}
+
+InjectedScriptHost::InspectableObject* InjectedScriptHost::inspectedObject(unsigned int num)
+{
+    if (num >= m_inspectedObjects.size())
+        return m_defaultInspectableObject.get();
+    return m_inspectedObjects[num].get();
+}
+
+String InjectedScriptHost::databaseIdImpl(Database* database)
+{
+    if (m_databaseAgent)
+        return m_databaseAgent->databaseId(database);
+    return String();
+}
+
+String InjectedScriptHost::storageIdImpl(Storage* storage)
+{
+    if (m_domStorageAgent)
+        return m_domStorageAgent->storageId(storage);
+    return String();
+}
+
+ScriptDebugServer& InjectedScriptHost::scriptDebugServer()
+{
+    return m_debuggerAgent->scriptDebugServer();
+}
+
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InjectedScriptHost.h b/Source/core/inspector/InjectedScriptHost.h
new file mode 100644
index 0000000..7c63ae3
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptHost.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  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. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef InjectedScriptHost_h
+#define InjectedScriptHost_h
+
+#include "bindings/v8/ScriptState.h"
+#include "core/inspector/InspectorAgent.h"
+#include "core/page/ConsoleTypes.h"
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Database;
+class InjectedScript;
+class InspectorAgent;
+class InspectorConsoleAgent;
+class InspectorDOMAgent;
+class InspectorDOMStorageAgent;
+class InspectorDatabaseAgent;
+class InspectorDebuggerAgent;
+class InspectorFrontend;
+class InspectorObject;
+class InspectorValue;
+class Node;
+class ScriptDebugServer;
+class ScriptObject;
+class ScriptValue;
+class Storage;
+
+struct EventListenerInfo;
+
+class InjectedScriptHost : public RefCounted<InjectedScriptHost> {
+public:
+    static PassRefPtr<InjectedScriptHost> create();
+    ~InjectedScriptHost();
+
+    void init(InspectorAgent* inspectorAgent
+            , InspectorConsoleAgent* consoleAgent
+            , InspectorDatabaseAgent* databaseAgent
+            , InspectorDOMStorageAgent* domStorageAgent
+            , InspectorDOMAgent* domAgent
+            , InspectorDebuggerAgent* debuggerAgent
+        )
+    {
+        m_inspectorAgent = inspectorAgent;
+        m_consoleAgent = consoleAgent;
+        m_databaseAgent = databaseAgent;
+        m_domStorageAgent = domStorageAgent;
+        m_domAgent = domAgent;
+        m_debuggerAgent = debuggerAgent;
+    }
+
+    static Node* scriptValueAsNode(ScriptValue);
+    static ScriptValue nodeAsScriptValue(ScriptState*, Node*);
+
+    void disconnect();
+
+    class InspectableObject {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        virtual ScriptValue get(ScriptState*);
+        virtual ~InspectableObject() { }
+    };
+    void addInspectedObject(PassOwnPtr<InspectableObject>);
+    void clearInspectedObjects();
+    InspectableObject* inspectedObject(unsigned int num);
+
+    void inspectImpl(PassRefPtr<InspectorValue> objectToInspect, PassRefPtr<InspectorValue> hints);
+    void getEventListenersImpl(Node*, Vector<EventListenerInfo>& listenersArray);
+
+    void clearConsoleMessages();
+    void copyText(const String& text);
+    String databaseIdImpl(Database*);
+    String storageIdImpl(Storage*);
+
+    ScriptDebugServer& scriptDebugServer();
+
+private:
+    InjectedScriptHost();
+
+    InspectorAgent* m_inspectorAgent;
+    InspectorConsoleAgent* m_consoleAgent;
+    InspectorDatabaseAgent* m_databaseAgent;
+    InspectorDOMStorageAgent* m_domStorageAgent;
+    InspectorDOMAgent* m_domAgent;
+    InspectorDebuggerAgent* m_debuggerAgent;
+    Vector<OwnPtr<InspectableObject> > m_inspectedObjects;
+    OwnPtr<InspectableObject> m_defaultInspectableObject;
+};
+
+} // namespace WebCore
+
+#endif // !defined(InjectedScriptHost_h)
diff --git a/Source/core/inspector/InjectedScriptHost.idl b/Source/core/inspector/InjectedScriptHost.idl
new file mode 100644
index 0000000..b285d67
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptHost.idl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2010 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.
+ */
+
+[
+    ImplementationLacksVTable
+] interface InjectedScriptHost {
+    void clearConsoleMessages();
+
+    void copyText(DOMString text);
+    [Custom] void inspect(any objectId, any hints);
+    [Custom] any inspectedObject(long num);
+    [Custom] any internalConstructorName(any object);
+    [Custom] boolean isHTMLAllCollection(any object);
+    [Custom] DOMString type(any object);
+    [Custom] any functionDetails(any object);
+    [Custom] Array getInternalProperties(any object);
+    [Custom] Array getEventListeners(Node node);
+    [Custom] any evaluate(DOMString text);
+    [Custom] DOMString databaseId(any database);
+    [Custom] DOMString storageId(any storage);
+
+    // Only declarative scope (local, with and catch) is accepted. Returns undefined. 
+    [Custom] any setFunctionVariableValue(any functionObject, int scopeIndex, DOMString variableName, any newValue);
+};
diff --git a/Source/core/inspector/InjectedScriptManager.cpp b/Source/core/inspector/InjectedScriptManager.cpp
new file mode 100644
index 0000000..8ea669c
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptManager.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InjectedScriptManager.h"
+
+#include "InjectedScriptSource.h"
+#include "bindings/v8/ScriptObject.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InjectedScriptHost.h"
+#include "core/inspector/InspectorValues.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+PassOwnPtr<InjectedScriptManager> InjectedScriptManager::createForPage()
+{
+    return adoptPtr(new InjectedScriptManager(&InjectedScriptManager::canAccessInspectedWindow));
+}
+
+PassOwnPtr<InjectedScriptManager> InjectedScriptManager::createForWorker()
+{
+    return adoptPtr(new InjectedScriptManager(&InjectedScriptManager::canAccessInspectedWorkerContext));
+}
+
+InjectedScriptManager::InjectedScriptManager(InspectedStateAccessCheck accessCheck)
+    : m_nextInjectedScriptId(1)
+    , m_injectedScriptHost(InjectedScriptHost::create())
+    , m_inspectedStateAccessCheck(accessCheck)
+{
+}
+
+InjectedScriptManager::~InjectedScriptManager()
+{
+}
+
+void InjectedScriptManager::disconnect()
+{
+    m_injectedScriptHost->disconnect();
+    m_injectedScriptHost.clear();
+}
+
+InjectedScriptHost* InjectedScriptManager::injectedScriptHost()
+{
+    return m_injectedScriptHost.get();
+}
+
+InjectedScript InjectedScriptManager::injectedScriptForId(int id)
+{
+    IdToInjectedScriptMap::iterator it = m_idToInjectedScript.find(id);
+    if (it != m_idToInjectedScript.end())
+        return it->value;
+    for (ScriptStateToId::iterator it = m_scriptStateToId.begin(); it != m_scriptStateToId.end(); ++it) {
+        if (it->value == id)
+            return injectedScriptFor(it->key);
+    }
+    return InjectedScript();
+}
+
+int InjectedScriptManager::injectedScriptIdFor(ScriptState* scriptState)
+{
+    ScriptStateToId::iterator it = m_scriptStateToId.find(scriptState);
+    if (it != m_scriptStateToId.end())
+        return it->value;
+    int id = m_nextInjectedScriptId++;
+    m_scriptStateToId.set(scriptState, id);
+    return id;
+}
+
+InjectedScript InjectedScriptManager::injectedScriptForObjectId(const String& objectId)
+{
+    RefPtr<InspectorValue> parsedObjectId = InspectorValue::parseJSON(objectId);
+    if (parsedObjectId && parsedObjectId->type() == InspectorValue::TypeObject) {
+        long injectedScriptId = 0;
+        bool success = parsedObjectId->asObject()->getNumber("injectedScriptId", &injectedScriptId);
+        if (success)
+            return m_idToInjectedScript.get(injectedScriptId);
+    }
+    return InjectedScript();
+}
+
+void InjectedScriptManager::discardInjectedScripts()
+{
+    m_idToInjectedScript.clear();
+    m_scriptStateToId.clear();
+}
+
+void InjectedScriptManager::discardInjectedScriptsFor(DOMWindow* window)
+{
+    if (m_scriptStateToId.isEmpty())
+        return;
+
+    Vector<long> idsToRemove;
+    IdToInjectedScriptMap::iterator end = m_idToInjectedScript.end();
+    for (IdToInjectedScriptMap::iterator it = m_idToInjectedScript.begin(); it != end; ++it) {
+        ScriptState* scriptState = it->value.scriptState();
+        if (window != domWindowFromScriptState(scriptState))
+            continue;
+        m_scriptStateToId.remove(scriptState);
+        idsToRemove.append(it->key);
+    }
+
+    for (size_t i = 0; i < idsToRemove.size(); i++)
+        m_idToInjectedScript.remove(idsToRemove[i]);
+
+    // Now remove script states that have id but no injected script.
+    Vector<ScriptState*> scriptStatesToRemove;
+    for (ScriptStateToId::iterator it = m_scriptStateToId.begin(); it != m_scriptStateToId.end(); ++it) {
+        ScriptState* scriptState = it->key;
+        if (window == domWindowFromScriptState(scriptState))
+            scriptStatesToRemove.append(scriptState);
+    }
+    for (size_t i = 0; i < scriptStatesToRemove.size(); i++)
+        m_scriptStateToId.remove(scriptStatesToRemove[i]);
+}
+
+bool InjectedScriptManager::canAccessInspectedWorkerContext(ScriptState*)
+{
+    return true;
+}
+
+void InjectedScriptManager::releaseObjectGroup(const String& objectGroup)
+{
+    for (IdToInjectedScriptMap::iterator it = m_idToInjectedScript.begin(); it != m_idToInjectedScript.end(); ++it)
+        it->value.releaseObjectGroup(objectGroup);
+}
+
+String InjectedScriptManager::injectedScriptSource()
+{
+    return String(reinterpret_cast<const char*>(InjectedScriptSource_js), sizeof(InjectedScriptSource_js));
+}
+
+InjectedScript InjectedScriptManager::injectedScriptFor(ScriptState* inspectedScriptState)
+{
+    ScriptStateToId::iterator it = m_scriptStateToId.find(inspectedScriptState);
+    if (it != m_scriptStateToId.end()) {
+        IdToInjectedScriptMap::iterator it1 = m_idToInjectedScript.find(it->value);
+        if (it1 != m_idToInjectedScript.end())
+            return it1->value;
+    }
+
+    if (!m_inspectedStateAccessCheck(inspectedScriptState))
+        return InjectedScript();
+
+    int id = injectedScriptIdFor(inspectedScriptState);
+    ScriptObject injectedScriptObject = createInjectedScript(injectedScriptSource(), inspectedScriptState, id);
+    InjectedScript result(injectedScriptObject, m_inspectedStateAccessCheck);
+    m_idToInjectedScript.set(id, result);
+    return result;
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InjectedScriptManager.h b/Source/core/inspector/InjectedScriptManager.h
new file mode 100644
index 0000000..e048e93
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptManager.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef InjectedScriptManager_h
+#define InjectedScriptManager_h
+
+#include "bindings/v8/ScriptState.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class DOMWindow;
+class InjectedScript;
+class InjectedScriptHost;
+class InspectorObject;
+class ScriptObject;
+
+class InjectedScriptManager {
+    WTF_MAKE_NONCOPYABLE(InjectedScriptManager); WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<InjectedScriptManager> createForPage();
+    static PassOwnPtr<InjectedScriptManager> createForWorker();
+    ~InjectedScriptManager();
+
+    void disconnect();
+
+    InjectedScriptHost* injectedScriptHost();
+
+    InjectedScript injectedScriptFor(ScriptState*);
+    InjectedScript injectedScriptForId(int);
+    int injectedScriptIdFor(ScriptState*);
+    InjectedScript injectedScriptForObjectId(const String& objectId);
+    void discardInjectedScripts();
+    void discardInjectedScriptsFor(DOMWindow*);
+    void releaseObjectGroup(const String& objectGroup);
+
+    typedef bool (*InspectedStateAccessCheck)(ScriptState*);
+    InspectedStateAccessCheck inspectedStateAccessCheck() const { return m_inspectedStateAccessCheck; }
+
+private:
+    explicit InjectedScriptManager(InspectedStateAccessCheck);
+
+    String injectedScriptSource();
+    ScriptObject createInjectedScript(const String& source, ScriptState*, int id);
+
+    static bool canAccessInspectedWindow(ScriptState*);
+    static bool canAccessInspectedWorkerContext(ScriptState*);
+
+    int m_nextInjectedScriptId;
+    typedef HashMap<int, InjectedScript> IdToInjectedScriptMap;
+    IdToInjectedScriptMap m_idToInjectedScript;
+    RefPtr<InjectedScriptHost> m_injectedScriptHost;
+    InspectedStateAccessCheck m_inspectedStateAccessCheck;
+    typedef HashMap<ScriptState*, int> ScriptStateToId;
+    ScriptStateToId m_scriptStateToId;
+};
+
+} // namespace WebCore
+
+#endif // !defined(InjectedScriptManager_h)
diff --git a/Source/core/inspector/InjectedScriptModule.cpp b/Source/core/inspector/InjectedScriptModule.cpp
new file mode 100644
index 0000000..f95a476
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptModule.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InjectedScriptModule.h"
+
+#include "bindings/v8/ScriptFunctionCall.h"
+#include "bindings/v8/ScriptObject.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InjectedScriptManager.h"
+
+namespace WebCore {
+
+InjectedScriptModule::InjectedScriptModule(const String& name)
+    : InjectedScriptBase(name)
+{
+}
+
+void InjectedScriptModule::ensureInjected(InjectedScriptManager* injectedScriptManager, ScriptState* scriptState)
+{
+    InjectedScript injectedScript = injectedScriptManager->injectedScriptFor(scriptState);
+    ASSERT(!injectedScript.hasNoValue());
+    if (injectedScript.hasNoValue())
+        return;
+
+    // FIXME: Make the InjectedScript a module itself.
+    ScriptFunctionCall function(injectedScript.injectedScriptObject(), "module");
+    function.appendArgument(name());
+    bool hadException = false;
+    ScriptValue resultValue = injectedScript.callFunctionWithEvalEnabled(function, hadException);
+    ASSERT(!hadException);
+    if (hadException || resultValue.hasNoValue() || !resultValue.isObject()) {
+        ScriptFunctionCall function(injectedScript.injectedScriptObject(), "injectModule");
+        function.appendArgument(name());
+        function.appendArgument(source());
+        resultValue = injectedScript.callFunctionWithEvalEnabled(function, hadException);
+        if (hadException || resultValue.hasNoValue() || !resultValue.isObject()) {
+            ASSERT_NOT_REACHED();
+            return;
+        }
+    }
+
+    ScriptObject moduleObject(scriptState, resultValue);
+    initialize(moduleObject, injectedScriptManager->inspectedStateAccessCheck());
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InjectedScriptModule.h b/Source/core/inspector/InjectedScriptModule.h
new file mode 100644
index 0000000..b4295a2
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptModule.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef InjectedScriptModule_h
+#define InjectedScriptModule_h
+
+#include "bindings/v8/ScriptState.h"
+#include "core/inspector/InjectedScriptBase.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class InjectedScriptManager;
+
+
+class InjectedScriptModule : public InjectedScriptBase {
+public:
+    virtual String source() const = 0;
+
+protected:
+    // Do not expose constructor in the child classes as well. Instead provide
+    // a static factory method that would create a new instance of the class
+    // and call its ensureInjected() method immediately.
+    InjectedScriptModule(const String& name);
+    void ensureInjected(InjectedScriptManager*, ScriptState*);
+};
+
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/core/inspector/InjectedScriptSource.js b/Source/core/inspector/InjectedScriptSource.js
new file mode 100644
index 0000000..34e163e
--- /dev/null
+++ b/Source/core/inspector/InjectedScriptSource.js
@@ -0,0 +1,1364 @@
+/*
+ * Copyright (C) 2007 Apple 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+/**
+ * @param {InjectedScriptHost} InjectedScriptHost
+ * @param {Window} inspectedWindow
+ * @param {number} injectedScriptId
+ */
+(function (InjectedScriptHost, inspectedWindow, injectedScriptId) {
+
+// Protect against Object overwritten by the user code.
+var Object = {}.constructor;
+
+/**
+ * @param {Arguments} array
+ * @param {number=} index
+ * @return {Array.<*>}
+ */
+function slice(array, index)
+{
+    var result = [];
+    for (var i = index || 0; i < array.length; ++i)
+        result.push(array[i]);
+    return result;
+}
+
+/**
+ * Please use this bind, not the one from Function.prototype
+ * @param {function(...)} func
+ * @param {Object} thisObject
+ * @param {...number} var_args
+ */
+function bind(func, thisObject, var_args)
+{
+    var args = slice(arguments, 2);
+
+    /**
+     * @param {...number} var_args
+     */
+    function bound(var_args)
+    {
+        return func.apply(thisObject, args.concat(slice(arguments)));
+    }
+    bound.toString = function() {
+        return "bound: " + func;
+    };
+    return bound;
+}
+
+/**
+ * @constructor
+ */
+var InjectedScript = function()
+{
+    this._lastBoundObjectId = 1;
+    this._idToWrappedObject = {};
+    this._idToObjectGroupName = {};
+    this._objectGroups = {};
+    this._modules = {};
+}
+
+/**
+ * @type {Object.<string, boolean>}
+ * @const
+ */
+InjectedScript.primitiveTypes = {
+    undefined: true,
+    boolean: true,
+    number: true,
+    string: true
+}
+
+InjectedScript.prototype = {
+    /**
+     * @param {*} object
+     * @return {boolean}
+     */
+    isPrimitiveValue: function(object)
+    {
+        // FIXME(33716): typeof document.all is always 'undefined'.
+        return InjectedScript.primitiveTypes[typeof object] && !this._isHTMLAllCollection(object);
+    },
+
+    /**
+     * @param {*} object
+     * @param {string} groupName
+     * @param {boolean} canAccessInspectedWindow
+     * @param {boolean} generatePreview
+     * @return {!RuntimeAgent.RemoteObject}
+     */
+    wrapObject: function(object, groupName, canAccessInspectedWindow, generatePreview)
+    {
+        if (canAccessInspectedWindow)
+            return this._wrapObject(object, groupName, false, generatePreview);
+        return this._fallbackWrapper(object);
+    },
+
+    /**
+     * @param {*} object
+     * @return {!RuntimeAgent.RemoteObject}
+     */
+    _fallbackWrapper: function(object)
+    {
+        var result = {};
+        result.type = typeof object;
+        if (this.isPrimitiveValue(object))
+            result.value = object;
+        else
+            result.description = this._toString(object);
+        return /** @type {!RuntimeAgent.RemoteObject} */ (result);
+    },
+
+    /**
+     * @param {boolean} canAccessInspectedWindow
+     * @param {Object} table
+     * @param {Array.<string>|string|boolean} columns
+     * @return {!RuntimeAgent.RemoteObject}
+     */
+    wrapTable: function(canAccessInspectedWindow, table, columns)
+    {
+        if (!canAccessInspectedWindow)
+            return this._fallbackWrapper(table);
+        var columnNames = null;
+        if (typeof columns === "string")
+            columns = [columns];
+        if (InjectedScriptHost.type(columns) == "array") {
+            columnNames = [];
+            for (var i = 0; i < columns.length; ++i)
+                columnNames.push(String(columns[i]));
+        }
+        return this._wrapObject(table, "console", false, true, columnNames);
+    },
+
+    /**
+     * @param {*} object
+     */
+    inspectNode: function(object)
+    {
+        this._inspect(object);
+    },
+
+    /**
+     * @param {*} object
+     * @return {*}
+     */
+    _inspect: function(object)
+    {
+        if (arguments.length === 0)
+            return;
+
+        var objectId = this._wrapObject(object, "");
+        var hints = {};
+
+        switch (injectedScript._describe(object)) {
+            case "Database":
+                var databaseId = InjectedScriptHost.databaseId(object)
+                if (databaseId)
+                    hints.databaseId = databaseId;
+                break;
+            case "Storage":
+                var storageId = InjectedScriptHost.storageId(object)
+                if (storageId)
+                    hints.domStorageId = InjectedScriptHost.evaluate("(" + storageId + ")");
+                break;
+        }
+        InjectedScriptHost.inspect(objectId, hints);
+        return object;
+    },
+
+    /**
+     * This method cannot throw.
+     * @param {*} object
+     * @param {string=} objectGroupName
+     * @param {boolean=} forceValueType
+     * @param {boolean=} generatePreview
+     * @param {?Array.<string>=} columnNames
+     * @return {!RuntimeAgent.RemoteObject}
+     * @suppress {checkTypes}
+     */
+    _wrapObject: function(object, objectGroupName, forceValueType, generatePreview, columnNames)
+    {
+        try {
+            return new InjectedScript.RemoteObject(object, objectGroupName, forceValueType, generatePreview, columnNames);
+        } catch (e) {
+            try {
+                var description = injectedScript._describe(e);
+            } catch (ex) {
+                var description = "<failed to convert exception to string>";
+            }
+            return new InjectedScript.RemoteObject(description);
+        }
+    },
+
+    /**
+     * @param {*} object
+     * @param {string=} objectGroupName
+     * @return {string}
+     */
+    _bind: function(object, objectGroupName)
+    {
+        var id = this._lastBoundObjectId++;
+        this._idToWrappedObject[id] = object;
+        var objectId = "{\"injectedScriptId\":" + injectedScriptId + ",\"id\":" + id + "}";
+        if (objectGroupName) {
+            var group = this._objectGroups[objectGroupName];
+            if (!group) {
+                group = [];
+                this._objectGroups[objectGroupName] = group;
+            }
+            group.push(id);
+            this._idToObjectGroupName[id] = objectGroupName;
+        }
+        return objectId;
+    },
+
+    /**
+     * @param {string} objectId
+     * @return {Object}
+     */
+    _parseObjectId: function(objectId)
+    {
+        return InjectedScriptHost.evaluate("(" + objectId + ")");
+    },
+
+    /**
+     * @param {string} objectGroupName
+     */
+    releaseObjectGroup: function(objectGroupName)
+    {
+        var group = this._objectGroups[objectGroupName];
+        if (!group)
+            return;
+        for (var i = 0; i < group.length; i++)
+            this._releaseObject(group[i]);
+        delete this._objectGroups[objectGroupName];
+    },
+
+    /**
+     * @param {string} methodName
+     * @param {string} args
+     * @return {*}
+     */
+    dispatch: function(methodName, args)
+    {
+        var argsArray = InjectedScriptHost.evaluate("(" + args + ")");
+        var result = this[methodName].apply(this, argsArray);
+        if (typeof result === "undefined") {
+            inspectedWindow.console.error("Web Inspector error: InjectedScript.%s returns undefined", methodName);
+            result = null;
+        }
+        return result;
+    },
+
+    /**
+     * @param {string} objectId
+     * @param {boolean} ownProperties
+     * @return {Array.<RuntimeAgent.PropertyDescriptor>|boolean}
+     */
+    getProperties: function(objectId, ownProperties)
+    {
+        var parsedObjectId = this._parseObjectId(objectId);
+        var object = this._objectForId(parsedObjectId);
+        var objectGroupName = this._idToObjectGroupName[parsedObjectId.id];
+
+        if (!this._isDefined(object))
+            return false;
+        var descriptors = this._propertyDescriptors(object, ownProperties);
+
+        // Go over properties, wrap object values.
+        for (var i = 0; i < descriptors.length; ++i) {
+            var descriptor = descriptors[i];
+            if ("get" in descriptor)
+                descriptor.get = this._wrapObject(descriptor.get, objectGroupName);
+            if ("set" in descriptor)
+                descriptor.set = this._wrapObject(descriptor.set, objectGroupName);
+            if ("value" in descriptor)
+                descriptor.value = this._wrapObject(descriptor.value, objectGroupName);
+            if (!("configurable" in descriptor))
+                descriptor.configurable = false;
+            if (!("enumerable" in descriptor))
+                descriptor.enumerable = false;
+        }
+        return descriptors;
+    },
+
+    /**
+     * @param {string} objectId
+     * @return {Array.<Object>|boolean}
+     */
+    getInternalProperties: function(objectId, ownProperties)
+    {
+        var parsedObjectId = this._parseObjectId(objectId);
+        var object = this._objectForId(parsedObjectId);
+        var objectGroupName = this._idToObjectGroupName[parsedObjectId.id];
+        if (!this._isDefined(object))
+            return false;
+        var descriptors = [];
+        var internalProperties = InjectedScriptHost.getInternalProperties(object);
+        if (internalProperties) {
+            for (var i = 0; i < internalProperties.length; i++) {
+                var property = internalProperties[i];
+                var descriptor = {
+                    name: property.name,
+                    value: this._wrapObject(property.value, objectGroupName)
+                };
+                descriptors.push(descriptor);
+            } 
+        }
+        return descriptors;
+    },
+
+    /**
+     * @param {string} functionId
+     * @return {!DebuggerAgent.FunctionDetails|string}
+     */
+    getFunctionDetails: function(functionId)
+    {
+        var parsedFunctionId = this._parseObjectId(functionId);
+        var func = this._objectForId(parsedFunctionId);
+        if (typeof func !== "function")
+            return "Cannot resolve function by id.";
+        var details = InjectedScriptHost.functionDetails(func);
+        if ("rawScopes" in details) {
+            var objectGroupName = this._idToObjectGroupName[parsedFunctionId.id];
+            var rawScopes = details.rawScopes;
+            var scopes = [];
+            delete details.rawScopes;
+            for (var i = 0; i < rawScopes.length; i++)
+                scopes.push(InjectedScript.CallFrameProxy._createScopeJson(rawScopes[i].type, rawScopes[i].object, objectGroupName));
+            details.scopeChain = scopes;
+        }
+        return details;
+    },
+
+    /**
+     * @param {string} objectId
+     */
+    releaseObject: function(objectId)
+    {
+        var parsedObjectId = this._parseObjectId(objectId);
+        this._releaseObject(parsedObjectId.id);
+    },
+
+    /**
+     * @param {string} id
+     */
+    _releaseObject: function(id)
+    {
+        delete this._idToWrappedObject[id];
+        delete this._idToObjectGroupName[id];
+    },
+
+    /**
+     * @param {Object} object
+     * @param {boolean} ownProperties
+     * @return {Array.<Object>}
+     */
+    _propertyDescriptors: function(object, ownProperties)
+    {
+        var descriptors = [];
+        var nameProcessed = {};
+        nameProcessed["__proto__"] = null;
+        for (var o = object; this._isDefined(o); o = o.__proto__) {
+            var names = Object.getOwnPropertyNames(/** @type {!Object} */ (o));
+            for (var i = 0; i < names.length; ++i) {
+                var name = names[i];
+                if (nameProcessed[name])
+                    continue;
+
+                try {
+                    nameProcessed[name] = true;
+                    var descriptor = Object.getOwnPropertyDescriptor(/** @type {!Object} */ (object), name);
+                    if (!descriptor) {
+                        // Not all bindings provide proper descriptors. Fall back to the writable, configurable property.
+                        try {
+                            descriptor = { name: name, value: object[name], writable: false, configurable: false, enumerable: false};
+                            if (o === object) 
+                                descriptor.isOwn = true;
+                            descriptors.push(descriptor);
+                        } catch (e) {
+                            // Silent catch.
+                        }
+                        continue;
+                    }
+                } catch (e) {
+                    var descriptor = {};
+                    descriptor.value = e;
+                    descriptor.wasThrown = true;
+                }
+
+                descriptor.name = name;
+                if (o === object) 
+                    descriptor.isOwn = true;
+                descriptors.push(descriptor);
+            }
+            if (ownProperties) {
+                if (object.__proto__)
+                    descriptors.push({ name: "__proto__", value: object.__proto__, writable: true, configurable: true, enumerable: false, isOwn: true});
+                break;
+            }
+        }
+        return descriptors;
+    },
+
+    /**
+     * @param {string} expression
+     * @param {string} objectGroup
+     * @param {boolean} injectCommandLineAPI
+     * @param {boolean} returnByValue
+     * @param {boolean} generatePreview
+     * @return {*}
+     */
+    evaluate: function(expression, objectGroup, injectCommandLineAPI, returnByValue, generatePreview)
+    {
+        return this._evaluateAndWrap(InjectedScriptHost.evaluate, InjectedScriptHost, expression, objectGroup, false, injectCommandLineAPI, returnByValue, generatePreview);
+    },
+
+    /**
+     * @param {string} objectId
+     * @param {string} expression
+     * @param {boolean} returnByValue
+     * @return {Object|string}
+     */
+    callFunctionOn: function(objectId, expression, args, returnByValue)
+    {
+        var parsedObjectId = this._parseObjectId(objectId);
+        var object = this._objectForId(parsedObjectId);
+        if (!this._isDefined(object))
+            return "Could not find object with given id";
+
+        if (args) {
+            var resolvedArgs = [];
+            args = InjectedScriptHost.evaluate(args);
+            for (var i = 0; i < args.length; ++i) {
+                var resolvedCallArgument;
+                try {
+                    resolvedCallArgument = this._resolveCallArgument(args[i]);
+                } catch (e) {
+                    return String(e);
+                }
+                resolvedArgs.push(resolvedCallArgument)
+            }
+        }
+
+        try {
+            var objectGroup = this._idToObjectGroupName[parsedObjectId.id];
+            var func = InjectedScriptHost.evaluate("(" + expression + ")");
+            if (typeof func !== "function")
+                return "Given expression does not evaluate to a function";
+
+            return { wasThrown: false,
+                     result: this._wrapObject(func.apply(object, resolvedArgs), objectGroup, returnByValue) };
+        } catch (e) {
+            return this._createThrownValue(e, objectGroup);
+        }
+    },
+    
+    /**
+     * Resolves a value from CallArgument description.
+     * @param {RuntimeAgent.CallArgument} callArgumentJson
+     * @return {*} resolved value
+     * @throws {string} error message
+     */
+    _resolveCallArgument: function(callArgumentJson) {
+        var objectId = callArgumentJson.objectId;
+        if (objectId) {
+            var parsedArgId = this._parseObjectId(objectId);
+            if (!parsedArgId || parsedArgId["injectedScriptId"] !== injectedScriptId)
+                throw "Arguments should belong to the same JavaScript world as the target object.";
+
+            var resolvedArg = this._objectForId(parsedArgId);
+            if (!this._isDefined(resolvedArg))
+                throw "Could not find object with given id";
+
+            return resolvedArg;
+        } else if ("value" in callArgumentJson)
+            return callArgumentJson.value;
+        else
+            return undefined;
+    },
+
+    /**
+     * @param {Function} evalFunction
+     * @param {Object} object
+     * @param {string} objectGroup
+     * @param {boolean} isEvalOnCallFrame
+     * @param {boolean} injectCommandLineAPI
+     * @param {boolean} returnByValue
+     * @param {boolean} generatePreview
+     * @return {*}
+     */
+    _evaluateAndWrap: function(evalFunction, object, expression, objectGroup, isEvalOnCallFrame, injectCommandLineAPI, returnByValue, generatePreview)
+    {
+        try {
+            return { wasThrown: false,
+                     result: this._wrapObject(this._evaluateOn(evalFunction, object, objectGroup, expression, isEvalOnCallFrame, injectCommandLineAPI), objectGroup, returnByValue, generatePreview) };
+        } catch (e) {
+            return this._createThrownValue(e, objectGroup);
+        }
+    },
+
+    /**
+     * @param {*} value
+     * @param {string} objectGroup
+     * @return {Object}
+     */
+    _createThrownValue: function(value, objectGroup)
+    {
+        var remoteObject = this._wrapObject(value, objectGroup);
+        try {
+            remoteObject.description = this._toString(value);
+        } catch (e) {}
+        return { wasThrown: true,
+                 result: remoteObject };
+    },
+
+    /**
+     * @param {Function} evalFunction
+     * @param {Object} object
+     * @param {string} objectGroup
+     * @param {string} expression
+     * @param {boolean} isEvalOnCallFrame
+     * @param {boolean} injectCommandLineAPI
+     * @return {*}
+     */
+    _evaluateOn: function(evalFunction, object, objectGroup, expression, isEvalOnCallFrame, injectCommandLineAPI)
+    {
+        // Only install command line api object for the time of evaluation.
+        // Surround the expression in with statements to inject our command line API so that
+        // the window object properties still take more precedent than our API functions.
+
+        try {
+            if (injectCommandLineAPI && inspectedWindow.console) {
+                inspectedWindow.console._commandLineAPI = new CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null);
+                expression = "with ((window && window.console && window.console._commandLineAPI) || {}) {\n" + expression + "\n}";
+            }
+            var result = evalFunction.call(object, expression);
+            if (objectGroup === "console")
+                this._lastResult = result;
+            return result;
+        } finally {
+            if (injectCommandLineAPI && inspectedWindow.console)
+                delete inspectedWindow.console._commandLineAPI;
+        }
+    },
+
+    /**
+     * @param {Object} callFrame
+     * @return {Array.<InjectedScript.CallFrameProxy>|boolean}
+     */
+    wrapCallFrames: function(callFrame)
+    {
+        if (!callFrame)
+            return false;
+
+        var result = [];
+        var depth = 0;
+        do {
+            result.push(new InjectedScript.CallFrameProxy(depth++, callFrame));
+            callFrame = callFrame.caller;
+        } while (callFrame);
+        return result;
+    },
+
+    /**
+     * @param {Object} topCallFrame
+     * @param {string} callFrameId
+     * @param {string} expression
+     * @param {string} objectGroup
+     * @param {boolean} injectCommandLineAPI
+     * @param {boolean} returnByValue
+     * @param {boolean} generatePreview
+     * @return {*}
+     */
+    evaluateOnCallFrame: function(topCallFrame, callFrameId, expression, objectGroup, injectCommandLineAPI, returnByValue, generatePreview)
+    {
+        var callFrame = this._callFrameForId(topCallFrame, callFrameId);
+        if (!callFrame)
+            return "Could not find call frame with given id";
+        return this._evaluateAndWrap(callFrame.evaluate, callFrame, expression, objectGroup, true, injectCommandLineAPI, returnByValue, generatePreview);
+    },
+
+    /**
+     * @param {Object} topCallFrame
+     * @param {string} callFrameId
+     * @return {*}
+     */
+    restartFrame: function(topCallFrame, callFrameId)
+    {
+        var callFrame = this._callFrameForId(topCallFrame, callFrameId);
+        if (!callFrame)
+            return "Could not find call frame with given id";
+        var result = callFrame.restart();
+        if (result === false)
+            result = "Restart frame is not supported"; 
+        return result;
+    },
+
+    /**
+     * Either callFrameId or functionObjectId must be specified.
+     * @param {Object} topCallFrame
+     * @param {string|boolean} callFrameId or false
+     * @param {string|boolean} functionObjectId or false
+     * @param {number} scopeNumber
+     * @param {string} variableName
+     * @param {string} newValueJsonString RuntimeAgent.CallArgument structure serialized as string 
+     * @return {string|undefined} undefined if success or an error message 
+     */
+    setVariableValue: function(topCallFrame, callFrameId, functionObjectId, scopeNumber, variableName, newValueJsonString)
+    {   
+        var setter;
+        if (typeof callFrameId === "string") {
+            var callFrame = this._callFrameForId(topCallFrame, callFrameId);
+            if (!callFrame)
+                return "Could not find call frame with given id";
+            setter = callFrame.setVariableValue.bind(callFrame);    
+        } else {
+            var parsedFunctionId = this._parseObjectId(/** @type {string} */(functionObjectId));
+            var func = this._objectForId(parsedFunctionId);
+            if (typeof func !== "function")
+                return "Cannot resolve function by id.";
+            setter = InjectedScriptHost.setFunctionVariableValue.bind(InjectedScriptHost, func); 
+        }
+        var newValueJson;
+        try {
+            newValueJson = InjectedScriptHost.evaluate("(" + newValueJsonString + ")");
+        } catch (e) {
+            return "Failed to parse new value JSON " + newValueJsonString + " : " + e;
+        }
+        var resolvedValue;
+        try {
+            resolvedValue = this._resolveCallArgument(newValueJson);
+        } catch (e) {
+            return String(e);
+        }
+        try {
+            setter(scopeNumber, variableName, resolvedValue);
+        } catch (e) {
+            return "Failed to change variable value: " + e;
+        }
+        return undefined;
+    },
+
+    /**
+     * @param {Object} topCallFrame
+     * @param {string} callFrameId
+     * @return {Object}
+     */
+    _callFrameForId: function(topCallFrame, callFrameId)
+    {
+        var parsedCallFrameId = InjectedScriptHost.evaluate("(" + callFrameId + ")");
+        var ordinal = parsedCallFrameId["ordinal"];
+        var callFrame = topCallFrame;
+        while (--ordinal >= 0 && callFrame)
+            callFrame = callFrame.caller;
+        return callFrame;
+    },
+
+    /**
+     * @param {Object} objectId
+     * @return {Object}
+     */
+    _objectForId: function(objectId)
+    {
+        return this._idToWrappedObject[objectId.id];
+    },
+
+    /**
+     * @param {string} objectId
+     * @return {Object}
+     */
+    findObjectById: function(objectId)
+    {
+        var parsedObjectId = this._parseObjectId(objectId);
+        return this._objectForId(parsedObjectId);
+    },
+
+    /**
+     * @param {string} objectId
+     * @return {Node}
+     */
+    nodeForObjectId: function(objectId)
+    {
+        var object = this.findObjectById(objectId);
+        if (!object || this._subtype(object) !== "node")
+            return null;
+        return /** @type {Node} */ (object);
+    },
+
+    /**
+     * @param {string} name
+     * @return {Object}
+     */ 
+    module: function(name)
+    {
+        return this._modules[name];
+    },
+
+    /**
+     * @param {string} name
+     * @param {string} source
+     * @return {Object}
+     */ 
+    injectModule: function(name, source)
+    {
+        delete this._modules[name];
+        var moduleFunction = InjectedScriptHost.evaluate("(" + source + ")");
+        if (typeof moduleFunction !== "function") {
+            inspectedWindow.console.error("Web Inspector error: A function was expected for module %s evaluation", name);
+            return null;
+        }
+        var module = moduleFunction.call(inspectedWindow, InjectedScriptHost, inspectedWindow, injectedScriptId);
+        this._modules[name] = module;
+        return module;
+    },
+
+    /**
+     * @param {*} object
+     * @return {boolean}
+     */
+    _isDefined: function(object)
+    {
+        return !!object || this._isHTMLAllCollection(object);
+    },
+
+    /**
+     * @param {*} object
+     * @return {boolean}
+     */
+    _isHTMLAllCollection: function(object)
+    {
+        // document.all is reported as undefined, but we still want to process it.
+        return (typeof object === "undefined") && InjectedScriptHost.isHTMLAllCollection(object);
+    },
+
+    /**
+     * @param {Object=} obj
+     * @return {string?}
+     */
+    _subtype: function(obj)
+    {
+        if (obj === null)
+            return "null";
+
+        if (this.isPrimitiveValue(obj))
+            return null;
+
+        if (this._isHTMLAllCollection(obj))
+            return "array";
+
+        var preciseType = InjectedScriptHost.type(obj);
+        if (preciseType)
+            return preciseType;
+
+        // FireBug's array detection.
+        try {
+            if (typeof obj.splice === "function" && isFinite(obj.length))
+                return "array";
+            if (Object.prototype.toString.call(obj) === "[object Arguments]" && isFinite(obj.length)) // arguments.
+                return "array";
+        } catch (e) {
+        }
+
+        // If owning frame has navigated to somewhere else window properties will be undefined.
+        return null;
+    },
+
+    /**
+     * @param {*} obj
+     * @return {string?}
+     */
+    _describe: function(obj)
+    {
+        if (this.isPrimitiveValue(obj))
+            return null;
+
+        obj = /** @type {Object} */ (obj);
+
+        // Type is object, get subtype.
+        var subtype = this._subtype(obj);
+
+        if (subtype === "regexp")
+            return this._toString(obj);
+
+        if (subtype === "date")
+            return this._toString(obj);
+
+        if (subtype === "node") {
+            var description = obj.nodeName.toLowerCase();
+            switch (obj.nodeType) {
+            case 1 /* Node.ELEMENT_NODE */:
+                description += obj.id ? "#" + obj.id : "";
+                var className = obj.className;
+                description += className ? "." + className : "";
+                break;
+            case 10 /*Node.DOCUMENT_TYPE_NODE */:
+                description = "<!DOCTYPE " + description + ">";
+                break;
+            }
+            return description;
+        }
+
+        var className = InjectedScriptHost.internalConstructorName(obj);
+        if (subtype === "array") {
+            if (typeof obj.length === "number")
+                className += "[" + obj.length + "]";
+            return className;
+        }
+
+        // NodeList in JSC is a function, check for array prior to this.
+        if (typeof obj === "function")
+            return this._toString(obj);
+
+        if (className === "Object") {
+            // In Chromium DOM wrapper prototypes will have Object as their constructor name,
+            // get the real DOM wrapper name from the constructor property.
+            var constructorName = obj.constructor && obj.constructor.name;
+            if (constructorName)
+                return constructorName;
+        }
+        return className;
+    },
+
+    /**
+     * @param {*} obj
+     * @return {string}
+     */
+    _toString: function(obj)
+    {
+        // We don't use String(obj) because inspectedWindow.String is undefined if owning frame navigated to another page.
+        return "" + obj;
+    }
+}
+
+/**
+ * @type {InjectedScript}
+ * @const
+ */
+var injectedScript = new InjectedScript();
+
+/**
+ * @constructor
+ * @param {*} object
+ * @param {string=} objectGroupName
+ * @param {boolean=} forceValueType
+ * @param {boolean=} generatePreview
+ * @param {?Array.<string>=} columnNames
+ */
+InjectedScript.RemoteObject = function(object, objectGroupName, forceValueType, generatePreview, columnNames)
+{
+    this.type = typeof object;
+    if (injectedScript.isPrimitiveValue(object) || object === null || forceValueType) {
+        // We don't send undefined values over JSON.
+        if (typeof object !== "undefined")
+            this.value = object;
+
+        // Null object is object with 'null' subtype'
+        if (object === null)
+            this.subtype = "null";
+
+        // Provide user-friendly number values.
+        if (typeof object === "number")
+            this.description = object + "";
+        return;
+    }
+
+    object = /** @type {Object} */ (object);
+
+    this.objectId = injectedScript._bind(object, objectGroupName);
+    var subtype = injectedScript._subtype(object);
+    if (subtype)
+        this.subtype = subtype;
+    this.className = InjectedScriptHost.internalConstructorName(object);
+    this.description = injectedScript._describe(object);
+
+    if (generatePreview && (this.type === "object" || injectedScript._isHTMLAllCollection(object)))
+        this.preview = this._generatePreview(object, undefined, columnNames);
+}
+
+InjectedScript.RemoteObject.prototype = {
+    /**
+     * @param {Object} object
+     * @param {Array.<string>=} firstLevelKeys
+     * @param {?Array.<string>=} secondLevelKeys
+     * @return {Object} preview
+     */
+    _generatePreview: function(object, firstLevelKeys, secondLevelKeys)
+    {
+        var preview = {};
+        preview.lossless = true;
+        preview.overflow = false;
+        preview.properties = [];
+
+        var isTableRowsRequest = secondLevelKeys === null || secondLevelKeys;
+        var firstLevelKeysCount = firstLevelKeys ? firstLevelKeys.length : 0;
+
+        var propertiesThreshold = {
+            properties: isTableRowsRequest ? 1000 : Math.max(5, firstLevelKeysCount),
+            indexes: isTableRowsRequest ? 1000 : Math.max(100, firstLevelKeysCount)
+        };
+        for (var o = object; injectedScript._isDefined(o); o = o.__proto__)
+            this._generateProtoPreview(o, preview, propertiesThreshold, firstLevelKeys, secondLevelKeys);
+        return preview;
+    },
+
+    /**
+     * @param {Object} object
+     * @param {Object} preview
+     * @param {Object} propertiesThreshold
+     * @param {Array.<string>=} firstLevelKeys
+     * @param {Array.<string>=} secondLevelKeys
+     */
+    _generateProtoPreview: function(object, preview, propertiesThreshold, firstLevelKeys, secondLevelKeys)
+    {
+        var propertyNames = firstLevelKeys ? firstLevelKeys : Object.keys(/** @type {!Object} */(object));
+        try {
+            for (var i = 0; i < propertyNames.length; ++i) {
+                if (!propertiesThreshold.properties || !propertiesThreshold.indexes) {
+                    preview.overflow = true;
+                    preview.lossless = false;
+                    break;
+                }
+                var name = propertyNames[i];
+                if (this.subtype === "array" && name === "length")
+                    continue;
+
+                var descriptor = Object.getOwnPropertyDescriptor(/** @type {!Object} */(object), name);
+                if (!("value" in descriptor) || !descriptor.enumerable) {
+                    preview.lossless = false;
+                    continue;
+                }
+
+                var value = descriptor.value;
+                if (value === null) {
+                    this._appendPropertyPreview(preview, { name: name, type: "object", value: "null" }, propertiesThreshold);
+                    continue;
+                }
+    
+                const maxLength = 100;
+                var type = typeof value;
+
+                if (InjectedScript.primitiveTypes[type]) {
+                    if (type === "string") {
+                        if (value.length > maxLength) {
+                            value = this._abbreviateString(value, maxLength, true);
+                            preview.lossless = false;
+                        }
+                        value = value.replace(/\n/g, "\u21B5");
+                    }
+                    this._appendPropertyPreview(preview, { name: name, type: type, value: value + "" }, propertiesThreshold);
+                    continue;
+                }
+
+                if (secondLevelKeys === null || secondLevelKeys) {
+                    var subPreview = this._generatePreview(value, secondLevelKeys || undefined);
+                    var property = { name: name, type: type, valuePreview: subPreview };
+                    this._appendPropertyPreview(preview, property, propertiesThreshold);
+                    if (!subPreview.lossless)
+                        preview.lossless = false;
+                    if (subPreview.overflow)
+                        preview.overflow = true;
+                    continue;
+                }
+
+                preview.lossless = false;
+
+                var subtype = injectedScript._subtype(value);
+                var description = "";
+                if (type !== "function")
+                    description = this._abbreviateString(/** @type {string} */ (injectedScript._describe(value)), maxLength, subtype === "regexp");
+
+                var property = { name: name, type: type, value: description };
+                if (subtype)
+                    property.subtype = subtype;
+                this._appendPropertyPreview(preview, property, propertiesThreshold);
+            }
+        } catch (e) {
+        }
+    },
+
+    /**
+     * @param {Object} preview
+     * @param {Object} property
+     * @param {Object} propertiesThreshold
+     */
+    _appendPropertyPreview: function(preview, property, propertiesThreshold)
+    {
+        if (isNaN(property.name))
+            propertiesThreshold.properties--;
+        else
+            propertiesThreshold.indexes--;
+        preview.properties.push(property);
+    },
+
+    /**
+     * @param {string} string
+     * @param {number} maxLength
+     * @param {boolean=} middle
+     * @returns
+     */
+    _abbreviateString: function(string, maxLength, middle)
+    {
+        if (string.length <= maxLength)
+            return string;
+        if (middle) {
+            var leftHalf = maxLength >> 1;
+            var rightHalf = maxLength - leftHalf - 1;
+            return string.substr(0, leftHalf) + "\u2026" + string.substr(string.length - rightHalf, rightHalf);
+        }
+        return string.substr(0, maxLength) + "\u2026";
+    }
+}
+/**
+ * @constructor
+ * @param {number} ordinal
+ * @param {Object} callFrame
+ */
+InjectedScript.CallFrameProxy = function(ordinal, callFrame)
+{
+    this.callFrameId = "{\"ordinal\":" + ordinal + ",\"injectedScriptId\":" + injectedScriptId + "}";
+    this.functionName = (callFrame.type === "function" ? callFrame.functionName : "");
+    this.location = { scriptId: String(callFrame.sourceID), lineNumber: callFrame.line, columnNumber: callFrame.column };
+    this.scopeChain = this._wrapScopeChain(callFrame);
+    this.this = injectedScript._wrapObject(callFrame.thisObject, "backtrace");
+}
+
+InjectedScript.CallFrameProxy.prototype = {
+    /**
+     * @param {Object} callFrame
+     * @return {!Array.<DebuggerAgent.Scope>}
+     */
+    _wrapScopeChain: function(callFrame)
+    {
+        var scopeChain = callFrame.scopeChain;
+        var scopeChainProxy = [];
+        for (var i = 0; i < scopeChain.length; i++) {
+            var scope = InjectedScript.CallFrameProxy._createScopeJson(callFrame.scopeType(i), scopeChain[i], "backtrace");
+            scopeChainProxy.push(scope);
+        }
+        return scopeChainProxy;
+    }
+}
+
+/**
+ * @param {number} scopeTypeCode
+ * @param {*} scopeObject
+ * @param {string} groupId
+ * @return {!DebuggerAgent.Scope}
+ */
+InjectedScript.CallFrameProxy._createScopeJson = function(scopeTypeCode, scopeObject, groupId) {
+    const GLOBAL_SCOPE = 0;
+    const LOCAL_SCOPE = 1;
+    const WITH_SCOPE = 2;
+    const CLOSURE_SCOPE = 3;
+    const CATCH_SCOPE = 4;
+
+    /** @type {!Object.<number, string>} */
+    var scopeTypeNames = {};
+    scopeTypeNames[GLOBAL_SCOPE] = "global";
+    scopeTypeNames[LOCAL_SCOPE] = "local";
+    scopeTypeNames[WITH_SCOPE] = "with";
+    scopeTypeNames[CLOSURE_SCOPE] = "closure";
+    scopeTypeNames[CATCH_SCOPE] = "catch";
+
+    return {
+        object: injectedScript._wrapObject(scopeObject, groupId),
+        type: /** @type {DebuggerAgent.ScopeType} */ (scopeTypeNames[scopeTypeCode])
+    };
+}
+
+/**
+ * @constructor
+ * @param {CommandLineAPIImpl} commandLineAPIImpl
+ * @param {Object} callFrame
+ */
+function CommandLineAPI(commandLineAPIImpl, callFrame)
+{
+    /**
+     * @param {string} member
+     * @return {boolean}
+     */
+    function inScopeVariables(member)
+    {
+        if (!callFrame)
+            return false;
+
+        var scopeChain = callFrame.scopeChain;
+        for (var i = 0; i < scopeChain.length; ++i) {
+            if (member in scopeChain[i])
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * @param {string} name The name of the method for which a toString method should be generated.
+     * @return {function():string}
+     */
+    function customToStringMethod(name)
+    {
+        return function () { return "function " + name + "() { [Command Line API] }"; };
+    }
+
+    for (var i = 0; i < CommandLineAPI.members_.length; ++i) {
+        var member = CommandLineAPI.members_[i];
+        if (member in inspectedWindow || inScopeVariables(member))
+            continue;
+
+        this[member] = bind(commandLineAPIImpl[member], commandLineAPIImpl);
+        this[member].toString = customToStringMethod(member);
+    }
+
+    for (var i = 0; i < 5; ++i) {
+        var member = "$" + i;
+        if (member in inspectedWindow || inScopeVariables(member))
+            continue;
+
+        this.__defineGetter__("$" + i, bind(commandLineAPIImpl._inspectedObject, commandLineAPIImpl, i));
+    }
+
+    this.$_ = injectedScript._lastResult;
+}
+
+// NOTE: Please keep the list of API methods below snchronized to that in WebInspector.RuntimeModel!
+/**
+ * @type {Array.<string>}
+ * @const
+ */
+CommandLineAPI.members_ = [
+    "$", "$$", "$x", "dir", "dirxml", "keys", "values", "profile", "profileEnd",
+    "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear", "getEventListeners", "table"
+];
+
+/**
+ * @constructor
+ */
+function CommandLineAPIImpl()
+{
+}
+
+CommandLineAPIImpl.prototype = {
+    /**
+     * @param {string} selector
+     * @param {Node=} start
+     */
+    $: function (selector, start)
+    {
+        if (this._canQuerySelectorOnNode(start))
+            return start.querySelector(selector);
+
+        return inspectedWindow.document.querySelector(selector);
+    },
+
+    /**
+     * @param {string} selector
+     * @param {Node=} start
+     */
+    $$: function (selector, start)
+    {
+        if (this._canQuerySelectorOnNode(start))
+            return start.querySelectorAll(selector);
+        return inspectedWindow.document.querySelectorAll(selector);
+    },
+
+    /**
+     * @param {Node=} node
+     * @return {boolean}
+     */
+    _canQuerySelectorOnNode: function(node)
+    {
+        return !!node && InjectedScriptHost.type(node) === "node" && (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.DOCUMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE);
+    },
+
+    /**
+     * @param {string} xpath
+     * @param {Node=} context
+     */
+    $x: function(xpath, context)
+    {
+        var doc = (context && context.ownerDocument) || inspectedWindow.document;
+        var result = doc.evaluate(xpath, context || doc, null, XPathResult.ANY_TYPE, null);
+        switch (result.resultType) {
+        case XPathResult.NUMBER_TYPE:
+            return result.numberValue;
+        case XPathResult.STRING_TYPE:
+            return result.stringValue;
+        case XPathResult.BOOLEAN_TYPE:
+            return result.booleanValue;
+        default:
+            var nodes = [];
+            var node;
+            while (node = result.iterateNext())
+                nodes.push(node);
+            return nodes;
+        }
+    },
+
+    dir: function()
+    {
+        return inspectedWindow.console.dir.apply(inspectedWindow.console, arguments)
+    },
+
+    dirxml: function()
+    {
+        return inspectedWindow.console.dirxml.apply(inspectedWindow.console, arguments)
+    },
+
+    keys: function(object)
+    {
+        return Object.keys(object);
+    },
+
+    values: function(object)
+    {
+        var result = [];
+        for (var key in object)
+            result.push(object[key]);
+        return result;
+    },
+
+    profile: function()
+    {
+        return inspectedWindow.console.profile.apply(inspectedWindow.console, arguments)
+    },
+
+    profileEnd: function()
+    {
+        return inspectedWindow.console.profileEnd.apply(inspectedWindow.console, arguments)
+    },
+
+    /**
+     * @param {Object} object
+     * @param {Array.<string>|string=} types
+     */
+    monitorEvents: function(object, types)
+    {
+        if (!object || !object.addEventListener || !object.removeEventListener)
+            return;
+        types = this._normalizeEventTypes(types);
+        for (var i = 0; i < types.length; ++i) {
+            object.removeEventListener(types[i], this._logEvent, false);
+            object.addEventListener(types[i], this._logEvent, false);
+        }
+    },
+
+    /**
+     * @param {Object} object
+     * @param {Array.<string>|string=} types
+     */
+    unmonitorEvents: function(object, types)
+    {
+        if (!object || !object.addEventListener || !object.removeEventListener)
+            return;
+        types = this._normalizeEventTypes(types);
+        for (var i = 0; i < types.length; ++i)
+            object.removeEventListener(types[i], this._logEvent, false);
+    },
+
+    /**
+     * @param {*} object
+     * @return {*}
+     */
+    inspect: function(object)
+    {
+        return injectedScript._inspect(object);
+    },
+
+    copy: function(object)
+    {
+        if (injectedScript._subtype(object) === "node")
+            object = object.outerHTML;
+        InjectedScriptHost.copyText(object);
+    },
+
+    clear: function()
+    {
+        InjectedScriptHost.clearConsoleMessages();
+    },
+
+    /**
+     * @param {Node} node
+     */
+    getEventListeners: function(node)
+    {
+        return InjectedScriptHost.getEventListeners(node);
+    },
+
+    table: function()
+    {
+        inspectedWindow.console.table.apply(inspectedWindow.console, arguments);
+    },
+
+    /**
+     * @param {number} num
+     */
+    _inspectedObject: function(num)
+    {
+        return InjectedScriptHost.inspectedObject(num);
+    },
+
+    /**
+     * @param {Array.<string>|string=} types
+     * @return {Array.<string>}
+     */
+    _normalizeEventTypes: function(types)
+    {
+        if (typeof types === "undefined")
+            types = [ "mouse", "key", "touch", "control", "load", "unload", "abort", "error", "select", "change", "submit", "reset", "focus", "blur", "resize", "scroll", "search", "devicemotion", "deviceorientation" ];
+        else if (typeof types === "string")
+            types = [ types ];
+
+        var result = [];
+        for (var i = 0; i < types.length; i++) {
+            if (types[i] === "mouse")
+                result.splice(0, 0, "mousedown", "mouseup", "click", "dblclick", "mousemove", "mouseover", "mouseout", "mousewheel");
+            else if (types[i] === "key")
+                result.splice(0, 0, "keydown", "keyup", "keypress", "textInput");
+            else if (types[i] === "touch")
+                result.splice(0, 0, "touchstart", "touchmove", "touchend", "touchcancel");
+            else if (types[i] === "control")
+                result.splice(0, 0, "resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset");
+            else
+                result.push(types[i]);
+        }
+        return result;
+    },
+
+    /**
+     * @param {Event} event
+     */
+    _logEvent: function(event)
+    {
+        inspectedWindow.console.log(event.type, event);
+    }
+}
+
+injectedScript._commandLineAPIImpl = new CommandLineAPIImpl();
+return injectedScript;
+})
diff --git a/Source/core/inspector/InspectorAgent.cpp b/Source/core/inspector/InspectorAgent.cpp
new file mode 100644
index 0000000..b60f7d6
--- /dev/null
+++ b/Source/core/inspector/InspectorAgent.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2011 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorAgent.h"
+
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptController.h"
+#include "bindings/v8/ScriptFunctionCall.h"
+#include "bindings/v8/ScriptObject.h"
+#include "core/dom/Document.h"
+#include "core/inspector/InjectedScriptHost.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/InspectorController.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/loader/DocumentLoader.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/page/SecurityOrigin.h"
+#include "core/page/Settings.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/network/ResourceRequest.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+using namespace std;
+
+namespace WebCore {
+
+namespace InspectorAgentState {
+static const char inspectorAgentEnabled[] = "inspectorAgentEnabled";
+}
+
+InspectorAgent::InspectorAgent(Page* page, InjectedScriptManager* injectedScriptManager, InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state)
+    : InspectorBaseAgent<InspectorAgent>("Inspector", instrumentingAgents, state)
+    , m_inspectedPage(page)
+    , m_frontend(0)
+    , m_injectedScriptManager(injectedScriptManager)
+{
+    ASSERT_ARG(page, page);
+    m_instrumentingAgents->setInspectorAgent(this);
+}
+
+InspectorAgent::~InspectorAgent()
+{
+    m_instrumentingAgents->setInspectorAgent(0);
+}
+
+void InspectorAgent::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld* world)
+{
+    if (world != mainThreadNormalWorld())
+        return;
+
+    if (m_injectedScriptForOrigin.isEmpty())
+        return;
+
+    String origin = frame->document()->securityOrigin()->toRawString();
+    String script = m_injectedScriptForOrigin.get(origin);
+    if (script.isEmpty())
+        return;
+    int injectedScriptId = m_injectedScriptManager->injectedScriptIdFor(mainWorldScriptState(frame));
+    StringBuilder scriptSource;
+    scriptSource.append(script);
+    scriptSource.append("(");
+    scriptSource.appendNumber(injectedScriptId);
+    scriptSource.append(")");
+    frame->script()->executeScript(scriptSource.toString());
+}
+
+void InspectorAgent::setFrontend(InspectorFrontend* inspectorFrontend)
+{
+    m_frontend = inspectorFrontend;
+}
+
+void InspectorAgent::clearFrontend()
+{
+    m_pendingEvaluateTestCommands.clear();
+    m_frontend = 0;
+    m_injectedScriptManager->discardInjectedScripts();
+    ErrorString error;
+    disable(&error);
+}
+
+void InspectorAgent::didCommitLoad()
+{
+    m_injectedScriptManager->discardInjectedScripts();
+}
+
+void InspectorAgent::enable(ErrorString*)
+{
+    m_state->setBoolean(InspectorAgentState::inspectorAgentEnabled, true);
+
+    if (m_pendingInspectData.first)
+        inspect(m_pendingInspectData.first, m_pendingInspectData.second);
+
+    for (Vector<pair<long, String> >::iterator it = m_pendingEvaluateTestCommands.begin(); m_frontend && it != m_pendingEvaluateTestCommands.end(); ++it)
+        m_frontend->inspector()->evaluateForTestInFrontend(static_cast<int>((*it).first), (*it).second);
+    m_pendingEvaluateTestCommands.clear();
+}
+
+void InspectorAgent::disable(ErrorString*)
+{
+    m_state->setBoolean(InspectorAgentState::inspectorAgentEnabled, false);
+}
+
+void InspectorAgent::domContentLoadedEventFired()
+{
+    m_injectedScriptManager->injectedScriptHost()->clearInspectedObjects();
+}
+
+bool InspectorAgent::isMainResourceLoader(DocumentLoader* loader, const KURL& requestUrl)
+{
+    return loader->frame() == m_inspectedPage->mainFrame() && requestUrl == loader->requestURL();
+}
+
+void InspectorAgent::evaluateForTestInFrontend(long callId, const String& script)
+{
+    if (m_state->getBoolean(InspectorAgentState::inspectorAgentEnabled))
+        m_frontend->inspector()->evaluateForTestInFrontend(static_cast<int>(callId), script);
+    else
+        m_pendingEvaluateTestCommands.append(pair<long, String>(callId, script));
+}
+
+void InspectorAgent::setInjectedScriptForOrigin(const String& origin, const String& source)
+{
+    m_injectedScriptForOrigin.set(origin, source);
+}
+
+void InspectorAgent::inspect(PassRefPtr<TypeBuilder::Runtime::RemoteObject> objectToInspect, PassRefPtr<InspectorObject> hints)
+{
+    if (m_state->getBoolean(InspectorAgentState::inspectorAgentEnabled) && m_frontend) {
+        m_frontend->inspector()->inspect(objectToInspect, hints);
+        m_pendingInspectData.first = 0;
+        m_pendingInspectData.second = 0;
+        return;
+    }
+    m_pendingInspectData.first = objectToInspect;
+    m_pendingInspectData.second = hints;
+}
+
+KURL InspectorAgent::inspectedURL() const
+{
+    return m_inspectedPage->mainFrame()->document()->url();
+}
+
+KURL InspectorAgent::inspectedURLWithoutFragment() const
+{
+    KURL url = inspectedURL();
+    url.removeFragmentIdentifier();
+    return url;
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorAgent.h b/Source/core/inspector/InspectorAgent.h
new file mode 100644
index 0000000..137474a
--- /dev/null
+++ b/Source/core/inspector/InspectorAgent.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef InspectorAgent_h
+#define InspectorAgent_h
+
+#include "core/inspector/InspectorBaseAgent.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class DOMWrapperWorld;
+class DocumentLoader;
+class Frame;
+class InjectedScriptManager;
+class InspectorFrontend;
+class InspectorObject;
+class InstrumentingAgents;
+class KURL;
+class Page;
+
+typedef String ErrorString;
+
+class InspectorAgent : public InspectorBaseAgent<InspectorAgent>, public InspectorBackendDispatcher::InspectorCommandHandler {
+    WTF_MAKE_NONCOPYABLE(InspectorAgent);
+public:
+    static PassOwnPtr<InspectorAgent> create(Page* page, InjectedScriptManager* injectedScriptManager, InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state)
+    {
+        return adoptPtr(new InspectorAgent(page, injectedScriptManager, instrumentingAgents, state));
+    }
+
+    virtual ~InspectorAgent();
+
+    // Inspector front-end API.
+    void enable(ErrorString*);
+    void disable(ErrorString*);
+
+    KURL inspectedURL() const;
+    KURL inspectedURLWithoutFragment() const;
+
+    InspectorFrontend* frontend() const { return m_frontend; }
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+
+    void didClearWindowObjectInWorld(Frame*, DOMWrapperWorld*);
+
+    void didCommitLoad();
+    void domContentLoadedEventFired();
+
+    bool hasFrontend() const { return m_frontend; }
+
+    // Generic code called from custom implementations.
+    void evaluateForTestInFrontend(long testCallId, const String& script);
+
+    void setInjectedScriptForOrigin(const String& origin, const String& source);
+
+    void inspect(PassRefPtr<TypeBuilder::Runtime::RemoteObject> objectToInspect, PassRefPtr<InspectorObject> hints);
+
+private:
+    InspectorAgent(Page*, InjectedScriptManager*, InstrumentingAgents*, InspectorCompositeState*);
+
+    void unbindAllResources();
+
+    void toggleRecordButton(bool);
+
+    bool isMainResourceLoader(DocumentLoader*, const KURL& requestUrl);
+
+    Page* m_inspectedPage;
+    InspectorFrontend* m_frontend;
+    InjectedScriptManager* m_injectedScriptManager;
+
+    Vector<pair<long, String> > m_pendingEvaluateTestCommands;
+    pair<RefPtr<TypeBuilder::Runtime::RemoteObject>, RefPtr<InspectorObject> > m_pendingInspectData;
+    typedef HashMap<String, String> InjectedScriptForOriginMap;
+    InjectedScriptForOriginMap m_injectedScriptForOrigin;
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorAgent_h)
diff --git a/Source/core/inspector/InspectorApplicationCacheAgent.cpp b/Source/core/inspector/InspectorApplicationCacheAgent.cpp
new file mode 100644
index 0000000..8bf09bf
--- /dev/null
+++ b/Source/core/inspector/InspectorApplicationCacheAgent.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 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:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorApplicationCacheAgent.h"
+
+#include "InspectorFrontend.h"
+#include "core/inspector/InspectorAgent.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/loader/DocumentLoader.h"
+#include "core/loader/FrameLoader.h"
+#include "core/loader/appcache/ApplicationCacheHost.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/network/NetworkStateNotifier.h"
+#include "core/platform/network/ResourceResponse.h"
+
+namespace WebCore {
+
+namespace ApplicationCacheAgentState {
+static const char applicationCacheAgentEnabled[] = "applicationCacheAgentEnabled";
+}
+
+InspectorApplicationCacheAgent::InspectorApplicationCacheAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InspectorPageAgent* pageAgent)
+    : InspectorBaseAgent<InspectorApplicationCacheAgent>("ApplicationCache", instrumentingAgents, state)
+    , m_pageAgent(pageAgent)
+    , m_frontend(0)
+{
+}
+
+void InspectorApplicationCacheAgent::setFrontend(InspectorFrontend* frontend)
+{
+    m_frontend = frontend->applicationcache();
+}
+
+void InspectorApplicationCacheAgent::clearFrontend()
+{
+    m_instrumentingAgents->setInspectorApplicationCacheAgent(0);
+    m_frontend = 0;
+}
+
+void InspectorApplicationCacheAgent::restore()
+{
+    if (m_state->getBoolean(ApplicationCacheAgentState::applicationCacheAgentEnabled)) {
+        ErrorString error;
+        enable(&error);
+    }
+}
+
+void InspectorApplicationCacheAgent::enable(ErrorString*)
+{
+    m_state->setBoolean(ApplicationCacheAgentState::applicationCacheAgentEnabled, true);
+    m_instrumentingAgents->setInspectorApplicationCacheAgent(this);
+
+    // We need to pass initial navigator.onOnline.
+    networkStateChanged();
+}
+
+void InspectorApplicationCacheAgent::updateApplicationCacheStatus(Frame* frame)
+{
+    DocumentLoader* documentLoader = frame->loader()->documentLoader();
+    if (!documentLoader)
+        return;
+
+    ApplicationCacheHost* host = documentLoader->applicationCacheHost();
+    ApplicationCacheHost::Status status = host->status();
+    ApplicationCacheHost::CacheInfo info = host->applicationCacheInfo();
+
+    String manifestURL = info.m_manifest.string();
+    m_frontend->applicationCacheStatusUpdated(m_pageAgent->frameId(frame), manifestURL, static_cast<int>(status));
+}
+
+void InspectorApplicationCacheAgent::networkStateChanged()
+{
+    bool isNowOnline = networkStateNotifier().onLine();
+    m_frontend->networkStateUpdated(isNowOnline);
+}
+
+void InspectorApplicationCacheAgent::getFramesWithManifests(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::ApplicationCache::FrameWithManifest> >& result)
+{
+    result = TypeBuilder::Array<TypeBuilder::ApplicationCache::FrameWithManifest>::create();
+
+    Frame* mainFrame = m_pageAgent->mainFrame();
+    for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext(mainFrame)) {
+        DocumentLoader* documentLoader = frame->loader()->documentLoader();
+        if (!documentLoader)
+            continue;
+
+        ApplicationCacheHost* host = documentLoader->applicationCacheHost();
+        ApplicationCacheHost::CacheInfo info = host->applicationCacheInfo();
+        String manifestURL = info.m_manifest.string();
+        if (!manifestURL.isEmpty()) {
+            RefPtr<TypeBuilder::ApplicationCache::FrameWithManifest> value = TypeBuilder::ApplicationCache::FrameWithManifest::create()
+                .setFrameId(m_pageAgent->frameId(frame))
+                .setManifestURL(manifestURL)
+                .setStatus(static_cast<int>(host->status()));
+            result->addItem(value);
+        }
+    }
+}
+
+DocumentLoader* InspectorApplicationCacheAgent::assertFrameWithDocumentLoader(ErrorString* errorString, String frameId)
+{
+    Frame* frame = m_pageAgent->assertFrame(errorString, frameId);
+    if (!frame)
+        return 0;
+
+    return InspectorPageAgent::assertDocumentLoader(errorString, frame);
+}
+
+void InspectorApplicationCacheAgent::getManifestForFrame(ErrorString* errorString, const String& frameId, String* manifestURL)
+{
+    DocumentLoader* documentLoader = assertFrameWithDocumentLoader(errorString, frameId);
+    if (!documentLoader)
+        return;
+
+    ApplicationCacheHost::CacheInfo info = documentLoader->applicationCacheHost()->applicationCacheInfo();
+    *manifestURL = info.m_manifest.string();
+}
+
+void InspectorApplicationCacheAgent::getApplicationCacheForFrame(ErrorString* errorString, const String& frameId, RefPtr<TypeBuilder::ApplicationCache::ApplicationCache>& applicationCache)
+{
+    DocumentLoader* documentLoader = assertFrameWithDocumentLoader(errorString, frameId);
+    if (!documentLoader)
+        return;
+
+    ApplicationCacheHost* host = documentLoader->applicationCacheHost();
+    ApplicationCacheHost::CacheInfo info = host->applicationCacheInfo();
+
+    ApplicationCacheHost::ResourceInfoList resources;
+    host->fillResourceList(&resources);
+
+    applicationCache = buildObjectForApplicationCache(resources, info);
+}
+
+PassRefPtr<TypeBuilder::ApplicationCache::ApplicationCache> InspectorApplicationCacheAgent::buildObjectForApplicationCache(const ApplicationCacheHost::ResourceInfoList& applicationCacheResources, const ApplicationCacheHost::CacheInfo& applicationCacheInfo)
+{
+    return TypeBuilder::ApplicationCache::ApplicationCache::create()
+        .setManifestURL(applicationCacheInfo.m_manifest.string())
+        .setSize(applicationCacheInfo.m_size)
+        .setCreationTime(applicationCacheInfo.m_creationTime)
+        .setUpdateTime(applicationCacheInfo.m_updateTime)
+        .setResources(buildArrayForApplicationCacheResources(applicationCacheResources))
+        .release();
+}
+
+PassRefPtr<TypeBuilder::Array<TypeBuilder::ApplicationCache::ApplicationCacheResource> > InspectorApplicationCacheAgent::buildArrayForApplicationCacheResources(const ApplicationCacheHost::ResourceInfoList& applicationCacheResources)
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::ApplicationCache::ApplicationCacheResource> > resources = TypeBuilder::Array<TypeBuilder::ApplicationCache::ApplicationCacheResource>::create();
+
+    ApplicationCacheHost::ResourceInfoList::const_iterator end = applicationCacheResources.end();
+    ApplicationCacheHost::ResourceInfoList::const_iterator it = applicationCacheResources.begin();
+    for (int i = 0; it != end; ++it, i++)
+        resources->addItem(buildObjectForApplicationCacheResource(*it));
+
+    return resources;
+}
+
+PassRefPtr<TypeBuilder::ApplicationCache::ApplicationCacheResource> InspectorApplicationCacheAgent::buildObjectForApplicationCacheResource(const ApplicationCacheHost::ResourceInfo& resourceInfo)
+{
+    String types;
+    if (resourceInfo.m_isMaster)
+        types.append("Master ");
+
+    if (resourceInfo.m_isManifest)
+        types.append("Manifest ");
+
+    if (resourceInfo.m_isFallback)
+        types.append("Fallback ");
+
+    if (resourceInfo.m_isForeign)
+        types.append("Foreign ");
+
+    if (resourceInfo.m_isExplicit)
+        types.append("Explicit ");
+
+    RefPtr<TypeBuilder::ApplicationCache::ApplicationCacheResource> value = TypeBuilder::ApplicationCache::ApplicationCacheResource::create()
+        .setUrl(resourceInfo.m_resource.string())
+        .setSize(static_cast<int>(resourceInfo.m_size))
+        .setType(types);
+    return value;
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorApplicationCacheAgent.h b/Source/core/inspector/InspectorApplicationCacheAgent.h
new file mode 100644
index 0000000..142e752
--- /dev/null
+++ b/Source/core/inspector/InspectorApplicationCacheAgent.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 Apple 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:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#ifndef InspectorApplicationCacheAgent_h
+#define InspectorApplicationCacheAgent_h
+
+
+#include "InspectorFrontend.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include "core/loader/appcache/ApplicationCacheHost.h"
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class Frame;
+class InspectorArray;
+class InspectorAgent;
+class InspectorFrontend;
+class InspectorObject;
+class InspectorPageAgent;
+class InspectorValue;
+class InspectorState;
+class InstrumentingAgents;
+class Page;
+class ResourceResponse;
+
+typedef String ErrorString;
+
+class InspectorApplicationCacheAgent : public InspectorBaseAgent<InspectorApplicationCacheAgent>, public InspectorBackendDispatcher::ApplicationCacheCommandHandler {
+    WTF_MAKE_NONCOPYABLE(InspectorApplicationCacheAgent); WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<InspectorApplicationCacheAgent> create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InspectorPageAgent* pageAgent)
+    {
+        return adoptPtr(new InspectorApplicationCacheAgent(instrumentingAgents, state, pageAgent));
+    }
+    ~InspectorApplicationCacheAgent() { }
+
+    // InspectorBaseAgent
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void restore();
+
+    // InspectorInstrumentation API
+    void updateApplicationCacheStatus(Frame*);
+    void networkStateChanged();
+
+    // ApplicationCache API for InspectorFrontend
+    virtual void enable(ErrorString*);
+    virtual void getFramesWithManifests(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::ApplicationCache::FrameWithManifest> >& result);
+    virtual void getManifestForFrame(ErrorString*, const String& frameId, String* manifestURL);
+    virtual void getApplicationCacheForFrame(ErrorString*, const String& frameId, RefPtr<TypeBuilder::ApplicationCache::ApplicationCache>&);
+
+private:
+    InspectorApplicationCacheAgent(InstrumentingAgents*, InspectorCompositeState*, InspectorPageAgent*);
+    PassRefPtr<TypeBuilder::ApplicationCache::ApplicationCache> buildObjectForApplicationCache(const ApplicationCacheHost::ResourceInfoList&, const ApplicationCacheHost::CacheInfo&);
+    PassRefPtr<TypeBuilder::Array<TypeBuilder::ApplicationCache::ApplicationCacheResource> > buildArrayForApplicationCacheResources(const ApplicationCacheHost::ResourceInfoList&);
+    PassRefPtr<TypeBuilder::ApplicationCache::ApplicationCacheResource> buildObjectForApplicationCacheResource(const ApplicationCacheHost::ResourceInfo&);
+
+    DocumentLoader* assertFrameWithDocumentLoader(ErrorString*, String frameId);
+
+    InspectorPageAgent* m_pageAgent;
+    InspectorFrontend::ApplicationCache* m_frontend;
+};
+
+} // namespace WebCore
+
+#endif // InspectorApplicationCacheAgent_h
diff --git a/Source/core/inspector/InspectorBaseAgent.cpp b/Source/core/inspector/InspectorBaseAgent.cpp
new file mode 100644
index 0000000..950e422
--- /dev/null
+++ b/Source/core/inspector/InspectorBaseAgent.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorBaseAgent.h"
+
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/inspector/InspectorState.h"
+
+namespace WebCore {
+
+InspectorBaseAgentInterface::InspectorBaseAgentInterface(const String& name, InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState)
+    : m_instrumentingAgents(instrumentingAgents)
+    , m_state(inspectorState->createAgentState(name))
+    , m_name(name)
+{
+}
+
+InspectorBaseAgentInterface::~InspectorBaseAgentInterface()
+{
+}
+
+void InspectorBaseAgentInterface::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Inspector);
+    info.addMember(m_name, "name");
+    info.addWeakPointer(m_instrumentingAgents);
+    info.addWeakPointer(m_state);
+}
+
+void InspectorAgentRegistry::append(PassOwnPtr<InspectorBaseAgentInterface> agent)
+{
+    m_agents.append(agent);
+}
+
+void InspectorAgentRegistry::setFrontend(InspectorFrontend* frontend)
+{
+    for (size_t i = 0; i < m_agents.size(); i++)
+        m_agents[i]->setFrontend(frontend);
+}
+
+void InspectorAgentRegistry::clearFrontend()
+{
+    for (size_t i = 0; i < m_agents.size(); i++)
+        m_agents[i]->clearFrontend();
+}
+
+void InspectorAgentRegistry::restore()
+{
+    for (size_t i = 0; i < m_agents.size(); i++)
+        m_agents[i]->restore();
+}
+
+void InspectorAgentRegistry::registerInDispatcher(InspectorBackendDispatcher* dispatcher)
+{
+    for (size_t i = 0; i < m_agents.size(); i++)
+        m_agents[i]->registerInDispatcher(dispatcher);
+}
+
+void InspectorAgentRegistry::discardAgents()
+{
+    for (size_t i = 0; i < m_agents.size(); i++)
+        m_agents[i]->discardAgent();
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorBaseAgent.h b/Source/core/inspector/InspectorBaseAgent.h
new file mode 100644
index 0000000..75bd7b4
--- /dev/null
+++ b/Source/core/inspector/InspectorBaseAgent.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef InspectorBaseAgent_h
+#define InspectorBaseAgent_h
+
+#include "InspectorBackendDispatcher.h"
+#include <wtf/Forward.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class InspectorFrontend;
+class InspectorCompositeState;
+class InspectorState;
+class InstrumentingAgents;
+
+class InspectorBaseAgentInterface {
+public:
+    InspectorBaseAgentInterface(const String&, InstrumentingAgents*, InspectorCompositeState*);
+    virtual ~InspectorBaseAgentInterface();
+
+    virtual void setFrontend(InspectorFrontend*) { }
+    virtual void clearFrontend() { }
+    virtual void restore() { }
+    virtual void registerInDispatcher(InspectorBackendDispatcher*) = 0;
+    virtual void discardAgent() { }
+
+    String name() { return m_name; }
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
+protected:
+    InstrumentingAgents* m_instrumentingAgents;
+    InspectorState* m_state;
+
+private:
+    String m_name;
+};
+
+class InspectorAgentRegistry {
+public:
+    void append(PassOwnPtr<InspectorBaseAgentInterface>);
+
+    void setFrontend(InspectorFrontend*);
+    void clearFrontend();
+    void restore();
+    void registerInDispatcher(InspectorBackendDispatcher*);
+    void discardAgents();
+
+private:
+    Vector<OwnPtr<InspectorBaseAgentInterface> > m_agents;
+};
+
+template<typename T>
+class InspectorBaseAgent : public InspectorBaseAgentInterface {
+public:
+    virtual ~InspectorBaseAgent() { }
+
+    virtual void registerInDispatcher(InspectorBackendDispatcher* dispatcher)
+    {
+        dispatcher->registerAgent(static_cast<T*>(this));
+    }
+
+protected:
+    InspectorBaseAgent(const String& name, InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState)
+        : InspectorBaseAgentInterface(name, instrumentingAgents, inspectorState)
+    {
+    }
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorBaseAgent_h)
diff --git a/Source/core/inspector/InspectorCSSAgent.cpp b/Source/core/inspector/InspectorCSSAgent.cpp
new file mode 100644
index 0000000..5a9a191
--- /dev/null
+++ b/Source/core/inspector/InspectorCSSAgent.cpp
@@ -0,0 +1,1473 @@
+/*
+ * Copyright (C) 2010, 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:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorCSSAgent.h"
+
+#include "CSSPropertyNames.h"
+#include "InspectorTypeBuilder.h"
+#include "core/css/CSSComputedStyleDeclaration.h"
+#include "core/css/CSSImportRule.h"
+#include "core/css/CSSPropertySourceData.h"
+#include "core/css/CSSRule.h"
+#include "core/css/CSSRuleList.h"
+#include "core/css/CSSStyleRule.h"
+#include "core/css/CSSStyleSheet.h"
+#include "core/css/StylePropertySet.h"
+#include "core/css/StylePropertyShorthand.h"
+#include "core/css/StyleResolver.h"
+#include "core/css/StyleRule.h"
+#include "core/css/StyleSheet.h"
+#include "core/css/StyleSheetList.h"
+#include "core/dom/ExceptionCodePlaceholder.h"
+#include "core/dom/NamedFlow.h"
+#include "core/dom/NamedFlowCollection.h"
+#include "core/dom/Node.h"
+#include "core/dom/NodeList.h"
+#include "core/html/HTMLHeadElement.h"
+#include "core/html/HTMLStyleElement.h"
+#include "core/inspector/InspectorDOMAgent.h"
+#include "core/inspector/InspectorHistory.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/page/ContentSecurityPolicy.h"
+#include "core/page/DOMWindow.h"
+#include "core/rendering/RenderRegion.h"
+#include "core/svg/SVGStyleElement.h"
+
+#include <wtf/CurrentTime.h>
+#include <wtf/HashSet.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
+#include <wtf/Vector.h>
+
+namespace CSSAgentState {
+static const char cssAgentEnabled[] = "cssAgentEnabled";
+static const char isSelectorProfiling[] = "isSelectorProfiling";
+}
+
+namespace WebCore {
+
+enum ForcePseudoClassFlags {
+    PseudoNone = 0,
+    PseudoHover = 1 << 0,
+    PseudoFocus = 1 << 1,
+    PseudoActive = 1 << 2,
+    PseudoVisited = 1 << 3
+};
+
+struct RuleMatchData {
+    String selector;
+    String url;
+    unsigned lineNumber;
+    double startTime;
+};
+
+struct RuleMatchingStats {
+    RuleMatchingStats()
+        : lineNumber(0), totalTime(0.0), hits(0), matches(0)
+    {
+    }
+    RuleMatchingStats(const RuleMatchData& data, double totalTime, unsigned hits, unsigned matches)
+        : selector(data.selector), url(data.url), lineNumber(data.lineNumber), totalTime(totalTime), hits(hits), matches(matches)
+    {
+    }
+
+    String selector;
+    String url;
+    unsigned lineNumber;
+    double totalTime;
+    unsigned hits;
+    unsigned matches;
+};
+
+class SelectorProfile {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    SelectorProfile()
+        : m_totalMatchingTimeMs(0.0)
+    {
+    }
+    virtual ~SelectorProfile()
+    {
+    }
+
+    double totalMatchingTimeMs() const { return m_totalMatchingTimeMs; }
+
+    String makeKey();
+    void startSelector(const CSSStyleRule*);
+    void commitSelector(bool);
+    void commitSelectorTime();
+    PassRefPtr<TypeBuilder::CSS::SelectorProfile> toInspectorObject() const;
+
+private:
+
+    // Key is "selector?url:line".
+    typedef HashMap<String, RuleMatchingStats> RuleMatchingStatsMap;
+
+    double m_totalMatchingTimeMs;
+    RuleMatchingStatsMap m_ruleMatchingStats;
+    RuleMatchData m_currentMatchData;
+};
+
+class StyleSheetAppender {
+public:
+    StyleSheetAppender(CSSStyleSheetToInspectorStyleSheet& cssStyleSheetToInspectorStyleSheet, Vector<CSSStyleSheet*>& result)
+        : m_cssStyleSheetToInspectorStyleSheet(cssStyleSheetToInspectorStyleSheet)
+        , m_result(result) { }
+
+    void run(CSSStyleSheet* styleSheet)
+    {
+        RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_cssStyleSheetToInspectorStyleSheet.get(static_cast<CSSStyleSheet*>(styleSheet));
+        // Avoid creating m_childRuleCSSOMWrappers in the stylesheet if it is in the process of re-parsing.
+        // Otherwise m_childRuleCSSOMWrappers size will be initialized only for a part of rules, resulting in an ASSERT failure in CSSStyleSheet::item().
+        // Instead, wait for the RuleMutationScope destruction and handle the complete CSSStyleSheet.
+        if (inspectorStyleSheet && inspectorStyleSheet->isReparsing())
+            return;
+        m_result.append(styleSheet);
+        for (unsigned i = 0, size = styleSheet->length(); i < size; ++i) {
+            CSSRule* rule = styleSheet->item(i);
+            if (rule->type() == CSSRule::IMPORT_RULE) {
+                CSSStyleSheet* importedStyleSheet = static_cast<CSSImportRule*>(rule)->styleSheet();
+                if (importedStyleSheet)
+                    run(importedStyleSheet);
+            }
+        }
+    }
+
+private:
+    CSSStyleSheetToInspectorStyleSheet& m_cssStyleSheetToInspectorStyleSheet;
+    Vector<CSSStyleSheet*>& m_result;
+};
+
+static unsigned computePseudoClassMask(InspectorArray* pseudoClassArray)
+{
+    DEFINE_STATIC_LOCAL(String, active, (ASCIILiteral("active")));
+    DEFINE_STATIC_LOCAL(String, hover, (ASCIILiteral("hover")));
+    DEFINE_STATIC_LOCAL(String, focus, (ASCIILiteral("focus")));
+    DEFINE_STATIC_LOCAL(String, visited, (ASCIILiteral("visited")));
+    if (!pseudoClassArray || !pseudoClassArray->length())
+        return PseudoNone;
+
+    unsigned result = PseudoNone;
+    for (size_t i = 0; i < pseudoClassArray->length(); ++i) {
+        RefPtr<InspectorValue> pseudoClassValue = pseudoClassArray->get(i);
+        String pseudoClass;
+        bool success = pseudoClassValue->asString(&pseudoClass);
+        if (!success)
+            continue;
+        if (pseudoClass == active)
+            result |= PseudoActive;
+        else if (pseudoClass == hover)
+            result |= PseudoHover;
+        else if (pseudoClass == focus)
+            result |= PseudoFocus;
+        else if (pseudoClass == visited)
+            result |= PseudoVisited;
+    }
+
+    return result;
+}
+
+inline String SelectorProfile::makeKey()
+{
+    return makeString(m_currentMatchData.selector, "?", m_currentMatchData.url, ":", String::number(m_currentMatchData.lineNumber));
+}
+
+inline void SelectorProfile::startSelector(const CSSStyleRule* rule)
+{
+    m_currentMatchData.selector = rule->selectorText();
+    CSSStyleSheet* styleSheet = rule->parentStyleSheet();
+    String url = emptyString();
+    if (styleSheet) {
+        url = InspectorStyleSheet::styleSheetURL(styleSheet);
+        if (url.isEmpty())
+            url = InspectorDOMAgent::documentURLString(styleSheet->ownerDocument());
+    }
+    m_currentMatchData.url = url;
+    m_currentMatchData.lineNumber = rule->styleRule()->sourceLine();
+    m_currentMatchData.startTime = WTF::currentTimeMS();
+}
+
+inline void SelectorProfile::commitSelector(bool matched)
+{
+    double matchTimeMs = WTF::currentTimeMS() - m_currentMatchData.startTime;
+    m_totalMatchingTimeMs += matchTimeMs;
+
+    RuleMatchingStatsMap::AddResult result = m_ruleMatchingStats.add(makeKey(), RuleMatchingStats(m_currentMatchData, matchTimeMs, 1, matched ? 1 : 0));
+    if (!result.isNewEntry) {
+        result.iterator->value.totalTime += matchTimeMs;
+        result.iterator->value.hits += 1;
+        if (matched)
+            result.iterator->value.matches += 1;
+    }
+}
+
+inline void SelectorProfile::commitSelectorTime()
+{
+    double processingTimeMs = WTF::currentTimeMS() - m_currentMatchData.startTime;
+    m_totalMatchingTimeMs += processingTimeMs;
+
+    RuleMatchingStatsMap::iterator it = m_ruleMatchingStats.find(makeKey());
+    if (it == m_ruleMatchingStats.end())
+        return;
+
+    it->value.totalTime += processingTimeMs;
+}
+
+PassRefPtr<TypeBuilder::CSS::SelectorProfile> SelectorProfile::toInspectorObject() const
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::CSS::SelectorProfileEntry> > selectorProfileData = TypeBuilder::Array<TypeBuilder::CSS::SelectorProfileEntry>::create();
+    for (RuleMatchingStatsMap::const_iterator it = m_ruleMatchingStats.begin(); it != m_ruleMatchingStats.end(); ++it) {
+        RefPtr<TypeBuilder::CSS::SelectorProfileEntry> entry = TypeBuilder::CSS::SelectorProfileEntry::create()
+            .setSelector(it->value.selector)
+            .setUrl(it->value.url)
+            .setLineNumber(it->value.lineNumber)
+            .setTime(it->value.totalTime)
+            .setHitCount(it->value.hits)
+            .setMatchCount(it->value.matches);
+        selectorProfileData->addItem(entry.release());
+    }
+
+    RefPtr<TypeBuilder::CSS::SelectorProfile> result = TypeBuilder::CSS::SelectorProfile::create()
+        .setTotalTime(totalMatchingTimeMs())
+        .setData(selectorProfileData);
+    return result.release();
+}
+
+class UpdateRegionLayoutTask {
+public:
+    UpdateRegionLayoutTask(InspectorCSSAgent*);
+    void scheduleFor(NamedFlow*, int documentNodeId);
+    void unschedule(NamedFlow*);
+    void reset();
+    void onTimer(Timer<UpdateRegionLayoutTask>*);
+
+private:
+    InspectorCSSAgent* m_cssAgent;
+    Timer<UpdateRegionLayoutTask> m_timer;
+    HashMap<NamedFlow*, int> m_namedFlows;
+};
+
+UpdateRegionLayoutTask::UpdateRegionLayoutTask(InspectorCSSAgent* cssAgent)
+    : m_cssAgent(cssAgent)
+    , m_timer(this, &UpdateRegionLayoutTask::onTimer)
+{
+}
+
+void UpdateRegionLayoutTask::scheduleFor(NamedFlow* namedFlow, int documentNodeId)
+{
+    m_namedFlows.add(namedFlow, documentNodeId);
+
+    if (!m_timer.isActive())
+        m_timer.startOneShot(0);
+}
+
+void UpdateRegionLayoutTask::unschedule(NamedFlow* namedFlow)
+{
+    m_namedFlows.remove(namedFlow);
+}
+
+void UpdateRegionLayoutTask::reset()
+{
+    m_timer.stop();
+    m_namedFlows.clear();
+}
+
+void UpdateRegionLayoutTask::onTimer(Timer<UpdateRegionLayoutTask>*)
+{
+    // The timer is stopped on m_cssAgent destruction, so this method will never be called after m_cssAgent has been destroyed.
+    Vector<std::pair<NamedFlow*, int> > namedFlows;
+
+    for (HashMap<NamedFlow*, int>::iterator it = m_namedFlows.begin(), end = m_namedFlows.end(); it != end; ++it)
+        namedFlows.append(std::make_pair(it->key, it->value));
+
+    for (unsigned i = 0, size = namedFlows.size(); i < size; ++i) {
+        NamedFlow* namedFlow = namedFlows.at(i).first;
+        int documentNodeId = namedFlows.at(i).second;
+
+        if (m_namedFlows.contains(namedFlow)) {
+            m_cssAgent->regionLayoutUpdated(namedFlow, documentNodeId);
+            m_namedFlows.remove(namedFlow);
+        }
+    }
+
+    if (!m_namedFlows.isEmpty() && !m_timer.isActive())
+        m_timer.startOneShot(0);
+}
+
+class InspectorCSSAgent::StyleSheetAction : public InspectorHistory::Action {
+    WTF_MAKE_NONCOPYABLE(StyleSheetAction);
+public:
+    StyleSheetAction(const String& name, InspectorStyleSheet* styleSheet)
+        : InspectorHistory::Action(name)
+        , m_styleSheet(styleSheet)
+    {
+    }
+
+protected:
+    RefPtr<InspectorStyleSheet> m_styleSheet;
+};
+
+class InspectorCSSAgent::SetStyleSheetTextAction : public InspectorCSSAgent::StyleSheetAction {
+    WTF_MAKE_NONCOPYABLE(SetStyleSheetTextAction);
+public:
+    SetStyleSheetTextAction(InspectorStyleSheet* styleSheet, const String& text)
+        : InspectorCSSAgent::StyleSheetAction("SetStyleSheetText", styleSheet)
+        , m_text(text)
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        if (!m_styleSheet->getText(&m_oldText))
+            return false;
+        return redo(ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        if (m_styleSheet->setText(m_oldText, ec)) {
+            m_styleSheet->reparseStyleSheet(m_oldText);
+            return true;
+        }
+        return false;
+    }
+
+    virtual bool redo(ExceptionCode& ec)
+    {
+        if (m_styleSheet->setText(m_text, ec)) {
+            m_styleSheet->reparseStyleSheet(m_text);
+            return true;
+        }
+        return false;
+    }
+
+    virtual String mergeId()
+    {
+        return String::format("SetStyleSheetText %s", m_styleSheet->id().utf8().data());
+    }
+
+    virtual void merge(PassOwnPtr<Action> action)
+    {
+        ASSERT(action->mergeId() == mergeId());
+
+        SetStyleSheetTextAction* other = static_cast<SetStyleSheetTextAction*>(action.get());
+        m_text = other->m_text;
+    }
+
+private:
+    String m_text;
+    String m_oldText;
+};
+
+class InspectorCSSAgent::SetStyleTextAction : public InspectorCSSAgent::StyleSheetAction {
+    WTF_MAKE_NONCOPYABLE(SetStyleTextAction);
+public:
+    SetStyleTextAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, const String& text)
+        : InspectorCSSAgent::StyleSheetAction("SetPropertyText", styleSheet)
+        , m_cssId(cssId)
+        , m_text(text)
+    {
+    }
+
+    virtual String toString()
+    {
+        return mergeId() + ": " + m_oldText + " -> " + m_text;
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        return redo(ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        String placeholder;
+        return m_styleSheet->setStyleText(m_cssId, m_oldText, &placeholder, ec);
+    }
+
+    virtual bool redo(ExceptionCode& ec)
+    {
+        return m_styleSheet->setStyleText(m_cssId, m_text, &m_oldText, ec);
+    }
+
+    virtual String mergeId()
+    {
+        return String::format("SetStyleText %s:%u", m_cssId.styleSheetId().utf8().data(), m_cssId.ordinal());
+    }
+
+    virtual void merge(PassOwnPtr<Action> action)
+    {
+        ASSERT(action->mergeId() == mergeId());
+
+        SetStyleTextAction* other = static_cast<SetStyleTextAction*>(action.get());
+        m_text = other->m_text;
+    }
+
+private:
+    InspectorCSSId m_cssId;
+    String m_text;
+    String m_oldText;
+};
+
+class InspectorCSSAgent::SetPropertyTextAction : public InspectorCSSAgent::StyleSheetAction {
+    WTF_MAKE_NONCOPYABLE(SetPropertyTextAction);
+public:
+    SetPropertyTextAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, unsigned propertyIndex, const String& text, bool overwrite)
+        : InspectorCSSAgent::StyleSheetAction("SetPropertyText", styleSheet)
+        , m_cssId(cssId)
+        , m_propertyIndex(propertyIndex)
+        , m_text(text)
+        , m_overwrite(overwrite)
+    {
+    }
+
+    virtual String toString()
+    {
+        return mergeId() + ": " + m_oldText + " -> " + m_text;
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        return redo(ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        String placeholder;
+        return m_styleSheet->setPropertyText(m_cssId, m_propertyIndex, m_overwrite ? m_oldText : "", true, &placeholder, ec);
+    }
+
+    virtual bool redo(ExceptionCode& ec)
+    {
+        String oldText;
+        bool result = m_styleSheet->setPropertyText(m_cssId, m_propertyIndex, m_text, m_overwrite, &oldText, ec);
+        m_oldText = oldText.stripWhiteSpace();
+        // FIXME: remove this once the model handles this case.
+        if (!m_oldText.endsWith(';'))
+            m_oldText.append(';');
+        return result;
+    }
+
+    virtual String mergeId()
+    {
+        return String::format("SetPropertyText %s:%u:%s", m_styleSheet->id().utf8().data(), m_propertyIndex, m_overwrite ? "true" : "false");
+    }
+
+    virtual void merge(PassOwnPtr<Action> action)
+    {
+        ASSERT(action->mergeId() == mergeId());
+
+        SetPropertyTextAction* other = static_cast<SetPropertyTextAction*>(action.get());
+        m_text = other->m_text;
+    }
+
+private:
+    InspectorCSSId m_cssId;
+    unsigned m_propertyIndex;
+    String m_text;
+    String m_oldText;
+    bool m_overwrite;
+};
+
+class InspectorCSSAgent::TogglePropertyAction : public InspectorCSSAgent::StyleSheetAction {
+    WTF_MAKE_NONCOPYABLE(TogglePropertyAction);
+public:
+    TogglePropertyAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, unsigned propertyIndex, bool disable)
+        : InspectorCSSAgent::StyleSheetAction("ToggleProperty", styleSheet)
+        , m_cssId(cssId)
+        , m_propertyIndex(propertyIndex)
+        , m_disable(disable)
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        return redo(ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        return m_styleSheet->toggleProperty(m_cssId, m_propertyIndex, !m_disable, ec);
+    }
+
+    virtual bool redo(ExceptionCode& ec)
+    {
+        return m_styleSheet->toggleProperty(m_cssId, m_propertyIndex, m_disable, ec);
+    }
+
+private:
+    InspectorCSSId m_cssId;
+    unsigned m_propertyIndex;
+    bool m_disable;
+};
+
+class InspectorCSSAgent::SetRuleSelectorAction : public InspectorCSSAgent::StyleSheetAction {
+    WTF_MAKE_NONCOPYABLE(SetRuleSelectorAction);
+public:
+    SetRuleSelectorAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, const String& selector)
+        : InspectorCSSAgent::StyleSheetAction("SetRuleSelector", styleSheet)
+        , m_cssId(cssId)
+        , m_selector(selector)
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        m_oldSelector = m_styleSheet->ruleSelector(m_cssId, ec);
+        if (ec)
+            return false;
+        return redo(ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        return m_styleSheet->setRuleSelector(m_cssId, m_oldSelector, ec);
+    }
+
+    virtual bool redo(ExceptionCode& ec)
+    {
+        return m_styleSheet->setRuleSelector(m_cssId, m_selector, ec);
+    }
+
+private:
+    InspectorCSSId m_cssId;
+    String m_selector;
+    String m_oldSelector;
+};
+
+class InspectorCSSAgent::AddRuleAction : public InspectorCSSAgent::StyleSheetAction {
+    WTF_MAKE_NONCOPYABLE(AddRuleAction);
+public:
+    AddRuleAction(InspectorStyleSheet* styleSheet, const String& selector)
+        : InspectorCSSAgent::StyleSheetAction("AddRule", styleSheet)
+        , m_selector(selector)
+    {
+    }
+
+    virtual bool perform(ExceptionCode& ec)
+    {
+        return redo(ec);
+    }
+
+    virtual bool undo(ExceptionCode& ec)
+    {
+        return m_styleSheet->deleteRule(m_newId, ec);
+    }
+
+    virtual bool redo(ExceptionCode& ec)
+    {
+        CSSStyleRule* cssStyleRule = m_styleSheet->addRule(m_selector, ec);
+        if (ec)
+            return false;
+        m_newId = m_styleSheet->ruleId(cssStyleRule);
+        return true;
+    }
+
+    InspectorCSSId newRuleId() { return m_newId; }
+
+private:
+    InspectorCSSId m_newId;
+    String m_selector;
+    String m_oldSelector;
+};
+
+// static
+CSSStyleRule* InspectorCSSAgent::asCSSStyleRule(CSSRule* rule)
+{
+    if (rule->type() != CSSRule::STYLE_RULE)
+        return 0;
+    return static_cast<CSSStyleRule*>(rule);
+}
+
+InspectorCSSAgent::InspectorCSSAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InspectorDOMAgent* domAgent)
+    : InspectorBaseAgent<InspectorCSSAgent>("CSS", instrumentingAgents, state)
+    , m_frontend(0)
+    , m_domAgent(domAgent)
+    , m_lastStyleSheetId(1)
+    , m_creatingViaInspectorStyleSheet(false)
+{
+    m_domAgent->setDOMListener(this);
+}
+
+InspectorCSSAgent::~InspectorCSSAgent()
+{
+    ASSERT(!m_domAgent);
+    reset();
+}
+
+void InspectorCSSAgent::setFrontend(InspectorFrontend* frontend)
+{
+    ASSERT(!m_frontend);
+    m_frontend = frontend->css();
+}
+
+void InspectorCSSAgent::clearFrontend()
+{
+    ASSERT(m_frontend);
+    m_frontend = 0;
+    resetNonPersistentData();
+    stopSelectorProfilerImpl(0, false);
+}
+
+void InspectorCSSAgent::discardAgent()
+{
+    m_domAgent->setDOMListener(0);
+    m_domAgent = 0;
+}
+
+void InspectorCSSAgent::restore()
+{
+    if (m_state->getBoolean(CSSAgentState::cssAgentEnabled)) {
+        ErrorString error;
+        enable(&error);
+    }
+    if (m_state->getBoolean(CSSAgentState::isSelectorProfiling)) {
+        String errorString;
+        startSelectorProfiler(&errorString);
+    }
+}
+
+void InspectorCSSAgent::reset()
+{
+    m_idToInspectorStyleSheet.clear();
+    m_cssStyleSheetToInspectorStyleSheet.clear();
+    m_nodeToInspectorStyleSheet.clear();
+    m_documentToInspectorStyleSheet.clear();
+    resetNonPersistentData();
+}
+
+void InspectorCSSAgent::resetNonPersistentData()
+{
+    m_namedFlowCollectionsRequested.clear();
+    if (m_updateRegionLayoutTask)
+        m_updateRegionLayoutTask->reset();
+    resetPseudoStates();
+}
+
+void InspectorCSSAgent::enable(ErrorString*)
+{
+    m_state->setBoolean(CSSAgentState::cssAgentEnabled, true);
+    m_instrumentingAgents->setInspectorCSSAgent(this);
+
+    RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader> > styleInfos = TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader>::create();
+    Vector<InspectorStyleSheet*> styleSheets;
+    collectAllStyleSheets(styleSheets);
+    for (size_t i = 0; i < styleSheets.size(); ++i)
+        m_frontend->styleSheetAdded(styleSheets.at(i)->buildObjectForStyleSheetInfo());
+}
+
+void InspectorCSSAgent::disable(ErrorString*)
+{
+    m_instrumentingAgents->setInspectorCSSAgent(0);
+    m_state->setBoolean(CSSAgentState::cssAgentEnabled, false);
+}
+
+void InspectorCSSAgent::mediaQueryResultChanged()
+{
+    if (m_frontend)
+        m_frontend->mediaQueryResultChanged();
+}
+
+void InspectorCSSAgent::didCreateNamedFlow(Document* document, NamedFlow* namedFlow)
+{
+    int documentNodeId = documentNodeWithRequestedFlowsId(document);
+    if (!documentNodeId)
+        return;
+
+    ErrorString errorString;
+    m_frontend->namedFlowCreated(buildObjectForNamedFlow(&errorString, namedFlow, documentNodeId));
+}
+
+void InspectorCSSAgent::willRemoveNamedFlow(Document* document, NamedFlow* namedFlow)
+{
+    int documentNodeId = documentNodeWithRequestedFlowsId(document);
+    if (!documentNodeId)
+        return;
+
+    if (m_updateRegionLayoutTask)
+        m_updateRegionLayoutTask->unschedule(namedFlow);
+
+    m_frontend->namedFlowRemoved(documentNodeId, namedFlow->name().string());
+}
+
+void InspectorCSSAgent::didUpdateRegionLayout(Document* document, NamedFlow* namedFlow)
+{
+    int documentNodeId = documentNodeWithRequestedFlowsId(document);
+    if (!documentNodeId)
+        return;
+
+    if (!m_updateRegionLayoutTask)
+        m_updateRegionLayoutTask = adoptPtr(new UpdateRegionLayoutTask(this));
+    m_updateRegionLayoutTask->scheduleFor(namedFlow, documentNodeId);
+}
+
+void InspectorCSSAgent::regionLayoutUpdated(NamedFlow* namedFlow, int documentNodeId)
+{
+    if (namedFlow->flowState() == NamedFlow::FlowStateNull)
+        return;
+
+    ErrorString errorString;
+    RefPtr<NamedFlow> protector(namedFlow);
+
+    m_frontend->regionLayoutUpdated(buildObjectForNamedFlow(&errorString, namedFlow, documentNodeId));
+}
+
+void InspectorCSSAgent::activeStyleSheetsUpdated(const Vector<RefPtr<StyleSheet> >& newSheets)
+{
+    HashSet<CSSStyleSheet*> removedSheets;
+    for (CSSStyleSheetToInspectorStyleSheet::iterator it = m_cssStyleSheetToInspectorStyleSheet.begin(); it != m_cssStyleSheetToInspectorStyleSheet.end(); ++it) {
+        if (it->value->canBind())
+            removedSheets.add(it->key);
+    }
+
+    Vector<CSSStyleSheet*> newSheetsVector;
+    for (size_t i = 0, size = newSheets.size(); i < size; ++i) {
+        StyleSheet* newSheet = newSheets.at(i).get();
+        if (newSheet->isCSSStyleSheet()) {
+            StyleSheetAppender appender(m_cssStyleSheetToInspectorStyleSheet, newSheetsVector);
+            appender.run(static_cast<CSSStyleSheet*>(newSheet));
+        }
+    }
+
+    HashSet<CSSStyleSheet*> addedSheets;
+    for (size_t i = 0; i < newSheetsVector.size(); ++i) {
+        CSSStyleSheet* newCSSSheet = newSheetsVector.at(i);
+        if (removedSheets.contains(newCSSSheet))
+            removedSheets.remove(newCSSSheet);
+        else
+            addedSheets.add(newCSSSheet);
+    }
+
+    RefPtr<TypeBuilder::Array<TypeBuilder::CSS::StyleSheetId> > removedIds = TypeBuilder::Array<TypeBuilder::CSS::StyleSheetId>::create();
+    for (HashSet<CSSStyleSheet*>::iterator it = removedSheets.begin(); it != removedSheets.end(); ++it) {
+        RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_cssStyleSheetToInspectorStyleSheet.get(*it);
+        ASSERT(inspectorStyleSheet);
+        if (m_idToInspectorStyleSheet.contains(inspectorStyleSheet->id())) {
+            String id = unbindStyleSheet(inspectorStyleSheet.get());
+            if (m_frontend)
+                m_frontend->styleSheetRemoved(id);
+        }
+    }
+    RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader> > addedHeaders = TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader>::create();
+    for (HashSet<CSSStyleSheet*>::iterator it = addedSheets.begin(); it != addedSheets.end(); ++it) {
+        if (!m_cssStyleSheetToInspectorStyleSheet.contains(*it)) {
+            InspectorStyleSheet* newStyleSheet = bindStyleSheet(static_cast<CSSStyleSheet*>(*it));
+            if (m_frontend)
+                m_frontend->styleSheetAdded(newStyleSheet->buildObjectForStyleSheetInfo());
+        }
+    }
+}
+
+bool InspectorCSSAgent::forcePseudoState(Element* element, CSSSelector::PseudoType pseudoType)
+{
+    if (m_nodeIdToForcedPseudoState.isEmpty())
+        return false;
+
+    int nodeId = m_domAgent->boundNodeId(element);
+    if (!nodeId)
+        return false;
+
+    NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.find(nodeId);
+    if (it == m_nodeIdToForcedPseudoState.end())
+        return false;
+
+    unsigned forcedPseudoState = it->value;
+    switch (pseudoType) {
+    case CSSSelector::PseudoActive:
+        return forcedPseudoState & PseudoActive;
+    case CSSSelector::PseudoFocus:
+        return forcedPseudoState & PseudoFocus;
+    case CSSSelector::PseudoHover:
+        return forcedPseudoState & PseudoHover;
+    case CSSSelector::PseudoVisited:
+        return forcedPseudoState & PseudoVisited;
+    default:
+        return false;
+    }
+}
+
+void InspectorCSSAgent::getMatchedStylesForNode(ErrorString* errorString, int nodeId, const bool* includePseudo, const bool* includeInherited, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> >& matchedCSSRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdMatches> >& pseudoIdMatches, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> >& inheritedEntries)
+{
+    Element* element = elementForId(errorString, nodeId);
+    if (!element)
+        return;
+
+    // Matched rules.
+    StyleResolver* styleResolver = element->ownerDocument()->styleResolver();
+    RefPtr<CSSRuleList> matchedRules = styleResolver->styleRulesForElement(element, StyleResolver::AllCSSRules);
+    matchedCSSRules = buildArrayForMatchedRuleList(matchedRules.get(), styleResolver, element);
+
+    // Pseudo elements.
+    if (!includePseudo || *includePseudo) {
+        RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdMatches> > pseudoElements = TypeBuilder::Array<TypeBuilder::CSS::PseudoIdMatches>::create();
+        for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < AFTER_LAST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
+            RefPtr<CSSRuleList> matchedRules = styleResolver->pseudoStyleRulesForElement(element, pseudoId, StyleResolver::AllCSSRules);
+            if (matchedRules && matchedRules->length()) {
+                RefPtr<TypeBuilder::CSS::PseudoIdMatches> matches = TypeBuilder::CSS::PseudoIdMatches::create()
+                    .setPseudoId(static_cast<int>(pseudoId))
+                    .setMatches(buildArrayForMatchedRuleList(matchedRules.get(), styleResolver, element));
+                pseudoElements->addItem(matches.release());
+            }
+        }
+
+        pseudoIdMatches = pseudoElements.release();
+    }
+
+    // Inherited styles.
+    if (!includeInherited || *includeInherited) {
+        RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> > entries = TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry>::create();
+        Element* parentElement = element->parentElement();
+        while (parentElement) {
+            StyleResolver* parentStyleResolver = parentElement->ownerDocument()->styleResolver();
+            RefPtr<CSSRuleList> parentMatchedRules = parentStyleResolver->styleRulesForElement(parentElement, StyleResolver::AllCSSRules);
+            RefPtr<TypeBuilder::CSS::InheritedStyleEntry> entry = TypeBuilder::CSS::InheritedStyleEntry::create()
+                .setMatchedCSSRules(buildArrayForMatchedRuleList(parentMatchedRules.get(), styleResolver, parentElement));
+            if (parentElement->style() && parentElement->style()->length()) {
+                InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(parentElement);
+                if (styleSheet)
+                    entry->setInlineStyle(styleSheet->buildObjectForStyle(styleSheet->styleForId(InspectorCSSId(styleSheet->id(), 0))));
+            }
+
+            entries->addItem(entry.release());
+            parentElement = parentElement->parentElement();
+        }
+
+        inheritedEntries = entries.release();
+    }
+}
+
+void InspectorCSSAgent::getInlineStylesForNode(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::CSS::CSSStyle>& inlineStyle, RefPtr<TypeBuilder::CSS::CSSStyle>& attributesStyle)
+{
+    Element* element = elementForId(errorString, nodeId);
+    if (!element)
+        return;
+
+    InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(element);
+    if (!styleSheet)
+        return;
+
+    inlineStyle = styleSheet->buildObjectForStyle(element->style());
+    RefPtr<TypeBuilder::CSS::CSSStyle> attributes = buildObjectForAttributesStyle(element);
+    attributesStyle = attributes ? attributes.release() : 0;
+}
+
+void InspectorCSSAgent::getComputedStyleForNode(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> >& style)
+{
+    Element* element = elementForId(errorString, nodeId);
+    if (!element)
+        return;
+
+    RefPtr<CSSComputedStyleDeclaration> computedStyleInfo = CSSComputedStyleDeclaration::create(element, true);
+    RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo, 0);
+    style = inspectorStyle->buildArrayForComputedStyle();
+}
+
+void InspectorCSSAgent::getAllStyleSheets(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader> >& styleInfos)
+{
+    styleInfos = TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader>::create();
+    Vector<InspectorStyleSheet*> styleSheets;
+    collectAllStyleSheets(styleSheets);
+    for (size_t i = 0; i < styleSheets.size(); ++i)
+        styleInfos->addItem(styleSheets.at(i)->buildObjectForStyleSheetInfo());
+}
+
+void InspectorCSSAgent::getStyleSheet(ErrorString* errorString, const String& styleSheetId, RefPtr<TypeBuilder::CSS::CSSStyleSheetBody>& styleSheetObject)
+{
+    InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
+    if (!inspectorStyleSheet)
+        return;
+
+    styleSheetObject = inspectorStyleSheet->buildObjectForStyleSheet();
+}
+
+void InspectorCSSAgent::getStyleSheetText(ErrorString* errorString, const String& styleSheetId, String* result)
+{
+    InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
+    if (!inspectorStyleSheet)
+        return;
+
+    inspectorStyleSheet->getText(result);
+}
+
+void InspectorCSSAgent::setStyleSheetText(ErrorString* errorString, const String& styleSheetId, const String& text)
+{
+    InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
+    if (!inspectorStyleSheet)
+        return;
+
+    ExceptionCode ec = 0;
+    m_domAgent->history()->perform(adoptPtr(new SetStyleSheetTextAction(inspectorStyleSheet, text)), ec);
+    *errorString = InspectorDOMAgent::toErrorString(ec);
+}
+
+void InspectorCSSAgent::setStyleText(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, const String& text, RefPtr<TypeBuilder::CSS::CSSStyle>& result)
+{
+    InspectorCSSId compoundId(fullStyleId);
+    ASSERT(!compoundId.isEmpty());
+
+    InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
+    if (!inspectorStyleSheet)
+        return;
+
+    ExceptionCode ec = 0;
+    m_domAgent->history()->perform(adoptPtr(new SetStyleTextAction(inspectorStyleSheet, compoundId, text)), ec);
+    if (!ec)
+        result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
+    *errorString = InspectorDOMAgent::toErrorString(ec);
+}
+
+void InspectorCSSAgent::setPropertyText(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, int propertyIndex, const String& text, bool overwrite, RefPtr<TypeBuilder::CSS::CSSStyle>& result)
+{
+    InspectorCSSId compoundId(fullStyleId);
+    ASSERT(!compoundId.isEmpty());
+
+    InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
+    if (!inspectorStyleSheet)
+        return;
+
+    ExceptionCode ec = 0;
+    bool success = m_domAgent->history()->perform(adoptPtr(new SetPropertyTextAction(inspectorStyleSheet, compoundId, propertyIndex, text, overwrite)), ec);
+    if (success)
+        result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
+    *errorString = InspectorDOMAgent::toErrorString(ec);
+}
+
+void InspectorCSSAgent::toggleProperty(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, int propertyIndex, bool disable, RefPtr<TypeBuilder::CSS::CSSStyle>& result)
+{
+    InspectorCSSId compoundId(fullStyleId);
+    ASSERT(!compoundId.isEmpty());
+
+    InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
+    if (!inspectorStyleSheet)
+        return;
+
+    ExceptionCode ec = 0;
+    bool success = m_domAgent->history()->perform(adoptPtr(new TogglePropertyAction(inspectorStyleSheet, compoundId, propertyIndex, disable)), ec);
+    if (success)
+        result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
+    *errorString = InspectorDOMAgent::toErrorString(ec);
+}
+
+void InspectorCSSAgent::setRuleSelector(ErrorString* errorString, const RefPtr<InspectorObject>& fullRuleId, const String& selector, RefPtr<TypeBuilder::CSS::CSSRule>& result)
+{
+    InspectorCSSId compoundId(fullRuleId);
+    ASSERT(!compoundId.isEmpty());
+
+    InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
+    if (!inspectorStyleSheet)
+        return;
+
+    ExceptionCode ec = 0;
+    bool success = m_domAgent->history()->perform(adoptPtr(new SetRuleSelectorAction(inspectorStyleSheet, compoundId, selector)), ec);
+
+    if (success)
+        result = inspectorStyleSheet->buildObjectForRule(inspectorStyleSheet->ruleForId(compoundId));
+    *errorString = InspectorDOMAgent::toErrorString(ec);
+}
+
+void InspectorCSSAgent::addRule(ErrorString* errorString, const int contextNodeId, const String& selector, RefPtr<TypeBuilder::CSS::CSSRule>& result)
+{
+    Node* node = m_domAgent->assertNode(errorString, contextNodeId);
+    if (!node)
+        return;
+
+    InspectorStyleSheet* inspectorStyleSheet = viaInspectorStyleSheet(node->document(), true);
+    if (!inspectorStyleSheet) {
+        *errorString = "No target stylesheet found";
+        return;
+    }
+
+    ExceptionCode ec = 0;
+    OwnPtr<AddRuleAction> action = adoptPtr(new AddRuleAction(inspectorStyleSheet, selector));
+    AddRuleAction* rawAction = action.get();
+    bool success = m_domAgent->history()->perform(action.release(), ec);
+    if (!success) {
+        *errorString = InspectorDOMAgent::toErrorString(ec);
+        return;
+    }
+
+    InspectorCSSId ruleId = rawAction->newRuleId();
+    CSSStyleRule* rule = inspectorStyleSheet->ruleForId(ruleId);
+    result = inspectorStyleSheet->buildObjectForRule(rule);
+}
+
+void InspectorCSSAgent::getSupportedCSSProperties(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSPropertyInfo> >& cssProperties)
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSPropertyInfo> > properties = TypeBuilder::Array<TypeBuilder::CSS::CSSPropertyInfo>::create();
+    for (int i = firstCSSProperty; i <= lastCSSProperty; ++i) {
+        CSSPropertyID id = convertToCSSPropertyID(i);
+        RefPtr<TypeBuilder::CSS::CSSPropertyInfo> property = TypeBuilder::CSS::CSSPropertyInfo::create()
+            .setName(getPropertyNameString(id));
+
+        const StylePropertyShorthand& shorthand = shorthandForProperty(id);
+        if (!shorthand.length()) {
+            properties->addItem(property.release());
+            continue;
+        }
+        RefPtr<TypeBuilder::Array<String> > longhands = TypeBuilder::Array<String>::create();
+        for (unsigned j = 0; j < shorthand.length(); ++j) {
+            CSSPropertyID longhandID = shorthand.properties()[j];
+            longhands->addItem(getPropertyNameString(longhandID));
+        }
+        property->setLonghands(longhands);
+        properties->addItem(property.release());
+    }
+    cssProperties = properties.release();
+}
+
+void InspectorCSSAgent::forcePseudoState(ErrorString* errorString, int nodeId, const RefPtr<InspectorArray>& forcedPseudoClasses)
+{
+    Element* element = m_domAgent->assertElement(errorString, nodeId);
+    if (!element)
+        return;
+
+    unsigned forcedPseudoState = computePseudoClassMask(forcedPseudoClasses.get());
+    NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.find(nodeId);
+    unsigned currentForcedPseudoState = it == m_nodeIdToForcedPseudoState.end() ? 0 : it->value;
+    bool needStyleRecalc = forcedPseudoState != currentForcedPseudoState;
+    if (!needStyleRecalc)
+        return;
+
+    if (forcedPseudoState)
+        m_nodeIdToForcedPseudoState.set(nodeId, forcedPseudoState);
+    else
+        m_nodeIdToForcedPseudoState.remove(nodeId);
+    element->ownerDocument()->styleResolverChanged(RecalcStyleImmediately);
+}
+
+void InspectorCSSAgent::getNamedFlowCollection(ErrorString* errorString, int documentNodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::NamedFlow> >& result)
+{
+    Document* document = m_domAgent->assertDocument(errorString, documentNodeId);
+    if (!document)
+        return;
+
+    m_namedFlowCollectionsRequested.add(documentNodeId);
+
+    Vector<RefPtr<NamedFlow> > namedFlowsVector = document->namedFlows()->namedFlows();
+    RefPtr<TypeBuilder::Array<TypeBuilder::CSS::NamedFlow> > namedFlows = TypeBuilder::Array<TypeBuilder::CSS::NamedFlow>::create();
+
+    for (Vector<RefPtr<NamedFlow> >::iterator it = namedFlowsVector.begin(); it != namedFlowsVector.end(); ++it)
+        namedFlows->addItem(buildObjectForNamedFlow(errorString, it->get(), documentNodeId));
+
+    result = namedFlows.release();
+}
+
+void InspectorCSSAgent::startSelectorProfiler(ErrorString*)
+{
+    m_currentSelectorProfile = adoptPtr(new SelectorProfile());
+    m_state->setBoolean(CSSAgentState::isSelectorProfiling, true);
+}
+
+void InspectorCSSAgent::stopSelectorProfiler(ErrorString* errorString, RefPtr<TypeBuilder::CSS::SelectorProfile>& result)
+{
+    result = stopSelectorProfilerImpl(errorString, true);
+}
+
+PassRefPtr<TypeBuilder::CSS::SelectorProfile> InspectorCSSAgent::stopSelectorProfilerImpl(ErrorString*, bool needProfile)
+{
+    if (!m_state->getBoolean(CSSAgentState::isSelectorProfiling))
+        return 0;
+    m_state->setBoolean(CSSAgentState::isSelectorProfiling, false);
+    RefPtr<TypeBuilder::CSS::SelectorProfile> result;
+    if (m_frontend && needProfile)
+        result = m_currentSelectorProfile->toInspectorObject();
+    m_currentSelectorProfile.clear();
+    return result.release();
+}
+
+void InspectorCSSAgent::willMatchRule(StyleRule* rule, InspectorCSSOMWrappers& inspectorCSSOMWrappers, DocumentStyleSheetCollection* styleSheetCollection)
+{
+//    printf("InspectorCSSAgent::willMatchRule %s\n", rule->selectorList().selectorsText().utf8().data());
+    if (m_currentSelectorProfile)
+        m_currentSelectorProfile->startSelector(inspectorCSSOMWrappers.getWrapperForRuleInSheets(rule, styleSheetCollection));
+}
+
+void InspectorCSSAgent::didMatchRule(bool matched)
+{
+    if (m_currentSelectorProfile)
+        m_currentSelectorProfile->commitSelector(matched);
+}
+
+void InspectorCSSAgent::willProcessRule(StyleRule* rule, StyleResolver* styleResolver)
+{
+    if (m_currentSelectorProfile)
+        m_currentSelectorProfile->startSelector(styleResolver->inspectorCSSOMWrappers().getWrapperForRuleInSheets(rule, styleResolver->document()->styleSheetCollection()));
+}
+
+void InspectorCSSAgent::didProcessRule()
+{
+    if (m_currentSelectorProfile)
+        m_currentSelectorProfile->commitSelectorTime();
+}
+
+InspectorStyleSheetForInlineStyle* InspectorCSSAgent::asInspectorStyleSheet(Element* element)
+{
+    NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
+    if (it == m_nodeToInspectorStyleSheet.end()) {
+        CSSStyleDeclaration* style = element->isStyledElement() ? element->style() : 0;
+        if (!style)
+            return 0;
+
+        String newStyleSheetId = String::number(m_lastStyleSheetId++);
+        RefPtr<InspectorStyleSheetForInlineStyle> inspectorStyleSheet = InspectorStyleSheetForInlineStyle::create(m_domAgent->pageAgent(), newStyleSheetId, element, TypeBuilder::CSS::StyleSheetOrigin::Regular, this);
+        m_idToInspectorStyleSheet.set(newStyleSheetId, inspectorStyleSheet);
+        m_nodeToInspectorStyleSheet.set(element, inspectorStyleSheet);
+        return inspectorStyleSheet.get();
+    }
+
+    return it->value.get();
+}
+
+Element* InspectorCSSAgent::elementForId(ErrorString* errorString, int nodeId)
+{
+    Node* node = m_domAgent->nodeForId(nodeId);
+    if (!node) {
+        *errorString = "No node with given id found";
+        return 0;
+    }
+    if (node->nodeType() != Node::ELEMENT_NODE) {
+        *errorString = "Not an element node";
+        return 0;
+    }
+    return toElement(node);
+}
+
+int InspectorCSSAgent::documentNodeWithRequestedFlowsId(Document* document)
+{
+    int documentNodeId = m_domAgent->boundNodeId(document);
+    if (!documentNodeId || !m_namedFlowCollectionsRequested.contains(documentNodeId))
+        return 0;
+
+    return documentNodeId;
+}
+
+void InspectorCSSAgent::collectAllStyleSheets(Vector<InspectorStyleSheet*>& result)
+{
+    Vector<Document*> documents = m_domAgent->documents();
+    for (Vector<Document*>::iterator it = documents.begin(); it != documents.end(); ++it) {
+        StyleSheetList* list = (*it)->styleSheets();
+        for (unsigned i = 0; i < list->length(); ++i) {
+            StyleSheet* styleSheet = list->item(i);
+            if (styleSheet->isCSSStyleSheet())
+                collectStyleSheets(static_cast<CSSStyleSheet*>(styleSheet), result);
+        }
+    }
+}
+
+void InspectorCSSAgent::collectStyleSheets(CSSStyleSheet* styleSheet, Vector<InspectorStyleSheet*>& result)
+{
+    InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(static_cast<CSSStyleSheet*>(styleSheet));
+    result.append(inspectorStyleSheet);
+    for (unsigned i = 0, size = styleSheet->length(); i < size; ++i) {
+        CSSRule* rule = styleSheet->item(i);
+        if (rule->type() == CSSRule::IMPORT_RULE) {
+            CSSStyleSheet* importedStyleSheet = static_cast<CSSImportRule*>(rule)->styleSheet();
+            if (importedStyleSheet)
+                collectStyleSheets(importedStyleSheet, result);
+        }
+    }
+}
+
+InspectorStyleSheet* InspectorCSSAgent::bindStyleSheet(CSSStyleSheet* styleSheet)
+{
+    RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_cssStyleSheetToInspectorStyleSheet.get(styleSheet);
+    if (!inspectorStyleSheet) {
+        String id = String::number(m_lastStyleSheetId++);
+        Document* document = styleSheet->ownerDocument();
+        inspectorStyleSheet = InspectorStyleSheet::create(m_domAgent->pageAgent(), id, styleSheet, detectOrigin(styleSheet, document), InspectorDOMAgent::documentURLString(document), this);
+        m_idToInspectorStyleSheet.set(id, inspectorStyleSheet);
+        m_cssStyleSheetToInspectorStyleSheet.set(styleSheet, inspectorStyleSheet);
+        if (m_creatingViaInspectorStyleSheet)
+            m_documentToInspectorStyleSheet.add(document, inspectorStyleSheet);
+    }
+    return inspectorStyleSheet.get();
+}
+
+String InspectorCSSAgent::unbindStyleSheet(InspectorStyleSheet* inspectorStyleSheet)
+{
+    String id = inspectorStyleSheet->id();
+    m_idToInspectorStyleSheet.remove(id);
+    if (inspectorStyleSheet->pageStyleSheet())
+        m_cssStyleSheetToInspectorStyleSheet.remove(inspectorStyleSheet->pageStyleSheet());
+    return id;
+}
+
+InspectorStyleSheet* InspectorCSSAgent::viaInspectorStyleSheet(Document* document, bool createIfAbsent)
+{
+    if (!document) {
+        ASSERT(!createIfAbsent);
+        return 0;
+    }
+
+    if (!document->isHTMLDocument() && !document->isSVGDocument())
+        return 0;
+
+    RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_documentToInspectorStyleSheet.get(document);
+    if (inspectorStyleSheet || !createIfAbsent)
+        return inspectorStyleSheet.get();
+
+    ExceptionCode ec = 0;
+    RefPtr<Element> styleElement = document->createElement("style", ec);
+    if (!ec)
+        styleElement->setAttribute("type", "text/css", ec);
+    if (!ec) {
+        ContainerNode* targetNode;
+        // HEAD is absent in ImageDocuments, for example.
+        if (document->head())
+            targetNode = document->head();
+        else if (document->body())
+            targetNode = document->body();
+        else
+            return 0;
+
+        InlineStyleOverrideScope overrideScope(document);
+        m_creatingViaInspectorStyleSheet = true;
+        targetNode->appendChild(styleElement, ec);
+        // At this point the added stylesheet will get bound through the updateActiveStyleSheets() invocation.
+        // We just need to pick the respective InspectorStyleSheet from m_documentToInspectorStyleSheet.
+        m_creatingViaInspectorStyleSheet = false;
+    }
+    if (ec)
+        return 0;
+
+    return m_documentToInspectorStyleSheet.get(document).get();
+}
+
+InspectorStyleSheet* InspectorCSSAgent::assertStyleSheetForId(ErrorString* errorString, const String& styleSheetId)
+{
+    IdToInspectorStyleSheet::iterator it = m_idToInspectorStyleSheet.find(styleSheetId);
+    if (it == m_idToInspectorStyleSheet.end()) {
+        *errorString = "No style sheet with given id found";
+        return 0;
+    }
+    return it->value.get();
+}
+
+TypeBuilder::CSS::StyleSheetOrigin::Enum InspectorCSSAgent::detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument)
+{
+    if (m_creatingViaInspectorStyleSheet)
+        return TypeBuilder::CSS::StyleSheetOrigin::Inspector;
+
+    TypeBuilder::CSS::StyleSheetOrigin::Enum origin = TypeBuilder::CSS::StyleSheetOrigin::Regular;
+    if (pageStyleSheet && !pageStyleSheet->ownerNode() && pageStyleSheet->href().isEmpty())
+        origin = TypeBuilder::CSS::StyleSheetOrigin::User_agent;
+    else if (pageStyleSheet && pageStyleSheet->ownerNode() && pageStyleSheet->ownerNode()->nodeName() == "#document")
+        origin = TypeBuilder::CSS::StyleSheetOrigin::User;
+    else {
+        InspectorStyleSheet* viaInspectorStyleSheetForOwner = viaInspectorStyleSheet(ownerDocument, false);
+        if (viaInspectorStyleSheetForOwner && pageStyleSheet == viaInspectorStyleSheetForOwner->pageStyleSheet())
+            origin = TypeBuilder::CSS::StyleSheetOrigin::Inspector;
+    }
+    return origin;
+}
+
+PassRefPtr<TypeBuilder::CSS::CSSRule> InspectorCSSAgent::buildObjectForRule(CSSStyleRule* rule, StyleResolver* styleResolver)
+{
+    if (!rule)
+        return 0;
+
+    // CSSRules returned by StyleResolver::styleRulesForElement lack parent pointers since that infomation is not cheaply available.
+    // Since the inspector wants to walk the parent chain, we construct the full wrappers here.
+    // FIXME: This could be factored better. StyleResolver::styleRulesForElement should return a StyleRule vector, not a CSSRuleList.
+    if (!rule->parentStyleSheet()) {
+        rule = styleResolver->inspectorCSSOMWrappers().getWrapperForRuleInSheets(rule->styleRule(), styleResolver->document()->styleSheetCollection());
+        if (!rule)
+            return 0;
+    }
+    return bindStyleSheet(rule->parentStyleSheet())->buildObjectForRule(rule);
+}
+
+PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > InspectorCSSAgent::buildArrayForRuleList(CSSRuleList* ruleList, StyleResolver* styleResolver)
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > result = TypeBuilder::Array<TypeBuilder::CSS::CSSRule>::create();
+    if (!ruleList)
+        return result.release();
+
+    for (unsigned i = 0, size = ruleList->length(); i < size; ++i) {
+        CSSStyleRule* rule = asCSSStyleRule(ruleList->item(i));
+        RefPtr<TypeBuilder::CSS::CSSRule> ruleObject = buildObjectForRule(rule, styleResolver);
+        if (!ruleObject)
+            continue;
+        result->addItem(ruleObject);
+    }
+    return result.release();
+}
+
+PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> > InspectorCSSAgent::buildArrayForMatchedRuleList(CSSRuleList* ruleList, StyleResolver* styleResolver, Element* element)
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> > result = TypeBuilder::Array<TypeBuilder::CSS::RuleMatch>::create();
+    if (!ruleList)
+        return result.release();
+
+    for (unsigned i = 0, size = ruleList->length(); i < size; ++i) {
+        CSSStyleRule* rule = asCSSStyleRule(ruleList->item(i));
+        RefPtr<TypeBuilder::CSS::CSSRule> ruleObject = buildObjectForRule(rule, styleResolver);
+        if (!ruleObject)
+            continue;
+        RefPtr<TypeBuilder::Array<int> > matchingSelectors = TypeBuilder::Array<int>::create();
+        const CSSSelectorList& selectorList = rule->styleRule()->selectorList();
+        long index = 0;
+        for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
+            bool matched = element->webkitMatchesSelector(selector->selectorText(), IGNORE_EXCEPTION);
+            if (matched)
+                matchingSelectors->addItem(index);
+            ++index;
+        }
+        RefPtr<TypeBuilder::CSS::RuleMatch> match = TypeBuilder::CSS::RuleMatch::create()
+            .setRule(ruleObject)
+            .setMatchingSelectors(matchingSelectors);
+        result->addItem(match);
+    }
+
+    return result;
+}
+
+PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorCSSAgent::buildObjectForAttributesStyle(Element* element)
+{
+    if (!element->isStyledElement())
+        return 0;
+
+    const StylePropertySet* attributeStyle = static_cast<StyledElement*>(element)->presentationAttributeStyle();
+    if (!attributeStyle)
+        return 0;
+
+    RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), const_cast<StylePropertySet*>(attributeStyle)->ensureCSSStyleDeclaration(), 0);
+    return inspectorStyle->buildObjectForStyle();
+}
+
+PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::Region> > InspectorCSSAgent::buildArrayForRegions(ErrorString* errorString, PassRefPtr<NodeList> regionList, int documentNodeId)
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::CSS::Region> > regions = TypeBuilder::Array<TypeBuilder::CSS::Region>::create();
+
+    for (unsigned i = 0; i < regionList->length(); ++i) {
+        TypeBuilder::CSS::Region::RegionOverset::Enum regionOverset;
+
+        switch (toElement(regionList->item(i))->renderRegion()->regionState()) {
+        case RenderRegion::RegionFit:
+            regionOverset = TypeBuilder::CSS::Region::RegionOverset::Fit;
+            break;
+        case RenderRegion::RegionEmpty:
+            regionOverset = TypeBuilder::CSS::Region::RegionOverset::Empty;
+            break;
+        case RenderRegion::RegionOverset:
+            regionOverset = TypeBuilder::CSS::Region::RegionOverset::Overset;
+            break;
+        case RenderRegion::RegionUndefined:
+            continue;
+        default:
+            ASSERT_NOT_REACHED();
+            continue;
+        }
+
+        RefPtr<TypeBuilder::CSS::Region> region = TypeBuilder::CSS::Region::create()
+            .setRegionOverset(regionOverset)
+            // documentNodeId was previously asserted
+            .setNodeId(m_domAgent->pushNodeToFrontend(errorString, documentNodeId, regionList->item(i)));
+
+        regions->addItem(region);
+    }
+
+    return regions.release();
+}
+
+PassRefPtr<TypeBuilder::CSS::NamedFlow> InspectorCSSAgent::buildObjectForNamedFlow(ErrorString* errorString, NamedFlow* webkitNamedFlow, int documentNodeId)
+{
+    RefPtr<NodeList> contentList = webkitNamedFlow->getContent();
+    RefPtr<TypeBuilder::Array<int> > content = TypeBuilder::Array<int>::create();
+
+    for (unsigned i = 0; i < contentList->length(); ++i) {
+        // documentNodeId was previously asserted
+        content->addItem(m_domAgent->pushNodeToFrontend(errorString, documentNodeId, contentList->item(i)));
+    }
+
+    RefPtr<TypeBuilder::CSS::NamedFlow> namedFlow = TypeBuilder::CSS::NamedFlow::create()
+        .setDocumentNodeId(documentNodeId)
+        .setName(webkitNamedFlow->name().string())
+        .setOverset(webkitNamedFlow->overset())
+        .setContent(content)
+        .setRegions(buildArrayForRegions(errorString, webkitNamedFlow->getRegions(), documentNodeId));
+
+    return namedFlow.release();
+}
+
+void InspectorCSSAgent::didRemoveDocument(Document* document)
+{
+    if (document)
+        m_documentToInspectorStyleSheet.remove(document);
+}
+
+void InspectorCSSAgent::didRemoveDOMNode(Node* node)
+{
+    if (!node)
+        return;
+
+    int nodeId = m_domAgent->boundNodeId(node);
+    if (nodeId)
+        m_nodeIdToForcedPseudoState.remove(nodeId);
+
+    NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(node);
+    if (it == m_nodeToInspectorStyleSheet.end())
+        return;
+
+    m_idToInspectorStyleSheet.remove(it->value->id());
+    m_nodeToInspectorStyleSheet.remove(node);
+}
+
+void InspectorCSSAgent::didModifyDOMAttr(Element* element)
+{
+    if (!element)
+        return;
+
+    NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
+    if (it == m_nodeToInspectorStyleSheet.end())
+        return;
+
+    it->value->didModifyElementAttribute();
+}
+
+void InspectorCSSAgent::styleSheetChanged(InspectorStyleSheet* styleSheet)
+{
+    if (m_frontend)
+        m_frontend->styleSheetChanged(styleSheet->id());
+}
+
+void InspectorCSSAgent::resetPseudoStates()
+{
+    HashSet<Document*> documentsToChange;
+    for (NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.begin(), end = m_nodeIdToForcedPseudoState.end(); it != end; ++it) {
+        Element* element = toElement(m_domAgent->nodeForId(it->key));
+        if (element && element->ownerDocument())
+            documentsToChange.add(element->ownerDocument());
+    }
+
+    m_nodeIdToForcedPseudoState.clear();
+    for (HashSet<Document*>::iterator it = documentsToChange.begin(), end = documentsToChange.end(); it != end; ++it)
+        (*it)->styleResolverChanged(RecalcStyleImmediately);
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorCSSAgent.h b/Source/core/inspector/InspectorCSSAgent.h
new file mode 100644
index 0000000..e4e2c63
--- /dev/null
+++ b/Source/core/inspector/InspectorCSSAgent.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2010, 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:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#ifndef InspectorCSSAgent_h
+#define InspectorCSSAgent_h
+
+#include "core/css/CSSSelector.h"
+#include "core/dom/SecurityContext.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include "core/inspector/InspectorDOMAgent.h"
+#include "core/inspector/InspectorStyleSheet.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/page/ContentSecurityPolicy.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CSSRule;
+class CSSRuleList;
+class CSSStyleDeclaration;
+class CSSStyleRule;
+class CSSStyleSheet;
+class Document;
+class DocumentStyleSheetCollection;
+class Element;
+class InspectorCSSOMWrappers;
+class InspectorFrontend;
+class InstrumentingAgents;
+class NameNodeMap;
+class Node;
+class NodeList;
+class SelectorProfile;
+class StyleResolver;
+class StyleRule;
+class StyleSheetVisitor;
+class UpdateRegionLayoutTask;
+
+typedef HashMap<CSSStyleSheet*, RefPtr<InspectorStyleSheet> > CSSStyleSheetToInspectorStyleSheet;
+
+class InspectorCSSAgent
+    : public InspectorBaseAgent<InspectorCSSAgent>
+    , public InspectorDOMAgent::DOMListener
+    , public InspectorBackendDispatcher::CSSCommandHandler
+    , public InspectorStyleSheet::Listener {
+    WTF_MAKE_NONCOPYABLE(InspectorCSSAgent);
+public:
+    class InlineStyleOverrideScope {
+    public:
+        InlineStyleOverrideScope(SecurityContext* context)
+            : m_contentSecurityPolicy(context->contentSecurityPolicy())
+        {
+            m_contentSecurityPolicy->setOverrideAllowInlineStyle(true);
+        }
+
+        ~InlineStyleOverrideScope()
+        {
+            m_contentSecurityPolicy->setOverrideAllowInlineStyle(false);
+        }
+
+    private:
+        ContentSecurityPolicy* m_contentSecurityPolicy;
+    };
+
+    static CSSStyleRule* asCSSStyleRule(CSSRule*);
+
+    static PassOwnPtr<InspectorCSSAgent> create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InspectorDOMAgent* domAgent)
+    {
+        return adoptPtr(new InspectorCSSAgent(instrumentingAgents, state, domAgent));
+    }
+    ~InspectorCSSAgent();
+
+    bool forcePseudoState(Element*, CSSSelector::PseudoType);
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void discardAgent();
+    virtual void restore();
+    virtual void enable(ErrorString*);
+    virtual void disable(ErrorString*);
+    void reset();
+    void mediaQueryResultChanged();
+    void didCreateNamedFlow(Document*, NamedFlow*);
+    void willRemoveNamedFlow(Document*, NamedFlow*);
+    void didUpdateRegionLayout(Document*, NamedFlow*);
+    void regionLayoutUpdated(NamedFlow*, int documentNodeId);
+    void activeStyleSheetsUpdated(const Vector<RefPtr<StyleSheet> >& newSheets);
+
+    virtual void getComputedStyleForNode(ErrorString*, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> >&);
+    virtual void getInlineStylesForNode(ErrorString*, int nodeId, RefPtr<TypeBuilder::CSS::CSSStyle>& inlineStyle, RefPtr<TypeBuilder::CSS::CSSStyle>& attributes);
+    virtual void getMatchedStylesForNode(ErrorString*, int nodeId, const bool* includePseudo, const bool* includeInherited, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> >& matchedCSSRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdMatches> >& pseudoIdMatches, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> >& inheritedEntries);
+    virtual void getAllStyleSheets(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader> >& styleSheetInfos);
+    virtual void getStyleSheet(ErrorString*, const String& styleSheetId, RefPtr<TypeBuilder::CSS::CSSStyleSheetBody>& result);
+    virtual void getStyleSheetText(ErrorString*, const String& styleSheetId, String* result);
+    virtual void setStyleSheetText(ErrorString*, const String& styleSheetId, const String& text);
+    virtual void setStyleText(ErrorString*, const RefPtr<InspectorObject>& styleId, const String& text, RefPtr<TypeBuilder::CSS::CSSStyle>& result);
+    virtual void setPropertyText(ErrorString*, const RefPtr<InspectorObject>& styleId, int propertyIndex, const String& text, bool overwrite, RefPtr<TypeBuilder::CSS::CSSStyle>& result);
+    virtual void toggleProperty(ErrorString*, const RefPtr<InspectorObject>& styleId, int propertyIndex, bool disable, RefPtr<TypeBuilder::CSS::CSSStyle>& result);
+    virtual void setRuleSelector(ErrorString*, const RefPtr<InspectorObject>& ruleId, const String& selector, RefPtr<TypeBuilder::CSS::CSSRule>& result);
+    virtual void addRule(ErrorString*, int contextNodeId, const String& selector, RefPtr<TypeBuilder::CSS::CSSRule>& result);
+    virtual void getSupportedCSSProperties(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSPropertyInfo> >& result);
+    virtual void forcePseudoState(ErrorString*, int nodeId, const RefPtr<InspectorArray>& forcedPseudoClasses);
+    virtual void getNamedFlowCollection(ErrorString*, int documentNodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::NamedFlow> >& result);
+
+    virtual void startSelectorProfiler(ErrorString*);
+    virtual void stopSelectorProfiler(ErrorString*, RefPtr<TypeBuilder::CSS::SelectorProfile>&);
+
+    PassRefPtr<TypeBuilder::CSS::SelectorProfile> stopSelectorProfilerImpl(ErrorString*, bool needProfile);
+    void willMatchRule(StyleRule*, InspectorCSSOMWrappers&, DocumentStyleSheetCollection*);
+    void didMatchRule(bool);
+    void willProcessRule(StyleRule*, StyleResolver*);
+    void didProcessRule();
+
+private:
+    class StyleSheetAction;
+    class SetStyleSheetTextAction;
+    class SetStyleTextAction;
+    class SetPropertyTextAction;
+    class TogglePropertyAction;
+    class SetRuleSelectorAction;
+    class AddRuleAction;
+
+    InspectorCSSAgent(InstrumentingAgents*, InspectorCompositeState*, InspectorDOMAgent*);
+
+    typedef HashMap<String, RefPtr<InspectorStyleSheet> > IdToInspectorStyleSheet;
+    typedef HashMap<Node*, RefPtr<InspectorStyleSheetForInlineStyle> > NodeToInspectorStyleSheet; // bogus "stylesheets" with elements' inline styles
+    typedef HashMap<RefPtr<Document>, RefPtr<InspectorStyleSheet> > DocumentToViaInspectorStyleSheet; // "via inspector" stylesheets
+    typedef HashMap<int, unsigned> NodeIdToForcedPseudoState;
+
+    void resetNonPersistentData();
+    InspectorStyleSheetForInlineStyle* asInspectorStyleSheet(Element* element);
+    Element* elementForId(ErrorString*, int nodeId);
+    int documentNodeWithRequestedFlowsId(Document*);
+    void collectAllStyleSheets(Vector<InspectorStyleSheet*>&);
+    void collectStyleSheets(CSSStyleSheet*, Vector<InspectorStyleSheet*>&);
+
+    InspectorStyleSheet* bindStyleSheet(CSSStyleSheet*);
+    String unbindStyleSheet(InspectorStyleSheet*);
+    InspectorStyleSheet* viaInspectorStyleSheet(Document*, bool createIfAbsent);
+    InspectorStyleSheet* assertStyleSheetForId(ErrorString*, const String&);
+    TypeBuilder::CSS::StyleSheetOrigin::Enum detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument);
+
+    PassRefPtr<TypeBuilder::CSS::CSSRule> buildObjectForRule(CSSStyleRule*, StyleResolver*);
+    PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > buildArrayForRuleList(CSSRuleList*, StyleResolver*);
+    PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> > buildArrayForMatchedRuleList(CSSRuleList*, StyleResolver*, Element*);
+    PassRefPtr<TypeBuilder::CSS::CSSStyle> buildObjectForAttributesStyle(Element*);
+    PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::Region> > buildArrayForRegions(ErrorString*, PassRefPtr<NodeList>, int documentNodeId);
+    PassRefPtr<TypeBuilder::CSS::NamedFlow> buildObjectForNamedFlow(ErrorString*, NamedFlow*, int documentNodeId);
+
+    // InspectorDOMAgent::DOMListener implementation
+    virtual void didRemoveDocument(Document*);
+    virtual void didRemoveDOMNode(Node*);
+    virtual void didModifyDOMAttr(Element*);
+
+    // InspectorCSSAgent::Listener implementation
+    virtual void styleSheetChanged(InspectorStyleSheet*);
+
+    void resetPseudoStates();
+
+    InspectorFrontend::CSS* m_frontend;
+    InspectorDOMAgent* m_domAgent;
+
+    IdToInspectorStyleSheet m_idToInspectorStyleSheet;
+    CSSStyleSheetToInspectorStyleSheet m_cssStyleSheetToInspectorStyleSheet;
+    NodeToInspectorStyleSheet m_nodeToInspectorStyleSheet;
+    DocumentToViaInspectorStyleSheet m_documentToInspectorStyleSheet;
+    NodeIdToForcedPseudoState m_nodeIdToForcedPseudoState;
+    HashSet<int> m_namedFlowCollectionsRequested;
+    OwnPtr<UpdateRegionLayoutTask> m_updateRegionLayoutTask;
+
+    int m_lastStyleSheetId;
+    bool m_creatingViaInspectorStyleSheet;
+
+    OwnPtr<SelectorProfile> m_currentSelectorProfile;
+
+    friend class StyleSheetBinder;
+};
+
+
+} // namespace WebCore
+
+#endif // !defined(InspectorCSSAgent_h)
diff --git a/Source/core/inspector/InspectorCanvasAgent.cpp b/Source/core/inspector/InspectorCanvasAgent.cpp
new file mode 100644
index 0000000..e31ee35
--- /dev/null
+++ b/Source/core/inspector/InspectorCanvasAgent.cpp
@@ -0,0 +1,346 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorCanvasAgent.h"
+
+#include "HTMLNames.h"
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptObject.h"
+#include "bindings/v8/ScriptProfiler.h"
+#include "bindings/v8/ScriptState.h"
+#include "core/html/HTMLCanvasElement.h"
+#include "core/inspector/BindingVisitors.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InjectedScriptCanvasModule.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/page/DOMWindow.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+
+using WebCore::TypeBuilder::Array;
+using WebCore::TypeBuilder::Canvas::ResourceId;
+using WebCore::TypeBuilder::Canvas::ResourceInfo;
+using WebCore::TypeBuilder::Canvas::ResourceState;
+using WebCore::TypeBuilder::Canvas::TraceLog;
+using WebCore::TypeBuilder::Canvas::TraceLogId;
+using WebCore::TypeBuilder::Network::FrameId;
+
+namespace WebCore {
+
+namespace CanvasAgentState {
+static const char canvasAgentEnabled[] = "canvasAgentEnabled";
+};
+
+InspectorCanvasAgent::InspectorCanvasAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InspectorPageAgent* pageAgent, InjectedScriptManager* injectedScriptManager)
+    : InspectorBaseAgent<InspectorCanvasAgent>("Canvas", instrumentingAgents, state)
+    , m_pageAgent(pageAgent)
+    , m_injectedScriptManager(injectedScriptManager)
+    , m_frontend(0)
+    , m_enabled(false)
+{
+}
+
+InspectorCanvasAgent::~InspectorCanvasAgent()
+{
+}
+
+void InspectorCanvasAgent::setFrontend(InspectorFrontend* frontend)
+{
+    ASSERT(frontend);
+    m_frontend = frontend->canvas();
+}
+
+void InspectorCanvasAgent::clearFrontend()
+{
+    m_frontend = 0;
+    disable(0);
+}
+
+void InspectorCanvasAgent::restore()
+{
+    if (m_state->getBoolean(CanvasAgentState::canvasAgentEnabled)) {
+        ErrorString error;
+        enable(&error);
+    }
+}
+
+void InspectorCanvasAgent::enable(ErrorString*)
+{
+    if (m_enabled)
+        return;
+    m_enabled = true;
+    m_state->setBoolean(CanvasAgentState::canvasAgentEnabled, m_enabled);
+    m_instrumentingAgents->setInspectorCanvasAgent(this);
+    findFramesWithUninstrumentedCanvases();
+}
+
+void InspectorCanvasAgent::disable(ErrorString*)
+{
+    m_enabled = false;
+    m_state->setBoolean(CanvasAgentState::canvasAgentEnabled, m_enabled);
+    m_instrumentingAgents->setInspectorCanvasAgent(0);
+    m_framesWithUninstrumentedCanvases.clear();
+}
+
+void InspectorCanvasAgent::dropTraceLog(ErrorString* errorString, const TraceLogId& traceLogId)
+{
+    InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
+    if (!module.hasNoValue())
+        module.dropTraceLog(errorString, traceLogId);
+}
+
+void InspectorCanvasAgent::hasUninstrumentedCanvases(ErrorString* errorString, bool* result)
+{
+    if (!checkIsEnabled(errorString))
+        return;
+    for (FramesWithUninstrumentedCanvases::iterator it = m_framesWithUninstrumentedCanvases.begin(); it != m_framesWithUninstrumentedCanvases.end(); ++it) {
+        if (it->value) {
+            *result = true;
+            return;
+        }
+    }
+    *result = false;
+}
+
+void InspectorCanvasAgent::captureFrame(ErrorString* errorString, const FrameId* frameId, TraceLogId* traceLogId)
+{
+    Frame* frame = frameId ? m_pageAgent->assertFrame(errorString, *frameId) : m_pageAgent->mainFrame();
+    if (!frame)
+        return;
+    InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, mainWorldScriptState(frame));
+    if (!module.hasNoValue())
+        module.captureFrame(errorString, traceLogId);
+}
+
+void InspectorCanvasAgent::startCapturing(ErrorString* errorString, const FrameId* frameId, TraceLogId* traceLogId)
+{
+    Frame* frame = frameId ? m_pageAgent->assertFrame(errorString, *frameId) : m_pageAgent->mainFrame();
+    if (!frame)
+        return;
+    InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, mainWorldScriptState(frame));
+    if (!module.hasNoValue())
+        module.startCapturing(errorString, traceLogId);
+}
+
+void InspectorCanvasAgent::stopCapturing(ErrorString* errorString, const TraceLogId& traceLogId)
+{
+    InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
+    if (!module.hasNoValue())
+        module.stopCapturing(errorString, traceLogId);
+}
+
+void InspectorCanvasAgent::getTraceLog(ErrorString* errorString, const TraceLogId& traceLogId, const int* startOffset, const int* maxLength, RefPtr<TraceLog>& traceLog)
+{
+    InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
+    if (!module.hasNoValue())
+        module.traceLog(errorString, traceLogId, startOffset, maxLength, &traceLog);
+}
+
+void InspectorCanvasAgent::replayTraceLog(ErrorString* errorString, const TraceLogId& traceLogId, int stepNo, RefPtr<ResourceState>& result)
+{
+    InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
+    if (!module.hasNoValue())
+        module.replayTraceLog(errorString, traceLogId, stepNo, &result);
+}
+
+void InspectorCanvasAgent::getResourceInfo(ErrorString* errorString, const ResourceId& resourceId, RefPtr<ResourceInfo>& result)
+{
+    InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, resourceId);
+    if (!module.hasNoValue())
+        module.resourceInfo(errorString, resourceId, &result);
+}
+
+void InspectorCanvasAgent::getResourceState(ErrorString* errorString, const TraceLogId& traceLogId, const ResourceId& resourceId, RefPtr<ResourceState>& result)
+{
+    InjectedScriptCanvasModule module = injectedScriptCanvasModule(errorString, traceLogId);
+    if (!module.hasNoValue())
+        module.resourceState(errorString, traceLogId, resourceId, &result);
+}
+
+ScriptObject InspectorCanvasAgent::wrapCanvas2DRenderingContextForInstrumentation(const ScriptObject& context)
+{
+    ErrorString error;
+    InjectedScriptCanvasModule module = injectedScriptCanvasModule(&error, context);
+    if (module.hasNoValue())
+        return ScriptObject();
+    return notifyRenderingContextWasWrapped(module.wrapCanvas2DContext(context));
+}
+
+ScriptObject InspectorCanvasAgent::wrapWebGLRenderingContextForInstrumentation(const ScriptObject& glContext)
+{
+    ErrorString error;
+    InjectedScriptCanvasModule module = injectedScriptCanvasModule(&error, glContext);
+    if (module.hasNoValue())
+        return ScriptObject();
+    return notifyRenderingContextWasWrapped(module.wrapWebGLContext(glContext));
+}
+
+ScriptObject InspectorCanvasAgent::notifyRenderingContextWasWrapped(const ScriptObject& wrappedContext)
+{
+    ASSERT(m_frontend);
+    ScriptState* scriptState = wrappedContext.scriptState();
+    DOMWindow* domWindow = scriptState ? domWindowFromScriptState(scriptState) : 0;
+    Frame* frame = domWindow ? domWindow->frame() : 0;
+    if (frame && !m_framesWithUninstrumentedCanvases.contains(frame))
+        m_framesWithUninstrumentedCanvases.set(frame, false);
+    String frameId = m_pageAgent->frameId(frame);
+    if (!frameId.isEmpty())
+        m_frontend->contextCreated(frameId);
+    return wrappedContext;
+}
+
+InjectedScriptCanvasModule InspectorCanvasAgent::injectedScriptCanvasModule(ErrorString* errorString, ScriptState* scriptState)
+{
+    if (!checkIsEnabled(errorString))
+        return InjectedScriptCanvasModule();
+    InjectedScriptCanvasModule module = InjectedScriptCanvasModule::moduleForState(m_injectedScriptManager, scriptState);
+    if (module.hasNoValue()) {
+        ASSERT_NOT_REACHED();
+        *errorString = "Internal error: no Canvas module";
+    }
+    return module;
+}
+
+InjectedScriptCanvasModule InspectorCanvasAgent::injectedScriptCanvasModule(ErrorString* errorString, const ScriptObject& scriptObject)
+{
+    if (!checkIsEnabled(errorString))
+        return InjectedScriptCanvasModule();
+    if (scriptObject.hasNoValue()) {
+        ASSERT_NOT_REACHED();
+        *errorString = "Internal error: original ScriptObject has no value";
+        return InjectedScriptCanvasModule();
+    }
+    return injectedScriptCanvasModule(errorString, scriptObject.scriptState());
+}
+
+InjectedScriptCanvasModule InspectorCanvasAgent::injectedScriptCanvasModule(ErrorString* errorString, const String& objectId)
+{
+    if (!checkIsEnabled(errorString))
+        return InjectedScriptCanvasModule();
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
+    if (injectedScript.hasNoValue()) {
+        *errorString = "Inspected frame has gone";
+        return InjectedScriptCanvasModule();
+    }
+    return injectedScriptCanvasModule(errorString, injectedScript.scriptState());
+}
+
+void InspectorCanvasAgent::findFramesWithUninstrumentedCanvases()
+{
+    class NodeVisitor : public WrappedNodeVisitor {
+    public:
+        NodeVisitor(Page* page, FramesWithUninstrumentedCanvases& result)
+            : m_page(page)
+            , m_framesWithUninstrumentedCanvases(result)
+        {
+        }
+
+        virtual void visitNode(Node* node) OVERRIDE
+        {
+            if (!node->hasTagName(HTMLNames::canvasTag) || !node->document() || !node->document()->frame())
+                return;
+            
+            Frame* frame = node->document()->frame();
+            if (frame->page() != m_page)
+                return;
+
+            HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(node);
+            if (canvas->renderingContext())
+                m_framesWithUninstrumentedCanvases.set(frame, true);
+        }
+
+    private:
+        Page* m_page;
+        FramesWithUninstrumentedCanvases& m_framesWithUninstrumentedCanvases;
+    } nodeVisitor(m_pageAgent->page(), m_framesWithUninstrumentedCanvases);
+
+    m_framesWithUninstrumentedCanvases.clear();
+    ScriptProfiler::visitNodeWrappers(&nodeVisitor);
+
+    for (FramesWithUninstrumentedCanvases::iterator it = m_framesWithUninstrumentedCanvases.begin(); it != m_framesWithUninstrumentedCanvases.end(); ++it) {
+        String frameId = m_pageAgent->frameId(it->key);
+        if (!frameId.isEmpty())
+            m_frontend->contextCreated(frameId);
+    }
+}
+
+bool InspectorCanvasAgent::checkIsEnabled(ErrorString* errorString) const
+{
+    if (m_enabled)
+        return true;
+    *errorString = "Canvas agent is not enabled";
+    return false;
+}
+
+void InspectorCanvasAgent::frameNavigated(Frame* frame)
+{
+    if (!m_enabled)
+        return;
+    if (frame == m_pageAgent->mainFrame()) {
+        for (FramesWithUninstrumentedCanvases::iterator it = m_framesWithUninstrumentedCanvases.begin(); it != m_framesWithUninstrumentedCanvases.end(); ++it)
+            m_framesWithUninstrumentedCanvases.set(it->key, false);
+        m_frontend->traceLogsRemoved(0, 0);
+    } else {
+        while (frame) {
+            if (m_framesWithUninstrumentedCanvases.contains(frame))
+                m_framesWithUninstrumentedCanvases.set(frame, false);
+            if (m_pageAgent->hasIdForFrame(frame)) {
+                String frameId = m_pageAgent->frameId(frame);
+                m_frontend->traceLogsRemoved(&frameId, 0);
+            }
+            frame = frame->tree()->traverseNext();
+        }
+    }
+}
+
+void InspectorCanvasAgent::frameDetachedFromParent(Frame* frame)
+{
+    if (m_enabled)
+        m_framesWithUninstrumentedCanvases.remove(frame);
+}
+
+void InspectorCanvasAgent::didBeginFrame()
+{
+    if (!m_enabled)
+        return;
+    ErrorString error;
+    for (FramesWithUninstrumentedCanvases::iterator it = m_framesWithUninstrumentedCanvases.begin(); it != m_framesWithUninstrumentedCanvases.end(); ++it) {
+        InjectedScriptCanvasModule module = injectedScriptCanvasModule(&error, mainWorldScriptState(it->key));
+        if (!module.hasNoValue())
+            module.markFrameEnd();
+    }
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorCanvasAgent.h b/Source/core/inspector/InspectorCanvasAgent.h
new file mode 100644
index 0000000..b672cd0
--- /dev/null
+++ b/Source/core/inspector/InspectorCanvasAgent.h
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+#ifndef InspectorCanvasAgent_h
+#define InspectorCanvasAgent_h
+
+
+#include "InspectorFrontend.h"
+#include "InspectorTypeBuilder.h"
+#include "bindings/v8/ScriptState.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class Frame;
+class InjectedScriptCanvasModule;
+class InjectedScriptManager;
+class InspectorPageAgent;
+class InspectorState;
+class InstrumentingAgents;
+class ScriptObject;
+
+typedef String ErrorString;
+
+class InspectorCanvasAgent : public InspectorBaseAgent<InspectorCanvasAgent>, public InspectorBackendDispatcher::CanvasCommandHandler {
+public:
+    static PassOwnPtr<InspectorCanvasAgent> create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InspectorPageAgent* pageAgent, InjectedScriptManager* injectedScriptManager)
+    {
+        return adoptPtr(new InspectorCanvasAgent(instrumentingAgents, state, pageAgent, injectedScriptManager));
+    }
+    ~InspectorCanvasAgent();
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void restore();
+
+    void frameNavigated(Frame*);
+    void frameDetachedFromParent(Frame*);
+    void didBeginFrame();
+
+    // Called from InspectorCanvasInstrumentation.
+    ScriptObject wrapCanvas2DRenderingContextForInstrumentation(const ScriptObject&);
+    ScriptObject wrapWebGLRenderingContextForInstrumentation(const ScriptObject&);
+
+    // Called from the front-end.
+    virtual void enable(ErrorString*);
+    virtual void disable(ErrorString*);
+    virtual void dropTraceLog(ErrorString*, const TypeBuilder::Canvas::TraceLogId&);
+    virtual void hasUninstrumentedCanvases(ErrorString*, bool*);
+    virtual void captureFrame(ErrorString*, const TypeBuilder::Network::FrameId*, TypeBuilder::Canvas::TraceLogId*);
+    virtual void startCapturing(ErrorString*, const TypeBuilder::Network::FrameId*, TypeBuilder::Canvas::TraceLogId*);
+    virtual void stopCapturing(ErrorString*, const TypeBuilder::Canvas::TraceLogId&);
+    virtual void getTraceLog(ErrorString*, const TypeBuilder::Canvas::TraceLogId&, const int*, const int*, RefPtr<TypeBuilder::Canvas::TraceLog>&);
+    virtual void replayTraceLog(ErrorString*, const TypeBuilder::Canvas::TraceLogId&, int, RefPtr<TypeBuilder::Canvas::ResourceState>&);
+    virtual void getResourceInfo(ErrorString*, const TypeBuilder::Canvas::ResourceId&, RefPtr<TypeBuilder::Canvas::ResourceInfo>&);
+    virtual void getResourceState(ErrorString*, const TypeBuilder::Canvas::TraceLogId&, const TypeBuilder::Canvas::ResourceId&, RefPtr<TypeBuilder::Canvas::ResourceState>&);
+
+private:
+    InspectorCanvasAgent(InstrumentingAgents*, InspectorCompositeState*, InspectorPageAgent*, InjectedScriptManager*);
+
+    InjectedScriptCanvasModule injectedScriptCanvasModule(ErrorString*, ScriptState*);
+    InjectedScriptCanvasModule injectedScriptCanvasModule(ErrorString*, const ScriptObject&);
+    InjectedScriptCanvasModule injectedScriptCanvasModule(ErrorString*, const String&);
+
+    void findFramesWithUninstrumentedCanvases();
+    bool checkIsEnabled(ErrorString*) const;
+    ScriptObject notifyRenderingContextWasWrapped(const ScriptObject&);
+
+    InspectorPageAgent* m_pageAgent;
+    InjectedScriptManager* m_injectedScriptManager;
+    InspectorFrontend::Canvas* m_frontend;
+    bool m_enabled;
+    // Contains all frames with canvases, value is true only for frames that have an uninstrumented canvas.
+    typedef HashMap<Frame*, bool> FramesWithUninstrumentedCanvases;
+    FramesWithUninstrumentedCanvases m_framesWithUninstrumentedCanvases;
+};
+
+} // namespace WebCore
+
+
+#endif // !defined(InspectorCanvasAgent_h)
diff --git a/Source/core/inspector/InspectorCanvasInstrumentation.h b/Source/core/inspector/InspectorCanvasInstrumentation.h
new file mode 100644
index 0000000..efdf7ec
--- /dev/null
+++ b/Source/core/inspector/InspectorCanvasInstrumentation.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifndef InspectorCanvasInstrumentation_h
+#define InspectorCanvasInstrumentation_h
+
+#include "bindings/v8/ScriptObject.h"
+#include "core/inspector/InspectorCanvasAgent.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include <wtf/UnusedParam.h>
+
+namespace WebCore {
+
+namespace InspectorInstrumentation {
+
+inline ScriptObject wrapCanvas2DRenderingContextForInstrumentation(Document* document, const ScriptObject& context)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document)) {
+        if (InspectorCanvasAgent* canvasAgent = instrumentingAgents->inspectorCanvasAgent())
+            return canvasAgent->wrapCanvas2DRenderingContextForInstrumentation(context);
+    }
+    return ScriptObject();
+}
+
+inline ScriptObject wrapWebGLRenderingContextForInstrumentation(Document* document, const ScriptObject& glContext)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document)) {
+        if (InspectorCanvasAgent* canvasAgent = instrumentingAgents->inspectorCanvasAgent())
+            return canvasAgent->wrapWebGLRenderingContextForInstrumentation(glContext);
+    }
+    return ScriptObject();
+}
+
+} // namespace InspectorInstrumentation
+
+} // namespace WebCore
+
+#endif // !defined(InspectorCanvasInstrumentation_h)
diff --git a/Source/core/inspector/InspectorClient.cpp b/Source/core/inspector/InspectorClient.cpp
new file mode 100644
index 0000000..3bb1c62
--- /dev/null
+++ b/Source/core/inspector/InspectorClient.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorClient.h"
+
+#include "bindings/v8/ScriptController.h"
+#include "bindings/v8/ScriptSourceCode.h"
+#include "bindings/v8/ScriptValue.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+
+namespace WebCore {
+
+bool InspectorClient::doDispatchMessageOnFrontendPage(Page* frontendPage, const String& message)
+{
+    if (!frontendPage)
+        return false;
+
+    Frame* frame = frontendPage->mainFrame();
+    if (!frame)
+        return false;
+
+    ScriptController* scriptController = frame->script();
+    if (!scriptController)
+        return false;
+
+    String dispatchToFrontend = "InspectorFrontendAPI.dispatchMessageAsync(" + message + ");";
+
+    // FIXME: This should execute the script in the appropriate world.
+    scriptController->evaluate(ScriptSourceCode(dispatchToFrontend));
+    return true;
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorClient.h b/Source/core/inspector/InspectorClient.h
new file mode 100644
index 0000000..2b95404
--- /dev/null
+++ b/Source/core/inspector/InspectorClient.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2011 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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. 
+ */
+
+#ifndef InspectorClient_h
+#define InspectorClient_h
+
+#include "core/inspector/InspectorStateClient.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+
+namespace WebCore {
+
+class InspectorController;
+class InspectorFrontendChannel;
+class Frame;
+class Page;
+
+class InspectorClient : public InspectorStateClient {
+public:
+    virtual void highlight() = 0;
+    virtual void hideHighlight() = 0;
+
+    virtual void clearBrowserCache() { }
+    virtual void clearBrowserCookies() { }
+
+    typedef void (*TraceEventCallback)(char phase, const unsigned char*, const char* name, unsigned long long id,
+        int numArgs, const char* const* argNames, const unsigned char* argTypes, const unsigned long long* argValues,
+        unsigned char flags);
+    virtual void setTraceEventCallback(TraceEventCallback) { }
+
+    virtual void overrideDeviceMetrics(int /*width*/, int /*height*/, float /*fontScaleFactor*/, bool /*fitWindow*/) { }
+    virtual void autoZoomPageToFitWidth() { }
+
+    virtual bool overridesShowPaintRects() { return false; }
+    virtual void setShowPaintRects(bool) { }
+
+    virtual void setShowDebugBorders(bool) { }
+
+    virtual bool canShowFPSCounter() { return false; }
+    virtual void setShowFPSCounter(bool) { }
+
+    virtual bool canContinuouslyPaint() { return false; }
+    virtual void setContinuousPaintingEnabled(bool) { }
+
+    virtual void getAllocatedObjects(HashSet<const void*>&) { }
+    virtual void dumpUncountedAllocatedObjects(const HashMap<const void*, size_t>&) { }
+
+    static bool doDispatchMessageOnFrontendPage(Page* frontendPage, const String& message);
+
+protected:
+    virtual ~InspectorClient() { }
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorClient_h)
diff --git a/Source/core/inspector/InspectorConsoleAgent.cpp b/Source/core/inspector/InspectorConsoleAgent.cpp
new file mode 100644
index 0000000..1aff9ac
--- /dev/null
+++ b/Source/core/inspector/InspectorConsoleAgent.cpp
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2011 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:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+
+#include "config.h"
+#include "core/inspector/InspectorConsoleAgent.h"
+
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptCallStackFactory.h"
+#include "bindings/v8/ScriptController.h"
+#include "bindings/v8/ScriptObject.h"
+#include "bindings/v8/ScriptProfiler.h"
+#include "core/inspector/ConsoleMessage.h"
+#include "core/inspector/InjectedScriptHost.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/inspector/ScriptArguments.h"
+#include "core/inspector/ScriptCallFrame.h"
+#include "core/inspector/ScriptCallStack.h"
+#include "core/page/Console.h"
+#include "core/page/DOMWindow.h"
+#include "core/platform/network/ResourceError.h"
+#include "core/platform/network/ResourceResponse.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+static const unsigned maximumConsoleMessages = 1000;
+static const int expireConsoleMessagesStep = 100;
+
+namespace ConsoleAgentState {
+static const char monitoringXHR[] = "monitoringXHR";
+static const char consoleMessagesEnabled[] = "consoleMessagesEnabled";
+}
+
+int InspectorConsoleAgent::s_enabledAgentCount = 0;
+
+InspectorConsoleAgent::InspectorConsoleAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager)
+    : InspectorBaseAgent<InspectorConsoleAgent>("Console", instrumentingAgents, state)
+    , m_injectedScriptManager(injectedScriptManager)
+    , m_frontend(0)
+    , m_previousMessage(0)
+    , m_expiredConsoleMessageCount(0)
+    , m_enabled(false)
+{
+    m_instrumentingAgents->setInspectorConsoleAgent(this);
+}
+
+InspectorConsoleAgent::~InspectorConsoleAgent()
+{
+    m_instrumentingAgents->setInspectorConsoleAgent(0);
+    m_instrumentingAgents = 0;
+    m_state = 0;
+    m_injectedScriptManager = 0;
+}
+
+void InspectorConsoleAgent::enable(ErrorString*)
+{
+    if (m_enabled)
+        return;
+    m_enabled = true;
+    if (!s_enabledAgentCount)
+        ScriptController::setCaptureCallStackForUncaughtExceptions(true);
+    ++s_enabledAgentCount;
+
+    m_state->setBoolean(ConsoleAgentState::consoleMessagesEnabled, true);
+
+    if (m_expiredConsoleMessageCount) {
+        ConsoleMessage expiredMessage(!isWorkerAgent(), OtherMessageSource, LogMessageType, WarningMessageLevel, String::format("%d console messages are not shown.", m_expiredConsoleMessageCount));
+        expiredMessage.addToFrontend(m_frontend, m_injectedScriptManager, false);
+    }
+
+    size_t messageCount = m_consoleMessages.size();
+    for (size_t i = 0; i < messageCount; ++i)
+        m_consoleMessages[i]->addToFrontend(m_frontend, m_injectedScriptManager, false);
+}
+
+void InspectorConsoleAgent::disable(ErrorString*)
+{
+    if (!m_enabled)
+        return;
+    m_enabled = false;
+    if (!(--s_enabledAgentCount))
+        ScriptController::setCaptureCallStackForUncaughtExceptions(false);
+    m_state->setBoolean(ConsoleAgentState::consoleMessagesEnabled, false);
+}
+
+void InspectorConsoleAgent::clearMessages(ErrorString*)
+{
+    m_consoleMessages.clear();
+    m_expiredConsoleMessageCount = 0;
+    m_previousMessage = 0;
+    m_injectedScriptManager->releaseObjectGroup("console");
+    if (m_frontend && m_enabled)
+        m_frontend->messagesCleared();
+}
+
+void InspectorConsoleAgent::reset()
+{
+    ErrorString error;
+    clearMessages(&error);
+    m_times.clear();
+    m_counts.clear();
+}
+
+void InspectorConsoleAgent::restore()
+{
+    if (m_state->getBoolean(ConsoleAgentState::consoleMessagesEnabled)) {
+        m_frontend->messagesCleared();
+        ErrorString error;
+        enable(&error);
+    }
+}
+
+void InspectorConsoleAgent::setFrontend(InspectorFrontend* frontend)
+{
+    m_frontend = frontend->console();
+}
+
+void InspectorConsoleAgent::clearFrontend()
+{
+    m_frontend = 0;
+    String errorString;
+    disable(&errorString);
+}
+
+void InspectorConsoleAgent::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptCallStack> callStack, unsigned long requestIdentifier)
+{
+    if (type == ClearMessageType) {
+        ErrorString error;
+        clearMessages(&error);
+    }
+
+    addConsoleMessage(adoptPtr(new ConsoleMessage(!isWorkerAgent(), source, type, level, message, callStack, requestIdentifier)));
+}
+
+void InspectorConsoleAgent::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, const String& message, ScriptState* state, PassRefPtr<ScriptArguments> arguments, unsigned long requestIdentifier)
+{
+    if (type == ClearMessageType) {
+        ErrorString error;
+        clearMessages(&error);
+    }
+
+    addConsoleMessage(adoptPtr(new ConsoleMessage(!isWorkerAgent(), source, type, level, message, arguments, state, requestIdentifier)));
+}
+
+void InspectorConsoleAgent::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, const String& message, const String& scriptId, unsigned lineNumber, ScriptState* state, unsigned long requestIdentifier)
+{
+    if (type == ClearMessageType) {
+        ErrorString error;
+        clearMessages(&error);
+    }
+
+    // Ignore errors like "*property=value". This trick is used for IE7: http://stackoverflow.com/questions/4563651/what-does-an-asterisk-do-in-a-css-property-name
+    if (source == CSSMessageSource && message.contains(": *"))
+        return;
+
+    bool canGenerateCallStack = !isWorkerAgent() && m_frontend;
+    addConsoleMessage(adoptPtr(new ConsoleMessage(canGenerateCallStack, source, type, level, message, scriptId, lineNumber, state, requestIdentifier)));
+}
+
+Vector<unsigned> InspectorConsoleAgent::consoleMessageArgumentCounts()
+{
+    Vector<unsigned> result(m_consoleMessages.size());
+    for (size_t i = 0; i < m_consoleMessages.size(); i++)
+        result[i] = m_consoleMessages[i]->argumentCount();
+    return result;
+}
+
+void InspectorConsoleAgent::startTiming(const String& title)
+{
+    // Follow Firebug's behavior of requiring a title that is not null or
+    // undefined for timing functions
+    if (title.isNull())
+        return;
+
+    m_times.add(title, monotonicallyIncreasingTime());
+}
+
+void InspectorConsoleAgent::stopTiming(const String& title, PassRefPtr<ScriptCallStack> callStack)
+{
+    // Follow Firebug's behavior of requiring a title that is not null or
+    // undefined for timing functions
+    if (title.isNull())
+        return;
+
+    HashMap<String, double>::iterator it = m_times.find(title);
+    if (it == m_times.end())
+        return;
+
+    double startTime = it->value;
+    m_times.remove(it);
+
+    double elapsed = monotonicallyIncreasingTime() - startTime;
+    String message = title + String::format(": %.3fms", elapsed * 1000);
+    const ScriptCallFrame& lastCaller = callStack->at(0);
+    addMessageToConsole(ConsoleAPIMessageSource, TimingMessageType, DebugMessageLevel, message, lastCaller.sourceURL(), lastCaller.lineNumber());
+}
+
+void InspectorConsoleAgent::count(ScriptState* state, PassRefPtr<ScriptArguments> arguments)
+{
+    RefPtr<ScriptCallStack> callStack(createScriptCallStackForConsole(state));
+    const ScriptCallFrame& lastCaller = callStack->at(0);
+    // Follow Firebug's behavior of counting with null and undefined title in
+    // the same bucket as no argument
+    String title;
+    arguments->getFirstArgumentAsString(title);
+    String identifier = title.isEmpty() ? String(lastCaller.sourceURL() + ':' + String::number(lastCaller.lineNumber()))
+                                        : String(title + '@');
+
+    HashMap<String, unsigned>::iterator it = m_counts.find(identifier);
+    int count;
+    if (it == m_counts.end())
+        count = 1;
+    else {
+        count = it->value + 1;
+        m_counts.remove(it);
+    }
+
+    m_counts.add(identifier, count);
+
+    String message = title + ": " + String::number(count);
+    addMessageToConsole(ConsoleAPIMessageSource, LogMessageType, DebugMessageLevel, message, callStack);
+}
+
+void InspectorConsoleAgent::frameWindowDiscarded(DOMWindow* window)
+{
+    size_t messageCount = m_consoleMessages.size();
+    for (size_t i = 0; i < messageCount; ++i)
+        m_consoleMessages[i]->windowCleared(window);
+    m_injectedScriptManager->discardInjectedScriptsFor(window);
+}
+
+void InspectorConsoleAgent::didFinishXHRLoading(ThreadableLoaderClient*, unsigned long requestIdentifier, const String&, const String& url, const String& sendURL, unsigned sendLineNumber)
+{
+    if (m_frontend && m_state->getBoolean(ConsoleAgentState::monitoringXHR)) {
+        String message = "XHR finished loading: \"" + url + "\".";
+        addMessageToConsole(NetworkMessageSource, LogMessageType, DebugMessageLevel, message, sendURL, sendLineNumber, 0, requestIdentifier);
+    }
+
+
+}
+
+void InspectorConsoleAgent::didReceiveResourceResponse(unsigned long requestIdentifier, DocumentLoader* loader, const ResourceResponse& response, ResourceLoader*)
+{
+    if (!loader)
+        return;
+    if (response.httpStatusCode() >= 400) {
+        String message = "Failed to load resource: the server responded with a status of " + String::number(response.httpStatusCode()) + " (" + response.httpStatusText() + ')';
+        addMessageToConsole(NetworkMessageSource, LogMessageType, ErrorMessageLevel, message, response.url().string(), 0, 0, requestIdentifier);
+    }
+}
+
+void InspectorConsoleAgent::didFailLoading(unsigned long requestIdentifier, DocumentLoader*, const ResourceError& error)
+{
+    if (error.isCancellation()) // Report failures only.
+        return;
+    StringBuilder message;
+    message.appendLiteral("Failed to load resource");
+    if (!error.localizedDescription().isEmpty()) {
+        message.appendLiteral(": ");
+        message.append(error.localizedDescription());
+    }
+    addMessageToConsole(NetworkMessageSource, LogMessageType, ErrorMessageLevel, message.toString(), error.failingURL(), 0, 0, requestIdentifier);
+}
+
+void InspectorConsoleAgent::setMonitoringXHREnabled(ErrorString*, bool enabled)
+{
+    m_state->setBoolean(ConsoleAgentState::monitoringXHR, enabled);
+}
+
+static bool isGroupMessage(MessageType type)
+{
+    return type == StartGroupMessageType
+        || type ==  StartGroupCollapsedMessageType
+        || type == EndGroupMessageType;
+}
+
+void InspectorConsoleAgent::addConsoleMessage(PassOwnPtr<ConsoleMessage> consoleMessage)
+{
+    ASSERT_ARG(consoleMessage, consoleMessage);
+
+    if (m_previousMessage && !isGroupMessage(m_previousMessage->type()) && m_previousMessage->isEqual(consoleMessage.get())) {
+        m_previousMessage->incrementCount();
+        if (m_frontend && m_enabled)
+            m_previousMessage->updateRepeatCountInConsole(m_frontend);
+    } else {
+        m_previousMessage = consoleMessage.get();
+        m_consoleMessages.append(consoleMessage);
+        if (m_frontend && m_enabled)
+            m_previousMessage->addToFrontend(m_frontend, m_injectedScriptManager, true);
+    }
+
+    if (!m_frontend && m_consoleMessages.size() >= maximumConsoleMessages) {
+        m_expiredConsoleMessageCount += expireConsoleMessagesStep;
+        m_consoleMessages.remove(0, expireConsoleMessagesStep);
+    }
+}
+
+class InspectableHeapObject : public InjectedScriptHost::InspectableObject {
+public:
+    explicit InspectableHeapObject(int heapObjectId) : m_heapObjectId(heapObjectId) { }
+    virtual ScriptValue get(ScriptState*)
+    {
+        return ScriptProfiler::objectByHeapObjectId(m_heapObjectId);
+    }
+private:
+    int m_heapObjectId;
+};
+
+void InspectorConsoleAgent::addInspectedHeapObject(ErrorString*, int inspectedHeapObjectId)
+{
+    m_injectedScriptManager->injectedScriptHost()->addInspectedObject(adoptPtr(new InspectableHeapObject(inspectedHeapObjectId)));
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorConsoleAgent.h b/Source/core/inspector/InspectorConsoleAgent.h
new file mode 100644
index 0000000..23c7df1
--- /dev/null
+++ b/Source/core/inspector/InspectorConsoleAgent.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2011 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:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#ifndef InspectorConsoleAgent_h
+#define InspectorConsoleAgent_h
+
+
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptState.h"
+#include "core/inspector/ConsoleAPITypes.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include "core/page/ConsoleTypes.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class ConsoleMessage;
+class DocumentLoader;
+class DOMWindow;
+class InspectorFrontend;
+class InspectorState;
+class InjectedScriptManager;
+class InstrumentingAgents;
+class ResourceError;
+class ResourceLoader;
+class ResourceResponse;
+class ScriptArguments;
+class ScriptCallStack;
+class ScriptProfile;
+class ThreadableLoaderClient;
+
+typedef String ErrorString;
+
+class InspectorConsoleAgent : public InspectorBaseAgent<InspectorConsoleAgent>, public InspectorBackendDispatcher::ConsoleCommandHandler {
+    WTF_MAKE_NONCOPYABLE(InspectorConsoleAgent);
+public:
+    InspectorConsoleAgent(InstrumentingAgents*, InspectorCompositeState*, InjectedScriptManager*);
+    virtual ~InspectorConsoleAgent();
+
+    virtual void enable(ErrorString*);
+    virtual void disable(ErrorString*);
+    virtual void clearMessages(ErrorString*);
+    bool enabled() { return m_enabled; }
+    void reset();
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void restore();
+
+    void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, ScriptState*, PassRefPtr<ScriptArguments>, unsigned long requestIdentifier = 0);
+    void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, const String& scriptId, unsigned lineNumber, ScriptState* = 0, unsigned long requestIdentifier = 0);
+
+    // FIXME: Remove once we no longer generate stacks outside of Inspector.
+    void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, PassRefPtr<ScriptCallStack>, unsigned long requestIdentifier = 0);
+
+    Vector<unsigned> consoleMessageArgumentCounts();
+
+    void startTiming(const String& title);
+    void stopTiming(const String& title, PassRefPtr<ScriptCallStack>);
+    void count(ScriptState*, PassRefPtr<ScriptArguments>);
+
+    void frameWindowDiscarded(DOMWindow*);
+
+    void didFinishXHRLoading(ThreadableLoaderClient*, unsigned long requestIdentifier, const String&, const String& url, const String& sendURL, unsigned sendLineNumber);
+    void didReceiveResourceResponse(unsigned long requestIdentifier, DocumentLoader*, const ResourceResponse& response, ResourceLoader*);
+    void didFailLoading(unsigned long requestIdentifier, DocumentLoader*, const ResourceError&);
+    void addProfileFinishedMessageToConsole(PassRefPtr<ScriptProfile>, unsigned lineNumber, const String& sourceURL);
+    void addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL);
+    virtual void setMonitoringXHREnabled(ErrorString*, bool enabled);
+    virtual void addInspectedNode(ErrorString*, int nodeId) = 0;
+    virtual void addInspectedHeapObject(ErrorString*, int inspectedHeapObjectId);
+
+    virtual bool isWorkerAgent() = 0;
+
+protected:
+    void addConsoleMessage(PassOwnPtr<ConsoleMessage>);
+
+    InjectedScriptManager* m_injectedScriptManager;
+    InspectorFrontend::Console* m_frontend;
+    ConsoleMessage* m_previousMessage;
+    Vector<OwnPtr<ConsoleMessage> > m_consoleMessages;
+    int m_expiredConsoleMessageCount;
+    HashMap<String, unsigned> m_counts;
+    HashMap<String, double> m_times;
+    bool m_enabled;
+private:
+    static int s_enabledAgentCount;
+};
+
+} // namespace WebCore
+
+
+#endif // !defined(InspectorConsoleAgent_h)
diff --git a/Source/core/inspector/InspectorConsoleInstrumentation.h b/Source/core/inspector/InspectorConsoleInstrumentation.h
new file mode 100644
index 0000000..150400b
--- /dev/null
+++ b/Source/core/inspector/InspectorConsoleInstrumentation.h
@@ -0,0 +1,128 @@
+/*
+* Copyright (C) 2011 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.
+*/
+
+#ifndef InspectorConsoleInstrumentation_h
+#define InspectorConsoleInstrumentation_h
+
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/ScriptArguments.h"
+#include "core/inspector/ScriptCallStack.h"
+#include "core/inspector/ScriptProfile.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/UnusedParam.h>
+
+namespace WebCore {
+
+namespace InspectorInstrumentation {
+
+void addMessageToConsoleImpl(InstrumentingAgents*, MessageSource, MessageType, MessageLevel, const String& message, ScriptState*, PassRefPtr<ScriptArguments>, unsigned long requestIdentifier);
+void addMessageToConsoleImpl(InstrumentingAgents*, MessageSource, MessageType, MessageLevel, const String& message, const String& scriptId, unsigned lineNumber, ScriptState*, unsigned long requestIdentifier);
+// FIXME: Remove once we no longer generate stacks outside of Inspector.
+void addMessageToConsoleImpl(InstrumentingAgents*, MessageSource, MessageType, MessageLevel, const String& message, PassRefPtr<ScriptCallStack>, unsigned long requestIdentifier);
+void consoleCountImpl(InstrumentingAgents*, ScriptState*, PassRefPtr<ScriptArguments>);
+void startConsoleTimingImpl(InstrumentingAgents*, Frame*, const String& title);
+void stopConsoleTimingImpl(InstrumentingAgents*, Frame*, const String& title, PassRefPtr<ScriptCallStack>);
+void consoleTimeStampImpl(InstrumentingAgents*, Frame*, PassRefPtr<ScriptArguments>);
+void addStartProfilingMessageToConsoleImpl(InstrumentingAgents*, const String& title, unsigned lineNumber, const String& sourceURL);
+void addProfileImpl(InstrumentingAgents*, RefPtr<ScriptProfile>, PassRefPtr<ScriptCallStack>);
+
+inline void addMessageToConsole(Page* page, MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptCallStack> callStack, unsigned long requestIdentifier = 0)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        addMessageToConsoleImpl(instrumentingAgents, source, type, level, message, callStack, requestIdentifier);
+}
+
+inline void addMessageToConsole(Page* page, MessageSource source, MessageType type, MessageLevel level, const String& message, ScriptState* state, PassRefPtr<ScriptArguments> arguments, unsigned long requestIdentifier = 0)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        addMessageToConsoleImpl(instrumentingAgents, source, type, level, message, state, arguments, requestIdentifier);
+}
+
+inline void addMessageToConsole(Page* page, MessageSource source, MessageType type, MessageLevel level, const String& message, const String& scriptId, unsigned lineNumber, ScriptState* state = 0, unsigned long requestIdentifier = 0)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        addMessageToConsoleImpl(instrumentingAgents, source, type, level, message, scriptId, lineNumber, state, requestIdentifier);
+}
+
+// FIXME: Convert to ScriptArguments to match non-worker context.
+inline void addMessageToConsole(WorkerContext* workerContext, MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptCallStack> callStack, unsigned long requestIdentifier = 0)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForWorkerContext(workerContext))
+        addMessageToConsoleImpl(instrumentingAgents, source, type, level, message, callStack, requestIdentifier);
+}
+
+inline void addMessageToConsole(WorkerContext* workerContext, MessageSource source, MessageType type, MessageLevel level, const String& message, const String& scriptId, unsigned lineNumber, ScriptState* state, unsigned long requestIdentifier = 0)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForWorkerContext(workerContext))
+        addMessageToConsoleImpl(instrumentingAgents, source, type, level, message, scriptId, lineNumber, state, requestIdentifier);
+}
+
+inline void consoleCount(Page* page, ScriptState* state, PassRefPtr<ScriptArguments> arguments)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        consoleCountImpl(instrumentingAgents, state, arguments);
+}
+
+inline void startConsoleTiming(Frame* frame, const String& title)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        startConsoleTimingImpl(instrumentingAgents, frame, title);
+}
+
+inline void stopConsoleTiming(Frame* frame, const String& title, PassRefPtr<ScriptCallStack> stack)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        stopConsoleTimingImpl(instrumentingAgents, frame, title, stack);
+}
+
+inline void consoleTimeStamp(Frame* frame, PassRefPtr<ScriptArguments> arguments)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        consoleTimeStampImpl(instrumentingAgents, frame, arguments);
+}
+
+inline void addStartProfilingMessageToConsole(Page* page, const String& title, unsigned lineNumber, const String& sourceURL)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        addStartProfilingMessageToConsoleImpl(instrumentingAgents, title, lineNumber, sourceURL);
+}
+
+inline void addProfile(Page* page, RefPtr<ScriptProfile> profile, PassRefPtr<ScriptCallStack> callStack)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        addProfileImpl(instrumentingAgents, profile, callStack);
+}
+
+} // namespace InspectorInstrumentation
+
+} // namespace WebCore
+
+#endif // !defined(InspectorConsoleInstrumentation_h)
diff --git a/Source/core/inspector/InspectorController.cpp b/Source/core/inspector/InspectorController.cpp
new file mode 100644
index 0000000..f4de398
--- /dev/null
+++ b/Source/core/inspector/InspectorController.cpp
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorController.h"
+
+#include "InspectorBackendDispatcher.h"
+#include "InspectorFrontend.h"
+#include "bindings/v8/DOMWrapperWorld.h"
+#include "bindings/v8/ScriptObject.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/inspector/IdentifiersFactory.h"
+#include "core/inspector/InjectedScriptHost.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/InspectorAgent.h"
+#include "core/inspector/InspectorApplicationCacheAgent.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include "core/inspector/InspectorCSSAgent.h"
+#include "core/inspector/InspectorCanvasAgent.h"
+#include "core/inspector/InspectorClient.h"
+#include "core/inspector/InspectorDOMAgent.h"
+#include "core/inspector/InspectorDOMDebuggerAgent.h"
+#include "core/inspector/InspectorDOMStorageAgent.h"
+#include "core/inspector/InspectorDatabaseAgent.h"
+#include "core/inspector/InspectorDebuggerAgent.h"
+#include "core/inspector/InspectorFileSystemAgent.h"
+#include "core/inspector/InspectorFrontendClient.h"
+#include "core/inspector/InspectorHeapProfilerAgent.h"
+#include "core/inspector/InspectorIndexedDBAgent.h"
+#include "core/inspector/InspectorInputAgent.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/InspectorLayerTreeAgent.h"
+#include "core/inspector/InspectorMemoryAgent.h"
+#include "core/inspector/InspectorOverlay.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InspectorProfilerAgent.h"
+#include "core/inspector/InspectorResourceAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorTimelineAgent.h"
+#include "core/inspector/InspectorWorkerAgent.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/inspector/PageConsoleAgent.h"
+#include "core/inspector/PageDebuggerAgent.h"
+#include "core/inspector/PageRuntimeAgent.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/PlatformMouseEvent.h"
+#include "core/platform/PlatformTouchEvent.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include <wtf/MemoryInstrumentationVector.h>
+#include <wtf/UnusedParam.h>
+
+namespace WebCore {
+
+InspectorController::InspectorController(Page* page, InspectorClient* inspectorClient)
+    : m_instrumentingAgents(InstrumentingAgents::create())
+    , m_injectedScriptManager(InjectedScriptManager::createForPage())
+    , m_state(adoptPtr(new InspectorCompositeState(inspectorClient)))
+    , m_overlay(InspectorOverlay::create(page, inspectorClient))
+    , m_page(page)
+    , m_inspectorClient(inspectorClient)
+    , m_isUnderTest(false)
+{
+    OwnPtr<InspectorAgent> inspectorAgentPtr(InspectorAgent::create(page, m_injectedScriptManager.get(), m_instrumentingAgents.get(), m_state.get()));
+    m_inspectorAgent = inspectorAgentPtr.get();
+    m_agents.append(inspectorAgentPtr.release());
+
+    OwnPtr<InspectorPageAgent> pageAgentPtr(InspectorPageAgent::create(m_instrumentingAgents.get(), page, m_inspectorAgent, m_state.get(), m_injectedScriptManager.get(), inspectorClient, m_overlay.get()));
+    InspectorPageAgent* pageAgent = pageAgentPtr.get();
+    m_pageAgent = pageAgentPtr.get();
+    m_agents.append(pageAgentPtr.release());
+
+    OwnPtr<InspectorDOMAgent> domAgentPtr(InspectorDOMAgent::create(m_instrumentingAgents.get(), pageAgent, m_state.get(), m_injectedScriptManager.get(), m_overlay.get(), inspectorClient));
+    m_domAgent = domAgentPtr.get();
+    m_agents.append(domAgentPtr.release());
+
+    m_agents.append(InspectorCSSAgent::create(m_instrumentingAgents.get(), m_state.get(), m_domAgent));
+
+    OwnPtr<InspectorDatabaseAgent> databaseAgentPtr(InspectorDatabaseAgent::create(m_instrumentingAgents.get(), m_state.get()));
+    InspectorDatabaseAgent* databaseAgent = databaseAgentPtr.get();
+    m_agents.append(databaseAgentPtr.release());
+
+    m_agents.append(InspectorIndexedDBAgent::create(m_instrumentingAgents.get(), m_state.get(), m_injectedScriptManager.get(), pageAgent));
+
+    m_agents.append(InspectorFileSystemAgent::create(m_instrumentingAgents.get(), pageAgent, m_state.get()));
+
+    OwnPtr<InspectorDOMStorageAgent> domStorageAgentPtr(InspectorDOMStorageAgent::create(m_instrumentingAgents.get(), m_pageAgent, m_state.get()));
+    InspectorDOMStorageAgent* domStorageAgent = domStorageAgentPtr.get();
+    m_agents.append(domStorageAgentPtr.release());
+
+    OwnPtr<InspectorMemoryAgent> memoryAgentPtr(InspectorMemoryAgent::create(m_instrumentingAgents.get(), inspectorClient, m_state.get(), m_page));
+    m_memoryAgent = memoryAgentPtr.get();
+    m_agents.append(memoryAgentPtr.release());
+
+    m_agents.append(InspectorTimelineAgent::create(m_instrumentingAgents.get(), pageAgent, m_memoryAgent, m_state.get(), InspectorTimelineAgent::PageInspector,
+       inspectorClient));
+    m_agents.append(InspectorApplicationCacheAgent::create(m_instrumentingAgents.get(), m_state.get(), pageAgent));
+
+    OwnPtr<InspectorResourceAgent> resourceAgentPtr(InspectorResourceAgent::create(m_instrumentingAgents.get(), pageAgent, inspectorClient, m_state.get()));
+    m_resourceAgent = resourceAgentPtr.get();
+    m_agents.append(resourceAgentPtr.release());
+
+    OwnPtr<InspectorRuntimeAgent> runtimeAgentPtr(PageRuntimeAgent::create(m_instrumentingAgents.get(), m_state.get(), m_injectedScriptManager.get(), page, pageAgent));
+    InspectorRuntimeAgent* runtimeAgent = runtimeAgentPtr.get();
+    m_agents.append(runtimeAgentPtr.release());
+
+    OwnPtr<InspectorConsoleAgent> consoleAgentPtr(PageConsoleAgent::create(m_instrumentingAgents.get(), m_inspectorAgent, m_state.get(), m_injectedScriptManager.get(), m_domAgent));
+    InspectorConsoleAgent* consoleAgent = consoleAgentPtr.get();
+    m_agents.append(consoleAgentPtr.release());
+
+    OwnPtr<InspectorDebuggerAgent> debuggerAgentPtr(PageDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), pageAgent, m_injectedScriptManager.get(), m_overlay.get()));
+    m_debuggerAgent = debuggerAgentPtr.get();
+    m_agents.append(debuggerAgentPtr.release());
+
+    OwnPtr<InspectorDOMDebuggerAgent> domDebuggerAgentPtr(InspectorDOMDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), m_domAgent, m_debuggerAgent, m_inspectorAgent));
+    m_domDebuggerAgent = domDebuggerAgentPtr.get();
+    m_agents.append(domDebuggerAgentPtr.release());
+
+    OwnPtr<InspectorProfilerAgent> profilerAgentPtr(InspectorProfilerAgent::create(m_instrumentingAgents.get(), consoleAgent, page, m_state.get(), m_injectedScriptManager.get()));
+    m_profilerAgent = profilerAgentPtr.get();
+    m_agents.append(profilerAgentPtr.release());
+
+    m_agents.append(InspectorHeapProfilerAgent::create(m_instrumentingAgents.get(), m_state.get(), m_injectedScriptManager.get()));
+
+
+    m_agents.append(InspectorWorkerAgent::create(m_instrumentingAgents.get(), m_state.get()));
+
+    m_agents.append(InspectorCanvasAgent::create(m_instrumentingAgents.get(), m_state.get(), pageAgent, m_injectedScriptManager.get()));
+
+    m_agents.append(InspectorInputAgent::create(m_instrumentingAgents.get(), m_state.get(), page));
+
+    m_agents.append(InspectorLayerTreeAgent::create(m_instrumentingAgents.get(), m_state.get()));
+
+    ASSERT_ARG(inspectorClient, inspectorClient);
+    m_injectedScriptManager->injectedScriptHost()->init(m_inspectorAgent
+        , consoleAgent
+        , databaseAgent
+        , domStorageAgent
+        , m_domAgent
+        , m_debuggerAgent
+    );
+
+    runtimeAgent->setScriptDebugServer(&m_debuggerAgent->scriptDebugServer());
+}
+
+InspectorController::~InspectorController()
+{
+    m_instrumentingAgents->reset();
+    m_agents.discardAgents();
+    ASSERT(!m_inspectorClient);
+}
+
+PassOwnPtr<InspectorController> InspectorController::create(Page* page, InspectorClient* client)
+{
+    return adoptPtr(new InspectorController(page, client));
+}
+
+void InspectorController::inspectedPageDestroyed()
+{
+    disconnectFrontend();
+    m_injectedScriptManager->disconnect();
+    m_inspectorClient = 0;
+    m_page = 0;
+}
+
+void InspectorController::setInspectorFrontendClient(PassOwnPtr<InspectorFrontendClient> inspectorFrontendClient)
+{
+    m_inspectorFrontendClient = inspectorFrontendClient;
+}
+
+bool InspectorController::hasInspectorFrontendClient() const
+{
+    return m_inspectorFrontendClient;
+}
+
+void InspectorController::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld* world)
+{
+    if (world != mainThreadNormalWorld())
+        return;
+
+    // If the page is supposed to serve as InspectorFrontend notify inspector frontend
+    // client that it's cleared so that the client can expose inspector bindings.
+    if (m_inspectorFrontendClient && frame == m_page->mainFrame())
+        m_inspectorFrontendClient->windowObjectCleared();
+}
+
+void InspectorController::connectFrontend(InspectorFrontendChannel* frontendChannel)
+{
+    ASSERT(frontendChannel);
+
+    m_inspectorFrontend = adoptPtr(new InspectorFrontend(frontendChannel));
+    // We can reconnect to existing front-end -> unmute state.
+    m_state->unmute();
+
+    m_agents.setFrontend(m_inspectorFrontend.get());
+
+    InspectorInstrumentation::registerInstrumentingAgents(m_instrumentingAgents.get());
+    InspectorInstrumentation::frontendCreated();
+
+    ASSERT(m_inspectorClient);
+    m_inspectorBackendDispatcher = InspectorBackendDispatcher::create(frontendChannel);
+
+    m_agents.registerInDispatcher(m_inspectorBackendDispatcher.get());
+}
+
+void InspectorController::disconnectFrontend()
+{
+    if (!m_inspectorFrontend)
+        return;
+    m_inspectorBackendDispatcher->clearFrontend();
+    m_inspectorBackendDispatcher.clear();
+
+    // Destroying agents would change the state, but we don't want that.
+    // Pre-disconnect state will be used to restore inspector agents.
+    m_state->mute();
+
+    m_agents.clearFrontend();
+
+    m_inspectorFrontend.clear();
+
+    // relese overlay page resources
+    m_overlay->freePage();
+    InspectorInstrumentation::frontendDeleted();
+    InspectorInstrumentation::unregisterInstrumentingAgents(m_instrumentingAgents.get());
+}
+
+void InspectorController::reconnectFrontend(InspectorFrontendChannel* frontendChannel, const String& inspectorStateCookie)
+{
+    ASSERT(!m_inspectorFrontend);
+    connectFrontend(frontendChannel);
+    m_state->loadFromCookie(inspectorStateCookie);
+    m_agents.restore();
+}
+
+void InspectorController::setProcessId(long processId)
+{
+    IdentifiersFactory::setProcessId(processId);
+}
+
+void InspectorController::webViewResized(const IntSize& size)
+{
+    m_pageAgent->webViewResized(size);
+}
+
+bool InspectorController::isUnderTest()
+{
+    return m_isUnderTest;
+}
+
+void InspectorController::evaluateForTestInFrontend(long callId, const String& script)
+{
+    m_isUnderTest = true;
+    m_inspectorAgent->evaluateForTestInFrontend(callId, script);
+}
+
+void InspectorController::drawHighlight(GraphicsContext& context) const
+{
+    m_overlay->paint(context);
+}
+
+void InspectorController::getHighlight(Highlight* highlight) const
+{
+    m_overlay->getHighlight(highlight);
+}
+
+void InspectorController::inspect(Node* node)
+{
+    Document* document = node->ownerDocument();
+    if (!document)
+        return;
+    Frame* frame = document->frame();
+    if (!frame)
+        return;
+
+    if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)
+        node = node->parentNode();
+
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(mainWorldScriptState(frame));
+    if (injectedScript.hasNoValue())
+        return;
+    injectedScript.inspectNode(node);
+}
+
+Page* InspectorController::inspectedPage() const
+{
+    return m_page;
+}
+
+void InspectorController::setInjectedScriptForOrigin(const String& origin, const String& source)
+{
+    m_inspectorAgent->setInjectedScriptForOrigin(origin, source);
+}
+
+void InspectorController::dispatchMessageFromFrontend(const String& message)
+{
+    if (m_inspectorBackendDispatcher)
+        m_inspectorBackendDispatcher->dispatch(message);
+}
+
+void InspectorController::hideHighlight()
+{
+    ErrorString error;
+    m_domAgent->hideHighlight(&error);
+}
+
+Node* InspectorController::highlightedNode() const
+{
+    return m_overlay->highlightedNode();
+}
+
+bool InspectorController::handleMouseEvent(Frame* frame, const PlatformMouseEvent& event)
+{
+    if (event.type() == PlatformEvent::MouseMoved) {
+        m_domAgent->handleMouseMove(frame, event);
+        return false;
+    }
+    if (event.type() == PlatformEvent::MousePressed)
+        return m_domAgent->handleMousePress();
+    return false;
+}
+
+bool InspectorController::handleTouchEvent(Frame* frame, const PlatformTouchEvent& event)
+{
+    return m_domAgent->handleTouchEvent(frame, event);
+}
+
+bool InspectorController::profilerEnabled()
+{
+    return m_profilerAgent->enabled();
+}
+
+void InspectorController::setProfilerEnabled(bool enable)
+{
+    ErrorString error;
+    if (enable)
+        m_profilerAgent->enable(&error);
+    else
+        m_profilerAgent->disable(&error);
+}
+
+void InspectorController::resume()
+{
+    if (m_debuggerAgent) {
+        ErrorString error;
+        m_debuggerAgent->resume(&error);
+    }
+}
+
+void InspectorController::setResourcesDataSizeLimitsFromInternals(int maximumResourcesContentSize, int maximumSingleResourceContentSize)
+{
+    m_resourceAgent->setResourcesDataSizeLimitsFromInternals(maximumResourcesContentSize, maximumSingleResourceContentSize);
+}
+
+void InspectorController::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::InspectorController);
+    info.addMember(m_inspectorAgent, "inspectorAgent");
+    info.addMember(m_instrumentingAgents, "instrumentingAgents");
+    info.addMember(m_injectedScriptManager, "injectedScriptManager");
+    info.addMember(m_state, "state");
+    info.addMember(m_overlay, "overlay");
+
+    info.addMember(m_inspectorAgent, "inspectorAgent");
+    info.addMember(m_domAgent, "domAgent");
+    info.addMember(m_resourceAgent, "resourceAgent");
+    info.addMember(m_pageAgent, "pageAgent");
+    info.addMember(m_debuggerAgent, "debuggerAgent");
+    info.addMember(m_domDebuggerAgent, "domDebuggerAgent");
+    info.addMember(m_profilerAgent, "profilerAgent");
+
+    info.addMember(m_inspectorBackendDispatcher, "inspectorBackendDispatcher");
+    info.addMember(m_inspectorFrontendClient, "inspectorFrontendClient");
+    info.addMember(m_inspectorFrontend, "inspectorFrontend");
+    info.addMember(m_page, "page");
+    info.addWeakPointer(m_inspectorClient);
+    info.addMember(m_agents, "agents");
+}
+
+void InspectorController::willProcessTask()
+{
+    if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->willProcessTask();
+    m_profilerAgent->willProcessTask();
+}
+
+void InspectorController::didProcessTask()
+{
+    if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didProcessTask();
+    m_profilerAgent->didProcessTask();
+    m_domDebuggerAgent->didProcessTask();
+}
+
+void InspectorController::didBeginFrame()
+{
+    if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didBeginFrame();
+    if (InspectorCanvasAgent* canvasAgent = m_instrumentingAgents->inspectorCanvasAgent())
+        canvasAgent->didBeginFrame();
+}
+
+void InspectorController::didCancelFrame()
+{
+    if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didCancelFrame();
+}
+
+void InspectorController::willComposite()
+{
+    if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->willComposite();
+}
+
+void InspectorController::didComposite()
+{
+    if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didComposite();
+}
+
+HashMap<String, size_t> InspectorController::processMemoryDistribution() const
+{
+    HashMap<String, size_t> memoryInfo;
+    m_memoryAgent->getProcessMemoryDistributionMap(&memoryInfo);
+    return memoryInfo;
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/InspectorController.h b/Source/core/inspector/InspectorController.h
new file mode 100644
index 0000000..4e55403
--- /dev/null
+++ b/Source/core/inspector/InspectorController.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef InspectorController_h
+#define InspectorController_h
+
+
+#include "core/inspector/InspectorBaseAgent.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class DOMWrapperWorld;
+class Frame;
+class GraphicsContext;
+class InjectedScriptManager;
+class InspectorAgent;
+class InspectorApplicationCacheAgent;
+class InspectorBackendDispatcher;
+class InspectorBaseAgentInterface;
+class InspectorClient;
+class InspectorDOMAgent;
+class InspectorDOMDebuggerAgent;
+class InspectorDebuggerAgent;
+class InspectorFrontend;
+class InspectorFrontendChannel;
+class InspectorFrontendClient;
+class InspectorMemoryAgent;
+class InspectorOverlay;
+class InspectorPageAgent;
+class InspectorProfilerAgent;
+class InspectorResourceAgent;
+class InspectorState;
+class InstrumentingAgents;
+class IntSize;
+class Page;
+class PlatformMouseEvent;
+class PlatformTouchEvent;
+class PostWorkerNotificationToFrontendTask;
+class Node;
+
+struct Highlight;
+
+class InspectorController {
+    WTF_MAKE_NONCOPYABLE(InspectorController);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ~InspectorController();
+
+    static PassOwnPtr<InspectorController> create(Page*, InspectorClient*);
+    void inspectedPageDestroyed();
+
+    Page* inspectedPage() const;
+
+    void setInspectorFrontendClient(PassOwnPtr<InspectorFrontendClient>);
+    bool hasInspectorFrontendClient() const;
+    void didClearWindowObjectInWorld(Frame*, DOMWrapperWorld*);
+    void setInjectedScriptForOrigin(const String& origin, const String& source);
+
+    void dispatchMessageFromFrontend(const String& message);
+
+    bool hasFrontend() const { return m_inspectorFrontend; }
+    void connectFrontend(InspectorFrontendChannel*);
+    void disconnectFrontend();
+    void reconnectFrontend(InspectorFrontendChannel*, const String& inspectorStateCookie);
+    void setProcessId(long);
+    void webViewResized(const IntSize&);
+
+    void inspect(Node*);
+    void drawHighlight(GraphicsContext&) const;
+    void getHighlight(Highlight*) const;
+    void hideHighlight();
+    Node* highlightedNode() const;
+
+    bool handleMouseEvent(Frame*, const PlatformMouseEvent&);
+    bool handleTouchEvent(Frame*, const PlatformTouchEvent&);
+
+    bool isUnderTest();
+    void evaluateForTestInFrontend(long callId, const String& script);
+
+    bool profilerEnabled();
+    void setProfilerEnabled(bool);
+
+    void resume();
+
+    void setResourcesDataSizeLimitsFromInternals(int maximumResourcesContentSize, int maximumSingleResourceContentSize);
+
+    InspectorClient* inspectorClient() const { return m_inspectorClient; }
+    InspectorPageAgent* pageAgent() const { return m_pageAgent; }
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+    void willProcessTask();
+    void didProcessTask();
+
+    void didBeginFrame();
+    void didCancelFrame();
+    void willComposite();
+    void didComposite();
+
+    HashMap<String, size_t> processMemoryDistribution() const;
+
+private:
+    InspectorController(Page*, InspectorClient*);
+
+    friend class PostWorkerNotificationToFrontendTask;
+    friend InstrumentingAgents* instrumentationForPage(Page*);
+
+    RefPtr<InstrumentingAgents> m_instrumentingAgents;
+    OwnPtr<InjectedScriptManager> m_injectedScriptManager;
+    OwnPtr<InspectorCompositeState> m_state;
+    OwnPtr<InspectorOverlay> m_overlay;
+
+    InspectorAgent* m_inspectorAgent;
+    InspectorDOMAgent* m_domAgent;
+    InspectorResourceAgent* m_resourceAgent;
+    InspectorPageAgent* m_pageAgent;
+    InspectorMemoryAgent* m_memoryAgent;
+    InspectorDebuggerAgent* m_debuggerAgent;
+    InspectorDOMDebuggerAgent* m_domDebuggerAgent;
+    InspectorProfilerAgent* m_profilerAgent;
+
+    RefPtr<InspectorBackendDispatcher> m_inspectorBackendDispatcher;
+    OwnPtr<InspectorFrontendClient> m_inspectorFrontendClient;
+    OwnPtr<InspectorFrontend> m_inspectorFrontend;
+    Page* m_page;
+    InspectorClient* m_inspectorClient;
+    InspectorAgentRegistry m_agents;
+    bool m_isUnderTest;
+};
+
+}
+
+
+#endif // !defined(InspectorController_h)
diff --git a/Source/core/inspector/InspectorCounters.cpp b/Source/core/inspector/InspectorCounters.cpp
new file mode 100644
index 0000000..5082e09
--- /dev/null
+++ b/Source/core/inspector/InspectorCounters.cpp
@@ -0,0 +1,62 @@
+/*
+* 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.
+*/
+
+#include "config.h"
+#include "core/inspector/InspectorCounters.h"
+
+#include "core/platform/ThreadGlobalData.h"
+
+namespace WebCore {
+
+int InspectorCounters::s_counters[CounterTypeLength];
+
+int InspectorCounters::counterValue(CounterType type)
+{
+    return s_counters[type];
+}
+
+ThreadLocalInspectorCounters::ThreadLocalInspectorCounters()
+{
+    for (size_t i = 0; i < CounterTypeLength; i++)
+        m_counters[i] = 0;
+}
+
+int ThreadLocalInspectorCounters::counterValue(CounterType type)
+{
+    return m_counters[type];
+}
+
+ThreadLocalInspectorCounters& ThreadLocalInspectorCounters::current()
+{
+    return threadGlobalData().inspectorCounters();
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorCounters.h b/Source/core/inspector/InspectorCounters.h
new file mode 100644
index 0000000..d619d16
--- /dev/null
+++ b/Source/core/inspector/InspectorCounters.h
@@ -0,0 +1,102 @@
+/*
+* 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.
+*/
+
+#ifndef InspectorCounters_h
+#define InspectorCounters_h
+
+#include <wtf/FastAllocBase.h>
+#include <wtf/UnusedParam.h>
+
+#if !ASSERT_DISABLED
+#include <wtf/MainThread.h>
+#endif
+
+namespace WebCore {
+
+class InspectorCounters {
+public:
+    enum CounterType {
+        DocumentCounter,
+        NodeCounter,
+        JSEventListenerCounter,
+        CounterTypeLength
+    };
+
+    static inline void incrementCounter(CounterType type)
+    {
+        ASSERT(isMainThread());
+        ++s_counters[type];
+    }
+
+    static inline void decrementCounter(CounterType type)
+    {
+        ASSERT(isMainThread());
+        --s_counters[type];
+    }
+
+    static int counterValue(CounterType);
+
+private:
+    InspectorCounters();
+
+    static int s_counters[CounterTypeLength];
+};
+
+
+class ThreadLocalInspectorCounters {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    enum CounterType {
+        JSEventListenerCounter,
+        CounterTypeLength
+    };
+    ThreadLocalInspectorCounters();
+
+    inline void incrementCounter(CounterType type)
+    {
+        ++m_counters[type];
+    }
+
+    inline void decrementCounter(CounterType type)
+    {
+        --m_counters[type];
+    }
+
+    int counterValue(CounterType);
+
+    static ThreadLocalInspectorCounters& current();
+
+private:
+    int m_counters[CounterTypeLength];
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorCounters_h)
diff --git a/Source/core/inspector/InspectorDOMAgent.cpp b/Source/core/inspector/InspectorDOMAgent.cpp
new file mode 100644
index 0000000..7f1c772
--- /dev/null
+++ b/Source/core/inspector/InspectorDOMAgent.cpp
@@ -0,0 +1,1839 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorDOMAgent.h"
+
+#include "CSSPropertyNames.h"
+#include "HTMLNames.h"
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptEventListener.h"
+#include "core/css/CSSComputedStyleDeclaration.h"
+#include "core/css/CSSPropertySourceData.h"
+#include "core/css/CSSRule.h"
+#include "core/css/CSSRuleList.h"
+#include "core/css/CSSStyleRule.h"
+#include "core/css/CSSStyleSheet.h"
+#include "core/css/StylePropertySet.h"
+#include "core/css/StyleResolver.h"
+#include "core/css/StyleSheetList.h"
+#include "core/dom/Attr.h"
+#include "core/dom/CharacterData.h"
+#include "core/dom/ContainerNode.h"
+#include "core/dom/Document.h"
+#include "core/dom/DocumentFragment.h"
+#include "core/dom/DocumentType.h"
+#include "core/dom/Element.h"
+#include "core/dom/ElementShadow.h"
+#include "core/dom/Event.h"
+#include "core/dom/EventContext.h"
+#include "core/dom/EventListener.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/EventTarget.h"
+#include "core/dom/MutationEvent.h"
+#include "core/dom/Node.h"
+#include "core/dom/NodeList.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/dom/Text.h"
+#include "core/fileapi/File.h"
+#include "core/fileapi/FileList.h"
+#include "core/html/HTMLElement.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/html/HTMLInputElement.h"
+#include "core/html/HTMLTemplateElement.h"
+#include "core/inspector/DOMEditor.h"
+#include "core/inspector/DOMPatchSupport.h"
+#include "core/inspector/IdentifiersFactory.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/InspectorClient.h"
+#include "core/inspector/InspectorHistory.h"
+#include "core/inspector/InspectorOverlay.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/loader/CookieJar.h"
+#include "core/page/DOMWindow.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameTree.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/platform/Cookie.h"
+#include "core/platform/Pasteboard.h"
+#include "core/platform/PlatformMouseEvent.h"
+#include "core/platform/PlatformTouchEvent.h"
+#include "core/platform/graphics/IntRect.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+#include "core/xml/XPathResult.h"
+
+#include "core/editing/htmlediting.h"
+#include "core/editing/markup.h"
+
+#include <wtf/HashSet.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+namespace DOMAgentState {
+static const char documentRequested[] = "documentRequested";
+};
+
+static const size_t maxTextSize = 10000;
+static const UChar ellipsisUChar[] = { 0x2026, 0 };
+
+static Color parseColor(const RefPtr<InspectorObject>* colorObject)
+{
+    if (!colorObject || !(*colorObject))
+        return Color::transparent;
+
+    int r;
+    int g;
+    int b;
+    bool success = (*colorObject)->getNumber("r", &r);
+    success |= (*colorObject)->getNumber("g", &g);
+    success |= (*colorObject)->getNumber("b", &b);
+    if (!success)
+        return Color::transparent;
+
+    double a;
+    success = (*colorObject)->getNumber("a", &a);
+    if (!success)
+        return Color(r, g, b);
+
+    // Clamp alpha to the [0..1] range.
+    if (a < 0)
+        a = 0;
+    else if (a > 1)
+        a = 1;
+
+    return Color(r, g, b, static_cast<int>(a * 255));
+}
+
+static Color parseConfigColor(const String& fieldName, InspectorObject* configObject)
+{
+    const RefPtr<InspectorObject> colorObject = configObject->getObject(fieldName);
+    return parseColor(&colorObject);
+}
+
+static bool parseQuad(const RefPtr<InspectorArray>& quadArray, FloatQuad* quad)
+{
+    if (!quadArray)
+        return false;
+    const size_t coordinatesInQuad = 8;
+    double coordinates[coordinatesInQuad];
+    if (quadArray->length() != coordinatesInQuad)
+        return false;
+    for (size_t i = 0; i < coordinatesInQuad; ++i) {
+        if (!quadArray->get(i)->asNumber(coordinates + i))
+            return false;
+    }
+    quad->setP1(FloatPoint(coordinates[0], coordinates[1]));
+    quad->setP2(FloatPoint(coordinates[2], coordinates[3]));
+    quad->setP3(FloatPoint(coordinates[4], coordinates[5]));
+    quad->setP4(FloatPoint(coordinates[6], coordinates[7]));
+
+    return true;
+}
+
+static Node* hoveredNodeForPoint(Frame* frame, const IntPoint& point, bool ignorePointerEventsNone)
+{
+    HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::AllowChildFrameContent;
+    if (ignorePointerEventsNone)
+        hitType |= HitTestRequest::IgnorePointerEventsNone;
+    HitTestRequest request(hitType);
+    HitTestResult result(frame->view()->windowToContents(point));
+    frame->contentRenderer()->hitTest(request, result);
+    result.setToNonShadowAncestor();
+    Node* node = result.innerNode();
+    while (node && node->nodeType() == Node::TEXT_NODE)
+        node = node->parentNode();
+    return node;
+}
+
+static Node* hoveredNodeForEvent(Frame* frame, const PlatformMouseEvent& event, bool ignorePointerEventsNone)
+{
+    return hoveredNodeForPoint(frame, event.position(), ignorePointerEventsNone);
+}
+
+static Node* hoveredNodeForEvent(Frame* frame, const PlatformTouchEvent& event, bool ignorePointerEventsNone)
+{
+    const Vector<PlatformTouchPoint>& points = event.touchPoints();
+    if (!points.size())
+        return 0;
+    return hoveredNodeForPoint(frame, points[0].pos(), ignorePointerEventsNone);
+}
+
+class RevalidateStyleAttributeTask {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    RevalidateStyleAttributeTask(InspectorDOMAgent*);
+    void scheduleFor(Element*);
+    void reset() { m_timer.stop(); }
+    void onTimer(Timer<RevalidateStyleAttributeTask>*);
+
+private:
+    InspectorDOMAgent* m_domAgent;
+    Timer<RevalidateStyleAttributeTask> m_timer;
+    HashSet<RefPtr<Element> > m_elements;
+};
+
+RevalidateStyleAttributeTask::RevalidateStyleAttributeTask(InspectorDOMAgent* domAgent)
+    : m_domAgent(domAgent)
+    , m_timer(this, &RevalidateStyleAttributeTask::onTimer)
+{
+}
+
+void RevalidateStyleAttributeTask::scheduleFor(Element* element)
+{
+    m_elements.add(element);
+    if (!m_timer.isActive())
+        m_timer.startOneShot(0);
+}
+
+void RevalidateStyleAttributeTask::onTimer(Timer<RevalidateStyleAttributeTask>*)
+{
+    // The timer is stopped on m_domAgent destruction, so this method will never be called after m_domAgent has been destroyed.
+    Vector<Element*> elements;
+    for (HashSet<RefPtr<Element> >::iterator it = m_elements.begin(), end = m_elements.end(); it != end; ++it)
+        elements.append(it->get());
+    m_domAgent->styleAttributeInvalidated(elements);
+
+    m_elements.clear();
+}
+
+String InspectorDOMAgent::toErrorString(const ExceptionCode& ec)
+{
+    if (ec) {
+        ExceptionCodeDescription description(ec);
+        return description.name;
+    }
+    return "";
+}
+
+InspectorDOMAgent::InspectorDOMAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager, InspectorOverlay* overlay, InspectorClient* client)
+    : InspectorBaseAgent<InspectorDOMAgent>("DOM", instrumentingAgents, inspectorState)
+    , m_pageAgent(pageAgent)
+    , m_injectedScriptManager(injectedScriptManager)
+    , m_overlay(overlay)
+    , m_client(client)
+    , m_frontend(0)
+    , m_domListener(0)
+    , m_lastNodeId(1)
+    , m_lastBackendNodeId(-1)
+    , m_searchingForNode(false)
+    , m_suppressAttributeModifiedEvent(false)
+{
+}
+
+InspectorDOMAgent::~InspectorDOMAgent()
+{
+    reset();
+    ASSERT(!m_searchingForNode);
+}
+
+void InspectorDOMAgent::setFrontend(InspectorFrontend* frontend)
+{
+    ASSERT(!m_frontend);
+    m_history = adoptPtr(new InspectorHistory());
+    m_domEditor = adoptPtr(new DOMEditor(m_history.get()));
+
+    m_frontend = frontend->dom();
+    m_instrumentingAgents->setInspectorDOMAgent(this);
+    m_document = m_pageAgent->mainFrame()->document();
+}
+
+void InspectorDOMAgent::clearFrontend()
+{
+    ASSERT(m_frontend);
+
+    m_history.clear();
+    m_domEditor.clear();
+
+    ErrorString error;
+    setSearchingForNode(&error, false, 0);
+    hideHighlight(&error);
+
+    m_frontend = 0;
+    m_instrumentingAgents->setInspectorDOMAgent(0);
+    m_state->setBoolean(DOMAgentState::documentRequested, false);
+    reset();
+}
+
+void InspectorDOMAgent::restore()
+{
+    // Reset document to avoid early return from setDocument.
+    m_document = 0;
+    setDocument(m_pageAgent->mainFrame()->document());
+}
+
+Vector<Document*> InspectorDOMAgent::documents()
+{
+    Vector<Document*> result;
+    for (Frame* frame = m_document->frame(); frame; frame = frame->tree()->traverseNext()) {
+        Document* document = frame->document();
+        if (!document)
+            continue;
+        result.append(document);
+    }
+    return result;
+}
+
+void InspectorDOMAgent::reset()
+{
+    if (m_history)
+        m_history->reset();
+    m_searchResults.clear();
+    discardBindings();
+    if (m_revalidateStyleAttrTask)
+        m_revalidateStyleAttrTask->reset();
+    m_document = 0;
+}
+
+void InspectorDOMAgent::setDOMListener(DOMListener* listener)
+{
+    m_domListener = listener;
+}
+
+void InspectorDOMAgent::setDocument(Document* doc)
+{
+    if (doc == m_document.get())
+        return;
+
+    reset();
+
+    m_document = doc;
+
+    if (!m_state->getBoolean(DOMAgentState::documentRequested))
+        return;
+
+    // Immediately communicate 0 document or document that has finished loading.
+    if (!doc || !doc->parsing())
+        m_frontend->documentUpdated();
+}
+
+void InspectorDOMAgent::releaseDanglingNodes()
+{
+    m_danglingNodeToIdMaps.clear();
+}
+
+int InspectorDOMAgent::bind(Node* node, NodeToIdMap* nodesMap)
+{
+    int id = nodesMap->get(node);
+    if (id)
+        return id;
+    id = m_lastNodeId++;
+    nodesMap->set(node, id);
+    m_idToNode.set(id, node);
+    m_idToNodesMap.set(id, nodesMap);
+    return id;
+}
+
+void InspectorDOMAgent::unbind(Node* node, NodeToIdMap* nodesMap)
+{
+    int id = nodesMap->get(node);
+    if (!id)
+        return;
+
+    m_idToNode.remove(id);
+
+    if (node->isFrameOwnerElement()) {
+        const HTMLFrameOwnerElement* frameOwner = static_cast<const HTMLFrameOwnerElement*>(node);
+        Document* contentDocument = frameOwner->contentDocument();
+        if (m_domListener)
+            m_domListener->didRemoveDocument(contentDocument);
+        if (contentDocument)
+            unbind(contentDocument, nodesMap);
+    }
+
+    if (node->isElementNode()) {
+        if (ElementShadow* shadow = toElement(node)->shadow()) {
+            for (ShadowRoot* root = shadow->youngestShadowRoot(); root; root = root->olderShadowRoot())
+                unbind(root, nodesMap);
+        }
+    }
+
+    nodesMap->remove(node);
+    if (m_domListener)
+        m_domListener->didRemoveDOMNode(node);
+
+    bool childrenRequested = m_childrenRequested.contains(id);
+    if (childrenRequested) {
+        // Unbind subtree known to client recursively.
+        m_childrenRequested.remove(id);
+        Node* child = innerFirstChild(node);
+        while (child) {
+            unbind(child, nodesMap);
+            child = innerNextSibling(child);
+        }
+    }
+}
+
+Node* InspectorDOMAgent::assertNode(ErrorString* errorString, int nodeId)
+{
+    Node* node = nodeForId(nodeId);
+    if (!node) {
+        *errorString = "Could not find node with given id";
+        return 0;
+    }
+    return node;
+}
+
+Document* InspectorDOMAgent::assertDocument(ErrorString* errorString, int nodeId)
+{
+    Node* node = assertNode(errorString, nodeId);
+    if (!node)
+        return 0;
+
+    if (!(node->isDocumentNode())) {
+        *errorString = "Document is not available";
+        return 0;
+    }
+    return toDocument(node);
+}
+
+Element* InspectorDOMAgent::assertElement(ErrorString* errorString, int nodeId)
+{
+    Node* node = assertNode(errorString, nodeId);
+    if (!node)
+        return 0;
+
+    if (node->nodeType() != Node::ELEMENT_NODE) {
+        *errorString = "Node is not an Element";
+        return 0;
+    }
+    return toElement(node);
+}
+
+Node* InspectorDOMAgent::assertEditableNode(ErrorString* errorString, int nodeId)
+{
+    Node* node = assertNode(errorString, nodeId);
+    if (!node)
+        return 0;
+
+    if (node->isInShadowTree()) {
+        *errorString = "Can not edit nodes from shadow trees";
+        return 0;
+    }
+
+    return node;
+}
+
+Element* InspectorDOMAgent::assertEditableElement(ErrorString* errorString, int nodeId)
+{
+    Element* element = assertElement(errorString, nodeId);
+    if (!element)
+        return 0;
+
+    if (element->isInShadowTree()) {
+        *errorString = "Can not edit elements from shadow trees";
+        return 0;
+    }
+    return element;
+}
+
+void InspectorDOMAgent::getDocument(ErrorString* errorString, RefPtr<TypeBuilder::DOM::Node>& root)
+{
+    m_state->setBoolean(DOMAgentState::documentRequested, true);
+
+    if (!m_document) {
+        *errorString = "Document is not available";
+        return;
+    }
+
+    // Reset backend state.
+    RefPtr<Document> doc = m_document;
+    reset();
+    m_document = doc;
+
+    root = buildObjectForNode(m_document.get(), 2, &m_documentNodeToIdMap);
+}
+
+void InspectorDOMAgent::pushChildNodesToFrontend(int nodeId, int depth)
+{
+    Node* node = nodeForId(nodeId);
+    if (!node || (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE && node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE))
+        return;
+
+    NodeToIdMap* nodeMap = m_idToNodesMap.get(nodeId);
+
+    if (m_childrenRequested.contains(nodeId)) {
+        if (depth <= 1)
+            return;
+
+        depth--;
+
+        for (node = innerFirstChild(node); node; node = innerNextSibling(node)) {
+            int childNodeId = nodeMap->get(node);
+            ASSERT(childNodeId);
+            pushChildNodesToFrontend(childNodeId, depth);
+        }
+
+        return;
+    }
+
+    RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > children = buildArrayForContainerChildren(node, depth, nodeMap);
+    m_frontend->setChildNodes(nodeId, children.release());
+}
+
+void InspectorDOMAgent::discardBindings()
+{
+    m_documentNodeToIdMap.clear();
+    m_idToNode.clear();
+    releaseDanglingNodes();
+    m_childrenRequested.clear();
+    m_backendIdToNode.clear();
+    m_nodeGroupToBackendIdMap.clear();
+}
+
+int InspectorDOMAgent::pushNodeToFrontend(ErrorString* errorString, int documentNodeId, Node* nodeToPush)
+{
+    Document* document = assertDocument(errorString, documentNodeId);
+    if (!document)
+        return 0;
+    if (nodeToPush->document() != document) {
+        *errorString = "Node is not part of the document with given id";
+        return 0;
+    }
+
+    return pushNodePathToFrontend(nodeToPush);
+}
+
+Node* InspectorDOMAgent::nodeForId(int id)
+{
+    if (!id)
+        return 0;
+
+    HashMap<int, Node*>::iterator it = m_idToNode.find(id);
+    if (it != m_idToNode.end())
+        return it->value;
+    return 0;
+}
+
+void InspectorDOMAgent::requestChildNodes(ErrorString* errorString, int nodeId, const int* depth)
+{
+    int sanitizedDepth;
+
+    if (!depth)
+        sanitizedDepth = 1;
+    else if (*depth == -1)
+        sanitizedDepth = INT_MAX;
+    else if (*depth > 0)
+        sanitizedDepth = *depth;
+    else {
+        *errorString = "Please provide a positive integer as a depth or -1 for entire subtree";
+        return;
+    }
+
+    pushChildNodesToFrontend(nodeId, sanitizedDepth);
+}
+
+void InspectorDOMAgent::querySelector(ErrorString* errorString, int nodeId, const String& selectors, int* elementId)
+{
+    *elementId = 0;
+    Node* node = assertNode(errorString, nodeId);
+    if (!node)
+        return;
+
+    ExceptionCode ec = 0;
+    RefPtr<Element> element = node->querySelector(selectors, ec);
+    if (ec) {
+        *errorString = "DOM Error while querying";
+        return;
+    }
+
+    if (element)
+        *elementId = pushNodePathToFrontend(element.get());
+}
+
+void InspectorDOMAgent::querySelectorAll(ErrorString* errorString, int nodeId, const String& selectors, RefPtr<TypeBuilder::Array<int> >& result)
+{
+    Node* node = assertNode(errorString, nodeId);
+    if (!node)
+        return;
+
+    ExceptionCode ec = 0;
+    RefPtr<NodeList> nodes = node->querySelectorAll(selectors, ec);
+    if (ec) {
+        *errorString = "DOM Error while querying";
+        return;
+    }
+
+    result = TypeBuilder::Array<int>::create();
+
+    for (unsigned i = 0; i < nodes->length(); ++i)
+        result->addItem(pushNodePathToFrontend(nodes->item(i)));
+}
+
+int InspectorDOMAgent::pushNodePathToFrontend(Node* nodeToPush)
+{
+    ASSERT(nodeToPush);  // Invalid input
+
+    if (!m_document)
+        return 0;
+    if (!m_documentNodeToIdMap.contains(m_document))
+        return 0;
+
+    // Return id in case the node is known.
+    int result = m_documentNodeToIdMap.get(nodeToPush);
+    if (result)
+        return result;
+
+    Node* node = nodeToPush;
+    Vector<Node*> path;
+    NodeToIdMap* danglingMap = 0;
+
+    while (true) {
+        Node* parent = innerParentNode(node);
+        if (!parent) {
+            // Node being pushed is detached -> push subtree root.
+            OwnPtr<NodeToIdMap> newMap = adoptPtr(new NodeToIdMap);
+            danglingMap = newMap.get();
+            m_danglingNodeToIdMaps.append(newMap.release());
+            RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > children = TypeBuilder::Array<TypeBuilder::DOM::Node>::create();
+            children->addItem(buildObjectForNode(node, 0, danglingMap));
+            m_frontend->setChildNodes(0, children);
+            break;
+        } else {
+            path.append(parent);
+            if (m_documentNodeToIdMap.get(parent))
+                break;
+            else
+                node = parent;
+        }
+    }
+
+    NodeToIdMap* map = danglingMap ? danglingMap : &m_documentNodeToIdMap;
+    for (int i = path.size() - 1; i >= 0; --i) {
+        int nodeId = map->get(path.at(i));
+        ASSERT(nodeId);
+        pushChildNodesToFrontend(nodeId);
+    }
+    return map->get(nodeToPush);
+}
+
+int InspectorDOMAgent::boundNodeId(Node* node)
+{
+    return m_documentNodeToIdMap.get(node);
+}
+
+BackendNodeId InspectorDOMAgent::backendNodeIdForNode(Node* node, const String& nodeGroup)
+{
+    if (!node)
+        return 0;
+
+    if (!m_nodeGroupToBackendIdMap.contains(nodeGroup))
+        m_nodeGroupToBackendIdMap.set(nodeGroup, NodeToBackendIdMap());
+
+    NodeToBackendIdMap& map = m_nodeGroupToBackendIdMap.find(nodeGroup)->value;
+    BackendNodeId id = map.get(node);
+    if (!id) {
+        id = --m_lastBackendNodeId;
+        map.set(node, id);
+        m_backendIdToNode.set(id, std::make_pair(node, nodeGroup));
+    }
+
+    return id;
+}
+
+void InspectorDOMAgent::releaseBackendNodeIds(ErrorString* errorString, const String& nodeGroup)
+{
+    if (m_nodeGroupToBackendIdMap.contains(nodeGroup)) {
+        NodeToBackendIdMap& map = m_nodeGroupToBackendIdMap.find(nodeGroup)->value;
+        for (NodeToBackendIdMap::iterator it = map.begin(); it != map.end(); ++it)
+            m_backendIdToNode.remove(it->value);
+        m_nodeGroupToBackendIdMap.remove(nodeGroup);
+        return;
+    }
+    *errorString = "Group name not found";
+}
+
+void InspectorDOMAgent::setAttributeValue(ErrorString* errorString, int elementId, const String& name, const String& value)
+{
+    Element* element = assertEditableElement(errorString, elementId);
+    if (!element)
+        return;
+
+    m_domEditor->setAttribute(element, name, value, errorString);
+}
+
+void InspectorDOMAgent::setAttributesAsText(ErrorString* errorString, int elementId, const String& text, const String* const name)
+{
+    Element* element = assertEditableElement(errorString, elementId);
+    if (!element)
+        return;
+
+    RefPtr<HTMLElement> parsedElement = createHTMLElement(element->document(), spanTag);
+    ExceptionCode ec = 0;
+    parsedElement.get()->setInnerHTML("<span " + text + "></span>", ec);
+    if (ec) {
+        *errorString = InspectorDOMAgent::toErrorString(ec);
+        return;
+    }
+
+    Node* child = parsedElement->firstChild();
+    if (!child) {
+        *errorString = "Could not parse value as attributes";
+        return;
+    }
+
+    Element* childElement = toElement(child);
+    if (!childElement->hasAttributes() && name) {
+        m_domEditor->removeAttribute(element, *name, errorString);
+        return;
+    }
+
+    bool foundOriginalAttribute = false;
+    unsigned numAttrs = childElement->attributeCount();
+    for (unsigned i = 0; i < numAttrs; ++i) {
+        // Add attribute pair
+        const Attribute* attribute = childElement->attributeItem(i);
+        foundOriginalAttribute = foundOriginalAttribute || (name && attribute->name().toString() == *name);
+        if (!m_domEditor->setAttribute(element, attribute->name().toString(), attribute->value(), errorString))
+            return;
+    }
+
+    if (!foundOriginalAttribute && name && !name->stripWhiteSpace().isEmpty())
+        m_domEditor->removeAttribute(element, *name, errorString);
+}
+
+void InspectorDOMAgent::removeAttribute(ErrorString* errorString, int elementId, const String& name)
+{
+    Element* element = assertEditableElement(errorString, elementId);
+    if (!element)
+        return;
+
+    m_domEditor->removeAttribute(element, name, errorString);
+}
+
+void InspectorDOMAgent::removeNode(ErrorString* errorString, int nodeId)
+{
+    Node* node = assertEditableNode(errorString, nodeId);
+    if (!node)
+        return;
+
+    ContainerNode* parentNode = node->parentNode();
+    if (!parentNode) {
+        *errorString = "Can not remove detached node";
+        return;
+    }
+
+    m_domEditor->removeChild(parentNode, node, errorString);
+}
+
+void InspectorDOMAgent::setNodeName(ErrorString* errorString, int nodeId, const String& tagName, int* newId)
+{
+    *newId = 0;
+
+    Node* oldNode = nodeForId(nodeId);
+    if (!oldNode || !oldNode->isElementNode())
+        return;
+
+    ExceptionCode ec = 0;
+    RefPtr<Element> newElem = oldNode->document()->createElement(tagName, ec);
+    if (ec)
+        return;
+
+    // Copy over the original node's attributes.
+    newElem->cloneAttributesFromElement(*toElement(oldNode));
+
+    // Copy over the original node's children.
+    Node* child;
+    while ((child = oldNode->firstChild())) {
+        if (!m_domEditor->insertBefore(newElem.get(), child, 0, errorString))
+            return;
+    }
+
+    // Replace the old node with the new node
+    ContainerNode* parent = oldNode->parentNode();
+    if (!m_domEditor->insertBefore(parent, newElem.get(), oldNode->nextSibling(), errorString))
+        return;
+    if (!m_domEditor->removeChild(parent, oldNode, errorString))
+        return;
+
+    *newId = pushNodePathToFrontend(newElem.get());
+    if (m_childrenRequested.contains(nodeId))
+        pushChildNodesToFrontend(*newId);
+}
+
+void InspectorDOMAgent::getOuterHTML(ErrorString* errorString, int nodeId, WTF::String* outerHTML)
+{
+    Node* node = assertNode(errorString, nodeId);
+    if (!node)
+        return;
+
+    *outerHTML = createMarkup(node);
+}
+
+void InspectorDOMAgent::setOuterHTML(ErrorString* errorString, int nodeId, const String& outerHTML)
+{
+    if (!nodeId) {
+        DOMPatchSupport domPatchSupport(m_domEditor.get(), m_document.get());
+        domPatchSupport.patchDocument(outerHTML);
+        return;
+    }
+
+    Node* node = assertEditableNode(errorString, nodeId);
+    if (!node)
+        return;
+
+    Document* document = node->isDocumentNode() ? toDocument(node) : node->ownerDocument();
+    if (!document || (!document->isHTMLDocument() && !document->isXHTMLDocument()
+#if ENABLE(SVG)
+        && !document->isSVGDocument()
+#endif
+    )) {
+        *errorString = "Not an HTML/XML document";
+        return;
+    }
+
+    Node* newNode = 0;
+    if (!m_domEditor->setOuterHTML(node, outerHTML, &newNode, errorString))
+        return;
+
+    if (!newNode) {
+        // The only child node has been deleted.
+        return;
+    }
+
+    int newId = pushNodePathToFrontend(newNode);
+
+    bool childrenRequested = m_childrenRequested.contains(nodeId);
+    if (childrenRequested)
+        pushChildNodesToFrontend(newId);
+}
+
+void InspectorDOMAgent::setNodeValue(ErrorString* errorString, int nodeId, const String& value)
+{
+    Node* node = assertEditableNode(errorString, nodeId);
+    if (!node)
+        return;
+
+    if (node->nodeType() != Node::TEXT_NODE) {
+        *errorString = "Can only set value of text nodes";
+        return;
+    }
+
+    m_domEditor->replaceWholeText(toText(node), value, errorString);
+}
+
+void InspectorDOMAgent::getEventListenersForNode(ErrorString* errorString, int nodeId, const String* objectGroup, RefPtr<TypeBuilder::Array<TypeBuilder::DOM::EventListener> >& listenersArray)
+{
+    listenersArray = TypeBuilder::Array<TypeBuilder::DOM::EventListener>::create();
+    Node* node = assertNode(errorString, nodeId);
+    if (!node)
+        return;
+    Vector<EventListenerInfo> eventInformation;
+    getEventListeners(node, eventInformation, true);
+
+    // Get Capturing Listeners (in this order)
+    size_t eventInformationLength = eventInformation.size();
+    for (size_t i = 0; i < eventInformationLength; ++i) {
+        const EventListenerInfo& info = eventInformation[i];
+        const EventListenerVector& vector = info.eventListenerVector;
+        for (size_t j = 0; j < vector.size(); ++j) {
+            const RegisteredEventListener& listener = vector[j];
+            if (listener.useCapture)
+                listenersArray->addItem(buildObjectForEventListener(listener, info.eventType, info.node, objectGroup));
+        }
+    }
+
+    // Get Bubbling Listeners (reverse order)
+    for (size_t i = eventInformationLength; i; --i) {
+        const EventListenerInfo& info = eventInformation[i - 1];
+        const EventListenerVector& vector = info.eventListenerVector;
+        for (size_t j = 0; j < vector.size(); ++j) {
+            const RegisteredEventListener& listener = vector[j];
+            if (!listener.useCapture)
+                listenersArray->addItem(buildObjectForEventListener(listener, info.eventType, info.node, objectGroup));
+        }
+    }
+}
+
+void InspectorDOMAgent::getEventListeners(Node* node, Vector<EventListenerInfo>& eventInformation, bool includeAncestors)
+{
+    // The Node's Ancestors including self.
+    Vector<Node*> ancestors;
+    // Push this node as the firs element.
+    ancestors.append(node);
+    if (includeAncestors) {
+        for (ContainerNode* ancestor = node->parentOrShadowHostNode(); ancestor; ancestor = ancestor->parentOrShadowHostNode())
+            ancestors.append(ancestor);
+    }
+
+    // Nodes and their Listeners for the concerned event types (order is top to bottom)
+    for (size_t i = ancestors.size(); i; --i) {
+        Node* ancestor = ancestors[i - 1];
+        EventTargetData* d = ancestor->eventTargetData();
+        if (!d)
+            continue;
+        // Get the list of event types this Node is concerned with
+        Vector<AtomicString> eventTypes = d->eventListenerMap.eventTypes();
+        for (size_t j = 0; j < eventTypes.size(); ++j) {
+            AtomicString& type = eventTypes[j];
+            const EventListenerVector& listeners = ancestor->getEventListeners(type);
+            EventListenerVector filteredListeners;
+            filteredListeners.reserveCapacity(listeners.size());
+            for (size_t k = 0; k < listeners.size(); ++k) {
+                if (listeners[k].listener->type() == EventListener::JSEventListenerType)
+                    filteredListeners.append(listeners[k]);
+            }
+            if (!filteredListeners.isEmpty())
+                eventInformation.append(EventListenerInfo(ancestor, type, filteredListeners));
+        }
+    }
+}
+
+void InspectorDOMAgent::performSearch(ErrorString*, const String& whitespaceTrimmedQuery, String* searchId, int* resultCount)
+{
+    // FIXME: Few things are missing here:
+    // 1) Search works with node granularity - number of matches within node is not calculated.
+    // 2) There is no need to push all search results to the front-end at a time, pushing next / previous result
+    //    is sufficient.
+
+    unsigned queryLength = whitespaceTrimmedQuery.length();
+    bool startTagFound = !whitespaceTrimmedQuery.find('<');
+    bool endTagFound = whitespaceTrimmedQuery.reverseFind('>') + 1 == queryLength;
+    bool startQuoteFound = !whitespaceTrimmedQuery.find('"');
+    bool endQuoteFound = whitespaceTrimmedQuery.reverseFind('"') + 1 == queryLength;
+    bool exactAttributeMatch = startQuoteFound && endQuoteFound;
+
+    String tagNameQuery = whitespaceTrimmedQuery;
+    String attributeQuery = whitespaceTrimmedQuery;
+    if (startTagFound)
+        tagNameQuery = tagNameQuery.right(tagNameQuery.length() - 1);
+    if (endTagFound)
+        tagNameQuery = tagNameQuery.left(tagNameQuery.length() - 1);
+    if (startQuoteFound)
+        attributeQuery = attributeQuery.right(attributeQuery.length() - 1);
+    if (endQuoteFound)
+        attributeQuery = attributeQuery.left(attributeQuery.length() - 1);
+
+    Vector<Document*> docs = documents();
+    ListHashSet<Node*> resultCollector;
+
+    for (Vector<Document*>::iterator it = docs.begin(); it != docs.end(); ++it) {
+        Document* document = *it;
+        Node* node = document->documentElement();
+        if (!node)
+            continue;
+
+        // Manual plain text search.
+        while ((node = NodeTraversal::next(node, document->documentElement()))) {
+            switch (node->nodeType()) {
+            case Node::TEXT_NODE:
+            case Node::COMMENT_NODE:
+            case Node::CDATA_SECTION_NODE: {
+                String text = node->nodeValue();
+                if (text.findIgnoringCase(whitespaceTrimmedQuery) != notFound)
+                    resultCollector.add(node);
+                break;
+            }
+            case Node::ELEMENT_NODE: {
+                if ((!startTagFound && !endTagFound && (node->nodeName().findIgnoringCase(tagNameQuery) != notFound))
+                    || (startTagFound && endTagFound && equalIgnoringCase(node->nodeName(), tagNameQuery))
+                    || (startTagFound && !endTagFound && node->nodeName().startsWith(tagNameQuery, false))
+                    || (!startTagFound && endTagFound && node->nodeName().endsWith(tagNameQuery, false))) {
+                    resultCollector.add(node);
+                    break;
+                }
+                // Go through all attributes and serialize them.
+                const Element* element = toElement(node);
+                if (!element->hasAttributes())
+                    break;
+
+                unsigned numAttrs = element->attributeCount();
+                for (unsigned i = 0; i < numAttrs; ++i) {
+                    // Add attribute pair
+                    const Attribute* attribute = element->attributeItem(i);
+                    if (attribute->localName().find(whitespaceTrimmedQuery) != notFound) {
+                        resultCollector.add(node);
+                        break;
+                    }
+                    size_t foundPosition = attribute->value().find(attributeQuery);
+                    if (foundPosition != notFound) {
+                        if (!exactAttributeMatch || (!foundPosition && attribute->value().length() == attributeQuery.length())) {
+                            resultCollector.add(node);
+                            break;
+                        }
+                    }
+                }
+                break;
+            }
+            default:
+                break;
+            }
+        }
+
+        // XPath evaluation
+        for (Vector<Document*>::iterator it = docs.begin(); it != docs.end(); ++it) {
+            Document* document = *it;
+            ExceptionCode ec = 0;
+            RefPtr<XPathResult> result = document->evaluate(whitespaceTrimmedQuery, document, 0, XPathResult::ORDERED_NODE_SNAPSHOT_TYPE, 0, ec);
+            if (ec || !result)
+                continue;
+
+            unsigned long size = result->snapshotLength(ec);
+            for (unsigned long i = 0; !ec && i < size; ++i) {
+                Node* node = result->snapshotItem(i, ec);
+                if (ec)
+                    break;
+
+                if (node->nodeType() == Node::ATTRIBUTE_NODE)
+                    node = static_cast<Attr*>(node)->ownerElement();
+                resultCollector.add(node);
+            }
+        }
+
+        // Selector evaluation
+        for (Vector<Document*>::iterator it = docs.begin(); it != docs.end(); ++it) {
+            Document* document = *it;
+            ExceptionCode ec = 0;
+            RefPtr<NodeList> nodeList = document->querySelectorAll(whitespaceTrimmedQuery, ec);
+            if (ec || !nodeList)
+                continue;
+
+            unsigned size = nodeList->length();
+            for (unsigned i = 0; i < size; ++i)
+                resultCollector.add(nodeList->item(i));
+        }
+    }
+
+    *searchId = IdentifiersFactory::createIdentifier();
+    SearchResults::iterator resultsIt = m_searchResults.add(*searchId, Vector<RefPtr<Node> >()).iterator;
+
+    for (ListHashSet<Node*>::iterator it = resultCollector.begin(); it != resultCollector.end(); ++it)
+        resultsIt->value.append(*it);
+
+    *resultCount = resultsIt->value.size();
+}
+
+void InspectorDOMAgent::getSearchResults(ErrorString* errorString, const String& searchId, int fromIndex, int toIndex, RefPtr<TypeBuilder::Array<int> >& nodeIds)
+{
+    SearchResults::iterator it = m_searchResults.find(searchId);
+    if (it == m_searchResults.end()) {
+        *errorString = "No search session with given id found";
+        return;
+    }
+
+    int size = it->value.size();
+    if (fromIndex < 0 || toIndex > size || fromIndex >= toIndex) {
+        *errorString = "Invalid search result range";
+        return;
+    }
+
+    nodeIds = TypeBuilder::Array<int>::create();
+    for (int i = fromIndex; i < toIndex; ++i)
+        nodeIds->addItem(pushNodePathToFrontend((it->value)[i].get()));
+}
+
+void InspectorDOMAgent::discardSearchResults(ErrorString*, const String& searchId)
+{
+    m_searchResults.remove(searchId);
+}
+
+bool InspectorDOMAgent::handleMousePress()
+{
+    if (!m_searchingForNode)
+        return false;
+
+    if (Node* node = m_overlay->highlightedNode()) {
+        inspect(node);
+        return true;
+    }
+    return false;
+}
+
+bool InspectorDOMAgent::handleTouchEvent(Frame* frame, const PlatformTouchEvent& event)
+{
+    if (!m_searchingForNode)
+        return false;
+    Node* node = hoveredNodeForEvent(frame, event, false);
+    if (node && m_inspectModeHighlightConfig) {
+        m_overlay->highlightNode(node, 0 /* eventTarget */, *m_inspectModeHighlightConfig);
+        inspect(node);
+        return true;
+    }
+    return false;
+}
+
+void InspectorDOMAgent::inspect(Node* inspectedNode)
+{
+    if (!m_frontend)
+        return;
+
+    Node* node = inspectedNode;
+    if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)
+        node = node->parentNode();
+
+    int nodeId = pushNodePathToFrontend(node);
+    if (nodeId)
+        m_frontend->inspectNodeRequested(nodeId);
+
+    ErrorString error;
+    setSearchingForNode(&error, false, 0);
+}
+
+void InspectorDOMAgent::handleMouseMove(Frame* frame, const PlatformMouseEvent& event)
+{
+    if (!m_searchingForNode)
+        return;
+
+    if (!frame->view() || !frame->contentRenderer())
+        return;
+    Node* node = hoveredNodeForEvent(frame, event, event.shiftKey());
+    Node* eventTarget = event.shiftKey() ? hoveredNodeForEvent(frame, event, false) : 0;
+    if (eventTarget == node)
+        eventTarget = 0;
+
+    if (node && m_inspectModeHighlightConfig)
+        m_overlay->highlightNode(node, eventTarget, *m_inspectModeHighlightConfig);
+}
+
+void InspectorDOMAgent::setSearchingForNode(ErrorString* errorString, bool enabled, InspectorObject* highlightInspectorObject)
+{
+    if (m_searchingForNode == enabled)
+        return;
+    m_searchingForNode = enabled;
+    if (enabled) {
+        m_inspectModeHighlightConfig = highlightConfigFromInspectorObject(errorString, highlightInspectorObject);
+        if (!m_inspectModeHighlightConfig)
+            return;
+    } else
+        hideHighlight(errorString);
+}
+
+PassOwnPtr<HighlightConfig> InspectorDOMAgent::highlightConfigFromInspectorObject(ErrorString* errorString, InspectorObject* highlightInspectorObject)
+{
+    if (!highlightInspectorObject) {
+        *errorString = "Internal error: highlight configuration parameter is missing";
+        return nullptr;
+    }
+
+    OwnPtr<HighlightConfig> highlightConfig = adoptPtr(new HighlightConfig());
+    bool showInfo = false; // Default: false (do not show a tooltip).
+    highlightInspectorObject->getBoolean("showInfo", &showInfo);
+    highlightConfig->showInfo = showInfo;
+    bool showRulers = false; // Default: false (do not show rulers).
+    highlightInspectorObject->getBoolean("showRulers", &showRulers);
+    highlightConfig->showRulers = showRulers;
+    highlightConfig->content = parseConfigColor("contentColor", highlightInspectorObject);
+    highlightConfig->contentOutline = parseConfigColor("contentOutlineColor", highlightInspectorObject);
+    highlightConfig->padding = parseConfigColor("paddingColor", highlightInspectorObject);
+    highlightConfig->border = parseConfigColor("borderColor", highlightInspectorObject);
+    highlightConfig->margin = parseConfigColor("marginColor", highlightInspectorObject);
+    highlightConfig->eventTarget = parseConfigColor("eventTargetColor", highlightInspectorObject);
+    return highlightConfig.release();
+}
+
+void InspectorDOMAgent::setInspectModeEnabled(ErrorString* errorString, bool enabled, const RefPtr<InspectorObject>* highlightConfig)
+{
+    setSearchingForNode(errorString, enabled, highlightConfig ? highlightConfig->get() : 0);
+}
+
+void InspectorDOMAgent::highlightRect(ErrorString*, int x, int y, int width, int height, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor)
+{
+    OwnPtr<FloatQuad> quad = adoptPtr(new FloatQuad(FloatRect(x, y, width, height)));
+    innerHighlightQuad(quad.release(), color, outlineColor);
+}
+
+void InspectorDOMAgent::highlightQuad(ErrorString* errorString, const RefPtr<InspectorArray>& quadArray, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor)
+{
+    OwnPtr<FloatQuad> quad = adoptPtr(new FloatQuad());
+    if (!parseQuad(quadArray, quad.get())) {
+        *errorString = "Invalid Quad format";
+        return;
+    }
+    innerHighlightQuad(quad.release(), color, outlineColor);
+}
+
+void InspectorDOMAgent::innerHighlightQuad(PassOwnPtr<FloatQuad> quad, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor)
+{
+    OwnPtr<HighlightConfig> highlightConfig = adoptPtr(new HighlightConfig());
+    highlightConfig->content = parseColor(color);
+    highlightConfig->contentOutline = parseColor(outlineColor);
+    m_overlay->highlightQuad(quad, *highlightConfig);
+}
+
+void InspectorDOMAgent::highlightNode(ErrorString* errorString, const RefPtr<InspectorObject>& highlightInspectorObject, const int* nodeId, const String* objectId)
+{
+    Node* node = 0;
+    if (nodeId) {
+        node = assertNode(errorString, *nodeId);
+    } else if (objectId) {
+        InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*objectId);
+        node = injectedScript.nodeForObjectId(*objectId);
+        if (!node)
+            *errorString = "Node for given objectId not found";
+    } else
+        *errorString = "Either nodeId or objectId must be specified";
+
+    if (!node)
+        return;
+
+    OwnPtr<HighlightConfig> highlightConfig = highlightConfigFromInspectorObject(errorString, highlightInspectorObject.get());
+    if (!highlightConfig)
+        return;
+
+    m_overlay->highlightNode(node, 0 /* eventTarget */, *highlightConfig);
+}
+
+void InspectorDOMAgent::highlightFrame(
+    ErrorString*,
+    const String& frameId,
+    const RefPtr<InspectorObject>* color,
+    const RefPtr<InspectorObject>* outlineColor)
+{
+    Frame* frame = m_pageAgent->frameForId(frameId);
+    if (frame && frame->ownerElement()) {
+        OwnPtr<HighlightConfig> highlightConfig = adoptPtr(new HighlightConfig());
+        highlightConfig->showInfo = true; // Always show tooltips for frames.
+        highlightConfig->content = parseColor(color);
+        highlightConfig->contentOutline = parseColor(outlineColor);
+        m_overlay->highlightNode(frame->ownerElement(), 0 /* eventTarget */, *highlightConfig);
+    }
+}
+
+void InspectorDOMAgent::hideHighlight(ErrorString*)
+{
+    m_overlay->hideHighlight();
+}
+
+void InspectorDOMAgent::moveTo(ErrorString* errorString, int nodeId, int targetElementId, const int* const anchorNodeId, int* newNodeId)
+{
+    Node* node = assertEditableNode(errorString, nodeId);
+    if (!node)
+        return;
+
+    Element* targetElement = assertEditableElement(errorString, targetElementId);
+    if (!targetElement)
+        return;
+
+    Node* anchorNode = 0;
+    if (anchorNodeId && *anchorNodeId) {
+        anchorNode = assertEditableNode(errorString, *anchorNodeId);
+        if (!anchorNode)
+            return;
+        if (anchorNode->parentNode() != targetElement) {
+            *errorString = "Anchor node must be child of the target element";
+            return;
+        }
+    }
+
+    if (!m_domEditor->insertBefore(targetElement, node, anchorNode, errorString))
+        return;
+
+    *newNodeId = pushNodePathToFrontend(node);
+}
+
+void InspectorDOMAgent::undo(ErrorString* errorString)
+{
+    ExceptionCode ec = 0;
+    m_history->undo(ec);
+    *errorString = InspectorDOMAgent::toErrorString(ec);
+}
+
+void InspectorDOMAgent::redo(ErrorString* errorString)
+{
+    ExceptionCode ec = 0;
+    m_history->redo(ec);
+    *errorString = InspectorDOMAgent::toErrorString(ec);
+}
+
+void InspectorDOMAgent::markUndoableState(ErrorString*)
+{
+    m_history->markUndoableState();
+}
+
+void InspectorDOMAgent::focus(ErrorString* errorString, int nodeId)
+{
+    Element* element = assertElement(errorString, nodeId);
+    if (!element)
+        return;
+    if (!element->isFocusable()) {
+        *errorString = "Element is not focusable";
+        return;
+    }
+    element->focus();
+}
+
+void InspectorDOMAgent::setFileInputFiles(ErrorString* errorString, int nodeId, const RefPtr<InspectorArray>& files)
+{
+    Node* node = assertNode(errorString, nodeId);
+    if (!node)
+        return;
+    HTMLInputElement* element = node->toInputElement();
+    if (!element || !element->isFileUpload()) {
+        *errorString = "Node is not a file input element";
+        return;
+    }
+
+    RefPtr<FileList> fileList = FileList::create();
+    for (InspectorArray::const_iterator iter = files->begin(); iter != files->end(); ++iter) {
+        String path;
+        if (!(*iter)->asString(&path)) {
+            *errorString = "Files must be strings";
+            return;
+        }
+        fileList->append(File::create(path));
+    }
+    element->setFiles(fileList);
+}
+
+void InspectorDOMAgent::resolveNode(ErrorString* errorString, int nodeId, const String* const objectGroup, RefPtr<TypeBuilder::Runtime::RemoteObject>& result)
+{
+    String objectGroupName = objectGroup ? *objectGroup : "";
+    Node* node = nodeForId(nodeId);
+    if (!node) {
+        *errorString = "No node with given id found";
+        return;
+    }
+    RefPtr<TypeBuilder::Runtime::RemoteObject> object = resolveNode(node, objectGroupName);
+    if (!object) {
+        *errorString = "Node with given id does not belong to the document";
+        return;
+    }
+    result = object;
+}
+
+void InspectorDOMAgent::getAttributes(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::Array<String> >& result)
+{
+    Element* element = assertElement(errorString, nodeId);
+    if (!element)
+        return;
+
+    result = buildArrayForElementAttributes(element);
+}
+
+void InspectorDOMAgent::requestNode(ErrorString*, const String& objectId, int* nodeId)
+{
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
+    Node* node = injectedScript.nodeForObjectId(objectId);
+    if (node)
+        *nodeId = pushNodePathToFrontend(node);
+    else
+        *nodeId = 0;
+}
+
+// static
+String InspectorDOMAgent::documentURLString(Document* document)
+{
+    if (!document || document->url().isNull())
+        return "";
+    return document->url().string();
+}
+
+static String documentBaseURLString(Document* document)
+{
+    return document->completeURL("").string();
+}
+
+PassRefPtr<TypeBuilder::DOM::Node> InspectorDOMAgent::buildObjectForNode(Node* node, int depth, NodeToIdMap* nodesMap)
+{
+    int id = bind(node, nodesMap);
+    String nodeName;
+    String localName;
+    String nodeValue;
+
+    switch (node->nodeType()) {
+    case Node::TEXT_NODE:
+    case Node::COMMENT_NODE:
+    case Node::CDATA_SECTION_NODE:
+        nodeValue = node->nodeValue();
+        if (nodeValue.length() > maxTextSize) {
+            nodeValue = nodeValue.left(maxTextSize);
+            nodeValue.append(ellipsisUChar);
+        }
+        break;
+    case Node::ATTRIBUTE_NODE:
+        localName = node->localName();
+        break;
+    case Node::DOCUMENT_FRAGMENT_NODE:
+    case Node::DOCUMENT_NODE:
+    case Node::ELEMENT_NODE:
+    default:
+        nodeName = node->nodeName();
+        localName = node->localName();
+        break;
+    }
+
+    RefPtr<TypeBuilder::DOM::Node> value = TypeBuilder::DOM::Node::create()
+        .setNodeId(id)
+        .setNodeType(static_cast<int>(node->nodeType()))
+        .setNodeName(nodeName)
+        .setLocalName(localName)
+        .setNodeValue(nodeValue);
+
+    if (node->isContainerNode()) {
+        int nodeCount = innerChildNodeCount(node);
+        value->setChildNodeCount(nodeCount);
+        RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > children = buildArrayForContainerChildren(node, depth, nodesMap);
+        if (children->length() > 0)
+            value->setChildren(children.release());
+    }
+
+    if (node->isElementNode()) {
+        Element* element = toElement(node);
+        value->setAttributes(buildArrayForElementAttributes(element));
+        if (node->isFrameOwnerElement()) {
+            HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(node);
+            Frame* frame = frameOwner->contentFrame();
+            if (frame)
+                value->setFrameId(m_pageAgent->frameId(frame));
+            Document* doc = frameOwner->contentDocument();
+            if (doc)
+                value->setContentDocument(buildObjectForNode(doc, 0, nodesMap));
+        }
+
+        ElementShadow* shadow = element->shadow();
+        if (shadow) {
+            RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > shadowRoots = TypeBuilder::Array<TypeBuilder::DOM::Node>::create();
+            for (ShadowRoot* root = shadow->youngestShadowRoot(); root; root = root->olderShadowRoot())
+                shadowRoots->addItem(buildObjectForNode(root, 0, nodesMap));
+            value->setShadowRoots(shadowRoots);
+        }
+
+        if (element->hasTagName(templateTag))
+            value->setTemplateContent(buildObjectForNode(static_cast<HTMLTemplateElement*>(element)->content(), 0, nodesMap));
+    } else if (node->isDocumentNode()) {
+        Document* document = toDocument(node);
+        value->setDocumentURL(documentURLString(document));
+        value->setBaseURL(documentBaseURLString(document));
+        value->setXmlVersion(document->xmlVersion());
+    } else if (node->nodeType() == Node::DOCUMENT_TYPE_NODE) {
+        DocumentType* docType = static_cast<DocumentType*>(node);
+        value->setPublicId(docType->publicId());
+        value->setSystemId(docType->systemId());
+        value->setInternalSubset(docType->internalSubset());
+    } else if (node->isAttributeNode()) {
+        Attr* attribute = static_cast<Attr*>(node);
+        value->setName(attribute->name());
+        value->setValue(attribute->value());
+    }
+    return value.release();
+}
+
+PassRefPtr<TypeBuilder::Array<String> > InspectorDOMAgent::buildArrayForElementAttributes(Element* element)
+{
+    RefPtr<TypeBuilder::Array<String> > attributesValue = TypeBuilder::Array<String>::create();
+    // Go through all attributes and serialize them.
+    if (!element->hasAttributes())
+        return attributesValue.release();
+    unsigned numAttrs = element->attributeCount();
+    for (unsigned i = 0; i < numAttrs; ++i) {
+        // Add attribute pair
+        const Attribute* attribute = element->attributeItem(i);
+        attributesValue->addItem(attribute->name().toString());
+        attributesValue->addItem(attribute->value());
+    }
+    return attributesValue.release();
+}
+
+PassRefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > InspectorDOMAgent::buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap)
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > children = TypeBuilder::Array<TypeBuilder::DOM::Node>::create();
+    if (depth == 0) {
+        // Special-case the only text child - pretend that container's children have been requested.
+        Node* firstChild = container->firstChild();
+        if (firstChild && firstChild->nodeType() == Node::TEXT_NODE && !firstChild->nextSibling()) {
+            children->addItem(buildObjectForNode(firstChild, 0, nodesMap));
+            m_childrenRequested.add(bind(container, nodesMap));
+        }
+        return children.release();
+    }
+
+    Node* child = innerFirstChild(container);
+    depth--;
+    m_childrenRequested.add(bind(container, nodesMap));
+
+    while (child) {
+        children->addItem(buildObjectForNode(child, depth, nodesMap));
+        child = innerNextSibling(child);
+    }
+    return children.release();
+}
+
+PassRefPtr<TypeBuilder::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, const AtomicString& eventType, Node* node, const String* objectGroupId)
+{
+    RefPtr<EventListener> eventListener = registeredEventListener.listener;
+    Document* document = node->document();
+    RefPtr<TypeBuilder::DOM::EventListener> value = TypeBuilder::DOM::EventListener::create()
+        .setType(eventType)
+        .setUseCapture(registeredEventListener.useCapture)
+        .setIsAttribute(eventListener->isAttribute())
+        .setNodeId(pushNodePathToFrontend(node))
+        .setHandlerBody(eventListenerHandlerBody(document, eventListener.get()));
+    if (objectGroupId) {
+        ScriptValue functionValue = eventListenerHandler(document, eventListener.get());
+        if (!functionValue.hasNoValue()) {
+            Frame* frame = document->frame();
+            if (frame) {
+                ScriptState* scriptState = eventListenerHandlerScriptState(frame, eventListener.get());
+                if (scriptState) {
+                    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
+                    if (!injectedScript.hasNoValue()) {
+                        RefPtr<TypeBuilder::Runtime::RemoteObject> valueJson = injectedScript.wrapObject(functionValue, *objectGroupId);
+                        value->setHandler(valueJson);
+                    }
+                }
+            }
+        }
+    }
+    String sourceName;
+    String scriptId;
+    int lineNumber;
+    if (eventListenerHandlerLocation(node->document(), eventListener.get(), sourceName, scriptId, lineNumber)) {
+        RefPtr<TypeBuilder::Debugger::Location> location = TypeBuilder::Debugger::Location::create()
+            .setScriptId(scriptId)
+            .setLineNumber(lineNumber);
+        value->setLocation(location);
+        if (!sourceName.isEmpty())
+            value->setSourceName(sourceName);
+    }
+    return value.release();
+}
+
+Node* InspectorDOMAgent::innerFirstChild(Node* node)
+{
+    node = node->firstChild();
+    while (isWhitespace(node))
+        node = node->nextSibling();
+    return node;
+}
+
+Node* InspectorDOMAgent::innerNextSibling(Node* node)
+{
+    do {
+        node = node->nextSibling();
+    } while (isWhitespace(node));
+    return node;
+}
+
+Node* InspectorDOMAgent::innerPreviousSibling(Node* node)
+{
+    do {
+        node = node->previousSibling();
+    } while (isWhitespace(node));
+    return node;
+}
+
+unsigned InspectorDOMAgent::innerChildNodeCount(Node* node)
+{
+    unsigned count = 0;
+    Node* child = innerFirstChild(node);
+    while (child) {
+        count++;
+        child = innerNextSibling(child);
+    }
+    return count;
+}
+
+Node* InspectorDOMAgent::innerParentNode(Node* node)
+{
+    if (node->isDocumentNode()) {
+        Document* document = toDocument(node);
+        return document->ownerElement();
+    }
+    return node->parentNode();
+}
+
+bool InspectorDOMAgent::isWhitespace(Node* node)
+{
+    //TODO: pull ignoreWhitespace setting from the frontend and use here.
+    return node && node->nodeType() == Node::TEXT_NODE && node->nodeValue().stripWhiteSpace().length() == 0;
+}
+
+void InspectorDOMAgent::mainFrameDOMContentLoaded()
+{
+    // Re-push document once it is loaded.
+    discardBindings();
+    if (m_state->getBoolean(DOMAgentState::documentRequested))
+        m_frontend->documentUpdated();
+}
+
+void InspectorDOMAgent::loadEventFired(Document* document)
+{
+    Element* frameOwner = document->ownerElement();
+    if (!frameOwner)
+        return;
+
+    int frameOwnerId = m_documentNodeToIdMap.get(frameOwner);
+    if (!frameOwnerId)
+        return;
+
+    // Re-add frame owner element together with its new children.
+    int parentId = m_documentNodeToIdMap.get(innerParentNode(frameOwner));
+    m_frontend->childNodeRemoved(parentId, frameOwnerId);
+    unbind(frameOwner, &m_documentNodeToIdMap);
+
+    RefPtr<TypeBuilder::DOM::Node> value = buildObjectForNode(frameOwner, 0, &m_documentNodeToIdMap);
+    Node* previousSibling = innerPreviousSibling(frameOwner);
+    int prevId = previousSibling ? m_documentNodeToIdMap.get(previousSibling) : 0;
+    m_frontend->childNodeInserted(parentId, prevId, value.release());
+}
+
+void InspectorDOMAgent::didInsertDOMNode(Node* node)
+{
+    if (isWhitespace(node))
+        return;
+
+    // We could be attaching existing subtree. Forget the bindings.
+    unbind(node, &m_documentNodeToIdMap);
+
+    ContainerNode* parent = node->parentNode();
+    if (!parent)
+        return;
+
+    int parentId = m_documentNodeToIdMap.get(parent);
+    // Return if parent is not mapped yet.
+    if (!parentId)
+        return;
+
+    if (!m_childrenRequested.contains(parentId)) {
+        // No children are mapped yet -> only notify on changes of hasChildren.
+        m_frontend->childNodeCountUpdated(parentId, innerChildNodeCount(parent));
+    } else {
+        // Children have been requested -> return value of a new child.
+        Node* prevSibling = innerPreviousSibling(node);
+        int prevId = prevSibling ? m_documentNodeToIdMap.get(prevSibling) : 0;
+        RefPtr<TypeBuilder::DOM::Node> value = buildObjectForNode(node, 0, &m_documentNodeToIdMap);
+        m_frontend->childNodeInserted(parentId, prevId, value.release());
+    }
+}
+
+void InspectorDOMAgent::didRemoveDOMNode(Node* node)
+{
+    if (isWhitespace(node))
+        return;
+
+    ContainerNode* parent = node->parentNode();
+
+    // If parent is not mapped yet -> ignore the event.
+    if (!m_documentNodeToIdMap.contains(parent))
+        return;
+
+    int parentId = m_documentNodeToIdMap.get(parent);
+
+    if (!m_childrenRequested.contains(parentId)) {
+        // No children are mapped yet -> only notify on changes of hasChildren.
+        if (innerChildNodeCount(parent) == 1)
+            m_frontend->childNodeCountUpdated(parentId, 0);
+    } else
+        m_frontend->childNodeRemoved(parentId, m_documentNodeToIdMap.get(node));
+    unbind(node, &m_documentNodeToIdMap);
+}
+
+void InspectorDOMAgent::willModifyDOMAttr(Element*, const AtomicString& oldValue, const AtomicString& newValue)
+{
+    m_suppressAttributeModifiedEvent = (oldValue == newValue);
+}
+
+void InspectorDOMAgent::didModifyDOMAttr(Element* element, const AtomicString& name, const AtomicString& value)
+{
+    bool shouldSuppressEvent = m_suppressAttributeModifiedEvent;
+    m_suppressAttributeModifiedEvent = false;
+    if (shouldSuppressEvent)
+        return;
+
+    int id = boundNodeId(element);
+    // If node is not mapped yet -> ignore the event.
+    if (!id)
+        return;
+
+    if (m_domListener)
+        m_domListener->didModifyDOMAttr(element);
+
+    m_frontend->attributeModified(id, name, value);
+}
+
+void InspectorDOMAgent::didRemoveDOMAttr(Element* element, const AtomicString& name)
+{
+    int id = boundNodeId(element);
+    // If node is not mapped yet -> ignore the event.
+    if (!id)
+        return;
+
+    if (m_domListener)
+        m_domListener->didModifyDOMAttr(element);
+
+    m_frontend->attributeRemoved(id, name);
+}
+
+void InspectorDOMAgent::styleAttributeInvalidated(const Vector<Element*>& elements)
+{
+    RefPtr<TypeBuilder::Array<int> > nodeIds = TypeBuilder::Array<int>::create();
+    for (unsigned i = 0, size = elements.size(); i < size; ++i) {
+        Element* element = elements.at(i);
+        int id = boundNodeId(element);
+        // If node is not mapped yet -> ignore the event.
+        if (!id)
+            continue;
+
+        if (m_domListener)
+            m_domListener->didModifyDOMAttr(element);
+        nodeIds->addItem(id);
+    }
+    m_frontend->inlineStyleInvalidated(nodeIds.release());
+}
+
+void InspectorDOMAgent::characterDataModified(CharacterData* characterData)
+{
+    int id = m_documentNodeToIdMap.get(characterData);
+    if (!id) {
+        // Push text node if it is being created.
+        didInsertDOMNode(characterData);
+        return;
+    }
+    m_frontend->characterDataModified(id, characterData->data());
+}
+
+void InspectorDOMAgent::didInvalidateStyleAttr(Node* node)
+{
+    int id = m_documentNodeToIdMap.get(node);
+    // If node is not mapped yet -> ignore the event.
+    if (!id)
+        return;
+
+    if (!m_revalidateStyleAttrTask)
+        m_revalidateStyleAttrTask = adoptPtr(new RevalidateStyleAttributeTask(this));
+    m_revalidateStyleAttrTask->scheduleFor(toElement(node));
+}
+
+void InspectorDOMAgent::didPushShadowRoot(Element* host, ShadowRoot* root)
+{
+    int hostId = m_documentNodeToIdMap.get(host);
+    if (hostId)
+        m_frontend->shadowRootPushed(hostId, buildObjectForNode(root, 0, &m_documentNodeToIdMap));
+}
+
+void InspectorDOMAgent::willPopShadowRoot(Element* host, ShadowRoot* root)
+{
+    int hostId = m_documentNodeToIdMap.get(host);
+    int rootId = m_documentNodeToIdMap.get(root);
+    if (hostId && rootId)
+        m_frontend->shadowRootPopped(hostId, rootId);
+}
+
+void InspectorDOMAgent::frameDocumentUpdated(Frame* frame)
+{
+    Document* document = frame->document();
+    if (!document)
+        return;
+
+    Page* page = frame->page();
+    ASSERT(page);
+    if (frame != page->mainFrame())
+        return;
+
+    // Only update the main frame document, nested frame document updates are not required
+    // (will be handled by loadEventFired()).
+    setDocument(document);
+}
+
+Node* InspectorDOMAgent::nodeForPath(const String& path)
+{
+    // The path is of form "1,HTML,2,BODY,1,DIV"
+    if (!m_document)
+        return 0;
+
+    Node* node = m_document.get();
+    Vector<String> pathTokens;
+    path.split(",", false, pathTokens);
+    if (!pathTokens.size())
+        return 0;
+    for (size_t i = 0; i < pathTokens.size() - 1; i += 2) {
+        bool success = true;
+        unsigned childNumber = pathTokens[i].toUInt(&success);
+        if (!success)
+            return 0;
+        if (childNumber >= innerChildNodeCount(node))
+            return 0;
+
+        Node* child = innerFirstChild(node);
+        String childName = pathTokens[i + 1];
+        for (size_t j = 0; child && j < childNumber; ++j)
+            child = innerNextSibling(child);
+
+        if (!child || child->nodeName() != childName)
+            return 0;
+        node = child;
+    }
+    return node;
+}
+
+void InspectorDOMAgent::pushNodeByPathToFrontend(ErrorString* errorString, const String& path, int* nodeId)
+{
+    if (Node* node = nodeForPath(path))
+        *nodeId = pushNodePathToFrontend(node);
+    else
+        *errorString = "No node with given path found";
+}
+
+void InspectorDOMAgent::pushNodeByBackendIdToFrontend(ErrorString* errorString, BackendNodeId backendNodeId, int* nodeId)
+{
+    if (!m_backendIdToNode.contains(backendNodeId)) {
+        *errorString = "No node with given backend id found";
+        return;
+    }
+
+    Node* node = m_backendIdToNode.get(backendNodeId).first;
+    String nodeGroup = m_backendIdToNode.get(backendNodeId).second;
+    *nodeId = pushNodePathToFrontend(node);
+
+    if (nodeGroup == "") {
+        m_backendIdToNode.remove(backendNodeId);
+        m_nodeGroupToBackendIdMap.find(nodeGroup)->value.remove(node);
+    }
+}
+
+PassRefPtr<TypeBuilder::Runtime::RemoteObject> InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup)
+{
+    Document* document = node->isDocumentNode() ? node->document() : node->ownerDocument();
+    Frame* frame = document ? document->frame() : 0;
+    if (!frame)
+        return 0;
+
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(mainWorldScriptState(frame));
+    if (injectedScript.hasNoValue())
+        return 0;
+
+    return injectedScript.wrapNode(node, objectGroup);
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorDOMAgent.h b/Source/core/inspector/InspectorDOMAgent.h
new file mode 100644
index 0000000..219622a
--- /dev/null
+++ b/Source/core/inspector/InspectorDOMAgent.h
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef InspectorDOMAgent_h
+#define InspectorDOMAgent_h
+
+#include "InspectorFrontend.h"
+#include "core/dom/EventTarget.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include "core/inspector/InspectorOverlay.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/platform/Timer.h"
+#include "core/rendering/RenderLayer.h"
+
+#include <wtf/Deque.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+class ContainerNode;
+class CharacterData;
+class DOMEditor;
+class Document;
+class Element;
+class Event;
+class InspectorClient;
+class InspectorFrontend;
+class InspectorHistory;
+class InspectorOverlay;
+class InspectorPageAgent;
+class HTMLElement;
+class InspectorState;
+class InstrumentingAgents;
+class NameNodeMap;
+class Node;
+class PlatformTouchEvent;
+class RevalidateStyleAttributeTask;
+class ScriptValue;
+class ShadowRoot;
+
+struct HighlightConfig;
+
+typedef String ErrorString;
+typedef int BackendNodeId;
+
+
+struct EventListenerInfo {
+    EventListenerInfo(Node* node, const AtomicString& eventType, const EventListenerVector& eventListenerVector)
+        : node(node)
+        , eventType(eventType)
+        , eventListenerVector(eventListenerVector)
+    {
+    }
+
+    Node* node;
+    const AtomicString eventType;
+    const EventListenerVector eventListenerVector;
+};
+
+class InspectorDOMAgent : public InspectorBaseAgent<InspectorDOMAgent>, public InspectorBackendDispatcher::DOMCommandHandler {
+    WTF_MAKE_NONCOPYABLE(InspectorDOMAgent);
+public:
+    struct DOMListener {
+        virtual ~DOMListener()
+        {
+        }
+        virtual void didRemoveDocument(Document*) = 0;
+        virtual void didRemoveDOMNode(Node*) = 0;
+        virtual void didModifyDOMAttr(Element*) = 0;
+    };
+
+    static PassOwnPtr<InspectorDOMAgent> create(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager, InspectorOverlay* overlay, InspectorClient* client)
+    {
+        return adoptPtr(new InspectorDOMAgent(instrumentingAgents, pageAgent, inspectorState, injectedScriptManager, overlay, client));
+    }
+
+    static String toErrorString(const ExceptionCode&);
+
+    ~InspectorDOMAgent();
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void restore();
+
+    Vector<Document*> documents();
+    void reset();
+
+    // Methods called from the frontend for DOM nodes inspection.
+    virtual void querySelector(ErrorString*, int nodeId, const String& selectors, int* elementId);
+    virtual void querySelectorAll(ErrorString*, int nodeId, const String& selectors, RefPtr<TypeBuilder::Array<int> >& result);
+    virtual void getDocument(ErrorString*, RefPtr<TypeBuilder::DOM::Node>& root);
+    virtual void requestChildNodes(ErrorString*, int nodeId, const int* depth);
+    virtual void setAttributeValue(ErrorString*, int elementId, const String& name, const String& value);
+    virtual void setAttributesAsText(ErrorString*, int elementId, const String& text, const String* name);
+    virtual void removeAttribute(ErrorString*, int elementId, const String& name);
+    virtual void removeNode(ErrorString*, int nodeId);
+    virtual void setNodeName(ErrorString*, int nodeId, const String& name, int* newId);
+    virtual void getOuterHTML(ErrorString*, int nodeId, WTF::String* outerHTML);
+    virtual void setOuterHTML(ErrorString*, int nodeId, const String& outerHTML);
+    virtual void setNodeValue(ErrorString*, int nodeId, const String& value);
+    virtual void getEventListenersForNode(ErrorString*, int nodeId, const WTF::String* objectGroup, RefPtr<TypeBuilder::Array<TypeBuilder::DOM::EventListener> >& listenersArray);
+    virtual void performSearch(ErrorString*, const String& whitespaceTrimmedQuery, String* searchId, int* resultCount);
+    virtual void getSearchResults(ErrorString*, const String& searchId, int fromIndex, int toIndex, RefPtr<TypeBuilder::Array<int> >&);
+    virtual void discardSearchResults(ErrorString*, const String& searchId);
+    virtual void resolveNode(ErrorString*, int nodeId, const String* objectGroup, RefPtr<TypeBuilder::Runtime::RemoteObject>& result);
+    virtual void getAttributes(ErrorString*, int nodeId, RefPtr<TypeBuilder::Array<String> >& result);
+    virtual void setInspectModeEnabled(ErrorString*, bool enabled, const RefPtr<InspectorObject>* highlightConfig);
+    virtual void requestNode(ErrorString*, const String& objectId, int* nodeId);
+    virtual void pushNodeByPathToFrontend(ErrorString*, const String& path, int* nodeId);
+    virtual void pushNodeByBackendIdToFrontend(ErrorString*, BackendNodeId, int* nodeId);
+    virtual void releaseBackendNodeIds(ErrorString*, const String& nodeGroup);
+    virtual void hideHighlight(ErrorString*);
+    virtual void highlightRect(ErrorString*, int x, int y, int width, int height, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor);
+    virtual void highlightQuad(ErrorString*, const RefPtr<InspectorArray>& quad, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor);
+    virtual void highlightNode(ErrorString*, const RefPtr<InspectorObject>& highlightConfig, const int* nodeId, const String* objectId);
+    virtual void highlightFrame(ErrorString*, const String& frameId, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor);
+
+    virtual void moveTo(ErrorString*, int nodeId, int targetNodeId, const int* anchorNodeId, int* newNodeId);
+    virtual void undo(ErrorString*);
+    virtual void redo(ErrorString*);
+    virtual void markUndoableState(ErrorString*);
+    virtual void focus(ErrorString*, int nodeId);
+    virtual void setFileInputFiles(ErrorString*, int nodeId, const RefPtr<InspectorArray>& files);
+
+    void getEventListeners(Node*, Vector<EventListenerInfo>& listenersArray, bool includeAncestors);
+
+    // Methods called from the InspectorInstrumentation.
+    void setDocument(Document*);
+    void releaseDanglingNodes();
+
+    void mainFrameDOMContentLoaded();
+    void loadEventFired(Document*);
+
+    void didInsertDOMNode(Node*);
+    void didRemoveDOMNode(Node*);
+    void willModifyDOMAttr(Element*, const AtomicString& oldValue, const AtomicString& newValue);
+    void didModifyDOMAttr(Element*, const AtomicString& name, const AtomicString& value);
+    void didRemoveDOMAttr(Element*, const AtomicString& name);
+    void styleAttributeInvalidated(const Vector<Element*>& elements);
+    void characterDataModified(CharacterData*);
+    void didInvalidateStyleAttr(Node*);
+    void didPushShadowRoot(Element* host, ShadowRoot*);
+    void willPopShadowRoot(Element* host, ShadowRoot*);
+    void frameDocumentUpdated(Frame*);
+
+    int pushNodeToFrontend(ErrorString*, int documentNodeId, Node*);
+    Node* nodeForId(int nodeId);
+    int boundNodeId(Node*);
+    void setDOMListener(DOMListener*);
+    BackendNodeId backendNodeIdForNode(Node*, const String& nodeGroup);
+
+    static String documentURLString(Document*);
+
+    PassRefPtr<TypeBuilder::Runtime::RemoteObject> resolveNode(Node*, const String& objectGroup);
+    bool handleMousePress();
+    bool handleTouchEvent(Frame*, const PlatformTouchEvent&);
+    void handleMouseMove(Frame*, const PlatformMouseEvent&);
+
+    InspectorHistory* history() { return m_history.get(); }
+
+    // We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently.
+    // We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics.
+    static Node* innerFirstChild(Node*);
+    static Node* innerNextSibling(Node*);
+    static Node* innerPreviousSibling(Node*);
+    static unsigned innerChildNodeCount(Node*);
+    static Node* innerParentNode(Node*);
+    static bool isWhitespace(Node*);
+
+    Node* assertNode(ErrorString*, int nodeId);
+    Element* assertElement(ErrorString*, int nodeId);
+    Document* assertDocument(ErrorString*, int nodeId);
+
+    // Methods called from other agents.
+    InspectorPageAgent* pageAgent() { return m_pageAgent; }
+
+private:
+    InspectorDOMAgent(InstrumentingAgents*, InspectorPageAgent*, InspectorCompositeState*, InjectedScriptManager*, InspectorOverlay*, InspectorClient*);
+
+    void setSearchingForNode(ErrorString*, bool enabled, InspectorObject* highlightConfig);
+    PassOwnPtr<HighlightConfig> highlightConfigFromInspectorObject(ErrorString*, InspectorObject* highlightInspectorObject);
+
+    // Node-related methods.
+    typedef HashMap<RefPtr<Node>, int> NodeToIdMap;
+    int bind(Node*, NodeToIdMap*);
+    void unbind(Node*, NodeToIdMap*);
+
+    Node* assertEditableNode(ErrorString*, int nodeId);
+    Element* assertEditableElement(ErrorString*, int nodeId);
+
+    void inspect(Node*);
+
+    int pushNodePathToFrontend(Node*);
+    void pushChildNodesToFrontend(int nodeId, int depth = 1);
+
+    bool hasBreakpoint(Node*, int type);
+    void updateSubtreeBreakpoints(Node* root, uint32_t rootMask, bool value);
+    void descriptionForDOMEvent(Node* target, int breakpointType, bool insertion, PassRefPtr<InspectorObject> description);
+
+    PassRefPtr<TypeBuilder::DOM::Node> buildObjectForNode(Node*, int depth, NodeToIdMap*);
+    PassRefPtr<TypeBuilder::Array<String> > buildArrayForElementAttributes(Element*);
+    PassRefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap);
+    PassRefPtr<TypeBuilder::DOM::EventListener> buildObjectForEventListener(const RegisteredEventListener&, const AtomicString& eventType, Node*, const String* objectGroupId);
+
+    Node* nodeForPath(const String& path);
+
+    void discardBindings();
+
+    void innerHighlightQuad(PassOwnPtr<FloatQuad>, const RefPtr<InspectorObject>* color, const RefPtr<InspectorObject>* outlineColor);
+
+    InspectorPageAgent* m_pageAgent;
+    InjectedScriptManager* m_injectedScriptManager;
+    InspectorOverlay* m_overlay;
+    InspectorClient* m_client;
+    InspectorFrontend::DOM* m_frontend;
+    DOMListener* m_domListener;
+    NodeToIdMap m_documentNodeToIdMap;
+    typedef HashMap<RefPtr<Node>, BackendNodeId> NodeToBackendIdMap;
+    HashMap<String, NodeToBackendIdMap> m_nodeGroupToBackendIdMap;
+    // Owns node mappings for dangling nodes.
+    Vector<OwnPtr<NodeToIdMap> > m_danglingNodeToIdMaps;
+    HashMap<int, Node*> m_idToNode;
+    HashMap<int, NodeToIdMap*> m_idToNodesMap;
+    HashSet<int> m_childrenRequested;
+    HashMap<BackendNodeId, std::pair<Node*, String> > m_backendIdToNode;
+    int m_lastNodeId;
+    BackendNodeId m_lastBackendNodeId;
+    RefPtr<Document> m_document;
+    typedef HashMap<String, Vector<RefPtr<Node> > > SearchResults;
+    SearchResults m_searchResults;
+    OwnPtr<RevalidateStyleAttributeTask> m_revalidateStyleAttrTask;
+    bool m_searchingForNode;
+    OwnPtr<HighlightConfig> m_inspectModeHighlightConfig;
+    OwnPtr<InspectorHistory> m_history;
+    OwnPtr<DOMEditor> m_domEditor;
+    bool m_suppressAttributeModifiedEvent;
+};
+
+
+} // namespace WebCore
+
+#endif // !defined(InspectorDOMAgent_h)
diff --git a/Source/core/inspector/InspectorDOMDebuggerAgent.cpp b/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
new file mode 100644
index 0000000..7dbd67b
--- /dev/null
+++ b/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorDOMDebuggerAgent.h"
+
+#include "InspectorFrontend.h"
+#include "core/html/HTMLElement.h"
+#include "core/inspector/InspectorAgent.h"
+#include "core/inspector/InspectorDOMAgent.h"
+#include "core/inspector/InspectorDebuggerAgent.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include <wtf/text/WTFString.h>
+
+namespace {
+
+enum DOMBreakpointType {
+    SubtreeModified = 0,
+    AttributeModified,
+    NodeRemoved,
+    DOMBreakpointTypesCount
+};
+
+static const char* const listenerEventCategoryType = "listener:";
+static const char* const instrumentationEventCategoryType = "instrumentation:";
+
+const uint32_t inheritableDOMBreakpointTypesMask = (1 << SubtreeModified);
+const int domBreakpointDerivedTypeShift = 16;
+
+}
+
+namespace WebCore {
+
+namespace DOMDebuggerAgentState {
+static const char eventListenerBreakpoints[] = "eventListenerBreakpoints";
+static const char pauseOnAllXHRs[] = "pauseOnAllXHRs";
+static const char xhrBreakpoints[] = "xhrBreakpoints";
+}
+
+PassOwnPtr<InspectorDOMDebuggerAgent> InspectorDOMDebuggerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, InspectorDOMAgent* domAgent, InspectorDebuggerAgent* debuggerAgent, InspectorAgent* inspectorAgent)
+{
+    return adoptPtr(new InspectorDOMDebuggerAgent(instrumentingAgents, inspectorState, domAgent, debuggerAgent, inspectorAgent));
+}
+
+InspectorDOMDebuggerAgent::InspectorDOMDebuggerAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, InspectorDOMAgent* domAgent, InspectorDebuggerAgent* debuggerAgent, InspectorAgent*)
+    : InspectorBaseAgent<InspectorDOMDebuggerAgent>("DOMDebugger", instrumentingAgents, inspectorState)
+    , m_domAgent(domAgent)
+    , m_debuggerAgent(debuggerAgent)
+    , m_pauseInNextEventListener(false)
+{
+    m_debuggerAgent->setListener(this);
+}
+
+InspectorDOMDebuggerAgent::~InspectorDOMDebuggerAgent()
+{
+    ASSERT(!m_debuggerAgent);
+    ASSERT(!m_instrumentingAgents->inspectorDOMDebuggerAgent());
+}
+
+// Browser debugger agent enabled only when JS debugger is enabled.
+void InspectorDOMDebuggerAgent::debuggerWasEnabled()
+{
+    m_instrumentingAgents->setInspectorDOMDebuggerAgent(this);
+}
+
+void InspectorDOMDebuggerAgent::debuggerWasDisabled()
+{
+    disable();
+}
+
+void InspectorDOMDebuggerAgent::stepInto()
+{
+    m_pauseInNextEventListener = true;
+}
+
+void InspectorDOMDebuggerAgent::didPause()
+{
+    m_pauseInNextEventListener = false;
+}
+
+void InspectorDOMDebuggerAgent::didProcessTask()
+{
+    if (!m_pauseInNextEventListener)
+        return;
+    if (m_debuggerAgent && m_debuggerAgent->runningNestedMessageLoop())
+        return;
+    m_pauseInNextEventListener = false;
+}
+
+void InspectorDOMDebuggerAgent::disable()
+{
+    m_instrumentingAgents->setInspectorDOMDebuggerAgent(0);
+    clear();
+}
+
+void InspectorDOMDebuggerAgent::clearFrontend()
+{
+    disable();
+}
+
+void InspectorDOMDebuggerAgent::discardAgent()
+{
+    m_debuggerAgent->setListener(0);
+    m_debuggerAgent = 0;
+}
+
+void InspectorDOMDebuggerAgent::discardBindings()
+{
+    m_domBreakpoints.clear();
+}
+
+void InspectorDOMDebuggerAgent::setEventListenerBreakpoint(ErrorString* error, const String& eventName)
+{
+    setBreakpoint(error, String(listenerEventCategoryType) + eventName);
+}
+
+void InspectorDOMDebuggerAgent::setInstrumentationBreakpoint(ErrorString* error, const String& eventName)
+{
+    setBreakpoint(error, String(instrumentationEventCategoryType) + eventName);
+}
+
+void InspectorDOMDebuggerAgent::setBreakpoint(ErrorString* error, const String& eventName)
+{
+    if (eventName.isEmpty()) {
+        *error = "Event name is empty";
+        return;
+    }
+
+    RefPtr<InspectorObject> eventListenerBreakpoints = m_state->getObject(DOMDebuggerAgentState::eventListenerBreakpoints);
+    eventListenerBreakpoints->setBoolean(eventName, true);
+    m_state->setObject(DOMDebuggerAgentState::eventListenerBreakpoints, eventListenerBreakpoints);
+}
+
+void InspectorDOMDebuggerAgent::removeEventListenerBreakpoint(ErrorString* error, const String& eventName)
+{
+    removeBreakpoint(error, String(listenerEventCategoryType) + eventName);
+}
+
+void InspectorDOMDebuggerAgent::removeInstrumentationBreakpoint(ErrorString* error, const String& eventName)
+{
+    removeBreakpoint(error, String(instrumentationEventCategoryType) + eventName);
+}
+
+void InspectorDOMDebuggerAgent::removeBreakpoint(ErrorString* error, const String& eventName)
+{
+    if (eventName.isEmpty()) {
+        *error = "Event name is empty";
+        return;
+    }
+
+    RefPtr<InspectorObject> eventListenerBreakpoints = m_state->getObject(DOMDebuggerAgentState::eventListenerBreakpoints);
+    eventListenerBreakpoints->remove(eventName);
+    m_state->setObject(DOMDebuggerAgentState::eventListenerBreakpoints, eventListenerBreakpoints);
+}
+
+void InspectorDOMDebuggerAgent::didInvalidateStyleAttr(Node* node)
+{
+    if (hasBreakpoint(node, AttributeModified)) {
+        RefPtr<InspectorObject> eventData = InspectorObject::create();
+        descriptionForDOMEvent(node, AttributeModified, false, eventData.get());
+        m_debuggerAgent->breakProgram(InspectorFrontend::Debugger::Reason::DOM, eventData.release());
+    }
+}
+
+void InspectorDOMDebuggerAgent::didInsertDOMNode(Node* node)
+{
+    if (m_domBreakpoints.size()) {
+        uint32_t mask = m_domBreakpoints.get(InspectorDOMAgent::innerParentNode(node));
+        uint32_t inheritableTypesMask = (mask | (mask >> domBreakpointDerivedTypeShift)) & inheritableDOMBreakpointTypesMask;
+        if (inheritableTypesMask)
+            updateSubtreeBreakpoints(node, inheritableTypesMask, true);
+    }
+}
+
+void InspectorDOMDebuggerAgent::didRemoveDOMNode(Node* node)
+{
+    if (m_domBreakpoints.size()) {
+        // Remove subtree breakpoints.
+        m_domBreakpoints.remove(node);
+        Vector<Node*> stack(1, InspectorDOMAgent::innerFirstChild(node));
+        do {
+            Node* node = stack.last();
+            stack.removeLast();
+            if (!node)
+                continue;
+            m_domBreakpoints.remove(node);
+            stack.append(InspectorDOMAgent::innerFirstChild(node));
+            stack.append(InspectorDOMAgent::innerNextSibling(node));
+        } while (!stack.isEmpty());
+    }
+}
+
+static int domTypeForName(ErrorString* errorString, const String& typeString)
+{
+    if (typeString == "subtree-modified")
+        return SubtreeModified;
+    if (typeString == "attribute-modified")
+        return AttributeModified;
+    if (typeString == "node-removed")
+        return NodeRemoved;
+    *errorString = makeString("Unknown DOM breakpoint type: ", typeString);
+    return -1;
+}
+
+static String domTypeName(int type)
+{
+    switch (type) {
+    case SubtreeModified: return "subtree-modified";
+    case AttributeModified: return "attribute-modified";
+    case NodeRemoved: return "node-removed";
+    default: break;
+    }
+    return "";
+}
+
+void InspectorDOMDebuggerAgent::setDOMBreakpoint(ErrorString* errorString, int nodeId, const String& typeString)
+{
+    Node* node = m_domAgent->assertNode(errorString, nodeId);
+    if (!node)
+        return;
+
+    int type = domTypeForName(errorString, typeString);
+    if (type == -1)
+        return;
+
+    uint32_t rootBit = 1 << type;
+    m_domBreakpoints.set(node, m_domBreakpoints.get(node) | rootBit);
+    if (rootBit & inheritableDOMBreakpointTypesMask) {
+        for (Node* child = InspectorDOMAgent::innerFirstChild(node); child; child = InspectorDOMAgent::innerNextSibling(child))
+            updateSubtreeBreakpoints(child, rootBit, true);
+    }
+}
+
+void InspectorDOMDebuggerAgent::removeDOMBreakpoint(ErrorString* errorString, int nodeId, const String& typeString)
+{
+    Node* node = m_domAgent->assertNode(errorString, nodeId);
+    if (!node)
+        return;
+    int type = domTypeForName(errorString, typeString);
+    if (type == -1)
+        return;
+
+    uint32_t rootBit = 1 << type;
+    uint32_t mask = m_domBreakpoints.get(node) & ~rootBit;
+    if (mask)
+        m_domBreakpoints.set(node, mask);
+    else
+        m_domBreakpoints.remove(node);
+
+    if ((rootBit & inheritableDOMBreakpointTypesMask) && !(mask & (rootBit << domBreakpointDerivedTypeShift))) {
+        for (Node* child = InspectorDOMAgent::innerFirstChild(node); child; child = InspectorDOMAgent::innerNextSibling(child))
+            updateSubtreeBreakpoints(child, rootBit, false);
+    }
+}
+
+void InspectorDOMDebuggerAgent::willInsertDOMNode(Node* parent)
+{
+    if (hasBreakpoint(parent, SubtreeModified)) {
+        RefPtr<InspectorObject> eventData = InspectorObject::create();
+        descriptionForDOMEvent(parent, SubtreeModified, true, eventData.get());
+        m_debuggerAgent->breakProgram(InspectorFrontend::Debugger::Reason::DOM, eventData.release());
+    }
+}
+
+void InspectorDOMDebuggerAgent::willRemoveDOMNode(Node* node)
+{
+    Node* parentNode = InspectorDOMAgent::innerParentNode(node);
+    if (hasBreakpoint(node, NodeRemoved)) {
+        RefPtr<InspectorObject> eventData = InspectorObject::create();
+        descriptionForDOMEvent(node, NodeRemoved, false, eventData.get());
+        m_debuggerAgent->breakProgram(InspectorFrontend::Debugger::Reason::DOM, eventData.release());
+    } else if (parentNode && hasBreakpoint(parentNode, SubtreeModified)) {
+        RefPtr<InspectorObject> eventData = InspectorObject::create();
+        descriptionForDOMEvent(node, SubtreeModified, false, eventData.get());
+        m_debuggerAgent->breakProgram(InspectorFrontend::Debugger::Reason::DOM, eventData.release());
+    }
+}
+
+void InspectorDOMDebuggerAgent::willModifyDOMAttr(Element* element, const AtomicString&, const AtomicString&)
+{
+    if (hasBreakpoint(element, AttributeModified)) {
+        RefPtr<InspectorObject> eventData = InspectorObject::create();
+        descriptionForDOMEvent(element, AttributeModified, false, eventData.get());
+        m_debuggerAgent->breakProgram(InspectorFrontend::Debugger::Reason::DOM, eventData.release());
+    }
+}
+
+void InspectorDOMDebuggerAgent::descriptionForDOMEvent(Node* target, int breakpointType, bool insertion, InspectorObject* description)
+{
+    ASSERT(hasBreakpoint(target, breakpointType));
+
+    Node* breakpointOwner = target;
+    if ((1 << breakpointType) & inheritableDOMBreakpointTypesMask) {
+        // For inheritable breakpoint types, target node isn't always the same as the node that owns a breakpoint.
+        // Target node may be unknown to frontend, so we need to push it first.
+        RefPtr<TypeBuilder::Runtime::RemoteObject> targetNodeObject = m_domAgent->resolveNode(target, InspectorDebuggerAgent::backtraceObjectGroup);
+        description->setValue("targetNode", targetNodeObject);
+
+        // Find breakpoint owner node.
+        if (!insertion)
+            breakpointOwner = InspectorDOMAgent::innerParentNode(target);
+        ASSERT(breakpointOwner);
+        while (!(m_domBreakpoints.get(breakpointOwner) & (1 << breakpointType))) {
+            Node* parentNode = InspectorDOMAgent::innerParentNode(breakpointOwner);
+            if (!parentNode)
+                break;
+            breakpointOwner = parentNode;
+        }
+
+        if (breakpointType == SubtreeModified)
+            description->setBoolean("insertion", insertion);
+    }
+
+    int breakpointOwnerNodeId = m_domAgent->boundNodeId(breakpointOwner);
+    ASSERT(breakpointOwnerNodeId);
+    description->setNumber("nodeId", breakpointOwnerNodeId);
+    description->setString("type", domTypeName(breakpointType));
+}
+
+bool InspectorDOMDebuggerAgent::hasBreakpoint(Node* node, int type)
+{
+    uint32_t rootBit = 1 << type;
+    uint32_t derivedBit = rootBit << domBreakpointDerivedTypeShift;
+    return m_domBreakpoints.get(node) & (rootBit | derivedBit);
+}
+
+void InspectorDOMDebuggerAgent::updateSubtreeBreakpoints(Node* node, uint32_t rootMask, bool set)
+{
+    uint32_t oldMask = m_domBreakpoints.get(node);
+    uint32_t derivedMask = rootMask << domBreakpointDerivedTypeShift;
+    uint32_t newMask = set ? oldMask | derivedMask : oldMask & ~derivedMask;
+    if (newMask)
+        m_domBreakpoints.set(node, newMask);
+    else
+        m_domBreakpoints.remove(node);
+
+    uint32_t newRootMask = rootMask & ~newMask;
+    if (!newRootMask)
+        return;
+
+    for (Node* child = InspectorDOMAgent::innerFirstChild(node); child; child = InspectorDOMAgent::innerNextSibling(child))
+        updateSubtreeBreakpoints(child, newRootMask, set);
+}
+
+void InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded(bool isDOMEvent, const String& eventName, bool synchronous)
+{
+    String fullEventName = (isDOMEvent ? listenerEventCategoryType : instrumentationEventCategoryType) + eventName;
+    if (m_pauseInNextEventListener)
+        m_pauseInNextEventListener = false;
+    else {
+        RefPtr<InspectorObject> eventListenerBreakpoints = m_state->getObject(DOMDebuggerAgentState::eventListenerBreakpoints);
+        if (eventListenerBreakpoints->find(fullEventName) == eventListenerBreakpoints->end())
+            return;
+    }
+
+    RefPtr<InspectorObject> eventData = InspectorObject::create();
+    eventData->setString("eventName", fullEventName);
+    if (synchronous)
+        m_debuggerAgent->breakProgram(InspectorFrontend::Debugger::Reason::EventListener, eventData.release());
+    else
+        m_debuggerAgent->schedulePauseOnNextStatement(InspectorFrontend::Debugger::Reason::EventListener, eventData.release());
+}
+
+void InspectorDOMDebuggerAgent::setXHRBreakpoint(ErrorString*, const String& url)
+{
+    if (url.isEmpty()) {
+        m_state->setBoolean(DOMDebuggerAgentState::pauseOnAllXHRs, true);
+        return;
+    }
+
+    RefPtr<InspectorObject> xhrBreakpoints = m_state->getObject(DOMDebuggerAgentState::xhrBreakpoints);
+    xhrBreakpoints->setBoolean(url, true);
+    m_state->setObject(DOMDebuggerAgentState::xhrBreakpoints, xhrBreakpoints);
+}
+
+void InspectorDOMDebuggerAgent::removeXHRBreakpoint(ErrorString*, const String& url)
+{
+    if (url.isEmpty()) {
+        m_state->setBoolean(DOMDebuggerAgentState::pauseOnAllXHRs, false);
+        return;
+    }
+
+    RefPtr<InspectorObject> xhrBreakpoints = m_state->getObject(DOMDebuggerAgentState::xhrBreakpoints);
+    xhrBreakpoints->remove(url);
+    m_state->setObject(DOMDebuggerAgentState::xhrBreakpoints, xhrBreakpoints);
+}
+
+void InspectorDOMDebuggerAgent::willSendXMLHttpRequest(const String& url)
+{
+    String breakpointURL;
+    if (m_state->getBoolean(DOMDebuggerAgentState::pauseOnAllXHRs))
+        breakpointURL = "";
+    else {
+        RefPtr<InspectorObject> xhrBreakpoints = m_state->getObject(DOMDebuggerAgentState::xhrBreakpoints);
+        for (InspectorObject::iterator it = xhrBreakpoints->begin(); it != xhrBreakpoints->end(); ++it) {
+            if (url.contains(it->key)) {
+                breakpointURL = it->key;
+                break;
+            }
+        }
+    }
+
+    if (breakpointURL.isNull())
+        return;
+
+    RefPtr<InspectorObject> eventData = InspectorObject::create();
+    eventData->setString("breakpointURL", breakpointURL);
+    eventData->setString("url", url);
+    m_debuggerAgent->breakProgram(InspectorFrontend::Debugger::Reason::XHR, eventData.release());
+}
+
+void InspectorDOMDebuggerAgent::clear()
+{
+    m_domBreakpoints.clear();
+    m_pauseInNextEventListener = false;
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorDOMDebuggerAgent.h b/Source/core/inspector/InspectorDOMDebuggerAgent.h
new file mode 100644
index 0000000..a5fb24a
--- /dev/null
+++ b/Source/core/inspector/InspectorDOMDebuggerAgent.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef InspectorDOMDebuggerAgent_h
+#define InspectorDOMDebuggerAgent_h
+
+
+#include "core/inspector/InspectorBaseAgent.h"
+#include "core/inspector/InspectorDebuggerAgent.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class Element;
+class InspectorAgent;
+class InspectorDOMAgent;
+class InspectorDebuggerAgent;
+class InspectorFrontend;
+class InspectorObject;
+class InspectorState;
+class InstrumentingAgents;
+class Node;
+
+typedef String ErrorString;
+
+class InspectorDOMDebuggerAgent : public InspectorBaseAgent<InspectorDOMDebuggerAgent>, public InspectorDebuggerAgent::Listener, public InspectorBackendDispatcher::DOMDebuggerCommandHandler {
+    WTF_MAKE_NONCOPYABLE(InspectorDOMDebuggerAgent);
+public:
+    static PassOwnPtr<InspectorDOMDebuggerAgent> create(InstrumentingAgents*, InspectorCompositeState*, InspectorDOMAgent*, InspectorDebuggerAgent*, InspectorAgent*);
+
+    virtual ~InspectorDOMDebuggerAgent();
+
+    // DOMDebugger API for InspectorFrontend
+    virtual void setXHRBreakpoint(ErrorString*, const String& url);
+    virtual void removeXHRBreakpoint(ErrorString*, const String& url);
+    virtual void setEventListenerBreakpoint(ErrorString*, const String& eventName);
+    virtual void removeEventListenerBreakpoint(ErrorString*, const String& eventName);
+    virtual void setInstrumentationBreakpoint(ErrorString*, const String& eventName);
+    virtual void removeInstrumentationBreakpoint(ErrorString*, const String& eventName);
+    virtual void setDOMBreakpoint(ErrorString*, int nodeId, const String& type);
+    virtual void removeDOMBreakpoint(ErrorString*, int nodeId, const String& type);
+
+    // InspectorInstrumentation API
+    void willInsertDOMNode(Node* parent);
+    void didInvalidateStyleAttr(Node*);
+    void didInsertDOMNode(Node*);
+    void willRemoveDOMNode(Node*);
+    void didRemoveDOMNode(Node*);
+    void willModifyDOMAttr(Element*, const AtomicString&, const AtomicString&);
+    void willSendXMLHttpRequest(const String& url);
+    void pauseOnNativeEventIfNeeded(bool isDOMEvent, const String& eventName, bool synchronous);
+
+    void didProcessTask();
+
+    virtual void clearFrontend();
+    virtual void discardAgent();
+
+private:
+    InspectorDOMDebuggerAgent(InstrumentingAgents*, InspectorCompositeState*, InspectorDOMAgent*, InspectorDebuggerAgent*, InspectorAgent*);
+
+    // InspectorDebuggerAgent::Listener implementation.
+    virtual void debuggerWasEnabled();
+    virtual void debuggerWasDisabled();
+    virtual void stepInto();
+    virtual void didPause();
+    void disable();
+
+    void descriptionForDOMEvent(Node* target, int breakpointType, bool insertion, InspectorObject* description);
+    void updateSubtreeBreakpoints(Node*, uint32_t rootMask, bool set);
+    bool hasBreakpoint(Node*, int type);
+    void discardBindings();
+    void setBreakpoint(ErrorString*, const String& eventName);
+    void removeBreakpoint(ErrorString*, const String& eventName);
+
+    void clear();
+
+    InspectorDOMAgent* m_domAgent;
+    InspectorDebuggerAgent* m_debuggerAgent;
+    HashMap<Node*, uint32_t> m_domBreakpoints;
+    bool m_pauseInNextEventListener;
+};
+
+} // namespace WebCore
+
+
+#endif // !defined(InspectorDOMDebuggerAgent_h)
diff --git a/Source/core/inspector/InspectorDOMStorageAgent.cpp b/Source/core/inspector/InspectorDOMStorageAgent.cpp
new file mode 100644
index 0000000..39ee87a
--- /dev/null
+++ b/Source/core/inspector/InspectorDOMStorageAgent.cpp
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2013 Samsung Electronics. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorDOMStorageAgent.h"
+
+#include "ExceptionCodeDescription.h"
+#include "InspectorFrontend.h"
+#include "core/dom/Document.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/html/VoidCallback.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/page/DOMWindow.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/page/PageGroup.h"
+#include "core/page/SecurityOrigin.h"
+#include "core/storage/Storage.h"
+#include "core/storage/StorageArea.h"
+#include "core/storage/StorageNamespace.h"
+#include "modules/webdatabase/Database.h"
+
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+namespace DOMStorageAgentState {
+static const char domStorageAgentEnabled[] = "domStorageAgentEnabled";
+};
+
+static bool hadException(ExceptionCode ec, ErrorString* errorString)
+{
+    switch (ec) {
+    case 0:
+        return false;
+    case SECURITY_ERR:
+        *errorString = "Security error";
+        return true;
+    default:
+        *errorString = "Unknown DOM storage error";
+        return true;
+    }
+}
+
+InspectorDOMStorageAgent::InspectorDOMStorageAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorCompositeState* state)
+    : InspectorBaseAgent<InspectorDOMStorageAgent>("DOMStorage", instrumentingAgents, state)
+    , m_pageAgent(pageAgent)
+    , m_frontend(0)
+{
+    m_instrumentingAgents->setInspectorDOMStorageAgent(this);
+}
+
+InspectorDOMStorageAgent::~InspectorDOMStorageAgent()
+{
+    m_instrumentingAgents->setInspectorDOMStorageAgent(0);
+    m_instrumentingAgents = 0;
+}
+
+void InspectorDOMStorageAgent::setFrontend(InspectorFrontend* frontend)
+{
+    m_frontend = frontend;
+}
+
+void InspectorDOMStorageAgent::clearFrontend()
+{
+    m_frontend = 0;
+    disable(0);
+}
+
+bool InspectorDOMStorageAgent::isEnabled() const
+{
+    return m_state->getBoolean(DOMStorageAgentState::domStorageAgentEnabled);
+}
+
+void InspectorDOMStorageAgent::enable(ErrorString*)
+{
+    m_state->setBoolean(DOMStorageAgentState::domStorageAgentEnabled, true);
+}
+
+void InspectorDOMStorageAgent::disable(ErrorString*)
+{
+    m_state->setBoolean(DOMStorageAgentState::domStorageAgentEnabled, false);
+}
+
+void InspectorDOMStorageAgent::getDOMStorageItems(ErrorString* errorString, const RefPtr<InspectorObject>& storageId, RefPtr<TypeBuilder::Array<TypeBuilder::Array<String> > >& items)
+{
+    Frame* frame;
+    RefPtr<StorageArea> storageArea = findStorageArea(errorString, storageId, frame);
+    if (!storageArea)
+        return;
+
+    RefPtr<TypeBuilder::Array<TypeBuilder::Array<String> > > storageItems = TypeBuilder::Array<TypeBuilder::Array<String> >::create();
+
+    ExceptionCode ec = 0;
+    for (unsigned i = 0; i < storageArea->length(ec, frame); ++i) {
+        String name(storageArea->key(i, ec, frame));
+        if (hadException(ec, errorString))
+            return;
+        String value(storageArea->getItem(name, ec, frame));
+        if (hadException(ec, errorString))
+            return;
+        RefPtr<TypeBuilder::Array<String> > entry = TypeBuilder::Array<String>::create();
+        entry->addItem(name);
+        entry->addItem(value);
+        storageItems->addItem(entry);
+    }
+    items = storageItems.release();
+}
+
+static String toErrorString(const ExceptionCode& ec)
+{
+    if (ec) {
+        ExceptionCodeDescription description(ec);
+        return description.name;
+    }
+    return "";
+}
+
+void InspectorDOMStorageAgent::setDOMStorageItem(ErrorString* errorString, const RefPtr<InspectorObject>& storageId, const String& key, const String& value)
+{
+    Frame* frame;
+    RefPtr<StorageArea> storageArea = findStorageArea(0, storageId, frame);
+    if (!storageArea) {
+        *errorString = "Storage not found";
+        return;
+    }
+
+    ExceptionCode exception = 0;
+    storageArea->setItem(key, value, exception, frame);
+    *errorString = toErrorString(exception);
+}
+
+void InspectorDOMStorageAgent::removeDOMStorageItem(ErrorString* errorString, const RefPtr<InspectorObject>& storageId, const String& key)
+{
+    Frame* frame;
+    RefPtr<StorageArea> storageArea = findStorageArea(0, storageId, frame);
+    if (!storageArea) {
+        *errorString = "Storage not found";
+        return;
+    }
+
+    ExceptionCode exception = 0;
+    storageArea->removeItem(key, exception, frame);
+    *errorString = toErrorString(exception);
+}
+
+String InspectorDOMStorageAgent::storageId(Storage* storage)
+{
+    ASSERT(storage);
+    Document* document = storage->frame()->document();
+    ASSERT(document);
+    DOMWindow* window = document->domWindow();
+    ASSERT(window);
+    RefPtr<SecurityOrigin> securityOrigin = document->securityOrigin();
+    bool isLocalStorage = window->optionalLocalStorage() == storage;
+    return storageId(securityOrigin.get(), isLocalStorage)->toJSONString();
+}
+
+PassRefPtr<TypeBuilder::DOMStorage::StorageId> InspectorDOMStorageAgent::storageId(SecurityOrigin* securityOrigin, bool isLocalStorage)
+{
+    return TypeBuilder::DOMStorage::StorageId::create()
+        .setSecurityOrigin(securityOrigin->toRawString())
+        .setIsLocalStorage(isLocalStorage).release();
+}
+
+void InspectorDOMStorageAgent::didDispatchDOMStorageEvent(const String& key, const String& oldValue, const String& newValue, StorageType storageType, SecurityOrigin* securityOrigin, Page*)
+{
+    if (!m_frontend || !isEnabled())
+        return;
+
+    RefPtr<TypeBuilder::DOMStorage::StorageId> id = storageId(securityOrigin, storageType == LocalStorage);
+
+    if (key.isNull())
+        m_frontend->domstorage()->domStorageItemsCleared(id);
+    else if (newValue.isNull())
+        m_frontend->domstorage()->domStorageItemRemoved(id, key);
+    else if (oldValue.isNull())
+        m_frontend->domstorage()->domStorageItemAdded(id, key, newValue);
+    else
+        m_frontend->domstorage()->domStorageItemUpdated(id, key, oldValue, newValue);
+}
+
+PassRefPtr<StorageArea> InspectorDOMStorageAgent::findStorageArea(ErrorString* errorString, const RefPtr<InspectorObject>& storageId, Frame*& targetFrame)
+{
+    String securityOrigin;
+    bool isLocalStorage = false;
+    bool success = storageId->getString("securityOrigin", &securityOrigin);
+    if (success)
+        success = storageId->getBoolean("isLocalStorage", &isLocalStorage);
+    if (!success) {
+        if (errorString)
+            *errorString = "Invalid storageId format";
+        return 0;
+    }
+
+    Frame* frame = m_pageAgent->findFrameWithSecurityOrigin(securityOrigin);
+    if (!frame) {
+        if (errorString)
+            *errorString = "Frame not found for the given security origin";
+        return 0;
+    }
+    targetFrame = frame;
+
+    Page* page = m_pageAgent->page();
+    if (isLocalStorage)
+        return page->group().localStorage()->storageArea(frame->document()->securityOrigin());
+    return page->sessionStorage()->storageArea(frame->document()->securityOrigin());
+}
+
+void InspectorDOMStorageAgent::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::InspectorDOMStorageAgent);
+    InspectorBaseAgent<InspectorDOMStorageAgent>::reportMemoryUsage(memoryObjectInfo);
+    info.addWeakPointer(m_frontend);
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorDOMStorageAgent.h b/Source/core/inspector/InspectorDOMStorageAgent.h
new file mode 100644
index 0000000..960f14b
--- /dev/null
+++ b/Source/core/inspector/InspectorDOMStorageAgent.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef InspectorDOMStorageAgent_h
+#define InspectorDOMStorageAgent_h
+
+#include "core/inspector/InspectorBaseAgent.h"
+#include "core/storage/StorageArea.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class Frame;
+class InspectorArray;
+class InspectorFrontend;
+class InspectorPageAgent;
+class InspectorState;
+class InstrumentingAgents;
+class Page;
+class Storage;
+class StorageArea;
+
+typedef String ErrorString;
+
+class InspectorDOMStorageAgent : public InspectorBaseAgent<InspectorDOMStorageAgent>, public InspectorBackendDispatcher::DOMStorageCommandHandler {
+public:
+    static PassOwnPtr<InspectorDOMStorageAgent> create(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorCompositeState* state)
+    {
+        return adoptPtr(new InspectorDOMStorageAgent(instrumentingAgents, pageAgent, state));
+    }
+    ~InspectorDOMStorageAgent();
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+
+    // Called from the front-end.
+    virtual void enable(ErrorString*);
+    virtual void disable(ErrorString*);
+    virtual void getDOMStorageItems(ErrorString*, const RefPtr<InspectorObject>& storageId, RefPtr<TypeBuilder::Array<TypeBuilder::Array<String> > >& items);
+    virtual void setDOMStorageItem(ErrorString*, const RefPtr<InspectorObject>& storageId, const String& key, const String& value);
+    virtual void removeDOMStorageItem(ErrorString*, const RefPtr<InspectorObject>& storageId, const String& key);
+
+    // Called from the injected script.
+    String storageId(Storage*);
+    PassRefPtr<TypeBuilder::DOMStorage::StorageId> storageId(SecurityOrigin*, bool isLocalStorage);
+
+    // Called from InspectorInstrumentation
+    void didDispatchDOMStorageEvent(const String& key, const String& oldValue, const String& newValue, StorageType, SecurityOrigin*, Page*);
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+private:
+
+    InspectorDOMStorageAgent(InstrumentingAgents*, InspectorPageAgent*, InspectorCompositeState*);
+
+    bool isEnabled() const;
+    PassRefPtr<StorageArea> findStorageArea(ErrorString*, const RefPtr<InspectorObject>&, Frame*&);
+
+    InspectorPageAgent* m_pageAgent;
+    InspectorFrontend* m_frontend;
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorDOMStorageAgent_h)
diff --git a/Source/core/inspector/InspectorDatabaseAgent.cpp b/Source/core/inspector/InspectorDatabaseAgent.cpp
new file mode 100644
index 0000000..df96e12
--- /dev/null
+++ b/Source/core/inspector/InspectorDatabaseAgent.cpp
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2010 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+
+#include "core/inspector/InspectorDatabaseAgent.h"
+
+#include "InspectorFrontend.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/ExceptionCodePlaceholder.h"
+#include "core/html/VoidCallback.h"
+#include "core/inspector/InspectorDatabaseResource.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/platform/sql/SQLValue.h"
+#include "modules/webdatabase/Database.h"
+#include "modules/webdatabase/SQLError.h"
+#include "modules/webdatabase/SQLResultSet.h"
+#include "modules/webdatabase/SQLResultSetRowList.h"
+#include "modules/webdatabase/SQLStatementCallback.h"
+#include "modules/webdatabase/SQLStatementErrorCallback.h"
+#include "modules/webdatabase/SQLTransaction.h"
+#include "modules/webdatabase/SQLTransactionCallback.h"
+#include "modules/webdatabase/SQLTransactionErrorCallback.h"
+
+#include <wtf/Vector.h>
+
+typedef WebCore::InspectorBackendDispatcher::DatabaseCommandHandler::ExecuteSQLCallback ExecuteSQLCallback;
+
+namespace WebCore {
+
+namespace DatabaseAgentState {
+static const char databaseAgentEnabled[] = "databaseAgentEnabled";
+};
+
+namespace {
+
+void reportTransactionFailed(ExecuteSQLCallback* requestCallback, SQLError* error)
+{
+    RefPtr<TypeBuilder::Database::Error> errorObject = TypeBuilder::Database::Error::create()
+        .setMessage(error->message())
+        .setCode(error->code());
+    requestCallback->sendSuccess(0, 0, errorObject.release());
+}
+
+class StatementCallback : public SQLStatementCallback {
+public:
+    static PassRefPtr<StatementCallback> create(PassRefPtr<ExecuteSQLCallback> requestCallback)
+    {
+        return adoptRef(new StatementCallback(requestCallback));
+    }
+
+    virtual ~StatementCallback() { }
+
+    virtual bool handleEvent(SQLTransaction*, SQLResultSet* resultSet)
+    {
+        SQLResultSetRowList* rowList = resultSet->rows();
+
+        RefPtr<TypeBuilder::Array<String> > columnNames = TypeBuilder::Array<String>::create();
+        const Vector<String>& columns = rowList->columnNames();
+        for (size_t i = 0; i < columns.size(); ++i)
+            columnNames->addItem(columns[i]);
+
+        RefPtr<TypeBuilder::Array<InspectorValue> > values = TypeBuilder::Array<InspectorValue>::create();
+        const Vector<SQLValue>& data = rowList->values();
+        for (size_t i = 0; i < data.size(); ++i) {
+            const SQLValue& value = rowList->values()[i];
+            switch (value.type()) {
+            case SQLValue::StringValue: values->addItem(InspectorString::create(value.string())); break;
+            case SQLValue::NumberValue: values->addItem(InspectorBasicValue::create(value.number())); break;
+            case SQLValue::NullValue: values->addItem(InspectorValue::null()); break;
+            }
+        }
+        m_requestCallback->sendSuccess(columnNames.release(), values.release(), 0);
+        return true;
+    }
+
+private:
+    StatementCallback(PassRefPtr<ExecuteSQLCallback> requestCallback)
+        : m_requestCallback(requestCallback) { }
+    RefPtr<ExecuteSQLCallback> m_requestCallback;
+};
+
+class StatementErrorCallback : public SQLStatementErrorCallback {
+public:
+    static PassRefPtr<StatementErrorCallback> create(PassRefPtr<ExecuteSQLCallback> requestCallback)
+    {
+        return adoptRef(new StatementErrorCallback(requestCallback));
+    }
+
+    virtual ~StatementErrorCallback() { }
+
+    virtual bool handleEvent(SQLTransaction*, SQLError* error)
+    {
+        reportTransactionFailed(m_requestCallback.get(), error);
+        return true;  
+    }
+
+private:
+    StatementErrorCallback(PassRefPtr<ExecuteSQLCallback> requestCallback)
+        : m_requestCallback(requestCallback) { }
+    RefPtr<ExecuteSQLCallback> m_requestCallback;
+};
+
+class TransactionCallback : public SQLTransactionCallback {
+public:
+    static PassRefPtr<TransactionCallback> create(const String& sqlStatement, PassRefPtr<ExecuteSQLCallback> requestCallback)
+    {
+        return adoptRef(new TransactionCallback(sqlStatement, requestCallback));
+    }
+
+    virtual ~TransactionCallback() { }
+
+    virtual bool handleEvent(SQLTransaction* transaction)
+    {
+        if (!m_requestCallback->isActive())
+            return true;
+
+        Vector<SQLValue> sqlValues;
+        RefPtr<SQLStatementCallback> callback(StatementCallback::create(m_requestCallback.get()));
+        RefPtr<SQLStatementErrorCallback> errorCallback(StatementErrorCallback::create(m_requestCallback.get()));
+        transaction->executeSQL(m_sqlStatement, sqlValues, callback.release(), errorCallback.release(), IGNORE_EXCEPTION);
+        return true;
+    }
+private:
+    TransactionCallback(const String& sqlStatement, PassRefPtr<ExecuteSQLCallback> requestCallback)
+        : m_sqlStatement(sqlStatement)
+        , m_requestCallback(requestCallback) { }
+    String m_sqlStatement;
+    RefPtr<ExecuteSQLCallback> m_requestCallback;
+};
+
+class TransactionErrorCallback : public SQLTransactionErrorCallback {
+public:
+    static PassRefPtr<TransactionErrorCallback> create(PassRefPtr<ExecuteSQLCallback> requestCallback)
+    {
+        return adoptRef(new TransactionErrorCallback(requestCallback));
+    }
+
+    virtual ~TransactionErrorCallback() { }
+
+    virtual bool handleEvent(SQLError* error)
+    {
+        reportTransactionFailed(m_requestCallback.get(), error);
+        return true;
+    }
+private:
+    TransactionErrorCallback(PassRefPtr<ExecuteSQLCallback> requestCallback)
+        : m_requestCallback(requestCallback) { }
+    RefPtr<ExecuteSQLCallback> m_requestCallback;
+};
+
+class TransactionSuccessCallback : public VoidCallback {
+public:
+    static PassRefPtr<TransactionSuccessCallback> create()
+    {
+        return adoptRef(new TransactionSuccessCallback());
+    }
+
+    virtual ~TransactionSuccessCallback() { }
+
+    virtual bool handleEvent() { return false; }
+
+private:
+    TransactionSuccessCallback() { }
+};
+
+} // namespace
+
+void InspectorDatabaseAgent::didOpenDatabase(PassRefPtr<Database> database, const String& domain, const String& name, const String& version)
+{
+    if (InspectorDatabaseResource* resource = findByFileName(database->fileName())) {
+        resource->setDatabase(database);
+        return;
+    }
+
+    RefPtr<InspectorDatabaseResource> resource = InspectorDatabaseResource::create(database, domain, name, version);
+    m_resources.set(resource->id(), resource);
+    // Resources are only bound while visible.
+    if (m_frontend && m_enabled)
+        resource->bind(m_frontend);
+}
+
+void InspectorDatabaseAgent::clearResources()
+{
+    m_resources.clear();
+}
+
+InspectorDatabaseAgent::InspectorDatabaseAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state)
+    : InspectorBaseAgent<InspectorDatabaseAgent>("Database", instrumentingAgents, state)
+    , m_enabled(false)
+{
+    m_instrumentingAgents->setInspectorDatabaseAgent(this);
+}
+
+InspectorDatabaseAgent::~InspectorDatabaseAgent()
+{
+    m_instrumentingAgents->setInspectorDatabaseAgent(0);
+}
+
+void InspectorDatabaseAgent::setFrontend(InspectorFrontend* frontend)
+{
+    m_frontend = frontend->database();
+}
+
+void InspectorDatabaseAgent::clearFrontend()
+{
+    m_frontend = 0;
+    disable(0);
+}
+
+void InspectorDatabaseAgent::enable(ErrorString*)
+{
+    if (m_enabled)
+        return;
+    m_enabled = true;
+    m_state->setBoolean(DatabaseAgentState::databaseAgentEnabled, m_enabled);
+
+    DatabaseResourcesMap::iterator databasesEnd = m_resources.end();
+    for (DatabaseResourcesMap::iterator it = m_resources.begin(); it != databasesEnd; ++it)
+        it->value->bind(m_frontend);
+}
+
+void InspectorDatabaseAgent::disable(ErrorString*)
+{
+    if (!m_enabled)
+        return;
+    m_enabled = false;
+    m_state->setBoolean(DatabaseAgentState::databaseAgentEnabled, m_enabled);
+}
+
+void InspectorDatabaseAgent::restore()
+{
+    m_enabled = m_state->getBoolean(DatabaseAgentState::databaseAgentEnabled);
+}
+
+void InspectorDatabaseAgent::getDatabaseTableNames(ErrorString* error, const String& databaseId, RefPtr<TypeBuilder::Array<String> >& names)
+{
+    if (!m_enabled) {
+        *error = "Database agent is not enabled";
+        return;
+    }
+
+    names = TypeBuilder::Array<String>::create();
+
+    Database* database = databaseForId(databaseId);
+    if (database) {
+        Vector<String> tableNames = database->tableNames();
+        unsigned length = tableNames.size();
+        for (unsigned i = 0; i < length; ++i)
+            names->addItem(tableNames[i]);
+    }
+}
+
+void InspectorDatabaseAgent::executeSQL(ErrorString*, const String& databaseId, const String& query, PassRefPtr<ExecuteSQLCallback> prpRequestCallback)
+{
+    RefPtr<ExecuteSQLCallback> requestCallback = prpRequestCallback;
+
+    if (!m_enabled) {
+        requestCallback->sendFailure("Database agent is not enabled");
+        return;
+    }
+
+    Database* database = databaseForId(databaseId);
+    if (!database) {
+        requestCallback->sendFailure("Database not found");
+        return;
+    }
+
+    RefPtr<SQLTransactionCallback> callback(TransactionCallback::create(query, requestCallback.get()));
+    RefPtr<SQLTransactionErrorCallback> errorCallback(TransactionErrorCallback::create(requestCallback.get()));
+    RefPtr<VoidCallback> successCallback(TransactionSuccessCallback::create());
+    database->transaction(callback.release(), errorCallback.release(), successCallback.release());
+}
+
+String InspectorDatabaseAgent::databaseId(Database* database)
+{
+    for (DatabaseResourcesMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) {
+        if (it->value->database() == database)
+            return it->key;
+    }
+    return String();
+}
+
+InspectorDatabaseResource* InspectorDatabaseAgent::findByFileName(const String& fileName)
+{
+    for (DatabaseResourcesMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) {
+        if (it->value->database()->fileName() == fileName)
+            return it->value.get();
+    }
+    return 0;
+}
+
+Database* InspectorDatabaseAgent::databaseForId(const String& databaseId)
+{
+    DatabaseResourcesMap::iterator it = m_resources.find(databaseId);
+    if (it == m_resources.end())
+        return 0;
+    return it->value->database();
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/InspectorDatabaseAgent.h b/Source/core/inspector/InspectorDatabaseAgent.h
new file mode 100644
index 0000000..7de93a1
--- /dev/null
+++ b/Source/core/inspector/InspectorDatabaseAgent.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef InspectorDatabaseAgent_h
+#define InspectorDatabaseAgent_h
+
+#include "InspectorFrontend.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class Database;
+class InspectorArray;
+class InspectorDatabaseResource;
+class InspectorFrontend;
+class InspectorState;
+class InstrumentingAgents;
+
+typedef String ErrorString;
+
+class InspectorDatabaseAgent : public InspectorBaseAgent<InspectorDatabaseAgent>, public InspectorBackendDispatcher::DatabaseCommandHandler {
+public:
+    static PassOwnPtr<InspectorDatabaseAgent> create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state)
+    {
+        return adoptPtr(new InspectorDatabaseAgent(instrumentingAgents, state));
+    }
+    ~InspectorDatabaseAgent();
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void restore();
+
+    void clearResources();
+
+    // Called from the front-end.
+    virtual void enable(ErrorString*);
+    virtual void disable(ErrorString*);
+    virtual void getDatabaseTableNames(ErrorString*, const String& databaseId, RefPtr<TypeBuilder::Array<String> >& names);
+    virtual void executeSQL(ErrorString*, const String& databaseId, const String& query, PassRefPtr<ExecuteSQLCallback>);
+
+    // Called from the injected script.
+    String databaseId(Database*);
+
+    void didOpenDatabase(PassRefPtr<Database>, const String& domain, const String& name, const String& version);
+private:
+    explicit InspectorDatabaseAgent(InstrumentingAgents*, InspectorCompositeState*);
+
+    Database* databaseForId(const String& databaseId);
+    InspectorDatabaseResource* findByFileName(const String& fileName);
+
+    InspectorFrontend::Database* m_frontend;
+    typedef HashMap<String, RefPtr<InspectorDatabaseResource> > DatabaseResourcesMap;
+    DatabaseResourcesMap m_resources;
+    bool m_enabled;
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorDatabaseAgent_h)
diff --git a/Source/core/inspector/InspectorDatabaseInstrumentation.h b/Source/core/inspector/InspectorDatabaseInstrumentation.h
new file mode 100644
index 0000000..ae05d5f
--- /dev/null
+++ b/Source/core/inspector/InspectorDatabaseInstrumentation.h
@@ -0,0 +1,55 @@
+/*
+* Copyright (C) 2011 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.
+*/
+
+#ifndef InspectorDatabaseInstrumentation_h
+#define InspectorDatabaseInstrumentation_h
+
+#include "core/inspector/InspectorInstrumentation.h"
+#include "modules/webdatabase/Database.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/UnusedParam.h>
+
+namespace WebCore {
+
+namespace InspectorInstrumentation {
+
+void didOpenDatabaseImpl(InstrumentingAgents*, PassRefPtr<Database>, const String& domain, const String& name, const String& version);
+
+inline void didOpenDatabase(ScriptExecutionContext* context, PassRefPtr<Database> database, const String& domain, const String& name, const String& version)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        didOpenDatabaseImpl(instrumentingAgents, database, domain, name, version);
+}
+
+} // namespace InspectorInstrumentation
+
+} // namespace WebCore
+
+#endif // !defined(InspectorDatabaseInstrumentation_h)
diff --git a/Source/core/inspector/InspectorDatabaseResource.cpp b/Source/core/inspector/InspectorDatabaseResource.cpp
new file mode 100644
index 0000000..e63082c
--- /dev/null
+++ b/Source/core/inspector/InspectorDatabaseResource.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2009 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+
+#include "core/inspector/InspectorDatabaseResource.h"
+
+#include "InspectorFrontend.h"
+#include "core/inspector/InspectorValues.h"
+#include "modules/webdatabase/Database.h"
+
+namespace WebCore {
+
+static int nextUnusedId = 1;
+
+PassRefPtr<InspectorDatabaseResource> InspectorDatabaseResource::create(PassRefPtr<Database> database, const String& domain, const String& name, const String& version)
+{
+    return adoptRef(new InspectorDatabaseResource(database, domain, name, version));
+}
+
+InspectorDatabaseResource::InspectorDatabaseResource(PassRefPtr<Database> database, const String& domain, const String& name, const String& version)
+    : m_database(database)
+    , m_id(String::number(nextUnusedId++))
+    , m_domain(domain)
+    , m_name(name)
+    , m_version(version)
+{
+}
+
+void InspectorDatabaseResource::bind(InspectorFrontend::Database* frontend)
+{
+    RefPtr<TypeBuilder::Database::Database> jsonObject = TypeBuilder::Database::Database::create()
+        .setId(m_id)
+        .setDomain(m_domain)
+        .setName(m_name)
+        .setVersion(m_version);
+    frontend->addDatabase(jsonObject);
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/InspectorDatabaseResource.h b/Source/core/inspector/InspectorDatabaseResource.h
new file mode 100644
index 0000000..6644fa2
--- /dev/null
+++ b/Source/core/inspector/InspectorDatabaseResource.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2009 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef InspectorDatabaseResource_h
+#define InspectorDatabaseResource_h
+
+#include "InspectorFrontend.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+class Database;
+class InspectorFrontend;
+
+class InspectorDatabaseResource : public RefCounted<InspectorDatabaseResource> {
+public:
+    static PassRefPtr<InspectorDatabaseResource> create(PassRefPtr<Database> database, const String& domain, const String& name, const String& version);
+
+    void bind(InspectorFrontend::Database*);
+    Database* database() { return m_database.get(); }
+    void setDatabase(PassRefPtr<Database> database) { m_database = database; }
+    String id() const { return m_id; }
+
+private:
+    InspectorDatabaseResource(PassRefPtr<Database>, const String& domain, const String& name, const String& version);
+
+    RefPtr<Database> m_database;
+    String m_id;
+    String m_domain;
+    String m_name;
+    String m_version;
+};
+
+} // namespace WebCore
+
+#endif // InspectorDatabaseResource_h
diff --git a/Source/core/inspector/InspectorDebuggerAgent.cpp b/Source/core/inspector/InspectorDebuggerAgent.cpp
new file mode 100644
index 0000000..b352bda
--- /dev/null
+++ b/Source/core/inspector/InspectorDebuggerAgent.cpp
@@ -0,0 +1,780 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2011 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorDebuggerAgent.h"
+
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptDebugServer.h"
+#include "bindings/v8/ScriptObject.h"
+#include "core/inspector/ContentSearchUtils.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/loader/cache/CachedResource.h"
+#include "core/platform/text/RegularExpression.h"
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/MemoryInstrumentationVector.h>
+#include <wtf/text/WTFString.h>
+
+using WebCore::TypeBuilder::Array;
+using WebCore::TypeBuilder::Debugger::FunctionDetails;
+using WebCore::TypeBuilder::Debugger::ScriptId;
+using WebCore::TypeBuilder::Runtime::RemoteObject;
+
+namespace WebCore {
+
+namespace DebuggerAgentState {
+static const char debuggerEnabled[] = "debuggerEnabled";
+static const char javaScriptBreakpoints[] = "javaScriptBreakopints";
+static const char pauseOnExceptionsState[] = "pauseOnExceptionsState";
+};
+
+const char* InspectorDebuggerAgent::backtraceObjectGroup = "backtrace";
+
+InspectorDebuggerAgent::InspectorDebuggerAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager)
+    : InspectorBaseAgent<InspectorDebuggerAgent>("Debugger", instrumentingAgents, inspectorState)
+    , m_injectedScriptManager(injectedScriptManager)
+    , m_frontend(0)
+    , m_pausedScriptState(0)
+    , m_javaScriptPauseScheduled(false)
+    , m_listener(0)
+{
+    // FIXME: make breakReason optional so that there was no need to init it with "other".
+    clearBreakDetails();
+    m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, ScriptDebugServer::DontPauseOnExceptions);
+}
+
+InspectorDebuggerAgent::~InspectorDebuggerAgent()
+{
+    ASSERT(!m_instrumentingAgents->inspectorDebuggerAgent());
+}
+
+void InspectorDebuggerAgent::enable()
+{
+    m_instrumentingAgents->setInspectorDebuggerAgent(this);
+
+    // FIXME(WK44513): breakpoints activated flag should be synchronized between all front-ends
+    scriptDebugServer().setBreakpointsActivated(true);
+    startListeningScriptDebugServer();
+
+    if (m_listener)
+        m_listener->debuggerWasEnabled();
+}
+
+void InspectorDebuggerAgent::disable()
+{
+    m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, InspectorObject::create());
+    m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, ScriptDebugServer::DontPauseOnExceptions);
+    m_instrumentingAgents->setInspectorDebuggerAgent(0);
+
+    stopListeningScriptDebugServer();
+    scriptDebugServer().clearBreakpoints();
+    scriptDebugServer().clearCompiledScripts();
+    clear();
+
+    if (m_listener)
+        m_listener->debuggerWasDisabled();
+}
+
+bool InspectorDebuggerAgent::enabled()
+{
+    return m_state->getBoolean(DebuggerAgentState::debuggerEnabled);
+}
+
+void InspectorDebuggerAgent::enable(ErrorString*)
+{
+    if (enabled())
+        return;
+
+    enable();
+    m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true);
+
+    ASSERT(m_frontend);
+}
+
+void InspectorDebuggerAgent::disable(ErrorString*)
+{
+    if (!enabled())
+        return;
+
+    disable();
+    m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false);
+}
+
+void InspectorDebuggerAgent::restore()
+{
+    if (enabled()) {
+        m_frontend->globalObjectCleared();
+        enable();
+        long pauseState = m_state->getLong(DebuggerAgentState::pauseOnExceptionsState);
+        String error;
+        setPauseOnExceptionsImpl(&error, pauseState);
+    }
+}
+
+void InspectorDebuggerAgent::setFrontend(InspectorFrontend* frontend)
+{
+    m_frontend = frontend->debugger();
+}
+
+void InspectorDebuggerAgent::clearFrontend()
+{
+    m_frontend = 0;
+
+    if (!enabled())
+        return;
+
+    disable();
+
+    // FIXME: due to m_state->mute() hack in InspectorController, debuggerEnabled is actually set to false only
+    // in InspectorState, but not in cookie. That's why after navigation debuggerEnabled will be true,
+    // but after front-end re-open it will still be false.
+    m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false);
+}
+
+void InspectorDebuggerAgent::setBreakpointsActive(ErrorString*, bool active)
+{
+    scriptDebugServer().setBreakpointsActivated(active);
+}
+
+bool InspectorDebuggerAgent::isPaused()
+{
+    return scriptDebugServer().isPaused();
+}
+
+bool InspectorDebuggerAgent::runningNestedMessageLoop()
+{
+    return scriptDebugServer().runningNestedMessageLoop();
+}
+
+void InspectorDebuggerAgent::addMessageToConsole(MessageSource source, MessageType type)
+{
+    if (scriptDebugServer().pauseOnExceptionsState() != ScriptDebugServer::DontPauseOnExceptions && source == ConsoleAPIMessageSource && type == AssertMessageType)
+        breakProgram(InspectorFrontend::Debugger::Reason::Assert, 0);
+}
+
+static PassRefPtr<InspectorObject> buildObjectForBreakpointCookie(const String& url, int lineNumber, int columnNumber, const String& condition, bool isRegex)
+{
+    RefPtr<InspectorObject> breakpointObject = InspectorObject::create();
+    breakpointObject->setString("url", url);
+    breakpointObject->setNumber("lineNumber", lineNumber);
+    breakpointObject->setNumber("columnNumber", columnNumber);
+    breakpointObject->setString("condition", condition);
+    breakpointObject->setBoolean("isRegex", isRegex);
+    return breakpointObject;
+}
+
+static bool matches(const String& url, const String& pattern, bool isRegex)
+{
+    if (isRegex) {
+        RegularExpression regex(pattern, TextCaseSensitive);
+        return regex.match(url) != -1;
+    }
+    return url == pattern;
+}
+
+void InspectorDebuggerAgent::setBreakpointByUrl(ErrorString* errorString, int lineNumber, const String* const optionalURL, const String* const optionalURLRegex, const int* const optionalColumnNumber, const String* const optionalCondition, TypeBuilder::Debugger::BreakpointId* outBreakpointId, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::Location> >& locations)
+{
+    locations = Array<TypeBuilder::Debugger::Location>::create();
+    if (!optionalURL == !optionalURLRegex) {
+        *errorString = "Either url or urlRegex must be specified.";
+        return;
+    }
+
+    String url = optionalURL ? *optionalURL : *optionalURLRegex;
+    int columnNumber = optionalColumnNumber ? *optionalColumnNumber : 0;
+    String condition = optionalCondition ? *optionalCondition : "";
+    bool isRegex = optionalURLRegex;
+
+    String breakpointId = (isRegex ? "/" + url + "/" : url) + ':' + String::number(lineNumber) + ':' + String::number(columnNumber);
+    RefPtr<InspectorObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
+    if (breakpointsCookie->find(breakpointId) != breakpointsCookie->end()) {
+        *errorString = "Breakpoint at specified location already exists.";
+        return;
+    }
+
+    breakpointsCookie->setObject(breakpointId, buildObjectForBreakpointCookie(url, lineNumber, columnNumber, condition, isRegex));
+    m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
+
+    ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
+    for (ScriptsMap::iterator it = m_scripts.begin(); it != m_scripts.end(); ++it) {
+        if (!matches(it->value.url, url, isRegex))
+            continue;
+        RefPtr<TypeBuilder::Debugger::Location> location = resolveBreakpoint(breakpointId, it->key, breakpoint);
+        if (location)
+            locations->addItem(location);
+    }
+    *outBreakpointId = breakpointId;
+}
+
+static bool parseLocation(ErrorString* errorString, RefPtr<InspectorObject> location, String* scriptId, int* lineNumber, int* columnNumber)
+{
+    if (!location->getString("scriptId", scriptId) || !location->getNumber("lineNumber", lineNumber)) {
+        // FIXME: replace with input validation.
+        *errorString = "scriptId and lineNumber are required.";
+        return false;
+    }
+    *columnNumber = 0;
+    location->getNumber("columnNumber", columnNumber);
+    return true;
+}
+
+void InspectorDebuggerAgent::setBreakpoint(ErrorString* errorString, const RefPtr<InspectorObject>& location, const String* const optionalCondition, TypeBuilder::Debugger::BreakpointId* outBreakpointId, RefPtr<TypeBuilder::Debugger::Location>& actualLocation)
+{
+    String scriptId;
+    int lineNumber;
+    int columnNumber;
+
+    if (!parseLocation(errorString, location, &scriptId, &lineNumber, &columnNumber))
+        return;
+
+    String condition = optionalCondition ? *optionalCondition : emptyString();
+
+    String breakpointId = scriptId + ':' + String::number(lineNumber) + ':' + String::number(columnNumber);
+    if (m_breakpointIdToDebugServerBreakpointIds.find(breakpointId) != m_breakpointIdToDebugServerBreakpointIds.end()) {
+        *errorString = "Breakpoint at specified location already exists.";
+        return;
+    }
+    ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
+    actualLocation = resolveBreakpoint(breakpointId, scriptId, breakpoint);
+    if (actualLocation)
+        *outBreakpointId = breakpointId;
+    else
+        *errorString = "Could not resolve breakpoint";
+}
+
+void InspectorDebuggerAgent::removeBreakpoint(ErrorString*, const String& breakpointId)
+{
+    RefPtr<InspectorObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
+    breakpointsCookie->remove(breakpointId);
+    m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
+
+    BreakpointIdToDebugServerBreakpointIdsMap::iterator debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.find(breakpointId);
+    if (debugServerBreakpointIdsIterator == m_breakpointIdToDebugServerBreakpointIds.end())
+        return;
+    for (size_t i = 0; i < debugServerBreakpointIdsIterator->value.size(); ++i)
+        scriptDebugServer().removeBreakpoint(debugServerBreakpointIdsIterator->value[i]);
+    m_breakpointIdToDebugServerBreakpointIds.remove(debugServerBreakpointIdsIterator);
+}
+
+void InspectorDebuggerAgent::continueToLocation(ErrorString* errorString, const RefPtr<InspectorObject>& location)
+{
+    if (!m_continueToLocationBreakpointId.isEmpty()) {
+        scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointId);
+        m_continueToLocationBreakpointId = "";
+    }
+
+    String scriptId;
+    int lineNumber;
+    int columnNumber;
+
+    if (!parseLocation(errorString, location, &scriptId, &lineNumber, &columnNumber))
+        return;
+
+    ScriptBreakpoint breakpoint(lineNumber, columnNumber, "");
+    m_continueToLocationBreakpointId = scriptDebugServer().setBreakpoint(scriptId, breakpoint, &lineNumber, &columnNumber);
+    resume(errorString);
+}
+
+PassRefPtr<TypeBuilder::Debugger::Location> InspectorDebuggerAgent::resolveBreakpoint(const String& breakpointId, const String& scriptId, const ScriptBreakpoint& breakpoint)
+{
+    ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId);
+    if (scriptIterator == m_scripts.end())
+        return 0;
+    Script& script = scriptIterator->value;
+    if (breakpoint.lineNumber < script.startLine || script.endLine < breakpoint.lineNumber)
+        return 0;
+
+    int actualLineNumber;
+    int actualColumnNumber;
+    String debugServerBreakpointId = scriptDebugServer().setBreakpoint(scriptId, breakpoint, &actualLineNumber, &actualColumnNumber);
+    if (debugServerBreakpointId.isEmpty())
+        return 0;
+
+    BreakpointIdToDebugServerBreakpointIdsMap::iterator debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.find(breakpointId);
+    if (debugServerBreakpointIdsIterator == m_breakpointIdToDebugServerBreakpointIds.end())
+        debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.set(breakpointId, Vector<String>()).iterator;
+    debugServerBreakpointIdsIterator->value.append(debugServerBreakpointId);
+
+    RefPtr<TypeBuilder::Debugger::Location> location = TypeBuilder::Debugger::Location::create()
+        .setScriptId(scriptId)
+        .setLineNumber(actualLineNumber);
+    location->setColumnNumber(actualColumnNumber);
+    return location;
+}
+
+static PassRefPtr<InspectorObject> scriptToInspectorObject(ScriptObject scriptObject)
+{
+    if (scriptObject.hasNoValue())
+        return 0;
+    RefPtr<InspectorValue> value = scriptObject.toInspectorValue(scriptObject.scriptState());
+    if (!value)
+        return 0;
+    return value->asObject();
+}
+
+void InspectorDebuggerAgent::searchInContent(ErrorString* error, const String& scriptId, const String& query, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<Array<WebCore::TypeBuilder::Page::SearchMatch> >& results)
+{
+    bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
+    bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false;
+
+    ScriptsMap::iterator it = m_scripts.find(scriptId);
+    if (it != m_scripts.end())
+        results = ContentSearchUtils::searchInTextByLines(it->value.source, query, caseSensitive, isRegex);
+    else
+        *error = "No script for id: " + scriptId;
+}
+
+void InspectorDebuggerAgent::setScriptSource(ErrorString* error, const String& scriptId, const String& newContent, const bool* const preview, RefPtr<Array<TypeBuilder::Debugger::CallFrame> >& newCallFrames, RefPtr<InspectorObject>& result)
+{
+    bool previewOnly = preview && *preview;
+    ScriptObject resultObject;
+    if (!scriptDebugServer().setScriptSource(scriptId, newContent, previewOnly, error, &m_currentCallStack, &resultObject))
+        return;
+    newCallFrames = currentCallFrames();
+    RefPtr<InspectorObject> object = scriptToInspectorObject(resultObject);
+    if (object)
+        result = object;
+}
+void InspectorDebuggerAgent::restartFrame(ErrorString* errorString, const String& callFrameId, RefPtr<Array<TypeBuilder::Debugger::CallFrame> >& newCallFrames, RefPtr<InspectorObject>& result)
+{
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(callFrameId);
+    if (injectedScript.hasNoValue()) {
+        *errorString = "Inspected frame has gone";
+        return;
+    }
+
+    injectedScript.restartFrame(errorString, m_currentCallStack, callFrameId, &result);
+    scriptDebugServer().updateCallStack(&m_currentCallStack);
+    newCallFrames = currentCallFrames();
+}
+
+void InspectorDebuggerAgent::getScriptSource(ErrorString* error, const String& scriptId, String* scriptSource)
+{
+    ScriptsMap::iterator it = m_scripts.find(scriptId);
+    if (it != m_scripts.end())
+        *scriptSource = it->value.source;
+    else
+        *error = "No script for id: " + scriptId;
+}
+
+void InspectorDebuggerAgent::getFunctionDetails(ErrorString* errorString, const String& functionId, RefPtr<TypeBuilder::Debugger::FunctionDetails>& details)
+{
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(functionId);
+    if (injectedScript.hasNoValue()) {
+        *errorString = "Function object id is obsolete";
+        return;
+    }
+    injectedScript.getFunctionDetails(errorString, functionId, &details);
+}
+
+void InspectorDebuggerAgent::schedulePauseOnNextStatement(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<InspectorObject> data)
+{
+    if (m_javaScriptPauseScheduled)
+        return;
+    m_breakReason = breakReason;
+    m_breakAuxData = data;
+    scriptDebugServer().setPauseOnNextStatement(true);
+}
+
+void InspectorDebuggerAgent::cancelPauseOnNextStatement()
+{
+    if (m_javaScriptPauseScheduled)
+        return;
+    clearBreakDetails();
+    scriptDebugServer().setPauseOnNextStatement(false);
+}
+
+void InspectorDebuggerAgent::pause(ErrorString*)
+{
+    if (m_javaScriptPauseScheduled)
+        return;
+    clearBreakDetails();
+    scriptDebugServer().setPauseOnNextStatement(true);
+    m_javaScriptPauseScheduled = true;
+}
+
+void InspectorDebuggerAgent::resume(ErrorString* errorString)
+{
+    if (!assertPaused(errorString))
+        return;
+    m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
+    scriptDebugServer().continueProgram();
+}
+
+void InspectorDebuggerAgent::stepOver(ErrorString* errorString)
+{
+    if (!assertPaused(errorString))
+        return;
+    m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
+    scriptDebugServer().stepOverStatement();
+}
+
+void InspectorDebuggerAgent::stepInto(ErrorString* errorString)
+{
+    if (!assertPaused(errorString))
+        return;
+    m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
+    scriptDebugServer().stepIntoStatement();
+    if (m_listener)
+        m_listener->stepInto();
+}
+
+void InspectorDebuggerAgent::stepOut(ErrorString* errorString)
+{
+    if (!assertPaused(errorString))
+        return;
+    m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
+    scriptDebugServer().stepOutOfFunction();
+}
+
+void InspectorDebuggerAgent::setPauseOnExceptions(ErrorString* errorString, const String& stringPauseState)
+{
+    ScriptDebugServer::PauseOnExceptionsState pauseState;
+    if (stringPauseState == "none")
+        pauseState = ScriptDebugServer::DontPauseOnExceptions;
+    else if (stringPauseState == "all")
+        pauseState = ScriptDebugServer::PauseOnAllExceptions;
+    else if (stringPauseState == "uncaught")
+        pauseState = ScriptDebugServer::PauseOnUncaughtExceptions;
+    else {
+        *errorString = "Unknown pause on exceptions mode: " + stringPauseState;
+        return;
+    }
+    setPauseOnExceptionsImpl(errorString, pauseState);
+}
+
+void InspectorDebuggerAgent::setPauseOnExceptionsImpl(ErrorString* errorString, int pauseState)
+{
+    scriptDebugServer().setPauseOnExceptionsState(static_cast<ScriptDebugServer::PauseOnExceptionsState>(pauseState));
+    if (scriptDebugServer().pauseOnExceptionsState() != pauseState)
+        *errorString = "Internal error. Could not change pause on exceptions state";
+    else
+        m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, pauseState);
+}
+
+void InspectorDebuggerAgent::evaluateOnCallFrame(ErrorString* errorString, const String& callFrameId, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptionsAndMuteConsole, const bool* const returnByValue, const bool* generatePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown)
+{
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(callFrameId);
+    if (injectedScript.hasNoValue()) {
+        *errorString = "Inspected frame has gone";
+        return;
+    }
+
+    ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = scriptDebugServer().pauseOnExceptionsState();
+    if (doNotPauseOnExceptionsAndMuteConsole ? *doNotPauseOnExceptionsAndMuteConsole : false) {
+        if (previousPauseOnExceptionsState != ScriptDebugServer::DontPauseOnExceptions)
+            scriptDebugServer().setPauseOnExceptionsState(ScriptDebugServer::DontPauseOnExceptions);
+        muteConsole();
+    }
+
+    injectedScript.evaluateOnCallFrame(errorString, m_currentCallStack, callFrameId, expression, objectGroup ? *objectGroup : "", includeCommandLineAPI ? *includeCommandLineAPI : false, returnByValue ? *returnByValue : false, generatePreview ? *generatePreview : false, &result, wasThrown);
+
+    if (doNotPauseOnExceptionsAndMuteConsole ? *doNotPauseOnExceptionsAndMuteConsole : false) {
+        unmuteConsole();
+        if (scriptDebugServer().pauseOnExceptionsState() != previousPauseOnExceptionsState)
+            scriptDebugServer().setPauseOnExceptionsState(previousPauseOnExceptionsState);
+    }
+}
+
+void InspectorDebuggerAgent::compileScript(ErrorString* errorString, const String& expression, const String& sourceURL, TypeBuilder::OptOutput<ScriptId>* scriptId, TypeBuilder::OptOutput<String>* syntaxErrorMessage)
+{
+    InjectedScript injectedScript = injectedScriptForEval(errorString, 0);
+    if (injectedScript.hasNoValue()) {
+        *errorString = "Inspected frame has gone";
+        return;
+    }
+
+    String scriptIdValue;
+    String exceptionMessage;
+    scriptDebugServer().compileScript(injectedScript.scriptState(), expression, sourceURL, &scriptIdValue, &exceptionMessage);
+    if (!scriptIdValue && !exceptionMessage) {
+        *errorString = "Script compilation failed";
+        return;
+    }
+    *syntaxErrorMessage = exceptionMessage;
+    *scriptId = scriptIdValue;
+}
+
+void InspectorDebuggerAgent::runScript(ErrorString* errorString, const ScriptId& scriptId, const int* executionContextId, const String* const objectGroup, const bool* const doNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown)
+{
+    InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId);
+    if (injectedScript.hasNoValue()) {
+        *errorString = "Inspected frame has gone";
+        return;
+    }
+
+    ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = scriptDebugServer().pauseOnExceptionsState();
+    if (doNotPauseOnExceptionsAndMuteConsole && *doNotPauseOnExceptionsAndMuteConsole) {
+        if (previousPauseOnExceptionsState != ScriptDebugServer::DontPauseOnExceptions)
+            scriptDebugServer().setPauseOnExceptionsState(ScriptDebugServer::DontPauseOnExceptions);
+        muteConsole();
+    }
+
+    ScriptValue value;
+    bool wasThrownValue;
+    String exceptionMessage;
+    scriptDebugServer().runScript(injectedScript.scriptState(), scriptId, &value, &wasThrownValue, &exceptionMessage);
+    *wasThrown = wasThrownValue;
+    if (value.hasNoValue()) {
+        *errorString = "Script execution failed";
+        return;
+    }
+    result = injectedScript.wrapObject(value, objectGroup ? *objectGroup : "");
+    if (wasThrownValue)
+        result->setDescription(exceptionMessage);
+
+    if (doNotPauseOnExceptionsAndMuteConsole && *doNotPauseOnExceptionsAndMuteConsole) {
+        unmuteConsole();
+        if (scriptDebugServer().pauseOnExceptionsState() != previousPauseOnExceptionsState)
+            scriptDebugServer().setPauseOnExceptionsState(previousPauseOnExceptionsState);
+    }
+}
+
+void InspectorDebuggerAgent::setOverlayMessage(ErrorString*, const String*)
+{
+}
+
+void InspectorDebuggerAgent::setVariableValue(ErrorString* errorString, int scopeNumber, const String& variableName, const RefPtr<InspectorObject>& newValue, const String* callFrameId, const String* functionObjectId)
+{
+    InjectedScript injectedScript;
+    if (callFrameId) {
+        injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*callFrameId);
+        if (injectedScript.hasNoValue()) {
+            *errorString = "Inspected frame has gone";
+            return;
+        }
+    } else if (functionObjectId) {
+        injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*functionObjectId);
+        if (injectedScript.hasNoValue()) {
+            *errorString = "Function object id cannot be resolved";
+            return;
+        }
+    } else {
+        *errorString = "Either call frame or function object must be specified";
+        return;
+    }
+    String newValueString = newValue->toJSONString();
+
+    injectedScript.setVariableValue(errorString, m_currentCallStack, callFrameId, functionObjectId, scopeNumber, variableName, newValueString);
+}
+
+void InspectorDebuggerAgent::scriptExecutionBlockedByCSP(const String& directiveText)
+{
+    if (scriptDebugServer().pauseOnExceptionsState() != ScriptDebugServer::DontPauseOnExceptions) {
+        RefPtr<InspectorObject> directive = InspectorObject::create();
+        directive->setString("directiveText", directiveText);
+        breakProgram(InspectorFrontend::Debugger::Reason::CSPViolation, directive.release());
+    }
+}
+
+PassRefPtr<Array<TypeBuilder::Debugger::CallFrame> > InspectorDebuggerAgent::currentCallFrames()
+{
+    if (!m_pausedScriptState)
+        return Array<TypeBuilder::Debugger::CallFrame>::create();
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(m_pausedScriptState);
+    if (injectedScript.hasNoValue()) {
+        ASSERT_NOT_REACHED();
+        return Array<TypeBuilder::Debugger::CallFrame>::create();
+    }
+    return injectedScript.wrapCallFrames(m_currentCallStack);
+}
+
+String InspectorDebuggerAgent::sourceMapURLForScript(const Script& script)
+{
+    DEFINE_STATIC_LOCAL(String, sourceMapHttpHeader, (ASCIILiteral("X-SourceMap")));
+
+    String sourceMapURL = ContentSearchUtils::findSourceMapURL(script.source);
+    if (!sourceMapURL.isEmpty())
+        return sourceMapURL;
+
+    if (script.url.isEmpty())
+        return String();
+
+    InspectorPageAgent* pageAgent = m_instrumentingAgents->inspectorPageAgent();
+    if (!pageAgent)
+        return String();
+
+    CachedResource* resource = pageAgent->cachedResource(pageAgent->mainFrame(), KURL(ParsedURLString, script.url));
+    if (resource)
+        return resource->response().httpHeaderField(sourceMapHttpHeader);
+    return String();
+}
+
+// JavaScriptDebugListener functions
+
+void InspectorDebuggerAgent::didParseSource(const String& scriptId, const Script& script)
+{
+    // Don't send script content to the front end until it's really needed.
+    const bool* isContentScript = script.isContentScript ? &script.isContentScript : 0;
+    String sourceMapURL = sourceMapURLForScript(script);
+    String* sourceMapURLParam = sourceMapURL.isNull() ? 0 : &sourceMapURL;
+    String sourceURL;
+    if (!script.startLine && !script.startColumn)
+        sourceURL = ContentSearchUtils::findSourceURL(script.source);
+    bool hasSourceURL = !sourceURL.isEmpty();
+    String scriptURL = hasSourceURL ? sourceURL : script.url;
+    bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : 0;
+    m_frontend->scriptParsed(scriptId, scriptURL, script.startLine, script.startColumn, script.endLine, script.endColumn, isContentScript, sourceMapURLParam, hasSourceURLParam);
+
+    m_scripts.set(scriptId, script);
+
+    if (scriptURL.isEmpty())
+        return;
+
+    RefPtr<InspectorObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
+    for (InspectorObject::iterator it = breakpointsCookie->begin(); it != breakpointsCookie->end(); ++it) {
+        RefPtr<InspectorObject> breakpointObject = it->value->asObject();
+        bool isRegex;
+        breakpointObject->getBoolean("isRegex", &isRegex);
+        String url;
+        breakpointObject->getString("url", &url);
+        if (!matches(scriptURL, url, isRegex))
+            continue;
+        ScriptBreakpoint breakpoint;
+        breakpointObject->getNumber("lineNumber", &breakpoint.lineNumber);
+        breakpointObject->getNumber("columnNumber", &breakpoint.columnNumber);
+        breakpointObject->getString("condition", &breakpoint.condition);
+        RefPtr<TypeBuilder::Debugger::Location> location = resolveBreakpoint(it->key, scriptId, breakpoint);
+        if (location)
+            m_frontend->breakpointResolved(it->key, location);
+    }
+}
+
+void InspectorDebuggerAgent::failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage)
+{
+    m_frontend->scriptFailedToParse(url, data, firstLine, errorLine, errorMessage);
+}
+
+void InspectorDebuggerAgent::didPause(ScriptState* scriptState, const ScriptValue& callFrames, const ScriptValue& exception)
+{
+    ASSERT(scriptState && !m_pausedScriptState);
+    m_pausedScriptState = scriptState;
+    m_currentCallStack = callFrames;
+
+    if (!exception.hasNoValue()) {
+        InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
+        if (!injectedScript.hasNoValue()) {
+            m_breakReason = InspectorFrontend::Debugger::Reason::Exception;
+            m_breakAuxData = injectedScript.wrapObject(exception, "backtrace")->openAccessors();
+            // m_breakAuxData might be null after this.
+        }
+    }
+
+    m_frontend->paused(currentCallFrames(), m_breakReason, m_breakAuxData);
+    m_javaScriptPauseScheduled = false;
+
+    if (!m_continueToLocationBreakpointId.isEmpty()) {
+        scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointId);
+        m_continueToLocationBreakpointId = "";
+    }
+    if (m_listener)
+        m_listener->didPause();
+}
+
+void InspectorDebuggerAgent::didContinue()
+{
+    m_pausedScriptState = 0;
+    m_currentCallStack = ScriptValue();
+    clearBreakDetails();
+    m_frontend->resumed();
+}
+
+void InspectorDebuggerAgent::breakProgram(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<InspectorObject> data)
+{
+    m_breakReason = breakReason;
+    m_breakAuxData = data;
+    scriptDebugServer().breakProgram();
+}
+
+void InspectorDebuggerAgent::clear()
+{
+    m_pausedScriptState = 0;
+    m_currentCallStack = ScriptValue();
+    m_scripts.clear();
+    m_breakpointIdToDebugServerBreakpointIds.clear();
+    m_continueToLocationBreakpointId = String();
+    clearBreakDetails();
+    m_javaScriptPauseScheduled = false;
+    ErrorString error;
+    setOverlayMessage(&error, 0);
+}
+
+bool InspectorDebuggerAgent::assertPaused(ErrorString* errorString)
+{
+    if (!m_pausedScriptState) {
+        *errorString = "Can only perform operation while paused.";
+        return false;
+    }
+    return true;
+}
+
+void InspectorDebuggerAgent::clearBreakDetails()
+{
+    m_breakReason = InspectorFrontend::Debugger::Reason::Other;
+    m_breakAuxData = 0;
+}
+
+void InspectorDebuggerAgent::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::InspectorDebuggerAgent);
+    InspectorBaseAgent<InspectorDebuggerAgent>::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_injectedScriptManager, "injectedScriptManager");
+    info.addWeakPointer(m_frontend);
+    info.addMember(m_pausedScriptState, "pausedScriptState");
+    info.addMember(m_currentCallStack, "currentCallStack");
+    info.addMember(m_scripts, "scripts");
+    info.addMember(m_breakpointIdToDebugServerBreakpointIds, "breakpointIdToDebugServerBreakpointIds");
+    info.addMember(m_continueToLocationBreakpointId, "continueToLocationBreakpointId");
+    info.addMember(m_breakAuxData, "breakAuxData");
+    info.addWeakPointer(m_listener);
+}
+
+void ScriptDebugListener::Script::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::InspectorDebuggerAgent);
+    info.addMember(url, "url");
+    info.addMember(source, "source");
+    info.addMember(sourceMappingURL, "sourceMappingURL");
+}
+
+void InspectorDebuggerAgent::reset()
+{
+    m_scripts.clear();
+    m_breakpointIdToDebugServerBreakpointIds.clear();
+    if (m_frontend)
+        m_frontend->globalObjectCleared();
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorDebuggerAgent.h b/Source/core/inspector/InspectorDebuggerAgent.h
new file mode 100644
index 0000000..1d8b715
--- /dev/null
+++ b/Source/core/inspector/InspectorDebuggerAgent.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2011 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef InspectorDebuggerAgent_h
+#define InspectorDebuggerAgent_h
+
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptState.h"
+#include "core/inspector/ConsoleAPITypes.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include "core/inspector/ScriptBreakpoint.h"
+#include "core/inspector/ScriptDebugListener.h"
+#include "core/page/ConsoleTypes.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class InjectedScriptManager;
+class InspectorFrontend;
+class InspectorArray;
+class InspectorObject;
+class InspectorState;
+class InspectorValue;
+class InstrumentingAgents;
+class ScriptDebugServer;
+class ScriptValue;
+
+typedef String ErrorString;
+
+class InspectorDebuggerAgent : public InspectorBaseAgent<InspectorDebuggerAgent>, public ScriptDebugListener, public InspectorBackendDispatcher::DebuggerCommandHandler {
+    WTF_MAKE_NONCOPYABLE(InspectorDebuggerAgent); WTF_MAKE_FAST_ALLOCATED;
+public:
+    static const char* backtraceObjectGroup;
+
+    virtual ~InspectorDebuggerAgent();
+
+    virtual void canSetScriptSource(ErrorString*, bool* result) { *result = true; }
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void restore();
+
+    bool isPaused();
+    bool runningNestedMessageLoop();
+    void addMessageToConsole(MessageSource, MessageType);
+
+    // Part of the protocol.
+    virtual void enable(ErrorString*);
+    virtual void disable(ErrorString*);
+    virtual void setBreakpointsActive(ErrorString*, bool active);
+
+    virtual void setBreakpointByUrl(ErrorString*, int lineNumber, const String* optionalURL, const String* optionalURLRegex, const int* optionalColumnNumber, const String* optionalCondition, TypeBuilder::Debugger::BreakpointId*, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::Location> >& locations);
+    virtual void setBreakpoint(ErrorString*, const RefPtr<InspectorObject>& location, const String* optionalCondition, TypeBuilder::Debugger::BreakpointId*, RefPtr<TypeBuilder::Debugger::Location>& actualLocation);
+    virtual void removeBreakpoint(ErrorString*, const String& breakpointId);
+    virtual void continueToLocation(ErrorString*, const RefPtr<InspectorObject>& location);
+
+    virtual void searchInContent(ErrorString*, const String& scriptId, const String& query, const bool* optionalCaseSensitive, const bool* optionalIsRegex, RefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchMatch> >&);
+    virtual void setScriptSource(ErrorString*, const String& scriptId, const String& newContent, const bool* preview, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::CallFrame> >& newCallFrames, RefPtr<InspectorObject>& result);
+    virtual void restartFrame(ErrorString*, const String& callFrameId, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::CallFrame> >& newCallFrames, RefPtr<InspectorObject>& result);
+    virtual void getScriptSource(ErrorString*, const String& scriptId, String* scriptSource);
+    virtual void getFunctionDetails(ErrorString*, const String& functionId, RefPtr<TypeBuilder::Debugger::FunctionDetails>&);
+    virtual void pause(ErrorString*);
+    virtual void resume(ErrorString*);
+    virtual void stepOver(ErrorString*);
+    virtual void stepInto(ErrorString*);
+    virtual void stepOut(ErrorString*);
+    virtual void setPauseOnExceptions(ErrorString*, const String& pauseState);
+    virtual void evaluateOnCallFrame(ErrorString*,
+                             const String& callFrameId,
+                             const String& expression,
+                             const String* objectGroup,
+                             const bool* includeCommandLineAPI,
+                             const bool* doNotPauseOnExceptionsAndMuteConsole,
+                             const bool* returnByValue,
+                             const bool* generatePreview,
+                             RefPtr<TypeBuilder::Runtime::RemoteObject>& result,
+                             TypeBuilder::OptOutput<bool>* wasThrown);
+    void compileScript(ErrorString*, const String& expression, const String& sourceURL, TypeBuilder::OptOutput<TypeBuilder::Debugger::ScriptId>*, TypeBuilder::OptOutput<String>* syntaxErrorMessage);
+    void runScript(ErrorString*, const TypeBuilder::Debugger::ScriptId&, const int* executionContextId, const String* objectGroup, const bool* doNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown);
+    virtual void setOverlayMessage(ErrorString*, const String*);
+    virtual void setVariableValue(ErrorString*, int in_scopeNumber, const String& in_variableName, const RefPtr<InspectorObject>& in_newValue, const String* in_callFrame, const String* in_functionObjectId);
+
+    void schedulePauseOnNextStatement(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<InspectorObject> data);
+    void cancelPauseOnNextStatement();
+    void breakProgram(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<InspectorObject> data);
+    virtual void scriptExecutionBlockedByCSP(const String& directiveText);
+
+    class Listener {
+    public:
+        virtual ~Listener() { }
+        virtual void debuggerWasEnabled() = 0;
+        virtual void debuggerWasDisabled() = 0;
+        virtual void stepInto() = 0;
+        virtual void didPause() = 0;
+    };
+    void setListener(Listener* listener) { m_listener = listener; }
+
+    virtual ScriptDebugServer& scriptDebugServer() = 0;
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
+protected:
+    InspectorDebuggerAgent(InstrumentingAgents*, InspectorCompositeState*, InjectedScriptManager*);
+
+    virtual void startListeningScriptDebugServer() = 0;
+    virtual void stopListeningScriptDebugServer() = 0;
+    virtual void muteConsole() = 0;
+    virtual void unmuteConsole() = 0;
+    InjectedScriptManager* injectedScriptManager() { return m_injectedScriptManager; }
+    virtual InjectedScript injectedScriptForEval(ErrorString*, const int* executionContextId) = 0;
+
+    virtual void enable();
+    virtual void disable();
+    virtual void didPause(ScriptState*, const ScriptValue& callFrames, const ScriptValue& exception);
+    virtual void didContinue();
+    void reset();
+
+private:
+    bool enabled();
+
+    PassRefPtr<TypeBuilder::Array<TypeBuilder::Debugger::CallFrame> > currentCallFrames();
+
+    virtual void didParseSource(const String& scriptId, const Script&);
+    virtual void failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage);
+
+    void setPauseOnExceptionsImpl(ErrorString*, int);
+
+    PassRefPtr<TypeBuilder::Debugger::Location> resolveBreakpoint(const String& breakpointId, const String& scriptId, const ScriptBreakpoint&);
+    void clear();
+    bool assertPaused(ErrorString*);
+    void clearBreakDetails();
+
+    String sourceMapURLForScript(const Script&);
+
+    typedef HashMap<String, Script> ScriptsMap;
+    typedef HashMap<String, Vector<String> > BreakpointIdToDebugServerBreakpointIdsMap;
+
+    InjectedScriptManager* m_injectedScriptManager;
+    InspectorFrontend::Debugger* m_frontend;
+    ScriptState* m_pausedScriptState;
+    ScriptValue m_currentCallStack;
+    ScriptsMap m_scripts;
+    BreakpointIdToDebugServerBreakpointIdsMap m_breakpointIdToDebugServerBreakpointIds;
+    String m_continueToLocationBreakpointId;
+    InspectorFrontend::Debugger::Reason::Enum m_breakReason;
+    RefPtr<InspectorObject> m_breakAuxData;
+    bool m_javaScriptPauseScheduled;
+    Listener* m_listener;
+};
+
+} // namespace WebCore
+
+
+#endif // !defined(InspectorDebuggerAgent_h)
diff --git a/Source/core/inspector/InspectorFileSystemAgent.cpp b/Source/core/inspector/InspectorFileSystemAgent.cpp
new file mode 100644
index 0000000..389d9c4
--- /dev/null
+++ b/Source/core/inspector/InspectorFileSystemAgent.cpp
@@ -0,0 +1,738 @@
+/*
+ * Copyright (C) 2011, 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.
+ */
+
+#include "config.h"
+
+#include "core/inspector/InspectorFileSystemAgent.h"
+
+#include "core/dom/DOMImplementation.h"
+#include "core/dom/Document.h"
+#include "core/dom/Event.h"
+#include "core/dom/ScriptExecutionContext.h"
+#include "core/fileapi/File.h"
+#include "core/fileapi/FileError.h"
+#include "core/fileapi/FileReader.h"
+#include "core/html/VoidCallback.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/loader/TextResourceDecoder.h"
+#include "core/page/Frame.h"
+#include "core/page/SecurityOrigin.h"
+#include "core/platform/KURL.h"
+#include "core/platform/MIMETypeRegistry.h"
+#include "core/platform/text/TextEncoding.h"
+#include "modules/filesystem/DOMFileSystem.h"
+#include "modules/filesystem/DirectoryEntry.h"
+#include "modules/filesystem/DirectoryReader.h"
+#include "modules/filesystem/EntriesCallback.h"
+#include "modules/filesystem/EntryArray.h"
+#include "modules/filesystem/EntryCallback.h"
+#include "modules/filesystem/ErrorCallback.h"
+#include "modules/filesystem/FileCallback.h"
+#include "modules/filesystem/FileEntry.h"
+#include "modules/filesystem/FileSystemCallback.h"
+#include "modules/filesystem/FileSystemCallbacks.h"
+#include "modules/filesystem/LocalFileSystem.h"
+#include "modules/filesystem/Metadata.h"
+#include "modules/filesystem/MetadataCallback.h"
+#include <wtf/text/Base64.h>
+
+using WebCore::TypeBuilder::Array;
+
+typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestFileSystemRootCallback RequestFileSystemRootCallback;
+typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestDirectoryContentCallback RequestDirectoryContentCallback;
+typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestMetadataCallback RequestMetadataCallback;
+typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestFileContentCallback RequestFileContentCallback;
+typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::DeleteEntryCallback DeleteEntryCallback;
+
+namespace WebCore {
+
+namespace FileSystemAgentState {
+static const char fileSystemAgentEnabled[] = "fileSystemAgentEnabled";
+}
+
+namespace {
+
+template<typename BaseCallback, typename Handler, typename Argument>
+class CallbackDispatcher : public BaseCallback {
+public:
+    typedef bool (Handler::*HandlingMethod)(Argument*);
+
+    static PassRefPtr<CallbackDispatcher> create(PassRefPtr<Handler> handler, HandlingMethod handlingMethod)
+    {
+        return adoptRef(new CallbackDispatcher(handler, handlingMethod));
+    }
+
+    virtual bool handleEvent(Argument* argument) OVERRIDE
+    {
+        return (m_handler.get()->*m_handlingMethod)(argument);
+    }
+
+private:
+    CallbackDispatcher(PassRefPtr<Handler> handler, HandlingMethod handlingMethod)
+        : m_handler(handler)
+        , m_handlingMethod(handlingMethod) { }
+
+    RefPtr<Handler> m_handler;
+    HandlingMethod m_handlingMethod;
+};
+
+template<typename BaseCallback>
+class CallbackDispatcherFactory {
+public:
+    template<typename Handler, typename Argument>
+    static PassRefPtr<CallbackDispatcher<BaseCallback, Handler, Argument> > create(Handler* handler, bool (Handler::*handlingMethod)(Argument*))
+    {
+        return CallbackDispatcher<BaseCallback, Handler, Argument>::create(PassRefPtr<Handler>(handler), handlingMethod);
+    }
+};
+
+class FileSystemRootRequest : public RefCounted<FileSystemRootRequest> {
+    WTF_MAKE_NONCOPYABLE(FileSystemRootRequest);
+public:
+    static PassRefPtr<FileSystemRootRequest> create(PassRefPtr<RequestFileSystemRootCallback> requestCallback, const String& type)
+    {
+        return adoptRef(new FileSystemRootRequest(requestCallback, type));
+    }
+
+    void start(ScriptExecutionContext*);
+
+private:
+    bool didHitError(FileError* error)
+    {
+        reportResult(error->code());
+        return true;
+    }
+
+    bool didGetEntry(Entry*);
+
+    void reportResult(FileError::ErrorCode errorCode, PassRefPtr<TypeBuilder::FileSystem::Entry> entry = 0)
+    {
+        m_requestCallback->sendSuccess(static_cast<int>(errorCode), entry);
+    }
+
+    FileSystemRootRequest(PassRefPtr<RequestFileSystemRootCallback> requestCallback, const String& type)
+        : m_requestCallback(requestCallback)
+        , m_type(type) { }
+
+    RefPtr<RequestFileSystemRootCallback> m_requestCallback;
+    String m_type;
+};
+
+void FileSystemRootRequest::start(ScriptExecutionContext* scriptExecutionContext)
+{
+    ASSERT(scriptExecutionContext);
+
+    RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileSystemRootRequest::didHitError);
+    FileSystemType type;
+    if (m_type == DOMFileSystemBase::persistentPathPrefix)
+        type = FileSystemTypePersistent;
+    else if (m_type == DOMFileSystemBase::temporaryPathPrefix)
+        type = FileSystemTypeTemporary;
+    else {
+        errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get());
+        return;
+    }
+
+    RefPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &FileSystemRootRequest::didGetEntry);
+    OwnPtr<ResolveURICallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, scriptExecutionContext, type, "/");
+
+    LocalFileSystem::localFileSystem().readFileSystem(scriptExecutionContext, type, fileSystemCallbacks.release());
+}
+
+bool FileSystemRootRequest::didGetEntry(Entry* entry)
+{
+    RefPtr<TypeBuilder::FileSystem::Entry> result = TypeBuilder::FileSystem::Entry::create()
+        .setUrl(entry->toURL())
+        .setName("/")
+        .setIsDirectory(true);
+    reportResult(static_cast<FileError::ErrorCode>(0), result);
+    return true;
+}
+
+class DirectoryContentRequest : public RefCounted<DirectoryContentRequest> {
+    WTF_MAKE_NONCOPYABLE(DirectoryContentRequest);
+public:
+    static PassRefPtr<DirectoryContentRequest> create(PassRefPtr<RequestDirectoryContentCallback> requestCallback, const String& url)
+    {
+        return adoptRef(new DirectoryContentRequest(requestCallback, url));
+    }
+
+    virtual ~DirectoryContentRequest()
+    {
+        reportResult(FileError::ABORT_ERR);
+    }
+
+    void start(ScriptExecutionContext*);
+
+private:
+    bool didHitError(FileError* error)
+    {
+        reportResult(error->code());
+        return true;
+    }
+
+    bool didGetEntry(Entry*);
+    bool didReadDirectoryEntries(EntryArray*);
+
+    void reportResult(FileError::ErrorCode errorCode, PassRefPtr<Array<TypeBuilder::FileSystem::Entry> > entries = 0)
+    {
+        m_requestCallback->sendSuccess(static_cast<int>(errorCode), entries);
+    }
+
+    DirectoryContentRequest(PassRefPtr<RequestDirectoryContentCallback> requestCallback, const String& url)
+        : m_requestCallback(requestCallback)
+        , m_url(ParsedURLString, url) { }
+
+    void readDirectoryEntries();
+
+    RefPtr<RequestDirectoryContentCallback> m_requestCallback;
+    KURL m_url;
+    RefPtr<Array<TypeBuilder::FileSystem::Entry> > m_entries;
+    RefPtr<DirectoryReader> m_directoryReader;
+};
+
+void DirectoryContentRequest::start(ScriptExecutionContext* scriptExecutionContext)
+{
+    ASSERT(scriptExecutionContext);
+
+    RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DirectoryContentRequest::didHitError);
+    FileSystemType type;
+    String path;
+    if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, path)) {
+        errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get());
+        return;
+    }
+
+    RefPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &DirectoryContentRequest::didGetEntry);
+    OwnPtr<ResolveURICallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, scriptExecutionContext, type, path);
+
+    LocalFileSystem::localFileSystem().readFileSystem(scriptExecutionContext, type, fileSystemCallbacks.release());
+}
+
+bool DirectoryContentRequest::didGetEntry(Entry* entry)
+{
+    if (!entry->isDirectory()) {
+        reportResult(FileError::TYPE_MISMATCH_ERR);
+        return true;
+    }
+
+    m_directoryReader = static_cast<DirectoryEntry*>(entry)->createReader();
+    m_entries = Array<TypeBuilder::FileSystem::Entry>::create();
+    readDirectoryEntries();
+    return true;
+}
+
+void DirectoryContentRequest::readDirectoryEntries()
+{
+    if (!m_directoryReader->filesystem()->scriptExecutionContext()) {
+        reportResult(FileError::ABORT_ERR);
+        return;
+    }
+
+    RefPtr<EntriesCallback> successCallback = CallbackDispatcherFactory<EntriesCallback>::create(this, &DirectoryContentRequest::didReadDirectoryEntries);
+    RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DirectoryContentRequest::didHitError);
+    m_directoryReader->readEntries(successCallback, errorCallback);
+}
+
+bool DirectoryContentRequest::didReadDirectoryEntries(EntryArray* entries)
+{
+    if (!entries->length()) {
+        reportResult(static_cast<FileError::ErrorCode>(0), m_entries);
+        return true;
+    }
+
+    for (unsigned i = 0; i < entries->length(); ++i) {
+        Entry* entry = entries->item(i);
+        RefPtr<TypeBuilder::FileSystem::Entry> entryForFrontend = TypeBuilder::FileSystem::Entry::create()
+            .setUrl(entry->toURL())
+            .setName(entry->name())
+            .setIsDirectory(entry->isDirectory());
+
+        using TypeBuilder::Page::ResourceType;
+        if (!entry->isDirectory()) {
+            String mimeType = MIMETypeRegistry::getMIMETypeForPath(entry->name());
+            ResourceType::Enum resourceType;
+            if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType)) {
+                resourceType = ResourceType::Image;
+                entryForFrontend->setIsTextFile(false);
+            } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType)) {
+                resourceType = ResourceType::Script;
+                entryForFrontend->setIsTextFile(true);
+            } else if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType)) {
+                resourceType = ResourceType::Document;
+                entryForFrontend->setIsTextFile(true);
+            } else {
+                resourceType = ResourceType::Other;
+                entryForFrontend->setIsTextFile(DOMImplementation::isXMLMIMEType(mimeType) || DOMImplementation::isTextMIMEType(mimeType));
+            }
+
+            entryForFrontend->setMimeType(mimeType);
+            entryForFrontend->setResourceType(resourceType);
+        }
+
+        m_entries->addItem(entryForFrontend);
+    }
+    readDirectoryEntries();
+    return true;
+}
+
+class MetadataRequest : public RefCounted<MetadataRequest> {
+    WTF_MAKE_NONCOPYABLE(MetadataRequest);
+public:
+    static PassRefPtr<MetadataRequest> create(PassRefPtr<RequestMetadataCallback> requestCallback, const String& url)
+    {
+        return adoptRef(new MetadataRequest(requestCallback, url));
+    }
+
+    virtual ~MetadataRequest()
+    {
+        reportResult(FileError::ABORT_ERR);
+    }
+
+    void start(ScriptExecutionContext*);
+
+private:
+    bool didHitError(FileError* error)
+    {
+        reportResult(error->code());
+        return true;
+    }
+
+    bool didGetEntry(Entry*);
+    bool didGetMetadata(Metadata*);
+
+    void reportResult(FileError::ErrorCode errorCode, PassRefPtr<TypeBuilder::FileSystem::Metadata> metadata = 0)
+    {
+        m_requestCallback->sendSuccess(static_cast<int>(errorCode), metadata);
+    }
+
+    MetadataRequest(PassRefPtr<RequestMetadataCallback> requestCallback, const String& url)
+        : m_requestCallback(requestCallback)
+        , m_url(ParsedURLString, url) { }
+
+    RefPtr<RequestMetadataCallback> m_requestCallback;
+    KURL m_url;
+    String m_path;
+    bool m_isDirectory;
+};
+
+void MetadataRequest::start(ScriptExecutionContext* scriptExecutionContext)
+{
+    ASSERT(scriptExecutionContext);
+
+    RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &MetadataRequest::didHitError);
+
+    FileSystemType type;
+    if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, m_path)) {
+        errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get());
+        return;
+    }
+
+    RefPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &MetadataRequest::didGetEntry);
+    OwnPtr<ResolveURICallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, scriptExecutionContext, type, m_path);
+    LocalFileSystem::localFileSystem().readFileSystem(scriptExecutionContext, type, fileSystemCallbacks.release());
+}
+
+bool MetadataRequest::didGetEntry(Entry* entry)
+{
+    if (!entry->filesystem()->scriptExecutionContext()) {
+        reportResult(FileError::ABORT_ERR);
+        return true;
+    }
+
+    RefPtr<MetadataCallback> successCallback = CallbackDispatcherFactory<MetadataCallback>::create(this, &MetadataRequest::didGetMetadata);
+    RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &MetadataRequest::didHitError);
+    entry->getMetadata(successCallback, errorCallback);
+    m_isDirectory = entry->isDirectory();
+    return true;
+}
+
+bool MetadataRequest::didGetMetadata(Metadata* metadata)
+{
+    using TypeBuilder::FileSystem::Metadata;
+    RefPtr<Metadata> result = Metadata::create()
+        .setModificationTime(metadata->modificationTime())
+        .setSize(metadata->size());
+    reportResult(static_cast<FileError::ErrorCode>(0), result);
+    return true;
+}
+
+class FileContentRequest : public EventListener {
+    WTF_MAKE_NONCOPYABLE(FileContentRequest);
+public:
+    static PassRefPtr<FileContentRequest> create(PassRefPtr<RequestFileContentCallback> requestCallback, const String& url, bool readAsText, long long start, long long end, const String& charset)
+    {
+        return adoptRef(new FileContentRequest(requestCallback, url, readAsText, start, end, charset));
+    }
+
+    virtual ~FileContentRequest()
+    {
+        reportResult(FileError::ABORT_ERR);
+    }
+
+    void start(ScriptExecutionContext*);
+
+    virtual bool operator==(const EventListener& other) OVERRIDE
+    {
+        return this == &other;
+    }
+
+    virtual void handleEvent(ScriptExecutionContext*, Event* event) OVERRIDE
+    {
+        if (event->type() == eventNames().loadEvent)
+            didRead();
+        else if (event->type() == eventNames().errorEvent)
+            didHitError(m_reader->error().get());
+    }
+
+private:
+    bool didHitError(FileError* error)
+    {
+        reportResult(error->code());
+        return true;
+    }
+
+    bool didGetEntry(Entry*);
+    bool didGetFile(File*);
+    void didRead();
+
+    void reportResult(FileError::ErrorCode errorCode, const String* result = 0, const String* charset = 0)
+    {
+        m_requestCallback->sendSuccess(static_cast<int>(errorCode), result, charset);
+    }
+
+    FileContentRequest(PassRefPtr<RequestFileContentCallback> requestCallback, const String& url, bool readAsText, long long start, long long end, const String& charset)
+        : EventListener(EventListener::CPPEventListenerType)
+        , m_requestCallback(requestCallback)
+        , m_url(ParsedURLString, url)
+        , m_readAsText(readAsText)
+        , m_start(start)
+        , m_end(end)
+        , m_charset(charset) { }
+
+    RefPtr<RequestFileContentCallback> m_requestCallback;
+    KURL m_url;
+    bool m_readAsText;
+    int m_start;
+    long long m_end;
+    String m_mimeType;
+    String m_charset;
+
+    RefPtr<FileReader> m_reader;
+};
+
+void FileContentRequest::start(ScriptExecutionContext* scriptExecutionContext)
+{
+    ASSERT(scriptExecutionContext);
+
+    RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileContentRequest::didHitError);
+
+    FileSystemType type;
+    String path;
+    if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, path)) {
+        errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get());
+        return;
+    }
+
+    RefPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &FileContentRequest::didGetEntry);
+    OwnPtr<ResolveURICallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, scriptExecutionContext, type, path);
+
+    LocalFileSystem::localFileSystem().readFileSystem(scriptExecutionContext, type, fileSystemCallbacks.release());
+}
+
+bool FileContentRequest::didGetEntry(Entry* entry)
+{
+    if (entry->isDirectory()) {
+        reportResult(FileError::TYPE_MISMATCH_ERR);
+        return true;
+    }
+
+    if (!entry->filesystem()->scriptExecutionContext()) {
+        reportResult(FileError::ABORT_ERR);
+        return true;
+    }
+
+    RefPtr<FileCallback> successCallback = CallbackDispatcherFactory<FileCallback>::create(this, &FileContentRequest::didGetFile);
+    RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &FileContentRequest::didHitError);
+    static_cast<FileEntry*>(entry)->file(successCallback, errorCallback);
+
+    m_reader = FileReader::create(entry->filesystem()->scriptExecutionContext());
+    m_mimeType = MIMETypeRegistry::getMIMETypeForPath(entry->name());
+
+    return true;
+}
+
+bool FileContentRequest::didGetFile(File* file)
+{
+    RefPtr<Blob> blob = file->slice(m_start, m_end);
+    m_reader->setOnload(this);
+    m_reader->setOnerror(this);
+
+    m_reader->readAsArrayBuffer(blob.get(), IGNORE_EXCEPTION);
+    return true;
+}
+
+void FileContentRequest::didRead()
+{
+    RefPtr<ArrayBuffer> buffer = m_reader->arrayBufferResult();
+
+    if (!m_readAsText) {
+        String result = base64Encode(static_cast<char*>(buffer->data()), buffer->byteLength());
+        reportResult(static_cast<FileError::ErrorCode>(0), &result, 0);
+        return;
+    }
+
+    RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create(m_mimeType, m_charset, true);
+    String result = decoder->decode(static_cast<char*>(buffer->data()), buffer->byteLength());
+    result.append(decoder->flush());
+    m_charset = decoder->encoding().domName();
+    reportResult(static_cast<FileError::ErrorCode>(0), &result, &m_charset);
+}
+
+class DeleteEntryRequest : public VoidCallback {
+public:
+    static PassRefPtr<DeleteEntryRequest> create(PassRefPtr<DeleteEntryCallback> requestCallback, const KURL& url)
+    {
+        return adoptRef(new DeleteEntryRequest(requestCallback, url));
+    }
+
+    virtual ~DeleteEntryRequest()
+    {
+        reportResult(FileError::ABORT_ERR);
+    }
+
+    virtual bool handleEvent() OVERRIDE
+    {
+        return didDeleteEntry();
+    }
+
+    void start(ScriptExecutionContext*);
+
+private:
+    bool didHitError(FileError* error)
+    {
+        reportResult(error->code());
+        return true;
+    }
+
+    bool didGetEntry(Entry*);
+    bool didDeleteEntry();
+
+    void reportResult(FileError::ErrorCode errorCode)
+    {
+        m_requestCallback->sendSuccess(static_cast<int>(errorCode));
+    }
+
+    DeleteEntryRequest(PassRefPtr<DeleteEntryCallback> requestCallback, const KURL& url)
+        : m_requestCallback(requestCallback)
+        , m_url(url) { }
+
+    RefPtr<DeleteEntryCallback> m_requestCallback;
+    KURL m_url;
+};
+
+void DeleteEntryRequest::start(ScriptExecutionContext* scriptExecutionContext)
+{
+    ASSERT(scriptExecutionContext);
+
+    RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DeleteEntryRequest::didHitError);
+
+    FileSystemType type;
+    String path;
+    if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, path)) {
+        errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get());
+        return;
+    }
+
+    if (path == "/") {
+        OwnPtr<AsyncFileSystemCallbacks> fileSystemCallbacks = VoidCallbacks::create(this, errorCallback);
+        LocalFileSystem::localFileSystem().deleteFileSystem(scriptExecutionContext, type, fileSystemCallbacks.release());
+    } else {
+        RefPtr<EntryCallback> successCallback = CallbackDispatcherFactory<EntryCallback>::create(this, &DeleteEntryRequest::didGetEntry);
+        OwnPtr<ResolveURICallbacks> fileSystemCallbacks = ResolveURICallbacks::create(successCallback, errorCallback, scriptExecutionContext, type, path);
+        LocalFileSystem::localFileSystem().readFileSystem(scriptExecutionContext, type, fileSystemCallbacks.release());
+    }
+}
+
+bool DeleteEntryRequest::didGetEntry(Entry* entry)
+{
+    RefPtr<ErrorCallback> errorCallback = CallbackDispatcherFactory<ErrorCallback>::create(this, &DeleteEntryRequest::didHitError);
+    if (entry->isDirectory()) {
+        DirectoryEntry* directoryEntry = static_cast<DirectoryEntry*>(entry);
+        directoryEntry->removeRecursively(this, errorCallback);
+    } else
+        entry->remove(this, errorCallback);
+    return true;
+}
+
+bool DeleteEntryRequest::didDeleteEntry()
+{
+    reportResult(static_cast<FileError::ErrorCode>(0));
+    return true;
+}
+
+} // anonymous namespace
+
+// static
+PassOwnPtr<InspectorFileSystemAgent> InspectorFileSystemAgent::create(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorCompositeState* state)
+{
+    return adoptPtr(new InspectorFileSystemAgent(instrumentingAgents, pageAgent, state));
+}
+
+InspectorFileSystemAgent::~InspectorFileSystemAgent()
+{
+    m_instrumentingAgents->setInspectorFileSystemAgent(0);
+}
+
+void InspectorFileSystemAgent::enable(ErrorString*)
+{
+    if (m_enabled)
+        return;
+    m_enabled = true;
+    m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled);
+}
+
+void InspectorFileSystemAgent::disable(ErrorString*)
+{
+    if (!m_enabled)
+        return;
+    m_enabled = false;
+    m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled);
+}
+
+void InspectorFileSystemAgent::requestFileSystemRoot(ErrorString* error, const String& origin, const String& type, PassRefPtr<RequestFileSystemRootCallback> requestCallback)
+{
+    if (!assertEnabled(error))
+        return;
+
+    ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::createFromString(origin).get());
+    if (!scriptExecutionContext)
+        return;
+
+    FileSystemRootRequest::create(requestCallback, type)->start(scriptExecutionContext);
+}
+
+void InspectorFileSystemAgent::requestDirectoryContent(ErrorString* error, const String& url, PassRefPtr<RequestDirectoryContentCallback> requestCallback)
+{
+    if (!assertEnabled(error))
+        return;
+
+    ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get());
+    if (!scriptExecutionContext)
+        return;
+
+    DirectoryContentRequest::create(requestCallback, url)->start(scriptExecutionContext);
+}
+
+void InspectorFileSystemAgent::requestMetadata(ErrorString* error, const String& url, PassRefPtr<RequestMetadataCallback> requestCallback)
+{
+    if (!assertEnabled(error))
+        return;
+
+    ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get());
+    if (!scriptExecutionContext)
+        return;
+
+    MetadataRequest::create(requestCallback, url)->start(scriptExecutionContext);
+}
+
+void InspectorFileSystemAgent::requestFileContent(ErrorString* error, const String& url, bool readAsText, const int* start, const int* end, const String* charset, PassRefPtr<RequestFileContentCallback> requestCallback)
+{
+    if (!assertEnabled(error))
+        return;
+
+    ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get());
+    if (!scriptExecutionContext)
+        return;
+
+    long long startPosition = start ? *start : 0;
+    long long endPosition = end ? *end : std::numeric_limits<long long>::max();
+    FileContentRequest::create(requestCallback, url, readAsText, startPosition, endPosition, charset ? *charset : "")->start(scriptExecutionContext);
+}
+
+void InspectorFileSystemAgent::deleteEntry(ErrorString* error, const String& urlString, PassRefPtr<DeleteEntryCallback> requestCallback)
+{
+    if (!assertEnabled(error))
+        return;
+
+    KURL url(ParsedURLString, urlString);
+
+    ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::create(url).get());
+    if (!scriptExecutionContext)
+        return;
+
+    DeleteEntryRequest::create(requestCallback, url)->start(scriptExecutionContext);
+}
+
+void InspectorFileSystemAgent::clearFrontend()
+{
+    m_enabled = false;
+    m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled);
+}
+
+void InspectorFileSystemAgent::restore()
+{
+    m_enabled = m_state->getBoolean(FileSystemAgentState::fileSystemAgentEnabled);
+}
+
+InspectorFileSystemAgent::InspectorFileSystemAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorCompositeState* state)
+    : InspectorBaseAgent<InspectorFileSystemAgent>("FileSystem", instrumentingAgents, state)
+    , m_pageAgent(pageAgent)
+    , m_enabled(false)
+{
+    ASSERT(instrumentingAgents);
+    ASSERT(state);
+    ASSERT(m_pageAgent);
+    m_instrumentingAgents->setInspectorFileSystemAgent(this);
+}
+
+bool InspectorFileSystemAgent::assertEnabled(ErrorString* error)
+{
+    if (!m_enabled) {
+        *error = "FileSystem agent is not enabled.";
+        return false;
+    }
+    return true;
+}
+
+ScriptExecutionContext* InspectorFileSystemAgent::assertScriptExecutionContextForOrigin(ErrorString* error, SecurityOrigin* origin)
+{
+    for (Frame* frame = m_pageAgent->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
+        if (frame->document() && frame->document()->securityOrigin()->isSameSchemeHostPort(origin))
+            return frame->document();
+    }
+
+    *error = "No frame is available for the request";
+    return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/InspectorFileSystemAgent.h b/Source/core/inspector/InspectorFileSystemAgent.h
new file mode 100644
index 0000000..4b38b8c
--- /dev/null
+++ b/Source/core/inspector/InspectorFileSystemAgent.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011, 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.
+ */
+
+#ifndef InspectorFileSystemAgent_h
+#define InspectorFileSystemAgent_h
+
+#include "core/inspector/InspectorBaseAgent.h"
+
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class InspectorFrontend;
+class InspectorPageAgent;
+class ScriptExecutionContext;
+class SecurityOrigin;
+
+class InspectorFileSystemAgent : public InspectorBaseAgent<InspectorFileSystemAgent>, public InspectorBackendDispatcher::FileSystemCommandHandler {
+public:
+    static PassOwnPtr<InspectorFileSystemAgent> create(InstrumentingAgents*, InspectorPageAgent*, InspectorCompositeState*);
+    virtual ~InspectorFileSystemAgent();
+
+    virtual void enable(ErrorString*) OVERRIDE;
+    virtual void disable(ErrorString*) OVERRIDE;
+
+    virtual void requestFileSystemRoot(ErrorString*, const String& origin, const String& typeString, PassRefPtr<RequestFileSystemRootCallback>) OVERRIDE;
+    virtual void requestDirectoryContent(ErrorString*, const String& url, PassRefPtr<RequestDirectoryContentCallback>) OVERRIDE;
+    virtual void requestMetadata(ErrorString*, const String& url, PassRefPtr<RequestMetadataCallback>) OVERRIDE;
+    virtual void requestFileContent(ErrorString*, const String& url, bool readAsText, const int* start, const int* end, const String* charset, PassRefPtr<RequestFileContentCallback>) OVERRIDE;
+    virtual void deleteEntry(ErrorString*, const String& url, PassRefPtr<DeleteEntryCallback>) OVERRIDE;
+
+    virtual void clearFrontend() OVERRIDE;
+    virtual void restore() OVERRIDE;
+
+private:
+    InspectorFileSystemAgent(InstrumentingAgents*, InspectorPageAgent*, InspectorCompositeState*);
+    bool assertEnabled(ErrorString*);
+    ScriptExecutionContext* assertScriptExecutionContextForOrigin(ErrorString*, SecurityOrigin*);
+
+    InspectorPageAgent* m_pageAgent;
+    bool m_enabled;
+};
+
+} // namespace WebCore
+
+#endif // InspectorFileSystemAgent_h
diff --git a/Source/core/inspector/InspectorFrontendChannel.h b/Source/core/inspector/InspectorFrontendChannel.h
new file mode 100644
index 0000000..b3214ef
--- /dev/null
+++ b/Source/core/inspector/InspectorFrontendChannel.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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. 
+ */
+
+#ifndef InspectorFrontendChannel_h
+#define InspectorFrontendChannel_h
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class InspectorFrontendChannel {
+public:
+    virtual ~InspectorFrontendChannel() { }
+    virtual bool sendMessageToFrontend(const String& message) = 0;
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorFrontendChannel_h)
diff --git a/Source/core/inspector/InspectorFrontendClient.h b/Source/core/inspector/InspectorFrontendClient.h
new file mode 100644
index 0000000..ef6a23c
--- /dev/null
+++ b/Source/core/inspector/InspectorFrontendClient.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef InspectorFrontendClient_h
+#define InspectorFrontendClient_h
+
+#include <wtf/Forward.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class ContextMenuItem;
+class Event;
+
+class InspectorFrontendClient {
+public:
+    enum DockSide {
+        UNDOCKED = 0,
+        DOCKED_TO_RIGHT,
+        DOCKED_TO_BOTTOM
+    };
+
+    virtual ~InspectorFrontendClient() { }
+
+    virtual void windowObjectCleared() = 0;
+    virtual void moveWindowBy(float x, float y) = 0;
+
+    virtual void bringToFront() = 0;
+    virtual void closeWindow() = 0;
+
+    virtual void requestSetDockSide(DockSide) = 0;
+    virtual void changeAttachedWindowHeight(unsigned) = 0;
+
+    virtual void openInNewTab(const String& url) = 0;
+
+    virtual void save(const WTF::String& url, const WTF::String& content, bool forceSaveAs) = 0;
+    virtual void append(const WTF::String& url, const WTF::String& content) = 0;
+
+    virtual void inspectedURLChanged(const String&) = 0;
+
+    virtual void sendMessageToBackend(const String&) = 0;
+
+    virtual void requestFileSystems() = 0;
+    virtual void addFileSystem() = 0;
+    virtual void removeFileSystem(const String& fileSystemPath) = 0;
+
+    virtual bool isUnderTest() = 0;
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/core/inspector/InspectorFrontendHost.cpp b/Source/core/inspector/InspectorFrontendHost.cpp
new file mode 100644
index 0000000..9881f83
--- /dev/null
+++ b/Source/core/inspector/InspectorFrontendHost.cpp
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorFrontendHost.h"
+
+#include "bindings/v8/DOMWrapperWorld.h"
+#include "bindings/v8/ScriptFunctionCall.h"
+#include "core/dom/Element.h"
+#include "core/dom/UserGestureIndicator.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/inspector/InspectorAgent.h"
+#include "core/inspector/InspectorController.h"
+#include "core/inspector/InspectorFrontendClient.h"
+#include "core/loader/FrameLoader.h"
+#include "core/page/ContextMenuController.h"
+#include "core/page/ContextMenuProvider.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/ContextMenu.h"
+#include "core/platform/ContextMenuItem.h"
+#include "core/platform/Pasteboard.h"
+#include "core/platform/network/ResourceError.h"
+#include "core/platform/network/ResourceRequest.h"
+#include "core/platform/network/ResourceResponse.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderTheme.h"
+#include "modules/filesystem/DOMFileSystem.h"
+#include <wtf/StdLibExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+class FrontendMenuProvider : public ContextMenuProvider {
+public:
+    static PassRefPtr<FrontendMenuProvider> create(InspectorFrontendHost* frontendHost, ScriptObject frontendApiObject, const Vector<ContextMenuItem>& items)
+    {
+        return adoptRef(new FrontendMenuProvider(frontendHost, frontendApiObject, items));
+    }
+
+    void disconnect()
+    {
+        m_frontendApiObject = ScriptObject();
+        m_frontendHost = 0;
+    }
+
+private:
+    FrontendMenuProvider(InspectorFrontendHost* frontendHost, ScriptObject frontendApiObject, const Vector<ContextMenuItem>& items)
+        : m_frontendHost(frontendHost)
+        , m_frontendApiObject(frontendApiObject)
+        , m_items(items)
+    {
+    }
+
+    virtual ~FrontendMenuProvider()
+    {
+        contextMenuCleared();
+    }
+
+    virtual void populateContextMenu(ContextMenu* menu)
+    {
+        for (size_t i = 0; i < m_items.size(); ++i)
+            menu->appendItem(m_items[i]);
+    }
+
+    virtual void contextMenuItemSelected(const ContextMenuItem* item)
+    {
+        if (m_frontendHost) {
+            UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
+            int itemNumber = item->action() - ContextMenuItemBaseCustomTag;
+
+            ScriptFunctionCall function(m_frontendApiObject, "contextMenuItemSelected");
+            function.appendArgument(itemNumber);
+            function.call();
+        }
+    }
+
+    virtual void contextMenuCleared()
+    {
+        if (m_frontendHost) {
+            ScriptFunctionCall function(m_frontendApiObject, "contextMenuCleared");
+            function.call();
+
+            m_frontendHost->m_menuProvider = 0;
+        }
+        m_items.clear();
+    }
+
+    InspectorFrontendHost* m_frontendHost;
+    ScriptObject m_frontendApiObject;
+    Vector<ContextMenuItem> m_items;
+};
+
+InspectorFrontendHost::InspectorFrontendHost(InspectorFrontendClient* client, Page* frontendPage)
+    : m_client(client)
+    , m_frontendPage(frontendPage)
+    , m_menuProvider(0)
+{
+}
+
+InspectorFrontendHost::~InspectorFrontendHost()
+{
+    ASSERT(!m_client);
+}
+
+void InspectorFrontendHost::disconnectClient()
+{
+    m_client = 0;
+    if (m_menuProvider)
+        m_menuProvider->disconnect();
+    m_frontendPage = 0;
+}
+
+void InspectorFrontendHost::loaded()
+{
+}
+
+void InspectorFrontendHost::requestSetDockSide(const String& side)
+{
+    if (!m_client)
+        return;
+    if (side == "undocked")
+        m_client->requestSetDockSide(InspectorFrontendClient::UNDOCKED);
+    else if (side == "right")
+        m_client->requestSetDockSide(InspectorFrontendClient::DOCKED_TO_RIGHT);
+    else if (side == "bottom")
+        m_client->requestSetDockSide(InspectorFrontendClient::DOCKED_TO_BOTTOM);
+}
+
+void InspectorFrontendHost::closeWindow()
+{
+    if (m_client) {
+        m_client->closeWindow();
+        disconnectClient(); // Disconnect from client.
+    }
+}
+
+void InspectorFrontendHost::bringToFront()
+{
+    if (m_client)
+        m_client->bringToFront();
+}
+
+void InspectorFrontendHost::setZoomFactor(float zoom)
+{
+    m_frontendPage->mainFrame()->setPageAndTextZoomFactors(zoom, 1);
+}
+
+void InspectorFrontendHost::inspectedURLChanged(const String& newURL)
+{
+    if (m_client)
+        m_client->inspectedURLChanged(newURL);
+}
+
+void InspectorFrontendHost::setAttachedWindowHeight(unsigned height)
+{
+    if (m_client)
+        m_client->changeAttachedWindowHeight(height);
+}
+
+void InspectorFrontendHost::moveWindowBy(float x, float y) const
+{
+    if (m_client)
+        m_client->moveWindowBy(x, y);
+}
+
+void InspectorFrontendHost::setInjectedScriptForOrigin(const String& origin, const String& script)
+{
+    ASSERT(m_frontendPage->inspectorController());
+    m_frontendPage->inspectorController()->setInjectedScriptForOrigin(origin, script);
+}
+
+String InspectorFrontendHost::localizedStringsURL()
+{
+    return "";
+}
+
+void InspectorFrontendHost::copyText(const String& text)
+{
+    Pasteboard::generalPasteboard()->writePlainText(text, Pasteboard::CannotSmartReplace);
+}
+
+void InspectorFrontendHost::openInNewTab(const String& url)
+{
+    if (m_client)
+        m_client->openInNewTab(url);
+}
+
+bool InspectorFrontendHost::canSave()
+{
+    return true;
+}
+
+void InspectorFrontendHost::save(const String& url, const String& content, bool forceSaveAs)
+{
+    if (m_client)
+        m_client->save(url, content, forceSaveAs);
+}
+
+void InspectorFrontendHost::append(const String& url, const String& content)
+{
+    if (m_client)
+        m_client->append(url, content);
+}
+
+void InspectorFrontendHost::close(const String&)
+{
+}
+
+void InspectorFrontendHost::sendMessageToBackend(const String& message)
+{
+    if (m_client)
+        m_client->sendMessageToBackend(message);
+}
+
+void InspectorFrontendHost::showContextMenu(Event* event, const Vector<ContextMenuItem>& items)
+{
+    if (!event)
+        return;
+
+    ASSERT(m_frontendPage);
+    ScriptState* frontendScriptState = scriptStateFromPage(debuggerWorld(), m_frontendPage);
+    ScriptObject frontendApiObject;
+    if (!ScriptGlobalObject::get(frontendScriptState, "InspectorFrontendAPI", frontendApiObject)) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+    RefPtr<FrontendMenuProvider> menuProvider = FrontendMenuProvider::create(this, frontendApiObject, items);
+    ContextMenuController* menuController = m_frontendPage->contextMenuController();
+    menuController->showContextMenu(event, menuProvider);
+    m_menuProvider = menuProvider.get();
+}
+
+String InspectorFrontendHost::loadResourceSynchronously(const String& url)
+{
+    ResourceRequest request(url);
+    request.setHTTPMethod("GET");
+
+    Vector<char> data;
+    ResourceError error;
+    ResourceResponse response;
+    m_frontendPage->mainFrame()->loader()->loadResourceSynchronously(request, DoNotAllowStoredCredentials, error, response, data);
+    return String(data.data(), data.size());
+}
+
+String InspectorFrontendHost::getSelectionBackgroundColor()
+{
+    Color color = m_frontendPage->theme()->activeSelectionBackgroundColor();
+    return color.isValid() ? color.serialized() : "";
+}
+
+String InspectorFrontendHost::getSelectionForegroundColor()
+{
+    Color color = m_frontendPage->theme()->activeSelectionForegroundColor();
+    return color.isValid() ? color.serialized() : "";
+}
+
+bool InspectorFrontendHost::supportsFileSystems()
+{
+    return true;
+}
+
+void InspectorFrontendHost::requestFileSystems()
+{
+    if (m_client)
+        m_client->requestFileSystems();
+}
+
+void InspectorFrontendHost::addFileSystem()
+{
+    if (m_client)
+        m_client->addFileSystem();
+}
+
+void InspectorFrontendHost::removeFileSystem(const String& fileSystemPath)
+{
+    if (m_client)
+        m_client->removeFileSystem(fileSystemPath);
+}
+
+PassRefPtr<DOMFileSystem> InspectorFrontendHost::isolatedFileSystem(const String& fileSystemName, const String& rootURL)
+{
+    ScriptExecutionContext* context = m_frontendPage->mainFrame()->document();
+    return DOMFileSystem::create(context, fileSystemName, FileSystemTypeIsolated, KURL(ParsedURLString, rootURL), AsyncFileSystem::create());
+}
+
+bool InspectorFrontendHost::isUnderTest()
+{
+    return m_client && m_client->isUnderTest();
+}
+
+bool InspectorFrontendHost::canSaveAs()
+{
+    return false;
+}
+
+bool InspectorFrontendHost::canInspectWorkers()
+{
+    return false;
+}
+
+String InspectorFrontendHost::hiddenPanels()
+{
+    return "";
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/InspectorFrontendHost.h b/Source/core/inspector/InspectorFrontendHost.h
new file mode 100644
index 0000000..f7682e8
--- /dev/null
+++ b/Source/core/inspector/InspectorFrontendHost.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2007 Apple 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  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. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef InspectorFrontendHost_h
+#define InspectorFrontendHost_h
+
+#include "core/page/ConsoleTypes.h"
+#include "core/page/ContextMenuProvider.h"
+#include "core/platform/ContextMenu.h"
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class ContextMenuItem;
+class DOMFileSystem;
+class Event;
+class FrontendMenuProvider;
+class InspectorClient;
+class InspectorFrontendClient;
+class Node;
+class Page;
+
+class InspectorFrontendHost : public RefCounted<InspectorFrontendHost> {
+public:
+    static PassRefPtr<InspectorFrontendHost> create(InspectorFrontendClient* client, Page* frontendPage)
+    {
+        return adoptRef(new InspectorFrontendHost(client, frontendPage));
+    }
+
+    ~InspectorFrontendHost();
+    void disconnectClient();
+
+    void requestSetDockSide(const String&);
+    void closeWindow();
+    void bringToFront();
+    void setZoomFactor(float);
+    void inspectedURLChanged(const String&);
+
+    void setAttachedWindowHeight(unsigned);
+    void moveWindowBy(float x, float y) const;
+    void setInjectedScriptForOrigin(const String& origin, const String& script);
+
+    void copyText(const String& text);
+    void openInNewTab(const String& url);
+    void save(const String& url, const String& content, bool forceSaveAs);
+    void append(const String& url, const String& content);
+    void close(const String& url);
+
+    // Called from [Custom] implementations.
+    void showContextMenu(Event*, const Vector<ContextMenuItem>& items);
+    void sendMessageToBackend(const String& message);
+
+    String loadResourceSynchronously(const String& url);
+    String getSelectionBackgroundColor();
+    String getSelectionForegroundColor();
+
+    void requestFileSystems();
+    void addFileSystem();
+    void removeFileSystem(const String& fileSystemPath);
+    PassRefPtr<DOMFileSystem> isolatedFileSystem(const String& fileSystemName, const String& rootURL);
+
+    bool isUnderTest();
+
+    // Deprecated but should stay around for a while as old front-ends may use them.
+    bool canInspectWorkers();
+    bool canSaveAs();
+    bool canSave();
+    bool supportsFileSystems();
+    void loaded();
+    String hiddenPanels();
+    String localizedStringsURL();
+
+private:
+    friend class FrontendMenuProvider;
+    InspectorFrontendHost(InspectorFrontendClient* client, Page* frontendPage);
+
+    InspectorFrontendClient* m_client;
+    Page* m_frontendPage;
+    FrontendMenuProvider* m_menuProvider;
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorFrontendHost_h)
diff --git a/Source/core/inspector/InspectorFrontendHost.idl b/Source/core/inspector/InspectorFrontendHost.idl
new file mode 100644
index 0000000..2ebcf0a
--- /dev/null
+++ b/Source/core/inspector/InspectorFrontendHost.idl
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2009 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.
+ */
+
+[
+    ImplementationLacksVTable
+] interface InspectorFrontendHost {
+    void closeWindow();
+    void bringToFront();
+    void setZoomFactor(float zoom);
+    void inspectedURLChanged(DOMString newURL);
+
+    void requestSetDockSide(DOMString side);
+    void setAttachedWindowHeight(unsigned long height);
+    void moveWindowBy(float x, float y);
+    void setInjectedScriptForOrigin(DOMString origin, DOMString script);
+
+    void copyText(DOMString text);
+    void openInNewTab(DOMString url);
+    void save(DOMString url, DOMString content, boolean forceSaveAs);
+    void append(DOMString url, DOMString content);
+    void close(DOMString url);
+
+    [Custom] DOMString platform();
+    [Custom] DOMString port();
+    [Custom] void showContextMenu(MouseEvent event, any items);
+    void sendMessageToBackend(DOMString message);
+
+    [Custom] void recordActionTaken(unsigned long actionCode);
+    [Custom] void recordPanelShown(unsigned long panelCode);
+    [Custom] void recordSettingChanged(unsigned long settingChanged);
+
+    DOMString loadResourceSynchronously(DOMString url);
+    DOMString getSelectionBackgroundColor();
+    DOMString getSelectionForegroundColor();
+
+    void requestFileSystems();
+    void addFileSystem();
+    void removeFileSystem(DOMString fileSystemPath);
+    DOMFileSystem isolatedFileSystem(DOMString fileSystemId, DOMString registeredName);
+
+    boolean isUnderTest();
+
+    // Deprecated
+    boolean canInspectWorkers();
+    boolean canSaveAs();
+    boolean canSave();
+    boolean supportsFileSystems();
+    void loaded();
+    DOMString hiddenPanels();
+    DOMString localizedStringsURL();
+};
diff --git a/Source/core/inspector/InspectorHeapProfilerAgent.cpp b/Source/core/inspector/InspectorHeapProfilerAgent.cpp
new file mode 100644
index 0000000..0653db9
--- /dev/null
+++ b/Source/core/inspector/InspectorHeapProfilerAgent.cpp
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorHeapProfilerAgent.h"
+
+#include "bindings/v8/ScriptProfiler.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InjectedScriptHost.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/platform/Timer.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/MemoryInstrumentationHashMap.h>
+
+namespace WebCore {
+
+namespace HeapProfilerAgentState {
+static const char profileHeadersRequested[] = "profileHeadersRequested";
+}
+
+static const char* const UserInitiatedProfileNameHeap = "org.webkit.profiles.user-initiated";
+
+class InspectorHeapProfilerAgent::HeapStatsUpdateTask {
+public:
+    HeapStatsUpdateTask(InspectorHeapProfilerAgent*);
+    void startTimer();
+    void resetTimer() { m_timer.stop(); }
+    void onTimer(Timer<HeapStatsUpdateTask>*);
+
+private:
+    InspectorHeapProfilerAgent* m_heapProfilerAgent;
+    Timer<HeapStatsUpdateTask> m_timer;
+};
+
+PassOwnPtr<InspectorHeapProfilerAgent> InspectorHeapProfilerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager)
+{
+    return adoptPtr(new InspectorHeapProfilerAgent(instrumentingAgents, inspectorState, injectedScriptManager));
+}
+
+InspectorHeapProfilerAgent::InspectorHeapProfilerAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager)
+    : InspectorBaseAgent<InspectorHeapProfilerAgent>("HeapProfiler", instrumentingAgents, inspectorState)
+    , m_injectedScriptManager(injectedScriptManager)
+    , m_frontend(0)
+    , m_nextUserInitiatedHeapSnapshotNumber(1)
+{
+    m_instrumentingAgents->setInspectorHeapProfilerAgent(this);
+}
+
+InspectorHeapProfilerAgent::~InspectorHeapProfilerAgent()
+{
+    m_instrumentingAgents->setInspectorHeapProfilerAgent(0);
+}
+
+void InspectorHeapProfilerAgent::clearProfiles(ErrorString*)
+{
+    m_snapshots.clear();
+    m_nextUserInitiatedHeapSnapshotNumber = 1;
+    resetFrontendProfiles();
+    m_injectedScriptManager->injectedScriptHost()->clearInspectedObjects();
+}
+
+void InspectorHeapProfilerAgent::resetFrontendProfiles()
+{
+    stopTrackingHeapObjects(0);
+    if (!m_frontend)
+        return;
+    if (!m_state->getBoolean(HeapProfilerAgentState::profileHeadersRequested))
+        return;
+    if (m_snapshots.isEmpty())
+        m_frontend->resetProfiles();
+}
+
+void InspectorHeapProfilerAgent::setFrontend(InspectorFrontend* frontend)
+{
+    m_frontend = frontend->heapprofiler();
+}
+
+void InspectorHeapProfilerAgent::clearFrontend()
+{
+    m_state->setBoolean(HeapProfilerAgentState::profileHeadersRequested, false);
+    m_frontend = 0;
+}
+
+void InspectorHeapProfilerAgent::restore()
+{
+    resetFrontendProfiles();
+}
+
+void InspectorHeapProfilerAgent::collectGarbage(WebCore::ErrorString*)
+{
+    ScriptProfiler::collectGarbage();
+}
+
+PassRefPtr<TypeBuilder::HeapProfiler::ProfileHeader> InspectorHeapProfilerAgent::createSnapshotHeader(const ScriptHeapSnapshot& snapshot)
+{
+    RefPtr<TypeBuilder::HeapProfiler::ProfileHeader> header = TypeBuilder::HeapProfiler::ProfileHeader::create()
+        .setUid(snapshot.uid())
+        .setTitle(snapshot.title());
+    header->setMaxJSObjectId(snapshot.maxSnapshotJSObjectId());
+    return header.release();
+}
+
+InspectorHeapProfilerAgent::HeapStatsUpdateTask::HeapStatsUpdateTask(InspectorHeapProfilerAgent* heapProfilerAgent)
+    : m_heapProfilerAgent(heapProfilerAgent)
+    , m_timer(this, &HeapStatsUpdateTask::onTimer)
+{
+}
+
+void InspectorHeapProfilerAgent::HeapStatsUpdateTask::onTimer(Timer<HeapStatsUpdateTask>*)
+{
+    // The timer is stopped on m_heapProfilerAgent destruction,
+    // so this method will never be called after m_heapProfilerAgent has been destroyed.
+    m_heapProfilerAgent->requestHeapStatsUpdate();
+}
+
+void InspectorHeapProfilerAgent::HeapStatsUpdateTask::startTimer()
+{
+    ASSERT(!m_timer.isActive());
+    m_timer.startRepeating(0.05);
+}
+
+class InspectorHeapProfilerAgent::HeapStatsStream : public ScriptProfiler::OutputStream {
+public:
+    HeapStatsStream(InspectorHeapProfilerAgent* heapProfilerAgent)
+        : m_heapProfilerAgent(heapProfilerAgent)
+    {
+    }
+
+    virtual void write(const uint32_t* chunk, const int size) OVERRIDE
+    {
+        ASSERT(chunk);
+        ASSERT(size > 0);
+        m_heapProfilerAgent->pushHeapStatsUpdate(chunk, size);
+    }
+private:
+    InspectorHeapProfilerAgent* m_heapProfilerAgent;
+};
+
+void InspectorHeapProfilerAgent::startTrackingHeapObjects(ErrorString*)
+{
+    if (m_heapStatsUpdateTask)
+        return;
+    ScriptProfiler::startTrackingHeapObjects();
+    m_heapStatsUpdateTask = adoptPtr(new HeapStatsUpdateTask(this));
+    m_heapStatsUpdateTask->startTimer();
+}
+
+void InspectorHeapProfilerAgent::requestHeapStatsUpdate()
+{
+    if (!m_frontend)
+        return;
+    HeapStatsStream stream(this);
+    SnapshotObjectId lastSeenObjectId = ScriptProfiler::requestHeapStatsUpdate(&stream);
+    m_frontend->lastSeenObjectId(lastSeenObjectId, WTF::currentTimeMS());
+}
+
+void InspectorHeapProfilerAgent::pushHeapStatsUpdate(const uint32_t* const data, const int size)
+{
+    if (!m_frontend)
+        return;
+    RefPtr<TypeBuilder::Array<int> > statsDiff = TypeBuilder::Array<int>::create();
+    for (int i = 0; i < size; ++i)
+        statsDiff->addItem(data[i]);
+    m_frontend->heapStatsUpdate(statsDiff.release());
+}
+
+void InspectorHeapProfilerAgent::stopTrackingHeapObjects(ErrorString*)
+{
+    if (!m_heapStatsUpdateTask)
+        return;
+    ScriptProfiler::stopTrackingHeapObjects();
+    m_heapStatsUpdateTask->resetTimer();
+    m_heapStatsUpdateTask.clear();
+}
+
+void InspectorHeapProfilerAgent::getProfileHeaders(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::HeapProfiler::ProfileHeader> >& headers)
+{
+    m_state->setBoolean(HeapProfilerAgentState::profileHeadersRequested, true);
+    headers = TypeBuilder::Array<TypeBuilder::HeapProfiler::ProfileHeader>::create();
+
+    IdToHeapSnapshotMap::iterator snapshotsEnd = m_snapshots.end();
+    for (IdToHeapSnapshotMap::iterator it = m_snapshots.begin(); it != snapshotsEnd; ++it)
+        headers->addItem(createSnapshotHeader(*it->value));
+}
+
+void InspectorHeapProfilerAgent::getHeapSnapshot(ErrorString* errorString, int rawUid)
+{
+    class OutputStream : public ScriptHeapSnapshot::OutputStream {
+    public:
+        OutputStream(InspectorFrontend::HeapProfiler* frontend, unsigned uid)
+            : m_frontend(frontend), m_uid(uid) { }
+        void Write(const String& chunk) { m_frontend->addHeapSnapshotChunk(m_uid, chunk); }
+        void Close() { m_frontend->finishHeapSnapshot(m_uid); }
+    private:
+        InspectorFrontend::HeapProfiler* m_frontend;
+        int m_uid;
+    };
+
+    unsigned uid = static_cast<unsigned>(rawUid);
+    IdToHeapSnapshotMap::iterator it = m_snapshots.find(uid);
+    if (it == m_snapshots.end()) {
+        *errorString = "Profile wasn't found";
+        return;
+    }
+    RefPtr<ScriptHeapSnapshot> snapshot = it->value;
+    if (m_frontend) {
+        OutputStream stream(m_frontend, uid);
+        snapshot->writeJSON(&stream);
+    }
+}
+
+void InspectorHeapProfilerAgent::removeProfile(ErrorString*, int rawUid)
+{
+    unsigned uid = static_cast<unsigned>(rawUid);
+    if (m_snapshots.contains(uid))
+        m_snapshots.remove(uid);
+}
+
+void InspectorHeapProfilerAgent::takeHeapSnapshot(ErrorString*, const bool* reportProgress)
+{
+    class HeapSnapshotProgress: public ScriptProfiler::HeapSnapshotProgress {
+    public:
+        explicit HeapSnapshotProgress(InspectorFrontend::HeapProfiler* frontend)
+            : m_frontend(frontend) { }
+        void Start(int totalWork)
+        {
+            m_totalWork = totalWork;
+        }
+        void Worked(int workDone)
+        {
+            if (m_frontend)
+                m_frontend->reportHeapSnapshotProgress(workDone, m_totalWork);
+        }
+        void Done() { }
+        bool isCanceled() { return false; }
+    private:
+        InspectorFrontend::HeapProfiler* m_frontend;
+        int m_totalWork;
+    };
+
+    String title = makeString(UserInitiatedProfileNameHeap, '.', String::number(m_nextUserInitiatedHeapSnapshotNumber));
+    ++m_nextUserInitiatedHeapSnapshotNumber;
+
+    HeapSnapshotProgress progress(reportProgress && *reportProgress ? m_frontend : 0);
+    RefPtr<ScriptHeapSnapshot> snapshot = ScriptProfiler::takeHeapSnapshot(title, &progress);
+    if (snapshot) {
+        m_snapshots.add(snapshot->uid(), snapshot);
+        if (m_frontend)
+            m_frontend->addProfileHeader(createSnapshotHeader(*snapshot));
+    }
+}
+
+void InspectorHeapProfilerAgent::getObjectByHeapObjectId(ErrorString* error, const String& heapSnapshotObjectId, const String* objectGroup, RefPtr<TypeBuilder::Runtime::RemoteObject>& result)
+{
+    bool ok;
+    unsigned id = heapSnapshotObjectId.toUInt(&ok);
+    if (!ok) {
+        *error = "Invalid heap snapshot object id";
+        return;
+    }
+    ScriptObject heapObject = ScriptProfiler::objectByHeapObjectId(id);
+    if (heapObject.hasNoValue()) {
+        *error = "Object is not available";
+        return;
+    }
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(heapObject.scriptState());
+    if (injectedScript.hasNoValue()) {
+        *error = "Object is not available. Inspected context is gone";
+        return;
+    }
+    result = injectedScript.wrapObject(heapObject, objectGroup ? *objectGroup : "");
+    if (!result)
+        *error = "Failed to wrap object";
+}
+
+void InspectorHeapProfilerAgent::getHeapObjectId(ErrorString* errorString, const String& objectId, String* heapSnapshotObjectId)
+{
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
+    if (injectedScript.hasNoValue()) {
+        *errorString = "Inspected context has gone";
+        return;
+    }
+    ScriptValue value = injectedScript.findObjectById(objectId);
+    if (value.hasNoValue() || value.isUndefined()) {
+        *errorString = "Object with given id not found";
+        return;
+    }
+    unsigned id = ScriptProfiler::getHeapObjectId(value);
+    *heapSnapshotObjectId = String::number(id);
+}
+
+void InspectorHeapProfilerAgent::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::InspectorProfilerAgent);
+    InspectorBaseAgent<InspectorHeapProfilerAgent>::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_injectedScriptManager, "injectedScriptManager");
+    info.addWeakPointer(m_frontend);
+    info.addMember(m_snapshots, "snapshots");
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorHeapProfilerAgent.h b/Source/core/inspector/InspectorHeapProfilerAgent.h
new file mode 100644
index 0000000..03ac560
--- /dev/null
+++ b/Source/core/inspector/InspectorHeapProfilerAgent.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef InspectorHeapProfilerAgent_h
+#define InspectorHeapProfilerAgent_h
+
+
+#include "InspectorFrontend.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class HeapObjectsStatsStream;
+class InjectedScriptManager;
+class HeapStatsUpdateTask;
+class ScriptHeapSnapshot;
+class ScriptProfile;
+
+typedef String ErrorString;
+
+class InspectorHeapProfilerAgent : public InspectorBaseAgent<InspectorHeapProfilerAgent>, public InspectorBackendDispatcher::HeapProfilerCommandHandler {
+    WTF_MAKE_NONCOPYABLE(InspectorHeapProfilerAgent); WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<InspectorHeapProfilerAgent> create(InstrumentingAgents*, InspectorCompositeState*, InjectedScriptManager*);
+    virtual ~InspectorHeapProfilerAgent();
+
+    virtual void collectGarbage(ErrorString*);
+    virtual void clearProfiles(ErrorString*);
+
+    virtual void getProfileHeaders(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::HeapProfiler::ProfileHeader> >&);
+    virtual void getHeapSnapshot(ErrorString*, int uid);
+    virtual void removeProfile(ErrorString*, int uid);
+    virtual void startTrackingHeapObjects(ErrorString*);
+    virtual void stopTrackingHeapObjects(ErrorString*);
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void restore();
+
+    virtual void takeHeapSnapshot(ErrorString*, const bool* reportProgress);
+
+    virtual void getObjectByHeapObjectId(ErrorString*, const String& heapSnapshotObjectId, const String* objectGroup, RefPtr<TypeBuilder::Runtime::RemoteObject>& result);
+    virtual void getHeapObjectId(ErrorString*, const String& objectId, String* heapSnapshotObjectId);
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+
+private:
+    class HeapStatsStream;
+    class HeapStatsUpdateTask;
+
+    InspectorHeapProfilerAgent(InstrumentingAgents*, InspectorCompositeState*, InjectedScriptManager*);
+
+    typedef HashMap<unsigned, RefPtr<ScriptHeapSnapshot> > IdToHeapSnapshotMap;
+
+    void resetFrontendProfiles();
+    void requestHeapStatsUpdate();
+    void pushHeapStatsUpdate(const uint32_t* const data, const int size);
+
+    PassRefPtr<TypeBuilder::HeapProfiler::ProfileHeader> createSnapshotHeader(const ScriptHeapSnapshot&);
+
+    InjectedScriptManager* m_injectedScriptManager;
+    InspectorFrontend::HeapProfiler* m_frontend;
+    unsigned m_nextUserInitiatedHeapSnapshotNumber;
+    IdToHeapSnapshotMap m_snapshots;
+    OwnPtr<HeapStatsUpdateTask> m_heapStatsUpdateTask;
+};
+
+} // namespace WebCore
+
+
+#endif // !defined(InspectorHeapProfilerAgent_h)
diff --git a/Source/core/inspector/InspectorHistory.cpp b/Source/core/inspector/InspectorHistory.cpp
new file mode 100644
index 0000000..565c142
--- /dev/null
+++ b/Source/core/inspector/InspectorHistory.cpp
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorHistory.h"
+
+#include "core/dom/ExceptionCodePlaceholder.h"
+#include "core/dom/Node.h"
+
+namespace WebCore {
+
+namespace {
+
+class UndoableStateMark : public InspectorHistory::Action {
+public:
+    UndoableStateMark() : InspectorHistory::Action("[UndoableState]") { }
+
+    virtual bool perform(ExceptionCode&) { return true; }
+
+    virtual bool undo(ExceptionCode&) { return true; }
+
+    virtual bool redo(ExceptionCode&) { return true; }
+
+    virtual bool isUndoableStateMark() { return true; }
+};
+
+}
+
+InspectorHistory::Action::Action(const String& name) : m_name(name)
+{
+}
+
+InspectorHistory::Action::~Action()
+{
+}
+
+String InspectorHistory::Action::toString()
+{
+    return m_name;
+}
+
+bool InspectorHistory::Action::isUndoableStateMark()
+{
+    return false;
+}
+
+String InspectorHistory::Action::mergeId()
+{
+    return "";
+}
+
+void InspectorHistory::Action::merge(PassOwnPtr<Action>)
+{
+}
+
+InspectorHistory::InspectorHistory() : m_afterLastActionIndex(0) { }
+
+InspectorHistory::~InspectorHistory() { }
+
+bool InspectorHistory::perform(PassOwnPtr<Action> action, ExceptionCode& ec)
+{
+    if (!action->perform(ec))
+        return false;
+
+    if (!action->mergeId().isEmpty() && m_afterLastActionIndex > 0 && action->mergeId() == m_history[m_afterLastActionIndex - 1]->mergeId())
+        m_history[m_afterLastActionIndex - 1]->merge(action);
+    else {
+        m_history.resize(m_afterLastActionIndex);
+        m_history.append(action);
+        ++m_afterLastActionIndex;
+    }
+    return true;
+}
+
+void InspectorHistory::markUndoableState()
+{
+    perform(adoptPtr(new UndoableStateMark()), IGNORE_EXCEPTION);
+}
+
+bool InspectorHistory::undo(ExceptionCode& ec)
+{
+    while (m_afterLastActionIndex > 0 && m_history[m_afterLastActionIndex - 1]->isUndoableStateMark())
+        --m_afterLastActionIndex;
+
+    while (m_afterLastActionIndex > 0) {
+        Action* action = m_history[m_afterLastActionIndex - 1].get();
+        if (!action->undo(ec)) {
+            reset();
+            return false;
+        }
+        --m_afterLastActionIndex;
+        if (action->isUndoableStateMark())
+            break;
+    }
+
+    return true;
+}
+
+bool InspectorHistory::redo(ExceptionCode& ec)
+{
+    while (m_afterLastActionIndex < m_history.size() && m_history[m_afterLastActionIndex]->isUndoableStateMark())
+        ++m_afterLastActionIndex;
+
+    while (m_afterLastActionIndex < m_history.size()) {
+        Action* action = m_history[m_afterLastActionIndex].get();
+        if (!action->redo(ec)) {
+            reset();
+            return false;
+        }
+        ++m_afterLastActionIndex;
+        if (action->isUndoableStateMark())
+            break;
+    }
+    return true;
+}
+
+void InspectorHistory::reset()
+{
+    m_afterLastActionIndex = 0;
+    m_history.clear();
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorHistory.h b/Source/core/inspector/InspectorHistory.h
new file mode 100644
index 0000000..36504ce
--- /dev/null
+++ b/Source/core/inspector/InspectorHistory.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+#ifndef InspectorHistory_h
+#define InspectorHistory_h
+
+#include "core/dom/ExceptionCode.h"
+
+#include <wtf/OwnPtr.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class ContainerNode;
+class Element;
+class Node;
+
+
+class InspectorHistory {
+    WTF_MAKE_NONCOPYABLE(InspectorHistory); WTF_MAKE_FAST_ALLOCATED;
+public:
+    class Action {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        Action(const String& name);
+        virtual ~Action();
+        virtual String toString();
+
+        virtual String mergeId();
+        virtual void merge(PassOwnPtr<Action>);
+
+        virtual bool perform(ExceptionCode&) = 0;
+
+        virtual bool undo(ExceptionCode&) = 0;
+        virtual bool redo(ExceptionCode&) = 0;
+
+        virtual bool isUndoableStateMark();
+    private:
+        String m_name;
+    };
+
+    InspectorHistory();
+    virtual ~InspectorHistory();
+
+    bool perform(PassOwnPtr<Action>, ExceptionCode&);
+    void markUndoableState();
+
+    bool undo(ExceptionCode&);
+    bool redo(ExceptionCode&);
+    void reset();
+
+private:
+    Vector<OwnPtr<Action> > m_history;
+    size_t m_afterLastActionIndex;
+};
+
+
+} // namespace WebCore
+
+#endif // !defined(InspectorHistory_h)
diff --git a/Source/core/inspector/InspectorIndexedDBAgent.cpp b/Source/core/inspector/InspectorIndexedDBAgent.cpp
new file mode 100644
index 0000000..9eafcf6
--- /dev/null
+++ b/Source/core/inspector/InspectorIndexedDBAgent.cpp
@@ -0,0 +1,792 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include "core/inspector/InspectorIndexedDBAgent.h"
+
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptController.h"
+#include "core/dom/DOMStringList.h"
+#include "core/dom/Document.h"
+#include "core/dom/Event.h"
+#include "core/dom/EventListener.h"
+#include "core/dom/EventTarget.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/page/DOMWindow.h"
+#include "core/page/Frame.h"
+#include "core/page/SecurityOrigin.h"
+#include "modules/indexeddb/DOMWindowIndexedDatabase.h"
+#include "modules/indexeddb/IDBCursor.h"
+#include "modules/indexeddb/IDBCursorWithValue.h"
+#include "modules/indexeddb/IDBDatabase.h"
+#include "modules/indexeddb/IDBDatabaseCallbacks.h"
+#include "modules/indexeddb/IDBFactory.h"
+#include "modules/indexeddb/IDBIndex.h"
+#include "modules/indexeddb/IDBKey.h"
+#include "modules/indexeddb/IDBKeyPath.h"
+#include "modules/indexeddb/IDBKeyRange.h"
+#include "modules/indexeddb/IDBMetadata.h"
+#include "modules/indexeddb/IDBObjectStore.h"
+#include "modules/indexeddb/IDBOpenDBRequest.h"
+#include "modules/indexeddb/IDBPendingTransactionMonitor.h"
+#include "modules/indexeddb/IDBRequest.h"
+#include "modules/indexeddb/IDBTransaction.h"
+
+#include <wtf/Vector.h>
+
+using WebCore::TypeBuilder::Array;
+using WebCore::TypeBuilder::IndexedDB::DatabaseWithObjectStores;
+using WebCore::TypeBuilder::IndexedDB::DataEntry;
+using WebCore::TypeBuilder::IndexedDB::Key;
+using WebCore::TypeBuilder::IndexedDB::KeyPath;
+using WebCore::TypeBuilder::IndexedDB::KeyRange;
+using WebCore::TypeBuilder::IndexedDB::ObjectStore;
+using WebCore::TypeBuilder::IndexedDB::ObjectStoreIndex;
+
+typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDatabaseNamesCallback RequestDatabaseNamesCallback;
+typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDatabaseCallback RequestDatabaseCallback;
+typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDataCallback RequestDataCallback;
+typedef WebCore::InspectorBackendDispatcher::CallbackBase RequestCallback;
+typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::ClearObjectStoreCallback ClearObjectStoreCallback;
+
+namespace WebCore {
+
+namespace IndexedDBAgentState {
+static const char indexedDBAgentEnabled[] = "indexedDBAgentEnabled";
+};
+
+namespace {
+
+class GetDatabaseNamesCallback : public EventListener {
+    WTF_MAKE_NONCOPYABLE(GetDatabaseNamesCallback);
+public:
+    static PassRefPtr<GetDatabaseNamesCallback> create(PassRefPtr<RequestDatabaseNamesCallback> requestCallback, const String& securityOrigin)
+    {
+        return adoptRef(new GetDatabaseNamesCallback(requestCallback, securityOrigin));
+    }
+
+    virtual ~GetDatabaseNamesCallback() { }
+
+    virtual bool operator==(const EventListener& other) OVERRIDE
+    {
+        return this == &other;
+    }
+
+    virtual void handleEvent(ScriptExecutionContext*, Event* event) OVERRIDE
+    {
+        if (!m_requestCallback->isActive())
+            return;
+        if (event->type() != eventNames().successEvent) {
+            m_requestCallback->sendFailure("Unexpected event type.");
+            return;
+        }
+
+        IDBRequest* idbRequest = static_cast<IDBRequest*>(event->target());
+        ExceptionCode ec = 0;
+        RefPtr<IDBAny> requestResult = idbRequest->result(ec);
+        if (ec) {
+            m_requestCallback->sendFailure("Could not get result in callback.");
+            return;
+        }
+        if (requestResult->type() != IDBAny::DOMStringListType) {
+            m_requestCallback->sendFailure("Unexpected result type.");
+            return;
+        }
+
+        RefPtr<DOMStringList> databaseNamesList = requestResult->domStringList();
+        RefPtr<TypeBuilder::Array<String> > databaseNames = TypeBuilder::Array<String>::create();
+        for (size_t i = 0; i < databaseNamesList->length(); ++i)
+            databaseNames->addItem(databaseNamesList->item(i));
+        m_requestCallback->sendSuccess(databaseNames.release());
+    }
+
+private:
+    GetDatabaseNamesCallback(PassRefPtr<RequestDatabaseNamesCallback> requestCallback, const String& securityOrigin)
+        : EventListener(EventListener::CPPEventListenerType)
+        , m_requestCallback(requestCallback)
+        , m_securityOrigin(securityOrigin) { }
+    RefPtr<RequestDatabaseNamesCallback> m_requestCallback;
+    String m_securityOrigin;
+};
+
+class ExecutableWithDatabase : public RefCounted<ExecutableWithDatabase> {
+public:
+    ExecutableWithDatabase(ScriptExecutionContext* context)
+        : m_context(context) { }
+    virtual ~ExecutableWithDatabase() { };
+    void start(IDBFactory*, SecurityOrigin*, const String& databaseName);
+    virtual void execute(PassRefPtr<IDBDatabase>) = 0;
+    virtual RequestCallback* requestCallback() = 0;
+    ScriptExecutionContext* context() { return m_context; };
+private:
+    ScriptExecutionContext* m_context;
+};
+
+class OpenDatabaseCallback : public EventListener {
+public:
+    static PassRefPtr<OpenDatabaseCallback> create(ExecutableWithDatabase* executableWithDatabase)
+    {
+        return adoptRef(new OpenDatabaseCallback(executableWithDatabase));
+    }
+
+    virtual ~OpenDatabaseCallback() { }
+
+    virtual bool operator==(const EventListener& other) OVERRIDE
+    {
+        return this == &other;
+    }
+
+    virtual void handleEvent(ScriptExecutionContext*, Event* event) OVERRIDE
+    {
+        if (event->type() != eventNames().successEvent) {
+            m_executableWithDatabase->requestCallback()->sendFailure("Unexpected event type.");
+            return;
+        }
+
+        IDBOpenDBRequest* idbOpenDBRequest = static_cast<IDBOpenDBRequest*>(event->target());
+        ExceptionCode ec = 0;
+        RefPtr<IDBAny> requestResult = idbOpenDBRequest->result(ec);
+        if (ec) {
+            m_executableWithDatabase->requestCallback()->sendFailure("Could not get result in callback.");
+            return;
+        }
+        if (requestResult->type() != IDBAny::IDBDatabaseType) {
+            m_executableWithDatabase->requestCallback()->sendFailure("Unexpected result type.");
+            return;
+        }
+
+        RefPtr<IDBDatabase> idbDatabase = requestResult->idbDatabase();
+        m_executableWithDatabase->execute(idbDatabase);
+        IDBPendingTransactionMonitor::deactivateNewTransactions();
+        idbDatabase->close();
+    }
+
+private:
+    OpenDatabaseCallback(ExecutableWithDatabase* executableWithDatabase)
+        : EventListener(EventListener::CPPEventListenerType)
+        , m_executableWithDatabase(executableWithDatabase) { }
+    RefPtr<ExecutableWithDatabase> m_executableWithDatabase;
+};
+
+void ExecutableWithDatabase::start(IDBFactory* idbFactory, SecurityOrigin*, const String& databaseName)
+{
+    RefPtr<OpenDatabaseCallback> callback = OpenDatabaseCallback::create(this);
+    ExceptionCode ec = 0;
+    RefPtr<IDBOpenDBRequest> idbOpenDBRequest = idbFactory->open(context(), databaseName, ec);
+    if (ec) {
+        requestCallback()->sendFailure("Could not open database.");
+        return;
+    }
+    idbOpenDBRequest->addEventListener(eventNames().successEvent, callback, false);
+}
+
+static PassRefPtr<IDBTransaction> transactionForDatabase(ScriptExecutionContext* scriptExecutionContext, IDBDatabase* idbDatabase, const String& objectStoreName, const String& mode = IDBTransaction::modeReadOnly())
+{
+    ExceptionCode ec = 0;
+    RefPtr<IDBTransaction> idbTransaction = idbDatabase->transaction(scriptExecutionContext, objectStoreName, mode, ec);
+    if (ec)
+        return 0;
+    return idbTransaction;
+}
+
+static PassRefPtr<IDBObjectStore> objectStoreForTransaction(IDBTransaction* idbTransaction, const String& objectStoreName)
+{
+    ExceptionCode ec = 0;
+    RefPtr<IDBObjectStore> idbObjectStore = idbTransaction->objectStore(objectStoreName, ec);
+    if (ec)
+        return 0;
+    return idbObjectStore;
+}
+
+static PassRefPtr<IDBIndex> indexForObjectStore(IDBObjectStore* idbObjectStore, const String& indexName)
+{
+    ExceptionCode ec = 0;
+    RefPtr<IDBIndex> idbIndex = idbObjectStore->index(indexName, ec);
+    if (ec)
+        return 0;
+    return idbIndex;
+}
+
+static PassRefPtr<KeyPath> keyPathFromIDBKeyPath(const IDBKeyPath& idbKeyPath)
+{
+    RefPtr<KeyPath> keyPath;
+    switch (idbKeyPath.type()) {
+    case IDBKeyPath::NullType:
+        keyPath = KeyPath::create().setType(KeyPath::Type::Null);
+        break;
+    case IDBKeyPath::StringType:
+        keyPath = KeyPath::create().setType(KeyPath::Type::String);
+        keyPath->setString(idbKeyPath.string());
+        break;
+    case IDBKeyPath::ArrayType: {
+        keyPath = KeyPath::create().setType(KeyPath::Type::Array);
+        RefPtr<TypeBuilder::Array<String> > array = TypeBuilder::Array<String>::create();
+        const Vector<String>& stringArray = idbKeyPath.array();
+        for (size_t i = 0; i < stringArray.size(); ++i)
+            array->addItem(stringArray[i]);
+        keyPath->setArray(array);
+        break;
+    }
+    default:
+        ASSERT_NOT_REACHED();
+    }
+
+    return keyPath.release();
+}
+
+class DatabaseLoader : public ExecutableWithDatabase {
+public:
+    static PassRefPtr<DatabaseLoader> create(ScriptExecutionContext* context, PassRefPtr<RequestDatabaseCallback> requestCallback)
+    {
+        return adoptRef(new DatabaseLoader(context, requestCallback));
+    }
+
+    virtual ~DatabaseLoader() { }
+
+    virtual void execute(PassRefPtr<IDBDatabase> prpDatabase)
+    {
+        RefPtr<IDBDatabase> idbDatabase = prpDatabase;
+        if (!requestCallback()->isActive())
+            return;
+
+        const IDBDatabaseMetadata databaseMetadata = idbDatabase->metadata();
+
+        RefPtr<TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStore> > objectStores = TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStore>::create();
+
+        for (IDBDatabaseMetadata::ObjectStoreMap::const_iterator it = databaseMetadata.objectStores.begin(); it != databaseMetadata.objectStores.end(); ++it) {
+            const IDBObjectStoreMetadata& objectStoreMetadata = it->value;
+
+            RefPtr<TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStoreIndex> > indexes = TypeBuilder::Array<TypeBuilder::IndexedDB::ObjectStoreIndex>::create();
+
+            for (IDBObjectStoreMetadata::IndexMap::const_iterator it = objectStoreMetadata.indexes.begin(); it != objectStoreMetadata.indexes.end(); ++it) {
+                const IDBIndexMetadata& indexMetadata = it->value;
+
+                RefPtr<ObjectStoreIndex> objectStoreIndex = ObjectStoreIndex::create()
+                    .setName(indexMetadata.name)
+                    .setKeyPath(keyPathFromIDBKeyPath(indexMetadata.keyPath))
+                    .setUnique(indexMetadata.unique)
+                    .setMultiEntry(indexMetadata.multiEntry);
+                indexes->addItem(objectStoreIndex);
+            }
+
+            RefPtr<ObjectStore> objectStore = ObjectStore::create()
+                .setName(objectStoreMetadata.name)
+                .setKeyPath(keyPathFromIDBKeyPath(objectStoreMetadata.keyPath))
+                .setAutoIncrement(objectStoreMetadata.autoIncrement)
+                .setIndexes(indexes);
+            objectStores->addItem(objectStore);
+        }
+        RefPtr<DatabaseWithObjectStores> result = DatabaseWithObjectStores::create()
+            .setName(databaseMetadata.name)
+            .setIntVersion(databaseMetadata.intVersion)
+            .setVersion(databaseMetadata.version)
+            .setObjectStores(objectStores);
+
+        m_requestCallback->sendSuccess(result);
+    }
+
+    virtual RequestCallback* requestCallback() { return m_requestCallback.get(); }
+private:
+    DatabaseLoader(ScriptExecutionContext* context, PassRefPtr<RequestDatabaseCallback> requestCallback)
+        : ExecutableWithDatabase(context)
+        , m_requestCallback(requestCallback) { }
+    RefPtr<RequestDatabaseCallback> m_requestCallback;
+};
+
+static PassRefPtr<IDBKey> idbKeyFromInspectorObject(InspectorObject* key)
+{
+    RefPtr<IDBKey> idbKey;
+
+    String type;
+    if (!key->getString("type", &type))
+        return 0;
+
+    DEFINE_STATIC_LOCAL(String, number, (ASCIILiteral("number")));
+    DEFINE_STATIC_LOCAL(String, string, (ASCIILiteral("string")));
+    DEFINE_STATIC_LOCAL(String, date, (ASCIILiteral("date")));
+    DEFINE_STATIC_LOCAL(String, array, (ASCIILiteral("array")));
+
+    if (type == number) {
+        double number;
+        if (!key->getNumber("number", &number))
+            return 0;
+        idbKey = IDBKey::createNumber(number);
+    } else if (type == string) {
+        String string;
+        if (!key->getString("string", &string))
+            return 0;
+        idbKey = IDBKey::createString(string);
+    } else if (type == date) {
+        double date;
+        if (!key->getNumber("date", &date))
+            return 0;
+        idbKey = IDBKey::createDate(date);
+    } else if (type == array) {
+        IDBKey::KeyArray keyArray;
+        RefPtr<InspectorArray> array = key->getArray("array");
+        for (size_t i = 0; i < array->length(); ++i) {
+            RefPtr<InspectorValue> value = array->get(i);
+            RefPtr<InspectorObject> object;
+            if (!value->asObject(&object))
+                return 0;
+            keyArray.append(idbKeyFromInspectorObject(object.get()));
+        }
+        idbKey = IDBKey::createArray(keyArray);
+    } else
+        return 0;
+
+    return idbKey.release();
+}
+
+static PassRefPtr<IDBKeyRange> idbKeyRangeFromKeyRange(InspectorObject* keyRange)
+{
+    RefPtr<InspectorObject> lower = keyRange->getObject("lower");
+    RefPtr<IDBKey> idbLower = lower ? idbKeyFromInspectorObject(lower.get()) : 0;
+    if (lower && !idbLower)
+        return 0;
+
+    RefPtr<InspectorObject> upper = keyRange->getObject("upper");
+    RefPtr<IDBKey> idbUpper = upper ? idbKeyFromInspectorObject(upper.get()) : 0;
+    if (upper && !idbUpper)
+        return 0;
+
+    bool lowerOpen;
+    if (!keyRange->getBoolean("lowerOpen", &lowerOpen))
+        return 0;
+    IDBKeyRange::LowerBoundType lowerBoundType = lowerOpen ? IDBKeyRange::LowerBoundOpen : IDBKeyRange::LowerBoundClosed;
+
+    bool upperOpen;
+    if (!keyRange->getBoolean("upperOpen", &upperOpen))
+        return 0;
+    IDBKeyRange::UpperBoundType upperBoundType = upperOpen ? IDBKeyRange::UpperBoundOpen : IDBKeyRange::UpperBoundClosed;
+
+    RefPtr<IDBKeyRange> idbKeyRange = IDBKeyRange::create(idbLower, idbUpper, lowerBoundType, upperBoundType);
+    return idbKeyRange.release();
+}
+
+class DataLoader;
+
+class OpenCursorCallback : public EventListener {
+public:
+    static PassRefPtr<OpenCursorCallback> create(InjectedScript injectedScript, PassRefPtr<RequestDataCallback> requestCallback, int skipCount, unsigned pageSize)
+    {
+        return adoptRef(new OpenCursorCallback(injectedScript, requestCallback, skipCount, pageSize));
+    }
+
+    virtual ~OpenCursorCallback() { }
+
+    virtual bool operator==(const EventListener& other) OVERRIDE
+    {
+        return this == &other;
+    }
+
+    virtual void handleEvent(ScriptExecutionContext*, Event* event) OVERRIDE
+    {
+        if (event->type() != eventNames().successEvent) {
+            m_requestCallback->sendFailure("Unexpected event type.");
+            return;
+        }
+
+        IDBRequest* idbRequest = static_cast<IDBRequest*>(event->target());
+        ExceptionCode ec = 0;
+        RefPtr<IDBAny> requestResult = idbRequest->result(ec);
+        if (ec) {
+            m_requestCallback->sendFailure("Could not get result in callback.");
+            return;
+        }
+        if (requestResult->type() == IDBAny::ScriptValueType) {
+            end(false);
+            return;
+        }
+        if (requestResult->type() != IDBAny::IDBCursorWithValueType) {
+            m_requestCallback->sendFailure("Unexpected result type.");
+            return;
+        }
+
+        RefPtr<IDBCursorWithValue> idbCursor = requestResult->idbCursorWithValue();
+
+        if (m_skipCount) {
+            ExceptionCode ec = 0;
+            idbCursor->advance(m_skipCount, ec);
+            if (ec)
+                m_requestCallback->sendFailure("Could not advance cursor.");
+            m_skipCount = 0;
+            return;
+        }
+
+        if (m_result->length() == m_pageSize) {
+            end(true);
+            return;
+        }
+
+        // Continue cursor before making injected script calls, otherwise transaction might be finished.
+        idbCursor->continueFunction(0, ec);
+        if (ec) {
+            m_requestCallback->sendFailure("Could not continue cursor.");
+            return;
+        }
+
+        RefPtr<DataEntry> dataEntry = DataEntry::create()
+            .setKey(m_injectedScript.wrapObject(idbCursor->key(), String()))
+            .setPrimaryKey(m_injectedScript.wrapObject(idbCursor->primaryKey(), String()))
+            .setValue(m_injectedScript.wrapObject(idbCursor->value(), String()));
+        m_result->addItem(dataEntry);
+
+    }
+
+    void end(bool hasMore)
+    {
+        if (!m_requestCallback->isActive())
+            return;
+        m_requestCallback->sendSuccess(m_result.release(), hasMore);
+    }
+
+private:
+    OpenCursorCallback(InjectedScript injectedScript, PassRefPtr<RequestDataCallback> requestCallback, int skipCount, unsigned pageSize)
+        : EventListener(EventListener::CPPEventListenerType)
+        , m_injectedScript(injectedScript)
+        , m_requestCallback(requestCallback)
+        , m_skipCount(skipCount)
+        , m_pageSize(pageSize)
+    {
+        m_result = Array<DataEntry>::create();
+    }
+    InjectedScript m_injectedScript;
+    RefPtr<RequestDataCallback> m_requestCallback;
+    int m_skipCount;
+    unsigned m_pageSize;
+    RefPtr<Array<DataEntry> > m_result;
+};
+
+class DataLoader : public ExecutableWithDatabase {
+public:
+    static PassRefPtr<DataLoader> create(ScriptExecutionContext* context, PassRefPtr<RequestDataCallback> requestCallback, const InjectedScript& injectedScript, const String& objectStoreName, const String& indexName, PassRefPtr<IDBKeyRange> idbKeyRange, int skipCount, unsigned pageSize)
+    {
+        return adoptRef(new DataLoader(context, requestCallback, injectedScript, objectStoreName, indexName, idbKeyRange, skipCount, pageSize));
+    }
+
+    virtual ~DataLoader() { }
+
+    virtual void execute(PassRefPtr<IDBDatabase> prpDatabase)
+    {
+        RefPtr<IDBDatabase> idbDatabase = prpDatabase;
+        if (!requestCallback()->isActive())
+            return;
+        RefPtr<IDBTransaction> idbTransaction = transactionForDatabase(context(), idbDatabase.get(), m_objectStoreName);
+        if (!idbTransaction) {
+            m_requestCallback->sendFailure("Could not get transaction");
+            return;
+        }
+        RefPtr<IDBObjectStore> idbObjectStore = objectStoreForTransaction(idbTransaction.get(), m_objectStoreName);
+        if (!idbObjectStore) {
+            m_requestCallback->sendFailure("Could not get object store");
+            return;
+        }
+
+        RefPtr<OpenCursorCallback> openCursorCallback = OpenCursorCallback::create(m_injectedScript, m_requestCallback, m_skipCount, m_pageSize);
+
+        ExceptionCode ec = 0;
+        RefPtr<IDBRequest> idbRequest;
+        if (!m_indexName.isEmpty()) {
+            RefPtr<IDBIndex> idbIndex = indexForObjectStore(idbObjectStore.get(), m_indexName);
+            if (!idbIndex) {
+                m_requestCallback->sendFailure("Could not get index");
+                return;
+            }
+
+            idbRequest = idbIndex->openCursor(context(), PassRefPtr<IDBKeyRange>(m_idbKeyRange), IDBCursor::directionNext(), ec);
+        } else
+            idbRequest = idbObjectStore->openCursor(context(), PassRefPtr<IDBKeyRange>(m_idbKeyRange), IDBCursor::directionNext(), ec);
+        idbRequest->addEventListener(eventNames().successEvent, openCursorCallback, false);
+    }
+
+    virtual RequestCallback* requestCallback() { return m_requestCallback.get(); }
+    DataLoader(ScriptExecutionContext* scriptExecutionContext, PassRefPtr<RequestDataCallback> requestCallback, const InjectedScript& injectedScript, const String& objectStoreName, const String& indexName, PassRefPtr<IDBKeyRange> idbKeyRange, int skipCount, unsigned pageSize)
+        : ExecutableWithDatabase(scriptExecutionContext)
+        , m_requestCallback(requestCallback)
+        , m_injectedScript(injectedScript)
+        , m_objectStoreName(objectStoreName)
+        , m_indexName(indexName)
+        , m_idbKeyRange(idbKeyRange)
+        , m_skipCount(skipCount)
+        , m_pageSize(pageSize) { }
+    RefPtr<RequestDataCallback> m_requestCallback;
+    InjectedScript m_injectedScript;
+    String m_objectStoreName;
+    String m_indexName;
+    RefPtr<IDBKeyRange> m_idbKeyRange;
+    int m_skipCount;
+    unsigned m_pageSize;
+};
+
+} // namespace
+
+InspectorIndexedDBAgent::InspectorIndexedDBAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager, InspectorPageAgent* pageAgent)
+    : InspectorBaseAgent<InspectorIndexedDBAgent>("IndexedDB", instrumentingAgents, state)
+    , m_injectedScriptManager(injectedScriptManager)
+    , m_pageAgent(pageAgent)
+{
+}
+
+InspectorIndexedDBAgent::~InspectorIndexedDBAgent()
+{
+}
+
+void InspectorIndexedDBAgent::clearFrontend()
+{
+    disable(0);
+}
+
+void InspectorIndexedDBAgent::restore()
+{
+    if (m_state->getBoolean(IndexedDBAgentState::indexedDBAgentEnabled)) {
+        ErrorString error;
+        enable(&error);
+    }
+}
+
+void InspectorIndexedDBAgent::enable(ErrorString*)
+{
+    m_state->setBoolean(IndexedDBAgentState::indexedDBAgentEnabled, true);
+}
+
+void InspectorIndexedDBAgent::disable(ErrorString*)
+{
+    m_state->setBoolean(IndexedDBAgentState::indexedDBAgentEnabled, false);
+}
+
+static Document* assertDocument(ErrorString* errorString, Frame* frame)
+{
+    Document* document = frame ? frame->document() : 0;
+
+    if (!document)
+        *errorString = "No document for given frame found";
+
+    return document;
+}
+
+static IDBFactory* assertIDBFactory(ErrorString* errorString, Document* document)
+{
+    DOMWindow* domWindow = document->domWindow();
+    if (!domWindow) {
+        *errorString = "No IndexedDB factory for given frame found";
+        return 0;
+    }
+    IDBFactory* idbFactory = DOMWindowIndexedDatabase::indexedDB(domWindow);
+
+    if (!idbFactory)
+        *errorString = "No IndexedDB factory for given frame found";
+
+    return idbFactory;
+}
+
+void InspectorIndexedDBAgent::requestDatabaseNames(ErrorString* errorString, const String& securityOrigin, PassRefPtr<RequestDatabaseNamesCallback> requestCallback)
+{
+    Frame* frame = m_pageAgent->findFrameWithSecurityOrigin(securityOrigin);
+    Document* document = assertDocument(errorString, frame);
+    if (!document)
+        return;
+    IDBFactory* idbFactory = assertIDBFactory(errorString, document);
+    if (!idbFactory)
+        return;
+
+    // FIXME: This should probably use ScriptState/ScriptScope instead of V8 API
+    v8::HandleScope handleScope;
+    v8::Handle<v8::Context> context = document->frame()->script()->mainWorldContext();
+    ASSERT(!context.IsEmpty());
+    v8::Context::Scope contextScope(context);
+
+    ExceptionCode ec = 0;
+    RefPtr<IDBRequest> idbRequest = idbFactory->getDatabaseNames(document, ec);
+    if (ec) {
+        requestCallback->sendFailure("Could not obtain database names.");
+        return;
+    }
+    idbRequest->addEventListener(eventNames().successEvent, GetDatabaseNamesCallback::create(requestCallback, document->securityOrigin()->toRawString()), false);
+}
+
+void InspectorIndexedDBAgent::requestDatabase(ErrorString* errorString, const String& securityOrigin, const String& databaseName, PassRefPtr<RequestDatabaseCallback> requestCallback)
+{
+    Frame* frame = m_pageAgent->findFrameWithSecurityOrigin(securityOrigin);
+    Document* document = assertDocument(errorString, frame);
+    if (!document)
+        return;
+    IDBFactory* idbFactory = assertIDBFactory(errorString, document);
+    if (!idbFactory)
+        return;
+
+    // FIXME: This should probably use ScriptState/ScriptScope instead of V8 API
+    v8::HandleScope handleScope;
+    v8::Handle<v8::Context> context = document->frame()->script()->mainWorldContext();
+    ASSERT(!context.IsEmpty());
+    v8::Context::Scope contextScope(context);
+
+    RefPtr<DatabaseLoader> databaseLoader = DatabaseLoader::create(document, requestCallback);
+    databaseLoader->start(idbFactory, document->securityOrigin(), databaseName);
+}
+
+void InspectorIndexedDBAgent::requestData(ErrorString* errorString, const String& securityOrigin, const String& databaseName, const String& objectStoreName, const String& indexName, int skipCount, int pageSize, const RefPtr<InspectorObject>* keyRange, PassRefPtr<RequestDataCallback> requestCallback)
+{
+    Frame* frame = m_pageAgent->findFrameWithSecurityOrigin(securityOrigin);
+    Document* document = assertDocument(errorString, frame);
+    if (!document)
+        return;
+    IDBFactory* idbFactory = assertIDBFactory(errorString, document);
+    if (!idbFactory)
+        return;
+
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(mainWorldScriptState(frame));
+
+    RefPtr<IDBKeyRange> idbKeyRange = keyRange ? idbKeyRangeFromKeyRange(keyRange->get()) : 0;
+    if (keyRange && !idbKeyRange) {
+        *errorString = "Can not parse key range.";
+        return;
+    }
+
+    // FIXME: This should probably use ScriptState/ScriptScope instead of V8 API
+    v8::HandleScope handleScope;
+    v8::Handle<v8::Context> context = document->frame()->script()->mainWorldContext();
+    ASSERT(!context.IsEmpty());
+    v8::Context::Scope contextScope(context);
+
+    RefPtr<DataLoader> dataLoader = DataLoader::create(document, requestCallback, injectedScript, objectStoreName, indexName, idbKeyRange, skipCount, pageSize);
+    dataLoader->start(idbFactory, document->securityOrigin(), databaseName);
+}
+
+class ClearObjectStoreListener : public EventListener {
+    WTF_MAKE_NONCOPYABLE(ClearObjectStoreListener);
+public:
+    static PassRefPtr<ClearObjectStoreListener> create(PassRefPtr<ClearObjectStoreCallback> requestCallback)
+    {
+        return adoptRef(new ClearObjectStoreListener(requestCallback));
+    }
+
+    virtual ~ClearObjectStoreListener() { }
+
+    virtual bool operator==(const EventListener& other) OVERRIDE
+    {
+        return this == &other;
+    }
+
+    virtual void handleEvent(ScriptExecutionContext*, Event* event) OVERRIDE
+    {
+        if (!m_requestCallback->isActive())
+            return;
+        if (event->type() != eventNames().completeEvent) {
+            m_requestCallback->sendFailure("Unexpected event type.");
+            return;
+        }
+
+        m_requestCallback->sendSuccess();
+    }
+private:
+    ClearObjectStoreListener(PassRefPtr<ClearObjectStoreCallback> requestCallback)
+        : EventListener(EventListener::CPPEventListenerType)
+        , m_requestCallback(requestCallback)
+    {
+    }
+
+    RefPtr<ClearObjectStoreCallback> m_requestCallback;
+};
+
+
+class ClearObjectStore : public ExecutableWithDatabase {
+public:
+    static PassRefPtr<ClearObjectStore> create(ScriptExecutionContext* context, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback)
+    {
+        return adoptRef(new ClearObjectStore(context, objectStoreName, requestCallback));
+    }
+
+    ClearObjectStore(ScriptExecutionContext* context, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback)
+        : ExecutableWithDatabase(context)
+        , m_objectStoreName(objectStoreName)
+        , m_requestCallback(requestCallback)
+    {
+    }
+
+    virtual void execute(PassRefPtr<IDBDatabase> prpDatabase)
+    {
+        RefPtr<IDBDatabase> idbDatabase = prpDatabase;
+        if (!requestCallback()->isActive())
+            return;
+        RefPtr<IDBTransaction> idbTransaction = transactionForDatabase(context(), idbDatabase.get(), m_objectStoreName, IDBTransaction::modeReadWrite());
+        if (!idbTransaction) {
+            m_requestCallback->sendFailure("Could not get transaction");
+            return;
+        }
+        RefPtr<IDBObjectStore> idbObjectStore = objectStoreForTransaction(idbTransaction.get(), m_objectStoreName);
+        if (!idbObjectStore) {
+            m_requestCallback->sendFailure("Could not get object store");
+            return;
+        }
+
+        ExceptionCode ec = 0;
+        RefPtr<IDBRequest> idbRequest = idbObjectStore->clear(context(), ec);
+        ASSERT(!ec);
+        if (ec) {
+            m_requestCallback->sendFailure(String::format("Could not clear object store '%s': %d", m_objectStoreName.utf8().data(), ec));
+            return;
+        }
+        idbTransaction->addEventListener(eventNames().completeEvent, ClearObjectStoreListener::create(m_requestCallback), false);
+    }
+
+    virtual RequestCallback* requestCallback() { return m_requestCallback.get(); }
+private:
+    const String m_objectStoreName;
+    RefPtr<ClearObjectStoreCallback> m_requestCallback;
+};
+
+void InspectorIndexedDBAgent::clearObjectStore(ErrorString* errorString, const String& securityOrigin, const String& databaseName, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback)
+{
+    Frame* frame = m_pageAgent->findFrameWithSecurityOrigin(securityOrigin);
+    Document* document = assertDocument(errorString, frame);
+    if (!document)
+        return;
+    IDBFactory* idbFactory = assertIDBFactory(errorString, document);
+    if (!idbFactory)
+        return;
+
+    // FIXME: This should probably use ScriptState/ScriptScope instead of V8 API
+    v8::HandleScope handleScope;
+    v8::Handle<v8::Context> context = document->frame()->script()->mainWorldContext();
+    ASSERT(!context.IsEmpty());
+    v8::Context::Scope contextScope(context);
+
+    RefPtr<ClearObjectStore> clearObjectStore = ClearObjectStore::create(document, objectStoreName, requestCallback);
+    clearObjectStore->start(idbFactory, document->securityOrigin(), databaseName);
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/InspectorIndexedDBAgent.h b/Source/core/inspector/InspectorIndexedDBAgent.h
new file mode 100644
index 0000000..259b2a7
--- /dev/null
+++ b/Source/core/inspector/InspectorIndexedDBAgent.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#ifndef InspectorIndexedDBAgent_h
+#define InspectorIndexedDBAgent_h
+
+#include "core/inspector/InspectorBaseAgent.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class InjectedScriptManager;
+class InspectorPageAgent;
+
+typedef String ErrorString;
+
+class InspectorIndexedDBAgent : public InspectorBaseAgent<InspectorIndexedDBAgent>, public InspectorBackendDispatcher::IndexedDBCommandHandler {
+public:
+    static PassOwnPtr<InspectorIndexedDBAgent> create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager, InspectorPageAgent* pageAgent)
+    {
+        return adoptPtr(new InspectorIndexedDBAgent(instrumentingAgents, state, injectedScriptManager, pageAgent));
+    }
+    ~InspectorIndexedDBAgent();
+
+    virtual void clearFrontend();
+    virtual void restore();
+
+    // Called from the front-end.
+    virtual void enable(ErrorString*);
+    virtual void disable(ErrorString*);
+    virtual void requestDatabaseNames(ErrorString*, const String& securityOrigin, PassRefPtr<RequestDatabaseNamesCallback>);
+    virtual void requestDatabase(ErrorString*, const String& securityOrigin, const String& databaseName, PassRefPtr<RequestDatabaseCallback>);
+    virtual void requestData(ErrorString*, const String& securityOrigin, const String& databaseName, const String& objectStoreName, const String& indexName, int skipCount, int pageSize, const RefPtr<InspectorObject>* keyRange, PassRefPtr<RequestDataCallback>);
+    virtual void clearObjectStore(ErrorString*, const String& in_securityOrigin, const String& in_databaseName, const String& in_objectStoreName, PassRefPtr<ClearObjectStoreCallback>);
+
+private:
+    InspectorIndexedDBAgent(InstrumentingAgents*, InspectorCompositeState*, InjectedScriptManager*, InspectorPageAgent*);
+
+    InjectedScriptManager* m_injectedScriptManager;
+    InspectorPageAgent* m_pageAgent;
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorIndexedDBAgent_h)
diff --git a/Source/core/inspector/InspectorInputAgent.cpp b/Source/core/inspector/InspectorInputAgent.cpp
new file mode 100644
index 0000000..0292338
--- /dev/null
+++ b/Source/core/inspector/InspectorInputAgent.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorInputAgent.h"
+
+#include "core/page/Chrome.h"
+#include "core/page/EventHandler.h"
+#include "core/page/FocusController.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/platform/PlatformEvent.h"
+#include "core/platform/PlatformKeyboardEvent.h"
+#include "core/platform/PlatformMouseEvent.h"
+#include "core/platform/graphics/IntPoint.h"
+#include "core/platform/graphics/IntRect.h"
+#include "core/platform/graphics/IntSize.h"
+
+#include <wtf/CurrentTime.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+InspectorInputAgent::InspectorInputAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, Page* page)
+    : InspectorBaseAgent<InspectorInputAgent>("Input", instrumentingAgents, inspectorState)
+    , m_page(page)
+{
+}
+
+InspectorInputAgent::~InspectorInputAgent()
+{
+}
+
+void InspectorInputAgent::dispatchKeyEvent(ErrorString* error, const String& type, const int* modifiers, const double* timestamp, const String* text, const String* unmodifiedText, const String* keyIdentifier, const int* windowsVirtualKeyCode, const int* nativeVirtualKeyCode, const int* macCharCode, const bool* autoRepeat, const bool* isKeypad, const bool* isSystemKey)
+{
+    PlatformEvent::Type convertedType;
+    if (type == "keyDown")
+        convertedType = PlatformEvent::KeyDown;
+    else if (type == "keyUp")
+        convertedType = PlatformEvent::KeyUp;
+    else if (type == "char")
+        convertedType = PlatformEvent::Char;
+    else if (type == "rawKeyDown")
+        convertedType = PlatformEvent::RawKeyDown;
+    else {
+        *error = "Unrecognized type: " + type;
+        return;
+    }
+
+    PlatformKeyboardEvent event(
+        convertedType,
+        text ? *text : "",
+        unmodifiedText ? *unmodifiedText : "",
+        keyIdentifier ? *keyIdentifier : "",
+        windowsVirtualKeyCode ? *windowsVirtualKeyCode : 0,
+        nativeVirtualKeyCode ? *nativeVirtualKeyCode : 0,
+        macCharCode ? *macCharCode : 0,
+        autoRepeat ? *autoRepeat : false,
+        isKeypad ? *isKeypad : false,
+        isSystemKey ? *isSystemKey : false,
+        static_cast<PlatformEvent::Modifiers>(modifiers ? *modifiers : 0),
+        timestamp ? *timestamp : currentTime());
+    m_page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(event);
+}
+
+void InspectorInputAgent::dispatchMouseEvent(ErrorString* error, const String& type, int x, int y, const int* modifiers, const double* timestamp, const String* button, const int* clickCount)
+{
+    PlatformEvent::Type convertedType;
+    if (type == "mousePressed")
+        convertedType = PlatformEvent::MousePressed;
+    else if (type == "mouseReleased")
+        convertedType = PlatformEvent::MouseReleased;
+    else if (type == "mouseMoved")
+        convertedType = PlatformEvent::MouseMoved;
+    else {
+        *error = "Unrecognized type: " + type;
+        return;
+    }
+
+    int convertedModifiers = modifiers ? *modifiers : 0;
+
+    MouseButton convertedButton = NoButton;
+    if (button) {
+        if (*button == "left")
+            convertedButton = LeftButton;
+        else if (*button == "middle")
+            convertedButton = MiddleButton;
+        else if (*button == "right")
+            convertedButton = RightButton;
+        else if (*button != "none") {
+            *error = "Unrecognized button: " + *button;
+            return;
+        }
+    }
+
+    // Some platforms may have flipped coordinate systems, but the given coordinates
+    // assume the origin is in the top-left of the window. Convert.
+    IntPoint convertedPoint = m_page->mainFrame()->view()->convertToContainingWindow(IntPoint(x, y));
+    IntPoint globalPoint = m_page->chrome()->rootViewToScreen(IntRect(IntPoint(x, y), IntSize(0, 0))).location();
+
+    PlatformMouseEvent event(
+        convertedPoint,
+        globalPoint,
+        convertedButton,
+        convertedType,
+        clickCount ? *clickCount : 0,
+        convertedModifiers & PlatformEvent::ShiftKey,
+        convertedModifiers & PlatformEvent::CtrlKey,
+        convertedModifiers & PlatformEvent::AltKey,
+        convertedModifiers & PlatformEvent::MetaKey,
+        timestamp ? *timestamp : currentTime());
+
+    EventHandler* handler = m_page->mainFrame()->eventHandler();
+    switch (convertedType) {
+    case PlatformEvent::MousePressed:
+        handler->handleMousePressEvent(event);
+        break;
+    case PlatformEvent::MouseReleased:
+        handler->handleMouseReleaseEvent(event);
+        break;
+    case PlatformEvent::MouseMoved:
+        handler->handleMouseMoveEvent(event);
+        break;
+    default:
+        *error = "Unhandled type: " + type;
+    }
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorInputAgent.h b/Source/core/inspector/InspectorInputAgent.h
new file mode 100644
index 0000000..fbb5d36
--- /dev/null
+++ b/Source/core/inspector/InspectorInputAgent.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#ifndef InspectorInputAgent_h
+#define InspectorInputAgent_h
+
+
+#include "core/inspector/InspectorBaseAgent.h"
+
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+class InspectorState;
+class Page;
+
+typedef String ErrorString;
+
+class InspectorInputAgent : public InspectorBaseAgent<InspectorInputAgent>, public InspectorBackendDispatcher::InputCommandHandler {
+    WTF_MAKE_NONCOPYABLE(InspectorInputAgent);
+public:
+    static PassOwnPtr<InspectorInputAgent> create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, Page* page)
+    {
+        return adoptPtr(new InspectorInputAgent(instrumentingAgents, inspectorState, page));
+    }
+
+    ~InspectorInputAgent();
+
+    // Methods called from the frontend for simulating input.
+    virtual void dispatchKeyEvent(ErrorString*, const String& type, const int* modifiers, const double* timestamp, const String* text, const String* unmodifiedText, const String* keyIdentifier, const int* windowsVirtualKeyCode, const int* nativeVirtualKeyCode, const int* macCharCode, const bool* autoRepeat, const bool* isKeypad, const bool* isSystemKey);
+    virtual void dispatchMouseEvent(ErrorString*, const String& type, int x, int y, const int* modifiers, const double* timestamp, const String* button, const int* clickCount);
+
+private:
+    InspectorInputAgent(InstrumentingAgents*, InspectorCompositeState*, Page*);
+
+    Page* m_page;
+};
+
+
+} // namespace WebCore
+
+#endif // !defined(InspectorInputAgent_h)
diff --git a/Source/core/inspector/InspectorInstrumentation.cpp b/Source/core/inspector/InspectorInstrumentation.cpp
new file mode 100644
index 0000000..79b3ffc
--- /dev/null
+++ b/Source/core/inspector/InspectorInstrumentation.cpp
@@ -0,0 +1,1328 @@
+/*
+* Copyright (C) 2011 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.
+*/
+
+#include "config.h"
+#include "core/inspector/InspectorInstrumentation.h"
+
+#include "bindings/v8/DOMWrapperWorld.h"
+#include "bindings/v8/ScriptController.h"
+#include "core/css/CSSRule.h"
+#include "core/css/CSSStyleRule.h"
+#include "core/css/StyleResolver.h"
+#include "core/css/StyleRule.h"
+#include "core/dom/DeviceOrientationData.h"
+#include "core/dom/Event.h"
+#include "core/dom/EventContext.h"
+#include "core/inspector/ConsoleAPITypes.h"
+#include "core/inspector/InspectorAgent.h"
+#include "core/inspector/InspectorApplicationCacheAgent.h"
+#include "core/inspector/InspectorCSSAgent.h"
+#include "core/inspector/InspectorCanvasAgent.h"
+#include "core/inspector/InspectorConsoleAgent.h"
+#include "core/inspector/InspectorController.h"
+#include "core/inspector/InspectorDOMAgent.h"
+#include "core/inspector/InspectorDOMDebuggerAgent.h"
+#include "core/inspector/InspectorDOMStorageAgent.h"
+#include "core/inspector/InspectorDatabaseAgent.h"
+#include "core/inspector/InspectorDebuggerAgent.h"
+#include "core/inspector/InspectorHeapProfilerAgent.h"
+#include "core/inspector/InspectorLayerTreeAgent.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InspectorProfilerAgent.h"
+#include "core/inspector/InspectorResourceAgent.h"
+#include "core/inspector/InspectorTimelineAgent.h"
+#include "core/inspector/InspectorWorkerAgent.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/inspector/PageDebuggerAgent.h"
+#include "core/inspector/PageRuntimeAgent.h"
+#include "core/inspector/ScriptArguments.h"
+#include "core/inspector/ScriptCallStack.h"
+#include "core/inspector/ScriptProfile.h"
+#include "core/inspector/WorkerInspectorController.h"
+#include "core/inspector/WorkerRuntimeAgent.h"
+#include "core/loader/DocumentLoader.h"
+#include "core/page/ConsoleTypes.h"
+#include "core/page/DOMWindow.h"
+#include "core/rendering/RenderObject.h"
+#include "core/workers/WorkerContext.h"
+#include "core/workers/WorkerThread.h"
+#include "core/xml/XMLHttpRequest.h"
+#include "modules/webdatabase/Database.h"
+#include <wtf/StdLibExtras.h>
+#include <wtf/text/CString.h>
+
+#include "core/platform/chromium/TraceEvent.h"
+
+namespace WebCore {
+
+static const char* const requestAnimationFrameEventName = "requestAnimationFrame";
+static const char* const cancelAnimationFrameEventName = "cancelAnimationFrame";
+static const char* const animationFrameFiredEventName = "animationFrameFired";
+static const char* const setTimerEventName = "setTimer";
+static const char* const clearTimerEventName = "clearTimer";
+static const char* const timerFiredEventName = "timerFired";
+
+namespace {
+static HashSet<InstrumentingAgents*>* instrumentingAgentsSet = 0;
+}
+
+namespace InspectorInstrumentation {
+int FrontendCounter::s_frontendCounter = 0;
+}
+
+InspectorInstrumentationCookie::InspectorInstrumentationCookie()
+    : m_instrumentingAgents(0)
+    , m_timelineAgentId(0)
+{
+}
+
+InspectorInstrumentationCookie::InspectorInstrumentationCookie(InstrumentingAgents* agents, int timelineAgentId)
+    : m_instrumentingAgents(agents)
+    , m_timelineAgentId(timelineAgentId)
+{
+}
+
+InspectorInstrumentationCookie::InspectorInstrumentationCookie(const InspectorInstrumentationCookie& other)
+    : m_instrumentingAgents(other.m_instrumentingAgents)
+    , m_timelineAgentId(other.m_timelineAgentId)
+{
+}
+
+InspectorInstrumentationCookie& InspectorInstrumentationCookie::operator=(const InspectorInstrumentationCookie& other)
+{
+    if (this != &other) {
+        m_instrumentingAgents = other.m_instrumentingAgents;
+        m_timelineAgentId = other.m_timelineAgentId;
+    }
+    return *this;
+}
+
+InspectorInstrumentationCookie::~InspectorInstrumentationCookie()
+{
+}
+
+namespace InspectorInstrumentation {
+
+void pauseOnNativeEventIfNeeded(InstrumentingAgents*, bool isDOMEvent, const String& eventName, bool synchronous);
+
+void cancelPauseOnNativeEvent(InstrumentingAgents*);
+
+InspectorTimelineAgent* retrieveTimelineAgent(const InspectorInstrumentationCookie&);
+
+void didClearWindowObjectInWorldImpl(InstrumentingAgents* instrumentingAgents, Frame* frame, DOMWrapperWorld* world)
+{
+    InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent();
+    if (pageAgent)
+        pageAgent->didClearWindowObjectInWorld(frame, world);
+    if (InspectorAgent* inspectorAgent = instrumentingAgents->inspectorAgent())
+        inspectorAgent->didClearWindowObjectInWorld(frame, world);
+    if (PageDebuggerAgent* debuggerAgent = instrumentingAgents->pageDebuggerAgent()) {
+        if (pageAgent && world == mainThreadNormalWorld() && frame == pageAgent->mainFrame())
+            debuggerAgent->didClearMainFrameWindowObject();
+    }
+    if (PageRuntimeAgent* pageRuntimeAgent = instrumentingAgents->pageRuntimeAgent()) {
+        if (world == mainThreadNormalWorld())
+            pageRuntimeAgent->didCreateMainWorldContext(frame);
+    }
+}
+
+bool isDebuggerPausedImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents->inspectorDebuggerAgent())
+        return debuggerAgent->isPaused();
+    return false;
+}
+
+void willInsertDOMNodeImpl(InstrumentingAgents* instrumentingAgents, Node* parent)
+{
+    if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents->inspectorDOMDebuggerAgent())
+        domDebuggerAgent->willInsertDOMNode(parent);
+}
+
+void didInsertDOMNodeImpl(InstrumentingAgents* instrumentingAgents, Node* node)
+{
+    if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+        domAgent->didInsertDOMNode(node);
+    if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents->inspectorDOMDebuggerAgent())
+        domDebuggerAgent->didInsertDOMNode(node);
+}
+
+void willRemoveDOMNodeImpl(InstrumentingAgents* instrumentingAgents, Node* node)
+{
+    if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents->inspectorDOMDebuggerAgent())
+        domDebuggerAgent->willRemoveDOMNode(node);
+}
+
+void didRemoveDOMNodeImpl(InstrumentingAgents* instrumentingAgents, Node* node)
+{
+    if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents->inspectorDOMDebuggerAgent())
+        domDebuggerAgent->didRemoveDOMNode(node);
+    if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+        domAgent->didRemoveDOMNode(node);
+}
+
+void willModifyDOMAttrImpl(InstrumentingAgents* instrumentingAgents, Element* element, const AtomicString& oldValue, const AtomicString& newValue)
+{
+    if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents->inspectorDOMDebuggerAgent())
+        domDebuggerAgent->willModifyDOMAttr(element, oldValue, newValue);
+    if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+        domAgent->willModifyDOMAttr(element, oldValue, newValue);
+}
+
+void didModifyDOMAttrImpl(InstrumentingAgents* instrumentingAgents, Element* element, const AtomicString& name, const AtomicString& value)
+{
+    if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+        domAgent->didModifyDOMAttr(element, name, value);
+}
+
+void didRemoveDOMAttrImpl(InstrumentingAgents* instrumentingAgents, Element* element, const AtomicString& name)
+{
+    if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+        domAgent->didRemoveDOMAttr(element, name);
+}
+
+void didInvalidateStyleAttrImpl(InstrumentingAgents* instrumentingAgents, Node* node)
+{
+    if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+        domAgent->didInvalidateStyleAttr(node);
+    if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents->inspectorDOMDebuggerAgent())
+        domDebuggerAgent->didInvalidateStyleAttr(node);
+}
+
+void activeStyleSheetsUpdatedImpl(InstrumentingAgents* instrumentingAgents, const Vector<RefPtr<StyleSheet> >& newSheets)
+{
+    if (InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent())
+        cssAgent->activeStyleSheetsUpdated(newSheets);
+}
+
+void frameWindowDiscardedImpl(InstrumentingAgents* instrumentingAgents, DOMWindow* window)
+{
+    if (InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent())
+        consoleAgent->frameWindowDiscarded(window);
+}
+
+void mediaQueryResultChangedImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent())
+        cssAgent->mediaQueryResultChanged();
+}
+
+void didPushShadowRootImpl(InstrumentingAgents* instrumentingAgents, Element* host, ShadowRoot* root)
+{
+    if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+        domAgent->didPushShadowRoot(host, root);
+}
+
+void willPopShadowRootImpl(InstrumentingAgents* instrumentingAgents, Element* host, ShadowRoot* root)
+{
+    if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+        domAgent->willPopShadowRoot(host, root);
+}
+
+void didCreateNamedFlowImpl(InstrumentingAgents* instrumentingAgents, Document* document, NamedFlow* namedFlow)
+{
+    if (InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent())
+        cssAgent->didCreateNamedFlow(document, namedFlow);
+}
+
+void willRemoveNamedFlowImpl(InstrumentingAgents* instrumentingAgents, Document* document, NamedFlow* namedFlow)
+{
+    if (InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent())
+        cssAgent->willRemoveNamedFlow(document, namedFlow);
+}
+
+void didUpdateRegionLayoutImpl(InstrumentingAgents* instrumentingAgents, Document* document, NamedFlow* namedFlow)
+{
+    if (InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent())
+        cssAgent->didUpdateRegionLayout(document, namedFlow);
+}
+
+void didScrollImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        pageAgent->didScroll();
+}
+
+void didResizeMainFrameImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        pageAgent->didResizeMainFrame();
+}
+
+bool forcePseudoStateImpl(InstrumentingAgents* instrumentingAgents, Element* element, CSSSelector::PseudoType pseudoState)
+{
+    if (InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent())
+        return cssAgent->forcePseudoState(element, pseudoState);
+    return false;
+}
+
+void characterDataModifiedImpl(InstrumentingAgents* instrumentingAgents, CharacterData* characterData)
+{
+    if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+        domAgent->characterDataModified(characterData);
+}
+
+void willSendXMLHttpRequestImpl(InstrumentingAgents* instrumentingAgents, const String& url)
+{
+    if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents->inspectorDOMDebuggerAgent())
+        domDebuggerAgent->willSendXMLHttpRequest(url);
+}
+
+void didScheduleResourceRequestImpl(InstrumentingAgents* instrumentingAgents, Document* document, const String& url)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didScheduleResourceRequest(document, url);
+}
+
+void didInstallTimerImpl(InstrumentingAgents* instrumentingAgents, ScriptExecutionContext* context, int timerId, int timeout, bool singleShot)
+{
+    pauseOnNativeEventIfNeeded(instrumentingAgents, false, setTimerEventName, true);
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didInstallTimer(context, timerId, timeout, singleShot);
+}
+
+void didRemoveTimerImpl(InstrumentingAgents* instrumentingAgents, ScriptExecutionContext* context, int timerId)
+{
+    pauseOnNativeEventIfNeeded(instrumentingAgents, false, clearTimerEventName, true);
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didRemoveTimer(context, timerId);
+}
+
+InspectorInstrumentationCookie willCallFunctionImpl(InstrumentingAgents* instrumentingAgents, ScriptExecutionContext* context, const String& scriptName, int scriptLine)
+{
+    int timelineAgentId = 0;
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent()) {
+        if (timelineAgent->willCallFunction(context, scriptName, scriptLine))
+            timelineAgentId = timelineAgent->id();
+    }
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+void didCallFunctionImpl(const InspectorInstrumentationCookie& cookie)
+{
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didCallFunction();
+}
+
+InspectorInstrumentationCookie willDispatchXHRReadyStateChangeEventImpl(InstrumentingAgents* instrumentingAgents, ScriptExecutionContext* context, XMLHttpRequest* request)
+{
+    int timelineAgentId = 0;
+    InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent();
+    if (timelineAgent) {
+        if (timelineAgent->willDispatchXHRReadyStateChangeEvent(context, request))
+            timelineAgentId = timelineAgent->id();
+    }
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+void didDispatchXHRReadyStateChangeEventImpl(const InspectorInstrumentationCookie& cookie)
+{
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didDispatchXHRReadyStateChangeEvent();
+}
+
+InspectorInstrumentationCookie willDispatchEventImpl(InstrumentingAgents* instrumentingAgents, Document* document, const Event& event, DOMWindow* window, Node* node, const EventPath& eventPath)
+{
+    int timelineAgentId = 0;
+    InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent();
+    if (timelineAgent) {
+        if (timelineAgent->willDispatchEvent(document, event, window, node, eventPath))
+            timelineAgentId = timelineAgent->id();
+    }
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+InspectorInstrumentationCookie willHandleEventImpl(InstrumentingAgents* instrumentingAgents, Event* event)
+{
+    pauseOnNativeEventIfNeeded(instrumentingAgents, true, event->type(), false);
+    return InspectorInstrumentationCookie(instrumentingAgents, 0);
+}
+
+void didHandleEventImpl(const InspectorInstrumentationCookie& cookie)
+{
+    cancelPauseOnNativeEvent(cookie.instrumentingAgents());
+}
+
+void didDispatchEventImpl(const InspectorInstrumentationCookie& cookie)
+{
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didDispatchEvent();
+}
+
+InspectorInstrumentationCookie willDispatchEventOnWindowImpl(InstrumentingAgents* instrumentingAgents, const Event& event, DOMWindow* window)
+{
+    int timelineAgentId = 0;
+    InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent();
+    if (timelineAgent) {
+        if (timelineAgent->willDispatchEventOnWindow(event, window))
+            timelineAgentId = timelineAgent->id();
+    }
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+void didDispatchEventOnWindowImpl(const InspectorInstrumentationCookie& cookie)
+{
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didDispatchEvent();
+}
+
+InspectorInstrumentationCookie willEvaluateScriptImpl(InstrumentingAgents* instrumentingAgents, Frame* frame, const String& url, int lineNumber)
+{
+    int timelineAgentId = 0;
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent()) {
+        if (timelineAgent->willEvaluateScript(frame, url, lineNumber))
+            timelineAgentId = timelineAgent->id();
+    }
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+void didEvaluateScriptImpl(const InspectorInstrumentationCookie& cookie)
+{
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didEvaluateScript();
+}
+
+void scriptsEnabledImpl(InstrumentingAgents* instrumentingAgents, bool isEnabled)
+{
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        pageAgent->scriptsEnabled(isEnabled);
+}
+
+void didCreateIsolatedContextImpl(InstrumentingAgents* instrumentingAgents, Frame* frame, ScriptState* scriptState, SecurityOrigin* origin)
+{
+    if (PageRuntimeAgent* runtimeAgent = instrumentingAgents->pageRuntimeAgent())
+        runtimeAgent->didCreateIsolatedContext(frame, scriptState, origin);
+}
+
+InspectorInstrumentationCookie willFireTimerImpl(InstrumentingAgents* instrumentingAgents, ScriptExecutionContext* context, int timerId)
+{
+    pauseOnNativeEventIfNeeded(instrumentingAgents, false, timerFiredEventName, false);
+
+    int timelineAgentId = 0;
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent()) {
+        if (timelineAgent->willFireTimer(context, timerId))
+            timelineAgentId = timelineAgent->id();
+    }
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+void didFireTimerImpl(const InspectorInstrumentationCookie& cookie)
+{
+    cancelPauseOnNativeEvent(cookie.instrumentingAgents());
+
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didFireTimer();
+}
+
+void didInvalidateLayoutImpl(InstrumentingAgents* instrumentingAgents, Frame* frame)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didInvalidateLayout(frame);
+}
+
+InspectorInstrumentationCookie willLayoutImpl(InstrumentingAgents* instrumentingAgents, Frame* frame)
+{
+    int timelineAgentId = 0;
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent()) {
+        if (timelineAgent->willLayout(frame))
+            timelineAgentId = timelineAgent->id();
+    }
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+void didLayoutImpl(const InspectorInstrumentationCookie& cookie, RenderObject* root)
+{
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didLayout(root);
+
+    if (InspectorPageAgent* pageAgent = cookie.instrumentingAgents()->inspectorPageAgent())
+        pageAgent->didLayout(root);
+}
+
+InspectorInstrumentationCookie willDispatchXHRLoadEventImpl(InstrumentingAgents* instrumentingAgents, ScriptExecutionContext* context, XMLHttpRequest* request)
+{
+    int timelineAgentId = 0;
+    InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent();
+    if (timelineAgent) {
+        if (timelineAgent->willDispatchXHRLoadEvent(context, request))
+            timelineAgentId = timelineAgent->id();
+    }
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+void didDispatchXHRLoadEventImpl(const InspectorInstrumentationCookie& cookie)
+{
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didDispatchXHRLoadEvent();
+}
+
+void willPaintImpl(InstrumentingAgents* instrumentingAgents, RenderObject* renderer)
+{
+    TRACE_EVENT_INSTANT1("instrumentation", InstrumentationEvents::Paint, InstrumentationEventArguments::PageId, reinterpret_cast<unsigned long long>(renderer->frame()->page()));
+
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->willPaint(renderer->frame());
+}
+
+void didPaintImpl(InstrumentingAgents* instrumentingAgents, RenderObject* renderer, GraphicsContext* context, const LayoutRect& rect)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didPaint(renderer, context, rect);
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        pageAgent->didPaint(renderer, context, rect);
+}
+
+void willScrollLayerImpl(InstrumentingAgents* instrumentingAgents, Frame* frame)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->willScrollLayer(frame);
+}
+
+void didScrollLayerImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didScrollLayer();
+}
+
+InspectorInstrumentationCookie willRecalculateStyleImpl(InstrumentingAgents* instrumentingAgents, Document* document)
+{
+    int timelineAgentId = 0;
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent()) {
+        if (timelineAgent->willRecalculateStyle(document))
+            timelineAgentId = timelineAgent->id();
+    }
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->willRecalculateStyle(document);
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+void didRecalculateStyleImpl(const InspectorInstrumentationCookie& cookie)
+{
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didRecalculateStyle();
+    InstrumentingAgents* instrumentingAgents = cookie.instrumentingAgents();
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didRecalculateStyle();
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        pageAgent->didRecalculateStyle();
+}
+
+void didRecalculateStyleForElementImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didRecalculateStyleForElement();
+}
+
+void didScheduleStyleRecalculationImpl(InstrumentingAgents* instrumentingAgents, Document* document)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didScheduleStyleRecalculation(document);
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didScheduleStyleRecalculation(document);
+}
+
+InspectorInstrumentationCookie willMatchRuleImpl(InstrumentingAgents* instrumentingAgents, StyleRule* rule, InspectorCSSOMWrappers& inspectorCSSOMWrappers, DocumentStyleSheetCollection* sheetCollection)
+{
+    InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent();
+    if (cssAgent) {
+        cssAgent->willMatchRule(rule, inspectorCSSOMWrappers, sheetCollection);
+        return InspectorInstrumentationCookie(instrumentingAgents, 1);
+    }
+
+    return InspectorInstrumentationCookie();
+}
+
+void didMatchRuleImpl(const InspectorInstrumentationCookie& cookie, bool matched)
+{
+    InspectorCSSAgent* cssAgent = cookie.instrumentingAgents()->inspectorCSSAgent();
+    if (cssAgent)
+        cssAgent->didMatchRule(matched);
+}
+
+InspectorInstrumentationCookie willProcessRuleImpl(InstrumentingAgents* instrumentingAgents, StyleRule* rule, StyleResolver* styleResolver)
+{
+    InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent();
+    if (cssAgent) {
+        cssAgent->willProcessRule(rule, styleResolver);
+        return InspectorInstrumentationCookie(instrumentingAgents, 1);
+    }
+
+    return InspectorInstrumentationCookie();
+}
+
+void didProcessRuleImpl(const InspectorInstrumentationCookie& cookie)
+{
+    InspectorCSSAgent* cssAgent = cookie.instrumentingAgents()->inspectorCSSAgent();
+    if (cssAgent)
+        cssAgent->didProcessRule();
+}
+
+void applyUserAgentOverrideImpl(InstrumentingAgents* instrumentingAgents, String* userAgent)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->applyUserAgentOverride(userAgent);
+}
+
+void applyScreenWidthOverrideImpl(InstrumentingAgents* instrumentingAgents, long* width)
+{
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        pageAgent->applyScreenWidthOverride(width);
+}
+
+void applyScreenHeightOverrideImpl(InstrumentingAgents* instrumentingAgents, long* height)
+{
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        pageAgent->applyScreenHeightOverride(height);
+}
+
+bool shouldApplyScreenWidthOverrideImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent()) {
+        long width = 0;
+        pageAgent->applyScreenWidthOverride(&width);
+        return !!width;
+    }
+    return false;
+}
+
+bool shouldApplyScreenHeightOverrideImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent()) {
+        long height = 0;
+        pageAgent->applyScreenHeightOverride(&height);
+        return !!height;
+    }
+    return false;
+}
+
+void applyEmulatedMediaImpl(InstrumentingAgents* instrumentingAgents, String* media)
+{
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        pageAgent->applyEmulatedMedia(media);
+}
+
+void willSendRequestImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->willSendResourceRequest(identifier, loader, request, redirectResponse);
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->willSendResourceRequest(identifier, loader, request, redirectResponse);
+}
+
+void continueAfterPingLoaderImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& response)
+{
+    willSendRequestImpl(instrumentingAgents, identifier, loader, request, response);
+}
+
+void markResourceAsCachedImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->markResourceAsCached(identifier);
+}
+
+void didLoadResourceFromMemoryCacheImpl(InstrumentingAgents* instrumentingAgents, DocumentLoader* loader, CachedResource* cachedResource)
+{
+    InspectorAgent* inspectorAgent = instrumentingAgents->inspectorAgent();
+    if (!inspectorAgent)
+        return;
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didLoadResourceFromMemoryCache(loader, cachedResource);
+}
+
+InspectorInstrumentationCookie willReceiveResourceDataImpl(InstrumentingAgents* instrumentingAgents, Frame* frame, unsigned long identifier, int length)
+{
+    int timelineAgentId = 0;
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent()) {
+        if (timelineAgent->willReceiveResourceData(frame, identifier, length))
+            timelineAgentId = timelineAgent->id();
+    }
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+void didReceiveResourceDataImpl(const InspectorInstrumentationCookie& cookie)
+{
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didReceiveResourceData();
+}
+
+InspectorInstrumentationCookie willReceiveResourceResponseImpl(InstrumentingAgents* instrumentingAgents, Frame* frame, unsigned long identifier, const ResourceResponse& response)
+{
+    int timelineAgentId = 0;
+    InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent();
+    if (timelineAgent) {
+        if (timelineAgent->willReceiveResourceResponse(frame, identifier, response))
+            timelineAgentId = timelineAgent->id();
+    }
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+void didReceiveResourceResponseImpl(const InspectorInstrumentationCookie& cookie, unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response, ResourceLoader* resourceLoader)
+{
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didReceiveResourceResponse(identifier, loader, response, resourceLoader);
+    if (InspectorResourceAgent* resourceAgent = cookie.instrumentingAgents()->inspectorResourceAgent())
+        resourceAgent->didReceiveResourceResponse(identifier, loader, response, resourceLoader);
+    if (InspectorConsoleAgent* consoleAgent = cookie.instrumentingAgents()->inspectorConsoleAgent())
+        consoleAgent->didReceiveResourceResponse(identifier, loader, response, resourceLoader); // This should come AFTER resource notification, front-end relies on this.
+}
+
+void didReceiveResourceResponseButCanceledImpl(Frame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
+{
+    InspectorInstrumentationCookie cookie = willReceiveResourceResponse(frame, identifier, r);
+    didReceiveResourceResponse(cookie, identifier, loader, r, 0);
+}
+
+void continueAfterXFrameOptionsDeniedImpl(Frame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
+{
+    didReceiveResourceResponseButCanceledImpl(frame, loader, identifier, r);
+}
+
+void continueWithPolicyDownloadImpl(Frame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
+{
+    didReceiveResourceResponseButCanceledImpl(frame, loader, identifier, r);
+}
+
+void continueWithPolicyIgnoreImpl(Frame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
+{
+    didReceiveResourceResponseButCanceledImpl(frame, loader, identifier, r);
+}
+
+void didReceiveDataImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier, const char* data, int dataLength, int encodedDataLength)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didReceiveData(identifier, data, dataLength, encodedDataLength);
+}
+
+void didFinishLoadingImpl(InstrumentingAgents* instrumentingAgents, DocumentLoader* loader, unsigned long identifier, double monotonicFinishTime)
+{
+    InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent();
+    InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent();
+    if (!timelineAgent && !resourceAgent)
+        return;
+
+    double finishTime = 0.0;
+    // FIXME: Expose all of the timing details to inspector and have it calculate finishTime.
+    if (monotonicFinishTime)
+        finishTime = loader->timing()->monotonicTimeToPseudoWallTime(monotonicFinishTime);
+
+    if (timelineAgent)
+        timelineAgent->didFinishLoadingResource(identifier, false, finishTime, loader->frame());
+    if (resourceAgent)
+        resourceAgent->didFinishLoading(identifier, loader, finishTime);
+}
+
+void didFailLoadingImpl(InstrumentingAgents* instrumentingAgents, DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didFailLoading(identifier, loader, error);
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didFailLoading(identifier, loader, error);
+    if (InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent())
+        consoleAgent->didFailLoading(identifier, loader, error); // This should come AFTER resource notification, front-end relies on this.
+}
+
+void documentThreadableLoaderStartedLoadingForClientImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier, ThreadableLoaderClient* client)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->documentThreadableLoaderStartedLoadingForClient(identifier, client);
+}
+
+void willLoadXHRImpl(InstrumentingAgents* instrumentingAgents, ThreadableLoaderClient* client, const String& method, const KURL& url, bool async, PassRefPtr<FormData> formData, const HTTPHeaderMap& headers, bool includeCredentials)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->willLoadXHR(client, method, url, async, formData, headers, includeCredentials);
+}
+
+void didFailXHRLoadingImpl(InstrumentingAgents* instrumentingAgents, ThreadableLoaderClient* client)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didFailXHRLoading(client);
+}
+
+void didFinishXHRLoadingImpl(InstrumentingAgents* instrumentingAgents, ThreadableLoaderClient* client, unsigned long identifier, const String& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber)
+{
+    if (InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent())
+        consoleAgent->didFinishXHRLoading(client, identifier, sourceString, url, sendURL, sendLineNumber);
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didFinishXHRLoading(client, identifier, sourceString, url, sendURL, sendLineNumber);
+}
+
+void didReceiveXHRResponseImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didReceiveXHRResponse(identifier);
+}
+
+void willLoadXHRSynchronouslyImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->willLoadXHRSynchronously();
+}
+
+void didLoadXHRSynchronouslyImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didLoadXHRSynchronously();
+}
+
+void scriptImportedImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier, const String& sourceString)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->scriptImported(identifier, sourceString);
+}
+
+void scriptExecutionBlockedByCSPImpl(InstrumentingAgents* instrumentingAgents, const String& directiveText)
+{
+    if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents->inspectorDebuggerAgent())
+        debuggerAgent->scriptExecutionBlockedByCSP(directiveText);
+}
+
+void didReceiveScriptResponseImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didReceiveScriptResponse(identifier);
+}
+
+void domContentLoadedEventFiredImpl(InstrumentingAgents* instrumentingAgents, Frame* frame)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didMarkDOMContentEvent(frame);
+
+    if (frame->page()->mainFrame() != frame)
+        return;
+
+    if (InspectorAgent* inspectorAgent = instrumentingAgents->inspectorAgent())
+        inspectorAgent->domContentLoadedEventFired();
+
+    if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+        domAgent->mainFrameDOMContentLoaded();
+
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        pageAgent->domContentEventFired();
+}
+
+void loadEventFiredImpl(InstrumentingAgents* instrumentingAgents, Frame* frame)
+{
+    if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+        domAgent->loadEventFired(frame->document());
+
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didMarkLoadEvent(frame);
+
+    if (frame->page()->mainFrame() != frame)
+        return;
+
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        pageAgent->loadEventFired();
+}
+
+void frameDetachedFromParentImpl(InstrumentingAgents* instrumentingAgents, Frame* frame)
+{
+    if (InspectorCanvasAgent* canvasAgent = instrumentingAgents->inspectorCanvasAgent())
+        canvasAgent->frameDetachedFromParent(frame);
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        pageAgent->frameDetachedFromParent(frame);
+}
+
+void didCommitLoadImpl(InstrumentingAgents* instrumentingAgents, Frame* frame, DocumentLoader* loader)
+{
+    InspectorAgent* inspectorAgent = instrumentingAgents->inspectorAgent();
+    if (!inspectorAgent)
+        return;
+
+    Frame* mainFrame = frame->page()->mainFrame();
+    if (loader->frame() == mainFrame) {
+        if (InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent())
+            consoleAgent->reset();
+
+        if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+            resourceAgent->mainFrameNavigated(loader);
+        if (InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent())
+            cssAgent->reset();
+        if (InspectorDatabaseAgent* databaseAgent = instrumentingAgents->inspectorDatabaseAgent())
+            databaseAgent->clearResources();
+        if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+            domAgent->setDocument(mainFrame->document());
+        if (InspectorLayerTreeAgent* layerTreeAgent = instrumentingAgents->inspectorLayerTreeAgent())
+            layerTreeAgent->reset();
+        inspectorAgent->didCommitLoad();
+    }
+    if (InspectorCanvasAgent* canvasAgent = instrumentingAgents->inspectorCanvasAgent())
+        canvasAgent->frameNavigated(loader->frame());
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        pageAgent->frameNavigated(loader);
+}
+
+void frameDocumentUpdatedImpl(InstrumentingAgents* instrumentingAgents, Frame* frame)
+{
+    InspectorAgent* inspectorAgent = instrumentingAgents->inspectorAgent();
+    if (!inspectorAgent)
+        return;
+
+    if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent())
+        domAgent->frameDocumentUpdated(frame);
+}
+
+void loaderDetachedFromFrameImpl(InstrumentingAgents* instrumentingAgents, DocumentLoader* loader)
+{
+    if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents->inspectorPageAgent())
+        inspectorPageAgent->loaderDetachedFromFrame(loader);
+}
+
+void frameStartedLoadingImpl(InstrumentingAgents* instrumentingAgents, Frame* frame)
+{
+    if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents->inspectorPageAgent())
+        inspectorPageAgent->frameStartedLoading(frame);
+}
+
+void frameStoppedLoadingImpl(InstrumentingAgents* instrumentingAgents, Frame* frame)
+{
+    if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents->inspectorPageAgent())
+        inspectorPageAgent->frameStoppedLoading(frame);
+}
+
+void frameScheduledNavigationImpl(InstrumentingAgents* instrumentingAgents, Frame* frame, double delay)
+{
+    if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents->inspectorPageAgent())
+        inspectorPageAgent->frameScheduledNavigation(frame, delay);
+}
+
+void frameClearedScheduledNavigationImpl(InstrumentingAgents* instrumentingAgents, Frame* frame)
+{
+    if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents->inspectorPageAgent())
+        inspectorPageAgent->frameClearedScheduledNavigation(frame);
+}
+
+InspectorInstrumentationCookie willRunJavaScriptDialogImpl(InstrumentingAgents* instrumentingAgents, const String& message)
+{
+    if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents->inspectorPageAgent())
+        inspectorPageAgent->willRunJavaScriptDialog(message);
+    return InspectorInstrumentationCookie(instrumentingAgents, 0);
+}
+
+void didRunJavaScriptDialogImpl(const InspectorInstrumentationCookie& cookie)
+{
+    if (InspectorPageAgent* inspectorPageAgent = cookie.instrumentingAgents()->inspectorPageAgent())
+        inspectorPageAgent->didRunJavaScriptDialog();
+}
+
+void willDestroyCachedResourceImpl(CachedResource* cachedResource)
+{
+    if (!instrumentingAgentsSet)
+        return;
+    HashSet<InstrumentingAgents*>::iterator end = instrumentingAgentsSet->end();
+    for (HashSet<InstrumentingAgents*>::iterator it = instrumentingAgentsSet->begin(); it != end; ++it) {
+        InstrumentingAgents* instrumentingAgents = *it;
+        if (InspectorResourceAgent* inspectorResourceAgent = instrumentingAgents->inspectorResourceAgent())
+            inspectorResourceAgent->willDestroyCachedResource(cachedResource);
+    }
+}
+
+InspectorInstrumentationCookie willWriteHTMLImpl(InstrumentingAgents* instrumentingAgents, Document* document, unsigned startLine)
+{
+    int timelineAgentId = 0;
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent()) {
+        if (timelineAgent->willWriteHTML(document, startLine))
+            timelineAgentId = timelineAgent->id();
+    }
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+void didWriteHTMLImpl(const InspectorInstrumentationCookie& cookie, unsigned endLine)
+{
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didWriteHTML(endLine);
+}
+
+// FIXME: Drop this once we no longer generate stacks outside of Inspector.
+void addMessageToConsoleImpl(InstrumentingAgents* instrumentingAgents, MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptCallStack> callStack, unsigned long requestIdentifier)
+{
+    if (InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent())
+        consoleAgent->addMessageToConsole(source, type, level, message, callStack, requestIdentifier);
+    if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents->inspectorDebuggerAgent())
+        debuggerAgent->addMessageToConsole(source, type);
+}
+
+void addMessageToConsoleImpl(InstrumentingAgents* instrumentingAgents, MessageSource source, MessageType type, MessageLevel level, const String& message, ScriptState* state, PassRefPtr<ScriptArguments> arguments, unsigned long requestIdentifier)
+{
+    if (InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent())
+        consoleAgent->addMessageToConsole(source, type, level, message, state, arguments, requestIdentifier);
+    if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents->inspectorDebuggerAgent())
+        debuggerAgent->addMessageToConsole(source, type);
+}
+
+void addMessageToConsoleImpl(InstrumentingAgents* instrumentingAgents, MessageSource source, MessageType type, MessageLevel level, const String& message, const String& scriptId, unsigned lineNumber, ScriptState* state, unsigned long requestIdentifier)
+{
+    if (InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent())
+        consoleAgent->addMessageToConsole(source, type, level, message, scriptId, lineNumber, state, requestIdentifier);
+}
+
+void consoleCountImpl(InstrumentingAgents* instrumentingAgents, ScriptState* state, PassRefPtr<ScriptArguments> arguments)
+{
+    if (InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent())
+        consoleAgent->count(state, arguments);
+}
+
+void startConsoleTimingImpl(InstrumentingAgents* instrumentingAgents, Frame* frame, const String& title)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->time(frame, title);
+    if (InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent())
+        consoleAgent->startTiming(title);
+}
+
+void stopConsoleTimingImpl(InstrumentingAgents* instrumentingAgents, Frame* frame, const String& title, PassRefPtr<ScriptCallStack> stack)
+{
+    if (InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent())
+        consoleAgent->stopTiming(title, stack);
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->timeEnd(frame, title);
+}
+
+void consoleTimeStampImpl(InstrumentingAgents* instrumentingAgents, Frame* frame, PassRefPtr<ScriptArguments> arguments)
+{
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent()) {
+        String message;
+        arguments->getFirstArgumentAsString(message);
+        timelineAgent->didTimeStamp(frame, message);
+     }
+}
+
+void addStartProfilingMessageToConsoleImpl(InstrumentingAgents* instrumentingAgents, const String& title, unsigned lineNumber, const String& sourceURL)
+{
+    if (InspectorProfilerAgent* profilerAgent = instrumentingAgents->inspectorProfilerAgent())
+        profilerAgent->addStartProfilingMessageToConsole(title, lineNumber, sourceURL);
+}
+
+void addProfileImpl(InstrumentingAgents* instrumentingAgents, RefPtr<ScriptProfile> profile, PassRefPtr<ScriptCallStack> callStack)
+{
+    if (InspectorProfilerAgent* profilerAgent = instrumentingAgents->inspectorProfilerAgent()) {
+        const ScriptCallFrame& lastCaller = callStack->at(0);
+        profilerAgent->addProfile(profile, lastCaller.lineNumber(), lastCaller.sourceURL());
+    }
+}
+
+String getCurrentUserInitiatedProfileNameImpl(InstrumentingAgents* instrumentingAgents, bool incrementProfileNumber)
+{
+    if (InspectorProfilerAgent* profilerAgent = instrumentingAgents->inspectorProfilerAgent())
+        return profilerAgent->getCurrentUserInitiatedProfileName(incrementProfileNumber);
+    return "";
+}
+
+bool profilerEnabledImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorProfilerAgent* profilerAgent = instrumentingAgents->inspectorProfilerAgent())
+        return profilerAgent->enabled();
+    return false;
+}
+
+void didOpenDatabaseImpl(InstrumentingAgents* instrumentingAgents, PassRefPtr<Database> database, const String& domain, const String& name, const String& version)
+{
+    InspectorAgent* inspectorAgent = instrumentingAgents->inspectorAgent();
+    if (!inspectorAgent)
+        return;
+    if (InspectorDatabaseAgent* dbAgent = instrumentingAgents->inspectorDatabaseAgent())
+        dbAgent->didOpenDatabase(database, domain, name, version);
+}
+
+void didDispatchDOMStorageEventImpl(InstrumentingAgents* instrumentingAgents, const String& key, const String& oldValue, const String& newValue, StorageType storageType, SecurityOrigin* securityOrigin, Page* page)
+{
+    if (InspectorDOMStorageAgent* domStorageAgent = instrumentingAgents->inspectorDOMStorageAgent())
+        domStorageAgent->didDispatchDOMStorageEvent(key, oldValue, newValue, storageType, securityOrigin, page);
+}
+
+bool shouldPauseDedicatedWorkerOnStartImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorWorkerAgent* workerAgent = instrumentingAgents->inspectorWorkerAgent())
+        return workerAgent->shouldPauseDedicatedWorkerOnStart();
+    return false;
+}
+
+void didStartWorkerContextImpl(InstrumentingAgents* instrumentingAgents, WorkerContextProxy* workerContextProxy, const KURL& url)
+{
+    if (InspectorWorkerAgent* workerAgent = instrumentingAgents->inspectorWorkerAgent())
+        workerAgent->didStartWorkerContext(workerContextProxy, url);
+}
+
+void willEvaluateWorkerScript(WorkerContext* workerContext, int workerThreadStartMode)
+{
+    if (workerThreadStartMode != PauseWorkerContextOnStart)
+        return;
+    InstrumentingAgents* instrumentingAgents = instrumentationForWorkerContext(workerContext);
+    if (!instrumentingAgents)
+        return;
+    if (WorkerRuntimeAgent* runtimeAgent = instrumentingAgents->workerRuntimeAgent())
+        runtimeAgent->pauseWorkerContext(workerContext);
+}
+
+void workerContextTerminatedImpl(InstrumentingAgents* instrumentingAgents, WorkerContextProxy* proxy)
+{
+    if (InspectorWorkerAgent* workerAgent = instrumentingAgents->inspectorWorkerAgent())
+        workerAgent->workerContextTerminated(proxy);
+}
+
+void didCreateWebSocketImpl(InstrumentingAgents* instrumentingAgents, Document* document, unsigned long identifier, const KURL& requestURL, const KURL&, const String& protocol)
+{
+    InspectorAgent* inspectorAgent = instrumentingAgents->inspectorAgent();
+    if (!inspectorAgent)
+        return;
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didCreateWebSocket(document, identifier, requestURL, protocol);
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didCreateWebSocket(document, identifier, requestURL, protocol);
+}
+
+void willSendWebSocketHandshakeRequestImpl(InstrumentingAgents* instrumentingAgents, Document* document, unsigned long identifier, const WebSocketHandshakeRequest& request)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->willSendWebSocketHandshakeRequest(document, identifier, request);
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->willSendWebSocketHandshakeRequest(document, identifier, request);
+}
+
+void didReceiveWebSocketHandshakeResponseImpl(InstrumentingAgents* instrumentingAgents, Document* document, unsigned long identifier, const WebSocketHandshakeResponse& response)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didReceiveWebSocketHandshakeResponse(document, identifier, response);
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didReceiveWebSocketHandshakeResponse(document, identifier, response);
+}
+
+void didCloseWebSocketImpl(InstrumentingAgents* instrumentingAgents, Document* document, unsigned long identifier)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didCloseWebSocket(document, identifier);
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didCloseWebSocket(document, identifier);
+}
+
+void didReceiveWebSocketFrameImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier, const WebSocketFrame& frame)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didReceiveWebSocketFrame(identifier, frame);
+}
+void didReceiveWebSocketFrameErrorImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier, const String& errorMessage)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didReceiveWebSocketFrameError(identifier, errorMessage);
+}
+void didSendWebSocketFrameImpl(InstrumentingAgents* instrumentingAgents, unsigned long identifier, const WebSocketFrame& frame)
+{
+    if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent())
+        resourceAgent->didSendWebSocketFrame(identifier, frame);
+}
+
+void networkStateChangedImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorApplicationCacheAgent* applicationCacheAgent = instrumentingAgents->inspectorApplicationCacheAgent())
+        applicationCacheAgent->networkStateChanged();
+}
+
+void updateApplicationCacheStatusImpl(InstrumentingAgents* instrumentingAgents, Frame* frame)
+{
+    if (InspectorApplicationCacheAgent* applicationCacheAgent = instrumentingAgents->inspectorApplicationCacheAgent())
+        applicationCacheAgent->updateApplicationCacheStatus(frame);
+}
+
+bool collectingHTMLParseErrorsImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorAgent* inspectorAgent = instrumentingAgents->inspectorAgent())
+        return inspectorAgent->hasFrontend();
+    return false;
+}
+
+bool canvasAgentEnabled(ScriptExecutionContext* scriptExecutionContext)
+{
+    InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(scriptExecutionContext);
+    return instrumentingAgents && instrumentingAgents->inspectorCanvasAgent();
+}
+
+bool consoleAgentEnabled(ScriptExecutionContext* scriptExecutionContext)
+{
+    InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(scriptExecutionContext);
+    InspectorConsoleAgent* consoleAgent = instrumentingAgents ? instrumentingAgents->inspectorConsoleAgent() : 0;
+    return consoleAgent && consoleAgent->enabled();
+}
+
+bool timelineAgentEnabled(ScriptExecutionContext* scriptExecutionContext)
+{
+    InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(scriptExecutionContext);
+    return instrumentingAgents && instrumentingAgents->inspectorTimelineAgent();
+}
+
+void pauseOnNativeEventIfNeeded(InstrumentingAgents* instrumentingAgents, bool isDOMEvent, const String& eventName, bool synchronous)
+{
+    if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents->inspectorDOMDebuggerAgent())
+        domDebuggerAgent->pauseOnNativeEventIfNeeded(isDOMEvent, eventName, synchronous);
+}
+
+void cancelPauseOnNativeEvent(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents->inspectorDebuggerAgent())
+        debuggerAgent->cancelPauseOnNextStatement();
+}
+
+void didRequestAnimationFrameImpl(InstrumentingAgents* instrumentingAgents, Document* document, int callbackId)
+{
+    pauseOnNativeEventIfNeeded(instrumentingAgents, false, requestAnimationFrameEventName, true);
+
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didRequestAnimationFrame(document, callbackId);
+}
+
+void didCancelAnimationFrameImpl(InstrumentingAgents* instrumentingAgents, Document* document, int callbackId)
+{
+    pauseOnNativeEventIfNeeded(instrumentingAgents, false, cancelAnimationFrameEventName, true);
+
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent())
+        timelineAgent->didCancelAnimationFrame(document, callbackId);
+}
+
+InspectorInstrumentationCookie willFireAnimationFrameImpl(InstrumentingAgents* instrumentingAgents, Document* document, int callbackId)
+{
+    pauseOnNativeEventIfNeeded(instrumentingAgents, false, animationFrameFiredEventName, false);
+
+    int timelineAgentId = 0;
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent()) {
+        if (timelineAgent->willFireAnimationFrame(document, callbackId))
+            timelineAgentId = timelineAgent->id();
+    }
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+void didFireAnimationFrameImpl(const InspectorInstrumentationCookie& cookie)
+{
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didFireAnimationFrame();
+}
+
+void registerInstrumentingAgents(InstrumentingAgents* instrumentingAgents)
+{
+    if (!instrumentingAgentsSet)
+        instrumentingAgentsSet = new HashSet<InstrumentingAgents*>();
+    instrumentingAgentsSet->add(instrumentingAgents);
+}
+
+void unregisterInstrumentingAgents(InstrumentingAgents* instrumentingAgents)
+{
+    if (!instrumentingAgentsSet)
+        return;
+    instrumentingAgentsSet->remove(instrumentingAgents);
+    if (instrumentingAgentsSet->isEmpty()) {
+        delete instrumentingAgentsSet;
+        instrumentingAgentsSet = 0;
+    }
+}
+
+InspectorTimelineAgent* retrieveTimelineAgent(const InspectorInstrumentationCookie& cookie)
+{
+    if (!cookie.instrumentingAgents())
+        return 0;
+    InspectorTimelineAgent* timelineAgent = cookie.instrumentingAgents()->inspectorTimelineAgent();
+    if (timelineAgent && cookie.hasMatchingTimelineAgentId(timelineAgent->id()))
+        return timelineAgent;
+    return 0;
+}
+
+InstrumentingAgents* instrumentingAgentsForPage(Page* page)
+{
+    if (!page)
+        return 0;
+    return instrumentationForPage(page);
+}
+
+InstrumentingAgents* instrumentingAgentsForRenderer(RenderObject* renderer)
+{
+    return instrumentingAgentsForFrame(renderer->frame());
+}
+
+InstrumentingAgents* instrumentingAgentsForWorkerContext(WorkerContext* workerContext)
+{
+    if (!workerContext)
+        return 0;
+    return instrumentationForWorkerContext(workerContext);
+}
+
+InstrumentingAgents* instrumentingAgentsForNonDocumentContext(ScriptExecutionContext* context)
+{
+    if (context->isWorkerContext())
+        return instrumentationForWorkerContext(static_cast<WorkerContext*>(context));
+    return 0;
+}
+
+GeolocationPosition* overrideGeolocationPositionImpl(InstrumentingAgents* instrumentingAgents, GeolocationPosition* position)
+{
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        position = pageAgent->overrideGeolocationPosition(position);
+    return position;
+}
+
+DeviceOrientationData* overrideDeviceOrientationImpl(InstrumentingAgents* instrumentingAgents, DeviceOrientationData* deviceOrientation)
+{
+    if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent())
+        deviceOrientation = pageAgent->overrideDeviceOrientation(deviceOrientation);
+    return deviceOrientation;
+}
+
+void layerTreeDidChangeImpl(InstrumentingAgents* instrumentingAgents)
+{
+    if (InspectorLayerTreeAgent* layerTreeAgent = instrumentingAgents->inspectorLayerTreeAgent())
+        layerTreeAgent->layerTreeDidChange();
+}
+
+void renderLayerDestroyedImpl(InstrumentingAgents* instrumentingAgents, const RenderLayer* renderLayer)
+{
+    if (InspectorLayerTreeAgent* layerTreeAgent = instrumentingAgents->inspectorLayerTreeAgent())
+        layerTreeAgent->renderLayerDestroyed(renderLayer);
+}
+
+void pseudoElementDestroyedImpl(InstrumentingAgents* instrumentingAgents, PseudoElement* pseudoElement)
+{
+    if (InspectorLayerTreeAgent* layerTreeAgent = instrumentingAgents->inspectorLayerTreeAgent())
+        layerTreeAgent->pseudoElementDestroyed(pseudoElement);
+}
+
+} // namespace InspectorInstrumentation
+
+namespace InstrumentationEvents {
+const char PaintLayer[] = "PaintLayer";
+const char RasterTask[] = "RasterTask";
+const char Paint[] = "Paint";
+const char Layer[] = "Layer";
+const char BeginFrame[] = "BeginFrame";
+};
+
+namespace InstrumentationEventArguments {
+const char LayerId[] = "layerId";
+const char PageId[] = "pageId";
+};
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorInstrumentation.h b/Source/core/inspector/InspectorInstrumentation.h
new file mode 100644
index 0000000..df4e588
--- /dev/null
+++ b/Source/core/inspector/InspectorInstrumentation.h
@@ -0,0 +1,206 @@
+/*
+* Copyright (C) 2010 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.
+*/
+
+#ifndef InspectorInstrumentation_h
+#define InspectorInstrumentation_h
+
+#include "bindings/v8/ScriptState.h"
+#include "core/css/CSSImportRule.h"
+#include "core/css/CSSRule.h"
+#include "core/css/CSSSelector.h"
+#include "core/css/CSSStyleSheet.h"
+#include "core/dom/Element.h"
+#include "core/dom/EventContext.h"
+#include "core/dom/ScriptExecutionContext.h"
+#include "core/inspector/ConsoleAPITypes.h"
+#include "core/page/ConsoleTypes.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/network/FormData.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/storage/StorageArea.h"
+#include "modules/websockets/WebSocketFrame.h"
+#include "modules/websockets/WebSocketHandshakeRequest.h"
+#include "modules/websockets/WebSocketHandshakeResponse.h"
+#include <wtf/RefPtr.h>
+#include <wtf/UnusedParam.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CSSRule;
+class CachedResource;
+class CharacterData;
+class DOMWindow;
+class DOMWrapperWorld;
+class Database;
+class Document;
+class Element;
+class EventContext;
+class DocumentLoader;
+class DocumentStyleSheetCollection;
+class DeviceOrientationData;
+class GeolocationPosition;
+class GraphicsContext;
+class InspectorCSSAgent;
+class InspectorCSSOMWrappers;
+class InspectorTimelineAgent;
+class InstrumentingAgents;
+class KURL;
+class Node;
+class PseudoElement;
+class RenderLayer;
+class RenderLayerBacking;
+class RenderObject;
+class ResourceRequest;
+class ResourceResponse;
+class ScriptArguments;
+class ScriptCallStack;
+class ScriptExecutionContext;
+class ScriptObject;
+class ScriptProfile;
+class SecurityOrigin;
+class ShadowRoot;
+class StorageArea;
+class StyleResolver;
+class StyleRule;
+class StyleSheet;
+class ThreadableLoaderClient;
+class WorkerContext;
+class WorkerContextProxy;
+class XMLHttpRequest;
+
+#define FAST_RETURN_IF_NO_FRONTENDS(value) if (!hasFrontends()) return value;
+
+class InspectorInstrumentationCookie {
+public:
+    InspectorInstrumentationCookie();
+    InspectorInstrumentationCookie(InstrumentingAgents*, int);
+    InspectorInstrumentationCookie(const InspectorInstrumentationCookie&);
+    InspectorInstrumentationCookie& operator=(const InspectorInstrumentationCookie&);
+    ~InspectorInstrumentationCookie();
+
+    InstrumentingAgents* instrumentingAgents() const { return m_instrumentingAgents.get(); }
+    bool isValid() const { return !!m_instrumentingAgents; }
+    bool hasMatchingTimelineAgentId(int id) const { return m_timelineAgentId == id; }
+
+private:
+    RefPtr<InstrumentingAgents> m_instrumentingAgents;
+    int m_timelineAgentId;
+};
+
+namespace InspectorInstrumentation {
+
+class FrontendCounter {
+private:
+    friend void frontendCreated();
+    friend void frontendDeleted();
+    friend bool hasFrontends();
+    static int s_frontendCounter;
+};
+
+inline void frontendCreated() { FrontendCounter::s_frontendCounter += 1; }
+inline void frontendDeleted() { FrontendCounter::s_frontendCounter -= 1; }
+inline bool hasFrontends() { return FrontendCounter::s_frontendCounter; }
+
+void registerInstrumentingAgents(InstrumentingAgents*);
+void unregisterInstrumentingAgents(InstrumentingAgents*);
+
+InstrumentingAgents* instrumentingAgentsForPage(Page*);
+InstrumentingAgents* instrumentingAgentsForFrame(Frame*);
+InstrumentingAgents* instrumentingAgentsForContext(ScriptExecutionContext*);
+InstrumentingAgents* instrumentingAgentsForDocument(Document*);
+InstrumentingAgents* instrumentingAgentsForRenderer(RenderObject*);
+InstrumentingAgents* instrumentingAgentsForElement(Element*);
+
+InstrumentingAgents* instrumentingAgentsForWorkerContext(WorkerContext*);
+InstrumentingAgents* instrumentingAgentsForNonDocumentContext(ScriptExecutionContext*);
+
+}  // namespace InspectorInstrumentation
+
+namespace InstrumentationEvents {
+extern const char PaintLayer[];
+extern const char RasterTask[];
+extern const char Paint[];
+extern const char Layer[];
+extern const char BeginFrame[];
+};
+
+namespace InstrumentationEventArguments {
+extern const char LayerId[];
+extern const char PageId[];
+};
+
+namespace InspectorInstrumentation {
+
+inline InstrumentingAgents* instrumentingAgentsForContext(ScriptExecutionContext* context)
+{
+    if (!context)
+        return 0;
+    if (context->isDocument())
+        return instrumentingAgentsForPage(toDocument(context)->page());
+    return instrumentingAgentsForNonDocumentContext(context);
+}
+
+inline InstrumentingAgents* instrumentingAgentsForFrame(Frame* frame)
+{
+    if (frame)
+        return instrumentingAgentsForPage(frame->page());
+    return 0;
+}
+
+inline InstrumentingAgents* instrumentingAgentsForDocument(Document* document)
+{
+    if (document) {
+        Page* page = document->page();
+        if (!page && document->templateDocumentHost())
+            page = document->templateDocumentHost()->page();
+        return instrumentingAgentsForPage(page);
+    }
+    return 0;
+}
+
+inline InstrumentingAgents* instrumentingAgentsForElement(Element* element)
+{
+    return instrumentingAgentsForDocument(element->document());
+}
+
+} // namespace InspectorInstrumentation
+
+} // namespace WebCore
+
+// This file will soon be generated
+#include "InspectorInstrumentationInl.h"
+
+#include "InspectorInstrumentationCustomInl.h"
+
+#include "InspectorOverridesInl.h"
+
+#endif // !defined(InspectorInstrumentation_h)
diff --git a/Source/core/inspector/InspectorInstrumentationCustomInl.h b/Source/core/inspector/InspectorInstrumentationCustomInl.h
new file mode 100644
index 0000000..4de1752
--- /dev/null
+++ b/Source/core/inspector/InspectorInstrumentationCustomInl.h
@@ -0,0 +1,149 @@
+/*
+* Copyright (C) 2013 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.
+*/
+
+#ifndef InspectorInstrumentationCustom_inl_h
+#define InspectorInstrumentationCustom_inl_h
+
+namespace WebCore {
+
+namespace InspectorInstrumentation {
+
+bool profilerEnabledImpl(InstrumentingAgents*);
+bool isDebuggerPausedImpl(InstrumentingAgents*);
+void willRemoveDOMNodeImpl(InstrumentingAgents*, Node*);
+void didRemoveDOMNodeImpl(InstrumentingAgents*, Node*);
+void didPushShadowRootImpl(InstrumentingAgents*, Element* host, ShadowRoot*);
+void willPopShadowRootImpl(InstrumentingAgents*, Element* host, ShadowRoot*);
+InspectorInstrumentationCookie willProcessRuleImpl(InstrumentingAgents*, StyleRule*, StyleResolver*);
+void continueAfterXFrameOptionsDeniedImpl(Frame*, DocumentLoader*, unsigned long identifier, const ResourceResponse&);
+void continueWithPolicyDownloadImpl(Frame*, DocumentLoader*, unsigned long identifier, const ResourceResponse&);
+void continueWithPolicyIgnoreImpl(Frame*, DocumentLoader*, unsigned long identifier, const ResourceResponse&);
+void willDestroyCachedResourceImpl(CachedResource*);
+void didDispatchDOMStorageEventImpl(InstrumentingAgents*, const String& key, const String& oldValue, const String& newValue, StorageType, SecurityOrigin*, Page*);
+bool collectingHTMLParseErrorsImpl(InstrumentingAgents*);
+
+bool canvasAgentEnabled(ScriptExecutionContext*);
+bool consoleAgentEnabled(ScriptExecutionContext*);
+bool timelineAgentEnabled(ScriptExecutionContext*);
+void willEvaluateWorkerScript(WorkerContext*, int workerThreadStartMode);
+
+inline bool profilerEnabled(Page* page)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        return profilerEnabledImpl(instrumentingAgents);
+    return false;
+}
+
+inline bool isDebuggerPaused(Frame* frame)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(false);
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        return isDebuggerPausedImpl(instrumentingAgents);
+    return false;
+}
+
+
+inline void willRemoveDOMNode(Document* document, Node* node)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document)) {
+        willRemoveDOMNodeImpl(instrumentingAgents, node);
+        didRemoveDOMNodeImpl(instrumentingAgents, node);
+    }
+}
+
+inline void didPushShadowRoot(Element* host, ShadowRoot* root)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(host->ownerDocument()))
+        didPushShadowRootImpl(instrumentingAgents, host, root);
+}
+
+inline void willPopShadowRoot(Element* host, ShadowRoot* root)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(host->ownerDocument()))
+        willPopShadowRootImpl(instrumentingAgents, host, root);
+}
+
+inline InspectorInstrumentationCookie willProcessRule(Document* document, StyleRule* rule, StyleResolver* styleResolver)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (!rule)
+        return InspectorInstrumentationCookie();
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        return willProcessRuleImpl(instrumentingAgents, rule, styleResolver);
+    return InspectorInstrumentationCookie();
+}
+
+inline void continueAfterXFrameOptionsDenied(Frame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    continueAfterXFrameOptionsDeniedImpl(frame, loader, identifier, r);
+}
+
+inline void continueWithPolicyDownload(Frame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    continueWithPolicyDownloadImpl(frame, loader, identifier, r);
+}
+
+inline void continueWithPolicyIgnore(Frame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    continueWithPolicyIgnoreImpl(frame, loader, identifier, r);
+}
+
+inline void willDestroyCachedResource(CachedResource* cachedResource)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    willDestroyCachedResourceImpl(cachedResource);
+}
+
+inline void didDispatchDOMStorageEvent(const String& key, const String& oldValue, const String& newValue, StorageType storageType, SecurityOrigin* securityOrigin, Page* page)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        didDispatchDOMStorageEventImpl(instrumentingAgents, key, oldValue, newValue, storageType, securityOrigin, page);
+}
+
+inline bool collectingHTMLParseErrors(Page* page)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(false);
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        return collectingHTMLParseErrorsImpl(instrumentingAgents);
+    return false;
+}
+
+} // namespace InspectorInstrumentation
+
+} // namespace WebCore
+
+#endif // !defined(InspectorInstrumentationCustom_inl_h)
diff --git a/Source/core/inspector/InspectorInstrumentationInl.h b/Source/core/inspector/InspectorInstrumentationInl.h
new file mode 100644
index 0000000..dffd386
--- /dev/null
+++ b/Source/core/inspector/InspectorInstrumentationInl.h
@@ -0,0 +1,887 @@
+/*
+* Copyright (C) 2013 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.
+*/
+
+#ifndef InspectorInstrumentation_inl_h
+#define InspectorInstrumentation_inl_h
+
+namespace WebCore {
+
+namespace InspectorInstrumentation {
+
+void didClearWindowObjectInWorldImpl(InstrumentingAgents*, Frame*, DOMWrapperWorld*);
+void willInsertDOMNodeImpl(InstrumentingAgents*, Node* parent);
+void didInsertDOMNodeImpl(InstrumentingAgents*, Node*);
+void willModifyDOMAttrImpl(InstrumentingAgents*, Element*, const AtomicString& oldValue, const AtomicString& newValue);
+void didModifyDOMAttrImpl(InstrumentingAgents*, Element*, const AtomicString& name, const AtomicString& value);
+void didRemoveDOMAttrImpl(InstrumentingAgents*, Element*, const AtomicString& name);
+void characterDataModifiedImpl(InstrumentingAgents*, CharacterData*);
+void didInvalidateStyleAttrImpl(InstrumentingAgents*, Node*);
+void activeStyleSheetsUpdatedImpl(InstrumentingAgents*, const Vector<RefPtr<StyleSheet> >&);
+void frameWindowDiscardedImpl(InstrumentingAgents*, DOMWindow*);
+void mediaQueryResultChangedImpl(InstrumentingAgents*);
+void didCreateNamedFlowImpl(InstrumentingAgents*, Document*, NamedFlow*);
+void willRemoveNamedFlowImpl(InstrumentingAgents*, Document*, NamedFlow*);
+void didUpdateRegionLayoutImpl(InstrumentingAgents*, Document*, NamedFlow*);
+void willSendXMLHttpRequestImpl(InstrumentingAgents*, const String& url);
+void didScheduleResourceRequestImpl(InstrumentingAgents*, Document*, const String& url);
+void didInstallTimerImpl(InstrumentingAgents*, ScriptExecutionContext*, int timerId, int timeout, bool singleShot);
+void didRemoveTimerImpl(InstrumentingAgents*, ScriptExecutionContext*, int timerId);
+InspectorInstrumentationCookie willCallFunctionImpl(InstrumentingAgents*, ScriptExecutionContext*, const String& scriptName, int scriptLine);
+void didCallFunctionImpl(const InspectorInstrumentationCookie&);
+InspectorInstrumentationCookie willDispatchXHRReadyStateChangeEventImpl(InstrumentingAgents*, ScriptExecutionContext*, XMLHttpRequest*);
+void didDispatchXHRReadyStateChangeEventImpl(const InspectorInstrumentationCookie&);
+InspectorInstrumentationCookie willDispatchEventImpl(InstrumentingAgents*, Document*, const Event&, DOMWindow*, Node*, const EventPath&);
+void didDispatchEventImpl(const InspectorInstrumentationCookie&);
+InspectorInstrumentationCookie willHandleEventImpl(InstrumentingAgents*, Event*);
+void didHandleEventImpl(const InspectorInstrumentationCookie&);
+InspectorInstrumentationCookie willDispatchEventOnWindowImpl(InstrumentingAgents*, const Event&, DOMWindow*);
+void didDispatchEventOnWindowImpl(const InspectorInstrumentationCookie&);
+InspectorInstrumentationCookie willEvaluateScriptImpl(InstrumentingAgents*, Frame*, const String& url, int lineNumber);
+void didEvaluateScriptImpl(const InspectorInstrumentationCookie&);
+void scriptsEnabledImpl(InstrumentingAgents*, bool isEnabled);
+void didCreateIsolatedContextImpl(InstrumentingAgents*, Frame*, ScriptState*, SecurityOrigin*);
+InspectorInstrumentationCookie willFireTimerImpl(InstrumentingAgents*, ScriptExecutionContext*, int timerId);
+void didFireTimerImpl(const InspectorInstrumentationCookie&);
+void didInvalidateLayoutImpl(InstrumentingAgents*, Frame*);
+InspectorInstrumentationCookie willLayoutImpl(InstrumentingAgents*, Frame*);
+void didLayoutImpl(const InspectorInstrumentationCookie&, RenderObject*);
+void didScrollImpl(InstrumentingAgents*);
+void didResizeMainFrameImpl(InstrumentingAgents*);
+InspectorInstrumentationCookie willDispatchXHRLoadEventImpl(InstrumentingAgents*, ScriptExecutionContext*, XMLHttpRequest*);
+void didDispatchXHRLoadEventImpl(const InspectorInstrumentationCookie&);
+void willScrollLayerImpl(InstrumentingAgents*, Frame*);
+void didScrollLayerImpl(InstrumentingAgents*);
+void willPaintImpl(InstrumentingAgents*, RenderObject*);
+void didPaintImpl(InstrumentingAgents*, RenderObject*, GraphicsContext*, const LayoutRect&);
+InspectorInstrumentationCookie willRecalculateStyleImpl(InstrumentingAgents*, Document*);
+void didRecalculateStyleImpl(const InspectorInstrumentationCookie&);
+void didRecalculateStyleForElementImpl(InstrumentingAgents*);
+void didScheduleStyleRecalculationImpl(InstrumentingAgents*, Document*);
+InspectorInstrumentationCookie willMatchRuleImpl(InstrumentingAgents*, StyleRule*, InspectorCSSOMWrappers&, DocumentStyleSheetCollection*);
+void didMatchRuleImpl(const InspectorInstrumentationCookie&, bool matched);
+void didProcessRuleImpl(const InspectorInstrumentationCookie&);
+void applyUserAgentOverrideImpl(InstrumentingAgents*, String*);
+void applyScreenWidthOverrideImpl(InstrumentingAgents*, long*);
+void applyScreenHeightOverrideImpl(InstrumentingAgents*, long*);
+void applyEmulatedMediaImpl(InstrumentingAgents*, String*);
+void willSendRequestImpl(InstrumentingAgents*, unsigned long identifier, DocumentLoader*, ResourceRequest&, const ResourceResponse& redirectResponse);
+void continueAfterPingLoaderImpl(InstrumentingAgents*, unsigned long identifier, DocumentLoader*, ResourceRequest&, const ResourceResponse&);
+void markResourceAsCachedImpl(InstrumentingAgents*, unsigned long identifier);
+void didLoadResourceFromMemoryCacheImpl(InstrumentingAgents*, DocumentLoader*, CachedResource*);
+InspectorInstrumentationCookie willReceiveResourceDataImpl(InstrumentingAgents*, Frame*, unsigned long identifier, int length);
+void didReceiveResourceDataImpl(const InspectorInstrumentationCookie&);
+InspectorInstrumentationCookie willReceiveResourceResponseImpl(InstrumentingAgents*, Frame*, unsigned long identifier, const ResourceResponse&);
+void didReceiveResourceResponseImpl(const InspectorInstrumentationCookie&, unsigned long identifier, DocumentLoader*, const ResourceResponse&, ResourceLoader*);
+void didReceiveDataImpl(InstrumentingAgents*, unsigned long identifier, const char* data, int dataLength, int encodedDataLength);
+void didFinishLoadingImpl(InstrumentingAgents*, DocumentLoader*, unsigned long identifier, double finishTime);
+void didFailLoadingImpl(InstrumentingAgents*, DocumentLoader*, unsigned long identifier, const ResourceError&);
+void documentThreadableLoaderStartedLoadingForClientImpl(InstrumentingAgents*, unsigned long identifier, ThreadableLoaderClient*);
+void willLoadXHRImpl(InstrumentingAgents*, ThreadableLoaderClient*, const String&, const KURL&, bool, PassRefPtr<FormData>, const HTTPHeaderMap&, bool);
+void didFailXHRLoadingImpl(InstrumentingAgents*, ThreadableLoaderClient*);
+void didFinishXHRLoadingImpl(InstrumentingAgents*, ThreadableLoaderClient*, unsigned long identifier, const String& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber);
+void didReceiveXHRResponseImpl(InstrumentingAgents*, unsigned long identifier);
+void willLoadXHRSynchronouslyImpl(InstrumentingAgents*);
+void didLoadXHRSynchronouslyImpl(InstrumentingAgents*);
+void scriptImportedImpl(InstrumentingAgents*, unsigned long identifier, const String& sourceString);
+void scriptExecutionBlockedByCSPImpl(InstrumentingAgents*, const String& directiveText);
+void didReceiveScriptResponseImpl(InstrumentingAgents*, unsigned long identifier);
+void domContentLoadedEventFiredImpl(InstrumentingAgents*, Frame*);
+void loadEventFiredImpl(InstrumentingAgents*, Frame*);
+void frameDetachedFromParentImpl(InstrumentingAgents*, Frame*);
+void didCommitLoadImpl(InstrumentingAgents*, Frame*, DocumentLoader*);
+void frameDocumentUpdatedImpl(InstrumentingAgents*, Frame*);
+void loaderDetachedFromFrameImpl(InstrumentingAgents*, DocumentLoader*);
+void frameStartedLoadingImpl(InstrumentingAgents*, Frame*);
+void frameStoppedLoadingImpl(InstrumentingAgents*, Frame*);
+void frameScheduledNavigationImpl(InstrumentingAgents*, Frame*, double delay);
+void frameClearedScheduledNavigationImpl(InstrumentingAgents*, Frame*);
+InspectorInstrumentationCookie willRunJavaScriptDialogImpl(InstrumentingAgents*, const String& message);
+void didRunJavaScriptDialogImpl(const InspectorInstrumentationCookie&);
+InspectorInstrumentationCookie willWriteHTMLImpl(InstrumentingAgents*, Document*, unsigned startLine);
+void didWriteHTMLImpl(const InspectorInstrumentationCookie&, unsigned endLine);
+void didRequestAnimationFrameImpl(InstrumentingAgents*, Document*, int callbackId);
+void didCancelAnimationFrameImpl(InstrumentingAgents*, Document*, int callbackId);
+InspectorInstrumentationCookie willFireAnimationFrameImpl(InstrumentingAgents*, Document*, int callbackId);
+void didFireAnimationFrameImpl(const InspectorInstrumentationCookie&);
+void didStartWorkerContextImpl(InstrumentingAgents*, WorkerContextProxy*, const KURL&);
+void workerContextTerminatedImpl(InstrumentingAgents*, WorkerContextProxy*);
+void didCreateWebSocketImpl(InstrumentingAgents*, Document*, unsigned long identifier, const KURL& requestURL, const KURL& documentURL, const String& protocol);
+void willSendWebSocketHandshakeRequestImpl(InstrumentingAgents*, Document*, unsigned long identifier, const WebSocketHandshakeRequest&);
+void didReceiveWebSocketHandshakeResponseImpl(InstrumentingAgents*, Document*, unsigned long identifier, const WebSocketHandshakeResponse&);
+void didCloseWebSocketImpl(InstrumentingAgents*, Document*, unsigned long identifier);
+void didReceiveWebSocketFrameImpl(InstrumentingAgents*, unsigned long identifier, const WebSocketFrame&);
+void didSendWebSocketFrameImpl(InstrumentingAgents*, unsigned long identifier, const WebSocketFrame&);
+void didReceiveWebSocketFrameErrorImpl(InstrumentingAgents*, unsigned long identifier, const String&);
+void networkStateChangedImpl(InstrumentingAgents*);
+void updateApplicationCacheStatusImpl(InstrumentingAgents*, Frame*);
+void layerTreeDidChangeImpl(InstrumentingAgents*);
+void renderLayerDestroyedImpl(InstrumentingAgents*, const RenderLayer*);
+void pseudoElementDestroyedImpl(InstrumentingAgents*, PseudoElement*);
+
+inline void didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld* world)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        didClearWindowObjectInWorldImpl(instrumentingAgents, frame, world);
+}
+
+inline void willInsertDOMNode(Document* document, Node* parent)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        willInsertDOMNodeImpl(instrumentingAgents, parent);
+}
+
+inline void didInsertDOMNode(Document* document, Node* node)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didInsertDOMNodeImpl(instrumentingAgents, node);
+}
+
+
+inline void willModifyDOMAttr(Document* document, Element* element, const AtomicString& oldValue, const AtomicString& newValue)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        willModifyDOMAttrImpl(instrumentingAgents, element, oldValue, newValue);
+}
+
+inline void didModifyDOMAttr(Document* document, Element* element, const AtomicString& name, const AtomicString& value)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didModifyDOMAttrImpl(instrumentingAgents, element, name, value);
+}
+
+inline void didRemoveDOMAttr(Document* document, Element* element, const AtomicString& name)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didRemoveDOMAttrImpl(instrumentingAgents, element, name);
+}
+inline void characterDataModified(Document* document, CharacterData* characterData)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        characterDataModifiedImpl(instrumentingAgents, characterData);
+}
+
+inline void didInvalidateStyleAttr(Document* document, Node* node)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didInvalidateStyleAttrImpl(instrumentingAgents, node);
+}
+
+inline void activeStyleSheetsUpdated(Document* document, const Vector<RefPtr<StyleSheet> >& newSheets)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        activeStyleSheetsUpdatedImpl(instrumentingAgents, newSheets);
+}
+
+inline void frameWindowDiscarded(Frame* frame, DOMWindow* domWindow)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        frameWindowDiscardedImpl(instrumentingAgents, domWindow);
+}
+
+inline void mediaQueryResultChanged(Document* document)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        mediaQueryResultChangedImpl(instrumentingAgents);
+}
+
+
+inline void didCreateNamedFlow(Document* document, NamedFlow* namedFlow)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didCreateNamedFlowImpl(instrumentingAgents, document, namedFlow);
+}
+inline void willRemoveNamedFlow(Document* document, NamedFlow* namedFlow)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        willRemoveNamedFlowImpl(instrumentingAgents, document, namedFlow);
+}
+
+inline void didUpdateRegionLayout(Document* document, NamedFlow* namedFlow)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didUpdateRegionLayoutImpl(instrumentingAgents, document, namedFlow);
+}
+
+inline void willSendXMLHttpRequest(ScriptExecutionContext* context, const String& url)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        willSendXMLHttpRequestImpl(instrumentingAgents, url);
+}
+
+inline void didScheduleResourceRequest(Document* document, const String& url)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didScheduleResourceRequestImpl(instrumentingAgents, document, url);
+}
+
+inline void didInstallTimer(ScriptExecutionContext* context, int timerId, int timeout, bool singleShot)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        didInstallTimerImpl(instrumentingAgents, context, timerId, timeout, singleShot);
+}
+
+inline void didRemoveTimer(ScriptExecutionContext* context, int timerId)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        didRemoveTimerImpl(instrumentingAgents, context, timerId);
+}
+
+inline InspectorInstrumentationCookie willCallFunction(ScriptExecutionContext* context, const String& scriptName, int scriptLine)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        return willCallFunctionImpl(instrumentingAgents, context, scriptName, scriptLine);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didCallFunction(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didCallFunctionImpl(cookie);
+}
+
+inline InspectorInstrumentationCookie willDispatchXHRReadyStateChangeEvent(ScriptExecutionContext* context, XMLHttpRequest* request)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        return willDispatchXHRReadyStateChangeEventImpl(instrumentingAgents, context, request);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didDispatchXHRReadyStateChangeEvent(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didDispatchXHRReadyStateChangeEventImpl(cookie);
+}
+
+inline InspectorInstrumentationCookie willDispatchEvent(Document* document, const Event& event, DOMWindow* window, Node* node, const EventPath& eventPath)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        return willDispatchEventImpl(instrumentingAgents, document, event, window, node, eventPath);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didDispatchEvent(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didDispatchEventImpl(cookie);
+}
+
+inline InspectorInstrumentationCookie willHandleEvent(ScriptExecutionContext* context, Event* event)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        return willHandleEventImpl(instrumentingAgents, event);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didHandleEvent(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didHandleEventImpl(cookie);
+}
+
+inline InspectorInstrumentationCookie willDispatchEventOnWindow(Frame* frame, const Event& event, DOMWindow* window)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        return willDispatchEventOnWindowImpl(instrumentingAgents, event, window);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didDispatchEventOnWindow(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didDispatchEventOnWindowImpl(cookie);
+}
+
+inline InspectorInstrumentationCookie willEvaluateScript(Frame* frame, const String& url, int lineNumber)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        return willEvaluateScriptImpl(instrumentingAgents, frame, url, lineNumber);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didEvaluateScript(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didEvaluateScriptImpl(cookie);
+}
+
+inline void scriptsEnabled(Page* page, bool isEnabled)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        scriptsEnabledImpl(instrumentingAgents, isEnabled);
+}
+
+inline void didCreateIsolatedContext(Frame* frame, ScriptState* scriptState, SecurityOrigin* origin)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        didCreateIsolatedContextImpl(instrumentingAgents, frame, scriptState, origin);
+}
+
+inline InspectorInstrumentationCookie willFireTimer(ScriptExecutionContext* context, int timerId)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        return willFireTimerImpl(instrumentingAgents, context, timerId);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didFireTimer(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didFireTimerImpl(cookie);
+}
+
+inline void didInvalidateLayout(Frame* frame)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        didInvalidateLayoutImpl(instrumentingAgents, frame);
+}
+
+inline InspectorInstrumentationCookie willLayout(Frame* frame)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        return willLayoutImpl(instrumentingAgents, frame);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didLayout(const InspectorInstrumentationCookie& cookie, RenderObject* root)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didLayoutImpl(cookie, root);
+}
+
+inline void didScroll(Page* page)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        didScrollImpl(instrumentingAgents);
+}
+
+inline void didResizeMainFrame(Page* page)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        didResizeMainFrameImpl(instrumentingAgents);
+}
+
+inline InspectorInstrumentationCookie willDispatchXHRLoadEvent(ScriptExecutionContext* context, XMLHttpRequest* request)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        return willDispatchXHRLoadEventImpl(instrumentingAgents, context, request);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didDispatchXHRLoadEvent(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didDispatchXHRLoadEventImpl(cookie);
+}
+
+inline void willScrollLayer(Frame* frame)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        willScrollLayerImpl(instrumentingAgents, frame);
+}
+
+inline void didScrollLayer(Frame* frame)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        didScrollLayerImpl(instrumentingAgents);
+}
+
+inline void willPaint(RenderObject* renderer)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForRenderer(renderer))
+        willPaintImpl(instrumentingAgents, renderer);
+}
+
+inline void didPaint(RenderObject* renderer, GraphicsContext* context, const LayoutRect& rect)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForRenderer(renderer))
+        didPaintImpl(instrumentingAgents, renderer, context, rect);
+}
+
+inline InspectorInstrumentationCookie willRecalculateStyle(Document* document)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        return willRecalculateStyleImpl(instrumentingAgents, document);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didRecalculateStyle(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didRecalculateStyleImpl(cookie);
+}
+
+inline void didRecalculateStyleForElement(Element* element)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForElement(element))
+        didRecalculateStyleForElementImpl(instrumentingAgents);
+}
+
+inline void didScheduleStyleRecalculation(Document* document)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didScheduleStyleRecalculationImpl(instrumentingAgents, document);
+}
+
+inline InspectorInstrumentationCookie willMatchRule(Document* document, StyleRule* rule, InspectorCSSOMWrappers& inspectorCSSOMWrappers, DocumentStyleSheetCollection* styleSheetCollection)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        return willMatchRuleImpl(instrumentingAgents, rule, inspectorCSSOMWrappers, styleSheetCollection);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didMatchRule(const InspectorInstrumentationCookie& cookie, bool matched)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didMatchRuleImpl(cookie, matched);
+}
+
+inline void didProcessRule(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didProcessRuleImpl(cookie);
+}
+
+inline void applyUserAgentOverride(Frame* frame, String* userAgent)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        applyUserAgentOverrideImpl(instrumentingAgents, userAgent);
+}
+
+inline void applyScreenWidthOverride(Frame* frame, long* width)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        applyScreenWidthOverrideImpl(instrumentingAgents, width);
+}
+
+inline void applyScreenHeightOverride(Frame* frame, long* height)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        applyScreenHeightOverrideImpl(instrumentingAgents, height);
+}
+
+inline void applyEmulatedMedia(Frame* frame, String* media)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        applyEmulatedMediaImpl(instrumentingAgents, media);
+}
+
+inline void willSendRequest(Frame* frame, unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        willSendRequestImpl(instrumentingAgents, identifier, loader, request, redirectResponse);
+}
+
+inline void continueAfterPingLoader(Frame* frame, unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& response)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        continueAfterPingLoaderImpl(instrumentingAgents, identifier, loader, request, response);
+}
+
+inline void markResourceAsCached(Page* page, unsigned long identifier)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        markResourceAsCachedImpl(instrumentingAgents, identifier);
+}
+
+inline void didLoadResourceFromMemoryCache(Page* page, DocumentLoader* loader, CachedResource* resource)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        didLoadResourceFromMemoryCacheImpl(instrumentingAgents, loader, resource);
+}
+
+inline void didReceiveResourceData(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didReceiveResourceDataImpl(cookie);
+}
+
+inline InspectorInstrumentationCookie willReceiveResourceData(Frame* frame, unsigned long identifier, int length)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        return willReceiveResourceDataImpl(instrumentingAgents, frame, identifier, length);
+    return InspectorInstrumentationCookie();
+}
+
+inline InspectorInstrumentationCookie willReceiveResourceResponse(Frame* frame, unsigned long identifier, const ResourceResponse& response)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        return willReceiveResourceResponseImpl(instrumentingAgents, frame, identifier, response);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didReceiveResourceResponse(const InspectorInstrumentationCookie& cookie, unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response, ResourceLoader* resourceLoader)
+{
+    // Call this unconditionally so that we're able to log to console with no front-end attached.
+    if (cookie.isValid())
+        didReceiveResourceResponseImpl(cookie, identifier, loader, response, resourceLoader);
+}
+
+inline void didReceiveData(Frame* frame, unsigned long identifier, const char* data, int dataLength, int encodedDataLength)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        didReceiveDataImpl(instrumentingAgents, identifier, data, dataLength, encodedDataLength);
+}
+
+inline void didFinishLoading(Frame* frame, DocumentLoader* loader, unsigned long identifier, double finishTime)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        didFinishLoadingImpl(instrumentingAgents, loader, identifier, finishTime);
+}
+
+inline void didFailLoading(Frame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        didFailLoadingImpl(instrumentingAgents, loader, identifier, error);
+}
+
+inline void documentThreadableLoaderStartedLoadingForClient(ScriptExecutionContext* context, unsigned long identifier, ThreadableLoaderClient* client)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        documentThreadableLoaderStartedLoadingForClientImpl(instrumentingAgents, identifier, client);
+}
+
+inline void willLoadXHR(ScriptExecutionContext* context, ThreadableLoaderClient* client, const String& method, const KURL& url, bool async, PassRefPtr<FormData> formData, const HTTPHeaderMap& headers, bool includeCredentials)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        willLoadXHRImpl(instrumentingAgents, client, method, url, async, formData, headers, includeCredentials);
+}
+
+inline void didFailXHRLoading(ScriptExecutionContext* context, ThreadableLoaderClient* client)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        didFailXHRLoadingImpl(instrumentingAgents, client);
+}
+
+inline void didFinishXHRLoading(ScriptExecutionContext* context, ThreadableLoaderClient* client, unsigned long identifier, const String& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        didFinishXHRLoadingImpl(instrumentingAgents, client, identifier, sourceString, url, sendURL, sendLineNumber);
+}
+
+inline void didReceiveXHRResponse(ScriptExecutionContext* context, unsigned long identifier)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        didReceiveXHRResponseImpl(instrumentingAgents, identifier);
+}
+
+inline void willLoadXHRSynchronously(ScriptExecutionContext* context)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        willLoadXHRSynchronouslyImpl(instrumentingAgents);
+}
+
+inline void didLoadXHRSynchronously(ScriptExecutionContext* context)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        didLoadXHRSynchronouslyImpl(instrumentingAgents);
+}
+
+inline void scriptImported(ScriptExecutionContext* context, unsigned long identifier, const String& sourceString)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        scriptImportedImpl(instrumentingAgents, identifier, sourceString);
+}
+
+inline void scriptExecutionBlockedByCSP(ScriptExecutionContext* context, const String& directiveText)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        scriptExecutionBlockedByCSPImpl(instrumentingAgents, directiveText);
+}
+
+inline void didReceiveScriptResponse(ScriptExecutionContext* context, unsigned long identifier)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        didReceiveScriptResponseImpl(instrumentingAgents, identifier);
+}
+
+inline void domContentLoadedEventFired(Frame* frame)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        domContentLoadedEventFiredImpl(instrumentingAgents, frame);
+}
+
+inline void loadEventFired(Frame* frame)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        loadEventFiredImpl(instrumentingAgents, frame);
+}
+
+inline void frameDetachedFromParent(Frame* frame)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        frameDetachedFromParentImpl(instrumentingAgents, frame);
+}
+
+inline void didCommitLoad(Frame* frame, DocumentLoader* loader)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        didCommitLoadImpl(instrumentingAgents, frame, loader);
+}
+
+inline void frameDocumentUpdated(Frame* frame)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        frameDocumentUpdatedImpl(instrumentingAgents, frame);
+}
+
+inline void loaderDetachedFromFrame(Frame* frame, DocumentLoader* loader)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        loaderDetachedFromFrameImpl(instrumentingAgents, loader);
+}
+
+inline void frameStartedLoading(Frame* frame)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        frameStartedLoadingImpl(instrumentingAgents, frame);
+}
+
+inline void frameStoppedLoading(Frame* frame)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        frameStoppedLoadingImpl(instrumentingAgents, frame);
+}
+
+inline void frameScheduledNavigation(Frame* frame, double delay)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        frameScheduledNavigationImpl(instrumentingAgents, frame, delay);
+}
+
+inline void frameClearedScheduledNavigation(Frame* frame)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        frameClearedScheduledNavigationImpl(instrumentingAgents, frame);
+}
+
+inline InspectorInstrumentationCookie willRunJavaScriptDialog(Page* page, const String& message)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        return willRunJavaScriptDialogImpl(instrumentingAgents, message);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didRunJavaScriptDialog(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didRunJavaScriptDialogImpl(cookie);
+}
+
+inline InspectorInstrumentationCookie willWriteHTML(Document* document, unsigned startLine)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        return willWriteHTMLImpl(instrumentingAgents, document, startLine);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didWriteHTML(const InspectorInstrumentationCookie& cookie, unsigned endLine)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didWriteHTMLImpl(cookie, endLine);
+}
+
+inline void didRequestAnimationFrame(Document* document, int callbackId)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didRequestAnimationFrameImpl(instrumentingAgents, document, callbackId);
+}
+
+inline void didCancelAnimationFrame(Document* document, int callbackId)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didCancelAnimationFrameImpl(instrumentingAgents, document, callbackId);
+}
+
+inline InspectorInstrumentationCookie willFireAnimationFrame(Document* document, int callbackId)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        return willFireAnimationFrameImpl(instrumentingAgents, document, callbackId);
+    return InspectorInstrumentationCookie();
+}
+
+inline void didFireAnimationFrame(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didFireAnimationFrameImpl(cookie);
+}
+
+inline void didStartWorkerContext(ScriptExecutionContext* context, WorkerContextProxy* proxy, const KURL& url)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        didStartWorkerContextImpl(instrumentingAgents, proxy, url);
+}
+
+inline void workerContextTerminated(ScriptExecutionContext* context, WorkerContextProxy* proxy)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        workerContextTerminatedImpl(instrumentingAgents, proxy);
+}
+
+inline void didCreateWebSocket(Document* document, unsigned long identifier, const KURL& requestURL, const KURL& documentURL, const String& protocol)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didCreateWebSocketImpl(instrumentingAgents, document, identifier, requestURL, documentURL, protocol);
+}
+
+inline void willSendWebSocketHandshakeRequest(Document* document, unsigned long identifier, const WebSocketHandshakeRequest& request)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        willSendWebSocketHandshakeRequestImpl(instrumentingAgents, document, identifier, request);
+}
+
+inline void didReceiveWebSocketHandshakeResponse(Document* document, unsigned long identifier, const WebSocketHandshakeResponse& response)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didReceiveWebSocketHandshakeResponseImpl(instrumentingAgents, document, identifier, response);
+}
+
+inline void didCloseWebSocket(Document* document, unsigned long identifier)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didCloseWebSocketImpl(instrumentingAgents, document, identifier);
+}
+
+inline void didReceiveWebSocketFrame(Document* document, unsigned long identifier, const WebSocketFrame& frame)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didReceiveWebSocketFrameImpl(instrumentingAgents, identifier, frame);
+}
+
+inline void didSendWebSocketFrame(Document* document, unsigned long identifier, const WebSocketFrame& frame)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didSendWebSocketFrameImpl(instrumentingAgents, identifier, frame);
+}
+
+inline void didReceiveWebSocketFrameError(Document* document, unsigned long identifier, const String& errorMessage)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
+        didReceiveWebSocketFrameErrorImpl(instrumentingAgents, identifier, errorMessage);
+}
+
+inline void networkStateChanged(Page* page)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        networkStateChangedImpl(instrumentingAgents);
+}
+
+inline void updateApplicationCacheStatus(Frame* frame)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        updateApplicationCacheStatusImpl(instrumentingAgents, frame);
+}
+
+inline void layerTreeDidChange(Page* page)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        layerTreeDidChangeImpl(instrumentingAgents);
+}
+
+inline void renderLayerDestroyed(Page* page, const RenderLayer* renderLayer)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        renderLayerDestroyedImpl(instrumentingAgents, renderLayer);
+}
+
+inline void pseudoElementDestroyed(Page* page, PseudoElement* pseudoElement)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        pseudoElementDestroyedImpl(instrumentingAgents, pseudoElement);
+}
+
+} // namespace InspectorInstrumentation
+
+} // namespace WebCore
+
+#endif // !defined(InspectorInstrumentation_inl_h)
diff --git a/Source/core/inspector/InspectorLayerTreeAgent.cpp b/Source/core/inspector/InspectorLayerTreeAgent.cpp
new file mode 100644
index 0000000..9b2f06e
--- /dev/null
+++ b/Source/core/inspector/InspectorLayerTreeAgent.cpp
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2012 Apple 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.
+ */
+
+#include "config.h"
+
+#include "core/inspector/InspectorLayerTreeAgent.h"
+
+#include "InspectorFrontend.h"
+#include "core/dom/PseudoElement.h"
+#include "core/inspector/IdentifiersFactory.h"
+#include "core/inspector/InspectorDOMAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/platform/graphics/IntRect.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderLayerBacking.h"
+#include "core/rendering/RenderLayerCompositor.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+
+namespace LayerTreeAgentState {
+static const char layerTreeAgentEnabled[] = "layerTreeAgentEnabled";
+};
+
+InspectorLayerTreeAgent::InspectorLayerTreeAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state)
+    : InspectorBaseAgent<InspectorLayerTreeAgent>("LayerTree", instrumentingAgents, state)
+    , m_frontend(0)
+{
+}
+
+InspectorLayerTreeAgent::~InspectorLayerTreeAgent()
+{
+    reset();
+}
+
+void InspectorLayerTreeAgent::setFrontend(InspectorFrontend* frontend)
+{
+    m_frontend = frontend->layertree();
+}
+
+void InspectorLayerTreeAgent::clearFrontend()
+{
+    m_frontend = 0;
+    disable(0);
+}
+
+void InspectorLayerTreeAgent::restore()
+{
+    if (m_state->getBoolean(LayerTreeAgentState::layerTreeAgentEnabled))
+        enable(0);
+}
+
+void InspectorLayerTreeAgent::reset()
+{
+    m_documentLayerToIdMap.clear();
+    m_idToLayer.clear();
+    m_pseudoElementToIdMap.clear();
+    m_idToPseudoElement.clear();
+}
+
+void InspectorLayerTreeAgent::enable(ErrorString*)
+{
+    m_state->setBoolean(LayerTreeAgentState::layerTreeAgentEnabled, true);
+    m_instrumentingAgents->setInspectorLayerTreeAgent(this);
+}
+
+void InspectorLayerTreeAgent::disable(ErrorString*)
+{
+    if (!m_state->getBoolean(LayerTreeAgentState::layerTreeAgentEnabled))
+        return;
+    m_state->setBoolean(LayerTreeAgentState::layerTreeAgentEnabled, false);
+    m_instrumentingAgents->setInspectorLayerTreeAgent(0);
+}
+
+void InspectorLayerTreeAgent::layerTreeDidChange()
+{
+    m_frontend->layerTreeDidChange();
+}
+
+void InspectorLayerTreeAgent::renderLayerDestroyed(const RenderLayer* renderLayer)
+{
+    unbind(renderLayer);
+}
+
+void InspectorLayerTreeAgent::pseudoElementDestroyed(PseudoElement* pseudoElement)
+{
+    unbindPseudoElement(pseudoElement);
+}
+
+void InspectorLayerTreeAgent::layersForNode(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >& layers)
+{
+    layers = TypeBuilder::Array<TypeBuilder::LayerTree::Layer>::create();
+
+    Node* node = m_instrumentingAgents->inspectorDOMAgent()->nodeForId(nodeId);
+    if (!node) {
+        *errorString = "Provided node id doesn't match any known node";
+        return;
+    }
+
+    RenderObject* renderer = node->renderer();
+    if (!renderer) {
+        *errorString = "Node for provided node id doesn't have a renderer";
+        return;
+    }
+
+    gatherLayersUsingRenderObjectHierarchy(errorString, renderer, layers);
+}
+
+void InspectorLayerTreeAgent::gatherLayersUsingRenderObjectHierarchy(ErrorString* errorString, RenderObject* renderer, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >& layers)
+{
+    if (renderer->hasLayer()) {
+        gatherLayersUsingRenderLayerHierarchy(errorString, toRenderLayerModelObject(renderer)->layer(), layers);
+        return;
+    }
+
+    for (renderer = renderer->firstChild(); renderer; renderer = renderer->nextSibling())
+        gatherLayersUsingRenderObjectHierarchy(errorString, renderer, layers);
+}
+
+void InspectorLayerTreeAgent::gatherLayersUsingRenderLayerHierarchy(ErrorString* errorString, RenderLayer* renderLayer, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >& layers)
+{
+    if (renderLayer->isComposited())
+        layers->addItem(buildObjectForLayer(errorString, renderLayer));
+
+    for (renderLayer = renderLayer->firstChild(); renderLayer; renderLayer = renderLayer->nextSibling())
+        gatherLayersUsingRenderLayerHierarchy(errorString, renderLayer, layers);
+}
+
+PassRefPtr<TypeBuilder::LayerTree::Layer> InspectorLayerTreeAgent::buildObjectForLayer(ErrorString* errorString, RenderLayer* renderLayer)
+{
+    RenderObject* renderer = renderLayer->renderer();
+    RenderLayerBacking* backing = renderLayer->backing();
+    Node* node = renderer->node();
+
+    bool isReflection = renderLayer->isReflection();
+    bool isGenerated = (isReflection ? renderer->parent() : renderer)->isBeforeOrAfterContent();
+
+    if (isReflection && isGenerated)
+        node = renderer->parent()->generatingNode();
+    else if (isGenerated)
+        node = renderer->generatingNode();
+    else if (isReflection)
+        node = renderer->parent()->node();
+
+    // Basic set of properties.
+    RefPtr<TypeBuilder::LayerTree::Layer> layerObject = TypeBuilder::LayerTree::Layer::create()
+        .setLayerId(bind(renderLayer))
+        .setNodeId(idForNode(errorString, node))
+        .setBounds(buildObjectForIntRect(enclosingIntRect(renderer->absoluteBoundingBoxRect())))
+        .setMemory(backing->backingStoreMemoryEstimate())
+        .setCompositedBounds(buildObjectForIntRect(backing->compositedBounds()))
+        .setPaintCount(backing->graphicsLayer()->repaintCount());
+
+    if (node && node->shadowHost())
+        layerObject->setIsInShadowTree(true);
+
+    if (isReflection)
+        layerObject->setIsReflection(true);
+
+    if (isGenerated) {
+        if (isReflection)
+            renderer = renderer->parent();
+        layerObject->setIsGeneratedContent(true);
+        layerObject->setPseudoElementId(bindPseudoElement(static_cast<PseudoElement*>(renderer->node())));
+        if (renderer->isBeforeContent())
+            layerObject->setPseudoClass("before");
+        else if (renderer->isAfterContent())
+            layerObject->setPseudoClass("after");
+    }
+
+    return layerObject;
+}
+
+int InspectorLayerTreeAgent::idForNode(ErrorString* errorString, Node* node)
+{
+    InspectorDOMAgent* domAgent = m_instrumentingAgents->inspectorDOMAgent();
+    
+    int nodeId = domAgent->boundNodeId(node);
+    if (!nodeId)
+        nodeId = domAgent->pushNodeToFrontend(errorString, domAgent->boundNodeId(node->document()), node);
+
+    return nodeId;
+}
+
+PassRefPtr<TypeBuilder::LayerTree::IntRect> InspectorLayerTreeAgent::buildObjectForIntRect(const IntRect& rect)
+{
+    return TypeBuilder::LayerTree::IntRect::create()
+        .setX(rect.x())
+        .setY(rect.y())
+        .setWidth(rect.width())
+        .setHeight(rect.height()).release();
+}
+
+void InspectorLayerTreeAgent::reasonsForCompositingLayer(ErrorString* errorString, const String& layerId, RefPtr<TypeBuilder::LayerTree::CompositingReasons>& compositingReasons)
+{
+    const RenderLayer* renderLayer = m_idToLayer.get(layerId);
+
+    if (!renderLayer) {
+        *errorString = "Could not find a bound layer for the provided id";
+        return;
+    }
+
+    CompositingReasons reasonsBitmask = renderLayer->compositor()->reasonsForCompositing(renderLayer);
+    compositingReasons = TypeBuilder::LayerTree::CompositingReasons::create();
+
+    if (reasonsBitmask & CompositingReason3DTransform)
+        compositingReasons->setTransform3D(true);
+
+    if (reasonsBitmask & CompositingReasonVideo)
+        compositingReasons->setVideo(true);
+
+    if (reasonsBitmask & CompositingReasonCanvas)
+        compositingReasons->setCanvas(true);
+
+    if (reasonsBitmask & CompositingReasonPlugin)
+        compositingReasons->setPlugin(true);
+
+    if (reasonsBitmask & CompositingReasonIFrame)
+        compositingReasons->setIFrame(true);
+    
+    if (reasonsBitmask & CompositingReasonBackfaceVisibilityHidden)
+        compositingReasons->setBackfaceVisibilityHidden(true);
+
+    if (reasonsBitmask & CompositingReasonClipsCompositingDescendants)
+        compositingReasons->setClipsCompositingDescendants(true);
+
+    if (reasonsBitmask & CompositingReasonAnimation)
+        compositingReasons->setAnimation(true);
+
+    if (reasonsBitmask & CompositingReasonFilters)
+        compositingReasons->setFilters(true);
+
+    if (reasonsBitmask & CompositingReasonPositionFixed)
+        compositingReasons->setPositionFixed(true);
+
+    if (reasonsBitmask & CompositingReasonPositionSticky)
+        compositingReasons->setPositionSticky(true);
+
+    if (reasonsBitmask & CompositingReasonOverflowScrollingTouch)
+        compositingReasons->setOverflowScrollingTouch(true);
+
+    if (reasonsBitmask & CompositingReasonStacking)
+        compositingReasons->setStacking(true);
+
+    if (reasonsBitmask & CompositingReasonOverlap)
+        compositingReasons->setOverlap(true);
+
+    if (reasonsBitmask & CompositingReasonNegativeZIndexChildren)
+        compositingReasons->setNegativeZIndexChildren(true);
+
+    if (reasonsBitmask & CompositingReasonTransformWithCompositedDescendants)
+        compositingReasons->setTransformWithCompositedDescendants(true);
+
+    if (reasonsBitmask & CompositingReasonOpacityWithCompositedDescendants)
+        compositingReasons->setOpacityWithCompositedDescendants(true);
+
+    if (reasonsBitmask & CompositingReasonMaskWithCompositedDescendants)
+        compositingReasons->setMaskWithCompositedDescendants(true);
+
+    if (reasonsBitmask & CompositingReasonReflectionWithCompositedDescendants)
+        compositingReasons->setReflectionWithCompositedDescendants(true);
+
+    if (reasonsBitmask & CompositingReasonFilterWithCompositedDescendants)
+        compositingReasons->setFilterWithCompositedDescendants(true);
+            
+    if (reasonsBitmask & CompositingReasonBlendingWithCompositedDescendants)
+        compositingReasons->setBlendingWithCompositedDescendants(true);
+
+    if (reasonsBitmask & CompositingReasonPerspective)
+        compositingReasons->setPerspective(true);
+
+    if (reasonsBitmask & CompositingReasonPreserve3D)
+        compositingReasons->setPreserve3D(true);
+
+    if (reasonsBitmask & CompositingReasonRoot)
+        compositingReasons->setRoot(true);
+}
+
+String InspectorLayerTreeAgent::bind(const RenderLayer* layer)
+{
+    if (!layer)
+        return emptyString();
+    String identifier = m_documentLayerToIdMap.get(layer);
+    if (identifier.isNull()) {
+        identifier = IdentifiersFactory::createIdentifier();
+        m_documentLayerToIdMap.set(layer, identifier);
+        m_idToLayer.set(identifier, layer);
+    }
+    return identifier;
+}
+
+void InspectorLayerTreeAgent::unbind(const RenderLayer* layer)
+{
+    HashMap<const RenderLayer*, String>::iterator iterator = m_documentLayerToIdMap.find(layer);
+    if (iterator == m_documentLayerToIdMap.end())
+        return;
+    m_idToLayer.remove(iterator->value);
+    m_documentLayerToIdMap.remove(iterator);
+}
+
+String InspectorLayerTreeAgent::bindPseudoElement(PseudoElement* pseudoElement)
+{
+    if (!pseudoElement)
+        return emptyString();
+    String identifier = m_pseudoElementToIdMap.get(pseudoElement);
+    if (identifier.isNull()) {
+        identifier = IdentifiersFactory::createIdentifier();
+        m_pseudoElementToIdMap.set(pseudoElement, identifier);
+        m_idToPseudoElement.set(identifier, pseudoElement);
+    }
+    return identifier;
+}
+
+void InspectorLayerTreeAgent::unbindPseudoElement(PseudoElement* pseudoElement)
+{
+    HashMap<PseudoElement*, String>::iterator iterator = m_pseudoElementToIdMap.find(pseudoElement);
+    if (iterator == m_pseudoElementToIdMap.end())
+        return;
+    m_idToPseudoElement.remove(iterator->value);
+    m_pseudoElementToIdMap.remove(iterator);
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/InspectorLayerTreeAgent.h b/Source/core/inspector/InspectorLayerTreeAgent.h
new file mode 100644
index 0000000..46ea3e4
--- /dev/null
+++ b/Source/core/inspector/InspectorLayerTreeAgent.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2012 Apple 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef InspectorLayerTreeAgent_h
+#define InspectorLayerTreeAgent_h
+
+
+#include "InspectorFrontend.h"
+#include "InspectorTypeBuilder.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include "core/rendering/RenderLayer.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class InspectorState;
+class InstrumentingAgents;
+
+typedef String ErrorString;
+
+class InspectorLayerTreeAgent : public InspectorBaseAgent<InspectorLayerTreeAgent>, public InspectorBackendDispatcher::LayerTreeCommandHandler {
+public:
+    static PassOwnPtr<InspectorLayerTreeAgent> create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state)
+    {
+        return adoptPtr(new InspectorLayerTreeAgent(instrumentingAgents, state));
+    }
+    ~InspectorLayerTreeAgent();
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void restore();
+    void reset();
+
+    void layerTreeDidChange();
+    void renderLayerDestroyed(const RenderLayer*);
+    void pseudoElementDestroyed(PseudoElement*);
+
+    // Called from the front-end.
+    virtual void enable(ErrorString*);
+    virtual void disable(ErrorString*);
+    virtual void layersForNode(ErrorString*, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >&);
+    virtual void reasonsForCompositingLayer(ErrorString*, const String& layerId, RefPtr<TypeBuilder::LayerTree::CompositingReasons>&);
+
+private:
+    InspectorLayerTreeAgent(InstrumentingAgents*, InspectorCompositeState*);
+
+    // RenderLayer-related methods.
+    String bind(const RenderLayer*);
+    void unbind(const RenderLayer*);
+
+    void gatherLayersUsingRenderObjectHierarchy(ErrorString*, RenderObject*, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >&);
+    void gatherLayersUsingRenderLayerHierarchy(ErrorString*, RenderLayer*, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >&);
+
+    PassRefPtr<TypeBuilder::LayerTree::Layer> buildObjectForLayer(ErrorString*, RenderLayer*);
+    PassRefPtr<TypeBuilder::LayerTree::IntRect> buildObjectForIntRect(const IntRect&);
+
+    int idForNode(ErrorString*, Node*);
+
+    String bindPseudoElement(PseudoElement*);
+    void unbindPseudoElement(PseudoElement*);
+
+    InspectorFrontend::LayerTree* m_frontend;
+
+    HashMap<const RenderLayer*, String> m_documentLayerToIdMap;
+    HashMap<String, const RenderLayer*> m_idToLayer;
+
+    HashMap<PseudoElement*, String> m_pseudoElementToIdMap;
+    HashMap<String, PseudoElement*> m_idToPseudoElement;
+};
+
+} // namespace WebCore
+
+
+#endif // !defined(InspectorLayerTreeAgent_h)
diff --git a/Source/core/inspector/InspectorMemoryAgent.cpp b/Source/core/inspector/InspectorMemoryAgent.cpp
new file mode 100644
index 0000000..6ba4bfd
--- /dev/null
+++ b/Source/core/inspector/InspectorMemoryAgent.cpp
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorMemoryAgent.h"
+
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptGCEvent.h"
+#include "bindings/v8/ScriptProfiler.h"
+#include "core/dom/CharacterData.h"
+#include "core/dom/Document.h"
+#include "core/dom/EventListenerMap.h"
+#include "core/dom/Node.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/StyledElement.h"
+#include "core/inspector/BindingVisitors.h"
+#include "core/inspector/HeapGraphSerializer.h"
+#include "core/inspector/InspectorClient.h"
+#include "core/inspector/InspectorDOMStorageAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/inspector/MemoryInstrumentationImpl.h"
+#include "core/loader/cache/MemoryCache.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/MemoryUsageSupport.h"
+#include <wtf/ArrayBufferView.h>
+#include <wtf/HashSet.h>
+#include <wtf/MemoryInstrumentationArrayBufferView.h>
+#include <wtf/NonCopyingSort.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringImpl.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+// Use a type alias instead of 'using' here which would cause a conflict on Mac.
+typedef WebCore::TypeBuilder::Memory::MemoryBlock InspectorMemoryBlock;
+typedef WebCore::TypeBuilder::Array<InspectorMemoryBlock> InspectorMemoryBlocks;
+
+namespace WebCore {
+
+namespace {
+
+class MemoryUsageStatsGenerator {
+public:
+    MemoryUsageStatsGenerator() { }
+
+    void dump(const TypeNameToSizeMap& sizesMap, InspectorMemoryBlocks* children)
+    {
+        m_sizesMap = sizesMap;
+
+        // FIXME: We filter out Rendering type because the coverage is not good enough at the moment
+        // and report RenderArena size instead.
+        for (TypeNameToSizeMap::iterator i = m_sizesMap.begin(); i != m_sizesMap.end(); ++i) {
+            if (i->key == PlatformMemoryTypes::Rendering) {
+                m_sizesMap.remove(i);
+                break;
+            }
+        }
+        Vector<String> objectTypes;
+        objectTypes.appendRange(m_sizesMap.keys().begin(), m_sizesMap.keys().end());
+
+        for (Vector<String>::const_iterator i = objectTypes.begin(); i != objectTypes.end(); ++i)
+            updateParentSizes(*i, m_sizesMap.get(*i));
+
+        objectTypes.clear();
+        objectTypes.appendRange(m_sizesMap.keys().begin(), m_sizesMap.keys().end());
+        nonCopyingSort(objectTypes.begin(), objectTypes.end(), stringCompare);
+
+        size_t index = 0;
+        while (index < objectTypes.size())
+            index = buildObjectForIndex(index, objectTypes, children);
+
+    }
+
+private:
+    static bool stringCompare(const String& a, const String& b) { return WTF::codePointCompare(a, b) < 0; }
+
+    void updateParentSizes(String objectType, const size_t size)
+    {
+        for (size_t dotPosition = objectType.reverseFind('.'); dotPosition != notFound; dotPosition = objectType.reverseFind('.', dotPosition)) {
+            objectType = objectType.substring(0, dotPosition);
+            TypeNameToSizeMap::AddResult result = m_sizesMap.add(objectType, size);
+            if (!result.isNewEntry)
+                result.iterator->value += size;
+        }
+    }
+
+    size_t buildObjectForIndex(size_t index, const Vector<String>& objectTypes, InspectorMemoryBlocks* array)
+    {
+        String typeName = objectTypes[index];
+        size_t dotPosition = typeName.reverseFind('.');
+        String blockName = (dotPosition == notFound) ? typeName : typeName.substring(dotPosition + 1);
+        RefPtr<InspectorMemoryBlock> block = InspectorMemoryBlock::create().setName(blockName);
+        block->setSize(m_sizesMap.get(typeName));
+        String prefix = typeName;
+        prefix.append('.');
+        array->addItem(block);
+        ++index;
+        RefPtr<InspectorMemoryBlocks> children;
+        while (index < objectTypes.size() && objectTypes[index].startsWith(prefix)) {
+            if (!children)
+                children = InspectorMemoryBlocks::create();
+            index = buildObjectForIndex(index, objectTypes, children.get());
+        }
+        if (children)
+            block->setChildren(children.release());
+        return index;
+    }
+
+    TypeNameToSizeMap m_sizesMap;
+};
+
+class ExternalStringsRoot : public ExternalStringVisitor {
+public:
+    ExternalStringsRoot() : m_memoryClassInfo(0) { }
+
+    void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+    {
+        MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::ExternalStrings);
+        m_memoryClassInfo = &info;
+        ScriptProfiler::visitExternalStrings(const_cast<ExternalStringsRoot*>(this));
+        m_memoryClassInfo = 0;
+        info.ignoreMember(m_memoryClassInfo);
+    }
+
+private:
+    virtual void visitJSExternalString(StringImpl* string)
+    {
+        m_memoryClassInfo->addMember(string, "externalString", WTF::RetainingPointer);
+    }
+
+    mutable MemoryClassInfo* m_memoryClassInfo;
+};
+
+class ExternalArraysRoot : public ExternalArrayVisitor {
+public:
+    ExternalArraysRoot() : m_memoryClassInfo(0) { }
+
+    void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+    {
+        MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::ExternalArrays);
+        m_memoryClassInfo = &info;
+        ScriptProfiler::visitExternalArrays(const_cast<ExternalArraysRoot*>(this));
+        m_memoryClassInfo = 0;
+        info.ignoreMember(m_memoryClassInfo);
+    }
+
+private:
+    virtual void visitJSExternalArray(ArrayBufferView* arrayBufferView)
+    {
+        m_memoryClassInfo->addMember(arrayBufferView, "externalArray", WTF::RetainingPointer);
+    }
+
+    mutable MemoryClassInfo* m_memoryClassInfo;
+};
+
+} // namespace
+
+InspectorMemoryAgent::~InspectorMemoryAgent()
+{
+}
+
+void InspectorMemoryAgent::getDOMCounters(ErrorString*, int* documents, int* nodes, int* jsEventListeners)
+{
+    *documents = InspectorCounters::counterValue(InspectorCounters::DocumentCounter);
+    *nodes = InspectorCounters::counterValue(InspectorCounters::NodeCounter);
+    *jsEventListeners = ThreadLocalInspectorCounters::current().counterValue(ThreadLocalInspectorCounters::JSEventListenerCounter);
+}
+
+static void reportJSHeapInfo(WTF::MemoryInstrumentationClient& memoryInstrumentationClient)
+{
+    HeapInfo info;
+    ScriptGCEvent::getHeapSize(info);
+
+    memoryInstrumentationClient.countObjectSize(0, WebCoreMemoryTypes::JSHeapUsed, info.usedJSHeapSize);
+    memoryInstrumentationClient.countObjectSize(0, WebCoreMemoryTypes::JSHeapUnused, info.totalJSHeapSize - info.usedJSHeapSize);
+}
+
+static void reportRenderTreeInfo(WTF::MemoryInstrumentationClient& memoryInstrumentationClient, Page* page)
+{
+    ArenaSize arenaSize = page->renderTreeSize();
+
+    memoryInstrumentationClient.countObjectSize(0, WebCoreMemoryTypes::RenderTreeUsed, arenaSize.treeSize);
+    memoryInstrumentationClient.countObjectSize(0, WebCoreMemoryTypes::RenderTreeUnused, arenaSize.allocated - arenaSize.treeSize);
+}
+
+namespace {
+
+class DOMTreesIterator : public WrappedNodeVisitor {
+public:
+    DOMTreesIterator(MemoryInstrumentationImpl& memoryInstrumentation, Page* page)
+        : m_page(page)
+        , m_memoryInstrumentation(memoryInstrumentation)
+    {
+    }
+
+    virtual void visitNode(Node* node) OVERRIDE
+    {
+        if (node->document() && node->document()->frame() && m_page != node->document()->frame()->page())
+            return;
+
+        while (Node* parentNode = node->parentNode())
+            node = parentNode;
+
+        m_memoryInstrumentation.addRootObject(node);
+    }
+
+    void visitFrame(Frame* frame)
+    {
+        m_memoryInstrumentation.addRootObject(frame);
+    }
+
+    void visitBindings()
+    {
+        ScriptProfiler::collectBindingMemoryInfo(&m_memoryInstrumentation);
+    }
+
+    void visitMemoryCache()
+    {
+        m_memoryInstrumentation.addRootObject(memoryCache());
+    }
+
+
+private:
+    Page* m_page;
+    MemoryInstrumentationImpl& m_memoryInstrumentation;
+};
+
+}
+
+static void collectDomTreeInfo(MemoryInstrumentationImpl& memoryInstrumentation, Page* page)
+{
+    ExternalStringsRoot stringsRoot;
+    memoryInstrumentation.addRootObject(stringsRoot);
+
+    ExternalArraysRoot arraysRoot;
+    memoryInstrumentation.addRootObject(arraysRoot);
+
+    DOMTreesIterator domTreesIterator(memoryInstrumentation, page);
+
+    ScriptProfiler::visitNodeWrappers(&domTreesIterator);
+
+    // Make sure all documents reachable from the main frame are accounted.
+    for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
+        if (Document* doc = frame->document()) {
+            domTreesIterator.visitNode(doc);
+            domTreesIterator.visitFrame(frame);
+        }
+    }
+
+    domTreesIterator.visitBindings();
+    domTreesIterator.visitMemoryCache();
+}
+
+static void addPlatformComponentsInfo(TypeNameToSizeMap* memoryInfo)
+{
+    Vector<MemoryUsageSupport::ComponentInfo> components;
+    MemoryUsageSupport::memoryUsageByComponents(components);
+    for (Vector<MemoryUsageSupport::ComponentInfo>::iterator it = components.begin(); it != components.end(); ++it)
+        memoryInfo->add(it->m_name, it->m_sizeInBytes);
+}
+
+static void addMemoryInstrumentationDebugData(MemoryInstrumentationClientImpl* client, TypeNameToSizeMap* memoryInfo)
+{
+    if (client->checkInstrumentedObjects()) {
+        memoryInfo->add("InstrumentedObjectsCount", client->totalCountedObjects());
+        memoryInfo->add("InstrumentedButNotAllocatedObjectsCount", client->totalObjectsNotInAllocatedSet());
+    }
+}
+
+void InspectorMemoryAgent::getProcessMemoryDistributionMap(TypeNameToSizeMap* memoryInfo)
+{
+    getProcessMemoryDistributionImpl(false, memoryInfo);
+}
+
+void InspectorMemoryAgent::getProcessMemoryDistribution(ErrorString*, const bool* reportGraph, RefPtr<InspectorMemoryBlock>& processMemory, RefPtr<InspectorObject>& graphMetaInformation)
+{
+    TypeNameToSizeMap memoryInfo;
+    graphMetaInformation = getProcessMemoryDistributionImpl(reportGraph && *reportGraph, &memoryInfo);
+
+    MemoryUsageStatsGenerator statsGenerator;
+    RefPtr<InspectorMemoryBlocks> children = InspectorMemoryBlocks::create();
+    statsGenerator.dump(memoryInfo, children.get());
+
+    processMemory = InspectorMemoryBlock::create().setName(WebCoreMemoryTypes::ProcessPrivateMemory);
+    processMemory->setChildren(children);
+
+    size_t privateBytes = 0;
+    size_t sharedBytes = 0;
+    MemoryUsageSupport::processMemorySizesInBytes(&privateBytes, &sharedBytes);
+    processMemory->setSize(privateBytes);
+}
+
+void InspectorMemoryAgent::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Inspector);
+    InspectorBaseAgent<InspectorMemoryAgent>::reportMemoryUsage(memoryObjectInfo);
+    info.addWeakPointer(m_inspectorClient);
+    info.addMember(m_page, "page");
+}
+
+namespace {
+
+class FrontendWrapper : public HeapGraphSerializer::Client {
+public:
+    explicit FrontendWrapper(InspectorFrontend::Memory* frontend) : m_frontend(frontend) { }
+    virtual void addNativeSnapshotChunk(PassRefPtr<TypeBuilder::Memory::HeapSnapshotChunk> heapSnapshotChunk) OVERRIDE
+    {
+        m_frontend->addNativeSnapshotChunk(heapSnapshotChunk);
+    }
+private:
+    InspectorFrontend::Memory* m_frontend;
+};
+
+}
+
+PassRefPtr<InspectorObject> InspectorMemoryAgent::getProcessMemoryDistributionImpl(bool reportGraph, TypeNameToSizeMap* memoryInfo)
+{
+    RefPtr<InspectorObject> meta;
+    OwnPtr<HeapGraphSerializer> graphSerializer;
+    OwnPtr<FrontendWrapper> frontendWrapper;
+
+    if (reportGraph) {
+        frontendWrapper = adoptPtr(new FrontendWrapper(m_frontend));
+        graphSerializer = adoptPtr(new HeapGraphSerializer(frontendWrapper.get()));
+    }
+
+    MemoryInstrumentationClientImpl memoryInstrumentationClient(graphSerializer.get());
+    m_inspectorClient->getAllocatedObjects(memoryInstrumentationClient.allocatedObjects());
+    MemoryInstrumentationImpl memoryInstrumentation(&memoryInstrumentationClient);
+
+    reportJSHeapInfo(memoryInstrumentationClient);
+    reportRenderTreeInfo(memoryInstrumentationClient, m_page);
+    collectDomTreeInfo(memoryInstrumentation, m_page); // FIXME: collect for all pages?
+
+    PlatformMemoryInstrumentation::reportStaticMembersMemoryUsage(&memoryInstrumentation);
+    WebCoreMemoryInstrumentation::reportStaticMembersMemoryUsage(&memoryInstrumentation);
+
+    memoryInstrumentation.addRootObject(this);
+    memoryInstrumentation.addRootObject(memoryInstrumentation);
+    memoryInstrumentation.addRootObject(memoryInstrumentationClient);
+    if (graphSerializer) {
+        memoryInstrumentation.addRootObject(graphSerializer.get());
+        meta = graphSerializer->finish();
+        graphSerializer.release(); // Release it earlier than frontendWrapper
+        frontendWrapper.release();
+    }
+
+    m_inspectorClient->dumpUncountedAllocatedObjects(memoryInstrumentationClient.countedObjects());
+
+    *memoryInfo = memoryInstrumentationClient.sizesMap();
+    addPlatformComponentsInfo(memoryInfo);
+    addMemoryInstrumentationDebugData(&memoryInstrumentationClient, memoryInfo);
+    return meta.release();
+}
+
+InspectorMemoryAgent::InspectorMemoryAgent(InstrumentingAgents* instrumentingAgents, InspectorClient* client, InspectorCompositeState* state, Page* page)
+    : InspectorBaseAgent<InspectorMemoryAgent>("Memory", instrumentingAgents, state)
+    , m_inspectorClient(client)
+    , m_page(page)
+    , m_frontend(0)
+{
+}
+
+void InspectorMemoryAgent::setFrontend(InspectorFrontend* frontend)
+{
+    ASSERT(!m_frontend);
+    m_frontend = frontend->memory();
+}
+
+void InspectorMemoryAgent::clearFrontend()
+{
+    m_frontend = 0;
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorMemoryAgent.h b/Source/core/inspector/InspectorMemoryAgent.h
new file mode 100644
index 0000000..0f580c3
--- /dev/null
+++ b/Source/core/inspector/InspectorMemoryAgent.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef InspectorMemoryAgent_h
+#define InspectorMemoryAgent_h
+
+
+#include "InspectorFrontend.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class InspectorClient;
+class InspectorDOMStorageAgent;
+class InspectorState;
+class InstrumentingAgents;
+class Page;
+
+typedef String ErrorString;
+
+class InspectorMemoryAgent : public InspectorBaseAgent<InspectorMemoryAgent>, public InspectorBackendDispatcher::MemoryCommandHandler {
+    WTF_MAKE_NONCOPYABLE(InspectorMemoryAgent);
+public:
+    typedef Vector<OwnPtr<InspectorBaseAgentInterface> > InspectorAgents;
+
+    static PassOwnPtr<InspectorMemoryAgent> create(InstrumentingAgents* instrumentingAgents, InspectorClient* client, InspectorCompositeState* state, Page* page)
+    {
+        return adoptPtr(new InspectorMemoryAgent(instrumentingAgents, client, state, page));
+    }
+    virtual ~InspectorMemoryAgent();
+
+    virtual void getDOMCounters(ErrorString*, int* documents, int* nodes, int* jsEventListeners);
+    virtual void getProcessMemoryDistribution(ErrorString*, const bool* reportGraph, RefPtr<TypeBuilder::Memory::MemoryBlock>& out_processMemory, RefPtr<InspectorObject>& graphMetaInformation);
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
+    void getProcessMemoryDistributionMap(HashMap<String, size_t>* memoryInfo);
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+
+private:
+    InspectorMemoryAgent(InstrumentingAgents*, InspectorClient*, InspectorCompositeState*, Page*);
+
+    PassRefPtr<InspectorObject> getProcessMemoryDistributionImpl(bool reportGraph, HashMap<String, size_t>* memoryInfo);
+
+    InspectorClient* m_inspectorClient;
+    Page* m_page;
+    InspectorFrontend::Memory* m_frontend;
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorMemoryAgent_h)
diff --git a/Source/core/inspector/InspectorOverlay.cpp b/Source/core/inspector/InspectorOverlay.cpp
new file mode 100644
index 0000000..efd9e98
--- /dev/null
+++ b/Source/core/inspector/InspectorOverlay.cpp
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2011 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorOverlay.h"
+
+#include "InspectorOverlayPage.h"
+#include "bindings/v8/ScriptController.h"
+#include "bindings/v8/ScriptSourceCode.h"
+#include "bindings/v8/ScriptValue.h"
+#include "core/dom/Element.h"
+#include "core/dom/Node.h"
+#include "core/dom/StyledElement.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/inspector/InspectorClient.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/loader/DocumentLoader.h"
+#include "core/loader/EmptyClients.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/RenderBoxModelObject.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderObject.h"
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+namespace {
+
+Path quadToPath(const FloatQuad& quad)
+{
+    Path quadPath;
+    quadPath.moveTo(quad.p1());
+    quadPath.addLineTo(quad.p2());
+    quadPath.addLineTo(quad.p3());
+    quadPath.addLineTo(quad.p4());
+    quadPath.closeSubpath();
+    return quadPath;
+}
+
+void drawOutlinedQuad(GraphicsContext* context, const FloatQuad& quad, const Color& fillColor, const Color& outlineColor)
+{
+    static const int outlineThickness = 2;
+
+    Path quadPath = quadToPath(quad);
+
+    // Clip out the quad, then draw with a 2px stroke to get a pixel
+    // of outline (because inflating a quad is hard)
+    {
+        context->save();
+        context->clipOut(quadPath);
+
+        context->setStrokeThickness(outlineThickness);
+        context->setStrokeColor(outlineColor, ColorSpaceDeviceRGB);
+        context->strokePath(quadPath);
+
+        context->restore();
+    }
+
+    // Now do the fill
+    context->setFillColor(fillColor, ColorSpaceDeviceRGB);
+    context->fillPath(quadPath);
+}
+
+static void contentsQuadToPage(const FrameView* mainView, const FrameView* view, FloatQuad& quad)
+{
+    quad.setP1(view->contentsToRootView(roundedIntPoint(quad.p1())));
+    quad.setP2(view->contentsToRootView(roundedIntPoint(quad.p2())));
+    quad.setP3(view->contentsToRootView(roundedIntPoint(quad.p3())));
+    quad.setP4(view->contentsToRootView(roundedIntPoint(quad.p4())));
+    quad += mainView->scrollOffset();
+}
+
+static void buildNodeHighlight(Node* node, const HighlightConfig& highlightConfig, Highlight* highlight)
+{
+    RenderObject* renderer = node->renderer();
+    Frame* containingFrame = node->document()->frame();
+
+    if (!renderer || !containingFrame)
+        return;
+
+    highlight->setDataFromConfig(highlightConfig);
+    FrameView* containingView = containingFrame->view();
+    FrameView* mainView = containingFrame->page()->mainFrame()->view();
+    IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
+    boundingBox.move(mainView->scrollOffset());
+    IntRect titleAnchorBox = boundingBox;
+
+    // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
+#if ENABLE(SVG)
+    bool isSVGRenderer = renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot();
+#else
+    bool isSVGRenderer = false;
+#endif
+
+    if (isSVGRenderer) {
+        highlight->type = HighlightTypeRects;
+        renderer->absoluteQuads(highlight->quads);
+        for (size_t i = 0; i < highlight->quads.size(); ++i)
+            contentsQuadToPage(mainView, containingView, highlight->quads[i]);
+    } else if (renderer->isBox() || renderer->isRenderInline()) {
+        LayoutRect contentBox;
+        LayoutRect paddingBox;
+        LayoutRect borderBox;
+        LayoutRect marginBox;
+
+        if (renderer->isBox()) {
+            RenderBox* renderBox = toRenderBox(renderer);
+
+            // RenderBox returns the "pure" content area box, exclusive of the scrollbars (if present), which also count towards the content area in CSS.
+            contentBox = renderBox->contentBoxRect();
+            contentBox.setWidth(contentBox.width() + renderBox->verticalScrollbarWidth());
+            contentBox.setHeight(contentBox.height() + renderBox->horizontalScrollbarHeight());
+
+            paddingBox = LayoutRect(contentBox.x() - renderBox->paddingLeft(), contentBox.y() - renderBox->paddingTop(),
+                    contentBox.width() + renderBox->paddingLeft() + renderBox->paddingRight(), contentBox.height() + renderBox->paddingTop() + renderBox->paddingBottom());
+            borderBox = LayoutRect(paddingBox.x() - renderBox->borderLeft(), paddingBox.y() - renderBox->borderTop(),
+                    paddingBox.width() + renderBox->borderLeft() + renderBox->borderRight(), paddingBox.height() + renderBox->borderTop() + renderBox->borderBottom());
+            marginBox = LayoutRect(borderBox.x() - renderBox->marginLeft(), borderBox.y() - renderBox->marginTop(),
+                    borderBox.width() + renderBox->marginWidth(), borderBox.height() + renderBox->marginHeight());
+        } else {
+            RenderInline* renderInline = toRenderInline(renderer);
+
+            // RenderInline's bounding box includes paddings and borders, excludes margins.
+            borderBox = renderInline->linesBoundingBox();
+            paddingBox = LayoutRect(borderBox.x() + renderInline->borderLeft(), borderBox.y() + renderInline->borderTop(),
+                    borderBox.width() - renderInline->borderLeft() - renderInline->borderRight(), borderBox.height() - renderInline->borderTop() - renderInline->borderBottom());
+            contentBox = LayoutRect(paddingBox.x() + renderInline->paddingLeft(), paddingBox.y() + renderInline->paddingTop(),
+                    paddingBox.width() - renderInline->paddingLeft() - renderInline->paddingRight(), paddingBox.height() - renderInline->paddingTop() - renderInline->paddingBottom());
+            // Ignore marginTop and marginBottom for inlines.
+            marginBox = LayoutRect(borderBox.x() - renderInline->marginLeft(), borderBox.y(),
+                    borderBox.width() + renderInline->marginWidth(), borderBox.height());
+        }
+
+        FloatQuad absContentQuad = renderer->localToAbsoluteQuad(FloatRect(contentBox));
+        FloatQuad absPaddingQuad = renderer->localToAbsoluteQuad(FloatRect(paddingBox));
+        FloatQuad absBorderQuad = renderer->localToAbsoluteQuad(FloatRect(borderBox));
+        FloatQuad absMarginQuad = renderer->localToAbsoluteQuad(FloatRect(marginBox));
+
+        contentsQuadToPage(mainView, containingView, absContentQuad);
+        contentsQuadToPage(mainView, containingView, absPaddingQuad);
+        contentsQuadToPage(mainView, containingView, absBorderQuad);
+        contentsQuadToPage(mainView, containingView, absMarginQuad);
+
+        titleAnchorBox = absMarginQuad.enclosingBoundingBox();
+
+        highlight->type = HighlightTypeNode;
+        highlight->quads.append(absMarginQuad);
+        highlight->quads.append(absBorderQuad);
+        highlight->quads.append(absPaddingQuad);
+        highlight->quads.append(absContentQuad);
+    }
+}
+
+static void buildQuadHighlight(Page* page, const FloatQuad& quad, const HighlightConfig& highlightConfig, Highlight *highlight)
+{
+    if (!page)
+        return;
+    highlight->setDataFromConfig(highlightConfig);
+    highlight->type = HighlightTypeRects;
+    highlight->quads.append(quad);
+}
+
+} // anonymous namespace
+
+InspectorOverlay::InspectorOverlay(Page* page, InspectorClient* client)
+    : m_page(page)
+    , m_client(client)
+    , m_drawViewSize(false)
+    , m_timer(this, &InspectorOverlay::onTimer)
+{
+}
+
+InspectorOverlay::~InspectorOverlay()
+{
+}
+
+void InspectorOverlay::paint(GraphicsContext& context)
+{
+    if (m_pausedInDebuggerMessage.isNull() && !m_highlightNode && !m_highlightQuad && m_size.isEmpty() && !m_drawViewSize)
+        return;
+    GraphicsContextStateSaver stateSaver(context);
+    FrameView* view = overlayPage()->mainFrame()->view();
+    ASSERT(!view->needsLayout());
+    view->paint(&context, IntRect(0, 0, view->width(), view->height()));
+}
+
+void InspectorOverlay::drawOutline(GraphicsContext* context, const LayoutRect& rect, const Color& color)
+{
+    FloatRect outlineRect = rect;
+    drawOutlinedQuad(context, outlineRect, Color(), color);
+}
+
+void InspectorOverlay::getHighlight(Highlight* highlight) const
+{
+    if (!m_highlightNode && !m_highlightQuad)
+        return;
+
+    highlight->type = HighlightTypeRects;
+    if (m_highlightNode)
+        buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, highlight);
+    else
+        buildQuadHighlight(m_page, *m_highlightQuad, m_quadHighlightConfig, highlight);
+}
+
+void InspectorOverlay::resize(const IntSize& size)
+{
+    m_size = size;
+    update();
+}
+
+void InspectorOverlay::setPausedInDebuggerMessage(const String* message)
+{
+    m_pausedInDebuggerMessage = message ? *message : String();
+    update();
+}
+
+void InspectorOverlay::hideHighlight()
+{
+    m_highlightNode.clear();
+    m_eventTargetNode.clear();
+    m_highlightQuad.clear();
+    update();
+}
+
+void InspectorOverlay::highlightNode(Node* node, Node* eventTarget, const HighlightConfig& highlightConfig)
+{
+    m_nodeHighlightConfig = highlightConfig;
+    m_highlightNode = node;
+    m_eventTargetNode = eventTarget;
+    update();
+}
+
+void InspectorOverlay::highlightQuad(PassOwnPtr<FloatQuad> quad, const HighlightConfig& highlightConfig)
+{
+    m_quadHighlightConfig = highlightConfig;
+    m_highlightQuad = quad;
+    update();
+}
+
+void InspectorOverlay::showAndHideViewSize()
+{
+    m_drawViewSize = true;
+    update();
+    m_timer.startOneShot(1);
+}
+
+Node* InspectorOverlay::highlightedNode() const
+{
+    return m_highlightNode.get();
+}
+
+void InspectorOverlay::update()
+{
+    if (!m_highlightNode && !m_eventTargetNode && !m_highlightQuad && m_pausedInDebuggerMessage.isNull() && m_size.isEmpty() && !m_drawViewSize) {
+        m_client->hideHighlight();
+        return;
+    }
+
+    FrameView* view = m_page->mainFrame()->view();
+    if (!view)
+        return;
+    FloatRect viewRect = view->visibleContentRect();
+    FrameView* overlayView = overlayPage()->mainFrame()->view();
+    IntSize viewportSize = enclosingIntRect(viewRect).size();
+    IntSize frameViewFullSize = enclosingIntRect(view->visibleContentRect(ScrollableArea::IncludeScrollbars)).size();
+    IntSize size = m_size.isEmpty() ? frameViewFullSize : m_size;
+    size.scale(m_page->pageScaleFactor());
+    overlayView->resize(size);
+
+    // Clear canvas and paint things.
+    reset(size, m_size.isEmpty() ? IntSize() : frameViewFullSize, viewRect.x(), viewRect.y());
+
+    // Include scrollbars to avoid masking them by the gutter.
+    drawGutter();
+    drawNodeHighlight();
+    drawQuadHighlight();
+    drawPausedInDebuggerMessage();
+    drawViewSize();
+
+    // Position DOM elements.
+    overlayPage()->mainFrame()->document()->recalcStyle(Node::Force);
+    if (overlayView->needsLayout())
+        overlayView->layout();
+
+    // Kick paint.
+    m_client->highlight();
+}
+
+void InspectorOverlay::hide()
+{
+    m_timer.stop();
+    m_highlightNode.clear();
+    m_eventTargetNode.clear();
+    m_highlightQuad.clear();
+    m_pausedInDebuggerMessage = String();
+    m_size = IntSize();
+    m_drawViewSize = false;
+    update();
+}
+
+static PassRefPtr<InspectorObject> buildObjectForPoint(const FloatPoint& point)
+{
+    RefPtr<InspectorObject> object = InspectorObject::create();
+    object->setNumber("x", point.x());
+    object->setNumber("y", point.y());
+    return object.release();
+}
+
+static PassRefPtr<InspectorArray> buildArrayForQuad(const FloatQuad& quad)
+{
+    RefPtr<InspectorArray> array = InspectorArray::create();
+    array->pushObject(buildObjectForPoint(quad.p1()));
+    array->pushObject(buildObjectForPoint(quad.p2()));
+    array->pushObject(buildObjectForPoint(quad.p3()));
+    array->pushObject(buildObjectForPoint(quad.p4()));
+    return array.release();
+}
+
+static PassRefPtr<InspectorObject> buildObjectForHighlight(const Highlight& highlight)
+{
+    RefPtr<InspectorObject> object = InspectorObject::create();
+    RefPtr<InspectorArray> array = InspectorArray::create();
+    for (size_t i = 0; i < highlight.quads.size(); ++i)
+        array->pushArray(buildArrayForQuad(highlight.quads[i]));
+    object->setArray("quads", array.release());
+    object->setBoolean("showRulers", highlight.showRulers);
+    object->setString("contentColor", highlight.contentColor.serialized());
+    object->setString("contentOutlineColor", highlight.contentOutlineColor.serialized());
+    object->setString("paddingColor", highlight.paddingColor.serialized());
+    object->setString("borderColor", highlight.borderColor.serialized());
+    object->setString("marginColor", highlight.marginColor.serialized());
+    object->setString("eventTargetColor", highlight.eventTargetColor.serialized());
+    return object.release();
+}
+
+static PassRefPtr<InspectorObject> buildObjectForSize(const IntSize& size)
+{
+    RefPtr<InspectorObject> result = InspectorObject::create();
+    result->setNumber("width", size.width());
+    result->setNumber("height", size.height());
+    return result.release();
+}
+
+void InspectorOverlay::drawGutter()
+{
+    evaluateInOverlay("drawGutter", "");
+}
+
+void InspectorOverlay::drawNodeHighlight()
+{
+    if (!m_highlightNode)
+        return;
+
+    Highlight highlight;
+    buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, &highlight);
+    if (m_eventTargetNode) {
+        Highlight eventTargetHighlight;
+        buildNodeHighlight(m_eventTargetNode.get(), m_nodeHighlightConfig, &eventTargetHighlight);
+        highlight.quads.append(eventTargetHighlight.quads[1]); // Add border from eventTargetNode to highlight.
+    }
+    RefPtr<InspectorObject> highlightObject = buildObjectForHighlight(highlight);
+
+    Node* node = m_highlightNode.get();
+    if (node->isElementNode() && m_nodeHighlightConfig.showInfo && node->renderer() && node->document()->frame()) {
+        RefPtr<InspectorObject> elementInfo = InspectorObject::create();
+        Element* element = toElement(node);
+        bool isXHTML = element->document()->isXHTMLDocument();
+        elementInfo->setString("tagName", isXHTML ? element->nodeName() : element->nodeName().lower());
+        elementInfo->setString("idValue", element->getIdAttribute());
+        HashSet<AtomicString> usedClassNames;
+        if (element->hasClass() && element->isStyledElement()) {
+            StringBuilder classNames;
+            const SpaceSplitString& classNamesString = static_cast<StyledElement*>(element)->classNames();
+            size_t classNameCount = classNamesString.size();
+            for (size_t i = 0; i < classNameCount; ++i) {
+                const AtomicString& className = classNamesString[i];
+                if (usedClassNames.contains(className))
+                    continue;
+                usedClassNames.add(className);
+                classNames.append('.');
+                classNames.append(className);
+            }
+            elementInfo->setString("className", classNames.toString());
+        }
+
+        RenderObject* renderer = node->renderer();
+        Frame* containingFrame = node->document()->frame();
+        FrameView* containingView = containingFrame->view();
+        IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect()));
+        RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
+        elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), modelObject) : boundingBox.width()));
+        elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), modelObject) : boundingBox.height()));
+        highlightObject->setObject("elementInfo", elementInfo.release());
+    }
+    evaluateInOverlay("drawNodeHighlight", highlightObject);
+}
+
+void InspectorOverlay::drawQuadHighlight()
+{
+    if (!m_highlightQuad)
+        return;
+
+    Highlight highlight;
+    buildQuadHighlight(m_page, *m_highlightQuad, m_quadHighlightConfig, &highlight);
+    evaluateInOverlay("drawQuadHighlight", buildObjectForHighlight(highlight));
+}
+
+void InspectorOverlay::drawPausedInDebuggerMessage()
+{
+    if (!m_pausedInDebuggerMessage.isNull())
+        evaluateInOverlay("drawPausedInDebuggerMessage", m_pausedInDebuggerMessage);
+}
+
+void InspectorOverlay::drawViewSize()
+{
+    if (m_drawViewSize)
+        evaluateInOverlay("drawViewSize", m_pausedInDebuggerMessage);
+}
+
+Page* InspectorOverlay::overlayPage()
+{
+    if (m_overlayPage)
+        return m_overlayPage.get();
+
+    static FrameLoaderClient* dummyFrameLoaderClient =  new EmptyFrameLoaderClient;
+    Page::PageClients pageClients;
+    fillWithEmptyClients(pageClients);
+    m_overlayPage = adoptPtr(new Page(pageClients));
+
+    Settings* settings = m_page->settings();
+    Settings* overlaySettings = m_overlayPage->settings();
+
+    overlaySettings->setStandardFontFamily(settings->standardFontFamily());
+    overlaySettings->setSerifFontFamily(settings->serifFontFamily());
+    overlaySettings->setSansSerifFontFamily(settings->sansSerifFontFamily());
+    overlaySettings->setCursiveFontFamily(settings->cursiveFontFamily());
+    overlaySettings->setFantasyFontFamily(settings->fantasyFontFamily());
+    overlaySettings->setPictographFontFamily(settings->pictographFontFamily());
+    overlaySettings->setMinimumFontSize(settings->minimumFontSize());
+    overlaySettings->setMinimumLogicalFontSize(settings->minimumLogicalFontSize());
+    overlaySettings->setMediaEnabled(false);
+    overlaySettings->setScriptEnabled(true);
+    overlaySettings->setPluginsEnabled(false);
+
+    RefPtr<Frame> frame = Frame::create(m_overlayPage.get(), 0, dummyFrameLoaderClient);
+    frame->setView(FrameView::create(frame.get()));
+    frame->init();
+    FrameLoader* loader = frame->loader();
+    frame->view()->setCanHaveScrollbars(false);
+    frame->view()->setTransparent(true);
+    ASSERT(loader->activeDocumentLoader());
+    loader->activeDocumentLoader()->writer()->setMIMEType("text/html");
+    loader->activeDocumentLoader()->writer()->begin();
+    loader->activeDocumentLoader()->writer()->addData(reinterpret_cast<const char*>(InspectorOverlayPage_html), sizeof(InspectorOverlayPage_html));
+    loader->activeDocumentLoader()->writer()->end();
+
+#if OS(WINDOWS)
+    evaluateInOverlay("setPlatform", "windows");
+#elif OS(DARWIN)
+    evaluateInOverlay("setPlatform", "mac");
+#elif OS(UNIX)
+    evaluateInOverlay("setPlatform", "linux");
+#endif
+
+    return m_overlayPage.get();
+}
+
+void InspectorOverlay::reset(const IntSize& viewportSize, const IntSize& frameViewFullSize, int scrollX, int scrollY)
+{
+    RefPtr<InspectorObject> resetData = InspectorObject::create();
+    resetData->setNumber("pageScaleFactor", m_page->pageScaleFactor());
+    resetData->setNumber("deviceScaleFactor", m_page->deviceScaleFactor());
+    resetData->setObject("viewportSize", buildObjectForSize(viewportSize));
+    resetData->setObject("frameViewFullSize", buildObjectForSize(frameViewFullSize));
+    resetData->setNumber("pageZoomFactor", m_page->mainFrame()->pageZoomFactor());
+    resetData->setNumber("scrollX", scrollX);
+    resetData->setNumber("scrollY", scrollY);
+    evaluateInOverlay("reset", resetData.release());
+}
+
+void InspectorOverlay::evaluateInOverlay(const String& method, const String& argument)
+{
+    RefPtr<InspectorArray> command = InspectorArray::create();
+    command->pushString(method);
+    command->pushString(argument);
+    overlayPage()->mainFrame()->script()->evaluate(ScriptSourceCode(makeString("dispatch(", command->toJSONString(), ")")));
+}
+
+void InspectorOverlay::evaluateInOverlay(const String& method, PassRefPtr<InspectorValue> argument)
+{
+    RefPtr<InspectorArray> command = InspectorArray::create();
+    command->pushString(method);
+    command->pushValue(argument);
+    overlayPage()->mainFrame()->script()->evaluate(ScriptSourceCode(makeString("dispatch(", command->toJSONString(), ")")));
+}
+
+void InspectorOverlay::onTimer(Timer<InspectorOverlay>*)
+{
+    m_drawViewSize = false;
+    update();
+}
+
+void InspectorOverlay::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::InspectorOverlay);
+    info.addMember(m_page, "page");
+    info.addWeakPointer(m_client);
+    info.addMember(m_pausedInDebuggerMessage, "pausedInDebuggerMessage");
+    info.addMember(m_highlightNode, "highlightNode");
+    info.addMember(m_nodeHighlightConfig, "nodeHighlightConfig");
+    info.addMember(m_highlightQuad, "highlightQuad");
+    info.addMember(m_overlayPage, "overlayPage");
+    info.addMember(m_quadHighlightConfig, "quadHighlightConfig");
+    info.addMember(m_size, "size");
+}
+
+void InspectorOverlay::freePage()
+{
+    m_overlayPage.clear();
+    m_timer.stop();
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorOverlay.h b/Source/core/inspector/InspectorOverlay.h
new file mode 100644
index 0000000..25165f9
--- /dev/null
+++ b/Source/core/inspector/InspectorOverlay.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2011 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef InspectorOverlay_h
+#define InspectorOverlay_h
+
+#include "core/platform/graphics/Color.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/LayoutRect.h"
+#include "core/platform/Timer.h"
+
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Color;
+class GraphicsContext;
+class InspectorClient;
+class InspectorValue;
+class IntRect;
+class Node;
+class Page;
+
+struct HighlightConfig {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    Color content;
+    Color contentOutline;
+    Color padding;
+    Color border;
+    Color margin;
+    Color eventTarget;
+    bool showInfo;
+    bool showRulers;
+};
+
+enum HighlightType {
+    HighlightTypeNode,
+    HighlightTypeRects,
+};
+
+struct Highlight {
+    Highlight()
+        : type(HighlightTypeNode)
+        , showRulers(false)
+    {
+    }
+
+    void setDataFromConfig(const HighlightConfig& highlightConfig)
+    {
+        contentColor = highlightConfig.content;
+        contentOutlineColor = highlightConfig.contentOutline;
+        paddingColor = highlightConfig.padding;
+        borderColor = highlightConfig.border;
+        marginColor = highlightConfig.margin;
+        eventTargetColor = highlightConfig.eventTarget;
+        showRulers = highlightConfig.showRulers;
+    }
+
+    Color contentColor;
+    Color contentOutlineColor;
+    Color paddingColor;
+    Color borderColor;
+    Color marginColor;
+    Color eventTargetColor;
+
+    // When the type is Node, there are 4 or 5 quads (margin, border, padding, content, optional eventTarget).
+    // When the type is Rects, this is just a list of quads.
+    HighlightType type;
+    Vector<FloatQuad> quads;
+    bool showRulers;
+};
+
+class InspectorOverlay {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<InspectorOverlay> create(Page* page, InspectorClient* client)
+    {
+        return adoptPtr(new InspectorOverlay(page, client));
+    }
+    ~InspectorOverlay();
+
+    void update();
+    void hide();
+    void paint(GraphicsContext&);
+    void drawOutline(GraphicsContext*, const LayoutRect&, const Color&);
+    void getHighlight(Highlight*) const;
+    void resize(const IntSize&);
+
+    void setPausedInDebuggerMessage(const String*);
+
+    void hideHighlight();
+    void highlightNode(Node*, Node* eventTarget, const HighlightConfig&);
+    void highlightQuad(PassOwnPtr<FloatQuad>, const HighlightConfig&);
+    void showAndHideViewSize();
+
+    Node* highlightedNode() const;
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+    void freePage();
+private:
+    InspectorOverlay(Page*, InspectorClient*);
+
+    void drawGutter();
+    void drawNodeHighlight();
+    void drawQuadHighlight();
+    void drawPausedInDebuggerMessage();
+    void drawViewSize();
+
+    Page* overlayPage();
+    void reset(const IntSize& viewportSize, const IntSize& frameViewFullSize, int scrollX, int scrollY);
+    void evaluateInOverlay(const String& method, const String& argument);
+    void evaluateInOverlay(const String& method, PassRefPtr<InspectorValue> argument);
+    void onTimer(Timer<InspectorOverlay>*);
+
+    Page* m_page;
+    InspectorClient* m_client;
+    String m_pausedInDebuggerMessage;
+    RefPtr<Node> m_highlightNode;
+    RefPtr<Node> m_eventTargetNode;
+    HighlightConfig m_nodeHighlightConfig;
+    OwnPtr<FloatQuad> m_highlightQuad;
+    OwnPtr<Page> m_overlayPage;
+    HighlightConfig m_quadHighlightConfig;
+    IntSize m_size;
+    bool m_drawViewSize;
+    Timer<InspectorOverlay> m_timer;
+};
+
+} // namespace WebCore
+
+
+#endif // InspectorOverlay_h
diff --git a/Source/core/inspector/InspectorOverlayPage.html b/Source/core/inspector/InspectorOverlayPage.html
new file mode 100644
index 0000000..503aeb4
--- /dev/null
+++ b/Source/core/inspector/InspectorOverlayPage.html
@@ -0,0 +1,647 @@
+<!--
+ 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:
+
+ 1.  Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+ 2.  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.
+ 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+body {
+    margin: 0;
+    padding: 0;
+}
+
+body.platform-mac {
+    font-size: 11px;
+    font-family: Menlo, Monaco;
+}
+
+body.platform-windows {
+    font-size: 12px;
+    font-family: Consolas, Lucida Console;
+}
+
+body.platform-linux {
+    font-size: 11px;
+    font-family: dejavu sans mono;
+}
+
+.fill {
+    position: absolute;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+}
+
+.dimmed {
+    background-color: rgba(0, 0, 0, 0.31);
+}
+
+.message-line {
+    margin: 10px 0;
+    text-align: center;
+}
+
+.message-box {
+    background-color: rgb(255, 255, 194);
+    border: 1px solid rgb(128, 128, 128);
+    display: inline-block;
+    padding: 2px 4px;
+}
+
+.px {
+    color: rgb(128, 128, 128);
+}
+
+#element-title {
+    position: absolute;
+    z-index: 10;
+}
+
+#tag-name {
+    /* Keep this in sync with view-source.css (.webkit-html-tag-name) */
+    color: rgb(136, 18, 128);
+}
+
+#node-id {
+    /* Keep this in sync with view-source.css (.webkit-html-attribute-value) */
+    color: rgb(26, 26, 166);
+}
+
+#class-name {
+    /* Keep this in sync with view-source.css (.webkit-html-attribute-name) */
+    color: rgb(153, 69, 0);
+}
+
+#right-gutter {
+    display: none;
+    right: 0;
+    top: 0;
+    bottom: 0;
+    position: absolute;
+    background-color: darkgray;
+}
+
+#bottom-gutter {
+    display: none;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    position: absolute;
+    background-color: darkgray;
+}
+
+</style>
+<script>
+const lightGridColor = "rgba(0,0,0,0.2)";
+const darkGridColor = "rgba(0,0,0,0.7)";
+const transparentColor = "rgba(0, 0, 0, 0)";
+const gridBackgroundColor = "rgba(255, 255, 255, 0.8)";
+
+function drawPausedInDebuggerMessage(message)
+{
+    var pausedInDebugger = document.getElementById("paused-in-debugger");
+    pausedInDebugger.textContent = message;
+    pausedInDebugger.style.visibility = "visible";
+    document.body.classList.add("dimmed");
+}
+
+function _drawGrid(rulerAtRight, rulerAtBottom)
+{
+    if (window._gridPainted)
+        return;
+    window._gridPainted = true;
+
+    context.save();
+
+    var pageFactor = pageZoomFactor * pageScaleFactor;
+    function zoom(x)
+    {
+        return Math.round(x * pageFactor);
+    }
+    function unzoom(x)
+    {
+        return Math.round(x / pageFactor);
+    }
+
+    var width = canvasWidth / pageFactor;
+    var height = canvasHeight / pageFactor;
+
+    const gridSubStep = 5;
+    const gridStep = 50;
+
+    {
+        // Draw X grid background
+        context.save();
+        context.fillStyle = gridBackgroundColor;
+        if (rulerAtBottom)
+            context.fillRect(0, zoom(height) - 15, zoom(width), zoom(height));
+        else
+            context.fillRect(0, 0, zoom(width), 15);
+
+        // Clip out backgrounds intersection
+        context.globalCompositeOperation = "destination-out";
+        context.fillStyle = "red";
+        if (rulerAtRight)
+            context.fillRect(zoom(width) - 15, 0, zoom(width), zoom(height));
+        else
+            context.fillRect(0, 0, 15, zoom(height));
+        context.restore();
+
+        // Draw Y grid background
+        context.fillStyle = gridBackgroundColor;
+        if (rulerAtRight)
+            context.fillRect(zoom(width) - 15, 0, zoom(width), zoom(height));
+        else
+            context.fillRect(0, 0, 15, zoom(height));
+    }
+
+    context.lineWidth = 1;
+    context.strokeStyle = darkGridColor;
+    context.fillStyle = darkGridColor;
+    {
+        // Draw labels.
+        context.save();
+        context.translate(-scrollX, 0.5 - scrollY);
+        var maxY = height + unzoom(scrollY);
+        for (var y = 2 * gridStep; y < maxY; y += 2 * gridStep) {
+            context.save();
+            context.translate(scrollX, zoom(y));
+            context.rotate(-Math.PI / 2);
+            context.fillText(y, 2, rulerAtRight ? zoom(width) - 7 : 13);
+            context.restore();
+        }
+        context.translate(0.5, -0.5);
+        var maxX = width + unzoom(scrollX);
+        for (var x = 2 * gridStep; x < maxX; x += 2 * gridStep) {
+            context.save();
+            context.fillText(x, zoom(x) + 2, rulerAtBottom ? scrollY + zoom(height) - 7 : scrollY + 13);
+            context.restore();
+        }
+        context.restore();
+    }
+
+    {
+        // Draw vertical grid
+        context.save();
+        if (rulerAtRight) {
+            context.translate(zoom(width), 0);
+            context.scale(-1, 1);
+        }
+        context.translate(-scrollX, 0.5 - scrollY);
+        var maxY = height + unzoom(scrollY);
+        for (var y = gridStep; y < maxY; y += gridStep) {
+            context.beginPath();
+            context.moveTo(scrollX, zoom(y));
+            var markLength = (y % (gridStep * 2)) ? 5 : 8;
+            context.lineTo(scrollX + markLength, zoom(y));
+            context.stroke();
+        }
+        context.strokeStyle = lightGridColor;
+        for (var y = gridSubStep; y < maxY; y += gridSubStep) {
+            if (!(y % gridStep))
+                continue;
+            context.beginPath();
+            context.moveTo(scrollX, zoom(y));
+            context.lineTo(scrollX + gridSubStep, zoom(y));
+            context.stroke();
+        }
+        context.restore();
+    }
+
+    {
+        // Draw horizontal grid
+        context.save();
+        if (rulerAtBottom) {
+            context.translate(0, zoom(height));
+            context.scale(1, -1);
+        }
+        context.translate(0.5 - scrollX, -scrollY);
+        var maxX = width + unzoom(scrollX);
+        for (var x = gridStep; x < maxX; x += gridStep) {
+            context.beginPath();
+            context.moveTo(zoom(x), scrollY);
+            var markLength = (x % (gridStep * 2)) ? 5 : 8;
+            context.lineTo(zoom(x), scrollY + markLength);
+            context.stroke();
+        }
+        context.strokeStyle = lightGridColor;
+        for (var x = gridSubStep; x < maxX; x += gridSubStep) {
+            if (!(x % gridStep))
+                continue;
+            context.beginPath();
+            context.moveTo(zoom(x), scrollY);
+            context.lineTo(zoom(x), scrollY + gridSubStep);
+            context.stroke();
+        }
+        context.restore();
+    }
+
+    context.restore();
+}
+
+function quadToPath(quad)
+{
+    context.beginPath();
+    context.moveTo(quad[0].x, quad[0].y);
+    context.lineTo(quad[1].x, quad[1].y);
+    context.lineTo(quad[2].x, quad[2].y);
+    context.lineTo(quad[3].x, quad[3].y);
+    context.closePath();
+    return context;
+}
+
+function drawOutlinedQuad(quad, fillColor, outlineColor)
+{
+    context.save();
+    context.lineWidth = 2;
+    quadToPath(quad).clip();
+    context.fillStyle = fillColor;
+    context.fill();
+    if (outlineColor) {
+        context.strokeStyle = outlineColor;
+        context.stroke();
+    }
+    context.restore();
+}
+
+function drawOutlinedQuadWithClip(quad, clipQuad, fillColor)
+{
+    var canvas = document.getElementById("canvas");
+    context.fillStyle = fillColor;
+    context.save();
+    context.lineWidth = 0;
+    quadToPath(quad).fill();
+    context.globalCompositeOperation = "destination-out";
+    context.fillStyle = "red";
+    quadToPath(clipQuad).fill();
+    context.restore();
+}
+
+function drawUnderlyingQuad(quad, fillColor)
+{
+    context.save();
+    context.lineWidth = 2;
+    context.globalCompositeOperation = "destination-over";
+    context.fillStyle = fillColor;
+    quadToPath(quad).fill();
+    context.restore();
+}
+
+function quadEquals(quad1, quad2)
+{
+    return quad1[0].x === quad2[0].x && quad1[0].y === quad2[0].y &&
+        quad1[1].x === quad2[1].x && quad1[1].y === quad2[1].y &&
+        quad1[2].x === quad2[2].x && quad1[2].y === quad2[2].y &&
+        quad1[3].x === quad2[3].x && quad1[3].y === quad2[3].y;
+}
+
+function drawGutter()
+{
+    var frameWidth = frameViewFullSize.width;
+    var frameHeight = frameViewFullSize.height;
+
+    if (!frameWidth || document.body.offsetWidth <= frameWidth)
+        rightGutter.style.removeProperty("display");
+    else {
+        rightGutter.style.display = "block";
+        rightGutter.style.left = frameWidth + "px";
+    }
+
+    if (!frameHeight || document.body.offsetHeight <= frameHeight)
+        bottomGutter.style.removeProperty("display");
+    else {
+        bottomGutter.style.display = "block";
+        bottomGutter.style.top = frameHeight + "px";
+    }
+}
+
+function drawViewSize()
+{
+    var text = viewportSize.width + "px \u00D7 " + viewportSize.height + "px";
+    context.save();
+    context.font = "20px ";
+    switch (platform) {
+    case "windows": context.font = "14px Consolas"; break;
+    case "mac": context.font = "14px Menlo"; break;
+    case "linux": context.font = "14px dejavu sans mono"; break;
+    }
+
+    var frameWidth = frameViewFullSize.width || canvasWidth;
+    var textWidth = context.measureText(text).width;
+    context.fillStyle = gridBackgroundColor;
+    context.fillRect(frameWidth - textWidth - 12, 15, frameWidth, 25);
+    context.fillStyle = darkGridColor;
+    context.fillText(text, frameWidth - textWidth - 6, 33);
+    context.restore();
+
+    _drawGrid(false, false);
+}
+
+function reset(resetData)
+{
+    window.viewportSize = resetData.viewportSize;
+    window.frameViewFullSize = resetData.frameViewFullSize;
+    window.deviceScaleFactor = resetData.deviceScaleFactor;
+    window.pageZoomFactor = resetData.pageZoomFactor;
+    window.pageScaleFactor = resetData.pageScaleFactor;
+    window.scrollX = Math.round(resetData.scrollX * pageScaleFactor);
+    window.scrollY = Math.round(resetData.scrollY * pageScaleFactor);
+
+    window.canvas = document.getElementById("canvas");
+    window.context = canvas.getContext("2d");
+    window.rightGutter = document.getElementById("right-gutter");
+    window.bottomGutter = document.getElementById("bottom-gutter");
+
+    canvas.width = deviceScaleFactor * viewportSize.width;
+    canvas.height = deviceScaleFactor * viewportSize.height;
+    canvas.style.width = viewportSize.width + "px";
+    canvas.style.height = viewportSize.height + "px";
+    context.scale(deviceScaleFactor, deviceScaleFactor);
+    window.canvasWidth = viewportSize.width;
+    window.canvasHeight = viewportSize.height;
+
+    document.getElementById("paused-in-debugger").style.visibility = "hidden";
+    document.getElementById("element-title").style.visibility = "hidden";
+    document.body.classList.remove("dimmed");
+    window._gridPainted = false;
+}
+
+function _drawElementTitle(highlight)
+{
+    var elementInfo = highlight.elementInfo;
+    if (!highlight.elementInfo)
+        return;
+
+    document.getElementById("tag-name").textContent = elementInfo.tagName;
+    document.getElementById("node-id").textContent = elementInfo.idValue ? "#" + elementInfo.idValue : "";
+    var className = elementInfo.className;
+    if (className && className.length > 50)
+       className = className.substring(0, 50) + "\u2026";
+    document.getElementById("class-name").textContent = className || "";
+    document.getElementById("node-width").textContent = elementInfo.nodeWidth;
+    document.getElementById("node-height").textContent = elementInfo.nodeHeight;
+    var elementTitle = document.getElementById("element-title");
+
+    var marginQuad = highlight.quads[0];
+
+    var titleWidth = elementTitle.offsetWidth + 6;
+    var titleHeight = elementTitle.offsetHeight + 4;
+
+    var anchorTop = marginQuad[0].y;
+    var anchorBottom = marginQuad[3].y
+
+    const arrowHeight = 7;
+    var renderArrowUp = false;
+    var renderArrowDown = false;
+
+    var boxX = Math.max(2, marginQuad[0].x);
+    if (boxX + titleWidth > canvasWidth)
+        boxX = canvasWidth - titleWidth - 2;
+
+    var boxY;
+    if (anchorTop > canvasHeight) {
+        boxY = canvasHeight - titleHeight - arrowHeight;
+        renderArrowDown = true;
+    } else if (anchorBottom < 0) {
+        boxY = arrowHeight;
+        renderArrowUp = true;
+    } else if (anchorBottom + titleHeight + arrowHeight < canvasHeight) {
+        boxY = anchorBottom + arrowHeight - 4;
+        renderArrowUp = true;
+    } else if (anchorTop - titleHeight - arrowHeight > 0) {
+        boxY = anchorTop - titleHeight - arrowHeight + 3;
+        renderArrowDown = true;
+    } else
+        boxY = arrowHeight;
+
+    context.save();
+    context.translate(0.5, 0.5);
+    context.beginPath();
+    context.moveTo(boxX, boxY);
+    if (renderArrowUp) {
+        context.lineTo(boxX + 2 * arrowHeight, boxY);
+        context.lineTo(boxX + 3 * arrowHeight, boxY - arrowHeight);
+        context.lineTo(boxX + 4 * arrowHeight, boxY);
+    }
+    context.lineTo(boxX + titleWidth, boxY);
+    context.lineTo(boxX + titleWidth, boxY + titleHeight);
+    if (renderArrowDown) {
+        context.lineTo(boxX + 4 * arrowHeight, boxY + titleHeight);
+        context.lineTo(boxX + 3 * arrowHeight, boxY + titleHeight + arrowHeight);
+        context.lineTo(boxX + 2 * arrowHeight, boxY + titleHeight);
+    }
+    context.lineTo(boxX, boxY + titleHeight);
+    context.closePath();
+    context.fillStyle = "rgb(255, 255, 194)";
+    context.fill();
+    context.strokeStyle = "rgb(128, 128, 128)";
+    context.stroke();
+
+    context.restore();
+
+    elementTitle.style.visibility = "visible";
+    elementTitle.style.top = (boxY + 3) + "px";
+    elementTitle.style.left = (boxX + 3) + "px";
+}
+
+function _drawRulers(highlight, rulerAtRight, rulerAtBottom)
+{
+    context.save();
+    var width = canvasWidth;
+    var height = canvasHeight;
+    context.strokeStyle = "rgba(128, 128, 128, 0.3)";
+    context.lineWidth = 1;
+    context.translate(0.5, 0.5);
+    var leftmostXForY = {};
+    var rightmostXForY = {};
+    var topmostYForX = {};
+    var bottommostYForX = {};
+
+    for (var i = 0; i < highlight.quads.length; ++i) {
+        var quad = highlight.quads[i];
+        for (var j = 0; j < quad.length; ++j) {
+            var x = quad[j].x;
+            var y = quad[j].y;
+            leftmostXForY[Math.round(y)] = Math.min(leftmostXForY[y] || Number.MAX_VALUE, Math.round(quad[j].x));
+            rightmostXForY[Math.round(y)] = Math.max(rightmostXForY[y] || Number.MIN_VALUE, Math.round(quad[j].x));
+            topmostYForX[Math.round(x)] = Math.min(topmostYForX[x] || Number.MAX_VALUE, Math.round(quad[j].y));
+            bottommostYForX[Math.round(x)] = Math.max(bottommostYForX[x] || Number.MIN_VALUE, Math.round(quad[j].y));
+        }
+    }
+
+    if (rulerAtRight) {
+        for (var y in rightmostXForY) {
+            context.beginPath();
+            context.moveTo(width, y);
+            context.lineTo(rightmostXForY[y], y);
+            context.stroke();
+        }
+    } else {
+        for (var y in leftmostXForY) {
+            context.beginPath();
+            context.moveTo(0, y);
+            context.lineTo(leftmostXForY[y], y);
+            context.stroke();
+        }
+    }
+
+    if (rulerAtBottom) {
+        for (var x in bottommostYForX) {
+            context.beginPath();
+            context.moveTo(x, height);
+            context.lineTo(x, topmostYForX[x]);
+            context.stroke();
+        }
+    } else {
+        for (var x in topmostYForX) {
+            context.beginPath();
+            context.moveTo(x, 0);
+            context.lineTo(x, topmostYForX[x]);
+            context.stroke();
+        }
+    }
+
+    context.restore();
+}
+
+function drawNodeHighlight(highlight)
+{
+    {
+        for (var i = 0; i < highlight.quads.length; ++i) {
+            var quad = highlight.quads[i];
+            for (var j = 0; j < quad.length; ++j) {
+                quad[j].x = Math.round(quad[j].x * pageScaleFactor - scrollX);
+                quad[j].y = Math.round(quad[j].y * pageScaleFactor - scrollY);
+            }
+        }
+    }
+
+    if (!highlight.quads.length) {
+        if (highlight.showRulers)
+            _drawGrid(false, false);
+        return;
+    }
+
+    context.save();
+
+    var quads = highlight.quads.slice();
+    var eventTargetQuad = quads.length >= 5 ? quads.pop() : null;
+    var contentQuad = quads.pop();
+    var paddingQuad = quads.pop();
+    var borderQuad = quads.pop();
+    var marginQuad = quads.pop();
+
+    var hasContent = contentQuad && highlight.contentColor !== transparentColor || highlight.contentOutlineColor !== transparentColor;
+    var hasPadding = paddingQuad && highlight.paddingColor !== transparentColor;
+    var hasBorder = borderQuad && highlight.borderColor !== transparentColor;
+    var hasMargin = marginQuad && highlight.marginColor !== transparentColor;
+    var hasEventTarget = eventTargetQuad && highlight.eventTargetColor !== transparentColor;
+
+    var clipQuad;
+    if (hasMargin && (!hasBorder || !quadEquals(marginQuad, borderQuad))) {
+        drawOutlinedQuadWithClip(marginQuad, borderQuad, highlight.marginColor);
+        clipQuad = borderQuad;
+    }
+    if (hasBorder && (!hasPadding || !quadEquals(borderQuad, paddingQuad))) {
+        drawOutlinedQuadWithClip(borderQuad, paddingQuad, highlight.borderColor);
+        clipQuad = paddingQuad;
+    }
+    if (hasPadding && (!hasContent || !quadEquals(paddingQuad, contentQuad))) {
+        drawOutlinedQuadWithClip(paddingQuad, contentQuad, highlight.paddingColor);
+        clipQuad = contentQuad;
+    }
+    if (hasContent)
+        drawOutlinedQuad(contentQuad, highlight.contentColor, highlight.contentOutlineColor);
+    if (hasEventTarget)
+        drawUnderlyingQuad(eventTargetQuad, highlight.eventTargetColor);
+
+    var width = canvasWidth;
+    var height = canvasHeight;
+    var minX = Number.MAX_VALUE, minY = Number.MAX_VALUE, maxX = Number.MIN_VALUE; maxY = Number.MIN_VALUE;
+    for (var i = 0; i < highlight.quads.length; ++i) {
+        var quad = highlight.quads[i];
+        for (var j = 0; j < quad.length; ++j) {
+            minX = Math.min(minX, quad[j].x);
+            maxX = Math.max(maxX, quad[j].x);
+            minY = Math.min(minY, quad[j].y);
+            maxY = Math.max(maxY, quad[j].y);
+        }
+    }
+
+    var rulerAtRight = minX < 20 && maxX + 20 < width;
+    var rulerAtBottom = minY < 20 && maxY + 20 < height;
+
+    if (highlight.showRulers) {
+        _drawGrid(rulerAtRight, rulerAtBottom);
+        _drawRulers(highlight, rulerAtRight, rulerAtBottom);
+    }
+    _drawElementTitle(highlight);
+
+    context.restore();
+}
+
+function drawQuadHighlight(highlight)
+{
+    context.save();
+    drawOutlinedQuad(highlight.quads[0], highlight.contentColor, highlight.contentOutlineColor);
+    context.restore();
+}
+
+function setPlatform(platform)
+{
+    window.platform = platform;
+    document.body.classList.add("platform-" + platform);
+}
+
+function dispatch(message)
+{
+    var functionName = message.shift();
+    window[functionName].apply(null, message);
+}
+
+function log(text)
+{
+    var logEntry = document.createElement("div");
+    logEntry.textContent = text;
+    document.getElementById("log").appendChild(logEntry);
+}
+
+</script>
+</head>
+<body class="fill">
+<div class="message-line"><span class="message-box" id="paused-in-debugger"></span></div>
+</body>
+<canvas id="canvas" class="fill"></canvas>
+<div id="element-title">
+  <span id="tag-name"></span><span id="node-id"></span><span id="class-name"></span>
+  <span id="node-width"></span><span class="px">px</span><span class="px"> &#xD7; </span><span id="node-height"></span><span class="px">px</span>
+</div>
+<div id="right-gutter"></div>
+<div id="bottom-gutter"></div>
+<div id="log"></div>
+</html>
diff --git a/Source/core/inspector/InspectorOverridesInl.h b/Source/core/inspector/InspectorOverridesInl.h
new file mode 100644
index 0000000..c97469b
--- /dev/null
+++ b/Source/core/inspector/InspectorOverridesInl.h
@@ -0,0 +1,105 @@
+/*
+* Copyright (C) 2013 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.
+*/
+
+#ifndef InspectorOverrides_inl_h
+#define InspectorOverrides_inl_h
+
+namespace WebCore {
+
+namespace InspectorInstrumentation {
+
+bool forcePseudoStateImpl(InstrumentingAgents*, Element*, CSSSelector::PseudoType);
+bool shouldApplyScreenWidthOverrideImpl(InstrumentingAgents*);
+bool shouldApplyScreenHeightOverrideImpl(InstrumentingAgents*);
+bool shouldPauseDedicatedWorkerOnStartImpl(InstrumentingAgents*);
+GeolocationPosition* overrideGeolocationPositionImpl(InstrumentingAgents*, GeolocationPosition*);
+DeviceOrientationData* overrideDeviceOrientationImpl(InstrumentingAgents*, DeviceOrientationData*);
+String getCurrentUserInitiatedProfileNameImpl(InstrumentingAgents*, bool incrementProfileNumber);
+
+inline bool forcePseudoState(Element* element, CSSSelector::PseudoType pseudoState)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(false);
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForElement(element))
+        return forcePseudoStateImpl(instrumentingAgents, element, pseudoState);
+    return false;
+}
+
+inline bool shouldApplyScreenWidthOverride(Frame* frame)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(false);
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        return shouldApplyScreenWidthOverrideImpl(instrumentingAgents);
+    return false;
+}
+
+inline bool shouldApplyScreenHeightOverride(Frame* frame)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(false);
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        return shouldApplyScreenHeightOverrideImpl(instrumentingAgents);
+    return false;
+}
+
+inline bool shouldPauseDedicatedWorkerOnStart(ScriptExecutionContext* context)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(false);
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        return shouldPauseDedicatedWorkerOnStartImpl(instrumentingAgents);
+    return false;
+}
+
+inline GeolocationPosition* overrideGeolocationPosition(Page* page, GeolocationPosition* position)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(position);
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        return overrideGeolocationPositionImpl(instrumentingAgents, position);
+    return position;
+}
+
+inline DeviceOrientationData* overrideDeviceOrientation(Page* page, DeviceOrientationData* deviceOrientation)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(deviceOrientation);
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        return overrideDeviceOrientationImpl(instrumentingAgents, deviceOrientation);
+    return deviceOrientation;
+}
+
+inline String getCurrentUserInitiatedProfileName(Page* page, bool incrementProfileNumber)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page))
+        return getCurrentUserInitiatedProfileNameImpl(instrumentingAgents, incrementProfileNumber);
+    return "";
+}
+
+}  // namespace InspectorInstrumentation
+
+}  // namespace WebCore
+
+#endif  // !defined(InspectorOverrides_inl_h)
diff --git a/Source/core/inspector/InspectorPageAgent.cpp b/Source/core/inspector/InspectorPageAgent.cpp
new file mode 100644
index 0000000..e1f3066
--- /dev/null
+++ b/Source/core/inspector/InspectorPageAgent.cpp
@@ -0,0 +1,1234 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorPageAgent.h"
+
+#include "HTMLNames.h"
+#include "InspectorFrontend.h"
+#include "bindings/v8/DOMWrapperWorld.h"
+#include "bindings/v8/ScriptController.h"
+#include "bindings/v8/ScriptObject.h"
+#include "core/dom/DOMImplementation.h"
+#include "core/dom/DeviceOrientationController.h"
+#include "core/dom/Document.h"
+#include "core/dom/UserGestureIndicator.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/inspector/ContentSearchUtils.h"
+#include "core/inspector/DOMPatchSupport.h"
+#include "core/inspector/IdentifiersFactory.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/InspectorAgent.h"
+#include "core/inspector/InspectorClient.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/InspectorOverlay.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/loader/CookieJar.h"
+#include "core/loader/DocumentLoader.h"
+#include "core/loader/FrameLoader.h"
+#include "core/loader/TextResourceDecoder.h"
+#include "core/loader/cache/CachedCSSStyleSheet.h"
+#include "core/loader/cache/CachedFont.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/loader/cache/CachedResource.h"
+#include "core/loader/cache/CachedResourceLoader.h"
+#include "core/loader/cache/CachedScript.h"
+#include "core/loader/cache/MemoryCache.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/page/SecurityOrigin.h"
+#include "core/page/Settings.h"
+#include "core/platform/Cookie.h"
+#include "core/platform/text/RegularExpression.h"
+#include "core/platform/text/TextEncoding.h"
+#include "modules/geolocation/GeolocationController.h"
+#include "modules/geolocation/GeolocationError.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/text/Base64.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/Vector.h>
+
+using namespace std;
+
+namespace WebCore {
+
+namespace PageAgentState {
+static const char pageAgentEnabled[] = "pageAgentEnabled";
+static const char pageAgentScriptExecutionDisabled[] = "pageAgentScriptExecutionDisabled";
+static const char pageAgentScriptsToEvaluateOnLoad[] = "pageAgentScriptsToEvaluateOnLoad";
+static const char pageAgentScreenWidthOverride[] = "pageAgentScreenWidthOverride";
+static const char pageAgentScreenHeightOverride[] = "pageAgentScreenHeightOverride";
+static const char pageAgentFontScaleFactorOverride[] = "pageAgentFontScaleFactorOverride";
+static const char pageAgentFitWindow[] = "pageAgentFitWindow";
+static const char pageAgentShowFPSCounter[] = "pageAgentShowFPSCounter";
+static const char pageAgentContinuousPaintingEnabled[] = "pageAgentContinuousPaintingEnabled";
+static const char pageAgentShowPaintRects[] = "pageAgentShowPaintRects";
+static const char pageAgentShowDebugBorders[] = "pageAgentShowDebugBorders";
+static const char touchEventEmulationEnabled[] = "touchEventEmulationEnabled";
+static const char pageAgentEmulatedMedia[] = "pageAgentEmulatedMedia";
+}
+
+static bool decodeBuffer(const char* buffer, unsigned size, const String& textEncodingName, String* result)
+{
+    if (buffer) {
+        TextEncoding encoding(textEncodingName);
+        if (!encoding.isValid())
+            encoding = WindowsLatin1Encoding();
+        *result = encoding.decode(buffer, size);
+        return true;
+    }
+    return false;
+}
+
+static bool prepareCachedResourceBuffer(CachedResource* cachedResource, bool* hasZeroSize)
+{
+    *hasZeroSize = false;
+    if (!cachedResource)
+        return false;
+
+    // Zero-sized resources don't have data at all -- so fake the empty buffer, instead of indicating error by returning 0.
+    if (!cachedResource->encodedSize()) {
+        *hasZeroSize = true;
+        return true;
+    }
+
+    if (cachedResource->isPurgeable()) {
+        // If the resource is purgeable then make it unpurgeable to get
+        // get its data. This might fail, in which case we return an
+        // empty String.
+        // FIXME: should we do something else in the case of a purged
+        // resource that informs the user why there is no data in the
+        // inspector?
+        if (!cachedResource->makePurgeable(false))
+            return false;
+    }
+
+    return true;
+}
+
+static bool hasTextContent(CachedResource* cachedResource)
+{
+    InspectorPageAgent::ResourceType type = InspectorPageAgent::cachedResourceType(*cachedResource);
+    return type == InspectorPageAgent::DocumentResource || type == InspectorPageAgent::StylesheetResource || type == InspectorPageAgent::ScriptResource || type == InspectorPageAgent::XHRResource;
+}
+
+static PassRefPtr<TextResourceDecoder> createXHRTextDecoder(const String& mimeType, const String& textEncodingName)
+{
+    RefPtr<TextResourceDecoder> decoder;
+    if (!textEncodingName.isEmpty())
+        decoder = TextResourceDecoder::create("text/plain", textEncodingName);
+    else if (DOMImplementation::isXMLMIMEType(mimeType.lower())) {
+        decoder = TextResourceDecoder::create("application/xml");
+        decoder->useLenientXMLDecoding();
+    } else if (equalIgnoringCase(mimeType, "text/html"))
+        decoder = TextResourceDecoder::create("text/html", "UTF-8");
+    else
+        decoder = TextResourceDecoder::create("text/plain", "UTF-8");
+    return decoder;
+}
+
+bool InspectorPageAgent::cachedResourceContent(CachedResource* cachedResource, String* result, bool* base64Encoded)
+{
+    bool hasZeroSize;
+    bool prepared = prepareCachedResourceBuffer(cachedResource, &hasZeroSize);
+    if (!prepared)
+        return false;
+
+    *base64Encoded = !hasTextContent(cachedResource);
+    if (*base64Encoded) {
+        RefPtr<SharedBuffer> buffer = hasZeroSize ? SharedBuffer::create() : cachedResource->resourceBuffer();
+
+        if (!buffer)
+            return false;
+
+        *result = base64Encode(buffer->data(), buffer->size());
+        return true;
+    }
+
+    if (hasZeroSize) {
+        *result = "";
+        return true;
+    }
+
+    if (cachedResource) {
+        switch (cachedResource->type()) {
+        case CachedResource::CSSStyleSheet:
+            *result = static_cast<CachedCSSStyleSheet*>(cachedResource)->sheetText(false);
+            return true;
+        case CachedResource::Script:
+            *result = static_cast<CachedScript*>(cachedResource)->script();
+            return true;
+        case CachedResource::RawResource: {
+            SharedBuffer* buffer = cachedResource->resourceBuffer();
+            if (!buffer)
+                return false;
+            RefPtr<TextResourceDecoder> decoder = createXHRTextDecoder(cachedResource->response().mimeType(), cachedResource->response().textEncodingName());
+            // We show content for raw resources only for certain mime types (text, html and xml). Otherwise decoder will be null.
+            if (!decoder)
+                return false;
+            String content = decoder->decode(buffer->data(), buffer->size());
+            *result = content + decoder->flush();
+            return true;
+        }
+        default:
+            SharedBuffer* buffer = cachedResource->resourceBuffer();
+            return decodeBuffer(buffer ? buffer->data() : 0, buffer ? buffer->size() : 0, cachedResource->encoding(), result);
+        }
+    }
+    return false;
+}
+
+bool InspectorPageAgent::mainResourceContent(Frame* frame, bool withBase64Encode, String* result)
+{
+    RefPtr<SharedBuffer> buffer = frame->loader()->documentLoader()->mainResourceData();
+    if (!buffer)
+        return false;
+    String textEncodingName = frame->document()->inputEncoding();
+
+    return InspectorPageAgent::dataContent(buffer->data(), buffer->size(), textEncodingName, withBase64Encode, result);
+}
+
+// static
+bool InspectorPageAgent::sharedBufferContent(PassRefPtr<SharedBuffer> buffer, const String& textEncodingName, bool withBase64Encode, String* result)
+{
+    return dataContent(buffer ? buffer->data() : 0, buffer ? buffer->size() : 0, textEncodingName, withBase64Encode, result);
+}
+
+bool InspectorPageAgent::dataContent(const char* data, unsigned size, const String& textEncodingName, bool withBase64Encode, String* result)
+{
+    if (withBase64Encode) {
+        *result = base64Encode(data, size);
+        return true;
+    }
+
+    return decodeBuffer(data, size, textEncodingName, result);
+}
+
+PassOwnPtr<InspectorPageAgent> InspectorPageAgent::create(InstrumentingAgents* instrumentingAgents, Page* page, InspectorAgent* inspectorAgent, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager, InspectorClient* client, InspectorOverlay* overlay)
+{
+    return adoptPtr(new InspectorPageAgent(instrumentingAgents, page, inspectorAgent, state, injectedScriptManager, client, overlay));
+}
+
+// static
+void InspectorPageAgent::resourceContent(ErrorString* errorString, Frame* frame, const KURL& url, String* result, bool* base64Encoded)
+{
+    DocumentLoader* loader = assertDocumentLoader(errorString, frame);
+    if (!loader)
+        return;
+
+    RefPtr<SharedBuffer> buffer;
+    bool success = false;
+    if (equalIgnoringFragmentIdentifier(url, loader->url())) {
+        *base64Encoded = false;
+        success = mainResourceContent(frame, *base64Encoded, result);
+    }
+
+    if (!success)
+        success = cachedResourceContent(cachedResource(frame, url), result, base64Encoded);
+
+    if (!success)
+        *errorString = "No resource with given URL found";
+}
+
+CachedResource* InspectorPageAgent::cachedResource(Frame* frame, const KURL& url)
+{
+    CachedResource* cachedResource = frame->document()->cachedResourceLoader()->cachedResource(url);
+    if (!cachedResource)
+        cachedResource = memoryCache()->resourceForURL(url);
+    return cachedResource;
+}
+
+TypeBuilder::Page::ResourceType::Enum InspectorPageAgent::resourceTypeJson(InspectorPageAgent::ResourceType resourceType)
+{
+    switch (resourceType) {
+    case DocumentResource:
+        return TypeBuilder::Page::ResourceType::Document;
+    case ImageResource:
+        return TypeBuilder::Page::ResourceType::Image;
+    case FontResource:
+        return TypeBuilder::Page::ResourceType::Font;
+    case StylesheetResource:
+        return TypeBuilder::Page::ResourceType::Stylesheet;
+    case ScriptResource:
+        return TypeBuilder::Page::ResourceType::Script;
+    case XHRResource:
+        return TypeBuilder::Page::ResourceType::XHR;
+    case WebSocketResource:
+        return TypeBuilder::Page::ResourceType::WebSocket;
+    case OtherResource:
+        return TypeBuilder::Page::ResourceType::Other;
+    }
+    return TypeBuilder::Page::ResourceType::Other;
+}
+
+InspectorPageAgent::ResourceType InspectorPageAgent::cachedResourceType(const CachedResource& cachedResource)
+{
+    switch (cachedResource.type()) {
+    case CachedResource::ImageResource:
+        return InspectorPageAgent::ImageResource;
+    case CachedResource::FontResource:
+        return InspectorPageAgent::FontResource;
+    case CachedResource::CSSStyleSheet:
+        // Fall through.
+    case CachedResource::XSLStyleSheet:
+        return InspectorPageAgent::StylesheetResource;
+    case CachedResource::Script:
+        return InspectorPageAgent::ScriptResource;
+    case CachedResource::RawResource:
+        return InspectorPageAgent::XHRResource;
+    case CachedResource::MainResource:
+        return InspectorPageAgent::DocumentResource;
+    default:
+        break;
+    }
+    return InspectorPageAgent::OtherResource;
+}
+
+TypeBuilder::Page::ResourceType::Enum InspectorPageAgent::cachedResourceTypeJson(const CachedResource& cachedResource)
+{
+    return resourceTypeJson(cachedResourceType(cachedResource));
+}
+
+InspectorPageAgent::InspectorPageAgent(InstrumentingAgents* instrumentingAgents, Page* page, InspectorAgent* inspectorAgent, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager, InspectorClient* client, InspectorOverlay* overlay)
+    : InspectorBaseAgent<InspectorPageAgent>("Page", instrumentingAgents, inspectorState)
+    , m_page(page)
+    , m_inspectorAgent(inspectorAgent)
+    , m_injectedScriptManager(injectedScriptManager)
+    , m_client(client)
+    , m_frontend(0)
+    , m_overlay(overlay)
+    , m_lastScriptIdentifier(0)
+    , m_enabled(false)
+    , m_isFirstLayoutAfterOnLoad(false)
+    , m_geolocationOverridden(false)
+    , m_ignoreScriptsEnabledNotification(false)
+{
+}
+
+void InspectorPageAgent::setFrontend(InspectorFrontend* frontend)
+{
+    m_frontend = frontend->page();
+}
+
+void InspectorPageAgent::clearFrontend()
+{
+    ErrorString error;
+    disable(&error);
+    updateTouchEventEmulationInPage(false);
+    m_frontend = 0;
+}
+
+void InspectorPageAgent::restore()
+{
+    if (m_state->getBoolean(PageAgentState::pageAgentEnabled)) {
+        ErrorString error;
+        enable(&error);
+        bool scriptExecutionDisabled = m_state->getBoolean(PageAgentState::pageAgentScriptExecutionDisabled);
+        setScriptExecutionDisabled(0, scriptExecutionDisabled);
+        bool showPaintRects = m_state->getBoolean(PageAgentState::pageAgentShowPaintRects);
+        setShowPaintRects(0, showPaintRects);
+        bool showDebugBorders = m_state->getBoolean(PageAgentState::pageAgentShowDebugBorders);
+        setShowDebugBorders(0, showDebugBorders);
+        bool showFPSCounter = m_state->getBoolean(PageAgentState::pageAgentShowFPSCounter);
+        setShowFPSCounter(0, showFPSCounter);
+        String emulatedMedia = m_state->getString(PageAgentState::pageAgentEmulatedMedia);
+        setEmulatedMedia(0, emulatedMedia);
+        bool continuousPaintingEnabled = m_state->getBoolean(PageAgentState::pageAgentContinuousPaintingEnabled);
+        setContinuousPaintingEnabled(0, continuousPaintingEnabled);
+
+        int currentWidth = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenWidthOverride));
+        int currentHeight = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenHeightOverride));
+        double currentFontScaleFactor = m_state->getDouble(PageAgentState::pageAgentFontScaleFactorOverride);
+        bool currentFitWindow = m_state->getBoolean(PageAgentState::pageAgentFitWindow);
+        updateViewMetrics(currentWidth, currentHeight, currentFontScaleFactor, currentFitWindow);
+        updateTouchEventEmulationInPage(m_state->getBoolean(PageAgentState::touchEventEmulationEnabled));
+    }
+}
+
+void InspectorPageAgent::webViewResized(const IntSize& size)
+{
+    int currentWidth = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenWidthOverride));
+    m_overlay->resize(currentWidth ? size : IntSize());
+}
+
+void InspectorPageAgent::enable(ErrorString*)
+{
+    m_enabled = true;
+    m_state->setBoolean(PageAgentState::pageAgentEnabled, true);
+    m_instrumentingAgents->setInspectorPageAgent(this);
+}
+
+void InspectorPageAgent::disable(ErrorString*)
+{
+    m_enabled = false;
+    m_state->setBoolean(PageAgentState::pageAgentEnabled, false);
+    m_state->remove(PageAgentState::pageAgentScriptsToEvaluateOnLoad);
+    m_overlay->hide();
+    m_instrumentingAgents->setInspectorPageAgent(0);
+
+    setShowPaintRects(0, false);
+    setShowDebugBorders(0, false);
+    setShowFPSCounter(0, false);
+    setEmulatedMedia(0, "");
+    setContinuousPaintingEnabled(0, false);
+
+    if (!deviceMetricsChanged(0, 0, 1, false))
+        return;
+
+    // When disabling the agent, reset the override values if necessary.
+    updateViewMetrics(0, 0, 1, false);
+    m_state->setLong(PageAgentState::pageAgentScreenWidthOverride, 0);
+    m_state->setLong(PageAgentState::pageAgentScreenHeightOverride, 0);
+    m_state->setDouble(PageAgentState::pageAgentFontScaleFactorOverride, 1);
+    m_state->setBoolean(PageAgentState::pageAgentFitWindow, false);
+}
+
+void InspectorPageAgent::addScriptToEvaluateOnLoad(ErrorString*, const String& source, String* identifier)
+{
+    RefPtr<InspectorObject> scripts = m_state->getObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad);
+    if (!scripts) {
+        scripts = InspectorObject::create();
+        m_state->setObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad, scripts);
+    }
+    // Assure we don't override existing ids -- m_lastScriptIdentifier could get out of sync WRT actual
+    // scripts once we restored the scripts from the cookie during navigation.
+    do {
+        *identifier = String::number(++m_lastScriptIdentifier);
+    } while (scripts->find(*identifier) != scripts->end());
+    scripts->setString(*identifier, source);
+
+    // Force cookie serialization.
+    m_state->setObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad, scripts);
+}
+
+void InspectorPageAgent::removeScriptToEvaluateOnLoad(ErrorString* error, const String& identifier)
+{
+    RefPtr<InspectorObject> scripts = m_state->getObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad);
+    if (!scripts || scripts->find(identifier) == scripts->end()) {
+        *error = "Script not found";
+        return;
+    }
+    scripts->remove(identifier);
+}
+
+void InspectorPageAgent::reload(ErrorString*, const bool* const optionalIgnoreCache, const String* optionalScriptToEvaluateOnLoad, const String* optionalScriptPreprocessor)
+{
+    m_pendingScriptToEvaluateOnLoadOnce = optionalScriptToEvaluateOnLoad ? *optionalScriptToEvaluateOnLoad : "";
+    m_pendingScriptPreprocessor = optionalScriptPreprocessor ? *optionalScriptPreprocessor : "";
+    m_page->mainFrame()->loader()->reload(optionalIgnoreCache ? *optionalIgnoreCache : false);
+}
+
+void InspectorPageAgent::navigate(ErrorString*, const String& url)
+{
+    UserGestureIndicator indicator(DefinitelyProcessingNewUserGesture);
+    Frame* frame = m_page->mainFrame();
+    frame->loader()->changeLocation(frame->document()->securityOrigin(), frame->document()->completeURL(url), "", false, false);
+}
+
+static PassRefPtr<TypeBuilder::Page::Cookie> buildObjectForCookie(const Cookie& cookie)
+{
+    return TypeBuilder::Page::Cookie::create()
+        .setName(cookie.name)
+        .setValue(cookie.value)
+        .setDomain(cookie.domain)
+        .setPath(cookie.path)
+        .setExpires(cookie.expires)
+        .setSize((cookie.name.length() + cookie.value.length()))
+        .setHttpOnly(cookie.httpOnly)
+        .setSecure(cookie.secure)
+        .setSession(cookie.session)
+        .release();
+}
+
+static PassRefPtr<TypeBuilder::Array<TypeBuilder::Page::Cookie> > buildArrayForCookies(ListHashSet<Cookie>& cookiesList)
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::Page::Cookie> > cookies = TypeBuilder::Array<TypeBuilder::Page::Cookie>::create();
+
+    ListHashSet<Cookie>::iterator end = cookiesList.end();
+    ListHashSet<Cookie>::iterator it = cookiesList.begin();
+    for (int i = 0; it != end; ++it, i++)
+        cookies->addItem(buildObjectForCookie(*it));
+
+    return cookies;
+}
+
+static Vector<CachedResource*> cachedResourcesForFrame(Frame* frame)
+{
+    Vector<CachedResource*> result;
+
+    const CachedResourceLoader::DocumentResourceMap& allResources = frame->document()->cachedResourceLoader()->allCachedResources();
+    CachedResourceLoader::DocumentResourceMap::const_iterator end = allResources.end();
+    for (CachedResourceLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it) {
+        CachedResource* cachedResource = it->value.get();
+
+        switch (cachedResource->type()) {
+        case CachedResource::ImageResource:
+            // Skip images that were not auto loaded (images disabled in the user agent).
+            if (static_cast<CachedImage*>(cachedResource)->stillNeedsLoad())
+                continue;
+            break;
+        case CachedResource::FontResource:
+            // Skip fonts that were referenced in CSS but never used/downloaded.
+            if (static_cast<CachedFont*>(cachedResource)->stillNeedsLoad())
+                continue;
+            break;
+        default:
+            // All other CachedResource types download immediately.
+            break;
+        }
+
+        result.append(cachedResource);
+    }
+
+    return result;
+}
+
+static Vector<KURL> allResourcesURLsForFrame(Frame* frame)
+{
+    Vector<KURL> result;
+
+    result.append(frame->loader()->documentLoader()->url());
+
+    Vector<CachedResource*> allResources = cachedResourcesForFrame(frame);
+    for (Vector<CachedResource*>::const_iterator it = allResources.begin(); it != allResources.end(); ++it)
+        result.append((*it)->url());
+
+    return result;
+}
+
+void InspectorPageAgent::getCookies(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::Page::Cookie> >& cookies, WTF::String* cookiesString)
+{
+    ListHashSet<Cookie> rawCookiesList;
+
+    for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext(mainFrame())) {
+        Document* document = frame->document();
+        Vector<KURL> allURLs = allResourcesURLsForFrame(frame);
+        for (Vector<KURL>::const_iterator it = allURLs.begin(); it != allURLs.end(); ++it) {
+            Vector<Cookie> docCookiesList;
+            getRawCookies(document, KURL(ParsedURLString, *it), docCookiesList);
+            int cookiesSize = docCookiesList.size();
+            for (int i = 0; i < cookiesSize; i++) {
+                if (!rawCookiesList.contains(docCookiesList[i]))
+                    rawCookiesList.add(docCookiesList[i]);
+            }
+        }
+    }
+
+    // FIXME: Remove "cookiesString" output.
+    cookies = buildArrayForCookies(rawCookiesList);
+    *cookiesString = "";
+}
+
+void InspectorPageAgent::deleteCookie(ErrorString*, const String& cookieName, const String& url)
+{
+    KURL parsedURL(ParsedURLString, url);
+    for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext(m_page->mainFrame()))
+        WebCore::deleteCookie(frame->document(), parsedURL, cookieName);
+}
+
+void InspectorPageAgent::getResourceTree(ErrorString*, RefPtr<TypeBuilder::Page::FrameResourceTree>& object)
+{
+    object = buildObjectForFrameTree(m_page->mainFrame());
+}
+
+void InspectorPageAgent::getResourceContent(ErrorString* errorString, const String& frameId, const String& url, String* content, bool* base64Encoded)
+{
+    Frame* frame = assertFrame(errorString, frameId);
+    if (!frame)
+        return;
+
+    resourceContent(errorString, frame, KURL(ParsedURLString, url), content, base64Encoded);
+}
+
+static bool textContentForCachedResource(CachedResource* cachedResource, String* result)
+{
+    if (hasTextContent(cachedResource)) {
+        String content;
+        bool base64Encoded;
+        if (InspectorPageAgent::cachedResourceContent(cachedResource, result, &base64Encoded)) {
+            ASSERT(!base64Encoded);
+            return true;
+        }
+    }
+    return false;
+}
+
+void InspectorPageAgent::searchInResource(ErrorString*, const String& frameId, const String& url, const String& query, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchMatch> >& results)
+{
+    results = TypeBuilder::Array<TypeBuilder::Page::SearchMatch>::create();
+
+    bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
+    bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false;
+
+    Frame* frame = frameForId(frameId);
+    KURL kurl(ParsedURLString, url);
+
+    FrameLoader* frameLoader = frame ? frame->loader() : 0;
+    DocumentLoader* loader = frameLoader ? frameLoader->documentLoader() : 0;
+    if (!loader)
+        return;
+
+    String content;
+    bool success = false;
+    if (equalIgnoringFragmentIdentifier(kurl, loader->url()))
+        success = mainResourceContent(frame, false, &content);
+
+    if (!success) {
+        CachedResource* resource = cachedResource(frame, kurl);
+        if (resource)
+            success = textContentForCachedResource(resource, &content);
+    }
+
+    if (!success)
+        return;
+
+    results = ContentSearchUtils::searchInTextByLines(content, query, caseSensitive, isRegex);
+}
+
+static PassRefPtr<TypeBuilder::Page::SearchResult> buildObjectForSearchResult(const String& frameId, const String& url, int matchesCount)
+{
+    return TypeBuilder::Page::SearchResult::create()
+        .setUrl(url)
+        .setFrameId(frameId)
+        .setMatchesCount(matchesCount)
+        .release();
+}
+
+void InspectorPageAgent::searchInResources(ErrorString*, const String& text, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchResult> >& results)
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchResult> > searchResults = TypeBuilder::Array<TypeBuilder::Page::SearchResult>::create();
+
+    bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
+    bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false;
+    OwnPtr<RegularExpression> regex = ContentSearchUtils::createSearchRegex(text, caseSensitive, isRegex);
+
+    for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext(m_page->mainFrame())) {
+        String content;
+        Vector<CachedResource*> allResources = cachedResourcesForFrame(frame);
+        for (Vector<CachedResource*>::const_iterator it = allResources.begin(); it != allResources.end(); ++it) {
+            CachedResource* cachedResource = *it;
+            if (textContentForCachedResource(cachedResource, &content)) {
+                int matchesCount = ContentSearchUtils::countRegularExpressionMatches(regex.get(), content);
+                if (matchesCount)
+                    searchResults->addItem(buildObjectForSearchResult(frameId(frame), cachedResource->url(), matchesCount));
+            }
+        }
+        if (mainResourceContent(frame, false, &content)) {
+            int matchesCount = ContentSearchUtils::countRegularExpressionMatches(regex.get(), content);
+            if (matchesCount)
+                searchResults->addItem(buildObjectForSearchResult(frameId(frame), frame->document()->url(), matchesCount));
+        }
+    }
+
+    results = searchResults;
+}
+
+void InspectorPageAgent::setDocumentContent(ErrorString* errorString, const String& frameId, const String& html)
+{
+    Frame* frame = assertFrame(errorString, frameId);
+    if (!frame)
+        return;
+
+    Document* document = frame->document();
+    if (!document) {
+        *errorString = "No Document instance to set HTML for";
+        return;
+    }
+    DOMPatchSupport::patchDocument(document, html);
+}
+
+void InspectorPageAgent::setDeviceMetricsOverride(ErrorString* errorString, int width, int height, double fontScaleFactor, bool fitWindow)
+{
+    const static long maxDimension = 10000000;
+
+    if (width < 0 || height < 0 || width > maxDimension || height > maxDimension) {
+        *errorString = makeString("Width and height values must be positive, not greater than ", String::number(maxDimension));
+        return;
+    }
+
+    if (!width ^ !height) {
+        *errorString = "Both width and height must be either zero or non-zero at once";
+        return;
+    }
+
+    if (fontScaleFactor <= 0) {
+        *errorString = "fontScaleFactor must be positive";
+        return;
+    }
+
+    if (!deviceMetricsChanged(width, height, fontScaleFactor, fitWindow))
+        return;
+
+    m_state->setLong(PageAgentState::pageAgentScreenWidthOverride, width);
+    m_state->setLong(PageAgentState::pageAgentScreenHeightOverride, height);
+    m_state->setDouble(PageAgentState::pageAgentFontScaleFactorOverride, fontScaleFactor);
+    m_state->setBoolean(PageAgentState::pageAgentFitWindow, fitWindow);
+
+    updateViewMetrics(width, height, fontScaleFactor, fitWindow);
+}
+
+bool InspectorPageAgent::deviceMetricsChanged(int width, int height, double fontScaleFactor, bool fitWindow)
+{
+    // These two always fit an int.
+    int currentWidth = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenWidthOverride));
+    int currentHeight = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenHeightOverride));
+    double currentFontScaleFactor = m_state->getDouble(PageAgentState::pageAgentFontScaleFactorOverride);
+    bool currentFitWindow = m_state->getBoolean(PageAgentState::pageAgentFitWindow);
+
+    return width != currentWidth || height != currentHeight || fontScaleFactor != currentFontScaleFactor || fitWindow != currentFitWindow;
+}
+
+void InspectorPageAgent::setShowPaintRects(ErrorString*, bool show)
+{
+    m_state->setBoolean(PageAgentState::pageAgentShowPaintRects, show);
+    m_client->setShowPaintRects(show);
+
+    if (!show && mainFrame() && mainFrame()->view())
+        mainFrame()->view()->invalidate();
+}
+
+void InspectorPageAgent::setShowDebugBorders(ErrorString*, bool show)
+{
+    m_state->setBoolean(PageAgentState::pageAgentShowDebugBorders, show);
+    m_client->setShowDebugBorders(show);
+    if (mainFrame() && mainFrame()->view())
+        mainFrame()->view()->invalidate();
+}
+
+void InspectorPageAgent::canShowFPSCounter(ErrorString*, bool* outParam)
+{
+    *outParam = m_client->canShowFPSCounter();
+}
+
+void InspectorPageAgent::setShowFPSCounter(ErrorString*, bool show)
+{
+    m_state->setBoolean(PageAgentState::pageAgentShowFPSCounter, show);
+    m_client->setShowFPSCounter(show);
+
+    if (mainFrame() && mainFrame()->view())
+        mainFrame()->view()->invalidate();
+}
+
+void InspectorPageAgent::canContinuouslyPaint(ErrorString*, bool* outParam)
+{
+    *outParam = m_client->canContinuouslyPaint();
+}
+
+void InspectorPageAgent::setContinuousPaintingEnabled(ErrorString*, bool enabled)
+{
+    m_state->setBoolean(PageAgentState::pageAgentContinuousPaintingEnabled, enabled);
+    m_client->setContinuousPaintingEnabled(enabled);
+
+    if (!enabled && mainFrame() && mainFrame()->view())
+        mainFrame()->view()->invalidate();
+}
+
+void InspectorPageAgent::getScriptExecutionStatus(ErrorString*, PageCommandHandler::Result::Enum* status)
+{
+    bool disabledByScriptController = false;
+    bool disabledInSettings = false;
+    Frame* frame = mainFrame();
+    if (frame) {
+        disabledByScriptController = !frame->script()->canExecuteScripts(NotAboutToExecuteScript);
+        if (frame->settings())
+            disabledInSettings = !frame->settings()->isScriptEnabled();
+    }
+
+    if (!disabledByScriptController) {
+        *status = PageCommandHandler::Result::Allowed;
+        return;
+    }
+
+    if (disabledInSettings)
+        *status = PageCommandHandler::Result::Disabled;
+    else
+        *status = PageCommandHandler::Result::Forbidden;
+}
+
+void InspectorPageAgent::setScriptExecutionDisabled(ErrorString*, bool value)
+{
+    m_state->setBoolean(PageAgentState::pageAgentScriptExecutionDisabled, value);
+    if (!mainFrame())
+        return;
+
+    Settings* settings = mainFrame()->settings();
+    if (settings) {
+        m_ignoreScriptsEnabledNotification = true;
+        settings->setScriptEnabled(!value);
+        m_ignoreScriptsEnabledNotification = false;
+    }
+}
+
+void InspectorPageAgent::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld* world)
+{
+    if (world != mainThreadNormalWorld())
+        return;
+
+    if (frame == m_page->mainFrame())
+        m_injectedScriptManager->discardInjectedScripts();
+
+    if (!m_frontend)
+        return;
+
+    RefPtr<InspectorObject> scripts = m_state->getObject(PageAgentState::pageAgentScriptsToEvaluateOnLoad);
+    if (scripts) {
+        InspectorObject::const_iterator end = scripts->end();
+        for (InspectorObject::const_iterator it = scripts->begin(); it != end; ++it) {
+            String scriptText;
+            if (it->value->asString(&scriptText))
+                frame->script()->executeScript(scriptText);
+        }
+    }
+    if (!m_scriptToEvaluateOnLoadOnce.isEmpty())
+        frame->script()->executeScript(m_scriptToEvaluateOnLoadOnce);
+}
+
+void InspectorPageAgent::domContentEventFired()
+{
+    m_isFirstLayoutAfterOnLoad = true;
+    m_frontend->domContentEventFired(currentTime());
+}
+
+void InspectorPageAgent::loadEventFired()
+{
+    m_frontend->loadEventFired(currentTime());
+}
+
+void InspectorPageAgent::frameNavigated(DocumentLoader* loader)
+{
+    if (loader->frame() == m_page->mainFrame()) {
+        m_scriptToEvaluateOnLoadOnce = m_pendingScriptToEvaluateOnLoadOnce;
+        m_scriptPreprocessor = m_pendingScriptPreprocessor;
+        m_pendingScriptToEvaluateOnLoadOnce = String();
+        m_pendingScriptPreprocessor = String();
+    }
+    m_frontend->frameNavigated(buildObjectForFrame(loader->frame()));
+}
+
+void InspectorPageAgent::frameDetachedFromParent(Frame* frame)
+{
+    HashMap<Frame*, String>::iterator iterator = m_frameToIdentifier.find(frame);
+    if (iterator != m_frameToIdentifier.end()) {
+        m_frontend->frameDetached(iterator->value);
+        m_identifierToFrame.remove(iterator->value);
+        m_frameToIdentifier.remove(iterator);
+    }
+}
+
+Frame* InspectorPageAgent::mainFrame()
+{
+    return m_page->mainFrame();
+}
+
+Frame* InspectorPageAgent::frameForId(const String& frameId)
+{
+    return frameId.isEmpty() ? 0 : m_identifierToFrame.get(frameId);
+}
+
+String InspectorPageAgent::frameId(Frame* frame)
+{
+    if (!frame)
+        return "";
+    String identifier = m_frameToIdentifier.get(frame);
+    if (identifier.isNull()) {
+        identifier = IdentifiersFactory::createIdentifier();
+        m_frameToIdentifier.set(frame, identifier);
+        m_identifierToFrame.set(identifier, frame);
+    }
+    return identifier;
+}
+
+bool InspectorPageAgent::hasIdForFrame(Frame* frame) const
+{
+    return frame && m_frameToIdentifier.contains(frame);
+}
+
+String InspectorPageAgent::loaderId(DocumentLoader* loader)
+{
+    if (!loader)
+        return "";
+    String identifier = m_loaderToIdentifier.get(loader);
+    if (identifier.isNull()) {
+        identifier = IdentifiersFactory::createIdentifier();
+        m_loaderToIdentifier.set(loader, identifier);
+    }
+    return identifier;
+}
+
+Frame* InspectorPageAgent::findFrameWithSecurityOrigin(const String& originRawString)
+{
+    for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
+        RefPtr<SecurityOrigin> documentOrigin = frame->document()->securityOrigin();
+        if (documentOrigin->toRawString() == originRawString)
+            return frame;
+    }
+    return 0;
+}
+
+Frame* InspectorPageAgent::assertFrame(ErrorString* errorString, const String& frameId)
+{
+    Frame* frame = frameForId(frameId);
+    if (!frame)
+        *errorString = "No frame for given id found";
+    return frame;
+}
+
+// static
+DocumentLoader* InspectorPageAgent::assertDocumentLoader(ErrorString* errorString, Frame* frame)
+{
+    FrameLoader* frameLoader = frame->loader();
+    DocumentLoader* documentLoader = frameLoader ? frameLoader->documentLoader() : 0;
+    if (!documentLoader)
+        *errorString = "No documentLoader for given frame found";
+    return documentLoader;
+}
+
+void InspectorPageAgent::loaderDetachedFromFrame(DocumentLoader* loader)
+{
+    HashMap<DocumentLoader*, String>::iterator iterator = m_loaderToIdentifier.find(loader);
+    if (iterator != m_loaderToIdentifier.end())
+        m_loaderToIdentifier.remove(iterator);
+}
+
+void InspectorPageAgent::frameStartedLoading(Frame* frame)
+{
+    m_frontend->frameStartedLoading(frameId(frame));
+}
+
+void InspectorPageAgent::frameStoppedLoading(Frame* frame)
+{
+    m_frontend->frameStoppedLoading(frameId(frame));
+}
+
+void InspectorPageAgent::frameScheduledNavigation(Frame* frame, double delay)
+{
+    m_frontend->frameScheduledNavigation(frameId(frame), delay);
+}
+
+void InspectorPageAgent::frameClearedScheduledNavigation(Frame* frame)
+{
+    m_frontend->frameClearedScheduledNavigation(frameId(frame));
+}
+
+void InspectorPageAgent::willRunJavaScriptDialog(const String& message)
+{
+    m_frontend->javascriptDialogOpening(message);
+}
+
+void InspectorPageAgent::didRunJavaScriptDialog()
+{
+    m_frontend->javascriptDialogClosed();
+}
+
+void InspectorPageAgent::applyScreenWidthOverride(long* width)
+{
+    long widthOverride = m_state->getLong(PageAgentState::pageAgentScreenWidthOverride);
+    if (widthOverride)
+        *width = widthOverride;
+}
+
+void InspectorPageAgent::applyScreenHeightOverride(long* height)
+{
+    long heightOverride = m_state->getLong(PageAgentState::pageAgentScreenHeightOverride);
+    if (heightOverride)
+        *height = heightOverride;
+}
+
+void InspectorPageAgent::didPaint(RenderObject*, GraphicsContext* context, const LayoutRect& rect)
+{
+    if (!m_enabled || m_client->overridesShowPaintRects() || !m_state->getBoolean(PageAgentState::pageAgentShowPaintRects))
+        return;
+
+    static int colorSelector = 0;
+    const Color colors[] = {
+        Color(0xFF, 0, 0, 0x3F),
+        Color(0xFF, 0, 0xFF, 0x3F),
+        Color(0, 0, 0xFF, 0x3F),
+    };
+
+    LayoutRect inflatedRect(rect);
+    inflatedRect.inflate(-1);
+    m_overlay->drawOutline(context, inflatedRect, colors[colorSelector++ % WTF_ARRAY_LENGTH(colors)]);
+}
+
+void InspectorPageAgent::didLayout(RenderObject*)
+{
+    bool isFirstLayout = m_isFirstLayoutAfterOnLoad;
+    if (isFirstLayout)
+        m_isFirstLayoutAfterOnLoad = false;
+
+    if (!m_enabled)
+        return;
+
+    if (isFirstLayout) {
+        int currentWidth = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenWidthOverride));
+        int currentHeight = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenHeightOverride));
+
+        if (currentWidth && currentHeight)
+            m_client->autoZoomPageToFitWidth();
+    }
+    m_overlay->update();
+}
+
+void InspectorPageAgent::didScroll()
+{
+    if (m_enabled)
+        m_overlay->update();
+}
+
+void InspectorPageAgent::didResizeMainFrame()
+{
+    if (m_enabled)
+        m_overlay->showAndHideViewSize();
+}
+
+void InspectorPageAgent::didRecalculateStyle()
+{
+    if (m_enabled)
+        m_overlay->update();
+}
+
+void InspectorPageAgent::scriptsEnabled(bool isEnabled)
+{
+    if (m_ignoreScriptsEnabledNotification)
+        return;
+
+    m_frontend->scriptsEnabled(isEnabled);
+}
+
+PassRefPtr<TypeBuilder::Page::Frame> InspectorPageAgent::buildObjectForFrame(Frame* frame)
+{
+    RefPtr<TypeBuilder::Page::Frame> frameObject = TypeBuilder::Page::Frame::create()
+        .setId(frameId(frame))
+        .setLoaderId(loaderId(frame->loader()->documentLoader()))
+        .setUrl(frame->document()->url().string())
+        .setMimeType(frame->loader()->documentLoader()->responseMIMEType())
+        .setSecurityOrigin(frame->document()->securityOrigin()->toRawString());
+    if (frame->tree()->parent())
+        frameObject->setParentId(frameId(frame->tree()->parent()));
+    if (frame->ownerElement()) {
+        String name = frame->ownerElement()->getNameAttribute();
+        if (name.isEmpty())
+            name = frame->ownerElement()->getAttribute(HTMLNames::idAttr);
+        frameObject->setName(name);
+    }
+
+    return frameObject;
+}
+
+PassRefPtr<TypeBuilder::Page::FrameResourceTree> InspectorPageAgent::buildObjectForFrameTree(Frame* frame)
+{
+    RefPtr<TypeBuilder::Page::Frame> frameObject = buildObjectForFrame(frame);
+    RefPtr<TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree::Resources> > subresources = TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree::Resources>::create();
+    RefPtr<TypeBuilder::Page::FrameResourceTree> result = TypeBuilder::Page::FrameResourceTree::create()
+         .setFrame(frameObject)
+         .setResources(subresources);
+
+    Vector<CachedResource*> allResources = cachedResourcesForFrame(frame);
+    for (Vector<CachedResource*>::const_iterator it = allResources.begin(); it != allResources.end(); ++it) {
+        CachedResource* cachedResource = *it;
+
+        RefPtr<TypeBuilder::Page::FrameResourceTree::Resources> resourceObject = TypeBuilder::Page::FrameResourceTree::Resources::create()
+            .setUrl(cachedResource->url())
+            .setType(cachedResourceTypeJson(*cachedResource))
+            .setMimeType(cachedResource->response().mimeType());
+        if (cachedResource->wasCanceled())
+            resourceObject->setCanceled(true);
+        else if (cachedResource->status() == CachedResource::LoadError)
+            resourceObject->setFailed(true);
+        subresources->addItem(resourceObject);
+    }
+
+    RefPtr<TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree> > childrenArray;
+    for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
+        if (!childrenArray) {
+            childrenArray = TypeBuilder::Array<TypeBuilder::Page::FrameResourceTree>::create();
+            result->setChildFrames(childrenArray);
+        }
+        childrenArray->addItem(buildObjectForFrameTree(child));
+    }
+    return result;
+}
+
+void InspectorPageAgent::updateViewMetrics(int width, int height, double fontScaleFactor, bool fitWindow)
+{
+    m_client->overrideDeviceMetrics(width, height, static_cast<float>(fontScaleFactor), fitWindow);
+
+    Document* document = mainFrame()->document();
+    if (document)
+        document->styleResolverChanged(RecalcStyleImmediately);
+    InspectorInstrumentation::mediaQueryResultChanged(document);
+}
+
+void InspectorPageAgent::updateTouchEventEmulationInPage(bool enabled)
+{
+    m_state->setBoolean(PageAgentState::touchEventEmulationEnabled, enabled);
+    if (mainFrame() && mainFrame()->settings())
+        mainFrame()->settings()->setTouchEventEmulationEnabled(enabled);
+}
+
+void InspectorPageAgent::setGeolocationOverride(ErrorString* error, const double* latitude, const double* longitude, const double* accuracy)
+{
+    GeolocationController* controller = GeolocationController::from(m_page);
+    GeolocationPosition* position = 0;
+    if (!controller) {
+        *error = "Internal error: unable to override geolocation";
+        return;
+    }
+    position = controller->lastPosition();
+    if (!m_geolocationOverridden && position)
+        m_platformGeolocationPosition = position;
+
+    m_geolocationOverridden = true;
+    if (latitude && longitude && accuracy)
+        m_geolocationPosition = GeolocationPosition::create(currentTimeMS(), *latitude, *longitude, *accuracy);
+    else
+        m_geolocationPosition.clear();
+
+    controller->positionChanged(0); // Kick location update.
+}
+
+void InspectorPageAgent::clearGeolocationOverride(ErrorString*)
+{
+    if (!m_geolocationOverridden)
+        return;
+    m_geolocationOverridden = false;
+    m_geolocationPosition.clear();
+
+    GeolocationController* controller = GeolocationController::from(m_page);
+    if (controller && m_platformGeolocationPosition.get())
+        controller->positionChanged(m_platformGeolocationPosition.get());
+}
+
+GeolocationPosition* InspectorPageAgent::overrideGeolocationPosition(GeolocationPosition* position)
+{
+    if (m_geolocationOverridden) {
+        if (position)
+            m_platformGeolocationPosition = position;
+        return m_geolocationPosition.get();
+    }
+    return position;
+}
+
+void InspectorPageAgent::setDeviceOrientationOverride(ErrorString* error, double alpha, double beta, double gamma)
+{
+    DeviceOrientationController* controller = DeviceOrientationController::from(m_page);
+    if (!controller) {
+        *error = "Internal error: unable to override device orientation";
+        return;
+    }
+
+    ErrorString clearError;
+    clearDeviceOrientationOverride(&clearError);
+
+    m_deviceOrientation = DeviceOrientationData::create(true, alpha, true, beta, true, gamma);
+    controller->didChangeDeviceOrientation(m_deviceOrientation.get());
+}
+
+void InspectorPageAgent::clearDeviceOrientationOverride(ErrorString*)
+{
+    m_deviceOrientation.clear();
+}
+
+DeviceOrientationData* InspectorPageAgent::overrideDeviceOrientation(DeviceOrientationData* deviceOrientation)
+{
+    if (m_deviceOrientation)
+        deviceOrientation = m_deviceOrientation.get();
+    return deviceOrientation;
+}
+
+void InspectorPageAgent::setTouchEmulationEnabled(ErrorString* error, bool enabled)
+{
+    if (m_state->getBoolean(PageAgentState::touchEventEmulationEnabled) == enabled)
+        return;
+    UNUSED_PARAM(error);
+    updateTouchEventEmulationInPage(enabled);
+}
+
+void InspectorPageAgent::setEmulatedMedia(ErrorString*, const String& media)
+{
+    String currentMedia = m_state->getString(PageAgentState::pageAgentEmulatedMedia);
+    if (media == currentMedia)
+        return;
+
+    m_state->setString(PageAgentState::pageAgentEmulatedMedia, media);
+    Document* document = 0;
+    if (m_page->mainFrame())
+        document = m_page->mainFrame()->document();
+    if (document) {
+        document->styleResolverChanged(RecalcStyleImmediately);
+        document->updateLayout();
+    }
+}
+
+void InspectorPageAgent::applyEmulatedMedia(String* media)
+{
+    String emulatedMedia = m_state->getString(PageAgentState::pageAgentEmulatedMedia);
+    if (!emulatedMedia.isEmpty())
+        *media = emulatedMedia;
+}
+
+void InspectorPageAgent::getCompositingBordersVisible(ErrorString* error, bool* outParam)
+{
+    Settings* settings = m_page->settings();
+    if (!settings) {
+        *error = "Internal error: unable to read settings";
+        return;
+    }
+
+    *outParam = settings->showDebugBorders() || settings->showRepaintCounter();
+}
+
+void InspectorPageAgent::setCompositingBordersVisible(ErrorString*, bool visible)
+{
+    Settings* settings = m_page->settings();
+    if (!settings)
+        return;
+
+    settings->setShowDebugBorders(visible);
+    settings->setShowRepaintCounter(visible);
+}
+
+void InspectorPageAgent::captureScreenshot(ErrorString*, String*)
+{
+    // Handled on the browser level.
+}
+
+void InspectorPageAgent::handleJavaScriptDialog(ErrorString* errorString, bool accept, const String* promptText)
+{
+    // Handled on the browser level.
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorPageAgent.h b/Source/core/inspector/InspectorPageAgent.h
new file mode 100644
index 0000000..6d9cf83
--- /dev/null
+++ b/Source/core/inspector/InspectorPageAgent.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef InspectorPageAgent_h
+#define InspectorPageAgent_h
+
+
+#include "InspectorFrontend.h"
+#include "core/dom/DeviceOrientationData.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include "core/page/Frame.h"
+#include "modules/geolocation/GeolocationPosition.h"
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CachedResource;
+class DOMWrapperWorld;
+class DocumentLoader;
+class Frame;
+class Frontend;
+class GraphicsContext;
+class InjectedScriptManager;
+class InspectorAgent;
+class InspectorArray;
+class InspectorClient;
+class InspectorObject;
+class InspectorOverlay;
+class InspectorState;
+class InstrumentingAgents;
+class KURL;
+class Page;
+class RenderObject;
+class RegularExpression;
+class SharedBuffer;
+class TextResourceDecoder;
+
+typedef String ErrorString;
+
+class InspectorPageAgent : public InspectorBaseAgent<InspectorPageAgent>, public InspectorBackendDispatcher::PageCommandHandler {
+    WTF_MAKE_NONCOPYABLE(InspectorPageAgent);
+public:
+    enum ResourceType {
+        DocumentResource,
+        StylesheetResource,
+        ImageResource,
+        FontResource,
+        ScriptResource,
+        XHRResource,
+        WebSocketResource,
+        OtherResource
+    };
+
+    static PassOwnPtr<InspectorPageAgent> create(InstrumentingAgents*, Page*, InspectorAgent*, InspectorCompositeState*, InjectedScriptManager*, InspectorClient*, InspectorOverlay*);
+
+    static bool cachedResourceContent(CachedResource*, String* result, bool* base64Encoded);
+    static bool sharedBufferContent(PassRefPtr<SharedBuffer>, const String& textEncodingName, bool withBase64Encode, String* result);
+    static void resourceContent(ErrorString*, Frame*, const KURL&, String* result, bool* base64Encoded);
+
+    static PassRefPtr<SharedBuffer> resourceData(Frame*, const KURL&, String* textEncodingName);
+    static CachedResource* cachedResource(Frame*, const KURL&);
+    static TypeBuilder::Page::ResourceType::Enum resourceTypeJson(ResourceType);
+    static ResourceType cachedResourceType(const CachedResource&);
+    static TypeBuilder::Page::ResourceType::Enum cachedResourceTypeJson(const CachedResource&);
+
+    // Page API for InspectorFrontend
+    virtual void enable(ErrorString*);
+    virtual void disable(ErrorString*);
+    virtual void addScriptToEvaluateOnLoad(ErrorString*, const String& source, String* result);
+    virtual void removeScriptToEvaluateOnLoad(ErrorString*, const String& identifier);
+    virtual void reload(ErrorString*, const bool* optionalIgnoreCache, const String* optionalScriptToEvaluateOnLoad, const String* optionalScriptPreprocessor);
+    virtual void navigate(ErrorString*, const String& url);
+    virtual void getCookies(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::Page::Cookie> >& cookies, WTF::String* cookiesString);
+    virtual void deleteCookie(ErrorString*, const String& cookieName, const String& url);
+    virtual void getResourceTree(ErrorString*, RefPtr<TypeBuilder::Page::FrameResourceTree>&);
+    virtual void getResourceContent(ErrorString*, const String& frameId, const String& url, String* content, bool* base64Encoded);
+    virtual void searchInResource(ErrorString*, const String& frameId, const String& url, const String& query, const bool* optionalCaseSensitive, const bool* optionalIsRegex, RefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchMatch> >&);
+    virtual void searchInResources(ErrorString*, const String&, const bool* caseSensitive, const bool* isRegex, RefPtr<TypeBuilder::Array<TypeBuilder::Page::SearchResult> >&);
+    virtual void setDocumentContent(ErrorString*, const String& frameId, const String& html);
+    virtual void setDeviceMetricsOverride(ErrorString*, int width, int height, double fontScaleFactor, bool fitWindow);
+    virtual void setShowPaintRects(ErrorString*, bool show);
+    virtual void setShowDebugBorders(ErrorString*, bool show);
+    virtual void canShowFPSCounter(ErrorString*, bool*);
+    virtual void setShowFPSCounter(ErrorString*, bool show);
+    virtual void canContinuouslyPaint(ErrorString*, bool*);
+    virtual void setContinuousPaintingEnabled(ErrorString*, bool enabled);
+    virtual void getScriptExecutionStatus(ErrorString*, PageCommandHandler::Result::Enum*);
+    virtual void setScriptExecutionDisabled(ErrorString*, bool);
+    virtual void setGeolocationOverride(ErrorString*, const double*, const double*, const double*);
+    virtual void clearGeolocationOverride(ErrorString*);
+    virtual void setDeviceOrientationOverride(ErrorString*, double, double, double);
+    virtual void clearDeviceOrientationOverride(ErrorString*);
+    virtual void setTouchEmulationEnabled(ErrorString*, bool);
+    virtual void setEmulatedMedia(ErrorString*, const String&);
+    virtual void getCompositingBordersVisible(ErrorString*, bool* out_param);
+    virtual void setCompositingBordersVisible(ErrorString*, bool);
+    virtual void captureScreenshot(ErrorString*, String* data);
+    virtual void handleJavaScriptDialog(ErrorString*, bool accept, const String* promptText);
+
+    // Geolocation override helpers.
+    GeolocationPosition* overrideGeolocationPosition(GeolocationPosition*);
+
+    // DeviceOrientation helper
+    DeviceOrientationData* overrideDeviceOrientation(DeviceOrientationData*);
+
+    // InspectorInstrumentation API
+    void didClearWindowObjectInWorld(Frame*, DOMWrapperWorld*);
+    void domContentEventFired();
+    void loadEventFired();
+    void frameNavigated(DocumentLoader*);
+    void frameDetachedFromParent(Frame*);
+    void loaderDetachedFromFrame(DocumentLoader*);
+    void frameStartedLoading(Frame*);
+    void frameStoppedLoading(Frame*);
+    void frameScheduledNavigation(Frame*, double delay);
+    void frameClearedScheduledNavigation(Frame*);
+    void willRunJavaScriptDialog(const String& message);
+    void didRunJavaScriptDialog();
+    void applyScreenWidthOverride(long*);
+    void applyScreenHeightOverride(long*);
+    void applyEmulatedMedia(String*);
+    void didPaint(RenderObject*, GraphicsContext*, const LayoutRect&);
+    void didLayout(RenderObject*);
+    void didScroll();
+    void didResizeMainFrame();
+    void didRecalculateStyle();
+    void scriptsEnabled(bool isEnabled);
+
+    // Inspector Controller API
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void restore();
+
+    void webViewResized(const IntSize&);
+
+    // Cross-agents API
+    Page* page() { return m_page; }
+    Frame* mainFrame();
+    String createIdentifier();
+    Frame* frameForId(const String& frameId);
+    String frameId(Frame*);
+    bool hasIdForFrame(Frame*) const;
+    String loaderId(DocumentLoader*);
+    Frame* findFrameWithSecurityOrigin(const String& originRawString);
+    Frame* assertFrame(ErrorString*, const String& frameId);
+    String scriptPreprocessor() { return m_scriptPreprocessor; }
+    static DocumentLoader* assertDocumentLoader(ErrorString*, Frame*);
+
+private:
+    InspectorPageAgent(InstrumentingAgents*, Page*, InspectorAgent*, InspectorCompositeState*, InjectedScriptManager*, InspectorClient*, InspectorOverlay*);
+    bool deviceMetricsChanged(int width, int height, double fontScaleFactor, bool fitWindow);
+    void updateViewMetrics(int, int, double, bool);
+    void updateTouchEventEmulationInPage(bool);
+
+    static bool mainResourceContent(Frame*, bool withBase64Encode, String* result);
+    static bool dataContent(const char* data, unsigned size, const String& textEncodingName, bool withBase64Encode, String* result);
+
+    PassRefPtr<TypeBuilder::Page::Frame> buildObjectForFrame(Frame*);
+    PassRefPtr<TypeBuilder::Page::FrameResourceTree> buildObjectForFrameTree(Frame*);
+    Page* m_page;
+    InspectorAgent* m_inspectorAgent;
+    InjectedScriptManager* m_injectedScriptManager;
+    InspectorClient* m_client;
+    InspectorFrontend::Page* m_frontend;
+    InspectorOverlay* m_overlay;
+    long m_lastScriptIdentifier;
+    String m_pendingScriptToEvaluateOnLoadOnce;
+    String m_scriptToEvaluateOnLoadOnce;
+    String m_pendingScriptPreprocessor;
+    String m_scriptPreprocessor;
+    HashMap<Frame*, String> m_frameToIdentifier;
+    HashMap<String, Frame*> m_identifierToFrame;
+    HashMap<DocumentLoader*, String> m_loaderToIdentifier;
+    bool m_enabled;
+    bool m_isFirstLayoutAfterOnLoad;
+    bool m_geolocationOverridden;
+    bool m_ignoreScriptsEnabledNotification;
+    RefPtr<GeolocationPosition> m_geolocationPosition;
+    RefPtr<GeolocationPosition> m_platformGeolocationPosition;
+    RefPtr<DeviceOrientationData> m_deviceOrientation;
+};
+
+
+} // namespace WebCore
+
+
+#endif // !defined(InspectorPagerAgent_h)
diff --git a/Source/core/inspector/InspectorProfilerAgent.cpp b/Source/core/inspector/InspectorProfilerAgent.cpp
new file mode 100644
index 0000000..0d38b5d
--- /dev/null
+++ b/Source/core/inspector/InspectorProfilerAgent.cpp
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorProfilerAgent.h"
+
+#include "InspectorFrontend.h"
+#include "bindings/v8/PageScriptDebugServer.h"
+#include "bindings/v8/ScriptObject.h"
+#include "bindings/v8/ScriptProfiler.h"
+#include "bindings/v8/WorkerScriptDebugServer.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/inspector/ConsoleAPITypes.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InjectedScriptHost.h"
+#include "core/inspector/InspectorConsoleAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/inspector/ScriptProfile.h"
+#include "core/page/Console.h"
+#include "core/page/ConsoleTypes.h"
+#include "core/page/Page.h"
+#include "core/platform/KURL.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/text/StringConcatenate.h>
+
+namespace WebCore {
+
+namespace ProfilerAgentState {
+static const char userInitiatedProfiling[] = "userInitiatedProfiling";
+static const char profilerEnabled[] = "profilerEnabled";
+static const char profileHeadersRequested[] = "profileHeadersRequested";
+}
+
+static const char* const UserInitiatedProfileName = "org.webkit.profiles.user-initiated";
+static const char* const CPUProfileType = "CPU";
+
+
+class PageProfilerAgent : public InspectorProfilerAgent {
+public:
+    PageProfilerAgent(InstrumentingAgents* instrumentingAgents, InspectorConsoleAgent* consoleAgent, Page* inspectedPage, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager)
+        : InspectorProfilerAgent(instrumentingAgents, consoleAgent, state, injectedScriptManager), m_inspectedPage(inspectedPage) { }
+    virtual ~PageProfilerAgent() { }
+
+private:
+    virtual void startProfiling(const String& title)
+    {
+        ScriptProfiler::startForPage(m_inspectedPage, title);
+    }
+
+    virtual PassRefPtr<ScriptProfile> stopProfiling(const String& title)
+    {
+        return ScriptProfiler::stopForPage(m_inspectedPage, title);
+    }
+
+    Page* m_inspectedPage;
+};
+
+PassOwnPtr<InspectorProfilerAgent> InspectorProfilerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorConsoleAgent* consoleAgent, Page* inspectedPage, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager)
+{
+    return adoptPtr(new PageProfilerAgent(instrumentingAgents, consoleAgent, inspectedPage, inspectorState, injectedScriptManager));
+}
+
+class WorkerProfilerAgent : public InspectorProfilerAgent {
+public:
+    WorkerProfilerAgent(InstrumentingAgents* instrumentingAgents, InspectorConsoleAgent* consoleAgent, WorkerContext* workerContext, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager)
+        : InspectorProfilerAgent(instrumentingAgents, consoleAgent, state, injectedScriptManager), m_workerContext(workerContext) { }
+    virtual ~WorkerProfilerAgent() { }
+
+private:
+    virtual void startProfiling(const String& title)
+    {
+        ScriptProfiler::startForWorkerContext(m_workerContext, title);
+    }
+
+    virtual PassRefPtr<ScriptProfile> stopProfiling(const String& title)
+    {
+        return ScriptProfiler::stopForWorkerContext(m_workerContext, title);
+    }
+
+    WorkerContext* m_workerContext;
+};
+
+PassOwnPtr<InspectorProfilerAgent> InspectorProfilerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorConsoleAgent* consoleAgent, WorkerContext* workerContext, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager)
+{
+    return adoptPtr(new WorkerProfilerAgent(instrumentingAgents, consoleAgent, workerContext, inspectorState, injectedScriptManager));
+}
+
+InspectorProfilerAgent::InspectorProfilerAgent(InstrumentingAgents* instrumentingAgents, InspectorConsoleAgent* consoleAgent, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager)
+    : InspectorBaseAgent<InspectorProfilerAgent>("Profiler", instrumentingAgents, inspectorState)
+    , m_consoleAgent(consoleAgent)
+    , m_injectedScriptManager(injectedScriptManager)
+    , m_frontend(0)
+    , m_enabled(false)
+    , m_recordingCPUProfile(false)
+    , m_currentUserInitiatedProfileNumber(-1)
+    , m_nextUserInitiatedProfileNumber(1)
+    , m_profileNameIdleTimeMap(ScriptProfiler::currentProfileNameIdleTimeMap())
+    , m_previousTaskEndTime(0.0)
+{
+    m_instrumentingAgents->setInspectorProfilerAgent(this);
+}
+
+InspectorProfilerAgent::~InspectorProfilerAgent()
+{
+    m_instrumentingAgents->setInspectorProfilerAgent(0);
+}
+
+void InspectorProfilerAgent::addProfile(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL)
+{
+    RefPtr<ScriptProfile> profile = prpProfile;
+    m_profiles.add(profile->uid(), profile);
+    if (m_frontend && m_state->getBoolean(ProfilerAgentState::profileHeadersRequested))
+        m_frontend->addProfileHeader(createProfileHeader(*profile));
+    addProfileFinishedMessageToConsole(profile, lineNumber, sourceURL);
+}
+
+void InspectorProfilerAgent::addProfileFinishedMessageToConsole(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL)
+{
+    if (!m_frontend)
+        return;
+    RefPtr<ScriptProfile> profile = prpProfile;
+    String message = makeString(profile->title(), '#', String::number(profile->uid()));
+    m_consoleAgent->addMessageToConsole(ConsoleAPIMessageSource, ProfileEndMessageType, DebugMessageLevel, message, sourceURL, lineNumber);
+}
+
+void InspectorProfilerAgent::addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL)
+{
+    if (!m_frontend)
+        return;
+    m_consoleAgent->addMessageToConsole(ConsoleAPIMessageSource, ProfileMessageType, DebugMessageLevel, title, sourceURL, lineNumber);
+}
+
+PassRefPtr<TypeBuilder::Profiler::ProfileHeader> InspectorProfilerAgent::createProfileHeader(const ScriptProfile& profile)
+{
+    return TypeBuilder::Profiler::ProfileHeader::create()
+        .setTypeId(TypeBuilder::Profiler::ProfileHeader::TypeId::CPU)
+        .setUid(profile.uid())
+        .setTitle(profile.title())
+        .release();
+}
+
+void InspectorProfilerAgent::enable(ErrorString*)
+{
+    if (enabled())
+        return;
+    m_state->setBoolean(ProfilerAgentState::profilerEnabled, true);
+    enable(false);
+}
+
+void InspectorProfilerAgent::disable(ErrorString*)
+{
+    m_state->setBoolean(ProfilerAgentState::profilerEnabled, false);
+    disable();
+}
+
+void InspectorProfilerAgent::disable()
+{
+    if (!m_enabled)
+        return;
+    m_enabled = false;
+    m_state->setBoolean(ProfilerAgentState::profileHeadersRequested, false);
+}
+
+void InspectorProfilerAgent::enable(bool skipRecompile)
+{
+    if (m_enabled)
+        return;
+    m_enabled = true;
+}
+
+String InspectorProfilerAgent::getCurrentUserInitiatedProfileName(bool incrementProfileNumber)
+{
+    if (incrementProfileNumber)
+        m_currentUserInitiatedProfileNumber = m_nextUserInitiatedProfileNumber++;
+
+    return makeString(UserInitiatedProfileName, '.', String::number(m_currentUserInitiatedProfileNumber));
+}
+
+void InspectorProfilerAgent::getProfileHeaders(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::Profiler::ProfileHeader> >& headers)
+{
+    m_state->setBoolean(ProfilerAgentState::profileHeadersRequested, true);
+    headers = TypeBuilder::Array<TypeBuilder::Profiler::ProfileHeader>::create();
+
+    ProfilesMap::iterator profilesEnd = m_profiles.end();
+    for (ProfilesMap::iterator it = m_profiles.begin(); it != profilesEnd; ++it)
+        headers->addItem(createProfileHeader(*it->value));
+}
+
+void InspectorProfilerAgent::getCPUProfile(ErrorString* errorString, int rawUid, RefPtr<TypeBuilder::Profiler::CPUProfile>& profileObject)
+{
+    unsigned uid = static_cast<unsigned>(rawUid);
+    ProfilesMap::iterator it = m_profiles.find(uid);
+    if (it == m_profiles.end()) {
+        *errorString = "Profile wasn't found";
+        return;
+    }
+    profileObject = TypeBuilder::Profiler::CPUProfile::create();
+    profileObject->setHead(it->value->buildInspectorObjectForHead());
+    profileObject->setIdleTime(it->value->idleTime());
+    profileObject->setSamples(it->value->buildInspectorObjectForSamples());
+}
+
+void InspectorProfilerAgent::removeProfile(ErrorString*, const String& type, int rawUid)
+{
+    unsigned uid = static_cast<unsigned>(rawUid);
+    if (type == CPUProfileType) {
+        if (m_profiles.contains(uid))
+            m_profiles.remove(uid);
+    }
+}
+
+void InspectorProfilerAgent::clearProfiles(ErrorString*)
+{
+    stop();
+    m_profiles.clear();
+    m_currentUserInitiatedProfileNumber = 1;
+    m_nextUserInitiatedProfileNumber = 1;
+    resetFrontendProfiles();
+    m_injectedScriptManager->injectedScriptHost()->clearInspectedObjects();
+}
+
+void InspectorProfilerAgent::resetFrontendProfiles()
+{
+    if (!m_frontend)
+        return;
+    if (!m_state->getBoolean(ProfilerAgentState::profileHeadersRequested))
+        return;
+    if (m_profiles.isEmpty())
+        m_frontend->resetProfiles();
+}
+
+void InspectorProfilerAgent::setFrontend(InspectorFrontend* frontend)
+{
+    m_frontend = frontend->profiler();
+}
+
+void InspectorProfilerAgent::clearFrontend()
+{
+    m_frontend = 0;
+    stop();
+    ErrorString error;
+    disable(&error);
+}
+
+void InspectorProfilerAgent::restore()
+{
+    // Need to restore enablement state here as in setFrontend m_state wasn't loaded yet.
+    restoreEnablement();
+    resetFrontendProfiles();
+    if (m_state->getBoolean(ProfilerAgentState::userInitiatedProfiling))
+        start();
+}
+
+void InspectorProfilerAgent::restoreEnablement()
+{
+    if (m_state->getBoolean(ProfilerAgentState::profilerEnabled)) {
+        ErrorString error;
+        enable(&error);
+    }
+}
+
+void InspectorProfilerAgent::start(ErrorString*)
+{
+    if (m_recordingCPUProfile)
+        return;
+    if (!enabled()) {
+        enable(true);
+    }
+    m_recordingCPUProfile = true;
+    String title = getCurrentUserInitiatedProfileName(true);
+    startProfiling(title);
+    addStartProfilingMessageToConsole(title, 0, String());
+    toggleRecordButton(true);
+    m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, true);
+}
+
+void InspectorProfilerAgent::stop(ErrorString* errorString, RefPtr<TypeBuilder::Profiler::ProfileHeader>& header)
+{
+    header = stop(errorString);
+}
+
+PassRefPtr<TypeBuilder::Profiler::ProfileHeader> InspectorProfilerAgent::stop(ErrorString* errorString)
+{
+    if (!m_recordingCPUProfile)
+        return 0;
+    m_recordingCPUProfile = false;
+    String title = getCurrentUserInitiatedProfileName();
+    RefPtr<ScriptProfile> profile = stopProfiling(title);
+    RefPtr<TypeBuilder::Profiler::ProfileHeader> profileHeader;
+    if (profile) {
+        addProfile(profile, 0, String());
+        profileHeader = createProfileHeader(*profile);
+    } else if (errorString)
+        *errorString = "Profile wasn't found";
+    toggleRecordButton(false);
+    m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, false);
+    return profileHeader;
+}
+
+void InspectorProfilerAgent::toggleRecordButton(bool isProfiling)
+{
+    if (m_frontend)
+        m_frontend->setRecordingProfile(isProfiling);
+}
+
+void InspectorProfilerAgent::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::InspectorProfilerAgent);
+    InspectorBaseAgent<InspectorProfilerAgent>::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_consoleAgent, "consoleAgent");
+    info.addMember(m_injectedScriptManager, "injectedScriptManager");
+    info.addWeakPointer(m_frontend);
+    info.addMember(m_profiles, "profiles");
+        info.addMember(m_profileNameIdleTimeMap, "profileNameIdleTimeMap");
+}
+
+void InspectorProfilerAgent::willProcessTask()
+{
+    if (!m_profileNameIdleTimeMap || !m_profileNameIdleTimeMap->size())
+        return;
+    if (!m_previousTaskEndTime)
+        return;
+
+    double idleTime = WTF::monotonicallyIncreasingTime() - m_previousTaskEndTime;
+    m_previousTaskEndTime = 0.0;
+    ProfileNameIdleTimeMap::iterator end = m_profileNameIdleTimeMap->end();
+    for (ProfileNameIdleTimeMap::iterator it = m_profileNameIdleTimeMap->begin(); it != end; ++it)
+        it->value += idleTime;
+}
+
+void InspectorProfilerAgent::didProcessTask()
+{
+    if (!m_profileNameIdleTimeMap || !m_profileNameIdleTimeMap->size())
+        return;
+    m_previousTaskEndTime = WTF::monotonicallyIncreasingTime();
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorProfilerAgent.h b/Source/core/inspector/InspectorProfilerAgent.h
new file mode 100644
index 0000000..aaa2e54
--- /dev/null
+++ b/Source/core/inspector/InspectorProfilerAgent.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef InspectorProfilerAgent_h
+#define InspectorProfilerAgent_h
+
+
+#include "InspectorFrontend.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class InjectedScriptManager;
+class InspectorArray;
+class InspectorConsoleAgent;
+class InspectorFrontend;
+class InspectorObject;
+class InspectorState;
+class InstrumentingAgents;
+class Page;
+class ScriptProfile;
+class WorkerContext;
+
+typedef String ErrorString;
+
+class InspectorProfilerAgent : public InspectorBaseAgent<InspectorProfilerAgent>, public InspectorBackendDispatcher::ProfilerCommandHandler {
+    WTF_MAKE_NONCOPYABLE(InspectorProfilerAgent); WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<InspectorProfilerAgent> create(InstrumentingAgents*, InspectorConsoleAgent*, Page*, InspectorCompositeState*, InjectedScriptManager*);
+    static PassOwnPtr<InspectorProfilerAgent> create(InstrumentingAgents*, InspectorConsoleAgent*, WorkerContext*, InspectorCompositeState*, InjectedScriptManager*);
+    virtual ~InspectorProfilerAgent();
+
+    void addProfile(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL);
+    void addProfileFinishedMessageToConsole(PassRefPtr<ScriptProfile>, unsigned lineNumber, const String& sourceURL);
+    void addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL);
+    virtual void clearProfiles(ErrorString*);
+
+    virtual void enable(ErrorString*);
+    virtual void disable(ErrorString*);
+    virtual void start(ErrorString* = 0);
+    virtual void stop(ErrorString*, RefPtr<TypeBuilder::Profiler::ProfileHeader>& header);
+
+    void disable();
+    void enable(bool skipRecompile);
+    bool enabled() { return m_enabled; }
+    String getCurrentUserInitiatedProfileName(bool incrementProfileNumber = false);
+    virtual void getProfileHeaders(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::Profiler::ProfileHeader> >&);
+    virtual void getCPUProfile(ErrorString*, int uid, RefPtr<TypeBuilder::Profiler::CPUProfile>&);
+    virtual void removeProfile(ErrorString*, const String& type, int uid);
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void restore();
+
+    void toggleRecordButton(bool isProfiling);
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+    void willProcessTask();
+    void didProcessTask();
+
+protected:
+    InspectorProfilerAgent(InstrumentingAgents*, InspectorConsoleAgent*, InspectorCompositeState*, InjectedScriptManager*);
+    virtual void startProfiling(const String& title) = 0;
+    virtual PassRefPtr<ScriptProfile> stopProfiling(const String& title) = 0;
+
+private:
+    typedef HashMap<unsigned int, RefPtr<ScriptProfile> > ProfilesMap;
+
+    void resetFrontendProfiles();
+    void restoreEnablement();
+    PassRefPtr<TypeBuilder::Profiler::ProfileHeader> stop(ErrorString* = 0);
+
+    PassRefPtr<TypeBuilder::Profiler::ProfileHeader> createProfileHeader(const ScriptProfile&);
+
+    InspectorConsoleAgent* m_consoleAgent;
+    InjectedScriptManager* m_injectedScriptManager;
+    InspectorFrontend::Profiler* m_frontend;
+    bool m_enabled;
+    bool m_recordingCPUProfile;
+    int m_currentUserInitiatedProfileNumber;
+    unsigned m_nextUserInitiatedProfileNumber;
+    ProfilesMap m_profiles;
+
+    typedef HashMap<String, double> ProfileNameIdleTimeMap;
+    ProfileNameIdleTimeMap* m_profileNameIdleTimeMap;
+    double m_previousTaskEndTime;
+};
+
+} // namespace WebCore
+
+
+#endif // !defined(InspectorProfilerAgent_h)
diff --git a/Source/core/inspector/InspectorResourceAgent.cpp b/Source/core/inspector/InspectorResourceAgent.cpp
new file mode 100644
index 0000000..b80f5b3
--- /dev/null
+++ b/Source/core/inspector/InspectorResourceAgent.cpp
@@ -0,0 +1,674 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorResourceAgent.h"
+
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptCallStackFactory.h"
+#include "core/dom/Document.h"
+#include "core/dom/ExceptionCodePlaceholder.h"
+#include "core/dom/ScriptableDocumentParser.h"
+#include "core/inspector/IdentifiersFactory.h"
+#include "core/inspector/InspectorClient.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/inspector/NetworkResourcesData.h"
+#include "core/inspector/ScriptCallStack.h"
+#include "core/loader/DocumentLoader.h"
+#include "core/loader/FrameLoader.h"
+#include "core/loader/ResourceLoader.h"
+#include "core/loader/UniqueIdentifier.h"
+#include "core/loader/cache/CachedRawResource.h"
+#include "core/loader/cache/CachedResource.h"
+#include "core/loader/cache/CachedResourceLoader.h"
+#include "core/loader/cache/MemoryCache.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/KURL.h"
+#include "core/platform/network/HTTPHeaderMap.h"
+#include "core/platform/network/ResourceError.h"
+#include "core/platform/network/ResourceRequest.h"
+#include "core/platform/network/ResourceResponse.h"
+#include "core/xml/XMLHttpRequest.h"
+#include "modules/websockets/WebSocketFrame.h"
+#include "modules/websockets/WebSocketHandshakeRequest.h"
+#include "modules/websockets/WebSocketHandshakeResponse.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/HexNumber.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+namespace ResourceAgentState {
+static const char resourceAgentEnabled[] = "resourceAgentEnabled";
+static const char extraRequestHeaders[] = "extraRequestHeaders";
+static const char cacheDisabled[] = "cacheDisabled";
+static const char userAgentOverride[] = "userAgentOverride";
+}
+
+void InspectorResourceAgent::setFrontend(InspectorFrontend* frontend)
+{
+    m_frontend = frontend->network();
+}
+
+void InspectorResourceAgent::clearFrontend()
+{
+    m_frontend = 0;
+    ErrorString error;
+    disable(&error);
+}
+
+void InspectorResourceAgent::restore()
+{
+    if (m_state->getBoolean(ResourceAgentState::resourceAgentEnabled))
+        enable();
+}
+
+static PassRefPtr<InspectorObject> buildObjectForHeaders(const HTTPHeaderMap& headers)
+{
+    RefPtr<InspectorObject> headersObject = InspectorObject::create();
+    HTTPHeaderMap::const_iterator end = headers.end();
+    for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it)
+        headersObject->setString(it->key.string(), it->value);
+    return headersObject;
+}
+
+static PassRefPtr<TypeBuilder::Network::ResourceTiming> buildObjectForTiming(const ResourceLoadTiming& timing, DocumentLoader* loader)
+{
+    return TypeBuilder::Network::ResourceTiming::create()
+        .setRequestTime(loader->timing()->monotonicTimeToPseudoWallTime(timing.convertResourceLoadTimeToMonotonicTime(0)))
+        .setProxyStart(timing.proxyStart)
+        .setProxyEnd(timing.proxyEnd)
+        .setDnsStart(timing.dnsStart)
+        .setDnsEnd(timing.dnsEnd)
+        .setConnectStart(timing.connectStart)
+        .setConnectEnd(timing.connectEnd)
+        .setSslStart(timing.sslStart)
+        .setSslEnd(timing.sslEnd)
+        .setSendStart(timing.sendStart)
+        .setSendEnd(timing.sendEnd)
+        .setReceiveHeadersEnd(timing.receiveHeadersEnd)
+        .release();
+}
+
+static PassRefPtr<TypeBuilder::Network::Request> buildObjectForResourceRequest(const ResourceRequest& request)
+{
+    RefPtr<TypeBuilder::Network::Request> requestObject = TypeBuilder::Network::Request::create()
+        .setUrl(request.url().string())
+        .setMethod(request.httpMethod())
+        .setHeaders(buildObjectForHeaders(request.httpHeaderFields()));
+    if (request.httpBody() && !request.httpBody()->isEmpty())
+        requestObject->setPostData(request.httpBody()->flattenToString());
+    return requestObject;
+}
+
+static PassRefPtr<TypeBuilder::Network::Response> buildObjectForResourceResponse(const ResourceResponse& response, DocumentLoader* loader)
+{
+    if (response.isNull())
+        return 0;
+
+
+    double status;
+    String statusText;
+    if (response.resourceLoadInfo() && response.resourceLoadInfo()->httpStatusCode) {
+        status = response.resourceLoadInfo()->httpStatusCode;
+        statusText = response.resourceLoadInfo()->httpStatusText;
+    } else {
+        status = response.httpStatusCode();
+        statusText = response.httpStatusText();
+    }
+    RefPtr<InspectorObject> headers;
+    if (response.resourceLoadInfo())
+        headers = buildObjectForHeaders(response.resourceLoadInfo()->responseHeaders);
+    else
+        headers = buildObjectForHeaders(response.httpHeaderFields());
+
+    RefPtr<TypeBuilder::Network::Response> responseObject = TypeBuilder::Network::Response::create()
+        .setUrl(response.url().string())
+        .setStatus(status)
+        .setStatusText(statusText)
+        .setHeaders(headers)
+        .setMimeType(response.mimeType())
+        .setConnectionReused(response.connectionReused())
+        .setConnectionId(response.connectionID());
+
+    responseObject->setFromDiskCache(response.wasCached());
+    if (response.resourceLoadTiming())
+        responseObject->setTiming(buildObjectForTiming(*response.resourceLoadTiming(), loader));
+
+    if (response.resourceLoadInfo()) {
+        if (!response.resourceLoadInfo()->responseHeadersText.isEmpty())
+            responseObject->setHeadersText(response.resourceLoadInfo()->responseHeadersText);
+
+        responseObject->setRequestHeaders(buildObjectForHeaders(response.resourceLoadInfo()->requestHeaders));
+        if (!response.resourceLoadInfo()->requestHeadersText.isEmpty())
+            responseObject->setRequestHeadersText(response.resourceLoadInfo()->requestHeadersText);
+    }
+
+    return responseObject;
+}
+
+static PassRefPtr<TypeBuilder::Network::CachedResource> buildObjectForCachedResource(const CachedResource& cachedResource, DocumentLoader* loader)
+{
+    RefPtr<TypeBuilder::Network::CachedResource> resourceObject = TypeBuilder::Network::CachedResource::create()
+        .setUrl(cachedResource.url())
+        .setType(InspectorPageAgent::cachedResourceTypeJson(cachedResource))
+        .setBodySize(cachedResource.encodedSize());
+    RefPtr<TypeBuilder::Network::Response> resourceResponse = buildObjectForResourceResponse(cachedResource.response(), loader);
+    if (resourceResponse)
+        resourceObject->setResponse(resourceResponse);
+    return resourceObject;
+}
+
+InspectorResourceAgent::~InspectorResourceAgent()
+{
+    if (m_state->getBoolean(ResourceAgentState::resourceAgentEnabled)) {
+        ErrorString error;
+        disable(&error);
+    }
+    ASSERT(!m_instrumentingAgents->inspectorResourceAgent());
+}
+
+void InspectorResourceAgent::willSendResourceRequest(unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse)
+{
+    String requestId = IdentifiersFactory::requestId(identifier);
+    m_resourcesData->resourceCreated(requestId, m_pageAgent->loaderId(loader));
+
+    RefPtr<InspectorObject> headers = m_state->getObject(ResourceAgentState::extraRequestHeaders);
+
+    if (headers) {
+        InspectorObject::const_iterator end = headers->end();
+        for (InspectorObject::const_iterator it = headers->begin(); it != end; ++it) {
+            String value;
+            if (it->value->asString(&value))
+                request.setHTTPHeaderField(it->key, value);
+        }
+    }
+
+    request.setReportLoadTiming(true);
+    request.setReportRawHeaders(true);
+
+    if (m_state->getBoolean(ResourceAgentState::cacheDisabled)) {
+        request.setHTTPHeaderField("Pragma", "no-cache");
+        request.setCachePolicy(ReloadIgnoringCacheData);
+        request.setHTTPHeaderField("Cache-Control", "no-cache");
+    }
+
+    RefPtr<TypeBuilder::Network::Initiator> initiatorObject = buildInitiatorObject(loader->frame() ? loader->frame()->document() : 0);
+    m_frontend->requestWillBeSent(requestId, m_pageAgent->frameId(loader->frame()), m_pageAgent->loaderId(loader), loader->url().string(), buildObjectForResourceRequest(request), currentTime(), initiatorObject, buildObjectForResourceResponse(redirectResponse, loader));
+}
+
+void InspectorResourceAgent::markResourceAsCached(unsigned long identifier)
+{
+    m_frontend->requestServedFromCache(IdentifiersFactory::requestId(identifier));
+}
+
+void InspectorResourceAgent::didReceiveResourceResponse(unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response, ResourceLoader* resourceLoader)
+{
+    if (!loader)
+        return;
+
+    String requestId = IdentifiersFactory::requestId(identifier);
+    RefPtr<TypeBuilder::Network::Response> resourceResponse = buildObjectForResourceResponse(response, loader);
+
+    bool isNotModified = response.httpStatusCode() == 304;
+
+    CachedResource* cachedResource = 0;
+    if (resourceLoader && !isNotModified)
+        cachedResource = resourceLoader->cachedResource();
+    if (!cachedResource)
+        cachedResource = InspectorPageAgent::cachedResource(loader->frame(), response.url());
+
+    if (cachedResource) {
+        // Use mime type from cached resource in case the one in response is empty.
+        if (resourceResponse && response.mimeType().isEmpty())
+            resourceResponse->setString(TypeBuilder::Network::Response::MimeType, cachedResource->response().mimeType());
+        m_resourcesData->addCachedResource(requestId, cachedResource);
+    }
+
+    InspectorPageAgent::ResourceType type = cachedResource ? InspectorPageAgent::cachedResourceType(*cachedResource) : InspectorPageAgent::OtherResource;
+    if (m_loadingXHRSynchronously || m_resourcesData->resourceType(requestId) == InspectorPageAgent::XHRResource)
+        type = InspectorPageAgent::XHRResource;
+    else if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::ScriptResource)
+        type = InspectorPageAgent::ScriptResource;
+    else if (equalIgnoringFragmentIdentifier(response.url(), loader->url()) && !loader->isCommitted())
+        type = InspectorPageAgent::DocumentResource;
+
+    m_resourcesData->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), response);
+    m_resourcesData->setResourceType(requestId, type);
+    m_frontend->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), m_pageAgent->loaderId(loader), currentTime(), InspectorPageAgent::resourceTypeJson(type), resourceResponse);
+    // If we revalidated the resource and got Not modified, send content length following didReceiveResponse
+    // as there will be no calls to didReceiveData from the network stack.
+    if (isNotModified && cachedResource && cachedResource->encodedSize())
+        didReceiveData(identifier, 0, cachedResource->encodedSize(), 0);
+}
+
+static bool isErrorStatusCode(int statusCode)
+{
+    return statusCode >= 400;
+}
+
+void InspectorResourceAgent::didReceiveData(unsigned long identifier, const char* data, int dataLength, int encodedDataLength)
+{
+    String requestId = IdentifiersFactory::requestId(identifier);
+
+    if (data) {
+        NetworkResourcesData::ResourceData const* resourceData = m_resourcesData->data(requestId);
+        if (resourceData && !m_loadingXHRSynchronously && (!resourceData->cachedResource() || resourceData->cachedResource()->dataBufferingPolicy() == DoNotBufferData || isErrorStatusCode(resourceData->httpStatusCode())))
+            m_resourcesData->maybeAddResourceData(requestId, data, dataLength);
+    }
+
+    m_frontend->dataReceived(requestId, currentTime(), dataLength, encodedDataLength);
+}
+
+void InspectorResourceAgent::didFinishLoading(unsigned long identifier, DocumentLoader* loader, double finishTime)
+{
+    String requestId = IdentifiersFactory::requestId(identifier);
+    if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::DocumentResource) {
+        RefPtr<SharedBuffer> buffer = loader->frameLoader()->documentLoader()->mainResourceData();
+        m_resourcesData->addResourceSharedBuffer(requestId, buffer, loader->frame()->document()->inputEncoding());
+    }
+
+    m_resourcesData->maybeDecodeDataToContent(requestId);
+
+    if (!finishTime)
+        finishTime = currentTime();
+
+    m_frontend->loadingFinished(requestId, finishTime);
+}
+
+void InspectorResourceAgent::didFailLoading(unsigned long identifier, DocumentLoader* loader, const ResourceError& error)
+{
+    String requestId = IdentifiersFactory::requestId(identifier);
+
+    if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::DocumentResource) {
+        Frame* frame = loader ? loader->frame() : 0;
+        if (frame && frame->loader()->documentLoader() && frame->document()) {
+            RefPtr<SharedBuffer> buffer = frame->loader()->documentLoader()->mainResourceData();
+            m_resourcesData->addResourceSharedBuffer(requestId, buffer, frame->document()->inputEncoding());
+        }
+    }
+
+    bool canceled = error.isCancellation();
+    m_frontend->loadingFailed(requestId, currentTime(), error.localizedDescription(), canceled ? &canceled : 0);
+}
+
+void InspectorResourceAgent::didLoadResourceFromMemoryCache(DocumentLoader* loader, CachedResource* resource)
+{
+    String loaderId = m_pageAgent->loaderId(loader);
+    String frameId = m_pageAgent->frameId(loader->frame());
+    unsigned long identifier = createUniqueIdentifier();
+    String requestId = IdentifiersFactory::requestId(identifier);
+    m_resourcesData->resourceCreated(requestId, loaderId);
+    m_resourcesData->addCachedResource(requestId, resource);
+    if (resource->type() == CachedResource::RawResource) {
+        CachedRawResource* rawResource = static_cast<CachedRawResource*>(resource);
+        String rawRequestId = IdentifiersFactory::requestId(rawResource->identifier());
+        m_resourcesData->reuseXHRReplayData(requestId, rawRequestId);
+    }
+
+    RefPtr<TypeBuilder::Network::Initiator> initiatorObject = buildInitiatorObject(loader->frame() ? loader->frame()->document() : 0);
+
+    m_frontend->requestServedFromMemoryCache(requestId, frameId, loaderId, loader->url().string(), currentTime(), initiatorObject, buildObjectForCachedResource(*resource, loader));
+}
+
+void InspectorResourceAgent::scriptImported(unsigned long identifier, const String& sourceString)
+{
+    m_resourcesData->setResourceContent(IdentifiersFactory::requestId(identifier), sourceString);
+}
+
+void InspectorResourceAgent::didReceiveScriptResponse(unsigned long identifier)
+{
+    m_resourcesData->setResourceType(IdentifiersFactory::requestId(identifier), InspectorPageAgent::ScriptResource);
+}
+
+void InspectorResourceAgent::documentThreadableLoaderStartedLoadingForClient(unsigned long identifier, ThreadableLoaderClient* client)
+{
+    if (!client)
+        return;
+
+    PendingXHRReplayDataMap::iterator it = m_pendingXHRReplayData.find(client);
+    if (it == m_pendingXHRReplayData.end())
+        return;
+
+    XHRReplayData* xhrReplayData = it->value.get();
+    String requestId = IdentifiersFactory::requestId(identifier);
+    m_resourcesData->setXHRReplayData(requestId, xhrReplayData);
+}
+
+void InspectorResourceAgent::willLoadXHR(ThreadableLoaderClient* client, const String& method, const KURL& url, bool async, PassRefPtr<FormData> formData, const HTTPHeaderMap& headers, bool includeCredentials)
+{
+    RefPtr<XHRReplayData> xhrReplayData = XHRReplayData::create(method, url, async, formData, includeCredentials);
+    HTTPHeaderMap::const_iterator end = headers.end();
+    for (HTTPHeaderMap::const_iterator it = headers.begin(); it!= end; ++it)
+        xhrReplayData->addHeader(it->key, it->value);
+    m_pendingXHRReplayData.set(client, xhrReplayData);
+}
+
+void InspectorResourceAgent::didFailXHRLoading(ThreadableLoaderClient* client)
+{
+    m_pendingXHRReplayData.remove(client);
+}
+
+void InspectorResourceAgent::didFinishXHRLoading(ThreadableLoaderClient* client, unsigned long identifier, const String& sourceString, const String&, const String&, unsigned)
+{
+    // For Asynchronous XHRs, the inspector can grab the data directly off of the CachedResource. For sync XHRs, we need to
+    // provide the data here, since no CachedResource was involved.
+    if (m_loadingXHRSynchronously)
+        m_resourcesData->setResourceContent(IdentifiersFactory::requestId(identifier), sourceString);
+    m_pendingXHRReplayData.remove(client);
+}
+
+void InspectorResourceAgent::didReceiveXHRResponse(unsigned long identifier)
+{
+    m_resourcesData->setResourceType(IdentifiersFactory::requestId(identifier), InspectorPageAgent::XHRResource);
+}
+
+void InspectorResourceAgent::willLoadXHRSynchronously()
+{
+    m_loadingXHRSynchronously = true;
+}
+
+void InspectorResourceAgent::didLoadXHRSynchronously()
+{
+    m_loadingXHRSynchronously = false;
+}
+
+void InspectorResourceAgent::willDestroyCachedResource(CachedResource* cachedResource)
+{
+    Vector<String> requestIds = m_resourcesData->removeCachedResource(cachedResource);
+    if (!requestIds.size())
+        return;
+
+    String content;
+    bool base64Encoded;
+    if (!InspectorPageAgent::cachedResourceContent(cachedResource, &content, &base64Encoded))
+        return;
+    Vector<String>::iterator end = requestIds.end();
+    for (Vector<String>::iterator it = requestIds.begin(); it != end; ++it)
+        m_resourcesData->setResourceContent(*it, content, base64Encoded);
+}
+
+void InspectorResourceAgent::applyUserAgentOverride(String* userAgent)
+{
+    String userAgentOverride = m_state->getString(ResourceAgentState::userAgentOverride);
+    if (!userAgentOverride.isEmpty())
+        *userAgent = userAgentOverride;
+}
+
+void InspectorResourceAgent::willRecalculateStyle(Document*)
+{
+    m_isRecalculatingStyle = true;
+}
+
+void InspectorResourceAgent::didRecalculateStyle()
+{
+    m_isRecalculatingStyle = false;
+    m_styleRecalculationInitiator = nullptr;
+}
+
+void InspectorResourceAgent::didScheduleStyleRecalculation(Document* document)
+{
+    if (!m_styleRecalculationInitiator)
+        m_styleRecalculationInitiator = buildInitiatorObject(document);
+}
+
+PassRefPtr<TypeBuilder::Network::Initiator> InspectorResourceAgent::buildInitiatorObject(Document* document)
+{
+    RefPtr<ScriptCallStack> stackTrace = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
+    if (stackTrace && stackTrace->size() > 0) {
+        RefPtr<TypeBuilder::Network::Initiator> initiatorObject = TypeBuilder::Network::Initiator::create()
+            .setType(TypeBuilder::Network::Initiator::Type::Script);
+        initiatorObject->setStackTrace(stackTrace->buildInspectorArray());
+        return initiatorObject;
+    }
+
+    if (document && document->scriptableDocumentParser()) {
+        RefPtr<TypeBuilder::Network::Initiator> initiatorObject = TypeBuilder::Network::Initiator::create()
+            .setType(TypeBuilder::Network::Initiator::Type::Parser);
+        initiatorObject->setUrl(document->url().string());
+        initiatorObject->setLineNumber(document->scriptableDocumentParser()->lineNumber().oneBasedInt());
+        return initiatorObject;
+    }
+
+    if (m_isRecalculatingStyle && m_styleRecalculationInitiator)
+        return m_styleRecalculationInitiator;
+
+    return TypeBuilder::Network::Initiator::create()
+        .setType(TypeBuilder::Network::Initiator::Type::Other)
+        .release();
+}
+
+void InspectorResourceAgent::didCreateWebSocket(Document*, unsigned long identifier, const KURL& requestURL, const String&)
+{
+    m_frontend->webSocketCreated(IdentifiersFactory::requestId(identifier), requestURL.string());
+}
+
+void InspectorResourceAgent::willSendWebSocketHandshakeRequest(Document*, unsigned long identifier, const WebSocketHandshakeRequest& request)
+{
+    RefPtr<TypeBuilder::Network::WebSocketRequest> requestObject = TypeBuilder::Network::WebSocketRequest::create()
+        .setHeaders(buildObjectForHeaders(request.headerFields()));
+    m_frontend->webSocketWillSendHandshakeRequest(IdentifiersFactory::requestId(identifier), currentTime(), requestObject);
+}
+
+void InspectorResourceAgent::didReceiveWebSocketHandshakeResponse(Document*, unsigned long identifier, const WebSocketHandshakeResponse& response)
+{
+    RefPtr<TypeBuilder::Network::WebSocketResponse> responseObject = TypeBuilder::Network::WebSocketResponse::create()
+        .setStatus(response.statusCode())
+        .setStatusText(response.statusText())
+        .setHeaders(buildObjectForHeaders(response.headerFields()));
+    m_frontend->webSocketHandshakeResponseReceived(IdentifiersFactory::requestId(identifier), currentTime(), responseObject);
+}
+
+void InspectorResourceAgent::didCloseWebSocket(Document*, unsigned long identifier)
+{
+    m_frontend->webSocketClosed(IdentifiersFactory::requestId(identifier), currentTime());
+}
+
+void InspectorResourceAgent::didReceiveWebSocketFrame(unsigned long identifier, const WebSocketFrame& frame)
+{
+    RefPtr<TypeBuilder::Network::WebSocketFrame> frameObject = TypeBuilder::Network::WebSocketFrame::create()
+        .setOpcode(frame.opCode)
+        .setMask(frame.masked)
+        .setPayloadData(String(frame.payload, frame.payloadLength));
+    m_frontend->webSocketFrameReceived(IdentifiersFactory::requestId(identifier), currentTime(), frameObject);
+}
+
+void InspectorResourceAgent::didSendWebSocketFrame(unsigned long identifier, const WebSocketFrame& frame)
+{
+    RefPtr<TypeBuilder::Network::WebSocketFrame> frameObject = TypeBuilder::Network::WebSocketFrame::create()
+        .setOpcode(frame.opCode)
+        .setMask(frame.masked)
+        .setPayloadData(String(frame.payload, frame.payloadLength));
+    m_frontend->webSocketFrameSent(IdentifiersFactory::requestId(identifier), currentTime(), frameObject);
+}
+
+void InspectorResourceAgent::didReceiveWebSocketFrameError(unsigned long identifier, const String& errorMessage)
+{
+    m_frontend->webSocketFrameError(IdentifiersFactory::requestId(identifier), currentTime(), errorMessage);
+}
+
+// called from Internals for layout test purposes.
+void InspectorResourceAgent::setResourcesDataSizeLimitsFromInternals(int maximumResourcesContentSize, int maximumSingleResourceContentSize)
+{
+    m_resourcesData->setResourcesDataSizeLimits(maximumResourcesContentSize, maximumSingleResourceContentSize);
+}
+
+void InspectorResourceAgent::enable(ErrorString*)
+{
+    enable();
+}
+
+void InspectorResourceAgent::enable()
+{
+    if (!m_frontend)
+        return;
+    m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, true);
+    m_instrumentingAgents->setInspectorResourceAgent(this);
+}
+
+void InspectorResourceAgent::disable(ErrorString*)
+{
+    m_state->setBoolean(ResourceAgentState::resourceAgentEnabled, false);
+    m_state->setString(ResourceAgentState::userAgentOverride, "");
+    m_instrumentingAgents->setInspectorResourceAgent(0);
+    m_resourcesData->clear();
+}
+
+void InspectorResourceAgent::setUserAgentOverride(ErrorString*, const String& userAgent)
+{
+    m_state->setString(ResourceAgentState::userAgentOverride, userAgent);
+}
+
+void InspectorResourceAgent::setExtraHTTPHeaders(ErrorString*, const RefPtr<InspectorObject>& headers)
+{
+    m_state->setObject(ResourceAgentState::extraRequestHeaders, headers);
+}
+
+void InspectorResourceAgent::getResponseBody(ErrorString* errorString, const String& requestId, String* content, bool* base64Encoded)
+{
+    NetworkResourcesData::ResourceData const* resourceData = m_resourcesData->data(requestId);
+    if (!resourceData) {
+        *errorString = "No resource with given identifier found";
+        return;
+    }
+
+    if (resourceData->hasContent()) {
+        *base64Encoded = resourceData->base64Encoded();
+        *content = resourceData->content();
+        return;
+    }
+
+    if (resourceData->isContentEvicted()) {
+        *errorString = "Request content was evicted from inspector cache";
+        return;
+    }
+
+    if (resourceData->buffer() && !resourceData->textEncodingName().isNull()) {
+        *base64Encoded = false;
+        if (InspectorPageAgent::sharedBufferContent(resourceData->buffer(), resourceData->textEncodingName(), *base64Encoded, content))
+            return;
+    }
+
+    if (resourceData->cachedResource()) {
+        if (InspectorPageAgent::cachedResourceContent(resourceData->cachedResource(), content, base64Encoded))
+            return;
+    }
+
+    *errorString = "No data found for resource with given identifier";
+}
+
+void InspectorResourceAgent::replayXHR(ErrorString*, const String& requestId)
+{
+    RefPtr<XMLHttpRequest> xhr = XMLHttpRequest::create(m_pageAgent->mainFrame()->document());
+    String actualRequestId = requestId;
+
+    XHRReplayData* xhrReplayData = m_resourcesData->xhrReplayData(requestId);
+    if (!xhrReplayData)
+        return;
+
+    CachedResource* cachedResource = memoryCache()->resourceForURL(xhrReplayData->url());
+    if (cachedResource)
+        memoryCache()->remove(cachedResource);
+
+    xhr->open(xhrReplayData->method(), xhrReplayData->url(), xhrReplayData->async(), IGNORE_EXCEPTION);
+    HTTPHeaderMap::const_iterator end = xhrReplayData->headers().end();
+    for (HTTPHeaderMap::const_iterator it = xhrReplayData->headers().begin(); it!= end; ++it)
+        xhr->setRequestHeader(it->key, it->value, IGNORE_EXCEPTION);
+    xhr->sendFromInspector(xhrReplayData->formData(), IGNORE_EXCEPTION);
+}
+
+void InspectorResourceAgent::canClearBrowserCache(ErrorString*, bool* result)
+{
+    *result = true;
+}
+
+void InspectorResourceAgent::clearBrowserCache(ErrorString*)
+{
+    m_client->clearBrowserCache();
+}
+
+void InspectorResourceAgent::canClearBrowserCookies(ErrorString*, bool* result)
+{
+    *result = true;
+}
+
+void InspectorResourceAgent::clearBrowserCookies(ErrorString*)
+{
+    m_client->clearBrowserCookies();
+}
+
+void InspectorResourceAgent::setCacheDisabled(ErrorString*, bool cacheDisabled)
+{
+    m_state->setBoolean(ResourceAgentState::cacheDisabled, cacheDisabled);
+    if (cacheDisabled)
+        memoryCache()->evictResources();
+}
+
+void InspectorResourceAgent::mainFrameNavigated(DocumentLoader* loader)
+{
+    if (m_state->getBoolean(ResourceAgentState::cacheDisabled))
+        memoryCache()->evictResources();
+
+    m_resourcesData->clear(m_pageAgent->loaderId(loader));
+}
+
+void InspectorResourceAgent::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::InspectorResourceAgent);
+    InspectorBaseAgent<InspectorResourceAgent>::reportMemoryUsage(memoryObjectInfo);
+    info.addWeakPointer(m_pageAgent);
+    info.addWeakPointer(m_client);
+    info.addWeakPointer(m_frontend);
+    info.addMember(m_userAgentOverride, "userAgentOverride");
+    info.addMember(m_resourcesData, "resourcesData");
+    info.addMember(m_pendingXHRReplayData, "pendingXHRReplayData");
+    info.addMember(m_styleRecalculationInitiator, "styleRecalculationInitiator");
+}
+
+InspectorResourceAgent::InspectorResourceAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorClient* client, InspectorCompositeState* state)
+    : InspectorBaseAgent<InspectorResourceAgent>("Network", instrumentingAgents, state)
+    , m_pageAgent(pageAgent)
+    , m_client(client)
+    , m_frontend(0)
+    , m_resourcesData(adoptPtr(new NetworkResourcesData()))
+    , m_loadingXHRSynchronously(false)
+    , m_isRecalculatingStyle(false)
+{
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorResourceAgent.h b/Source/core/inspector/InspectorResourceAgent.h
new file mode 100644
index 0000000..cece633
--- /dev/null
+++ b/Source/core/inspector/InspectorResourceAgent.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef InspectorResourceAgent_h
+#define InspectorResourceAgent_h
+
+#include "InspectorFrontend.h"
+#include "core/inspector/InspectorBaseAgent.h"
+
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+
+namespace WTF {
+class String;
+}
+
+namespace WebCore {
+
+class CachedResource;
+class Document;
+class DocumentLoader;
+class FormData;
+class Frame;
+class HTTPHeaderMap;
+class InspectorArray;
+class InspectorClient;
+class InspectorFrontend;
+class InspectorObject;
+class InspectorPageAgent;
+class InspectorState;
+class InstrumentingAgents;
+class KURL;
+class NetworkResourcesData;
+class Page;
+class ResourceError;
+class ResourceLoader;
+class ResourceRequest;
+class ResourceResponse;
+class SharedBuffer;
+class ThreadableLoaderClient;
+class XHRReplayData;
+class XMLHttpRequest;
+
+struct WebSocketFrame;
+class WebSocketHandshakeRequest;
+class WebSocketHandshakeResponse;
+
+typedef String ErrorString;
+
+class InspectorResourceAgent : public InspectorBaseAgent<InspectorResourceAgent>, public InspectorBackendDispatcher::NetworkCommandHandler {
+public:
+    static PassOwnPtr<InspectorResourceAgent> create(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorClient* client, InspectorCompositeState* state)
+    {
+        return adoptPtr(new InspectorResourceAgent(instrumentingAgents, pageAgent, client, state));
+    }
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void restore();
+
+    static PassRefPtr<InspectorResourceAgent> restore(Page*, InspectorCompositeState*, InspectorFrontend*);
+
+    ~InspectorResourceAgent();
+
+    void willSendResourceRequest(unsigned long identifier, DocumentLoader*, ResourceRequest&, const ResourceResponse& redirectResponse);
+    void markResourceAsCached(unsigned long identifier);
+    void didReceiveResourceResponse(unsigned long identifier, DocumentLoader* laoder, const ResourceResponse&, ResourceLoader*);
+    void didReceiveData(unsigned long identifier, const char* data, int dataLength, int encodedDataLength);
+    void didFinishLoading(unsigned long identifier, DocumentLoader*, double finishTime);
+    void didFailLoading(unsigned long identifier, DocumentLoader*, const ResourceError&);
+    void didLoadResourceFromMemoryCache(DocumentLoader*, CachedResource*);
+    void mainFrameNavigated(DocumentLoader*);
+    void scriptImported(unsigned long identifier, const String& sourceString);
+    void didReceiveScriptResponse(unsigned long identifier);
+
+    void documentThreadableLoaderStartedLoadingForClient(unsigned long identifier, ThreadableLoaderClient*);
+    void willLoadXHR(ThreadableLoaderClient*, const String& method, const KURL&, bool async, PassRefPtr<FormData> body, const HTTPHeaderMap& headers, bool includeCrendentials);
+    void didFailXHRLoading(ThreadableLoaderClient*);
+    void didFinishXHRLoading(ThreadableLoaderClient*, unsigned long identifier, const String& sourceString, const String&, const String&, unsigned);
+    void didReceiveXHRResponse(unsigned long identifier);
+    void willLoadXHRSynchronously();
+    void didLoadXHRSynchronously();
+
+    void willDestroyCachedResource(CachedResource*);
+
+    void applyUserAgentOverride(String* userAgent);
+
+    // FIXME: InspectorResourceAgent should now be aware of style recalculation.
+    void willRecalculateStyle(Document*);
+    void didRecalculateStyle();
+    void didScheduleStyleRecalculation(Document*);
+
+    PassRefPtr<TypeBuilder::Network::Initiator> buildInitiatorObject(Document*);
+
+    void didCreateWebSocket(Document*, unsigned long identifier, const KURL& requestURL, const String&);
+    void willSendWebSocketHandshakeRequest(Document*, unsigned long identifier, const WebSocketHandshakeRequest&);
+    void didReceiveWebSocketHandshakeResponse(Document*, unsigned long identifier, const WebSocketHandshakeResponse&);
+    void didCloseWebSocket(Document*, unsigned long identifier);
+    void didReceiveWebSocketFrame(unsigned long identifier, const WebSocketFrame&);
+    void didSendWebSocketFrame(unsigned long identifier, const WebSocketFrame&);
+    void didReceiveWebSocketFrameError(unsigned long identifier, const String&);
+
+    // called from Internals for layout test purposes.
+    void setResourcesDataSizeLimitsFromInternals(int maximumResourcesContentSize, int maximumSingleResourceContentSize);
+
+    // Called from frontend
+    virtual void enable(ErrorString*);
+    virtual void disable(ErrorString*);
+    virtual void setUserAgentOverride(ErrorString*, const String& userAgent);
+    virtual void setExtraHTTPHeaders(ErrorString*, const RefPtr<InspectorObject>&);
+    virtual void getResponseBody(ErrorString*, const String& requestId, String* content, bool* base64Encoded);
+
+    virtual void replayXHR(ErrorString*, const String& requestId);
+
+    virtual void canClearBrowserCache(ErrorString*, bool*);
+    virtual void clearBrowserCache(ErrorString*);
+    virtual void canClearBrowserCookies(ErrorString*, bool*);
+    virtual void clearBrowserCookies(ErrorString*);
+    virtual void setCacheDisabled(ErrorString*, bool cacheDisabled);
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+private:
+    InspectorResourceAgent(InstrumentingAgents*, InspectorPageAgent*, InspectorClient*, InspectorCompositeState*);
+
+    void enable();
+
+    InspectorPageAgent* m_pageAgent;
+    InspectorClient* m_client;
+    InspectorFrontend::Network* m_frontend;
+    String m_userAgentOverride;
+    OwnPtr<NetworkResourcesData> m_resourcesData;
+    bool m_loadingXHRSynchronously;
+
+    typedef HashMap<ThreadableLoaderClient*, RefPtr<XHRReplayData> > PendingXHRReplayDataMap;
+    PendingXHRReplayDataMap m_pendingXHRReplayData;
+    // FIXME: InspectorResourceAgent should now be aware of style recalculation.
+    RefPtr<TypeBuilder::Network::Initiator> m_styleRecalculationInitiator;
+    bool m_isRecalculatingStyle;
+};
+
+} // namespace WebCore
+
+
+#endif // !defined(InspectorResourceAgent_h)
diff --git a/Source/core/inspector/InspectorRuntimeAgent.cpp b/Source/core/inspector/InspectorRuntimeAgent.cpp
new file mode 100644
index 0000000..e119823
--- /dev/null
+++ b/Source/core/inspector/InspectorRuntimeAgent.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorRuntimeAgent.h"
+
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/InspectorValues.h"
+#include <wtf/PassRefPtr.h>
+
+
+#include "bindings/v8/ScriptDebugServer.h"
+
+namespace WebCore {
+
+static bool asBool(const bool* const b)
+{
+    return b ? *b : false;
+}
+
+InspectorRuntimeAgent::InspectorRuntimeAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager)
+    : InspectorBaseAgent<InspectorRuntimeAgent>("Runtime", instrumentingAgents, state)
+    , m_enabled(false)
+    , m_injectedScriptManager(injectedScriptManager)
+    , m_scriptDebugServer(0)
+{
+}
+
+InspectorRuntimeAgent::~InspectorRuntimeAgent()
+{
+}
+
+static ScriptDebugServer::PauseOnExceptionsState setPauseOnExceptionsState(ScriptDebugServer* scriptDebugServer, ScriptDebugServer::PauseOnExceptionsState newState)
+{
+    ASSERT(scriptDebugServer);
+    ScriptDebugServer::PauseOnExceptionsState presentState = scriptDebugServer->pauseOnExceptionsState();
+    if (presentState != newState)
+        scriptDebugServer->setPauseOnExceptionsState(newState);
+    return presentState;
+}
+
+void InspectorRuntimeAgent::evaluate(ErrorString* errorString, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptionsAndMuteConsole, const int* executionContextId, const bool* const returnByValue, const bool* generatePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown)
+{
+    InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId);
+    if (injectedScript.hasNoValue())
+        return;
+    ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = ScriptDebugServer::DontPauseOnExceptions;
+    if (asBool(doNotPauseOnExceptionsAndMuteConsole))
+        previousPauseOnExceptionsState = setPauseOnExceptionsState(m_scriptDebugServer, ScriptDebugServer::DontPauseOnExceptions);
+    if (asBool(doNotPauseOnExceptionsAndMuteConsole))
+        muteConsole();
+
+    injectedScript.evaluate(errorString, expression, objectGroup ? *objectGroup : "", asBool(includeCommandLineAPI), asBool(returnByValue), asBool(generatePreview), &result, wasThrown);
+
+    if (asBool(doNotPauseOnExceptionsAndMuteConsole)) {
+        unmuteConsole();
+        setPauseOnExceptionsState(m_scriptDebugServer, previousPauseOnExceptionsState);
+    }
+}
+
+void InspectorRuntimeAgent::callFunctionOn(ErrorString* errorString, const String& objectId, const String& expression, const RefPtr<InspectorArray>* const optionalArguments, const bool* const doNotPauseOnExceptionsAndMuteConsole, const bool* const returnByValue, const bool* generatePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown)
+{
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
+    if (injectedScript.hasNoValue()) {
+        *errorString = "Inspected frame has gone";
+        return;
+    }
+    String arguments;
+    if (optionalArguments)
+        arguments = (*optionalArguments)->toJSONString();
+
+    ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = ScriptDebugServer::DontPauseOnExceptions;
+    if (asBool(doNotPauseOnExceptionsAndMuteConsole))
+        previousPauseOnExceptionsState = setPauseOnExceptionsState(m_scriptDebugServer, ScriptDebugServer::DontPauseOnExceptions);
+    if (asBool(doNotPauseOnExceptionsAndMuteConsole))
+        muteConsole();
+
+    injectedScript.callFunctionOn(errorString, objectId, expression, arguments, asBool(returnByValue), asBool(generatePreview), &result, wasThrown);
+
+    if (asBool(doNotPauseOnExceptionsAndMuteConsole)) {
+        unmuteConsole();
+        setPauseOnExceptionsState(m_scriptDebugServer, previousPauseOnExceptionsState);
+    }
+}
+
+void InspectorRuntimeAgent::getProperties(ErrorString* errorString, const String& objectId, const bool* const ownProperties, RefPtr<TypeBuilder::Array<TypeBuilder::Runtime::PropertyDescriptor> >& result, RefPtr<TypeBuilder::Array<TypeBuilder::Runtime::InternalPropertyDescriptor> >& internalProperties)
+{
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
+    if (injectedScript.hasNoValue()) {
+        *errorString = "Inspected frame has gone";
+        return;
+    }
+
+    ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = setPauseOnExceptionsState(m_scriptDebugServer, ScriptDebugServer::DontPauseOnExceptions);
+    muteConsole();
+
+    injectedScript.getProperties(errorString, objectId, ownProperties ? *ownProperties : false, &result);
+    injectedScript.getInternalProperties(errorString, objectId, &internalProperties);
+
+    unmuteConsole();
+    setPauseOnExceptionsState(m_scriptDebugServer, previousPauseOnExceptionsState);
+}
+
+void InspectorRuntimeAgent::releaseObject(ErrorString*, const String& objectId)
+{
+    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
+    if (!injectedScript.hasNoValue())
+        injectedScript.releaseObject(objectId);
+}
+
+void InspectorRuntimeAgent::releaseObjectGroup(ErrorString*, const String& objectGroup)
+{
+    m_injectedScriptManager->releaseObjectGroup(objectGroup);
+}
+
+void InspectorRuntimeAgent::run(ErrorString*)
+{
+}
+
+void InspectorRuntimeAgent::setScriptDebugServer(ScriptDebugServer* scriptDebugServer)
+{
+    m_scriptDebugServer = scriptDebugServer;
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorRuntimeAgent.h b/Source/core/inspector/InspectorRuntimeAgent.h
new file mode 100644
index 0000000..2034795
--- /dev/null
+++ b/Source/core/inspector/InspectorRuntimeAgent.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef InspectorRuntimeAgent_h
+#define InspectorRuntimeAgent_h
+
+
+#include "bindings/v8/ScriptState.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class InjectedScript;
+class InjectedScriptManager;
+class InspectorArray;
+class InspectorFrontend;
+class InspectorObject;
+class InspectorValue;
+class InstrumentingAgents;
+class ScriptDebugServer;
+class WorkerContext;
+
+typedef String ErrorString;
+
+class InspectorRuntimeAgent : public InspectorBaseAgent<InspectorRuntimeAgent>, public InspectorBackendDispatcher::RuntimeCommandHandler {
+    WTF_MAKE_NONCOPYABLE(InspectorRuntimeAgent);
+public:
+    virtual ~InspectorRuntimeAgent();
+
+    bool enabled() { return m_enabled; }
+    // Part of the protocol.
+    virtual void enable(ErrorString*) { m_enabled = true; }
+    virtual void disable(ErrorString*) { m_enabled = false; }
+    virtual void evaluate(ErrorString*,
+                  const String& expression,
+                  const String* objectGroup,
+                  const bool* includeCommandLineAPI,
+                  const bool* doNotPauseOnExceptionsAndMuteConsole,
+                  const int* executionContextId,
+                  const bool* returnByValue,
+                  const bool* generatePreview,
+                  RefPtr<TypeBuilder::Runtime::RemoteObject>& result,
+                  TypeBuilder::OptOutput<bool>* wasThrown);
+    virtual void callFunctionOn(ErrorString*,
+                        const String& objectId,
+                        const String& expression,
+                        const RefPtr<InspectorArray>* optionalArguments,
+                        const bool* doNotPauseOnExceptionsAndMuteConsole,
+                        const bool* returnByValue,
+                        const bool* generatePreview,
+                        RefPtr<TypeBuilder::Runtime::RemoteObject>& result,
+                        TypeBuilder::OptOutput<bool>* wasThrown);
+    virtual void releaseObject(ErrorString*, const String& objectId);
+    virtual void getProperties(ErrorString*, const String& objectId, const bool* ownProperties, RefPtr<TypeBuilder::Array<TypeBuilder::Runtime::PropertyDescriptor> >& result, RefPtr<TypeBuilder::Array<TypeBuilder::Runtime::InternalPropertyDescriptor> >& internalProperties);
+    virtual void releaseObjectGroup(ErrorString*, const String& objectGroup);
+    virtual void run(ErrorString*);
+
+    void setScriptDebugServer(ScriptDebugServer*);
+
+protected:
+    InspectorRuntimeAgent(InstrumentingAgents*, InspectorCompositeState*, InjectedScriptManager*);
+    virtual InjectedScript injectedScriptForEval(ErrorString*, const int* executionContextId) = 0;
+
+    virtual void muteConsole() = 0;
+    virtual void unmuteConsole() = 0;
+
+    InjectedScriptManager* injectedScriptManager() { return m_injectedScriptManager; }
+    bool m_enabled;
+
+private:
+    InjectedScriptManager* m_injectedScriptManager;
+    ScriptDebugServer* m_scriptDebugServer;
+};
+
+} // namespace WebCore
+
+#endif // InspectorRuntimeAgent_h
diff --git a/Source/core/inspector/InspectorState.cpp b/Source/core/inspector/InspectorState.cpp
new file mode 100644
index 0000000..fc3124f
--- /dev/null
+++ b/Source/core/inspector/InspectorState.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2011 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 GOOGLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorState.h"
+
+#include "core/inspector/InspectorStateClient.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+InspectorState::InspectorState(InspectorStateUpdateListener* listener, PassRefPtr<InspectorObject> properties)
+    : m_listener(listener)
+    , m_properties(properties)
+{
+}
+
+void InspectorState::updateCookie()
+{
+    if (m_listener)
+        m_listener->inspectorStateUpdated();
+}
+
+void InspectorState::setFromCookie(PassRefPtr<InspectorObject> properties)
+{
+    m_properties = properties;
+}
+
+void InspectorState::setValue(const String& propertyName, PassRefPtr<InspectorValue> value)
+{
+    m_properties->setValue(propertyName, value);
+    updateCookie();
+}
+
+void InspectorState::remove(const String& propertyName)
+{
+    m_properties->remove(propertyName);
+    updateCookie();
+}
+
+bool InspectorState::getBoolean(const String& propertyName)
+{
+    InspectorObject::iterator it = m_properties->find(propertyName);
+    bool value = false;
+    if (it != m_properties->end())
+        it->value->asBoolean(&value);
+    return value;
+}
+
+String InspectorState::getString(const String& propertyName)
+{
+    InspectorObject::iterator it = m_properties->find(propertyName);
+    String value;
+    if (it != m_properties->end())
+        it->value->asString(&value);
+    return value;
+}
+
+long InspectorState::getLong(const String& propertyName)
+{
+    InspectorObject::iterator it = m_properties->find(propertyName);
+    long value = 0;
+    if (it != m_properties->end())
+        it->value->asNumber(&value);
+    return value;
+}
+
+double InspectorState::getDouble(const String& propertyName)
+{
+    InspectorObject::iterator it = m_properties->find(propertyName);
+    double value = 0;
+    if (it != m_properties->end())
+        it->value->asNumber(&value);
+    return value;
+}
+
+PassRefPtr<InspectorObject> InspectorState::getObject(const String& propertyName)
+{
+    InspectorObject::iterator it = m_properties->find(propertyName);
+    if (it == m_properties->end()) {
+        m_properties->setObject(propertyName, InspectorObject::create());
+        it = m_properties->find(propertyName);
+    }
+    return it->value->asObject();
+}
+
+InspectorState* InspectorCompositeState::createAgentState(const String& agentName)
+{
+    ASSERT(m_stateObject->find(agentName) == m_stateObject->end());
+    ASSERT(m_inspectorStateMap.find(agentName) == m_inspectorStateMap.end());
+    RefPtr<InspectorObject> stateProperties = InspectorObject::create();
+    m_stateObject->setObject(agentName, stateProperties);
+    OwnPtr<InspectorState> statePtr = adoptPtr(new InspectorState(this, stateProperties));
+    InspectorState* state = statePtr.get();
+    m_inspectorStateMap.add(agentName, statePtr.release());
+    return state;
+}
+
+void InspectorCompositeState::loadFromCookie(const String& inspectorCompositeStateCookie)
+{
+    RefPtr<InspectorValue> cookie = InspectorValue::parseJSON(inspectorCompositeStateCookie);
+    if (cookie)
+        m_stateObject = cookie->asObject();
+    if (!m_stateObject)
+        m_stateObject = InspectorObject::create();
+
+    InspectorStateMap::iterator end = m_inspectorStateMap.end();
+    for (InspectorStateMap::iterator it = m_inspectorStateMap.begin(); it != end; ++it) {
+        RefPtr<InspectorObject> agentStateObject = m_stateObject->getObject(it->key);
+        if (!agentStateObject) {
+            agentStateObject = InspectorObject::create();
+            m_stateObject->setObject(it->key, agentStateObject);
+        }
+        it->value->setFromCookie(agentStateObject);
+    }
+}
+
+void InspectorCompositeState::mute()
+{
+    m_isMuted = true;
+}
+
+void InspectorCompositeState::unmute()
+{
+    m_isMuted = false;
+}
+
+void InspectorCompositeState::inspectorStateUpdated()
+{
+    if (m_client && !m_isMuted)
+        m_client->updateInspectorStateCookie(m_stateObject->toJSONString());
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorState.h b/Source/core/inspector/InspectorState.h
new file mode 100644
index 0000000..7952f2b
--- /dev/null
+++ b/Source/core/inspector/InspectorState.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef InspectorState_h
+#define InspectorState_h
+
+
+#include "core/inspector/InspectorValues.h"
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class InspectorStateClient;
+
+class InspectorStateUpdateListener {
+public:
+    virtual ~InspectorStateUpdateListener() { }
+    virtual void inspectorStateUpdated() = 0;
+};
+
+class InspectorState {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    InspectorState(InspectorStateUpdateListener*, PassRefPtr<InspectorObject>);
+    virtual ~InspectorState() {}
+
+    void loadFromCookie(const String& inspectorStateCookie);
+
+    void mute();
+    void unmute();
+
+    bool getBoolean(const String& propertyName);
+    String getString(const String& propertyName);
+    long getLong(const String& propertyName);
+    double getDouble(const String& propertyName);
+    PassRefPtr<InspectorObject> getObject(const String& propertyName);
+
+    void setBoolean(const String& propertyName, bool value) { setValue(propertyName, InspectorBasicValue::create(value)); }
+    void setString(const String& propertyName, const String& value) { setValue(propertyName, InspectorString::create(value)); }
+    void setLong(const String& propertyName, long value) { setValue(propertyName, InspectorBasicValue::create((double)value)); }
+    void setDouble(const String& propertyName, double value) { setValue(propertyName, InspectorBasicValue::create(value)); }
+    void setObject(const String& propertyName, PassRefPtr<InspectorObject> value) { setValue(propertyName, value); }
+
+    void remove(const String&);
+private:
+    void updateCookie();
+    void setValue(const String& propertyName, PassRefPtr<InspectorValue>);
+
+    // Gets called from InspectorCompositeState::loadFromCookie().
+    void setFromCookie(PassRefPtr<InspectorObject>);
+
+    friend class InspectorCompositeState;
+
+    InspectorStateUpdateListener* m_listener;
+    RefPtr<InspectorObject> m_properties;
+};
+
+class InspectorCompositeState : public InspectorStateUpdateListener {
+public:
+    InspectorCompositeState(InspectorStateClient* inspectorClient)
+        : m_client(inspectorClient)
+        , m_stateObject(InspectorObject::create())
+        , m_isMuted(false)
+    {
+    }
+    virtual ~InspectorCompositeState() { }
+
+    void mute();
+    void unmute();
+
+    InspectorState* createAgentState(const String&);
+    void loadFromCookie(const String&);
+
+private:
+    typedef HashMap<String, OwnPtr<InspectorState> > InspectorStateMap;
+
+    // From InspectorStateUpdateListener.
+    virtual void inspectorStateUpdated();
+
+    InspectorStateClient* m_client;
+    RefPtr<InspectorObject> m_stateObject;
+    bool m_isMuted;
+    InspectorStateMap m_inspectorStateMap;
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorState_h)
diff --git a/Source/core/inspector/InspectorStateClient.h b/Source/core/inspector/InspectorStateClient.h
new file mode 100644
index 0000000..214c707
--- /dev/null
+++ b/Source/core/inspector/InspectorStateClient.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+
+#ifndef InspectorStateClient_h
+#define InspectorStateClient_h
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class InspectorStateClient {
+public:
+    virtual ~InspectorStateClient() { }
+
+    // Navigation can cause some WebKit implementations to change the view / page / inspector controller instance.
+    // However, there are some inspector controller states that should survive navigation (such as tracking resources
+    // or recording timeline) and worker restart. Following callbacks allow embedders to track these states.
+    virtual void updateInspectorStateCookie(const String&) { };
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorStateClient_h)
diff --git a/Source/core/inspector/InspectorStyleSheet.cpp b/Source/core/inspector/InspectorStyleSheet.cpp
new file mode 100644
index 0000000..8b82254
--- /dev/null
+++ b/Source/core/inspector/InspectorStyleSheet.cpp
@@ -0,0 +1,1821 @@
+/*
+ * Copyright (C) 2010, 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:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorStyleSheet.h"
+
+#include "CSSPropertyNames.h"
+#include "HTMLNames.h"
+#include "SVGNames.h"
+#include "core/css/CSSHostRule.h"
+#include "core/css/CSSImportRule.h"
+#include "core/css/CSSMediaRule.h"
+#include "core/css/CSSParser.h"
+#include "core/css/CSSPropertySourceData.h"
+#include "core/css/CSSRule.h"
+#include "core/css/CSSRuleList.h"
+#include "core/css/CSSStyleRule.h"
+#include "core/css/CSSStyleSheet.h"
+#include "core/css/CSSSupportsRule.h"
+#include "core/css/StylePropertySet.h"
+#include "core/css/StyleResolver.h"
+#include "core/css/StyleRule.h"
+#include "core/css/StyleRuleImport.h"
+#include "core/css/StyleSheetContents.h"
+#include "core/css/StyleSheetList.h"
+#include "core/css/WebKitCSSKeyframesRule.h"
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/Node.h"
+#include "core/html/HTMLHeadElement.h"
+#include "core/html/parser/HTMLParserIdioms.h"
+#include "core/inspector/ContentSearchUtils.h"
+#include "core/inspector/InspectorCSSAgent.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/page/ContentSecurityPolicy.h"
+#include "core/platform/text/RegularExpression.h"
+
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/Vector.h>
+
+using WebCore::TypeBuilder::Array;
+using WebCore::RuleSourceDataList;
+using WebCore::CSSRuleSourceData;
+
+class ParsedStyleSheet {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ParsedStyleSheet();
+
+    WebCore::CSSStyleSheet* cssStyleSheet() const { return m_parserOutput; }
+    const String& text() const { ASSERT(m_hasText); return m_text; }
+    void setText(const String& text);
+    bool hasText() const { return m_hasText; }
+    void setSourceData(PassOwnPtr<RuleSourceDataList>);
+    bool hasSourceData() const { return m_sourceData; }
+    PassRefPtr<WebCore::CSSRuleSourceData> ruleSourceDataAt(unsigned) const;
+
+private:
+
+    // StyleSheet constructed while parsing m_text.
+    WebCore::CSSStyleSheet* m_parserOutput;
+    String m_text;
+    bool m_hasText;
+    OwnPtr<RuleSourceDataList> m_sourceData;
+};
+
+ParsedStyleSheet::ParsedStyleSheet()
+    : m_parserOutput(0)
+    , m_hasText(false)
+{
+}
+
+void ParsedStyleSheet::setText(const String& text)
+{
+    m_hasText = true;
+    m_text = text;
+    setSourceData(nullptr);
+}
+
+static void flattenSourceData(RuleSourceDataList* dataList, RuleSourceDataList* target)
+{
+    for (size_t i = 0; i < dataList->size(); ++i) {
+        RefPtr<CSSRuleSourceData>& data = dataList->at(i);
+        if (data->type == CSSRuleSourceData::STYLE_RULE)
+            target->append(data);
+        else if (data->type == CSSRuleSourceData::MEDIA_RULE)
+            flattenSourceData(&data->childRules, target);
+        else if (data->type == CSSRuleSourceData::HOST_RULE)
+            flattenSourceData(&data->childRules, target);
+        else if (data->type == CSSRuleSourceData::SUPPORTS_RULE)
+            flattenSourceData(&data->childRules, target);
+    }
+}
+
+void ParsedStyleSheet::setSourceData(PassOwnPtr<RuleSourceDataList> sourceData)
+{
+    if (!sourceData) {
+        m_sourceData.clear();
+        return;
+    }
+
+    m_sourceData = adoptPtr(new RuleSourceDataList());
+
+    // FIXME: This is a temporary solution to retain the original flat sourceData structure
+    // containing only style rules, even though CSSParser now provides the full rule source data tree.
+    // Normally, we should just assign m_sourceData = sourceData;
+    flattenSourceData(sourceData.get(), m_sourceData.get());
+}
+
+PassRefPtr<WebCore::CSSRuleSourceData> ParsedStyleSheet::ruleSourceDataAt(unsigned index) const
+{
+    if (!hasSourceData() || index >= m_sourceData->size())
+        return 0;
+
+    return m_sourceData->at(index);
+}
+
+namespace WebCore {
+
+static PassOwnPtr<CSSParser> createCSSParser(Document* document)
+{
+    return adoptPtr(new CSSParser(document ? CSSParserContext(document) : strictCSSParserContext()));
+}
+
+namespace {
+
+class StyleSheetHandler : public CSSParser::SourceDataHandler {
+public:
+    StyleSheetHandler(const String& parsedText, Document* document, StyleSheetContents* styleSheetContents, RuleSourceDataList* result)
+        : m_parsedText(parsedText)
+        , m_document(document)
+        , m_styleSheetContents(styleSheetContents)
+        , m_result(result)
+        , m_propertyRangeStart(UINT_MAX)
+        , m_selectorRangeStart(UINT_MAX)
+        , m_commentRangeStart(UINT_MAX)
+    {
+        ASSERT(m_result);
+    }
+
+private:
+    virtual void startRuleHeader(CSSRuleSourceData::Type, unsigned) OVERRIDE;
+    virtual void endRuleHeader(unsigned) OVERRIDE;
+    virtual void startSelector(unsigned) OVERRIDE;
+    virtual void endSelector(unsigned) OVERRIDE;
+    virtual void startRuleBody(unsigned) OVERRIDE;
+    virtual void endRuleBody(unsigned, bool) OVERRIDE;
+    virtual void startEndUnknownRule() OVERRIDE { addNewRuleToSourceTree(CSSRuleSourceData::createUnknown()); }
+    virtual void startProperty(unsigned) OVERRIDE;
+    virtual void endProperty(bool, bool, unsigned, CSSParser::SyntaxErrorType) OVERRIDE;
+    virtual void startComment(unsigned) OVERRIDE;
+    virtual void endComment(unsigned) OVERRIDE;
+
+    void addNewRuleToSourceTree(PassRefPtr<CSSRuleSourceData>);
+    PassRefPtr<CSSRuleSourceData> popRuleData();
+    template <typename CharacterType> inline void setRuleHeaderEnd(const CharacterType*, unsigned);
+    void fixUnparsedPropertyRanges(CSSRuleSourceData*);
+
+    const String& m_parsedText;
+    Document* m_document;
+    StyleSheetContents* m_styleSheetContents;
+    RuleSourceDataList* m_result;
+    RuleSourceDataList m_currentRuleDataStack;
+    RefPtr<CSSRuleSourceData> m_currentRuleData;
+    OwnPtr<CSSParser> m_commentParser;
+    unsigned m_propertyRangeStart;
+    unsigned m_selectorRangeStart;
+    unsigned m_commentRangeStart;
+};
+
+void StyleSheetHandler::startRuleHeader(CSSRuleSourceData::Type type, unsigned offset)
+{
+    // Pop off data for a previous invalid rule.
+    if (m_currentRuleData)
+        m_currentRuleDataStack.removeLast();
+
+    RefPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(type);
+    data->ruleHeaderRange.start = offset;
+    m_currentRuleData = data;
+    m_currentRuleDataStack.append(data.release());
+}
+
+template <typename CharacterType>
+inline void StyleSheetHandler::setRuleHeaderEnd(const CharacterType* dataStart, unsigned listEndOffset)
+{
+    while (listEndOffset > 1) {
+        if (isHTMLSpace(*(dataStart + listEndOffset - 1)))
+            --listEndOffset;
+        else
+            break;
+    }
+
+    m_currentRuleDataStack.last()->ruleHeaderRange.end = listEndOffset;
+}
+
+void StyleSheetHandler::endRuleHeader(unsigned offset)
+{
+    ASSERT(!m_currentRuleDataStack.isEmpty());
+
+    if (m_parsedText.is8Bit())
+        setRuleHeaderEnd<LChar>(m_parsedText.characters8(), offset);
+    else
+        setRuleHeaderEnd<UChar>(m_parsedText.characters16(), offset);
+}
+
+void StyleSheetHandler::startSelector(unsigned offset)
+{
+    m_selectorRangeStart = offset;
+}
+
+void StyleSheetHandler::endSelector(unsigned offset)
+{
+    ASSERT(m_currentRuleDataStack.size());
+    m_currentRuleDataStack.last()->selectorRanges.append(SourceRange(m_selectorRangeStart, offset));
+    m_selectorRangeStart = UINT_MAX;
+}
+
+void StyleSheetHandler::startRuleBody(unsigned offset)
+{
+    m_currentRuleData.clear();
+    ASSERT(!m_currentRuleDataStack.isEmpty());
+    if (m_parsedText[offset] == '{')
+        ++offset; // Skip the rule body opening brace.
+    m_currentRuleDataStack.last()->ruleBodyRange.start = offset;
+}
+
+void StyleSheetHandler::endRuleBody(unsigned offset, bool error)
+{
+    ASSERT(!m_currentRuleDataStack.isEmpty());
+    m_currentRuleDataStack.last()->ruleBodyRange.end = offset;
+    m_propertyRangeStart = UINT_MAX;
+    RefPtr<CSSRuleSourceData> rule = popRuleData();
+    if (error)
+        return;
+
+    fixUnparsedPropertyRanges(rule.get());
+    addNewRuleToSourceTree(rule.release());
+}
+
+void StyleSheetHandler::addNewRuleToSourceTree(PassRefPtr<CSSRuleSourceData> rule)
+{
+    if (m_currentRuleDataStack.isEmpty())
+        m_result->append(rule);
+    else
+        m_currentRuleDataStack.last()->childRules.append(rule);
+}
+
+PassRefPtr<CSSRuleSourceData> StyleSheetHandler::popRuleData()
+{
+    ASSERT(!m_currentRuleDataStack.isEmpty());
+    m_currentRuleData.clear();
+    RefPtr<CSSRuleSourceData> data = m_currentRuleDataStack.last();
+    m_currentRuleDataStack.removeLast();
+    return data.release();
+}
+
+template <typename CharacterType>
+static inline void fixUnparsedProperties(const CharacterType* characters, CSSRuleSourceData* ruleData)
+{
+    Vector<CSSPropertySourceData>& propertyData = ruleData->styleSourceData->propertyData;
+    unsigned size = propertyData.size();
+    if (!size)
+        return;
+
+    unsigned styleStart = ruleData->ruleBodyRange.start;
+    CSSPropertySourceData* nextData = &(propertyData.at(0));
+    for (unsigned i = 0; i < size; ++i) {
+        CSSPropertySourceData* currentData = nextData;
+        nextData = i < size - 1 ? &(propertyData.at(i + 1)) : 0;
+
+        if (currentData->parsedOk)
+            continue;
+        if (currentData->range.end > 0 && characters[styleStart + currentData->range.end - 1] == ';')
+            continue;
+
+        unsigned propertyEndInStyleSheet;
+        if (!nextData)
+            propertyEndInStyleSheet = ruleData->ruleBodyRange.end - 1;
+        else
+            propertyEndInStyleSheet = styleStart + nextData->range.start - 1;
+
+        while (isHTMLSpace(characters[propertyEndInStyleSheet]))
+            --propertyEndInStyleSheet;
+
+        // propertyEndInStyleSheet points at the last property text character.
+        unsigned newPropertyEnd = propertyEndInStyleSheet - styleStart + 1; // Exclusive of the last property text character.
+        if (currentData->range.end != newPropertyEnd) {
+            currentData->range.end = newPropertyEnd;
+            unsigned valueStartInStyleSheet = styleStart + currentData->range.start + currentData->name.length();
+            while (valueStartInStyleSheet < propertyEndInStyleSheet && characters[valueStartInStyleSheet] != ':')
+                ++valueStartInStyleSheet;
+            if (valueStartInStyleSheet < propertyEndInStyleSheet)
+                ++valueStartInStyleSheet; // Shift past the ':'.
+            while (valueStartInStyleSheet < propertyEndInStyleSheet && isHTMLSpace(characters[valueStartInStyleSheet]))
+                ++valueStartInStyleSheet;
+            // Need to exclude the trailing ';' from the property value.
+            currentData->value = String(characters + valueStartInStyleSheet, propertyEndInStyleSheet - valueStartInStyleSheet + (characters[propertyEndInStyleSheet] == ';' ? 0 : 1));
+        }
+    }
+}
+
+void StyleSheetHandler::fixUnparsedPropertyRanges(CSSRuleSourceData* ruleData)
+{
+    if (!ruleData->styleSourceData)
+        return;
+
+    if (m_parsedText.is8Bit()) {
+        fixUnparsedProperties<LChar>(m_parsedText.characters8(), ruleData);
+        return;
+    }
+
+    fixUnparsedProperties<UChar>(m_parsedText.characters16(), ruleData);
+}
+
+void StyleSheetHandler::startProperty(unsigned offset)
+{
+    if (m_currentRuleDataStack.isEmpty() || !m_currentRuleDataStack.last()->styleSourceData)
+        return;
+    m_propertyRangeStart = offset;
+}
+
+void StyleSheetHandler::endProperty(bool isImportant, bool isParsed, unsigned offset, CSSParser::SyntaxErrorType errorType)
+{
+    if (errorType != CSSParser::NoSyntaxError)
+        m_propertyRangeStart = UINT_MAX;
+
+    if (m_propertyRangeStart == UINT_MAX || m_currentRuleDataStack.isEmpty() || !m_currentRuleDataStack.last()->styleSourceData)
+        return;
+
+    ASSERT(offset <= m_parsedText.length());
+    if (offset < m_parsedText.length() && m_parsedText[offset] == ';') // Include semicolon into the property text.
+        ++offset;
+
+    const unsigned start = m_propertyRangeStart;
+    const unsigned end = offset;
+    ASSERT(start < end);
+    String propertyString = m_parsedText.substring(start, end - start).stripWhiteSpace();
+    if (propertyString.endsWith(';'))
+        propertyString = propertyString.left(propertyString.length() - 1);
+    size_t colonIndex = propertyString.find(':');
+    ASSERT(colonIndex != notFound);
+
+    String name = propertyString.left(colonIndex).stripWhiteSpace();
+    String value = propertyString.substring(colonIndex + 1, propertyString.length()).stripWhiteSpace();
+    // The property range is relative to the declaration start offset.
+    unsigned topRuleBodyRangeStart = m_currentRuleDataStack.last()->ruleBodyRange.start;
+    m_currentRuleDataStack.last()->styleSourceData->propertyData.append(
+        CSSPropertySourceData(name, value, isImportant, false, isParsed, SourceRange(start - topRuleBodyRangeStart, end - topRuleBodyRangeStart)));
+    m_propertyRangeStart = UINT_MAX;
+}
+
+void StyleSheetHandler::startComment(unsigned offset)
+{
+    ASSERT(m_commentRangeStart == UINT_MAX);
+    m_commentRangeStart = offset;
+}
+
+void StyleSheetHandler::endComment(unsigned offset)
+{
+    ASSERT(offset <= m_parsedText.length());
+
+    unsigned startOffset = m_commentRangeStart;
+    m_commentRangeStart = UINT_MAX;
+    if (m_propertyRangeStart != UINT_MAX) {
+        ASSERT(startOffset >= m_propertyRangeStart);
+        // startProperty() is called automatically at the start of a style declaration.
+        // Check if no text has been scanned yet, otherwise the comment is inside a property.
+        if (!m_parsedText.substring(m_propertyRangeStart, startOffset).stripWhiteSpace().isEmpty())
+            return;
+        m_propertyRangeStart = UINT_MAX;
+    }
+    if (m_currentRuleDataStack.isEmpty() || !m_currentRuleDataStack.last()->ruleHeaderRange.end || !m_currentRuleDataStack.last()->styleSourceData)
+        return;
+
+    // The lexer is not inside a property AND it is scanning a declaration-aware rule body.
+    String commentText = m_parsedText.substring(startOffset, offset - startOffset);
+
+    ASSERT(commentText.startsWith("/*"));
+    commentText = commentText.substring(2);
+
+    // Require well-formed comments.
+    if (!commentText.endsWith("*/"))
+        return;
+    commentText = commentText.substring(0, commentText.length() - 2).stripWhiteSpace();
+    if (commentText.isEmpty())
+        return;
+
+    // FIXME: Use the actual rule type rather than STYLE_RULE?
+    if (!m_commentParser)
+        m_commentParser = createCSSParser(m_document);
+    RuleSourceDataList sourceData;
+
+    // FIXME: Use another subclass of CSSParser::SourceDataHandler and assert that
+    // no comments are encountered (will not need m_document and m_styleSheetContents).
+    StyleSheetHandler handler(commentText, m_document, m_styleSheetContents, &sourceData);
+    RefPtr<StylePropertySet> tempMutableStyle = StylePropertySet::create();
+    m_commentParser->parseDeclaration(tempMutableStyle.get(), commentText, &handler, m_styleSheetContents);
+    Vector<CSSPropertySourceData>& commentPropertyData = sourceData.first()->styleSourceData->propertyData;
+    if (commentPropertyData.size() != 1)
+        return;
+    CSSPropertySourceData& propertyData = commentPropertyData.at(0);
+    if (propertyData.range.length() != commentText.length())
+        return;
+
+    unsigned topRuleBodyRangeStart = m_currentRuleDataStack.last()->ruleBodyRange.start;
+    m_currentRuleDataStack.last()->styleSourceData->propertyData.append(
+        CSSPropertySourceData(propertyData.name, propertyData.value, false, true, true, SourceRange(startOffset - topRuleBodyRangeStart, offset - topRuleBodyRangeStart)));
+}
+
+} // namespace
+
+enum MediaListSource {
+    MediaListSourceLinkedSheet,
+    MediaListSourceInlineSheet,
+    MediaListSourceMediaRule,
+    MediaListSourceImportRule
+};
+
+static PassRefPtr<TypeBuilder::CSS::SourceRange> buildSourceRangeObject(const SourceRange& range, Vector<size_t>* lineEndings)
+{
+    if (!lineEndings)
+        return 0;
+    TextPosition start = ContentSearchUtils::textPositionFromOffset(range.start, *lineEndings);
+    TextPosition end = ContentSearchUtils::textPositionFromOffset(range.end, *lineEndings);
+
+    RefPtr<TypeBuilder::CSS::SourceRange> result = TypeBuilder::CSS::SourceRange::create()
+        .setStartLine(start.m_line.zeroBasedInt())
+        .setStartColumn(start.m_column.zeroBasedInt())
+        .setEndLine(end.m_line.zeroBasedInt())
+        .setEndColumn(end.m_column.zeroBasedInt());
+    return result.release();
+}
+
+static PassRefPtr<TypeBuilder::CSS::CSSMedia> buildMediaObject(const MediaList* media, MediaListSource mediaListSource, const String& sourceURL)
+{
+    // Make certain compilers happy by initializing |source| up-front.
+    TypeBuilder::CSS::CSSMedia::Source::Enum source = TypeBuilder::CSS::CSSMedia::Source::InlineSheet;
+    switch (mediaListSource) {
+    case MediaListSourceMediaRule:
+        source = TypeBuilder::CSS::CSSMedia::Source::MediaRule;
+        break;
+    case MediaListSourceImportRule:
+        source = TypeBuilder::CSS::CSSMedia::Source::ImportRule;
+        break;
+    case MediaListSourceLinkedSheet:
+        source = TypeBuilder::CSS::CSSMedia::Source::LinkedSheet;
+        break;
+    case MediaListSourceInlineSheet:
+        source = TypeBuilder::CSS::CSSMedia::Source::InlineSheet;
+        break;
+    }
+
+    RefPtr<TypeBuilder::CSS::CSSMedia> mediaObject = TypeBuilder::CSS::CSSMedia::create()
+        .setText(media->mediaText())
+        .setSource(source);
+
+    if (!sourceURL.isEmpty()) {
+        mediaObject->setSourceURL(sourceURL);
+        mediaObject->setSourceLine(media->queries()->lastLine());
+    }
+    return mediaObject.release();
+}
+
+static PassRefPtr<CSSRuleList> asCSSRuleList(CSSStyleSheet* styleSheet)
+{
+    if (!styleSheet)
+        return 0;
+
+    RefPtr<StaticCSSRuleList> list = StaticCSSRuleList::create();
+    Vector<RefPtr<CSSRule> >& listRules = list->rules();
+    for (unsigned i = 0, size = styleSheet->length(); i < size; ++i) {
+        CSSRule* item = styleSheet->item(i);
+        if (item->type() == CSSRule::CHARSET_RULE)
+            continue;
+        listRules.append(item);
+    }
+    return list.release();
+}
+
+static PassRefPtr<CSSRuleList> asCSSRuleList(CSSRule* rule)
+{
+    if (!rule)
+        return 0;
+
+    if (rule->type() == CSSRule::MEDIA_RULE)
+        return static_cast<CSSMediaRule*>(rule)->cssRules();
+
+    if (rule->type() == CSSRule::WEBKIT_KEYFRAMES_RULE)
+        return static_cast<WebKitCSSKeyframesRule*>(rule)->cssRules();
+
+    if (rule->type() == CSSRule::HOST_RULE)
+        return static_cast<CSSHostRule*>(rule)->cssRules();
+
+    if (rule->type() == CSSRule::SUPPORTS_RULE)
+        return static_cast<CSSSupportsRule*>(rule)->cssRules();
+
+    return 0;
+}
+
+static void fillMediaListChain(CSSRule* rule, Array<TypeBuilder::CSS::CSSMedia>* mediaArray)
+{
+    MediaList* mediaList;
+    CSSRule* parentRule = rule;
+    String sourceURL;
+    while (parentRule) {
+        CSSStyleSheet* parentStyleSheet = 0;
+        bool isMediaRule = true;
+        if (parentRule->type() == CSSRule::MEDIA_RULE) {
+            CSSMediaRule* mediaRule = static_cast<CSSMediaRule*>(parentRule);
+            mediaList = mediaRule->media();
+            parentStyleSheet = mediaRule->parentStyleSheet();
+        } else if (parentRule->type() == CSSRule::IMPORT_RULE) {
+            CSSImportRule* importRule = static_cast<CSSImportRule*>(parentRule);
+            mediaList = importRule->media();
+            parentStyleSheet = importRule->parentStyleSheet();
+            isMediaRule = false;
+        } else
+            mediaList = 0;
+
+        if (parentStyleSheet) {
+            sourceURL = parentStyleSheet->contents()->baseURL();
+            if (sourceURL.isEmpty())
+                sourceURL = InspectorDOMAgent::documentURLString(parentStyleSheet->ownerDocument());
+        } else
+            sourceURL = "";
+
+        if (mediaList && mediaList->length())
+            mediaArray->addItem(buildMediaObject(mediaList, isMediaRule ? MediaListSourceMediaRule : MediaListSourceImportRule, sourceURL));
+
+        if (parentRule->parentRule())
+            parentRule = parentRule->parentRule();
+        else {
+            CSSStyleSheet* styleSheet = parentRule->parentStyleSheet();
+            while (styleSheet) {
+                mediaList = styleSheet->media();
+                if (mediaList && mediaList->length()) {
+                    Document* doc = styleSheet->ownerDocument();
+                    if (doc)
+                        sourceURL = doc->url();
+                    else if (!styleSheet->contents()->baseURL().isEmpty())
+                        sourceURL = styleSheet->contents()->baseURL();
+                    else
+                        sourceURL = "";
+                    mediaArray->addItem(buildMediaObject(mediaList, styleSheet->ownerNode() ? MediaListSourceLinkedSheet : MediaListSourceInlineSheet, sourceURL));
+                }
+                parentRule = styleSheet->ownerRule();
+                if (parentRule)
+                    break;
+                styleSheet = styleSheet->parentStyleSheet();
+            }
+        }
+    }
+}
+
+PassRefPtr<InspectorStyle> InspectorStyle::create(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet)
+{
+    return adoptRef(new InspectorStyle(styleId, style, parentStyleSheet));
+}
+
+InspectorStyle::InspectorStyle(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet)
+    : m_styleId(styleId)
+    , m_style(style)
+    , m_parentStyleSheet(parentStyleSheet)
+    , m_formatAcquired(false)
+{
+    ASSERT(m_style);
+}
+
+InspectorStyle::~InspectorStyle()
+{
+}
+
+PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorStyle::buildObjectForStyle() const
+{
+    RefPtr<TypeBuilder::CSS::CSSStyle> result = styleWithProperties();
+    if (!m_styleId.isEmpty())
+        result->setStyleId(m_styleId.asProtocolValue<TypeBuilder::CSS::CSSStyleId>());
+
+    result->setWidth(m_style->getPropertyValue("width"));
+    result->setHeight(m_style->getPropertyValue("height"));
+
+    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
+    if (sourceData)
+        result->setRange(buildSourceRangeObject(sourceData->ruleBodyRange, m_parentStyleSheet->lineEndings().get()));
+
+    return result.release();
+}
+
+PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> > InspectorStyle::buildArrayForComputedStyle() const
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> > result = TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty>::create();
+    Vector<InspectorStyleProperty> properties;
+    populateAllProperties(properties);
+
+    for (Vector<InspectorStyleProperty>::iterator it = properties.begin(), itEnd = properties.end(); it != itEnd; ++it) {
+        const CSSPropertySourceData& propertyEntry = it->sourceData;
+        RefPtr<TypeBuilder::CSS::CSSComputedStyleProperty> entry = TypeBuilder::CSS::CSSComputedStyleProperty::create()
+            .setName(propertyEntry.name)
+            .setValue(propertyEntry.value);
+        result->addItem(entry);
+    }
+
+    return result.release();
+}
+
+// This method does the following preprocessing of |propertyText| with |overwrite| == false and |index| past the last active property:
+// - If the last property (if present) has no closing ";", the ";" is prepended to the current |propertyText| value.
+// - A heuristic formatting is attempted to retain the style structure.
+//
+// The propertyText (if not empty) is checked to be a valid style declaration (containing at least one property). If not,
+// the method returns false (denoting an error).
+bool InspectorStyle::setPropertyText(unsigned index, const String& propertyText, bool overwrite, String* oldText, ExceptionCode& ec)
+{
+    ASSERT(m_parentStyleSheet);
+    DEFINE_STATIC_LOCAL(String, bogusPropertyName, (ASCIILiteral("-webkit-boguz-propertee")));
+
+    if (!m_parentStyleSheet->ensureParsedDataReady()) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    Vector<InspectorStyleProperty> allProperties;
+    populateAllProperties(allProperties);
+
+    if (!propertyText.stripWhiteSpace().isEmpty()) {
+        RefPtr<StylePropertySet> tempMutableStyle = StylePropertySet::create();
+        String declarationText = propertyText + " " + bogusPropertyName + ": none";
+        RuleSourceDataList sourceData;
+        StyleSheetHandler handler(declarationText, ownerDocument(), m_style->parentStyleSheet()->contents(), &sourceData);
+        createCSSParser(ownerDocument())->parseDeclaration(tempMutableStyle.get(), declarationText, &handler, m_style->parentStyleSheet()->contents());
+        Vector<CSSPropertySourceData>& propertyData = sourceData.first()->styleSourceData->propertyData;
+        unsigned propertyCount = propertyData.size();
+
+        // At least one property + the bogus property added just above should be present.
+        if (propertyCount < 2) {
+            ec = SYNTAX_ERR;
+            return false;
+        }
+
+        // Check for the proper propertyText termination (the parser could at least restore to the PROPERTY_NAME state).
+        if (propertyData.at(propertyCount - 1).name != bogusPropertyName) {
+            ec = SYNTAX_ERR;
+            return false;
+        }
+    }
+
+    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
+    if (!sourceData) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    String text;
+    bool success = styleText(&text);
+    if (!success) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    InspectorStyleTextEditor editor(&allProperties, text, newLineAndWhitespaceDelimiters());
+    if (overwrite) {
+        if (index >= allProperties.size()) {
+            ec = INDEX_SIZE_ERR;
+            return false;
+        }
+        *oldText = allProperties.at(index).rawText;
+        editor.replaceProperty(index, propertyText);
+    } else
+        editor.insertProperty(index, propertyText, sourceData->ruleBodyRange.length());
+
+    return applyStyleText(editor.styleText());
+}
+
+bool InspectorStyle::toggleProperty(unsigned index, bool disable, ExceptionCode& ec)
+{
+    ASSERT(m_parentStyleSheet);
+    if (!m_parentStyleSheet->ensureParsedDataReady()) {
+        ec = NO_MODIFICATION_ALLOWED_ERR;
+        return false;
+    }
+
+    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
+    if (!sourceData) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    String text;
+    bool success = styleText(&text);
+    if (!success) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    Vector<InspectorStyleProperty> allProperties;
+    populateAllProperties(allProperties);
+    if (index >= allProperties.size()) {
+        ec = INDEX_SIZE_ERR;
+        return false;
+    }
+
+    InspectorStyleProperty& property = allProperties.at(index);
+    if (property.sourceData.disabled == disable)
+        return true; // Idempotent operation.
+
+    InspectorStyleTextEditor editor(&allProperties, text, newLineAndWhitespaceDelimiters());
+    if (disable)
+        editor.disableProperty(index);
+    else
+        editor.enableProperty(index);
+
+    return applyStyleText(editor.styleText());
+}
+
+bool InspectorStyle::styleText(String* result) const
+{
+    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
+    if (!sourceData)
+        return false;
+
+    String styleSheetText;
+    bool success = m_parentStyleSheet->getText(&styleSheetText);
+    if (!success)
+        return false;
+
+    SourceRange& bodyRange = sourceData->ruleBodyRange;
+    *result = styleSheetText.substring(bodyRange.start, bodyRange.end - bodyRange.start);
+    return true;
+}
+
+void InspectorStyle::populateAllProperties(Vector<InspectorStyleProperty>& result) const
+{
+    HashSet<String> foundShorthands;
+    HashSet<String> sourcePropertyNames;
+
+    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
+    OwnPtr<CSSParser> cssParser;
+    if (sourceData) {
+        String styleDeclaration;
+        bool isStyleTextKnown = styleText(&styleDeclaration);
+        ASSERT_UNUSED(isStyleTextKnown, isStyleTextKnown);
+        Vector<CSSPropertySourceData>& sourcePropertyData = sourceData->styleSourceData->propertyData;
+        for (Vector<CSSPropertySourceData>::const_iterator it = sourcePropertyData.begin(); it != sourcePropertyData.end(); ++it) {
+            InspectorStyleProperty p(*it, true);
+            p.setRawTextFromStyleDeclaration(styleDeclaration);
+            result.append(p);
+            sourcePropertyNames.add(it->name.lower());
+        }
+    }
+
+    for (int i = 0, size = m_style->length(); i < size; ++i) {
+        String name = m_style->item(i);
+        if (sourcePropertyNames.contains(name.lower()))
+            continue;
+
+        sourcePropertyNames.add(name.lower());
+        result.append(InspectorStyleProperty(CSSPropertySourceData(name, m_style->getPropertyValue(name), !m_style->getPropertyPriority(name).isEmpty(), false, true, SourceRange()), false));
+    }
+}
+
+PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorStyle::styleWithProperties() const
+{
+    Vector<InspectorStyleProperty> properties;
+    populateAllProperties(properties);
+
+    RefPtr<Array<TypeBuilder::CSS::CSSProperty> > propertiesObject = Array<TypeBuilder::CSS::CSSProperty>::create();
+    RefPtr<Array<TypeBuilder::CSS::ShorthandEntry> > shorthandEntries = Array<TypeBuilder::CSS::ShorthandEntry>::create();
+    HashMap<String, RefPtr<TypeBuilder::CSS::CSSProperty> > propertyNameToPreviousActiveProperty;
+    HashSet<String> foundShorthands;
+    String previousPriority;
+    String previousStatus;
+    OwnPtr<Vector<size_t> > lineEndings(m_parentStyleSheet ? m_parentStyleSheet->lineEndings() : PassOwnPtr<Vector<size_t> >());
+    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
+    unsigned ruleBodyRangeStart = sourceData ? sourceData->ruleBodyRange.start : 0;
+
+    for (Vector<InspectorStyleProperty>::iterator it = properties.begin(), itEnd = properties.end(); it != itEnd; ++it) {
+        const CSSPropertySourceData& propertyEntry = it->sourceData;
+        const String& name = propertyEntry.name;
+        const bool disabled = it->sourceData.disabled;
+
+        TypeBuilder::CSS::CSSProperty::Status::Enum status = disabled ? TypeBuilder::CSS::CSSProperty::Status::Disabled : TypeBuilder::CSS::CSSProperty::Status::Active;
+
+        RefPtr<TypeBuilder::CSS::CSSProperty> property = TypeBuilder::CSS::CSSProperty::create()
+            .setName(name)
+            .setValue(propertyEntry.value);
+        propertiesObject->addItem(property);
+
+        // Default "parsedOk" == true.
+        if (!propertyEntry.parsedOk)
+            property->setParsedOk(false);
+        if (it->hasRawText())
+            property->setText(it->rawText);
+
+        // Default "priority" == "".
+        if (propertyEntry.important)
+            property->setPriority("important");
+        if (it->hasSource) {
+            // The property range is relative to the style body start.
+            // Should be converted into an absolute range (relative to the stylesheet start)
+            // for the proper conversion into line:column.
+            SourceRange absolutePropertyRange = propertyEntry.range;
+            absolutePropertyRange.start += ruleBodyRangeStart;
+            absolutePropertyRange.end += ruleBodyRangeStart;
+            property->setRange(buildSourceRangeObject(absolutePropertyRange, lineEndings.get()));
+        }
+        if (!disabled) {
+            if (it->hasSource) {
+                ASSERT(sourceData);
+                property->setImplicit(false);
+
+                // Parsed property overrides any property with the same name. Non-parsed property overrides
+                // previous non-parsed property with the same name (if any).
+                bool shouldInactivate = false;
+                CSSPropertyID propertyId = cssPropertyID(name);
+                // Canonicalize property names to treat non-prefixed and vendor-prefixed property names the same (opacity vs. -webkit-opacity).
+                String canonicalPropertyName = propertyId ? getPropertyNameString(propertyId) : name;
+                HashMap<String, RefPtr<TypeBuilder::CSS::CSSProperty> >::iterator activeIt = propertyNameToPreviousActiveProperty.find(canonicalPropertyName);
+                if (activeIt != propertyNameToPreviousActiveProperty.end()) {
+                    if (propertyEntry.parsedOk) {
+                        bool successPriority = activeIt->value->getString(TypeBuilder::CSS::CSSProperty::Priority, &previousPriority);
+                        bool successStatus = activeIt->value->getString(TypeBuilder::CSS::CSSProperty::Status, &previousStatus);
+                        if (successStatus && previousStatus != "inactive") {
+                            if (propertyEntry.important || !successPriority) // Priority not set == "not important".
+                                shouldInactivate = true;
+                            else if (status == TypeBuilder::CSS::CSSProperty::Status::Active) {
+                                // Inactivate a non-important property following the same-named important property.
+                                status = TypeBuilder::CSS::CSSProperty::Status::Inactive;
+                            }
+                        }
+                    } else {
+                        bool previousParsedOk;
+                        bool success = activeIt->value->getBoolean(TypeBuilder::CSS::CSSProperty::ParsedOk, &previousParsedOk);
+                        if (success && !previousParsedOk)
+                            shouldInactivate = true;
+                    }
+                } else
+                    propertyNameToPreviousActiveProperty.set(canonicalPropertyName, property);
+
+                if (shouldInactivate) {
+                    activeIt->value->setStatus(TypeBuilder::CSS::CSSProperty::Status::Inactive);
+                    propertyNameToPreviousActiveProperty.set(canonicalPropertyName, property);
+                }
+            } else {
+                bool implicit = m_style->isPropertyImplicit(name);
+                // Default "implicit" == false.
+                if (implicit)
+                    property->setImplicit(true);
+                status = TypeBuilder::CSS::CSSProperty::Status::Style;
+
+                String shorthand = m_style->getPropertyShorthand(name);
+                if (!shorthand.isEmpty()) {
+                    if (!foundShorthands.contains(shorthand)) {
+                        foundShorthands.add(shorthand);
+                        RefPtr<TypeBuilder::CSS::ShorthandEntry> entry = TypeBuilder::CSS::ShorthandEntry::create()
+                            .setName(shorthand)
+                            .setValue(shorthandValue(shorthand));
+                        shorthandEntries->addItem(entry);
+                    }
+                }
+            }
+        }
+
+        // Default "status" == "style".
+        if (status != TypeBuilder::CSS::CSSProperty::Status::Style)
+            property->setStatus(status);
+    }
+
+    RefPtr<TypeBuilder::CSS::CSSStyle> result = TypeBuilder::CSS::CSSStyle::create()
+        .setCssProperties(propertiesObject)
+        .setShorthandEntries(shorthandEntries);
+    return result.release();
+}
+
+PassRefPtr<CSSRuleSourceData> InspectorStyle::extractSourceData() const
+{
+    if (!m_parentStyleSheet || !m_parentStyleSheet->ensureParsedDataReady())
+        return 0;
+    return m_parentStyleSheet->ruleSourceDataFor(m_style.get());
+}
+
+bool InspectorStyle::applyStyleText(const String& text)
+{
+    return m_parentStyleSheet->setStyleText(m_style.get(), text);
+}
+
+String InspectorStyle::shorthandValue(const String& shorthandProperty) const
+{
+    String value = m_style->getPropertyValue(shorthandProperty);
+    if (value.isEmpty()) {
+        for (unsigned i = 0; i < m_style->length(); ++i) {
+            String individualProperty = m_style->item(i);
+            if (m_style->getPropertyShorthand(individualProperty) != shorthandProperty)
+                continue;
+            if (m_style->isPropertyImplicit(individualProperty))
+                continue;
+            String individualValue = m_style->getPropertyValue(individualProperty);
+            if (individualValue == "initial")
+                continue;
+            if (value.length())
+                value.append(" ");
+            value.append(individualValue);
+        }
+    }
+    return value;
+}
+
+String InspectorStyle::shorthandPriority(const String& shorthandProperty) const
+{
+    String priority = m_style->getPropertyPriority(shorthandProperty);
+    if (priority.isEmpty()) {
+        for (unsigned i = 0; i < m_style->length(); ++i) {
+            String individualProperty = m_style->item(i);
+            if (m_style->getPropertyShorthand(individualProperty) != shorthandProperty)
+                continue;
+            priority = m_style->getPropertyPriority(individualProperty);
+            break;
+        }
+    }
+    return priority;
+}
+
+Vector<String> InspectorStyle::longhandProperties(const String& shorthandProperty) const
+{
+    Vector<String> properties;
+    HashSet<String> foundProperties;
+    for (unsigned i = 0; i < m_style->length(); ++i) {
+        String individualProperty = m_style->item(i);
+        if (foundProperties.contains(individualProperty) || m_style->getPropertyShorthand(individualProperty) != shorthandProperty)
+            continue;
+
+        foundProperties.add(individualProperty);
+        properties.append(individualProperty);
+    }
+    return properties;
+}
+
+NewLineAndWhitespace& InspectorStyle::newLineAndWhitespaceDelimiters() const
+{
+    DEFINE_STATIC_LOCAL(String, defaultPrefix, (ASCIILiteral("    ")));
+
+    if (m_formatAcquired)
+        return m_format;
+
+    RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
+    Vector<CSSPropertySourceData>* sourcePropertyData = sourceData ? &(sourceData->styleSourceData->propertyData) : 0;
+    int propertyCount;
+    if (!sourcePropertyData || !(propertyCount = sourcePropertyData->size())) {
+        m_format.first = "\n";
+        m_format.second = defaultPrefix;
+        return m_format; // Do not remember the default formatting and attempt to acquire it later.
+    }
+
+    String text;
+    bool success = styleText(&text);
+    ASSERT_UNUSED(success, success);
+
+    m_formatAcquired = true;
+
+    String candidatePrefix = defaultPrefix;
+    StringBuilder formatLineFeed;
+    StringBuilder prefix;
+    int scanStart = 0;
+    int propertyIndex = 0;
+    bool isFullPrefixScanned = false;
+    bool lineFeedTerminated = false;
+    const UChar* characters = text.characters();
+    while (propertyIndex < propertyCount) {
+        const WebCore::CSSPropertySourceData& currentProperty = sourcePropertyData->at(propertyIndex++);
+
+        bool processNextProperty = false;
+        int scanEnd = currentProperty.range.start;
+        for (int i = scanStart; i < scanEnd; ++i) {
+            UChar ch = characters[i];
+            bool isLineFeed = isHTMLLineBreak(ch);
+            if (isLineFeed) {
+                if (!lineFeedTerminated)
+                    formatLineFeed.append(ch);
+                prefix.clear();
+            } else if (isHTMLSpace(ch))
+                prefix.append(ch);
+            else {
+                candidatePrefix = prefix.toString();
+                prefix.clear();
+                scanStart = currentProperty.range.end;
+                ++propertyIndex;
+                processNextProperty = true;
+                break;
+            }
+            if (!isLineFeed && formatLineFeed.length())
+                lineFeedTerminated = true;
+        }
+        if (!processNextProperty) {
+            isFullPrefixScanned = true;
+            break;
+        }
+    }
+
+    m_format.first = formatLineFeed.toString();
+    m_format.second = isFullPrefixScanned ? prefix.toString() : candidatePrefix;
+    return m_format;
+}
+
+Document* InspectorStyle::ownerDocument() const
+{
+    return m_parentStyleSheet->pageStyleSheet() ? m_parentStyleSheet->pageStyleSheet()->ownerDocument() : 0;
+}
+
+PassRefPtr<InspectorStyleSheet> InspectorStyleSheet::create(InspectorPageAgent* pageAgent, const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, TypeBuilder::CSS::StyleSheetOrigin::Enum origin, const String& documentURL, Listener* listener)
+{
+    return adoptRef(new InspectorStyleSheet(pageAgent, id, pageStyleSheet, origin, documentURL, listener));
+}
+
+// static
+String InspectorStyleSheet::styleSheetURL(CSSStyleSheet* pageStyleSheet)
+{
+    if (pageStyleSheet && !pageStyleSheet->contents()->baseURL().isEmpty())
+        return pageStyleSheet->contents()->baseURL().string();
+    return emptyString();
+}
+
+InspectorStyleSheet::InspectorStyleSheet(InspectorPageAgent* pageAgent, const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, TypeBuilder::CSS::StyleSheetOrigin::Enum origin, const String& documentURL, Listener* listener)
+    : m_pageAgent(pageAgent)
+    , m_id(id)
+    , m_pageStyleSheet(pageStyleSheet)
+    , m_origin(origin)
+    , m_documentURL(documentURL)
+    , m_isRevalidating(false)
+    , m_isReparsing(false)
+    , m_listener(listener)
+{
+    m_parsedStyleSheet = new ParsedStyleSheet();
+}
+
+InspectorStyleSheet::~InspectorStyleSheet()
+{
+    delete m_parsedStyleSheet;
+}
+
+String InspectorStyleSheet::finalURL() const
+{
+    String url = styleSheetURL(m_pageStyleSheet.get());
+    return url.isEmpty() ? m_documentURL : url;
+}
+
+void InspectorStyleSheet::reparseStyleSheet(const String& text)
+{
+    {
+        // Have a separate scope for clearRules() (bug 95324).
+        CSSStyleSheet::RuleMutationScope mutationScope(m_pageStyleSheet.get());
+        m_pageStyleSheet->contents()->clearRules();
+        m_pageStyleSheet->clearChildRuleCSSOMWrappers();
+    }
+    {
+        m_isReparsing = true;
+        CSSStyleSheet::RuleMutationScope mutationScope(m_pageStyleSheet.get());
+        m_pageStyleSheet->contents()->parseString(text);
+        fireStyleSheetChanged();
+        m_isReparsing = false;
+    }
+}
+
+bool InspectorStyleSheet::setText(const String& text, ExceptionCode& ec)
+{
+    if (!checkPageStyleSheet(ec))
+        return false;
+    if (!m_parsedStyleSheet)
+        return false;
+
+    m_parsedStyleSheet->setText(text);
+    m_flatRules.clear();
+
+    return true;
+}
+
+String InspectorStyleSheet::ruleSelector(const InspectorCSSId& id, ExceptionCode& ec)
+{
+    CSSStyleRule* rule = ruleForId(id);
+    if (!rule) {
+        ec = NOT_FOUND_ERR;
+        return "";
+    }
+    return rule->selectorText();
+}
+
+bool InspectorStyleSheet::setRuleSelector(const InspectorCSSId& id, const String& selector, ExceptionCode& ec)
+{
+    if (!checkPageStyleSheet(ec))
+        return false;
+    CSSStyleRule* rule = ruleForId(id);
+    if (!rule) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+    CSSStyleSheet* styleSheet = rule->parentStyleSheet();
+    if (!styleSheet || !ensureParsedDataReady()) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    rule->setSelectorText(selector);
+    RefPtr<CSSRuleSourceData> sourceData = ruleSourceDataFor(rule->style());
+    if (!sourceData) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    String sheetText = m_parsedStyleSheet->text();
+    sheetText.replace(sourceData->ruleHeaderRange.start, sourceData->ruleHeaderRange.length(), selector);
+    m_parsedStyleSheet->setText(sheetText);
+    fireStyleSheetChanged();
+    return true;
+}
+
+static bool checkStyleRuleSelector(Document* document, const String& selector)
+{
+    CSSSelectorList selectorList;
+    createCSSParser(document)->parseSelector(selector, selectorList);
+    return selectorList.isValid();
+}
+
+CSSStyleRule* InspectorStyleSheet::addRule(const String& selector, ExceptionCode& ec)
+{
+    if (!checkPageStyleSheet(ec))
+        return 0;
+    if (!checkStyleRuleSelector(m_pageStyleSheet->ownerDocument(), selector)) {
+        ec = SYNTAX_ERR;
+        return 0;
+    }
+
+    String text;
+    bool success = getText(&text);
+    if (!success) {
+        ec = NOT_FOUND_ERR;
+        return 0;
+    }
+    StringBuilder styleSheetText;
+    styleSheetText.append(text);
+
+    m_pageStyleSheet->addRule(selector, "", ec);
+    if (ec)
+        return 0;
+    ASSERT(m_pageStyleSheet->length());
+    unsigned lastRuleIndex = m_pageStyleSheet->length() - 1;
+    CSSRule* rule = m_pageStyleSheet->item(lastRuleIndex);
+    ASSERT(rule);
+
+    CSSStyleRule* styleRule = InspectorCSSAgent::asCSSStyleRule(rule);
+    if (!styleRule) {
+        // What we just added has to be a CSSStyleRule - we cannot handle other types of rules yet.
+        // If it is not a style rule, pretend we never touched the stylesheet.
+        m_pageStyleSheet->deleteRule(lastRuleIndex, ASSERT_NO_EXCEPTION);
+        ec = SYNTAX_ERR;
+        return 0;
+    }
+
+    if (!styleSheetText.isEmpty())
+        styleSheetText.append('\n');
+
+    styleSheetText.append(selector);
+    styleSheetText.appendLiteral(" {}");
+    // Using setText() as this operation changes the style sheet rule set.
+    setText(styleSheetText.toString(), ASSERT_NO_EXCEPTION);
+
+    fireStyleSheetChanged();
+
+    return styleRule;
+}
+
+bool InspectorStyleSheet::deleteRule(const InspectorCSSId& id, ExceptionCode& ec)
+{
+    if (!checkPageStyleSheet(ec))
+        return false;
+    RefPtr<CSSStyleRule> rule = ruleForId(id);
+    if (!rule) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+    CSSStyleSheet* styleSheet = rule->parentStyleSheet();
+    if (!styleSheet || !ensureParsedDataReady()) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    RefPtr<CSSRuleSourceData> sourceData = ruleSourceDataFor(rule->style());
+    if (!sourceData) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    styleSheet->deleteRule(id.ordinal(), ec);
+    // |rule| MAY NOT be addressed after this line!
+
+    if (ec)
+        return false;
+
+    String sheetText = m_parsedStyleSheet->text();
+    sheetText.remove(sourceData->ruleHeaderRange.start, sourceData->ruleBodyRange.end - sourceData->ruleHeaderRange.start + 1);
+    setText(sheetText, ASSERT_NO_EXCEPTION);
+    fireStyleSheetChanged();
+    return true;
+}
+
+CSSStyleRule* InspectorStyleSheet::ruleForId(const InspectorCSSId& id) const
+{
+    if (!m_pageStyleSheet)
+        return 0;
+
+    ASSERT(!id.isEmpty());
+    ensureFlatRules();
+    return id.ordinal() >= m_flatRules.size() ? 0 : m_flatRules.at(id.ordinal()).get();
+
+}
+
+PassRefPtr<TypeBuilder::CSS::CSSStyleSheetBody> InspectorStyleSheet::buildObjectForStyleSheet()
+{
+    CSSStyleSheet* styleSheet = pageStyleSheet();
+    if (!styleSheet)
+        return 0;
+
+    RefPtr<CSSRuleList> cssRuleList = asCSSRuleList(styleSheet);
+
+    RefPtr<TypeBuilder::CSS::CSSStyleSheetBody> result = TypeBuilder::CSS::CSSStyleSheetBody::create()
+        .setStyleSheetId(id())
+        .setRules(buildArrayForRuleList(cssRuleList.get()));
+
+    String styleSheetText;
+    bool success = getText(&styleSheetText);
+    if (success)
+        result->setText(styleSheetText);
+
+    return result.release();
+}
+
+PassRefPtr<TypeBuilder::CSS::CSSStyleSheetHeader> InspectorStyleSheet::buildObjectForStyleSheetInfo()
+{
+    CSSStyleSheet* styleSheet = pageStyleSheet();
+    if (!styleSheet)
+        return 0;
+
+    Document* document = styleSheet->ownerDocument();
+    Frame* frame = document ? document->frame() : 0;
+    RefPtr<TypeBuilder::CSS::CSSStyleSheetHeader> result = TypeBuilder::CSS::CSSStyleSheetHeader::create()
+        .setStyleSheetId(id())
+        .setOrigin(m_origin)
+        .setDisabled(styleSheet->disabled())
+        .setSourceURL(finalURL())
+        .setTitle(styleSheet->title())
+        .setFrameId(m_pageAgent->frameId(frame));
+
+    return result.release();
+}
+
+static PassRefPtr<TypeBuilder::Array<String> > selectorsFromSource(const CSSRuleSourceData* sourceData, const String& sheetText)
+{
+    RegularExpression comment("/\\*[^]*?\\*/", TextCaseSensitive, MultilineEnabled);
+    RefPtr<TypeBuilder::Array<String> > result = TypeBuilder::Array<String>::create();
+    const SelectorRangeList& ranges = sourceData->selectorRanges;
+    for (size_t i = 0, size = ranges.size(); i < size; ++i) {
+        const SourceRange& range = ranges.at(i);
+        String selector = sheetText.substring(range.start, range.length());
+
+        // We don't want to see any comments in the selector components, only the meaningful parts.
+        int matchLength;
+        int offset = 0;
+        while ((offset = comment.match(selector, offset, &matchLength)) >= 0)
+            selector.replace(offset, matchLength, "");
+
+        result->addItem(selector.stripWhiteSpace());
+    }
+    return result.release();
+}
+
+PassRefPtr<TypeBuilder::CSS::SelectorList> InspectorStyleSheet::buildObjectForSelectorList(CSSStyleRule* rule)
+{
+    RefPtr<CSSRuleSourceData> sourceData;
+    if (ensureParsedDataReady())
+        sourceData = ruleSourceDataFor(rule->style());
+    RefPtr<TypeBuilder::Array<String> > selectors;
+
+    // This intentionally does not rely on the source data to avoid catching the trailing comments (before the declaration starting '{').
+    String selectorText = rule->selectorText();
+
+    if (sourceData)
+        selectors = selectorsFromSource(sourceData.get(), m_parsedStyleSheet->text());
+    else {
+        selectors = TypeBuilder::Array<String>::create();
+        const CSSSelectorList& selectorList = rule->styleRule()->selectorList();
+        for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector))
+            selectors->addItem(selector->selectorText());
+    }
+    RefPtr<TypeBuilder::CSS::SelectorList> result = TypeBuilder::CSS::SelectorList::create()
+        .setSelectors(selectors)
+        .setText(selectorText)
+        .release();
+    if (sourceData)
+        result->setRange(buildSourceRangeObject(sourceData->ruleHeaderRange, lineEndings().get()));
+    return result.release();
+}
+
+PassRefPtr<TypeBuilder::CSS::CSSRule> InspectorStyleSheet::buildObjectForRule(CSSStyleRule* rule)
+{
+    CSSStyleSheet* styleSheet = pageStyleSheet();
+    if (!styleSheet)
+        return 0;
+
+    RefPtr<TypeBuilder::CSS::CSSRule> result = TypeBuilder::CSS::CSSRule::create()
+        .setSelectorList(buildObjectForSelectorList(rule))
+        .setSourceLine(rule->styleRule()->sourceLine())
+        .setOrigin(m_origin)
+        .setStyle(buildObjectForStyle(rule->style()));
+
+    // "sourceURL" is present only for regular rules, otherwise "origin" should be used in the frontend.
+    if (m_origin == TypeBuilder::CSS::StyleSheetOrigin::Regular)
+        result->setSourceURL(finalURL());
+
+    if (canBind()) {
+        InspectorCSSId id(ruleId(rule));
+        if (!id.isEmpty())
+            result->setRuleId(id.asProtocolValue<TypeBuilder::CSS::CSSRuleId>());
+    }
+
+    RefPtr<Array<TypeBuilder::CSS::CSSMedia> > mediaArray = Array<TypeBuilder::CSS::CSSMedia>::create();
+
+    fillMediaListChain(rule, mediaArray.get());
+    if (mediaArray->length())
+        result->setMedia(mediaArray.release());
+
+    return result.release();
+}
+
+PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorStyleSheet::buildObjectForStyle(CSSStyleDeclaration* style)
+{
+    RefPtr<CSSRuleSourceData> sourceData;
+    if (ensureParsedDataReady())
+        sourceData = ruleSourceDataFor(style);
+
+    InspectorCSSId id = ruleOrStyleId(style);
+    if (id.isEmpty()) {
+        RefPtr<TypeBuilder::CSS::CSSStyle> bogusStyle = TypeBuilder::CSS::CSSStyle::create()
+            .setCssProperties(Array<TypeBuilder::CSS::CSSProperty>::create())
+            .setShorthandEntries(Array<TypeBuilder::CSS::ShorthandEntry>::create());
+        return bogusStyle.release();
+    }
+    RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
+    RefPtr<TypeBuilder::CSS::CSSStyle> result = inspectorStyle->buildObjectForStyle();
+
+    // Style text cannot be retrieved without stylesheet, so set cssText here.
+    if (sourceData) {
+        String sheetText;
+        bool success = getText(&sheetText);
+        if (success) {
+            const SourceRange& bodyRange = sourceData->ruleBodyRange;
+            result->setCssText(sheetText.substring(bodyRange.start, bodyRange.end - bodyRange.start));
+        }
+    }
+
+    return result.release();
+}
+
+bool InspectorStyleSheet::setStyleText(const InspectorCSSId& id, const String& text, String* oldText, ExceptionCode& ec)
+{
+    RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
+    if (!inspectorStyle || !inspectorStyle->cssStyle()) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    bool success = inspectorStyle->styleText(oldText);
+    if (!success) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    success = setStyleText(inspectorStyle->cssStyle(), text);
+    if (success)
+        fireStyleSheetChanged();
+    else
+        ec = SYNTAX_ERR;
+    return success;
+}
+
+bool InspectorStyleSheet::setPropertyText(const InspectorCSSId& id, unsigned propertyIndex, const String& text, bool overwrite, String* oldText, ExceptionCode& ec)
+{
+    RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
+    if (!inspectorStyle) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    bool success = inspectorStyle->setPropertyText(propertyIndex, text, overwrite, oldText, ec);
+    if (success)
+        fireStyleSheetChanged();
+    return success;
+}
+
+bool InspectorStyleSheet::toggleProperty(const InspectorCSSId& id, unsigned propertyIndex, bool disable, ExceptionCode& ec)
+{
+    RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
+    if (!inspectorStyle) {
+        ec = NOT_FOUND_ERR;
+        return false;
+    }
+
+    bool success = inspectorStyle->toggleProperty(propertyIndex, disable, ec);
+    if (success)
+        fireStyleSheetChanged();
+    return success;
+}
+
+bool InspectorStyleSheet::getText(String* result) const
+{
+    if (!ensureText())
+        return false;
+    *result = m_parsedStyleSheet->text();
+    return true;
+}
+
+CSSStyleDeclaration* InspectorStyleSheet::styleForId(const InspectorCSSId& id) const
+{
+    CSSStyleRule* rule = ruleForId(id);
+    if (!rule)
+        return 0;
+
+    return rule->style();
+}
+
+void InspectorStyleSheet::fireStyleSheetChanged()
+{
+    if (m_listener)
+        m_listener->styleSheetChanged(this);
+}
+
+PassRefPtr<InspectorStyle> InspectorStyleSheet::inspectorStyleForId(const InspectorCSSId& id)
+{
+    CSSStyleDeclaration* style = styleForId(id);
+    if (!style)
+        return 0;
+
+    return InspectorStyle::create(id, style, this);
+}
+
+InspectorCSSId InspectorStyleSheet::ruleOrStyleId(CSSStyleDeclaration* style) const
+{
+    unsigned index = ruleIndexByStyle(style);
+    if (index != UINT_MAX)
+        return InspectorCSSId(id(), index);
+    return InspectorCSSId();
+}
+
+Document* InspectorStyleSheet::ownerDocument() const
+{
+    return m_pageStyleSheet->ownerDocument();
+}
+
+PassRefPtr<CSSRuleSourceData> InspectorStyleSheet::ruleSourceDataFor(CSSStyleDeclaration* style) const
+{
+    return m_parsedStyleSheet->ruleSourceDataAt(ruleIndexByStyle(style));
+}
+
+PassOwnPtr<Vector<size_t> > InspectorStyleSheet::lineEndings() const
+{
+    if (!m_parsedStyleSheet->hasText())
+        return PassOwnPtr<Vector<size_t> >();
+    return ContentSearchUtils::lineEndings(m_parsedStyleSheet->text());
+}
+
+unsigned InspectorStyleSheet::ruleIndexByStyle(CSSStyleDeclaration* pageStyle) const
+{
+    ensureFlatRules();
+    unsigned index = 0;
+    for (unsigned i = 0, size = m_flatRules.size(); i < size; ++i) {
+        if (m_flatRules.at(i)->style() == pageStyle)
+            return index;
+
+        ++index;
+    }
+    return UINT_MAX;
+}
+
+bool InspectorStyleSheet::checkPageStyleSheet(ExceptionCode& ec) const
+{
+    if (!m_pageStyleSheet) {
+        ec = NOT_SUPPORTED_ERR;
+        return false;
+    }
+    return true;
+}
+
+bool InspectorStyleSheet::ensureParsedDataReady()
+{
+    return ensureText() && ensureSourceData();
+}
+
+bool InspectorStyleSheet::ensureText() const
+{
+    if (!m_parsedStyleSheet)
+        return false;
+    if (m_parsedStyleSheet->hasText())
+        return true;
+
+    String text;
+    bool success = originalStyleSheetText(&text);
+    if (success)
+        m_parsedStyleSheet->setText(text);
+    // No need to clear m_flatRules here - it's empty.
+
+    return success;
+}
+
+bool InspectorStyleSheet::ensureSourceData()
+{
+    if (m_parsedStyleSheet->hasSourceData())
+        return true;
+
+    if (!m_parsedStyleSheet->hasText())
+        return false;
+
+    RefPtr<StyleSheetContents> newStyleSheet = StyleSheetContents::create();
+    OwnPtr<RuleSourceDataList> result = adoptPtr(new RuleSourceDataList());
+    StyleSheetHandler handler(m_parsedStyleSheet->text(), m_pageStyleSheet->ownerDocument(), newStyleSheet.get(), result.get());
+    createCSSParser(m_pageStyleSheet->ownerDocument())->parseSheet(newStyleSheet.get(), m_parsedStyleSheet->text(), 0, &handler);
+    m_parsedStyleSheet->setSourceData(result.release());
+    return m_parsedStyleSheet->hasSourceData();
+}
+
+void InspectorStyleSheet::ensureFlatRules() const
+{
+    // We are fine with redoing this for empty stylesheets as this will run fast.
+    if (m_flatRules.isEmpty())
+        collectFlatRules(asCSSRuleList(pageStyleSheet()), &m_flatRules);
+}
+
+bool InspectorStyleSheet::setStyleText(CSSStyleDeclaration* style, const String& text)
+{
+    if (!m_pageStyleSheet)
+        return false;
+    if (!ensureParsedDataReady())
+        return false;
+
+    String patchedStyleSheetText;
+    bool success = styleSheetTextWithChangedStyle(style, text, &patchedStyleSheetText);
+    if (!success)
+        return false;
+
+    InspectorCSSId id = ruleOrStyleId(style);
+    if (id.isEmpty())
+        return false;
+
+    ExceptionCode ec = 0;
+    style->setCssText(text, ec);
+    if (!ec)
+        m_parsedStyleSheet->setText(patchedStyleSheetText);
+
+    return !ec;
+}
+
+bool InspectorStyleSheet::styleSheetTextWithChangedStyle(CSSStyleDeclaration* style, const String& newStyleText, String* result)
+{
+    if (!style)
+        return false;
+
+    if (!ensureParsedDataReady())
+        return false;
+
+    RefPtr<CSSRuleSourceData> sourceData = ruleSourceDataFor(style);
+    unsigned bodyStart = sourceData->ruleBodyRange.start;
+    unsigned bodyEnd = sourceData->ruleBodyRange.end;
+    ASSERT(bodyStart <= bodyEnd);
+
+    String text = m_parsedStyleSheet->text();
+    ASSERT_WITH_SECURITY_IMPLICATION(bodyEnd <= text.length()); // bodyEnd is exclusive
+
+    text.replace(bodyStart, bodyEnd - bodyStart, newStyleText);
+    *result = text;
+    return true;
+}
+
+InspectorCSSId InspectorStyleSheet::ruleId(CSSStyleRule* rule) const
+{
+    return ruleOrStyleId(rule->style());
+}
+
+void InspectorStyleSheet::revalidateStyle(CSSStyleDeclaration* pageStyle)
+{
+    if (m_isRevalidating)
+        return;
+
+    m_isRevalidating = true;
+    ensureFlatRules();
+    for (unsigned i = 0, size = m_flatRules.size(); i < size; ++i) {
+        CSSStyleRule* parsedRule = m_flatRules.at(i).get();
+        if (parsedRule->style() == pageStyle) {
+            if (parsedRule->styleRule()->properties()->asText() != pageStyle->cssText())
+                setStyleText(pageStyle, pageStyle->cssText());
+            break;
+        }
+    }
+    m_isRevalidating = false;
+}
+
+bool InspectorStyleSheet::originalStyleSheetText(String* result) const
+{
+    bool success = inlineStyleSheetText(result);
+    if (!success)
+        success = resourceStyleSheetText(result);
+    return success;
+}
+
+bool InspectorStyleSheet::resourceStyleSheetText(String* result) const
+{
+    if (m_origin == TypeBuilder::CSS::StyleSheetOrigin::User || m_origin == TypeBuilder::CSS::StyleSheetOrigin::User_agent)
+        return false;
+
+    if (!m_pageStyleSheet || !ownerDocument() || !ownerDocument()->frame())
+        return false;
+
+    String error;
+    bool base64Encoded;
+    InspectorPageAgent::resourceContent(&error, ownerDocument()->frame(), KURL(ParsedURLString, m_pageStyleSheet->href()), result, &base64Encoded);
+    return error.isEmpty() && !base64Encoded;
+}
+
+bool InspectorStyleSheet::inlineStyleSheetText(String* result) const
+{
+    if (!m_pageStyleSheet)
+        return false;
+
+    Node* ownerNode = m_pageStyleSheet->ownerNode();
+    if (!ownerNode || ownerNode->nodeType() != Node::ELEMENT_NODE)
+        return false;
+    Element* ownerElement = toElement(ownerNode);
+
+    if (!ownerElement->hasTagName(HTMLNames::styleTag)
+#if ENABLE(SVG)
+        && !ownerElement->hasTagName(SVGNames::styleTag)
+#endif
+    )
+        return false;
+    *result = ownerElement->textContent();
+    return true;
+}
+
+PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > InspectorStyleSheet::buildArrayForRuleList(CSSRuleList* ruleList)
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > result = TypeBuilder::Array<TypeBuilder::CSS::CSSRule>::create();
+    if (!ruleList)
+        return result.release();
+
+    RefPtr<CSSRuleList> refRuleList = ruleList;
+    CSSStyleRuleVector rules;
+    collectFlatRules(refRuleList, &rules);
+
+    for (unsigned i = 0, size = rules.size(); i < size; ++i)
+        result->addItem(buildObjectForRule(rules.at(i).get()));
+
+    return result.release();
+}
+
+void InspectorStyleSheet::collectFlatRules(PassRefPtr<CSSRuleList> ruleList, CSSStyleRuleVector* result)
+{
+    if (!ruleList)
+        return;
+
+    for (unsigned i = 0, size = ruleList->length(); i < size; ++i) {
+        CSSRule* rule = ruleList->item(i);
+        CSSStyleRule* styleRule = InspectorCSSAgent::asCSSStyleRule(rule);
+        if (styleRule)
+            result->append(styleRule);
+        else {
+            RefPtr<CSSRuleList> childRuleList = asCSSRuleList(rule);
+            if (childRuleList)
+                collectFlatRules(childRuleList, result);
+        }
+    }
+}
+
+PassRefPtr<InspectorStyleSheetForInlineStyle> InspectorStyleSheetForInlineStyle::create(InspectorPageAgent* pageAgent, const String& id, PassRefPtr<Element> element, TypeBuilder::CSS::StyleSheetOrigin::Enum origin, Listener* listener)
+{
+    return adoptRef(new InspectorStyleSheetForInlineStyle(pageAgent, id, element, origin, listener));
+}
+
+InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle(InspectorPageAgent* pageAgent, const String& id, PassRefPtr<Element> element, TypeBuilder::CSS::StyleSheetOrigin::Enum origin, Listener* listener)
+    : InspectorStyleSheet(pageAgent, id, 0, origin, "", listener)
+    , m_element(element)
+    , m_ruleSourceData(0)
+    , m_isStyleTextValid(false)
+{
+    ASSERT(m_element);
+    m_inspectorStyle = InspectorStyle::create(InspectorCSSId(id, 0), inlineStyle(), this);
+    m_styleText = m_element->isStyledElement() ? m_element->getAttribute("style").string() : String();
+}
+
+void InspectorStyleSheetForInlineStyle::didModifyElementAttribute()
+{
+    m_isStyleTextValid = false;
+    if (m_element->isStyledElement() && m_element->style() != m_inspectorStyle->cssStyle())
+        m_inspectorStyle = InspectorStyle::create(InspectorCSSId(id(), 0), inlineStyle(), this);
+    m_ruleSourceData.clear();
+}
+
+bool InspectorStyleSheetForInlineStyle::getText(String* result) const
+{
+    if (!m_isStyleTextValid) {
+        m_styleText = elementStyleText();
+        m_isStyleTextValid = true;
+    }
+    *result = m_styleText;
+    return true;
+}
+
+bool InspectorStyleSheetForInlineStyle::setStyleText(CSSStyleDeclaration* style, const String& text)
+{
+    ASSERT_UNUSED(style, style == inlineStyle());
+    ExceptionCode ec = 0;
+
+    {
+        InspectorCSSAgent::InlineStyleOverrideScope overrideScope(m_element->ownerDocument());
+        m_element->setAttribute("style", text, ec);
+    }
+
+    m_styleText = text;
+    m_isStyleTextValid = true;
+    m_ruleSourceData.clear();
+    return !ec;
+}
+
+PassOwnPtr<Vector<size_t> > InspectorStyleSheetForInlineStyle::lineEndings() const
+{
+    return ContentSearchUtils::lineEndings(elementStyleText());
+}
+
+Document* InspectorStyleSheetForInlineStyle::ownerDocument() const
+{
+    return m_element->document();
+}
+
+bool InspectorStyleSheetForInlineStyle::ensureParsedDataReady()
+{
+    // The "style" property value can get changed indirectly, e.g. via element.style.borderWidth = "2px".
+    const String& currentStyleText = elementStyleText();
+    if (m_styleText != currentStyleText) {
+        m_ruleSourceData.clear();
+        m_styleText = currentStyleText;
+        m_isStyleTextValid = true;
+    }
+
+    if (m_ruleSourceData)
+        return true;
+
+    m_ruleSourceData = getStyleAttributeData();
+
+    bool success = !!m_ruleSourceData;
+    if (!success) {
+        m_ruleSourceData = CSSRuleSourceData::create(CSSRuleSourceData::STYLE_RULE);
+        return false;
+    }
+
+    return true;
+}
+
+PassRefPtr<InspectorStyle> InspectorStyleSheetForInlineStyle::inspectorStyleForId(const InspectorCSSId& id)
+{
+    ASSERT_UNUSED(id, !id.ordinal());
+    return m_inspectorStyle;
+}
+
+CSSStyleDeclaration* InspectorStyleSheetForInlineStyle::inlineStyle() const
+{
+    return m_element->style();
+}
+
+const String& InspectorStyleSheetForInlineStyle::elementStyleText() const
+{
+    return m_element->getAttribute("style").string();
+}
+
+PassRefPtr<CSSRuleSourceData> InspectorStyleSheetForInlineStyle::getStyleAttributeData() const
+{
+    if (!m_element->isStyledElement())
+        return 0;
+
+    if (m_styleText.isEmpty()) {
+        RefPtr<CSSRuleSourceData> result = CSSRuleSourceData::create(CSSRuleSourceData::STYLE_RULE);
+        result->ruleBodyRange.start = 0;
+        result->ruleBodyRange.end = 0;
+        return result.release();
+    }
+
+    RefPtr<StylePropertySet> tempDeclaration = StylePropertySet::create();
+    RuleSourceDataList ruleSourceDataResult;
+    StyleSheetHandler handler(m_styleText, m_element->document(), m_element->document()->elementSheet()->contents(), &ruleSourceDataResult);
+    createCSSParser(m_element->document())->parseDeclaration(tempDeclaration.get(), m_styleText, &handler, m_element->document()->elementSheet()->contents());
+    return ruleSourceDataResult.first().release();
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorStyleSheet.h b/Source/core/inspector/InspectorStyleSheet.h
new file mode 100644
index 0000000..1994981
--- /dev/null
+++ b/Source/core/inspector/InspectorStyleSheet.h
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2010, 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:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#ifndef InspectorStyleSheet_h
+#define InspectorStyleSheet_h
+
+#include "InspectorTypeBuilder.h"
+#include "core/css/CSSPropertySourceData.h"
+#include "core/css/CSSStyleDeclaration.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/inspector/InspectorStyleTextEditor.h"
+#include "core/inspector/InspectorValues.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+class ParsedStyleSheet;
+
+namespace WebCore {
+
+class CSSRuleList;
+class CSSStyleDeclaration;
+class CSSStyleRule;
+class CSSStyleSheet;
+class Document;
+class Element;
+class InspectorPageAgent;
+class InspectorStyleSheet;
+class Node;
+
+
+typedef String ErrorString;
+
+class InspectorCSSId {
+public:
+    InspectorCSSId()
+        : m_ordinal(0)
+    {
+    }
+
+    explicit InspectorCSSId(RefPtr<InspectorObject> value)
+    {
+        if (!value->getString("styleSheetId", &m_styleSheetId))
+            return;
+        
+        RefPtr<InspectorValue> ordinalValue = value->get("ordinal");
+        if (!ordinalValue || !ordinalValue->asNumber(&m_ordinal))
+            m_styleSheetId = "";
+    }
+
+    InspectorCSSId(const String& styleSheetId, unsigned ordinal)
+        : m_styleSheetId(styleSheetId)
+        , m_ordinal(ordinal)
+    {
+    }
+
+    bool isEmpty() const { return m_styleSheetId.isEmpty(); }
+
+    const String& styleSheetId() const { return m_styleSheetId; }
+    unsigned ordinal() const { return m_ordinal; }
+
+    // ID type is either TypeBuilder::CSS::CSSStyleId or TypeBuilder::CSS::CSSRuleId.
+    template<typename ID>
+    PassRefPtr<ID> asProtocolValue() const
+    {
+        if (isEmpty())
+            return 0;
+
+        RefPtr<ID> result = ID::create()
+            .setStyleSheetId(m_styleSheetId)
+            .setOrdinal(m_ordinal);
+        return result.release();
+    }
+
+private:
+    String m_styleSheetId;
+    unsigned m_ordinal;
+};
+
+struct InspectorStyleProperty {
+    explicit InspectorStyleProperty(CSSPropertySourceData sourceData)
+        : sourceData(sourceData)
+        , hasSource(true)
+    {
+    }
+
+    InspectorStyleProperty(CSSPropertySourceData sourceData, bool hasSource)
+        : sourceData(sourceData)
+        , hasSource(hasSource)
+    {
+    }
+
+    void setRawTextFromStyleDeclaration(const String& styleDeclaration)
+    {
+        unsigned start = sourceData.range.start;
+        unsigned end = sourceData.range.end;
+        ASSERT(start < end);
+        ASSERT(end <= styleDeclaration.length());
+        rawText = styleDeclaration.substring(start, end - start);
+    }
+
+    bool hasRawText() const { return !rawText.isEmpty(); }
+
+    CSSPropertySourceData sourceData;
+    bool hasSource;
+    String rawText;
+};
+
+class InspectorStyle : public RefCounted<InspectorStyle> {
+public:
+    static PassRefPtr<InspectorStyle> create(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet);
+    virtual ~InspectorStyle();
+
+    CSSStyleDeclaration* cssStyle() const { return m_style.get(); }
+    PassRefPtr<TypeBuilder::CSS::CSSStyle> buildObjectForStyle() const;
+    PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> > buildArrayForComputedStyle() const;
+    bool setPropertyText(unsigned index, const String& text, bool overwrite, String* oldText, ExceptionCode&);
+    bool toggleProperty(unsigned index, bool disable, ExceptionCode&);
+    bool styleText(String* result) const;
+
+private:
+    InspectorStyle(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet);
+
+    void populateAllProperties(Vector<InspectorStyleProperty>& result) const;
+    PassRefPtr<TypeBuilder::CSS::CSSStyle> styleWithProperties() const;
+    PassRefPtr<CSSRuleSourceData> extractSourceData() const;
+    bool applyStyleText(const String&);
+    String shorthandValue(const String& shorthandProperty) const;
+    String shorthandPriority(const String& shorthandProperty) const;
+    Vector<String> longhandProperties(const String& shorthandProperty) const;
+    NewLineAndWhitespace& newLineAndWhitespaceDelimiters() const;
+    inline Document* ownerDocument() const;
+
+    InspectorCSSId m_styleId;
+    RefPtr<CSSStyleDeclaration> m_style;
+    InspectorStyleSheet* m_parentStyleSheet;
+    mutable std::pair<String, String> m_format;
+    mutable bool m_formatAcquired;
+};
+
+class InspectorStyleSheet : public RefCounted<InspectorStyleSheet> {
+public:
+    class Listener {
+    public:
+        Listener() { }
+        virtual ~Listener() { }
+        virtual void styleSheetChanged(InspectorStyleSheet*) = 0;
+    };
+
+    typedef HashMap<CSSStyleDeclaration*, RefPtr<InspectorStyle> > InspectorStyleMap;
+    static PassRefPtr<InspectorStyleSheet> create(InspectorPageAgent*, const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, TypeBuilder::CSS::StyleSheetOrigin::Enum, const String& documentURL, Listener*);
+    static String styleSheetURL(CSSStyleSheet* pageStyleSheet);
+
+    virtual ~InspectorStyleSheet();
+
+    String id() const { return m_id; }
+    String finalURL() const;
+    bool canBind() const { return m_origin != TypeBuilder::CSS::StyleSheetOrigin::User_agent && m_origin != TypeBuilder::CSS::StyleSheetOrigin::User; }
+    CSSStyleSheet* pageStyleSheet() const { return m_pageStyleSheet.get(); }
+    bool isReparsing() const { return m_isReparsing; }
+    void reparseStyleSheet(const String&);
+    bool setText(const String&, ExceptionCode&);
+    String ruleSelector(const InspectorCSSId&, ExceptionCode&);
+    bool setRuleSelector(const InspectorCSSId&, const String& selector, ExceptionCode&);
+    CSSStyleRule* addRule(const String& selector, ExceptionCode&);
+    bool deleteRule(const InspectorCSSId&, ExceptionCode&);
+    CSSStyleRule* ruleForId(const InspectorCSSId&) const;
+    PassRefPtr<TypeBuilder::CSS::CSSStyleSheetBody> buildObjectForStyleSheet();
+    PassRefPtr<TypeBuilder::CSS::CSSStyleSheetHeader> buildObjectForStyleSheetInfo();
+    PassRefPtr<TypeBuilder::CSS::CSSRule> buildObjectForRule(CSSStyleRule*);
+    PassRefPtr<TypeBuilder::CSS::CSSStyle> buildObjectForStyle(CSSStyleDeclaration*);
+    bool setStyleText(const InspectorCSSId&, const String& text, String* oldText, ExceptionCode&);
+    bool setPropertyText(const InspectorCSSId&, unsigned propertyIndex, const String& text, bool overwrite, String* oldPropertyText, ExceptionCode&);
+    bool toggleProperty(const InspectorCSSId&, unsigned propertyIndex, bool disable, ExceptionCode&);
+
+    virtual bool getText(String* result) const;
+    virtual CSSStyleDeclaration* styleForId(const InspectorCSSId&) const;
+    void fireStyleSheetChanged();
+
+    InspectorCSSId ruleId(CSSStyleRule*) const;
+    InspectorCSSId styleId(CSSStyleDeclaration* style) const { return ruleOrStyleId(style); }
+
+protected:
+    InspectorStyleSheet(InspectorPageAgent*, const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, TypeBuilder::CSS::StyleSheetOrigin::Enum, const String& documentURL, Listener*);
+
+    InspectorCSSId ruleOrStyleId(CSSStyleDeclaration* style) const;
+    virtual Document* ownerDocument() const;
+    virtual PassRefPtr<CSSRuleSourceData> ruleSourceDataFor(CSSStyleDeclaration* style) const;
+    virtual unsigned ruleIndexByStyle(CSSStyleDeclaration*) const;
+    virtual bool ensureParsedDataReady();
+    virtual PassRefPtr<InspectorStyle> inspectorStyleForId(const InspectorCSSId&);
+
+    // Also accessed by friend class InspectorStyle.
+    virtual bool setStyleText(CSSStyleDeclaration*, const String&);
+    virtual PassOwnPtr<Vector<size_t> > lineEndings() const;
+
+private:
+    typedef Vector<RefPtr<CSSStyleRule> > CSSStyleRuleVector;
+    friend class InspectorStyle;
+
+    static void collectFlatRules(PassRefPtr<CSSRuleList>, CSSStyleRuleVector* result);
+    bool checkPageStyleSheet(ExceptionCode&) const;
+    bool ensureText() const;
+    bool ensureSourceData();
+    void ensureFlatRules() const;
+    bool styleSheetTextWithChangedStyle(CSSStyleDeclaration*, const String& newStyleText, String* result);
+    void revalidateStyle(CSSStyleDeclaration*);
+    bool originalStyleSheetText(String* result) const;
+    bool resourceStyleSheetText(String* result) const;
+    bool inlineStyleSheetText(String* result) const;
+    PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > buildArrayForRuleList(CSSRuleList*);
+    PassRefPtr<TypeBuilder::CSS::SelectorList> buildObjectForSelectorList(CSSStyleRule*);
+
+    InspectorPageAgent* m_pageAgent;
+    String m_id;
+    RefPtr<CSSStyleSheet> m_pageStyleSheet;
+    TypeBuilder::CSS::StyleSheetOrigin::Enum m_origin;
+    String m_documentURL;
+    bool m_isRevalidating;
+    bool m_isReparsing;
+    ParsedStyleSheet* m_parsedStyleSheet;
+    mutable CSSStyleRuleVector m_flatRules;
+    Listener* m_listener;
+};
+
+class InspectorStyleSheetForInlineStyle : public InspectorStyleSheet {
+public:
+    static PassRefPtr<InspectorStyleSheetForInlineStyle> create(InspectorPageAgent*, const String& id, PassRefPtr<Element>, TypeBuilder::CSS::StyleSheetOrigin::Enum, Listener*);
+
+    void didModifyElementAttribute();
+    virtual bool getText(String* result) const;
+    virtual CSSStyleDeclaration* styleForId(const InspectorCSSId& id) const { ASSERT_UNUSED(id, !id.ordinal()); return inlineStyle(); }
+
+protected:
+    InspectorStyleSheetForInlineStyle(InspectorPageAgent*, const String& id, PassRefPtr<Element>, TypeBuilder::CSS::StyleSheetOrigin::Enum, Listener*);
+
+    virtual Document* ownerDocument() const;
+    virtual PassRefPtr<CSSRuleSourceData> ruleSourceDataFor(CSSStyleDeclaration* style) const { ASSERT_UNUSED(style, style == inlineStyle()); return m_ruleSourceData; }
+    virtual unsigned ruleIndexByStyle(CSSStyleDeclaration*) const { return 0; }
+    virtual bool ensureParsedDataReady();
+    virtual PassRefPtr<InspectorStyle> inspectorStyleForId(const InspectorCSSId&);
+
+    // Also accessed by friend class InspectorStyle.
+    virtual bool setStyleText(CSSStyleDeclaration*, const String&);
+    virtual PassOwnPtr<Vector<size_t> > lineEndings() const;
+
+private:
+    CSSStyleDeclaration* inlineStyle() const;
+    const String& elementStyleText() const;
+    PassRefPtr<CSSRuleSourceData> getStyleAttributeData() const;
+
+    RefPtr<Element> m_element;
+    RefPtr<CSSRuleSourceData> m_ruleSourceData;
+    RefPtr<InspectorStyle> m_inspectorStyle;
+
+    // Contains "style" attribute value.
+    mutable String m_styleText;
+    mutable bool m_isStyleTextValid;
+};
+
+
+} // namespace WebCore
+
+#endif // !defined(InspectorStyleSheet_h)
diff --git a/Source/core/inspector/InspectorStyleTextEditor.cpp b/Source/core/inspector/InspectorStyleTextEditor.cpp
new file mode 100644
index 0000000..f2701b2
--- /dev/null
+++ b/Source/core/inspector/InspectorStyleTextEditor.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2011, 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:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorStyleTextEditor.h"
+
+#include "core/css/CSSPropertySourceData.h"
+#include "core/html/parser/HTMLParserIdioms.h"
+#include "core/inspector/InspectorStyleSheet.h"
+
+namespace WebCore {
+
+InspectorStyleTextEditor::InspectorStyleTextEditor(Vector<InspectorStyleProperty>* allProperties, const String& styleText, const NewLineAndWhitespace& format)
+    : m_allProperties(allProperties)
+    , m_styleText(styleText)
+    , m_format(format)
+{
+}
+
+void InspectorStyleTextEditor::insertProperty(unsigned index, const String& propertyText, unsigned styleBodyLength)
+{
+    long propertyStart = 0;
+
+    bool insertLast = true;
+    if (index < m_allProperties->size()) {
+        const InspectorStyleProperty& property = m_allProperties->at(index);
+        if (property.hasSource) {
+            propertyStart = property.sourceData.range.start;
+            // If inserting before a disabled property, it should be shifted, too.
+            insertLast = false;
+        }
+    }
+
+    bool insertFirstInSource = !m_allProperties->size() || !m_allProperties->at(0).hasSource;
+    bool insertLastInSource = true;
+    for (unsigned i = index, size = m_allProperties->size(); i < size; ++i) {
+        const InspectorStyleProperty& property = m_allProperties->at(i);
+        if (property.hasSource) {
+            insertLastInSource = false;
+            break;
+        }
+    }
+
+    String textToSet = propertyText;
+
+    int formattingPrependOffset = 0;
+    if (insertLast && !insertFirstInSource) {
+        propertyStart = styleBodyLength;
+        if (propertyStart && textToSet.length()) {
+            const UChar* characters = m_styleText.characters();
+
+            long curPos = propertyStart - 1; // The last position of style declaration, since propertyStart points past one.
+            while (curPos && isHTMLSpace(characters[curPos]))
+                --curPos;
+            if (curPos) {
+                bool terminated = characters[curPos] == ';' || (characters[curPos] == '/' && characters[curPos - 1] == '*');
+                if (!terminated) {
+                    // Prepend a ";" to the property text if appending to a style declaration where
+                    // the last property has no trailing ";".
+                    textToSet.insert(";", 0);
+                    formattingPrependOffset = 1;
+                }
+            }
+        }
+    }
+
+    const String& formatLineFeed = m_format.first;
+    const String& formatPropertyPrefix = m_format.second;
+    if (insertLastInSource) {
+        long formatPropertyPrefixLength = formatPropertyPrefix.length();
+        if (!formattingPrependOffset && (propertyStart < formatPropertyPrefixLength || m_styleText.substring(propertyStart - formatPropertyPrefixLength, formatPropertyPrefixLength) != formatPropertyPrefix)) {
+            textToSet.insert(formatPropertyPrefix, formattingPrependOffset);
+            if (!propertyStart || !isHTMLLineBreak(m_styleText[propertyStart - 1]))
+                textToSet.insert(formatLineFeed, formattingPrependOffset);
+        }
+        if (!isHTMLLineBreak(m_styleText[propertyStart]))
+            textToSet.append(formatLineFeed);
+    } else {
+        String fullPrefix = formatLineFeed + formatPropertyPrefix;
+        long fullPrefixLength = fullPrefix.length();
+        textToSet.append(fullPrefix);
+        if (insertFirstInSource && (propertyStart < fullPrefixLength || m_styleText.substring(propertyStart - fullPrefixLength, fullPrefixLength) != fullPrefix))
+            textToSet.insert(fullPrefix, formattingPrependOffset);
+    }
+    m_styleText.insert(textToSet, propertyStart);
+}
+
+void InspectorStyleTextEditor::replaceProperty(unsigned index, const String& newText)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(index < m_allProperties->size());
+    internalReplaceProperty(m_allProperties->at(index), newText);
+}
+
+void InspectorStyleTextEditor::removeProperty(unsigned index)
+{
+    replaceProperty(index, "");
+}
+
+void InspectorStyleTextEditor::enableProperty(unsigned index)
+{
+    InspectorStyleProperty& disabledProperty = m_allProperties->at(index);
+    ASSERT(disabledProperty.sourceData.disabled);
+    internalReplaceProperty(disabledProperty, disabledProperty.rawText.substring(2, disabledProperty.rawText.length() - 4).stripWhiteSpace());
+}
+
+void InspectorStyleTextEditor::disableProperty(unsigned index)
+{
+    ASSERT(!m_allProperties->at(index).sourceData.disabled);
+
+    InspectorStyleProperty& property = m_allProperties->at(index);
+    property.setRawTextFromStyleDeclaration(m_styleText);
+    property.sourceData.disabled = true;
+
+    internalReplaceProperty(property, "/* " + property.rawText + " */");
+}
+
+void InspectorStyleTextEditor::internalReplaceProperty(const InspectorStyleProperty& property, const String& newText)
+{
+    const SourceRange& range = property.sourceData.range;
+    long replaceRangeStart = range.start;
+    long replaceRangeEnd = range.end;
+    const UChar* characters = m_styleText.characters();
+    long newTextLength = newText.length();
+    String finalNewText = newText;
+
+    // Removing a property - remove preceding prefix.
+    String fullPrefix = m_format.first + m_format.second;
+    long fullPrefixLength = fullPrefix.length();
+    if (!newTextLength && fullPrefixLength) {
+        if (replaceRangeStart >= fullPrefixLength && m_styleText.substring(replaceRangeStart - fullPrefixLength, fullPrefixLength) == fullPrefix)
+            replaceRangeStart -= fullPrefixLength;
+    } else if (newTextLength) {
+        if (isHTMLLineBreak(newText.characters()[newTextLength - 1])) {
+            // Coalesce newlines of the original and new property values (to avoid a lot of blank lines while incrementally applying property values).
+            bool foundNewline = false;
+            bool isLastNewline = false;
+            int i;
+            int textLength = m_styleText.length();
+            for (i = replaceRangeEnd; i < textLength && isSpaceOrNewline(characters[i]); ++i) {
+                isLastNewline = isHTMLLineBreak(characters[i]);
+                if (isLastNewline)
+                    foundNewline = true;
+                else if (foundNewline && !isLastNewline) {
+                    replaceRangeEnd = i;
+                    break;
+                }
+            }
+            if (foundNewline && isLastNewline)
+                replaceRangeEnd = i;
+        }
+
+        if (fullPrefixLength > replaceRangeStart || m_styleText.substring(replaceRangeStart - fullPrefixLength, fullPrefixLength) != fullPrefix)
+            finalNewText.insert(fullPrefix, 0);
+    }
+
+    int replacedLength = replaceRangeEnd - replaceRangeStart;
+    m_styleText.replace(replaceRangeStart, replacedLength, finalNewText);
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorStyleTextEditor.h b/Source/core/inspector/InspectorStyleTextEditor.h
new file mode 100644
index 0000000..5fdab78
--- /dev/null
+++ b/Source/core/inspector/InspectorStyleTextEditor.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011, 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:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#ifndef InspectorStyleTextEditor_h
+#define InspectorStyleTextEditor_h
+
+#include "core/css/CSSPropertySourceData.h"
+
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+
+struct InspectorStyleProperty;
+struct SourceRange;
+
+typedef std::pair<String, String> NewLineAndWhitespace;
+
+class InspectorStyleTextEditor {
+public:
+    InspectorStyleTextEditor(Vector<InspectorStyleProperty>* allProperties,const String& styleText, const NewLineAndWhitespace& format);
+    void insertProperty(unsigned index, const String& propertyText, unsigned styleBodyLength);
+    void replaceProperty(unsigned index, const String& newText);
+    void removeProperty(unsigned index);
+    void enableProperty(unsigned index);
+    void disableProperty(unsigned index);
+    const String& styleText() const { return m_styleText; }
+
+private:
+    void internalReplaceProperty(const InspectorStyleProperty&, const String& newText);
+
+    Vector<InspectorStyleProperty>* m_allProperties;
+    String m_styleText;
+    const std::pair<String, String> m_format;
+};
+
+
+} // namespace WebCore
+
+#endif // !defined(InspectorStyleTextEditor_h)
diff --git a/Source/core/inspector/InspectorTimelineAgent.cpp b/Source/core/inspector/InspectorTimelineAgent.cpp
new file mode 100644
index 0000000..bf18d07
--- /dev/null
+++ b/Source/core/inspector/InspectorTimelineAgent.cpp
@@ -0,0 +1,800 @@
+/*
+* Copyright (C) 2013 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.
+*/
+
+#include "config.h"
+#include "core/inspector/InspectorTimelineAgent.h"
+
+#include "InspectorFrontend.h"
+#include "core/dom/Event.h"
+#include "core/inspector/IdentifiersFactory.h"
+#include "core/inspector/InspectorClient.h"
+#include "core/inspector/InspectorCounters.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/InspectorMemoryAgent.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/inspector/TimelineRecordFactory.h"
+#include "core/inspector/TimelineTraceEventProcessor.h"
+#include "core/loader/DocumentLoader.h"
+#include "core/page/DOMWindow.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/platform/MemoryUsageSupport.h"
+#include "core/platform/graphics/IntRect.h"
+#include "core/platform/network/ResourceRequest.h"
+#include "core/platform/network/ResourceResponse.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/RenderView.h"
+#include "core/xml/XMLHttpRequest.h"
+
+#include <wtf/CurrentTime.h>
+
+namespace WebCore {
+
+namespace TimelineAgentState {
+static const char timelineAgentEnabled[] = "timelineAgentEnabled";
+static const char timelineMaxCallStackDepth[] = "timelineMaxCallStackDepth";
+static const char includeDomCounters[] = "includeDomCounters";
+static const char includeNativeMemoryStatistics[] = "includeNativeMemoryStatistics";
+}
+
+// Must be kept in sync with WebInspector.TimelineModel.RecordType in TimelineModel.js
+namespace TimelineRecordType {
+static const char Program[] = "Program";
+
+static const char EventDispatch[] = "EventDispatch";
+static const char BeginFrame[] = "BeginFrame";
+static const char ScheduleStyleRecalculation[] = "ScheduleStyleRecalculation";
+static const char RecalculateStyles[] = "RecalculateStyles";
+static const char InvalidateLayout[] = "InvalidateLayout";
+static const char Layout[] = "Layout";
+static const char Paint[] = "Paint";
+static const char ScrollLayer[] = "ScrollLayer";
+static const char ResizeImage[] = "ResizeImage";
+static const char CompositeLayers[] = "CompositeLayers";
+
+static const char ParseHTML[] = "ParseHTML";
+
+static const char TimerInstall[] = "TimerInstall";
+static const char TimerRemove[] = "TimerRemove";
+static const char TimerFire[] = "TimerFire";
+
+static const char EvaluateScript[] = "EvaluateScript";
+
+static const char MarkLoad[] = "MarkLoad";
+static const char MarkDOMContent[] = "MarkDOMContent";
+
+static const char TimeStamp[] = "TimeStamp";
+static const char Time[] = "Time";
+static const char TimeEnd[] = "TimeEnd";
+
+static const char ScheduleResourceRequest[] = "ScheduleResourceRequest";
+static const char ResourceSendRequest[] = "ResourceSendRequest";
+static const char ResourceReceiveResponse[] = "ResourceReceiveResponse";
+static const char ResourceReceivedData[] = "ResourceReceivedData";
+static const char ResourceFinish[] = "ResourceFinish";
+
+static const char XHRReadyStateChange[] = "XHRReadyStateChange";
+static const char XHRLoad[] = "XHRLoad";
+
+static const char FunctionCall[] = "FunctionCall";
+static const char GCEvent[] = "GCEvent";
+
+static const char RequestAnimationFrame[] = "RequestAnimationFrame";
+static const char CancelAnimationFrame[] = "CancelAnimationFrame";
+static const char FireAnimationFrame[] = "FireAnimationFrame";
+
+static const char WebSocketCreate[] = "WebSocketCreate";
+static const char WebSocketSendHandshakeRequest[] = "WebSocketSendHandshakeRequest";
+static const char WebSocketReceiveHandshakeResponse[] = "WebSocketReceiveHandshakeResponse";
+static const char WebSocketDestroy[] = "WebSocketDestroy";
+
+// Event names visible to other modules.
+const char DecodeImage[] = "DecodeImage";
+const char Rasterize[] = "Rasterize";
+}
+
+static Frame* frameForScriptExecutionContext(ScriptExecutionContext* context)
+{
+    Frame* frame = 0;
+    if (context->isDocument())
+        frame = toDocument(context)->frame();
+    return frame;
+}
+
+static bool eventHasListeners(const AtomicString& eventType, DOMWindow* window, Node* node, const EventPath& eventPath)
+{
+    if (window && window->hasEventListeners(eventType))
+        return true;
+
+    if (node->hasEventListeners(eventType))
+        return true;
+
+    for (size_t i = 0; i < eventPath.size(); i++) {
+        if (eventPath[i]->node()->hasEventListeners(eventType))
+            return true;
+    }
+
+    return false;
+}
+
+void TimelineTimeConverter::reset()
+{
+    m_startOffset = monotonicallyIncreasingTime() - currentTime();
+}
+
+void InspectorTimelineAgent::pushGCEventRecords()
+{
+    if (!m_gcEvents.size())
+        return;
+
+    GCEvents events = m_gcEvents;
+    m_gcEvents.clear();
+    for (GCEvents::iterator i = events.begin(); i != events.end(); ++i) {
+        RefPtr<InspectorObject> record = TimelineRecordFactory::createGenericRecord(m_timeConverter.fromMonotonicallyIncreasingTime(i->startTime), m_maxCallStackDepth);
+        record->setObject("data", TimelineRecordFactory::createGCEventData(i->collectedBytes));
+        record->setNumber("endTime", m_timeConverter.fromMonotonicallyIncreasingTime(i->endTime));
+        addRecordToTimeline(record.release(), TimelineRecordType::GCEvent);
+    }
+}
+
+void InspectorTimelineAgent::didGC(double startTime, double endTime, size_t collectedBytesCount)
+{
+    m_gcEvents.append(GCEvent(startTime, endTime, collectedBytesCount));
+}
+
+InspectorTimelineAgent::~InspectorTimelineAgent()
+{
+    clearFrontend();
+}
+
+void InspectorTimelineAgent::setFrontend(InspectorFrontend* frontend)
+{
+    m_frontend = frontend->timeline();
+}
+
+void InspectorTimelineAgent::clearFrontend()
+{
+    ErrorString error;
+    stop(&error);
+    m_frontend = 0;
+}
+
+void InspectorTimelineAgent::restore()
+{
+    if (m_state->getBoolean(TimelineAgentState::timelineAgentEnabled)) {
+        m_maxCallStackDepth = m_state->getLong(TimelineAgentState::timelineMaxCallStackDepth);
+        ErrorString error;
+        bool includeDomCounters = m_state->getBoolean(TimelineAgentState::includeDomCounters);
+        bool includeNativeMemoryStatistics = m_state->getBoolean(TimelineAgentState::includeNativeMemoryStatistics);
+        start(&error, &m_maxCallStackDepth, &includeDomCounters, &includeNativeMemoryStatistics);
+    }
+}
+
+void InspectorTimelineAgent::start(ErrorString*, const int* maxCallStackDepth, const bool* includeDomCounters, const bool* includeNativeMemoryStatistics)
+{
+    if (!m_frontend)
+        return;
+
+    if (maxCallStackDepth && *maxCallStackDepth >= 0)
+        m_maxCallStackDepth = *maxCallStackDepth;
+    else
+        m_maxCallStackDepth = 5;
+    m_state->setLong(TimelineAgentState::timelineMaxCallStackDepth, m_maxCallStackDepth);
+    m_state->setBoolean(TimelineAgentState::includeDomCounters, includeDomCounters && *includeDomCounters);
+    m_state->setBoolean(TimelineAgentState::includeNativeMemoryStatistics, includeNativeMemoryStatistics && *includeNativeMemoryStatistics);
+    m_timeConverter.reset();
+
+    m_instrumentingAgents->setInspectorTimelineAgent(this);
+    ScriptGCEvent::addEventListener(this);
+    m_state->setBoolean(TimelineAgentState::timelineAgentEnabled, true);
+    if (m_client && m_pageAgent)
+        m_traceEventProcessor = adoptRef(new TimelineTraceEventProcessor(m_weakFactory.createWeakPtr(), m_client));
+}
+
+void InspectorTimelineAgent::stop(ErrorString*)
+{
+    if (!m_state->getBoolean(TimelineAgentState::timelineAgentEnabled))
+        return;
+
+    m_traceEventProcessor->shutdown();
+    m_traceEventProcessor.clear();
+    m_weakFactory.revokeAll();
+    m_instrumentingAgents->setInspectorTimelineAgent(0);
+    ScriptGCEvent::removeEventListener(this);
+
+    clearRecordStack();
+    m_gcEvents.clear();
+
+    m_state->setBoolean(TimelineAgentState::timelineAgentEnabled, false);
+}
+
+void InspectorTimelineAgent::didBeginFrame()
+{
+    TRACE_EVENT_INSTANT0("webkit", InstrumentationEvents::BeginFrame);
+    m_pendingFrameRecord = TimelineRecordFactory::createGenericRecord(timestamp(), 0);
+}
+
+void InspectorTimelineAgent::didCancelFrame()
+{
+    m_pendingFrameRecord.clear();
+}
+
+bool InspectorTimelineAgent::willCallFunction(ScriptExecutionContext* context, const String& scriptName, int scriptLine)
+{
+    pushCurrentRecord(TimelineRecordFactory::createFunctionCallData(scriptName, scriptLine), TimelineRecordType::FunctionCall, true, frameForScriptExecutionContext(context));
+    return true;
+}
+
+void InspectorTimelineAgent::didCallFunction()
+{
+    didCompleteCurrentRecord(TimelineRecordType::FunctionCall);
+}
+
+bool InspectorTimelineAgent::willDispatchEvent(Document* document, const Event& event, DOMWindow* window, Node* node, const EventPath& eventPath)
+{
+    if (!eventHasListeners(event.type(), window, node, eventPath))
+       return false;
+
+    pushCurrentRecord(TimelineRecordFactory::createEventDispatchData(event), TimelineRecordType::EventDispatch, false, document->frame());
+    return true;
+}
+
+bool InspectorTimelineAgent::willDispatchEventOnWindow(const Event& event, DOMWindow* window)
+{
+    if (!window->hasEventListeners(event.type()))
+        return false;
+    pushCurrentRecord(TimelineRecordFactory::createEventDispatchData(event), TimelineRecordType::EventDispatch, false, window->frame());
+    return true;
+}
+
+void InspectorTimelineAgent::didDispatchEvent()
+{
+    didCompleteCurrentRecord(TimelineRecordType::EventDispatch);
+}
+
+void InspectorTimelineAgent::didDispatchEventOnWindow()
+{
+    didDispatchEvent();
+}
+
+void InspectorTimelineAgent::didInvalidateLayout(Frame* frame)
+{
+    appendRecord(InspectorObject::create(), TimelineRecordType::InvalidateLayout, true, frame);
+}
+
+bool InspectorTimelineAgent::willLayout(Frame* frame)
+{
+    RenderObject* root = frame->view()->layoutRoot();
+    bool partialLayout = !!root;
+
+    if (!partialLayout)
+        root = frame->contentRenderer();
+
+    unsigned dirtyObjects = 0;
+    unsigned totalObjects = 0;
+    for (RenderObject* o = root; o; o = o->nextInPreOrder(root)) {
+        ++totalObjects;
+        if (o->needsLayout())
+            ++dirtyObjects;
+    }
+    pushCurrentRecord(TimelineRecordFactory::createLayoutData(dirtyObjects, totalObjects, partialLayout), TimelineRecordType::Layout, true, frame);
+    return true;
+}
+
+void InspectorTimelineAgent::didLayout(RenderObject* root)
+{
+    if (m_recordStack.isEmpty())
+        return;
+    TimelineRecordEntry& entry = m_recordStack.last();
+    ASSERT(entry.type == TimelineRecordType::Layout);
+    Vector<FloatQuad> quads;
+    root->absoluteQuads(quads);
+    if (quads.size() >= 1)
+        TimelineRecordFactory::appendLayoutRoot(entry.data.get(), quads[0]);
+    else
+        ASSERT_NOT_REACHED();
+    didCompleteCurrentRecord(TimelineRecordType::Layout);
+}
+
+void InspectorTimelineAgent::didScheduleStyleRecalculation(Document* document)
+{
+    appendRecord(InspectorObject::create(), TimelineRecordType::ScheduleStyleRecalculation, true, document->frame());
+}
+
+bool InspectorTimelineAgent::willRecalculateStyle(Document* document)
+{
+    pushCurrentRecord(InspectorObject::create(), TimelineRecordType::RecalculateStyles, true, document->frame());
+    ASSERT(!m_styleRecalcElementCounter);
+    return true;
+}
+
+void InspectorTimelineAgent::didRecalculateStyle()
+{
+    if (m_recordStack.isEmpty())
+        return;
+    TimelineRecordEntry& entry = m_recordStack.last();
+    ASSERT(entry.type == TimelineRecordType::RecalculateStyles);
+    TimelineRecordFactory::appendStyleRecalcDetails(entry.data.get(), m_styleRecalcElementCounter);
+    m_styleRecalcElementCounter = 0;
+    didCompleteCurrentRecord(TimelineRecordType::RecalculateStyles);
+}
+
+void InspectorTimelineAgent::didRecalculateStyleForElement()
+{
+    ++m_styleRecalcElementCounter;
+}
+
+void InspectorTimelineAgent::willPaint(Frame* frame)
+{
+    pushCurrentRecord(InspectorObject::create(), TimelineRecordType::Paint, true, frame, true);
+}
+
+void InspectorTimelineAgent::didPaint(RenderObject* renderer, GraphicsContext*, const LayoutRect& clipRect)
+{
+    TimelineRecordEntry& entry = m_recordStack.last();
+    ASSERT(entry.type == TimelineRecordType::Paint);
+    FloatQuad quad;
+    localToPageQuad(*renderer, clipRect, &quad);
+    entry.data = TimelineRecordFactory::createPaintData(quad);
+    didCompleteCurrentRecord(TimelineRecordType::Paint);
+}
+
+void InspectorTimelineAgent::willScrollLayer(Frame* frame)
+{
+    pushCurrentRecord(InspectorObject::create(), TimelineRecordType::ScrollLayer, false, frame);
+}
+
+void InspectorTimelineAgent::didScrollLayer()
+{
+    didCompleteCurrentRecord(TimelineRecordType::ScrollLayer);
+}
+
+void InspectorTimelineAgent::willDecodeImage(const String& imageType)
+{
+    pushCurrentRecord(TimelineRecordFactory::createDecodeImageData(imageType), TimelineRecordType::DecodeImage, true, 0);
+}
+
+void InspectorTimelineAgent::didDecodeImage()
+{
+    didCompleteCurrentRecord(TimelineRecordType::DecodeImage);
+}
+
+void InspectorTimelineAgent::willResizeImage(bool shouldCache)
+{
+    pushCurrentRecord(TimelineRecordFactory::createResizeImageData(shouldCache), TimelineRecordType::ResizeImage, true, 0);
+}
+
+void InspectorTimelineAgent::didResizeImage()
+{
+    didCompleteCurrentRecord(TimelineRecordType::ResizeImage);
+}
+
+void InspectorTimelineAgent::willComposite()
+{
+    pushCurrentRecord(InspectorObject::create(), TimelineRecordType::CompositeLayers, false, 0);
+}
+
+void InspectorTimelineAgent::didComposite()
+{
+    didCompleteCurrentRecord(TimelineRecordType::CompositeLayers);
+}
+
+bool InspectorTimelineAgent::willWriteHTML(Document* document, unsigned startLine)
+{
+    pushCurrentRecord(TimelineRecordFactory::createParseHTMLData(startLine), TimelineRecordType::ParseHTML, true, document->frame());
+    return true;
+}
+
+void InspectorTimelineAgent::didWriteHTML(unsigned endLine)
+{
+    if (!m_recordStack.isEmpty()) {
+        TimelineRecordEntry entry = m_recordStack.last();
+        entry.data->setNumber("endLine", endLine);
+        didCompleteCurrentRecord(TimelineRecordType::ParseHTML);
+    }
+}
+
+void InspectorTimelineAgent::didInstallTimer(ScriptExecutionContext* context, int timerId, int timeout, bool singleShot)
+{
+    appendRecord(TimelineRecordFactory::createTimerInstallData(timerId, timeout, singleShot), TimelineRecordType::TimerInstall, true, frameForScriptExecutionContext(context));
+}
+
+void InspectorTimelineAgent::didRemoveTimer(ScriptExecutionContext* context, int timerId)
+{
+    appendRecord(TimelineRecordFactory::createGenericTimerData(timerId), TimelineRecordType::TimerRemove, true, frameForScriptExecutionContext(context));
+}
+
+bool InspectorTimelineAgent::willFireTimer(ScriptExecutionContext* context, int timerId)
+{
+    pushCurrentRecord(TimelineRecordFactory::createGenericTimerData(timerId), TimelineRecordType::TimerFire, false, frameForScriptExecutionContext(context));
+    return true;
+}
+
+void InspectorTimelineAgent::didFireTimer()
+{
+    didCompleteCurrentRecord(TimelineRecordType::TimerFire);
+}
+
+bool InspectorTimelineAgent::willDispatchXHRReadyStateChangeEvent(ScriptExecutionContext* context, XMLHttpRequest* request)
+{
+    if (!request->hasEventListeners(eventNames().readystatechangeEvent))
+        return false;
+    pushCurrentRecord(TimelineRecordFactory::createXHRReadyStateChangeData(request->url().string(), request->readyState()), TimelineRecordType::XHRReadyStateChange, false, frameForScriptExecutionContext(context));
+    return true;
+}
+
+void InspectorTimelineAgent::didDispatchXHRReadyStateChangeEvent()
+{
+    didCompleteCurrentRecord(TimelineRecordType::XHRReadyStateChange);
+}
+
+bool InspectorTimelineAgent::willDispatchXHRLoadEvent(ScriptExecutionContext* context, XMLHttpRequest* request)
+{
+    if (!request->hasEventListeners(eventNames().loadEvent))
+        return false;
+    pushCurrentRecord(TimelineRecordFactory::createXHRLoadData(request->url()), TimelineRecordType::XHRLoad, true, frameForScriptExecutionContext(context));
+    return true;
+}
+
+void InspectorTimelineAgent::didDispatchXHRLoadEvent()
+{
+    didCompleteCurrentRecord(TimelineRecordType::XHRLoad);
+}
+
+bool InspectorTimelineAgent::willEvaluateScript(Frame* frame, const String& url, int lineNumber)
+{
+    pushCurrentRecord(TimelineRecordFactory::createEvaluateScriptData(url, lineNumber), TimelineRecordType::EvaluateScript, true, frame);
+    return true;
+}
+
+void InspectorTimelineAgent::didEvaluateScript()
+{
+    didCompleteCurrentRecord(TimelineRecordType::EvaluateScript);
+}
+
+void InspectorTimelineAgent::didScheduleResourceRequest(Document* document, const String& url)
+{
+    appendRecord(TimelineRecordFactory::createScheduleResourceRequestData(url), TimelineRecordType::ScheduleResourceRequest, true, document->frame());
+}
+
+void InspectorTimelineAgent::willSendResourceRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request, const ResourceResponse&)
+{
+    String requestId = IdentifiersFactory::requestId(identifier);
+    appendRecord(TimelineRecordFactory::createResourceSendRequestData(requestId, request), TimelineRecordType::ResourceSendRequest, true, loader->frame());
+}
+
+bool InspectorTimelineAgent::willReceiveResourceData(Frame* frame, unsigned long identifier, int length)
+{
+    String requestId = IdentifiersFactory::requestId(identifier);
+    pushCurrentRecord(TimelineRecordFactory::createReceiveResourceData(requestId, length), TimelineRecordType::ResourceReceivedData, false, frame);
+    return true;
+}
+
+void InspectorTimelineAgent::didReceiveResourceData()
+{
+    didCompleteCurrentRecord(TimelineRecordType::ResourceReceivedData);
+}
+
+bool InspectorTimelineAgent::willReceiveResourceResponse(Frame* frame, unsigned long identifier, const ResourceResponse& response)
+{
+    String requestId = IdentifiersFactory::requestId(identifier);
+    pushCurrentRecord(TimelineRecordFactory::createResourceReceiveResponseData(requestId, response), TimelineRecordType::ResourceReceiveResponse, false, frame);
+    return true;
+}
+
+void InspectorTimelineAgent::didReceiveResourceResponse(unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response, ResourceLoader* resourceLoader)
+{
+    didCompleteCurrentRecord(TimelineRecordType::ResourceReceiveResponse);
+}
+
+void InspectorTimelineAgent::didFinishLoadingResource(unsigned long identifier, bool didFail, double finishTime, Frame* frame)
+{
+    appendRecord(TimelineRecordFactory::createResourceFinishData(IdentifiersFactory::requestId(identifier), didFail, finishTime * 1000), TimelineRecordType::ResourceFinish, false, frame);
+}
+
+void InspectorTimelineAgent::didFailLoading(unsigned long identifier, DocumentLoader* loader, const ResourceError& error)
+{
+    didFinishLoadingResource(identifier, true, 0, loader->frame());
+}
+
+void InspectorTimelineAgent::didTimeStamp(Frame* frame, const String& message)
+{
+    appendRecord(TimelineRecordFactory::createTimeStampData(message), TimelineRecordType::TimeStamp, true, frame);
+}
+
+void InspectorTimelineAgent::time(Frame* frame, const String& message)
+{
+    appendRecord(TimelineRecordFactory::createTimeStampData(message), TimelineRecordType::Time, true, frame);
+}
+
+void InspectorTimelineAgent::timeEnd(Frame* frame, const String& message)
+{
+    appendRecord(TimelineRecordFactory::createTimeStampData(message), TimelineRecordType::TimeEnd, true, frame);
+}
+
+void InspectorTimelineAgent::didMarkDOMContentEvent(Frame* frame)
+{
+    bool isMainFrame = frame && m_pageAgent && (frame == m_pageAgent->mainFrame());
+    appendRecord(TimelineRecordFactory::createMarkData(isMainFrame), TimelineRecordType::MarkDOMContent, false, frame);
+}
+
+void InspectorTimelineAgent::didMarkLoadEvent(Frame* frame)
+{
+    bool isMainFrame = frame && m_pageAgent && (frame == m_pageAgent->mainFrame());
+    appendRecord(TimelineRecordFactory::createMarkData(isMainFrame), TimelineRecordType::MarkLoad, false, frame);
+}
+
+void InspectorTimelineAgent::didCommitLoad()
+{
+    clearRecordStack();
+}
+
+void InspectorTimelineAgent::didRequestAnimationFrame(Document* document, int callbackId)
+{
+    appendRecord(TimelineRecordFactory::createAnimationFrameData(callbackId), TimelineRecordType::RequestAnimationFrame, true, document->frame());
+}
+
+void InspectorTimelineAgent::didCancelAnimationFrame(Document* document, int callbackId)
+{
+    appendRecord(TimelineRecordFactory::createAnimationFrameData(callbackId), TimelineRecordType::CancelAnimationFrame, true, document->frame());
+}
+
+bool InspectorTimelineAgent::willFireAnimationFrame(Document* document, int callbackId)
+{
+    pushCurrentRecord(TimelineRecordFactory::createAnimationFrameData(callbackId), TimelineRecordType::FireAnimationFrame, false, document->frame());
+    return true;
+}
+
+void InspectorTimelineAgent::didFireAnimationFrame()
+{
+    didCompleteCurrentRecord(TimelineRecordType::FireAnimationFrame);
+}
+
+void InspectorTimelineAgent::willProcessTask()
+{
+    pushCurrentRecord(InspectorObject::create(), TimelineRecordType::Program, false, 0);
+}
+
+void InspectorTimelineAgent::didProcessTask()
+{
+    didCompleteCurrentRecord(TimelineRecordType::Program);
+}
+
+void InspectorTimelineAgent::didCreateWebSocket(Document* document, unsigned long identifier, const KURL& url, const String& protocol)
+{
+    appendRecord(TimelineRecordFactory::createWebSocketCreateData(identifier, url, protocol), TimelineRecordType::WebSocketCreate, true, document->frame());
+}
+
+void InspectorTimelineAgent::willSendWebSocketHandshakeRequest(Document* document, unsigned long identifier, const WebSocketHandshakeRequest&)
+{
+    appendRecord(TimelineRecordFactory::createGenericWebSocketData(identifier), TimelineRecordType::WebSocketSendHandshakeRequest, true, document->frame());
+}
+
+void InspectorTimelineAgent::didReceiveWebSocketHandshakeResponse(Document* document, unsigned long identifier, const WebSocketHandshakeResponse&)
+{
+    appendRecord(TimelineRecordFactory::createGenericWebSocketData(identifier), TimelineRecordType::WebSocketReceiveHandshakeResponse, false, document->frame());
+}
+
+void InspectorTimelineAgent::didCloseWebSocket(Document* document, unsigned long identifier)
+{
+    appendRecord(TimelineRecordFactory::createGenericWebSocketData(identifier), TimelineRecordType::WebSocketDestroy, true, document->frame());
+}
+
+void InspectorTimelineAgent::addRecordToTimeline(PassRefPtr<InspectorObject> record, const String& type)
+{
+    commitFrameRecord();
+    innerAddRecordToTimeline(record, type);
+}
+
+void InspectorTimelineAgent::innerAddRecordToTimeline(PassRefPtr<InspectorObject> prpRecord, const String& type)
+{
+    prpRecord->setString("type", type);
+    RefPtr<TypeBuilder::Timeline::TimelineEvent> record = TypeBuilder::Timeline::TimelineEvent::runtimeCast(prpRecord);
+    if (type == TimelineRecordType::Program)
+        setNativeHeapStatistics(record.get());
+    else
+        setDOMCounters(record.get());
+
+    if (m_recordStack.isEmpty())
+        sendEvent(record.release());
+    else {
+        TimelineRecordEntry parent = m_recordStack.last();
+        parent.children->pushObject(record.release());
+    }
+}
+
+static size_t getUsedHeapSize()
+{
+    HeapInfo info;
+    ScriptGCEvent::getHeapSize(info);
+    return info.usedJSHeapSize;
+}
+
+void InspectorTimelineAgent::setDOMCounters(TypeBuilder::Timeline::TimelineEvent* record)
+{
+    record->setUsedHeapSize(getUsedHeapSize());
+
+    if (m_state->getBoolean(TimelineAgentState::includeDomCounters)) {
+        int documentCount = 0;
+        int nodeCount = 0;
+        if (m_inspectorType == PageInspector) {
+            documentCount = InspectorCounters::counterValue(InspectorCounters::DocumentCounter);
+            nodeCount = InspectorCounters::counterValue(InspectorCounters::NodeCounter);
+        }
+        int listenerCount = ThreadLocalInspectorCounters::current().counterValue(ThreadLocalInspectorCounters::JSEventListenerCounter);
+        RefPtr<TypeBuilder::Timeline::DOMCounters> counters = TypeBuilder::Timeline::DOMCounters::create()
+            .setDocuments(documentCount)
+            .setNodes(nodeCount)
+            .setJsEventListeners(listenerCount);
+        record->setCounters(counters.release());
+    }
+}
+
+void InspectorTimelineAgent::setNativeHeapStatistics(TypeBuilder::Timeline::TimelineEvent* record)
+{
+    if (!m_memoryAgent)
+        return;
+    if (!m_state->getBoolean(TimelineAgentState::includeNativeMemoryStatistics))
+        return;
+    HashMap<String, size_t> map;
+    m_memoryAgent->getProcessMemoryDistributionMap(&map);
+    RefPtr<InspectorObject> stats = InspectorObject::create();
+    for (HashMap<String, size_t>::iterator it = map.begin(); it != map.end(); ++it)
+        stats->setNumber(it->key, it->value);
+    size_t privateBytes = 0;
+    size_t sharedBytes = 0;
+    MemoryUsageSupport::processMemorySizesInBytes(&privateBytes, &sharedBytes);
+    stats->setNumber("PrivateBytes", privateBytes);
+    record->setNativeHeapStatistics(stats.release());
+}
+
+void InspectorTimelineAgent::setFrameIdentifier(InspectorObject* record, Frame* frame)
+{
+    if (!frame || !m_pageAgent)
+        return;
+    String frameId;
+    if (frame && m_pageAgent)
+        frameId = m_pageAgent->frameId(frame);
+    record->setString("frameId", frameId);
+}
+
+void InspectorTimelineAgent::didCompleteCurrentRecord(const String& type)
+{
+    // An empty stack could merely mean that the timeline agent was turned on in the middle of
+    // an event.  Don't treat as an error.
+    if (!m_recordStack.isEmpty()) {
+        if (m_platformInstrumentationClientInstalledAtStackDepth == m_recordStack.size()) {
+            m_platformInstrumentationClientInstalledAtStackDepth = 0;
+            PlatformInstrumentation::setClient(0);
+        }
+
+        pushGCEventRecords();
+        TimelineRecordEntry entry = m_recordStack.last();
+        m_recordStack.removeLast();
+        ASSERT(entry.type == type);
+        entry.record->setObject("data", entry.data);
+        entry.record->setArray("children", entry.children);
+        entry.record->setNumber("endTime", timestamp());
+        size_t usedHeapSizeDelta = getUsedHeapSize() - entry.usedHeapSizeAtStart;
+        if (usedHeapSizeDelta)
+            entry.record->setNumber("usedHeapSizeDelta", usedHeapSizeDelta);
+        addRecordToTimeline(entry.record, type);
+    }
+}
+
+InspectorTimelineAgent::InspectorTimelineAgent(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorMemoryAgent* memoryAgent, InspectorCompositeState* state, InspectorType type, InspectorClient* client)
+    : InspectorBaseAgent<InspectorTimelineAgent>("Timeline", instrumentingAgents, state)
+    , m_pageAgent(pageAgent)
+    , m_memoryAgent(memoryAgent)
+    , m_frontend(0)
+    , m_id(1)
+    , m_maxCallStackDepth(5)
+    , m_platformInstrumentationClientInstalledAtStackDepth(0)
+    , m_inspectorType(type)
+    , m_client(client)
+    , m_weakFactory(this)
+    , m_styleRecalcElementCounter(0)
+{
+}
+
+void InspectorTimelineAgent::appendRecord(PassRefPtr<InspectorObject> data, const String& type, bool captureCallStack, Frame* frame)
+{
+    pushGCEventRecords();
+    RefPtr<InspectorObject> record = TimelineRecordFactory::createGenericRecord(timestamp(), captureCallStack ? m_maxCallStackDepth : 0);
+    record->setObject("data", data);
+    setFrameIdentifier(record.get(), frame);
+    addRecordToTimeline(record.release(), type);
+}
+
+void InspectorTimelineAgent::sendEvent(PassRefPtr<InspectorObject> event)
+{
+    // FIXME: runtimeCast is a hack. We do it because we can't build TimelineEvent directly now.
+    RefPtr<TypeBuilder::Timeline::TimelineEvent> recordChecked = TypeBuilder::Timeline::TimelineEvent::runtimeCast(event);
+    m_frontend->eventRecorded(recordChecked.release());
+}
+
+void InspectorTimelineAgent::pushCurrentRecord(PassRefPtr<InspectorObject> data, const String& type, bool captureCallStack, Frame* frame, bool hasLowLevelDetails)
+{
+    pushGCEventRecords();
+    commitFrameRecord();
+    RefPtr<InspectorObject> record = TimelineRecordFactory::createGenericRecord(timestamp(), captureCallStack ? m_maxCallStackDepth : 0);
+    setFrameIdentifier(record.get(), frame);
+    m_recordStack.append(TimelineRecordEntry(record.release(), data, InspectorArray::create(), type, getUsedHeapSize()));
+    if (hasLowLevelDetails && !m_platformInstrumentationClientInstalledAtStackDepth && !PlatformInstrumentation::hasClient()) {
+        m_platformInstrumentationClientInstalledAtStackDepth = m_recordStack.size();
+        PlatformInstrumentation::setClient(this);
+    }
+}
+
+void InspectorTimelineAgent::commitFrameRecord()
+{
+    if (!m_pendingFrameRecord)
+        return;
+    
+    m_pendingFrameRecord->setObject("data", InspectorObject::create());
+    innerAddRecordToTimeline(m_pendingFrameRecord.release(), TimelineRecordType::BeginFrame);
+}
+
+void InspectorTimelineAgent::clearRecordStack()
+{
+    if (m_platformInstrumentationClientInstalledAtStackDepth) {
+        m_platformInstrumentationClientInstalledAtStackDepth = 0;
+        PlatformInstrumentation::setClient(0);
+    }
+    m_pendingFrameRecord.clear();
+    m_recordStack.clear();
+    m_id++;
+}
+
+void InspectorTimelineAgent::localToPageQuad(const RenderObject& renderer, const LayoutRect& rect, FloatQuad* quad)
+{
+    Frame* frame = renderer.frame();
+    FrameView* view = frame->view();
+    FloatQuad absolute = renderer.localToAbsoluteQuad(FloatQuad(rect));
+    quad->setP1(view->contentsToRootView(roundedIntPoint(absolute.p1())));
+    quad->setP2(view->contentsToRootView(roundedIntPoint(absolute.p2())));
+    quad->setP3(view->contentsToRootView(roundedIntPoint(absolute.p3())));
+    quad->setP4(view->contentsToRootView(roundedIntPoint(absolute.p4())));
+}
+
+double InspectorTimelineAgent::timestamp()
+{
+    return m_timeConverter.fromMonotonicallyIncreasingTime(WTF::monotonicallyIncreasingTime());
+}
+
+Page* InspectorTimelineAgent::page()
+{
+    return m_pageAgent ? m_pageAgent->page() : 0;
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/InspectorTimelineAgent.h b/Source/core/inspector/InspectorTimelineAgent.h
new file mode 100644
index 0000000..62d0de9
--- /dev/null
+++ b/Source/core/inspector/InspectorTimelineAgent.h
@@ -0,0 +1,281 @@
+/*
+* 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.
+*/
+
+#ifndef InspectorTimelineAgent_h
+#define InspectorTimelineAgent_h
+
+
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptGCEvent.h"
+#include "core/dom/EventContext.h"
+#include "core/inspector/InspectorBaseAgent.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/ScriptGCEventListener.h"
+#include "core/platform/PlatformInstrumentation.h"
+#include "core/platform/graphics/LayoutRect.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+class DOMWindow;
+class Document;
+class DocumentLoader;
+class Event;
+class FloatQuad;
+class Frame;
+class GraphicsContext;
+class InspectorClient;
+class InspectorFrontend;
+class InspectorMemoryAgent;
+class InspectorPageAgent;
+class InspectorState;
+class InstrumentingAgents;
+class IntRect;
+class KURL;
+class Node;
+class Page;
+class RenderObject;
+class ResourceError;
+class ResourceLoader;
+class ResourceRequest;
+class ResourceResponse;
+class ScriptExecutionContext;
+class TimelineTraceEventProcessor;
+class WebSocketHandshakeRequest;
+class WebSocketHandshakeResponse;
+class XMLHttpRequest;
+
+typedef String ErrorString;
+
+namespace TimelineRecordType {
+extern const char DecodeImage[];
+extern const char Rasterize[];
+};
+
+class TimelineTimeConverter {
+public:
+    TimelineTimeConverter()
+        : m_startOffset(0)
+    {
+    }
+    double fromMonotonicallyIncreasingTime(double time) const  { return (time - m_startOffset) * 1000.0; }
+    void reset();
+
+private:
+    double m_startOffset;
+};
+
+class InspectorTimelineAgent
+    : public InspectorBaseAgent<InspectorTimelineAgent>,
+      public ScriptGCEventListener,
+      public InspectorBackendDispatcher::TimelineCommandHandler,
+      public PlatformInstrumentationClient {
+    WTF_MAKE_NONCOPYABLE(InspectorTimelineAgent);
+public:
+    enum InspectorType { PageInspector, WorkerInspector };
+
+    static PassOwnPtr<InspectorTimelineAgent> create(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorMemoryAgent* memoryAgent, InspectorCompositeState* state, InspectorType type, InspectorClient* client)
+    {
+        return adoptPtr(new InspectorTimelineAgent(instrumentingAgents, pageAgent, memoryAgent, state, type, client));
+    }
+
+    ~InspectorTimelineAgent();
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void restore();
+
+    virtual void start(ErrorString*, const int* maxCallStackDepth, const bool* includeDomCounters, const bool* includeNativeMemoryStatistics);
+    virtual void stop(ErrorString*);
+
+    int id() const { return m_id; }
+
+    void didCommitLoad();
+
+    // Methods called from WebCore.
+    bool willCallFunction(ScriptExecutionContext* context, const String& scriptName, int scriptLine);
+    void didCallFunction();
+
+    bool willDispatchEvent(Document* document, const Event& event, DOMWindow* window, Node* node, const EventPath& eventPath);
+    bool willDispatchEventOnWindow(const Event& event, DOMWindow* window);
+    void didDispatchEvent();
+    void didDispatchEventOnWindow();
+
+    void didBeginFrame();
+    void didCancelFrame();
+
+    void didInvalidateLayout(Frame*);
+    bool willLayout(Frame*);
+    void didLayout(RenderObject*);
+
+    void didScheduleStyleRecalculation(Document*);
+    bool willRecalculateStyle(Document*);
+    void didRecalculateStyle();
+    void didRecalculateStyleForElement();
+
+    void willPaint(Frame*);
+    void didPaint(RenderObject*, GraphicsContext*, const LayoutRect&);
+
+    void willScrollLayer(Frame*);
+    void didScrollLayer();
+
+    void willComposite();
+    void didComposite();
+
+    bool willWriteHTML(Document*, unsigned startLine);
+    void didWriteHTML(unsigned endLine);
+
+    void didInstallTimer(ScriptExecutionContext* context, int timerId, int timeout, bool singleShot);
+    void didRemoveTimer(ScriptExecutionContext* context, int timerId);
+    bool willFireTimer(ScriptExecutionContext* context, int timerId);
+    void didFireTimer();
+
+    bool willDispatchXHRReadyStateChangeEvent(ScriptExecutionContext* context, XMLHttpRequest* request);
+    void didDispatchXHRReadyStateChangeEvent();
+    bool willDispatchXHRLoadEvent(ScriptExecutionContext* context, XMLHttpRequest* request);
+    void didDispatchXHRLoadEvent();
+
+    bool willEvaluateScript(Frame*, const String&, int);
+    void didEvaluateScript();
+
+    void didTimeStamp(Frame*, const String&);
+    void didMarkDOMContentEvent(Frame*);
+    void didMarkLoadEvent(Frame*);
+
+    void time(Frame*, const String&);
+    void timeEnd(Frame*, const String&);
+
+    void didScheduleResourceRequest(Document*, const String& url);
+    void willSendResourceRequest(unsigned long, DocumentLoader*, const ResourceRequest&, const ResourceResponse&);
+    bool willReceiveResourceResponse(Frame*, unsigned long, const ResourceResponse&);
+    void didReceiveResourceResponse(unsigned long, DocumentLoader*, const ResourceResponse&, ResourceLoader*);
+    void didFinishLoadingResource(unsigned long, bool didFail, double finishTime, Frame*);
+    void didFailLoading(unsigned long identifier, DocumentLoader* loader, const ResourceError& error);
+    bool willReceiveResourceData(Frame*, unsigned long identifier, int length);
+    void didReceiveResourceData();
+
+    void didRequestAnimationFrame(Document*, int callbackId);
+    void didCancelAnimationFrame(Document*, int callbackId);
+    bool willFireAnimationFrame(Document*, int callbackId);
+    void didFireAnimationFrame();
+
+    void willProcessTask();
+    void didProcessTask();
+
+    void didCreateWebSocket(Document*, unsigned long identifier, const KURL&, const String& protocol);
+    void willSendWebSocketHandshakeRequest(Document*, unsigned long identifier, const WebSocketHandshakeRequest&);
+    void didReceiveWebSocketHandshakeResponse(Document*, unsigned long identifier, const WebSocketHandshakeResponse&);
+    void didCloseWebSocket(Document*, unsigned long identifier);
+
+    // ScriptGCEventListener methods.
+    virtual void didGC(double, double, size_t);
+
+    // PlatformInstrumentationClient methods.
+    virtual void willDecodeImage(const String& imageType) OVERRIDE;
+    virtual void didDecodeImage() OVERRIDE;
+    virtual void willResizeImage(bool shouldCache) OVERRIDE;
+    virtual void didResizeImage() OVERRIDE;
+
+private:
+    friend class TimelineRecordStack;
+    friend class TimelineTraceEventProcessor;
+
+    struct TimelineRecordEntry {
+        TimelineRecordEntry(PassRefPtr<InspectorObject> record, PassRefPtr<InspectorObject> data, PassRefPtr<InspectorArray> children, const String& type, size_t usedHeapSizeAtStart)
+            : record(record), data(data), children(children), type(type), usedHeapSizeAtStart(usedHeapSizeAtStart)
+        {
+        }
+        RefPtr<InspectorObject> record;
+        RefPtr<InspectorObject> data;
+        RefPtr<InspectorArray> children;
+        String type;
+        size_t usedHeapSizeAtStart;
+    };
+        
+    InspectorTimelineAgent(InstrumentingAgents*, InspectorPageAgent*, InspectorMemoryAgent*, InspectorCompositeState*, InspectorType, InspectorClient*);
+
+    void sendEvent(PassRefPtr<InspectorObject>);
+    void appendRecord(PassRefPtr<InspectorObject> data, const String& type, bool captureCallStack, Frame*);
+    void pushCurrentRecord(PassRefPtr<InspectorObject>, const String& type, bool captureCallStack, Frame*, bool hasLowLevelDetails = false);
+
+    void setDOMCounters(TypeBuilder::Timeline::TimelineEvent* record);
+    void setNativeHeapStatistics(TypeBuilder::Timeline::TimelineEvent* record);
+    void setFrameIdentifier(InspectorObject* record, Frame*);
+    void pushGCEventRecords();
+
+    void didCompleteCurrentRecord(const String& type);
+
+    void setHeapSizeStatistics(InspectorObject* record);
+    void commitFrameRecord();
+
+    void addRecordToTimeline(PassRefPtr<InspectorObject>, const String& type);
+    void innerAddRecordToTimeline(PassRefPtr<InspectorObject>, const String& type);
+    void clearRecordStack();
+
+    void localToPageQuad(const RenderObject& renderer, const LayoutRect&, FloatQuad*);
+    const TimelineTimeConverter& timeConverter() const { return m_timeConverter; }
+    double timestamp();
+    Page* page();
+
+    InspectorPageAgent* m_pageAgent;
+    InspectorMemoryAgent* m_memoryAgent;
+    TimelineTimeConverter m_timeConverter;
+
+    InspectorFrontend::Timeline* m_frontend;
+    double m_timestampOffset;
+
+    Vector<TimelineRecordEntry> m_recordStack;
+
+    int m_id;
+    struct GCEvent {
+        GCEvent(double startTime, double endTime, size_t collectedBytes)
+            : startTime(startTime), endTime(endTime), collectedBytes(collectedBytes)
+        {
+        }
+        double startTime;
+        double endTime;
+        size_t collectedBytes;
+    };
+    typedef Vector<GCEvent> GCEvents;
+    GCEvents m_gcEvents;
+    int m_maxCallStackDepth;
+    unsigned m_platformInstrumentationClientInstalledAtStackDepth;
+    RefPtr<InspectorObject> m_pendingFrameRecord;
+    InspectorType m_inspectorType;
+    InspectorClient* m_client;
+    WeakPtrFactory<InspectorTimelineAgent> m_weakFactory;
+    RefPtr<TimelineTraceEventProcessor> m_traceEventProcessor;
+    unsigned m_styleRecalcElementCounter;
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorTimelineAgent_h)
diff --git a/Source/core/inspector/InspectorValues.cpp b/Source/core/inspector/InspectorValues.cpp
new file mode 100644
index 0000000..c132a98
--- /dev/null
+++ b/Source/core/inspector/InspectorValues.cpp
@@ -0,0 +1,796 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InspectorValues.h"
+
+#include <wtf/DecimalNumber.h>
+#include <wtf/dtoa.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+namespace {
+
+static const int stackLimit = 1000;
+
+enum Token {
+    OBJECT_BEGIN,
+    OBJECT_END,
+    ARRAY_BEGIN,
+    ARRAY_END,
+    STRING,
+    NUMBER,
+    BOOL_TRUE,
+    BOOL_FALSE,
+    NULL_TOKEN,
+    LIST_SEPARATOR,
+    OBJECT_PAIR_SEPARATOR,
+    INVALID_TOKEN,
+};
+
+const char* const nullString = "null";
+const char* const trueString = "true";
+const char* const falseString = "false";
+
+bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEnd, const char* token)
+{
+    while (start < end && *token != '\0' && *start++ == *token++) { }
+    if (*token != '\0')
+        return false;
+    *tokenEnd = start;
+    return true;
+}
+
+bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool canHaveLeadingZeros)
+{
+    if (start == end)
+        return false;
+    bool haveLeadingZero = '0' == *start;
+    int length = 0;
+    while (start < end && '0' <= *start && *start <= '9') {
+        ++start;
+        ++length;
+    }
+    if (!length)
+        return false;
+    if (!canHaveLeadingZeros && length > 1 && haveLeadingZero)
+        return false;
+    *tokenEnd = start;
+    return true;
+}
+
+bool parseNumberToken(const UChar* start, const UChar* end, const UChar** tokenEnd)
+{
+    // We just grab the number here.  We validate the size in DecodeNumber.
+    // According   to RFC4627, a valid number is: [minus] int [frac] [exp]
+    if (start == end)
+        return false;
+    UChar c = *start;
+    if ('-' == c)
+        ++start;
+
+    if (!readInt(start, end, &start, false))
+        return false;
+    if (start == end) {
+        *tokenEnd = start;
+        return true;
+    }
+
+    // Optional fraction part
+    c = *start;
+    if ('.' == c) {
+        ++start;
+        if (!readInt(start, end, &start, true))
+            return false;
+        if (start == end) {
+            *tokenEnd = start;
+            return true;
+        }
+        c = *start;
+    }
+
+    // Optional exponent part
+    if ('e' == c || 'E' == c) {
+        ++start;
+        if (start == end)
+            return false;
+        c = *start;
+        if ('-' == c || '+' == c) {
+            ++start;
+            if (start == end)
+                return false;
+        }
+        if (!readInt(start, end, &start, true))
+            return false;
+    }
+
+    *tokenEnd = start;
+    return true;
+}
+
+bool readHexDigits(const UChar* start, const UChar* end, const UChar** tokenEnd, int digits)
+{
+    if (end - start < digits)
+        return false;
+    for (int i = 0; i < digits; ++i) {
+        UChar c = *start++;
+        if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')))
+            return false;
+    }
+    *tokenEnd = start;
+    return true;
+}
+
+bool parseStringToken(const UChar* start, const UChar* end, const UChar** tokenEnd)
+{
+    while (start < end) {
+        UChar c = *start++;
+        if ('\\' == c) {
+            c = *start++;
+            // Make sure the escaped char is valid.
+            switch (c) {
+            case 'x':
+                if (!readHexDigits(start, end, &start, 2))
+                    return false;
+                break;
+            case 'u':
+                if (!readHexDigits(start, end, &start, 4))
+                    return false;
+                break;
+            case '\\':
+            case '/':
+            case 'b':
+            case 'f':
+            case 'n':
+            case 'r':
+            case 't':
+            case 'v':
+            case '"':
+                break;
+            default:
+                return false;
+            }
+        } else if ('"' == c) {
+            *tokenEnd = start;
+            return true;
+        }
+    }
+    return false;
+}
+
+Token parseToken(const UChar* start, const UChar* end, const UChar** tokenStart, const UChar** tokenEnd)
+{
+    while (start < end && isSpaceOrNewline(*start))
+        ++start;
+
+    if (start == end)
+        return INVALID_TOKEN;
+
+    *tokenStart = start;
+
+    switch (*start) {
+    case 'n':
+        if (parseConstToken(start, end, tokenEnd, nullString))
+            return NULL_TOKEN;
+        break;
+    case 't':
+        if (parseConstToken(start, end, tokenEnd, trueString))
+            return BOOL_TRUE;
+        break;
+    case 'f':
+        if (parseConstToken(start, end, tokenEnd, falseString))
+            return BOOL_FALSE;
+        break;
+    case '[':
+        *tokenEnd = start + 1;
+        return ARRAY_BEGIN;
+    case ']':
+        *tokenEnd = start + 1;
+        return ARRAY_END;
+    case ',':
+        *tokenEnd = start + 1;
+        return LIST_SEPARATOR;
+    case '{':
+        *tokenEnd = start + 1;
+        return OBJECT_BEGIN;
+    case '}':
+        *tokenEnd = start + 1;
+        return OBJECT_END;
+    case ':':
+        *tokenEnd = start + 1;
+        return OBJECT_PAIR_SEPARATOR;
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+    case '-':
+        if (parseNumberToken(start, end, tokenEnd))
+            return NUMBER;
+        break;
+    case '"':
+        if (parseStringToken(start + 1, end, tokenEnd))
+            return STRING;
+        break;
+    }
+    return INVALID_TOKEN;
+}
+
+inline int hexToInt(UChar c)
+{
+    if ('0' <= c && c <= '9')
+        return c - '0';
+    if ('A' <= c && c <= 'F')
+        return c - 'A' + 10;
+    if ('a' <= c && c <= 'f')
+        return c - 'a' + 10;
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+bool decodeString(const UChar* start, const UChar* end, StringBuilder* output)
+{
+    while (start < end) {
+        UChar c = *start++;
+        if ('\\' != c) {
+            output->append(c);
+            continue;
+        }
+        c = *start++;
+        switch (c) {
+        case '"':
+        case '/':
+        case '\\':
+            break;
+        case 'b':
+            c = '\b';
+            break;
+        case 'f':
+            c = '\f';
+            break;
+        case 'n':
+            c = '\n';
+            break;
+        case 'r':
+            c = '\r';
+            break;
+        case 't':
+            c = '\t';
+            break;
+        case 'v':
+            c = '\v';
+            break;
+        case 'x':
+            c = (hexToInt(*start) << 4) +
+                hexToInt(*(start + 1));
+            start += 2;
+            break;
+        case 'u':
+            c = (hexToInt(*start) << 12) +
+                (hexToInt(*(start + 1)) << 8) +
+                (hexToInt(*(start + 2)) << 4) +
+                hexToInt(*(start + 3));
+            start += 4;
+            break;
+        default:
+            return false;
+        }
+        output->append(c);
+    }
+    return true;
+}
+
+bool decodeString(const UChar* start, const UChar* end, String* output)
+{
+    if (start == end) {
+        *output = "";
+        return true;
+    }
+    if (start > end)
+        return false;
+    StringBuilder buffer;
+    buffer.reserveCapacity(end - start);
+    if (!decodeString(start, end, &buffer))
+        return false;
+    *output = buffer.toString();
+    return true;
+}
+
+PassRefPtr<InspectorValue> buildValue(const UChar* start, const UChar* end, const UChar** valueTokenEnd, int depth)
+{
+    if (depth > stackLimit)
+        return 0;
+
+    RefPtr<InspectorValue> result;
+    const UChar* tokenStart;
+    const UChar* tokenEnd;
+    Token token = parseToken(start, end, &tokenStart, &tokenEnd);
+    switch (token) {
+    case INVALID_TOKEN:
+        return 0;
+    case NULL_TOKEN:
+        result = InspectorValue::null();
+        break;
+    case BOOL_TRUE:
+        result = InspectorBasicValue::create(true);
+        break;
+    case BOOL_FALSE:
+        result = InspectorBasicValue::create(false);
+        break;
+    case NUMBER: {
+        bool ok;
+        double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok);
+        if (!ok)
+            return 0;
+        result = InspectorBasicValue::create(value);
+        break;
+    }
+    case STRING: {
+        String value;
+        bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value);
+        if (!ok)
+            return 0;
+        result = InspectorString::create(value);
+        break;
+    }
+    case ARRAY_BEGIN: {
+        RefPtr<InspectorArray> array = InspectorArray::create();
+        start = tokenEnd;
+        token = parseToken(start, end, &tokenStart, &tokenEnd);
+        while (token != ARRAY_END) {
+            RefPtr<InspectorValue> arrayNode = buildValue(start, end, &tokenEnd, depth + 1);
+            if (!arrayNode)
+                return 0;
+            array->pushValue(arrayNode);
+
+            // After a list value, we expect a comma or the end of the list.
+            start = tokenEnd;
+            token = parseToken(start, end, &tokenStart, &tokenEnd);
+            if (token == LIST_SEPARATOR) {
+                start = tokenEnd;
+                token = parseToken(start, end, &tokenStart, &tokenEnd);
+                if (token == ARRAY_END)
+                    return 0;
+            } else if (token != ARRAY_END) {
+                // Unexpected value after list value.  Bail out.
+                return 0;
+            }
+        }
+        if (token != ARRAY_END)
+            return 0;
+        result = array.release();
+        break;
+    }
+    case OBJECT_BEGIN: {
+        RefPtr<InspectorObject> object = InspectorObject::create();
+        start = tokenEnd;
+        token = parseToken(start, end, &tokenStart, &tokenEnd);
+        while (token != OBJECT_END) {
+            if (token != STRING)
+                return 0;
+            String key;
+            if (!decodeString(tokenStart + 1, tokenEnd - 1, &key))
+                return 0;
+            start = tokenEnd;
+
+            token = parseToken(start, end, &tokenStart, &tokenEnd);
+            if (token != OBJECT_PAIR_SEPARATOR)
+                return 0;
+            start = tokenEnd;
+
+            RefPtr<InspectorValue> value = buildValue(start, end, &tokenEnd, depth + 1);
+            if (!value)
+                return 0;
+            object->setValue(key, value);
+            start = tokenEnd;
+
+            // After a key/value pair, we expect a comma or the end of the
+            // object.
+            token = parseToken(start, end, &tokenStart, &tokenEnd);
+            if (token == LIST_SEPARATOR) {
+                start = tokenEnd;
+                token = parseToken(start, end, &tokenStart, &tokenEnd);
+                 if (token == OBJECT_END)
+                    return 0;
+            } else if (token != OBJECT_END) {
+                // Unexpected value after last object value.  Bail out.
+                return 0;
+            }
+        }
+        if (token != OBJECT_END)
+            return 0;
+        result = object.release();
+        break;
+    }
+
+    default:
+        // We got a token that's not a value.
+        return 0;
+    }
+    *valueTokenEnd = tokenEnd;
+    return result.release();
+}
+
+inline bool escapeChar(UChar c, StringBuilder* dst)
+{
+    switch (c) {
+    case '\b': dst->append("\\b", 2); break;
+    case '\f': dst->append("\\f", 2); break;
+    case '\n': dst->append("\\n", 2); break;
+    case '\r': dst->append("\\r", 2); break;
+    case '\t': dst->append("\\t", 2); break;
+    case '\\': dst->append("\\\\", 2); break;
+    case '"': dst->append("\\\"", 2); break;
+    default:
+        return false;
+    }
+    return true;
+}
+
+inline void doubleQuoteString(const String& str, StringBuilder* dst)
+{
+    dst->append('"');
+    for (unsigned i = 0; i < str.length(); ++i) {
+        UChar c = str[i];
+        if (!escapeChar(c, dst)) {
+            if (c < 32 || c > 126 || c == '<' || c == '>') {
+                // 1. Escaping <, > to prevent script execution.
+                // 2. Technically, we could also pass through c > 126 as UTF8, but this
+                //    is also optional.  It would also be a pain to implement here.
+                unsigned int symbol = static_cast<unsigned int>(c);
+                String symbolCode = String::format("\\u%04X", symbol);
+                dst->append(symbolCode.characters(), symbolCode.length());
+            } else
+                dst->append(c);
+        }
+    }
+    dst->append('"');
+}
+
+} // anonymous namespace
+
+bool InspectorValue::asBoolean(bool*) const
+{
+    return false;
+}
+
+bool InspectorValue::asNumber(double*) const
+{
+    return false;
+}
+
+bool InspectorValue::asNumber(long*) const
+{
+    return false;
+}
+
+bool InspectorValue::asNumber(int*) const
+{
+    return false;
+}
+
+bool InspectorValue::asNumber(unsigned long*) const
+{
+    return false;
+}
+
+bool InspectorValue::asNumber(unsigned int*) const
+{
+    return false;
+}
+
+bool InspectorValue::asString(String*) const
+{
+    return false;
+}
+
+bool InspectorValue::asValue(RefPtr<InspectorValue>* output)
+{
+    *output = this;
+    return true;
+}
+
+bool InspectorValue::asObject(RefPtr<InspectorObject>*)
+{
+    return false;
+}
+
+bool InspectorValue::asArray(RefPtr<InspectorArray>*)
+{
+    return false;
+}
+
+PassRefPtr<InspectorObject> InspectorValue::asObject()
+{
+    return 0;
+}
+
+PassRefPtr<InspectorArray> InspectorValue::asArray()
+{
+    return 0;
+}
+
+PassRefPtr<InspectorValue> InspectorValue::parseJSON(const String& json)
+{
+    const UChar* start = json.characters();
+    const UChar* end = json.characters() + json.length();
+    const UChar *tokenEnd;
+    RefPtr<InspectorValue> value = buildValue(start, end, &tokenEnd, 0);
+    if (!value || tokenEnd != end)
+        return 0;
+    return value.release();
+}
+
+String InspectorValue::toJSONString() const
+{
+    StringBuilder result;
+    result.reserveCapacity(512);
+    writeJSON(&result);
+    return result.toString();
+}
+
+void InspectorValue::writeJSON(StringBuilder* output) const
+{
+    ASSERT(m_type == TypeNull);
+    output->append(nullString, 4);
+}
+
+bool InspectorBasicValue::asBoolean(bool* output) const
+{
+    if (type() != TypeBoolean)
+        return false;
+    *output = m_boolValue;
+    return true;
+}
+
+bool InspectorBasicValue::asNumber(double* output) const
+{
+    if (type() != TypeNumber)
+        return false;
+    *output = m_doubleValue;
+    return true;
+}
+
+bool InspectorBasicValue::asNumber(long* output) const
+{
+    if (type() != TypeNumber)
+        return false;
+    *output = static_cast<long>(m_doubleValue);
+    return true;
+}
+
+bool InspectorBasicValue::asNumber(int* output) const
+{
+    if (type() != TypeNumber)
+        return false;
+    *output = static_cast<int>(m_doubleValue);
+    return true;
+}
+
+bool InspectorBasicValue::asNumber(unsigned long* output) const
+{
+    if (type() != TypeNumber)
+        return false;
+    *output = static_cast<unsigned long>(m_doubleValue);
+    return true;
+}
+
+bool InspectorBasicValue::asNumber(unsigned int* output) const
+{
+    if (type() != TypeNumber)
+        return false;
+    *output = static_cast<unsigned int>(m_doubleValue);
+    return true;
+}
+
+void InspectorBasicValue::writeJSON(StringBuilder* output) const
+{
+    ASSERT(type() == TypeBoolean || type() == TypeNumber);
+    if (type() == TypeBoolean) {
+        if (m_boolValue)
+            output->append(trueString, 4);
+        else
+            output->append(falseString, 5);
+    } else if (type() == TypeNumber) {
+        NumberToLStringBuffer buffer;
+        if (!std::isfinite(m_doubleValue)) {
+            output->append(nullString, 4);
+            return;
+        }
+        DecimalNumber decimal = m_doubleValue;
+        unsigned length = 0;
+        if (decimal.bufferLengthForStringDecimal() > WTF::NumberToStringBufferLength) {
+            // Not enough room for decimal. Use exponential format.
+            if (decimal.bufferLengthForStringExponential() > WTF::NumberToStringBufferLength) {
+                // Fallback for an abnormal case if it's too little even for exponential.
+                output->append("NaN", 3);
+                return;
+            }
+            length = decimal.toStringExponential(buffer, WTF::NumberToStringBufferLength);
+        } else
+            length = decimal.toStringDecimal(buffer, WTF::NumberToStringBufferLength);
+        output->append(buffer, length);
+    }
+}
+
+bool InspectorString::asString(String* output) const
+{
+    *output = m_stringValue;
+    return true;
+}
+
+void InspectorString::writeJSON(StringBuilder* output) const
+{
+    ASSERT(type() == TypeString);
+    doubleQuoteString(m_stringValue, output);
+}
+
+InspectorObjectBase::~InspectorObjectBase()
+{
+}
+
+bool InspectorObjectBase::asObject(RefPtr<InspectorObject>* output)
+{
+    COMPILE_ASSERT(sizeof(InspectorObject) == sizeof(InspectorObjectBase), cannot_cast);
+    *output = static_cast<InspectorObject*>(this);
+    return true;
+}
+
+PassRefPtr<InspectorObject> InspectorObjectBase::asObject()
+{
+    return openAccessors();
+}
+
+InspectorObject* InspectorObjectBase::openAccessors()
+{
+    COMPILE_ASSERT(sizeof(InspectorObject) == sizeof(InspectorObjectBase), cannot_cast);
+    return static_cast<InspectorObject*>(this);
+}
+
+bool InspectorObjectBase::getBoolean(const String& name, bool* output) const
+{
+    RefPtr<InspectorValue> value = get(name);
+    if (!value)
+        return false;
+    return value->asBoolean(output);
+}
+
+bool InspectorObjectBase::getString(const String& name, String* output) const
+{
+    RefPtr<InspectorValue> value = get(name);
+    if (!value)
+        return false;
+    return value->asString(output);
+}
+
+PassRefPtr<InspectorObject> InspectorObjectBase::getObject(const String& name) const
+{
+    PassRefPtr<InspectorValue> value = get(name);
+    if (!value)
+        return 0;
+    return value->asObject();
+}
+
+PassRefPtr<InspectorArray> InspectorObjectBase::getArray(const String& name) const
+{
+    PassRefPtr<InspectorValue> value = get(name);
+    if (!value)
+        return 0;
+    return value->asArray();
+}
+
+PassRefPtr<InspectorValue> InspectorObjectBase::get(const String& name) const
+{
+    Dictionary::const_iterator it = m_data.find(name);
+    if (it == m_data.end())
+        return 0;
+    return it->value;
+}
+
+void InspectorObjectBase::remove(const String& name)
+{
+    m_data.remove(name);
+    for (size_t i = 0; i < m_order.size(); ++i) {
+        if (m_order[i] == name) {
+            m_order.remove(i);
+            break;
+        }
+    }
+}
+
+void InspectorObjectBase::writeJSON(StringBuilder* output) const
+{
+    output->append('{');
+    for (size_t i = 0; i < m_order.size(); ++i) {
+        Dictionary::const_iterator it = m_data.find(m_order[i]);
+        ASSERT(it != m_data.end());
+        if (i)
+            output->append(',');
+        doubleQuoteString(it->key, output);
+        output->append(':');
+        it->value->writeJSON(output);
+    }
+    output->append('}');
+}
+
+InspectorObjectBase::InspectorObjectBase()
+    : InspectorValue(TypeObject)
+    , m_data()
+    , m_order()
+{
+}
+
+InspectorArrayBase::~InspectorArrayBase()
+{
+}
+
+bool InspectorArrayBase::asArray(RefPtr<InspectorArray>* output)
+{
+    COMPILE_ASSERT(sizeof(InspectorArrayBase) == sizeof(InspectorArray), cannot_cast);
+    *output = static_cast<InspectorArray*>(this);
+    return true;
+}
+
+PassRefPtr<InspectorArray> InspectorArrayBase::asArray()
+{
+    COMPILE_ASSERT(sizeof(InspectorArrayBase) == sizeof(InspectorArray), cannot_cast);
+    return static_cast<InspectorArray*>(this);
+}
+
+void InspectorArrayBase::writeJSON(StringBuilder* output) const
+{
+    output->append('[');
+    for (Vector<RefPtr<InspectorValue> >::const_iterator it = m_data.begin(); it != m_data.end(); ++it) {
+        if (it != m_data.begin())
+            output->append(',');
+        (*it)->writeJSON(output);
+    }
+    output->append(']');
+}
+
+InspectorArrayBase::InspectorArrayBase()
+    : InspectorValue(TypeArray)
+    , m_data()
+{
+}
+
+PassRefPtr<InspectorValue> InspectorArrayBase::get(size_t index)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(index < m_data.size());
+    return m_data[index];
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/InspectorValues.h b/Source/core/inspector/InspectorValues.h
new file mode 100644
index 0000000..1f0aecb
--- /dev/null
+++ b/Source/core/inspector/InspectorValues.h
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef InspectorValues_h
+#define InspectorValues_h
+
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class InspectorArray;
+class InspectorObject;
+
+class InspectorValue : public RefCounted<InspectorValue> {
+public:
+    static const int maxDepth = 1000;
+
+    InspectorValue() : m_type(TypeNull) { }
+    virtual ~InspectorValue() { }
+
+    static PassRefPtr<InspectorValue> null()
+    {
+        return adoptRef(new InspectorValue());
+    }
+
+    typedef enum {
+        TypeNull = 0,
+        TypeBoolean,
+        TypeNumber,
+        TypeString,
+        TypeObject,
+        TypeArray
+    } Type;
+
+    Type type() const { return m_type; }
+
+    bool isNull() const { return m_type == TypeNull; }
+
+    virtual bool asBoolean(bool* output) const;
+    virtual bool asNumber(double* output) const;
+    virtual bool asNumber(long* output) const;
+    virtual bool asNumber(int* output) const;
+    virtual bool asNumber(unsigned long* output) const;
+    virtual bool asNumber(unsigned int* output) const;
+    virtual bool asString(String* output) const;
+    virtual bool asValue(RefPtr<InspectorValue>* output);
+    virtual bool asObject(RefPtr<InspectorObject>* output);
+    virtual bool asArray(RefPtr<InspectorArray>* output);
+    virtual PassRefPtr<InspectorObject> asObject();
+    virtual PassRefPtr<InspectorArray> asArray();
+
+    static PassRefPtr<InspectorValue> parseJSON(const String& json);
+
+    String toJSONString() const;
+    virtual void writeJSON(StringBuilder* output) const;
+
+protected:
+    explicit InspectorValue(Type type) : m_type(type) { }
+
+private:
+    Type m_type;
+};
+
+class InspectorBasicValue : public InspectorValue {
+public:
+
+    static PassRefPtr<InspectorBasicValue> create(bool value)
+    {
+        return adoptRef(new InspectorBasicValue(value));
+    }
+
+    static PassRefPtr<InspectorBasicValue> create(int value)
+    {
+        return adoptRef(new InspectorBasicValue(value));
+    }
+
+    static PassRefPtr<InspectorBasicValue> create(double value)
+    {
+        return adoptRef(new InspectorBasicValue(value));
+    }
+
+    virtual bool asBoolean(bool* output) const;
+    virtual bool asNumber(double* output) const;
+    virtual bool asNumber(long* output) const;
+    virtual bool asNumber(int* output) const;
+    virtual bool asNumber(unsigned long* output) const;
+    virtual bool asNumber(unsigned int* output) const;
+
+    virtual void writeJSON(StringBuilder* output) const;
+
+private:
+    explicit InspectorBasicValue(bool value) : InspectorValue(TypeBoolean), m_boolValue(value) { }
+    explicit InspectorBasicValue(int value) : InspectorValue(TypeNumber), m_doubleValue((double)value) { }
+    explicit InspectorBasicValue(double value) : InspectorValue(TypeNumber), m_doubleValue(value) { }
+
+    union {
+        bool m_boolValue;
+        double m_doubleValue;
+    };
+};
+
+class InspectorString : public InspectorValue {
+public:
+    static PassRefPtr<InspectorString> create(const String& value)
+    {
+        return adoptRef(new InspectorString(value));
+    }
+
+    static PassRefPtr<InspectorString> create(const char* value)
+    {
+        return adoptRef(new InspectorString(value));
+    }
+
+    virtual bool asString(String* output) const;    
+
+    virtual void writeJSON(StringBuilder* output) const;
+
+private:
+    explicit InspectorString(const String& value) : InspectorValue(TypeString), m_stringValue(value) { }
+    explicit InspectorString(const char* value) : InspectorValue(TypeString), m_stringValue(value) { }
+
+    String m_stringValue;
+};
+
+class InspectorObjectBase : public InspectorValue {
+private:
+    typedef HashMap<String, RefPtr<InspectorValue> > Dictionary;
+
+public:
+    typedef Dictionary::iterator iterator;
+    typedef Dictionary::const_iterator const_iterator;
+
+    virtual PassRefPtr<InspectorObject> asObject();
+    InspectorObject* openAccessors();
+
+protected:
+    ~InspectorObjectBase();
+
+    virtual bool asObject(RefPtr<InspectorObject>* output);
+
+    void setBoolean(const String& name, bool);
+    void setNumber(const String& name, double);
+    void setString(const String& name, const String&);
+    void setValue(const String& name, PassRefPtr<InspectorValue>);
+    void setObject(const String& name, PassRefPtr<InspectorObject>);
+    void setArray(const String& name, PassRefPtr<InspectorArray>);
+
+    iterator find(const String& name);
+    const_iterator find(const String& name) const;
+    bool getBoolean(const String& name, bool* output) const;
+    template<class T> bool getNumber(const String& name, T* output) const
+    {
+        RefPtr<InspectorValue> value = get(name);
+        if (!value)
+            return false;
+        return value->asNumber(output);
+    }
+    bool getString(const String& name, String* output) const;
+    PassRefPtr<InspectorObject> getObject(const String& name) const;
+    PassRefPtr<InspectorArray> getArray(const String& name) const;
+    PassRefPtr<InspectorValue> get(const String& name) const;
+
+    void remove(const String& name);
+
+    virtual void writeJSON(StringBuilder* output) const;
+
+    iterator begin() { return m_data.begin(); }
+    iterator end() { return m_data.end(); }
+    const_iterator begin() const { return m_data.begin(); }
+    const_iterator end() const { return m_data.end(); }
+
+    int size() const { return m_data.size(); }
+
+protected:
+    InspectorObjectBase();
+
+private:
+    Dictionary m_data;
+    Vector<String> m_order;
+};
+
+class InspectorObject : public InspectorObjectBase {
+public:
+    static PassRefPtr<InspectorObject> create()
+    {
+        return adoptRef(new InspectorObject());
+    }
+
+    using InspectorObjectBase::asObject;
+
+    using InspectorObjectBase::setBoolean;
+    using InspectorObjectBase::setNumber;
+    using InspectorObjectBase::setString;
+    using InspectorObjectBase::setValue;
+    using InspectorObjectBase::setObject;
+    using InspectorObjectBase::setArray;
+
+    using InspectorObjectBase::find;
+    using InspectorObjectBase::getBoolean;
+    using InspectorObjectBase::getNumber;
+    using InspectorObjectBase::getString;
+    using InspectorObjectBase::getObject;
+    using InspectorObjectBase::getArray;
+    using InspectorObjectBase::get;
+
+    using InspectorObjectBase::remove;
+
+    using InspectorObjectBase::begin;
+    using InspectorObjectBase::end;
+
+    using InspectorObjectBase::size;
+};
+
+
+class InspectorArrayBase : public InspectorValue {
+public:
+    typedef Vector<RefPtr<InspectorValue> >::iterator iterator;
+    typedef Vector<RefPtr<InspectorValue> >::const_iterator const_iterator;
+
+    virtual PassRefPtr<InspectorArray> asArray();
+
+    unsigned length() const { return m_data.size(); }
+
+protected:
+    ~InspectorArrayBase();
+
+    virtual bool asArray(RefPtr<InspectorArray>* output);
+
+    void pushBoolean(bool);
+    void pushInt(int);
+    void pushNumber(double);
+    void pushString(const String&);
+    void pushValue(PassRefPtr<InspectorValue>);
+    void pushObject(PassRefPtr<InspectorObject>);
+    void pushArray(PassRefPtr<InspectorArray>);
+
+    PassRefPtr<InspectorValue> get(size_t index);
+
+    virtual void writeJSON(StringBuilder* output) const;
+
+    iterator begin() { return m_data.begin(); }
+    iterator end() { return m_data.end(); }
+    const_iterator begin() const { return m_data.begin(); }
+    const_iterator end() const { return m_data.end(); }
+
+protected:
+    InspectorArrayBase();
+
+private:
+    Vector<RefPtr<InspectorValue> > m_data;
+};
+
+class InspectorArray : public InspectorArrayBase {
+public:
+    static PassRefPtr<InspectorArray> create()
+    {
+        return adoptRef(new InspectorArray());
+    }
+
+    using InspectorArrayBase::asArray;
+
+    using InspectorArrayBase::pushBoolean;
+    using InspectorArrayBase::pushInt;
+    using InspectorArrayBase::pushNumber;
+    using InspectorArrayBase::pushString;
+    using InspectorArrayBase::pushValue;
+    using InspectorArrayBase::pushObject;
+    using InspectorArrayBase::pushArray;
+
+    using InspectorArrayBase::get;
+
+    using InspectorArrayBase::begin;
+    using InspectorArrayBase::end;
+};
+
+
+inline InspectorObjectBase::iterator InspectorObjectBase::find(const String& name)
+{
+    return m_data.find(name);
+}
+
+inline InspectorObjectBase::const_iterator InspectorObjectBase::find(const String& name) const
+{
+    return m_data.find(name);
+}
+
+inline void InspectorObjectBase::setBoolean(const String& name, bool value)
+{
+    setValue(name, InspectorBasicValue::create(value));
+}
+
+inline void InspectorObjectBase::setNumber(const String& name, double value)
+{
+    setValue(name, InspectorBasicValue::create(value));
+}
+
+inline void InspectorObjectBase::setString(const String& name, const String& value)
+{
+    setValue(name, InspectorString::create(value));
+}
+
+inline void InspectorObjectBase::setValue(const String& name, PassRefPtr<InspectorValue> value)
+{
+    ASSERT(value);
+    if (m_data.set(name, value).isNewEntry)
+        m_order.append(name);
+}
+
+inline void InspectorObjectBase::setObject(const String& name, PassRefPtr<InspectorObject> value)
+{
+    ASSERT(value);
+    if (m_data.set(name, value).isNewEntry)
+        m_order.append(name);
+}
+
+inline void InspectorObjectBase::setArray(const String& name, PassRefPtr<InspectorArray> value)
+{
+    ASSERT(value);
+    if (m_data.set(name, value).isNewEntry)
+        m_order.append(name);
+}
+
+inline void InspectorArrayBase::pushBoolean(bool value)
+{
+    m_data.append(InspectorBasicValue::create(value));
+}
+
+inline void InspectorArrayBase::pushInt(int value)
+{
+    m_data.append(InspectorBasicValue::create(value));
+}
+
+inline void InspectorArrayBase::pushNumber(double value)
+{
+    m_data.append(InspectorBasicValue::create(value));
+}
+
+inline void InspectorArrayBase::pushString(const String& value)
+{
+    m_data.append(InspectorString::create(value));
+}
+
+inline void InspectorArrayBase::pushValue(PassRefPtr<InspectorValue> value)
+{
+    ASSERT(value);
+    m_data.append(value);
+}
+
+inline void InspectorArrayBase::pushObject(PassRefPtr<InspectorObject> value)
+{
+    ASSERT(value);
+    m_data.append(value);
+}
+
+inline void InspectorArrayBase::pushArray(PassRefPtr<InspectorArray> value)
+{
+    ASSERT(value);
+    m_data.append(value);
+}
+
+} // namespace WebCore
+
+#endif // !defined(InspectorValues_h)
diff --git a/Source/core/inspector/InspectorWorkerAgent.cpp b/Source/core/inspector/InspectorWorkerAgent.cpp
new file mode 100644
index 0000000..e995c22
--- /dev/null
+++ b/Source/core/inspector/InspectorWorkerAgent.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+
+#include "core/inspector/InspectorWorkerAgent.h"
+
+#include "InspectorFrontend.h"
+#include "core/inspector/InspectorFrontendChannel.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/platform/KURL.h"
+#include "core/workers/WorkerContextProxy.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+namespace WorkerAgentState {
+static const char workerInspectionEnabled[] = "workerInspectionEnabled";
+static const char autoconnectToWorkers[] = "autoconnectToWorkers";
+};
+
+class InspectorWorkerAgent::WorkerFrontendChannel : public WorkerContextProxy::PageInspector {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit WorkerFrontendChannel(InspectorFrontend* frontend, WorkerContextProxy* proxy)
+        : m_frontend(frontend)
+        , m_proxy(proxy)
+        , m_id(s_nextId++)
+        , m_connected(false)
+    {
+    }
+    virtual ~WorkerFrontendChannel()
+    {
+        disconnectFromWorkerContext();
+    }
+
+    int id() const { return m_id; }
+    WorkerContextProxy* proxy() const { return m_proxy; }
+
+    void connectToWorkerContext()
+    {
+        if (m_connected)
+            return;
+        m_connected = true;
+        m_proxy->connectToInspector(this);
+    }
+
+    void disconnectFromWorkerContext()
+    {
+        if (!m_connected)
+            return;
+        m_connected = false;
+        m_proxy->disconnectFromInspector();
+    }
+
+private:
+    // WorkerContextProxy::PageInspector implementation
+    virtual void dispatchMessageFromWorker(const String& message)
+    {
+        RefPtr<InspectorValue> value = InspectorValue::parseJSON(message);
+        if (!value)
+            return;
+        RefPtr<InspectorObject> messageObject = value->asObject();
+        if (!messageObject)
+            return;
+        m_frontend->worker()->dispatchMessageFromWorker(m_id, messageObject);
+    }
+
+    InspectorFrontend* m_frontend;
+    WorkerContextProxy* m_proxy;
+    int m_id;
+    bool m_connected;
+    static int s_nextId;
+};
+
+int InspectorWorkerAgent::WorkerFrontendChannel::s_nextId = 1;
+
+PassOwnPtr<InspectorWorkerAgent> InspectorWorkerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState)
+{
+    return adoptPtr(new InspectorWorkerAgent(instrumentingAgents, inspectorState));
+}
+
+InspectorWorkerAgent::InspectorWorkerAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState)
+    : InspectorBaseAgent<InspectorWorkerAgent>("Worker", instrumentingAgents, inspectorState)
+    , m_inspectorFrontend(0)
+{
+    m_instrumentingAgents->setInspectorWorkerAgent(this);
+}
+
+InspectorWorkerAgent::~InspectorWorkerAgent()
+{
+    m_instrumentingAgents->setInspectorWorkerAgent(0);
+}
+
+void InspectorWorkerAgent::setFrontend(InspectorFrontend* frontend)
+{
+    m_inspectorFrontend = frontend;
+}
+
+void InspectorWorkerAgent::restore()
+{
+    if (m_state->getBoolean(WorkerAgentState::workerInspectionEnabled))
+        createWorkerFrontendChannelsForExistingWorkers();
+}
+
+void InspectorWorkerAgent::clearFrontend()
+{
+    m_state->setBoolean(WorkerAgentState::autoconnectToWorkers, false);
+    disable(0);
+    m_inspectorFrontend = 0;
+}
+
+void InspectorWorkerAgent::enable(ErrorString*)
+{
+    m_state->setBoolean(WorkerAgentState::workerInspectionEnabled, true);
+    if (!m_inspectorFrontend)
+        return;
+    createWorkerFrontendChannelsForExistingWorkers();
+}
+
+void InspectorWorkerAgent::disable(ErrorString*)
+{
+    m_state->setBoolean(WorkerAgentState::workerInspectionEnabled, false);
+    if (!m_inspectorFrontend)
+        return;
+    destroyWorkerFrontendChannels();
+}
+
+void InspectorWorkerAgent::canInspectWorkers(ErrorString*, bool* result)
+{
+    *result = true;
+}
+
+void InspectorWorkerAgent::connectToWorker(ErrorString* error, int workerId)
+{
+    WorkerFrontendChannel* channel = m_idToChannel.get(workerId);
+    if (channel)
+        channel->connectToWorkerContext();
+    else
+        *error = "Worker is gone";
+}
+
+void InspectorWorkerAgent::disconnectFromWorker(ErrorString* error, int workerId)
+{
+    WorkerFrontendChannel* channel = m_idToChannel.get(workerId);
+    if (channel)
+        channel->disconnectFromWorkerContext();
+    else
+        *error = "Worker is gone";
+}
+
+void InspectorWorkerAgent::sendMessageToWorker(ErrorString* error, int workerId, const RefPtr<InspectorObject>& message)
+{
+    WorkerFrontendChannel* channel = m_idToChannel.get(workerId);
+    if (channel)
+        channel->proxy()->sendMessageToInspector(message->toJSONString());
+    else
+        *error = "Worker is gone";
+}
+
+void InspectorWorkerAgent::setAutoconnectToWorkers(ErrorString*, bool value)
+{
+    m_state->setBoolean(WorkerAgentState::autoconnectToWorkers, value);
+}
+
+bool InspectorWorkerAgent::shouldPauseDedicatedWorkerOnStart()
+{
+    return m_state->getBoolean(WorkerAgentState::autoconnectToWorkers);
+}
+
+void InspectorWorkerAgent::didStartWorkerContext(WorkerContextProxy* workerContextProxy, const KURL& url)
+{
+    m_dedicatedWorkers.set(workerContextProxy, url.string());
+    if (m_inspectorFrontend && m_state->getBoolean(WorkerAgentState::workerInspectionEnabled))
+        createWorkerFrontendChannel(workerContextProxy, url.string());
+}
+
+void InspectorWorkerAgent::workerContextTerminated(WorkerContextProxy* proxy)
+{
+    m_dedicatedWorkers.remove(proxy);
+    for (WorkerChannels::iterator it = m_idToChannel.begin(); it != m_idToChannel.end(); ++it) {
+        if (proxy == it->value->proxy()) {
+            m_inspectorFrontend->worker()->workerTerminated(it->key);
+            delete it->value;
+            m_idToChannel.remove(it);
+            return;
+        }
+    }
+}
+
+void InspectorWorkerAgent::createWorkerFrontendChannelsForExistingWorkers()
+{
+    for (DedicatedWorkers::iterator it = m_dedicatedWorkers.begin(); it != m_dedicatedWorkers.end(); ++it)
+        createWorkerFrontendChannel(it->key, it->value);
+}
+
+void InspectorWorkerAgent::destroyWorkerFrontendChannels()
+{
+    for (WorkerChannels::iterator it = m_idToChannel.begin(); it != m_idToChannel.end(); ++it) {
+        it->value->disconnectFromWorkerContext();
+        delete it->value;
+    }
+    m_idToChannel.clear();
+}
+
+void InspectorWorkerAgent::createWorkerFrontendChannel(WorkerContextProxy* workerContextProxy, const String& url)
+{
+    WorkerFrontendChannel* channel = new WorkerFrontendChannel(m_inspectorFrontend, workerContextProxy);
+    m_idToChannel.set(channel->id(), channel);
+
+    ASSERT(m_inspectorFrontend);
+    bool autoconnectToWorkers = m_state->getBoolean(WorkerAgentState::autoconnectToWorkers);
+    if (autoconnectToWorkers)
+        channel->connectToWorkerContext();
+    m_inspectorFrontend->worker()->workerCreated(channel->id(), url, autoconnectToWorkers);
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/InspectorWorkerAgent.h b/Source/core/inspector/InspectorWorkerAgent.h
new file mode 100644
index 0000000..4f53b1f
--- /dev/null
+++ b/Source/core/inspector/InspectorWorkerAgent.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef InspectorWorkerAgent_h
+#define InspectorWorkerAgent_h
+
+#include "core/inspector/InspectorBaseAgent.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+class InspectorFrontend;
+class InspectorObject;
+class InspectorState;
+class InstrumentingAgents;
+class KURL;
+class WorkerContextProxy;
+
+typedef String ErrorString;
+
+class InspectorWorkerAgent : public InspectorBaseAgent<InspectorWorkerAgent>, public InspectorBackendDispatcher::WorkerCommandHandler {
+public:
+    static PassOwnPtr<InspectorWorkerAgent> create(InstrumentingAgents*, InspectorCompositeState*);
+    ~InspectorWorkerAgent();
+
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void restore();
+    virtual void clearFrontend();
+
+    // Called from InspectorInstrumentation
+    bool shouldPauseDedicatedWorkerOnStart();
+    void didStartWorkerContext(WorkerContextProxy*, const KURL&);
+    void workerContextTerminated(WorkerContextProxy*);
+
+    // Called from InspectorBackendDispatcher
+    virtual void enable(ErrorString*);
+    virtual void disable(ErrorString*);
+    virtual void canInspectWorkers(ErrorString*, bool*);
+    virtual void connectToWorker(ErrorString*, int workerId);
+    virtual void disconnectFromWorker(ErrorString*, int workerId);
+    virtual void sendMessageToWorker(ErrorString*, int workerId, const RefPtr<InspectorObject>& message);
+    virtual void setAutoconnectToWorkers(ErrorString*, bool value);
+
+private:
+    InspectorWorkerAgent(InstrumentingAgents*, InspectorCompositeState*);
+    void createWorkerFrontendChannelsForExistingWorkers();
+    void createWorkerFrontendChannel(WorkerContextProxy*, const String& url);
+    void destroyWorkerFrontendChannels();
+
+    InspectorFrontend* m_inspectorFrontend;
+
+    class WorkerFrontendChannel;
+    typedef HashMap<int, WorkerFrontendChannel*> WorkerChannels;
+    WorkerChannels m_idToChannel;
+    typedef HashMap<WorkerContextProxy*, String> DedicatedWorkers;
+    DedicatedWorkers m_dedicatedWorkers;
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorWorkerAgent_h)
diff --git a/Source/core/inspector/InspectorWorkerResource.h b/Source/core/inspector/InspectorWorkerResource.h
new file mode 100644
index 0000000..f8bed52
--- /dev/null
+++ b/Source/core/inspector/InspectorWorkerResource.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef InspectorWorkerResource_h
+#define InspectorWorkerResource_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class InspectorWorkerResource : public RefCounted<InspectorWorkerResource> {
+public:
+    static PassRefPtr<InspectorWorkerResource> create(intptr_t id, const String& url, bool isSharedWorker)
+    {
+        return adoptRef(new InspectorWorkerResource(id, url, isSharedWorker));
+    }
+
+    intptr_t id() const { return m_id; }
+    const String& url() const { return m_url; }
+    bool isSharedWorker() const { return m_isSharedWorker; }
+private:
+    InspectorWorkerResource(intptr_t id, const String& url, bool isSharedWorker)
+        : m_id(id)
+        , m_url(url)
+        , m_isSharedWorker(isSharedWorker)
+    {
+    }
+
+    intptr_t m_id;
+    String m_url;
+    bool m_isSharedWorker;
+};
+
+} // namespace WebCore
+
+#endif // InspectorWorkerResource_h
diff --git a/Source/core/inspector/InstrumentingAgents.cpp b/Source/core/inspector/InstrumentingAgents.cpp
new file mode 100644
index 0000000..0666ca9
--- /dev/null
+++ b/Source/core/inspector/InstrumentingAgents.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+#include "core/inspector/InstrumentingAgents.h"
+
+#include "core/inspector/InspectorController.h"
+#include "core/inspector/WorkerInspectorController.h"
+#include "core/page/Page.h"
+#include "core/workers/WorkerContext.h"
+#include <wtf/MainThread.h>
+
+namespace WebCore {
+
+InstrumentingAgents::InstrumentingAgents()
+    : m_inspectorAgent(0)
+    , m_inspectorPageAgent(0)
+    , m_inspectorCSSAgent(0)
+    , m_inspectorLayerTreeAgent(0)
+    , m_inspectorConsoleAgent(0)
+    , m_inspectorDOMAgent(0)
+    , m_inspectorResourceAgent(0)
+    , m_pageRuntimeAgent(0)
+    , m_workerRuntimeAgent(0)
+    , m_inspectorTimelineAgent(0)
+    , m_inspectorDOMStorageAgent(0)
+    , m_inspectorDatabaseAgent(0)
+    , m_inspectorFileSystemAgent(0)
+    , m_inspectorApplicationCacheAgent(0)
+    , m_inspectorDebuggerAgent(0)
+    , m_pageDebuggerAgent(0)
+    , m_inspectorDOMDebuggerAgent(0)
+    , m_inspectorProfilerAgent(0)
+    , m_inspectorWorkerAgent(0)
+    , m_inspectorCanvasAgent(0)
+{
+}
+
+void InstrumentingAgents::reset()
+{
+    m_inspectorAgent = 0;
+    m_inspectorPageAgent = 0;
+    m_inspectorCSSAgent = 0;
+    m_inspectorLayerTreeAgent = 0;
+    m_inspectorConsoleAgent = 0;
+    m_inspectorDOMAgent = 0;
+    m_inspectorResourceAgent = 0;
+    m_pageRuntimeAgent = 0;
+    m_workerRuntimeAgent = 0;
+    m_inspectorTimelineAgent = 0;
+    m_inspectorDOMStorageAgent = 0;
+    m_inspectorDatabaseAgent = 0;
+    m_inspectorFileSystemAgent = 0;
+    m_inspectorApplicationCacheAgent = 0;
+    m_inspectorDebuggerAgent = 0;
+    m_pageDebuggerAgent = 0;
+    m_inspectorDOMDebuggerAgent = 0;
+    m_inspectorProfilerAgent = 0;
+    m_inspectorWorkerAgent = 0;
+    m_inspectorCanvasAgent = 0;
+}
+
+InstrumentingAgents* instrumentationForPage(Page* page)
+{
+    ASSERT(isMainThread());
+    if (InspectorController* controller = page->inspectorController())
+        return controller->m_instrumentingAgents.get();
+    return 0;
+}
+
+InstrumentingAgents* instrumentationForWorkerContext(WorkerContext* workerContext)
+{
+    if (WorkerInspectorController* controller = workerContext->workerInspectorController())
+        return controller->m_instrumentingAgents.get();
+    return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/InstrumentingAgents.h b/Source/core/inspector/InstrumentingAgents.h
new file mode 100644
index 0000000..0ca9a58
--- /dev/null
+++ b/Source/core/inspector/InstrumentingAgents.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef InstrumentingAgents_h
+#define InstrumentingAgents_h
+
+#include <wtf/FastAllocBase.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class InspectorAgent;
+class InspectorApplicationCacheAgent;
+class InspectorCSSAgent;
+class InspectorCanvasAgent;
+class InspectorConsoleAgent;
+class InspectorDOMAgent;
+class InspectorDOMDebuggerAgent;
+class InspectorDOMStorageAgent;
+class InspectorDatabaseAgent;
+class InspectorDebuggerAgent;
+class InspectorFileSystemAgent;
+class InspectorHeapProfilerAgent;
+class InspectorLayerTreeAgent;
+class InspectorPageAgent;
+class InspectorProfilerAgent;
+class InspectorResourceAgent;
+class InspectorTimelineAgent;
+class InspectorWorkerAgent;
+class Page;
+class PageDebuggerAgent;
+class PageRuntimeAgent;
+class WorkerContext;
+class WorkerRuntimeAgent;
+
+class InstrumentingAgents : public RefCounted<InstrumentingAgents> {
+    WTF_MAKE_NONCOPYABLE(InstrumentingAgents);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassRefPtr<InstrumentingAgents> create()
+    {
+        return adoptRef(new InstrumentingAgents());
+    }
+    ~InstrumentingAgents() { }
+    void reset();
+
+    InspectorAgent* inspectorAgent() const { return m_inspectorAgent; }
+    void setInspectorAgent(InspectorAgent* agent) { m_inspectorAgent = agent; }
+
+    InspectorPageAgent* inspectorPageAgent() const { return m_inspectorPageAgent; }
+    void setInspectorPageAgent(InspectorPageAgent* agent) { m_inspectorPageAgent = agent; }
+
+    InspectorCSSAgent* inspectorCSSAgent() const { return m_inspectorCSSAgent; }
+    void setInspectorCSSAgent(InspectorCSSAgent* agent) { m_inspectorCSSAgent = agent; }
+
+    InspectorConsoleAgent* inspectorConsoleAgent() const { return m_inspectorConsoleAgent; }
+    void setInspectorConsoleAgent(InspectorConsoleAgent* agent) { m_inspectorConsoleAgent = agent; }
+
+    InspectorDOMAgent* inspectorDOMAgent() const { return m_inspectorDOMAgent; }
+    void setInspectorDOMAgent(InspectorDOMAgent* agent) { m_inspectorDOMAgent = agent; }
+
+    InspectorResourceAgent* inspectorResourceAgent() const { return m_inspectorResourceAgent; }
+    void setInspectorResourceAgent(InspectorResourceAgent* agent) { m_inspectorResourceAgent = agent; }
+
+    PageRuntimeAgent* pageRuntimeAgent() const { return m_pageRuntimeAgent; }
+    void setPageRuntimeAgent(PageRuntimeAgent* agent) { m_pageRuntimeAgent = agent; }
+
+    WorkerRuntimeAgent* workerRuntimeAgent() const { return m_workerRuntimeAgent; }
+    void setWorkerRuntimeAgent(WorkerRuntimeAgent* agent) { m_workerRuntimeAgent = agent; }
+
+    InspectorTimelineAgent* inspectorTimelineAgent() const { return m_inspectorTimelineAgent; }
+    void setInspectorTimelineAgent(InspectorTimelineAgent* agent) { m_inspectorTimelineAgent = agent; }
+
+    InspectorDOMStorageAgent* inspectorDOMStorageAgent() const { return m_inspectorDOMStorageAgent; }
+    void setInspectorDOMStorageAgent(InspectorDOMStorageAgent* agent) { m_inspectorDOMStorageAgent = agent; }
+
+    InspectorDatabaseAgent* inspectorDatabaseAgent() const { return m_inspectorDatabaseAgent; }
+    void setInspectorDatabaseAgent(InspectorDatabaseAgent* agent) { m_inspectorDatabaseAgent = agent; }
+
+    InspectorFileSystemAgent* inspectorFileSystemAgent() const { return m_inspectorFileSystemAgent; }
+    void setInspectorFileSystemAgent(InspectorFileSystemAgent* agent) { m_inspectorFileSystemAgent = agent; }
+
+    InspectorApplicationCacheAgent* inspectorApplicationCacheAgent() const { return m_inspectorApplicationCacheAgent; }
+    void setInspectorApplicationCacheAgent(InspectorApplicationCacheAgent* agent) { m_inspectorApplicationCacheAgent = agent; }
+
+    InspectorDebuggerAgent* inspectorDebuggerAgent() const { return m_inspectorDebuggerAgent; }
+    void setInspectorDebuggerAgent(InspectorDebuggerAgent* agent) { m_inspectorDebuggerAgent = agent; }
+
+    PageDebuggerAgent* pageDebuggerAgent() const { return m_pageDebuggerAgent; }
+    void setPageDebuggerAgent(PageDebuggerAgent* agent) { m_pageDebuggerAgent = agent; }
+
+    InspectorDOMDebuggerAgent* inspectorDOMDebuggerAgent() const { return m_inspectorDOMDebuggerAgent; }
+    void setInspectorDOMDebuggerAgent(InspectorDOMDebuggerAgent* agent) { m_inspectorDOMDebuggerAgent = agent; }
+
+    InspectorProfilerAgent* inspectorProfilerAgent() const { return m_inspectorProfilerAgent; }
+    void setInspectorProfilerAgent(InspectorProfilerAgent* agent) { m_inspectorProfilerAgent = agent; }
+
+    InspectorHeapProfilerAgent* inspectorHeapProfilerAgent() const { return m_inspectorHeapProfilerAgent; }
+    void setInspectorHeapProfilerAgent(InspectorHeapProfilerAgent* agent) { m_inspectorHeapProfilerAgent = agent; }
+
+    InspectorWorkerAgent* inspectorWorkerAgent() const { return m_inspectorWorkerAgent; }
+    void setInspectorWorkerAgent(InspectorWorkerAgent* agent) { m_inspectorWorkerAgent = agent; }
+
+    InspectorCanvasAgent* inspectorCanvasAgent() const { return m_inspectorCanvasAgent; }
+    void setInspectorCanvasAgent(InspectorCanvasAgent* agent) { m_inspectorCanvasAgent = agent; }
+
+    InspectorLayerTreeAgent* inspectorLayerTreeAgent() const { return m_inspectorLayerTreeAgent; }
+    void setInspectorLayerTreeAgent(InspectorLayerTreeAgent* agent) { m_inspectorLayerTreeAgent = agent; }
+
+private:
+    InstrumentingAgents();
+
+    InspectorAgent* m_inspectorAgent;
+    InspectorPageAgent* m_inspectorPageAgent;
+    InspectorCSSAgent* m_inspectorCSSAgent;
+    InspectorLayerTreeAgent* m_inspectorLayerTreeAgent;
+    InspectorConsoleAgent* m_inspectorConsoleAgent;
+    InspectorDOMAgent* m_inspectorDOMAgent;
+    InspectorResourceAgent* m_inspectorResourceAgent;
+    PageRuntimeAgent* m_pageRuntimeAgent;
+    WorkerRuntimeAgent* m_workerRuntimeAgent;
+    InspectorTimelineAgent* m_inspectorTimelineAgent;
+    InspectorDOMStorageAgent* m_inspectorDOMStorageAgent;
+    InspectorDatabaseAgent* m_inspectorDatabaseAgent;
+    InspectorFileSystemAgent* m_inspectorFileSystemAgent;
+    InspectorApplicationCacheAgent* m_inspectorApplicationCacheAgent;
+    InspectorDebuggerAgent* m_inspectorDebuggerAgent;
+    PageDebuggerAgent* m_pageDebuggerAgent;
+    InspectorDOMDebuggerAgent* m_inspectorDOMDebuggerAgent;
+    InspectorProfilerAgent* m_inspectorProfilerAgent;
+    InspectorHeapProfilerAgent* m_inspectorHeapProfilerAgent;
+    InspectorWorkerAgent* m_inspectorWorkerAgent;
+    InspectorCanvasAgent* m_inspectorCanvasAgent;
+};
+
+InstrumentingAgents* instrumentationForPage(Page*);
+InstrumentingAgents* instrumentationForWorkerContext(WorkerContext*);
+
+}
+
+#endif // !defined(InstrumentingAgents_h)
diff --git a/Source/core/inspector/JavaScriptCallFrame.cpp b/Source/core/inspector/JavaScriptCallFrame.cpp
new file mode 100644
index 0000000..2548acd
--- /dev/null
+++ b/Source/core/inspector/JavaScriptCallFrame.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+#include "config.h"
+#include "core/inspector/JavaScriptCallFrame.h"
+
+#include "bindings/v8/V8Binding.h"
+
+namespace WebCore {
+
+JavaScriptCallFrame::JavaScriptCallFrame(v8::Handle<v8::Context> debuggerContext, v8::Handle<v8::Object> callFrame)
+    : m_debuggerContext(debuggerContext)
+    , m_callFrame(callFrame)
+{
+}
+
+JavaScriptCallFrame::~JavaScriptCallFrame()
+{
+}
+
+JavaScriptCallFrame* JavaScriptCallFrame::caller()
+{
+    if (!m_caller) {
+        v8::HandleScope handleScope;
+        v8::Context::Scope contextScope(m_debuggerContext.get());
+        v8::Handle<v8::Value> callerFrame = m_callFrame.get()->Get(v8::String::NewSymbol("caller"));
+        if (!callerFrame->IsObject())
+            return 0;
+        m_caller = JavaScriptCallFrame::create(m_debuggerContext.get(), v8::Handle<v8::Object>::Cast(callerFrame));
+    }
+    return m_caller.get();
+}
+
+int JavaScriptCallFrame::sourceID() const
+{
+    v8::HandleScope handleScope;
+    v8::Context::Scope contextScope(m_debuggerContext.get());
+    v8::Handle<v8::Value> result = m_callFrame.get()->Get(v8::String::NewSymbol("sourceID"));
+    if (result->IsInt32())
+        return result->Int32Value();
+    return 0;
+}
+
+int JavaScriptCallFrame::line() const
+{
+    v8::HandleScope handleScope;
+    v8::Context::Scope contextScope(m_debuggerContext.get());
+    v8::Handle<v8::Value> result = m_callFrame.get()->Get(v8::String::NewSymbol("line"));
+    if (result->IsInt32())
+        return result->Int32Value();
+    return 0;
+}
+
+int JavaScriptCallFrame::column() const
+{
+    v8::HandleScope handleScope;
+    v8::Context::Scope contextScope(m_debuggerContext.get());
+    v8::Handle<v8::Value> result = m_callFrame.get()->Get(v8::String::NewSymbol("column"));
+    if (result->IsInt32())
+        return result->Int32Value();
+    return 0;
+}
+
+String JavaScriptCallFrame::functionName() const
+{
+    v8::HandleScope handleScope;
+    v8::Context::Scope contextScope(m_debuggerContext.get());
+    v8::Handle<v8::Value> result = m_callFrame.get()->Get(v8::String::NewSymbol("functionName"));
+    return toWebCoreStringWithUndefinedOrNullCheck(result);
+}
+
+v8::Handle<v8::Value> JavaScriptCallFrame::scopeChain() const
+{
+    v8::Handle<v8::Array> scopeChain = v8::Handle<v8::Array>::Cast(m_callFrame.get()->Get(v8::String::NewSymbol("scopeChain")));
+    v8::Handle<v8::Array> result = v8::Array::New(scopeChain->Length());
+    for (uint32_t i = 0; i < scopeChain->Length(); i++)
+        result->Set(i, scopeChain->Get(i));
+    return result;
+}
+
+int JavaScriptCallFrame::scopeType(int scopeIndex) const
+{
+    v8::Handle<v8::Array> scopeType = v8::Handle<v8::Array>::Cast(m_callFrame.get()->Get(v8::String::NewSymbol("scopeType")));
+    return scopeType->Get(scopeIndex)->Int32Value();
+}
+
+v8::Handle<v8::Value> JavaScriptCallFrame::thisObject() const
+{
+    return m_callFrame.get()->Get(v8::String::NewSymbol("thisObject"));
+}
+
+v8::Handle<v8::Value> JavaScriptCallFrame::evaluate(const String& expression)
+{
+    v8::Handle<v8::Function> evalFunction = v8::Handle<v8::Function>::Cast(m_callFrame.get()->Get(v8::String::NewSymbol("evaluate")));
+    v8::Handle<v8::Value> argv[] = { v8String(expression, m_debuggerContext->GetIsolate()) };
+    return evalFunction->Call(m_callFrame.get(), 1, argv);
+}
+
+v8::Handle<v8::Value> JavaScriptCallFrame::restart()
+{
+    v8::Handle<v8::Function> restartFunction = v8::Handle<v8::Function>::Cast(m_callFrame.get()->Get(v8::String::NewSymbol("restart")));
+    v8::Debug::SetLiveEditEnabled(true);
+    v8::Handle<v8::Value> result = restartFunction->Call(m_callFrame.get(), 0, 0);
+    v8::Debug::SetLiveEditEnabled(false);
+    return result;
+}
+
+v8::Handle<v8::Value> JavaScriptCallFrame::setVariableValue(int scopeNumber, const String& variableName, v8::Handle<v8::Value> newValue)
+{
+    v8::Handle<v8::Function> setVariableValueFunction = v8::Handle<v8::Function>::Cast(m_callFrame.get()->Get(v8::String::NewSymbol("setVariableValue")));
+    v8::Handle<v8::Value> argv[] = {
+        v8::Handle<v8::Value>(v8::Integer::New(scopeNumber)),
+        v8String(variableName, m_debuggerContext->GetIsolate()),
+        newValue
+    };
+    return setVariableValueFunction->Call(m_callFrame.get(), 3, argv);
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/JavaScriptCallFrame.h b/Source/core/inspector/JavaScriptCallFrame.h
new file mode 100644
index 0000000..391af77
--- /dev/null
+++ b/Source/core/inspector/JavaScriptCallFrame.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+#ifndef JavaScriptCallFrame_h
+#define JavaScriptCallFrame_h
+
+
+#include "bindings/v8/ScopedPersistent.h"
+#include <v8-debug.h>
+#include "wtf/RefCounted.h"
+#include "wtf/text/WTFString.h"
+
+namespace WebCore {
+
+class JavaScriptCallFrame : public RefCounted<JavaScriptCallFrame> {
+public:
+    static PassRefPtr<JavaScriptCallFrame> create(v8::Handle<v8::Context> debuggerContext, v8::Handle<v8::Object> callFrame)
+    {
+        return adoptRef(new JavaScriptCallFrame(debuggerContext, callFrame));
+    }
+    ~JavaScriptCallFrame();
+
+    JavaScriptCallFrame* caller();
+
+    int sourceID() const;
+    int line() const;
+    int column() const;
+    String functionName() const;
+
+    v8::Handle<v8::Value> scopeChain() const;
+    int scopeType(int scopeIndex) const;
+    v8::Handle<v8::Value> thisObject() const;
+
+    v8::Handle<v8::Value> evaluate(const String& expression);
+    v8::Handle<v8::Value> restart();
+    v8::Handle<v8::Value> setVariableValue(int scopeNumber, const String& variableName, v8::Handle<v8::Value> newValue);
+
+private:
+    JavaScriptCallFrame(v8::Handle<v8::Context> debuggerContext, v8::Handle<v8::Object> callFrame);
+
+    RefPtr<JavaScriptCallFrame> m_caller;
+    ScopedPersistent<v8::Context> m_debuggerContext;
+    ScopedPersistent<v8::Object> m_callFrame;
+};
+
+} // namespace WebCore
+
+
+#endif // JavaScriptCallFrame_h
diff --git a/Source/core/inspector/JavaScriptCallFrame.idl b/Source/core/inspector/JavaScriptCallFrame.idl
new file mode 100644
index 0000000..ebd87d4
--- /dev/null
+++ b/Source/core/inspector/JavaScriptCallFrame.idl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 Apple 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
+ */
+
+[
+    DoNotCheckConstants,
+    ImplementationLacksVTable
+] interface JavaScriptCallFrame {
+
+    // Scope type
+    const unsigned short GLOBAL_SCOPE = 0;
+    const unsigned short LOCAL_SCOPE = 1;
+    const unsigned short WITH_SCOPE = 2;
+    const unsigned short CLOSURE_SCOPE = 3;
+    const unsigned short CATCH_SCOPE = 4;
+
+    [Custom] void evaluate(DOMString script);
+    [Custom] any restart();
+    
+    // Only declarative scope (local, with and catch) is accepted. Returns undefined. 
+    [Custom] any setVariableValue(long scopeIndex, DOMString variableName, any newValue);
+
+    readonly attribute JavaScriptCallFrame caller;
+    readonly attribute long sourceID;
+    readonly attribute long line;
+    readonly attribute long column;
+    [CustomGetter] readonly attribute Array scopeChain;
+    [Custom] unsigned short scopeType(long scopeIndex);
+    [CustomGetter] readonly attribute Object thisObject;
+    readonly attribute DOMString functionName;
+    [CustomGetter] readonly attribute DOMString type;
+};
+
diff --git a/Source/core/inspector/MemoryInstrumentationImpl.cpp b/Source/core/inspector/MemoryInstrumentationImpl.cpp
new file mode 100644
index 0000000..b13bb9c
--- /dev/null
+++ b/Source/core/inspector/MemoryInstrumentationImpl.cpp
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "core/inspector/MemoryInstrumentationImpl.h"
+
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/inspector/HeapGraphSerializer.h"
+#include <wtf/Assertions.h>
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/MemoryInstrumentationHashSet.h>
+#include <wtf/MemoryInstrumentationVector.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+TypeNameToSizeMap MemoryInstrumentationClientImpl::sizesMap() const
+{
+    // TypeToSizeMap uses const char* as the key.
+    // Thus it could happen that we have two different keys with equal string.
+    TypeNameToSizeMap sizesMap;
+    for (TypeToSizeMap::const_iterator i = m_totalSizes.begin(); i != m_totalSizes.end(); ++i) {
+        String objectType(i->key);
+        TypeNameToSizeMap::AddResult result = sizesMap.add(objectType, i->value);
+        if (!result.isNewEntry)
+            result.iterator->value += i->value;
+    }
+
+    return sizesMap;
+}
+
+void MemoryInstrumentationClientImpl::countObjectSize(const void* object, MemoryObjectType objectType, size_t size)
+{
+    ASSERT(objectType);
+
+    TypeToSizeMap::AddResult result = m_totalSizes.add(objectType, size);
+    if (!result.isNewEntry)
+        result.iterator->value += size;
+    ++m_totalCountedObjects;
+
+    if (!checkInstrumentedObjects())
+        return;
+
+    if (object)
+        m_countedObjects.add(object, size);
+}
+
+bool MemoryInstrumentationClientImpl::visited(const void* object)
+{
+    return !m_visitedObjects.add(object).isNewEntry;
+}
+
+bool MemoryInstrumentationClientImpl::checkCountedObject(const void* object)
+{
+    if (!checkInstrumentedObjects())
+        return true;
+    if (!m_allocatedObjects.contains(object)) {
+        ++m_totalObjectsNotInAllocatedSet;
+        return false;
+    }
+    return true;
+}
+
+void MemoryInstrumentationClientImpl::reportNode(const MemoryObjectInfo& node)
+{
+    if (m_graphSerializer)
+        m_graphSerializer->reportNode(node);
+}
+
+void MemoryInstrumentationClientImpl::reportEdge(const void* target, const char* name, MemberType memberType)
+{
+    if (m_graphSerializer)
+        m_graphSerializer->reportEdge(target, name, memberType);
+}
+
+void MemoryInstrumentationClientImpl::reportLeaf(const MemoryObjectInfo& target, const char* edgeName)
+{
+    if (m_graphSerializer)
+        m_graphSerializer->reportLeaf(target, edgeName);
+}
+
+void MemoryInstrumentationClientImpl::reportBaseAddress(const void* base, const void* real)
+{
+    if (m_graphSerializer)
+        m_graphSerializer->reportBaseAddress(base, real);
+}
+
+int MemoryInstrumentationClientImpl::registerString(const char* string)
+{
+    if (m_graphSerializer)
+        return m_graphSerializer->registerString(string);
+    return -1;
+}
+
+void MemoryInstrumentationClientImpl::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::InspectorMemoryAgent);
+    info.addMember(m_totalSizes, "totalSizes");
+    info.addMember(m_visitedObjects, "visitedObjects");
+    info.addMember(m_allocatedObjects, "allocatedObjects");
+    info.addMember(m_countedObjects, "countedObjects");
+    info.addMember(m_graphSerializer, "graphSerializer");
+}
+
+void MemoryInstrumentationImpl::processDeferredObjects()
+{
+    while (!m_deferredObjects.isEmpty()) {
+        OwnPtr<WrapperBase> pointer = m_deferredObjects.last().release();
+        m_deferredObjects.removeLast();
+        pointer->process(this);
+    }
+}
+
+void MemoryInstrumentationImpl::deferObject(PassOwnPtr<WrapperBase> pointer)
+{
+    m_deferredObjects.append(pointer);
+}
+
+void MemoryInstrumentationImpl::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::InspectorMemoryAgent);
+    info.addMember(m_deferredObjects, "deferredObjects");
+}
+
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/MemoryInstrumentationImpl.h b/Source/core/inspector/MemoryInstrumentationImpl.h
new file mode 100644
index 0000000..aae2772
--- /dev/null
+++ b/Source/core/inspector/MemoryInstrumentationImpl.h
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+
+#ifndef MemoryInstrumentationImpl_h
+#define MemoryInstrumentationImpl_h
+
+
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/MemoryInstrumentation.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
+
+using WTF::MemoryObjectType;
+using WTF::MemberType;
+
+namespace WebCore {
+
+class HeapGraphSerializer;
+
+typedef HashSet<const void*> VisitedObjects;
+typedef HashMap<String, size_t> TypeNameToSizeMap;
+
+class MemoryInstrumentationClientImpl : public WTF::MemoryInstrumentationClient {
+public:
+    typedef HashMap<const void*, size_t> ObjectToSizeMap;
+
+    explicit MemoryInstrumentationClientImpl(HeapGraphSerializer* serializer)
+        : m_totalCountedObjects(0)
+        , m_totalObjectsNotInAllocatedSet(0)
+        , m_graphSerializer(serializer)
+    { }
+
+    size_t totalSize(MemoryObjectType objectType) const
+    {
+        TypeToSizeMap::const_iterator i = m_totalSizes.find(objectType);
+        return i == m_totalSizes.end() ? 0 : i->value;
+    }
+
+    size_t reportedSizeForAllTypes() const
+    {
+        size_t size = 0;
+        for (TypeToSizeMap::const_iterator i = m_totalSizes.begin(); i != m_totalSizes.end(); ++i)
+            size += i->value;
+        return size;
+    }
+
+    TypeNameToSizeMap sizesMap() const;
+    VisitedObjects& allocatedObjects() { return m_allocatedObjects; }
+    const ObjectToSizeMap& countedObjects() { return m_countedObjects; }
+
+    bool checkInstrumentedObjects() const { return !m_allocatedObjects.isEmpty(); }
+    size_t visitedObjects() const { return m_visitedObjects.size(); }
+    size_t totalCountedObjects() const { return m_totalCountedObjects; }
+    size_t totalObjectsNotInAllocatedSet() const { return m_totalObjectsNotInAllocatedSet; }
+
+    virtual void countObjectSize(const void*, MemoryObjectType, size_t) OVERRIDE;
+    virtual bool visited(const void*) OVERRIDE;
+    virtual bool checkCountedObject(const void*) OVERRIDE;
+    virtual void reportNode(const MemoryObjectInfo&) OVERRIDE;
+    virtual void reportEdge(const void*, const char*, MemberType) OVERRIDE;
+    virtual void reportLeaf(const MemoryObjectInfo&, const char*) OVERRIDE;
+    virtual void reportBaseAddress(const void*, const void*) OVERRIDE;
+    virtual int registerString(const char*) OVERRIDE;
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+private:
+    typedef HashMap<MemoryObjectType, size_t> TypeToSizeMap;
+    TypeToSizeMap m_totalSizes;
+    VisitedObjects m_visitedObjects;
+    VisitedObjects m_allocatedObjects;
+    ObjectToSizeMap m_countedObjects;
+    size_t m_totalCountedObjects;
+    size_t m_totalObjectsNotInAllocatedSet;
+    HeapGraphSerializer* m_graphSerializer;
+};
+
+class MemoryInstrumentationImpl : public WTF::MemoryInstrumentation {
+public:
+    explicit MemoryInstrumentationImpl(WTF::MemoryInstrumentationClient* client)
+        : MemoryInstrumentation(client)
+    {
+    }
+
+    size_t selfSize() const;
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+private:
+    virtual void deferObject(PassOwnPtr<WrapperBase>) OVERRIDE;
+    virtual void processDeferredObjects() OVERRIDE;
+
+    Vector<OwnPtr<WrapperBase> > m_deferredObjects;
+};
+
+} // namespace WebCore
+
+#endif // !defined(MemoryInstrumentationImpl_h)
+
diff --git a/Source/core/inspector/NetworkResourcesData.cpp b/Source/core/inspector/NetworkResourcesData.cpp
new file mode 100644
index 0000000..efb6932
--- /dev/null
+++ b/Source/core/inspector/NetworkResourcesData.cpp
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2011 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:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS 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 GOOGLE INC.
+ * OR ITS 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.
+ */
+
+#include "config.h"
+#include "core/inspector/NetworkResourcesData.h"
+
+#include "core/dom/DOMImplementation.h"
+#include "core/loader/TextResourceDecoder.h"
+#include "core/loader/cache/CachedResource.h"
+#include "core/platform/SharedBuffer.h"
+#include "core/platform/network/ResourceResponse.h"
+#include <wtf/MemoryInstrumentationHashMap.h>
+
+namespace {
+// 100MB
+static size_t maximumResourcesContentSize = 100 * 1000 * 1000;
+
+// 10MB
+static size_t maximumSingleResourceContentSize = 10 * 1000 * 1000;
+}
+
+namespace WebCore {
+
+
+PassRefPtr<XHRReplayData> XHRReplayData::create(const String &method, const KURL& url, bool async, PassRefPtr<FormData> formData, bool includeCredentials)
+{
+    return adoptRef(new XHRReplayData(method, url, async, formData, includeCredentials));
+}
+
+void XHRReplayData::addHeader(const AtomicString& key, const String& value)
+{
+    m_headers.set(key, value);
+}
+
+XHRReplayData::XHRReplayData(const String &method, const KURL& url, bool async, PassRefPtr<FormData> formData, bool includeCredentials)
+    : m_method(method)
+    , m_url(url)
+    , m_async(async)
+    , m_formData(formData)
+    , m_includeCredentials(includeCredentials)
+{
+}
+
+void XHRReplayData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this);
+    info.addMember(m_method, "method");
+    info.addMember(m_url, "url");
+    info.addMember(m_formData, "formData");
+    info.addMember(m_headers, "headers");
+}
+
+// ResourceData
+NetworkResourcesData::ResourceData::ResourceData(const String& requestId, const String& loaderId)
+    : m_requestId(requestId)
+    , m_loaderId(loaderId)
+    , m_base64Encoded(false)
+    , m_isContentEvicted(false)
+    , m_type(InspectorPageAgent::OtherResource)
+    , m_cachedResource(0)
+{
+}
+
+void NetworkResourcesData::ResourceData::setContent(const String& content, bool base64Encoded)
+{
+    ASSERT(!hasData());
+    ASSERT(!hasContent());
+    m_content = content;
+    m_base64Encoded = base64Encoded;
+}
+
+static size_t contentSizeInBytes(const String& content)
+{
+    return content.isNull() ? 0 : content.impl()->sizeInBytes();
+}
+
+unsigned NetworkResourcesData::ResourceData::removeContent()
+{
+    unsigned result = 0;
+    if (hasData()) {
+        ASSERT(!hasContent());
+        result = m_dataBuffer->size();
+        m_dataBuffer = nullptr;
+    }
+
+    if (hasContent()) {
+        ASSERT(!hasData());
+        result = contentSizeInBytes(m_content);
+        m_content = String();
+    }
+    return result;
+}
+
+unsigned NetworkResourcesData::ResourceData::evictContent()
+{
+    m_isContentEvicted = true;
+    return removeContent();
+}
+
+size_t NetworkResourcesData::ResourceData::dataLength() const
+{
+    return m_dataBuffer ? m_dataBuffer->size() : 0;
+}
+
+void NetworkResourcesData::ResourceData::appendData(const char* data, size_t dataLength)
+{
+    ASSERT(!hasContent());
+    if (!m_dataBuffer)
+        m_dataBuffer = SharedBuffer::create(data, dataLength);
+    else
+        m_dataBuffer->append(data, dataLength);
+}
+
+size_t NetworkResourcesData::ResourceData::decodeDataToContent()
+{
+    ASSERT(!hasContent());
+    size_t dataLength = m_dataBuffer->size();
+    m_content = m_decoder->decode(m_dataBuffer->data(), m_dataBuffer->size());
+    m_content.append(m_decoder->flush());
+    m_dataBuffer = nullptr;
+    return contentSizeInBytes(m_content) - dataLength;
+}
+
+void NetworkResourcesData::ResourceData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this);
+    info.addMember(m_requestId, "requestId");
+    info.addMember(m_loaderId, "loaderId");
+    info.addMember(m_frameId, "frameId");
+    info.addMember(m_url, "url");
+    info.addMember(m_content, "content");
+    info.addMember(m_xhrReplayData, "xhrReplayData");
+    info.addMember(m_dataBuffer, "dataBuffer");
+    info.addMember(m_textEncodingName, "textEncodingName");
+    info.addMember(m_decoder, "decoder");
+    info.addMember(m_buffer, "buffer");
+    info.addMember(m_cachedResource, "cachedResource");
+}
+
+// NetworkResourcesData
+NetworkResourcesData::NetworkResourcesData()
+    : m_contentSize(0)
+    , m_maximumResourcesContentSize(maximumResourcesContentSize)
+    , m_maximumSingleResourceContentSize(maximumSingleResourceContentSize)
+{
+}
+
+NetworkResourcesData::~NetworkResourcesData()
+{
+    clear();
+}
+
+void NetworkResourcesData::resourceCreated(const String& requestId, const String& loaderId)
+{
+    ensureNoDataForRequestId(requestId);
+    m_requestIdToResourceDataMap.set(requestId, new ResourceData(requestId, loaderId));
+}
+
+static PassRefPtr<TextResourceDecoder> createOtherResourceTextDecoder(const String& mimeType, const String& textEncodingName)
+{
+    RefPtr<TextResourceDecoder> decoder;
+    if (!textEncodingName.isEmpty())
+        decoder = TextResourceDecoder::create("text/plain", textEncodingName);
+    else if (DOMImplementation::isXMLMIMEType(mimeType.lower())) {
+        decoder = TextResourceDecoder::create("application/xml");
+        decoder->useLenientXMLDecoding();
+    } else if (equalIgnoringCase(mimeType, "text/html"))
+        decoder = TextResourceDecoder::create("text/html", "UTF-8");
+    else if (mimeType == "text/plain")
+        decoder = TextResourceDecoder::create("text/plain", "ISO-8859-1");
+    return decoder;
+}
+
+void NetworkResourcesData::responseReceived(const String& requestId, const String& frameId, const ResourceResponse& response)
+{
+    ResourceData* resourceData = resourceDataForRequestId(requestId);
+    if (!resourceData)
+        return;
+    resourceData->setFrameId(frameId);
+    resourceData->setUrl(response.url());
+    resourceData->setDecoder(createOtherResourceTextDecoder(response.mimeType(), response.textEncodingName()));
+    resourceData->setHTTPStatusCode(response.httpStatusCode());
+}
+
+void NetworkResourcesData::setResourceType(const String& requestId, InspectorPageAgent::ResourceType type)
+{
+    ResourceData* resourceData = resourceDataForRequestId(requestId);
+    if (!resourceData)
+        return;
+    resourceData->setType(type);
+}
+
+InspectorPageAgent::ResourceType NetworkResourcesData::resourceType(const String& requestId)
+{
+    ResourceData* resourceData = resourceDataForRequestId(requestId);
+    if (!resourceData)
+        return InspectorPageAgent::OtherResource;
+    return resourceData->type();
+}
+
+void NetworkResourcesData::setResourceContent(const String& requestId, const String& content, bool base64Encoded)
+{
+    ResourceData* resourceData = resourceDataForRequestId(requestId);
+    if (!resourceData)
+        return;
+    size_t dataLength = contentSizeInBytes(content);
+    if (dataLength > m_maximumSingleResourceContentSize)
+        return;
+    if (resourceData->isContentEvicted())
+        return;
+    if (ensureFreeSpace(dataLength) && !resourceData->isContentEvicted()) {
+        // We can not be sure that we didn't try to save this request data while it was loading, so remove it, if any.
+        if (resourceData->hasContent())
+            m_contentSize -= resourceData->removeContent();
+        m_requestIdsDeque.append(requestId);
+        resourceData->setContent(content, base64Encoded);
+        m_contentSize += dataLength;
+    }
+}
+
+void NetworkResourcesData::maybeAddResourceData(const String& requestId, const char* data, size_t dataLength)
+{
+    ResourceData* resourceData = resourceDataForRequestId(requestId);
+    if (!resourceData)
+        return;
+    if (!resourceData->decoder())
+        return;
+    if (resourceData->dataLength() + dataLength > m_maximumSingleResourceContentSize)
+        m_contentSize -= resourceData->evictContent();
+    if (resourceData->isContentEvicted())
+        return;
+    if (ensureFreeSpace(dataLength) && !resourceData->isContentEvicted()) {
+        m_requestIdsDeque.append(requestId);
+        resourceData->appendData(data, dataLength);
+        m_contentSize += dataLength;
+    }
+}
+
+void NetworkResourcesData::maybeDecodeDataToContent(const String& requestId)
+{
+    ResourceData* resourceData = resourceDataForRequestId(requestId);
+    if (!resourceData)
+        return;
+    if (!resourceData->hasData())
+        return;
+    m_contentSize += resourceData->decodeDataToContent();
+    size_t dataLength = contentSizeInBytes(resourceData->content());
+    if (dataLength > m_maximumSingleResourceContentSize)
+        m_contentSize -= resourceData->evictContent();
+}
+
+void NetworkResourcesData::addCachedResource(const String& requestId, CachedResource* cachedResource)
+{
+    ResourceData* resourceData = resourceDataForRequestId(requestId);
+    if (!resourceData)
+        return;
+    resourceData->setCachedResource(cachedResource);
+}
+
+void NetworkResourcesData::addResourceSharedBuffer(const String& requestId, PassRefPtr<SharedBuffer> buffer, const String& textEncodingName)
+{
+    ResourceData* resourceData = resourceDataForRequestId(requestId);
+    if (!resourceData)
+        return;
+    resourceData->setBuffer(buffer);
+    resourceData->setTextEncodingName(textEncodingName);
+}
+
+NetworkResourcesData::ResourceData const* NetworkResourcesData::data(const String& requestId)
+{
+    return resourceDataForRequestId(requestId);
+}
+
+XHRReplayData* NetworkResourcesData::xhrReplayData(const String& requestId)
+{
+    if (m_reusedXHRReplayDataRequestIds.contains(requestId))
+        return xhrReplayData(m_reusedXHRReplayDataRequestIds.get(requestId));
+
+    ResourceData* resourceData = resourceDataForRequestId(requestId);
+    if (!resourceData)
+        return 0;
+    return resourceData->xhrReplayData();
+}
+
+void NetworkResourcesData::setXHRReplayData(const String& requestId, XHRReplayData* xhrReplayData)
+{
+    ResourceData* resourceData = resourceDataForRequestId(requestId);
+    if (!resourceData) {
+        Vector<String> result;
+        ReusedRequestIds::iterator it;
+        ReusedRequestIds::iterator end = m_reusedXHRReplayDataRequestIds.end();
+        for (it = m_reusedXHRReplayDataRequestIds.begin(); it != end; ++it) {
+            if (it->value == requestId)
+                setXHRReplayData(it->key, xhrReplayData);
+        }
+        return;
+    }
+
+    resourceData->setXHRReplayData(xhrReplayData);
+}
+
+void NetworkResourcesData::reuseXHRReplayData(const String& requestId, const String& reusedRequestId)
+{
+    ResourceData* reusedResourceData = resourceDataForRequestId(reusedRequestId);
+    ResourceData* resourceData = resourceDataForRequestId(requestId);
+    if (!reusedResourceData || !resourceData) {
+        m_reusedXHRReplayDataRequestIds.set(requestId, reusedRequestId);
+        return;
+    }
+
+    resourceData->setXHRReplayData(reusedResourceData->xhrReplayData());
+}
+
+Vector<String> NetworkResourcesData::removeCachedResource(CachedResource* cachedResource)
+{
+    Vector<String> result;
+    ResourceDataMap::iterator it;
+    ResourceDataMap::iterator end = m_requestIdToResourceDataMap.end();
+    for (it = m_requestIdToResourceDataMap.begin(); it != end; ++it) {
+        ResourceData* resourceData = it->value;
+        if (resourceData->cachedResource() == cachedResource) {
+            resourceData->setCachedResource(0);
+            result.append(it->key);
+        }
+    }
+
+    return result;
+}
+
+void NetworkResourcesData::clear(const String& preservedLoaderId)
+{
+    m_requestIdsDeque.clear();
+    m_contentSize = 0;
+
+    ResourceDataMap preservedMap;
+
+    ResourceDataMap::iterator it;
+    ResourceDataMap::iterator end = m_requestIdToResourceDataMap.end();
+    for (it = m_requestIdToResourceDataMap.begin(); it != end; ++it) {
+        ResourceData* resourceData = it->value;
+        if (!preservedLoaderId.isNull() && resourceData->loaderId() == preservedLoaderId)
+            preservedMap.set(it->key, it->value);
+        else
+            delete resourceData;
+    }
+    m_requestIdToResourceDataMap.swap(preservedMap);
+
+    m_reusedXHRReplayDataRequestIds.clear();
+}
+
+void NetworkResourcesData::setResourcesDataSizeLimits(size_t maximumResourcesContentSize, size_t maximumSingleResourceContentSize)
+{
+    clear();
+    m_maximumResourcesContentSize = maximumResourcesContentSize;
+    m_maximumSingleResourceContentSize = maximumSingleResourceContentSize;
+}
+
+NetworkResourcesData::ResourceData* NetworkResourcesData::resourceDataForRequestId(const String& requestId)
+{
+    if (requestId.isNull())
+        return 0;
+    return m_requestIdToResourceDataMap.get(requestId);
+}
+
+void NetworkResourcesData::ensureNoDataForRequestId(const String& requestId)
+{
+    ResourceData* resourceData = resourceDataForRequestId(requestId);
+    if (!resourceData)
+        return;
+    if (resourceData->hasContent() || resourceData->hasData())
+        m_contentSize -= resourceData->evictContent();
+    delete resourceData;
+    m_requestIdToResourceDataMap.remove(requestId);
+}
+
+bool NetworkResourcesData::ensureFreeSpace(size_t size)
+{
+    if (size > m_maximumResourcesContentSize)
+        return false;
+
+    while (size > m_maximumResourcesContentSize - m_contentSize) {
+        String requestId = m_requestIdsDeque.takeFirst();
+        ResourceData* resourceData = resourceDataForRequestId(requestId);
+        if (resourceData)
+            m_contentSize -= resourceData->evictContent();
+    }
+    return true;
+}
+
+void NetworkResourcesData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this);
+    info.addMember(m_requestIdsDeque, "requestIdsDeque");
+    info.addMember(m_reusedXHRReplayDataRequestIds, "reusedXHRReplayDataRequestIds");
+    info.addMember(m_requestIdToResourceDataMap, "requestIdToResourceDataMap");
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/NetworkResourcesData.h b/Source/core/inspector/NetworkResourcesData.h
new file mode 100644
index 0000000..4394a91
--- /dev/null
+++ b/Source/core/inspector/NetworkResourcesData.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2011 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:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS 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 GOOGLE INC.
+ * OR ITS 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.
+ */
+
+#ifndef NetworkResourcesData_h
+#define NetworkResourcesData_h
+
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/loader/TextResourceDecoder.h"
+#include "core/platform/network/HTTPHeaderMap.h"
+#include <wtf/Deque.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/WTFString.h>
+
+
+namespace WebCore {
+
+class CachedResource;
+class FormData;
+class SharedBuffer;
+class TextResourceDecoder;
+
+class XHRReplayData : public RefCounted<XHRReplayData> {
+public:
+    static PassRefPtr<XHRReplayData> create(const String &method, const KURL&, bool async, PassRefPtr<FormData>, bool includeCredentials);
+
+    void addHeader(const AtomicString& key, const String& value);
+    const String& method() const { return m_method; }
+    const KURL& url() const { return m_url; }
+    bool async() const { return m_async; }
+    PassRefPtr<FormData> formData() const { return m_formData; }
+    const HTTPHeaderMap& headers() const { return m_headers; }
+    bool includeCredentials() const { return m_includeCredentials; }
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+private:
+    XHRReplayData(const String &method, const KURL&, bool async, PassRefPtr<FormData>, bool includeCredentials);
+
+    String m_method;
+    KURL m_url;
+    bool m_async;
+    RefPtr<FormData> m_formData;
+    HTTPHeaderMap m_headers;
+    bool m_includeCredentials;
+};
+
+class NetworkResourcesData {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    class ResourceData {
+        WTF_MAKE_FAST_ALLOCATED;
+        friend class NetworkResourcesData;
+    public:
+        ResourceData(const String& requestId, const String& loaderId);
+
+        String requestId() const { return m_requestId; }
+        String loaderId() const { return m_loaderId; }
+
+        String frameId() const { return m_frameId; }
+        void setFrameId(const String& frameId) { m_frameId = frameId; }
+
+        String url() const { return m_url; }
+        void setUrl(const String& url) { m_url = url; }
+
+        bool hasContent() const { return !m_content.isNull(); }
+        String content() const { return m_content; }
+        void setContent(const String&, bool base64Encoded);
+
+        bool base64Encoded() const { return m_base64Encoded; }
+
+        unsigned removeContent();
+        bool isContentEvicted() const { return m_isContentEvicted; }
+        unsigned evictContent();
+
+        InspectorPageAgent::ResourceType type() const { return m_type; }
+        void setType(InspectorPageAgent::ResourceType type) { m_type = type; }
+
+        int httpStatusCode() const { return m_httpStatusCode; }
+        void setHTTPStatusCode(int httpStatusCode) { m_httpStatusCode = httpStatusCode; }
+
+        String textEncodingName() const { return m_textEncodingName; }
+        void setTextEncodingName(const String& textEncodingName) { m_textEncodingName = textEncodingName; }
+
+        PassRefPtr<TextResourceDecoder> decoder() const { return m_decoder; }
+        void setDecoder(PassRefPtr<TextResourceDecoder> decoder) { m_decoder = decoder; }
+
+        PassRefPtr<SharedBuffer> buffer() const { return m_buffer; }
+        void setBuffer(PassRefPtr<SharedBuffer> buffer) { m_buffer = buffer; }
+
+        CachedResource* cachedResource() const { return m_cachedResource; }
+        void setCachedResource(CachedResource* cachedResource) { m_cachedResource = cachedResource; }
+
+        XHRReplayData* xhrReplayData() const { return m_xhrReplayData.get(); }
+        void setXHRReplayData(XHRReplayData* xhrReplayData) { m_xhrReplayData = xhrReplayData; }
+
+        void reportMemoryUsage(MemoryObjectInfo*) const;
+
+    private:
+        bool hasData() const { return m_dataBuffer; }
+        size_t dataLength() const;
+        void appendData(const char* data, size_t dataLength);
+        size_t decodeDataToContent();
+
+        String m_requestId;
+        String m_loaderId;
+        String m_frameId;
+        String m_url;
+        String m_content;
+        RefPtr<XHRReplayData> m_xhrReplayData;
+        bool m_base64Encoded;
+        RefPtr<SharedBuffer> m_dataBuffer;
+        bool m_isContentEvicted;
+        InspectorPageAgent::ResourceType m_type;
+        int m_httpStatusCode;
+
+        String m_textEncodingName;
+        RefPtr<TextResourceDecoder> m_decoder;
+
+        RefPtr<SharedBuffer> m_buffer;
+        CachedResource* m_cachedResource;
+    };
+
+    NetworkResourcesData();
+
+    ~NetworkResourcesData();
+
+    void resourceCreated(const String& requestId, const String& loaderId);
+    void responseReceived(const String& requestId, const String& frameId, const ResourceResponse&);
+    void setResourceType(const String& requestId, InspectorPageAgent::ResourceType);
+    InspectorPageAgent::ResourceType resourceType(const String& requestId);
+    void setResourceContent(const String& requestId, const String& content, bool base64Encoded = false);
+    void maybeAddResourceData(const String& requestId, const char* data, size_t dataLength);
+    void maybeDecodeDataToContent(const String& requestId);
+    void addCachedResource(const String& requestId, CachedResource*);
+    void addResourceSharedBuffer(const String& requestId, PassRefPtr<SharedBuffer>, const String& textEncodingName);
+    ResourceData const* data(const String& requestId);
+    Vector<String> removeCachedResource(CachedResource*);
+    void clear(const String& preservedLoaderId = String());
+
+    void setResourcesDataSizeLimits(size_t maximumResourcesContentSize, size_t maximumSingleResourceContentSize);
+    void setXHRReplayData(const String& requestId, XHRReplayData*);
+    void reuseXHRReplayData(const String& requestId, const String& reusedRequestId);
+    XHRReplayData* xhrReplayData(const String& requestId);
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+private:
+    ResourceData* resourceDataForRequestId(const String& requestId);
+    void ensureNoDataForRequestId(const String& requestId);
+    bool ensureFreeSpace(size_t);
+
+    Deque<String> m_requestIdsDeque;
+
+    typedef HashMap<String, String> ReusedRequestIds;
+    ReusedRequestIds m_reusedXHRReplayDataRequestIds;
+    typedef HashMap<String, ResourceData*> ResourceDataMap;
+    ResourceDataMap m_requestIdToResourceDataMap;
+    size_t m_contentSize;
+    size_t m_maximumResourcesContentSize;
+    size_t m_maximumSingleResourceContentSize;
+};
+
+} // namespace WebCore
+
+
+#endif // !defined(NetworkResourcesData_h)
diff --git a/Source/core/inspector/PageConsoleAgent.cpp b/Source/core/inspector/PageConsoleAgent.cpp
new file mode 100644
index 0000000..2caee57
--- /dev/null
+++ b/Source/core/inspector/PageConsoleAgent.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+#include "core/inspector/PageConsoleAgent.h"
+
+#include "bindings/v8/ScriptObject.h"
+#include "core/dom/Node.h"
+#include "core/inspector/InjectedScriptHost.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/InspectorAgent.h"
+#include "core/inspector/InspectorDOMAgent.h"
+#include "core/page/DOMWindow.h"
+
+namespace WebCore {
+
+PageConsoleAgent::PageConsoleAgent(InstrumentingAgents* instrumentingAgents, InspectorAgent* inspectorAgent, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager, InspectorDOMAgent* domAgent)
+    : InspectorConsoleAgent(instrumentingAgents, state, injectedScriptManager)
+    , m_inspectorAgent(inspectorAgent)
+    , m_inspectorDOMAgent(domAgent)
+{
+}
+
+PageConsoleAgent::~PageConsoleAgent()
+{
+    m_inspectorAgent = 0;
+    m_inspectorDOMAgent = 0;
+}
+
+void PageConsoleAgent::clearMessages(ErrorString* errorString)
+{
+    m_inspectorDOMAgent->releaseDanglingNodes();
+    InspectorConsoleAgent::clearMessages(errorString);
+}
+
+class InspectableNode : public InjectedScriptHost::InspectableObject {
+public:
+    explicit InspectableNode(Node* node) : m_node(node) { }
+    virtual ScriptValue get(ScriptState* state)
+    {
+        return InjectedScriptHost::nodeAsScriptValue(state, m_node);
+    }
+private:
+    Node* m_node;
+};
+
+void PageConsoleAgent::addInspectedNode(ErrorString* errorString, int nodeId)
+{
+    Node* node = m_inspectorDOMAgent->nodeForId(nodeId);
+    if (!node || node->isInShadowTree()) {
+        *errorString = "nodeId is not valid";
+        return;
+    }
+    m_injectedScriptManager->injectedScriptHost()->addInspectedObject(adoptPtr(new InspectableNode(node)));
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/PageConsoleAgent.h b/Source/core/inspector/PageConsoleAgent.h
new file mode 100644
index 0000000..13607b9
--- /dev/null
+++ b/Source/core/inspector/PageConsoleAgent.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef PageConsoleAgent_h
+#define PageConsoleAgent_h
+
+#include "core/inspector/InspectorConsoleAgent.h"
+#include <wtf/PassOwnPtr.h>
+
+
+namespace WebCore {
+
+class InspectorAgent;
+class InspectorDOMAgent;
+
+class PageConsoleAgent : public InspectorConsoleAgent {
+    WTF_MAKE_NONCOPYABLE(PageConsoleAgent);
+public:
+    static PassOwnPtr<PageConsoleAgent> create(InstrumentingAgents* instrumentingAgents, InspectorAgent* agent, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager, InspectorDOMAgent* domAgent)
+    {
+        return adoptPtr(new PageConsoleAgent(instrumentingAgents, agent, state, injectedScriptManager, domAgent));
+    }
+    virtual ~PageConsoleAgent();
+
+    virtual bool isWorkerAgent() OVERRIDE { return false; }
+
+private:
+    PageConsoleAgent(InstrumentingAgents*, InspectorAgent*, InspectorCompositeState*, InjectedScriptManager*, InspectorDOMAgent*);
+    virtual void clearMessages(ErrorString*);
+    virtual void addInspectedNode(ErrorString*, int nodeId);
+
+    InspectorAgent* m_inspectorAgent;
+    InspectorDOMAgent* m_inspectorDOMAgent;
+};
+
+} // namespace WebCore
+
+
+#endif // !defined(PageConsoleAgent_h)
diff --git a/Source/core/inspector/PageDebuggerAgent.cpp b/Source/core/inspector/PageDebuggerAgent.cpp
new file mode 100644
index 0000000..f108a37
--- /dev/null
+++ b/Source/core/inspector/PageDebuggerAgent.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+#include "core/inspector/PageDebuggerAgent.h"
+
+#include "bindings/v8/PageScriptDebugServer.h"
+#include "core/inspector/InspectorOverlay.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/page/Page.h"
+#include "core/page/PageConsole.h"
+
+namespace WebCore {
+
+PassOwnPtr<PageDebuggerAgent> PageDebuggerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, InspectorPageAgent* pageAgent, InjectedScriptManager* injectedScriptManager, InspectorOverlay* overlay)
+{
+    return adoptPtr(new PageDebuggerAgent(instrumentingAgents, inspectorState, pageAgent, injectedScriptManager, overlay));
+}
+
+PageDebuggerAgent::PageDebuggerAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, InspectorPageAgent* pageAgent, InjectedScriptManager* injectedScriptManager, InspectorOverlay* overlay)
+    : InspectorDebuggerAgent(instrumentingAgents, inspectorState, injectedScriptManager)
+    , m_pageAgent(pageAgent)
+    , m_overlay(overlay)
+{
+}
+
+PageDebuggerAgent::~PageDebuggerAgent()
+{
+}
+
+void PageDebuggerAgent::enable()
+{
+    InspectorDebuggerAgent::enable();
+    m_instrumentingAgents->setPageDebuggerAgent(this);
+}
+
+void PageDebuggerAgent::disable()
+{
+    InspectorDebuggerAgent::disable();
+    m_instrumentingAgents->setPageDebuggerAgent(0);
+}
+
+void PageDebuggerAgent::startListeningScriptDebugServer()
+{
+    scriptDebugServer().addListener(this, m_pageAgent->page());
+}
+
+void PageDebuggerAgent::stopListeningScriptDebugServer()
+{
+    scriptDebugServer().removeListener(this, m_pageAgent->page());
+}
+
+PageScriptDebugServer& PageDebuggerAgent::scriptDebugServer()
+{
+    return PageScriptDebugServer::shared();
+}
+
+void PageDebuggerAgent::muteConsole()
+{
+    PageConsole::mute();
+}
+
+void PageDebuggerAgent::unmuteConsole()
+{
+    PageConsole::unmute();
+}
+
+InjectedScript PageDebuggerAgent::injectedScriptForEval(ErrorString* errorString, const int* executionContextId)
+{
+    if (!executionContextId) {
+        ScriptState* scriptState = mainWorldScriptState(m_pageAgent->mainFrame());
+        return injectedScriptManager()->injectedScriptFor(scriptState);
+    }
+    InjectedScript injectedScript = injectedScriptManager()->injectedScriptForId(*executionContextId);
+    if (injectedScript.hasNoValue())
+        *errorString = "Execution context with given id not found.";
+    return injectedScript;
+}
+
+void PageDebuggerAgent::setOverlayMessage(ErrorString*, const String* message)
+{
+    m_overlay->setPausedInDebuggerMessage(message);
+}
+
+void PageDebuggerAgent::didClearMainFrameWindowObject()
+{
+    reset();
+    scriptDebugServer().setScriptPreprocessor(m_pageAgent->scriptPreprocessor());
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/PageDebuggerAgent.h b/Source/core/inspector/PageDebuggerAgent.h
new file mode 100644
index 0000000..61d0a0a
--- /dev/null
+++ b/Source/core/inspector/PageDebuggerAgent.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef PageDebuggerAgent_h
+#define PageDebuggerAgent_h
+
+#include "bindings/v8/PageScriptDebugServer.h"
+#include "core/inspector/InspectorDebuggerAgent.h"
+
+namespace WebCore {
+
+class InspectorOverlay;
+class InspectorPageAgent;
+class Page;
+class PageScriptDebugServer;
+
+class PageDebuggerAgent : public InspectorDebuggerAgent {
+    WTF_MAKE_NONCOPYABLE(PageDebuggerAgent);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<PageDebuggerAgent> create(InstrumentingAgents*, InspectorCompositeState*, InspectorPageAgent*, InjectedScriptManager*, InspectorOverlay*);
+    virtual ~PageDebuggerAgent();
+
+    void didClearMainFrameWindowObject();
+
+protected:
+    virtual void enable();
+    virtual void disable();
+
+private:
+    virtual void startListeningScriptDebugServer();
+    virtual void stopListeningScriptDebugServer();
+    virtual PageScriptDebugServer& scriptDebugServer();
+    virtual void muteConsole();
+    virtual void unmuteConsole();
+
+    virtual InjectedScript injectedScriptForEval(ErrorString*, const int* executionContextId);
+    virtual void setOverlayMessage(ErrorString*, const String*);
+
+    PageDebuggerAgent(InstrumentingAgents*, InspectorCompositeState*, InspectorPageAgent*, InjectedScriptManager*, InspectorOverlay*);
+    InspectorPageAgent* m_pageAgent;
+    InspectorOverlay* m_overlay;
+};
+
+} // namespace WebCore
+
+
+#endif // !defined(PageDebuggerAgent_h)
diff --git a/Source/core/inspector/PageRuntimeAgent.cpp b/Source/core/inspector/PageRuntimeAgent.cpp
new file mode 100644
index 0000000..37e7ed5
--- /dev/null
+++ b/Source/core/inspector/PageRuntimeAgent.cpp
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+#include "core/inspector/PageRuntimeAgent.h"
+
+#include "bindings/v8/ScriptController.h"
+#include "core/dom/Document.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/InspectorPageAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/page/Page.h"
+#include "core/page/PageConsole.h"
+#include "core/page/SecurityOrigin.h"
+
+using WebCore::TypeBuilder::Runtime::ExecutionContextDescription;
+
+namespace WebCore {
+
+namespace PageRuntimeAgentState {
+static const char runtimeEnabled[] = "runtimeEnabled";
+};
+
+PageRuntimeAgent::PageRuntimeAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager, Page* page, InspectorPageAgent* pageAgent)
+    : InspectorRuntimeAgent(instrumentingAgents, state, injectedScriptManager)
+    , m_inspectedPage(page)
+    , m_pageAgent(pageAgent)
+    , m_frontend(0)
+    , m_mainWorldContextCreated(false)
+{
+    m_instrumentingAgents->setPageRuntimeAgent(this);
+}
+
+PageRuntimeAgent::~PageRuntimeAgent()
+{
+    m_instrumentingAgents->setPageRuntimeAgent(0);
+}
+
+void PageRuntimeAgent::setFrontend(InspectorFrontend* frontend)
+{
+    m_frontend = frontend->runtime();
+}
+
+void PageRuntimeAgent::clearFrontend()
+{
+    m_frontend = 0;
+    String errorString;
+    disable(&errorString);
+}
+
+void PageRuntimeAgent::restore()
+{
+    if (m_state->getBoolean(PageRuntimeAgentState::runtimeEnabled)) {
+        String error;
+        enable(&error);
+    }
+}
+
+void PageRuntimeAgent::enable(ErrorString* errorString)
+{
+    if (m_enabled)
+        return;
+
+    InspectorRuntimeAgent::enable(errorString);
+    m_state->setBoolean(PageRuntimeAgentState::runtimeEnabled, true);
+    // Only report existing contexts if the page did commit load, otherwise we may
+    // unintentionally initialize contexts in the frames which may trigger some listeners
+    // that are expected to be triggered only after the load is committed, see http://crbug.com/131623
+    if (m_mainWorldContextCreated)
+        reportExecutionContextCreation();
+}
+
+void PageRuntimeAgent::disable(ErrorString* errorString)
+{
+    if (!m_enabled)
+        return;
+
+    InspectorRuntimeAgent::disable(errorString);
+    m_state->setBoolean(PageRuntimeAgentState::runtimeEnabled, false);
+}
+
+void PageRuntimeAgent::didCreateMainWorldContext(Frame* frame)
+{
+    m_mainWorldContextCreated = true;
+
+    if (!m_enabled)
+        return;
+    ASSERT(m_frontend);
+    String frameId = m_pageAgent->frameId(frame);
+    ScriptState* scriptState = mainWorldScriptState(frame);
+    notifyContextCreated(frameId, scriptState, 0, true);
+}
+
+void PageRuntimeAgent::didCreateIsolatedContext(Frame* frame, ScriptState* scriptState, SecurityOrigin* origin)
+{
+    if (!m_enabled)
+        return;
+    ASSERT(m_frontend);
+    String frameId = m_pageAgent->frameId(frame);
+    notifyContextCreated(frameId, scriptState, origin, false);
+}
+
+InjectedScript PageRuntimeAgent::injectedScriptForEval(ErrorString* errorString, const int* executionContextId)
+{
+    if (!executionContextId) {
+        ScriptState* scriptState = mainWorldScriptState(m_inspectedPage->mainFrame());
+        InjectedScript result = injectedScriptManager()->injectedScriptFor(scriptState);
+        if (result.hasNoValue())
+            *errorString = "Internal error: main world execution context not found.";
+        return result;
+    }
+    InjectedScript injectedScript = injectedScriptManager()->injectedScriptForId(*executionContextId);
+    if (injectedScript.hasNoValue())
+        *errorString = "Execution context with given id not found.";
+    return injectedScript;
+}
+
+void PageRuntimeAgent::muteConsole()
+{
+    PageConsole::mute();
+}
+
+void PageRuntimeAgent::unmuteConsole()
+{
+    PageConsole::unmute();
+}
+
+void PageRuntimeAgent::reportExecutionContextCreation()
+{
+    Vector<std::pair<ScriptState*, SecurityOrigin*> > isolatedContexts;
+    for (Frame* frame = m_inspectedPage->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
+        if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript))
+            continue;
+        String frameId = m_pageAgent->frameId(frame);
+
+        ScriptState* scriptState = mainWorldScriptState(frame);
+        notifyContextCreated(frameId, scriptState, 0, true);
+        frame->script()->collectIsolatedContexts(isolatedContexts);
+        if (isolatedContexts.isEmpty())
+            continue;
+        for (size_t i = 0; i< isolatedContexts.size(); i++)
+            notifyContextCreated(frameId, isolatedContexts[i].first, isolatedContexts[i].second, false);
+        isolatedContexts.clear();
+    }
+}
+
+void PageRuntimeAgent::notifyContextCreated(const String& frameId, ScriptState* scriptState, SecurityOrigin* securityOrigin, bool isPageContext)
+{
+    ASSERT(securityOrigin || isPageContext);
+    int executionContextId = injectedScriptManager()->injectedScriptIdFor(scriptState);
+    String name = securityOrigin ? securityOrigin->toRawString() : "";
+    m_frontend->executionContextCreated(ExecutionContextDescription::create()
+        .setId(executionContextId)
+        .setIsPageContext(isPageContext)
+        .setName(name)
+        .setFrameId(frameId)
+        .release());
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/PageRuntimeAgent.h b/Source/core/inspector/PageRuntimeAgent.h
new file mode 100644
index 0000000..bdf131a
--- /dev/null
+++ b/Source/core/inspector/PageRuntimeAgent.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef PageRuntimeAgent_h
+#define PageRuntimeAgent_h
+
+
+#include "InspectorFrontend.h"
+#include "bindings/v8/ScriptState.h"
+#include "core/inspector/InspectorRuntimeAgent.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class InspectorPageAgent;
+class Page;
+class SecurityOrigin;
+
+class PageRuntimeAgent : public InspectorRuntimeAgent {
+public:
+    static PassOwnPtr<PageRuntimeAgent> create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager, Page* page, InspectorPageAgent* pageAgent)
+    {
+        return adoptPtr(new PageRuntimeAgent(instrumentingAgents, state, injectedScriptManager, page, pageAgent));
+    }
+    virtual ~PageRuntimeAgent();
+    virtual void setFrontend(InspectorFrontend*);
+    virtual void clearFrontend();
+    virtual void restore();
+    virtual void enable(ErrorString*);
+    virtual void disable(ErrorString*);
+
+    void didCreateMainWorldContext(Frame*);
+    void didCreateIsolatedContext(Frame*, ScriptState*, SecurityOrigin*);
+
+private:
+    PageRuntimeAgent(InstrumentingAgents*, InspectorCompositeState*, InjectedScriptManager*, Page*, InspectorPageAgent*);
+
+    virtual InjectedScript injectedScriptForEval(ErrorString*, const int* executionContextId);
+    virtual void muteConsole();
+    virtual void unmuteConsole();
+    void reportExecutionContextCreation();
+    void notifyContextCreated(const String& frameId, ScriptState*, SecurityOrigin*, bool isPageContext);
+
+    Page* m_inspectedPage;
+    InspectorPageAgent* m_pageAgent;
+    InspectorFrontend::Runtime* m_frontend;
+    bool m_mainWorldContextCreated;
+};
+
+} // namespace WebCore
+
+
+#endif // !defined(InspectorPagerAgent_h)
diff --git a/Source/core/inspector/ScriptArguments.cpp b/Source/core/inspector/ScriptArguments.cpp
new file mode 100644
index 0000000..516cd04
--- /dev/null
+++ b/Source/core/inspector/ScriptArguments.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2010 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.
+ */
+
+#include "config.h"
+#include "core/inspector/ScriptArguments.h"
+
+#include "bindings/v8/ScriptValue.h"
+
+namespace WebCore {
+
+PassRefPtr<ScriptArguments> ScriptArguments::create(ScriptState* scriptState, Vector<ScriptValue>& arguments)
+{
+    return adoptRef(new ScriptArguments(scriptState, arguments));
+}
+
+ScriptArguments::ScriptArguments(ScriptState* scriptState, Vector<ScriptValue>& arguments)
+    : m_scriptState(scriptState)
+{
+    m_arguments.swap(arguments);
+}
+
+ScriptArguments::~ScriptArguments()
+{
+}
+
+const ScriptValue &ScriptArguments::argumentAt(size_t index) const
+{
+    ASSERT(m_arguments.size() > index);
+    return m_arguments[index];
+}
+
+ScriptState* ScriptArguments::globalState() const
+{
+    return m_scriptState.get();
+}
+
+bool ScriptArguments::getFirstArgumentAsString(String& result, bool checkForNullOrUndefined)
+{
+    if (!argumentCount())
+        return false;
+
+    const ScriptValue& value = argumentAt(0);
+    if (checkForNullOrUndefined && (value.isNull() || value.isUndefined()))
+        return false;
+
+    if (!globalState()) {
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
+    result = value.toString(globalState());
+    return true;
+}
+
+bool ScriptArguments::isEqual(ScriptArguments* other) const
+{
+    if (!other)
+        return false;
+
+    if (m_arguments.size() != other->m_arguments.size())
+        return false;
+    if (!globalState() && m_arguments.size())
+        return false;
+
+    for (size_t i = 0; i < m_arguments.size(); ++i) {
+        if (!m_arguments[i].isEqual(other->globalState(), other->m_arguments[i]))
+            return false;
+    }
+    return true;
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/ScriptArguments.h b/Source/core/inspector/ScriptArguments.h
new file mode 100644
index 0000000..e8d5443
--- /dev/null
+++ b/Source/core/inspector/ScriptArguments.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 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.
+ */
+
+#ifndef ScriptArguments_h
+#define ScriptArguments_h
+
+#include "bindings/v8/ScriptState.h"
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class ScriptValue;
+
+class ScriptArguments : public RefCounted<ScriptArguments> {
+public:
+    static PassRefPtr<ScriptArguments> create(ScriptState*, Vector<ScriptValue>& arguments);
+
+    ~ScriptArguments();
+
+    const ScriptValue& argumentAt(size_t) const;
+    size_t argumentCount() const { return m_arguments.size(); }
+
+    ScriptState* globalState() const;
+
+    bool getFirstArgumentAsString(WTF::String& result, bool checkForNullOrUndefined = false);
+    bool isEqual(ScriptArguments*) const;
+
+private:
+    ScriptArguments(ScriptState*, Vector<ScriptValue>& arguments);
+
+    ScriptStateProtectedPtr m_scriptState;
+    Vector<ScriptValue> m_arguments;
+};
+
+} // namespace WebCore
+
+#endif // ScriptArguments_h
diff --git a/Source/core/inspector/ScriptBreakpoint.h b/Source/core/inspector/ScriptBreakpoint.h
new file mode 100644
index 0000000..11e8d51
--- /dev/null
+++ b/Source/core/inspector/ScriptBreakpoint.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef ScriptBreakpoint_h
+#define ScriptBreakpoint_h
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+struct ScriptBreakpoint {
+    ScriptBreakpoint()
+    {
+    }
+
+    ScriptBreakpoint(int lineNumber, int columnNumber, const String& condition)
+        : lineNumber(lineNumber)
+        , columnNumber(columnNumber)
+        , condition(condition)
+    {
+    }
+
+    int lineNumber;
+    int columnNumber;
+    String condition;
+};
+
+} // namespace WebCore
+
+#endif // !defined(ScriptBreakpoint_h)
diff --git a/Source/core/inspector/ScriptCallFrame.cpp b/Source/core/inspector/ScriptCallFrame.cpp
new file mode 100644
index 0000000..67a3c12
--- /dev/null
+++ b/Source/core/inspector/ScriptCallFrame.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010 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.
+ */
+
+#include "config.h"
+#include "core/inspector/ScriptCallFrame.h"
+
+#include "InspectorFrontend.h"
+#include "core/inspector/InspectorValues.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+ScriptCallFrame::ScriptCallFrame(const String& functionName, const String& scriptName, unsigned lineNumber, unsigned column)
+    : m_functionName(functionName)
+    , m_scriptName(scriptName)
+    , m_lineNumber(lineNumber)
+    , m_column(column)
+{
+}
+
+ScriptCallFrame::~ScriptCallFrame()
+{
+}
+
+bool ScriptCallFrame::isEqual(const ScriptCallFrame& o) const
+{
+    return m_functionName == o.m_functionName
+        && m_scriptName == o.m_scriptName
+        && m_lineNumber == o.m_lineNumber;
+}
+
+PassRefPtr<TypeBuilder::Console::CallFrame> ScriptCallFrame::buildInspectorObject() const
+{
+    return TypeBuilder::Console::CallFrame::create()
+        .setFunctionName(m_functionName)
+        .setUrl(m_scriptName)
+        .setLineNumber(m_lineNumber)
+        .setColumnNumber(m_column)
+        .release();
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/ScriptCallFrame.h b/Source/core/inspector/ScriptCallFrame.h
new file mode 100644
index 0000000..93fc006
--- /dev/null
+++ b/Source/core/inspector/ScriptCallFrame.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2010 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.
+ */
+
+#ifndef ScriptCallFrame_h
+#define ScriptCallFrame_h
+
+#include "InspectorTypeBuilder.h"
+
+#include <wtf/Forward.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class InspectorObject;
+
+class ScriptCallFrame  {
+public:
+    ScriptCallFrame(const String& functionName, const String& scriptName, unsigned lineNumber, unsigned column = 0);
+    ~ScriptCallFrame();
+
+    const String& functionName() const { return m_functionName; }
+    const String& sourceURL() const { return m_scriptName; }
+    unsigned lineNumber() const { return m_lineNumber; }
+    unsigned columnNumber() const { return m_column; }
+
+    bool isEqual(const ScriptCallFrame&) const;
+
+    PassRefPtr<TypeBuilder::Console::CallFrame> buildInspectorObject() const;
+
+private:
+    String m_functionName;
+    String m_scriptName;
+    unsigned m_lineNumber;
+    unsigned m_column;
+};
+
+} // namespace WebCore
+
+#endif // ScriptCallFrame_h
diff --git a/Source/core/inspector/ScriptCallStack.cpp b/Source/core/inspector/ScriptCallStack.cpp
new file mode 100644
index 0000000..bc72ddc
--- /dev/null
+++ b/Source/core/inspector/ScriptCallStack.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2008, 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.
+ */
+
+#include "config.h"
+#include "core/inspector/ScriptCallStack.h"
+
+#include "InspectorTypeBuilder.h"
+#include "core/inspector/InspectorValues.h"
+
+namespace WebCore {
+
+PassRefPtr<ScriptCallStack> ScriptCallStack::create(Vector<ScriptCallFrame>& frames)
+{
+    return adoptRef(new ScriptCallStack(frames));
+}
+
+ScriptCallStack::ScriptCallStack(Vector<ScriptCallFrame>& frames)
+{
+    m_frames.swap(frames);
+}
+
+ScriptCallStack::~ScriptCallStack()
+{
+}
+
+const ScriptCallFrame &ScriptCallStack::at(size_t index) const
+{
+    ASSERT(m_frames.size() > index);
+    return m_frames[index];
+}
+
+size_t ScriptCallStack::size() const
+{
+    return m_frames.size();
+}
+
+bool ScriptCallStack::isEqual(ScriptCallStack* o) const
+{
+    if (!o)
+        return false;
+
+    size_t frameCount = o->m_frames.size();
+    if (frameCount != m_frames.size())
+        return false;
+
+    for (size_t i = 0; i < frameCount; ++i) {
+        if (!m_frames[i].isEqual(o->m_frames[i]))
+            return false;
+    }
+
+    return true;
+}
+
+PassRefPtr<TypeBuilder::Array<TypeBuilder::Console::CallFrame> > ScriptCallStack::buildInspectorArray() const
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::Console::CallFrame> > frames = TypeBuilder::Array<TypeBuilder::Console::CallFrame>::create();
+    for (size_t i = 0; i < m_frames.size(); i++)
+        frames->addItem(m_frames.at(i).buildInspectorObject());
+    return frames;
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/ScriptCallStack.h b/Source/core/inspector/ScriptCallStack.h
new file mode 100644
index 0000000..3796fe1
--- /dev/null
+++ b/Source/core/inspector/ScriptCallStack.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2008, 2010 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.
+ */
+
+#ifndef ScriptCallStack_h
+#define ScriptCallStack_h
+
+#include "InspectorTypeBuilder.h"
+
+#include "core/inspector/ScriptCallFrame.h"
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class InspectorArray;
+
+class ScriptCallStack : public RefCounted<ScriptCallStack> {
+public:
+    static const size_t maxCallStackSizeToCapture = 200;
+    
+    static PassRefPtr<ScriptCallStack> create(Vector<ScriptCallFrame>&);
+
+    ~ScriptCallStack();
+
+    const ScriptCallFrame &at(size_t) const;
+    size_t size() const;
+
+    bool isEqual(ScriptCallStack*) const;
+
+    PassRefPtr<TypeBuilder::Array<TypeBuilder::Console::CallFrame> > buildInspectorArray() const;
+
+private:
+    ScriptCallStack(Vector<ScriptCallFrame>&);
+
+    Vector<ScriptCallFrame> m_frames;
+};
+
+} // namespace WebCore
+
+#endif // ScriptCallStack_h
diff --git a/Source/core/inspector/ScriptDebugListener.h b/Source/core/inspector/ScriptDebugListener.h
new file mode 100644
index 0000000..ae76fdf
--- /dev/null
+++ b/Source/core/inspector/ScriptDebugListener.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 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:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+
+#ifndef ScriptDebugListener_h
+#define ScriptDebugListener_h
+
+
+#include "bindings/v8/ScriptState.h"
+#include <wtf/Forward.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+class ScriptValue;
+
+class ScriptDebugListener {
+public:
+    class Script {
+    public:
+        Script()
+            : startLine(0)
+            , startColumn(0)
+            , endLine(0)
+            , endColumn(0)
+            , isContentScript(false)
+        {
+        }
+
+        String url;
+        String source;
+        String sourceMappingURL;
+        int startLine;
+        int startColumn;
+        int endLine;
+        int endColumn;
+        bool isContentScript;
+
+        void reportMemoryUsage(MemoryObjectInfo*) const;
+    };
+
+    virtual ~ScriptDebugListener() { }
+
+    virtual void didParseSource(const String& scriptId, const Script&) = 0;
+    virtual void failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage) = 0;
+    virtual void didPause(ScriptState*, const ScriptValue& callFrames, const ScriptValue& exception) = 0;
+    virtual void didContinue() = 0;
+};
+
+} // namespace WebCore
+
+
+#endif // ScriptDebugListener_h
diff --git a/Source/core/inspector/ScriptGCEventListener.h b/Source/core/inspector/ScriptGCEventListener.h
new file mode 100644
index 0000000..5f8a18f
--- /dev/null
+++ b/Source/core/inspector/ScriptGCEventListener.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef ScriptGCEventListener_h
+#define ScriptGCEventListener_h
+
+
+namespace WebCore {
+
+class ScriptGCEventListener
+{
+public:
+    virtual void didGC(double startTime, double endTime, size_t collectedBytes) = 0;
+    virtual ~ScriptGCEventListener(){}
+};
+    
+} // namespace WebCore
+
+#endif // !defined(ScriptGCEventListener_h)
diff --git a/Source/core/inspector/ScriptProfile.cpp b/Source/core/inspector/ScriptProfile.cpp
new file mode 100644
index 0000000..ff5a02d
--- /dev/null
+++ b/Source/core/inspector/ScriptProfile.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+#include "config.h"
+#include "core/inspector/ScriptProfile.h"
+
+#include "bindings/v8/V8Binding.h"
+#include "core/inspector/InspectorValues.h"
+#include <v8-profiler.h>
+#include "wtf/PassRefPtr.h"
+#include "wtf/RefPtr.h"
+
+namespace WebCore {
+
+ScriptProfile::~ScriptProfile()
+{
+    const_cast<v8::CpuProfile*>(m_profile)->Delete();
+}
+
+String ScriptProfile::title() const
+{
+    v8::HandleScope scope;
+    return toWebCoreString(m_profile->GetTitle());
+}
+
+unsigned int ScriptProfile::uid() const
+{
+    return m_profile->GetUid();
+}
+
+PassRefPtr<ScriptProfileNode> ScriptProfile::head() const
+{
+    return ScriptProfileNode::create(m_profile->GetTopDownRoot());
+}
+
+double ScriptProfile::idleTime() const
+{
+    return m_idleTime;
+}
+
+static PassRefPtr<TypeBuilder::Profiler::CPUProfileNode> buildInspectorObjectFor(const v8::CpuProfileNode* node)
+{
+    v8::HandleScope handleScope;
+
+    RefPtr<TypeBuilder::Array<TypeBuilder::Profiler::CPUProfileNode> > children = TypeBuilder::Array<TypeBuilder::Profiler::CPUProfileNode>::create();
+    const int childrenCount = node->GetChildrenCount();
+    for (int i = 0; i < childrenCount; i++) {
+        const v8::CpuProfileNode* child = node->GetChild(i);
+        children->addItem(buildInspectorObjectFor(child));
+    }
+
+    RefPtr<TypeBuilder::Profiler::CPUProfileNode> result = TypeBuilder::Profiler::CPUProfileNode::create()
+        .setFunctionName(toWebCoreString(node->GetFunctionName()))
+        .setUrl(toWebCoreString(node->GetScriptResourceName()))
+        .setLineNumber(node->GetLineNumber())
+        .setTotalTime(node->GetTotalTime())
+        .setSelfTime(node->GetSelfTime())
+        .setNumberOfCalls(0)
+        .setVisible(true)
+        .setCallUID(node->GetCallUid())
+        .setChildren(children.release());
+    result->setId(node->GetNodeId());
+    return result.release();
+}
+
+PassRefPtr<TypeBuilder::Profiler::CPUProfileNode> ScriptProfile::buildInspectorObjectForHead() const
+{
+    return buildInspectorObjectFor(m_profile->GetTopDownRoot());
+}
+
+PassRefPtr<TypeBuilder::Array<int> > ScriptProfile::buildInspectorObjectForSamples() const
+{
+    RefPtr<TypeBuilder::Array<int> > array = TypeBuilder::Array<int>::create();
+    int count = m_profile->GetSamplesCount();
+    for (int i = 0; i < count; i++)
+        array->addItem(m_profile->GetSample(i)->GetNodeId());
+    return array.release();
+}
+
+
+} // namespace WebCore
diff --git a/Source/core/inspector/ScriptProfile.h b/Source/core/inspector/ScriptProfile.h
new file mode 100644
index 0000000..de86412
--- /dev/null
+++ b/Source/core/inspector/ScriptProfile.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+#ifndef ScriptProfile_h
+#define ScriptProfile_h
+
+#include "InspectorTypeBuilder.h"
+#include "core/inspector/ScriptProfileNode.h"
+#include "wtf/RefCounted.h"
+#include "wtf/text/WTFString.h"
+
+namespace v8 {
+class CpuProfile;
+}
+
+namespace WebCore {
+
+class InspectorObject;
+
+class ScriptProfile : public RefCounted<ScriptProfile> {
+public:
+    static PassRefPtr<ScriptProfile> create(const v8::CpuProfile* profile, double idleTime)
+    {
+        return adoptRef(new ScriptProfile(profile, idleTime));
+    }
+    virtual ~ScriptProfile();
+
+    String title() const;
+    unsigned int uid() const;
+    PassRefPtr<ScriptProfileNode> head() const;
+    double idleTime() const;
+
+    PassRefPtr<TypeBuilder::Profiler::CPUProfileNode> buildInspectorObjectForHead() const;
+    PassRefPtr<TypeBuilder::Array<int> > buildInspectorObjectForSamples() const;
+
+private:
+    ScriptProfile(const v8::CpuProfile* profile, double idleTime)
+        : m_profile(profile)
+        , m_idleTime(idleTime)
+    {}
+
+    const v8::CpuProfile* m_profile;
+    double m_idleTime;
+};
+
+} // namespace WebCore
+
+#endif // ScriptProfile_h
diff --git a/Source/core/inspector/ScriptProfile.idl b/Source/core/inspector/ScriptProfile.idl
new file mode 100644
index 0000000..8569aae
--- /dev/null
+++ b/Source/core/inspector/ScriptProfile.idl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+
+[
+] interface ScriptProfile {
+    readonly attribute DOMString title;
+    readonly attribute unsigned long uid;
+    readonly attribute ScriptProfileNode head;
+    readonly attribute double idleTime;
+};
+
diff --git a/Source/core/inspector/ScriptProfileNode.cpp b/Source/core/inspector/ScriptProfileNode.cpp
new file mode 100644
index 0000000..782dc05
--- /dev/null
+++ b/Source/core/inspector/ScriptProfileNode.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+#include "config.h"
+#include "core/inspector/ScriptProfileNode.h"
+
+#include "bindings/v8/V8Binding.h"
+
+#include <v8-profiler.h>
+
+namespace WebCore {
+
+String ScriptProfileNode::functionName() const
+{
+    return toWebCoreString(m_profileNode->GetFunctionName());
+}
+
+String ScriptProfileNode::url() const
+{
+    return toWebCoreString(m_profileNode->GetScriptResourceName());
+}
+
+unsigned long ScriptProfileNode::lineNumber() const
+{
+    return m_profileNode->GetLineNumber();
+}
+
+double ScriptProfileNode::totalTime() const
+{
+    return m_profileNode->GetTotalTime();
+}
+
+double ScriptProfileNode::selfTime() const
+{
+    return m_profileNode->GetSelfTime();
+}
+
+unsigned long ScriptProfileNode::numberOfCalls() const
+{
+    return 0;
+}
+
+ProfileNodesList ScriptProfileNode::children() const
+{
+    const int childrenCount = m_profileNode->GetChildrenCount();
+    ProfileNodesList result(childrenCount);
+    for (int i = 0; i < childrenCount; ++i)
+        result[i] = ScriptProfileNode::create(m_profileNode->GetChild(i));
+    return result;
+}
+
+bool ScriptProfileNode::visible() const
+{
+    return true;
+}
+
+unsigned long ScriptProfileNode::callUID() const
+{
+    return m_profileNode->GetCallUid();
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/ScriptProfileNode.h b/Source/core/inspector/ScriptProfileNode.h
new file mode 100644
index 0000000..d2fb117
--- /dev/null
+++ b/Source/core/inspector/ScriptProfileNode.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+#ifndef ScriptProfileNode_h
+#define ScriptProfileNode_h
+
+#include "wtf/RefCounted.h"
+#include "wtf/text/WTFString.h"
+
+namespace v8 {
+class CpuProfileNode;
+}
+
+namespace WebCore {
+
+class ScriptProfileNode;
+
+typedef Vector<RefPtr<ScriptProfileNode> > ProfileNodesList;
+
+class ScriptProfileNode : public RefCounted<ScriptProfileNode> {
+public:
+    static PassRefPtr<ScriptProfileNode> create(const v8::CpuProfileNode* profileNode)
+    {
+        return adoptRef(new ScriptProfileNode(profileNode));
+    }
+    virtual ~ScriptProfileNode() {}
+
+    String functionName() const;
+    String url() const;
+    unsigned long lineNumber() const;
+    double totalTime() const;
+    double selfTime() const;
+    unsigned long numberOfCalls() const;
+    ProfileNodesList children() const;
+    bool visible() const;
+    unsigned long callUID() const;
+
+protected:
+    ScriptProfileNode(const v8::CpuProfileNode* profileNode)
+        : m_profileNode(profileNode)
+    {}
+
+private:
+    const v8::CpuProfileNode* m_profileNode;
+};
+
+} // namespace WebCore
+
+#endif // ScriptProfileNode_h
diff --git a/Source/core/inspector/ScriptProfileNode.idl b/Source/core/inspector/ScriptProfileNode.idl
new file mode 100644
index 0000000..de7bc62
--- /dev/null
+++ b/Source/core/inspector/ScriptProfileNode.idl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+
+[
+] interface ScriptProfileNode {
+    readonly attribute DOMString functionName;
+    readonly attribute DOMString url;
+    readonly attribute unsigned long lineNumber;
+    readonly attribute double totalTime;
+    readonly attribute double selfTime;
+    readonly attribute unsigned long numberOfCalls;
+    sequence<ScriptProfileNode> children();
+    readonly attribute boolean visible;
+    readonly attribute unsigned long callUID;
+};
+
diff --git a/Source/core/inspector/TimelineRecordFactory.cpp b/Source/core/inspector/TimelineRecordFactory.cpp
new file mode 100644
index 0000000..e82ce1a
--- /dev/null
+++ b/Source/core/inspector/TimelineRecordFactory.cpp
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#include "config.h"
+#include "core/inspector/TimelineRecordFactory.h"
+
+#include "bindings/v8/ScriptCallStackFactory.h"
+#include "core/dom/Event.h"
+#include "core/inspector/InspectorValues.h"
+#include "core/inspector/ScriptCallStack.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/IntRect.h"
+#include "core/platform/graphics/LayoutRect.h"
+#include "core/platform/network/ResourceRequest.h"
+#include "core/platform/network/ResourceResponse.h"
+#include <wtf/CurrentTime.h>
+
+namespace WebCore {
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createGenericRecord(double startTime, int maxCallStackDepth)
+{
+    RefPtr<InspectorObject> record = InspectorObject::create();
+    record->setNumber("startTime", startTime);
+
+    if (maxCallStackDepth) {
+        RefPtr<ScriptCallStack> stackTrace = createScriptCallStack(maxCallStackDepth, true);
+        if (stackTrace && stackTrace->size())
+            record->setValue("stackTrace", stackTrace->buildInspectorArray());
+    }
+    return record.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createBackgroundRecord(double startTime, const String& threadName)
+{
+    RefPtr<InspectorObject> record = InspectorObject::create();
+    record->setNumber("startTime", startTime);
+    record->setString("thread", threadName);
+    return record.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createGCEventData(const size_t usedHeapSizeDelta)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setNumber("usedHeapSizeDelta", usedHeapSizeDelta);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createFunctionCallData(const String& scriptName, int scriptLine)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setString("scriptName", scriptName);
+    data->setNumber("scriptLine", scriptLine);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createEventDispatchData(const Event& event)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setString("type", event.type().string());
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createGenericTimerData(int timerId)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setNumber("timerId", timerId);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createTimerInstallData(int timerId, int timeout, bool singleShot)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setNumber("timerId", timerId);
+    data->setNumber("timeout", timeout);
+    data->setBoolean("singleShot", singleShot);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createXHRReadyStateChangeData(const String& url, int readyState)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setString("url", url);
+    data->setNumber("readyState", readyState);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createXHRLoadData(const String& url)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setString("url", url);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createEvaluateScriptData(const String& url, double lineNumber)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setString("url", url);
+    data->setNumber("lineNumber", lineNumber);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createTimeStampData(const String& message)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setString("message", message);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createScheduleResourceRequestData(const String& url)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setString("url", url);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createResourceSendRequestData(const String& requestId, const ResourceRequest& request)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setString("requestId", requestId);
+    data->setString("url", request.url().string());
+    data->setString("requestMethod", request.httpMethod());
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createResourceReceiveResponseData(const String& requestId, const ResourceResponse& response)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setString("requestId", requestId);
+    data->setNumber("statusCode", response.httpStatusCode());
+    data->setString("mimeType", response.mimeType());
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createResourceFinishData(const String& requestId, bool didFail, double finishTime)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setString("requestId", requestId);
+    data->setBoolean("didFail", didFail);
+    if (finishTime)
+        data->setNumber("networkTime", finishTime);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createReceiveResourceData(const String& requestId, int length)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setString("requestId", requestId);
+    data->setNumber("encodedDataLength", length);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createLayoutData(unsigned dirtyObjects, unsigned totalObjects, bool partialLayout)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setNumber("dirtyObjects", dirtyObjects);
+    data->setNumber("totalObjects", totalObjects);
+    data->setBoolean("partialLayout", partialLayout);
+    return data.release();
+}
+    
+PassRefPtr<InspectorObject> TimelineRecordFactory::createDecodeImageData(const String& imageType)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setString("imageType", imageType);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createResizeImageData(bool shouldCache)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setBoolean("cached", shouldCache);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createMarkData(bool isMainFrame)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setBoolean("isMainFrame", isMainFrame);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createParseHTMLData(unsigned startLine)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setNumber("startLine", startLine);
+    return data.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createAnimationFrameData(int callbackId)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setNumber("id", callbackId);
+    return data.release();
+}
+
+static PassRefPtr<InspectorArray> createQuad(const FloatQuad& quad)
+{
+    RefPtr<InspectorArray> array = InspectorArray::create();
+    array->pushNumber(quad.p1().x());
+    array->pushNumber(quad.p1().y());
+    array->pushNumber(quad.p2().x());
+    array->pushNumber(quad.p2().y());
+    array->pushNumber(quad.p3().x());
+    array->pushNumber(quad.p3().y());
+    array->pushNumber(quad.p4().x());
+    array->pushNumber(quad.p4().y());
+    return array.release();
+}
+
+PassRefPtr<InspectorObject> TimelineRecordFactory::createPaintData(const FloatQuad& quad)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setArray("clip", createQuad(quad));
+    return data.release();
+}
+
+void TimelineRecordFactory::appendLayoutRoot(InspectorObject* data, const FloatQuad& quad)
+{
+    data->setArray("root", createQuad(quad));
+}
+
+void TimelineRecordFactory::appendStyleRecalcDetails(InspectorObject* data, unsigned elementCount)
+{
+    data->setNumber("elementCount", elementCount);
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/TimelineRecordFactory.h b/Source/core/inspector/TimelineRecordFactory.h
new file mode 100644
index 0000000..e13b61e
--- /dev/null
+++ b/Source/core/inspector/TimelineRecordFactory.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+ 
+#ifndef TimelineRecordFactory_h
+#define TimelineRecordFactory_h
+
+#include "core/inspector/InspectorValues.h"
+#include "core/platform/KURL.h"
+#include "core/platform/graphics/LayoutRect.h"
+#include <wtf/Forward.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+    class Event;
+    class FloatQuad;
+    class InspectorFrontend;
+    class InspectorObject;
+    class IntRect;
+    class ResourceRequest;
+    class ResourceResponse;
+
+    class TimelineRecordFactory {
+    public:
+        static PassRefPtr<InspectorObject> createGenericRecord(double startTime, int maxCallStackDepth);
+        static PassRefPtr<InspectorObject> createBackgroundRecord(double startTime, const String& thread);
+
+        static PassRefPtr<InspectorObject> createGCEventData(const size_t usedHeapSizeDelta);
+
+        static PassRefPtr<InspectorObject> createFunctionCallData(const String& scriptName, int scriptLine);
+
+        static PassRefPtr<InspectorObject> createEventDispatchData(const Event&);
+
+        static PassRefPtr<InspectorObject> createGenericTimerData(int timerId);
+
+        static PassRefPtr<InspectorObject> createTimerInstallData(int timerId, int timeout, bool singleShot);
+
+        static PassRefPtr<InspectorObject> createXHRReadyStateChangeData(const String& url, int readyState);
+
+        static PassRefPtr<InspectorObject> createXHRLoadData(const String& url);
+
+        static PassRefPtr<InspectorObject> createEvaluateScriptData(const String&, double lineNumber);
+
+        static PassRefPtr<InspectorObject> createTimeStampData(const String&);
+
+        static PassRefPtr<InspectorObject> createResourceSendRequestData(const String& requestId, const ResourceRequest&);
+
+        static PassRefPtr<InspectorObject> createScheduleResourceRequestData(const String&);
+
+        static PassRefPtr<InspectorObject> createResourceReceiveResponseData(const String& requestId, const ResourceResponse&);
+
+        static PassRefPtr<InspectorObject> createReceiveResourceData(const String& requestId, int length);
+
+        static PassRefPtr<InspectorObject> createResourceFinishData(const String& requestId, bool didFail, double finishTime);
+
+        static PassRefPtr<InspectorObject> createLayoutData(unsigned dirtyObjects, unsigned totalObjects, bool partialLayout);
+
+        static PassRefPtr<InspectorObject> createDecodeImageData(const String& imageType);
+
+        static PassRefPtr<InspectorObject> createResizeImageData(bool shouldCache);
+
+        static PassRefPtr<InspectorObject> createMarkData(bool isMainFrame);
+
+        static PassRefPtr<InspectorObject> createParseHTMLData(unsigned startLine);
+
+        static PassRefPtr<InspectorObject> createAnimationFrameData(int callbackId);
+
+        static PassRefPtr<InspectorObject> createPaintData(const FloatQuad&);
+
+        static void appendLayoutRoot(InspectorObject* data, const FloatQuad&);
+
+        static void appendStyleRecalcDetails(InspectorObject* data, unsigned elementCount);
+
+        static inline PassRefPtr<InspectorObject> createWebSocketCreateData(unsigned long identifier, const KURL& url, const String& protocol)
+        {
+            RefPtr<InspectorObject> data = InspectorObject::create();
+            data->setNumber("identifier", identifier);
+            data->setString("url", url.string());
+            if (!protocol.isNull())
+                data->setString("webSocketProtocol", protocol);
+            return data.release();
+        }
+
+        static inline PassRefPtr<InspectorObject> createGenericWebSocketData(unsigned long identifier)
+        {
+            RefPtr<InspectorObject> data = InspectorObject::create();
+            data->setNumber("identifier", identifier);
+            return data.release();
+        }
+    private:
+        TimelineRecordFactory() { }
+    };
+
+} // namespace WebCore
+
+#endif // !defined(TimelineRecordFactory_h)
diff --git a/Source/core/inspector/TimelineTraceEventProcessor.cpp b/Source/core/inspector/TimelineTraceEventProcessor.cpp
new file mode 100644
index 0000000..83550b9
--- /dev/null
+++ b/Source/core/inspector/TimelineTraceEventProcessor.cpp
@@ -0,0 +1,323 @@
+/*
+* Copyright (C) 2013 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.
+*/
+
+#include "config.h"
+#include "core/inspector/TimelineTraceEventProcessor.h"
+
+#include "core/inspector/InspectorClient.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/TimelineRecordFactory.h"
+
+#include <wtf/CurrentTime.h>
+#include <wtf/MainThread.h>
+#include <wtf/ThreadSpecific.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+namespace {
+
+class TraceEventDispatcher {
+    WTF_MAKE_NONCOPYABLE(TraceEventDispatcher);
+public:
+    static TraceEventDispatcher* instance()
+    {
+        DEFINE_STATIC_LOCAL(TraceEventDispatcher, instance, ());
+        return &instance;
+    }
+
+    void addProcessor(TimelineTraceEventProcessor* processor, InspectorClient* client)
+    {
+        MutexLocker locker(m_mutex);
+
+        m_processors.append(processor);
+        if (m_processors.size() == 1)
+            client->setTraceEventCallback(dispatchEventOnAnyThread);
+    }
+
+    void removeProcessor(TimelineTraceEventProcessor* processor, InspectorClient* client)
+    {
+        MutexLocker locker(m_mutex);
+
+        size_t index = m_processors.find(processor);
+        if (index == notFound) {
+            ASSERT_NOT_REACHED();
+            return;
+        }
+        m_processors.remove(index);
+        if (m_processors.isEmpty())
+            client->setTraceEventCallback(0);
+    }
+
+private:
+    TraceEventDispatcher() { }
+
+    static void dispatchEventOnAnyThread(char phase, const unsigned char*, const char* name, unsigned long long id,
+        int numArgs, const char* const* argNames, const unsigned char* argTypes, const unsigned long long* argValues,
+        unsigned char flags)
+    {
+        TraceEventDispatcher* self = instance();
+        Vector<RefPtr<TimelineTraceEventProcessor> > processors;
+        {
+            MutexLocker locker(self->m_mutex);
+            processors = self->m_processors;
+        }
+        for (int i = 0, size = processors.size(); i < size; ++i) {
+            processors[i]->processEventOnAnyThread(static_cast<TimelineTraceEventProcessor::TraceEventPhase>(phase),
+                name, id, numArgs, argNames, argTypes, argValues, flags);
+        }
+    }
+
+    Mutex m_mutex;
+    Vector<RefPtr<TimelineTraceEventProcessor> > m_processors;
+};
+
+} // namespce
+
+
+TimelineRecordStack::TimelineRecordStack(WeakPtr<InspectorTimelineAgent> timelineAgent)
+    : m_timelineAgent(timelineAgent)
+{
+}
+
+void TimelineRecordStack::addScopedRecord(PassRefPtr<InspectorObject> record)
+{
+    m_stack.append(Entry(record));
+}
+
+void TimelineRecordStack::closeScopedRecord(double endTime)
+{
+    if (m_stack.isEmpty())
+        return;
+    Entry last = m_stack.last();
+    m_stack.removeLast();
+    last.record->setNumber("endTime", endTime);
+    if (last.children->length())
+        last.record->setArray("children", last.children);
+    addInstantRecord(last.record);
+}
+
+void TimelineRecordStack::addInstantRecord(PassRefPtr<InspectorObject> record)
+{
+    if (m_stack.isEmpty())
+        send(record);
+    else
+        m_stack.last().children->pushObject(record);
+}
+
+#ifndef NDEBUG
+bool TimelineRecordStack::isOpenRecordOfType(const String& type)
+{
+    String lastRecordType;
+    return m_stack.isEmpty() || (m_stack.last().record->getString("type", &lastRecordType) && type == lastRecordType);
+}
+#endif
+
+void TimelineRecordStack::send(PassRefPtr<InspectorObject> record)
+{
+    InspectorTimelineAgent* timelineAgent = m_timelineAgent.get();
+    if (!timelineAgent)
+        return;
+    timelineAgent->sendEvent(record);
+}
+
+TimelineTraceEventProcessor::TimelineTraceEventProcessor(WeakPtr<InspectorTimelineAgent> timelineAgent, InspectorClient *client)
+    : m_timelineAgent(timelineAgent)
+    , m_timeConverter(timelineAgent.get()->timeConverter())
+    , m_inspectorClient(client)
+    , m_pageId(reinterpret_cast<unsigned long long>(m_timelineAgent.get()->page()))
+    , m_layerId(0)
+{
+    registerHandler(InstrumentationEvents::BeginFrame, TracePhaseInstant, &TimelineTraceEventProcessor::onBeginFrame);
+    registerHandler(InstrumentationEvents::PaintLayer, TracePhaseBegin, &TimelineTraceEventProcessor::onPaintLayerBegin);
+    registerHandler(InstrumentationEvents::PaintLayer, TracePhaseEnd, &TimelineTraceEventProcessor::onPaintLayerEnd);
+    registerHandler(InstrumentationEvents::RasterTask, TracePhaseBegin, &TimelineTraceEventProcessor::onRasterTaskBegin);
+    registerHandler(InstrumentationEvents::RasterTask, TracePhaseEnd, &TimelineTraceEventProcessor::onRasterTaskEnd);
+    registerHandler(InstrumentationEvents::Layer, TracePhaseDeleteObject, &TimelineTraceEventProcessor::onLayerDeleted);
+    registerHandler(InstrumentationEvents::Paint, TracePhaseInstant, &TimelineTraceEventProcessor::onPaint);
+    registerHandler(PlatformInstrumentation::ImageDecodeEvent, TracePhaseBegin, &TimelineTraceEventProcessor::onImageDecodeBegin);
+    registerHandler(PlatformInstrumentation::ImageDecodeEvent, TracePhaseEnd, &TimelineTraceEventProcessor::onImageDecodeEnd);
+
+    TraceEventDispatcher::instance()->addProcessor(this, m_inspectorClient);
+}
+
+TimelineTraceEventProcessor::~TimelineTraceEventProcessor()
+{
+}
+
+void TimelineTraceEventProcessor::registerHandler(const char* name, TraceEventPhase phase, TraceEventHandler handler)
+{
+    m_handlersByType.set(std::make_pair(name, phase), handler);
+}
+
+void TimelineTraceEventProcessor::shutdown()
+{
+    TraceEventDispatcher::instance()->removeProcessor(this, m_inspectorClient);
+}
+
+size_t TimelineTraceEventProcessor::TraceEvent::findParameter(const char* name) const
+{
+    for (int i = 0; i < m_argumentCount; ++i) {
+        if (!strcmp(name, m_argumentNames[i]))
+            return i;
+    }
+    return notFound;
+}
+
+const TimelineTraceEventProcessor::TraceValueUnion& TimelineTraceEventProcessor::TraceEvent::parameter(const char* name, TraceValueTypes expectedType) const
+{
+    static TraceValueUnion missingValue;
+    size_t index = findParameter(name);
+    if (index == notFound || m_argumentTypes[index] != expectedType) {
+        ASSERT_NOT_REACHED();
+        return missingValue;
+    }
+    return *reinterpret_cast<const TraceValueUnion*>(m_argumentValues + index);
+}
+
+void TimelineTraceEventProcessor::processEventOnAnyThread(TraceEventPhase phase, const char* name, unsigned long long id,
+    int numArgs, const char* const* argNames, const unsigned char* argTypes, const unsigned long long* argValues,
+    unsigned char)
+{
+    HandlersMap::iterator it = m_handlersByType.find(std::make_pair(name, phase));
+    if (it == m_handlersByType.end())
+        return;
+
+    TraceEvent event(WTF::monotonicallyIncreasingTime(), phase, name, id, currentThread(), numArgs, argNames, argTypes, argValues);
+
+    if (!isMainThread()) {
+        MutexLocker locker(m_backgroundEventsMutex);
+        m_backgroundEvents.append(event);
+        return;
+    }
+    (this->*(it->value))(event);
+}
+
+void TimelineTraceEventProcessor::onBeginFrame(const TraceEvent&)
+{
+    processBackgroundEvents();
+}
+
+void TimelineTraceEventProcessor::onPaintLayerBegin(const TraceEvent& event)
+{
+    m_layerId = event.asUInt(InstrumentationEventArguments::LayerId);
+    ASSERT(m_layerId);
+}
+
+void TimelineTraceEventProcessor::onPaintLayerEnd(const TraceEvent&)
+{
+    m_layerId = 0;
+}
+
+void TimelineTraceEventProcessor::onRasterTaskBegin(const TraceEvent& event)
+{
+    unsigned long long layerId = event.asUInt(InstrumentationEventArguments::LayerId);
+    if (!m_knownLayers.contains(layerId))
+        return;
+    TimelineThreadState& state = threadState(event.threadIdentifier());
+    ASSERT(!state.inRasterizeEvent);
+    state.inRasterizeEvent = true;
+    RefPtr<InspectorObject> record = createRecord(event, TimelineRecordType::Rasterize);
+    state.recordStack.addScopedRecord(record.release());
+}
+
+void TimelineTraceEventProcessor::onRasterTaskEnd(const TraceEvent& event)
+{
+    TimelineThreadState& state = threadState(event.threadIdentifier());
+    if (!state.inRasterizeEvent)
+        return;
+    ASSERT(state.recordStack.isOpenRecordOfType(TimelineRecordType::Rasterize));
+    state.recordStack.closeScopedRecord(m_timeConverter.fromMonotonicallyIncreasingTime(event.timestamp()));
+    state.inRasterizeEvent = false;
+}
+
+void TimelineTraceEventProcessor::onImageDecodeBegin(const TraceEvent& event)
+{
+    TimelineThreadState& state = threadState(event.threadIdentifier());
+    if (!state.inRasterizeEvent)
+        return;
+    state.recordStack.addScopedRecord(createRecord(event, TimelineRecordType::DecodeImage));
+}
+
+void TimelineTraceEventProcessor::onImageDecodeEnd(const TraceEvent& event)
+{
+    TimelineThreadState& state = threadState(event.threadIdentifier());
+    if (!state.inRasterizeEvent)
+        return;
+    ASSERT(state.recordStack.isOpenRecordOfType(TimelineRecordType::DecodeImage));
+    state.recordStack.closeScopedRecord(m_timeConverter.fromMonotonicallyIncreasingTime(event.timestamp()));
+}
+
+void TimelineTraceEventProcessor::onLayerDeleted(const TraceEvent& event)
+{
+    unsigned long long id = event.id();
+    ASSERT(id);
+    processBackgroundEvents();
+    m_knownLayers.remove(id);
+}
+
+void TimelineTraceEventProcessor::onPaint(const TraceEvent& event)
+{
+    if (!m_layerId)
+        return;
+
+    unsigned long long pageId = event.asUInt(InstrumentationEventArguments::PageId);
+    if (pageId == m_pageId)
+        m_knownLayers.add(m_layerId);
+}
+
+PassRefPtr<InspectorObject> TimelineTraceEventProcessor::createRecord(const TraceEvent& event, const String& recordType, PassRefPtr<InspectorObject> data)
+{
+    double startTime = m_timeConverter.fromMonotonicallyIncreasingTime(event.timestamp());
+    RefPtr<InspectorObject> record = TimelineRecordFactory::createBackgroundRecord(startTime, String::number(event.threadIdentifier()));
+    record->setString("type", recordType);
+    record->setObject("data", data ? data : InspectorObject::create());
+    return record.release();
+}
+
+void TimelineTraceEventProcessor::processBackgroundEvents()
+{
+    ASSERT(isMainThread());
+    Vector<TraceEvent> events;
+    {
+        MutexLocker locker(m_backgroundEventsMutex);
+        events.reserveCapacity(m_backgroundEvents.capacity());
+        m_backgroundEvents.swap(events);
+    }
+    for (size_t i = 0, size = events.size(); i < size; ++i) {
+        const TraceEvent& event = events[i];
+        HandlersMap::iterator it = m_handlersByType.find(std::make_pair(event.name(), event.phase()));
+        ASSERT(it != m_handlersByType.end() && it->value);
+        (this->*(it->value))(event);
+    }
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/inspector/TimelineTraceEventProcessor.h b/Source/core/inspector/TimelineTraceEventProcessor.h
new file mode 100644
index 0000000..67760d2
--- /dev/null
+++ b/Source/core/inspector/TimelineTraceEventProcessor.h
@@ -0,0 +1,260 @@
+/*
+* Copyright (C) 2013 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.
+*/
+
+#ifndef TimelineTraceEventProcessor_h
+#define TimelineTraceEventProcessor_h
+
+
+#include "core/inspector/InspectorTimelineAgent.h"
+#include "core/inspector/InspectorValues.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Threading.h>
+#include <wtf/Vector.h>
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+
+class InspectorClient;
+class InspectorTimelineAgent;
+class Page;
+
+class TimelineRecordStack {
+private:
+    struct Entry {
+        Entry(PassRefPtr<InspectorObject> record)
+            : record(record)
+            , children(InspectorArray::create())
+        {
+        }
+
+        RefPtr<InspectorObject> record;
+        RefPtr<InspectorArray> children;
+    };
+
+public:
+    TimelineRecordStack() { }
+    TimelineRecordStack(WeakPtr<InspectorTimelineAgent>);
+
+    void addScopedRecord(PassRefPtr<InspectorObject> record);
+    void closeScopedRecord(double endTime);
+    void addInstantRecord(PassRefPtr<InspectorObject> record);
+
+#ifndef NDEBUG
+    bool isOpenRecordOfType(const String& type);
+#endif
+
+private:
+    void send(PassRefPtr<InspectorObject>);
+
+    WeakPtr<InspectorTimelineAgent> m_timelineAgent;
+    Vector<Entry> m_stack;
+};
+
+class TimelineTraceEventProcessor : public ThreadSafeRefCounted<TimelineTraceEventProcessor> {
+public:
+    // FIXME: re-use definitions in TraceEvent.h once it's promoted to all platforms.
+    enum TraceEventPhase {
+        TracePhaseBegin = 'B',
+        TracePhaseEnd = 'E',
+        TracePhaseInstant = 'I',
+        TracePhaseCreateObject = 'N',
+        TracePhaseDeleteObject = 'D'
+    };
+
+    TimelineTraceEventProcessor(WeakPtr<InspectorTimelineAgent>, InspectorClient*);
+    ~TimelineTraceEventProcessor();
+
+    void shutdown();
+    void processEventOnAnyThread(TraceEventPhase, const char* name, unsigned long long id,
+        int numArgs, const char* const* argNames, const unsigned char* argTypes, const unsigned long long* argValues,
+        unsigned char flags);
+
+private:
+    // FIXME: use the definition in TraceEvent.h once we expose the latter to all plaforms.
+    union TraceValueUnion {
+        bool m_bool;
+        unsigned long long m_uint;
+        long long m_int;
+        double m_double;
+        const void* m_pointer;
+        const char* m_string;
+    };
+
+    enum TraceValueTypes {
+        TypeBool = 1,
+        TypeUInt = 2,
+        TypeInt = 3,
+        TypeDouble = 4,
+        TypePointer = 5,
+        TypeString = 6,
+        TypeCopyString = 7
+    };
+
+    struct TimelineThreadState {
+        TimelineThreadState() { }
+
+        TimelineThreadState(WeakPtr<InspectorTimelineAgent> timelineAgent)
+            : recordStack(timelineAgent)
+            , inRasterizeEvent(false)
+        {
+        }
+
+        TimelineRecordStack recordStack;
+        bool inRasterizeEvent;
+    };
+
+    class TraceEvent {
+    public:
+        TraceEvent()
+            : m_name(0)
+            , m_argumentCount(0)
+        {
+        }
+
+        TraceEvent(double timestamp, TraceEventPhase phase, const char* name, unsigned long long id, ThreadIdentifier threadIdentifier,
+            int argumentCount, const char* const* argumentNames, const unsigned char* argumentTypes, const unsigned long long* argumentValues)
+            : m_timestamp(timestamp)
+            , m_phase(phase)
+            , m_name(name)
+            , m_id(id)
+            , m_threadIdentifier(threadIdentifier)
+            , m_argumentCount(argumentCount)
+        {
+            if (m_argumentCount > MaxArguments) {
+                ASSERT_NOT_REACHED();
+                m_argumentCount = MaxArguments;
+            }
+            for (int i = 0; i < m_argumentCount; ++i) {
+                m_argumentNames[i] = argumentNames[i];
+                m_argumentTypes[i] = argumentTypes[i];
+                m_argumentValues[i] = argumentValues[i];
+            }
+        }
+
+        double timestamp() const { return m_timestamp; }
+        TraceEventPhase phase() const { return m_phase; }
+        const char* name() const { return m_name; }
+        unsigned long long id() const { return m_id; }
+        ThreadIdentifier threadIdentifier() const { return m_threadIdentifier; }
+        int argumentCount() const { return m_argumentCount; }
+        bool isNull() const { return !m_name; }
+
+        bool asBool(const char* name) const
+        {
+            return parameter(name, TypeBool).m_bool;
+        }
+        long long asInt(const char* name) const
+        {
+            size_t index = findParameter(name);
+            if (index == notFound || (m_argumentTypes[index] != TypeInt && m_argumentTypes[index] != TypeUInt)) {
+                ASSERT_NOT_REACHED();
+                return 0;
+            }
+            return reinterpret_cast<const TraceValueUnion*>(m_argumentValues + index)->m_int;
+        }
+        unsigned long long asUInt(const char* name) const
+        {
+            return asInt(name);
+        }
+        double asDouble(const char* name) const
+        {
+            return parameter(name, TypeDouble).m_double;
+        }
+        const char* asString(const char* name) const
+        {
+            return parameter(name, TypeString).m_string;
+        }
+
+    private:
+        enum { MaxArguments = 2 };
+
+        size_t findParameter(const char*) const;
+        const TraceValueUnion& parameter(const char* name, TraceValueTypes expectedType) const;
+
+        double m_timestamp;
+        TraceEventPhase m_phase;
+        const char* m_name;
+        unsigned long long m_id;
+        ThreadIdentifier m_threadIdentifier;
+        int m_argumentCount;
+        const char* m_argumentNames[MaxArguments];
+        unsigned char m_argumentTypes[MaxArguments];
+        unsigned long long m_argumentValues[MaxArguments];
+    };
+
+    typedef void (TimelineTraceEventProcessor::*TraceEventHandler)(const TraceEvent&);
+
+    TimelineThreadState& threadState(ThreadIdentifier thread)
+    {
+        ThreadStateMap::iterator it = m_threadStates.find(thread);
+        if (it != m_threadStates.end())
+            return it->value;
+        return m_threadStates.add(thread, TimelineThreadState(m_timelineAgent)).iterator->value;
+    }
+
+    void processBackgroundEvents();
+    PassRefPtr<InspectorObject> createRecord(const TraceEvent&, const String& recordType, PassRefPtr<InspectorObject> data = 0);
+
+    void registerHandler(const char* name, TraceEventPhase, TraceEventHandler);
+
+    void onBeginFrame(const TraceEvent&);
+    void onPaintLayerBegin(const TraceEvent&);
+    void onPaintLayerEnd(const TraceEvent&);
+    void onRasterTaskBegin(const TraceEvent&);
+    void onRasterTaskEnd(const TraceEvent&);
+    void onImageDecodeBegin(const TraceEvent&);
+    void onImageDecodeEnd(const TraceEvent&);
+    void onLayerDeleted(const TraceEvent&);
+    void onPaint(const TraceEvent&);
+
+    WeakPtr<InspectorTimelineAgent> m_timelineAgent;
+    TimelineTimeConverter m_timeConverter;
+    InspectorClient* m_inspectorClient;
+    unsigned long long m_pageId;
+
+    typedef HashMap<std::pair<String, int>, TraceEventHandler> HandlersMap;
+    HandlersMap m_handlersByType;
+    Mutex m_backgroundEventsMutex;
+    Vector<TraceEvent> m_backgroundEvents;
+
+    typedef HashMap<ThreadIdentifier, TimelineThreadState> ThreadStateMap;
+    ThreadStateMap m_threadStates;
+
+    HashSet<unsigned long long> m_knownLayers;
+    unsigned long long m_layerId;
+};
+
+} // namespace WebCore
+
+#endif // !defined(TimelineTraceEventProcessor_h)
diff --git a/Source/core/inspector/WorkerConsoleAgent.cpp b/Source/core/inspector/WorkerConsoleAgent.cpp
new file mode 100644
index 0000000..2dda5ba
--- /dev/null
+++ b/Source/core/inspector/WorkerConsoleAgent.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+
+#include "core/inspector/WorkerConsoleAgent.h"
+
+namespace WebCore {
+
+WorkerConsoleAgent::WorkerConsoleAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager)
+    : InspectorConsoleAgent(instrumentingAgents, state, injectedScriptManager)
+{
+}
+
+WorkerConsoleAgent::~WorkerConsoleAgent()
+{
+}
+
+void WorkerConsoleAgent::addInspectedNode(ErrorString* error, int)
+{
+    *error = "addInspectedNode is not supported for workers";
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/WorkerConsoleAgent.h b/Source/core/inspector/WorkerConsoleAgent.h
new file mode 100644
index 0000000..27ec0ac
--- /dev/null
+++ b/Source/core/inspector/WorkerConsoleAgent.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef WorkerConsoleAgent_h
+#define WorkerConsoleAgent_h
+
+#include "core/inspector/InspectorConsoleAgent.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class WorkerConsoleAgent : public InspectorConsoleAgent {
+    WTF_MAKE_NONCOPYABLE(WorkerConsoleAgent);
+public:
+    static PassOwnPtr<WorkerConsoleAgent> create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager)
+    {
+        return adoptPtr(new WorkerConsoleAgent(instrumentingAgents, state, injectedScriptManager));
+    }
+    virtual ~WorkerConsoleAgent();
+
+    virtual bool isWorkerAgent() OVERRIDE { return true; }
+
+private:
+    WorkerConsoleAgent(InstrumentingAgents*, InspectorCompositeState*, InjectedScriptManager*);
+    virtual void addInspectedNode(ErrorString*, int nodeId);
+};
+
+} // namespace WebCore
+
+#endif // !defined(WorkerConsoleAgent_h)
diff --git a/Source/core/inspector/WorkerDebuggerAgent.cpp b/Source/core/inspector/WorkerDebuggerAgent.cpp
new file mode 100644
index 0000000..b7a4c22
--- /dev/null
+++ b/Source/core/inspector/WorkerDebuggerAgent.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+
+#include "core/inspector/WorkerDebuggerAgent.h"
+
+#include "bindings/v8/ScriptDebugServer.h"
+#include "core/workers/WorkerContext.h"
+#include "core/workers/WorkerThread.h"
+#include <wtf/MessageQueue.h>
+
+namespace WebCore {
+
+namespace {
+
+Mutex& workerDebuggerAgentsMutex()
+{
+    AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
+    return mutex;
+}
+
+typedef HashMap<WorkerThread*, WorkerDebuggerAgent*> WorkerDebuggerAgents;
+
+WorkerDebuggerAgents& workerDebuggerAgents()
+{
+    DEFINE_STATIC_LOCAL(WorkerDebuggerAgents, agents, ());
+    return agents;
+}
+
+
+class RunInspectorCommandsTask : public ScriptDebugServer::Task {
+public:
+    RunInspectorCommandsTask(WorkerThread* thread, WorkerContext* workerContext)
+        : m_thread(thread)
+        , m_workerContext(workerContext) { }
+    virtual ~RunInspectorCommandsTask() { }
+    virtual void run()
+    {
+        // Process all queued debugger commands. It is safe to use m_workerContext here
+        // because it is alive if RunWorkerLoop is not terminated, otherwise it will
+        // just be ignored. WorkerThread is certainly alive if this task is being executed.
+        while (MessageQueueMessageReceived == m_thread->runLoop().runInMode(m_workerContext, WorkerDebuggerAgent::debuggerTaskMode, WorkerRunLoop::DontWaitForMessage)) { }
+    }
+
+private:
+    WorkerThread* m_thread;
+    WorkerContext* m_workerContext;
+};
+
+} // namespace
+
+const char* WorkerDebuggerAgent::debuggerTaskMode = "debugger";
+
+PassOwnPtr<WorkerDebuggerAgent> WorkerDebuggerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, WorkerContext* inspectedWorkerContext, InjectedScriptManager* injectedScriptManager)
+{
+    return adoptPtr(new WorkerDebuggerAgent(instrumentingAgents, inspectorState, inspectedWorkerContext, injectedScriptManager));
+}
+
+WorkerDebuggerAgent::WorkerDebuggerAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, WorkerContext* inspectedWorkerContext, InjectedScriptManager* injectedScriptManager)
+    : InspectorDebuggerAgent(instrumentingAgents, inspectorState, injectedScriptManager)
+    , m_scriptDebugServer(inspectedWorkerContext, WorkerDebuggerAgent::debuggerTaskMode)
+    , m_inspectedWorkerContext(inspectedWorkerContext)
+{
+    MutexLocker lock(workerDebuggerAgentsMutex());
+    workerDebuggerAgents().set(inspectedWorkerContext->thread(), this);
+}
+
+WorkerDebuggerAgent::~WorkerDebuggerAgent()
+{
+    MutexLocker lock(workerDebuggerAgentsMutex());
+    ASSERT(workerDebuggerAgents().contains(m_inspectedWorkerContext->thread()));
+    workerDebuggerAgents().remove(m_inspectedWorkerContext->thread());
+}
+
+void WorkerDebuggerAgent::interruptAndDispatchInspectorCommands(WorkerThread* thread)
+{
+    MutexLocker lock(workerDebuggerAgentsMutex());
+    WorkerDebuggerAgent* agent = workerDebuggerAgents().get(thread);
+    if (agent)
+        agent->m_scriptDebugServer.interruptAndRunTask(adoptPtr(new RunInspectorCommandsTask(thread, agent->m_inspectedWorkerContext)));
+}
+
+void WorkerDebuggerAgent::startListeningScriptDebugServer()
+{
+    scriptDebugServer().addListener(this);
+}
+
+void WorkerDebuggerAgent::stopListeningScriptDebugServer()
+{
+    scriptDebugServer().removeListener(this);
+}
+
+WorkerScriptDebugServer& WorkerDebuggerAgent::scriptDebugServer()
+{
+    return m_scriptDebugServer;
+}
+
+InjectedScript WorkerDebuggerAgent::injectedScriptForEval(ErrorString* error, const int* executionContextId)
+{
+    if (executionContextId) {
+        *error = "Execution context id is not supported for workers as there is only one execution context.";
+        return InjectedScript();
+    }
+    ScriptState* scriptState = scriptStateFromWorkerContext(m_inspectedWorkerContext);
+    return injectedScriptManager()->injectedScriptFor(scriptState);
+}
+
+void WorkerDebuggerAgent::muteConsole()
+{
+    // We don't need to mute console for workers.
+}
+
+void WorkerDebuggerAgent::unmuteConsole()
+{
+    // We don't need to mute console for workers.
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/WorkerDebuggerAgent.h b/Source/core/inspector/WorkerDebuggerAgent.h
new file mode 100644
index 0000000..b406a1d
--- /dev/null
+++ b/Source/core/inspector/WorkerDebuggerAgent.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef WorkerDebuggerAgent_h
+#define WorkerDebuggerAgent_h
+
+#include "bindings/v8/WorkerScriptDebugServer.h"
+#include "core/inspector/InspectorDebuggerAgent.h"
+
+namespace WebCore {
+
+class WorkerContext;
+class WorkerThread;
+
+class WorkerDebuggerAgent : public InspectorDebuggerAgent {
+    WTF_MAKE_NONCOPYABLE(WorkerDebuggerAgent);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<WorkerDebuggerAgent> create(InstrumentingAgents*, InspectorCompositeState*, WorkerContext*, InjectedScriptManager*);
+    virtual ~WorkerDebuggerAgent();
+
+    static const char* debuggerTaskMode;
+    static void interruptAndDispatchInspectorCommands(WorkerThread*);
+
+private:
+    WorkerDebuggerAgent(InstrumentingAgents*, InspectorCompositeState*, WorkerContext*, InjectedScriptManager*);
+
+    virtual void startListeningScriptDebugServer();
+    virtual void stopListeningScriptDebugServer();
+    virtual WorkerScriptDebugServer& scriptDebugServer();
+    virtual InjectedScript injectedScriptForEval(ErrorString*, const int* executionContextId);
+    virtual void muteConsole();
+    virtual void unmuteConsole();
+
+    WorkerScriptDebugServer m_scriptDebugServer;
+    WorkerContext* m_inspectedWorkerContext;
+};
+
+} // namespace WebCore
+
+#endif // !defined(WorkerDebuggerAgent_h)
diff --git a/Source/core/inspector/WorkerInspectorController.cpp b/Source/core/inspector/WorkerInspectorController.cpp
new file mode 100644
index 0000000..21994ea
--- /dev/null
+++ b/Source/core/inspector/WorkerInspectorController.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+
+#include "core/inspector/WorkerInspectorController.h"
+
+#include "InspectorBackendDispatcher.h"
+#include "InspectorFrontend.h"
+#include "core/inspector/InjectedScriptHost.h"
+#include "core/inspector/InjectedScriptManager.h"
+#include "core/inspector/InspectorClient.h"
+#include "core/inspector/InspectorConsoleAgent.h"
+#include "core/inspector/InspectorFrontendChannel.h"
+#include "core/inspector/InspectorHeapProfilerAgent.h"
+#include "core/inspector/InspectorProfilerAgent.h"
+#include "core/inspector/InspectorState.h"
+#include "core/inspector/InspectorStateClient.h"
+#include "core/inspector/InspectorTimelineAgent.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/inspector/WorkerConsoleAgent.h"
+#include "core/inspector/WorkerDebuggerAgent.h"
+#include "core/inspector/WorkerRuntimeAgent.h"
+#include "core/workers/WorkerContext.h"
+#include "core/workers/WorkerReportingProxy.h"
+#include "core/workers/WorkerThread.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+namespace {
+
+class PageInspectorProxy : public InspectorFrontendChannel {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit PageInspectorProxy(WorkerContext* workerContext) : m_workerContext(workerContext) { }
+    virtual ~PageInspectorProxy() { }
+private:
+    virtual bool sendMessageToFrontend(const String& message)
+    {
+        m_workerContext->thread()->workerReportingProxy().postMessageToPageInspector(message);
+        return true;
+    }
+    WorkerContext* m_workerContext;
+};
+
+class WorkerStateClient : public InspectorStateClient {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    WorkerStateClient(WorkerContext* context) : m_workerContext(context) { }
+    virtual ~WorkerStateClient() { }
+
+private:
+    virtual void updateInspectorStateCookie(const String& cookie)
+    {
+        m_workerContext->thread()->workerReportingProxy().updateInspectorStateCookie(cookie);
+    }
+
+    WorkerContext* m_workerContext;
+};
+
+}
+
+WorkerInspectorController::WorkerInspectorController(WorkerContext* workerContext)
+    : m_workerContext(workerContext)
+    , m_stateClient(adoptPtr(new WorkerStateClient(workerContext)))
+    , m_state(adoptPtr(new InspectorCompositeState(m_stateClient.get())))
+    , m_instrumentingAgents(InstrumentingAgents::create())
+    , m_injectedScriptManager(InjectedScriptManager::createForWorker())
+    , m_runtimeAgent(0)
+{
+    OwnPtr<InspectorRuntimeAgent> runtimeAgent = WorkerRuntimeAgent::create(m_instrumentingAgents.get(), m_state.get(), m_injectedScriptManager.get(), workerContext);
+    m_runtimeAgent = runtimeAgent.get();
+    m_agents.append(runtimeAgent.release());
+
+    OwnPtr<InspectorConsoleAgent> consoleAgent = WorkerConsoleAgent::create(m_instrumentingAgents.get(), m_state.get(), m_injectedScriptManager.get());
+    OwnPtr<InspectorDebuggerAgent> debuggerAgent = WorkerDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), workerContext, m_injectedScriptManager.get());
+    InspectorDebuggerAgent* debuggerAgentPtr = debuggerAgent.get();
+    m_runtimeAgent->setScriptDebugServer(&debuggerAgent->scriptDebugServer());
+    m_agents.append(debuggerAgent.release());
+
+    m_agents.append(InspectorProfilerAgent::create(m_instrumentingAgents.get(), consoleAgent.get(), workerContext, m_state.get(), m_injectedScriptManager.get()));
+    m_agents.append(InspectorHeapProfilerAgent::create(m_instrumentingAgents.get(), m_state.get(), m_injectedScriptManager.get()));
+    m_agents.append(InspectorTimelineAgent::create(m_instrumentingAgents.get(), 0, 0, m_state.get(), InspectorTimelineAgent::WorkerInspector, 0));
+    m_agents.append(consoleAgent.release());
+
+    m_injectedScriptManager->injectedScriptHost()->init(0
+        , 0
+        , 0
+        , 0
+        , 0
+        , debuggerAgentPtr
+    );
+}
+ 
+WorkerInspectorController::~WorkerInspectorController()
+{
+    m_instrumentingAgents->reset();
+    disconnectFrontend();
+}
+
+void WorkerInspectorController::connectFrontend()
+{
+    ASSERT(!m_frontend);
+    m_state->unmute();
+    m_frontendChannel = adoptPtr(new PageInspectorProxy(m_workerContext));
+    m_frontend = adoptPtr(new InspectorFrontend(m_frontendChannel.get()));
+    m_backendDispatcher = InspectorBackendDispatcher::create(m_frontendChannel.get());
+    m_agents.registerInDispatcher(m_backendDispatcher.get());
+    m_agents.setFrontend(m_frontend.get());
+}
+
+void WorkerInspectorController::disconnectFrontend()
+{
+    if (!m_frontend)
+        return;
+    m_backendDispatcher->clearFrontend();
+    m_backendDispatcher.clear();
+    // Destroying agents would change the state, but we don't want that.
+    // Pre-disconnect state will be used to restore inspector agents.
+    m_state->mute();
+    m_agents.clearFrontend();
+    m_frontend.clear();
+    m_frontendChannel.clear();
+}
+
+void WorkerInspectorController::restoreInspectorStateFromCookie(const String& inspectorCookie)
+{
+    ASSERT(!m_frontend);
+    connectFrontend();
+    m_state->loadFromCookie(inspectorCookie);
+
+    m_agents.restore();
+}
+
+void WorkerInspectorController::dispatchMessageFromFrontend(const String& message)
+{
+    if (m_backendDispatcher)
+        m_backendDispatcher->dispatch(message);
+}
+
+void WorkerInspectorController::resume()
+{
+    ErrorString unused;
+    m_runtimeAgent->run(&unused);
+}
+
+}
diff --git a/Source/core/inspector/WorkerInspectorController.h b/Source/core/inspector/WorkerInspectorController.h
new file mode 100644
index 0000000..ce09a0b
--- /dev/null
+++ b/Source/core/inspector/WorkerInspectorController.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef WorkerInspectorController_h
+#define WorkerInspectorController_h
+
+#include "core/inspector/InspectorBaseAgent.h"
+#include <wtf/FastAllocBase.h>
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class InjectedScriptManager;
+class InspectorBackendDispatcher;
+class InspectorFrontend;
+class InspectorFrontendChannel;
+class InspectorRuntimeAgent;
+class InspectorState;
+class InspectorStateClient;
+class InstrumentingAgents;
+class WorkerContext;
+
+class WorkerInspectorController {
+    WTF_MAKE_NONCOPYABLE(WorkerInspectorController);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    WorkerInspectorController(WorkerContext*);
+    ~WorkerInspectorController();
+
+    bool hasFrontend() const { return m_frontend; }
+    void connectFrontend();
+    void disconnectFrontend();
+    void restoreInspectorStateFromCookie(const String& inspectorCookie);
+    void dispatchMessageFromFrontend(const String&);
+    void resume();
+
+private:
+    friend InstrumentingAgents* instrumentationForWorkerContext(WorkerContext*);
+
+    WorkerContext* m_workerContext;
+    OwnPtr<InspectorStateClient> m_stateClient;
+    OwnPtr<InspectorCompositeState> m_state;
+    RefPtr<InstrumentingAgents> m_instrumentingAgents;
+    OwnPtr<InjectedScriptManager> m_injectedScriptManager;
+    InspectorRuntimeAgent* m_runtimeAgent;
+    InspectorAgentRegistry m_agents;
+    OwnPtr<InspectorFrontendChannel> m_frontendChannel;
+    OwnPtr<InspectorFrontend> m_frontend;
+    RefPtr<InspectorBackendDispatcher> m_backendDispatcher;
+};
+
+}
+
+#endif // !defined(WorkerInspectorController_h)
diff --git a/Source/core/inspector/WorkerRuntimeAgent.cpp b/Source/core/inspector/WorkerRuntimeAgent.cpp
new file mode 100644
index 0000000..43bb707
--- /dev/null
+++ b/Source/core/inspector/WorkerRuntimeAgent.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "config.h"
+
+#include "core/inspector/WorkerRuntimeAgent.h"
+
+#include "bindings/v8/ScriptState.h"
+#include "core/inspector/InjectedScript.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/inspector/WorkerDebuggerAgent.h"
+#include "core/workers/WorkerContext.h"
+#include "core/workers/WorkerRunLoop.h"
+#include "core/workers/WorkerThread.h"
+
+namespace WebCore {
+
+WorkerRuntimeAgent::WorkerRuntimeAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager, WorkerContext* workerContext)
+    : InspectorRuntimeAgent(instrumentingAgents, state, injectedScriptManager)
+    , m_workerContext(workerContext)
+    , m_paused(false)
+{
+    m_instrumentingAgents->setWorkerRuntimeAgent(this);
+}
+
+WorkerRuntimeAgent::~WorkerRuntimeAgent()
+{
+    m_instrumentingAgents->setWorkerRuntimeAgent(0);
+}
+
+InjectedScript WorkerRuntimeAgent::injectedScriptForEval(ErrorString* error, const int* executionContextId)
+{
+    if (executionContextId) {
+        *error = "Execution context id is not supported for workers as there is only one execution context.";
+        return InjectedScript();
+    }
+    ScriptState* scriptState = scriptStateFromWorkerContext(m_workerContext);
+    return injectedScriptManager()->injectedScriptFor(scriptState);
+}
+
+void WorkerRuntimeAgent::muteConsole()
+{
+    // We don't need to mute console for workers.
+}
+
+void WorkerRuntimeAgent::unmuteConsole()
+{
+    // We don't need to mute console for workers.
+}
+
+void WorkerRuntimeAgent::run(ErrorString*)
+{
+    m_paused = false;
+}
+
+void WorkerRuntimeAgent::pauseWorkerContext(WorkerContext* context)
+{
+    m_paused = true;
+    MessageQueueWaitResult result;
+    do {
+        result = context->thread()->runLoop().runInMode(context, WorkerDebuggerAgent::debuggerTaskMode);
+    // Keep waiting until execution is resumed.
+    } while (result == MessageQueueMessageReceived && m_paused);
+}
+
+} // namespace WebCore
diff --git a/Source/core/inspector/WorkerRuntimeAgent.h b/Source/core/inspector/WorkerRuntimeAgent.h
new file mode 100644
index 0000000..67381bb
--- /dev/null
+++ b/Source/core/inspector/WorkerRuntimeAgent.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef WorkerRuntimeAgent_h
+#define WorkerRuntimeAgent_h
+
+#include "core/inspector/InspectorRuntimeAgent.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class WorkerContext;
+
+class WorkerRuntimeAgent : public InspectorRuntimeAgent {
+public:
+    static PassOwnPtr<WorkerRuntimeAgent> create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager, WorkerContext* context)
+    {
+        return adoptPtr(new WorkerRuntimeAgent(instrumentingAgents, state, injectedScriptManager, context));
+    }
+    virtual ~WorkerRuntimeAgent();
+
+    // Protocol commands.
+    virtual void run(ErrorString*);
+
+    void pauseWorkerContext(WorkerContext*);
+
+private:
+    WorkerRuntimeAgent(InstrumentingAgents*, InspectorCompositeState*, InjectedScriptManager*, WorkerContext*);
+    virtual InjectedScript injectedScriptForEval(ErrorString*, const int* executionContextId);
+    virtual void muteConsole();
+    virtual void unmuteConsole();
+    WorkerContext* m_workerContext;
+    bool m_paused;
+};
+
+} // namespace WebCore
+
+#endif // !defined(InspectorPagerAgent_h)
diff --git a/Source/core/inspector/combine-javascript-resources.pl b/Source/core/inspector/combine-javascript-resources.pl
new file mode 100755
index 0000000..428b6b7
--- /dev/null
+++ b/Source/core/inspector/combine-javascript-resources.pl
@@ -0,0 +1,81 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2008 Apple 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:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. 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.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
+
+# Script to combine multiple JavaScript files into one file, based on
+# the script tags in the head of an input HTML file.
+
+use strict;
+use Getopt::Long;
+use File::Basename;
+use File::Path;
+
+my $generatedScriptsDirectory;
+my $outputDirectory;
+my $scriptName;
+my $htmlFile;
+
+GetOptions('output-dir=s' => \$outputDirectory,
+           'output-script-name=s' => \$scriptName,
+           'generated-scripts-dir=s' => \$generatedScriptsDirectory,
+           'input-html=s' => \$htmlFile);
+
+unless (defined $htmlFile and defined $scriptName and defined $outputDirectory) {
+    print "Usage: $0 --input-html <path> --output-dir path --output-script-name <name>\n";
+    exit;
+}
+
+my $htmlDirectory = dirname($htmlFile);
+my $htmlContents;
+
+{
+    local $/;
+    open HTML, $htmlFile or die;
+    $htmlContents = <HTML>;
+    close HTML;
+}
+
+$htmlContents =~ m/<head>(.*)<\/head>/si;
+my $headContents = $1;
+
+mkpath $outputDirectory;
+open SCRIPT_OUT, ">", "$outputDirectory/$scriptName" or die "Can't open $outputDirectory/$scriptName: $!";
+
+while ($headContents =~ m/<script.*src="([^"]*)"[^>]*>/gi) {
+    local $/;
+    open SCRIPT_IN, "$generatedScriptsDirectory/$1" or open SCRIPT_IN, "$htmlDirectory/$1" or die "Can't open $htmlDirectory/$1: $!";
+    print SCRIPT_OUT "/* $1 */\n\n";
+    print SCRIPT_OUT <SCRIPT_IN>;
+    close SCRIPT_IN;
+}
+
+close SCRIPT_OUT;
+
+$headContents =~ s/<script.*src="[^"]*"[^>]*><\/script>\s*//gi;
+$headContents .= "<script type=\"text/javascript\" src=\"$scriptName\"></script>\n";
+$htmlContents =~ s/<head>.*<\/head>/<head>$headContents<\/head>/si;
+
+open HTML, ">", "$outputDirectory/" . basename($htmlFile) or die "Can't open $outputDirectory/" . basename($htmlFile) . ": $!";
+print HTML $htmlContents;
+close HTML;
diff --git a/Source/core/inspector/generate-inspector-protocol-version b/Source/core/inspector/generate-inspector-protocol-version
new file mode 100755
index 0000000..12f4298
--- /dev/null
+++ b/Source/core/inspector/generate-inspector-protocol-version
@@ -0,0 +1,476 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 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.
+#
+# Inspector protocol validator.
+# 
+# Tests that subsequent protocol changes are not breaking backwards compatibility.
+# Following violations are reported:
+#
+#   - Domain has been removed
+#   - Command has been removed
+#   - Required command parameter was added or changed from optional
+#   - Required response parameter was removed or changed to optional
+#   - Event has been removed
+#   - Required event parameter was removed or changed to optional
+#   - Parameter type has changed.
+#   
+# For the parameters with composite types the above checks are also applied
+# recursively to every property of the type.
+#
+# Adding --show_changes to the command line prints out a list of valid public API changes.
+
+import os.path
+import re
+import sys
+
+def list_to_map(items, key):
+    result = {}
+    for item in items:
+        if not "hidden" in item:
+            result[item[key]] = item
+    return result
+
+def named_list_to_map(container, name, key):
+    if name in container:
+        return list_to_map(container[name], key)
+    return {}
+
+def removed(reverse):
+    if reverse:
+        return "added"
+    return "removed"
+
+def required(reverse):
+    if reverse:
+        return "optional"
+    return "required"
+
+def compare_schemas(schema_1, schema_2, reverse):
+    errors = []
+    types_1 = normalize_types_in_schema(schema_1)
+    types_2 = normalize_types_in_schema(schema_2)
+
+    domains_by_name_1 = list_to_map(schema_1, "domain")
+    domains_by_name_2 = list_to_map(schema_2, "domain")
+
+    for name in domains_by_name_1:
+        domain_1 = domains_by_name_1[name]
+        if not name in domains_by_name_2:
+            errors.append("%s: domain has been %s" % (name, removed(reverse)))
+            continue
+        compare_domains(domain_1, domains_by_name_2[name], types_1, types_2, errors, reverse)
+    return errors
+
+def compare_domains(domain_1, domain_2, types_map_1, types_map_2, errors, reverse):
+    domain_name = domain_1["domain"]
+    commands_1 = named_list_to_map(domain_1, "commands", "name")
+    commands_2 = named_list_to_map(domain_2, "commands", "name")
+    for name in commands_1:
+        command_1 = commands_1[name]
+        if not name in commands_2:
+            errors.append("%s.%s: command has been %s" % (domain_1["domain"], name, removed(reverse)))
+            continue
+        compare_commands(domain_name, command_1, commands_2[name], types_map_1, types_map_2, errors, reverse)
+
+    events_1 = named_list_to_map(domain_1, "events", "name")
+    events_2 = named_list_to_map(domain_2, "events", "name")
+    for name in events_1:
+        event_1 = events_1[name]
+        if not name in events_2:
+            errors.append("%s.%s: event has been %s" % (domain_1["domain"], name, removed(reverse)))
+            continue
+        compare_events(domain_name, event_1, events_2[name], types_map_1, types_map_2, errors, reverse)
+
+def compare_commands(domain_name, command_1, command_2, types_map_1, types_map_2, errors, reverse):
+    context = domain_name + "." + command_1["name"]
+
+    params_1 = named_list_to_map(command_1, "parameters", "name")
+    params_2 = named_list_to_map(command_2, "parameters", "name")
+    # Note the reversed order: we allow removing but forbid adding parameters.
+    compare_params_list(context, "parameter", params_2, params_1, types_map_2, types_map_1, 0, errors, not reverse)
+
+    returns_1 = named_list_to_map(command_1, "returns", "name")
+    returns_2 = named_list_to_map(command_2, "returns", "name")
+    compare_params_list(context, "response parameter", returns_1, returns_2, types_map_1, types_map_2, 0, errors, reverse)
+
+def compare_events(domain_name, event_1, event_2, types_map_1, types_map_2, errors, reverse):
+    context = domain_name + "." + event_1["name"]
+    params_1 = named_list_to_map(event_1, "parameters", "name")
+    params_2 = named_list_to_map(event_2, "parameters", "name")
+    compare_params_list(context, "parameter", params_1, params_2, types_map_1, types_map_2, 0, errors, reverse)
+
+def compare_params_list(context, kind, params_1, params_2, types_map_1, types_map_2, depth, errors, reverse):
+    for name in params_1:
+        param_1 = params_1[name]
+        if not name in params_2:
+            if not "optional" in param_1:
+                errors.append("%s.%s: required %s has been %s" % (context, name, kind, removed(reverse)))
+            continue
+
+        param_2 = params_2[name]
+        if param_2 and "optional" in param_2 and not "optional" in param_1:
+            errors.append("%s.%s: %s %s is now %s" % (context, name, required(reverse), kind, required(not reverse)))
+            continue
+        type_1 = extract_type(param_1, types_map_1, errors)
+        type_2 = extract_type(param_2, types_map_2, errors)
+        compare_types(context + "." + name, kind, type_1, type_2, types_map_1, types_map_2, depth, errors, reverse)
+
+def compare_types(context, kind, type_1, type_2, types_map_1, types_map_2, depth, errors, reverse):
+    if depth > 10:
+        return
+
+    base_type_1 = type_1["type"]
+    base_type_2 = type_2["type"]
+
+    if base_type_1 != base_type_2:
+        errors.append("%s: %s base type mismatch, '%s' vs '%s'" % (context, kind, base_type_1, base_type_2))
+    elif base_type_1 == "object":
+        params_1 = named_list_to_map(type_1, "properties", "name")
+        params_2 = named_list_to_map(type_2, "properties", "name")
+        # If both parameters have the same named type use it in the context.
+        if "id" in type_1 and "id" in type_2 and type_1["id"] == type_2["id"]:
+            type_name = type_1["id"]
+        else:
+            type_name = "<object>"
+        context += " %s->%s" % (kind, type_name)
+        compare_params_list(context, "property", params_1, params_2, types_map_1, types_map_2, depth + 1, errors, reverse)
+    elif base_type_1 == "array":
+        item_type_1 = extract_type(type_1["items"], types_map_1, errors)
+        item_type_2 = extract_type(type_2["items"], types_map_2, errors)
+        compare_types(context, kind, item_type_1, item_type_2, types_map_1, types_map_2, depth + 1, errors, reverse)
+
+def extract_type(typed_object, types_map, errors):
+    if "type" in typed_object:
+        result = { "id": "<transient>", "type": typed_object["type"] }
+        if typed_object["type"] == "object":
+            result["properties"] = []
+        elif typed_object["type"] == "array":
+            result["items"] = typed_object["items"]
+        return result
+    elif "$ref" in typed_object:
+        ref = typed_object["$ref"]
+        if not ref in types_map:
+            errors.append("Can not resolve type: %s" % ref)
+            types_map[ref] = { "id": "<transient>", "type": "object" } 
+        return types_map[ref]
+
+def normalize_types_in_schema(schema):
+    types = {}
+    for domain in schema:
+        domain_name = domain["domain"]
+        normalize_types(domain, domain_name, types)
+    return types
+
+def normalize_types(obj, domain_name, types):
+    if isinstance(obj, list):
+        for item in obj:
+            normalize_types(item, domain_name, types)
+    elif isinstance(obj, dict):
+        for key, value in obj.items():
+            if key == "$ref" and value.find(".") == -1:
+                obj[key] = "%s.%s" % (domain_name, value)
+            elif key == "id":
+                obj[key] = "%s.%s" % (domain_name, value)
+                types[obj[key]] = obj
+            else:
+                normalize_types(value, domain_name, types)
+
+def load_json(filename):
+    input_file = open(filename, "r")
+    json_string = input_file.read()
+    json_string = re.sub(":\s*true", ": True", json_string)
+    json_string = re.sub(":\s*false", ": False", json_string)
+    return eval(json_string)
+
+def self_test():
+    def create_test_schema_1():
+        return [
+        {
+            "domain": "Network",
+            "types": [
+                {
+                    "id": "LoaderId",
+                    "type": "string"
+                },
+                {
+                    "id": "Headers",
+                    "type": "object"
+                },
+                {
+                    "id": "Request",
+                    "type": "object",
+                    "properties": [
+                        { "name": "url", "type": "string" },
+                        { "name": "method", "type": "string" },
+                        { "name": "headers", "$ref": "Headers" },
+                        { "name": "becameOptionalField", "type": "string" },
+                        { "name": "removedField", "type": "string" },
+                    ]
+                }
+            ],
+            "commands": [
+                {
+                    "name": "removedCommand",
+                },
+                {
+                    "name": "setExtraHTTPHeaders",
+                    "parameters": [
+                        { "name": "headers", "$ref": "Headers" },
+                        { "name": "mismatched", "type": "string" },
+                        { "name": "becameOptional", "$ref": "Headers" },
+                        { "name": "removedRequired", "$ref": "Headers" },
+                        { "name": "becameRequired", "$ref": "Headers", "optional": True },
+                        { "name": "removedOptional", "$ref": "Headers", "optional": True },
+                    ],
+                    "returns": [
+                        { "name": "mimeType", "type": "string" },
+                        { "name": "becameOptional", "type": "string" },
+                        { "name": "removedRequired", "type": "string" },
+                        { "name": "becameRequired", "type": "string", "optional": True },
+                        { "name": "removedOptional", "type": "string", "optional": True },
+                    ]
+                }
+            ],
+            "events": [
+                {
+                    "name": "requestWillBeSent",
+                    "parameters": [
+                        { "name": "frameId", "type": "string", "hidden": True },
+                        { "name": "request", "$ref": "Request" },
+                        { "name": "becameOptional", "type": "string" },
+                        { "name": "removedRequired", "type": "string" },
+                        { "name": "becameRequired", "type": "string", "optional": True },
+                        { "name": "removedOptional", "type": "string", "optional": True },
+                        ]
+                },
+                {
+                    "name": "removedEvent",
+                    "parameters": [
+                        { "name": "errorText", "type": "string" },
+                        { "name": "canceled", "type": "boolean", "optional": True }
+                    ]
+                }
+            ]
+        },
+        {
+            "domain":  "removedDomain"
+        }
+    ]
+
+    def create_test_schema_2():
+        return [
+        {
+            "domain": "Network",
+            "types": [
+                {
+                    "id": "LoaderId",
+                    "type": "string"
+                },
+                {
+                    "id": "Request",
+                    "type": "object",
+                    "properties": [
+                        { "name": "url", "type": "string" },
+                        { "name": "method", "type": "string" },
+                        { "name": "headers", "type": "object" },
+                        { "name": "becameOptionalField", "type": "string", "optional": True },
+                    ]
+                }
+            ],
+            "commands": [
+                {
+                    "name": "addedCommand",
+                },
+                {
+                    "name": "setExtraHTTPHeaders",
+                    "parameters": [
+                        { "name": "headers", "type": "object" },
+                        { "name": "mismatched", "type": "object" },
+                        { "name": "becameOptional", "type": "object" , "optional": True },
+                        { "name": "addedRequired", "type": "object" },
+                        { "name": "becameRequired", "type": "object" },
+                        { "name": "addedOptional", "type": "object", "optional": True  },
+                    ],
+                    "returns": [
+                        { "name": "mimeType", "type": "string" },
+                        { "name": "becameOptional", "type": "string", "optional": True },
+                        { "name": "addedRequired", "type": "string"},
+                        { "name": "becameRequired", "type": "string" },
+                        { "name": "addedOptional", "type": "string", "optional": True  },
+                    ]
+                }
+            ],
+            "events": [
+                {
+                    "name": "requestWillBeSent",
+                    "parameters": [
+                        { "name": "request", "$ref": "Request" },
+                        { "name": "becameOptional", "type": "string", "optional": True },
+                        { "name": "addedRequired", "type": "string"},
+                        { "name": "becameRequired", "type": "string" },
+                        { "name": "addedOptional", "type": "string", "optional": True  },
+                    ]
+                },
+                {
+                    "name": "addedEvent"
+                }
+            ]
+        },
+        {
+            "domain": "addedDomain"
+        }
+    ]
+
+    expected_errors = [
+        "removedDomain: domain has been removed",
+        "Network.removedCommand: command has been removed",
+        "Network.removedEvent: event has been removed",
+        "Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, 'object' vs 'string'",
+        "Network.setExtraHTTPHeaders.addedRequired: required parameter has been added",
+        "Network.setExtraHTTPHeaders.becameRequired: optional parameter is now required",
+        "Network.setExtraHTTPHeaders.removedRequired: required response parameter has been removed",
+        "Network.setExtraHTTPHeaders.becameOptional: required response parameter is now optional",
+        "Network.requestWillBeSent.removedRequired: required parameter has been removed",
+        "Network.requestWillBeSent.becameOptional: required parameter is now optional",
+        "Network.requestWillBeSent.request parameter->Network.Request.removedField: required property has been removed",
+        "Network.requestWillBeSent.request parameter->Network.Request.becameOptionalField: required property is now optional",
+    ]
+
+    expected_errors_reverse = [
+       "addedDomain: domain has been added",
+       "Network.addedEvent: event has been added",
+       "Network.addedCommand: command has been added",
+       "Network.setExtraHTTPHeaders.mismatched: parameter base type mismatch, 'string' vs 'object'",
+       "Network.setExtraHTTPHeaders.removedRequired: required parameter has been removed",
+       "Network.setExtraHTTPHeaders.becameOptional: required parameter is now optional",
+       "Network.setExtraHTTPHeaders.addedRequired: required response parameter has been added",
+       "Network.setExtraHTTPHeaders.becameRequired: optional response parameter is now required",
+       "Network.requestWillBeSent.becameRequired: optional parameter is now required",
+       "Network.requestWillBeSent.addedRequired: required parameter has been added",
+    ]
+
+    def is_subset(subset, superset, message):
+        for i in range(len(subset)):
+            if subset[i] not in superset:
+                sys.stderr.write("%s error: %s\n" % (message, subset[i]))
+                return False
+        return True
+
+    def errors_match(expected, actual):
+        return (is_subset(actual, expected, "Unexpected") and
+                is_subset(expected, actual, "Missing"))
+
+    return (errors_match(expected_errors,
+                         compare_schemas(create_test_schema_1(), create_test_schema_2(), False)) and
+            errors_match(expected_errors_reverse,
+                         compare_schemas(create_test_schema_2(), create_test_schema_1(), True)))
+
+
+def main():
+    if not self_test():
+        sys.stderr.write("Self-test failed")
+        return 1
+
+    if len(sys.argv) < 4 or sys.argv[1] != "-o":
+        sys.stderr.write("Usage: %s -o OUTPUT_FILE INPUT_FILE [--show-changes]\n" % sys.argv[0])
+        return 1
+
+    output_path = sys.argv[2]
+    output_file = open(output_path, "w")
+
+    input_path = sys.argv[3]
+    dir_name = os.path.dirname(input_path)
+    schema = load_json(input_path)
+
+    major = schema["version"]["major"]
+    minor = schema["version"]["minor"]
+    version = "%s.%s" % (major, minor)
+    if len(dir_name) == 0:
+        dir_name = "."
+    baseline_path = os.path.normpath(dir_name + "/Inspector-" + version + ".json")
+    baseline_schema = load_json(baseline_path)
+
+    errors = compare_schemas(baseline_schema["domains"], schema["domains"], False)
+    if len(errors) > 0:
+        sys.stderr.write("  Compatibility with %s: FAILED\n" % version)
+        for error in errors:
+            sys.stderr.write( "    %s\n" % error)
+        return 1
+
+    if len(sys.argv) > 4 and sys.argv[4] == "--show-changes":
+        changes = compare_schemas(
+            load_json(input_path)["domains"], load_json(baseline_path)["domains"], True)
+        if len(changes) > 0:
+            print "  Public changes since %s:" % version
+            for change in changes:
+                print "    %s" % change
+
+    output_file.write("""
+#ifndef InspectorProtocolVersion_h
+#define InspectorProtocolVersion_h
+
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+String inspectorProtocolVersion() { return "%s"; }
+
+int inspectorProtocolVersionMajor() { return %s; }
+
+int inspectorProtocolVersionMinor() { return %s; }
+
+bool supportsInspectorProtocolVersion(const String& version)
+{
+    Vector<String> tokens;
+    version.split(".", tokens);
+    if (tokens.size() != 2)
+        return false;
+
+    bool ok = true;
+    int major = tokens[0].toInt(&ok);
+    if (!ok || major != %s)
+        return false;
+
+    int minor = tokens[1].toInt(&ok);
+    if (!ok || minor > %s)
+        return false;
+
+    return true;
+}
+
+}
+
+#endif // !defined(InspectorProtocolVersion_h)
+""" % (version, major, minor, major, minor))
+
+    output_file.close()
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/Source/core/inspector/inline-javascript-imports.py b/Source/core/inspector/inline-javascript-imports.py
new file mode 100755
index 0000000..e0a194f
--- /dev/null
+++ b/Source/core/inspector/inline-javascript-imports.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 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.
+#
+
+# This script replaces calls to importScripts with script sources
+# in input script file and dumps result into output script file.
+
+from cStringIO import StringIO
+
+import os.path
+import re
+import sys
+
+
+def main(argv):
+
+    if len(argv) < 3:
+        print('usage: %s inputFile importsDir outputFile' % argv[0])
+        return 1
+
+    inputFileName = argv[1]
+    importsDir = argv[2]
+    outputFileName = argv[3]
+
+    inputFile = open(inputFileName, 'r')
+    inputScript = inputFile.read()
+    inputFile.close()
+
+    def replace(match):
+        importFileName = match.group(1)
+        fullPath = os.path.join(importsDir, importFileName)
+        if not os.access(fullPath, os.F_OK):
+            raise Exception('File %s referenced in %s not found on any source paths, '
+                            'check source tree for consistency' %
+                            (importFileName, inputFileName))
+        importFile = open(fullPath, 'r')
+        importScript = importFile.read()
+        importFile.close()
+        return importScript
+
+    outputScript = re.sub(r'importScripts?\([\'"]([^\'"]+)[\'"]\)', replace, inputScript)
+
+    outputFile = open(outputFileName, 'w')
+    outputFile.write(outputScript)
+    outputFile.close()
+
+    # Touch output file directory to make sure that Xcode will copy
+    # modified resource files.
+    if sys.platform == 'darwin':
+        outputDirName = os.path.dirname(outputFileName)
+        os.utime(outputDirName, None)
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
diff --git a/Source/core/inspector/xxd.pl b/Source/core/inspector/xxd.pl
new file mode 100644
index 0000000..5ee08a5
--- /dev/null
+++ b/Source/core/inspector/xxd.pl
@@ -0,0 +1,45 @@
+#! /usr/bin/perl
+
+# Copyright (C) 2010-2011 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.
+#
+
+$varname = shift;
+$fname = shift;
+$output = shift;
+
+open($input, '<', $fname) or die "Can't open file for read: $fname $!";
+$/ = undef;
+$text = <$input>;
+close($input);
+
+$text = join(', ', map('0x' . unpack("H*", $_), split(undef, $text)));
+
+open($output, '>', $output) or die "Can't open file for write: $output $!";
+print $output "const unsigned char $varname\[\] = {\n$text\n};\n";
+close($output);