diff --git a/DEPS b/DEPS index 0a0b968..4d9810f 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': '935b8785b9c5c7e29732c0a4830704e4be4d13f5', + 'v8_revision': 'c6d4236d881aa80fb360d95a361672082a66a15e', # 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/android_webview/common/render_view_messages.h b/android_webview/common/render_view_messages.h index e13c3a2..45796f1 100644 --- a/android_webview/common/render_view_messages.h +++ b/android_webview/common/render_view_messages.h
@@ -81,7 +81,7 @@ IPC_MESSAGE_ROUTED3(AwViewMsg_SmoothScroll, int /* target_x */, int /* target_y */, - long /* duration_ms */); + long /* duration_ms */) //----------------------------------------------------------------------------- // RenderView messages
diff --git a/base/win/registry.cc b/base/win/registry.cc index 28e0461..ea96e67 100644 --- a/base/win/registry.cc +++ b/base/win/registry.cc
@@ -364,7 +364,7 @@ DWORD type = REG_MULTI_SZ; DWORD size = 0; LONG result = ReadValue(name, NULL, &size, &type); - if (FAILED(result) || size == 0) + if (result != ERROR_SUCCESS || size == 0) return result; if (type != REG_MULTI_SZ) @@ -372,7 +372,7 @@ std::vector<wchar_t> buffer(size / sizeof(wchar_t)); result = ReadValue(name, &buffer[0], &size, NULL); - if (FAILED(result) || size == 0) + if (result != ERROR_SUCCESS || size == 0) return result; // Parse the double-null-terminated list of strings.
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc index a38c2552..d4d321c 100644 --- a/chrome/common/chrome_content_client.cc +++ b/chrome/common/chrome_content_client.cc
@@ -330,7 +330,7 @@ base::win::RegKey path_key(HKEY_LOCAL_MACHINE, kFlashRegistryRoot, KEY_READ); DWORD debug_value; - if (FAILED(path_key.ReadValueDW(kIsDebuggerValueName, &debug_value))) + if (path_key.ReadValueDW(kIsDebuggerValueName, &debug_value) != ERROR_SUCCESS) return false; return (debug_value == 1);
diff --git a/components/mus/ws/window_tree_apptest.cc b/components/mus/ws/window_tree_apptest.cc index 3cc0ca0..0e5e0ad 100644 --- a/components/mus/ws/window_tree_apptest.cc +++ b/components/mus/ws/window_tree_apptest.cc
@@ -30,7 +30,6 @@ using mus::mojom::WindowTreeClient; namespace mus { - namespace ws { namespace { @@ -76,7 +75,7 @@ // ----------------------------------------------------------------------------- bool EmbedUrl(mojo::ApplicationImpl* app, - WindowTree* vm, + WindowTree* ws, const String& url, Id root_id) { bool result = false; @@ -88,82 +87,82 @@ app->ConnectToApplication(request.Pass()); mojom::WindowTreeClientPtr client; connection->ConnectToService(&client); - vm->Embed(root_id, client.Pass(), mojom::WindowTree::ACCESS_POLICY_DEFAULT, + ws->Embed(root_id, client.Pass(), mojom::WindowTree::ACCESS_POLICY_DEFAULT, base::Bind(&EmbedCallbackImpl, &run_loop, &result)); } run_loop.Run(); return result; } -bool Embed(WindowTree* vm, Id root_id, mojom::WindowTreeClientPtr client) { +bool Embed(WindowTree* ws, Id root_id, mojom::WindowTreeClientPtr client) { bool result = false; base::RunLoop run_loop; { - vm->Embed(root_id, client.Pass(), mojom::WindowTree::ACCESS_POLICY_DEFAULT, + ws->Embed(root_id, client.Pass(), mojom::WindowTree::ACCESS_POLICY_DEFAULT, base::Bind(&EmbedCallbackImpl, &run_loop, &result)); } run_loop.Run(); return result; } -ErrorCode NewWindowWithErrorCode(WindowTree* vm, Id window_id) { +ErrorCode NewWindowWithErrorCode(WindowTree* ws, Id window_id) { ErrorCode result = ERROR_CODE_NONE; base::RunLoop run_loop; - vm->NewWindow(window_id, + ws->NewWindow(window_id, base::Bind(&ErrorCodeResultCallback, &run_loop, &result)); run_loop.Run(); return result; } -bool AddWindow(WindowTree* vm, Id parent, Id child) { +bool AddWindow(WindowTree* ws, Id parent, Id child) { bool result = false; base::RunLoop run_loop; - vm->AddWindow(parent, child, + ws->AddWindow(parent, child, base::Bind(&BoolResultCallback, &run_loop, &result)); run_loop.Run(); return result; } -bool RemoveWindowFromParent(WindowTree* vm, Id window_id) { +bool RemoveWindowFromParent(WindowTree* ws, Id window_id) { bool result = false; base::RunLoop run_loop; - vm->RemoveWindowFromParent( + ws->RemoveWindowFromParent( window_id, base::Bind(&BoolResultCallback, &run_loop, &result)); run_loop.Run(); return result; } -bool ReorderWindow(WindowTree* vm, +bool ReorderWindow(WindowTree* ws, Id window_id, Id relative_window_id, mojom::OrderDirection direction) { bool result = false; base::RunLoop run_loop; - vm->ReorderWindow(window_id, relative_window_id, direction, + ws->ReorderWindow(window_id, relative_window_id, direction, base::Bind(&BoolResultCallback, &run_loop, &result)); run_loop.Run(); return result; } -void GetWindowTree(WindowTree* vm, +void GetWindowTree(WindowTree* ws, Id window_id, std::vector<TestWindow>* windows) { base::RunLoop run_loop; - vm->GetWindowTree(window_id, + ws->GetWindowTree(window_id, base::Bind(&WindowTreeResultCallback, &run_loop, windows)); run_loop.Run(); } -bool DeleteWindow(WindowTree* vm, Id window_id) { +bool DeleteWindow(WindowTree* ws, Id window_id) { base::RunLoop run_loop; bool result = false; - vm->DeleteWindow(window_id, + ws->DeleteWindow(window_id, base::Bind(&BoolResultCallback, &run_loop, &result)); run_loop.Run(); return result; } -bool SetWindowBounds(WindowTree* vm, Id window_id, int x, int y, int w, int h) { +bool SetWindowBounds(WindowTree* ws, Id window_id, int x, int y, int w, int h) { base::RunLoop run_loop; bool result = false; RectPtr rect(mojo::Rect::New()); @@ -171,22 +170,22 @@ rect->y = y; rect->width = w; rect->height = h; - vm->SetWindowBounds(window_id, rect.Pass(), + ws->SetWindowBounds(window_id, rect.Pass(), base::Bind(&BoolResultCallback, &run_loop, &result)); run_loop.Run(); return result; } -bool SetWindowVisibility(WindowTree* vm, Id window_id, bool visible) { +bool SetWindowVisibility(WindowTree* ws, Id window_id, bool visible) { base::RunLoop run_loop; bool result = false; - vm->SetWindowVisibility(window_id, visible, + ws->SetWindowVisibility(window_id, visible, base::Bind(&BoolResultCallback, &run_loop, &result)); run_loop.Run(); return result; } -bool SetWindowProperty(WindowTree* vm, +bool SetWindowProperty(WindowTree* ws, Id window_id, const std::string& name, const std::vector<uint8_t>* data) { @@ -195,7 +194,7 @@ Array<uint8_t> mojo_data; if (data) mojo_data = Array<uint8_t>::From(*data); - vm->SetWindowProperty(window_id, name, mojo_data.Pass(), + ws->SetWindowProperty(window_id, name, mojo_data.Pass(), base::Bind(&BoolResultCallback, &run_loop, &result)); run_loop.Run(); return result; @@ -203,14 +202,14 @@ // Utility functions ----------------------------------------------------------- -// Waits for all messages to be received by |vm|. This is done by attempting to +// Waits for all messages to be received by |ws|. This is done by attempting to // create a bogus window. When we get the response we know all messages have // been // processed. -bool WaitForAllMessages(WindowTree* vm) { +bool WaitForAllMessages(WindowTree* ws) { ErrorCode result = ERROR_CODE_NONE; base::RunLoop run_loop; - vm->NewWindow(WindowIdToTransportId(InvalidWindowId()), + ws->NewWindow(WindowIdToTransportId(InvalidWindowId()), base::Bind(&ErrorCodeResultCallback, &run_loop, &result)); run_loop.Run(); return result != ERROR_CODE_NONE; @@ -440,19 +439,19 @@ protected: // Returns the changes from the various connections. - std::vector<Change>* changes1() { return vm_client1_->tracker()->changes(); } - std::vector<Change>* changes2() { return vm_client2_->tracker()->changes(); } - std::vector<Change>* changes3() { return vm_client3_->tracker()->changes(); } + std::vector<Change>* changes1() { return ws_client1_->tracker()->changes(); } + std::vector<Change>* changes2() { return ws_client2_->tracker()->changes(); } + std::vector<Change>* changes3() { return ws_client3_->tracker()->changes(); } - // Various connections. |vm1()|, being the first connection, has special + // Various connections. |ws1()|, being the first connection, has special // permissions (it's treated as the window manager). - WindowTree* vm1() { return vm_client1_->tree(); } - WindowTree* vm2() { return vm_client2_->tree(); } - WindowTree* vm3() { return vm_client3_->tree(); } + WindowTree* ws1() { return ws_client1_->tree(); } + WindowTree* ws2() { return ws_client2_->tree(); } + WindowTree* ws3() { return ws_client3_->tree(); } - TestWindowTreeClientImpl* vm_client1() { return vm_client1_.get(); } - TestWindowTreeClientImpl* vm_client2() { return vm_client2_.get(); } - TestWindowTreeClientImpl* vm_client3() { return vm_client3_.get(); } + TestWindowTreeClientImpl* ws_client1() { return ws_client1_.get(); } + TestWindowTreeClientImpl* ws_client2() { return ws_client2_.get(); } + TestWindowTreeClientImpl* ws_client3() { return ws_client3_.get(); } Id root_window_id() const { return root_window_id_; } @@ -460,18 +459,18 @@ int connection_id_2() const { return connection_id_2_; } void EstablishSecondConnectionWithRoot(Id root_id) { - ASSERT_TRUE(vm_client2_.get() == nullptr); - vm_client2_ = - EstablishConnectionViaEmbed(vm1(), root_id, &connection_id_2_); + ASSERT_TRUE(ws_client2_.get() == nullptr); + ws_client2_ = + EstablishConnectionViaEmbed(ws1(), root_id, &connection_id_2_); ASSERT_GT(connection_id_2_, 0); - ASSERT_TRUE(vm_client2_.get() != nullptr); - vm_client2_->set_root_window(root_window_id_); + ASSERT_TRUE(ws_client2_.get() != nullptr); + ws_client2_->set_root_window(root_window_id_); } void EstablishSecondConnection(bool create_initial_window) { Id window_1_1 = 0; if (create_initial_window) { - window_1_1 = vm_client1()->NewWindow(1); + window_1_1 = ws_client1()->NewWindow(1); ASSERT_TRUE(window_1_1); } ASSERT_NO_FATAL_FAILURE( @@ -484,10 +483,10 @@ } void EstablishThirdConnection(WindowTree* owner, Id root_id) { - ASSERT_TRUE(vm_client3_.get() == nullptr); - vm_client3_ = EstablishConnectionViaEmbed(owner, root_id, nullptr); - ASSERT_TRUE(vm_client3_.get() != nullptr); - vm_client3_->set_root_window(root_window_id_); + ASSERT_TRUE(ws_client3_.get() == nullptr); + ws_client3_ = EstablishConnectionViaEmbed(owner, root_id, nullptr); + ASSERT_TRUE(ws_client3_.get() != nullptr); + ws_client3_->set_root_window(root_window_id_); } scoped_ptr<TestWindowTreeClientImpl> WaitForWindowTreeClient() { @@ -542,15 +541,15 @@ application_impl()->ConnectToService(request.Pass(), &factory); mojom::WindowTreeClientPtr tree_client_ptr; - vm_client1_.reset(new TestWindowTreeClientImpl(application_impl())); - vm_client1_->Bind(GetProxy(&tree_client_ptr)); + ws_client1_.reset(new TestWindowTreeClientImpl(application_impl())); + ws_client1_->Bind(GetProxy(&tree_client_ptr)); factory->CreateWindowTreeHost(GetProxy(&host_), mojom::WindowTreeHostClientPtr(), tree_client_ptr.Pass(), nullptr); // Next we should get an embed call on the "window manager" client. - vm_client1_->WaitForIncomingMethodCall(); + ws_client1_->WaitForIncomingMethodCall(); ASSERT_EQ(1u, changes1()->size()); EXPECT_EQ(CHANGE_TYPE_EMBED, (*changes1())[0].type); @@ -561,7 +560,7 @@ connection_id_1_ = (*changes1())[0].connection_id; ASSERT_FALSE((*changes1())[0].windows.empty()); root_window_id_ = (*changes1())[0].windows[0].window_id; - vm_client1_->set_root_window(root_window_id_); + ws_client1_->set_root_window(root_window_id_); changes1()->clear(); } @@ -571,9 +570,9 @@ return true; } - scoped_ptr<TestWindowTreeClientImpl> vm_client1_; - scoped_ptr<TestWindowTreeClientImpl> vm_client2_; - scoped_ptr<TestWindowTreeClientImpl> vm_client3_; + scoped_ptr<TestWindowTreeClientImpl> ws_client1_; + scoped_ptr<TestWindowTreeClientImpl> ws_client2_; + scoped_ptr<TestWindowTreeClientImpl> ws_client3_; mojom::WindowTreeHostPtr host_; @@ -597,13 +596,13 @@ // Verifies when Embed() is invoked any child windows are removed. TEST_F(WindowTreeAppTest, WindowsRemovedWhenEmbedding) { // Two windows 1 and 2. 2 is parented to 1. - Id window_1_1 = vm_client1()->NewWindow(1); + Id window_1_1 = ws_client1()->NewWindow(1); ASSERT_TRUE(window_1_1); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_1)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_1)); - Id window_1_2 = vm_client1()->NewWindow(2); + Id window_1_2 = ws_client1()->NewWindow(2); ASSERT_TRUE(window_1_2); - ASSERT_TRUE(AddWindow(vm1(), window_1_1, window_1_2)); + ASSERT_TRUE(AddWindow(ws1(), window_1_1, window_1_2)); ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); ASSERT_EQ(1u, changes2()->size()); @@ -614,43 +613,43 @@ // Embed() removed window 2. { std::vector<TestWindow> windows; - GetWindowTree(vm1(), window_1_2, &windows); + GetWindowTree(ws1(), window_1_2, &windows); EXPECT_EQ(WindowParentToString(window_1_2, kNullParentId), SingleWindowDescription(windows)); } - // vm2 should not see window 2. + // ws2 should not see window 2. { std::vector<TestWindow> windows; - GetWindowTree(vm2(), window_1_1, &windows); + GetWindowTree(ws2(), window_1_1, &windows); EXPECT_EQ(WindowParentToString(window_1_1, kNullParentId), SingleWindowDescription(windows)); } { std::vector<TestWindow> windows; - GetWindowTree(vm2(), window_1_2, &windows); + GetWindowTree(ws2(), window_1_2, &windows); EXPECT_TRUE(windows.empty()); } // Windows 3 and 4 in connection 2. - Id window_2_3 = vm_client2()->NewWindow(3); - Id window_2_4 = vm_client2()->NewWindow(4); + Id window_2_3 = ws_client2()->NewWindow(3); + Id window_2_4 = ws_client2()->NewWindow(4); ASSERT_TRUE(window_2_3); ASSERT_TRUE(window_2_4); - ASSERT_TRUE(AddWindow(vm2(), window_2_3, window_2_4)); + ASSERT_TRUE(AddWindow(ws2(), window_2_3, window_2_4)); // Connection 3 rooted at 2. - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm2(), window_2_3)); + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_3)); // Window 4 should no longer have a parent. { std::vector<TestWindow> windows; - GetWindowTree(vm2(), window_2_3, &windows); + GetWindowTree(ws2(), window_2_3, &windows); EXPECT_EQ(WindowParentToString(window_2_3, kNullParentId), SingleWindowDescription(windows)); windows.clear(); - GetWindowTree(vm2(), window_2_4, &windows); + GetWindowTree(ws2(), window_2_4, &windows); EXPECT_EQ(WindowParentToString(window_2_4, kNullParentId), SingleWindowDescription(windows)); } @@ -658,7 +657,7 @@ // And window 4 should not be visible to connection 3. { std::vector<TestWindow> windows; - GetWindowTree(vm3(), window_2_3, &windows); + GetWindowTree(ws3(), window_2_3, &windows); EXPECT_EQ(WindowParentToString(window_2_3, kNullParentId), SingleWindowDescription(windows)); } @@ -670,21 +669,21 @@ ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_2 = vm_client2()->NewWindow(2); + Id window_2_2 = ws_client2()->NewWindow(2); ASSERT_TRUE(window_2_2); - ASSERT_TRUE(AddWindow(vm2(), window_1_1, window_2_2)); + ASSERT_TRUE(AddWindow(ws2(), window_1_1, window_2_2)); - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm2(), window_2_2)); + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_2)); - Id window_3_3 = vm_client3()->NewWindow(3); + Id window_3_3 = ws_client3()->NewWindow(3); ASSERT_TRUE(window_3_3); - ASSERT_TRUE(AddWindow(vm3(), window_2_2, window_3_3)); + ASSERT_TRUE(AddWindow(ws3(), window_2_2, window_3_3)); // Even though 3 is a child of 2 connection 2 can't see 3 as it's from a // different connection. { std::vector<TestWindow> windows; - GetWindowTree(vm2(), window_2_2, &windows); + GetWindowTree(ws2(), window_2_2, &windows); EXPECT_EQ(WindowParentToString(window_2_2, window_1_1), SingleWindowDescription(windows)); } @@ -692,14 +691,14 @@ // Connection 2 shouldn't be able to get window 3 at all. { std::vector<TestWindow> windows; - GetWindowTree(vm2(), window_3_3, &windows); + GetWindowTree(ws2(), window_3_3, &windows); EXPECT_TRUE(windows.empty()); } // Connection 1 should be able to see it all (its the root). { std::vector<TestWindow> windows; - GetWindowTree(vm1(), window_1_1, &windows); + GetWindowTree(ws1(), window_1_1, &windows); ASSERT_EQ(3u, windows.size()); EXPECT_EQ(WindowParentToString(window_1_1, kNullParentId), windows[0].ToString()); @@ -715,80 +714,80 @@ ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_2 = vm_client2()->NewWindow(2); + Id window_2_2 = ws_client2()->NewWindow(2); ASSERT_TRUE(window_2_2); - ASSERT_TRUE(AddWindow(vm2(), window_1_1, window_2_2)); + ASSERT_TRUE(AddWindow(ws2(), window_1_1, window_2_2)); - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm2(), window_2_2)); + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_2)); - Id window_2_3 = vm_client2()->NewWindow(3); + Id window_2_3 = ws_client2()->NewWindow(3); ASSERT_TRUE(window_2_3); // Connection 2 shouldn't be able to add anything to the window anymore. - ASSERT_FALSE(AddWindow(vm2(), window_2_2, window_2_3)); + ASSERT_FALSE(AddWindow(ws2(), window_2_2, window_2_3)); // Create window 3 in connection 3 and add it to window 3. - Id window_3_3 = vm_client3()->NewWindow(3); + Id window_3_3 = ws_client3()->NewWindow(3); ASSERT_TRUE(window_3_3); - ASSERT_TRUE(AddWindow(vm3(), window_2_2, window_3_3)); + ASSERT_TRUE(AddWindow(ws3(), window_2_2, window_3_3)); // Connection 2 shouldn't be able to remove window 3. - ASSERT_FALSE(RemoveWindowFromParent(vm2(), window_3_3)); + ASSERT_FALSE(RemoveWindowFromParent(ws2(), window_3_3)); } // Verifies client gets a valid id. TEST_F(WindowTreeAppTest, NewWindow) { - Id window_1_1 = vm_client1()->NewWindow(1); + Id window_1_1 = ws_client1()->NewWindow(1); ASSERT_TRUE(window_1_1); EXPECT_TRUE(changes1()->empty()); // Can't create a window with the same id. ASSERT_EQ(mojom::ERROR_CODE_VALUE_IN_USE, - NewWindowWithErrorCode(vm1(), window_1_1)); + NewWindowWithErrorCode(ws1(), window_1_1)); EXPECT_TRUE(changes1()->empty()); // Can't create a window with a bogus connection id. EXPECT_EQ( mojom::ERROR_CODE_ILLEGAL_ARGUMENT, - NewWindowWithErrorCode(vm1(), BuildWindowId(connection_id_1() + 1, 1))); + NewWindowWithErrorCode(ws1(), BuildWindowId(connection_id_1() + 1, 1))); EXPECT_TRUE(changes1()->empty()); } // Verifies AddWindow fails when window is already in position. TEST_F(WindowTreeAppTest, AddWindowWithNoChange) { - Id window_1_2 = vm_client1()->NewWindow(2); - Id window_1_3 = vm_client1()->NewWindow(3); + Id window_1_2 = ws_client1()->NewWindow(2); + Id window_1_3 = ws_client1()->NewWindow(3); ASSERT_TRUE(window_1_2); ASSERT_TRUE(window_1_3); ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); // Make 3 a child of 2. - ASSERT_TRUE(AddWindow(vm1(), window_1_2, window_1_3)); + ASSERT_TRUE(AddWindow(ws1(), window_1_2, window_1_3)); // Try again, this should fail. - EXPECT_FALSE(AddWindow(vm1(), window_1_2, window_1_3)); + EXPECT_FALSE(AddWindow(ws1(), window_1_2, window_1_3)); } // Verifies AddWindow fails when window is already in position. TEST_F(WindowTreeAppTest, AddAncestorFails) { - Id window_1_2 = vm_client1()->NewWindow(2); - Id window_1_3 = vm_client1()->NewWindow(3); + Id window_1_2 = ws_client1()->NewWindow(2); + Id window_1_3 = ws_client1()->NewWindow(3); ASSERT_TRUE(window_1_2); ASSERT_TRUE(window_1_3); ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); // Make 3 a child of 2. - ASSERT_TRUE(AddWindow(vm1(), window_1_2, window_1_3)); + ASSERT_TRUE(AddWindow(ws1(), window_1_2, window_1_3)); // Try to make 2 a child of 3, this should fail since 2 is an ancestor of 3. - EXPECT_FALSE(AddWindow(vm1(), window_1_3, window_1_2)); + EXPECT_FALSE(AddWindow(ws1(), window_1_3, window_1_2)); } // Verifies adding to root sends right notifications. TEST_F(WindowTreeAppTest, AddToRoot) { - Id window_1_21 = vm_client1()->NewWindow(21); - Id window_1_3 = vm_client1()->NewWindow(3); + Id window_1_21 = ws_client1()->NewWindow(21); + Id window_1_3 = ws_client1()->NewWindow(3); ASSERT_TRUE(window_1_21); ASSERT_TRUE(window_1_3); @@ -797,41 +796,41 @@ changes2()->clear(); // Make 3 a child of 21. - ASSERT_TRUE(AddWindow(vm1(), window_1_21, window_1_3)); + ASSERT_TRUE(AddWindow(ws1(), window_1_21, window_1_3)); // Make 21 a child of 1. - ASSERT_TRUE(AddWindow(vm1(), window_1_1, window_1_21)); + ASSERT_TRUE(AddWindow(ws1(), window_1_1, window_1_21)); // Connection 2 should not be told anything (because the window is from a // different connection). Create a window to ensure we got a response from // the server. - ASSERT_TRUE(vm_client2()->NewWindow(100)); + ASSERT_TRUE(ws_client2()->NewWindow(100)); EXPECT_TRUE(changes2()->empty()); } // Verifies HierarchyChanged is correctly sent for various adds/removes. TEST_F(WindowTreeAppTest, WindowHierarchyChangedWindows) { // 1,2->1,11. - Id window_1_2 = vm_client1()->NewWindow(2); + Id window_1_2 = ws_client1()->NewWindow(2); ASSERT_TRUE(window_1_2); - ASSERT_TRUE(SetWindowVisibility(vm1(), window_1_2, true)); - Id window_1_11 = vm_client1()->NewWindow(11); + ASSERT_TRUE(SetWindowVisibility(ws1(), window_1_2, true)); + Id window_1_11 = ws_client1()->NewWindow(11); ASSERT_TRUE(window_1_11); - ASSERT_TRUE(SetWindowVisibility(vm1(), window_1_11, true)); - ASSERT_TRUE(AddWindow(vm1(), window_1_2, window_1_11)); + ASSERT_TRUE(SetWindowVisibility(ws1(), window_1_11, true)); + ASSERT_TRUE(AddWindow(ws1(), window_1_2, window_1_11)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); - ASSERT_TRUE(SetWindowVisibility(vm1(), window_1_1, true)); + ASSERT_TRUE(SetWindowVisibility(ws1(), window_1_1, true)); - ASSERT_TRUE(WaitForAllMessages(vm2())); + ASSERT_TRUE(WaitForAllMessages(ws2())); changes2()->clear(); // 1,1->1,2->1,11 { // Client 2 should not get anything (1,2 is from another connection). - ASSERT_TRUE(AddWindow(vm1(), window_1_1, window_1_2)); - ASSERT_TRUE(WaitForAllMessages(vm2())); + ASSERT_TRUE(AddWindow(ws1(), window_1_1, window_1_2)); + ASSERT_TRUE(WaitForAllMessages(ws2())); EXPECT_TRUE(changes2()->empty()); } @@ -839,8 +838,8 @@ { // Client 2 is now connected to the root, so it should have gotten a drawn // notification. - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_1)); - vm_client2_->WaitForChangeCount(1u); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_1)); + ws_client2_->WaitForChangeCount(1u); EXPECT_EQ( "DrawnStateChanged window=" + IdToString(window_1_1) + " drawn=true", SingleChangeToDescription(*changes2())); @@ -851,29 +850,29 @@ // Client 2 is no longer connected to the root, should get drawn state // changed. changes2()->clear(); - ASSERT_TRUE(RemoveWindowFromParent(vm1(), window_1_1)); - vm_client2_->WaitForChangeCount(1); + ASSERT_TRUE(RemoveWindowFromParent(ws1(), window_1_1)); + ws_client2_->WaitForChangeCount(1); EXPECT_EQ( "DrawnStateChanged window=" + IdToString(window_1_1) + " drawn=false", SingleChangeToDescription(*changes2())); } // 1,1->1,2->1,11->1,111. - Id window_1_111 = vm_client1()->NewWindow(111); + Id window_1_111 = ws_client1()->NewWindow(111); ASSERT_TRUE(window_1_111); - ASSERT_TRUE(SetWindowVisibility(vm1(), window_1_111, true)); + ASSERT_TRUE(SetWindowVisibility(ws1(), window_1_111, true)); { changes2()->clear(); - ASSERT_TRUE(AddWindow(vm1(), window_1_11, window_1_111)); - ASSERT_TRUE(WaitForAllMessages(vm2())); + ASSERT_TRUE(AddWindow(ws1(), window_1_11, window_1_111)); + ASSERT_TRUE(WaitForAllMessages(ws2())); EXPECT_TRUE(changes2()->empty()); } // 0,1->1,1->1,2->1,11->1,111 { changes2()->clear(); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_1)); - vm_client2_->WaitForChangeCount(1); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_1)); + ws_client2_->WaitForChangeCount(1); EXPECT_EQ( "DrawnStateChanged window=" + IdToString(window_1_1) + " drawn=true", SingleChangeToDescription(*changes2())); @@ -886,24 +885,24 @@ ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_11 = vm_client2()->NewWindow(11); - Id window_2_2 = vm_client2()->NewWindow(2); - Id window_2_21 = vm_client2()->NewWindow(21); + Id window_2_11 = ws_client2()->NewWindow(11); + Id window_2_2 = ws_client2()->NewWindow(2); + Id window_2_21 = ws_client2()->NewWindow(21); ASSERT_TRUE(window_2_11); ASSERT_TRUE(window_2_2); ASSERT_TRUE(window_2_21); // Set up the hierarchy. - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_1)); - ASSERT_TRUE(AddWindow(vm2(), window_1_1, window_2_11)); - ASSERT_TRUE(AddWindow(vm2(), window_2_2, window_2_21)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_1)); + ASSERT_TRUE(AddWindow(ws2(), window_1_1, window_2_11)); + ASSERT_TRUE(AddWindow(ws2(), window_2_2, window_2_21)); // Remove 11, should result in a hierarchy change for the root. { changes1()->clear(); - ASSERT_TRUE(RemoveWindowFromParent(vm2(), window_2_11)); + ASSERT_TRUE(RemoveWindowFromParent(ws2(), window_2_11)); - vm_client1_->WaitForChangeCount(1); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_11) + " new_parent=null old_parent=" + IdToString(window_1_1), SingleChangeToDescription(*changes1())); @@ -912,8 +911,8 @@ // Add 2 to 1. { changes1()->clear(); - ASSERT_TRUE(AddWindow(vm2(), window_1_1, window_2_2)); - vm_client1_->WaitForChangeCount(1); + ASSERT_TRUE(AddWindow(ws2(), window_1_1, window_2_2)); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_2) + " new_parent=" + IdToString(window_1_1) + " old_parent=null", SingleChangeToDescription(*changes1())); @@ -926,14 +925,14 @@ TEST_F(WindowTreeAppTest, ReorderWindow) { ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); - Id window_2_1 = vm_client2()->NewWindow(1); - Id window_2_2 = vm_client2()->NewWindow(2); - Id window_2_3 = vm_client2()->NewWindow(3); - Id window_1_4 = vm_client1()->NewWindow(4); // Peer to 1,1 - Id window_1_5 = vm_client1()->NewWindow(5); // Peer to 1,1 - Id window_2_6 = vm_client2()->NewWindow(6); // Child of 1,2. - Id window_2_7 = vm_client2()->NewWindow(7); // Unparented. - Id window_2_8 = vm_client2()->NewWindow(8); // Unparented. + Id window_2_1 = ws_client2()->NewWindow(1); + Id window_2_2 = ws_client2()->NewWindow(2); + Id window_2_3 = ws_client2()->NewWindow(3); + Id window_1_4 = ws_client1()->NewWindow(4); // Peer to 1,1 + Id window_1_5 = ws_client1()->NewWindow(5); // Peer to 1,1 + Id window_2_6 = ws_client2()->NewWindow(6); // Child of 1,2. + Id window_2_7 = ws_client2()->NewWindow(7); // Unparented. + Id window_2_8 = ws_client2()->NewWindow(8); // Unparented. ASSERT_TRUE(window_2_1); ASSERT_TRUE(window_2_2); ASSERT_TRUE(window_2_3); @@ -943,19 +942,19 @@ ASSERT_TRUE(window_2_7); ASSERT_TRUE(window_2_8); - ASSERT_TRUE(AddWindow(vm2(), window_2_1, window_2_2)); - ASSERT_TRUE(AddWindow(vm2(), window_2_2, window_2_6)); - ASSERT_TRUE(AddWindow(vm2(), window_2_1, window_2_3)); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_4)); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_5)); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_2_1)); + ASSERT_TRUE(AddWindow(ws2(), window_2_1, window_2_2)); + ASSERT_TRUE(AddWindow(ws2(), window_2_2, window_2_6)); + ASSERT_TRUE(AddWindow(ws2(), window_2_1, window_2_3)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_4)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_5)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_2_1)); { changes1()->clear(); - ASSERT_TRUE(ReorderWindow(vm2(), window_2_2, window_2_3, + ASSERT_TRUE(ReorderWindow(ws2(), window_2_2, window_2_3, mojom::ORDER_DIRECTION_ABOVE)); - vm_client1_->WaitForChangeCount(1); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ("Reordered window=" + IdToString(window_2_2) + " relative=" + IdToString(window_2_3) + " direction=above", SingleChangeToDescription(*changes1())); @@ -963,34 +962,34 @@ { changes1()->clear(); - ASSERT_TRUE(ReorderWindow(vm2(), window_2_2, window_2_3, + ASSERT_TRUE(ReorderWindow(ws2(), window_2_2, window_2_3, mojom::ORDER_DIRECTION_BELOW)); - vm_client1_->WaitForChangeCount(1); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ("Reordered window=" + IdToString(window_2_2) + " relative=" + IdToString(window_2_3) + " direction=below", SingleChangeToDescription(*changes1())); } // view2 is already below view3. - EXPECT_FALSE(ReorderWindow(vm2(), window_2_2, window_2_3, + EXPECT_FALSE(ReorderWindow(ws2(), window_2_2, window_2_3, mojom::ORDER_DIRECTION_BELOW)); // view4 & 5 are unknown to connection2_. - EXPECT_FALSE(ReorderWindow(vm2(), window_1_4, window_1_5, + EXPECT_FALSE(ReorderWindow(ws2(), window_1_4, window_1_5, mojom::ORDER_DIRECTION_ABOVE)); // view6 & view3 have different parents. - EXPECT_FALSE(ReorderWindow(vm1(), window_2_3, window_2_6, + EXPECT_FALSE(ReorderWindow(ws1(), window_2_3, window_2_6, mojom::ORDER_DIRECTION_ABOVE)); // Non-existent window-ids - EXPECT_FALSE(ReorderWindow(vm1(), BuildWindowId(connection_id_1(), 27), + EXPECT_FALSE(ReorderWindow(ws1(), BuildWindowId(connection_id_1(), 27), BuildWindowId(connection_id_1(), 28), mojom::ORDER_DIRECTION_ABOVE)); // view7 & view8 are un-parented. - EXPECT_FALSE(ReorderWindow(vm1(), window_2_7, window_2_8, + EXPECT_FALSE(ReorderWindow(ws1(), window_2_7, window_2_8, mojom::ORDER_DIRECTION_ABOVE)); } @@ -998,14 +997,14 @@ TEST_F(WindowTreeAppTest, DeleteWindow) { ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_2 = vm_client2()->NewWindow(2); + Id window_2_2 = ws_client2()->NewWindow(2); ASSERT_TRUE(window_2_2); // Make 2 a child of 1. { changes1()->clear(); - ASSERT_TRUE(AddWindow(vm2(), window_1_1, window_2_2)); - vm_client1_->WaitForChangeCount(1); + ASSERT_TRUE(AddWindow(ws2(), window_1_1, window_2_2)); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_2) + " new_parent=" + IdToString(window_1_1) + " old_parent=null", SingleChangeToDescription(*changes1())); @@ -1015,10 +1014,10 @@ { changes1()->clear(); changes2()->clear(); - ASSERT_TRUE(DeleteWindow(vm2(), window_2_2)); + ASSERT_TRUE(DeleteWindow(ws2(), window_2_2)); EXPECT_TRUE(changes2()->empty()); - vm_client1_->WaitForChangeCount(1); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ("WindowDeleted window=" + IdToString(window_2_2), SingleChangeToDescription(*changes1())); } @@ -1027,7 +1026,7 @@ // Verifies DeleteWindow isn't allowed from a separate connection. TEST_F(WindowTreeAppTest, DeleteWindowFromAnotherConnectionDisallowed) { ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); - EXPECT_FALSE(DeleteWindow(vm2(), BuildWindowId(connection_id_1(), 1))); + EXPECT_FALSE(DeleteWindow(ws2(), BuildWindowId(connection_id_1(), 1))); } // Verifies if a window was deleted and then reused that other clients are @@ -1035,14 +1034,14 @@ TEST_F(WindowTreeAppTest, ReuseDeletedWindowId) { ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_2 = vm_client2()->NewWindow(2); + Id window_2_2 = ws_client2()->NewWindow(2); ASSERT_TRUE(window_2_2); // Add 2 to 1. { changes1()->clear(); - ASSERT_TRUE(AddWindow(vm2(), window_1_1, window_2_2)); - vm_client1_->WaitForChangeCount(1); + ASSERT_TRUE(AddWindow(ws2(), window_1_1, window_2_2)); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_2) + " new_parent=" + IdToString(window_1_1) + " old_parent=null", SingleChangeToDescription(*changes1())); @@ -1053,21 +1052,21 @@ // Delete 2. { changes1()->clear(); - ASSERT_TRUE(DeleteWindow(vm2(), window_2_2)); + ASSERT_TRUE(DeleteWindow(ws2(), window_2_2)); - vm_client1_->WaitForChangeCount(1); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ("WindowDeleted window=" + IdToString(window_2_2), SingleChangeToDescription(*changes1())); } // Create 2 again, and add it back to 1. Should get the same notification. - window_2_2 = vm_client2()->NewWindow(2); + window_2_2 = ws_client2()->NewWindow(2); ASSERT_TRUE(window_2_2); { changes1()->clear(); - ASSERT_TRUE(AddWindow(vm2(), window_1_1, window_2_2)); + ASSERT_TRUE(AddWindow(ws2(), window_1_1, window_2_2)); - vm_client1_->WaitForChangeCount(1); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_2) + " new_parent=" + IdToString(window_1_1) + " old_parent=null", SingleChangeToDescription(*changes1())); @@ -1082,23 +1081,23 @@ Id window_1_1 = BuildWindowId(connection_id_1(), 1); // Create 11 in first connection and make it a child of 1. - Id window_1_11 = vm_client1()->NewWindow(11); + Id window_1_11 = ws_client1()->NewWindow(11); ASSERT_TRUE(window_1_11); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_1)); - ASSERT_TRUE(AddWindow(vm1(), window_1_1, window_1_11)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_1)); + ASSERT_TRUE(AddWindow(ws1(), window_1_1, window_1_11)); // Create two windows in second connection, 2 and 3, both children of 1. - Id window_2_2 = vm_client2()->NewWindow(2); - Id window_2_3 = vm_client2()->NewWindow(3); + Id window_2_2 = ws_client2()->NewWindow(2); + Id window_2_3 = ws_client2()->NewWindow(3); ASSERT_TRUE(window_2_2); ASSERT_TRUE(window_2_3); - ASSERT_TRUE(AddWindow(vm2(), window_1_1, window_2_2)); - ASSERT_TRUE(AddWindow(vm2(), window_1_1, window_2_3)); + ASSERT_TRUE(AddWindow(ws2(), window_1_1, window_2_2)); + ASSERT_TRUE(AddWindow(ws2(), window_1_1, window_2_3)); // Verifies GetWindowTree() on the root. The root connection sees all. { std::vector<TestWindow> windows; - GetWindowTree(vm1(), root_window_id(), &windows); + GetWindowTree(ws1(), root_window_id(), &windows); ASSERT_EQ(5u, windows.size()); EXPECT_EQ(WindowParentToString(root_window_id(), kNullParentId), windows[0].ToString()); @@ -1112,12 +1111,12 @@ windows[4].ToString()); } - // Verifies GetWindowTree() on the window 1,1 from vm2(). vm2() sees 1,1 as + // Verifies GetWindowTree() on the window 1,1 from ws2(). ws2() sees 1,1 as // 1,1 - // is vm2()'s root and vm2() sees all the windows it created. + // is ws2()'s root and ws2() sees all the windows it created. { std::vector<TestWindow> windows; - GetWindowTree(vm2(), window_1_1, &windows); + GetWindowTree(ws2(), window_1_1, &windows); ASSERT_EQ(3u, windows.size()); EXPECT_EQ(WindowParentToString(window_1_1, kNullParentId), windows[0].ToString()); @@ -1130,36 +1129,36 @@ // Connection 2 shouldn't be able to get the root tree. { std::vector<TestWindow> windows; - GetWindowTree(vm2(), root_window_id(), &windows); + GetWindowTree(ws2(), root_window_id(), &windows); ASSERT_EQ(0u, windows.size()); } } TEST_F(WindowTreeAppTest, SetWindowBounds) { - Id window_1_1 = vm_client1()->NewWindow(1); + Id window_1_1 = ws_client1()->NewWindow(1); ASSERT_TRUE(window_1_1); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_1)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_1)); ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); changes2()->clear(); - ASSERT_TRUE(SetWindowBounds(vm1(), window_1_1, 0, 0, 100, 100)); + ASSERT_TRUE(SetWindowBounds(ws1(), window_1_1, 0, 0, 100, 100)); - vm_client2_->WaitForChangeCount(1); + ws_client2_->WaitForChangeCount(1); EXPECT_EQ("BoundsChanged window=" + IdToString(window_1_1) + " old_bounds=0,0 0x0 new_bounds=0,0 100x100", SingleChangeToDescription(*changes2())); // Should not be possible to change the bounds of a window created by another // connection. - ASSERT_FALSE(SetWindowBounds(vm2(), window_1_1, 0, 0, 0, 0)); + ASSERT_FALSE(SetWindowBounds(ws2(), window_1_1, 0, 0, 0, 0)); } // Verify AddWindow fails when trying to manipulate windows in other roots. TEST_F(WindowTreeAppTest, CantMoveWindowsFromOtherRoot) { // Create 1 and 2 in the first connection. - Id window_1_1 = vm_client1()->NewWindow(1); - Id window_1_2 = vm_client1()->NewWindow(2); + Id window_1_1 = ws_client1()->NewWindow(1); + Id window_1_2 = ws_client1()->NewWindow(2); ASSERT_TRUE(window_1_1); ASSERT_TRUE(window_1_2); @@ -1167,47 +1166,47 @@ // Try to move 2 to be a child of 1 from connection 2. This should fail as 2 // should not be able to access 1. - ASSERT_FALSE(AddWindow(vm2(), window_1_1, window_1_2)); + ASSERT_FALSE(AddWindow(ws2(), window_1_1, window_1_2)); // Try to reparent 1 to the root. A connection is not allowed to reparent its // roots. - ASSERT_FALSE(AddWindow(vm2(), root_window_id(), window_1_1)); + ASSERT_FALSE(AddWindow(ws2(), root_window_id(), window_1_1)); } // Verify RemoveWindowFromParent fails for windows that are descendants of the // roots. TEST_F(WindowTreeAppTest, CantRemoveWindowsInOtherRoots) { // Create 1 and 2 in the first connection and parent both to the root. - Id window_1_1 = vm_client1()->NewWindow(1); - Id window_1_2 = vm_client1()->NewWindow(2); + Id window_1_1 = ws_client1()->NewWindow(1); + Id window_1_2 = ws_client1()->NewWindow(2); ASSERT_TRUE(window_1_1); ASSERT_TRUE(window_1_2); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_1)); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_2)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_1)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_2)); // Establish the second connection and give it the root 1. ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); // Connection 2 should not be able to remove window 2 or 1 from its parent. - ASSERT_FALSE(RemoveWindowFromParent(vm2(), window_1_2)); - ASSERT_FALSE(RemoveWindowFromParent(vm2(), window_1_1)); + ASSERT_FALSE(RemoveWindowFromParent(ws2(), window_1_2)); + ASSERT_FALSE(RemoveWindowFromParent(ws2(), window_1_1)); // Create windows 10 and 11 in 2. - Id window_2_10 = vm_client2()->NewWindow(10); - Id window_2_11 = vm_client2()->NewWindow(11); + Id window_2_10 = ws_client2()->NewWindow(10); + Id window_2_11 = ws_client2()->NewWindow(11); ASSERT_TRUE(window_2_10); ASSERT_TRUE(window_2_11); // Parent 11 to 10. - ASSERT_TRUE(AddWindow(vm2(), window_2_10, window_2_11)); + ASSERT_TRUE(AddWindow(ws2(), window_2_10, window_2_11)); // Remove 11 from 10. - ASSERT_TRUE(RemoveWindowFromParent(vm2(), window_2_11)); + ASSERT_TRUE(RemoveWindowFromParent(ws2(), window_2_11)); // Verify nothing was actually removed. { std::vector<TestWindow> windows; - GetWindowTree(vm1(), root_window_id(), &windows); + GetWindowTree(ws1(), root_window_id(), &windows); ASSERT_EQ(3u, windows.size()); EXPECT_EQ(WindowParentToString(root_window_id(), kNullParentId), windows[0].ToString()); @@ -1221,28 +1220,28 @@ // Verify GetWindowTree fails for windows that are not descendants of the roots. TEST_F(WindowTreeAppTest, CantGetWindowTreeOfOtherRoots) { // Create 1 and 2 in the first connection and parent both to the root. - Id window_1_1 = vm_client1()->NewWindow(1); - Id window_1_2 = vm_client1()->NewWindow(2); + Id window_1_1 = ws_client1()->NewWindow(1); + Id window_1_2 = ws_client1()->NewWindow(2); ASSERT_TRUE(window_1_1); ASSERT_TRUE(window_1_2); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_1)); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_2)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_1)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_2)); ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); std::vector<TestWindow> windows; // Should get nothing for the root. - GetWindowTree(vm2(), root_window_id(), &windows); + GetWindowTree(ws2(), root_window_id(), &windows); ASSERT_TRUE(windows.empty()); // Should get nothing for window 2. - GetWindowTree(vm2(), window_1_2, &windows); + GetWindowTree(ws2(), window_1_2, &windows); ASSERT_TRUE(windows.empty()); // Should get window 1 if asked for. - GetWindowTree(vm2(), window_1_1, &windows); + GetWindowTree(ws2(), window_1_1, &windows); ASSERT_EQ(1u, windows.size()); EXPECT_EQ(WindowParentToString(window_1_1, kNullParentId), windows[0].ToString()); @@ -1253,11 +1252,11 @@ changes2()->clear(); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm1(), window_1_1)); + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws1(), window_1_1)); // Connection2 should have been told of the unembed and delete. { - vm_client2_->WaitForChangeCount(2); + ws_client2_->WaitForChangeCount(2); EXPECT_EQ("OnUnembed", ChangesToDescription1(*changes2())[0]); EXPECT_EQ("WindowDeleted window=" + IdToString(window_1_1), ChangesToDescription1(*changes2())[1]); @@ -1266,7 +1265,7 @@ // Connection2 has no root. Verify it can't see window 1,1 anymore. { std::vector<TestWindow> windows; - GetWindowTree(vm2(), window_1_1, &windows); + GetWindowTree(ws2(), window_1_1, &windows); EXPECT_TRUE(windows.empty()); } } @@ -1276,20 +1275,20 @@ Id window_1_1 = BuildWindowId(connection_id_1(), 1); changes2()->clear(); - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm1(), window_1_1)); + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws1(), window_1_1)); // Connection2 should have been told about the unembed and delete. - vm_client2_->WaitForChangeCount(2); + ws_client2_->WaitForChangeCount(2); changes2()->clear(); // Create a window in the third connection and parent it to the root. - Id window_3_1 = vm_client3()->NewWindow(1); + Id window_3_1 = ws_client3()->NewWindow(1); ASSERT_TRUE(window_3_1); - ASSERT_TRUE(AddWindow(vm3(), window_1_1, window_3_1)); + ASSERT_TRUE(AddWindow(ws3(), window_1_1, window_3_1)); // Connection 1 should have been told about the add (it owns the window). { - vm_client1_->WaitForChangeCount(1); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ("HierarchyChanged window=" + IdToString(window_3_1) + " new_parent=" + IdToString(window_1_1) + " old_parent=null", SingleChangeToDescription(*changes1())); @@ -1301,39 +1300,39 @@ // We should get a new connection for the new embedding. scoped_ptr<TestWindowTreeClientImpl> connection4( - EstablishConnectionViaEmbed(vm1(), window_1_1, nullptr)); + EstablishConnectionViaEmbed(ws1(), window_1_1, nullptr)); ASSERT_TRUE(connection4.get()); EXPECT_EQ("[" + WindowParentToString(window_1_1, kNullParentId) + "]", ChangeWindowDescription(*connection4->tracker()->changes())); // And 3 should get an unembed and delete. - vm_client3_->WaitForChangeCount(2); + ws_client3_->WaitForChangeCount(2); EXPECT_EQ("OnUnembed", ChangesToDescription1(*changes3())[0]); EXPECT_EQ("WindowDeleted window=" + IdToString(window_1_1), ChangesToDescription1(*changes3())[1]); } - // vm3() has no root. Verify it can't see window 1,1 anymore. + // ws3() has no root. Verify it can't see window 1,1 anymore. { std::vector<TestWindow> windows; - GetWindowTree(vm3(), window_1_1, &windows); + GetWindowTree(ws3(), window_1_1, &windows); EXPECT_TRUE(windows.empty()); } // Verify 3,1 is no longer parented to 1,1. We have to do this from 1,1 as - // vm3() can no longer see 1,1. + // ws3() can no longer see 1,1. { std::vector<TestWindow> windows; - GetWindowTree(vm1(), window_1_1, &windows); + GetWindowTree(ws1(), window_1_1, &windows); ASSERT_EQ(1u, windows.size()); EXPECT_EQ(WindowParentToString(window_1_1, kNullParentId), windows[0].ToString()); } - // Verify vm3() can still see the window it created 3,1. + // Verify ws3() can still see the window it created 3,1. { std::vector<TestWindow> windows; - GetWindowTree(vm3(), window_3_1, &windows); + GetWindowTree(ws3(), window_3_1, &windows); ASSERT_EQ(1u, windows.size()); EXPECT_EQ(WindowParentToString(window_3_1, kNullParentId), windows[0].ToString()); @@ -1343,15 +1342,15 @@ // Assertions for SetWindowVisibility. TEST_F(WindowTreeAppTest, SetWindowVisibility) { // Create 1 and 2 in the first connection and parent both to the root. - Id window_1_1 = vm_client1()->NewWindow(1); - Id window_1_2 = vm_client1()->NewWindow(2); + Id window_1_1 = ws_client1()->NewWindow(1); + Id window_1_2 = ws_client1()->NewWindow(2); ASSERT_TRUE(window_1_1); ASSERT_TRUE(window_1_2); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_1)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_1)); { std::vector<TestWindow> windows; - GetWindowTree(vm1(), root_window_id(), &windows); + GetWindowTree(ws1(), root_window_id(), &windows); ASSERT_EQ(2u, windows.size()); EXPECT_EQ(WindowParentToString(root_window_id(), kNullParentId) + " visible=true drawn=true", @@ -1362,11 +1361,11 @@ } // Show all the windows. - ASSERT_TRUE(SetWindowVisibility(vm1(), window_1_1, true)); - ASSERT_TRUE(SetWindowVisibility(vm1(), window_1_2, true)); + ASSERT_TRUE(SetWindowVisibility(ws1(), window_1_1, true)); + ASSERT_TRUE(SetWindowVisibility(ws1(), window_1_2, true)); { std::vector<TestWindow> windows; - GetWindowTree(vm1(), root_window_id(), &windows); + GetWindowTree(ws1(), root_window_id(), &windows); ASSERT_EQ(2u, windows.size()); EXPECT_EQ(WindowParentToString(root_window_id(), kNullParentId) + " visible=true drawn=true", @@ -1377,10 +1376,10 @@ } // Hide 1. - ASSERT_TRUE(SetWindowVisibility(vm1(), window_1_1, false)); + ASSERT_TRUE(SetWindowVisibility(ws1(), window_1_1, false)); { std::vector<TestWindow> windows; - GetWindowTree(vm1(), window_1_1, &windows); + GetWindowTree(ws1(), window_1_1, &windows); ASSERT_EQ(1u, windows.size()); EXPECT_EQ(WindowParentToString(window_1_1, root_window_id()) + " visible=false drawn=false", @@ -1388,10 +1387,10 @@ } // Attach 2 to 1. - ASSERT_TRUE(AddWindow(vm1(), window_1_1, window_1_2)); + ASSERT_TRUE(AddWindow(ws1(), window_1_1, window_1_2)); { std::vector<TestWindow> windows; - GetWindowTree(vm1(), window_1_1, &windows); + GetWindowTree(ws1(), window_1_1, &windows); ASSERT_EQ(2u, windows.size()); EXPECT_EQ(WindowParentToString(window_1_1, root_window_id()) + " visible=false drawn=false", @@ -1402,10 +1401,10 @@ } // Show 1. - ASSERT_TRUE(SetWindowVisibility(vm1(), window_1_1, true)); + ASSERT_TRUE(SetWindowVisibility(ws1(), window_1_1, true)); { std::vector<TestWindow> windows; - GetWindowTree(vm1(), window_1_1, &windows); + GetWindowTree(ws1(), window_1_1, &windows); ASSERT_EQ(2u, windows.size()); EXPECT_EQ(WindowParentToString(window_1_1, root_window_id()) + " visible=true drawn=true", @@ -1419,30 +1418,30 @@ // Assertions for SetWindowVisibility sending notifications. TEST_F(WindowTreeAppTest, SetWindowVisibilityNotifications) { // Create 1,1 and 1,2. 1,2 is made a child of 1,1 and 1,1 a child of the root. - Id window_1_1 = vm_client1()->NewWindow(1); + Id window_1_1 = ws_client1()->NewWindow(1); ASSERT_TRUE(window_1_1); - ASSERT_TRUE(SetWindowVisibility(vm1(), window_1_1, true)); - Id window_1_2 = vm_client1()->NewWindow(2); + ASSERT_TRUE(SetWindowVisibility(ws1(), window_1_1, true)); + Id window_1_2 = ws_client1()->NewWindow(2); ASSERT_TRUE(window_1_2); - ASSERT_TRUE(SetWindowVisibility(vm1(), window_1_2, true)); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_1)); - ASSERT_TRUE(AddWindow(vm1(), window_1_1, window_1_2)); + ASSERT_TRUE(SetWindowVisibility(ws1(), window_1_2, true)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_1)); + ASSERT_TRUE(AddWindow(ws1(), window_1_1, window_1_2)); // Establish the second connection at 1,2. ASSERT_NO_FATAL_FAILURE(EstablishSecondConnectionWithRoot(window_1_2)); // Add 2,3 as a child of 1,2. - Id window_2_3 = vm_client2()->NewWindow(3); + Id window_2_3 = ws_client2()->NewWindow(3); ASSERT_TRUE(window_2_3); - ASSERT_TRUE(SetWindowVisibility(vm2(), window_2_3, true)); - ASSERT_TRUE(AddWindow(vm2(), window_1_2, window_2_3)); - WaitForAllMessages(vm1()); + ASSERT_TRUE(SetWindowVisibility(ws2(), window_2_3, true)); + ASSERT_TRUE(AddWindow(ws2(), window_1_2, window_2_3)); + WaitForAllMessages(ws1()); changes2()->clear(); // Hide 1,2 from connection 1. Connection 2 should see this. - ASSERT_TRUE(SetWindowVisibility(vm1(), window_1_2, false)); + ASSERT_TRUE(SetWindowVisibility(ws1(), window_1_2, false)); { - vm_client2_->WaitForChangeCount(1); + ws_client2_->WaitForChangeCount(1); EXPECT_EQ( "VisibilityChanged window=" + IdToString(window_1_2) + " visible=false", SingleChangeToDescription(*changes2())); @@ -1450,9 +1449,9 @@ changes1()->clear(); // Show 1,2 from connection 2, connection 1 should be notified. - ASSERT_TRUE(SetWindowVisibility(vm2(), window_1_2, true)); + ASSERT_TRUE(SetWindowVisibility(ws2(), window_1_2, true)); { - vm_client1_->WaitForChangeCount(1); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ( "VisibilityChanged window=" + IdToString(window_1_2) + " visible=true", SingleChangeToDescription(*changes1())); @@ -1460,9 +1459,9 @@ changes2()->clear(); // Hide 1,1, connection 2 should be told the draw state changed. - ASSERT_TRUE(SetWindowVisibility(vm1(), window_1_1, false)); + ASSERT_TRUE(SetWindowVisibility(ws1(), window_1_1, false)); { - vm_client2_->WaitForChangeCount(1); + ws_client2_->WaitForChangeCount(1); EXPECT_EQ( "DrawnStateChanged window=" + IdToString(window_1_2) + " drawn=false", SingleChangeToDescription(*changes2())); @@ -1470,9 +1469,9 @@ changes2()->clear(); // Show 1,1 from connection 1. Connection 2 should see this. - ASSERT_TRUE(SetWindowVisibility(vm1(), window_1_1, true)); + ASSERT_TRUE(SetWindowVisibility(ws1(), window_1_1, true)); { - vm_client2_->WaitForChangeCount(1); + ws_client2_->WaitForChangeCount(1); EXPECT_EQ( "DrawnStateChanged window=" + IdToString(window_1_2) + " drawn=true", SingleChangeToDescription(*changes2())); @@ -1480,9 +1479,9 @@ // Change visibility of 2,3, connection 1 should see this. changes1()->clear(); - ASSERT_TRUE(SetWindowVisibility(vm2(), window_2_3, false)); + ASSERT_TRUE(SetWindowVisibility(ws2(), window_2_3, false)); { - vm_client1_->WaitForChangeCount(1); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ( "VisibilityChanged window=" + IdToString(window_2_3) + " visible=false", SingleChangeToDescription(*changes1())); @@ -1490,9 +1489,9 @@ changes2()->clear(); // Remove 1,1 from the root, connection 2 should see drawn state changed. - ASSERT_TRUE(RemoveWindowFromParent(vm1(), window_1_1)); + ASSERT_TRUE(RemoveWindowFromParent(ws1(), window_1_1)); { - vm_client2_->WaitForChangeCount(1); + ws_client2_->WaitForChangeCount(1); EXPECT_EQ( "DrawnStateChanged window=" + IdToString(window_1_2) + " drawn=false", SingleChangeToDescription(*changes2())); @@ -1500,9 +1499,9 @@ changes2()->clear(); // Add 1,1 back to the root, connection 2 should see drawn state changed. - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_1)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_1)); { - vm_client2_->WaitForChangeCount(1); + ws_client2_->WaitForChangeCount(1); EXPECT_EQ( "DrawnStateChanged window=" + IdToString(window_1_2) + " drawn=true", SingleChangeToDescription(*changes2())); @@ -1510,16 +1509,16 @@ } TEST_F(WindowTreeAppTest, SetWindowProperty) { - Id window_1_1 = vm_client1()->NewWindow(1); + Id window_1_1 = ws_client1()->NewWindow(1); ASSERT_TRUE(window_1_1); ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); changes2()->clear(); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_1)); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_1)); { std::vector<TestWindow> windows; - GetWindowTree(vm1(), root_window_id(), &windows); + GetWindowTree(ws1(), root_window_id(), &windows); ASSERT_EQ(2u, windows.size()); EXPECT_EQ(root_window_id(), windows[0].window_id); EXPECT_EQ(window_1_1, windows[1].window_id); @@ -1529,9 +1528,9 @@ // Set properties on 1. changes2()->clear(); std::vector<uint8_t> one(1, '1'); - ASSERT_TRUE(SetWindowProperty(vm1(), window_1_1, "one", &one)); + ASSERT_TRUE(SetWindowProperty(ws1(), window_1_1, "one", &one)); { - vm_client2_->WaitForChangeCount(1); + ws_client2_->WaitForChangeCount(1); EXPECT_EQ( "PropertyChanged window=" + IdToString(window_1_1) + " key=one value=1", SingleChangeToDescription(*changes2())); @@ -1540,7 +1539,7 @@ // Test that our properties exist in the window tree { std::vector<TestWindow> windows; - GetWindowTree(vm1(), window_1_1, &windows); + GetWindowTree(ws1(), window_1_1, &windows); ASSERT_EQ(1u, windows.size()); ASSERT_EQ(1u, windows[0].properties.size()); EXPECT_EQ(one, windows[0].properties["one"]); @@ -1548,9 +1547,9 @@ changes2()->clear(); // Set back to null. - ASSERT_TRUE(SetWindowProperty(vm1(), window_1_1, "one", NULL)); + ASSERT_TRUE(SetWindowProperty(ws1(), window_1_1, "one", NULL)); { - vm_client2_->WaitForChangeCount(1); + ws_client2_->WaitForChangeCount(1); EXPECT_EQ("PropertyChanged window=" + IdToString(window_1_1) + " key=one value=NULL", SingleChangeToDescription(*changes2())); @@ -1561,24 +1560,24 @@ // Create connection 2 and 3. ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_2 = vm_client2()->NewWindow(2); + Id window_2_2 = ws_client2()->NewWindow(2); ASSERT_TRUE(window_2_2); - ASSERT_TRUE(AddWindow(vm2(), window_1_1, window_2_2)); + ASSERT_TRUE(AddWindow(ws2(), window_1_1, window_2_2)); changes2()->clear(); - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm2(), window_2_2)); + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_2)); // Connection 1 should get a hierarchy change for window_2_2. - vm_client1_->WaitForChangeCount(1); + ws_client1_->WaitForChangeCount(1); changes1()->clear(); // Close connection 3. Connection 2 (which had previously embedded 3) should // be notified of this. - vm_client3_.reset(); - vm_client2_->WaitForChangeCount(1); + ws_client3_.reset(); + ws_client2_->WaitForChangeCount(1); EXPECT_EQ("OnEmbeddedAppDisconnected window=" + IdToString(window_2_2), SingleChangeToDescription(*changes2())); - vm_client1_->WaitForChangeCount(1); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ("OnEmbeddedAppDisconnected window=" + IdToString(window_2_2), SingleChangeToDescription(*changes1())); } @@ -1589,20 +1588,20 @@ // Create connection 2 and 3. ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - ASSERT_TRUE(AddWindow(vm1(), root_window_id(), window_1_1)); - Id window_2_2 = vm_client2()->NewWindow(2); - Id window_2_3 = vm_client2()->NewWindow(3); + ASSERT_TRUE(AddWindow(ws1(), root_window_id(), window_1_1)); + Id window_2_2 = ws_client2()->NewWindow(2); + Id window_2_3 = ws_client2()->NewWindow(3); ASSERT_TRUE(window_2_2); ASSERT_TRUE(window_2_3); - ASSERT_TRUE(AddWindow(vm2(), window_1_1, window_2_2)); - ASSERT_TRUE(AddWindow(vm2(), window_2_2, window_2_3)); + ASSERT_TRUE(AddWindow(ws2(), window_1_1, window_2_2)); + ASSERT_TRUE(AddWindow(ws2(), window_2_2, window_2_3)); changes2()->clear(); - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm2(), window_2_3)); + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_3)); changes3()->clear(); // Close connection 2. Connection 3 should get a delete (for its root). - vm_client2_.reset(); - vm_client3_->WaitForChangeCount(1); + ws_client2_.reset(); + ws_client3_->WaitForChangeCount(1); EXPECT_EQ("WindowDeleted window=" + IdToString(window_2_3), SingleChangeToDescription(*changes3())); } @@ -1612,26 +1611,26 @@ TEST_F(WindowTreeAppTest, DontCleanMapOnDestroy) { ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - ASSERT_TRUE(vm_client2()->NewWindow(1)); + ASSERT_TRUE(ws_client2()->NewWindow(1)); changes1()->clear(); - vm_client2_.reset(); - vm_client1_->WaitForChangeCount(1); + ws_client2_.reset(); + ws_client1_->WaitForChangeCount(1); EXPECT_EQ("OnEmbeddedAppDisconnected window=" + IdToString(window_1_1), SingleChangeToDescription(*changes1())); std::vector<TestWindow> windows; - GetWindowTree(vm1(), window_1_1, &windows); + GetWindowTree(ws1(), window_1_1, &windows); EXPECT_FALSE(windows.empty()); } // Verifies Embed() works when supplying a WindowTreeClient. TEST_F(WindowTreeAppTest, EmbedSupplyingWindowTreeClient) { - ASSERT_TRUE(vm_client1()->NewWindow(1)); + ASSERT_TRUE(ws_client1()->NewWindow(1)); TestWindowTreeClientImpl client2(application_impl()); mojom::WindowTreeClientPtr client2_ptr; mojo::Binding<WindowTreeClient> client2_binding(&client2, &client2_ptr); ASSERT_TRUE( - Embed(vm1(), BuildWindowId(connection_id_1(), 1), client2_ptr.Pass())); + Embed(ws1(), BuildWindowId(connection_id_1(), 1), client2_ptr.Pass())); client2.WaitForOnEmbed(); EXPECT_EQ("OnEmbed", SingleChangeToDescription(*client2.tracker()->changes())); @@ -1641,19 +1640,19 @@ ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_2 = vm_client2()->NewWindow(2); + Id window_2_2 = ws_client2()->NewWindow(2); ASSERT_TRUE(window_2_2); - ASSERT_TRUE(AddWindow(vm2(), window_1_1, window_2_2)); - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm2(), window_2_2)); + ASSERT_TRUE(AddWindow(ws2(), window_1_1, window_2_2)); + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_2)); - Id window_3_3 = vm_client3()->NewWindow(3); + Id window_3_3 = ws_client3()->NewWindow(3); ASSERT_TRUE(window_3_3); - ASSERT_TRUE(AddWindow(vm3(), window_2_2, window_3_3)); + ASSERT_TRUE(AddWindow(ws3(), window_2_2, window_3_3)); // 2 should not be able to embed in window_3_3 as window_3_3 was not created // by // 2. - EXPECT_FALSE(EmbedUrl(application_impl(), vm2(), application_impl()->url(), + EXPECT_FALSE(EmbedUrl(application_impl(), ws2(), application_impl()->url(), window_3_3)); } @@ -1662,22 +1661,22 @@ ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_2 = vm_client2()->NewWindow(2); + Id window_2_2 = ws_client2()->NewWindow(2); ASSERT_TRUE(window_2_2); - ASSERT_TRUE(AddWindow(vm2(), window_1_1, window_2_2)); + ASSERT_TRUE(AddWindow(ws2(), window_1_1, window_2_2)); changes2()->clear(); // Establish a third connection in window_2_2. - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm1(), window_2_2)); + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws1(), window_2_2)); - WaitForAllMessages(vm2()); + WaitForAllMessages(ws2()); EXPECT_EQ(std::string(), SingleChangeToDescription(*changes2())); } TEST_F(WindowTreeAppTest, CantEmbedFromConnectionRoot) { // Shouldn't be able to embed into the root. - ASSERT_FALSE(EmbedUrl(application_impl(), vm1(), application_impl()->url(), + ASSERT_FALSE(EmbedUrl(application_impl(), ws1(), application_impl()->url(), root_window_id())); // Even though the call above failed a WindowTreeClient was obtained. We need @@ -1687,25 +1686,25 @@ // Don't allow a connection to embed into its own root. ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); - EXPECT_FALSE(EmbedUrl(application_impl(), vm2(), application_impl()->url(), + EXPECT_FALSE(EmbedUrl(application_impl(), ws2(), application_impl()->url(), BuildWindowId(connection_id_1(), 1))); // Need to wait for a WindowTreeClient for same reason as above. WaitForWindowTreeClient(); - Id window_1_2 = vm_client1()->NewWindow(2); + Id window_1_2 = ws_client1()->NewWindow(2); ASSERT_TRUE(window_1_2); ASSERT_TRUE( - AddWindow(vm1(), BuildWindowId(connection_id_1(), 1), window_1_2)); - ASSERT_TRUE(vm_client3_.get() == nullptr); - vm_client3_ = EstablishConnectionViaEmbedWithPolicyBitmask( - vm1(), window_1_2, mojom::WindowTree::ACCESS_POLICY_EMBED_ROOT, nullptr); - ASSERT_TRUE(vm_client3_.get() != nullptr); - vm_client3_->set_root_window(root_window_id()); + AddWindow(ws1(), BuildWindowId(connection_id_1(), 1), window_1_2)); + ASSERT_TRUE(ws_client3_.get() == nullptr); + ws_client3_ = EstablishConnectionViaEmbedWithPolicyBitmask( + ws1(), window_1_2, mojom::WindowTree::ACCESS_POLICY_EMBED_ROOT, nullptr); + ASSERT_TRUE(ws_client3_.get() != nullptr); + ws_client3_->set_root_window(root_window_id()); - // window_1_2 is vm3's root, so even though v3 is an embed root it should not + // window_1_2 is ws3's root, so even though v3 is an embed root it should not // be able to Embed into itself. - ASSERT_FALSE(EmbedUrl(application_impl(), vm3(), application_impl()->url(), + ASSERT_FALSE(EmbedUrl(application_impl(), ws3(), application_impl()->url(), window_1_2)); } @@ -1720,5 +1719,4 @@ // tests. } // namespace ws - } // namespace mus
diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc index 3100bddf..6aa0418 100644 --- a/components/password_manager/core/browser/password_autofill_manager.cc +++ b/components/password_manager/core/browser/password_autofill_manager.cc
@@ -258,8 +258,8 @@ bool PasswordAutofillManager::RemoveSuggestion(const base::string16& value, int identifier) { - // http://crbug.com/329038 - NOTIMPLEMENTED(); + // Password suggestions cannot be deleted this way. + // See http://crbug.com/329038#c15 return false; }
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc index 0a6544ed..55a6d91 100644 --- a/content/browser/service_worker/service_worker_version_unittest.cc +++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -23,8 +23,8 @@ #define IPC_MESSAGE_START TestMsgStart -IPC_MESSAGE_CONTROL0(TestMsg_Message); -IPC_MESSAGE_ROUTED1(TestMsg_MessageFromWorker, int); +IPC_MESSAGE_CONTROL0(TestMsg_Message) +IPC_MESSAGE_ROUTED1(TestMsg_MessageFromWorker, int) // ---------------------------------------------------------------------------
diff --git a/content/common/android/sync_compositor_messages.h b/content/common/android/sync_compositor_messages.h index d48091a..4ea5b15 100644 --- a/content/common/android/sync_compositor_messages.h +++ b/content/common/android/sync_compositor_messages.h
@@ -105,23 +105,23 @@ content::SyncCompositorCommonBrowserParams, IPC::WebInputEventPointer, content::SyncCompositorCommonRendererParams, - content::InputEventAckState); + content::InputEventAckState) IPC_SYNC_MESSAGE_ROUTED2_1(SyncCompositorMsg_BeginFrame, content::SyncCompositorCommonBrowserParams, cc::BeginFrameArgs, - content::SyncCompositorCommonRendererParams); + content::SyncCompositorCommonRendererParams) IPC_SYNC_MESSAGE_ROUTED2_1(SyncCompositorMsg_ComputeScroll, content::SyncCompositorCommonBrowserParams, base::TimeTicks, - content::SyncCompositorCommonRendererParams); + content::SyncCompositorCommonRendererParams) IPC_SYNC_MESSAGE_ROUTED2_2(SyncCompositorMsg_DemandDrawHw, content::SyncCompositorCommonBrowserParams, content::SyncCompositorDemandDrawHwParams, content::SyncCompositorCommonRendererParams, - cc::CompositorFrame); + cc::CompositorFrame) IPC_MESSAGE_ROUTED1(SyncCompositorHostMsg_UpdateState, - content::SyncCompositorCommonRendererParams); + content::SyncCompositorCommonRendererParams)
diff --git a/content/common/media/media_player_messages_android.h b/content/common/media/media_player_messages_android.h index 29c52699..909c273 100644 --- a/content/common/media/media_player_messages_android.h +++ b/content/common/media/media_player_messages_android.h
@@ -209,7 +209,7 @@ // Initialize a media player object. IPC_MESSAGE_ROUTED1( MediaPlayerHostMsg_Initialize, - MediaPlayerHostMsg_Initialize_Params); + MediaPlayerHostMsg_Initialize_Params) // Pause the player. IPC_MESSAGE_ROUTED2(MediaPlayerHostMsg_Pause, @@ -251,7 +251,7 @@ // Requests the player with |player_id| to use the CDM with |cdm_id|. IPC_MESSAGE_ROUTED2(MediaPlayerHostMsg_SetCdm, int /* player_id */, - int /* cdm_id */); + int /* cdm_id */) // Sent after the renderer demuxer has seeked. IPC_MESSAGE_CONTROL2(MediaPlayerHostMsg_DemuxerSeekDone,
diff --git a/content/common/view_messages.h b/content/common/view_messages.h index f4fb6a4..c1a3d36 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h
@@ -891,7 +891,7 @@ IPC_MESSAGE_CONTROL3(ViewMsg_SystemColorsChanged, int /* AppleAquaColorVariant */, std::string /* AppleHighlightedTextColor */, - std::string /* AppleHighlightColor */); + std::string /* AppleHighlightColor */) #endif #if defined(OS_ANDROID) @@ -1399,7 +1399,7 @@ IPC_MESSAGE_ROUTED0(ViewHostMsg_StartPluginIme) // Receives content of a web page as plain text. -IPC_MESSAGE_ROUTED1(ViewMsg_GetRenderedTextCompleted, std::string); +IPC_MESSAGE_ROUTED1(ViewMsg_GetRenderedTextCompleted, std::string) #endif // Adding a new message? Stick to the sort order above: first platform
diff --git a/third_party/WebKit/Source/core/animation/SVGAngleInterpolationType.cpp b/third_party/WebKit/Source/core/animation/SVGAngleInterpolationType.cpp index aa3145a9..4fced35 100644 --- a/third_party/WebKit/Source/core/animation/SVGAngleInterpolationType.cpp +++ b/third_party/WebKit/Source/core/animation/SVGAngleInterpolationType.cpp
@@ -23,11 +23,6 @@ return InterpolationValue::create(*this, InterpolableNumber::create(toSVGAngle(svgValue).value())); } -PassOwnPtr<InterpolationValue> SVGAngleInterpolationType::maybeConvertUnderlyingValue(const InterpolationEnvironment& environment) const -{ - return maybeConvertSVGValue(environment.svgBaseValue()); -} - RefPtrWillBeRawPtr<SVGPropertyBase> SVGAngleInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*) const { double doubleValue = toInterpolableNumber(interpolableValue).value();
diff --git a/third_party/WebKit/Source/core/animation/SVGAngleInterpolationType.h b/third_party/WebKit/Source/core/animation/SVGAngleInterpolationType.h index 176bf33..15e766ed 100644 --- a/third_party/WebKit/Source/core/animation/SVGAngleInterpolationType.h +++ b/third_party/WebKit/Source/core/animation/SVGAngleInterpolationType.h
@@ -18,7 +18,6 @@ private: PassOwnPtr<InterpolationValue> maybeConvertNeutral() const final; PassOwnPtr<InterpolationValue> maybeConvertSVGValue(const SVGPropertyBase& svgValue) const final; - PassOwnPtr<InterpolationValue> maybeConvertUnderlyingValue(const InterpolationEnvironment&) const final; RefPtrWillBeRawPtr<SVGPropertyBase> appliedSVGValue(const InterpolableValue&, const NonInterpolableValue*) const final; };
diff --git a/third_party/WebKit/Source/core/animation/SVGInterpolationType.cpp b/third_party/WebKit/Source/core/animation/SVGInterpolationType.cpp index 82435d9..0b18d60 100644 --- a/third_party/WebKit/Source/core/animation/SVGInterpolationType.cpp +++ b/third_party/WebKit/Source/core/animation/SVGInterpolationType.cpp
@@ -20,6 +20,11 @@ return maybeConvertSVGValue(*svgValue); } +PassOwnPtr<InterpolationValue> SVGInterpolationType::maybeConvertUnderlyingValue(const InterpolationEnvironment& environment) const +{ + return maybeConvertSVGValue(environment.svgBaseValue()); +} + void SVGInterpolationType::apply(const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue, InterpolationEnvironment& environment) const { SVGElement& targetElement = environment.svgElement();
diff --git a/third_party/WebKit/Source/core/animation/SVGInterpolationType.h b/third_party/WebKit/Source/core/animation/SVGInterpolationType.h index e8b3b3b..5e4ef44 100644 --- a/third_party/WebKit/Source/core/animation/SVGInterpolationType.h +++ b/third_party/WebKit/Source/core/animation/SVGInterpolationType.h
@@ -24,6 +24,7 @@ virtual RefPtrWillBeRawPtr<SVGPropertyBase> appliedSVGValue(const InterpolableValue&, const NonInterpolableValue*) const = 0; PassOwnPtr<InterpolationValue> maybeConvertSingle(const PropertySpecificKeyframe&, const InterpolationEnvironment&, const UnderlyingValue&, ConversionCheckers&) const override; + PassOwnPtr<InterpolationValue> maybeConvertUnderlyingValue(const InterpolationEnvironment&) const override; void apply(const InterpolableValue&, const NonInterpolableValue*, InterpolationEnvironment&) const final; };
diff --git a/third_party/WebKit/Source/core/animation/SVGNumberInterpolationType.cpp b/third_party/WebKit/Source/core/animation/SVGNumberInterpolationType.cpp index 86702f4..820077f 100644 --- a/third_party/WebKit/Source/core/animation/SVGNumberInterpolationType.cpp +++ b/third_party/WebKit/Source/core/animation/SVGNumberInterpolationType.cpp
@@ -24,11 +24,6 @@ return InterpolationValue::create(*this, InterpolableNumber::create(toSVGNumber(svgValue).value())); } -PassOwnPtr<InterpolationValue> SVGNumberInterpolationType::maybeConvertUnderlyingValue(const InterpolationEnvironment& environment) const -{ - return maybeConvertSVGValue(environment.svgBaseValue()); -} - RefPtrWillBeRawPtr<SVGPropertyBase> SVGNumberInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*) const { double value = toInterpolableNumber(interpolableValue).value();
diff --git a/third_party/WebKit/Source/core/animation/SVGNumberInterpolationType.h b/third_party/WebKit/Source/core/animation/SVGNumberInterpolationType.h index 05aa0b8..e169aafa 100644 --- a/third_party/WebKit/Source/core/animation/SVGNumberInterpolationType.h +++ b/third_party/WebKit/Source/core/animation/SVGNumberInterpolationType.h
@@ -20,7 +20,6 @@ private: PassOwnPtr<InterpolationValue> maybeConvertNeutral() const final; PassOwnPtr<InterpolationValue> maybeConvertSVGValue(const SVGPropertyBase& svgValue) const final; - PassOwnPtr<InterpolationValue> maybeConvertUnderlyingValue(const InterpolationEnvironment&) const final; RefPtrWillBeRawPtr<SVGPropertyBase> appliedSVGValue(const InterpolableValue&, const NonInterpolableValue*) const final; bool m_isNonNegative;
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp index 0e74191..756bf7d 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp
@@ -25,11 +25,15 @@ #include "config.h" #include "platform/graphics/GraphicsLayer.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/scroll/ScrollableArea.h" #include "platform/transforms/Matrix3DTransformOperation.h" #include "platform/transforms/RotateTransformOperation.h" #include "platform/transforms/TranslateTransformOperation.h" #include "public/platform/Platform.h" +#include "public/platform/WebCompositorAnimationPlayer.h" +#include "public/platform/WebCompositorAnimationPlayerClient.h" +#include "public/platform/WebCompositorAnimationTimeline.h" #include "public/platform/WebCompositorSupport.h" #include "public/platform/WebFloatAnimationCurve.h" #include "public/platform/WebGraphicsContext3D.h" @@ -83,6 +87,8 @@ m_layerTreeView.clear(); } + WebLayerTreeView* layerTreeView() { return m_layerTreeView.get(); } + protected: WebLayer* m_platformLayer; OwnPtr<GraphicsLayerForTesting> m_graphicsLayer; @@ -94,6 +100,21 @@ MockGraphicsLayerClient m_client; }; +class AnimationPlayerForTesting : public WebCompositorAnimationPlayerClient { +public: + AnimationPlayerForTesting() + { + m_compositorPlayer = adoptPtr(Platform::current()->compositorSupport()->createAnimationPlayer()); + } + + WebCompositorAnimationPlayer* compositorPlayer() const override + { + return m_compositorPlayer.get(); + } + + OwnPtr<WebCompositorAnimationPlayer> m_compositorPlayer; +}; + TEST_F(GraphicsLayerTest, updateLayerShouldFlattenTransformWithAnimations) { ASSERT_FALSE(m_platformLayer->hasActiveAnimation()); @@ -102,25 +123,63 @@ curve->add(WebFloatKeyframe(0.0, 0.0)); OwnPtr<WebCompositorAnimation> floatAnimation(adoptPtr(Platform::current()->compositorSupport()->createAnimation(*curve, WebCompositorAnimation::TargetPropertyOpacity))); int animationId = floatAnimation->id(); - ASSERT_TRUE(m_platformLayer->addAnimation(floatAnimation.leakPtr())); - ASSERT_TRUE(m_platformLayer->hasActiveAnimation()); + if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled()) { + OwnPtr<WebCompositorAnimationTimeline> compositorTimeline = adoptPtr(Platform::current()->compositorSupport()->createAnimationTimeline()); + AnimationPlayerForTesting player; - m_graphicsLayer->setShouldFlattenTransform(false); + layerTreeView()->attachCompositorAnimationTimeline(compositorTimeline.get()); + compositorTimeline->playerAttached(player); - m_platformLayer = m_graphicsLayer->platformLayer(); - ASSERT_TRUE(m_platformLayer); + player.compositorPlayer()->attachLayer(m_platformLayer); + ASSERT_TRUE(player.compositorPlayer()->isLayerAttached()); - ASSERT_TRUE(m_platformLayer->hasActiveAnimation()); - m_platformLayer->removeAnimation(animationId); - ASSERT_FALSE(m_platformLayer->hasActiveAnimation()); + player.compositorPlayer()->addAnimation(floatAnimation.leakPtr()); - m_graphicsLayer->setShouldFlattenTransform(true); + ASSERT_TRUE(m_platformLayer->hasActiveAnimation()); - m_platformLayer = m_graphicsLayer->platformLayer(); - ASSERT_TRUE(m_platformLayer); + m_graphicsLayer->setShouldFlattenTransform(false); - ASSERT_FALSE(m_platformLayer->hasActiveAnimation()); + m_platformLayer = m_graphicsLayer->platformLayer(); + ASSERT_TRUE(m_platformLayer); + + ASSERT_TRUE(m_platformLayer->hasActiveAnimation()); + player.compositorPlayer()->removeAnimation(animationId); + ASSERT_FALSE(m_platformLayer->hasActiveAnimation()); + + m_graphicsLayer->setShouldFlattenTransform(true); + + m_platformLayer = m_graphicsLayer->platformLayer(); + ASSERT_TRUE(m_platformLayer); + + ASSERT_FALSE(m_platformLayer->hasActiveAnimation()); + + player.compositorPlayer()->detachLayer(); + ASSERT_FALSE(player.compositorPlayer()->isLayerAttached()); + + compositorTimeline->playerDestroyed(player); + layerTreeView()->detachCompositorAnimationTimeline(compositorTimeline.get()); + } else { + ASSERT_TRUE(m_platformLayer->addAnimation(floatAnimation.leakPtr())); + + ASSERT_TRUE(m_platformLayer->hasActiveAnimation()); + + m_graphicsLayer->setShouldFlattenTransform(false); + + m_platformLayer = m_graphicsLayer->platformLayer(); + ASSERT_TRUE(m_platformLayer); + + ASSERT_TRUE(m_platformLayer->hasActiveAnimation()); + m_platformLayer->removeAnimation(animationId); + ASSERT_FALSE(m_platformLayer->hasActiveAnimation()); + + m_graphicsLayer->setShouldFlattenTransform(true); + + m_platformLayer = m_graphicsLayer->platformLayer(); + ASSERT_TRUE(m_platformLayer); + + ASSERT_FALSE(m_platformLayer->hasActiveAnimation()); + } } class FakeScrollableArea : public NoBaseWillBeGarbageCollectedFinalized<FakeScrollableArea>, public ScrollableArea {
diff --git a/third_party/brotli/README.chromium b/third_party/brotli/README.chromium index c57d2f2..972cdb3 100644 --- a/third_party/brotli/README.chromium +++ b/third_party/brotli/README.chromium
@@ -1,6 +1,6 @@ Name: Brotli URL: https://github.com/google/brotli -Version: 8e90bf4c5f6479353beb83af4118782621947765 +Version: c90ec29f54e9165df815b0f1311cfddb1be4afad License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/brotli/dec/bit_reader.c b/third_party/brotli/dec/bit_reader.c index 351cbc2..ddd014e 100644 --- a/third_party/brotli/dec/bit_reader.c +++ b/third_party/brotli/dec/bit_reader.c
@@ -24,15 +24,9 @@ extern "C" { #endif -void BrotliInitBitReader(BrotliBitReader* const br, BrotliInput input) { - BROTLI_DCHECK(br != NULL); - - br->input_ = input; +void BrotliInitBitReader(BrotliBitReader* const br) { br->val_ = 0; br->bit_pos_ = sizeof(br->val_) << 3; - br->avail_in = 0; - br->eos_ = 0; - br->next_in = br->buf_; } int BrotliWarmupBitReader(BrotliBitReader* const br) { @@ -43,12 +37,17 @@ if (!BROTLI_ALIGNED_READ) { aligned_read_mask = 0; } - while (br->bit_pos_ == (sizeof(br->val_) << 3) || - (((size_t)br->next_in) & aligned_read_mask) != 0) { - if (!br->avail_in) { + if (BrotliGetAvailableBits(br) == 0) { + if (!BrotliPullByte(br)) { return 0; } - BrotliPullByte(br); + } + + while ((((size_t)br->next_in) & aligned_read_mask) != 0) { + if (!BrotliPullByte(br)) { + /* If we consumed all the input, we don't care about the alignment. */ + return 1; + } } return 1; }
diff --git a/third_party/brotli/dec/bit_reader.h b/third_party/brotli/dec/bit_reader.h index f25fd4a7..f390348 100644 --- a/third_party/brotli/dec/bit_reader.h +++ b/third_party/brotli/dec/bit_reader.h
@@ -20,45 +20,57 @@ #include <string.h> #include "./port.h" -#include "./streams.h" #include "./types.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif -#define BROTLI_READ_SIZE 1024 -/* 128 bytes, plus 8 bytes slack for valid 128-byte BrotliCheckInputAmount with - some bytes read in val_ of bit reader. */ -#define BROTLI_IMPLICIT_ZEROES 136 -#define BROTLI_IBUF_SIZE (BROTLI_READ_SIZE + BROTLI_IMPLICIT_ZEROES) -#define BROTLI_IBUF_MASK (BROTLI_READ_SIZE - 1) +#if (BROTLI_64_BITS) +#define BROTLI_SHORT_FILL_BIT_WINDOW_READ 4 +typedef uint64_t reg_t; +#else +#define BROTLI_SHORT_FILL_BIT_WINDOW_READ 2 +typedef uint32_t reg_t; +#endif -/* Masking with this expression turns to a single "Unsigned Bit Field Extract" - UBFX instruction on ARM. */ +static const uint32_t kBitMask[33] = { 0x0000, + 0x00000001, 0x00000003, 0x00000007, 0x0000000F, + 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, + 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, + 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, + 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, + 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, + 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, + 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF +}; + static BROTLI_INLINE uint32_t BitMask(uint32_t n) { + if (IS_CONSTANT(n) || BROTLI_HAS_UBFX) { + /* Masking with this expression turns to a single + "Unsigned Bit Field Extract" UBFX instruction on ARM. */ return ~((0xffffffffU) << n); + } else { + return kBitMask[n]; + } } typedef struct { -#if (BROTLI_64_BITS) - uint64_t val_; /* pre-fetched bits */ -#else - uint32_t val_; /* pre-fetched bits */ -#endif + reg_t val_; /* pre-fetched bits */ uint32_t bit_pos_; /* current bit-reading position in val_ */ - uint8_t* next_in; /* the byte we're reading from */ - uint32_t avail_in; - int eos_; /* input stream is finished */ - BrotliInput input_; /* input callback */ - - /* Input byte buffer, consist of a ringbuffer and a "slack" region where */ - /* bytes from the start of the ringbuffer are copied. */ - uint8_t buf_[BROTLI_IBUF_SIZE]; + const uint8_t* next_in; /* the byte we're reading from */ + size_t avail_in; } BrotliBitReader; +typedef struct { + reg_t val_; + uint32_t bit_pos_; + const uint8_t* next_in; + size_t avail_in; +} BrotliBitReaderState; + /* Initializes the bitreader fields. */ -void BrotliInitBitReader(BrotliBitReader* const br, BrotliInput input); +void BrotliInitBitReader(BrotliBitReader* const br); /* Ensures that accumulator is not empty. May consume one byte of input. Returns 0 if data is required but there is no input available. @@ -66,66 +78,35 @@ reading. */ int BrotliWarmupBitReader(BrotliBitReader* const br); -/* Pulls data from the input to the the read buffer. +static BROTLI_INLINE void BrotliBitReaderSaveState( + BrotliBitReader* const from, BrotliBitReaderState* to) { + to->val_ = from->val_; + to->bit_pos_ = from->bit_pos_; + to->next_in = from->next_in; + to->avail_in = from->avail_in; +} - Returns 0 if one of: - - the input callback returned an error, or - - there is no more input and the position is past the end of the stream. - - finish is false and less than BROTLI_READ_SIZE are available - a next call - when more data is available makes it continue including the partially read - data +static BROTLI_INLINE void BrotliBitReaderRestoreState( + BrotliBitReader* const to, BrotliBitReaderState* from) { + to->val_ = from->val_; + to->bit_pos_ = from->bit_pos_; + to->next_in = from->next_in; + to->avail_in = from->avail_in; +} - If finish is true and the end of the stream is reached, - BROTLI_IMPLICIT_ZEROES additional zero bytes are copied to the ringbuffer. -*/ -static BROTLI_INLINE int BrotliReadInput( - BrotliBitReader* const br, int finish) { - if (PREDICT_FALSE(br->eos_)) { - return 0; - } else { - size_t i; - int bytes_read; - if (br->next_in != br->buf_) { - for (i = 0; i < br->avail_in; i++) { - br->buf_[i] = br->next_in[i]; - } - br->next_in = br->buf_; - } - bytes_read = BrotliRead(br->input_, br->next_in + br->avail_in, - (size_t)(BROTLI_READ_SIZE - br->avail_in)); - if (bytes_read < 0) { - return 0; - } - br->avail_in += (uint32_t)bytes_read; - if (br->avail_in < BROTLI_READ_SIZE) { - if (!finish) { - return 0; - } - br->eos_ = 1; - /* Store BROTLI_IMPLICIT_ZEROES bytes of zero after the stream end. */ - memset(br->next_in + br->avail_in, 0, BROTLI_IMPLICIT_ZEROES); - br->avail_in += BROTLI_IMPLICIT_ZEROES; - } - return 1; - } +static BROTLI_INLINE uint32_t BrotliGetAvailableBits( + const BrotliBitReader* br) { + return (BROTLI_64_BITS ? 64 : 32) - br->bit_pos_; } /* Returns amount of unread bytes the bit reader still has buffered from the BrotliInput, including whole bytes in br->val_. */ static BROTLI_INLINE size_t BrotliGetRemainingBytes(BrotliBitReader* br) { - size_t result = br->avail_in + sizeof(br->val_) - (br->bit_pos_ >> 3); - if (!br->eos_) { - return result; - } - if (result <= BROTLI_IMPLICIT_ZEROES) { - return 0; - } - return result - BROTLI_IMPLICIT_ZEROES; + return br->avail_in + (BrotliGetAvailableBits(br) >> 3); } /* Checks if there is at least num bytes left in the input ringbuffer (excluding - the bits remaining in br->val_). The maximum value for num is - BROTLI_IMPLICIT_ZEROES bytes. */ + the bits remaining in br->val_). */ static BROTLI_INLINE int BrotliCheckInputAmount( BrotliBitReader* const br, size_t num) { return br->avail_in >= num; @@ -160,6 +141,7 @@ } } +#if (BROTLI_64_BITS) static BROTLI_INLINE uint64_t BrotliLoad64LE(const uint8_t* in) { if (BROTLI_LITTLE_ENDIAN) { return *((const uint64_t*)in); @@ -186,6 +168,7 @@ return value; } } +#endif /* Guarantees that there are at least n_bits + 1 bits in accumulator. Precondition: accumulator contains at least 1 bit. @@ -215,8 +198,8 @@ br->val_ >>= 32; br->bit_pos_ ^= 32; /* here same as -= 32 because of the if condition */ br->val_ |= ((uint64_t)BrotliLoad32LE(br->next_in)) << 32; - br->avail_in -= 4; - br->next_in += 4; + br->avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ; + br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ; } } #else @@ -233,15 +216,24 @@ br->val_ >>= 16; br->bit_pos_ ^= 16; /* here same as -= 16 because of the if condition */ br->val_ |= ((uint32_t)BrotliLoad16LE(br->next_in)) << 16; - br->avail_in -= 2; - br->next_in += 2; + br->avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ; + br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ; } } #endif } +/* Mosltly like BrotliFillBitWindow, but guarantees only 16 bits and reads no + more than BROTLI_SHORT_FILL_BIT_WINDOW_READ bytes of input. */ +static BROTLI_INLINE void BrotliFillBitWindow16(BrotliBitReader* const br) { + BrotliFillBitWindow(br, 17); +} + /* Pulls one byte of input to accumulator. */ -static BROTLI_INLINE void BrotliPullByte(BrotliBitReader* const br) { +static BROTLI_INLINE int BrotliPullByte(BrotliBitReader* const br) { + if (br->avail_in == 0) { + return 0; + } br->val_ >>= 8; #if (BROTLI_64_BITS) br->val_ |= ((uint64_t)*br->next_in) << 56; @@ -251,39 +243,68 @@ br->bit_pos_ -= 8; --br->avail_in; ++br->next_in; + return 1; } -/* Like BrotliGetBits, but does not mask the result, it is only guaranteed -that it has minimum n_bits. */ -static BROTLI_INLINE uint32_t BrotliGetBitsUnmasked( - BrotliBitReader* const br, uint32_t n_bits) { - BrotliFillBitWindow(br, n_bits); - return (uint32_t)(br->val_ >> br->bit_pos_); +/* Returns currently available bits. + The number of valid bits could be calclulated by BrotliGetAvailableBits. */ +static BROTLI_INLINE reg_t BrotliGetBitsUnmasked(BrotliBitReader* const br) { + return br->val_ >> br->bit_pos_; +} + +/* Like BrotliGetBits, but does not mask the result. + The result contains at least 16 valid bits. */ +static BROTLI_INLINE uint32_t BrotliGet16BitsUnmasked( + BrotliBitReader* const br) { + BrotliFillBitWindow(br, 16); + return (uint32_t)BrotliGetBitsUnmasked(br); } /* Returns the specified number of bits from br without advancing bit pos. */ static BROTLI_INLINE uint32_t BrotliGetBits( BrotliBitReader* const br, uint32_t n_bits) { BrotliFillBitWindow(br, n_bits); - return (uint32_t)(br->val_ >> br->bit_pos_) & BitMask(n_bits); + return (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits); +} + +/* Tries to peek the specified amount of bits. Returns 0, if there is not + enough input. */ +static BROTLI_INLINE int BrotliSafeGetBits( + BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) { + while (BrotliGetAvailableBits(br) < n_bits) { + if (!BrotliPullByte(br)) { + return 0; + } + } + *val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits); + return 1; } /* Advances the bit pos by n_bits. */ static BROTLI_INLINE void BrotliDropBits( - BrotliBitReader* const br, int n_bits) { - br->bit_pos_ += (uint32_t)n_bits; + BrotliBitReader* const br, uint32_t n_bits) { + br->bit_pos_ += n_bits; +} + +static BROTLI_INLINE void BrotliBitReaderUnload(BrotliBitReader* br) { + uint32_t unused_bytes = BrotliGetAvailableBits(br) >> 3; + uint32_t unused_bits = unused_bytes << 3; + br->avail_in += unused_bytes; + br->next_in -= unused_bytes; + br->val_ <<= unused_bits; + br->bit_pos_ += unused_bits; } /* Reads the specified number of bits from br and advances the bit pos. Precondition: accumulator MUST contain at least n_bits. */ static BROTLI_INLINE void BrotliTakeBits( BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) { - *val = (uint32_t)(br->val_ >> br->bit_pos_) & BitMask(n_bits); + *val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits); #ifdef BROTLI_DECODE_DEBUG printf("[BrotliReadBits] %d %d %d val: %6x\n", (int)br->avail_in, (int)br->bit_pos_, n_bits, (int)*val); #endif - br->bit_pos_ += n_bits; + BrotliDropBits(br, n_bits); } /* Reads the specified number of bits from br and advances the bit pos. @@ -307,14 +328,13 @@ } /* Tries to read the specified amount of bits. Returns 0, if there is not - enough input. */ + enough input. n_bits MUST be positive. */ static BROTLI_INLINE int BrotliSafeReadBits( BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) { - while (br->bit_pos_ + (uint32_t)n_bits > (sizeof(br->val_) << 3)) { - if (br->avail_in == 0) { + while (BrotliGetAvailableBits(br) < n_bits) { + if (!BrotliPullByte(br)) { return 0; } - BrotliPullByte(br); } BrotliTakeBits(br, n_bits, val); return 1; @@ -323,7 +343,7 @@ /* Advances the bit reader position to the next byte boundary and verifies that any skipped bits are set to zero. */ static BROTLI_INLINE int BrotliJumpToByteBoundary(BrotliBitReader* br) { - uint32_t pad_bits_count = (64 - (int)br->bit_pos_) & 0x7; + uint32_t pad_bits_count = BrotliGetAvailableBits(br) & 0x7; uint32_t pad_bits = 0; if (pad_bits_count != 0) { BrotliTakeBits(br, pad_bits_count, &pad_bits); @@ -335,12 +355,13 @@ Precondition: bit reader is parked to a byte boundary. Returns -1 if operation is not feasible. */ static BROTLI_INLINE int BrotliPeekByte(BrotliBitReader* br, size_t offset) { - size_t bytes_left = sizeof(br->val_) - (br->bit_pos_ >> 3); - if (br->bit_pos_ & 7) { + uint32_t available_bits = BrotliGetAvailableBits(br); + size_t bytes_left = available_bits >> 3; + if (available_bits & 7) { return -1; } if (offset < bytes_left) { - return (br->val_ >> (br->bit_pos_ + (unsigned)(offset << 3))) & 0xFF; + return (BrotliGetBitsUnmasked(br) >> (unsigned)(offset << 3)) & 0xFF; } offset -= bytes_left; if (offset < br->avail_in) { @@ -354,30 +375,17 @@ warmed up again after this. */ static BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest, BrotliBitReader* br, size_t num) { - while (br->bit_pos_ + 8 <= (BROTLI_64_BITS ? 64 : 32) - && num > 0) { - *dest = (uint8_t)(br->val_ >> br->bit_pos_); - br->bit_pos_ += 8; + while (BrotliGetAvailableBits(br) >= 8 && num > 0) { + *dest = (uint8_t)BrotliGetBitsUnmasked(br); + BrotliDropBits(br, 8); ++dest; --num; } memcpy(dest, br->next_in, num); - br->avail_in -= (uint32_t)num; + br->avail_in -= num; br->next_in += num; } -/* Checks that bit reader hasn't read after the end of input. - Returns 0 if bit reader has used implicit zeroes after the end of input. */ -static BROTLI_INLINE int BrotliIsBitReaderOK(BrotliBitReader* br) { - size_t remaining_bytes = - br->avail_in + sizeof(br->val_) - (br->bit_pos_ >> 3); - return !br->eos_ || (remaining_bytes >= BROTLI_IMPLICIT_ZEROES); -} - -#undef BROTLI_IMPLICIT_ZEROES -#undef BROTLI_IBUF_SIZE -#undef BROTLI_IBUF_MASK - #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif
diff --git a/third_party/brotli/dec/decode.c b/third_party/brotli/dec/decode.c index eb91ce3..bd0d2132 100644 --- a/third_party/brotli/dec/decode.c +++ b/third_party/brotli/dec/decode.c
@@ -46,8 +46,8 @@ #define BROTLI_LOG(x) #endif -static const uint8_t kDefaultCodeLength = 8; -static const uint8_t kCodeLengthRepeatCode = 16; +static const uint32_t kDefaultCodeLength = 8; +static const uint32_t kCodeLengthRepeatCode = 16; static const uint32_t kNumLiteralCodes = 256; static const uint32_t kNumInsertAndCopyCodes = 704; static const uint32_t kNumBlockLengthCodes = 26; @@ -274,27 +274,94 @@ } } -/* Decodes the next Huffman code from bit-stream. Reads 0 - 15 bits. */ -static BROTLI_INLINE uint32_t ReadSymbol(const HuffmanCode* table, - BrotliBitReader* br) { - /* Read the bits for two reads at once. */ - uint32_t val = BrotliGetBitsUnmasked(br, 15); - table += val & HUFFMAN_TABLE_MASK; +/* Decodes the Huffman code. + This method doesn't read data from the bit reader, BUT drops the amount of + bits that correspond to the decoded symbol. + bits MUST contain at least 15 (BROTLI_HUFFMAN_MAX_CODE_LENGTH) valid bits. */ +static BROTLI_INLINE uint32_t DecodeSymbol(uint32_t bits, + const HuffmanCode* table, + BrotliBitReader* br) { + table += bits & HUFFMAN_TABLE_MASK; if (table->bits > HUFFMAN_TABLE_BITS) { uint32_t nbits = table->bits - HUFFMAN_TABLE_BITS; BrotliDropBits(br, HUFFMAN_TABLE_BITS); table += table->value; - table += (val >> HUFFMAN_TABLE_BITS) & BitMask(nbits); + table += (bits >> HUFFMAN_TABLE_BITS) & BitMask(nbits); } BrotliDropBits(br, table->bits); return table->value; } +/* Reads and decodes the next Huffman code from bit-stream. + This method peeks 16 bits of input and drops 0 - 15 of them. */ +static BROTLI_INLINE uint32_t ReadSymbol(const HuffmanCode* table, + BrotliBitReader* br) { + return DecodeSymbol(BrotliGet16BitsUnmasked(br), table, br); +} + +/* Same as DecodeSymbol, but it is known that there is less than 15 bits of + input are currently available. */ +static BROTLI_NOINLINE int SafeDecodeSymbol(const HuffmanCode* table, + BrotliBitReader* br, + uint32_t* result) { + uint32_t val; + uint32_t available_bits = BrotliGetAvailableBits(br); + if (available_bits == 0) { + if (table->bits == 0) { + *result = table->value; + return 1; + } + return 0; /* No valid bits at all. */ + } + val = (uint32_t)BrotliGetBitsUnmasked(br); + table += val & HUFFMAN_TABLE_MASK; + if (table->bits <= HUFFMAN_TABLE_BITS) { + if (table->bits <= available_bits) { + BrotliDropBits(br, table->bits); + *result = table->value; + return 1; + } else { + return 0; /* Not enough bits for the first level. */ + } + } + if (available_bits <= HUFFMAN_TABLE_BITS) { + return 0; /* Not enough bits to move to the second level. */ + } + + /* Speculatively drop HUFFMAN_TABLE_BITS. */ + val = (val & BitMask(table->bits)) >> HUFFMAN_TABLE_BITS; + available_bits -= HUFFMAN_TABLE_BITS; + table += table->value + val; + if (available_bits < table->bits) { + return 0; /* Not enough bits for the second level. */ + } + + BrotliDropBits(br, HUFFMAN_TABLE_BITS + table->bits); + *result = table->value; + return 1; +} + +static BROTLI_INLINE int SafeReadSymbol(const HuffmanCode* table, + BrotliBitReader* br, + uint32_t* result) { + uint32_t val; + if (PREDICT_TRUE(BrotliSafeGetBits(br, 15, &val))) { + *result = DecodeSymbol(val, table, br); + return 1; + } + return SafeDecodeSymbol(table, br, result); +} + + /* Makes a look-up in first level Huffman table. Peeks 8 bits. */ -static BROTLI_INLINE void PreloadSymbol(const HuffmanCode* table, +static BROTLI_INLINE void PreloadSymbol(int safe, + const HuffmanCode* table, BrotliBitReader* br, uint32_t* bits, uint32_t* value) { + if (safe) { + return; + } table += BrotliGetBits(br, HUFFMAN_TABLE_BITS); *bits = table->bits; *value = table->value; @@ -308,7 +375,7 @@ uint32_t* value) { uint32_t result = *value; if (PREDICT_FALSE(*bits > HUFFMAN_TABLE_BITS)) { - uint32_t val = BrotliGetBitsUnmasked(br, 15); + uint32_t val = BrotliGet16BitsUnmasked(br); const HuffmanCode* ext = table + (val & HUFFMAN_TABLE_MASK) + *value; uint32_t mask = BitMask((*bits - HUFFMAN_TABLE_BITS)); BrotliDropBits(br, HUFFMAN_TABLE_BITS); @@ -316,9 +383,9 @@ BrotliDropBits(br, ext->bits); result = ext->value; } else { - BrotliDropBits(br, (int)*bits); + BrotliDropBits(br, *bits); } - PreloadSymbol(table, br, bits, value); + PreloadSymbol(0, table, br, bits, value); return result; } @@ -331,6 +398,250 @@ return result; } +/* Reads (s->symbol + 1) symbols. + Totally 1..4 symbols are read, 1..10 bits each. + The list of symbols MUST NOT contain duplicates. + */ +static BrotliResult ReadSimpleHuffmanSymbols(uint32_t alphabet_size, + BrotliState* s) { + /* max_bits == 1..10; symbol == 0..3; 1..40 bits will be read. */ + BrotliBitReader* br = &s->br; + uint32_t max_bits = Log2Floor(alphabet_size - 1); + uint32_t i = s->sub_loop_counter; + uint32_t num_symbols = s->symbol; + while (i <= num_symbols) { + uint32_t v; + if (PREDICT_FALSE(!BrotliSafeReadBits(br, max_bits, &v))) { + s->sub_loop_counter = i; + s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + if (v >= alphabet_size) { + return BROTLI_FAILURE(); + } + s->symbols_lists_array[i] = (uint16_t)v; + BROTLI_LOG_UINT(s->symbols_lists_array[i]); + ++i; + } + + for (i = 0; i < num_symbols; ++i) { + uint32_t k = i + 1; + for (; k <= num_symbols; ++k) { + if (s->symbols_lists_array[i] == s->symbols_lists_array[k]) { + return BROTLI_FAILURE(); + } + } + } + + return BROTLI_RESULT_SUCCESS; +} + +/* Process single decoded symbol code length: + A) reset the repeat variable + B) remember code length (if it is not 0) + C) extend corredponding index-chain + D) reduce the huffman space + E) update the histogram + */ +static BROTLI_INLINE void ProcessSingleCodeLength(uint32_t code_len, + uint32_t* symbol, uint32_t* repeat, uint32_t* space, + uint32_t* prev_code_len, uint16_t* symbol_lists, + uint16_t* code_length_histo, int* next_symbol) { + *repeat = 0; + if (code_len != 0) { /* code_len == 1..15 */ + symbol_lists[next_symbol[code_len]] = (uint16_t)(*symbol); + next_symbol[code_len] = (int)(*symbol); + *prev_code_len = code_len; + *space -= 32768U >> code_len; + code_length_histo[code_len]++; + } + (*symbol)++; +} + +/* Process repeated symbol code length. + A) Check if it is the extension of previous repeat sequence; if the decoded + value is not kCodeLengthRepeatCode, then it is a new symbol-skip + B) Update repeat variable + C) Check if operation is feasible (fits alphapet) + D) For each symbol do the same operations as in ProcessSingleCodeLength + + PRECONDITION: code_len == kCodeLengthRepeatCode or kCodeLengthRepeatCode + 1 + */ +static BROTLI_INLINE void ProcessRepeatedCodeLength(uint32_t code_len, + uint32_t repeat_delta, uint32_t alphabet_size, uint32_t* symbol, + uint32_t* repeat, uint32_t* space, uint32_t* prev_code_len, + uint32_t* repeat_code_len, uint16_t* symbol_lists, + uint16_t* code_length_histo, int* next_symbol) { + uint32_t old_repeat; + uint32_t new_len = 0; + if (code_len == kCodeLengthRepeatCode) { + new_len = *prev_code_len; + } + if (*repeat_code_len != new_len) { + *repeat = 0; + *repeat_code_len = new_len; + } + old_repeat = *repeat; + if (*repeat > 0) { + *repeat -= 2; + *repeat <<= code_len - 14U; + } + *repeat += repeat_delta + 3U; + repeat_delta = *repeat - old_repeat; + if (*symbol + repeat_delta > alphabet_size) { + (void)BROTLI_FAILURE(); + *symbol = alphabet_size; + *space = 0xFFFFF; + return; + } + if (*repeat_code_len != 0) { + unsigned last = *symbol + repeat_delta; + int next = next_symbol[*repeat_code_len]; + do { + symbol_lists[next] = (uint16_t)*symbol; + next = (int)*symbol; + } while (++(*symbol) != last); + next_symbol[*repeat_code_len] = next; + *space -= repeat_delta << (15 - *repeat_code_len); + code_length_histo[*repeat_code_len] = (uint16_t) + (code_length_histo[*repeat_code_len] + repeat_delta); + } else { + *symbol += repeat_delta; + } +} + +/* Reads and decodes symbol codelengths. */ +static BrotliResult ReadSymbolCodeLengths( + uint32_t alphabet_size, BrotliState* s) { + BrotliBitReader* br = &s->br; + uint32_t symbol = s->symbol; + uint32_t repeat = s->repeat; + uint32_t space = s->space; + uint32_t prev_code_len = s->prev_code_len; + uint32_t repeat_code_len = s->repeat_code_len; + uint16_t* symbol_lists = s->symbol_lists; + uint16_t* code_length_histo = s->code_length_histo; + int* next_symbol = s->next_symbol; + if (!BrotliWarmupBitReader(br)) { + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + while (symbol < alphabet_size && space > 0) { + const HuffmanCode* p = s->table; + uint32_t code_len; + if (!BrotliCheckInputAmount(br, BROTLI_SHORT_FILL_BIT_WINDOW_READ)) { + s->symbol = symbol; + s->repeat = repeat; + s->prev_code_len = prev_code_len; + s->repeat_code_len = repeat_code_len; + s->space = space; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + BrotliFillBitWindow16(br); + p += BrotliGetBitsUnmasked(br) & + BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH); + BrotliDropBits(br, p->bits); /* Use 1..5 bits */ + code_len = p->value; /* code_len == 0..17 */ + if (code_len < kCodeLengthRepeatCode) { + ProcessSingleCodeLength(code_len, &symbol, &repeat, &space, + &prev_code_len, symbol_lists, code_length_histo, next_symbol); + } else { /* code_len == 16..17, extra_bits == 2..3 */ + uint32_t repeat_delta = + (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(code_len - 14U); + BrotliDropBits(br, code_len - 14U); + ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size, + &symbol, &repeat, &space, &prev_code_len, &repeat_code_len, + symbol_lists, code_length_histo, next_symbol); + } + } + s->space = space; + return BROTLI_RESULT_SUCCESS; +} + +static BrotliResult SafeReadSymbolCodeLengths( + uint32_t alphabet_size, BrotliState* s) { + BrotliBitReader* br = &s->br; + while (s->symbol < alphabet_size && s->space > 0) { + const HuffmanCode* p = s->table; + uint32_t code_len; + uint32_t bits = 0; + uint32_t available_bits = BrotliGetAvailableBits(br); + if (available_bits != 0) { + bits = (uint32_t)BrotliGetBitsUnmasked(br); + } + p += bits & BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH); + if (p->bits > available_bits) goto pullMoreInput; + code_len = p->value; /* code_len == 0..17 */ + if (code_len < kCodeLengthRepeatCode) { + BrotliDropBits(br, p->bits); + ProcessSingleCodeLength(code_len, &s->symbol, &s->repeat, &s->space, + &s->prev_code_len, s->symbol_lists, s->code_length_histo, + s->next_symbol); + } else { /* code_len == 16..17, extra_bits == 2..3 */ + uint32_t extra_bits = code_len - 14U; + uint32_t repeat_delta = (bits >> p->bits) & BitMask(extra_bits); + if (available_bits < p->bits + extra_bits) goto pullMoreInput; + BrotliDropBits(br, p->bits + extra_bits); + ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size, + &s->symbol, &s->repeat, &s->space, &s->prev_code_len, + &s->repeat_code_len, s->symbol_lists, s->code_length_histo, + s->next_symbol); + } + continue; + +pullMoreInput: + if (!BrotliPullByte(br)) { + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + } + return BROTLI_RESULT_SUCCESS; +} + +/* Reads and decodes 15..18 codes using static prefix code. + Each code is 2..4 bits long. In total 30..72 bits are used. */ +static BrotliResult ReadCodeLengthCodeLengths(BrotliState* s) { + BrotliBitReader* br = &s->br; + uint32_t num_codes = s->repeat; + unsigned space = s->space; + uint32_t i = s->sub_loop_counter; + for (; i < CODE_LENGTH_CODES; ++i) { + const uint8_t code_len_idx = kCodeLengthCodeOrder[i]; + uint32_t ix; + uint32_t v; + if (PREDICT_FALSE(!BrotliSafeGetBits(br, 4, &ix))) { + uint32_t available_bits = BrotliGetAvailableBits(br); + if (available_bits != 0) { + ix = BrotliGetBitsUnmasked(br) & 0xF; + } else { + ix = 0; + } + if (kCodeLengthPrefixLength[ix] > available_bits) { + s->sub_loop_counter = i; + s->repeat = num_codes; + s->space = space; + s->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + } + v = kCodeLengthPrefixValue[ix]; + BrotliDropBits(br, kCodeLengthPrefixLength[ix]); + s->code_length_code_lengths[code_len_idx] = (uint8_t)v; + BROTLI_LOG_ARRAY_INDEX(s->code_length_code_lengths, code_len_idx); + if (v != 0) { + space = space - (32U >> v); + ++num_codes; + ++s->code_length_histo[v]; + if (space - 1U >= 32U) { + /* space is 0 or wrapped around */ + break; + } + } + } + if (!(num_codes == 1 || space == 0)) { + return BROTLI_FAILURE(); + } + return BROTLI_RESULT_SUCCESS; +} + /* Decodes the Huffman tables. There are 2 scenarios: A) Huffman code contains only few symbols (1..4). Those symbols are read @@ -348,84 +659,71 @@ uint32_t* opt_table_size, BrotliState* s) { BrotliBitReader* br = &s->br; - uint32_t i; /* Unnecessary masking, but might be good for safety. */ alphabet_size &= 0x3ff; /* State machine */ switch (s->substate_huffman) { case BROTLI_STATE_HUFFMAN_NONE: - if (!BrotliCheckInputAmount(br, 32)) { + if (!BrotliSafeReadBits(br, 2, &s->sub_loop_counter)) { return BROTLI_RESULT_NEEDS_MORE_INPUT; } - i = BrotliReadBits(br, 2); + BROTLI_LOG_UINT(s->sub_loop_counter); /* The value is used as follows: 1 for simple code; 0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */ - BROTLI_LOG_UINT(i); - if (i == 1) { - /* Read symbols, codes & code lengths directly. */ - uint32_t max_bits = Log2Floor(alphabet_size - 1); - uint32_t num_symbols = BrotliReadBits(br, 2); - for (i = 0; i < 4; ++i) { - s->symbols_lists_array[i] = 0; - } - i = 0; - /* max_bits == 0..10; symbol == 0..3; 0..40 bits will be read. */ - do { - uint32_t v = BrotliReadBits(br, max_bits); - if (v >= alphabet_size) { - return BROTLI_FAILURE(); - } - s->symbols_lists_array[i] = (uint16_t)v; - BROTLI_LOG_UINT(s->symbols_lists_array[i]); - } while (++i <= num_symbols); - for (i = 0; i < num_symbols; ++i) { - uint32_t k = i + 1; - for (; k <= num_symbols; ++k) { - if (s->symbols_lists_array[i] == s->symbols_lists_array[k]) { - return BROTLI_FAILURE(); - } - } - } - if (num_symbols == 3) { - num_symbols += BrotliReadBits(br, 1); - } - BROTLI_LOG_UINT(num_symbols); - i = BrotliBuildSimpleHuffmanTable( - table, HUFFMAN_TABLE_BITS, s->symbols_lists_array, num_symbols); - if (opt_table_size) { - *opt_table_size = i; - } - s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE; - return BROTLI_RESULT_SUCCESS; - } else { /* Decode Huffman-coded code lengths. */ - int8_t num_codes = 0; - unsigned space = 32; + if (s->sub_loop_counter != 1) { + s->space = 32; + s->repeat = 0; /* num_codes */ memset(&s->code_length_histo[0], 0, sizeof(s->code_length_histo[0]) * (BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1)); memset(&s->code_length_code_lengths[0], 0, - sizeof(s->code_length_code_lengths)); - /* 15..18 codes will be read, 2..4 bits each; 30..72 bits totally. */ - for (; i < CODE_LENGTH_CODES; ++i) { - const uint8_t code_len_idx = kCodeLengthCodeOrder[i]; - uint8_t ix = (uint8_t)BrotliGetBits(br, 4); - uint8_t v = kCodeLengthPrefixValue[ix]; - BrotliDropBits(br, kCodeLengthPrefixLength[ix]); - s->code_length_code_lengths[code_len_idx] = v; - BROTLI_LOG_ARRAY_INDEX(s->code_length_code_lengths, code_len_idx); - if (v != 0) { - space = space - (32U >> v); - ++num_codes; - ++s->code_length_histo[v]; - if (space - 1U >= 32U) { - /* space is 0 or wrapped around */ - break; - } - } + sizeof(s->code_length_code_lengths)); + s->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX; + goto Complex; + } + /* No break, transit to the next state. */ + + case BROTLI_STATE_HUFFMAN_SIMPLE_SIZE: + /* Read symbols, codes & code lengths directly. */ + if (!BrotliSafeReadBits(br, 2, &s->symbol)) { /* num_symbols */ + s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + s->sub_loop_counter = 0; + /* No break, transit to the next state. */ + case BROTLI_STATE_HUFFMAN_SIMPLE_READ: { + BrotliResult result = ReadSimpleHuffmanSymbols(alphabet_size, s); + if (result != BROTLI_RESULT_SUCCESS) { + return result; + } + /* No break, transit to the next state. */ + } + case BROTLI_STATE_HUFFMAN_SIMPLE_BUILD: { + uint32_t table_size; + if (s->symbol == 3) { + uint32_t bits; + if (!BrotliSafeReadBits(br, 1, &bits)) { + s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_BUILD; + return BROTLI_RESULT_NEEDS_MORE_INPUT; } - if (!(num_codes == 1 || space == 0)) { - return BROTLI_FAILURE(); - } + s->symbol += bits; + } + BROTLI_LOG_UINT(s->symbol); + table_size = BrotliBuildSimpleHuffmanTable( + table, HUFFMAN_TABLE_BITS, s->symbols_lists_array, s->symbol); + if (opt_table_size) { + *opt_table_size = table_size; + } + s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE; + return BROTLI_RESULT_SUCCESS; + } + +Complex: /* Decode Huffman-coded code lengths. */ + case BROTLI_STATE_HUFFMAN_COMPLEX: { + uint32_t i; + BrotliResult result = ReadCodeLengthCodeLengths(s); + if (result != BROTLI_RESULT_SUCCESS) { + return result; } BrotliBuildCodeLengthsHuffmanTable(s->table, s->code_length_code_lengths, @@ -443,89 +741,25 @@ s->space = 32768; s->substate_huffman = BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS; /* No break, transit to the next state. */ + } case BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS: { - uint32_t symbol = s->symbol; - uint32_t repeat = s->repeat; - uint32_t space = s->space; - uint8_t prev_code_len = s->prev_code_len; - uint8_t repeat_code_len = s->repeat_code_len; - uint16_t* symbol_lists = s->symbol_lists; - uint16_t* code_length_histo = s->code_length_histo; - int* next_symbol = s->next_symbol; - while (symbol < alphabet_size && space > 0) { - const HuffmanCode* p = s->table; - uint8_t code_len; - if (!BrotliCheckInputAmount(br, 8)) { - s->symbol = symbol; - s->repeat = repeat; - s->prev_code_len = prev_code_len; - s->repeat_code_len = repeat_code_len; - s->space = space; - return BROTLI_RESULT_NEEDS_MORE_INPUT; - } - p += BrotliGetBits(br, BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH); - BrotliDropBits(br, p->bits); /* Use 1..5 bits */ - code_len = (uint8_t)p->value; /* code_len == 0..17 */ - if (code_len < kCodeLengthRepeatCode) { - repeat = 0; - if (code_len != 0) { /* code_len == 1..15 */ - symbol_lists[next_symbol[code_len]] = (uint16_t)symbol; - next_symbol[code_len] = (int)symbol; - prev_code_len = code_len; - space -= 32768U >> code_len; - code_length_histo[code_len]++; - } - symbol++; - } else { /* code_len == 16..17, extra_bits == 2..3 */ - uint32_t repeat_delta = BrotliReadBits(br, code_len - 14U); - uint32_t old_repeat; - uint8_t new_len = 0; - if (code_len == kCodeLengthRepeatCode) { - new_len = prev_code_len; - } - if (repeat_code_len != new_len) { - repeat = 0; - repeat_code_len = new_len; - } - old_repeat = repeat; - if (repeat > 0) { - repeat -= 2; - repeat <<= code_len - 14; - } - repeat += repeat_delta + 3; - repeat_delta = repeat - old_repeat; /* repeat_delta >= 3 */ - /* So, for extra 2..3 bits we produce more than 2 symbols. - Consequently, at most 5 bits per symbol are used. */ - if (symbol + repeat_delta > alphabet_size) { - return BROTLI_FAILURE(); - } - if (repeat_code_len != 0) { - unsigned last = symbol + repeat_delta; - int next = next_symbol[repeat_code_len]; - do { - symbol_lists[next] = (uint16_t)symbol; - next = (int)symbol; - } while (++symbol != last); - next_symbol[repeat_code_len] = next; - space -= repeat_delta << (15 - repeat_code_len); - code_length_histo[repeat_code_len] = (uint16_t) - (code_length_histo[repeat_code_len] + repeat_delta); - } else { - symbol += repeat_delta; - } - } + uint32_t table_size; + BrotliResult result = ReadSymbolCodeLengths(alphabet_size, s); + if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) { + result = SafeReadSymbolCodeLengths(alphabet_size, s); } - if (space != 0) { - BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", space)); + if (result != BROTLI_RESULT_SUCCESS) { + return result; + } + + if (s->space != 0) { + BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", s->space)); return BROTLI_FAILURE(); } - { - uint32_t table_size = BrotliBuildHuffmanTable( - table, HUFFMAN_TABLE_BITS, symbol_lists, - s->code_length_histo); - if (opt_table_size) { - *opt_table_size = table_size; - } + table_size = BrotliBuildHuffmanTable(table, HUFFMAN_TABLE_BITS, + s->symbol_lists, s->code_length_histo); + if (opt_table_size) { + *opt_table_size = table_size; } s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE; return BROTLI_RESULT_SUCCESS; @@ -537,13 +771,41 @@ } /* Decodes a block length by reading 3..39 bits. */ -static BROTLI_INLINE int ReadBlockLength(const HuffmanCode* table, - BrotliBitReader* br) { +static BROTLI_INLINE uint32_t ReadBlockLength(const HuffmanCode* table, + BrotliBitReader* br) { uint32_t code; uint32_t nbits; code = ReadSymbol(table, br); nbits = kBlockLengthPrefixCode[code].nbits; /* nbits == 2..24 */ - return kBlockLengthPrefixCode[code].offset + (int)BrotliReadBits(br, nbits); + return kBlockLengthPrefixCode[code].offset + BrotliReadBits(br, nbits); +} + +/* WARNING: if state is not BROTLI_STATE_READ_BLOCK_LENGTH_NONE, then + reading can't be continued with ReadBlockLength. */ +static BROTLI_INLINE int SafeReadBlockLength(BrotliState* s, + uint32_t* result, + const HuffmanCode* table, + BrotliBitReader* br) { + uint32_t index; + if (s->substate_read_block_length == BROTLI_STATE_READ_BLOCK_LENGTH_NONE) { + if (!SafeReadSymbol(table, br, &index)) { + return 0; + } + } else { + index = s->block_length_index; + } + { + uint32_t bits; + uint32_t nbits = kBlockLengthPrefixCode[index].nbits; /* nbits == 2..24 */ + if (!BrotliSafeReadBits(br, nbits, &bits)) { + s->block_length_index = index; + s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX; + return 0; + } + *result = kBlockLengthPrefixCode[index].offset + bits; + s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE; + return 1; + } } /* Transform: @@ -597,12 +859,6 @@ state->mtf_upper_bound = upper_bound; } -/* Expose function for testing. Will be removed by linker as unused. */ -void InverseMoveToFrontTransformForTesting( - uint8_t* v, uint32_t l, BrotliState* s) { - InverseMoveToFrontTransform(v, l, s); -} - /* Decodes a series of Huffman table using ReadHuffmanCode function. */ static BrotliResult HuffmanTreeGroupDecode(HuffmanTreeGroup* group, @@ -640,7 +896,6 @@ BrotliState* s) { BrotliBitReader* br = &s->br; BrotliResult result = BROTLI_RESULT_SUCCESS; - int use_rle_for_zeros; switch((int)s->substate_context_map) { case BROTLI_STATE_CONTEXT_MAP_NONE: @@ -662,41 +917,65 @@ } s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX; /* No break, continue to next state. */ - case BROTLI_STATE_CONTEXT_MAP_READ_PREFIX: - if (!BrotliWarmupBitReader(br) || !BrotliCheckInputAmount(br, 8)) { + case BROTLI_STATE_CONTEXT_MAP_READ_PREFIX: { + uint32_t bits; + /* In next stage ReadHuffmanCode uses at least 4 bits, so it is safe + to peek 4 bits ahead. */ + if (!BrotliSafeGetBits(br, 5, &bits)) { return BROTLI_RESULT_NEEDS_MORE_INPUT; } - use_rle_for_zeros = (int)BrotliReadBits(br, 1); - if (use_rle_for_zeros) { - s->max_run_length_prefix = BrotliReadBits(br, 4) + 1; + if ((bits & 1) != 0) { /* Use RLE for zeroes. */ + s->max_run_length_prefix = (bits >> 1) + 1; + BrotliDropBits(br, 5); } else { s->max_run_length_prefix = 0; + BrotliDropBits(br, 1); } BROTLI_LOG_UINT(s->max_run_length_prefix); s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_HUFFMAN; /* No break, continue to next state. */ + } case BROTLI_STATE_CONTEXT_MAP_HUFFMAN: result = ReadHuffmanCode(*num_htrees + s->max_run_length_prefix, s->context_map_table, NULL, s); if (result != BROTLI_RESULT_SUCCESS) return result; + s->code = 0xFFFF; s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE; /* No break, continue to next state. */ case BROTLI_STATE_CONTEXT_MAP_DECODE: { uint32_t context_index = s->context_index; uint32_t max_run_length_prefix = s->max_run_length_prefix; uint8_t* context_map = *context_map_arg; - uint32_t code; + uint32_t code = s->code; + if (code != 0xFFFF) { + goto rleCode; + } while (context_index < context_map_size) { - if (!BrotliCheckInputAmount(br, 32)) { + if (!SafeReadSymbol(s->context_map_table, br, &code)) { + s->code = 0xFFFF; s->context_index = context_index; return BROTLI_RESULT_NEEDS_MORE_INPUT; } - code = ReadSymbol(s->context_map_table, br); BROTLI_LOG_UINT(code); + if (code == 0) { context_map[context_index++] = 0; - } else if (code <= max_run_length_prefix) { - uint32_t reps = (1U << code) + BrotliReadBits(br, code); + continue; + } + if (code > max_run_length_prefix) { + context_map[context_index++] = + (uint8_t)(code - max_run_length_prefix); + continue; + } +rleCode: + { + uint32_t reps; + if (!BrotliSafeReadBits(br, code, &reps)) { + s->code = code; + s->context_index = context_index; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + reps += 1U << code; BROTLI_LOG_UINT(reps); if (context_index + reps > context_map_size) { return BROTLI_FAILURE(); @@ -704,13 +983,18 @@ do { context_map[context_index++] = 0; } while (--reps); - } else { - context_map[context_index++] = - (uint8_t)(code - max_run_length_prefix); } } - if (BrotliReadBits(br, 1)) { - InverseMoveToFrontTransform(context_map, context_map_size, s); + /* No break, continue to next state. */ + } + case BROTLI_STATE_CONTEXT_MAP_TRANSFORM: { + uint32_t bits; + if (!BrotliSafeReadBits(br, 1, &bits)) { + s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_TRANSFORM; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + if (bits != 0) { + InverseMoveToFrontTransform(*context_map_arg, context_map_size, s); } s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE; return BROTLI_RESULT_SUCCESS; @@ -721,15 +1005,32 @@ } /* Decodes a command or literal and updates block type ringbuffer. - Reads 0..15 bits. */ -static void DecodeBlockType(const uint32_t max_block_type, - const HuffmanCode* trees, - int tree_type, - uint32_t* ringbuffers, - BrotliBitReader* br) { - uint32_t* ringbuffer = ringbuffers + tree_type * 2; - uint32_t block_type = ReadSymbol( - &trees[tree_type * BROTLI_HUFFMAN_MAX_TABLE_SIZE], br); + Reads 3..54 bits. */ +static int BROTLI_INLINE DecodeBlockTypeAndLength(int safe, + BrotliState* s, int tree_type) { + uint32_t max_block_type = s->num_block_types[tree_type]; + int tree_offset = tree_type * BROTLI_HUFFMAN_MAX_TABLE_SIZE; + const HuffmanCode* type_tree = &s->block_type_trees[tree_offset]; + const HuffmanCode* len_tree = &s->block_len_trees[tree_offset]; + BrotliBitReader* br = &s->br; + uint32_t* ringbuffer = &s->block_type_rb[tree_type * 2]; + uint32_t block_type; + + /* Read 0..15 + 3..39 bits */ + if (!safe) { + block_type = ReadSymbol(type_tree, br); + s->block_length[tree_type] = ReadBlockLength(len_tree, br); + } else { + BrotliBitReaderState memento; + BrotliBitReaderSaveState(br, &memento); + if (!SafeReadSymbol(type_tree, br, &block_type)) return 0; + if (!SafeReadBlockLength(s, &s->block_length[tree_type], len_tree, br)) { + s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE; + BrotliBitReaderRestoreState(br, &memento); + return 0; + } + } + if (block_type == 1) { block_type = ringbuffer[1] + 1; } else if (block_type == 0) { @@ -742,17 +1043,18 @@ } ringbuffer[0] = ringbuffer[1]; ringbuffer[1] = block_type; + return 1; } /* Decodes the block type and updates the state for literal context. - Reads 18..54 bits. */ -static void DecodeBlockTypeWithContext(BrotliState* s, - BrotliBitReader* br) { + Reads 3..54 bits. */ +static int BROTLI_INLINE DecodeLiteralBlockSwitchInternal(int safe, + BrotliState* s) { uint8_t context_mode; uint32_t context_offset; - DecodeBlockType(s->num_block_types[0], s->block_type_trees, 0, - s->block_type_rb, br); /* Reads 0..15 bits. */ - s->block_length[0] = ReadBlockLength(s->block_len_trees, br); /* 3..39 bits */ + if (!DecodeBlockTypeAndLength(safe, s, 0)) { + return 0; + } context_offset = s->block_type_rb[1] << kLiteralContextBits; s->context_map_slice = s->context_map + context_offset; s->literal_htree_index = s->context_map_slice[0]; @@ -760,115 +1062,125 @@ context_mode = s->context_modes[s->block_type_rb[1]]; s->context_lookup1 = &kContextLookup[kContextLookupOffsets[context_mode]]; s->context_lookup2 = &kContextLookup[kContextLookupOffsets[context_mode + 1]]; + return 1; } -BrotliResult WriteRingBuffer(BrotliOutput output, - BrotliState* s) { - int num_written; +static void BROTLI_NOINLINE DecodeLiteralBlockSwitch(BrotliState* s) { + DecodeLiteralBlockSwitchInternal(0, s); +} + +static int BROTLI_NOINLINE SafeDecodeLiteralBlockSwitch(BrotliState* s) { + return DecodeLiteralBlockSwitchInternal(1, s); +} + +/* Block switch for insert/copy length. + Reads 3..54 bits. */ +static int BROTLI_INLINE DecodeCommandBlockSwitchInternal(int safe, + BrotliState* s) { + if (!DecodeBlockTypeAndLength(safe, s, 1)) { + return 0; + } + s->htree_command = s->insert_copy_hgroup.htrees[s->block_type_rb[3]]; + return 1; +} + +static void BROTLI_NOINLINE DecodeCommandBlockSwitch(BrotliState* s) { + DecodeCommandBlockSwitchInternal(0, s); +} +static int BROTLI_NOINLINE SafeDecodeCommandBlockSwitch(BrotliState* s) { + return DecodeCommandBlockSwitchInternal(1, s); +} + +/* Block switch for distance codes. + Reads 3..54 bits. */ +static int BROTLI_INLINE DecodeDistanceBlockSwitchInternal(int safe, + BrotliState* s) { + if (!DecodeBlockTypeAndLength(safe, s, 2)) { + return 0; + } + s->dist_context_map_slice = + s->dist_context_map + (s->block_type_rb[5] << kDistanceContextBits); + s->dist_htree_index = s->dist_context_map_slice[s->distance_context]; + return 1; +} + +static void BROTLI_NOINLINE DecodeDistanceBlockSwitch(BrotliState* s) { + DecodeDistanceBlockSwitchInternal(0, s); +} + +static int BROTLI_NOINLINE SafeDecodeDistanceBlockSwitch(BrotliState* s) { + return DecodeDistanceBlockSwitchInternal(1, s); +} + +static BrotliResult WriteRingBuffer(size_t* available_out, uint8_t** next_out, + size_t* total_out, BrotliState* s) { + size_t pos = (s->pos > s->ringbuffer_size) ? + (size_t)s->ringbuffer_size : (size_t)(s->pos); + uint8_t* start = s->ringbuffer + + (s->partial_pos_out & (size_t)s->ringbuffer_mask); + size_t partial_pos_rb = + (s->rb_roundtrips * (size_t)s->ringbuffer_size) + pos; + size_t to_write = (partial_pos_rb - s->partial_pos_out); + size_t num_written = *available_out; + if (num_written > to_write) { + num_written = to_write; + } if (s->meta_block_remaining_len < 0) { return BROTLI_FAILURE(); } - num_written = BrotliWrite( - output, s->ringbuffer + s->partially_written, - (size_t)(s->to_write - s->partially_written)); - BROTLI_LOG_UINT(s->partially_written); - BROTLI_LOG_UINT(s->to_write); + memcpy(*next_out, start, num_written); + *next_out += num_written; + *available_out -= num_written; + BROTLI_LOG_UINT(to_write); BROTLI_LOG_UINT(num_written); - if (num_written < 0) { - return BROTLI_FAILURE(); - } - s->partially_written += num_written; - if (s->partially_written < s->to_write) { + s->partial_pos_out += (size_t)num_written; + *total_out = s->partial_pos_out; + if (num_written < to_write) { return BROTLI_RESULT_NEEDS_MORE_OUTPUT; } return BROTLI_RESULT_SUCCESS; } -BrotliResult BROTLI_NOINLINE CopyUncompressedBlockToOutput(BrotliOutput output, - int pos, - BrotliState* s) { - BrotliResult result; - int num_read; - int nbytes; +static BrotliResult BROTLI_NOINLINE CopyUncompressedBlockToOutput( + size_t* available_out, uint8_t** next_out, size_t* total_out, + BrotliState* s) { /* State machine */ for (;;) { - switch ((int)s->substate_uncompressed) { - case BROTLI_STATE_UNCOMPRESSED_NONE: - nbytes = (int)BrotliGetRemainingBytes(&s->br); - /* For short lengths copy byte-by-byte */ - if (s->meta_block_remaining_len < 8 || - s->meta_block_remaining_len < nbytes) { - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_SHORT; - break; + switch (s->substate_uncompressed) { + case BROTLI_STATE_UNCOMPRESSED_NONE: { + int nbytes = (int)BrotliGetRemainingBytes(&s->br); + if (nbytes > s->meta_block_remaining_len) { + nbytes = s->meta_block_remaining_len; + } + if (s->pos + nbytes > s->ringbuffer_size) { + nbytes = s->ringbuffer_size - s->pos; } /* Copy remaining bytes from s->br.buf_ to ringbuffer. */ - BrotliCopyBytes(&s->ringbuffer[pos], &s->br, (size_t)nbytes); - pos += nbytes; + BrotliCopyBytes(&s->ringbuffer[s->pos], &s->br, (size_t)nbytes); + s->pos += nbytes; s->meta_block_remaining_len -= nbytes; - if (pos >= s->ringbuffer_size) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE; - break; - } - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_COPY; - break; - case BROTLI_STATE_UNCOMPRESSED_SHORT: - if (!BrotliWarmupBitReader(&s->br)) { + if (s->pos < s->ringbuffer_size) { + if (s->meta_block_remaining_len == 0) { + return BROTLI_RESULT_SUCCESS; + } return BROTLI_RESULT_NEEDS_MORE_INPUT; } - while (s->meta_block_remaining_len > 0) { - if (!BrotliCheckInputAmount(&s->br, 8)) { - return BROTLI_RESULT_NEEDS_MORE_INPUT; - } - s->ringbuffer[pos++] = (uint8_t)BrotliReadBits(&s->br, 8); - s->meta_block_remaining_len--; - } - if (pos >= s->ringbuffer_size) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE; - } else { - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE; - return BROTLI_RESULT_SUCCESS; - } - /* No break, if state is updated, continue to next state */ - case BROTLI_STATE_UNCOMPRESSED_WRITE: - result = WriteRingBuffer(output, s); + s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE; + /*s->partial_pos_rb += (size_t)s->ringbuffer_size;*/ + /* No break, continue to next state */ + } + case BROTLI_STATE_UNCOMPRESSED_WRITE: { + BrotliResult result = WriteRingBuffer( + available_out, next_out, total_out, s); if (result != BROTLI_RESULT_SUCCESS) { return result; } - pos &= s->ringbuffer_mask; + s->pos = 0; + s->rb_roundtrips++; s->max_distance = s->max_backward_distance; - /* If we wrote past the logical end of the ringbuffer, copy the tail - of the ringbuffer to its beginning and flush the ringbuffer to the - output. */ - memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)pos); - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_COPY; - /* No break, continue to next state */ - case BROTLI_STATE_UNCOMPRESSED_COPY: - /* Copy straight from the input onto the ringbuffer. The ringbuffer will - be flushed to the output at a later time. */ - nbytes = s->meta_block_remaining_len; - if (pos + nbytes > s->ringbuffer_size) { - nbytes = s->ringbuffer_size - pos; - } - num_read = BrotliRead(s->br.input_, &s->ringbuffer[pos], - (size_t)nbytes); - pos += num_read; - s->meta_block_remaining_len -= num_read; - if (num_read < nbytes) { - if (num_read < 0) return BROTLI_FAILURE(); - return BROTLI_RESULT_NEEDS_MORE_INPUT; - } - if (pos == s->ringbuffer_size) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE; - break; - } s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE; - return BROTLI_RESULT_SUCCESS; + break; + } } } return BROTLI_FAILURE(); @@ -877,36 +1189,27 @@ int BrotliDecompressedSize(size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size) { - BrotliMemInput memin; - BrotliInput in = BrotliInitMemInput(encoded_buffer, encoded_size, &memin); - BrotliBitReader br; BrotliState s; int next_block_header; - size_t offset; BrotliStateInit(&s); - BrotliInitBitReader(&br, in); - if (!BrotliReadInput(&br, 1) || !BrotliWarmupBitReader(&br)) { + s.br.next_in = encoded_buffer; + s.br.avail_in = encoded_size; + if (!BrotliWarmupBitReader(&s.br)) { return 0; } - DecodeWindowBits(&br); - if (DecodeMetaBlockLength(&s, &br) != BROTLI_RESULT_SUCCESS) { + DecodeWindowBits(&s.br); + if (DecodeMetaBlockLength(&s, &s.br) != BROTLI_RESULT_SUCCESS) { return 0; } *decoded_size = (size_t)s.meta_block_remaining_len; if (s.is_last_metablock) { return 1; } - if (!s.is_uncompressed || !BrotliJumpToByteBoundary(&br)) { + if (!s.is_uncompressed || !BrotliJumpToByteBoundary(&s.br)) { return 0; } - next_block_header = BrotliPeekByte(&br, (size_t)s.meta_block_remaining_len); - if (next_block_header != -1) { - return (next_block_header & 3) == 3; - } - /* Currently bit reader can't peek outside of its buffer... */ - offset = BROTLI_READ_SIZE - BrotliGetRemainingBytes(&br); - offset += (size_t)s.meta_block_remaining_len; - return (offset < encoded_size) && ((encoded_buffer[offset] & 3) == 3); + next_block_header = BrotliPeekByte(&s.br, (size_t)s.meta_block_remaining_len); + return (next_block_header != -1) && ((next_block_header & 3) == 3); } /* Allocates the smallest feasible ring buffer. @@ -918,9 +1221,12 @@ processed. When this method is called, metablock size and flags MUST be decoded. */ -int BROTLI_NOINLINE BrotliAllocateRingBuffer(BrotliState* s, +static int BROTLI_NOINLINE BrotliAllocateRingBuffer(BrotliState* s, BrotliBitReader* br) { - static const int kRingBufferWriteAheadSlack = BROTLI_READ_SIZE; + /* We need the slack region for the following reasons: + - doing up to two 16-byte copies for fast backward copying + - inserting transformed dictionary word (5 prefix + 24 base + 8 suffix) */ + static const int kRingBufferWriteAheadSlack = 42; int is_last = s->is_last_metablock; s->ringbuffer_size = 1 << s->window_bits; @@ -950,8 +1256,7 @@ s->ringbuffer_mask = s->ringbuffer_size - 1; s->ringbuffer = (uint8_t*)malloc((size_t)(s->ringbuffer_size + - kRingBufferWriteAheadSlack + - kBrotliMaxDictionaryWordLength)); + kRingBufferWriteAheadSlack + kBrotliMaxDictionaryWordLength)); if (s->ringbuffer == 0) { return 0; } @@ -966,17 +1271,527 @@ return 1; } +/* Reads 1..256 2-bit context modes. */ +static BrotliResult ReadContextModes(BrotliState* s) { + BrotliBitReader* br = &s->br; + int i = s->loop_counter; + + while (i < (int)s->num_block_types[0]) { + uint32_t bits; + if (!BrotliSafeReadBits(br, 2, &bits)) { + s->loop_counter = i; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + s->context_modes[i] = (uint8_t)(bits << 1); + BROTLI_LOG_ARRAY_INDEX(s->context_modes, i); + i++; + } + return BROTLI_RESULT_SUCCESS; +} + +static void BROTLI_INLINE TakeDistanceFromRingBuffer(BrotliState* s) { + if (s->distance_code == 0) { + --s->dist_rb_idx; + s->distance_code = s->dist_rb[s->dist_rb_idx & 3]; + } else { + int distance_code = s->distance_code << 1; + /* kDistanceShortCodeIndexOffset has 2-bit values from LSB: */ + /* 3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 */ + const uint32_t kDistanceShortCodeIndexOffset = 0xaaafff1b; + /* kDistanceShortCodeValueOffset has 2-bit values from LSB: */ + /*-0, 0,-0, 0,-1, 1,-2, 2,-3, 3,-1, 1,-2, 2,-3, 3 */ + const uint32_t kDistanceShortCodeValueOffset = 0xfa5fa500; + int v = (s->dist_rb_idx + + (int)(kDistanceShortCodeIndexOffset >> distance_code)) & 0x3; + s->distance_code = s->dist_rb[v]; + v = (int)(kDistanceShortCodeValueOffset >> distance_code) & 0x3; + if ((distance_code & 0x3) != 0) { + s->distance_code += v; + } else { + s->distance_code -= v; + if (s->distance_code <= 0) { + /* A huge distance will cause a BROTLI_FAILURE() soon. */ + /* This is a little faster than failing here. */ + s->distance_code = 0x0fffffff; + } + } + } +} + +static BROTLI_INLINE int SafeReadBits( + BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) { + if (n_bits != 0) { + return BrotliSafeReadBits(br, n_bits, val); + } else { + *val = 0; + return 1; + } +} + +/* Precondition: s->distance_code < 0 */ +static int BROTLI_INLINE ReadDistanceInternal(int safe, + BrotliState* s, BrotliBitReader* br) { + int distval; + BrotliBitReaderState memento; + HuffmanCode* distance_tree = s->distance_hgroup.htrees[s->dist_htree_index]; + if (!safe) { + s->distance_code = (int)ReadSymbol(distance_tree, br); + } else { + uint32_t code; + BrotliBitReaderSaveState(br, &memento); + if (!SafeReadSymbol(distance_tree, br, &code)) { + return 0; + } + s->distance_code = (int)code; + } + /* Convert the distance code to the actual distance by possibly */ + /* looking up past distances from the s->ringbuffer. */ + if ((s->distance_code & ~0xf) == 0) { + TakeDistanceFromRingBuffer(s); + --s->block_length[2]; + return 1; + } + distval = s->distance_code - (int)s->num_direct_distance_codes; + if (distval >= 0) { + uint32_t nbits; + int postfix; + int offset; + if (!safe && (s->distance_postfix_bits == 0)) { + nbits = ((uint32_t)distval >> 1) + 1; + offset = ((2 + (distval & 1)) << nbits) - 4; + s->distance_code = (int)s->num_direct_distance_codes + + offset + (int)BrotliReadBits(br, nbits); + } else { + /* This branch also works well when s->distance_postfix_bits == 0 */ + uint32_t bits; + postfix = distval & s->distance_postfix_mask; + distval >>= s->distance_postfix_bits; + nbits = ((uint32_t)distval >> 1) + 1; + if (safe) { + if (!SafeReadBits(br, nbits, &bits)) { + s->distance_code = -1; /* Restore precondition. */ + BrotliBitReaderRestoreState(br, &memento); + return 0; + } + } else { + bits = BrotliReadBits(br, nbits); + } + offset = ((2 + (distval & 1)) << nbits) - 4; + s->distance_code = (int)s->num_direct_distance_codes + + ((offset + (int)bits) << s->distance_postfix_bits) + postfix; + } + } + s->distance_code = s->distance_code - NUM_DISTANCE_SHORT_CODES + 1; + --s->block_length[2]; + return 1; +} + +static void BROTLI_INLINE ReadDistance(BrotliState* s, BrotliBitReader* br) { + ReadDistanceInternal(0, s, br); +} + +static int BROTLI_INLINE SafeReadDistance(BrotliState* s, BrotliBitReader* br) { + return ReadDistanceInternal(1, s, br); +} + +static int BROTLI_INLINE ReadCommandInternal(int safe, + BrotliState* s, BrotliBitReader* br, int* insert_length) { + uint32_t cmd_code; + uint32_t insert_len_extra = 0; + uint32_t copy_length; + CmdLutElement v; + BrotliBitReaderState memento; + if (!safe) { + cmd_code = ReadSymbol(s->htree_command, br); + } else { + BrotliBitReaderSaveState(br, &memento); + if (!SafeReadSymbol(s->htree_command, br, &cmd_code)) { + return 0; + } + } + v = kCmdLut[cmd_code]; + s->distance_code = v.distance_code; + s->distance_context = v.context; + s->dist_htree_index = s->dist_context_map_slice[s->distance_context]; + *insert_length = v.insert_len_offset; + if (!safe) { + if (PREDICT_FALSE(v.insert_len_extra_bits != 0)) { + insert_len_extra = BrotliReadBits(br, v.insert_len_extra_bits); + } + copy_length = BrotliReadBits(br, v.copy_len_extra_bits); + } else { + if (!SafeReadBits(br, v.insert_len_extra_bits, &insert_len_extra) || + !SafeReadBits(br, v.copy_len_extra_bits, ©_length)) { + BrotliBitReaderRestoreState(br, &memento); + return 0; + } + } + s->copy_length = (int)copy_length + v.copy_len_offset; + --s->block_length[1]; + *insert_length += (int)insert_len_extra; + return 1; +} + +static void BROTLI_INLINE ReadCommand(BrotliState* s, BrotliBitReader* br, + int* insert_length) { + ReadCommandInternal(0, s, br, insert_length); +} + +static int BROTLI_INLINE SafeReadCommand(BrotliState* s, BrotliBitReader* br, + int* insert_length) { + return ReadCommandInternal(1, s, br, insert_length); +} + +static BROTLI_INLINE int WarmupBitReader(int safe, BrotliBitReader* const br) { + if (safe) { + return 1; + } + return BrotliWarmupBitReader(br); +} + +static BROTLI_INLINE int CheckInputAmount(int safe, + BrotliBitReader* const br, size_t num) { + if (safe) { + return 1; + } + return BrotliCheckInputAmount(br, num); +} + +#define BROTLI_SAFE(METHOD) { \ + if (safe) { \ + if (! Safe ## METHOD ) { \ + result = BROTLI_RESULT_NEEDS_MORE_INPUT; \ + goto saveStateAndReturn; \ + } \ + } else { \ + METHOD ; \ + } \ +} + +static BROTLI_INLINE BrotliResult ProcessCommandsInternal(int safe, + BrotliState* s) { + int pos = s->pos; + int i = s->loop_counter; + BrotliResult result = BROTLI_RESULT_SUCCESS; + BrotliBitReader* br = &s->br; + + if (!CheckInputAmount(safe, br, 28) || !WarmupBitReader(safe, br)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + + /* Jump into state machine. */ + if (s->state == BROTLI_STATE_COMMAND_BEGIN) { + goto CommandBegin; + } else if (s->state == BROTLI_STATE_COMMAND_INNER) { + goto CommandInner; + } else if (s->state == BROTLI_STATE_COMMAND_POST_DECODE_LITERALS) { + goto CommandPostDecodeLiterals; + } else if (s->state == BROTLI_STATE_COMMAND_POST_WRAP_COPY) { + goto CommandPostWrapCopy; + } else { + return BROTLI_FAILURE(); + } + +CommandBegin: + if (safe) { + s->state = BROTLI_STATE_COMMAND_BEGIN; + } + if (!CheckInputAmount(safe, br, 28)) { /* 156 bits + 7 bytes */ + s->state = BROTLI_STATE_COMMAND_BEGIN; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + if (PREDICT_FALSE(s->block_length[1] == 0)) { + BROTLI_SAFE(DecodeCommandBlockSwitch(s)); + goto CommandBegin; + } + /* Read the insert/copy length in the command */ + BROTLI_SAFE(ReadCommand(s, br, &i)); + BROTLI_LOG_UINT(i); + BROTLI_LOG_UINT(s->copy_length); + BROTLI_LOG_UINT(s->distance_code); + if (i == 0) { + goto CommandPostDecodeLiterals; + } + s->meta_block_remaining_len -= i; + +CommandInner: + if (safe) { + s->state = BROTLI_STATE_COMMAND_INNER; + } + /* Read the literals in the command */ + if (s->trivial_literal_context) { + uint32_t bits; + uint32_t value; + PreloadSymbol(safe, s->literal_htree, br, &bits, &value); + do { + if (!CheckInputAmount(safe, br, 28)) { /* 162 bits + 7 bytes */ + s->state = BROTLI_STATE_COMMAND_INNER; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + if (PREDICT_FALSE(s->block_length[0] == 0)) { + BROTLI_SAFE(DecodeLiteralBlockSwitch(s)); + PreloadSymbol(safe, s->literal_htree, br, &bits, &value); + } + if (!safe) { + s->ringbuffer[pos] = (uint8_t)ReadPreloadedSymbol( + s->literal_htree, br, &bits, &value); + } else { + uint32_t literal; + if (!SafeReadSymbol(s->literal_htree, br, &literal)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + s->ringbuffer[pos] = (uint8_t)literal; + } + --s->block_length[0]; + BROTLI_LOG_UINT(s->literal_htree_index); + BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos); + ++pos; + if (PREDICT_FALSE(pos == s->ringbuffer_size)) { + s->state = BROTLI_STATE_COMMAND_INNER_WRITE; + --i; + goto saveStateAndReturn; + } + } while (--i != 0); + } else { + uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask]; + uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask]; + do { + const HuffmanCode* hc; + uint8_t context; + if (!CheckInputAmount(safe, br, 28)) { /* 162 bits + 7 bytes */ + s->state = BROTLI_STATE_COMMAND_INNER; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + if (PREDICT_FALSE(s->block_length[0] == 0)) { + BROTLI_SAFE(DecodeLiteralBlockSwitch(s)); + } + context = s->context_lookup1[p1] | s->context_lookup2[p2]; + BROTLI_LOG_UINT(context); + hc = s->literal_hgroup.htrees[s->context_map_slice[context]]; + p2 = p1; + if (!safe) { + p1 = (uint8_t)ReadSymbol(hc, br); + } else { + uint32_t literal; + if (!SafeReadSymbol(hc, br, &literal)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + p1 = (uint8_t)literal; + } + s->ringbuffer[pos] = p1; + --s->block_length[0]; + BROTLI_LOG_UINT(s->context_map_slice[context]); + BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask); + ++pos; + if (PREDICT_FALSE(pos == s->ringbuffer_size)) { + s->state = BROTLI_STATE_COMMAND_INNER_WRITE; + --i; + goto saveStateAndReturn; + } + } while (--i != 0); + } + if (s->meta_block_remaining_len <= 0) { + s->state = BROTLI_STATE_METABLOCK_DONE; + goto saveStateAndReturn; + } + +CommandPostDecodeLiterals: + if (safe) { + s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS; + } + if (s->distance_code >= 0) { + --s->dist_rb_idx; + s->distance_code = s->dist_rb[s->dist_rb_idx & 3]; + goto postReadDistance; /* We already have the implicit distance */ + } + /* Read distance code in the command, unless it was implicitly zero. */ + if (PREDICT_FALSE(s->block_length[2] == 0)) { + BROTLI_SAFE(DecodeDistanceBlockSwitch(s)); + } + BROTLI_SAFE(ReadDistance(s, br)); +postReadDistance: + BROTLI_LOG_UINT(s->distance_code); + if (s->max_distance != s->max_backward_distance) { + if (pos < s->max_backward_distance_minus_custom_dict_size) { + s->max_distance = pos + s->custom_dict_size; + } else { + s->max_distance = s->max_backward_distance; + } + } + i = s->copy_length; + /* Apply copy of LZ77 back-reference, or static dictionary reference if + the distance is larger than the max LZ77 distance */ + if (s->distance_code > s->max_distance) { + if (i >= kBrotliMinDictionaryWordLength && + i <= kBrotliMaxDictionaryWordLength) { + int offset = kBrotliDictionaryOffsetsByLength[i]; + int word_id = s->distance_code - s->max_distance - 1; + uint32_t shift = kBrotliDictionarySizeBitsByLength[i]; + int mask = (int)BitMask(shift); + int word_idx = word_id & mask; + int transform_idx = word_id >> shift; + offset += word_idx * i; + if (transform_idx < kNumTransforms) { + const uint8_t* word = &kBrotliDictionary[offset]; + int len = i; + if (transform_idx == 0) { + memcpy(&s->ringbuffer[pos], word, (size_t)len); + } else { + len = TransformDictionaryWord( + &s->ringbuffer[pos], word, len, transform_idx); + } + pos += len; + s->meta_block_remaining_len -= len; + if (pos >= s->ringbuffer_size) { + /*s->partial_pos_rb += (size_t)s->ringbuffer_size;*/ + s->state = BROTLI_STATE_COMMAND_POST_WRITE_1; + goto saveStateAndReturn; + } + } else { + BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " + "len: %d bytes left: %d\n", + pos, s->distance_code, i, + s->meta_block_remaining_len)); + return BROTLI_FAILURE(); + } + } else { + BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " + "len: %d bytes left: %d\n", pos, s->distance_code, i, + s->meta_block_remaining_len)); + return BROTLI_FAILURE(); + } + } else { + const uint8_t *ringbuffer_end_minus_copy_length = + s->ringbuffer_end - i; + uint8_t* copy_src = &s->ringbuffer[ + (pos - s->distance_code) & s->ringbuffer_mask]; + uint8_t* copy_dst = &s->ringbuffer[pos]; + /* update the recent distances cache */ + s->dist_rb[s->dist_rb_idx & 3] = s->distance_code; + ++s->dist_rb_idx; + s->meta_block_remaining_len -= i; + if (PREDICT_FALSE(s->meta_block_remaining_len < 0)) { + BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " + "len: %d bytes left: %d\n", pos, s->distance_code, i, + s->meta_block_remaining_len)); + return BROTLI_FAILURE(); + } + /* There is 128+ bytes of slack in the ringbuffer allocation. + Also, we have 16 short codes, that make these 16 bytes irrelevant + in the ringbuffer. Let's copy over them as a first guess. + */ + memmove16(copy_dst, copy_src); + /* Now check if the copy extends over the ringbuffer end, + or if the copy overlaps with itself, if yes, do wrap-copy. */ + if (copy_src < copy_dst) { + if (copy_dst >= ringbuffer_end_minus_copy_length) { + goto CommandPostWrapCopy; + } + if (copy_src + i > copy_dst) { + goto postSelfintersecting; + } + } else { + if (copy_src >= ringbuffer_end_minus_copy_length) { + goto CommandPostWrapCopy; + } + if (copy_dst + i > copy_src) { + goto postSelfintersecting; + } + } + pos += i; + if (i > 16) { + if (i > 32) { + memcpy(copy_dst + 16, copy_src + 16, (size_t)(i - 16)); + } else { + /* This branch covers about 45% cases. + Fixed size short copy allows more compiler optimizations. */ + memmove16(copy_dst + 16, copy_src + 16); + } + } + } + if (s->meta_block_remaining_len <= 0) { + /* Next metablock, if any */ + s->state = BROTLI_STATE_METABLOCK_DONE; + goto saveStateAndReturn; + } else { + goto CommandBegin; + } +postSelfintersecting: + while (--i >= 0) { + s->ringbuffer[pos] = + s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask]; + ++pos; + } + if (s->meta_block_remaining_len <= 0) { + /* Next metablock, if any */ + s->state = BROTLI_STATE_METABLOCK_DONE; + goto saveStateAndReturn; + } else { + goto CommandBegin; + } + +CommandPostWrapCopy: + s->state = BROTLI_STATE_COMMAND_POST_WRAP_COPY; + while (--i >= 0) { + s->ringbuffer[pos] = + s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask]; + ++pos; + if (pos == s->ringbuffer_size) { + /*s->partial_pos_rb += (size_t)s->ringbuffer_size;*/ + s->state = BROTLI_STATE_COMMAND_POST_WRITE_2; + goto saveStateAndReturn; + } + } + if (s->meta_block_remaining_len <= 0) { + /* Next metablock, if any */ + s->state = BROTLI_STATE_METABLOCK_DONE; + goto saveStateAndReturn; + } else { + goto CommandBegin; + } + +saveStateAndReturn: + s->pos = pos; + s->loop_counter = i; + return result; +} + +#undef BROTLI_SAFE + +static BROTLI_NOINLINE BrotliResult ProcessCommands(BrotliState* s) { + return ProcessCommandsInternal(0, s); +} + +static BROTLI_NOINLINE BrotliResult SafeProcessCommands(BrotliState* s) { + return ProcessCommandsInternal(1, s); +} + BrotliResult BrotliDecompressBuffer(size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size, uint8_t* decoded_buffer) { - BrotliMemInput memin; - BrotliInput in = BrotliInitMemInput(encoded_buffer, encoded_size, &memin); - BrotliMemOutput mout; - BrotliOutput out = BrotliInitMemOutput(decoded_buffer, *decoded_size, &mout); - BrotliResult success = BrotliDecompress(in, out); - *decoded_size = mout.pos; - return success; + BrotliState s; + BrotliResult result; + size_t total_out = 0; + size_t available_in = encoded_size; + const uint8_t* next_in = encoded_buffer; + size_t available_out = *decoded_size; + uint8_t* next_out = decoded_buffer; + BrotliStateInit(&s); + result = BrotliDecompressStream(&available_in, &next_in, &available_out, + &next_out, &total_out, &s); + *decoded_size = total_out; + BrotliStateCleanup(&s); + if (result != BROTLI_RESULT_SUCCESS) { + result = BROTLI_RESULT_ERROR; + } + return result; } BrotliResult BrotliDecompress(BrotliInput input, BrotliOutput output) { @@ -999,61 +1814,184 @@ uint8_t** next_out, size_t* total_out, BrotliState* s) { - BrotliMemInput memin; - BrotliInput in = BrotliInitMemInput(*next_in, *available_in, &memin); - BrotliMemOutput memout; - BrotliOutput out = BrotliInitMemOutput(*next_out, *available_out, &memout); - BrotliResult result = BrotliDecompressStreaming(in, out, finish, s); - /* The current implementation reads everything, so 0 bytes are available. */ - *next_in += memin.pos; - *available_in -= memin.pos; - /* Update the output position to where we write next. */ - *next_out += memout.pos; - *available_out -= memout.pos; - *total_out += memout.pos; + BrotliResult result = BrotliDecompressStream(available_in, next_in, + available_out, next_out, total_out, s); + if (finish && result == BROTLI_RESULT_NEEDS_MORE_INPUT) { + result = BROTLI_FAILURE(); + } return result; } BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, int finish, BrotliState* s) { - uint8_t context; - int pos = s->pos; - int i = s->loop_counter; - uint32_t j; + const size_t kBufferSize = 65536; + BrotliResult result; + uint8_t* input_buffer; + uint8_t* output_buffer; + size_t avail_in; + const uint8_t* next_in; + size_t total_out; + + if (s->legacy_input_buffer == 0) { + s->legacy_input_buffer = (uint8_t*)malloc(kBufferSize); + } + if (s->legacy_output_buffer == 0) { + s->legacy_output_buffer = (uint8_t*)malloc(kBufferSize); + } + if (s->legacy_input_buffer == 0 || s->legacy_output_buffer == 0) { + return BROTLI_FAILURE(); + } + input_buffer = s->legacy_input_buffer; + output_buffer = s->legacy_output_buffer; + + /* Push remaining output. */ + if (s->legacy_output_len > s->legacy_output_pos) { + size_t to_write = s->legacy_output_len - s->legacy_output_pos; + int num_written = BrotliWrite( + output, output_buffer + s->legacy_output_pos, to_write); + if (num_written < 0) { + return BROTLI_FAILURE(); + } + s->legacy_output_pos += (size_t)num_written; + if ((size_t)num_written < to_write) { + return BROTLI_RESULT_NEEDS_MORE_OUTPUT; + } + } + s->legacy_output_pos = 0; + + avail_in = s->legacy_input_len - s->legacy_input_pos; + next_in = input_buffer + s->legacy_input_pos; + + while (1) { + size_t to_write; + int num_written; + size_t avail_out = kBufferSize; + uint8_t* next_out = output_buffer; + result = BrotliDecompressStream(&avail_in, &next_in, + &avail_out, &next_out, &total_out, s); + s->legacy_input_pos = (size_t)(next_out - input_buffer); + to_write = (size_t)(next_out - output_buffer); + num_written = BrotliWrite(output, output_buffer, to_write); + if (num_written < 0) { + return BROTLI_FAILURE(); + } + if ((size_t)num_written < to_write) { + s->legacy_output_len = to_write; + s->legacy_output_pos = (size_t)num_written; + return BROTLI_RESULT_NEEDS_MORE_OUTPUT; + } + if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) { + int num_read = BrotliRead(input, input_buffer, kBufferSize); + if (num_read < 0 || (num_read == 0 && finish)) { + return BROTLI_FAILURE(); + } + if (num_read == 0) { + s->legacy_input_len = 0; + s->legacy_input_pos = 0; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + avail_in = (size_t)num_read; + next_in = input_buffer; + s->legacy_input_len = avail_in; + s->legacy_input_pos = 0; + } else if (result != BROTLI_RESULT_NEEDS_MORE_OUTPUT) { + /* Success or failure. */ + return result; + } + } +} + +/* Invariant: input stream is never overconsumed: + * invalid input implies that the whole stream is invalid -> any amount of + input could be read and discarded + * when result is "needs more input", then at leat one more byte is REQUIRED + to complete decoding; all input data MUST be consumed by decoder, so + client could swap the input buffer + * when result is "needs more output" decoder MUST ensure that it doesn't + hold more than 7 bits in bit reader; this saves client from swapping input + buffer ahead of time + * when result is "success" decoder MUST return all unused data back to input + buffer; this is possible because the invariant is hold on enter +*/ +BrotliResult BrotliDecompressStream(size_t* available_in, + const uint8_t** next_in, size_t* available_out, uint8_t** next_out, + size_t* total_out, BrotliState* s) { BrotliResult result = BROTLI_RESULT_SUCCESS; BrotliBitReader* br = &s->br; - int initial_remaining_len; - int bytes_copied; - uint8_t *copy_src; - uint8_t *copy_dst; - /* We need the slack region for the following reasons: - - doing up to two 16-byte copies for fast backward copying - - transforms - - flushing the input s->ringbuffer when decoding uncompressed blocks */ - s->br.input_ = input; + if (s->buffer_length == 0) { /* Just connect bit reader to input stream. */ + br->avail_in = *available_in; + br->next_in = *next_in; + } else { + /* At least one byte of input is required. More than one byte of input may + be required to complete the transaction -> reading more data must be + done in a loop -> do it in a main loop. */ + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + br->next_in = &s->buffer.u8[0]; + } /* State machine */ for (;;) { - if (result != BROTLI_RESULT_SUCCESS) { + if (result != BROTLI_RESULT_SUCCESS) { /* Error | needs more input/output */ if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) { - if (BrotliReadInput(br, finish)) { - result = BROTLI_RESULT_SUCCESS; - continue; + if (s->ringbuffer != 0) { /* Proactively push output. */ + WriteRingBuffer(available_out, next_out, total_out, s); } - if (finish) { - BROTLI_LOG(("Unexpected end of input. State: %d\n", s->state)); - result = BROTLI_FAILURE(); + if (s->buffer_length != 0) { /* Used with internal buffer. */ + if (br->avail_in == 0) { /* Successfully finished read transaction. */ + /* Accamulator contains less than 8 bits, because internal buffer + is expanded byte-by-byte until it is enough to complete read. */ + s->buffer_length = 0; + /* Switch to input stream and restart. */ + result = BROTLI_RESULT_SUCCESS; + br->avail_in = *available_in; + br->next_in = *next_in; + continue; + } else if (*available_in != 0) { + /* Not enough data in buffer, but can take one more byte from + input stream. */ + result = BROTLI_RESULT_SUCCESS; + s->buffer.u8[s->buffer_length] = **next_in; + s->buffer_length++; + br->avail_in = s->buffer_length; + (*next_in)++; + (*available_in)--; + /* Retry with more data in buffer. */ + continue; + } + /* Can't finish reading and no more input.*/ + break; + } else { /* Input stream doesn't contain enough input. */ + /* Copy tail to internal buffer and return. */ + *next_in = br->next_in; + *available_in = br->avail_in; + while (*available_in) { + s->buffer.u8[s->buffer_length] = **next_in; + s->buffer_length++; + (*next_in)++; + (*available_in)--; + } + break; } + /* Unreachable. */ } - break; /* Fail, or partial data. */ + + /* Fail or needs more output. */ + + if (s->buffer_length != 0) { + /* Just consumed the buffered input and produced some output. Otherwise + it would result in "needs more input". Reset internal buffer.*/ + s->buffer_length = 0; + } else { + /* Using input stream in last iteration. When decoder switches to input + stream it has less than 8 bits in accamulator, so it is safe to + return unused accamulator bits there. */ + BrotliBitReaderUnload(br); + *available_in = br->avail_in; + *next_in = br->next_in; + } + break; } switch (s->state) { case BROTLI_STATE_UNINITED: - pos = 0; - BrotliInitBitReader(br, input); - - s->state = BROTLI_STATE_BITREADER_WARMUP; - /* No break, continue to next state */ - case BROTLI_STATE_BITREADER_WARMUP: /* Prepare to the first read. */ if (!BrotliWarmupBitReader(br)) { result = BROTLI_RESULT_NEEDS_MORE_INPUT; @@ -1085,13 +2023,12 @@ /* No break, continue to next state */ case BROTLI_STATE_METABLOCK_BEGIN: BrotliStateMetablockBegin(s); - BROTLI_LOG_UINT(pos); + BROTLI_LOG_UINT(s->pos); s->state = BROTLI_STATE_METABLOCK_HEADER; /* No break, continue to next state */ case BROTLI_STATE_METABLOCK_HEADER: result = DecodeMetaBlockLength(s, br); /* Reads 2 - 31 bits. */ if (result != BROTLI_RESULT_SUCCESS) { - i = s->loop_counter; /* Has been updated in DecodeMetaBlockLength. */ break; } BROTLI_LOG_UINT(s->is_last_metablock); @@ -1122,20 +2059,20 @@ s->state = BROTLI_STATE_UNCOMPRESSED; break; } - i = 0; + s->loop_counter = 0; s->state = BROTLI_STATE_HUFFMAN_CODE_0; break; - case BROTLI_STATE_UNCOMPRESSED: - initial_remaining_len = s->meta_block_remaining_len; - /* pos is given as argument since s->pos is only updated at the end. */ - result = CopyUncompressedBlockToOutput(output, pos, s); - bytes_copied = initial_remaining_len - s->meta_block_remaining_len; - pos = (pos + bytes_copied) & s->ringbuffer_mask; + case BROTLI_STATE_UNCOMPRESSED: { + int bytes_copied = s->meta_block_remaining_len; + result = CopyUncompressedBlockToOutput( + available_out, next_out, total_out, s); + bytes_copied -= s->meta_block_remaining_len; if (result != BROTLI_RESULT_SUCCESS) { break; } s->state = BROTLI_STATE_METABLOCK_DONE; break; + } case BROTLI_STATE_METADATA: for (; s->meta_block_remaining_len > 0; --s->meta_block_remaining_len) { uint32_t bits; @@ -1150,63 +2087,61 @@ } break; case BROTLI_STATE_HUFFMAN_CODE_0: - if (i >= 3) { - s->state = BROTLI_STATE_CONTEXT_MODES; + if (s->loop_counter >= 3) { + s->state = BROTLI_STATE_METABLOCK_HEADER_2; break; } /* Reads 1..11 bits. */ - result = DecodeVarLenUint8(s, br, &s->num_block_types[i]); + result = DecodeVarLenUint8(s, br, &s->num_block_types[s->loop_counter]); if (result != BROTLI_RESULT_SUCCESS) { break; } - s->num_block_types[i]++; - BROTLI_LOG_UINT(s->num_block_types[i]); + s->num_block_types[s->loop_counter]++; + BROTLI_LOG_UINT(s->num_block_types[s->loop_counter]); + if (s->num_block_types[s->loop_counter] < 2) { + s->loop_counter++; + break; + } s->state = BROTLI_STATE_HUFFMAN_CODE_1; /* No break, continue to next state */ - case BROTLI_STATE_HUFFMAN_CODE_1: - if (!BrotliWarmupBitReader(br)) { - result = BROTLI_RESULT_NEEDS_MORE_INPUT; - break; - } - if (s->num_block_types[i] >= 2) { - result = ReadHuffmanCode(s->num_block_types[i] + 2, - &s->block_type_trees[i * BROTLI_HUFFMAN_MAX_TABLE_SIZE], - NULL, s); - if (result != BROTLI_RESULT_SUCCESS) break; - s->state = BROTLI_STATE_HUFFMAN_CODE_2; - } else { - i++; - s->state = BROTLI_STATE_HUFFMAN_CODE_0; - break; - } + case BROTLI_STATE_HUFFMAN_CODE_1: { + int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_TABLE_SIZE; + result = ReadHuffmanCode(s->num_block_types[s->loop_counter] + 2, + &s->block_type_trees[tree_offset], NULL, s); + if (result != BROTLI_RESULT_SUCCESS) break; + s->state = BROTLI_STATE_HUFFMAN_CODE_2; /* No break, continue to next state */ - case BROTLI_STATE_HUFFMAN_CODE_2: + } + case BROTLI_STATE_HUFFMAN_CODE_2: { + int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_TABLE_SIZE; result = ReadHuffmanCode(kNumBlockLengthCodes, - &s->block_len_trees[i * BROTLI_HUFFMAN_MAX_TABLE_SIZE], - NULL, s); + &s->block_len_trees[tree_offset], NULL, s); if (result != BROTLI_RESULT_SUCCESS) break; s->state = BROTLI_STATE_HUFFMAN_CODE_3; /* No break, continue to next state */ - case BROTLI_STATE_HUFFMAN_CODE_3: - if (!BrotliCheckInputAmount(br, 8)) { + } + case BROTLI_STATE_HUFFMAN_CODE_3: { + int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_TABLE_SIZE; + if (!SafeReadBlockLength(s, &s->block_length[s->loop_counter], + &s->block_len_trees[tree_offset], br)) { result = BROTLI_RESULT_NEEDS_MORE_INPUT; break; } - s->block_length[i] = ReadBlockLength( /* Reads 3..39 bits. */ - &s->block_len_trees[i * BROTLI_HUFFMAN_MAX_TABLE_SIZE], br); - BROTLI_LOG_UINT(s->block_length[i]); - i++; + BROTLI_LOG_UINT(s->block_length[s->loop_counter]); + s->loop_counter++; s->state = BROTLI_STATE_HUFFMAN_CODE_0; break; - case BROTLI_STATE_CONTEXT_MODES: - /* We need up to 256 * 2 + 6 bits, this fits in 128 bytes. */ - if (!BrotliCheckInputAmount(br, 128)) { + } + case BROTLI_STATE_METABLOCK_HEADER_2: { + uint32_t bits; + if (!BrotliSafeReadBits(br, 6, &bits)) { result = BROTLI_RESULT_NEEDS_MORE_INPUT; break; } - s->distance_postfix_bits = BrotliReadBits(br, 2); + s->distance_postfix_bits = bits & BitMask(2); + bits >>= 2; s->num_direct_distance_codes = NUM_DISTANCE_SHORT_CODES + - (BrotliReadBits(br, 4) << s->distance_postfix_bits); + (bits << s->distance_postfix_bits); BROTLI_LOG_UINT(s->num_direct_distance_codes); BROTLI_LOG_UINT(s->distance_postfix_bits); s->distance_postfix_mask = (int)BitMask(s->distance_postfix_bits); @@ -1215,13 +2150,19 @@ result = BROTLI_FAILURE(); break; } - for (j = 0; j < s->num_block_types[0]; ++j) { - s->context_modes[j] = (uint8_t)(BrotliReadBits(br, 2) << 1); - BROTLI_LOG_ARRAY_INDEX(s->context_modes, j); + s->loop_counter = 0; + s->state = BROTLI_STATE_CONTEXT_MODES; + /* No break, continue to next state */ + } + case BROTLI_STATE_CONTEXT_MODES: + result = ReadContextModes(s); + if (result != BROTLI_RESULT_SUCCESS) { + break; } s->state = BROTLI_STATE_CONTEXT_MAP_1; /* No break, continue to next state */ - case BROTLI_STATE_CONTEXT_MAP_1: + case BROTLI_STATE_CONTEXT_MAP_1: { + uint32_t j; result = DecodeContextMap(s->num_block_types[0] << kLiteralContextBits, &s->num_literal_htrees, &s->context_map, s); if (result != BROTLI_RESULT_SUCCESS) { @@ -1236,6 +2177,7 @@ } s->state = BROTLI_STATE_CONTEXT_MAP_2; /* No break, continue to next state */ + } case BROTLI_STATE_CONTEXT_MAP_2: { uint32_t num_distance_codes = @@ -1259,13 +2201,13 @@ return BROTLI_FAILURE(); } } - i = 0; + s->loop_counter = 0; s->state = BROTLI_STATE_TREE_GROUP; /* No break, continue to next state */ case BROTLI_STATE_TREE_GROUP: { HuffmanTreeGroup* hgroup = NULL; - switch (i) { + switch (s->loop_counter) { case 0: hgroup = &s->literal_hgroup; break; @@ -1279,8 +2221,8 @@ result = HuffmanTreeGroupDecode(hgroup, s); } if (result != BROTLI_RESULT_SUCCESS) break; - i++; - if (i >= 3) { + s->loop_counter++; + if (s->loop_counter >= 3) { uint8_t context_mode = s->context_modes[s->block_type_rb[1]]; s->context_map_slice = s->context_map; s->dist_context_map_slice = s->dist_context_map; @@ -1294,377 +2236,43 @@ } break; case BROTLI_STATE_COMMAND_BEGIN: - if (s->meta_block_remaining_len <= 0) { - /* Next metablock, if any */ - s->state = BROTLI_STATE_METABLOCK_DONE; - break; - } - /* Decoding of Brotli commands is the inner loop, jumping with goto makes it - 3% faster */ - CommandBegin: - if (!BrotliCheckInputAmount(br, 32)) { - s->state = BROTLI_STATE_COMMAND_BEGIN; - result = BROTLI_RESULT_NEEDS_MORE_INPUT; - break; - } - /* Read the insert/copy length in the command */ - if (s->block_length[1] == 0) { - /* Block switch for insert/copy length. Reads 0..15 bits. */ - DecodeBlockType(s->num_block_types[1], - s->block_type_trees, 1, - s->block_type_rb, br); - s->htree_command = s->insert_copy_hgroup.htrees[s->block_type_rb[3]]; - s->block_length[1] = ReadBlockLength( /* Reads 3..39 bits. */ - &s->block_len_trees[BROTLI_HUFFMAN_MAX_TABLE_SIZE], br); - } - { - uint32_t cmd_code = ReadSymbol(s->htree_command, br); - int insert_len_extra = 0; - CmdLutElement v; - --s->block_length[1]; - v = kCmdLut[cmd_code]; - s->distance_code = v.distance_code; - s->distance_context = v.context; - s->dist_htree_index = s->dist_context_map_slice[s->distance_context]; - i = v.insert_len_offset; - if (PREDICT_FALSE(v.insert_len_extra_bits != 0)) { - insert_len_extra = (int)BrotliReadBits(br, v.insert_len_extra_bits); - } - s->copy_length = (int)BrotliReadBits(br, v.copy_len_extra_bits) + - v.copy_len_offset; - i += insert_len_extra; - } - BROTLI_LOG_UINT(i); - BROTLI_LOG_UINT(s->copy_length); - BROTLI_LOG_UINT(s->distance_code); - if (i == 0) { - goto postDecodeLiterals; - } - s->meta_block_remaining_len -= i; - /* No break, go to next state */ case BROTLI_STATE_COMMAND_INNER: - /* Read the literals in the command */ - if (s->trivial_literal_context) { - uint32_t bits; - uint32_t value; - PreloadSymbol(s->literal_htree, br, &bits, &value); - do { - if (!BrotliCheckInputAmount(br, 64)) { - s->state = BROTLI_STATE_COMMAND_INNER; - result = BROTLI_RESULT_NEEDS_MORE_INPUT; - break; - } - if (PREDICT_FALSE(s->block_length[0] == 0)) { - /* Block switch for literals */ - DecodeBlockTypeWithContext(s, br); - PreloadSymbol(s->literal_htree, br, &bits, &value); - } - s->ringbuffer[pos] = - (uint8_t)ReadPreloadedSymbol(s->literal_htree, - br, &bits, &value); - --s->block_length[0]; - BROTLI_LOG_UINT(s->literal_htree_index); - BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos); - ++pos; - if (PREDICT_FALSE(pos == s->ringbuffer_size)) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->state = BROTLI_STATE_COMMAND_INNER_WRITE; - --i; - goto innerWrite; - } - } while (--i != 0); - } else { - uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask]; - uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask]; - do { - const HuffmanCode* hc; - if (!BrotliCheckInputAmount(br, 64)) { - s->state = BROTLI_STATE_COMMAND_INNER; - result = BROTLI_RESULT_NEEDS_MORE_INPUT; - break; - } - if (PREDICT_FALSE(s->block_length[0] == 0)) { - /* Block switch for literals */ - DecodeBlockTypeWithContext(s, br); - } - context = s->context_lookup1[p1] | s->context_lookup2[p2]; - BROTLI_LOG_UINT(context); - hc = s->literal_hgroup.htrees[s->context_map_slice[context]]; - --s->block_length[0]; - p2 = p1; - p1 = (uint8_t)ReadSymbol(hc, br); - s->ringbuffer[pos] = p1; - BROTLI_LOG_UINT(s->context_map_slice[context]); - BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask); - ++pos; - if (PREDICT_FALSE(pos == s->ringbuffer_size)) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->state = BROTLI_STATE_COMMAND_INNER_WRITE; - --i; - goto innerWrite; - } - } while (--i != 0); - } - if (result != BROTLI_RESULT_SUCCESS) break; - if (s->meta_block_remaining_len <= 0) { - s->state = BROTLI_STATE_METABLOCK_DONE; - break; - } -postDecodeLiterals: - if (s->distance_code >= 0) { - --s->dist_rb_idx; - s->distance_code = s->dist_rb[s->dist_rb_idx & 3]; - goto postReadDistance; /* We already have the implicit distance */ - } - /* Read distance code in the command, unless it was implicitly zero. */ - BROTLI_DCHECK(s->distance_code < 0); - if (s->block_length[2] == 0) { - /* Block switch for distance codes */ - uint32_t dist_context_offset; - DecodeBlockType(s->num_block_types[2], - s->block_type_trees, 2, - s->block_type_rb, br); /* Reads 0..15 bits. */ - s->block_length[2] = ReadBlockLength( /* Reads 3..39 bits. */ - &s->block_len_trees[2 * BROTLI_HUFFMAN_MAX_TABLE_SIZE], br); - dist_context_offset = s->block_type_rb[5] << kDistanceContextBits; - s->dist_context_map_slice = - s->dist_context_map + dist_context_offset; - s->dist_htree_index = s->dist_context_map_slice[s->distance_context]; - } - --s->block_length[2]; - s->distance_code = (int)ReadSymbol( - s->distance_hgroup.htrees[s->dist_htree_index], br); - /* Convert the distance code to the actual distance by possibly */ - /* looking up past distances from the s->ringbuffer. */ - if ((s->distance_code & ~0xf) == 0) { - if (s->distance_code == 0) { - --s->dist_rb_idx; - s->distance_code = s->dist_rb[s->dist_rb_idx & 3]; - } else { - int distance_code = s->distance_code << 1; - /* kDistanceShortCodeIndexOffset has 2-bit values from LSB: */ - /* 3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 */ - const uint32_t kDistanceShortCodeIndexOffset = 0xaaafff1b; - /* kDistanceShortCodeValueOffset has 2-bit values from LSB: */ - /* 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3 */ - const uint32_t kDistanceShortCodeValueOffset = 0xfa5fa500; - int v = (s->dist_rb_idx + - (int)(kDistanceShortCodeIndexOffset >> distance_code)) & 0x3; - s->distance_code = s->dist_rb[v]; - v = (int)(kDistanceShortCodeValueOffset >> distance_code) & 0x3; - if ((distance_code & 0x3) != 0) { - s->distance_code += v; - } else { - s->distance_code -= v; - if (s->distance_code <= 0) { - /* A huge distance will cause a BROTLI_FAILURE() soon. */ - /* This is a little faster than failing here. */ - s->distance_code = 0x0fffffff; - } - } - } - } else { - int distval = s->distance_code - (int)s->num_direct_distance_codes; - if (distval >= 0) { - uint32_t nbits; - int postfix; - int offset; - if (s->distance_postfix_bits == 0) { - nbits = ((uint32_t)distval >> 1) + 1; - offset = ((2 + (distval & 1)) << nbits) - 4; - s->distance_code = (int)s->num_direct_distance_codes + - offset + (int)BrotliReadBits(br, nbits); - } else { - postfix = distval & s->distance_postfix_mask; - distval >>= s->distance_postfix_bits; - nbits = ((uint32_t)distval >> 1) + 1; - offset = ((2 + (distval & 1)) << nbits) - 4; - s->distance_code = (int)s->num_direct_distance_codes + - ((offset + (int)BrotliReadBits(br, nbits)) << - s->distance_postfix_bits) + postfix; - } - } - s->distance_code = s->distance_code - NUM_DISTANCE_SHORT_CODES + 1; - } -postReadDistance: - BROTLI_LOG_UINT(s->distance_code); - if (s->max_distance != s->max_backward_distance) { - if (pos < s->max_backward_distance_minus_custom_dict_size) { - s->max_distance = pos + s->custom_dict_size; - } else { - s->max_distance = s->max_backward_distance; - } - } - i = s->copy_length; - /* Apply copy of LZ77 back-reference, or static dictionary reference if - the distance is larger than the max LZ77 distance */ - if (s->distance_code > s->max_distance) { - if (i >= kBrotliMinDictionaryWordLength && - i <= kBrotliMaxDictionaryWordLength) { - int offset = kBrotliDictionaryOffsetsByLength[i]; - int word_id = s->distance_code - s->max_distance - 1; - uint32_t shift = kBrotliDictionarySizeBitsByLength[i]; - int mask = (int)BitMask(shift); - int word_idx = word_id & mask; - int transform_idx = word_id >> shift; - offset += word_idx * i; - if (transform_idx < kNumTransforms) { - const uint8_t* word = &kBrotliDictionary[offset]; - int len = i; - if (transform_idx == 0) { - memcpy(&s->ringbuffer[pos], word, (size_t)len); - } else { - len = TransformDictionaryWord( - &s->ringbuffer[pos], word, len, transform_idx); - } - pos += len; - s->meta_block_remaining_len -= len; - if (pos >= s->ringbuffer_size) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->state = BROTLI_STATE_COMMAND_POST_WRITE_1; - break; - } - } else { - BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " - "len: %d bytes left: %d\n", - pos, s->distance_code, i, - s->meta_block_remaining_len)); - result = BROTLI_FAILURE(); - break; - } - } else { - BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " - "len: %d bytes left: %d\n", pos, s->distance_code, i, - s->meta_block_remaining_len)); - result = BROTLI_FAILURE(); - break; - } - } else { - const uint8_t *ringbuffer_end_minus_copy_length = - s->ringbuffer_end - i; - copy_src = &s->ringbuffer[(pos - s->distance_code) & - s->ringbuffer_mask]; - copy_dst = &s->ringbuffer[pos]; - /* update the recent distances cache */ - s->dist_rb[s->dist_rb_idx & 3] = s->distance_code; - ++s->dist_rb_idx; - s->meta_block_remaining_len -= i; - if (PREDICT_FALSE(s->meta_block_remaining_len < 0)) { - BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " - "len: %d bytes left: %d\n", pos, s->distance_code, i, - s->meta_block_remaining_len)); - result = BROTLI_FAILURE(); - break; - } - /* There is 128+ bytes of slack in the ringbuffer allocation. - Also, we have 16 short codes, that make these 16 bytes irrelevant - in the ringbuffer. Let's copy over them as a first guess. - */ - memmove16(copy_dst, copy_src); - /* Now check if the copy extends over the ringbuffer end, - or if the copy overlaps with itself, if yes, do wrap-copy. */ - if (copy_src < copy_dst) { - if (copy_dst >= ringbuffer_end_minus_copy_length) { - goto postWrapCopy; - } - if (copy_src + i > copy_dst) { - goto postSelfintersecting; - } - } else { - if (copy_src >= ringbuffer_end_minus_copy_length) { - goto postWrapCopy; - } - if (copy_dst + i > copy_src) { - goto postSelfintersecting; - } - } - pos += i; - if (i > 16) { - if (i > 32) { - memcpy(copy_dst + 16, copy_src + 16, (size_t)(i - 16)); - } else { - /* This branch covers about 45% cases. - Fixed size short copy allows more compiler optimizations. */ - memmove16(copy_dst + 16, copy_src + 16); - } - } - } - if (s->meta_block_remaining_len <= 0) { - /* Next metablock, if any */ - s->state = BROTLI_STATE_METABLOCK_DONE; - break; - } else { - goto CommandBegin; - } - postSelfintersecting: - while (--i >= 0) { - s->ringbuffer[pos] = - s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask]; - ++pos; - } - if (s->meta_block_remaining_len <= 0) { - /* Next metablock, if any */ - s->state = BROTLI_STATE_METABLOCK_DONE; - break; - } else { - goto CommandBegin; - } - postWrapCopy: - s->state = BROTLI_STATE_COMMAND_POST_WRAP_COPY; - /* No break, go to next state */ + case BROTLI_STATE_COMMAND_POST_DECODE_LITERALS: case BROTLI_STATE_COMMAND_POST_WRAP_COPY: - while (--i >= 0) { - s->ringbuffer[pos] = - s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask]; - ++pos; - if (pos == s->ringbuffer_size) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->state = BROTLI_STATE_COMMAND_POST_WRITE_2; - break; - } - } - if (s->state == BROTLI_STATE_COMMAND_POST_WRAP_COPY) { - if (s->meta_block_remaining_len <= 0) { - /* Next metablock, if any */ - s->state = BROTLI_STATE_METABLOCK_DONE; - break; - } else { - goto CommandBegin; - } + result = ProcessCommands(s); + if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) { + result = SafeProcessCommands(s); } break; case BROTLI_STATE_COMMAND_INNER_WRITE: case BROTLI_STATE_COMMAND_POST_WRITE_1: case BROTLI_STATE_COMMAND_POST_WRITE_2: -innerWrite: - result = WriteRingBuffer(output, s); + result = WriteRingBuffer(available_out, next_out, total_out, s); if (result != BROTLI_RESULT_SUCCESS) { break; } - pos -= s->ringbuffer_size; + s->pos -= s->ringbuffer_size; + s->rb_roundtrips++; s->max_distance = s->max_backward_distance; if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_1) { - memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)pos); + memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)s->pos); if (s->meta_block_remaining_len <= 0) { /* Next metablock, if any */ s->state = BROTLI_STATE_METABLOCK_DONE; - break; } else { - goto CommandBegin; + s->state = BROTLI_STATE_COMMAND_BEGIN; } + break; } else if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_2) { s->state = BROTLI_STATE_COMMAND_POST_WRAP_COPY; } else { /* BROTLI_STATE_COMMAND_INNER_WRITE */ - if (i == 0) { + if (s->loop_counter == 0) { if (s->meta_block_remaining_len <= 0) { s->state = BROTLI_STATE_METABLOCK_DONE; - break; + } else { + s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS; } - goto postDecodeLiterals; + break; } s->state = BROTLI_STATE_COMMAND_INNER; } @@ -1675,30 +2283,26 @@ s->state = BROTLI_STATE_METABLOCK_BEGIN; break; } - s->to_write = pos; - s->partially_written = 0; + if (!BrotliJumpToByteBoundary(br)) { + result = BROTLI_FAILURE(); + } + if (s->buffer_length == 0) { + BrotliBitReaderUnload(br); + *available_in = br->avail_in; + *next_in = br->next_in; + } s->state = BROTLI_STATE_DONE; /* No break, continue to next state */ case BROTLI_STATE_DONE: if (s->ringbuffer != 0) { - result = WriteRingBuffer(output, s); + result = WriteRingBuffer(available_out, next_out, total_out, s); if (result != BROTLI_RESULT_SUCCESS) { break; } } - if (!BrotliJumpToByteBoundary(br)) { - result = BROTLI_FAILURE(); - } - if (!BrotliIsBitReaderOK(br)) { - /* The brotli input stream was too small, does not follow the spec. - NOTE: larger input is allowed, smaller not. */ - result = BROTLI_FAILURE(); - } return result; } } - s->pos = pos; - s->loop_counter = i; return result; }
diff --git a/third_party/brotli/dec/decode.h b/third_party/brotli/dec/decode.h index cd3d124..78a156e 100644 --- a/third_party/brotli/dec/decode.h +++ b/third_party/brotli/dec/decode.h
@@ -62,9 +62,6 @@ /* Decompresses the data in encoded_buffer into decoded_buffer, and sets */ /* *decoded_size to the decompressed length. */ -/* Returns 0 if there was either a bit stream error or memory allocation */ -/* error, and 1 otherwise. */ -/* If decoded size is zero, returns 1 and keeps decoded_buffer unchanged. */ BrotliResult BrotliDecompressBuffer(size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size, @@ -72,6 +69,7 @@ /* Same as above, but uses the specified input and output callbacks instead */ /* of reading from and writing to pre-allocated memory buffers. */ +/* DEPRECATED */ BrotliResult BrotliDecompress(BrotliInput input, BrotliOutput output); /* Same as above, but supports the caller to call the decoder repeatedly with @@ -99,6 +97,7 @@ it returning a smaller value than the amount of bytes to write always results in an error. */ +/* DEPRECATED */ BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, int finish, BrotliState* s); @@ -129,6 +128,7 @@ *available_out yourself before a next call, e.g. to point to a new larger buffer. */ +/* DEPRECATED */ BrotliResult BrotliDecompressBufferStreaming(size_t* available_in, const uint8_t** next_in, int finish, @@ -137,6 +137,13 @@ size_t* total_out, BrotliState* s); +BrotliResult BrotliDecompressStream(size_t* available_in, + const uint8_t** next_in, + size_t* available_out, + uint8_t** next_out, + size_t* total_out, + BrotliState* s); + /* Fills the new state with a dictionary for LZ77, warming up the ringbuffer, e.g. for custom static dictionaries for data formats. Not to be confused with the built-in transformable dictionary of Brotli. @@ -151,10 +158,6 @@ size_t size, const uint8_t* dict, BrotliState* s); -/* Escalate internal functions visibility; for testing purposes only. */ -void InverseMoveToFrontTransformForTesting( - uint8_t* v, uint32_t l, BrotliState* s); - #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif
diff --git a/third_party/brotli/dec/huffman.c b/third_party/brotli/dec/huffman.c index d4ccbd9..0628c36 100644 --- a/third_party/brotli/dec/huffman.c +++ b/third_party/brotli/dec/huffman.c
@@ -377,6 +377,7 @@ void BrotliHuffmanTreeGroupRelease(HuffmanTreeGroup* group) { BROTLI_FREE(group->codes); + group->htrees = NULL; } #if defined(__cplusplus) || defined(c_plusplus)
diff --git a/third_party/brotli/dec/port.h b/third_party/brotli/dec/port.h index bf33242b..f8fc4a8 100644 --- a/third_party/brotli/dec/port.h +++ b/third_party/brotli/dec/port.h
@@ -19,8 +19,10 @@ * BROTLI_BUILD_32_BIT disables 64-bit optimizations * BROTLI_BUILD_64_BIT forces to use 64-bit optimizations * BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations - * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations * BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations + * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations + * BROTLI_BUILD_MODERN_COMPILER forces to use modern compilers built-ins, + features and attributes * BROTLI_BUILD_PORTABLE disables dangerous optimizations, like unaligned read and overlapping memcpy; this reduces decompression speed by 5% * BROTLI_DEBUG dumps file name and line number when decoder detects stream @@ -46,6 +48,59 @@ #define __has_feature(x) 0 #endif +#if defined(__sparc) +#define BROTLI_TARGET_SPARC +#endif + +#if defined(__arm__) || defined(__thumb__) || \ + defined(_M_ARM) || defined(_M_ARMT) +#define BROTLI_TARGET_ARM +#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) || \ + (defined(M_ARM) && (M_ARM >= 7)) +#define BROTLI_TARGET_ARMV7 +#endif /* ARMv7 */ +#if defined(__aarch64__) +#define BROTLI_TARGET_ARMV8 +#endif /* ARMv8 */ +#endif /* ARM */ + +#if defined(__x86_64__) || defined(_M_X64) +#define BROTLI_TARGET_X64 +#endif + +#if defined(__PPC64__) +#define BROTLI_TARGET_POWERPC64 +#endif + +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +#define BROTLI_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#else +#define BROTLI_GCC_VERSION 0 +#endif + +#if defined(__ICC) +#define BROTLI_ICC_VERSION __ICC +#else +#define BROTLI_ICC_VERSION 0 +#endif + +#if defined(BROTLI_BUILD_MODERN_COMPILER) +#define BROTLI_MODERN_COMPILER 1 +#elif (BROTLI_GCC_VERSION > 300) || (BROTLI_ICC_VERSION >= 1600) +#define BROTLI_MODERN_COMPILER 1 +#else +#define BROTLI_MODERN_COMPILER 0 +#endif + +/* SPARC and ARMv6 don't support unaligned read. + Choose portable build for them. */ +#if !defined(BROTLI_BUILD_PORTABLE) +#if defined(BROTLI_TARGET_SPARC) || \ + (defined(BROTLI_TARGET_ARM) && !defined(BROTLI_TARGET_ARMV7)) +#define BROTLI_BUILD_PORTABLE +#endif /* SPARK or ARMv6 */ +#endif /* portable build */ + #ifdef BROTLI_BUILD_PORTABLE #define BROTLI_ALIGNED_READ 1 #define BROTLI_SAFE_MEMMOVE 1 @@ -73,8 +128,7 @@ } */ -#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || \ - (defined(__llvm__) && __has_builtin(__builtin_expect)) +#if BROTLI_MODERN_COMPILER || __has_builtin(__builtin_expect) #define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) #define PREDICT_FALSE(x) (__builtin_expect(x, 0)) #else @@ -83,15 +137,13 @@ #endif /* IS_CONSTANT macros returns true for compile-time constant expressions. */ -#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) || \ - (defined(__llvm__) && __has_builtin(__builtin_constant_p)) +#if BROTLI_MODERN_COMPILER || __has_builtin(__builtin_constant_p) #define IS_CONSTANT(x) __builtin_constant_p(x) #else #define IS_CONSTANT(x) 0 #endif -#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) || \ - (defined(__llvm__) && __has_attribute(always_inline)) +#if BROTLI_MODERN_COMPILER || __has_attribute(always_inline) #define ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline)) #else #define ATTRIBUTE_ALWAYS_INLINE @@ -118,8 +170,8 @@ #define BROTLI_64_BITS 1 #elif defined(BROTLI_BUILD_32_BIT) #define BROTLI_64_BITS 0 -#elif defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || \ - defined(__PPC64__) +#elif defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8) || \ + defined(BROTLI_TARGET_POWERPC64) #define BROTLI_64_BITS 1 #else #define BROTLI_64_BITS 0 @@ -150,8 +202,7 @@ #define BROTLI_LITTLE_ENDIAN 0 #endif -#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || \ - (defined(__llvm__) && __has_attribute(noinline)) +#if BROTLI_MODERN_COMPILER || __has_attribute(noinline) #define BROTLI_NOINLINE __attribute__ ((noinline)) #else #define BROTLI_NOINLINE @@ -169,8 +220,8 @@ if ((N & 4) != 0) {X; X; X; X;} \ } -#if (__GNUC__ > 2) || defined(__llvm__) -#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) +#if BROTLI_MODERN_COMPILER || defined(__llvm__) +#if defined(BROTLI_TARGET_ARMV7) static BROTLI_INLINE unsigned BrotliRBit(unsigned input) { unsigned output; __asm__("rbit %0, %1\n" : "=r"(output) : "r"(input)); @@ -180,6 +231,12 @@ #endif /* armv7 */ #endif /* gcc || clang */ +#if defined(BROTLI_TARGET_ARM) +#define BROTLI_HAS_UBFX 1 +#else +#define BROTLI_HAS_UBFX 0 +#endif + #define BROTLI_FREE(X) { \ free(X); \ X = NULL; \
diff --git a/third_party/brotli/dec/prefix.h b/third_party/brotli/dec/prefix.h index 0d77f6e..91e43e92 100644 --- a/third_party/brotli/dec/prefix.h +++ b/third_party/brotli/dec/prefix.h
@@ -23,7 +23,7 @@ /* Represents the range of values belonging to a prefix code: */ /* [offset, offset + 2^nbits) */ struct PrefixCodeRange { - int16_t offset; + uint16_t offset; uint8_t nbits; };
diff --git a/third_party/brotli/dec/state.c b/third_party/brotli/dec/state.c index d32dfd3..f4f239a 100644 --- a/third_party/brotli/dec/state.c +++ b/third_party/brotli/dec/state.c
@@ -24,6 +24,7 @@ #endif void BrotliStateInit(BrotliState* s) { + BrotliInitBitReader(&s->br); s->state = BROTLI_STATE_UNINITED; s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE; s->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE; @@ -31,9 +32,13 @@ s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE; s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE; s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE; + s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE; + s->buffer_length = 0; s->loop_counter = 0; s->pos = 0; + s->rb_roundtrips = 0; + s->partial_pos_out = 0; s->block_type_trees = NULL; s->block_len_trees = NULL; @@ -45,6 +50,8 @@ s->context_map_slice = NULL; s->dist_context_map_slice = NULL; + s->sub_loop_counter = 0; + s->literal_hgroup.codes = NULL; s->literal_hgroup.htrees = NULL; s->insert_copy_hgroup.codes = NULL; @@ -71,13 +78,20 @@ s->symbol_lists = &s->symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1]; s->mtf_upper_bound = 255; + + s->legacy_input_buffer = 0; + s->legacy_output_buffer = 0; + s->legacy_input_len = 0; + s->legacy_output_len = 0; + s->legacy_input_pos = 0; + s->legacy_output_pos = 0; } void BrotliStateMetablockBegin(BrotliState* s) { s->meta_block_remaining_len = 0; - s->block_length[0] = 1 << 28; - s->block_length[1] = 1 << 28; - s->block_length[2] = 1 << 28; + s->block_length[0] = 1U << 28; + s->block_length[1] = 1U << 28; + s->block_length[2] = 1U << 28; s->num_block_types[0] = 1; s->num_block_types[1] = 1; s->num_block_types[2] = 1; @@ -113,27 +127,27 @@ BrotliHuffmanTreeGroupRelease(&s->literal_hgroup); BrotliHuffmanTreeGroupRelease(&s->insert_copy_hgroup); BrotliHuffmanTreeGroupRelease(&s->distance_hgroup); - s->literal_hgroup.codes = NULL; - s->literal_hgroup.htrees = NULL; - s->insert_copy_hgroup.codes = NULL; - s->insert_copy_hgroup.htrees = NULL; - s->distance_hgroup.codes = NULL; - s->distance_hgroup.htrees = NULL; } void BrotliStateCleanup(BrotliState* s) { - BROTLI_FREE(s->context_modes); - BROTLI_FREE(s->context_map); - BROTLI_FREE(s->dist_context_map); - - BrotliHuffmanTreeGroupRelease(&s->literal_hgroup); - BrotliHuffmanTreeGroupRelease(&s->insert_copy_hgroup); - BrotliHuffmanTreeGroupRelease(&s->distance_hgroup); + BrotliStateCleanupAfterMetablock(s); BROTLI_FREE(s->ringbuffer); BROTLI_FREE(s->block_type_trees); + BROTLI_FREE(s->legacy_input_buffer); + BROTLI_FREE(s->legacy_output_buffer); } +int BrotliStateIsStreamStart(const BrotliState* s) { + return (s->state == BROTLI_STATE_UNINITED && + BrotliGetAvailableBits(&s->br) == 0); +} + +int BrotliStateIsStreamEnd(const BrotliState* s) { + return s->state == BROTLI_STATE_DONE; +} + + #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif
diff --git a/third_party/brotli/dec/state.h b/third_party/brotli/dec/state.h index 241ee6cc..0d9329b 100644 --- a/third_party/brotli/dec/state.h +++ b/third_party/brotli/dec/state.h
@@ -21,7 +21,6 @@ #include <stdio.h> #include "./bit_reader.h" #include "./huffman.h" -#include "./streams.h" #include "./types.h" #if defined(__cplusplus) || defined(c_plusplus) @@ -30,19 +29,20 @@ typedef enum { BROTLI_STATE_UNINITED, - BROTLI_STATE_BITREADER_WARMUP, BROTLI_STATE_METABLOCK_BEGIN, BROTLI_STATE_METABLOCK_HEADER, + BROTLI_STATE_METABLOCK_HEADER_2, BROTLI_STATE_CONTEXT_MODES, BROTLI_STATE_COMMAND_BEGIN, BROTLI_STATE_COMMAND_INNER, + BROTLI_STATE_COMMAND_POST_DECODE_LITERALS, + BROTLI_STATE_COMMAND_POST_WRAP_COPY, BROTLI_STATE_UNCOMPRESSED, BROTLI_STATE_METADATA, BROTLI_STATE_COMMAND_INNER_WRITE, BROTLI_STATE_METABLOCK_DONE, BROTLI_STATE_COMMAND_POST_WRITE_1, BROTLI_STATE_COMMAND_POST_WRITE_2, - BROTLI_STATE_COMMAND_POST_WRAP_COPY, BROTLI_STATE_HUFFMAN_CODE_0, BROTLI_STATE_HUFFMAN_CODE_1, BROTLI_STATE_HUFFMAN_CODE_2, @@ -66,8 +66,6 @@ typedef enum { BROTLI_STATE_UNCOMPRESSED_NONE, - BROTLI_STATE_UNCOMPRESSED_SHORT, - BROTLI_STATE_UNCOMPRESSED_COPY, BROTLI_STATE_UNCOMPRESSED_WRITE } BrotliRunningUncompressedState; @@ -80,11 +78,16 @@ BROTLI_STATE_CONTEXT_MAP_NONE, BROTLI_STATE_CONTEXT_MAP_READ_PREFIX, BROTLI_STATE_CONTEXT_MAP_HUFFMAN, - BROTLI_STATE_CONTEXT_MAP_DECODE + BROTLI_STATE_CONTEXT_MAP_DECODE, + BROTLI_STATE_CONTEXT_MAP_TRANSFORM } BrotliRunningContextMapState; typedef enum { BROTLI_STATE_HUFFMAN_NONE, + BROTLI_STATE_HUFFMAN_SIMPLE_SIZE, + BROTLI_STATE_HUFFMAN_SIMPLE_READ, + BROTLI_STATE_HUFFMAN_SIMPLE_BUILD, + BROTLI_STATE_HUFFMAN_COMPLEX, BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS } BrotliRunningHuffmanState; @@ -94,10 +97,23 @@ BROTLI_STATE_DECODE_UINT8_LONG } BrotliRunningDecodeUint8State; -typedef struct { +typedef enum { + BROTLI_STATE_READ_BLOCK_LENGTH_NONE, + BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX +} BrotliRunningReadBlockLengthState; + +struct BrotliStateStruct { BrotliRunningState state; - /* This counter is reused for several disjoint loops. */ BrotliBitReader br; + + /* Temporary storage for remaining input. */ + union { + uint64_t u64; + uint8_t u8[8]; + } buffer; + uint32_t buffer_length; + + /* This counter is reused for several disjoint loops. */ int loop_counter; int pos; int max_backward_distance; @@ -115,6 +131,8 @@ uint8_t* context_map_slice; uint8_t* dist_context_map_slice; + uint32_t sub_loop_counter; + /* This ring buffer holds a few past copy distances that will be used by */ /* some special distance codes. */ HuffmanTreeGroup literal_hgroup; @@ -127,7 +145,8 @@ int trivial_literal_context; int distance_context; int meta_block_remaining_len; - int block_length[3]; + uint32_t block_length_index; + uint32_t block_length[3]; uint32_t num_block_types[3]; uint32_t block_type_rb[6]; uint32_t distance_postfix_bits; @@ -138,16 +157,16 @@ HuffmanCode *literal_htree; uint8_t literal_htree_index; uint8_t dist_htree_index; - uint8_t repeat_code_len; - uint8_t prev_code_len; + uint32_t repeat_code_len; + uint32_t prev_code_len; int copy_length; int distance_code; /* For partial write operations */ - int to_write; - int partially_written; + size_t rb_roundtrips; /* How many times we went around the ringbuffer */ + size_t partial_pos_out; /* How much output to the user in total (<= rb) */ /* For ReadHuffmanCode */ uint32_t symbol; @@ -173,6 +192,7 @@ /* For DecodeContextMap */ uint32_t context_index; uint32_t max_run_length_prefix; + uint32_t code; HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_TABLE_SIZE]; /* For InverseMoveToFrontTransform */ @@ -191,6 +211,7 @@ BrotliRunningUncompressedState substate_uncompressed; BrotliRunningHuffmanState substate_huffman; BrotliRunningDecodeUint8State substate_decode_uint8; + BrotliRunningReadBlockLengthState substate_read_block_length; uint8_t is_last_metablock; uint8_t is_uncompressed; @@ -201,13 +222,32 @@ uint32_t num_literal_htrees; uint8_t* context_map; uint8_t* context_modes; -} BrotliState; + + uint8_t* legacy_input_buffer; + uint8_t* legacy_output_buffer; + size_t legacy_input_len; + size_t legacy_output_len; + size_t legacy_input_pos; + size_t legacy_output_pos; +}; + +typedef struct BrotliStateStruct BrotliState; void BrotliStateInit(BrotliState* s); void BrotliStateCleanup(BrotliState* s); void BrotliStateMetablockBegin(BrotliState* s); void BrotliStateCleanupAfterMetablock(BrotliState* s); + +/* Returns 1, if s is in a state where we have not read any input bytes yet, + and 0 otherwise */ +int BrotliStateIsStreamStart(const BrotliState* s); + +/* Returns 1, if s is in a state where we reached the end of the input and + produced all of the output, and 0 otherwise. */ +int BrotliStateIsStreamEnd(const BrotliState* s); + + #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif
diff --git a/third_party/brotli/dec/streams.c b/third_party/brotli/dec/streams.c index f7060a9..007c513 100644 --- a/third_party/brotli/dec/streams.c +++ b/third_party/brotli/dec/streams.c
@@ -99,7 +99,7 @@ return (int)count; } -BrotliOutput BrotliNullOutput() { +BrotliOutput BrotliNullOutput(void) { BrotliOutput out; out.cb_ = BrotliNullOutputFunction; out.data_ = NULL;
diff --git a/third_party/brotli/dec/streams.h b/third_party/brotli/dec/streams.h index decfa7e..99eb125 100644 --- a/third_party/brotli/dec/streams.h +++ b/third_party/brotli/dec/streams.h
@@ -95,7 +95,7 @@ /* Output callback that does nothing, always consumes the whole input. */ int BrotliNullOutputFunction(void* data, const uint8_t* buf, size_t count); -BrotliOutput BrotliNullOutput(); +BrotliOutput BrotliNullOutput(void); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */
diff --git a/third_party/brotli/dec/types.h b/third_party/brotli/dec/types.h index e7e5ab1..8a9cc4a8 100644 --- a/third_party/brotli/dec/types.h +++ b/third_party/brotli/dec/types.h
@@ -21,14 +21,14 @@ #include <stddef.h> /* for size_t */ #if defined(_MSC_VER) && (_MSC_VER < 1600) -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef signed short int16_t; -typedef unsigned short uint16_t; -typedef signed int int32_t; -typedef unsigned int uint32_t; -typedef unsigned long long int uint64_t; -typedef long long int int64_t; +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +typedef __int64 int64_t; #else #include <stdint.h> #endif /* defined(_MSC_VER) && (_MSC_VER < 1600) */
diff --git a/ui/metro_viewer/metro_viewer_messages.h b/ui/metro_viewer/metro_viewer_messages.h index ad7690c..068909f26 100644 --- a/ui/metro_viewer/metro_viewer_messages.h +++ b/ui/metro_viewer/metro_viewer_messages.h
@@ -49,21 +49,21 @@ uint32, /* virtual key */ uint32, /* repeat count */ uint32, /* scan code */ - uint32 /* key state */); + uint32 /* key state */) // Informs the browser that a key was released. IPC_MESSAGE_CONTROL4(MetroViewerHostMsg_KeyUp, uint32, /* virtual key */ uint32, /* repeat count */ uint32, /* scan code */ - uint32 /* key state */); + uint32 /* key state */) IPC_MESSAGE_CONTROL4(MetroViewerHostMsg_Character, uint32, /* virtual key */ uint32, /* repeat count */ uint32, /* scan code */ - uint32 /* key state */); + uint32 /* key state */) // Informs the browser that the Metro window has been activated. IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_WindowActivated, - bool /* Whether the window should be repainted */); + bool /* Whether the window should be repainted */) // Informs the browser that the user has completed an edge gesture. IPC_MESSAGE_CONTROL0(MetroViewerHostMsg_EdgeGesture) @@ -109,19 +109,19 @@ // Requests the viewer to activate desktop mode. IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_ActivateDesktop, base::FilePath /* shortcut */, - bool /* ash exit */); + bool /* ash exit */) // Request the viewer to close itself gracefully. -IPC_MESSAGE_CONTROL0(MetroViewerHostMsg_MetroExit); +IPC_MESSAGE_CONTROL0(MetroViewerHostMsg_MetroExit) // Requests the viewer to open a URL in desktop mode. IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_OpenURLOnDesktop, - base::FilePath, /* shortcut */ - base::string16 /* url */); + base::FilePath /* shortcut */, + base::string16 /* url */) // Requests the viewer to change the pointer to a new cursor. IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_SetCursor, - int64 /* cursor */); + int64 /* cursor */) // This structure contains the parameters sent to the viewer process to display // the file save dialog.