diff --git a/DEPS b/DEPS index eeb43696..82fcb58 100644 --- a/DEPS +++ b/DEPS
@@ -43,7 +43,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'e86c7faf2af172045cdf379e9c3c78433071c425', + 'v8_revision': '54afc6c29a30fa0fb0683dca33214861d40a18ba', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other.
diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc index fc06a2f..f6f62a54 100644 --- a/content/browser/frame_host/frame_tree_node.cc +++ b/content/browser/frame_host/frame_tree_node.cc
@@ -16,7 +16,6 @@ #include "content/browser/frame_host/navigation_request.h" #include "content/browser/frame_host/navigator.h" #include "content/browser/frame_host/render_frame_host_impl.h" -#include "content/browser/frame_host/traced_frame_tree_node.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/common/frame_messages.h" #include "content/common/site_isolation_policy.h" @@ -107,18 +106,17 @@ false /* is a potentially trustworthy unique origin */), pending_sandbox_flags_(blink::WebSandboxFlags::None), frame_owner_properties_(frame_owner_properties), - loading_progress_(kLoadingProgressNotStarted) { + loading_progress_(kLoadingProgressNotStarted), + blame_context_(frame_tree_node_id_, parent) { std::pair<FrameTreeNodeIdMap::iterator, bool> result = g_frame_tree_node_id_map.Get().insert( std::make_pair(frame_tree_node_id_, this)); CHECK(result.second); RecordUniqueNameLength(unique_name.size()); - TRACE_EVENT_OBJECT_CREATED_WITH_ID( - "navigation", "FrameTreeNode", - TRACE_ID_WITH_SCOPE("FrameTreeNode", frame_tree_node_id_)); - // Don't TraceSnapshot() until the RenderFrameHostManager is initialized and - // calls SetCurrentURL(). + + // Note: this should always be done last in the constructor. + blame_context_.Initialize(); } FrameTreeNode::~FrameTreeNode() { @@ -130,10 +128,6 @@ opener_->RemoveObserver(opener_observer_.get()); g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_); - - TRACE_EVENT_OBJECT_DELETED_WITH_ID( - "navigation", "FrameTreeNode", - TRACE_ID_WITH_SCOPE("FrameTreeNode", frame_tree_node_id_)); } void FrameTreeNode::AddObserver(Observer* observer) { @@ -189,7 +183,7 @@ void FrameTreeNode::ResetForNewProcess() { current_frame_host()->set_last_committed_url(GURL()); - TraceSnapshot(); + blame_context_.TakeSnapshot(); // Remove child nodes from the tree, then delete them. This destruction // operation will notify observers. @@ -215,7 +209,7 @@ if (!has_committed_real_load_ && url != GURL(url::kAboutBlankURL)) has_committed_real_load_ = true; current_frame_host()->set_last_committed_url(url); - TraceSnapshot(); + blame_context_.TakeSnapshot(); } void FrameTreeNode::SetCurrentOrigin( @@ -491,15 +485,6 @@ } } -void FrameTreeNode::TraceSnapshot() const { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( - "navigation", "FrameTreeNode", - TRACE_ID_WITH_SCOPE("FrameTreeNode", frame_tree_node_id_), - std::unique_ptr<base::trace_event::ConvertableToTraceFormat>( - new TracedFrameTreeNode(*this))); -} - FrameTreeNode* FrameTreeNode::GetSibling(int relative_offset) const { if (!parent_ || !parent_->child_count()) return nullptr;
diff --git a/content/browser/frame_host/frame_tree_node.h b/content/browser/frame_host/frame_tree_node.h index c6ab2b3..32e56234 100644 --- a/content/browser/frame_host/frame_tree_node.h +++ b/content/browser/frame_host/frame_tree_node.h
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "content/browser/frame_host/frame_tree_node_blame_context.h" #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/frame_host/render_frame_host_manager.h" #include "content/common/content_export.h" @@ -283,11 +284,12 @@ // FrameTreeNode. void BeforeUnloadCanceled(); + // Returns the BlameContext associated with this node. + FrameTreeNodeBlameContext& blame_context() { return blame_context_; } + private: class OpenerDestroyedObserver; - void TraceSnapshot() const; - FrameTreeNode* GetSibling(int relative_offset) const; // The next available browser-global FrameTreeNode ID. @@ -364,6 +366,11 @@ base::TimeTicks last_focus_time_; + // A helper for tracing the snapshots of this FrameTreeNode and attributing + // browser process activities to this node (when possible). It is unrelated + // to the core logic of FrameTreeNode. + FrameTreeNodeBlameContext blame_context_; + DISALLOW_COPY_AND_ASSIGN(FrameTreeNode); };
diff --git a/content/browser/frame_host/frame_tree_node_blame_context.cc b/content/browser/frame_host/frame_tree_node_blame_context.cc new file mode 100644 index 0000000..fb993be --- /dev/null +++ b/content/browser/frame_host/frame_tree_node_blame_context.cc
@@ -0,0 +1,71 @@ +// Copyright 2016 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. + +#include "content/browser/frame_host/frame_tree_node_blame_context.h" + +#include "base/strings/stringprintf.h" +#include "base/trace_event/trace_event_argument.h" +#include "content/browser/frame_host/frame_tree.h" +#include "url/gurl.h" + +namespace content { + +namespace { + +const char kFrameTreeNodeBlameContextCategory[] = "navigation"; +const char kFrameTreeNodeBlameContextName[] = "FrameTreeNodeBlameContext"; +const char kFrameTreeNodeBlameContextType[] = "FrameTreeNode"; +const char kFrameTreeNodeBlameContextScope[] = "FrameTreeNode"; +const char kRenderFrameBlameContextScope[] = "RenderFrame"; + +} // namespace + +FrameTreeNodeBlameContext::FrameTreeNodeBlameContext(int node_id, + FrameTreeNode* parent) + : base::trace_event::BlameContext(kFrameTreeNodeBlameContextCategory, + kFrameTreeNodeBlameContextName, + kFrameTreeNodeBlameContextType, + kFrameTreeNodeBlameContextScope, + node_id, + parent ? &parent->blame_context() + : nullptr) {} + +FrameTreeNodeBlameContext::~FrameTreeNodeBlameContext() {} + +void FrameTreeNodeBlameContext::AsValueInto( + base::trace_event::TracedValue* value) { + BlameContext::AsValueInto(value); + + // id() is equal to the owner FrameTreeNode's id, as set in the constructor. + FrameTreeNode* owner = FrameTreeNode::GloballyFindByID(id()); + DCHECK(owner); + + RenderFrameHostImpl* current_frame_host = owner->current_frame_host(); + if (!current_frame_host) + return; + + // On Windows, |rph->GetHandle()| does not duplicate ownership of the + // process handle and the render host still retains it. Therefore, we + // cannot create a base::Process object, which provides a proper way to get + // a process id, from the handle. For a stopgap, we use this deprecated + // function that does not require the ownership (http://crbug.com/417532). + int process_id = base::GetProcId( + current_frame_host->GetProcess()->GetHandle()); + if (process_id >= 0) { + int routing_id = current_frame_host->GetRoutingID(); + DCHECK_NE(routing_id, MSG_ROUTING_NONE); + + value->BeginDictionary(kRenderFrameBlameContextScope); + value->SetInteger("pid_ref", process_id); + value->SetString("id_ref", base::StringPrintf("0x%x", routing_id)); + value->SetString("scope", kRenderFrameBlameContextScope); + value->EndDictionary(); + } + + GURL url = current_frame_host->last_committed_url(); + if (url.is_valid()) + value->SetString("url", url.spec()); +} + +} // namespace content
diff --git a/content/browser/frame_host/frame_tree_node_blame_context.h b/content/browser/frame_host/frame_tree_node_blame_context.h new file mode 100644 index 0000000..6573f7c --- /dev/null +++ b/content/browser/frame_host/frame_tree_node_blame_context.h
@@ -0,0 +1,39 @@ +// Copyright 2016 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. + +#ifndef CONTENT_BROWSER_FRAME_HOST_FRAME_TREE_NODE_BLAME_CONTEXT_H +#define CONTENT_BROWSER_FRAME_HOST_FRAME_TREE_NODE_BLAME_CONTEXT_H + +#include "base/macros.h" +#include "base/trace_event/blame_context.h" +#include "url/gurl.h" + +namespace base { +namespace trace_event { +class TracedValue; +} +} + +namespace content { + +class FrameTreeNode; + +// FrameTreeNodeBlameContext is a helper class for tracing snapshots of each +// FrameTreeNode and attributing browser activities to frames (when possible), +// in the framework of FrameBlamer (crbug.com/546021). This class is unrelated +// to the core logic of FrameTreeNode. +class FrameTreeNodeBlameContext : public base::trace_event::BlameContext { + public: + FrameTreeNodeBlameContext(int node_id, FrameTreeNode* parent); + ~FrameTreeNodeBlameContext() override; + + private: + void AsValueInto(base::trace_event::TracedValue* value) override; + + DISALLOW_COPY_AND_ASSIGN(FrameTreeNodeBlameContext); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_FRAME_HOST_FRAME_TREE_NODE_BLAME_CONTEXT_H
diff --git a/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc b/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc new file mode 100644 index 0000000..6f76b92 --- /dev/null +++ b/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc
@@ -0,0 +1,263 @@ +// Copyright 2016 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. + +#include "content/browser/frame_host/frame_tree_node_blame_context.h" + +#include "base/memory/ptr_util.h" +#include "base/run_loop.h" +#include "base/test/trace_event_analyzer.h" +#include "base/trace_event/trace_buffer.h" +#include "base/trace_event/trace_event_argument.h" +#include "content/browser/frame_host/frame_tree.h" +#include "content/browser/frame_host/frame_tree_node.h" +#include "content/test/test_render_view_host.h" +#include "content/test/test_web_contents.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/public/web/WebSandboxFlags.h" + +namespace content { + +namespace { + +bool EventPointerCompare(const trace_analyzer::TraceEvent* lhs, + const trace_analyzer::TraceEvent* rhs) { + CHECK(lhs); + CHECK(rhs); + return *lhs < *rhs; +} + +void OnTraceDataCollected(base::Closure quit_closure, + base::trace_event::TraceResultBuffer* buffer, + const scoped_refptr<base::RefCountedString>& json, + bool has_more_events) { + buffer->AddFragment(json->data()); + if (!has_more_events) + quit_closure.Run(); +} + +void ExpectFrameTreeNodeObject(const trace_analyzer::TraceEvent* event) { + EXPECT_EQ("navigation", event->category); + EXPECT_EQ("FrameTreeNode", event->name); +} + +void ExpectFrameTreeNodeSnapshot(const trace_analyzer::TraceEvent* event) { + ExpectFrameTreeNodeObject(event); + EXPECT_TRUE(event->HasArg("snapshot")); + EXPECT_TRUE(event->arg_values.at("snapshot") + ->IsType(base::Value::Type::TYPE_DICTIONARY)); +} + +std::string GetParentNodeID(const trace_analyzer::TraceEvent* event) { + const base::Value* arg_snapshot = event->arg_values.at("snapshot").get(); + const base::DictionaryValue* snapshot; + EXPECT_TRUE(arg_snapshot->GetAsDictionary(&snapshot)); + if (!snapshot->HasKey("parent")) + return std::string(); + const base::DictionaryValue* parent; + EXPECT_TRUE(snapshot->GetDictionary("parent", &parent)); + std::string parent_id; + EXPECT_TRUE(parent->GetString("id_ref", &parent_id)); + return parent_id; +} + +std::string GetSnapshotURL(const trace_analyzer::TraceEvent* event) { + const base::Value* arg_snapshot = event->arg_values.at("snapshot").get(); + const base::DictionaryValue* snapshot; + EXPECT_TRUE(arg_snapshot->GetAsDictionary(&snapshot)); + if (!snapshot->HasKey("url")) + return std::string(); + std::string url; + EXPECT_TRUE(snapshot->GetString("url", &url)); + return url; +} + +} // namespace + +class FrameTreeNodeBlameContextTest : public RenderViewHostImplTestHarness { + public: + FrameTree* tree() { return contents()->GetFrameTree(); } + FrameTreeNode* root() { return tree()->root(); } + int process_id() { + return root()->current_frame_host()->GetProcess()->GetID(); + } + + // Creates a frame tree specified by |shape|, which is a string of paired + // parentheses. Each pair of parentheses represents a FrameTreeNode, and the + // nesting of parentheses represents the parent-child relation between nodes. + // Nodes represented by outer-most parentheses are children of the root node. + // NOTE: Each node can have at most 9 child nodes, and the tree height (i.e., + // max # of edges in any root-to-leaf path) must be at most 9. + // See the test cases for sample usage. + void CreateFrameTree(const char* shape) { + main_test_rfh()->InitializeRenderFrameIfNeeded(); + CreateSubframes(root(), 1, shape); + } + + void RemoveAllNonRootFrames() { + while (root()->child_count()) + tree()->RemoveFrame(root()->child_at(0)); + } + + void StartTracing() { + base::trace_event::TraceLog::GetInstance()->SetEnabled( + base::trace_event::TraceConfig("*"), + base::trace_event::TraceLog::RECORDING_MODE); + } + + void StopTracing() { + base::trace_event::TraceLog::GetInstance()->SetDisabled(); + } + + std::unique_ptr<trace_analyzer::TraceAnalyzer> CreateTraceAnalyzer() { + base::trace_event::TraceResultBuffer buffer; + base::trace_event::TraceResultBuffer::SimpleOutput trace_output; + buffer.SetOutputCallback(trace_output.GetCallback()); + base::RunLoop run_loop; + buffer.Start(); + base::trace_event::TraceLog::GetInstance()->Flush( + base::Bind(&OnTraceDataCollected, run_loop.QuitClosure(), + base::Unretained(&buffer))); + run_loop.Run(); + buffer.Finish(); + + return base::WrapUnique( + trace_analyzer::TraceAnalyzer::Create(trace_output.json_output)); + } + + private: + int CreateSubframes(FrameTreeNode* node, int self_id, const char* shape) { + int consumption = 0; + for (int child_num = 1; shape[consumption++] == '('; ++child_num) { + int child_id = self_id * 10 + child_num; + tree()->AddFrame( + node, process_id(), child_id, blink::WebTreeScopeType::Document, + std::string(), base::StringPrintf("uniqueName%d", child_id), + blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties()); + FrameTreeNode* child = node->child_at(child_num - 1); + consumption += CreateSubframes(child, child_id, shape + consumption); + } + return consumption; + } +}; + +// Creates a frame tree, tests if (i) the creation of each new frame is +// correctly traced, and (ii) the topology given by the snapshots is correct. +TEST_F(FrameTreeNodeBlameContextTest, FrameCreation) { + /* Shape of the frame tree to be created: + * () + * / \ + * () () + * / \ | + * () () () + * | + * () + */ + const char* tree_shape = "(()())((()))"; + + StartTracing(); + CreateFrameTree(tree_shape); + StopTracing(); + + std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer = + CreateTraceAnalyzer(); + trace_analyzer::TraceEventVector events; + trace_analyzer::Query q = + trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_CREATE_OBJECT) || + trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT); + analyzer->FindEvents(q, &events); + + // Two events for each new node: creation and snapshot. + EXPECT_EQ(12u, events.size()); + + std::set<FrameTreeNode*> creation_traced; + std::set<FrameTreeNode*> snapshot_traced; + for (auto event : events) { + ExpectFrameTreeNodeObject(event); + FrameTreeNode* node = + tree()->FindByID(strtol(event->id.c_str(), nullptr, 16)); + EXPECT_NE(nullptr, node); + if (event->HasArg("snapshot")) { + ExpectFrameTreeNodeSnapshot(event); + EXPECT_FALSE(ContainsValue(snapshot_traced, node)); + snapshot_traced.insert(node); + std::string parent_id = GetParentNodeID(event); + EXPECT_FALSE(parent_id.empty()); + EXPECT_EQ(node->parent(), + tree()->FindByID(strtol(parent_id.c_str(), nullptr, 16))); + } else { + EXPECT_EQ(TRACE_EVENT_PHASE_CREATE_OBJECT, event->phase); + EXPECT_FALSE(ContainsValue(creation_traced, node)); + creation_traced.insert(node); + } + } +} + +// Deletes frames from a frame tree, tests if the destruction of each frame is +// correctly traced. +TEST_F(FrameTreeNodeBlameContextTest, FrameDeletion) { + /* Shape of the frame tree to be created: + * () + * / \ + * () () + * / \ | + * () () () + * | + * () + */ + const char* tree_shape = "(()())((()))"; + + CreateFrameTree(tree_shape); + std::set<int> node_ids; + for (FrameTreeNode* node : tree()->Nodes()) + node_ids.insert(node->frame_tree_node_id()); + + StartTracing(); + RemoveAllNonRootFrames(); + StopTracing(); + + std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer = + CreateTraceAnalyzer(); + trace_analyzer::TraceEventVector events; + trace_analyzer::Query q = + trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_DELETE_OBJECT); + analyzer->FindEvents(q, &events); + + // The removal of all non-root nodes should be traced. + EXPECT_EQ(6u, events.size()); + for (auto event : events) { + ExpectFrameTreeNodeObject(event); + int id = strtol(event->id.c_str(), nullptr, 16); + EXPECT_TRUE(ContainsValue(node_ids, id)); + node_ids.erase(id); + } +} + +// Changes URL of the root node. Tests if URL change is correctly traced. +TEST_F(FrameTreeNodeBlameContextTest, URLChange) { + main_test_rfh()->InitializeRenderFrameIfNeeded(); + GURL url1("http://a.com/"); + GURL url2("https://b.net/"); + + StartTracing(); + root()->SetCurrentURL(url1); + root()->SetCurrentURL(url2); + root()->ResetForNewProcess(); + StopTracing(); + + std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer = + CreateTraceAnalyzer(); + trace_analyzer::TraceEventVector events; + trace_analyzer::Query q = + trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT); + analyzer->FindEvents(q, &events); + std::sort(events.begin(), events.end(), EventPointerCompare); + + // Three snapshots are traced, one for each URL change. + EXPECT_EQ(3u, events.size()); + EXPECT_EQ(url1.spec(), GetSnapshotURL(events[0])); + EXPECT_EQ(url2.spec(), GetSnapshotURL(events[1])); + EXPECT_EQ("", GetSnapshotURL(events[2])); +} + +} // namespace content
diff --git a/content/browser/frame_host/traced_frame_tree_node.cc b/content/browser/frame_host/traced_frame_tree_node.cc deleted file mode 100644 index 7026011..0000000 --- a/content/browser/frame_host/traced_frame_tree_node.cc +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2016 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. - -#include "content/browser/frame_host/traced_frame_tree_node.h" - -#include "base/command_line.h" -#include "base/json/json_writer.h" -#include "base/strings/stringprintf.h" -#include "content/browser/frame_host/frame_tree.h" -#include "content/public/common/content_switches.h" -#include "url/gurl.h" - -namespace content { - -TracedFrameTreeNode::TracedFrameTreeNode(const FrameTreeNode& node) - : parent_node_id_(-1), - process_id_(-1), - routing_id_(-1) { - FrameTreeNode* parent = node.parent(); - if (parent) - parent_node_id_ = parent->frame_tree_node_id(); - - RenderFrameHostImpl* current_frame_host = node.current_frame_host(); - - if (current_frame_host->last_committed_url().is_valid()) - url_ = current_frame_host->last_committed_url().spec(); - - // On Windows, |rph->GetHandle()| does not duplicate ownership - // of the process handle and the render host still retains it. Therefore, we - // cannot create a base::Process object, which provides a proper way to get a - // process id, from the handle. For a stopgap, we use this deprecated - // function that does not require the ownership (http://crbug.com/417532). - process_id_ = base::GetProcId(current_frame_host->GetProcess()->GetHandle()); - - routing_id_ = current_frame_host->GetRoutingID(); - DCHECK_NE(routing_id_, MSG_ROUTING_NONE); -} - -TracedFrameTreeNode::~TracedFrameTreeNode() { -} - -void TracedFrameTreeNode::AppendAsTraceFormat(std::string* out) const { - std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue()); - - if (parent_node_id_ >= 0) { - std::unique_ptr<base::DictionaryValue> ref(new base::DictionaryValue()); - ref->SetString("id_ref", base::StringPrintf("0x%x", parent_node_id_)); - ref->SetString("scope", "FrameTreeNode"); - value->Set("parent", std::move(ref)); - } - - if (process_id_ >= 0) { - std::unique_ptr<base::DictionaryValue> ref(new base::DictionaryValue()); - ref->SetInteger("pid_ref", process_id_); - ref->SetString("id_ref", base::StringPrintf("0x%x", routing_id_)); - ref->SetString("scope", "RenderFrame"); - value->Set("RenderFrame", std::move(ref)); - } - - if (!url_.empty()) - value->SetString("url", url_); - - std::string tmp; - base::JSONWriter::Write(*value, &tmp); - *out += tmp; -} - -} // content
diff --git a/content/browser/frame_host/traced_frame_tree_node.h b/content/browser/frame_host/traced_frame_tree_node.h deleted file mode 100644 index 79c2a80..0000000 --- a/content/browser/frame_host/traced_frame_tree_node.h +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2016 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. - -#include "base/macros.h" -#include "base/memory/scoped_vector.h" -#include "base/trace_event/trace_event_impl.h" -#include "base/values.h" -#include "content/common/content_export.h" - -namespace content { - -class FrameTree; -class FrameTreeNode; - -// This is a temporary container used when tracing snapshots of FrameTree -// objects. When a snapshot of a FrameTree is taken, a TracedFrameTreeNode is -// created and stored by the tracing system until the trace is dumped. -class CONTENT_EXPORT TracedFrameTreeNode : - public base::trace_event::ConvertableToTraceFormat { - public: - TracedFrameTreeNode(const FrameTreeNode& node); - void AppendAsTraceFormat(std::string* out) const override; - - private: - ~TracedFrameTreeNode() override; - - int parent_node_id_; - std::string url_; - int process_id_; - int routing_id_; - - DISALLOW_COPY_AND_ASSIGN(TracedFrameTreeNode); -}; - -} // content
diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 150367d..71d766a 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi
@@ -759,6 +759,8 @@ 'browser/frame_host/frame_tree.h', 'browser/frame_host/frame_tree_node.cc', 'browser/frame_host/frame_tree_node.h', + 'browser/frame_host/frame_tree_node_blame_context.cc', + 'browser/frame_host/frame_tree_node_blame_context.h', 'browser/frame_host/interstitial_page_impl.cc', 'browser/frame_host/interstitial_page_impl.h', 'browser/frame_host/interstitial_page_navigator_impl.cc', @@ -802,8 +804,6 @@ 'browser/frame_host/render_widget_host_view_child_frame.h', 'browser/frame_host/render_widget_host_view_guest.cc', 'browser/frame_host/render_widget_host_view_guest.h', - 'browser/frame_host/traced_frame_tree_node.cc', - 'browser/frame_host/traced_frame_tree_node.h', 'browser/gamepad/gamepad_consumer.h', 'browser/gamepad/gamepad_data_fetcher.cc', 'browser/gamepad/gamepad_data_fetcher.h',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 061b6476..4b773ca 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi
@@ -461,6 +461,7 @@ 'browser/fileapi/transient_file_util_unittest.cc', 'browser/fileapi/upload_file_system_file_element_reader_unittest.cc', 'browser/frame_host/frame_tree_unittest.cc', + 'browser/frame_host/frame_tree_node_blame_context_unittest.cc', 'browser/frame_host/navigation_controller_impl_unittest.cc', 'browser/frame_host/navigation_entry_impl_unittest.cc', 'browser/frame_host/navigation_handle_impl_unittest.cc',
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp index 84b3a098..1320b72 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.cpp +++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -3238,6 +3238,7 @@ if (LayoutViewItem layoutView = LayoutViewItem(document->layoutView())) { if (layoutView.usesCompositing()) layoutView.compositor()->frameViewDidScroll(); + layoutView.clearHitTestCache(); } if (m_didScrollTimer.isActive()) @@ -3247,7 +3248,6 @@ if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache()) cache->handleScrollPositionChanged(this); - layoutView()->clearHitTestCache(); frame().loader().saveScrollState(); frame().loader().client()->didChangeScrollOffset();
diff --git a/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp b/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp index 07c5d044..73fff60 100644 --- a/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp +++ b/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp
@@ -51,6 +51,8 @@ using blink::WebMediaSource; using blink::WebSourceBuffer; +#define MEDIA_SOURCE_LOG_LEVEL 3 + namespace blink { static bool throwExceptionIfClosedOrUpdating(bool isOpen, bool isUpdating, ExceptionState& exceptionState) @@ -102,24 +104,24 @@ , m_activeSourceBuffers(SourceBufferList::create(getExecutionContext(), m_asyncEventQueue.get())) , m_isAddedToRegistry(false) { - WTF_LOG(Media, "MediaSource::MediaSource %p", this); + DVLOG(MEDIA_SOURCE_LOG_LEVEL) << __FUNCTION__ << "(" << this << ")"; } MediaSource::~MediaSource() { - WTF_LOG(Media, "MediaSource::~MediaSource %p", this); - ASSERT(isClosed()); + DVLOG(MEDIA_SOURCE_LOG_LEVEL) << __FUNCTION__ << "(" << this << ")"; + DCHECK(isClosed()); } void MediaSource::logAndThrowDOMException(ExceptionState& exceptionState, const ExceptionCode& error, const String& message) { - WTF_LOG(Media, "throwDOMException: error=%d msg=%s", error, message.utf8().data()); + DVLOG(MEDIA_SOURCE_LOG_LEVEL) << __FUNCTION__ << "(error=" << error << ", message=" << message << ")"; exceptionState.throwDOMException(error, message); } SourceBuffer* MediaSource::addSourceBuffer(const String& type, ExceptionState& exceptionState) { - WTF_LOG(Media, "MediaSource::addSourceBuffer(%s) %p", type.ascii().data(), this); + DVLOG(MEDIA_SOURCE_LOG_LEVEL) << __FUNCTION__ << "(" << type << ") " << this; // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type // 1. If type is an empty string then throw an InvalidAccessError exception @@ -149,7 +151,7 @@ OwnPtr<WebSourceBuffer> webSourceBuffer = createWebSourceBuffer(contentType.type(), codecs, exceptionState); if (!webSourceBuffer) { - ASSERT(exceptionState.code() == NotSupportedError || exceptionState.code() == QuotaExceededError); + DCHECK(exceptionState.code() == NotSupportedError || exceptionState.code() == QuotaExceededError); // 2. If type contains a MIME type that is not supported ..., then throw a NotSupportedError exception and abort these steps. // 3. If the user agent can't handle any more SourceBuffer objects then throw a QuotaExceededError exception and abort these steps return 0; @@ -160,13 +162,13 @@ m_sourceBuffers->add(buffer); // 7. Return the new object to the caller. - WTF_LOG(Media, "MediaSource::addSourceBuffer(%s) %p -> %p", type.ascii().data(), this, buffer); + DVLOG(MEDIA_SOURCE_LOG_LEVEL) << __FUNCTION__ << "(" << type << ") " << buffer << " -> " << this; return buffer; } void MediaSource::removeSourceBuffer(SourceBuffer* buffer, ExceptionState& exceptionState) { - WTF_LOG(Media, "MediaSource::removeSourceBuffer() %p", this); + DVLOG(MEDIA_SOURCE_LOG_LEVEL) << __FUNCTION__ << "(" << buffer << ") -> " << this; // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-removeSourceBuffer-void-SourceBuffer-sourceBuffer @@ -203,7 +205,7 @@ return; } - ASSERT(isClosed()); + DCHECK(isClosed()); m_activeSourceBuffers->clear(); @@ -234,7 +236,7 @@ // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-MediaSource-isTypeSupported-boolean-DOMString-type // 1. If type is an empty string, then return false. if (type.isEmpty()) { - WTF_LOG(Media, "MediaSource::isTypeSupported(%s) -> false (empty input)", type.ascii().data()); + DVLOG(MEDIA_SOURCE_LOG_LEVEL) << __FUNCTION__ << "(" << type << ") -> false (empty input)"; return false; } @@ -243,14 +245,14 @@ // 2. If type does not contain a valid MIME type string, then return false. if (contentType.type().isEmpty()) { - WTF_LOG(Media, "MediaSource::isTypeSupported(%s) -> false (invalid mime type)", type.ascii().data()); + DVLOG(MEDIA_SOURCE_LOG_LEVEL) << __FUNCTION__ << "(" << type << ") -> false (invalid mime type)"; return false; } // Note: MediaSource.isTypeSupported() returning true implies that HTMLMediaElement.canPlayType() will return "maybe" or "probably" // since it does not make sense for a MediaSource to support a type the HTMLMediaElement knows it cannot play. if (HTMLMediaElement::supportsType(contentType) == WebMimeRegistry::IsNotSupported) { - WTF_LOG(Media, "MediaSource::isTypeSupported(%s) -> false (not supported by HTMLMediaElement)", type.ascii().data()); + DVLOG(MEDIA_SOURCE_LOG_LEVEL) << __FUNCTION__ << "(" << type << ") -> false (not supported by HTMLMediaElement)"; return false; } @@ -259,7 +261,7 @@ // 5. If the MediaSource does not support the specified combination of media type, media subtype, and codecs then return false. // 6. Return true. bool result = MIMETypeRegistry::isSupportedMediaSourceMIMEType(contentType.type(), codecs); - WTF_LOG(Media, "MediaSource::isTypeSupported(%s) -> %s", type.ascii().data(), result ? "true" : "false"); + DVLOG(MEDIA_SOURCE_LOG_LEVEL) << __FUNCTION__ << "(" << type << ") -> " << (result ? "true" : "false"); return result; } @@ -286,22 +288,22 @@ void MediaSource::setWebMediaSourceAndOpen(PassOwnPtr<WebMediaSource> webMediaSource) { TRACE_EVENT_ASYNC_END0("media", "MediaSource::attachToElement", this); - ASSERT(webMediaSource); - ASSERT(!m_webMediaSource); - ASSERT(m_attachedElement); + DCHECK(webMediaSource); + DCHECK(!m_webMediaSource); + DCHECK(m_attachedElement); m_webMediaSource = std::move(webMediaSource); setReadyState(openKeyword()); } void MediaSource::addedToRegistry() { - ASSERT(!m_isAddedToRegistry); + DCHECK(!m_isAddedToRegistry); m_isAddedToRegistry = true; } void MediaSource::removedFromRegistry() { - ASSERT(m_isAddedToRegistry); + DCHECK(m_isAddedToRegistry); m_isAddedToRegistry = false; } @@ -442,10 +444,10 @@ void MediaSource::setReadyState(const AtomicString& state) { - ASSERT(state == openKeyword() || state == closedKeyword() || state == endedKeyword()); + DCHECK(state == openKeyword() || state == closedKeyword() || state == endedKeyword()); AtomicString oldState = readyState(); - WTF_LOG(Media, "MediaSource::setReadyState() %p : %s -> %s", this, oldState.ascii().data(), state.ascii().data()); + DVLOG(MEDIA_SOURCE_LOG_LEVEL) << __FUNCTION__ << " : " << oldState << " -> " << state << " " << this; if (state == closedKeyword()) { m_webMediaSource.clear(); @@ -469,7 +471,7 @@ } else if (error == decode) { endOfStreamInternal(WebMediaSource::EndOfStreamStatusDecodeError, exceptionState); } else { - ASSERT_NOT_REACHED(); // IDL enforcement should prevent this case. + NOTREACHED(); // IDL enforcement should prevent this case. } } @@ -504,7 +506,7 @@ void MediaSource::setSourceBufferActive(SourceBuffer* sourceBuffer) { - ASSERT(!m_activeSourceBuffers->contains(sourceBuffer)); + DCHECK(!m_activeSourceBuffers->contains(sourceBuffer)); // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-MediaSource-activeSourceBuffers // SourceBuffer objects in SourceBuffer.activeSourceBuffers must appear in @@ -513,7 +515,7 @@ // same order as buffers in |m_sourceBuffers|, so this method needs to // insert |sourceBuffer| into |m_activeSourceBuffers|. size_t indexInSourceBuffers = m_sourceBuffers->find(sourceBuffer); - ASSERT(indexInSourceBuffers != kNotFound); + DCHECK(indexInSourceBuffers != kNotFound); size_t insertPosition = 0; while (insertPosition < m_activeSourceBuffers->length() @@ -544,7 +546,7 @@ if (m_attachedElement) return false; - ASSERT(isClosed()); + DCHECK(isClosed()); TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSource::attachToElement", this); m_attachedElement = element; @@ -583,7 +585,7 @@ case WebMediaSource::AddStatusOk: return adoptPtr(webSourceBuffer); case WebMediaSource::AddStatusNotSupported: - ASSERT(!webSourceBuffer); + DCHECK(!webSourceBuffer); // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type // Step 2: If type contains a MIME type ... that is not supported with the types // specified for the other SourceBuffer objects in sourceBuffers, then throw @@ -591,7 +593,7 @@ logAndThrowDOMException(exceptionState, NotSupportedError, "The type provided ('" + type + "') is not supported."); return nullptr; case WebMediaSource::AddStatusReachedIdLimit: - ASSERT(!webSourceBuffer); + DCHECK(!webSourceBuffer); // 2.2 https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type // Step 3: If the user agent can't handle any more SourceBuffer objects then throw // a QuotaExceededError exception and abort these steps. @@ -599,13 +601,13 @@ return nullptr; } - ASSERT_NOT_REACHED(); + NOTREACHED(); return nullptr; } void MediaSource::scheduleEvent(const AtomicString& eventName) { - ASSERT(m_asyncEventQueue); + DCHECK(m_asyncEventQueue); Event* event = Event::create(eventName); event->setTarget(this);
diff --git a/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp b/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp index 8ccf343..8e0eb43 100644 --- a/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp +++ b/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp
@@ -114,6 +114,8 @@ if (!decoder) return 0; + // Blink does not know Skia has already adopted |data|. + WTF::adopted(data); RefPtr<SegmentReader> segmentReader = SegmentReader::createFromSkData(data); decoder->setData(segmentReader.get(), true); if (!decoder->isSizeAvailable())