diff --git a/DEPS b/DEPS index 139cdbb..a9060d8 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '6e834799946537370e6f3c10aa2745ed969b2a27', + 'skia_revision': '7fa5c31c2c9af834bee66d5fcf476e250076c8d6', # 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': 'a8190a51525dd6f0a74eba767d41e2f822b25054', + 'v8_revision': '207d5c39e9c289fc91d8344f32f6b0820001f557', # 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. @@ -52,7 +52,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'a9042d3c195294cf6b2186f1c52260f1fc2b6004', + 'angle_revision': 'b36e5393d35bfa28c72d0b61d6ba2565725b99a0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -60,7 +60,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '400667e6604eb07e53a2894ede1f492fc3c0b117', + 'swiftshader_revision': '30385f0f418b2c366acd7ef9bf6024b41bd4a1e1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'e8775f0f64bcae6b0789df6d4a2a5aca9f5cf4ac', + 'catapult_revision': 'cabc13146729eeee3d96d42c345c07da760bb31c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/WATCHLISTS b/WATCHLISTS index 8f92d7d..2207316 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -383,6 +383,9 @@ 'chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/|' \ 'components/contextual_search/', }, + 'content_network' : { + 'filepath': 'content/network/', + }, 'cookie_monster': { 'filepath': 'net/cookies/|'\ 'chrome/browser/net/sqlite_persistent_cookie_store', @@ -1913,6 +1916,9 @@ 'content_loader': ['loading-reviews@chromium.org', 'mmenke@chromium.org', 'rdsmith@chromium.org'], + 'content_network': ['asanka@chromium.org', + 'mmenke@chromium.org', + 'rdsmith@chromium.org'], 'content_renderer': ['mlamouri+watch-content@chromium.org'], 'content_shell': ['jochen+watch@chromium.org', 'mlamouri+watch-content@chromium.org',
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java index e9f0386c..fd758ecf 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java
@@ -8,6 +8,7 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.test.util.CommonResources; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.content.browser.ContentViewCore; @@ -66,9 +67,9 @@ assertEquals(POPUP_TITLE, getTitleOnUiThread(popupContents)); } + @DisabledTest @SmallTest @Feature({"AndroidWebView"}) - @RetryOnFailure public void testOnPageFinishedCalledOnDomModificationAfterNavigation() throws Throwable { final String popupPath = "/popup.html"; final String parentPageHtml = CommonResources.makeHtmlPageFrom("", "<script>"
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc index 30aac4c..803b4364 100644 --- a/android_webview/renderer/aw_content_renderer_client.cc +++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -32,6 +32,9 @@ #include "components/supervised_user_error_page/supervised_user_error_page_android.h" #include "components/visitedlink/renderer/visitedlink_slave.h" #include "components/web_restrictions/interfaces/web_restrictions.mojom.h" +#include "content/public/child/child_thread.h" +#include "content/public/common/service_manager_connection.h" +#include "content/public/common/simple_connection_filter.h" #include "content/public/common/url_constants.h" #include "content/public/renderer/document_state.h" #include "content/public/renderer/navigation_state.h" @@ -40,8 +43,8 @@ #include "content/public/renderer/render_view.h" #include "net/base/escape.h" #include "net/base/net_errors.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/interface_provider.h" -#include "services/service_manager/public/cpp/interface_registry.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/platform/WebURLError.h" @@ -73,8 +76,14 @@ thread->AddObserver(aw_render_thread_observer_.get()); visited_link_slave_.reset(new visitedlink::VisitedLinkSlave); - thread->GetInterfaceRegistry()->AddInterface( - visited_link_slave_->GetBindCallback()); + + auto registry = base::MakeUnique<service_manager::BinderRegistry>(); + registry->AddInterface(visited_link_slave_->GetBindCallback(), + base::ThreadTaskRunnerHandle::Get()); + content::ChildThread::Get() + ->GetServiceManagerConnection() + ->AddConnectionFilter(base::MakeUnique<content::SimpleConnectionFilter>( + std::move(registry))); #if BUILDFLAG(ENABLE_SPELLCHECK) if (!spellcheck_) {
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index ab776d3c..ec32769a 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -246,9 +246,9 @@ "screenshot_delegate.h", "session/session_controller.cc", "session/session_controller.h", + "session/session_observer.cc", + "session/session_observer.h", "session/session_state_delegate.h", - "session/session_state_observer.cc", - "session/session_state_observer.h", "shared/immersive_context.cc", "shared/immersive_context.h", "shared/immersive_focus_watcher.h", @@ -494,8 +494,6 @@ "system/toast/toast_overlay.h", "system/tray/actionable_view.cc", "system/tray/actionable_view.h", - "system/tray/default_system_tray_delegate.cc", - "system/tray/default_system_tray_delegate.h", "system/tray/fixed_sized_image_view.cc", "system/tray/fixed_sized_image_view.h", "system/tray/hover_highlight_view.cc",
diff --git a/ash/display/shutdown_observer_chromeos.cc b/ash/display/shutdown_observer_chromeos.cc index a9540e3e..d91f442 100644 --- a/ash/display/shutdown_observer_chromeos.cc +++ b/ash/display/shutdown_observer_chromeos.cc
@@ -4,22 +4,18 @@ #include "ash/display/shutdown_observer_chromeos.h" -#include "ash/shell.h" #include "ui/display/manager/chromeos/display_configurator.h" namespace ash { ShutdownObserver::ShutdownObserver( display::DisplayConfigurator* display_configurator) - : display_configurator_(display_configurator) { - Shell::Get()->AddShellObserver(this); -} + : display_configurator_(display_configurator), + scoped_session_observer_(this) {} -ShutdownObserver::~ShutdownObserver() { - Shell::Get()->RemoveShellObserver(this); -} +ShutdownObserver::~ShutdownObserver() {} -void ShutdownObserver::OnAppTerminating() { +void ShutdownObserver::OnChromeTerminating() { // Stop handling display configuration events once the shutdown // process starts. crbug.com/177014. display_configurator_->PrepareForExit();
diff --git a/ash/display/shutdown_observer_chromeos.h b/ash/display/shutdown_observer_chromeos.h index 67c69ee1..fc773db 100644 --- a/ash/display/shutdown_observer_chromeos.h +++ b/ash/display/shutdown_observer_chromeos.h
@@ -5,7 +5,7 @@ #ifndef ASH_DISPLAY_SHUTDOWN_OBSERVER_CHROMEOS_H_ #define ASH_DISPLAY_SHUTDOWN_OBSERVER_CHROMEOS_H_ -#include "ash/shell_observer.h" +#include "ash/session/session_observer.h" #include "base/macros.h" namespace display { @@ -14,18 +14,19 @@ namespace ash { -// Adds self as ShellObserver and listens for OnAppTerminating() on behalf of -// |display_configurator_|. -class ShutdownObserver : public ShellObserver { +// Adds self as SessionObserver and listens for OnChromeTerminating() on +// behalf of |display_configurator_|. +class ShutdownObserver : public SessionObserver { public: explicit ShutdownObserver(display::DisplayConfigurator* display_configurator); ~ShutdownObserver() override; private: - // ShellObserver: - void OnAppTerminating() override; + // SessionObserver: + void OnChromeTerminating() override; - display::DisplayConfigurator* display_configurator_; + display::DisplayConfigurator* const display_configurator_; + ScopedSessionObserver scoped_session_observer_; DISALLOW_COPY_AND_ASSIGN(ShutdownObserver); };
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc index 8308a4df..5a56430 100644 --- a/ash/drag_drop/drag_drop_controller.cc +++ b/ash/drag_drop/drag_drop_controller.cc
@@ -12,6 +12,7 @@ #include "ash/shell_port.h" #include "ash/wm_window.h" #include "base/bind.h" +#include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/metrics/histogram_macros.h" #include "base/run_loop.h" @@ -203,8 +204,8 @@ drag_image_final_bounds_for_cancel_animation_ = gfx::Rect(start_location - provider->GetDragImageOffset(), provider->GetDragImage().size()); - drag_image_.reset( - new DragImageView(WmWindow::Get(source_window->GetRootWindow()), source)); + drag_image_ = + base::MakeUnique<DragImageView>(source_window->GetRootWindow(), source); drag_image_->SetImage(provider->GetDragImage()); drag_image_offset_ = provider->GetDragImageOffset(); gfx::Rect drag_image_bounds(start_location, drag_image_->GetPreferredSize());
diff --git a/ash/drag_drop/drag_image_view.cc b/ash/drag_drop/drag_image_view.cc index 15e7527..1c8776a 100644 --- a/ash/drag_drop/drag_image_view.cc +++ b/ash/drag_drop/drag_image_view.cc
@@ -8,10 +8,11 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/root_window_controller.h" -#include "ash/wm_window.h" #include "skia/ext/image_operations.h" +#include "ui/aura/window.h" #include "ui/base/resource/resource_bundle.h" #include "ui/display/display.h" +#include "ui/display/screen.h" #include "ui/gfx/canvas.h" #include "ui/resources/grit/ui_resources.h" #include "ui/views/widget/widget.h" @@ -20,7 +21,7 @@ namespace { using views::Widget; -std::unique_ptr<Widget> CreateDragWidget(WmWindow* root_window) { +std::unique_ptr<Widget> CreateDragWidget(aura::Window* root_window) { std::unique_ptr<Widget> drag_widget(new Widget); Widget::InitParams params; params.type = Widget::InitParams::TYPE_TOOLTIP; @@ -30,8 +31,10 @@ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.shadow_type = Widget::InitParams::SHADOW_TYPE_NONE; params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW; - root_window->GetRootWindowController()->ConfigureWidgetInitParamsForContainer( - drag_widget.get(), kShellWindowId_DragImageAndTooltipContainer, ¶ms); + RootWindowController::ForWindow(root_window) + ->ConfigureWidgetInitParamsForContainer( + drag_widget.get(), kShellWindowId_DragImageAndTooltipContainer, + ¶ms); drag_widget->Init(params); drag_widget->SetOpacity(1.f); return drag_widget; @@ -39,7 +42,7 @@ } // namespace -DragImageView::DragImageView(WmWindow* root_window, +DragImageView::DragImageView(aura::Window* root_window, ui::DragDropTypes::DragEventSource event_source) : drag_event_source_(event_source), touch_drag_operation_(ui::DragDropTypes::DRAG_NONE) { @@ -121,9 +124,10 @@ if (GetImage().size() == drag_image_size_) { canvas->DrawImageInt(GetImage(), 0, 0); } else { - WmWindow* window = WmWindow::Get(widget_->GetNativeWindow()); - const float device_scale = - window->GetDisplayNearestWindow().device_scale_factor(); + aura::Window* window = widget_->GetNativeWindow(); + const float device_scale = display::Screen::GetScreen() + ->GetDisplayNearestWindow(window) + .device_scale_factor(); // The drag image already has device scale factor applied. But // |drag_image_size_| is in DIP units. gfx::Size drag_image_size_pixels =
diff --git a/ash/drag_drop/drag_image_view.h b/ash/drag_drop/drag_image_view.h index be1830e..e59cc10 100644 --- a/ash/drag_drop/drag_image_view.h +++ b/ash/drag_drop/drag_image_view.h
@@ -14,6 +14,10 @@ #include "ui/gfx/geometry/size.h" #include "ui/views/controls/image_view.h" +namespace aura { +class Window; +} + namespace gfx { class Image; } @@ -24,8 +28,6 @@ namespace ash { -class WmWindow; - // This class allows to show a (native) view always on top of everything. It // does this by creating a widget and setting the content as the given view. The // caller can then use this object to freely move / drag it around on the @@ -36,7 +38,7 @@ // |source| is the event source that started this drag drop operation (touch // or mouse). It is used to determine attributes of the drag image such as // whether to show drag operation hint on top of the image. - DragImageView(WmWindow* root_window, + DragImageView(aura::Window* root_window, ui::DragDropTypes::DragEventSource source); ~DragImageView() override;
diff --git a/ash/drag_drop/drag_image_view_unittest.cc b/ash/drag_drop/drag_image_view_unittest.cc index 6fa0bd3..44911a7 100644 --- a/ash/drag_drop/drag_image_view_unittest.cc +++ b/ash/drag_drop/drag_image_view_unittest.cc
@@ -4,18 +4,19 @@ #include "ash/drag_drop/drag_image_view.h" -#include "ash/test/ash_test.h" +#include "ash/test/ash_test_base.h" +#include "ui/aura/window.h" #include "ui/base/dragdrop/drag_drop_types.h" namespace ash { namespace test { -using DragDropImageTest = AshTest; +using DragDropImageTest = AshTestBase; TEST_F(DragDropImageTest, SetBoundsConsidersDragHintForTouch) { - std::unique_ptr<WindowOwner> window_owner(CreateTestWindow()); + std::unique_ptr<aura::Window> window(CreateTestWindow()); DragImageView drag_image_view( - window_owner->window(), + window.get(), ui::DragDropTypes::DragEventSource::DRAG_EVENT_SOURCE_TOUCH); gfx::Size minimum_size = drag_image_view.GetMinimumSize(); @@ -45,9 +46,9 @@ } TEST_F(DragDropImageTest, SetBoundsIgnoresDragHintForMouse) { - std::unique_ptr<WindowOwner> window_owner(CreateTestWindow()); + std::unique_ptr<aura::Window> window(CreateTestWindow()); DragImageView drag_image_view( - window_owner->window(), + window.get(), ui::DragDropTypes::DragEventSource::DRAG_EVENT_SOURCE_MOUSE); // Expect no drag hint image.
diff --git a/ash/mus/system_tray_delegate_mus.h b/ash/mus/system_tray_delegate_mus.h index 69f3d2d..8160966 100644 --- a/ash/mus/system_tray_delegate_mus.h +++ b/ash/mus/system_tray_delegate_mus.h
@@ -7,7 +7,7 @@ #include <memory> -#include "ash/system/tray/default_system_tray_delegate.h" +#include "ash/system/tray/system_tray_delegate.h" #include "base/macros.h" namespace ash { @@ -18,7 +18,7 @@ // version see SystemTrayDelegateChromeOS. // // TODO: Replace with SystemTrayController. http://crbug.com/647412. -class SystemTrayDelegateMus : public DefaultSystemTrayDelegate { +class SystemTrayDelegateMus : public SystemTrayDelegate { public: SystemTrayDelegateMus(); ~SystemTrayDelegateMus() override;
diff --git a/ash/mus/window_manager.cc b/ash/mus/window_manager.cc index 003dc5d..b47556ff 100644 --- a/ash/mus/window_manager.cc +++ b/ash/mus/window_manager.cc
@@ -330,6 +330,8 @@ ash::Shell::set_window_manager_client(client); } +void WindowManager::OnWmConnected() {} + void WindowManager::OnWmSetBounds(aura::Window* window, const gfx::Rect& bounds) { // TODO(sky): this indirectly sets bounds, which is against what @@ -401,8 +403,8 @@ // TODO(erg): SkBitmap is the wrong data type for the drag image; we should // be passing ImageSkias once http://crbug.com/655874 is implemented. - WmWindow* root_window = - WmWindow::Get((*GetRootWindowControllers().begin())->GetRootWindow()); + aura::Window* root_window = + (*GetRootWindowControllers().begin())->GetRootWindow(); ui::DragDropTypes::DragEventSource ui_source = source == ui::mojom::PointerKind::MOUSE
diff --git a/ash/mus/window_manager.h b/ash/mus/window_manager.h index 6af032e..b424d381 100644 --- a/ash/mus/window_manager.h +++ b/ash/mus/window_manager.h
@@ -147,6 +147,7 @@ // WindowManagerDelegate: void SetWindowManagerClient(aura::WindowManagerClient* client) override; + void OnWmConnected() override; void OnWmSetBounds(aura::Window* window, const gfx::Rect& bounds) override; bool OnWmSetProperty( aura::Window* window,
diff --git a/ash/public/interfaces/session_controller.mojom b/ash/public/interfaces/session_controller.mojom index 65ead11..ed066cbd 100644 --- a/ash/public/interfaces/session_controller.mojom +++ b/ash/public/interfaces/session_controller.mojom
@@ -147,6 +147,9 @@ // dismissing. When the mojo call returns, screen locker takes that as a // signal of finished unlock animation and dismisses itself. RunUnlockAnimation() => (); + + // Notifies that chrome is terminating. + NotifyChromeTerminating(); }; // Interface for ash to request session service from its client (e.g. Chrome).
diff --git a/ash/session/session_controller.cc b/ash/session/session_controller.cc index f2fe59c..b546c92b 100644 --- a/ash/session/session_controller.cc +++ b/ash/session/session_controller.cc
@@ -6,7 +6,7 @@ #include <algorithm> -#include "ash/session/session_state_observer.h" +#include "ash/session/session_observer.h" #include "ash/shell.h" #include "ash/wm/lock_state_controller.h" #include "base/bind.h" @@ -141,13 +141,11 @@ client_->CycleActiveUser(direction); } -void SessionController::AddSessionStateObserver( - SessionStateObserver* observer) { +void SessionController::AddObserver(SessionObserver* observer) { observers_.AddObserver(observer); } -void SessionController::RemoveSessionStateObserver( - SessionStateObserver* observer) { +void SessionController::RemoveObserver(SessionObserver* observer) { observers_.RemoveObserver(observer); } @@ -221,6 +219,11 @@ Shell::Get()->lock_state_controller()->OnLockScreenHide(callback); } +void SessionController::NotifyChromeTerminating() { + for (auto& observer : observers_) + observer.OnChromeTerminating(); +} + void SessionController::ClearUserSessionsForTest() { user_sessions_.clear(); }
diff --git a/ash/session/session_controller.h b/ash/session/session_controller.h index afe6222c..5500b41 100644 --- a/ash/session/session_controller.h +++ b/ash/session/session_controller.h
@@ -21,7 +21,7 @@ namespace ash { -class SessionStateObserver; +class SessionObserver; // Implements mojom::SessionController to cache session related info such as // session state, meta data about user sessions to support synchronous @@ -96,8 +96,8 @@ // ordering as user sessions are created. void CycleActiveUser(CycleUserDirection direction); - void AddSessionStateObserver(SessionStateObserver* observer); - void RemoveSessionStateObserver(SessionStateObserver* observer); + void AddObserver(SessionObserver* observer); + void RemoveObserver(SessionObserver* observer); // Returns the ash notion of login status. // NOTE: Prefer GetSessionState() in new code because the concept of @@ -111,6 +111,7 @@ void SetUserSessionOrder( const std::vector<uint32_t>& user_session_order) override; void RunUnlockAnimation(const RunUnlockAnimationCallback& callback) override; + void NotifyChromeTerminating() override; // Test helpers. void ClearUserSessionsForTest(); @@ -159,7 +160,7 @@ // animation starts and reset when session state is no longer LOCKED. bool is_unlocking_ = false; - base::ObserverList<ash::SessionStateObserver> observers_; + base::ObserverList<ash::SessionObserver> observers_; DISALLOW_COPY_AND_ASSIGN(SessionController); };
diff --git a/ash/session/session_controller_unittest.cc b/ash/session/session_controller_unittest.cc index 2fb05f8..b90ee19 100644 --- a/ash/session/session_controller_unittest.cc +++ b/ash/session/session_controller_unittest.cc
@@ -12,7 +12,7 @@ #include "ash/login_status.h" #include "ash/public/interfaces/session_controller.mojom.h" #include "ash/session/session_controller.h" -#include "ash/session/session_state_observer.h" +#include "ash/session/session_observer.h" #include "base/callback.h" #include "base/macros.h" #include "base/memory/ptr_util.h" @@ -24,12 +24,12 @@ namespace ash { namespace { -class TestSessionStateObserver : public SessionStateObserver { +class TestSessionObserver : public SessionObserver { public: - TestSessionStateObserver() : active_account_id_(EmptyAccountId()) {} - ~TestSessionStateObserver() override {} + TestSessionObserver() : active_account_id_(EmptyAccountId()) {} + ~TestSessionObserver() override {} - // SessionStateObserver: + // SessionObserver: void OnActiveUserSessionChanged(const AccountId& account_id) override { active_account_id_ = account_id; } @@ -59,7 +59,7 @@ AccountId active_account_id_; std::vector<AccountId> user_session_account_ids_; - DISALLOW_COPY_AND_ASSIGN(TestSessionStateObserver); + DISALLOW_COPY_AND_ASSIGN(TestSessionObserver); }; void FillDefaultSessionInfo(mojom::SessionInfo* info) { @@ -77,12 +77,10 @@ // testing::Test: void SetUp() override { controller_ = base::MakeUnique<SessionController>(); - controller_->AddSessionStateObserver(&observer_); + controller_->AddObserver(&observer_); } - void TearDown() override { - controller_->RemoveSessionStateObserver(&observer_); - } + void TearDown() override { controller_->RemoveObserver(&observer_); } void SetSessionInfo(const mojom::SessionInfo& info) { mojom::SessionInfoPtr info_ptr = mojom::SessionInfo::New(); @@ -110,11 +108,11 @@ } SessionController* controller() { return controller_.get(); } - const TestSessionStateObserver* observer() const { return &observer_; } + const TestSessionObserver* observer() const { return &observer_; } private: std::unique_ptr<SessionController> controller_; - TestSessionStateObserver observer_; + TestSessionObserver observer_; DISALLOW_COPY_AND_ASSIGN(SessionControllerTest); };
diff --git a/ash/session/session_observer.cc b/ash/session/session_observer.cc new file mode 100644 index 0000000..b89a471 --- /dev/null +++ b/ash/session/session_observer.cc
@@ -0,0 +1,24 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/session/session_observer.h" + +#include "ash/session/session_controller.h" +#include "ash/shell.h" + +namespace ash { + +ScopedSessionObserver::ScopedSessionObserver(SessionObserver* observer) + : observer_(observer) { + // Shell may not exist in some tests. + if (Shell::HasInstance()) + Shell::Get()->session_controller()->AddObserver(observer_); +} + +ScopedSessionObserver::~ScopedSessionObserver() { + if (Shell::HasInstance()) + Shell::Get()->session_controller()->RemoveObserver(observer_); +} + +} // namespace ash
diff --git a/ash/session/session_state_observer.h b/ash/session/session_observer.h similarity index 71% rename from ash/session/session_state_observer.h rename to ash/session/session_observer.h index 7732f53..554273ad 100644 --- a/ash/session/session_state_observer.h +++ b/ash/session/session_observer.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SESSION_SESSION_STATE_OBSERVER_H_ -#define ASH_SESSION_SESSION_STATE_OBSERVER_H_ +#ifndef ASH_SESSION_SESSION_OBSERVER_H_ +#define ASH_SESSION_SESSION_OBSERVER_H_ #include "ash/ash_export.h" #include "base/macros.h" @@ -15,8 +15,7 @@ enum class LoginStatus; -// TODO(xiyuan): Rename to On*Changed(). -class ASH_EXPORT SessionStateObserver { +class ASH_EXPORT SessionObserver { public: // Called when the active user session has changed. virtual void OnActiveUserSessionChanged(const AccountId& account_id) {} @@ -36,22 +35,25 @@ // Called when the lock state is changed. |locked| is the current lock stated. virtual void OnLockStateChanged(bool locked) {} + // Called when chrome is terminating. + virtual void OnChromeTerminating() {} + protected: - virtual ~SessionStateObserver() {} + virtual ~SessionObserver() {} }; // A class to attach / detach an object as a session state observer. -class ASH_EXPORT ScopedSessionStateObserver { +class ASH_EXPORT ScopedSessionObserver { public: - explicit ScopedSessionStateObserver(SessionStateObserver* observer); - virtual ~ScopedSessionStateObserver(); + explicit ScopedSessionObserver(SessionObserver* observer); + virtual ~ScopedSessionObserver(); private: - ash::SessionStateObserver* observer_; + SessionObserver* const observer_; - DISALLOW_COPY_AND_ASSIGN(ScopedSessionStateObserver); + DISALLOW_COPY_AND_ASSIGN(ScopedSessionObserver); }; } // namespace ash -#endif // ASH_SESSION_SESSION_STATE_OBSERVER_H_ +#endif // ASH_SESSION_SESSION_OBSERVER_H_
diff --git a/ash/session/session_state_observer.cc b/ash/session/session_state_observer.cc deleted file mode 100644 index 7f3e965..0000000 --- a/ash/session/session_state_observer.cc +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/session/session_state_observer.h" - -#include "ash/session/session_controller.h" -#include "ash/shell.h" - -namespace ash { - -ScopedSessionStateObserver::ScopedSessionStateObserver( - SessionStateObserver* observer) - : observer_(observer) { - Shell::Get()->session_controller()->AddSessionStateObserver(observer_); -} - -ScopedSessionStateObserver::~ScopedSessionStateObserver() { - if (Shell::HasInstance()) - Shell::Get()->session_controller()->RemoveSessionStateObserver(observer_); -} - -} // namespace ash
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index a054cc9..359d0c6 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -155,13 +155,13 @@ chromevox_panel_height_(0), duration_override_in_ms_(0), shelf_background_type_(SHELF_BACKGROUND_OVERLAP), - keyboard_observer_(this) { + keyboard_observer_(this), + scoped_session_observer_(this) { DCHECK(shelf_widget_); DCHECK(wm_shelf_); Shell::Get()->AddShellObserver(this); ShellPort::Get()->AddLockStateObserver(this); Shell::Get()->activation_client()->AddObserver(this); - Shell::Get()->session_controller()->AddSessionStateObserver(this); state_.session_state = Shell::Get()->session_controller()->GetSessionState(); } @@ -173,7 +173,6 @@ observer.WillDeleteShelfLayoutManager(); Shell::Get()->RemoveShellObserver(this); ShellPort::Get()->RemoveLockStateObserver(this); - Shell::Get()->session_controller()->RemoveSessionStateObserver(this); } void ShelfLayoutManager::PrepareForShutdown() {
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h index 4130b8d..11dff93 100644 --- a/ash/shelf/shelf_layout_manager.h +++ b/ash/shelf/shelf_layout_manager.h
@@ -9,7 +9,7 @@ #include "ash/ash_export.h" #include "ash/public/cpp/shelf_types.h" -#include "ash/session/session_state_observer.h" +#include "ash/session/session_observer.h" #include "ash/shelf/wm_shelf.h" #include "ash/shell_observer.h" #include "ash/wm/lock_state_observer.h" @@ -55,7 +55,7 @@ public keyboard::KeyboardControllerObserver, public LockStateObserver, public wm::WmSnapToPixelLayoutManager, - public SessionStateObserver { + public SessionObserver { public: ShelfLayoutManager(ShelfWidget* shelf_widget, WmShelf* wm_shelf); ~ShelfLayoutManager() override; @@ -150,7 +150,7 @@ // Overridden from LockStateObserver: void OnLockStateEvent(LockStateObserver::EventType event) override; - // Overridden from SessionStateObserver: + // Overridden from SessionObserver: void OnSessionStateChanged(session_manager::SessionState state) override; void OnLoginStatusChanged(LoginStatus loing_status) override; @@ -360,6 +360,7 @@ ScopedObserver<keyboard::KeyboardController, keyboard::KeyboardControllerObserver> keyboard_observer_; + ScopedSessionObserver scoped_session_observer_; DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManager); };
diff --git a/ash/shelf/shelf_locking_manager.cc b/ash/shelf/shelf_locking_manager.cc index 39e4535..0a6a037 100644 --- a/ash/shelf/shelf_locking_manager.cc +++ b/ash/shelf/shelf_locking_manager.cc
@@ -12,21 +12,19 @@ namespace ash { ShelfLockingManager::ShelfLockingManager(WmShelf* shelf) - : shelf_(shelf), stored_alignment_(shelf->GetAlignment()) { + : shelf_(shelf), + stored_alignment_(shelf->GetAlignment()), + scoped_session_observer_(this) { DCHECK(shelf_); ShellPort::Get()->AddLockStateObserver(this); SessionController* controller = Shell::Get()->session_controller(); session_locked_ = controller->GetSessionState() != session_manager::SessionState::ACTIVE; screen_locked_ = controller->IsScreenLocked(); - controller->AddSessionStateObserver(this); - Shell::Get()->AddShellObserver(this); } ShelfLockingManager::~ShelfLockingManager() { ShellPort::Get()->RemoveLockStateObserver(this); - Shell::Get()->session_controller()->RemoveSessionStateObserver(this); - Shell::Get()->RemoveShellObserver(this); } void ShelfLockingManager::OnLockStateChanged(bool locked) {
diff --git a/ash/shelf/shelf_locking_manager.h b/ash/shelf/shelf_locking_manager.h index fb4f7b79..c65e593 100644 --- a/ash/shelf/shelf_locking_manager.h +++ b/ash/shelf/shelf_locking_manager.h
@@ -7,8 +7,7 @@ #include "ash/ash_export.h" #include "ash/public/cpp/shelf_types.h" -#include "ash/session/session_state_observer.h" -#include "ash/shell_observer.h" +#include "ash/session/session_observer.h" #include "ash/wm/lock_state_observer.h" namespace ash { @@ -16,8 +15,7 @@ class WmShelf; // ShelfLockingManager observes screen and session events to [un]lock the shelf. -class ASH_EXPORT ShelfLockingManager : public ShellObserver, - public SessionStateObserver, +class ASH_EXPORT ShelfLockingManager : public SessionObserver, public LockStateObserver { public: explicit ShelfLockingManager(WmShelf* shelf); @@ -26,10 +24,8 @@ bool is_locked() const { return session_locked_ || screen_locked_; } void set_stored_alignment(ShelfAlignment value) { stored_alignment_ = value; } - // ShellObserver: + // SessionObserver: void OnLockStateChanged(bool locked) override; - - // SessionStateObserver: void OnSessionStateChanged(session_manager::SessionState state) override; // LockStateObserver: @@ -44,6 +40,8 @@ bool screen_locked_ = false; ShelfAlignment stored_alignment_; + ScopedSessionObserver scoped_session_observer_; + DISALLOW_COPY_AND_ASSIGN(ShelfLockingManager); };
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index c8a3e821..ed9850e7 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -516,11 +516,10 @@ const gfx::Vector2d& cursor_offset_from_center, float scale_factor) { drag_replaced_view_ = replaced_view; - WmWindow* root_window = - WmWindow::Get(drag_replaced_view_->GetWidget()->GetNativeWindow()) - ->GetRootWindow(); - drag_image_.reset(new DragImageView( - root_window, ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE)); + aura::Window* root_window = + drag_replaced_view_->GetWidget()->GetNativeWindow()->GetRootWindow(); + drag_image_ = base::MakeUnique<DragImageView>( + root_window, ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE); drag_image_->SetImage(icon); gfx::Size size = drag_image_->GetPreferredSize(); size.set_width(size.width() * scale_factor);
diff --git a/ash/shell.cc b/ash/shell.cc index a58793a..111ffaf 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -328,11 +328,6 @@ shell_port_->SetDisplayWorkAreaInsets(WmWindow::Get(contains), insets); } -void Shell::OnAppTerminating() { - for (auto& observer : shell_observers_) - observer.OnAppTerminating(); -} - void Shell::OnCastingSessionStartedOrStopped(bool started) { for (auto& observer : shell_observers_) observer.OnCastingSessionStartedOrStopped(started); @@ -581,7 +576,7 @@ PowerStatus::Initialize(); - session_controller_->AddSessionStateObserver(this); + session_controller_->AddObserver(this); } Shell::~Shell() { @@ -614,6 +609,8 @@ speech_feedback_handler_.reset(); RemovePreTargetHandler(overlay_filter_.get()); + overlay_filter_.reset(); + RemovePreTargetHandler(accelerator_filter_.get()); RemovePreTargetHandler(event_transformation_handler_.get()); RemovePreTargetHandler(toplevel_window_event_handler_.get()); @@ -655,8 +652,8 @@ // Drag-and-drop must be canceled prior to close all windows. drag_drop_controller_.reset(); -// Controllers who have WindowObserver added must be deleted -// before |window_tree_host_manager_| is deleted. + // Controllers who have WindowObserver added must be deleted + // before |window_tree_host_manager_| is deleted. // VideoActivityNotifier must be deleted before |video_detector_| is // deleted because it's observing video activity through @@ -760,7 +757,7 @@ // Needs to happen right before |instance_| is reset. shell_port_.reset(); - session_controller_->RemoveSessionStateObserver(this); + session_controller_->RemoveObserver(this); wallpaper_delegate_.reset(); pref_service_ = nullptr; shell_delegate_.reset(); @@ -944,7 +941,6 @@ overlay_filter_.reset(new OverlayEventFilter); AddPreTargetHandler(overlay_filter_.get()); - AddShellObserver(overlay_filter_.get()); accelerator_filter_.reset(new ::wm::AcceleratorFilter( std::unique_ptr<::wm::AcceleratorDelegate>(new AcceleratorDelegate), @@ -975,8 +971,6 @@ power_button_controller_->OnDisplayModeChanged( display_configurator_->cached_displays()); - AddShellObserver(lock_state_controller_.get()); - // The connector is unavailable in some tests. if (config == Config::MASH && shell_delegate_->GetShellConnector()) { ui::mojom::UserActivityMonitorPtr user_activity_monitor; @@ -1233,17 +1227,9 @@ void Shell::OnLoginStatusChanged(LoginStatus login_status) { UpdateAfterLoginStatusChange(login_status); - - // TODO(xiyuan): Update OnLoginStateChanged -> OnLoginStatusChanged. - for (auto& observer : shell_observers_) - observer.OnLoginStateChanged(login_status); } void Shell::OnLockStateChanged(bool locked) { - // TODO(xiyuan): Convert OnLockStateChanged() ShellObservers to - // SessionStateObservers. - for (auto& observer : shell_observers_) - observer.OnLockStateChanged(locked); #ifndef NDEBUG // Make sure that there is no system modal in Lock layer when unlocked. if (!locked) {
diff --git a/ash/shell.h b/ash/shell.h index bfb2267..71eaef5 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -12,7 +12,7 @@ #include "ash/ash_export.h" #include "ash/metrics/user_metrics_recorder.h" #include "ash/public/cpp/shelf_types.h" -#include "ash/session/session_state_observer.h" +#include "ash/session/session_observer.h" #include "ash/wm/cursor_manager_chromeos.h" #include "ash/wm/system_modal_container_event_filter_delegate.h" #include "base/gtest_prod_util.h" @@ -189,7 +189,7 @@ // // Upon creation, the Shell sets itself as the RootWindow's delegate, which // takes ownership of the Shell. -class ASH_EXPORT Shell : public SessionStateObserver, +class ASH_EXPORT Shell : public SessionObserver, public SystemModalContainerEventFilterDelegate, public ui::EventTarget, public aura::client::ActivationChangeObserver { @@ -269,9 +269,6 @@ void SetDisplayWorkAreaInsets(aura::Window* window, const gfx::Insets& insets); - // Called when the application is exiting. - void OnAppTerminating(); - // Called when a casting session is started or stopped. void OnCastingSessionStartedOrStopped(bool started); @@ -631,7 +628,7 @@ aura::Window* gained_active, aura::Window* lost_active) override; - // SessionStateObserver: + // SessionObserver: void OnSessionStateChanged(session_manager::SessionState state) override; void OnLoginStatusChanged(LoginStatus login_status) override; void OnLockStateChanged(bool locked) override;
diff --git a/ash/shell/app_list.cc b/ash/shell/app_list.cc index 0cc998ba..5f4f95f0a2 100644 --- a/ash/shell/app_list.cc +++ b/ash/shell/app_list.cc
@@ -294,6 +294,8 @@ return std::vector<views::View*>(); } + views::View* GetSearchAnswerWebView() override { return nullptr; } + void CustomLauncherPageAnimationChanged(double progress) override {} void CustomLauncherPagePopSubpage() override {}
diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc index 0baaab39..0532775 100644 --- a/ash/shell/shell_delegate_impl.cc +++ b/ash/shell/shell_delegate_impl.cc
@@ -15,9 +15,9 @@ #include "ash/shell/context_menu.h" #include "ash/shell/example_factory.h" #include "ash/shell/toplevel_window.h" -#include "ash/system/tray/default_system_tray_delegate.h" #include "ash/test/test_keyboard_ui.h" #include "ash/test/test_shelf_delegate.h" +#include "ash/test/test_system_tray_delegate.h" #include "ash/wm/window_state.h" #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" @@ -127,7 +127,7 @@ } SystemTrayDelegate* ShellDelegateImpl::CreateSystemTrayDelegate() { - return new DefaultSystemTrayDelegate; + return new test::TestSystemTrayDelegate; } std::unique_ptr<WallpaperDelegate>
diff --git a/ash/shell_observer.h b/ash/shell_observer.h index f1def0e..53e8d5f 100644 --- a/ash/shell_observer.h +++ b/ash/shell_observer.h
@@ -14,16 +14,6 @@ class ASH_EXPORT ShellObserver { public: - // Invoked when the user logs in. - virtual void OnLoginStateChanged(LoginStatus status) {} - - // Invoked when the application is exiting. - virtual void OnAppTerminating() {} - - // Invoked when the screen is locked (after the lock window is visible) or - // unlocked. - virtual void OnLockStateChanged(bool locked) {} - // Called when a casting session is started or stopped. virtual void OnCastingSessionStartedOrStopped(bool started) {}
diff --git a/ash/system/bluetooth/tray_bluetooth.cc b/ash/system/bluetooth/tray_bluetooth.cc index 895dc594..d5c5b3fb 100644 --- a/ash/system/bluetooth/tray_bluetooth.cc +++ b/ash/system/bluetooth/tray_bluetooth.cc
@@ -482,13 +482,12 @@ TrayPopupUtils::CreateToggleButton(this, IDS_ASH_STATUS_TRAY_BLUETOOTH); tri_view()->AddView(TriView::Container::END, toggle_); - settings_ = - CreateSettingsButton(login_, IDS_ASH_STATUS_TRAY_BLUETOOTH_SETTINGS); + settings_ = CreateSettingsButton(IDS_ASH_STATUS_TRAY_BLUETOOTH_SETTINGS); tri_view()->AddView(TriView::Container::END, settings_); } void ShowSettings() { - if (TrayPopupUtils::CanOpenWebUISettings(login_)) { + if (TrayPopupUtils::CanOpenWebUISettings()) { Shell::Get()->system_tray_controller()->ShowBluetoothSettings(); owner()->system_tray()->CloseSystemBubble(); } @@ -573,6 +572,7 @@ } } + // TODO(jamescook): Don't cache this. LoginStatus login_; std::map<views::View*, std::string> device_map_;
diff --git a/ash/system/date/system_info_default_view.cc b/ash/system/date/system_info_default_view.cc index 2866a7f..9b11ab8e 100644 --- a/ash/system/date/system_info_default_view.cc +++ b/ash/system/date/system_info_default_view.cc
@@ -25,8 +25,7 @@ // horizontally. const int kMaxNumTileWidths = 3; -SystemInfoDefaultView::SystemInfoDefaultView(SystemTrayItem* owner, - LoginStatus login) +SystemInfoDefaultView::SystemInfoDefaultView(SystemTrayItem* owner) : date_view_(nullptr), tri_view_(TrayPopupUtils::CreateMultiTargetRowView()) { tri_view_->SetMinHeight(kTrayPopupSystemInfoRowHeight); @@ -54,7 +53,7 @@ } tri_view_->SetContainerVisible(TriView::Container::END, false); - if (TrayPopupUtils::CanOpenWebUISettings(login)) + if (TrayPopupUtils::CanOpenWebUISettings()) date_view_->SetAction(tray::DateView::DateAction::SHOW_DATE_SETTINGS); }
diff --git a/ash/system/date/system_info_default_view.h b/ash/system/date/system_info_default_view.h index 4143cac..1ba1c4fd 100644 --- a/ash/system/date/system_info_default_view.h +++ b/ash/system/date/system_info_default_view.h
@@ -6,7 +6,6 @@ #define ASH_SYSTEM_DATE_SYSTEM_INFO_DEFAULT_VIEW_H_ #include "ash/ash_export.h" -#include "ash/login_status.h" #include "base/macros.h" #include "ui/views/view.h" @@ -24,8 +23,7 @@ // power status. class ASH_EXPORT SystemInfoDefaultView : public views::View { public: - SystemInfoDefaultView(SystemTrayItem* owner, LoginStatus login); - + explicit SystemInfoDefaultView(SystemTrayItem* owner); ~SystemInfoDefaultView() override; tray::DateView* GetDateView();
diff --git a/ash/system/date/tray_system_info.cc b/ash/system/date/tray_system_info.cc index 4f407dc9..5014f9f7 100644 --- a/ash/system/date/tray_system_info.cc +++ b/ash/system/date/tray_system_info.cc
@@ -53,7 +53,7 @@ } views::View* TraySystemInfo::CreateDefaultView(LoginStatus status) { - default_view_ = new SystemInfoDefaultView(this, status); + default_view_ = new SystemInfoDefaultView(this); // Save the login status we created the view with. login_status_ = status;
diff --git a/ash/system/ime/tray_ime_chromeos.cc b/ash/system/ime/tray_ime_chromeos.cc index ee3524b2..67b9afc 100644 --- a/ash/system/ime/tray_ime_chromeos.cc +++ b/ash/system/ime/tray_ime_chromeos.cc
@@ -75,8 +75,8 @@ // enterprise-controlled icon). class IMEDetailedView : public ImeListView { public: - IMEDetailedView(SystemTrayItem* owner, LoginStatus login) - : ImeListView(owner), login_(login), settings_button_(nullptr) {} + explicit IMEDetailedView(SystemTrayItem* owner) + : ImeListView(owner), settings_button_(nullptr) {} ~IMEDetailedView() override {} @@ -119,8 +119,7 @@ } tri_view()->SetContainerVisible(TriView::Container::END, true); - settings_button_ = - CreateSettingsButton(login_, IDS_ASH_STATUS_TRAY_IME_SETTINGS); + settings_button_ = CreateSettingsButton(IDS_ASH_STATUS_TRAY_IME_SETTINGS); tri_view()->AddView(TriView::Container::END, settings_button_); } @@ -132,8 +131,6 @@ owner()->system_tray()->CloseSystemBubble(); } - LoginStatus login_; - views::Button* settings_button_; // This icon says that the IMEs are managed by policy. @@ -247,7 +244,7 @@ views::View* TrayIME::CreateDetailedView(LoginStatus status) { CHECK(detailed_ == NULL); - detailed_ = new tray::IMEDetailedView(this, status); + detailed_ = new tray::IMEDetailedView(this); detailed_->SetImeManagedMessage(ime_managed_message_); detailed_->Init(ShouldShowKeyboardToggle(), GetSingleImeBehavior()); return detailed_;
diff --git a/ash/system/ime_menu/ime_menu_tray.cc b/ash/system/ime_menu/ime_menu_tray.cc index daa09b1..7913d0f 100644 --- a/ash/system/ime_menu/ime_menu_tray.cc +++ b/ash/system/ime_menu/ime_menu_tray.cc
@@ -9,7 +9,7 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/resources/grit/ash_resources.h" #include "ash/root_window_controller.h" -#include "ash/session/session_state_delegate.h" +#include "ash/session/session_controller.h" #include "ash/shelf/wm_shelf.h" #include "ash/shelf/wm_shelf_util.h" #include "ash/shell.h" @@ -27,6 +27,7 @@ #include "ash/wm_window.h" #include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" +#include "components/session_manager/session_manager_types.h" #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ime/ime_bridge.h" #include "ui/base/ime/text_input_client.h" @@ -85,9 +86,11 @@ // Returns true if the current screen is login or lock screen. bool IsInLoginOrLockScreen() { - LoginStatus login = - Shell::Get()->system_tray_delegate()->GetUserLoginStatus(); - return !TrayPopupUtils::CanOpenWebUISettings(login); + using session_manager::SessionState; + SessionState state = Shell::Get()->session_controller()->GetSessionState(); + return state == SessionState::LOGIN_PRIMARY || + state == SessionState::LOCKED || + state == SessionState::LOGIN_SECONDARY; } // Returns true if the current input context type is password. @@ -150,7 +153,7 @@ if (show_settings_button) { settings_button_ = CreateImeMenuButton( this, kSystemMenuSettingsIcon, IDS_ASH_STATUS_TRAY_IME_SETTINGS, 0); - if (IsInLoginOrLockScreen()) + if (!TrayPopupUtils::CanOpenWebUISettings()) settings_button_->SetEnabled(false); AddChildView(settings_button_); } @@ -243,6 +246,8 @@ settings_button_ = CreateImeMenuButton(this, kSystemMenuSettingsIcon, IDS_ASH_STATUS_TRAY_IME_SETTINGS, 0); AddChildView(settings_button_); + if (!TrayPopupUtils::CanOpenWebUISettings()) + settings_button_->SetEnabled(false); } ImeMenuTray* ime_menu_tray_;
diff --git a/ash/system/overview/overview_button_tray.cc b/ash/system/overview/overview_button_tray.cc index 5102aa6..d07eeebeb 100644 --- a/ash/system/overview/overview_button_tray.cc +++ b/ash/system/overview/overview_button_tray.cc
@@ -22,7 +22,9 @@ namespace ash { OverviewButtonTray::OverviewButtonTray(WmShelf* wm_shelf) - : TrayBackgroundView(wm_shelf, true), icon_(new views::ImageView()) { + : TrayBackgroundView(wm_shelf, true), + icon_(new views::ImageView()), + scoped_session_observer_(this) { SetInkDropMode(InkDropMode::ON); icon_->SetImage(CreateVectorIcon(kShelfOverviewIcon, kShelfIconColor)); @@ -34,12 +36,10 @@ set_separator_visibility(false); Shell::Get()->AddShellObserver(this); - Shell::Get()->session_controller()->AddSessionStateObserver(this); } OverviewButtonTray::~OverviewButtonTray() { Shell::Get()->RemoveShellObserver(this); - Shell::Get()->session_controller()->RemoveSessionStateObserver(this); } void OverviewButtonTray::UpdateAfterLoginStatusChange(LoginStatus status) {
diff --git a/ash/system/overview/overview_button_tray.h b/ash/system/overview/overview_button_tray.h index 35a96d3e..5b82d4d 100644 --- a/ash/system/overview/overview_button_tray.h +++ b/ash/system/overview/overview_button_tray.h
@@ -6,7 +6,7 @@ #define ASH_SYSTEM_OVERVIEW_OVERVIEW_BUTTON_TRAY_H_ #include "ash/ash_export.h" -#include "ash/session/session_state_observer.h" +#include "ash/session/session_observer.h" #include "ash/shell_observer.h" #include "ash/system/tray/tray_background_view.h" #include "base/macros.h" @@ -23,7 +23,7 @@ // This tray will only be visible while in this state. This tray does not // provide any bubble view windows. class ASH_EXPORT OverviewButtonTray : public TrayBackgroundView, - public SessionStateObserver, + public SessionObserver, public ShellObserver { public: explicit OverviewButtonTray(WmShelf* wm_shelf); @@ -36,7 +36,7 @@ // ActionableView: bool PerformAction(const ui::Event& event) override; - // SessionStateObserver: + // SessionObserver: void OnSessionStateChanged(session_manager::SessionState state) override; // ShellObserver: @@ -65,6 +65,8 @@ // Weak pointer, will be parented by TrayContainer for its lifetime. views::ImageView* icon_; + ScopedSessionObserver scoped_session_observer_; + DISALLOW_COPY_AND_ASSIGN(OverviewButtonTray); };
diff --git a/ash/system/palette/palette_tray.cc b/ash/system/palette/palette_tray.cc index ef18de1..98323e0c 100644 --- a/ash/system/palette/palette_tray.cc +++ b/ash/system/palette/palette_tray.cc
@@ -130,6 +130,7 @@ PaletteTray::PaletteTray(WmShelf* wm_shelf) : TrayBackgroundView(wm_shelf, true), palette_tool_manager_(new PaletteToolManager(this)), + scoped_session_observer_(this), weak_factory_(this) { PaletteTool::RegisterToolInstances(palette_tool_manager_.get()); @@ -142,7 +143,6 @@ tray_container()->AddChildView(icon_); Shell::Get()->AddShellObserver(this); - Shell::Get()->session_controller()->AddSessionStateObserver(this); ui::InputDeviceManager::GetInstance()->AddObserver(this); } @@ -152,7 +152,6 @@ ui::InputDeviceManager::GetInstance()->RemoveObserver(this); Shell::Get()->RemoveShellObserver(this); - Shell::Get()->session_controller()->RemoveSessionStateObserver(this); } bool PaletteTray::PerformAction(const ui::Event& event) {
diff --git a/ash/system/palette/palette_tray.h b/ash/system/palette/palette_tray.h index d5ca55bb..9faa389 100644 --- a/ash/system/palette/palette_tray.h +++ b/ash/system/palette/palette_tray.h
@@ -10,7 +10,7 @@ #include "ash/ash_export.h" #include "ash/palette_delegate.h" -#include "ash/session/session_state_observer.h" +#include "ash/session/session_observer.h" #include "ash/shell_observer.h" #include "ash/system/palette/palette_tool_manager.h" #include "ash/system/tray/tray_background_view.h" @@ -36,7 +36,7 @@ // class also controls the lifetime for all of the tools available in the // palette. class ASH_EXPORT PaletteTray : public TrayBackgroundView, - public SessionStateObserver, + public SessionObserver, public ShellObserver, public PaletteToolManager::Delegate, public ui::InputDeviceEventObserver, @@ -48,7 +48,7 @@ // ActionableView: bool PerformAction(const ui::Event& event) override; - // SessionStateObserver: + // SessionObserver: void OnSessionStateChanged(session_manager::SessionState state) override; // ShellObserver: @@ -134,6 +134,8 @@ // Number of actions in pen palette bubble. int num_actions_in_bubble_ = 0; + ScopedSessionObserver scoped_session_observer_; + base::WeakPtrFactory<PaletteTray> weak_factory_; DISALLOW_COPY_AND_ASSIGN(PaletteTray);
diff --git a/ash/system/power/tablet_power_button_controller_unittest.cc b/ash/system/power/tablet_power_button_controller_unittest.cc index ea5cb6b1..df64eba 100644 --- a/ash/system/power/tablet_power_button_controller_unittest.cc +++ b/ash/system/power/tablet_power_button_controller_unittest.cc
@@ -99,9 +99,7 @@ } void Initialize(LoginStatus status) { - lock_state_controller_->OnLoginStateChanged(status); SetUserLoggedIn(status != LoginStatus::NOT_LOGGED_IN); - lock_state_controller_->OnLockStateChanged(false); } void EnableMaximizeMode(bool enabled) {
diff --git a/ash/system/power/video_activity_notifier.cc b/ash/system/power/video_activity_notifier.cc index e757a20..5b9bd97 100644 --- a/ash/system/power/video_activity_notifier.cc +++ b/ash/system/power/video_activity_notifier.cc
@@ -22,16 +22,15 @@ VideoActivityNotifier::VideoActivityNotifier(VideoDetector* detector) : detector_(detector), video_state_(detector->state()), - screen_is_locked_(Shell::Get()->session_controller()->IsScreenLocked()) { + screen_is_locked_(Shell::Get()->session_controller()->IsScreenLocked()), + scoped_session_observer_(this) { detector_->AddObserver(this); - Shell::Get()->AddShellObserver(this); MaybeNotifyPowerManager(); UpdateTimer(); } VideoActivityNotifier::~VideoActivityNotifier() { - Shell::Get()->RemoveShellObserver(this); detector_->RemoveObserver(this); } @@ -44,11 +43,12 @@ } void VideoActivityNotifier::OnLockStateChanged(bool locked) { - if (screen_is_locked_ != locked) { - screen_is_locked_ = locked; - MaybeNotifyPowerManager(); - UpdateTimer(); - } + if (screen_is_locked_ == locked) + return; + + screen_is_locked_ = locked; + MaybeNotifyPowerManager(); + UpdateTimer(); } bool VideoActivityNotifier::TriggerTimeoutForTest() {
diff --git a/ash/system/power/video_activity_notifier.h b/ash/system/power/video_activity_notifier.h index a3b378d..d93cb32 100644 --- a/ash/system/power/video_activity_notifier.h +++ b/ash/system/power/video_activity_notifier.h
@@ -6,6 +6,7 @@ #define ASH_SYSTEM_POWER_VIDEO_ACTIVITY_NOTIFIER_H_ #include "ash/ash_export.h" +#include "ash/session/session_observer.h" #include "ash/wm/video_detector.h" #include "base/compiler_specific.h" #include "base/macros.h" @@ -15,7 +16,7 @@ // Notifies the power manager when a video is playing. class ASH_EXPORT VideoActivityNotifier : public VideoDetector::Observer, - public ShellObserver { + public SessionObserver { public: explicit VideoActivityNotifier(VideoDetector* detector); ~VideoActivityNotifier() override; @@ -23,7 +24,7 @@ // VideoDetector::Observer implementation. void OnVideoStateChanged(VideoDetector::State state) override; - // ShellObserver implementation. + // SessionObserver implementation. void OnLockStateChanged(bool locked) override; // If |notify_timer_| is running, calls MaybeNotifyPowerManager() and returns @@ -55,6 +56,8 @@ // should_notify_power_manager() is true. base::RepeatingTimer notify_timer_; + ScopedSessionObserver scoped_session_observer_; + DISALLOW_COPY_AND_ASSIGN(VideoActivityNotifier); };
diff --git a/ash/system/session/logout_confirmation_controller.cc b/ash/system/session/logout_confirmation_controller.cc index 5ea8d63..d3b29cf 100644 --- a/ash/system/session/logout_confirmation_controller.cc +++ b/ash/system/session/logout_confirmation_controller.cc
@@ -7,6 +7,7 @@ #include <utility> #include "ash/login_status.h" +#include "ash/session/session_controller.h" #include "ash/shell.h" #include "ash/system/session/logout_confirmation_dialog.h" #include "ash/system/tray/system_tray_delegate.h" @@ -26,18 +27,16 @@ : clock_(new base::DefaultTickClock), logout_closure_(logout_closure), dialog_(NULL), - logout_timer_(false, false) { - if (Shell::HasInstance()) { - Shell::Get()->AddShellObserver(this); + logout_timer_(false, false), + scoped_session_observer_(this) { + if (Shell::HasInstance()) Shell::Get()->system_tray_notifier()->AddLastWindowClosedObserver(this); - } } LogoutConfirmationController::~LogoutConfirmationController() { - if (Shell::HasInstance()) { - Shell::Get()->RemoveShellObserver(this); + if (Shell::HasInstance()) Shell::Get()->system_tray_notifier()->RemoveLastWindowClosedObserver(this); - } + if (dialog_) dialog_->ControllerGone(); }
diff --git a/ash/system/session/logout_confirmation_controller.h b/ash/system/session/logout_confirmation_controller.h index ba2f9b5..eb04e2c 100644 --- a/ash/system/session/logout_confirmation_controller.h +++ b/ash/system/session/logout_confirmation_controller.h
@@ -8,7 +8,7 @@ #include <memory> #include "ash/ash_export.h" -#include "ash/shell_observer.h" +#include "ash/session/session_observer.h" #include "ash/system/session/last_window_closed_observer.h" #include "base/callback.h" #include "base/macros.h" @@ -34,7 +34,7 @@ // In public sessions, asks the user to end the session when the last window is // closed. class ASH_EXPORT LogoutConfirmationController - : public ShellObserver, + : public SessionObserver, public LastWindowClosedObserver { public: // The |logout_closure| must be safe to call as long as |this| is alive. @@ -50,7 +50,7 @@ void SetClockForTesting(std::unique_ptr<base::TickClock> clock); - // ShellObserver: + // SessionObserver: void OnLockStateChanged(bool locked) override; // Called by the |dialog_| when the user confirms logout. @@ -72,6 +72,8 @@ LogoutConfirmationDialog* dialog_; // Owned by the Views hierarchy. base::Timer logout_timer_; + ScopedSessionObserver scoped_session_observer_; + DISALLOW_COPY_AND_ASSIGN(LogoutConfirmationController); };
diff --git a/ash/system/tiles/tiles_default_view.cc b/ash/system/tiles/tiles_default_view.cc index 216d1b7c..d5c51a7 100644 --- a/ash/system/tiles/tiles_default_view.cc +++ b/ash/system/tiles/tiles_default_view.cc
@@ -37,15 +37,16 @@ namespace ash { -TilesDefaultView::TilesDefaultView(SystemTrayItem* owner, LoginStatus login) +TilesDefaultView::TilesDefaultView(SystemTrayItem* owner) : owner_(owner), - login_(login), settings_button_(nullptr), help_button_(nullptr), lock_button_(nullptr), - power_button_(nullptr) {} + power_button_(nullptr) { + DCHECK(owner_); +} -TilesDefaultView::~TilesDefaultView() {} +TilesDefaultView::~TilesDefaultView() = default; void TilesDefaultView::Init() { views::BoxLayout* box_layout = @@ -59,13 +60,12 @@ // Show the buttons in this row as disabled if the user is at the login // screen, lock screen, or in a secondary account flow. The exception is // |power_button_| which is always shown as enabled. - const bool disable_buttons = !TrayPopupUtils::CanOpenWebUISettings(login_); + const bool disable_buttons = !TrayPopupUtils::CanOpenWebUISettings(); settings_button_ = new SystemMenuButton( this, TrayPopupInkDropStyle::HOST_CENTERED, kSystemMenuSettingsIcon, IDS_ASH_STATUS_TRAY_SETTINGS); - if (disable_buttons || - !Shell::Get()->session_controller()->ShouldEnableSettings()) + if (disable_buttons) settings_button_->SetEnabled(false); AddChildView(settings_button_); AddChildView(TrayPopupUtils::CreateVerticalSeparator());
diff --git a/ash/system/tiles/tiles_default_view.h b/ash/system/tiles/tiles_default_view.h index 075e7aa..d6fe3a8a8 100644 --- a/ash/system/tiles/tiles_default_view.h +++ b/ash/system/tiles/tiles_default_view.h
@@ -6,7 +6,6 @@ #define ASH_SYSTEM_TILES_TILES_DEFAULT_VIEW_H_ #include "ash/ash_export.h" -#include "ash/login_status.h" #include "base/macros.h" #include "ui/views/controls/button/button.h" #include "ui/views/view.h" @@ -23,7 +22,7 @@ class ASH_EXPORT TilesDefaultView : public views::View, public views::ButtonListener { public: - TilesDefaultView(SystemTrayItem* owner, LoginStatus login); + explicit TilesDefaultView(SystemTrayItem* owner); ~TilesDefaultView() override; // Sets the layout manager and child views of |this|. @@ -43,7 +42,6 @@ friend class TrayTilesTest; SystemTrayItem* owner_; - LoginStatus login_; // Pointers to the child buttons of |this|. Note that some buttons may not // exist (depending on the user's current login status, for instance), in
diff --git a/ash/system/tiles/tray_tiles.cc b/ash/system/tiles/tray_tiles.cc index 360c852..60e9024f 100644 --- a/ash/system/tiles/tray_tiles.cc +++ b/ash/system/tiles/tray_tiles.cc
@@ -5,7 +5,6 @@ #include "ash/system/tiles/tray_tiles.h" #include "ash/metrics/user_metrics_action.h" -#include "ash/session/session_state_delegate.h" #include "ash/system/tiles/tiles_default_view.h" namespace ash { @@ -25,13 +24,14 @@ return default_view_; } -views::View* TrayTiles::CreateDefaultViewForTesting(LoginStatus status) { - return CreateDefaultView(status); +views::View* TrayTiles::CreateDefaultViewForTesting() { + // Login status is unused. + return CreateDefaultView(LoginStatus::USER); } views::View* TrayTiles::CreateDefaultView(LoginStatus status) { CHECK(default_view_ == nullptr); - default_view_ = new TilesDefaultView(this, status); + default_view_ = new TilesDefaultView(this); default_view_->Init(); return default_view_; }
diff --git a/ash/system/tiles/tray_tiles.h b/ash/system/tiles/tray_tiles.h index a1c1f629..6100a2c 100644 --- a/ash/system/tiles/tray_tiles.h +++ b/ash/system/tiles/tray_tiles.h
@@ -25,7 +25,7 @@ views::View* GetHelpButtonView() const; TilesDefaultView* GetDefaultViewForTesting() const; - views::View* CreateDefaultViewForTesting(LoginStatus status); + views::View* CreateDefaultViewForTesting(); private: friend class TrayTilesTest;
diff --git a/ash/system/tiles/tray_tiles_unittest.cc b/ash/system/tiles/tray_tiles_unittest.cc index ba6721a..afee1f0 100644 --- a/ash/system/tiles/tray_tiles_unittest.cc +++ b/ash/system/tiles/tray_tiles_unittest.cc
@@ -4,28 +4,30 @@ #include "ash/system/tiles/tray_tiles.h" -#include "ash/session/session_state_delegate.h" -#include "ash/shell_port.h" #include "ash/system/tiles/tiles_default_view.h" #include "ash/test/ash_test_base.h" +#include "ash/test/test_session_controller_client.h" #include "ui/views/controls/button/custom_button.h" #include "ui/views/view.h" +using views::Button; + namespace ash { -class TrayTilesTest : public test::AshTestBase { +// Tests manually control their session state. +class TrayTilesTest : public test::NoSessionAshTestBase { public: TrayTilesTest() {} ~TrayTilesTest() override {} void SetUp() override { - test::AshTestBase::SetUp(); + test::NoSessionAshTestBase::SetUp(); tray_tiles_.reset(new TrayTiles(GetPrimarySystemTray())); } void TearDown() override { tray_tiles_.reset(); - test::AshTestBase::TearDown(); + test::NoSessionAshTestBase::TearDown(); } views::CustomButton* GetSettingsButton() { @@ -52,41 +54,61 @@ DISALLOW_COPY_AND_ASSIGN(TrayTilesTest); }; -TEST_F(TrayTilesTest, ButtonStatesWithAddingUser) { +// Settings buttons are disabled before login. +TEST_F(TrayTilesTest, ButtonStatesNotLoggedIn) { + std::unique_ptr<views::View> default_view( + tray_tiles()->CreateDefaultViewForTesting()); + EXPECT_EQ(Button::STATE_DISABLED, GetSettingsButton()->state()); + EXPECT_EQ(Button::STATE_DISABLED, GetHelpButton()->state()); + EXPECT_EQ(Button::STATE_DISABLED, GetLockButton()->state()); + EXPECT_EQ(Button::STATE_NORMAL, GetPowerButton()->state()); +} + +// All buttons are enabled after login. +TEST_F(TrayTilesTest, ButtonStatesLoggedIn) { + SetSessionStarted(true); + std::unique_ptr<views::View> default_view( + tray_tiles()->CreateDefaultViewForTesting()); + EXPECT_EQ(Button::STATE_NORMAL, GetSettingsButton()->state()); + EXPECT_EQ(Button::STATE_NORMAL, GetHelpButton()->state()); + EXPECT_EQ(Button::STATE_NORMAL, GetLockButton()->state()); + EXPECT_EQ(Button::STATE_NORMAL, GetPowerButton()->state()); +} + +// Settings buttons are disabled at the lock screen. +TEST_F(TrayTilesTest, ButtonStatesLockScreen) { + BlockUserSession(BLOCKED_BY_LOCK_SCREEN); + std::unique_ptr<views::View> default_view( + tray_tiles()->CreateDefaultViewForTesting()); + EXPECT_EQ(Button::STATE_DISABLED, GetSettingsButton()->state()); + EXPECT_EQ(Button::STATE_DISABLED, GetHelpButton()->state()); + EXPECT_EQ(Button::STATE_DISABLED, GetLockButton()->state()); + EXPECT_EQ(Button::STATE_NORMAL, GetPowerButton()->state()); +} + +// Settings buttons are disabled when adding a second multiprofile user. +TEST_F(TrayTilesTest, ButtonStatesAddingUser) { SetUserAddingScreenRunning(true); std::unique_ptr<views::View> default_view( - tray_tiles()->CreateDefaultViewForTesting(LoginStatus::USER)); - EXPECT_EQ(GetSettingsButton()->state(), views::Button::STATE_DISABLED); - EXPECT_EQ(GetHelpButton()->state(), views::Button::STATE_DISABLED); - EXPECT_EQ(GetLockButton()->state(), views::Button::STATE_DISABLED); - EXPECT_EQ(GetPowerButton()->state(), views::Button::STATE_NORMAL); + tray_tiles()->CreateDefaultViewForTesting()); + EXPECT_EQ(Button::STATE_DISABLED, GetSettingsButton()->state()); + EXPECT_EQ(Button::STATE_DISABLED, GetHelpButton()->state()); + EXPECT_EQ(Button::STATE_DISABLED, GetLockButton()->state()); + EXPECT_EQ(Button::STATE_NORMAL, GetPowerButton()->state()); } -TEST_F(TrayTilesTest, ButtonStatesWithLoginStatusNotLoggedIn) { +// Settings buttons are disabled when adding a supervised user. +TEST_F(TrayTilesTest, ButtonStatesSupervisedUserFlow) { + // Simulate a supervised user session with disabled settings. + const bool enable_settings = false; + GetSessionControllerClient()->AddUserSession("foo@example.com", + enable_settings); std::unique_ptr<views::View> default_view( - tray_tiles()->CreateDefaultViewForTesting(LoginStatus::NOT_LOGGED_IN)); - EXPECT_EQ(GetSettingsButton()->state(), views::Button::STATE_DISABLED); - EXPECT_EQ(GetHelpButton()->state(), views::Button::STATE_DISABLED); - EXPECT_EQ(GetLockButton()->state(), views::Button::STATE_DISABLED); - EXPECT_EQ(GetPowerButton()->state(), views::Button::STATE_NORMAL); -} - -TEST_F(TrayTilesTest, ButtonStatesWithLoginStatusLocked) { - std::unique_ptr<views::View> default_view( - tray_tiles()->CreateDefaultViewForTesting(LoginStatus::LOCKED)); - EXPECT_EQ(GetSettingsButton()->state(), views::Button::STATE_DISABLED); - EXPECT_EQ(GetHelpButton()->state(), views::Button::STATE_DISABLED); - EXPECT_EQ(GetLockButton()->state(), views::Button::STATE_DISABLED); - EXPECT_EQ(GetPowerButton()->state(), views::Button::STATE_NORMAL); -} - -TEST_F(TrayTilesTest, ButtonStatesWithLoginStatusUser) { - std::unique_ptr<views::View> default_view( - tray_tiles()->CreateDefaultViewForTesting(LoginStatus::USER)); - EXPECT_EQ(GetSettingsButton()->state(), views::Button::STATE_NORMAL); - EXPECT_EQ(GetHelpButton()->state(), views::Button::STATE_NORMAL); - EXPECT_EQ(GetLockButton()->state(), views::Button::STATE_NORMAL); - EXPECT_EQ(GetPowerButton()->state(), views::Button::STATE_NORMAL); + tray_tiles()->CreateDefaultViewForTesting()); + EXPECT_EQ(Button::STATE_DISABLED, GetSettingsButton()->state()); + EXPECT_EQ(Button::STATE_DISABLED, GetHelpButton()->state()); + EXPECT_EQ(Button::STATE_DISABLED, GetLockButton()->state()); + EXPECT_EQ(Button::STATE_NORMAL, GetPowerButton()->state()); } } // namespace ash
diff --git a/ash/system/tray/default_system_tray_delegate.cc b/ash/system/tray/default_system_tray_delegate.cc deleted file mode 100644 index fa8bfd9..0000000 --- a/ash/system/tray/default_system_tray_delegate.cc +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/system/tray/default_system_tray_delegate.h" - -#include <string> - -namespace ash { - -DefaultSystemTrayDelegate::DefaultSystemTrayDelegate() {} - -DefaultSystemTrayDelegate::~DefaultSystemTrayDelegate() {} - -LoginStatus DefaultSystemTrayDelegate::GetUserLoginStatus() const { - return LoginStatus::USER; -} - -std::string DefaultSystemTrayDelegate::GetSupervisedUserManager() const { - if (!IsUserSupervised()) - return std::string(); - return "manager@chrome.com"; -} - -bool DefaultSystemTrayDelegate::IsUserSupervised() const { - return GetUserLoginStatus() == LoginStatus::SUPERVISED; -} - -} // namespace ash
diff --git a/ash/system/tray/default_system_tray_delegate.h b/ash/system/tray/default_system_tray_delegate.h deleted file mode 100644 index 461f353..0000000 --- a/ash/system/tray/default_system_tray_delegate.h +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_SYSTEM_TRAY_DEFAULT_SYSTEM_TRAY_DELEGATE_H_ -#define ASH_SYSTEM_TRAY_DEFAULT_SYSTEM_TRAY_DELEGATE_H_ - -#include "ash/ash_export.h" -#include "ash/system/tray/system_tray_delegate.h" -#include "base/macros.h" - -namespace ash { - -class ASH_EXPORT DefaultSystemTrayDelegate : public SystemTrayDelegate { - public: - DefaultSystemTrayDelegate(); - ~DefaultSystemTrayDelegate() override; - - // SystemTrayDelegate: - LoginStatus GetUserLoginStatus() const override; - std::string GetSupervisedUserManager() const override; - bool IsUserSupervised() const override; - - private: - DISALLOW_COPY_AND_ASSIGN(DefaultSystemTrayDelegate); -}; - -} // namespace ash - -#endif // ASH_SYSTEM_TRAY_DEFAULT_SYSTEM_TRAY_DELEGATE_H_
diff --git a/ash/system/tray/system_tray_delegate.h b/ash/system/tray/system_tray_delegate.h index 8cb3f2c..9980cbb 100644 --- a/ash/system/tray/system_tray_delegate.h +++ b/ash/system/tray/system_tray_delegate.h
@@ -121,7 +121,7 @@ // The active user has been changed. This will be called when the UI is ready // to be switched to the new user. - // Note: This will happen after SessionStateObserver::ActiveUserChanged fires. + // Note: This will happen after SessionObserver::ActiveUserChanged fires. virtual void ActiveUserWasChanged(); // Returns true when the Search key is configured to be treated as Caps Lock.
diff --git a/ash/system/tray/tray_details_view.cc b/ash/system/tray/tray_details_view.cc index 9ae56da2..fee3c72 100644 --- a/ash/system/tray/tray_details_view.cc +++ b/ash/system/tray/tray_details_view.cc
@@ -326,21 +326,21 @@ } views::CustomButton* TrayDetailsView::CreateSettingsButton( - LoginStatus status, int setting_accessible_name_id) { SystemMenuButton* button = new SystemMenuButton(this, TrayPopupInkDropStyle::HOST_CENTERED, kSystemMenuSettingsIcon, setting_accessible_name_id); - if (!TrayPopupUtils::CanOpenWebUISettings(status)) + if (!TrayPopupUtils::CanOpenWebUISettings()) button->SetEnabled(false); return button; } -views::CustomButton* TrayDetailsView::CreateHelpButton(LoginStatus status) { +views::CustomButton* TrayDetailsView::CreateHelpButton() { SystemMenuButton* button = new SystemMenuButton(this, TrayPopupInkDropStyle::HOST_CENTERED, kSystemMenuHelpIcon, IDS_ASH_STATUS_TRAY_HELP); - if (!TrayPopupUtils::CanOpenWebUISettings(status)) + // Help opens a web page, so treat it like Web UI settings. + if (!TrayPopupUtils::CanOpenWebUISettings()) button->SetEnabled(false); return button; }
diff --git a/ash/system/tray/tray_details_view.h b/ash/system/tray/tray_details_view.h index 42a65b2..f7f30f4 100644 --- a/ash/system/tray/tray_details_view.h +++ b/ash/system/tray/tray_details_view.h
@@ -8,7 +8,6 @@ #include <memory> #include "ash/ash_export.h" -#include "ash/login_status.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/view_click_listener.h" #include "base/macros.h" @@ -79,9 +78,8 @@ // Helper functions which create and return the settings and help buttons, // respectively, used in the material design top-most header row. The caller // assumes ownership of the returned buttons. - views::CustomButton* CreateSettingsButton(LoginStatus status, - int setting_accessible_name_id); - views::CustomButton* CreateHelpButton(LoginStatus status); + views::CustomButton* CreateSettingsButton(int setting_accessible_name_id); + views::CustomButton* CreateHelpButton(); TriView* tri_view() { return tri_view_; }
diff --git a/ash/system/tray/tray_popup_utils.cc b/ash/system/tray/tray_popup_utils.cc index 64fa187..c2d5237d9 100644 --- a/ash/system/tray/tray_popup_utils.cc +++ b/ash/system/tray/tray_popup_utils.cc
@@ -427,13 +427,8 @@ return separator; } -bool TrayPopupUtils::CanOpenWebUISettings(LoginStatus status) { - // TODO(tdanderson): Consider moving this into ShellPort, or introduce a - // CanShowSettings() method in each delegate type that has a - // ShowSettings() method. - return status != LoginStatus::NOT_LOGGED_IN && - status != LoginStatus::LOCKED && - !Shell::Get()->session_controller()->IsInSecondaryLoginScreen(); +bool TrayPopupUtils::CanOpenWebUISettings() { + return Shell::Get()->session_controller()->ShouldEnableSettings(); } void TrayPopupUtils::InitializeAsCheckableRow(HoverHighlightView* container,
diff --git a/ash/system/tray/tray_popup_utils.h b/ash/system/tray/tray_popup_utils.h index 83dd125..a839061 100644 --- a/ash/system/tray/tray_popup_utils.h +++ b/ash/system/tray/tray_popup_utils.h
@@ -200,9 +200,9 @@ static views::Separator* CreateListSubHeaderSeparator(); // Returns true if it is possible to open WebUI settings in a browser window, - // i.e., the user is logged in, not on the lock screen, and not in a secondary - // account flow. - static bool CanOpenWebUISettings(LoginStatus status); + // i.e. the user is logged in, not on the lock screen, not adding a secondary + // user, and not in the supervised user creation flow. + static bool CanOpenWebUISettings(); // Initializes a row in the system menu as checkable and update the check mark // status of this row.
diff --git a/ash/system/tray_accessibility.cc b/ash/system/tray_accessibility.cc index 3d042c2f..bf12a2d 100644 --- a/ash/system/tray_accessibility.cc +++ b/ash/system/tray_accessibility.cc
@@ -203,10 +203,8 @@ //////////////////////////////////////////////////////////////////////////////// // ash::tray::AccessibilityDetailedView -AccessibilityDetailedView::AccessibilityDetailedView(SystemTrayItem* owner, - LoginStatus login) - : TrayDetailsView(owner), - login_(login) { +AccessibilityDetailedView::AccessibilityDetailedView(SystemTrayItem* owner) + : TrayDetailsView(owner) { Reset(); AppendAccessibilityList(); CreateTitleRow(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_TITLE); @@ -415,22 +413,22 @@ tri_view()->SetContainerVisible(TriView::Container::END, true); - help_view_ = CreateHelpButton(login_); + help_view_ = CreateHelpButton(); settings_view_ = - CreateSettingsButton(login_, IDS_ASH_STATUS_TRAY_ACCESSIBILITY_SETTINGS); + CreateSettingsButton(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_SETTINGS); tri_view()->AddView(TriView::Container::END, help_view_); tri_view()->AddView(TriView::Container::END, settings_view_); } void AccessibilityDetailedView::ShowSettings() { - if (TrayPopupUtils::CanOpenWebUISettings(login_)) { + if (TrayPopupUtils::CanOpenWebUISettings()) { Shell::Get()->system_tray_controller()->ShowAccessibilitySettings(); owner()->system_tray()->CloseSystemBubble(); } } void AccessibilityDetailedView::ShowHelp() { - if (TrayPopupUtils::CanOpenWebUISettings(login_)) { + if (TrayPopupUtils::CanOpenWebUISettings()) { Shell::Get()->system_tray_controller()->ShowAccessibilityHelp(); owner()->system_tray()->CloseSystemBubble(); } @@ -468,7 +466,7 @@ } tray::AccessibilityDetailedView* TrayAccessibility::CreateDetailedMenu() { - return new tray::AccessibilityDetailedView(this, login_); + return new tray::AccessibilityDetailedView(this); } bool TrayAccessibility::GetInitialVisibility() {
diff --git a/ash/system/tray_accessibility.h b/ash/system/tray_accessibility.h index fdca228..e3a2e1a6 100644 --- a/ash/system/tray_accessibility.h +++ b/ash/system/tray_accessibility.h
@@ -63,7 +63,7 @@ class AccessibilityDetailedView : public TrayDetailsView, public ShellObserver { public: - AccessibilityDetailedView(SystemTrayItem* owner, LoginStatus login); + explicit AccessibilityDetailedView(SystemTrayItem* owner); ~AccessibilityDetailedView() override {} private:
diff --git a/ash/system/user/tray_user.h b/ash/system/user/tray_user.h index ceffa7e..35461e6 100644 --- a/ash/system/user/tray_user.h +++ b/ash/system/user/tray_user.h
@@ -7,7 +7,7 @@ #include "ash/ash_export.h" #include "ash/public/cpp/session_types.h" -#include "ash/session/session_state_observer.h" +#include "ash/session/session_observer.h" #include "ash/system/tray/system_tray_item.h" #include "base/macros.h" @@ -27,7 +27,7 @@ class UserView; } -class ASH_EXPORT TrayUser : public SystemTrayItem, public SessionStateObserver { +class ASH_EXPORT TrayUser : public SystemTrayItem, public SessionObserver { public: // The given |index| is the user index in a multi profile scenario. Index #0 // is the active user, the other indices are other logged in users (if there @@ -69,7 +69,7 @@ void UpdateAfterLoginStatusChange(LoginStatus status) override; void UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) override; - // Overridden from SessionStateObserver. + // Overridden from SessionObserver. void OnActiveUserSessionChanged(const AccountId& account_id) override; void OnUserSessionAdded(const AccountId& account_id) override; void OnUserSessionUpdated(const AccountId& account_id) override; @@ -79,7 +79,7 @@ // Updates the layout of this item. void UpdateLayoutOfItem(); - ScopedSessionStateObserver scoped_session_observer_; + ScopedSessionObserver scoped_session_observer_; // The user index to use. const UserIndex user_index_;
diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc index b319cd83..47422979 100644 --- a/ash/test/ash_test_base.cc +++ b/ash/test/ash_test_base.cc
@@ -153,7 +153,7 @@ void AshTestBase::TearDown() { teardown_called_ = true; - Shell::Get()->OnAppTerminating(); + Shell::Get()->session_controller()->NotifyChromeTerminating(); // Flush the message loop to finish pending release tasks. RunAllPendingInMessageLoop(); @@ -233,6 +233,15 @@ return widget; } +std::unique_ptr<aura::Window> AshTestBase::CreateTestWindow( + const gfx::Rect& bounds_in_screen, + ui::wm::WindowType type, + int shell_window_id) { + return base::WrapUnique<aura::Window>( + CreateTestWindowInShellWithDelegateAndType(nullptr, type, shell_window_id, + bounds_in_screen)); +} + aura::Window* AshTestBase::CreateTestWindowInShellWithId(int id) { return CreateTestWindowInShellWithDelegate(NULL, id, gfx::Rect()); }
diff --git a/ash/test/ash_test_base.h b/ash/test/ash_test_base.h index 4837d39..6201cc5 100644 --- a/ash/test/ash_test_base.h +++ b/ash/test/ash_test_base.h
@@ -92,6 +92,17 @@ int container_id, const gfx::Rect& bounds); + // Creates a visible window in the appropriate container. If + // |bounds_in_screen| is empty the window is added to the primary root + // window, otherwise the window is added to the display matching + // |bounds_in_screen|. |shell_window_id| is the shell window id to give to + // the new window. + // TODO(sky): convert existing CreateTestWindow() functions into this one. + std::unique_ptr<aura::Window> CreateTestWindow( + const gfx::Rect& bounds_in_screen = gfx::Rect(), + ui::wm::WindowType type = ui::wm::WINDOW_TYPE_NORMAL, + int shell_window_id = kShellWindowId_Invalid); + // Versions of the functions in aura::test:: that go through our shell // StackingController instead of taking a parent. aura::Window* CreateTestWindowInShellWithId(int id);
diff --git a/ash/test/test_session_controller_client.cc b/ash/test/test_session_controller_client.cc index 5d907cc90..6492a7c 100644 --- a/ash/test/test_session_controller_client.cc +++ b/ash/test/test_session_controller_client.cc
@@ -96,7 +96,8 @@ } void TestSessionControllerClient::AddUserSession( - const std::string& display_email) { + const std::string& display_email, + bool enable_settings) { mojom::UserSessionPtr session = mojom::UserSession::New(); session->session_id = ++fake_session_id_; session->type = user_manager::USER_TYPE_REGULAR; @@ -104,7 +105,7 @@ AccountId::FromUserEmail(GetUserIdFromEmail(display_email)); session->display_name = "Über tray Über tray Über tray Über tray"; session->display_email = display_email; - session->should_enable_settings = true; + session->should_enable_settings = enable_settings; session->should_show_notification_tray = true; controller_->UpdateUserSession(std::move(session)); }
diff --git a/ash/test/test_session_controller_client.h b/ash/test/test_session_controller_client.h index 0163bb2..6524a9e 100644 --- a/ash/test/test_session_controller_client.h +++ b/ash/test/test_session_controller_client.h
@@ -50,8 +50,10 @@ void CreatePredefinedUserSessions(int count); // Adds a user session from a given display email. The display email will be - // canonicalized and used to construct an AccountId. - void AddUserSession(const std::string& display_email); + // canonicalized and used to construct an AccountId. |enable_settings| sets + // whether web UI settings are allowed. + void AddUserSession(const std::string& display_email, + bool enable_settings = true); // Simulates screen unlocking. It is virtual so that test cases can override // it. The default implementation sets the session state of SessionController
diff --git a/ash/test/test_system_tray_delegate.cc b/ash/test/test_system_tray_delegate.cc index 6f6ab3cd..dac714c 100644 --- a/ash/test/test_system_tray_delegate.cc +++ b/ash/test/test_system_tray_delegate.cc
@@ -66,6 +66,12 @@ return login_status_; } +std::string TestSystemTrayDelegate::GetSupervisedUserManager() const { + if (!IsUserSupervised()) + return std::string(); + return "manager@chrome.com"; +} + bool TestSystemTrayDelegate::IsUserSupervised() const { return login_status_ == LoginStatus::SUPERVISED; }
diff --git a/ash/test/test_system_tray_delegate.h b/ash/test/test_system_tray_delegate.h index 8dc944f..5362012 100644 --- a/ash/test/test_system_tray_delegate.h +++ b/ash/test/test_system_tray_delegate.h
@@ -5,15 +5,15 @@ #ifndef ASH_TEST_TEST_SYSTEM_TRAY_DELEGATE_H_ #define ASH_TEST_TEST_SYSTEM_TRAY_DELEGATE_H_ -#include "ash/system/tray/default_system_tray_delegate.h" #include "ash/system/tray/ime_info.h" +#include "ash/system/tray/system_tray_delegate.h" #include "base/macros.h" #include "base/time/time.h" namespace ash { namespace test { -class TestSystemTrayDelegate : public DefaultSystemTrayDelegate { +class TestSystemTrayDelegate : public SystemTrayDelegate { public: TestSystemTrayDelegate(); ~TestSystemTrayDelegate() override; @@ -38,8 +38,9 @@ // Sets the list of available IMEs. void SetAvailableIMEList(const IMEInfoList& list); - // Overridden from SystemTrayDelegate: + // SystemTrayDelegate: LoginStatus GetUserLoginStatus() const override; + std::string GetSupervisedUserManager() const override; bool IsUserSupervised() const override; bool GetSessionStartTime(base::TimeTicks* session_start_time) override; bool GetSessionLengthLimit(base::TimeDelta* session_length_limit) override;
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc index b858cf3..9c0ecc4 100644 --- a/ash/wallpaper/wallpaper_controller.cc +++ b/ash/wallpaper/wallpaper_controller.cc
@@ -92,10 +92,10 @@ wallpaper_mode_(WALLPAPER_NONE), prominent_color_(kInvalidColor), wallpaper_reload_delay_(kWallpaperReloadDelayMs), - task_runner_(task_runner) { + task_runner_(task_runner), + scoped_session_observer_(this) { ShellPort::Get()->AddDisplayObserver(this); Shell::Get()->AddShellObserver(this); - Shell::Get()->session_controller()->AddSessionStateObserver(this); } WallpaperController::~WallpaperController() { @@ -105,7 +105,6 @@ color_calculator_->RemoveObserver(this); ShellPort::Get()->RemoveDisplayObserver(this); Shell::Get()->RemoveShellObserver(this); - Shell::Get()->session_controller()->RemoveSessionStateObserver(this); } void WallpaperController::BindRequest(
diff --git a/ash/wallpaper/wallpaper_controller.h b/ash/wallpaper/wallpaper_controller.h index 4ccda4c0..345f469 100644 --- a/ash/wallpaper/wallpaper_controller.h +++ b/ash/wallpaper/wallpaper_controller.h
@@ -9,7 +9,7 @@ #include "ash/ash_export.h" #include "ash/public/interfaces/wallpaper.mojom.h" -#include "ash/session/session_state_observer.h" +#include "ash/session/session_observer.h" #include "ash/shell_observer.h" #include "ash/wm_display_observer.h" #include "base/compiler_specific.h" @@ -43,7 +43,7 @@ public ShellObserver, public wallpaper::WallpaperResizerObserver, public wallpaper::WallpaperColorCalculatorObserver, - public SessionStateObserver { + public SessionObserver { public: enum WallpaperMode { WALLPAPER_NONE, WALLPAPER_IMAGE }; @@ -97,7 +97,7 @@ // ShellObserver: void OnRootWindowAdded(WmWindow* root_window) override; - // SessionStateObserver: + // SessionObserver: void OnSessionStateChanged(session_manager::SessionState state) override; // Returns the maximum size of all displays combined in native @@ -194,6 +194,8 @@ scoped_refptr<base::TaskRunner> task_runner_; + ScopedSessionObserver scoped_session_observer_; + DISALLOW_COPY_AND_ASSIGN(WallpaperController); };
diff --git a/ash/wm/lock_state_controller.cc b/ash/wm/lock_state_controller.cc index 482ad35d2..2370054f 100644 --- a/ash/wm/lock_state_controller.cc +++ b/ash/wm/lock_state_controller.cc
@@ -72,6 +72,7 @@ animating_lock_(false), can_cancel_lock_animation_(false), shutdown_controller_(shutdown_controller), + scoped_session_observer_(this), weak_ptr_factory_(this) { DCHECK(shutdown_controller_); Shell::GetPrimaryRootWindow()->GetHost()->AddObserver(this); @@ -189,7 +190,7 @@ Shell::Get()->shell_delegate()->Exit(); } -void LockStateController::OnAppTerminating() { +void LockStateController::OnChromeTerminating() { // If we hear that Chrome is exiting but didn't request it ourselves, all we // can really hope for is that we'll have time to clear the screen. // This is also the case when the user signs off.
diff --git a/ash/wm/lock_state_controller.h b/ash/wm/lock_state_controller.h index d5a7f176..bbda1be 100644 --- a/ash/wm/lock_state_controller.h +++ b/ash/wm/lock_state_controller.h
@@ -8,7 +8,7 @@ #include <memory> #include "ash/ash_export.h" -#include "ash/shell_observer.h" +#include "ash/session/session_observer.h" #include "ash/wm/session_state_animator.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -50,7 +50,7 @@ // OnLockStateChanged is called. It leads to // StartUnlockAnimationAfterUIDestroyed. class ASH_EXPORT LockStateController : public aura::WindowTreeHostObserver, - public ShellObserver { + public SessionObserver { public: // Amount of time to wait for our lock requests to be honored before giving // up. @@ -121,8 +121,8 @@ // aura::WindowTreeHostObserver override: void OnHostCloseRequested(const aura::WindowTreeHost* host) override; - // ShellObserver overrides: - void OnAppTerminating() override; + // SessionObserver overrides: + void OnChromeTerminating() override; void OnLockStateChanged(bool locked) override; void set_animator_for_test(SessionStateAnimator* animator) { @@ -242,6 +242,8 @@ base::Closure lock_screen_displayed_callback_; + ScopedSessionObserver scoped_session_observer_; + base::WeakPtrFactory<LockStateController> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(LockStateController);
diff --git a/ash/wm/lock_state_controller_unittest.cc b/ash/wm/lock_state_controller_unittest.cc index cff7f3399..e2111158 100644 --- a/ash/wm/lock_state_controller_unittest.cc +++ b/ash/wm/lock_state_controller_unittest.cc
@@ -335,11 +335,9 @@ void Initialize(bool legacy_button, LoginStatus status) { power_button_controller_->set_has_legacy_power_button_for_test( legacy_button); - lock_state_controller_->OnLoginStateChanged(status); SetUserLoggedIn(status != LoginStatus::NOT_LOGGED_IN); if (status == LoginStatus::GUEST) SetCanLockScreen(false); - lock_state_controller_->OnLockStateChanged(false); } PowerButtonController* power_button_controller_; // not owned @@ -805,7 +803,7 @@ // display an animation, we should just blank the screen. TEST_F(LockStateControllerTest, ShutdownWithoutButton) { Initialize(false, LoginStatus::USER); - lock_state_controller_->OnAppTerminating(); + lock_state_controller_->OnChromeTerminating(); EXPECT_TRUE(test_animator_->AreContainersAnimated( SessionStateAnimator::kAllNonRootContainersMask,
diff --git a/ash/wm/maximize_mode/maximize_mode_controller.cc b/ash/wm/maximize_mode/maximize_mode_controller.cc index 0c606b3..4119bb6 100644 --- a/ash/wm/maximize_mode/maximize_mode_controller.cc +++ b/ash/wm/maximize_mode/maximize_mode_controller.cc
@@ -110,6 +110,7 @@ tick_clock_(new base::DefaultTickClock()), tablet_mode_switch_is_on_(false), lid_is_closed_(false), + scoped_session_observer_(this), weak_factory_(this) { Shell::Get()->AddShellObserver(this); ShellPort::Get()->RecordUserMetricsAction( @@ -437,7 +438,7 @@ return force_tablet_mode_ == ForceTabletMode::NONE; } -void MaximizeModeController::OnAppTerminating() { +void MaximizeModeController::OnChromeTerminating() { // The system is about to shut down, so record TouchView usage interval // metrics based on whether TouchView mode is currently active. RecordTouchViewUsageInterval(CurrentTouchViewIntervalType());
diff --git a/ash/wm/maximize_mode/maximize_mode_controller.h b/ash/wm/maximize_mode/maximize_mode_controller.h index b37b436..2c22b30 100644 --- a/ash/wm/maximize_mode/maximize_mode_controller.h +++ b/ash/wm/maximize_mode/maximize_mode_controller.h
@@ -9,6 +9,7 @@ #include "ash/ash_export.h" #include "ash/public/interfaces/touch_view.mojom.h" +#include "ash/session/session_observer.h" #include "ash/shell_observer.h" #include "ash/wm_display_observer.h" #include "base/compiler_specific.h" @@ -45,12 +46,13 @@ // MaximizeModeController listens to accelerometer events and automatically // enters and exits maximize mode when the lid is opened beyond the triggering // angle and rotates the display to match the device when in maximize mode. -class ASH_EXPORT MaximizeModeController : - public chromeos::AccelerometerReader::Observer, - public chromeos::PowerManagerClient::Observer, - NON_EXPORTED_BASE(public mojom::TouchViewManager), - public ShellObserver, - public WmDisplayObserver { +class ASH_EXPORT MaximizeModeController + : public chromeos::AccelerometerReader::Observer, + public chromeos::PowerManagerClient::Observer, + NON_EXPORTED_BASE(public mojom::TouchViewManager), + public ShellObserver, + public WmDisplayObserver, + public SessionObserver { public: // Used for keeping track if the user wants the machine to behave as a // clamshell/touchview regardless of hardware orientation. @@ -88,7 +90,6 @@ void BindRequest(mojom::TouchViewManagerRequest request); // ShellObserver: - void OnAppTerminating() override; void OnMaximizeModeStarted() override; void OnMaximizeModeEnded() override; void OnShellInitialized() override; @@ -96,6 +97,9 @@ // WmDisplayObserver: void OnDisplayConfigurationChanged() override; + // SessionObserver: + void OnChromeTerminating() override; + // chromeos::AccelerometerReader::Observer: void OnAccelerometerUpdated( scoped_refptr<const chromeos::AccelerometerUpdate> update) override; @@ -210,6 +214,8 @@ // Tracks whether a flag is used to force maximize mode. ForceTabletMode force_tablet_mode_ = ForceTabletMode::NONE; + ScopedSessionObserver scoped_session_observer_; + base::WeakPtrFactory<MaximizeModeController> weak_factory_; DISALLOW_COPY_AND_ASSIGN(MaximizeModeController);
diff --git a/ash/wm/overlay_event_filter.cc b/ash/wm/overlay_event_filter.cc index 598db294..4eff9a2d 100644 --- a/ash/wm/overlay_event_filter.cc +++ b/ash/wm/overlay_event_filter.cc
@@ -11,10 +11,10 @@ namespace ash { -OverlayEventFilter::OverlayEventFilter() : delegate_(NULL) {} +OverlayEventFilter::OverlayEventFilter() : scoped_session_observer_(this) {} OverlayEventFilter::~OverlayEventFilter() { - delegate_ = NULL; + delegate_ = nullptr; } void OverlayEventFilter::OnKeyEvent(ui::KeyEvent* event) { @@ -32,11 +32,11 @@ event->StopPropagation(); } -void OverlayEventFilter::OnLoginStateChanged(LoginStatus status) { +void OverlayEventFilter::OnLoginStatusChanged(LoginStatus status) { Cancel(); } -void OverlayEventFilter::OnAppTerminating() { +void OverlayEventFilter::OnChromeTerminating() { Cancel(); }
diff --git a/ash/wm/overlay_event_filter.h b/ash/wm/overlay_event_filter.h index 218a835..dc3aff8a 100644 --- a/ash/wm/overlay_event_filter.h +++ b/ash/wm/overlay_event_filter.h
@@ -6,7 +6,7 @@ #define ASH_WM_OVERLAY_EVENT_FILTER_H_ #include "ash/ash_export.h" -#include "ash/shell_observer.h" +#include "ash/session/session_observer.h" #include "base/compiler_specific.h" #include "base/macros.h" #include "ui/aura/window.h" @@ -21,7 +21,7 @@ // of any key events during activation, and also signal cancellation when keys // for canceling are pressed. class ASH_EXPORT OverlayEventFilter : public ui::EventHandler, - public ShellObserver { + public SessionObserver { public: // Windows that need to receive events from OverlayEventFilter implement this. class ASH_EXPORT Delegate { @@ -58,13 +58,14 @@ // ui::EventHandler overrides: void OnKeyEvent(ui::KeyEvent* event) override; - // ShellObserver overrides: - void OnLoginStateChanged(LoginStatus status) override; - void OnAppTerminating() override; + // SessionObserver overrides: + void OnLoginStatusChanged(LoginStatus status) override; + void OnChromeTerminating() override; void OnLockStateChanged(bool locked) override; private: - Delegate* delegate_; + Delegate* delegate_ = nullptr; + ScopedSessionObserver scoped_session_observer_; DISALLOW_COPY_AND_ASSIGN(OverlayEventFilter); };
diff --git a/ash/wm/video_detector.cc b/ash/wm/video_detector.cc index e77fe7fb..b7a8f36 100644 --- a/ash/wm/video_detector.cc +++ b/ash/wm/video_detector.cc
@@ -81,6 +81,7 @@ : state_(State::NOT_PLAYING), video_is_playing_(false), window_observer_manager_(this), + scoped_session_observer_(this), is_shutting_down_(false) { aura::Env::GetInstance()->AddObserver(this); Shell::Get()->AddShellObserver(this); @@ -140,7 +141,7 @@ window_observer_manager_.Remove(window); } -void VideoDetector::OnAppTerminating() { +void VideoDetector::OnChromeTerminating() { // Stop checking video activity once the shutdown // process starts. crbug.com/231696. is_shutting_down_ = true;
diff --git a/ash/wm/video_detector.h b/ash/wm/video_detector.h index 5fd44231a..1f9e2a2 100644 --- a/ash/wm/video_detector.h +++ b/ash/wm/video_detector.h
@@ -10,6 +10,7 @@ #include <set> #include "ash/ash_export.h" +#include "ash/session/session_observer.h" #include "ash/shell_observer.h" #include "base/compiler_specific.h" #include "base/macros.h" @@ -35,6 +36,7 @@ // continuous scrolling of a page. class ASH_EXPORT VideoDetector : public aura::EnvObserver, public aura::WindowObserver, + public SessionObserver, public ShellObserver { public: // State of detected video activity. @@ -97,8 +99,10 @@ void OnWindowDestroyed(aura::Window* window) override; void OnWindowDestroying(aura::Window* window) override; + // SessionStateController overrides. + void OnChromeTerminating() override; + // ShellObserver overrides. - void OnAppTerminating() override; void OnFullscreenStateChanged(bool is_fullscreen, WmWindow* root_window) override; @@ -137,6 +141,7 @@ base::TimeTicks now_for_test_; ScopedObserver<aura::Window, aura::WindowObserver> window_observer_manager_; + ScopedSessionObserver scoped_session_observer_; bool is_shutting_down_;
diff --git a/ash/wm/video_detector_unittest.cc b/ash/wm/video_detector_unittest.cc index 5ca4dd4..86403dd 100644 --- a/ash/wm/video_detector_unittest.cc +++ b/ash/wm/video_detector_unittest.cc
@@ -7,6 +7,7 @@ #include <deque> #include <memory> +#include "ash/session/session_controller.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/wm/window_state.h" @@ -198,7 +199,7 @@ TEST_F(VideoDetectorTest, DontReportDuringShutdown) { std::unique_ptr<aura::Window> window = CreateTestWindow(gfx::Rect(0, 0, 1024, 768)); - Shell::Get()->OnAppTerminating(); + Shell::Get()->session_controller()->NotifyChromeTerminating(); SendUpdates(window.get(), kMinRect, kMinFps + 5, 2 * kMinDuration); EXPECT_TRUE(observer_->empty()); }
diff --git a/base/files/file_util_unittest.cc b/base/files/file_util_unittest.cc index 2d95be4..7b35f59 100644 --- a/base/files/file_util_unittest.cc +++ b/base/files/file_util_unittest.cc
@@ -2255,6 +2255,17 @@ } #if defined(OS_POSIX) +TEST_F(FileUtilTest, SetNonBlocking) { + const int kInvalidFd = 99999; + EXPECT_FALSE(SetNonBlocking(kInvalidFd)); + + base::FilePath path; + ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &path)); + path = path.Append(FPL("file_util")).Append(FPL("original.txt")); + ScopedFD fd(open(path.value().c_str(), O_RDONLY)); + ASSERT_GE(fd.get(), 0); + EXPECT_TRUE(SetNonBlocking(fd.get())); +} // Testing VerifyPathControlledByAdmin() is hard, because there is no // way a test can make a file owned by root, or change file paths
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc b/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc index d4c26d6..e2ff1ef 100644 --- a/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc +++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc
@@ -340,6 +340,22 @@ #endif } +void SchedulerSingleThreadTaskRunnerManager::Start() { + decltype(workers_) workers_to_start; + { + AutoSchedulerLock auto_lock(lock_); + started_ = true; + workers_to_start = workers_; + } + + // Start workers that were created before this method was called. Other + // workers are started as they are created. + for (scoped_refptr<SchedulerWorker> worker : workers_to_start) { + worker->Start(); + worker->WakeUp(); + } +} + scoped_refptr<SingleThreadTaskRunner> SchedulerSingleThreadTaskRunnerManager::CreateSingleThreadTaskRunnerWithTraits( const TaskTraits& traits) { @@ -359,7 +375,7 @@ void SchedulerSingleThreadTaskRunnerManager::JoinForTesting() { decltype(workers_) local_workers; { - AutoSchedulerLock auto_lock(workers_lock_); + AutoSchedulerLock auto_lock(lock_); local_workers = std::move(workers_); } @@ -367,7 +383,7 @@ worker->JoinForTesting(); { - AutoSchedulerLock auto_lock(workers_lock_); + AutoSchedulerLock auto_lock(lock_); DCHECK(workers_.empty()) << "New worker(s) unexpectedly registered during join."; workers_ = std::move(local_workers); @@ -410,23 +426,33 @@ SchedulerWorker* SchedulerSingleThreadTaskRunnerManager::CreateAndRegisterSchedulerWorker( const SchedulerWorkerPoolParams& params) { - AutoSchedulerLock auto_lock(workers_lock_); - int id = next_worker_id_++; + SchedulerWorker* worker; + bool start_worker; - workers_.emplace_back(SchedulerWorker::Create( - params.priority_hint(), - CreateSchedulerWorkerDelegate<DelegateType>(params, id), task_tracker_, - SchedulerWorker::InitialState::DETACHED)); - return workers_.back().get(); + { + AutoSchedulerLock auto_lock(lock_); + int id = next_worker_id_++; + workers_.emplace_back(make_scoped_refptr(new SchedulerWorker( + params.priority_hint(), + CreateSchedulerWorkerDelegate<DelegateType>(params, id), + task_tracker_))); + worker = workers_.back().get(); + start_worker = started_; + } + + if (start_worker) + worker->Start(); + + return worker; } void SchedulerSingleThreadTaskRunnerManager::UnregisterSchedulerWorker( SchedulerWorker* worker) { // Cleanup uses a SchedulerLock, so call Cleanup() after releasing - // |workers_lock_|. + // |lock_|. scoped_refptr<SchedulerWorker> worker_to_destroy; { - AutoSchedulerLock auto_lock(workers_lock_); + AutoSchedulerLock auto_lock(lock_); // We might be joining, so record that a worker was unregistered for // verification at destruction.
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager.h b/base/task_scheduler/scheduler_single_thread_task_runner_manager.h index 24d1a9a01..c862f19 100644 --- a/base/task_scheduler/scheduler_single_thread_task_runner_manager.h +++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager.h
@@ -35,6 +35,12 @@ } // namespace +// Manages a pool of threads which are each associated with one +// SingleThreadTaskRunner. +// +// No threads are created (and hence no tasks can run) before Start() is called. +// +// This class is thread-safe. class BASE_EXPORT SchedulerSingleThreadTaskRunnerManager final { public: SchedulerSingleThreadTaskRunnerManager( @@ -45,6 +51,10 @@ DelayedTaskManager* delayed_task_manager); ~SchedulerSingleThreadTaskRunnerManager(); + // Starts threads for existing SingleThreadTaskRunners and allows threads to + // be started when SingleThreadTaskRunners are created in the future. + void Start(); + scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunnerWithTraits( const TaskTraits& traits); @@ -79,11 +89,14 @@ TaskTracker* const task_tracker_; DelayedTaskManager* const delayed_task_manager_; - // Synchronizes access to |workers_| and |worker_id_|. - SchedulerLock workers_lock_; + // Synchronizes access to |workers_|, |next_worker_id_| and |started_|. + SchedulerLock lock_; std::vector<scoped_refptr<SchedulerWorker>> workers_; int next_worker_id_ = 0; + // Set to true when Start() is called. + bool started_ = false; + #if DCHECK_IS_ON() subtle::Atomic32 workers_unregistered_during_join_ = 0; #endif
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc b/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc index 8244bb5..1d6745ac 100644 --- a/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc +++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
@@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" +#include "base/synchronization/atomic_flag.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" #include "base/task_scheduler/delayed_task_manager.h" @@ -14,6 +15,7 @@ #include "base/task_scheduler/task_tracker.h" #include "base/task_scheduler/task_traits.h" #include "base/test/test_timeouts.h" +#include "base/threading/platform_thread.h" #include "base/threading/simple_thread.h" #include "base/threading/thread.h" #include "testing/gtest/include/gtest/gtest.h" @@ -70,6 +72,7 @@ MakeUnique<SchedulerSingleThreadTaskRunnerManager>( GetParamsVector(), Bind(&GetThreadPoolIndexForTraits), &task_tracker_, delayed_task_manager_.get()); + StartSingleThreadTaskRunnerManagerFromSetUp(); } void TearDown() override { @@ -79,6 +82,10 @@ } protected: + virtual void StartSingleThreadTaskRunnerManagerFromSetUp() { + single_thread_task_runner_manager_->Start(); + } + virtual void TearDownSingleThreadTaskRunnerManager() { single_thread_task_runner_manager_->JoinForTesting(); single_thread_task_runner_manager_.reset(); @@ -466,5 +473,53 @@ #endif // defined(OS_WIN) +namespace { + +class TaskSchedulerSingleThreadTaskRunnerManagerStartTest + : public TaskSchedulerSingleThreadTaskRunnerManagerTest { + public: + TaskSchedulerSingleThreadTaskRunnerManagerStartTest() = default; + + private: + void StartSingleThreadTaskRunnerManagerFromSetUp() override { + // Start() is called in the test body rather than in SetUp(). + } + + DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerStartTest); +}; + +} // namespace + +// Verify that a task posted before Start() doesn't run until Start() is called. +TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerStartTest, + PostTaskBeforeStart) { + AtomicFlag manager_started; + WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + single_thread_task_runner_manager_ + ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()) + ->PostTask( + FROM_HERE, + Bind( + [](WaitableEvent* task_running, AtomicFlag* manager_started) { + task_running->Signal(); + + // The task should not run before Start(). + EXPECT_TRUE(manager_started->IsSet()); + }, + Unretained(&task_running), Unretained(&manager_started))); + + // Wait a little bit to make sure that the task isn't scheduled before start. + // Note: This test won't catch a case where the task is scheduled between + // setting |manager_started| and calling Start(). However, we expect the test + // to be flaky if the tested code allows that to happen. + PlatformThread::Sleep(TestTimeouts::tiny_timeout()); + manager_started.Set(); + single_thread_task_runner_manager_->Start(); + + // This should not hang if the task is scheduled after Start(). + task_running.Wait(); +} + } // namespace internal } // namespace base
diff --git a/base/task_scheduler/scheduler_worker.cc b/base/task_scheduler/scheduler_worker.cc index 4084c52..409d5e15 100644 --- a/base/task_scheduler/scheduler_worker.cc +++ b/base/task_scheduler/scheduler_worker.cc
@@ -201,25 +201,39 @@ wake_up_event->Reset(); } -scoped_refptr<SchedulerWorker> SchedulerWorker::Create( +SchedulerWorker::SchedulerWorker( ThreadPriority priority_hint, std::unique_ptr<Delegate> delegate, TaskTracker* task_tracker, - InitialState initial_state, - SchedulerBackwardCompatibility backward_compatibility) { - scoped_refptr<SchedulerWorker> worker( - new SchedulerWorker(priority_hint, std::move(delegate), task_tracker, - backward_compatibility)); - // Creation happens before any other thread can reference this one, so no - // synchronization is necessary. - if (initial_state == SchedulerWorker::InitialState::ALIVE) { - worker->CreateThread(); - if (!worker->thread_) { - return nullptr; - } + SchedulerBackwardCompatibility backward_compatibility, + InitialState initial_state) + : priority_hint_(priority_hint), + delegate_(std::move(delegate)), + task_tracker_(task_tracker), +#if defined(OS_WIN) + backward_compatibility_(backward_compatibility), +#endif + initial_state_(initial_state) { + DCHECK(delegate_); + DCHECK(task_tracker_); +} + +bool SchedulerWorker::Start() { + AutoSchedulerLock auto_lock(thread_lock_); + DCHECK(!started_); + DCHECK(!thread_); + + if (should_exit_.IsSet()) + return true; + + started_ = true; + + if (initial_state_ == InitialState::ALIVE) { + CreateThread(); + return !!thread_; } - return worker; + return true; } void SchedulerWorker::WakeUp() { @@ -228,13 +242,14 @@ DCHECK(!join_called_for_testing_.IsSet()); if (!thread_) - CreateThreadAssertSynchronized(); + CreateThread(); if (thread_) thread_->WakeUp(); } void SchedulerWorker::JoinForTesting() { + DCHECK(started_); DCHECK(!join_called_for_testing_.IsSet()); join_called_for_testing_.Set(); @@ -266,27 +281,9 @@ // away |thread_| for destruction. AutoSchedulerLock auto_lock(thread_lock_); DCHECK(!should_exit_.IsSet()); - if (thread_) { - should_exit_.Set(); + should_exit_.Set(); + if (thread_) thread_->WakeUp(); - } -} - -SchedulerWorker::SchedulerWorker( - ThreadPriority priority_hint, - std::unique_ptr<Delegate> delegate, - TaskTracker* task_tracker, - SchedulerBackwardCompatibility backward_compatibility) - : priority_hint_(priority_hint), - delegate_(std::move(delegate)), - task_tracker_(task_tracker) -#if defined(OS_WIN) - , - backward_compatibility_(backward_compatibility) -#endif -{ - DCHECK(delegate_); - DCHECK(task_tracker_); } SchedulerWorker::~SchedulerWorker() { @@ -322,12 +319,9 @@ } void SchedulerWorker::CreateThread() { - thread_ = Thread::Create(make_scoped_refptr(this)); -} - -void SchedulerWorker::CreateThreadAssertSynchronized() { thread_lock_.AssertAcquired(); - CreateThread(); + if (started_) + thread_ = Thread::Create(make_scoped_refptr(this)); } bool SchedulerWorker::ShouldExit() {
diff --git a/base/task_scheduler/scheduler_worker.h b/base/task_scheduler/scheduler_worker.h index 0fc595d..d6330a5 100644 --- a/base/task_scheduler/scheduler_worker.h +++ b/base/task_scheduler/scheduler_worker.h
@@ -98,27 +98,35 @@ enum class InitialState { ALIVE, DETACHED }; // Creates a SchedulerWorker that runs Tasks from Sequences returned by - // |delegate|. |priority_hint| is the preferred thread priority; the actual - // thread priority depends on shutdown state and platform capabilities. - // |task_tracker| is used to handle shutdown behavior of Tasks. If - // |worker_state| is DETACHED, the thread will be created upon a WakeUp(). - // Returns nullptr if creating the underlying platform thread fails during - // Create(). |backward_compatibility| indicates whether backward compatibility - // is enabled. Either JoinForTesting() or Cleanup() must be called before - // releasing the last external reference. - static scoped_refptr<SchedulerWorker> Create( - ThreadPriority priority_hint, - std::unique_ptr<Delegate> delegate, - TaskTracker* task_tracker, - InitialState initial_state, - SchedulerBackwardCompatibility backward_compatibility = - SchedulerBackwardCompatibility::DISABLED); + // |delegate|. No actual thread will be created for this SchedulerWorker + // before Start() is called. |priority_hint| is the preferred thread priority; + // the actual thread priority depends on shutdown state and platform + // capabilities. |task_tracker| is used to handle shutdown behavior of Tasks. + // |backward_compatibility| indicates whether backward compatibility is + // enabled. |initial_state| determines whether the thread is created in + // Start() or in the first WakeUp() after Start(). Either JoinForTesting() or + // Cleanup() must be called before releasing the last external reference. + SchedulerWorker(ThreadPriority priority_hint, + std::unique_ptr<Delegate> delegate, + TaskTracker* task_tracker, + SchedulerBackwardCompatibility backward_compatibility = + SchedulerBackwardCompatibility::DISABLED, + InitialState initial_state = InitialState::ALIVE); - // Wakes up this SchedulerWorker if it wasn't already awake. After this - // is called, this SchedulerWorker will run Tasks from Sequences - // returned by the GetWork() method of its delegate until it returns nullptr. - // WakeUp() may fail if the worker is detached and it fails to allocate a new - // worker. If this happens, there will be no call to GetWork(). + // Allows this SchedulerWorker to be backed by a thread. If + // InitialState::ALIVE was passed to the constructor and Cleanup() wasn't + // called, a thread is created immediately (in a wait state pending a WakeUp() + // call). If InitialState::DETACHED was passed to the constructor and + // Cleanup() wasn't called, creation is delayed until the next WakeUp(). No + // thread will be created if Cleanup() was called. Returns true on success. + bool Start(); + + // Wakes up this SchedulerWorker if it wasn't already awake. After this is + // called, this SchedulerWorker will run Tasks from Sequences returned by the + // GetWork() method of its delegate until it returns nullptr. WakeUp() may + // fail if the worker is detached and it fails to allocate a new worker. If + // this happens, there will be no call to GetWork(). No-op if Start() wasn't + // called. void WakeUp(); SchedulerWorker::Delegate* delegate() { return delegate_.get(); } @@ -155,10 +163,6 @@ DELEGATE, }; - SchedulerWorker(ThreadPriority thread_priority, - std::unique_ptr<Delegate> delegate, - TaskTracker* task_tracker, - SchedulerBackwardCompatibility backward_compatibility); ~SchedulerWorker(); // Returns ownership of the thread instance when appropriate so that it can be @@ -168,23 +172,21 @@ DetachNotify detach_notify); void CreateThread(); - - void CreateThreadAssertSynchronized(); - bool ShouldExit(); - // Synchronizes access to |thread_| (read+write) as well as |should_exit_| - // (write-only). See Cleanup() for details. + // Synchronizes access to |thread_| (read+write), |started_| (read+write) and + // |should_exit_| (write-only). See Cleanup() for details. mutable SchedulerLock thread_lock_; - AtomicFlag should_exit_; - // The underlying thread for this SchedulerWorker. // The thread object will be cleaned up by the running thread unless we join // against the thread. Joining requires the thread object to remain alive for // the Thread::Join() call. std::unique_ptr<Thread> thread_; + bool started_ = false; + AtomicFlag should_exit_; + const ThreadPriority priority_hint_; const std::unique_ptr<Delegate> delegate_; @@ -194,6 +196,8 @@ const SchedulerBackwardCompatibility backward_compatibility_; #endif + const InitialState initial_state_; + // Set once JoinForTesting() has been called. AtomicFlag join_called_for_testing_;
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.cc b/base/task_scheduler/scheduler_worker_pool_impl.cc index 0515154e..d45495413 100644 --- a/base/task_scheduler/scheduler_worker_pool_impl.cc +++ b/base/task_scheduler/scheduler_worker_pool_impl.cc
@@ -206,10 +206,6 @@ idle_workers_stack_lock_.CreateConditionVariable()), join_for_testing_returned_(WaitableEvent::ResetPolicy::MANUAL, WaitableEvent::InitialState::NOT_SIGNALED), -#if DCHECK_IS_ON() - workers_created_(WaitableEvent::ResetPolicy::MANUAL, - WaitableEvent::InitialState::NOT_SIGNALED), -#endif // Mimics the UMA_HISTOGRAM_LONG_TIMES macro. detach_duration_histogram_(Histogram::FactoryTimeGet( kDetachDurationHistogramPrefix + name_ + kPoolNameSuffix, @@ -245,13 +241,11 @@ void SchedulerWorkerPoolImpl::Start(const SchedulerWorkerPoolParams& params) { suggested_reclaim_time_ = params.suggested_reclaim_time(); - std::vector<SchedulerWorker*> workers_to_wake_up; - { AutoSchedulerLock auto_lock(idle_workers_stack_lock_); #if DCHECK_IS_ON() - DCHECK(!workers_created_.IsSignaled()); + DCHECK(!workers_created_.IsSet()); #endif DCHECK(workers_.empty()); @@ -270,34 +264,34 @@ // Create workers in reverse order of index so that the worker with the // highest index is at the bottom of the idle stack. for (int index = params.max_threads() - 1; index >= 0; --index) { - const SchedulerWorker::InitialState initial_state = - index < num_alive_workers ? SchedulerWorker::InitialState::ALIVE - : SchedulerWorker::InitialState::DETACHED; - scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( + workers_[index] = make_scoped_refptr(new SchedulerWorker( params.priority_hint(), MakeUnique<SchedulerWorkerDelegateImpl>( this, re_enqueue_sequence_callback_, index), - task_tracker_, initial_state, params.backward_compatibility()); - if (!worker) - break; + task_tracker_, params.backward_compatibility(), + index < num_alive_workers ? SchedulerWorker::InitialState::ALIVE + : SchedulerWorker::InitialState::DETACHED)); - if (index < num_wake_ups_before_start_) - workers_to_wake_up.push_back(worker.get()); - else - idle_workers_stack_.Push(worker.get()); - - workers_[index] = std::move(worker); + // Put workers that won't be woken up at the end of this method on the + // idle stack. + if (index >= num_wake_ups_before_start_) + idle_workers_stack_.Push(workers_[index].get()); } #if DCHECK_IS_ON() - workers_created_.Signal(); + workers_created_.Set(); #endif - - CHECK(!workers_.empty()); } - for (SchedulerWorker* worker : workers_to_wake_up) - worker->WakeUp(); + // Start all workers. CHECK that the first worker can be started (assume that + // failure means that threads can't be created on this machine). Wake up one + // worker for each wake up that occurred before Start(). + for (size_t index = 0; index < workers_.size(); ++index) { + const bool start_success = workers_[index]->Start(); + CHECK(start_success || index > 0); + if (static_cast<int>(index) < num_wake_ups_before_start_) + workers_[index]->WakeUp(); + } } SchedulerWorkerPoolImpl::~SchedulerWorkerPoolImpl() { @@ -398,14 +392,14 @@ int SchedulerWorkerPoolImpl::GetMaxConcurrentTasksDeprecated() const { #if DCHECK_IS_ON() - DCHECK(workers_created_.IsSignaled()); + DCHECK(workers_created_.IsSet()); #endif return workers_.size(); } void SchedulerWorkerPoolImpl::WaitForAllWorkersIdleForTesting() { #if DCHECK_IS_ON() - DCHECK(workers_created_.IsSignaled()); + DCHECK(workers_created_.IsSet()); #endif AutoSchedulerLock auto_lock(idle_workers_stack_lock_); while (idle_workers_stack_.Size() < workers_.size()) @@ -414,7 +408,7 @@ void SchedulerWorkerPoolImpl::JoinForTesting() { #if DCHECK_IS_ON() - DCHECK(workers_created_.IsSignaled()); + DCHECK(workers_created_.IsSet()); #endif DCHECK(!CanWorkerDetachForTesting() || suggested_reclaim_time_.is_max()) << "Workers can detach during join."; @@ -453,12 +447,9 @@ void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::OnMainEntry( SchedulerWorker* worker) { #if DCHECK_IS_ON() - // Wait for |outer_->workers_created_| to avoid traversing - // |outer_->workers_| while it is being filled by Initialize(). - outer_->workers_created_.Wait(); + DCHECK(outer_->workers_created_.IsSet()); DCHECK(ContainsWorker(outer_->workers_, worker)); #endif - DCHECK_EQ(num_tasks_since_last_wait_, 0U); if (!last_detach_time_.is_null()) { @@ -577,7 +568,7 @@ AutoSchedulerLock auto_lock(idle_workers_stack_lock_); #if DCHECK_IS_ON() - DCHECK_EQ(workers_.empty(), !workers_created_.IsSignaled()); + DCHECK_EQ(workers_.empty(), !workers_created_.IsSet()); #endif if (workers_.empty())
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.h b/base/task_scheduler/scheduler_worker_pool_impl.h index f9b04a1..7b285a5 100644 --- a/base/task_scheduler/scheduler_worker_pool_impl.h +++ b/base/task_scheduler/scheduler_worker_pool_impl.h
@@ -147,12 +147,12 @@ // All workers owned by this worker pool. Initialized by Start() within the // scope of |idle_workers_stack_lock_|. Never modified afterwards (i.e. can be - // read without synchronization once |workers_created_.IsSignaled()|). + // read without synchronization once |workers_created_.IsSet()|). std::vector<scoped_refptr<SchedulerWorker>> workers_; // Suggested reclaim time for workers. Initialized by Start(). Never modified // afterwards (i.e. can be read without synchronization once - // |workers_created_.IsSignaled()|). + // |workers_created_.IsSet()|). TimeDelta suggested_reclaim_time_; // Synchronizes access to |idle_workers_stack_|, @@ -172,7 +172,9 @@ // Signaled when all workers become idle. std::unique_ptr<ConditionVariable> idle_workers_stack_cv_for_testing_; - // Number of wake ups that occurred before Start(). + // Number of wake ups that occurred before Start(). Never modified after + // Start() (i.e. can be read without synchronization once + // |workers_created_.IsSet()|). int num_wake_ups_before_start_ = 0; // Signaled once JoinForTesting() has returned. @@ -183,8 +185,8 @@ AtomicFlag worker_detachment_disallowed_; #if DCHECK_IS_ON() - // Signaled when all workers have been created. - mutable WaitableEvent workers_created_; + // Set when all workers have been created. + AtomicFlag workers_created_; #endif // TaskScheduler.DetachDuration.[worker pool name] histogram. Intentionally
diff --git a/base/task_scheduler/scheduler_worker_stack_unittest.cc b/base/task_scheduler/scheduler_worker_stack_unittest.cc index b7d57ff..426bc6f5 100644 --- a/base/task_scheduler/scheduler_worker_stack_unittest.cc +++ b/base/task_scheduler/scheduler_worker_stack_unittest.cc
@@ -44,29 +44,20 @@ class TaskSchedulerWorkerStackTest : public testing::Test { protected: void SetUp() override { - worker_a_ = SchedulerWorker::Create( - ThreadPriority::NORMAL, - WrapUnique(new MockSchedulerWorkerDelegate), &task_tracker_, - SchedulerWorker::InitialState::ALIVE); + worker_a_ = make_scoped_refptr(new SchedulerWorker( + ThreadPriority::NORMAL, WrapUnique(new MockSchedulerWorkerDelegate), + &task_tracker_)); ASSERT_TRUE(worker_a_); - worker_b_ = SchedulerWorker::Create( - ThreadPriority::NORMAL, - WrapUnique(new MockSchedulerWorkerDelegate), &task_tracker_, - SchedulerWorker::InitialState::ALIVE); + worker_b_ = make_scoped_refptr(new SchedulerWorker( + ThreadPriority::NORMAL, WrapUnique(new MockSchedulerWorkerDelegate), + &task_tracker_)); ASSERT_TRUE(worker_b_); - worker_c_ = SchedulerWorker::Create( - ThreadPriority::NORMAL, - WrapUnique(new MockSchedulerWorkerDelegate), &task_tracker_, - SchedulerWorker::InitialState::ALIVE); + worker_c_ = make_scoped_refptr(new SchedulerWorker( + ThreadPriority::NORMAL, WrapUnique(new MockSchedulerWorkerDelegate), + &task_tracker_)); ASSERT_TRUE(worker_c_); } - void TearDown() override { - worker_a_->JoinForTesting(); - worker_b_->JoinForTesting(); - worker_c_->JoinForTesting(); - } - scoped_refptr<SchedulerWorker> worker_a_; scoped_refptr<SchedulerWorker> worker_b_; scoped_refptr<SchedulerWorker> worker_c_;
diff --git a/base/task_scheduler/scheduler_worker_unittest.cc b/base/task_scheduler/scheduler_worker_unittest.cc index 747c80b..8d2d1b02 100644 --- a/base/task_scheduler/scheduler_worker_unittest.cc +++ b/base/task_scheduler/scheduler_worker_unittest.cc
@@ -77,10 +77,11 @@ WaitableEvent::InitialState::NOT_SIGNALED) {} void SetUp() override { - worker_ = SchedulerWorker::Create( + worker_ = make_scoped_refptr(new SchedulerWorker( ThreadPriority::NORMAL, MakeUnique<TestSchedulerWorkerDelegate>(this), - &task_tracker_, SchedulerWorker::InitialState::ALIVE); + &task_tracker_)); ASSERT_TRUE(worker_); + worker_->Start(); worker_set_.Signal(); main_entry_called_.Wait(); } @@ -391,6 +392,10 @@ void WaitForDelegateDestroy() { destroyed_.Wait(); } + void set_expect_get_work(bool expect_get_work) { + expect_get_work_ = expect_get_work; + } + void ResetState() { work_running_.Signal(); work_processed_.Reset(); @@ -413,6 +418,7 @@ WaitableEvent can_detach_block_; WaitableEvent destroyed_; + bool expect_get_work_ = true; bool can_detach_ = false; bool work_requested_ = false; @@ -426,6 +432,8 @@ scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override { + EXPECT_TRUE(controls_->expect_get_work_); + // Sends one item of work to signal |work_processed_|. On subsequent calls, // sends nullptr to indicate there's no more work to be done. if (controls_->work_requested_) @@ -502,9 +510,9 @@ delegate->controls(); controls->set_can_detach(true); EXPECT_CALL(*delegate, OnMainEntry(_)); - scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( - ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, - SchedulerWorker::InitialState::ALIVE); + auto worker = make_scoped_refptr(new SchedulerWorker( + ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker)); + worker->Start(); worker->WakeUp(); controls->WaitForWorkToRun(); Mock::VerifyAndClear(delegate); @@ -526,9 +534,9 @@ controls->set_can_detach(true); controls->MakeCanDetachBlock(); - scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( - ThreadPriority::NORMAL, std::move(delegate), &task_tracker, - SchedulerWorker::InitialState::ALIVE); + auto worker = make_scoped_refptr(new SchedulerWorker( + ThreadPriority::NORMAL, std::move(delegate), &task_tracker)); + worker->Start(); worker->WakeUp(); controls->WaitForDetachRequest(); @@ -550,9 +558,9 @@ controls->set_can_detach(true); - scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( - ThreadPriority::NORMAL, std::move(delegate), &task_tracker, - SchedulerWorker::InitialState::ALIVE); + auto worker = make_scoped_refptr(new SchedulerWorker( + ThreadPriority::NORMAL, std::move(delegate), &task_tracker)); + worker->Start(); worker->WakeUp(); controls->WaitForDetach(); @@ -573,9 +581,9 @@ controls->HaveWorkBlock(); - scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( - ThreadPriority::NORMAL, std::move(delegate), &task_tracker, - SchedulerWorker::InitialState::ALIVE); + auto worker = make_scoped_refptr(new SchedulerWorker( + ThreadPriority::NORMAL, std::move(delegate), &task_tracker)); + worker->Start(); worker->WakeUp(); controls->WaitForWorkToRun(); @@ -595,9 +603,9 @@ scoped_refptr<ControllableDetachDelegate::Controls> controls = delegate->controls(); - scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( - ThreadPriority::NORMAL, std::move(delegate), &task_tracker, - SchedulerWorker::InitialState::ALIVE); + auto worker = make_scoped_refptr(new SchedulerWorker( + ThreadPriority::NORMAL, std::move(delegate), &task_tracker)); + worker->Start(); worker->WakeUp(); controls->WaitForDetachRequest(); @@ -618,9 +626,9 @@ controls->HaveWorkBlock(); - scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( - ThreadPriority::NORMAL, std::move(delegate), &task_tracker, - SchedulerWorker::InitialState::ALIVE); + auto worker = make_scoped_refptr(new SchedulerWorker( + ThreadPriority::NORMAL, std::move(delegate), &task_tracker)); + worker->Start(); worker->WakeUp(); controls->WaitForWorkToRun(); @@ -631,6 +639,29 @@ controls->WaitForDelegateDestroy(); } +// Verify that Start() is a no-op after Cleanup(). +TEST(TaskSchedulerWorkerTest, CleanupBeforeStart) { + TaskTracker task_tracker; + // Will be owned by SchedulerWorker. + // No mock here as that's reasonably covered by other tests and the delegate + // may destroy on a different thread. Mocks aren't designed with that in mind. + std::unique_ptr<ControllableDetachDelegate> delegate = + MakeUnique<ControllableDetachDelegate>(&task_tracker); + scoped_refptr<ControllableDetachDelegate::Controls> controls = + delegate->controls(); + controls->set_expect_get_work(false); + + auto worker = make_scoped_refptr(new SchedulerWorker( + ThreadPriority::NORMAL, std::move(delegate), &task_tracker)); + + worker->Cleanup(); + + worker->Start(); + worker->WakeUp(); + + EXPECT_FALSE(worker->ThreadAliveForTesting()); +} + namespace { class CallJoinFromDifferentThread : public SimpleThread { @@ -671,9 +702,9 @@ controls->HaveWorkBlock(); - scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( - ThreadPriority::NORMAL, std::move(delegate), &task_tracker, - SchedulerWorker::InitialState::ALIVE); + auto worker = make_scoped_refptr(new SchedulerWorker( + ThreadPriority::NORMAL, std::move(delegate), &task_tracker)); + worker->Start(); worker->WakeUp(); controls->WaitForWorkToRun(); @@ -702,9 +733,9 @@ controls->set_can_detach(true); EXPECT_CALL(*delegate, OnMainEntry(_)); - scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( - ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, - SchedulerWorker::InitialState::ALIVE); + auto worker = make_scoped_refptr(new SchedulerWorker( + ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker)); + worker->Start(); worker->WakeUp(); controls->WaitForWorkToRun(); Mock::VerifyAndClear(delegate); @@ -726,16 +757,18 @@ worker->JoinForTesting(); } -TEST(TaskSchedulerWorkerTest, CreateDetached) { +TEST(TaskSchedulerWorkerTest, StartDetached) { TaskTracker task_tracker; // Will be owned by SchedulerWorker. MockedControllableDetachDelegate* delegate = new StrictMock<MockedControllableDetachDelegate>(&task_tracker); scoped_refptr<ControllableDetachDelegate::Controls> controls = delegate->controls(); - scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( + auto worker = make_scoped_refptr(new SchedulerWorker( ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, - SchedulerWorker::InitialState::DETACHED); + SchedulerBackwardCompatibility::DISABLED, + SchedulerWorker::InitialState::DETACHED)); + worker->Start(); ASSERT_FALSE(worker->ThreadAliveForTesting()); EXPECT_CALL(*delegate, OnMainEntry(worker.get())); worker->WakeUp(); @@ -804,9 +837,9 @@ ? ThreadPriority::BACKGROUND : ThreadPriority::NORMAL); - scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( - ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker, - SchedulerWorker::InitialState::ALIVE); + auto worker = make_scoped_refptr(new SchedulerWorker( + ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker)); + worker->Start(); // Verify that the initial thread priority is BACKGROUND (or NORMAL if thread // priority can't be increased). @@ -831,9 +864,11 @@ delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL); // Create a DETACHED thread. - scoped_refptr<SchedulerWorker> worker = SchedulerWorker::Create( + auto worker = make_scoped_refptr(new SchedulerWorker( ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker, - SchedulerWorker::InitialState::DETACHED); + SchedulerBackwardCompatibility::DISABLED, + SchedulerWorker::InitialState::DETACHED)); + worker->Start(); // Pretend that shutdown has started. task_tracker.SetHasShutdownStartedForTesting(); @@ -888,10 +923,10 @@ // Create a worker with backward compatibility ENABLED. Wake it up and wait // until GetWork() returns. - auto worker = SchedulerWorker::Create( + auto worker = make_scoped_refptr(new SchedulerWorker( ThreadPriority::NORMAL, std::move(delegate), &task_tracker, - SchedulerWorker::InitialState::ALIVE, - SchedulerBackwardCompatibility::INIT_COM_STA); + SchedulerBackwardCompatibility::INIT_COM_STA)); + worker->Start(); worker->WakeUp(); delegate_raw->WaitUntilGetWorkReturned(); @@ -909,10 +944,10 @@ // Create a worker with backward compatibility DISABLED. Wake it up and wait // until GetWork() returns. - auto worker = SchedulerWorker::Create( + auto worker = make_scoped_refptr(new SchedulerWorker( ThreadPriority::NORMAL, std::move(delegate), &task_tracker, - SchedulerWorker::InitialState::ALIVE, - SchedulerBackwardCompatibility::DISABLED); + SchedulerBackwardCompatibility::DISABLED)); + worker->Start(); worker->WakeUp(); delegate_raw->WaitUntilGetWorkReturned();
diff --git a/base/task_scheduler/task_scheduler_impl.cc b/base/task_scheduler/task_scheduler_impl.cc index 9d0320c..6a2732d 100644 --- a/base/task_scheduler/task_scheduler_impl.cc +++ b/base/task_scheduler/task_scheduler_impl.cc
@@ -240,6 +240,7 @@ MakeUnique<SchedulerSingleThreadTaskRunnerManager>( worker_pool_params_vector, worker_pool_index_for_traits_callback_, task_tracker_.get(), delayed_task_manager_.get()); + single_thread_task_runner_manager_->Start(); // Callback invoked by workers to re-enqueue a sequence in the appropriate // PriorityQueue.
diff --git a/base/test/test_shortcut_win.cc b/base/test/test_shortcut_win.cc index eb074a3a..ef07da60 100644 --- a/base/test/test_shortcut_win.cc +++ b/base/test/test_shortcut_win.cc
@@ -67,7 +67,7 @@ if (FAILED(hr)) return; - EXPECT_TRUE(SUCCEEDED(hr = i_persist_file.QueryFrom(i_shell_link.get()))); + EXPECT_TRUE(SUCCEEDED(hr = i_persist_file.QueryFrom(i_shell_link.Get()))); if (FAILED(hr)) return; @@ -112,7 +112,7 @@ if (GetVersion() >= VERSION_WIN7) { ScopedComPtr<IPropertyStore> property_store; - EXPECT_TRUE(SUCCEEDED(hr = property_store.QueryFrom(i_shell_link.get()))); + EXPECT_TRUE(SUCCEEDED(hr = property_store.QueryFrom(i_shell_link.Get()))); if (FAILED(hr)) return;
diff --git a/base/values.cc b/base/values.cc index 0bcddbdd..72f6185 100644 --- a/base/values.cc +++ b/base/values.cc
@@ -553,7 +553,7 @@ // directly. case Type::DICTIONARY: { Value copy = that; - dict_ = std::move(copy.dict_); + *dict_ = std::move(*copy.dict_); return; } case Type::LIST:
diff --git a/base/values_unittest.cc b/base/values_unittest.cc index 97807ef..be1e4d8 100644 --- a/base/values_unittest.cc +++ b/base/values_unittest.cc
@@ -206,6 +206,14 @@ EXPECT_EQ(value.type(), copied_value.type()); EXPECT_EQ(123, copy); + copied_value.Clear(); + copied_value = value; + + copied_value.GetInteger("Int", ©); + + EXPECT_EQ(value.type(), copied_value.type()); + EXPECT_EQ(123, copy); + auto blank = MakeUnique<Value>(); *blank = value;
diff --git a/base/win/scoped_comptr.h b/base/win/scoped_comptr.h index ac704e0..74c429d7 100644 --- a/base/win/scoped_comptr.h +++ b/base/win/scoped_comptr.h
@@ -35,7 +35,7 @@ ptr_->AddRef(); } - ScopedComPtr(const ScopedComPtr<Interface, interface_id>& p) : ptr_(p.get()) { + ScopedComPtr(const ScopedComPtr<Interface, interface_id>& p) : ptr_(p.Get()) { if (ptr_) ptr_->AddRef(); } @@ -49,7 +49,7 @@ Reset(); } - Interface* get() const { return ptr_; } + Interface* Get() const { return ptr_; } explicit operator bool() const { return ptr_ != nullptr; } @@ -183,12 +183,12 @@ } bool operator==(const ScopedComPtr<Interface, interface_id>& rhs) const { - return ptr_ == rhs.get(); + return ptr_ == rhs.Get(); } template <typename U> bool operator==(const ScopedComPtr<U>& rhs) const { - return ptr_ == rhs.get(); + return ptr_ == rhs.Get(); } template <typename U> @@ -197,12 +197,12 @@ } bool operator!=(const ScopedComPtr<Interface, interface_id>& rhs) const { - return ptr_ != rhs.get(); + return ptr_ != rhs.Get(); } template <typename U> bool operator!=(const ScopedComPtr<U>& rhs) const { - return ptr_ != rhs.get(); + return ptr_ != rhs.Get(); } template <typename U> @@ -222,7 +222,7 @@ template <typename T, typename U> bool operator==(const T* lhs, const ScopedComPtr<U>& rhs) { - return lhs == rhs.get(); + return lhs == rhs.Get(); } template <typename T> @@ -252,7 +252,7 @@ template <typename T> std::ostream& operator<<(std::ostream& out, const ScopedComPtr<T>& p) { - return out << p.get(); + return out << p.Get(); } // Helper to make IID_PPV_ARGS work with ScopedComPtr.
diff --git a/base/win/scoped_comptr_unittest.cc b/base/win/scoped_comptr_unittest.cc index 3cde314..b5f5f36 100644 --- a/base/win/scoped_comptr_unittest.cc +++ b/base/win/scoped_comptr_unittest.cc
@@ -42,39 +42,39 @@ EXPECT_TRUE(SUCCEEDED(unk.CreateInstance(CLSID_ShellLink))); ScopedComPtr<IUnknown> unk2; unk2.Attach(unk.Detach()); - EXPECT_TRUE(unk.get() == NULL); - EXPECT_TRUE(unk2.get() != NULL); + EXPECT_TRUE(unk.Get() == NULL); + EXPECT_TRUE(unk2.Get() != NULL); ScopedComPtr<IMalloc> mem_alloc; EXPECT_TRUE(SUCCEEDED(CoGetMalloc(1, mem_alloc.Receive()))); ScopedComPtr<IUnknown> qi_test; EXPECT_HRESULT_SUCCEEDED(mem_alloc.QueryInterface(IID_PPV_ARGS(&qi_test))); - EXPECT_TRUE(qi_test.get() != NULL); + EXPECT_TRUE(qi_test.Get() != NULL); qi_test.Reset(); // test ScopedComPtr& constructor ScopedComPtr<IMalloc> copy1(mem_alloc); - EXPECT_TRUE(copy1.IsSameObject(mem_alloc.get())); - EXPECT_FALSE(copy1.IsSameObject(unk2.get())); // unk2 is valid but different - EXPECT_FALSE(copy1.IsSameObject(unk.get())); // unk is NULL + EXPECT_TRUE(copy1.IsSameObject(mem_alloc.Get())); + EXPECT_FALSE(copy1.IsSameObject(unk2.Get())); // unk2 is valid but different + EXPECT_FALSE(copy1.IsSameObject(unk.Get())); // unk is NULL IMalloc* naked_copy = copy1.Detach(); copy1 = naked_copy; // Test the =(T*) operator. naked_copy->Release(); copy1.Reset(); - EXPECT_FALSE(copy1.IsSameObject(unk2.get())); // unk2 is valid, copy1 is not + EXPECT_FALSE(copy1.IsSameObject(unk2.Get())); // unk2 is valid, copy1 is not // test Interface* constructor - ScopedComPtr<IMalloc> copy2(static_cast<IMalloc*>(mem_alloc.get())); - EXPECT_TRUE(copy2.IsSameObject(mem_alloc.get())); + ScopedComPtr<IMalloc> copy2(static_cast<IMalloc*>(mem_alloc.Get())); + EXPECT_TRUE(copy2.IsSameObject(mem_alloc.Get())); - EXPECT_TRUE(SUCCEEDED(unk.QueryFrom(mem_alloc.get()))); - EXPECT_TRUE(unk.get() != NULL); + EXPECT_TRUE(SUCCEEDED(unk.QueryFrom(mem_alloc.Get()))); + EXPECT_TRUE(unk.Get() != NULL); unk.Reset(); - EXPECT_TRUE(unk.get() == NULL); - EXPECT_TRUE(unk.IsSameObject(copy1.get())); // both are NULL + EXPECT_TRUE(unk.Get() == NULL); + EXPECT_TRUE(unk.IsSameObject(copy1.Get())); // both are NULL } TEST(ScopedComPtrTest, ScopedComPtrVector) { @@ -98,7 +98,7 @@ bleh.push_back(p2); EXPECT_EQ(p->adds, 4); EXPECT_EQ(p->releases, 1); - EXPECT_EQ(bleh[0].get(), p.get()); + EXPECT_EQ(bleh[0].Get(), p.get()); bleh.pop_back(); EXPECT_EQ(p->adds, 4); EXPECT_EQ(p->releases, 2);
diff --git a/base/win/shortcut.cc b/base/win/shortcut.cc index 856b00f..07f9a29 100644 --- a/base/win/shortcut.cc +++ b/base/win/shortcut.cc
@@ -33,7 +33,7 @@ i_persist_file->Reset(); if (FAILED(i_shell_link->CreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER)) || - FAILED(i_persist_file->QueryFrom(i_shell_link->get())) || + FAILED(i_persist_file->QueryFrom(i_shell_link->Get())) || (shortcut && FAILED((*i_persist_file)->Load(shortcut, STGM_READWRITE)))) { i_shell_link->Reset(); i_persist_file->Reset(); @@ -88,7 +88,7 @@ // |old_i_persist_file| was successfully initialized in the call above. If // so, initialize the interfaces to begin writing a new shortcut (to // overwrite the current one if successful). - if (old_i_persist_file.get()) + if (old_i_persist_file.Get()) InitializeShortcutInterfaces(NULL, &i_shell_link, &i_persist_file); break; default: @@ -96,7 +96,7 @@ } // Return false immediately upon failure to initialize shortcut interfaces. - if (!i_persist_file.get()) + if (!i_persist_file.Get()) return false; if ((properties.options & ShortcutProperties::PROPERTIES_TARGET) && @@ -113,7 +113,7 @@ if (properties.options & ShortcutProperties::PROPERTIES_ARGUMENTS) { if (FAILED(i_shell_link->SetArguments(properties.arguments.c_str()))) return false; - } else if (old_i_persist_file.get()) { + } else if (old_i_persist_file.Get()) { wchar_t current_arguments[MAX_PATH] = {0}; if (SUCCEEDED(old_i_shell_link->GetArguments(current_arguments, MAX_PATH))) { @@ -139,17 +139,17 @@ if ((has_app_id || has_dual_mode) && GetVersion() >= VERSION_WIN7) { ScopedComPtr<IPropertyStore> property_store; - if (FAILED(property_store.QueryFrom(i_shell_link.get())) || - !property_store.get()) + if (FAILED(property_store.QueryFrom(i_shell_link.Get())) || + !property_store.Get()) return false; if (has_app_id && - !SetAppIdForPropertyStore(property_store.get(), + !SetAppIdForPropertyStore(property_store.Get(), properties.app_id.c_str())) { return false; } if (has_dual_mode && - !SetBooleanValueForPropertyStore(property_store.get(), + !SetBooleanValueForPropertyStore(property_store.Get(), PKEY_AppUserModel_IsDualMode, properties.dual_mode)) { return false; @@ -204,7 +204,7 @@ ScopedComPtr<IPersistFile> persist; // Query IShellLink for the IPersistFile interface. - if (FAILED(persist.QueryFrom(i_shell_link.get()))) + if (FAILED(persist.QueryFrom(i_shell_link.Get()))) return false; // Load the shell link. @@ -251,7 +251,7 @@ if ((options & ShortcutProperties::PROPERTIES_WIN7) && GetVersion() >= VERSION_WIN7) { ScopedComPtr<IPropertyStore> property_store; - if (FAILED(property_store.QueryFrom(i_shell_link.get()))) + if (FAILED(property_store.QueryFrom(i_shell_link.Get()))) return false; if (options & ShortcutProperties::PROPERTIES_APP_ID) {
diff --git a/cc/base/switches.cc b/cc/base/switches.cc index 1c562c9..07941af 100644 --- a/cc/base/switches.cc +++ b/cc/base/switches.cc
@@ -58,7 +58,7 @@ // Renders a border around compositor layers to help debug and study // layer compositing. const char kShowCompositedLayerBorders[] = "show-composited-layer-borders"; -const char kUIShowCompositedLayerBorders[] = "ui-show-layer-borders"; +const char kUIShowCompositedLayerBorders[] = "ui-show-composited-layer-borders"; const char kCompositedRenderPassBorders[] = "renderpass"; const char kCompositedSurfaceBorders[] = "surface"; const char kCompositedLayerBorders[] = "layer";
diff --git a/cc/blink/web_scrollbar_layer_impl.cc b/cc/blink/web_scrollbar_layer_impl.cc index 2a3f2a1..d96d21b 100644 --- a/cc/blink/web_scrollbar_layer_impl.cc +++ b/cc/blink/web_scrollbar_layer_impl.cc
@@ -14,6 +14,7 @@ #include "cc/layers/painted_scrollbar_layer.h" #include "cc/layers/scrollbar_layer_interface.h" #include "cc/layers/solid_color_scrollbar_layer.h" +#include "cc/trees/element_id.h" using cc::PaintedOverlayScrollbarLayer; using cc::PaintedScrollbarLayer; @@ -41,12 +42,14 @@ base::MakeUnique<ScrollbarImpl>(std::move(scrollbar), painter, std::move(geometry)), - cc::Layer::INVALID_ID)) + cc::Layer::INVALID_ID, + cc::ElementId())) : new WebLayerImpl(PaintedScrollbarLayer::Create( base::MakeUnique<ScrollbarImpl>(std::move(scrollbar), painter, std::move(geometry)), - cc::Layer::INVALID_ID))) {} + cc::Layer::INVALID_ID, + cc::ElementId()))) {} WebScrollbarLayerImpl::WebScrollbarLayerImpl( blink::WebScrollbar::Orientation orientation, @@ -58,7 +61,8 @@ thumb_thickness, track_start, is_left_side_vertical_scrollbar, - cc::Layer::INVALID_ID))) {} + cc::Layer::INVALID_ID, + cc::ElementId()))) {} WebScrollbarLayerImpl::~WebScrollbarLayerImpl() { } @@ -70,8 +74,9 @@ void WebScrollbarLayerImpl::SetScrollLayer(blink::WebLayer* layer) { cc::Layer* scroll_layer = layer ? static_cast<WebLayerImpl*>(layer)->layer() : 0; - layer_->layer()->ToScrollbarLayer()->SetScrollLayer( - scroll_layer ? scroll_layer->id() : cc::Layer::INVALID_ID); + layer_->layer()->ToScrollbarLayer()->SetScrollInfo( + scroll_layer ? scroll_layer->id() : cc::Layer::INVALID_ID, + scroll_layer ? scroll_layer->element_id() : cc::ElementId()); } } // namespace cc_blink
diff --git a/cc/input/scrollbar_animation_controller_unittest.cc b/cc/input/scrollbar_animation_controller_unittest.cc index ead11c2..7602601 100644 --- a/cc/input/scrollbar_animation_controller_unittest.cc +++ b/cc/input/scrollbar_animation_controller_unittest.cc
@@ -105,8 +105,10 @@ clip_layer_->test_properties()->AddChild(std::move(scroll_layer)); host_impl_.active_tree()->SetRootLayerForTesting(std::move(clip)); - v_scrollbar_layer_->SetScrollLayerId(scroll_layer_ptr->id()); - h_scrollbar_layer_->SetScrollLayerId(scroll_layer_ptr->id()); + v_scrollbar_layer_->SetScrollInfo(scroll_layer_ptr->id(), + scroll_layer_ptr->element_id()); + h_scrollbar_layer_->SetScrollInfo(scroll_layer_ptr->id(), + scroll_layer_ptr->element_id()); v_scrollbar_layer_->test_properties()->opacity_can_animate = true; h_scrollbar_layer_->test_properties()->opacity_can_animate = true; clip_layer_->SetBounds(gfx::Size(100, 100)); @@ -1159,7 +1161,8 @@ clip->test_properties()->AddChild(std::move(scroll_layer)); host_impl_.active_tree()->SetRootLayerForTesting(std::move(clip)); - scrollbar_layer_->SetScrollLayerId(scroll_layer_ptr->id()); + scrollbar_layer_->SetScrollInfo(scroll_layer_ptr->id(), + scroll_layer_ptr->element_id()); clip_layer_->SetBounds(gfx::Size(100, 100)); scroll_layer_ptr->SetBounds(gfx::Size(200, 200)); host_impl_.active_tree()->BuildLayerListAndPropertyTreesForTesting();
diff --git a/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc b/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc index 50659ff..87f9fe43 100644 --- a/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc +++ b/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc
@@ -85,7 +85,8 @@ clip_layer_->test_properties()->AddChild(std::move(scroll_layer)); host_impl_.active_tree()->SetRootLayerForTesting(std::move(clip)); - scrollbar_layer_->SetScrollLayerId(scroll_layer_ptr->id()); + scrollbar_layer_->SetScrollInfo(scroll_layer_ptr->id(), + scroll_layer_ptr->element_id()); scrollbar_layer_->test_properties()->opacity_can_animate = true; clip_layer_->SetBounds(gfx::Size(100, 100)); scroll_layer_ptr->SetBounds(gfx::Size(200, 200));
diff --git a/cc/ipc/quads.mojom b/cc/ipc/quads.mojom index 5ec7e45..436c443 100644 --- a/cc/ipc/quads.mojom +++ b/cc/ipc/quads.mojom
@@ -8,6 +8,7 @@ import "cc/ipc/shared_quad_state.mojom"; import "cc/ipc/surface_id.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; +import "ui/gfx/mojo/color_space.mojom"; import "ui/gfx/mojo/transform.mojom"; struct DebugBorderQuadState { @@ -102,6 +103,7 @@ float resource_offset; float resource_multiplier; uint32 bits_per_channel; + gfx.mojom.ColorSpace video_color_space; }; union DrawQuadState {
diff --git a/cc/ipc/quads_struct_traits.cc b/cc/ipc/quads_struct_traits.cc index 011f627..2de061d5 100644 --- a/cc/ipc/quads_struct_traits.cc +++ b/cc/ipc/quads_struct_traits.cc
@@ -229,7 +229,8 @@ if (!data.ReadYaTexCoordRect(&quad->ya_tex_coord_rect) || !data.ReadUvTexCoordRect(&quad->uv_tex_coord_rect) || !data.ReadYaTexSize(&quad->ya_tex_size) || - !data.ReadUvTexSize(&quad->uv_tex_size)) { + !data.ReadUvTexSize(&quad->uv_tex_size) || + !data.ReadVideoColorSpace(&quad->video_color_space)) { return false; } quad->resources.ids[cc::YUVVideoDrawQuad::kYPlaneResourceIdIndex] =
diff --git a/cc/ipc/quads_struct_traits.h b/cc/ipc/quads_struct_traits.h index ed27b99..ebeb86c 100644 --- a/cc/ipc/quads_struct_traits.h +++ b/cc/ipc/quads_struct_traits.h
@@ -21,6 +21,7 @@ #include "cc/quads/tile_draw_quad.h" #include "cc/quads/yuv_video_draw_quad.h" #include "ui/gfx/geometry/mojo/geometry_struct_traits.h" +#include "ui/gfx/ipc/color/gfx_param_traits.h" namespace mojo { @@ -414,6 +415,11 @@ cc::YUVVideoDrawQuad::MaterialCast(&input); return quad->bits_per_channel; } + static gfx::ColorSpace video_color_space(const cc::DrawQuad& input) { + const cc::YUVVideoDrawQuad* quad = + cc::YUVVideoDrawQuad::MaterialCast(&input); + return quad->video_color_space; + } static bool Read(cc::mojom::YUVVideoQuadStateDataView data, cc::DrawQuad* out);
diff --git a/cc/ipc/transferable_resource.mojom b/cc/ipc/transferable_resource.mojom index 971536c..ea20a63 100644 --- a/cc/ipc/transferable_resource.mojom +++ b/cc/ipc/transferable_resource.mojom
@@ -6,6 +6,7 @@ import "gpu/ipc/common/mailbox_holder.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; +import "ui/gfx/mojo/color_space.mojom"; import "ui/gfx/mojo/buffer_types.mojom"; enum ResourceFormat { @@ -31,4 +32,5 @@ bool is_overlay_candidate; bool is_backed_by_surface_texture; bool wants_promotion_hint; + gfx.mojom.ColorSpace color_space; };
diff --git a/cc/ipc/transferable_resource_struct_traits.cc b/cc/ipc/transferable_resource_struct_traits.cc index 140276a..ea6c56d 100644 --- a/cc/ipc/transferable_resource_struct_traits.cc +++ b/cc/ipc/transferable_resource_struct_traits.cc
@@ -16,7 +16,8 @@ Read(cc::mojom::TransferableResourceDataView data, cc::TransferableResource* out) { if (!data.ReadSize(&out->size) || - !data.ReadMailboxHolder(&out->mailbox_holder)) + !data.ReadMailboxHolder(&out->mailbox_holder) || + !data.ReadColorSpace(&out->color_space)) return false; out->id = data.id(); out->format = static_cast<cc::ResourceFormat>(data.format());
diff --git a/cc/ipc/transferable_resource_struct_traits.h b/cc/ipc/transferable_resource_struct_traits.h index 1e3f24b..e9964c6 100644 --- a/cc/ipc/transferable_resource_struct_traits.h +++ b/cc/ipc/transferable_resource_struct_traits.h
@@ -7,6 +7,7 @@ #include "cc/ipc/transferable_resource.mojom-shared.h" #include "cc/resources/transferable_resource.h" +#include "ui/gfx/ipc/color/gfx_param_traits.h" namespace mojo { @@ -74,6 +75,11 @@ #endif } + static const gfx::ColorSpace& color_space( + const cc::TransferableResource& resource) { + return resource.color_space; + } + static bool Read(cc::mojom::TransferableResourceDataView data, cc::TransferableResource* out); };
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 72a530a..15760beb 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -1129,6 +1129,9 @@ bool use_paint_properties = paint_properties_.source_frame_number == layer_tree_host_->SourceFrameNumber(); + // The ElementId should be set first because other setters depend on it such + // as LayerImpl::SetScrollClipLayer. + layer->SetElementId(inputs_.element_id); layer->SetBackgroundColor(inputs_.background_color); layer->SetSafeOpaqueBackgroundColor(safe_opaque_background_color_); layer->SetBounds(use_paint_properties ? paint_properties_.bounds @@ -1169,7 +1172,6 @@ layer->SetScrollClipLayer(inputs_.scroll_clip_layer_id); layer->set_user_scrollable_horizontal(inputs_.user_scrollable_horizontal); layer->set_user_scrollable_vertical(inputs_.user_scrollable_vertical); - layer->SetElementId(inputs_.element_id); layer->SetMutableProperties(inputs_.mutable_properties); // When a scroll offset animation is interrupted the new scroll position on
diff --git a/cc/layers/layer.h b/cc/layers/layer.h index 58dde9c..6aac890 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h
@@ -403,6 +403,7 @@ int num_copy_requests_in_target_subtree(); + // Stable identifier for clients. See comment in cc/trees/element_id.h. void SetElementId(ElementId id); ElementId element_id() const { return inputs_.element_id; }
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index bd7b9fe..6bee362 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc
@@ -312,6 +312,10 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { DCHECK(layer->IsActive()); + // The ElementId should be set first because other setters depend on it such + // as LayerImpl::SetScrollClipLayer. + layer->SetElementId(element_id_); + layer->offset_to_transform_parent_ = offset_to_transform_parent_; layer->main_thread_scrolling_reasons_ = main_thread_scrolling_reasons_; layer->user_scrollable_horizontal_ = user_scrollable_horizontal_; @@ -346,7 +350,6 @@ layer->SetBounds(bounds_); layer->SetScrollClipLayer(scroll_clip_layer_id_); - layer->SetElementId(element_id_); layer->SetMutableProperties(mutable_properties_); // If the main thread commits multiple times before the impl thread actually
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index c1d3d58..c038ebb 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h
@@ -182,6 +182,7 @@ float Opacity() const; const gfx::Transform& Transform() const; + // Stable identifier for clients. See comment in cc/trees/element_id.h. void SetElementId(ElementId element_id); ElementId element_id() const { return element_id_; }
diff --git a/cc/layers/painted_overlay_scrollbar_layer.cc b/cc/layers/painted_overlay_scrollbar_layer.cc index 81a515e..2aa29c4 100644 --- a/cc/layers/painted_overlay_scrollbar_layer.cc +++ b/cc/layers/painted_overlay_scrollbar_layer.cc
@@ -32,16 +32,19 @@ scoped_refptr<PaintedOverlayScrollbarLayer> PaintedOverlayScrollbarLayer::Create(std::unique_ptr<Scrollbar> scrollbar, - int scroll_layer_id) { - return make_scoped_refptr( - new PaintedOverlayScrollbarLayer(std::move(scrollbar), scroll_layer_id)); + int scroll_layer_id, + ElementId scroll_element_id) { + return make_scoped_refptr(new PaintedOverlayScrollbarLayer( + std::move(scrollbar), scroll_layer_id, scroll_element_id)); } PaintedOverlayScrollbarLayer::PaintedOverlayScrollbarLayer( std::unique_ptr<Scrollbar> scrollbar, - int scroll_layer_id) + int scroll_layer_id, + ElementId scroll_element_id) : scrollbar_(std::move(scrollbar)), scroll_layer_id_(scroll_layer_id), + scroll_element_id_(scroll_element_id), thumb_thickness_(scrollbar_->ThumbThickness()), thumb_length_(scrollbar_->ThumbLength()) { DCHECK(scrollbar_->UsesNinePatchThumbResource()); @@ -49,15 +52,17 @@ PaintedOverlayScrollbarLayer::~PaintedOverlayScrollbarLayer() {} -int PaintedOverlayScrollbarLayer::ScrollLayerId() const { - return scroll_layer_id_; +ElementId PaintedOverlayScrollbarLayer::scroll_element_id() const { + return scroll_element_id_; } -void PaintedOverlayScrollbarLayer::SetScrollLayer(int layer_id) { - if (layer_id == scroll_layer_id_) +void PaintedOverlayScrollbarLayer::SetScrollInfo(int layer_id, + ElementId element_id) { + if (layer_id == scroll_layer_id_ && element_id == scroll_element_id_) return; scroll_layer_id_ = layer_id; + scroll_element_id_ = element_id; SetNeedsFullTreeSync(); } @@ -79,7 +84,7 @@ PaintedOverlayScrollbarLayerImpl* scrollbar_layer = static_cast<PaintedOverlayScrollbarLayerImpl*>(layer); - scrollbar_layer->SetScrollLayerId(scroll_layer_id_); + scrollbar_layer->SetScrollInfo(scroll_layer_id_, scroll_element_id_); scrollbar_layer->SetThumbThickness(thumb_thickness_); scrollbar_layer->SetThumbLength(thumb_length_);
diff --git a/cc/layers/painted_overlay_scrollbar_layer.h b/cc/layers/painted_overlay_scrollbar_layer.h index f7cd66e..c71f7b59 100644 --- a/cc/layers/painted_overlay_scrollbar_layer.h +++ b/cc/layers/painted_overlay_scrollbar_layer.h
@@ -22,15 +22,17 @@ static scoped_refptr<PaintedOverlayScrollbarLayer> Create( std::unique_ptr<Scrollbar> scrollbar, - int scroll_layer_id); + int scroll_layer_id, + ElementId scroll_element_id = ElementId()); bool OpacityCanAnimateOnImplThread() const override; bool AlwaysUseActiveTreeOpacity() const override; ScrollbarLayerInterface* ToScrollbarLayer() override; // ScrollbarLayerInterface - int ScrollLayerId() const override; - void SetScrollLayer(int layer_id) override; + ElementId scroll_element_id() const override; + // TODO(pdr): Remove layer_id and refactor scrollbars to just use element ids. + void SetScrollInfo(int layer_id, ElementId element_id) override; ScrollbarOrientation orientation() const override; // Layer interface @@ -40,7 +42,8 @@ protected: PaintedOverlayScrollbarLayer(std::unique_ptr<Scrollbar> scrollbar, - int scroll_layer_id); + int scroll_layer_id, + ElementId scroll_element_id); ~PaintedOverlayScrollbarLayer() override; private: @@ -59,6 +62,7 @@ std::unique_ptr<Scrollbar> scrollbar_; int scroll_layer_id_; + ElementId scroll_element_id_; int thumb_thickness_; int thumb_length_;
diff --git a/cc/layers/painted_scrollbar_layer.cc b/cc/layers/painted_scrollbar_layer.cc index 98aca6db..5ff2202 100644 --- a/cc/layers/painted_scrollbar_layer.cc +++ b/cc/layers/painted_scrollbar_layer.cc
@@ -34,16 +34,19 @@ scoped_refptr<PaintedScrollbarLayer> PaintedScrollbarLayer::Create( std::unique_ptr<Scrollbar> scrollbar, - int scroll_layer_id) { - return make_scoped_refptr( - new PaintedScrollbarLayer(std::move(scrollbar), scroll_layer_id)); + int scroll_layer_id, + ElementId scroll_element_id) { + return make_scoped_refptr(new PaintedScrollbarLayer( + std::move(scrollbar), scroll_layer_id, scroll_element_id)); } PaintedScrollbarLayer::PaintedScrollbarLayer( std::unique_ptr<Scrollbar> scrollbar, - int scroll_layer_id) + int scroll_layer_id, + ElementId scroll_element_id) : scrollbar_(std::move(scrollbar)), scroll_layer_id_(scroll_layer_id), + scroll_element_id_(scroll_element_id), internal_contents_scale_(1.f), thumb_thickness_(scrollbar_->ThumbThickness()), thumb_length_(scrollbar_->ThumbLength()), @@ -57,15 +60,16 @@ PaintedScrollbarLayer::~PaintedScrollbarLayer() {} -int PaintedScrollbarLayer::ScrollLayerId() const { - return scroll_layer_id_; +ElementId PaintedScrollbarLayer::scroll_element_id() const { + return scroll_element_id_; } -void PaintedScrollbarLayer::SetScrollLayer(int layer_id) { - if (layer_id == scroll_layer_id_) +void PaintedScrollbarLayer::SetScrollInfo(int layer_id, ElementId element_id) { + if (layer_id == scroll_layer_id_ && element_id == scroll_element_id_) return; scroll_layer_id_ = layer_id; + scroll_element_id_ = element_id; SetNeedsFullTreeSync(); } @@ -87,7 +91,7 @@ PaintedScrollbarLayerImpl* scrollbar_layer = static_cast<PaintedScrollbarLayerImpl*>(layer); - scrollbar_layer->SetScrollLayerId(scroll_layer_id_); + scrollbar_layer->SetScrollInfo(scroll_layer_id_, scroll_element_id_); scrollbar_layer->set_internal_contents_scale_and_bounds( internal_contents_scale_, internal_content_bounds_);
diff --git a/cc/layers/painted_scrollbar_layer.h b/cc/layers/painted_scrollbar_layer.h index 8e1884f..5eacb1e 100644 --- a/cc/layers/painted_scrollbar_layer.h +++ b/cc/layers/painted_scrollbar_layer.h
@@ -22,15 +22,17 @@ static scoped_refptr<PaintedScrollbarLayer> Create( std::unique_ptr<Scrollbar> scrollbar, - int scroll_layer_id); + int scroll_layer_id, + ElementId element_id = ElementId()); bool OpacityCanAnimateOnImplThread() const override; bool AlwaysUseActiveTreeOpacity() const override; ScrollbarLayerInterface* ToScrollbarLayer() override; // ScrollbarLayerInterface - int ScrollLayerId() const override; - void SetScrollLayer(int layer_id) override; + ElementId scroll_element_id() const override; + // TODO(pdr): Remove layer_id and refactor scrollbars to just use element ids. + void SetScrollInfo(int layer_id, ElementId element_id) override; ScrollbarOrientation orientation() const override; @@ -45,7 +47,8 @@ protected: PaintedScrollbarLayer(std::unique_ptr<Scrollbar> scrollbar, - int scroll_layer_id); + int scroll_layer_id, + ElementId scroll_element_id); ~PaintedScrollbarLayer() override; // For unit tests @@ -77,6 +80,7 @@ std::unique_ptr<Scrollbar> scrollbar_; int scroll_layer_id_; + ElementId scroll_element_id_; float internal_contents_scale_; gfx::Size internal_content_bounds_;
diff --git a/cc/layers/scrollbar_layer_impl_base.cc b/cc/layers/scrollbar_layer_impl_base.cc index da53036f..e9c5514d 100644 --- a/cc/layers/scrollbar_layer_impl_base.cc +++ b/cc/layers/scrollbar_layer_impl_base.cc
@@ -36,20 +36,24 @@ LayerImpl::PushPropertiesTo(layer); DCHECK(layer->ToScrollbarLayer()); layer->ToScrollbarLayer()->set_is_overlay_scrollbar(is_overlay_scrollbar_); - layer->ToScrollbarLayer()->SetScrollLayerId(ScrollLayerId()); + layer->ToScrollbarLayer()->SetScrollInfo(ScrollLayerId(), + scroll_element_id()); } ScrollbarLayerImplBase* ScrollbarLayerImplBase::ToScrollbarLayer() { return this; } -void ScrollbarLayerImplBase::SetScrollLayerId(int scroll_layer_id) { - if (scroll_layer_id_ == scroll_layer_id) +void ScrollbarLayerImplBase::SetScrollInfo(int scroll_layer_id, + ElementId scroll_element_id) { + if (scroll_layer_id_ == scroll_layer_id && + scroll_element_id == scroll_element_id) return; layer_tree_impl()->UnregisterScrollbar(this); scroll_layer_id_ = scroll_layer_id; + scroll_element_id_ = scroll_element_id; layer_tree_impl()->RegisterScrollbar(this); }
diff --git a/cc/layers/scrollbar_layer_impl_base.h b/cc/layers/scrollbar_layer_impl_base.h index 0b9b4039..21f4d6aa 100644 --- a/cc/layers/scrollbar_layer_impl_base.h +++ b/cc/layers/scrollbar_layer_impl_base.h
@@ -18,8 +18,9 @@ class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl { public: int ScrollLayerId() const { return scroll_layer_id_; } + ElementId scroll_element_id() const { return scroll_element_id_; } - void SetScrollLayerId(int scroll_layer_id); + void SetScrollInfo(int scroll_layer_id, ElementId scroll_element_id); float current_pos() const { return current_pos_; } bool SetCurrentPos(float current_pos); @@ -77,6 +78,7 @@ private: int scroll_layer_id_; + ElementId scroll_element_id_; bool is_overlay_scrollbar_; float thumb_thickness_scale_factor_;
diff --git a/cc/layers/scrollbar_layer_interface.h b/cc/layers/scrollbar_layer_interface.h index 30c335b..917f709 100644 --- a/cc/layers/scrollbar_layer_interface.h +++ b/cc/layers/scrollbar_layer_interface.h
@@ -13,8 +13,9 @@ class CC_EXPORT ScrollbarLayerInterface { public: - virtual int ScrollLayerId() const = 0; - virtual void SetScrollLayer(int layer_id) = 0; + virtual ElementId scroll_element_id() const = 0; + // TODO(pdr): Remove layer_id and refactor scrollbars to just use element ids. + virtual void SetScrollInfo(int layer_id, ElementId element_id) = 0; virtual ScrollbarOrientation orientation() const = 0;
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc index c1793b29..68613e8 100644 --- a/cc/layers/scrollbar_layer_unittest.cc +++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -152,10 +152,10 @@ const bool kIsLeftSideVerticalScrollbar = false; child2 = SolidColorScrollbarLayer::Create( scrollbar->Orientation(), thumb_thickness, track_start, - kIsLeftSideVerticalScrollbar, child1->id()); + kIsLeftSideVerticalScrollbar, child1->id(), child1->element_id()); } else { - child2 = - PaintedScrollbarLayer::Create(std::move(scrollbar), child1->id()); + child2 = PaintedScrollbarLayer::Create(std::move(scrollbar), child1->id(), + child1->element_id()); } layer_tree_root->AddChild(child1); layer_tree_root->InsertChild(child2, reverse_order ? 0 : 1); @@ -199,7 +199,8 @@ FakePaintedOverlayScrollbar* fake_scrollbar = scrollbar.get(); scoped_refptr<PaintedOverlayScrollbarLayer> scrollbar_layer = PaintedOverlayScrollbarLayer::Create(std::move(scrollbar), - layer_tree_root->id()); + layer_tree_root->id(), + layer_tree_root->element_id()); // Setup. { @@ -293,8 +294,8 @@ scoped_refptr<Layer> layer_tree_root = Layer::Create(); scoped_refptr<Layer> scroll_layer = Layer::Create(); scoped_refptr<Layer> content_layer = Layer::Create(); - scoped_refptr<Layer> scrollbar_layer = - PaintedScrollbarLayer::Create(std::move(scrollbar), scroll_layer->id()); + scoped_refptr<Layer> scrollbar_layer = PaintedScrollbarLayer::Create( + std::move(scrollbar), scroll_layer->id(), scroll_layer->element_id()); // Choose bounds to give max_scroll_offset = (30, 50). layer_tree_root->SetBounds(gfx::Size(70, 150)); @@ -362,7 +363,8 @@ scoped_refptr<Layer> root_layer = Layer::Create(); scoped_refptr<Layer> content_layer = Layer::Create(); scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = - FakePaintedScrollbarLayer::Create(false, true, root_layer->id()); + FakePaintedScrollbarLayer::Create(false, true, root_layer->id(), + root_layer->element_id()); root_layer->SetScrollClipLayerId(root_clip_layer->id()); // Give the root-clip a size that will result in MaxScrollOffset = (80, 0). @@ -377,7 +379,7 @@ root_layer->SetScrollOffset(gfx::ScrollOffset(0, 0)); scrollbar_layer->SetBounds(gfx::Size(70, 10)); - scrollbar_layer->SetScrollLayer(root_layer->id()); + scrollbar_layer->SetScrollInfo(root_layer->id(), root_layer->element_id()); scrollbar_layer->fake_scrollbar()->set_location(gfx::Point(20, 10)); scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10)); scrollbar_layer->fake_scrollbar()->set_thumb_thickness(10); @@ -401,7 +403,8 @@ scoped_refptr<Layer> root_layer = Layer::Create(); scoped_refptr<Layer> content_layer = Layer::Create(); scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = - FakePaintedScrollbarLayer::Create(false, true, root_layer->id()); + FakePaintedScrollbarLayer::Create(false, true, root_layer->id(), + root_layer->element_id()); root_layer->SetScrollClipLayerId(root_clip_layer->id()); // Give the root-clip a size that will result in MaxScrollOffset = (80, 0). @@ -416,7 +419,7 @@ root_layer->SetScrollOffset(gfx::ScrollOffset(0, 0)); scrollbar_layer->SetBounds(gfx::Size(70, 10)); - scrollbar_layer->SetScrollLayer(root_layer->id()); + scrollbar_layer->SetScrollInfo(root_layer->id(), root_layer->element_id()); scrollbar_layer->fake_scrollbar()->set_location(gfx::Point(20, 10)); scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10)); scrollbar_layer->fake_scrollbar()->set_thumb_thickness(10); @@ -479,7 +482,8 @@ // Create an overlay left side vertical scrollbar. scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = FakePaintedScrollbarLayer::Create(false, true, VERTICAL, true, true, - root_layer->id()); + root_layer->id(), + root_layer->element_id()); root_layer->SetScrollClipLayerId(root_clip_layer->id()); root_clip_layer->SetBounds(gfx::Size(50, 20)); root_layer->SetBounds(gfx::Size(50, 100)); @@ -490,7 +494,7 @@ root_layer->SetScrollOffset(gfx::ScrollOffset(0, 0)); scrollbar_layer->SetBounds(gfx::Size(10, 20)); - scrollbar_layer->SetScrollLayer(root_layer->id()); + scrollbar_layer->SetScrollInfo(root_layer->id(), root_layer->element_id()); scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 10, 20)); scrollbar_layer->fake_scrollbar()->set_thumb_thickness(10); scrollbar_layer->fake_scrollbar()->set_thumb_length(4); @@ -599,7 +603,8 @@ const bool kIsLeftSideVerticalScrollbar = false; child2 = SolidColorScrollbarLayer::Create( scrollbar->Orientation(), kThumbThickness, kTrackStart, - kIsLeftSideVerticalScrollbar, scroll_layer->id()); + kIsLeftSideVerticalScrollbar, scroll_layer->id(), + scroll_layer->element_id()); scroll_layer->AddChild(child1); scroll_layer->InsertChild(child2, 1); layer_tree_root->AddChild(scroll_layer); @@ -651,7 +656,8 @@ const bool kIsLeftSideVerticalScrollbar = false; scrollbar_layer = SolidColorScrollbarLayer::Create( scrollbar->Orientation(), kThumbThickness, kTrackStart, - kIsLeftSideVerticalScrollbar, scroll_layer->id()); + kIsLeftSideVerticalScrollbar, scroll_layer->id(), + scroll_layer->element_id()); scroll_layer->AddChild(child1); scroll_layer->InsertChild(scrollbar_layer, 1); layer_tree_root->AddChild(scroll_layer); @@ -732,7 +738,8 @@ const bool kIsLeftSideVerticalScrollbar = false; scrollbar_layer = SolidColorScrollbarLayer::Create( scrollbar->Orientation(), kThumbThickness, kTrackStart, - kIsLeftSideVerticalScrollbar, scroll_layer->id()); + kIsLeftSideVerticalScrollbar, scroll_layer->id(), + scroll_layer->element_id()); scroll_layer->SetScrollClipLayerId(layer_tree_root->id()); scroll_layer->AddChild(child1); scroll_layer->InsertChild(scrollbar_layer, 1); @@ -744,7 +751,8 @@ layer_tree_host_->UpdateLayers(); layer_tree_host_->CommitAndCreateLayerImplTree(); LayerTreeHostImpl* host_impl = layer_tree_host_->host_impl(); - EXPECT_TRUE(host_impl->ScrollbarAnimationControllerForId(scroll_layer->id())); + EXPECT_TRUE(host_impl->ScrollbarAnimationControllerForElementId( + scroll_layer->element_id())); scroll_layer->SetBounds(gfx::Size(20, 20)); scroll_layer->SetForceRenderSurfaceForTesting(true); @@ -879,10 +887,12 @@ const bool kIsLeftSideVerticalScrollbar = false; scrollbar_layer = SolidColorScrollbarLayer::Create( scrollbar->Orientation(), kThumbThickness, kTrackStart, - kIsLeftSideVerticalScrollbar, layer_tree_root->id()); + kIsLeftSideVerticalScrollbar, layer_tree_root->id(), + layer_tree_root->element_id()); } else { - scrollbar_layer = PaintedScrollbarLayer::Create(std::move(scrollbar), - layer_tree_root->id()); + scrollbar_layer = PaintedScrollbarLayer::Create( + std::move(scrollbar), layer_tree_root->id(), + layer_tree_root->element_id()); } layer_tree_root->AddChild(content_layer); layer_tree_root->AddChild(scrollbar_layer); @@ -941,7 +951,8 @@ scoped_refptr<Layer> layer_tree_root = Layer::Create(); scoped_refptr<Layer> content_layer = Layer::Create(); scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = - FakePaintedScrollbarLayer::Create(false, true, layer_tree_root->id()); + FakePaintedScrollbarLayer::Create(false, true, layer_tree_root->id(), + layer_tree_root->element_id()); layer_tree_root->AddChild(content_layer); layer_tree_root->AddChild(scrollbar_layer); @@ -1101,7 +1112,8 @@ scoped_refptr<Layer> layer_tree_root = Layer::Create(); scoped_refptr<Layer> content_layer = Layer::Create(); scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = - FakePaintedScrollbarLayer::Create(false, true, layer_tree_root->id()); + FakePaintedScrollbarLayer::Create(false, true, layer_tree_root->id(), + layer_tree_root->element_id()); layer_tree_root->AddChild(content_layer); layer_tree_root->AddChild(scrollbar_layer); @@ -1171,7 +1183,8 @@ scoped_refptr<Layer> layer_tree_root = Layer::Create(); scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = FakePaintedScrollbarLayer::Create(paint_during_update, has_thumb, - layer_tree_root->id()); + layer_tree_root->id(), + layer_tree_root->element_id()); layer_tree_root->AddChild(scrollbar_layer);
diff --git a/cc/layers/solid_color_scrollbar_layer.cc b/cc/layers/solid_color_scrollbar_layer.cc index 2eb5484..e53941e 100644 --- a/cc/layers/solid_color_scrollbar_layer.cc +++ b/cc/layers/solid_color_scrollbar_layer.cc
@@ -27,10 +27,11 @@ int thumb_thickness, int track_start, bool is_left_side_vertical_scrollbar, - int scroll_layer_id) { + int scroll_layer_id, + ElementId scroll_element_id) { return make_scoped_refptr(new SolidColorScrollbarLayer( orientation, thumb_thickness, track_start, - is_left_side_vertical_scrollbar, scroll_layer_id)); + is_left_side_vertical_scrollbar, scroll_layer_id, scroll_element_id)); } SolidColorScrollbarLayer::SolidColorScrollbarLayerInputs:: @@ -38,8 +39,10 @@ int thumb_thickness, int track_start, bool is_left_side_vertical_scrollbar, - int scroll_layer_id) + int scroll_layer_id, + ElementId scroll_element_id) : scroll_layer_id(scroll_layer_id), + scroll_element_id(scroll_element_id), orientation(orientation), thumb_thickness(thumb_thickness), track_start(track_start), @@ -53,12 +56,14 @@ int thumb_thickness, int track_start, bool is_left_side_vertical_scrollbar, - int scroll_layer_id) + int scroll_layer_id, + ElementId scroll_element_id) : solid_color_scrollbar_layer_inputs_(orientation, thumb_thickness, track_start, is_left_side_vertical_scrollbar, - scroll_layer_id) { + scroll_layer_id, + scroll_element_id) { Layer::SetOpacity(0.f); } @@ -79,8 +84,9 @@ SolidColorScrollbarLayerImpl* scrollbar_layer = static_cast<SolidColorScrollbarLayerImpl*>(layer); - scrollbar_layer->SetScrollLayerId( - solid_color_scrollbar_layer_inputs_.scroll_layer_id); + scrollbar_layer->SetScrollInfo( + solid_color_scrollbar_layer_inputs_.scroll_layer_id, + solid_color_scrollbar_layer_inputs_.scroll_element_id); } void SolidColorScrollbarLayer::SetNeedsDisplayRect(const gfx::Rect& rect) { @@ -95,15 +101,18 @@ return true; } -int SolidColorScrollbarLayer::ScrollLayerId() const { - return solid_color_scrollbar_layer_inputs_.scroll_layer_id; +ElementId SolidColorScrollbarLayer::scroll_element_id() const { + return solid_color_scrollbar_layer_inputs_.scroll_element_id; } -void SolidColorScrollbarLayer::SetScrollLayer(int layer_id) { - if (layer_id == solid_color_scrollbar_layer_inputs_.scroll_layer_id) +void SolidColorScrollbarLayer::SetScrollInfo(int layer_id, + ElementId element_id) { + if (layer_id == solid_color_scrollbar_layer_inputs_.scroll_layer_id && + element_id == solid_color_scrollbar_layer_inputs_.scroll_element_id) return; solid_color_scrollbar_layer_inputs_.scroll_layer_id = layer_id; + solid_color_scrollbar_layer_inputs_.scroll_element_id = element_id; SetNeedsFullTreeSync(); }
diff --git a/cc/layers/solid_color_scrollbar_layer.h b/cc/layers/solid_color_scrollbar_layer.h index 319674c..814851c 100644 --- a/cc/layers/solid_color_scrollbar_layer.h +++ b/cc/layers/solid_color_scrollbar_layer.h
@@ -22,7 +22,8 @@ int thumb_thickness, int track_start, bool is_left_side_vertical_scrollbar, - int scroll_layer_id); + int scroll_layer_id, + ElementId scroll_element_id); // Layer overrides. bool OpacityCanAnimateOnImplThread() const override; @@ -35,8 +36,9 @@ void SetNeedsDisplayRect(const gfx::Rect& rect) override; // ScrollbarLayerInterface - int ScrollLayerId() const override; - void SetScrollLayer(int layer_id) override; + ElementId scroll_element_id() const override; + // TODO(pdr): Remove layer_id and refactor scrollbars to just use element ids. + void SetScrollInfo(int layer_id, ElementId element_id) override; ScrollbarOrientation orientation() const override; @@ -57,7 +59,8 @@ int thumb_thickness, int track_start, bool is_left_side_vertical_scrollbar, - int scroll_layer_id); + int scroll_layer_id, + ElementId scroll_element_id); ~SolidColorScrollbarLayer() override; private: @@ -69,10 +72,12 @@ int thumb_thickness, int track_start, bool is_left_side_vertical_scrollbar, - int scroll_layer_id); + int scroll_layer_id, + ElementId scroll_element_id); ~SolidColorScrollbarLayerInputs(); int scroll_layer_id; + ElementId scroll_element_id; ScrollbarOrientation orientation; int thumb_thickness; int track_start;
diff --git a/cc/surfaces/compositor_frame_sink_support_unittest.cc b/cc/surfaces/compositor_frame_sink_support_unittest.cc index 30de5764a..03baed9 100644 --- a/cc/surfaces/compositor_frame_sink_support_unittest.cc +++ b/cc/surfaces/compositor_frame_sink_support_unittest.cc
@@ -4,7 +4,6 @@ #include "cc/surfaces/compositor_frame_sink_support.h" -#include "base/debug/stack_trace.h" #include "base/macros.h" #include "cc/output/compositor_frame.h" #include "cc/surfaces/compositor_frame_sink_support_client.h" @@ -127,7 +126,8 @@ } // namespace -class CompositorFrameSinkSupportTest : public testing::Test { +class CompositorFrameSinkSupportTest : public testing::Test, + public SurfaceObserver { public: CompositorFrameSinkSupportTest() : surface_manager_(SurfaceManager::LifetimeType::REFERENCES) {} @@ -194,6 +194,7 @@ surface_manager_.SetDependencyTracker( base::MakeUnique<SurfaceDependencyTracker>(&surface_manager_, begin_frame_source_.get())); + surface_manager_.AddObserver(this); supports_.push_back(CompositorFrameSinkSupport::Create( &support_client_, &surface_manager_, kDisplayFrameSink, is_root, handles_frame_sink_id_invalidation, needs_sync_points)); @@ -216,6 +217,7 @@ } void TearDown() override { + surface_manager_.RemoveObserver(this); surface_manager_.SetDependencyTracker(nullptr); surface_manager_.UnregisterBeginFrameSource(begin_frame_source_.get()); @@ -224,12 +226,25 @@ begin_frame_source_.reset(); supports_.clear(); + + damaged_surfaces_.clear(); + } + + bool IsSurfaceDamaged(const SurfaceId& surface_id) const { + return damaged_surfaces_.count(surface_id) > 0; + } + + // SurfaceObserver implementation: + void OnSurfaceCreated(const SurfaceInfo& surface_info) override {} + void OnSurfaceDamaged(const SurfaceId& surface_id, bool* changed) override { + damaged_surfaces_.insert(surface_id); } protected: testing::NiceMock<MockCompositorFrameSinkSupportClient> support_client_; private: + base::flat_set<SurfaceId> damaged_surfaces_; SurfaceManager surface_manager_; std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source_; std::vector<std::unique_ptr<CompositorFrameSinkSupport>> supports_; @@ -321,6 +336,8 @@ EXPECT_TRUE(parent_surface()->HasPendingFrame()); EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id1)); + // The parent should not report damage until it activates. + EXPECT_FALSE(IsSurfaceDamaged(parent_id)); child_support1().SubmitCompositorFrame(child_id1.local_surface_id(), MakeCompositorFrame({child_id2})); @@ -331,6 +348,9 @@ EXPECT_TRUE(child_surface1()->HasPendingFrame()); EXPECT_THAT(child_surface1()->blocking_surfaces(), UnorderedElementsAre(child_id2)); + // The parent and child should not report damage until they activate. + EXPECT_FALSE(IsSurfaceDamaged(parent_id)); + EXPECT_FALSE(IsSurfaceDamaged(child_id1)); // The parent should still be blocked on |child_id1| because it's pending. EXPECT_THAT(parent_surface()->blocking_surfaces(), @@ -352,6 +372,12 @@ EXPECT_TRUE(parent_surface()->HasActiveFrame()); EXPECT_FALSE(parent_surface()->HasPendingFrame()); EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); + + // All three surfaces |parent_id|, |child_id1|, and |child_id2| should + // now report damage. This would trigger a new display frame. + EXPECT_TRUE(IsSurfaceDamaged(parent_id)); + EXPECT_TRUE(IsSurfaceDamaged(child_id1)); + EXPECT_TRUE(IsSurfaceDamaged(child_id2)); } // parent_surface and child_surface1 are blocked on |child_id2|. @@ -541,8 +567,11 @@ const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1); // child_support1 submits a CompositorFrame without any dependencies. + // DidReceiveCompositorFrameAck should call on immediate activation. + EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(1); child_support1().SubmitCompositorFrame(child_id1.local_surface_id(), MakeCompositorFrame()); + testing::Mock::VerifyAndClearExpectations(&support_client_); // Verify that the child surface is not blocked. EXPECT_TRUE(child_surface1()->HasActiveFrame()); @@ -554,7 +583,10 @@ // parent_support submits a CompositorFrame that depends on |child_id1| // (which is already active) and |child_id2|. Thus, the parent should not - // activate immediately. + // activate immediately. DidReceiveCompositorFrameAck should not be called + // immediately because the parent CompositorFrame is also blocked on + // |child_id2|. + EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0); parent_support().SubmitCompositorFrame( parent_id.local_surface_id(), MakeCompositorFrame({child_id1, child_id2})); @@ -563,14 +595,19 @@ EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id2)); EXPECT_THAT(GetChildReferences(parent_id), IsEmpty()); + testing::Mock::VerifyAndClearExpectations(&support_client_); // Verify that there's a temporary reference for |child_id1| that still // exists. EXPECT_TRUE(HasTemporaryReference(child_id1)); // child_support2 submits a CompositorFrame without any dependencies. + // Both the child and the parent should immediately ACK CompositorFrames + // on activation. + EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(2); child_support2().SubmitCompositorFrame(child_id2.local_surface_id(), MakeCompositorFrame()); + testing::Mock::VerifyAndClearExpectations(&support_client_); // Verify that the child surface is not blocked. EXPECT_TRUE(child_surface1()->HasActiveFrame()); @@ -689,6 +726,7 @@ // The parent submits a CompositorFrame that depends on |child_id1| before the // child submits a CompositorFrame. + EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0); parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), MakeCompositorFrame({child_id1})); @@ -697,12 +735,17 @@ EXPECT_TRUE(parent_surface()->HasPendingFrame()); EXPECT_THAT(parent_surface()->blocking_surfaces(), UnorderedElementsAre(child_id1)); + testing::Mock::VerifyAndClearExpectations(&support_client_); // Verify that no references are added while the CompositorFrame is pending. EXPECT_THAT(GetChildReferences(parent_id), IsEmpty()); + // DidReceiveCompositorFrameAck should get called twice: once for the child + // and once for the now active parent CompositorFrame. + EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(2); child_support1().SubmitCompositorFrame( child_id1.local_surface_id(), MakeCompositorFrame(empty_surface_ids())); + testing::Mock::VerifyAndClearExpectations(&support_client_); // Verify that the child CompositorFrame activates immediately. EXPECT_TRUE(child_surface1()->HasActiveFrame()); @@ -720,8 +763,11 @@ EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1)); // The parent submits another CompositorFrame that depends on |child_id2|. + // Submitting a pending CompositorFrame will not trigger a CompositorFrameAck. + EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0); parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), MakeCompositorFrame({child_id2})); + testing::Mock::VerifyAndClearExpectations(&support_client_); // The parent surface should now have both a pending and activate // CompositorFrame. Verify that the set of child references from
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc index a161eee5..80d5a7a 100644 --- a/cc/surfaces/surface.cc +++ b/cc/surfaces/surface.cc
@@ -32,25 +32,20 @@ Surface::~Surface() { ClearCopyRequests(); - if (factory_) { - if (pending_frame_) - UnrefFrameResources(*pending_frame_); - if (active_frame_) - UnrefFrameResources(*active_frame_); - } - if (!draw_callback_.is_null()) - draw_callback_.Run(); - for (auto& observer : observers_) observer.OnSurfaceDiscarded(this); observers_.Clear(); + + UnrefFrameResourcesAndRunDrawCallback(std::move(pending_frame_data_)); + UnrefFrameResourcesAndRunDrawCallback(std::move(active_frame_data_)); } void Surface::SetPreviousFrameSurface(Surface* surface) { - DCHECK(surface); + DCHECK(surface && (HasActiveFrame() || HasPendingFrame())); frame_index_ = surface->frame_index() + 1; previous_frame_surface_id_ = surface->surface_id(); - CompositorFrame& frame = active_frame_ ? *active_frame_ : *pending_frame_; + CompositorFrame& frame = active_frame_data_ ? active_frame_data_->frame + : pending_frame_data_->frame; surface->TakeLatencyInfo(&frame.metadata.latency_info); surface->TakeLatencyInfoFromPendingFrame(&frame.metadata.latency_info); } @@ -58,49 +53,47 @@ void Surface::QueueFrame(CompositorFrame frame, const DrawCallback& callback) { TakeLatencyInfoFromPendingFrame(&frame.metadata.latency_info); - base::Optional<CompositorFrame> previous_pending_frame = - std::move(pending_frame_); - pending_frame_.reset(); + base::Optional<FrameData> previous_pending_frame_data = + std::move(pending_frame_data_); + pending_frame_data_.reset(); - UpdateBlockingSurfaces(previous_pending_frame, frame); + UpdateBlockingSurfaces(previous_pending_frame_data.has_value(), frame); // Receive and track the resources referenced from the CompositorFrame // regardless of whether it's pending or active. factory_->ReceiveFromChild(frame.resource_list); - if (!blocking_surfaces_.empty()) { - pending_frame_ = std::move(frame); + bool is_pending_frame = !blocking_surfaces_.empty(); + + if (is_pending_frame) { + pending_frame_data_ = FrameData(std::move(frame), callback); // Ask the surface manager to inform |this| when its dependencies are // resolved. factory_->manager()->RequestSurfaceResolution(this); } else { // If there are no blockers, then immediately activate the frame. - ActivateFrame(std::move(frame)); + ActivateFrame(FrameData(std::move(frame), callback)); } // Returns resources for the previous pending frame. - if (previous_pending_frame) - UnrefFrameResources(*previous_pending_frame); - - if (!draw_callback_.is_null()) - draw_callback_.Run(); - draw_callback_ = callback; + UnrefFrameResourcesAndRunDrawCallback(std::move(previous_pending_frame_data)); } void Surface::EvictFrame() { QueueFrame(CompositorFrame(), DrawCallback()); - active_frame_.reset(); + active_frame_data_.reset(); } void Surface::RequestCopyOfOutput( std::unique_ptr<CopyOutputRequest> copy_request) { - if (!active_frame_ || active_frame_->render_pass_list.empty()) { + if (!active_frame_data_ || + active_frame_data_->frame.render_pass_list.empty()) { copy_request->SendEmptyResult(); return; } std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests = - active_frame_->render_pass_list.back()->copy_requests; + active_frame_data_->frame.render_pass_list.back()->copy_requests; if (copy_request->has_source()) { const base::UnguessableToken& source = copy_request->source(); @@ -138,8 +131,8 @@ } void Surface::ActivatePendingFrameForDeadline() { - if (!pending_frame_ || - !pending_frame_->metadata.can_activate_before_dependencies) { + if (!pending_frame_data_ || + !pending_frame_data_->frame.metadata.can_activate_before_dependencies) { return; } @@ -149,52 +142,62 @@ ActivatePendingFrame(); } +Surface::FrameData::FrameData(CompositorFrame&& frame, + const DrawCallback& draw_callback) + : frame(std::move(frame)), draw_callback(draw_callback) {} + +Surface::FrameData::FrameData(FrameData&& other) = default; + +Surface::FrameData& Surface::FrameData::operator=(FrameData&& other) = default; + +Surface::FrameData::~FrameData() = default; + void Surface::ActivatePendingFrame() { - DCHECK(pending_frame_); - ActivateFrame(std::move(pending_frame_.value())); - pending_frame_.reset(); + DCHECK(pending_frame_data_); + ActivateFrame(std::move(*pending_frame_data_)); + pending_frame_data_.reset(); } // A frame is activated if all its Surface ID dependences are active or a // deadline has hit and the frame was forcibly activated by the display // compositor. -void Surface::ActivateFrame(CompositorFrame frame) { +void Surface::ActivateFrame(FrameData frame_data) { DCHECK(factory_); // Save root pass copy requests. std::vector<std::unique_ptr<CopyOutputRequest>> old_copy_requests; - if (active_frame_ && !active_frame_->render_pass_list.empty()) { + if (active_frame_data_ && + !active_frame_data_->frame.render_pass_list.empty()) { std::swap(old_copy_requests, - active_frame_->render_pass_list.back()->copy_requests); + active_frame_data_->frame.render_pass_list.back()->copy_requests); } ClearCopyRequests(); - TakeLatencyInfo(&frame.metadata.latency_info); + TakeLatencyInfo(&frame_data.frame.metadata.latency_info); - base::Optional<CompositorFrame> previous_frame = std::move(active_frame_); - active_frame_ = std::move(frame); + base::Optional<FrameData> previous_frame_data = std::move(active_frame_data_); + + active_frame_data_ = std::move(frame_data); for (auto& copy_request : old_copy_requests) RequestCopyOfOutput(std::move(copy_request)); // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't // increment frame index for them. - if (!active_frame_->render_pass_list.empty()) + if (!active_frame_data_->frame.render_pass_list.empty()) ++frame_index_; previous_frame_surface_id_ = surface_id(); - if (previous_frame) - UnrefFrameResources(*previous_frame); + UnrefFrameResourcesAndRunDrawCallback(std::move(previous_frame_data)); for (auto& observer : observers_) observer.OnSurfaceActivated(this); } -void Surface::UpdateBlockingSurfaces( - const base::Optional<CompositorFrame>& previous_pending_frame, - const CompositorFrame& current_frame) { +void Surface::UpdateBlockingSurfaces(bool has_previous_pending_frame, + const CompositorFrame& current_frame) { // If there is no SurfaceDependencyTracker installed then the |current_frame| // does not block on anything. if (!factory_->manager()->dependency_tracker()) { @@ -215,7 +218,7 @@ // If this Surface has a previous pending frame, then we must determine the // changes in dependencies so that we can update the SurfaceDependencyTracker // map. - if (previous_pending_frame.has_value()) { + if (has_previous_pending_frame) { SurfaceDependencies removed_dependencies; for (const SurfaceId& surface_id : blocking_surfaces_) { if (!new_blocking_surfaces.count(surface_id)) @@ -243,10 +246,10 @@ void Surface::TakeCopyOutputRequests( std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests) { DCHECK(copy_requests->empty()); - if (!active_frame_) + if (!active_frame_data_) return; - for (const auto& render_pass : active_frame_->render_pass_list) { + for (const auto& render_pass : active_frame_data_->frame.render_pass_list) { for (auto& request : render_pass->copy_requests) { copy_requests->insert( std::make_pair(render_pass->id, std::move(request))); @@ -256,25 +259,25 @@ } const CompositorFrame& Surface::GetActiveFrame() const { - DCHECK(active_frame_); - return active_frame_.value(); + DCHECK(active_frame_data_); + return active_frame_data_->frame; } const CompositorFrame& Surface::GetPendingFrame() { - DCHECK(pending_frame_); - return pending_frame_.value(); + DCHECK(pending_frame_data_); + return pending_frame_data_->frame; } void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) { - if (!active_frame_) + if (!active_frame_data_) return; - TakeLatencyInfoFromFrame(&active_frame_.value(), latency_info); + TakeLatencyInfoFromFrame(&active_frame_data_->frame, latency_info); } void Surface::RunDrawCallbacks() { - if (!draw_callback_.is_null()) { - DrawCallback callback = draw_callback_; - draw_callback_ = DrawCallback(); + if (active_frame_data_ && !active_frame_data_->draw_callback.is_null()) { + DrawCallback callback = active_frame_data_->draw_callback; + active_frame_data_->draw_callback = DrawCallback(); callback.Run(); } } @@ -293,18 +296,26 @@ }); } -void Surface::UnrefFrameResources(const CompositorFrame& frame) { +void Surface::UnrefFrameResourcesAndRunDrawCallback( + base::Optional<FrameData> frame_data) { + if (!frame_data || !factory_) + return; + ReturnedResourceArray resources; - TransferableResource::ReturnResources(frame.resource_list, &resources); + TransferableResource::ReturnResources(frame_data->frame.resource_list, + &resources); // No point in returning same sync token to sender. for (auto& resource : resources) resource.sync_token.Clear(); factory_->UnrefResources(resources); + + if (!frame_data->draw_callback.is_null()) + frame_data->draw_callback.Run(); } void Surface::ClearCopyRequests() { - if (active_frame_) { - for (const auto& render_pass : active_frame_->render_pass_list) { + if (active_frame_data_) { + for (const auto& render_pass : active_frame_data_->frame.render_pass_list) { for (const auto& copy_request : render_pass->copy_requests) copy_request->SendEmptyResult(); } @@ -313,9 +324,9 @@ void Surface::TakeLatencyInfoFromPendingFrame( std::vector<ui::LatencyInfo>* latency_info) { - if (!pending_frame_) + if (!pending_frame_data_) return; - TakeLatencyInfoFromFrame(&pending_frame_.value(), latency_info); + TakeLatencyInfoFromFrame(&pending_frame_data_->frame, latency_info); } // static
diff --git a/cc/surfaces/surface.h b/cc/surfaces/surface.h index 6cd9bbf..7614440f 100644 --- a/cc/surfaces/surface.h +++ b/cc/surfaces/surface.h
@@ -102,29 +102,39 @@ } const std::vector<SurfaceId>* active_referenced_surfaces() const { - return active_frame_ ? &active_frame_->metadata.referenced_surfaces - : nullptr; + return active_frame_data_ + ? &active_frame_data_->frame.metadata.referenced_surfaces + : nullptr; } const SurfaceDependencies& blocking_surfaces() const { return blocking_surfaces_; } - bool HasActiveFrame() const { return active_frame_.has_value(); } - bool HasPendingFrame() const { return pending_frame_.has_value(); } + bool HasActiveFrame() const { return active_frame_data_.has_value(); } + bool HasPendingFrame() const { return pending_frame_data_.has_value(); } bool destroyed() const { return destroyed_; } void set_destroyed(bool destroyed) { destroyed_ = destroyed; } private: + struct FrameData { + FrameData(CompositorFrame&& frame, const DrawCallback& draw_callback); + FrameData(FrameData&& other); + ~FrameData(); + FrameData& operator=(FrameData&& other); + CompositorFrame frame; + DrawCallback draw_callback; + }; + void ActivatePendingFrame(); // Called when all of the surface's dependencies have been resolved. - void ActivateFrame(CompositorFrame frame); - void UpdateBlockingSurfaces( - const base::Optional<CompositorFrame>& previous_pending_frame, - const CompositorFrame& current_frame); + void ActivateFrame(FrameData frame_data); + void UpdateBlockingSurfaces(bool has_previous_pending_frame, + const CompositorFrame& current_frame); - void UnrefFrameResources(const CompositorFrame& frame_data); + void UnrefFrameResourcesAndRunDrawCallback( + base::Optional<FrameData> frame_data); void ClearCopyRequests(); void TakeLatencyInfoFromPendingFrame( @@ -136,9 +146,9 @@ SurfaceId surface_id_; SurfaceId previous_frame_surface_id_; base::WeakPtr<SurfaceFactory> factory_; - // TODO(jamesr): Support multiple frames in flight. - base::Optional<CompositorFrame> pending_frame_; - base::Optional<CompositorFrame> active_frame_; + + base::Optional<FrameData> pending_frame_data_; + base::Optional<FrameData> active_frame_data_; int frame_index_; bool destroyed_; std::vector<SurfaceSequence> destruction_dependencies_; @@ -150,8 +160,6 @@ SurfaceDependencies blocking_surfaces_; base::ObserverList<PendingFrameObserver, true> observers_; - DrawCallback draw_callback_; - DISALLOW_COPY_AND_ASSIGN(Surface); };
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc index 91beec72..a5e31dd 100644 --- a/cc/surfaces/surface_aggregator.cc +++ b/cc/surfaces/surface_aggregator.cc
@@ -144,7 +144,8 @@ } int SurfaceAggregator::ChildIdForSurface(Surface* surface) { - auto it = surface_id_to_resource_child_id_.find(surface->surface_id()); + SurfaceToResourceChildIdMap::iterator it = + surface_id_to_resource_child_id_.find(surface->surface_id()); if (it == surface_id_to_resource_child_id_.end()) { int child_id = provider_->CreateChild(base::Bind(&UnrefHelper, surface->factory())); @@ -238,7 +239,7 @@ return; } - referenced_surfaces_.insert(surface_id); + SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; // TODO(vmpstr): provider check is a hack for unittests that don't set up a // resource provider. ResourceProvider::ResourceIdMap empty_map; @@ -336,8 +337,7 @@ gfx::RectF(surface_quad->rect)); } - // Need to re-query since referenced_surfaces_ iterators are not stable. - referenced_surfaces_.erase(referenced_surfaces_.find(surface_id)); + referenced_surfaces_.erase(it); } void SurfaceAggregator::AddColorConversionPass() { @@ -568,7 +568,8 @@ for (const auto& surface : previous_contained_surfaces_) { if (!contained_surfaces_.count(surface.first)) { // Release resources of removed surface. - auto it = surface_id_to_resource_child_id_.find(surface.first); + SurfaceToResourceChildIdMap::iterator it = + surface_id_to_resource_child_id_.find(surface.first); if (it != surface_id_to_resource_child_id_.end()) { provider_->DestroyChild(it->second); surface_id_to_resource_child_id_.erase(it); @@ -652,18 +653,13 @@ }; std::vector<SurfaceInfo> child_surfaces; - // This data is created once and typically small or empty. Collect all items - // and pass to a flat_vector to sort once. - std::vector<int> pixel_moving_background_filter_passes_data; + std::unordered_set<int> pixel_moving_background_filter_passes; for (const auto& render_pass : frame.render_pass_list) { if (render_pass->background_filters.HasFilterThatMovesPixels()) { - pixel_moving_background_filter_passes_data.push_back( + pixel_moving_background_filter_passes.insert( RemapPassId(render_pass->id, surface_id)); } } - base::flat_set<int> pixel_moving_background_filter_passes( - std::move(pixel_moving_background_filter_passes_data), - base::KEEP_FIRST_OF_DUPES); for (const auto& render_pass : base::Reversed(frame.render_pass_list)) { int remapped_pass_id = RemapPassId(render_pass->id, surface_id); @@ -732,7 +728,8 @@ // Avoid infinite recursion by adding current surface to // referenced_surfaces_. - referenced_surfaces_.insert(surface->surface_id()); + SurfaceSet::iterator it = + referenced_surfaces_.insert(surface->surface_id()).first; for (const auto& surface_info : child_surfaces) { gfx::Rect surface_damage = PrewalkTree(surface_info.id, surface_info.has_moved_pixels, @@ -772,7 +769,7 @@ } } - referenced_surfaces_.erase(referenced_surfaces_.find(surface->surface_id())); + referenced_surfaces_.erase(it); if (!damage_rect.IsEmpty() && frame.metadata.may_contain_video) result->may_contain_video = true; return damage_rect; @@ -813,7 +810,7 @@ } } } else { - auto it = referenced_surfaces_.insert(surface_id).first; + SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; CopyPasses(frame, surface); referenced_surfaces_.erase(it); } @@ -863,7 +860,7 @@ frame.metadata.may_contain_video = prewalk_result.may_contain_video; CopyUndrawnSurfaces(&prewalk_result); - auto it = referenced_surfaces_.insert(surface_id).first; + SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; CopyPasses(root_surface_frame, surface); referenced_surfaces_.erase(it); AddColorConversionPass(); @@ -893,8 +890,10 @@ contained_surfaces_.swap(previous_contained_surfaces_); contained_surfaces_.clear(); - for (auto it : previous_contained_surfaces_) { - Surface* surface = manager_->GetSurfaceForId(it.first); + for (SurfaceIndexMap::iterator it = previous_contained_surfaces_.begin(); + it != previous_contained_surfaces_.end(); + ++it) { + Surface* surface = manager_->GetSurfaceForId(it->first); if (surface) surface->TakeLatencyInfo(&frame.metadata.latency_info); } @@ -915,7 +914,8 @@ } void SurfaceAggregator::ReleaseResources(const SurfaceId& surface_id) { - auto it = surface_id_to_resource_child_id_.find(surface_id); + SurfaceToResourceChildIdMap::iterator it = + surface_id_to_resource_child_id_.find(surface_id); if (it != surface_id_to_resource_child_id_.end()) { provider_->DestroyChild(it->second); surface_id_to_resource_child_id_.erase(it);
diff --git a/cc/surfaces/surface_aggregator.h b/cc/surfaces/surface_aggregator.h index 5fe0c3d7..ec69f5d 100644 --- a/cc/surfaces/surface_aggregator.h +++ b/cc/surfaces/surface_aggregator.h
@@ -5,10 +5,12 @@ #ifndef CC_SURFACES_SURFACE_AGGREGATOR_H_ #define CC_SURFACES_SURFACE_AGGREGATOR_H_ +#include <map> #include <memory> +#include <set> +#include <unordered_map> +#include <unordered_set> -#include "base/containers/flat_map.h" -#include "base/containers/flat_set.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "cc/quads/draw_quad.h" @@ -28,7 +30,7 @@ class CC_SURFACES_EXPORT SurfaceAggregator { public: - using SurfaceIndexMap = base::flat_map<SurfaceId, int>; + using SurfaceIndexMap = std::unordered_map<SurfaceId, int, SurfaceIdHash>; SurfaceAggregator(SurfaceManager* manager, ResourceProvider* provider, @@ -63,7 +65,7 @@ ~PrewalkResult(); // This is the set of Surfaces that were referenced by another Surface, but // not included in a SurfaceDrawQuad. - base::flat_set<SurfaceId> undrawn_surfaces; + std::set<SurfaceId> undrawn_surfaces; bool may_contain_video = false; }; @@ -143,8 +145,9 @@ // each source (SurfaceId, RenderPass id) to a unified ID namespace that's // used in the aggregated frame. An entry is removed from the map if it's not // used for one output frame. - base::flat_map<std::pair<SurfaceId, int>, RenderPassInfo> - render_pass_allocator_map_; + using RenderPassIdAllocatorMap = + std::map<std::pair<SurfaceId, int>, RenderPassInfo>; + RenderPassIdAllocatorMap render_pass_allocator_map_; int next_render_pass_id_; const bool aggregate_only_damaged_; bool output_is_secure_; @@ -159,7 +162,9 @@ // The id for the final color conversion render pass. int color_conversion_render_pass_id_ = 0; - base::flat_map<SurfaceId, int> surface_id_to_resource_child_id_; + using SurfaceToResourceChildIdMap = + std::unordered_map<SurfaceId, int, SurfaceIdHash>; + SurfaceToResourceChildIdMap surface_id_to_resource_child_id_; // The following state is only valid for the duration of one Aggregate call // and is only stored on the class to avoid having to pass through every @@ -167,7 +172,8 @@ // This is the set of surfaces referenced in the aggregation so far, used to // detect cycles. - base::flat_set<SurfaceId> referenced_surfaces_; + using SurfaceSet = std::set<SurfaceId>; + SurfaceSet referenced_surfaces_; // For each Surface used in the last aggregation, gives the frame_index at // that time. @@ -175,22 +181,22 @@ SurfaceIndexMap contained_surfaces_; // After surface validation, every Surface in this set is valid. - base::flat_set<SurfaceId> valid_surfaces_; + std::unordered_set<SurfaceId, SurfaceIdHash> valid_surfaces_; // This is the pass list for the aggregated frame. RenderPassList* dest_pass_list_; // This is the set of aggregated pass ids that are affected by filters that // move pixels. - base::flat_set<int> moved_pixel_passes_; + std::unordered_set<int> moved_pixel_passes_; // This is the set of aggregated pass ids that are drawn by copy requests, so // should not have their damage rects clipped to the root damage rect. - base::flat_set<int> copy_request_passes_; + std::unordered_set<int> copy_request_passes_; // This maps each aggregated pass id to the set of (aggregated) pass ids // that its RenderPassDrawQuads depend on - base::flat_map<int, base::flat_set<int>> render_pass_dependencies_; + std::unordered_map<int, std::unordered_set<int>> render_pass_dependencies_; // The root damage rect of the currently-aggregating frame. gfx::Rect root_damage_rect_;
diff --git a/cc/surfaces/surface_factory.cc b/cc/surfaces/surface_factory.cc index 659ed06a..45eb882 100644 --- a/cc/surfaces/surface_factory.cc +++ b/cc/surfaces/surface_factory.cc
@@ -66,10 +66,6 @@ } surface->QueueFrame(std::move(frame), callback); - if (!manager_->SurfaceModified(SurfaceId(frame_sink_id_, local_surface_id))) { - TRACE_EVENT_INSTANT0("cc", "Damage not visible.", TRACE_EVENT_SCOPE_THREAD); - surface->RunDrawCallbacks(); - } if (current_surface_ && create_new_surface) { surface->SetPreviousFrameSurface(current_surface_.get()); Destroy(std::move(current_surface_)); @@ -133,6 +129,10 @@ // is potentially transformed into a real reference by the client. client_->ReferencedSurfacesChanged(surface->surface_id().local_surface_id(), surface->active_referenced_surfaces()); + if (!manager_->SurfaceModified(surface->surface_id())) { + TRACE_EVENT_INSTANT0("cc", "Damage not visible.", TRACE_EVENT_SCOPE_THREAD); + surface->RunDrawCallbacks(); + } } void SurfaceFactory::OnSurfaceDependenciesChanged(
diff --git a/cc/test/fake_painted_scrollbar_layer.cc b/cc/test/fake_painted_scrollbar_layer.cc index e479e4a..aca20a9a 100644 --- a/cc/test/fake_painted_scrollbar_layer.cc +++ b/cc/test/fake_painted_scrollbar_layer.cc
@@ -13,9 +13,10 @@ scoped_refptr<FakePaintedScrollbarLayer> FakePaintedScrollbarLayer::Create( bool paint_during_update, bool has_thumb, - int scrolling_layer_id) { + int scrolling_layer_id, + ElementId scrolling_element_id) { return Create(paint_during_update, has_thumb, HORIZONTAL, false, false, - scrolling_layer_id); + scrolling_layer_id, scrolling_element_id); } scoped_refptr<FakePaintedScrollbarLayer> FakePaintedScrollbarLayer::Create( @@ -24,19 +25,22 @@ ScrollbarOrientation orientation, bool is_left_side_vertical_scrollbar, bool is_overlay, - int scrolling_layer_id) { + int scrolling_layer_id, + ElementId scrolling_element_id) { FakeScrollbar* fake_scrollbar = new FakeScrollbar(paint_during_update, has_thumb, orientation, is_left_side_vertical_scrollbar, is_overlay); - return make_scoped_refptr( - new FakePaintedScrollbarLayer(fake_scrollbar, scrolling_layer_id)); + return make_scoped_refptr(new FakePaintedScrollbarLayer( + fake_scrollbar, scrolling_layer_id, scrolling_element_id)); } FakePaintedScrollbarLayer::FakePaintedScrollbarLayer( FakeScrollbar* fake_scrollbar, - int scrolling_layer_id) + int scrolling_layer_id, + ElementId scrolling_element_id) : PaintedScrollbarLayer(std::unique_ptr<Scrollbar>(fake_scrollbar), - scrolling_layer_id), + scrolling_layer_id, + scrolling_element_id), update_count_(0), push_properties_count_(0), fake_scrollbar_(fake_scrollbar) {
diff --git a/cc/test/fake_painted_scrollbar_layer.h b/cc/test/fake_painted_scrollbar_layer.h index bbb38cdf..fe760b2 100644 --- a/cc/test/fake_painted_scrollbar_layer.h +++ b/cc/test/fake_painted_scrollbar_layer.h
@@ -21,14 +21,16 @@ static scoped_refptr<FakePaintedScrollbarLayer> Create( bool paint_during_update, bool has_thumb, - int scrolling_layer_id); + int scrolling_layer_id, + ElementId scrolling_element_id = ElementId()); static scoped_refptr<FakePaintedScrollbarLayer> Create( bool paint_during_update, bool has_thumb, ScrollbarOrientation orientation, bool is_left_side_vertical_scrollbar, bool is_overlay, - int scrolling_layer_id); + int scrolling_layer_id, + ElementId scrolling_element_id = ElementId()); int update_count() const { return update_count_; } void reset_update_count() { update_count_ = 0; } @@ -56,7 +58,8 @@ private: FakePaintedScrollbarLayer(FakeScrollbar* fake_scrollbar, - int scrolling_layer_id); + int scrolling_layer_id, + ElementId scrolling_element_id); ~FakePaintedScrollbarLayer() override; int update_count_;
diff --git a/cc/test/test_compositor_frame_sink.cc b/cc/test/test_compositor_frame_sink.cc index f8ade2ff..75ace29 100644 --- a/cc/test/test_compositor_frame_sink.cc +++ b/cc/test/test_compositor_frame_sink.cc
@@ -117,6 +117,7 @@ client_->SetBeginFrameSource(nullptr); support_ = nullptr; display_ = nullptr; + begin_frame_source_ = nullptr; local_surface_id_allocator_ = nullptr; surface_manager_ = nullptr; test_client_ = nullptr;
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc index e38d14a..36ccec2 100644 --- a/cc/trees/draw_property_utils.cc +++ b/cc/trees/draw_property_utils.cc
@@ -743,6 +743,23 @@ } } +static void UpdateScrollTree(ScrollTree* scroll_tree, + const LayerTreeHost* layer_tree_host) { + if (!scroll_tree->needs_update()) + return; + + for (int i = ScrollTree::kRootNodeId; + i < static_cast<int>(scroll_tree->size()); ++i) { + ScrollNode* scroll_node = scroll_tree->Node(i); + if (Layer* scroll_layer = + layer_tree_host->LayerById(scroll_node->owning_layer_id)) { + if (Layer* scroll_clip_layer = scroll_layer->scroll_clip_layer()) { + scroll_node->scroll_clip_layer_bounds = scroll_clip_layer->bounds(); + } + } + } +} + static void ComputeClips(PropertyTrees* property_trees) { DCHECK(!property_trees->transform_tree.needs_update()); ClipTree* clip_tree = &property_trees->clip_tree; @@ -872,6 +889,7 @@ property_trees->clip_tree.set_needs_update(true); property_trees->effect_tree.set_needs_update(true); } + UpdateScrollTree(&property_trees->scroll_tree, layer_tree_host); ComputeTransforms(&property_trees->transform_tree); ComputeEffects(&property_trees->effect_tree); // Computation of clips uses ToScreen which is updated while computing
diff --git a/cc/trees/element_id.h b/cc/trees/element_id.h index 74de4c99..8518cf8 100644 --- a/cc/trees/element_id.h +++ b/cc/trees/element_id.h
@@ -24,16 +24,25 @@ namespace cc { -// An "element" is really an animation target. It retains the name element to be -// symmetric with ElementAnimations and blink::ElementAnimations, but is not -// in fact tied to the notion of a blink element. It is also not associated with -// the notion of a Layer. Ultimately, these ids will be used to look up the -// property tree node associated with the given animation. +// Element ids are chosen by cc's clients and can be used as a stable identifier +// across updates. // -// These ids are chosen by cc's clients to permit the destruction and -// restoration of cc entities (when visuals are hidden and shown) but maintain -// stable identifiers. There will be a single layer for an ElementId, but -// not every layer will have an id. +// Historically, the layer tree stored all compositing data but this has been +// refactored over time into auxilliary structures such as property trees. +// +// In composited scrolling, Layers directly reference scroll tree nodes +// (Layer::scroll_tree_index) but scroll tree nodes are being refactored to +// reference stable element ids instead of layers. Scroll property nodes have +// unique element ids that blink creates from scrollable areas (though this is +// opaque to the compositor). This refactoring of scroll nodes keeping a +// scrolling element id instead of a scrolling layer id allows for more general +// compositing where, for example, multiple layers scroll with one scroll node. +// +// The animation system (see: ElementAnimations and blink::ElementAnimations) is +// another auxilliary structure to the layer tree and uses element ids as a +// stable identifier for animation targets. A Layer's element id can change over +// the Layer's lifetime because non-default ElementIds are only set during an +// animation's lifetime. struct CC_EXPORT ElementId { ElementId(int primaryId, int secondaryId) : primaryId(primaryId), secondaryId(secondaryId) {}
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index e8a6f4b0..6cc84cd2 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -788,7 +788,7 @@ SetNeedsUpdateLayers(); } for (size_t i = 0; i < info->scrollbars.size(); ++i) { - Layer* layer = LayerById(info->scrollbars[i].layer_id); + Layer* layer = LayerByElementId(info->scrollbars[i].element_id); if (!layer) continue; layer->SetScrollbarsHiddenFromImplSide(info->scrollbars[i].hidden);
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index a3afacd0..df9ffab 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc
@@ -164,15 +164,15 @@ } LayerTreeHostCommon::ScrollbarsUpdateInfo::ScrollbarsUpdateInfo() - : layer_id(Layer::INVALID_ID), hidden(true) {} + : element_id(), hidden(true) {} -LayerTreeHostCommon::ScrollbarsUpdateInfo::ScrollbarsUpdateInfo(int layer_id, +LayerTreeHostCommon::ScrollbarsUpdateInfo::ScrollbarsUpdateInfo(ElementId id, bool hidden) - : layer_id(layer_id), hidden(hidden) {} + : element_id(id), hidden(hidden) {} bool LayerTreeHostCommon::ScrollbarsUpdateInfo::operator==( const LayerTreeHostCommon::ScrollbarsUpdateInfo& other) const { - return layer_id == other.layer_id && hidden == other.hidden; + return element_id == other.element_id && hidden == other.hidden; } ScrollAndScaleSet::ScrollAndScaleSet()
diff --git a/cc/trees/layer_tree_host_common.h b/cc/trees/layer_tree_host_common.h index 2dc7f18..81c1710 100644 --- a/cc/trees/layer_tree_host_common.h +++ b/cc/trees/layer_tree_host_common.h
@@ -147,11 +147,11 @@ // to be told when they're faded out so it can stop handling input for // invisible scrollbars. struct CC_EXPORT ScrollbarsUpdateInfo { - int layer_id; + ElementId element_id; bool hidden; ScrollbarsUpdateInfo(); - ScrollbarsUpdateInfo(int layer_id, bool hidden); + ScrollbarsUpdateInfo(ElementId element_id, bool hidden); bool operator==(const ScrollbarsUpdateInfo& other) const; };
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 97d189fc..9d04554 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -206,8 +206,6 @@ did_lock_scrolling_layer_(false), wheel_scrolling_(false), scroll_affects_scroll_handler_(false), - scroll_layer_id_mouse_currently_over_(Layer::INVALID_ID), - scroll_layer_id_mouse_currently_captured_(Layer::INVALID_ID), tile_priorities_dirty_(false), settings_(settings), visible_(false), @@ -2939,7 +2937,7 @@ if (scroll_node) { // Flash the overlay scrollbar even if the scroll dalta is 0. ScrollbarAnimationController* animation_controller = - ScrollbarAnimationControllerForId(scroll_node->owning_layer_id); + ScrollbarAnimationControllerForElementId(scroll_node->element_id); if (animation_controller) animation_controller->WillUpdateScroll(); @@ -2990,7 +2988,7 @@ if (scrolls_main_viewport_scroll_layer) { // Flash the overlay scrollbar even if the scroll dalta is 0. ScrollbarAnimationController* animation_controller = - ScrollbarAnimationControllerForId(scroll_node->owning_layer_id); + ScrollbarAnimationControllerForElementId(scroll_node->element_id); if (animation_controller) animation_controller->WillUpdateScroll(); @@ -3250,7 +3248,7 @@ return InputHandlerScrollResult(); ScrollbarAnimationController* animation_controller = - ScrollbarAnimationControllerForId(scroll_node->owning_layer_id); + ScrollbarAnimationControllerForElementId(scroll_node->element_id); if (animation_controller) animation_controller->WillUpdateScroll(); @@ -3390,21 +3388,22 @@ void LayerTreeHostImpl::MouseDown() { ScrollbarAnimationController* animation_controller = - ScrollbarAnimationControllerForId(scroll_layer_id_mouse_currently_over_); + ScrollbarAnimationControllerForElementId( + scroll_element_id_mouse_currently_over_); if (animation_controller) { animation_controller->DidMouseDown(); - scroll_layer_id_mouse_currently_captured_ = - scroll_layer_id_mouse_currently_over_; + scroll_element_id_mouse_currently_captured_ = + scroll_element_id_mouse_currently_over_; } } void LayerTreeHostImpl::MouseUp() { - if (scroll_layer_id_mouse_currently_captured_ != Layer::INVALID_ID) { + if (scroll_element_id_mouse_currently_captured_) { ScrollbarAnimationController* animation_controller = - ScrollbarAnimationControllerForId( - scroll_layer_id_mouse_currently_captured_); + ScrollbarAnimationControllerForElementId( + scroll_element_id_mouse_currently_captured_); - scroll_layer_id_mouse_currently_captured_ = Layer::INVALID_ID; + scroll_element_id_mouse_currently_captured_ = ElementId(); if (animation_controller) animation_controller->DidMouseUp(); @@ -3421,10 +3420,10 @@ // TODO(sahel): get rid of this extera checking when // FindScrollLayerForDeviceViewportPoint finds the proper layer for // scrolling on main thread when mouse is over scrollbar as well. - int new_id = Layer::INVALID_ID; + ElementId new_element_id; if (layer_impl && layer_impl->ToScrollbarLayer()) - new_id = layer_impl->ToScrollbarLayer()->ScrollLayerId(); - if (new_id == Layer::INVALID_ID) { + new_element_id = layer_impl->ToScrollbarLayer()->scroll_element_id(); + if (!new_element_id) { bool scroll_on_main_thread = false; uint32_t main_thread_scrolling_reasons; LayerImpl* scroll_layer_impl = FindScrollLayerForDeviceViewportPoint( @@ -3435,25 +3434,28 @@ if (scroll_layer_impl == InnerViewportScrollLayer()) scroll_layer_impl = OuterViewportScrollLayer(); - new_id = scroll_layer_impl ? scroll_layer_impl->id() : Layer::INVALID_ID; + if (scroll_layer_impl) + new_element_id = scroll_layer_impl->element_id(); } - if (new_id != scroll_layer_id_mouse_currently_over_) { + if (new_element_id != scroll_element_id_mouse_currently_over_) { ScrollbarAnimationController* old_animation_controller = - ScrollbarAnimationControllerForId( - scroll_layer_id_mouse_currently_over_); + ScrollbarAnimationControllerForElementId( + scroll_element_id_mouse_currently_over_); if (old_animation_controller) { old_animation_controller->DidMouseLeave(); } - scroll_layer_id_mouse_currently_over_ = new_id; + scroll_element_id_mouse_currently_over_ = new_element_id; } ScrollbarAnimationController* new_animation_controller = - ScrollbarAnimationControllerForId(new_id); + ScrollbarAnimationControllerForElementId(new_element_id); if (!new_animation_controller) return; - for (ScrollbarLayerImplBase* scrollbar : ScrollbarsFor(new_id)) { + int new_layer_id = active_tree_->LayerIdByElementId(new_element_id); + for (ScrollbarLayerImplBase* scrollbar : + active_tree_->ScrollbarsFor(new_layer_id)) { new_animation_controller->DidMouseMoveNear( scrollbar->orientation(), DeviceSpaceDistanceToLayer(device_viewport_point, scrollbar) / @@ -3464,7 +3466,7 @@ void LayerTreeHostImpl::MouseLeave() { for (auto& pair : scrollbar_animation_controllers_) pair.second->DidMouseLeave(); - scroll_layer_id_mouse_currently_over_ = Layer::INVALID_ID; + scroll_element_id_mouse_currently_over_ = ElementId(); } void LayerTreeHostImpl::PinchGestureBegin() { @@ -3533,8 +3535,9 @@ static void CollectScrollbarUpdates( ScrollAndScaleSet* scroll_info, - std::unordered_map<int, std::unique_ptr<ScrollbarAnimationController>>* - controllers) { + std::unordered_map<ElementId, + std::unique_ptr<ScrollbarAnimationController>, + ElementIdHash>* controllers) { scroll_info->scrollbars.reserve(controllers->size()); for (auto& pair : *controllers) { scroll_info->scrollbars.push_back(LayerTreeHostCommon::ScrollbarsUpdateInfo( @@ -3678,29 +3681,30 @@ } void LayerTreeHostImpl::RegisterScrollbarAnimationController( - int scroll_layer_id) { + int scroll_layer_id, + ElementId scroll_element_id) { if (settings().scrollbar_animator == LayerTreeSettings::NO_ANIMATOR) return; - if (ScrollbarAnimationControllerForId(scroll_layer_id)) + if (ScrollbarAnimationControllerForElementId(scroll_element_id)) return; - scrollbar_animation_controllers_[scroll_layer_id] = + scrollbar_animation_controllers_[scroll_element_id] = active_tree_->CreateScrollbarAnimationController(scroll_layer_id); } void LayerTreeHostImpl::UnregisterScrollbarAnimationController( - int scroll_layer_id) { - scrollbar_animation_controllers_.erase(scroll_layer_id); + ElementId scroll_element_id) { + scrollbar_animation_controllers_.erase(scroll_element_id); } ScrollbarAnimationController* -LayerTreeHostImpl::ScrollbarAnimationControllerForId( - int scroll_layer_id) const { +LayerTreeHostImpl::ScrollbarAnimationControllerForElementId( + ElementId scroll_element_id) const { // The viewport layers have only one set of scrollbars and their controller // is registered with the outer viewport. if (InnerViewportScrollLayer() && OuterViewportScrollLayer() && - scroll_layer_id == InnerViewportScrollLayer()->id()) - scroll_layer_id = OuterViewportScrollLayer()->id(); - auto i = scrollbar_animation_controllers_.find(scroll_layer_id); + scroll_element_id == InnerViewportScrollLayer()->element_id()) + scroll_element_id = OuterViewportScrollLayer()->element_id(); + auto i = scrollbar_animation_controllers_.find(scroll_element_id); if (i == scrollbar_animation_controllers_.end()) return nullptr; return i->second.get();
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 26d68d3..b3893b08 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -321,10 +321,11 @@ size_t SourceAnimationFrameNumberForTesting() const; - void RegisterScrollbarAnimationController(int scroll_layer_id); - void UnregisterScrollbarAnimationController(int scroll_layer_id); - ScrollbarAnimationController* ScrollbarAnimationControllerForId( - int scroll_layer_id) const; + void RegisterScrollbarAnimationController(int scroll_layer_id, + ElementId scroll_element_id); + void UnregisterScrollbarAnimationController(ElementId scroll_element_id); + ScrollbarAnimationController* ScrollbarAnimationControllerForElementId( + ElementId scroll_element_id) const; DrawMode GetDrawMode() const; @@ -759,8 +760,8 @@ bool did_lock_scrolling_layer_; bool wheel_scrolling_; bool scroll_affects_scroll_handler_; - int scroll_layer_id_mouse_currently_over_; - int scroll_layer_id_mouse_currently_captured_; + ElementId scroll_element_id_mouse_currently_over_; + ElementId scroll_element_id_mouse_currently_captured_; std::vector<std::unique_ptr<SwapPromise>> swap_promises_for_main_thread_scroll_update_; @@ -820,9 +821,11 @@ std::unique_ptr<MutatorHost> mutator_host_; std::set<VideoFrameController*> video_frame_controllers_; - // Map from scroll layer ID to scrollbar animation controller. + // Map from scroll element ID to scrollbar animation controller. // There is one animation controller per pair of overlay scrollbars. - std::unordered_map<int, std::unique_ptr<ScrollbarAnimationController>> + std::unordered_map<ElementId, + std::unique_ptr<ScrollbarAnimationController>, + ElementIdHash> scrollbar_animation_controllers_; RenderingStatsInstrumentation* rendering_stats_instrumentation_;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 181db8f..31466c5 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -1041,7 +1041,7 @@ false, true); scrollbar->SetBounds(scrollbar_size); scrollbar->SetPosition(gfx::PointF(345, 0)); - scrollbar->SetScrollLayerId(scroll->id()); + scrollbar->SetScrollInfo(scroll->id(), scroll->element_id()); scrollbar->SetDrawsContent(true); scrollbar->test_properties()->opacity = 1.f; @@ -1113,7 +1113,7 @@ false, true); drawn_scrollbar->SetBounds(scrollbar_size); drawn_scrollbar->SetPosition(gfx::PointF(345, 0)); - drawn_scrollbar->SetScrollLayerId(scroll->id()); + drawn_scrollbar->SetScrollInfo(scroll->id(), scroll->element_id()); drawn_scrollbar->SetDrawsContent(true); drawn_scrollbar->test_properties()->opacity = 1.f; @@ -2856,13 +2856,13 @@ LayerImpl* scroll = host_impl_->active_tree()->OuterViewportScrollLayer(); LayerImpl* root = host_impl_->active_tree()->InnerViewportContainerLayer(); - scrollbar->SetScrollLayerId(scroll->id()); + scrollbar->SetScrollInfo(scroll->id(), scroll->element_id()); root->test_properties()->AddChild(std::move(scrollbar)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->active_tree()->DidBecomeActive(); DrawFrame(); - // SetScrollLayerId will initialize the scrollbar which will cause it to + // SetScrollInfo will initialize the scrollbar which will cause it to // show and request a redraw. did_request_redraw_ = false; } @@ -3113,7 +3113,7 @@ LayerImpl* scroll = host_impl_->pending_tree()->OuterViewportScrollLayer(); LayerImpl* container = host_impl_->pending_tree()->InnerViewportContainerLayer(); - scrollbar->SetScrollLayerId(scroll->id()); + scrollbar->SetScrollInfo(scroll->id(), scroll->element_id()); container->test_properties()->AddChild(std::move(scrollbar)); host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f); host_impl_->pending_tree()->BuildPropertyTreesForTesting(); @@ -3129,11 +3129,11 @@ active_tree_node->opacity); if (expecting_animations) { - host_impl_->ScrollbarAnimationControllerForId(scroll->id()) + host_impl_->ScrollbarAnimationControllerForElementId(scroll->element_id()) ->DidMouseMoveNear(VERTICAL, 0); } else { - EXPECT_EQ(nullptr, - host_impl_->ScrollbarAnimationControllerForId(scroll->id())); + EXPECT_EQ(nullptr, host_impl_->ScrollbarAnimationControllerForElementId( + scroll->element_id())); } host_impl_->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL); @@ -3208,14 +3208,15 @@ LayerImpl* scroll = host_impl_->pending_tree()->OuterViewportScrollLayer(); LayerImpl* container = host_impl_->pending_tree()->InnerViewportContainerLayer(); - scrollbar->SetScrollLayerId(scroll->id()); + scrollbar->SetScrollInfo(scroll->id(), scroll->element_id()); container->test_properties()->AddChild(std::move(scrollbar)); host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f); host_impl_->pending_tree()->BuildPropertyTreesForTesting(); host_impl_->ActivateSyncTree(); ScrollbarAnimationController* scrollbar_controller = - host_impl_->ScrollbarAnimationControllerForId(scroll->id()); + host_impl_->ScrollbarAnimationControllerForElementId( + scroll->element_id()); // Scrollbars will flash shown but we should have a fade out animation // queued. Run it and fade out the scrollbars. @@ -3283,7 +3284,7 @@ LayerImpl::Create(host_impl_->active_tree(), child_clip_id); child->SetBounds(inner_viewport_size); - horiz_scrollbar->SetScrollLayerId(root_scroll->id()); + horiz_scrollbar->SetScrollInfo(root_scroll->id(), root_scroll->element_id()); EXPECT_EQ(300, horiz_scrollbar->clip_layer_length()); } @@ -3334,14 +3335,17 @@ // Check scrollbar registration on the viewport layers. EXPECT_EQ(0ul, host_impl_->ScrollbarsFor(root_scroll->id()).size()); - EXPECT_EQ(nullptr, - host_impl_->ScrollbarAnimationControllerForId(root_scroll->id())); - vert_1_scrollbar->SetScrollLayerId(root_scroll->id()); + EXPECT_EQ(nullptr, host_impl_->ScrollbarAnimationControllerForElementId( + root_scroll->element_id())); + vert_1_scrollbar->SetScrollInfo(root_scroll->id(), root_scroll->element_id()); EXPECT_EQ(1ul, host_impl_->ScrollbarsFor(root_scroll->id()).size()); - EXPECT_TRUE(host_impl_->ScrollbarAnimationControllerForId(root_scroll->id())); - horiz_1_scrollbar->SetScrollLayerId(root_scroll->id()); + EXPECT_TRUE(host_impl_->ScrollbarAnimationControllerForElementId( + root_scroll->element_id())); + horiz_1_scrollbar->SetScrollInfo(root_scroll->id(), + root_scroll->element_id()); EXPECT_EQ(2ul, host_impl_->ScrollbarsFor(root_scroll->id()).size()); - EXPECT_TRUE(host_impl_->ScrollbarAnimationControllerForId(root_scroll->id())); + EXPECT_TRUE(host_impl_->ScrollbarAnimationControllerForElementId( + root_scroll->element_id())); // Changing one of the viewport layers should result in a scrollbar animation // update. @@ -3362,17 +3366,20 @@ // Check scrollbar registration on a sublayer. child->SetScrollClipLayer(child_clip->id()); child->SetElementId(LayerIdToElementIdForTesting(child->id())); + ElementId child_scroll_element_id = child->element_id(); child_clip->test_properties()->AddChild(std::move(child)); root_scroll->test_properties()->AddChild(std::move(child_clip)); EXPECT_EQ(0ul, host_impl_->ScrollbarsFor(child_scroll_id).size()); - EXPECT_EQ(nullptr, - host_impl_->ScrollbarAnimationControllerForId(child_scroll_id)); - vert_2_scrollbar->SetScrollLayerId(child_scroll_id); + EXPECT_EQ(nullptr, host_impl_->ScrollbarAnimationControllerForElementId( + child_scroll_element_id)); + vert_2_scrollbar->SetScrollInfo(child_scroll_id, child_scroll_element_id); EXPECT_EQ(1ul, host_impl_->ScrollbarsFor(child_scroll_id).size()); - EXPECT_TRUE(host_impl_->ScrollbarAnimationControllerForId(child_scroll_id)); - horiz_2_scrollbar->SetScrollLayerId(child_scroll_id); + EXPECT_TRUE(host_impl_->ScrollbarAnimationControllerForElementId( + child_scroll_element_id)); + horiz_2_scrollbar->SetScrollInfo(child_scroll_id, child_scroll_element_id); EXPECT_EQ(2ul, host_impl_->ScrollbarsFor(child_scroll_id).size()); - EXPECT_TRUE(host_impl_->ScrollbarAnimationControllerForId(child_scroll_id)); + EXPECT_TRUE(host_impl_->ScrollbarAnimationControllerForElementId( + child_scroll_element_id)); // Changing one of the child layers should result in a scrollbar animation // update. @@ -3387,20 +3394,22 @@ // Check scrollbar unregistration. vert_1_scrollbar.reset(); EXPECT_EQ(1ul, host_impl_->ScrollbarsFor(root_scroll->id()).size()); - EXPECT_TRUE(host_impl_->ScrollbarAnimationControllerForId(root_scroll->id())); + EXPECT_TRUE(host_impl_->ScrollbarAnimationControllerForElementId( + root_scroll->element_id())); horiz_1_scrollbar.reset(); EXPECT_EQ(0ul, host_impl_->ScrollbarsFor(root_scroll->id()).size()); - EXPECT_EQ(nullptr, - host_impl_->ScrollbarAnimationControllerForId(root_scroll->id())); + EXPECT_EQ(nullptr, host_impl_->ScrollbarAnimationControllerForElementId( + root_scroll->element_id())); EXPECT_EQ(2ul, host_impl_->ScrollbarsFor(child_scroll_id).size()); vert_2_scrollbar.reset(); EXPECT_EQ(1ul, host_impl_->ScrollbarsFor(child_scroll_id).size()); - EXPECT_TRUE(host_impl_->ScrollbarAnimationControllerForId(child_scroll_id)); + EXPECT_TRUE(host_impl_->ScrollbarAnimationControllerForElementId( + child_scroll_element_id)); horiz_2_scrollbar.reset(); EXPECT_EQ(0ul, host_impl_->ScrollbarsFor(child_scroll_id).size()); - EXPECT_EQ(nullptr, - host_impl_->ScrollbarAnimationControllerForId(root_scroll->id())); + EXPECT_EQ(nullptr, host_impl_->ScrollbarAnimationControllerForElementId( + root_scroll->element_id())); // Changing scroll offset should no longer trigger any animation. host_impl_->active_tree()->InnerViewportScrollLayer()->SetCurrentScrollOffset( @@ -3437,7 +3446,7 @@ std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar = SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 6, VERTICAL, 5, 5, true, true); - scrollbar->SetScrollLayerId(root_scroll->id()); + scrollbar->SetScrollInfo(root_scroll->id(), root_scroll->element_id()); scrollbar->SetDrawsContent(true); scrollbar->SetBounds(scrollbar_size); scrollbar->SetTouchEventHandlerRegion(gfx::Rect(scrollbar_size)); @@ -3452,7 +3461,8 @@ host_impl_->active_tree()->UpdateDrawProperties(false); ScrollbarAnimationController* scrollbar_animation_controller = - host_impl_->ScrollbarAnimationControllerForId(root_scroll->id()); + host_impl_->ScrollbarAnimationControllerForElementId( + root_scroll->element_id()); const float kMouseDistanceToTriggerAnimation = SingleScrollbarAnimationControllerThinning:: @@ -12076,7 +12086,7 @@ SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), scrollbar_1_id, VERTICAL, 5, 5, true, true); - scrollbar_1->SetScrollLayerId(root_scroll->id()); + scrollbar_1->SetScrollInfo(root_scroll->id(), root_scroll->element_id()); scrollbar_1->SetDrawsContent(true); scrollbar_1->SetBounds(scrollbar_size_1); scrollbar_1->SetTouchEventHandlerRegion(gfx::Rect(scrollbar_size_1)); @@ -12092,7 +12102,8 @@ host_impl_->active_tree()->UpdateDrawProperties(false); ScrollbarAnimationController* scrollbar_1_animation_controller = - host_impl_->ScrollbarAnimationControllerForId(root_scroll->id()); + host_impl_->ScrollbarAnimationControllerForElementId( + root_scroll->element_id()); EXPECT_TRUE(scrollbar_1_animation_controller); const float kMouseDistanceToTriggerAnimation = @@ -12141,13 +12152,14 @@ child->SetDrawsContent(true); child->SetScrollClipLayer(child_clip_id); child->SetElementId(LayerIdToElementIdForTesting(child->id())); + ElementId child_element_id = child->element_id(); if (main_thread_scrolling) { child->set_main_thread_scrolling_reasons( MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects); } - scrollbar_2->SetScrollLayerId(child_scroll_id); + scrollbar_2->SetScrollInfo(child_scroll_id, child_element_id); scrollbar_2->SetDrawsContent(true); scrollbar_2->SetBounds(scrollbar_size_2); @@ -12159,7 +12171,7 @@ host_impl_->active_tree()->DidBecomeActive(); ScrollbarAnimationController* scrollbar_2_animation_controller = - host_impl_->ScrollbarAnimationControllerForId(child_scroll_id); + host_impl_->ScrollbarAnimationControllerForElementId(child_element_id); EXPECT_TRUE(scrollbar_2_animation_controller); // Mouse goes over scrollbar_2, moves close to scrollbar_2, moves close to @@ -12220,17 +12232,17 @@ // scrollbar_2_animation_controller, then mouse up should not cause crash. host_impl_->MouseMoveAt(gfx::Point(40, 150)); host_impl_->MouseDown(); - host_impl_->UnregisterScrollbarAnimationController(root_scroll->id()); + host_impl_->UnregisterScrollbarAnimationController(root_scroll->element_id()); host_impl_->MouseUp(); } TEST_F(LayerTreeHostImplTest, - LayerTreeHostImplTestScrollbarStatesInMainThreadScorlling) { + LayerTreeHostImplTestScrollbarStatesInMainThreadScrolling) { SetupMouseMoveAtTestScrollbarStates(true); } TEST_F(LayerTreeHostImplTest, - LayerTreeHostImplTestScrollbarStatesInNotMainThreadScorlling) { + LayerTreeHostImplTestScrollbarStatesInNotMainThreadScrolling) { SetupMouseMoveAtTestScrollbarStates(false); }
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index b549100..31f10d9 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -1750,7 +1750,8 @@ bool paint_scrollbar = true; bool has_thumb = false; scrollbar_ = FakePaintedScrollbarLayer::Create(paint_scrollbar, has_thumb, - root_layer_->id()); + root_layer_->id(), + root_layer_->element_id()); scrollbar_->SetPosition(gfx::PointF(0.f, 10.f)); scrollbar_->SetBounds(gfx::Size(10, 10)); @@ -3737,7 +3738,7 @@ bool paint_scrollbar = true; bool has_thumb = false; scrollbar_layer_ = FakePaintedScrollbarLayer::Create( - paint_scrollbar, has_thumb, root_->id()); + paint_scrollbar, has_thumb, root_->id(), root_->element_id()); root_->AddChild(scrollbar_layer_);
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc index 3c7351f..56b4c57 100644 --- a/cc/trees/layer_tree_host_unittest_context.cc +++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -973,7 +973,8 @@ scoped_refptr<PaintedScrollbarLayer> scrollbar = PaintedScrollbarLayer::Create( - std::unique_ptr<Scrollbar>(new FakeScrollbar), layer->id()); + std::unique_ptr<Scrollbar>(new FakeScrollbar), layer->id(), + layer->element_id()); scrollbar->SetBounds(gfx::Size(10, 10)); scrollbar->SetIsDrawable(true); root->AddChild(scrollbar); @@ -1088,8 +1089,8 @@ void BeginTest() override { scoped_refptr<Layer> scroll_layer = Layer::Create(); - scrollbar_layer_ = - FakePaintedScrollbarLayer::Create(false, true, scroll_layer->id()); + scrollbar_layer_ = FakePaintedScrollbarLayer::Create( + false, true, scroll_layer->id(), scroll_layer->element_id()); scrollbar_layer_->SetBounds(gfx::Size(10, 100)); layer_tree_host()->root_layer()->AddChild(scrollbar_layer_); layer_tree_host()->root_layer()->AddChild(scroll_layer);
diff --git a/cc/trees/layer_tree_host_unittest_damage.cc b/cc/trees/layer_tree_host_unittest_damage.cc index 73d71a2..a5dbac8 100644 --- a/cc/trees/layer_tree_host_unittest_damage.cc +++ b/cc/trees/layer_tree_host_unittest_damage.cc
@@ -350,8 +350,8 @@ scroll_clip_layer->AddChild(content_layer_); root_layer->AddChild(scroll_clip_layer); - scoped_refptr<Layer> scrollbar_layer = - FakePaintedScrollbarLayer::Create(false, true, content_layer_->id()); + scoped_refptr<Layer> scrollbar_layer = FakePaintedScrollbarLayer::Create( + false, true, content_layer_->id(), content_layer_->element_id()); scrollbar_layer->SetPosition(gfx::PointF(300.f, 300.f)); scrollbar_layer->SetBounds(gfx::Size(10, 100)); root_layer->AddChild(scrollbar_layer);
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 6ac6ecf..62e63b3a 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -274,8 +274,8 @@ if (scrollbar_needs_animation) { ScrollbarAnimationController* controller = - layer_tree_host_impl_->ScrollbarAnimationControllerForId( - scroll_layer_id); + layer_tree_host_impl_->ScrollbarAnimationControllerForElementId( + scroll_layer->element_id()); if (!controller) return; @@ -552,7 +552,8 @@ if (!layer->needs_show_scrollbars()) return; ScrollbarAnimationController* controller = - layer_tree_host_impl_->ScrollbarAnimationControllerForId(layer->id()); + layer_tree_host_impl_->ScrollbarAnimationControllerForElementId( + layer->element_id()); if (controller) { controller->DidRequestShowFromMainThread(); layer->set_needs_show_scrollbars(false); @@ -736,14 +737,12 @@ if (old_element_id == new_element_id) return; - // TODO(pdr): Make the scrollbar animation controller lookup based on - // element ids instead of layer ids. ScrollbarAnimationController* old_animation_controller = - layer_tree_host_impl_->ScrollbarAnimationControllerForId( - LayerIdByElementId(old_element_id)); + layer_tree_host_impl_->ScrollbarAnimationControllerForElementId( + old_element_id); ScrollbarAnimationController* new_animation_controller = - layer_tree_host_impl_->ScrollbarAnimationControllerForId( - LayerIdByElementId(new_element_id)); + layer_tree_host_impl_->ScrollbarAnimationControllerForElementId( + new_element_id); if (old_animation_controller) old_animation_controller->DidScrollEnd(); @@ -1726,9 +1725,11 @@ scrollbar_map_.insert(std::pair<int, int>(scrollbar_layer->ScrollLayerId(), scrollbar_layer->id())); - if (IsActiveTree() && scrollbar_layer->is_overlay_scrollbar()) + if (IsActiveTree() && scrollbar_layer->is_overlay_scrollbar()) { + auto scroll_layer_id = scrollbar_layer->ScrollLayerId(); layer_tree_host_impl_->RegisterScrollbarAnimationController( - scrollbar_layer->ScrollLayerId()); + scroll_layer_id, scrollbar_layer->scroll_element_id()); + } DidUpdateScrollState(scrollbar_layer->ScrollLayerId()); } @@ -1746,9 +1747,10 @@ break; } - if (IsActiveTree() && scrollbar_map_.count(scroll_layer_id) == 0) + if (IsActiveTree() && scrollbar_map_.count(scroll_layer_id) == 0) { layer_tree_host_impl_->UnregisterScrollbarAnimationController( - scroll_layer_id); + scrollbar_layer->scroll_element_id()); + } } ScrollbarSet LayerTreeImpl::ScrollbarsFor(int scroll_layer_id) const {
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 9477510..9cf35a8d 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -465,6 +465,7 @@ "//third_party/WebKit/public:mojo_bindings_java", "//third_party/android_support_test_runner:rules_java", "//third_party/android_support_test_runner:runner_java", + "//third_party/android_tools:android_support_annotations_java", "//third_party/android_tools:android_support_design_java", "//third_party/android_tools:android_support_transition_java", "//third_party/android_tools:android_support_v7_appcompat_java", @@ -476,6 +477,7 @@ "//third_party/junit", "//ui/android:ui_java", "//ui/base/mojo:mojo_bindings_java", + "//url/mojo:url_mojom_gurl_java", google_play_services_library, ]
diff --git a/chrome/android/java/res/color/app_menu_button_tint.xml b/chrome/android/java/res/color/app_menu_button_tint.xml new file mode 100644 index 0000000..49255ac --- /dev/null +++ b/chrome/android/java/res/color/app_menu_button_tint.xml
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2017 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" android:color="@color/google_grey_300" /> + <item android:color="@color/light_normal_color"/> +</selector>
diff --git a/chrome/android/java/res/layout/icon_row_menu_footer.xml b/chrome/android/java/res/layout/icon_row_menu_footer.xml new file mode 100644 index 0000000..ca37c40b --- /dev/null +++ b/chrome/android/java/res/layout/icon_row_menu_footer.xml
@@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2017 The Chromium Authors. All rights reserved. + + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> +<org.chromium.chrome.browser.appmenu.AppMenuIconRowFooter + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:chrome="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + + <View style="@style/Divider" /> + + <!-- TODO(twellington): find a way to merge this with icon_row_menu_item.xml --> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="?android:attr/listPreferredItemHeightSmall" + android:orientation="horizontal" + android:id="@+id/menu_items" > + + <org.chromium.chrome.browser.widget.TintedImageButton + android:id="@+id/forward_menu_id" + style="@style/OverflowMenuButton" + android:src="@drawable/btn_forward" + android:contentDescription="@string/accessibility_menu_forward" + chrome:tint="@color/app_menu_button_tint" /> + + <org.chromium.chrome.browser.widget.TintedImageButton + android:id="@+id/bookmark_this_page_id" + style="@style/OverflowMenuButton" + android:src="@drawable/btn_star" + android:contentDescription="@string/accessibility_menu_bookmark" + chrome:tint="@color/app_menu_button_tint" /> + + <org.chromium.chrome.browser.widget.TintedImageButton + android:id="@+id/offline_page_id" + style="@style/OverflowMenuButton" + android:src="@drawable/ic_file_download_white_24dp" + android:contentDescription="@string/download_page" + chrome:tint="@color/app_menu_button_tint" /> + + <org.chromium.chrome.browser.widget.TintedImageButton + android:id="@+id/info_menu_id" + style="@style/OverflowMenuButton" + android:src="@drawable/btn_info" + android:contentDescription="@string/accessibility_menu_info" + chrome:tint="@color/app_menu_button_tint" /> + + <org.chromium.chrome.browser.widget.TintedImageButton + android:id="@+id/reload_menu_id" + style="@style/OverflowMenuButton" + android:src="@drawable/btn_reload_stop" + android:contentDescription="@string/accessibility_btn_refresh" + chrome:tint="@color/app_menu_button_tint" /> + </LinearLayout> +</org.chromium.chrome.browser.appmenu.AppMenuIconRowFooter> \ No newline at end of file
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml index e34f561..51eb9bc 100644 --- a/chrome/android/java/res/values/dimens.xml +++ b/chrome/android/java/res/values/dimens.xml
@@ -437,7 +437,8 @@ <dimen name="toolbar_wide_display_nav_icon_offset">-18dp</dimen> <dimen name="toolbar_wide_display_end_offset">-14dp</dimen> - <!-- Bottom sheet bottom nav dimensions --> + <!-- Bottom sheet dimensions --> + <dimen name="bottom_sheet_help_bubble_inset">10dp</dimen> <dimen name="bottom_nav_height">56dp</dimen> <dimen name="bottom_nav_height_inverse">-56dp</dimen> <dimen name="bottom_nav_space_from_toolbar">96dp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/AppIndexingUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/AppIndexingUtil.java index 8b54604ab..f0398fc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/AppIndexingUtil.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/AppIndexingUtil.java
@@ -8,6 +8,7 @@ import android.util.LruCache; import android.webkit.URLUtil; +import org.chromium.base.Callback; import org.chromium.base.SysUtils; import org.chromium.base.VisibleForTesting; import org.chromium.blink.mojom.document_metadata.CopylessPaste; @@ -29,6 +30,8 @@ // and instead just report the view (not the content) to App Indexing. private LruCache<String, CacheEntry> mPageCache; + private static Callback<WebPage> sCallbackForTesting; + /** * Extracts entities from document metadata and reports it to on-device App Indexing. * This call can cache entities from recently parsed webpages, in which case, only the url and @@ -62,6 +65,9 @@ @Override public void call(WebPage webpage) { putCacheEntry(url, webpage != null); + if (sCallbackForTesting != null) { + sCallbackForTesting.onResult(webpage); + } if (webpage == null) return; getAppIndexingReporter().reportWebPage(webpage); } @@ -69,6 +75,11 @@ } } + @VisibleForTesting + public static void setCallbackForTesting(Callback<WebPage> callback) { + sCallbackForTesting = callback; + } + private boolean wasPageVisitedRecently(String url) { if (url == null) { return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 74f81640..26f38a77 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -1265,12 +1265,18 @@ protected AppMenuPropertiesDelegate createAppMenuPropertiesDelegate() { return new AppMenuPropertiesDelegate(this) { private boolean showDataSaverFooter() { - return DataReductionProxySettings.getInstance() - .shouldUseDataReductionMainMenuItem(); + return getBottomSheet() == null + && DataReductionProxySettings.getInstance() + .shouldUseDataReductionMainMenuItem(); } @Override public int getFooterResourceId() { + if (getBottomSheet() != null) { + boolean isPageMenu = !isTablet() && !isInOverviewMode(); + return isPageMenu ? R.layout.icon_row_menu_footer : 0; + } + return showDataSaverFooter() ? R.layout.data_reduction_main_menu_footer : 0; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java index 065f2df..7de210cf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java
@@ -13,6 +13,7 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.support.annotation.IdRes; +import android.support.annotation.Nullable; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; @@ -59,6 +60,7 @@ private ListPopupWindow mPopup; private AppMenuAdapter mAdapter; private AppMenuHandler mHandler; + private View mPromptView; private int mCurrentScreenRotation = -1; private boolean mIsByPermanentButton; private AnimatorSet mMenuItemEnterAnimator; @@ -159,11 +161,13 @@ int footerHeight = 0; if (footerResourceId != 0) { mPopup.setPromptPosition(ListPopupWindow.POSITION_PROMPT_BELOW); - View promptView = LayoutInflater.from(context).inflate(footerResourceId, null); - mPopup.setPromptView(promptView); + mPromptView = LayoutInflater.from(context).inflate(footerResourceId, null); + mPopup.setPromptView(mPromptView); int measureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - promptView.measure(measureSpec, measureSpec); - footerHeight = promptView.getMeasuredHeight(); + mPromptView.measure(measureSpec, measureSpec); + footerHeight = mPromptView.getMeasuredHeight(); + } else { + mPromptView = null; } mPopup.setOnDismissListener(new OnDismissListener() { @Override @@ -264,6 +268,14 @@ } } + /** + * @return The prompt view for the menu or null if one has not been set. + */ + @Nullable + public View getPromptView() { + return mPromptView; + } + private boolean isAnchorAtBottom(View anchorView, Rect visibleDisplayFrame) { anchorView.getLocationOnScreen(mTempLocation); return (mTempLocation[1] + anchorView.getHeight()) == visibleDisplayFrame.bottom;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandler.java index 27fce0f7..150a279 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandler.java
@@ -165,6 +165,7 @@ mAppMenu.show(wrapper, anchorView, isByPermanentButton, rotation, appRect, pt.y, footerResourceId, mHighlightMenuId); mAppMenuDragHelper.onShow(startDragging); + mDelegate.onShow(mAppMenu); setMenuHighlight(null); RecordUserAction.record("MobileMenuShow"); return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuIconRowFooter.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuIconRowFooter.java new file mode 100644 index 0000000..2d2dd1e5 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuIconRowFooter.java
@@ -0,0 +1,133 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.appmenu; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; + +import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.bookmarks.BookmarkBridge; +import org.chromium.chrome.browser.download.DownloadUtils; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.widget.TintedImageButton; + +/** + * A {@link LinearLayout} that displays a horizontal row of icons for page actions. + */ +public class AppMenuIconRowFooter extends LinearLayout implements View.OnClickListener { + private ChromeActivity mActivity; + private AppMenu mAppMenu; + + private TintedImageButton mForwardButton; + private TintedImageButton mBookmarkButton; + private TintedImageButton mDownloadButton; + private TintedImageButton mPageInfoButton; + private TintedImageButton mReloadButton; + + public AppMenuIconRowFooter(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + + mForwardButton = (TintedImageButton) findViewById(R.id.forward_menu_id); + mForwardButton.setOnClickListener(this); + + mBookmarkButton = (TintedImageButton) findViewById(R.id.bookmark_this_page_id); + mBookmarkButton.setOnClickListener(this); + + mDownloadButton = (TintedImageButton) findViewById(R.id.offline_page_id); + mDownloadButton.setOnClickListener(this); + + mPageInfoButton = (TintedImageButton) findViewById(R.id.info_menu_id); + mPageInfoButton.setOnClickListener(this); + + mReloadButton = (TintedImageButton) findViewById(R.id.reload_menu_id); + mReloadButton.setOnClickListener(this); + } + + /** + * Initializes the icons, setting enabled state, drawables, and content descriptions. + * @param activity The {@link ChromeActivity} displaying the menu. + * @param appMenu The {@link AppMenu} that contains the icon row. + * @param bookmarkBridge The {@link BookmarkBridge} used to retrieve information about + * bookmarks. + */ + public void initialize( + ChromeActivity activity, AppMenu appMenu, BookmarkBridge bookmarkBridge) { + mActivity = activity; + mAppMenu = appMenu; + Tab currentTab = mActivity.getActivityTab(); + + mForwardButton.setEnabled(currentTab.canGoForward()); + + updateBookmarkMenuItem(bookmarkBridge, currentTab); + + mDownloadButton.setEnabled(DownloadUtils.isAllowedToDownloadPage(currentTab)); + + mReloadButton.setImageResource(R.drawable.btn_reload_stop); + loadingStateChanged(currentTab.isLoading()); + } + + @Override + public void onClick(View v) { + mActivity.onMenuOrKeyboardAction(v.getId(), true); + mAppMenu.dismiss(); + } + + /** + * Called when the current tab's load state has changed. + * @param isLoading Whether the tab is currently loading. + */ + public void loadingStateChanged(boolean isLoading) { + mReloadButton.getDrawable().setLevel(isLoading + ? AppMenuPropertiesDelegate.RELOAD_BUTTON_LEVEL_STOP_LOADING + : AppMenuPropertiesDelegate.RELOAD_BUTTON_LEVEL_RELOAD); + mReloadButton.setContentDescription(isLoading + ? mActivity.getString(R.string.accessibility_btn_stop_loading) + : mActivity.getString(R.string.accessibility_btn_refresh)); + } + + private void updateBookmarkMenuItem(BookmarkBridge bookmarkBridge, Tab currentTab) { + mBookmarkButton.setEnabled(bookmarkBridge.isEditBookmarksEnabled()); + + if (currentTab.getBookmarkId() != Tab.INVALID_BOOKMARK_ID) { + mBookmarkButton.setImageResource(R.drawable.btn_star_filled); + mBookmarkButton.setContentDescription(mActivity.getString(R.string.edit_bookmark)); + mBookmarkButton.setTint(ApiCompatibilityUtils.getColorStateList( + getResources(), R.color.blue_mode_tint)); + } else { + mBookmarkButton.setImageResource(R.drawable.btn_star); + mBookmarkButton.setContentDescription( + mActivity.getString(R.string.accessibility_menu_bookmark)); + } + } + + TintedImageButton getForwardButtonForTests() { + return mForwardButton; + } + + TintedImageButton getBookmarkButtonForTests() { + return mBookmarkButton; + } + + TintedImageButton getDownloadButtonForTests() { + return mDownloadButton; + } + + TintedImageButton getPageInfoButtonForTests() { + return mPageInfoButton; + } + + TintedImageButton getReloadButtonForTests() { + return mReloadButton; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java index 05a4d78b..2abb265 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
@@ -9,8 +9,10 @@ import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.SystemClock; +import android.support.annotation.Nullable; import android.view.Menu; import android.view.MenuItem; +import android.view.View; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.CommandLine; @@ -44,8 +46,8 @@ // Indices for different levels in drawable.btn_reload_stop. // Used only when preparing menu and refresh reload button in menu when tab // page load status changes. - private static final int RELOAD_BUTTON_LEVEL_RELOAD = 0; - private static final int RELOAD_BUTTON_LEVEL_STOP_LOADING = 1; + static final int RELOAD_BUTTON_LEVEL_RELOAD = 0; + static final int RELOAD_BUTTON_LEVEL_STOP_LOADING = 1; protected MenuItem mReloadMenuItem; @@ -53,6 +55,9 @@ protected BookmarkBridge mBookmarkBridge; + @Nullable + private AppMenuIconRowFooter mAppMenuIconRowFooter; + public AppMenuPropertiesDelegate(ChromeActivity activity) { mActivity = activity; } @@ -102,9 +107,13 @@ || url.startsWith(UrlConstants.CHROME_NATIVE_URL_PREFIX); boolean isFileScheme = url.startsWith(UrlConstants.FILE_URL_PREFIX); boolean isContentScheme = url.startsWith(UrlConstants.CONTENT_URL_PREFIX); - boolean shouldShowIconRow = !mActivity.isTablet() - || mActivity.getWindow().getDecorView().getWidth() - < DeviceFormFactor.getMinimumTabletWidthPx(mActivity); + + // If the BottomSheet is not null, the icon row will be displayed using + // AppMenuIconRowFooter as a prompt view. + boolean shouldShowIconRow = mActivity.getBottomSheet() == null + && (!mActivity.isTablet() + || mActivity.getWindow().getDecorView().getWidth() + < DeviceFormFactor.getMinimumTabletWidthPx(mActivity)); // Update the icon row items (shown in narrow form factors). menu.findItem(R.id.icon_row_menu_id).setVisible(shouldShowIconRow); @@ -222,6 +231,21 @@ } /** + * Called after the menu has been shown to finish initializing views. + * @param menu The {@link AppMenu} that was shown. + */ + public void onShow(final AppMenu menu) { + View promptView = menu.getPromptView(); + if (!(promptView instanceof AppMenuIconRowFooter)) { + mAppMenuIconRowFooter = null; + return; + } + + mAppMenuIconRowFooter = (AppMenuIconRowFooter) promptView; + mAppMenuIconRowFooter.initialize(mActivity, menu, mBookmarkBridge); + } + + /** * Sets the visibility and labels of the "Add to Home screen" and "Open WebAPK" menu items. */ protected void prepareAddToHomescreenMenuItem( @@ -271,6 +295,8 @@ ? RELOAD_BUTTON_LEVEL_STOP_LOADING : RELOAD_BUTTON_LEVEL_RELOAD); mReloadMenuItem.setTitle(isLoading ? R.string.accessibility_btn_stop_loading : R.string.accessibility_btn_refresh); + } else if (mAppMenuIconRowFooter != null) { + mAppMenuIconRowFooter.loadingStateChanged(isLoading); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java index e80e93c..90534f19 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -79,6 +79,8 @@ private static final String UNKNOWN_MIME_TYPE = "application/unknown"; private static final String DOWNLOAD_UMA_ENTRY = "DownloadUmaEntry"; private static final String DOWNLOAD_RETRY_COUNT_FILE_NAME = "DownloadRetryCount"; + private static final String DOWNLOAD_MANUAL_RETRY_SUFFIX = ".Manual"; + private static final String DOWNLOAD_TOTAL_RETRY_SUFFIX = ".Total"; private static final long UPDATE_DELAY_MILLIS = 1000; // Wait 10 seconds to resume all downloads, so that we won't impact tab loading. private static final long RESUME_DELAY_MILLIS = 10000; @@ -783,7 +785,8 @@ case DOWNLOAD_STATUS_CANCELLED: recordDownloadFinishedUMA(downloadStatus, downloadItem.getId(), downloadItem.getDownloadInfo().getBytesReceived()); - clearDownloadRetryCount(downloadItem.getId()); + clearDownloadRetryCount(downloadItem.getId(), true); + clearDownloadRetryCount(downloadItem.getId(), false); break; case DOWNLOAD_STATUS_INTERRUPTED: entry = getUmaStatsEntry(downloadItem.getId()); @@ -1196,14 +1199,19 @@ if (!progress.mCanDownloadWhileMetered) { progress.mCanDownloadWhileMetered = isActiveNetworkMetered(mContext); } - clearDownloadRetryCount(item.getId()); + incrementDownloadRetryCount(item.getId(), true); + clearDownloadRetryCount(item.getId(), true); } else { - int count = incrementAndReturnDownloadRetryCount(item.getId()); - if (count > getAutoResumptionLimit()) { + // TODO(qinmin): Consolidate this logic with the logic in notification service that + // throttles browser restarts. + SharedPreferences sharedPrefs = getAutoRetryCountSharedPreference(mContext); + int count = sharedPrefs.getInt(item.getId(), 0); + if (count >= getAutoResumptionLimit()) { removeAutoResumableDownload(item.getId()); onDownloadInterrupted(item.getDownloadInfo(), false); return; } + incrementDownloadRetryCount(item.getId(), false); } nativeResumeDownload(getNativeDownloadManagerService(), item.getId(), item.getDownloadInfo().isOffTheRecord()); @@ -1771,29 +1779,73 @@ /** * Increments the interruption count for a download. If the interruption count reaches a certain - * threshold, the download will no longer auto resume unless user click the resume button - * to clear the count. + * threshold, the download will no longer auto resume unless user click the resume button to + * clear the count. + * * @param downloadGuid Download GUID. - * @return The interruption count of the download, after incrementation. + * @param hasUserGesture Whether the retry is caused by user gesture. */ - private int incrementAndReturnDownloadRetryCount(String downloadGuid) { - SharedPreferences sharedPrefs = getAutoRetryCountSharedPreference(mContext); - int count = sharedPrefs.getInt(downloadGuid, 0); - count++; - SharedPreferences.Editor editor = sharedPrefs.edit(); - editor.putInt(downloadGuid, count); - editor.apply(); - return count; + private void incrementDownloadRetryCount(String downloadGuid, boolean hasUserGesture) { + String name = getDownloadRetryCountSharedPrefName(downloadGuid, hasUserGesture, false); + incrementDownloadRetrySharedPreferenceCount(name); + name = getDownloadRetryCountSharedPrefName(downloadGuid, hasUserGesture, true); + incrementDownloadRetrySharedPreferenceCount(name); } /** - * clears the interruption count for a download. - * @param downloadGuid Download GUID. + * Helper method to increment the retry count for a SharedPreference entry. + * @param sharedPreferenceName Name of the SharedPreference entry. */ - private void clearDownloadRetryCount(String downloadGuid) { + private void incrementDownloadRetrySharedPreferenceCount(String sharedPreferenceName) { SharedPreferences sharedPrefs = getAutoRetryCountSharedPreference(mContext); + int count = sharedPrefs.getInt(sharedPreferenceName, 0); SharedPreferences.Editor editor = sharedPrefs.edit(); - editor.remove(downloadGuid); + count++; + editor.putInt(sharedPreferenceName, count); + editor.apply(); + } + + /** + * Helper method to retrieve the SharedPreference name for different download retry types. + * TODO(qinmin): introduce a proto for this and consolidate all the UMA metrics (including + * retry counts in DownloadHistory) stored in persistent storage. + * @param downloadGuid Guid of the download. + * @param hasUserGesture Whether the SharedPreference is for manual retry attempts. + * @param isTotalCount Whether the SharedPreference is for total retry attempts. + */ + private String getDownloadRetryCountSharedPrefName( + String downloadGuid, boolean hasUserGesture, boolean isTotalCount) { + if (isTotalCount) return downloadGuid + DOWNLOAD_TOTAL_RETRY_SUFFIX; + if (hasUserGesture) return downloadGuid + DOWNLOAD_MANUAL_RETRY_SUFFIX; + return downloadGuid; + } + + /** + * clears the retry count for a download. + * + * @param downloadGuid Download GUID. + * @param isAutoRetryOnly Whether to clear the auto retry count only. + */ + private void clearDownloadRetryCount(String downloadGuid, boolean isAutoRetryOnly) { + SharedPreferences sharedPrefs = getAutoRetryCountSharedPreference(mContext); + String name = getDownloadRetryCountSharedPrefName(downloadGuid, !isAutoRetryOnly, false); + int count = Math.min(sharedPrefs.getInt(name, 0), 200); + assert count >= 0; + SharedPreferences.Editor editor = sharedPrefs.edit(); + editor.remove(name); + if (isAutoRetryOnly) { + RecordHistogram.recordSparseSlowlyHistogram( + "MobileDownload.ResumptionsCount.Automatic", count); + } else { + RecordHistogram.recordSparseSlowlyHistogram( + "MobileDownload.ResumptionsCount.Manual", count); + name = getDownloadRetryCountSharedPrefName(downloadGuid, false, true); + count = sharedPrefs.getInt(name, 0); + assert count >= 0; + RecordHistogram.recordSparseSlowlyHistogram( + "MobileDownload.ResumptionsCount.Total", Math.min(count, 500)); + editor.remove(name); + } editor.apply(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java index a08fc8f..58902cb1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -9,6 +9,7 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; +import android.content.SharedPreferences; import android.graphics.Color; import android.graphics.Region; import android.os.Build; @@ -25,6 +26,7 @@ import android.widget.FrameLayout; import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.base.ContextUtils; import org.chromium.base.ObserverList; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; @@ -34,11 +36,13 @@ import org.chromium.chrome.browser.ntp.NativePageFactory; import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.util.MathUtils; import org.chromium.chrome.browser.widget.FadingBackgroundView; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetContentController.ContentType; +import org.chromium.chrome.browser.widget.textbubble.ViewAnchoredTextBubble; import org.chromium.content_public.browser.LoadUrlParams; import java.lang.annotation.Retention; @@ -71,6 +75,9 @@ public static final int SHEET_STATE_FULL = 2; public static final int SHEET_STATE_SCROLLING = 3; + /** Shared preference key for tracking whether the help bubble has been shown. */ + private static final String BOTTOM_SHEET_HELP_BUBBLE_SHOWN = "bottom_sheet_help_bubble_shown"; + /** * The base duration of the settling animation of the sheet. 218 ms is a spec for material * design (this is the minimum time a user is guaranteed to pay attention to something). @@ -193,6 +200,9 @@ /** Whether the sheet is currently open. */ private boolean mIsSheetOpen; + /** Whether the root view has been laid out at least once. **/ + private boolean mHasRootLayoutOccurred; + /** * An interface defining content that can be displayed inside of the bottom sheet for Chrome * Home. @@ -424,6 +434,18 @@ */ public void setTabModelSelector(TabModelSelector tabModelSelector) { mTabModelSelector = tabModelSelector; + + if (mHasRootLayoutOccurred && mTabModelSelector.isTabStateInitialized()) { + showHelpBubbleIfNecessary(); + } else if (!mTabModelSelector.isTabStateInitialized()) { + mTabModelSelector.addObserver(new EmptyTabModelSelectorObserver() { + @Override + public void onTabStateInitialized() { + if (mHasRootLayoutOccurred) showHelpBubbleIfNecessary(); + mTabModelSelector.removeObserver(this); + } + }); + } } /** @@ -496,6 +518,13 @@ cancelAnimation(); setSheetState(mCurrentState, false); + + if (!mHasRootLayoutOccurred && mTabModelSelector != null + && mTabModelSelector.isTabStateInitialized()) { + showHelpBubbleIfNecessary(); + } + + mHasRootLayoutOccurred = true; } }); @@ -1070,4 +1099,27 @@ mFindInPageView != null && mFindInPageView.getVisibility() == View.VISIBLE; return !isToolbarAndroidViewHidden() && !isInOverviewMode && !isFindInPageVisible; } + + private void showHelpBubbleIfNecessary() { + // The help bubble should only be shown after layout has occurred so that the anchor view is + // in the correct position on the screen. It also must be shown after the tab state has been + // initialized so that any tab that auto-opens the BottomSheet has had a chance to do so. + assert mHasRootLayoutOccurred && mTabModelSelector != null + && mTabModelSelector.isTabStateInitialized(); + + if (mCurrentState != SHEET_STATE_PEEK) return; + + SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); + if (preferences.getBoolean(BOTTOM_SHEET_HELP_BUBBLE_SHOWN, false)) return; + + ViewAnchoredTextBubble helpBubble = new ViewAnchoredTextBubble( + getContext(), mControlContainer, R.string.bottom_sheet_help_bubble_message); + int inset = getContext().getResources().getDimensionPixelSize( + R.dimen.bottom_sheet_help_bubble_inset); + helpBubble.setInsetPx(0, inset, 0, inset); + helpBubble.setDismissOnTouchInteraction(true); + helpBubble.show(); + + preferences.edit().putBoolean(BOTTOM_SHEET_HELP_BUBBLE_SHOWN, true).apply(); + } }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 7204c8b..69b1a34 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -2936,6 +2936,11 @@ <message name="IDS_DISABLED_INCOGNITO_LAUNCHER_SHORTCUT_MESSAGE" desc="Text for a toast displayed prompting the user to remove the disabled 'New incognito tab' app shortcut and recreate it."> Remove and recreate this shortcut </message> + + <!-- Chrome Home --> + <message name="IDS_BOTTOM_SHEET_HELP_BUBBLE_MESSAGE" desc="Text displayed in a help bubble above the bottom navigation sheet prompting users to pull the sheet up to see their bookmarks and other content."> + Pull up to see bookmarks and more + </message> </messages> </release> </grit>
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index cb5733cf..08fb529d 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -74,6 +74,7 @@ "java/src/org/chromium/chrome/browser/appmenu/AppMenuDragHelper.java", "java/src/org/chromium/chrome/browser/appmenu/AppMenuHandler.java", "java/src/org/chromium/chrome/browser/appmenu/AppMenuItemIcon.java", + "java/src/org/chromium/chrome/browser/appmenu/AppMenuIconRowFooter.java", "java/src/org/chromium/chrome/browser/appmenu/AppMenuObserver.java", "java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java", "java/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryBridge.java", @@ -1270,6 +1271,7 @@ "javatests/src/org/chromium/chrome/browser/ChromeActivityTest.java", "javatests/src/org/chromium/chrome/browser/ChromeBackgroundServiceTest.java", "javatests/src/org/chromium/chrome/browser/ContentViewFocusTest.java", + "javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java", "javatests/src/org/chromium/chrome/browser/CrashTest.java", "javatests/src/org/chromium/chrome/browser/FocusedEditableTextFieldZoomTest.java", "javatests/src/org/chromium/chrome/browser/HistoryUITest.java", @@ -1304,6 +1306,7 @@ "javatests/src/org/chromium/chrome/browser/WebShareTest.java", "javatests/src/org/chromium/chrome/browser/accessibility/FontSizePrefsTest.java", "javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java", + "javatests/src/org/chromium/chrome/browser/appmenu/ChromeHomeAppMenuTest.java", "javatests/src/org/chromium/chrome/browser/appmenu/DataSaverAppMenuTest.java", "javatests/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryTest.java", "javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java new file mode 100644 index 0000000..fe1956f2 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java
@@ -0,0 +1,184 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser; + +import android.support.test.filters.LargeTest; + +import org.chromium.base.Callback; +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.CallbackHelper; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.Restriction; +import org.chromium.blink.mojom.document_metadata.Entity; +import org.chromium.blink.mojom.document_metadata.Property; +import org.chromium.blink.mojom.document_metadata.Values; +import org.chromium.blink.mojom.document_metadata.WebPage; +import org.chromium.chrome.browser.firstrun.FirstRunStatus; +import org.chromium.chrome.test.ChromeTabbedActivityTestBase; +import org.chromium.chrome.test.util.ChromeTabUtils; +import org.chromium.net.test.EmbeddedTestServer; +import org.chromium.url.mojom.Url; + +import java.util.concurrent.TimeoutException; + +/** + * Tests Copyless Paste AppIndexing using instrumented tests. + */ +@CommandLineFlags.Add("enable-features=CopylessPaste") +@Restriction(Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE) +public class CopylessPasteTest extends ChromeTabbedActivityTestBase { + // NODATA_PAGE doesn't contain desired metadata. + private static final String NODATA_PAGE = "/chrome/test/data/android/about.html"; + + // DATA_PAGE contains desired metadata. + private static final String DATA_PAGE = "/chrome/test/data/android/appindexing/json-ld.html"; + + private EmbeddedTestServer mTestServer; + private CopylessHelper mCallbackHelper; + + @Override + protected void setUp() throws Exception { + // We have to set up the test server before starting the activity. + mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext()); + + mCallbackHelper = new CopylessHelper(); + + AppIndexingUtil.setCallbackForTesting(new Callback<WebPage>() { + @Override + public void onResult(WebPage webpage) { + mCallbackHelper.notifyCalled(webpage); + } + }); + + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + FirstRunStatus.setFirstRunFlowComplete(true); + } + }); + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + mTestServer.stopAndDestroyServer(); + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + FirstRunStatus.setFirstRunFlowComplete(false); + } + }); + AppIndexingUtil.setCallbackForTesting(null); + super.tearDown(); + } + + @Override + public void startMainActivity() throws InterruptedException { + startMainActivityOnBlankPage(); + } + + private static class CopylessHelper extends CallbackHelper { + private WebPage mWebPage; + + public WebPage getWebPage() { + return mWebPage; + } + + public void notifyCalled(WebPage page) { + mWebPage = page; + notifyCalled(); + } + } + + /** + * Tests that CopylessPaste is disabled in Incognito tabs. + */ + @LargeTest + @Feature({"CopylessPaste"}) + public void testIncognito() throws InterruptedException, TimeoutException { + // Incognito tabs are ignored. + newIncognitoTabsFromMenu(1); + loadUrl(mTestServer.getURL(NODATA_PAGE)); + loadUrl(mTestServer.getURL(DATA_PAGE)); + ChromeTabUtils.closeCurrentTab(getInstrumentation(), getActivity()); + assertEquals(0, mCallbackHelper.getCallCount()); + } + + /** + * Tests that CopylessPaste skips invalid schemes. + */ + @LargeTest + @Feature({"CopylessPaste"}) + public void testInvalidScheme() throws InterruptedException, TimeoutException { + // CopylessPaste only parses http and https. + loadUrl("chrome://newtab"); + loadUrl("chrome://about"); + assertEquals(0, mCallbackHelper.getCallCount()); + } + + /** + * Tests that CopylessPaste works on pages without desired metadata. + */ + @LargeTest + @Feature({"CopylessPaste"}) + public void testNoMeta() throws InterruptedException, TimeoutException { + loadUrl(mTestServer.getURL(NODATA_PAGE)); + mCallbackHelper.waitForCallback(0); + assertNull(mCallbackHelper.getWebPage()); + } + + /** + * Tests that CopylessPaste works end-to-end. + */ + @LargeTest + @Feature({"CopylessPaste"}) + public void testValid() throws InterruptedException, TimeoutException { + loadUrl(mTestServer.getURL(DATA_PAGE)); + mCallbackHelper.waitForCallback(0); + WebPage extracted = mCallbackHelper.getWebPage(); + + WebPage expected = new WebPage(); + expected.url = new Url(); + expected.url.url = mTestServer.getURL(DATA_PAGE); + expected.title = "JSON-LD for AppIndexing Test"; + Entity e = new Entity(); + e.type = "Hotel"; + e.properties = new Property[2]; + e.properties[0] = new Property(); + e.properties[0].name = "@context"; + e.properties[0].values = new Values(); + e.properties[0].values.setStringValues(new String[] {"http://schema.org"}); + e.properties[1] = new Property(); + e.properties[1].name = "name"; + e.properties[1].values = new Values(); + e.properties[1].values.setStringValues(new String[] {"Hotel Name"}); + expected.entities = new Entity[1]; + expected.entities[0] = e; + assertEquals(expected, extracted); + } + + /** + * Tests that CopylessPaste skips parsing visited pages. + */ + @LargeTest + @Feature({"CopylessPaste"}) + public void testCache() throws InterruptedException, TimeoutException { + // The URLs used here should be unique in CopylessPasteTest. + String uniqueTag = "#123"; + // NODATA_PAGE doesn't contain desired metadata. + loadUrl(mTestServer.getURL(NODATA_PAGE + uniqueTag)); + mCallbackHelper.waitForCallback(0); + // DATA_PAGE contains desired metadata. + loadUrl(mTestServer.getURL(DATA_PAGE + uniqueTag)); + mCallbackHelper.waitForCallback(1); + + // Cache hit without entities. Shouldn't parse again. + loadUrl(mTestServer.getURL(NODATA_PAGE + uniqueTag)); + // Cache hit with entities. Shouldn't parse again. + loadUrl(mTestServer.getURL(DATA_PAGE + uniqueTag)); + assertEquals(2, mCallbackHelper.getCallCount()); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java index 372bc449..470592cd 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java
@@ -33,7 +33,7 @@ */ @RetryOnFailure public class AppMenuTest extends ChromeActivityTestCaseBase<ChromeActivity> { - private static final String TEST_URL = UrlUtils.encodeHtmlDataUri("<html>poit.</html>"); + private static final String TEST_URL = UrlUtils.encodeHtmlDataUri("<html>foo</html>"); private AppMenu mAppMenu; private AppMenuHandler mAppMenuHandler;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/ChromeHomeAppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/ChromeHomeAppMenuTest.java new file mode 100644 index 0000000..6c7fbb2 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/ChromeHomeAppMenuTest.java
@@ -0,0 +1,87 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.appmenu; + +import android.support.test.filters.SmallTest; + +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.UrlUtils; +import org.chromium.chrome.test.BottomSheetTestCaseBase; +import org.chromium.content.browser.test.util.Criteria; +import org.chromium.content.browser.test.util.CriteriaHelper; + +/** + * Tests for the app menu when Chrome Home is enabled. + */ +public class ChromeHomeAppMenuTest extends BottomSheetTestCaseBase { + private static final String TEST_URL = UrlUtils.encodeHtmlDataUri("<html>foo</html>"); + private AppMenuHandler mAppMenuHandler; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mAppMenuHandler = getActivity().getAppMenuHandler(); + } + + @SmallTest + public void testPageMenu() throws IllegalArgumentException, InterruptedException { + loadUrl(TEST_URL); + + showAppMenuAndAssertMenuShown(); + AppMenu appMenu = getActivity().getAppMenuHandler().getAppMenu(); + AppMenuIconRowFooter iconRow = (AppMenuIconRowFooter) appMenu.getPromptView(); + + assertFalse(iconRow.getForwardButtonForTests().isEnabled()); + assertTrue(iconRow.getBookmarkButtonForTests().isEnabled()); + // Only HTTP/S pages can be downloaded. + assertFalse(iconRow.getDownloadButtonForTests().isEnabled()); + assertTrue(iconRow.getPageInfoButtonForTests().isEnabled()); + assertTrue(iconRow.getReloadButtonForTests().isEnabled()); + + // Navigate backward, open the menu and assert forward button is enabled. + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mAppMenuHandler.hideAppMenu(); + getActivity().getActivityTab().goBack(); + } + }); + + showAppMenuAndAssertMenuShown(); + iconRow = (AppMenuIconRowFooter) appMenu.getPromptView(); + assertTrue(iconRow.getForwardButtonForTests().isEnabled()); + } + + @SmallTest + public void testTabSwitcherMenu() throws IllegalArgumentException { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + getActivity().getLayoutManager().showOverview(false); + } + }); + + showAppMenuAndAssertMenuShown(); + AppMenu appMenu = getActivity().getAppMenuHandler().getAppMenu(); + + assertNull(appMenu.getPromptView()); + } + + private void showAppMenuAndAssertMenuShown() { + ThreadUtils.runOnUiThread(new Runnable() { + @Override + public void run() { + mAppMenuHandler.showAppMenu(null, false); + } + }); + CriteriaHelper.pollUiThread(new Criteria("AppMenu did not show") { + @Override + public boolean isSatisfied() { + return mAppMenuHandler.isAppMenuShowing(); + } + }); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java index 4560a32..5c55ae4 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.offlinepages; import android.content.Context; +import android.support.annotation.MainThread; import android.support.test.filters.MediumTest; import org.chromium.base.Callback; @@ -30,11 +31,13 @@ @CommandLineFlags.Add("enable-features=OfflineRecentPages") public class RecentTabsTest extends ChromeTabbedActivityTestBase { private static final String TEST_PAGE = "/chrome/test/data/android/about.html"; + private static final String TEST_PAGE_2 = "/chrome/test/data/android/simple.html"; private static final int TIMEOUT_MS = 5000; private OfflinePageBridge mOfflinePageBridge; private EmbeddedTestServer mTestServer; private String mTestPage; + private String mTestPage2; private void initializeBridgeForProfile(final boolean incognitoProfile) throws InterruptedException { @@ -84,6 +87,7 @@ mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext()); mTestPage = mTestServer.getURL(TEST_PAGE); + mTestPage2 = mTestServer.getURL(TEST_PAGE_2); } @Override @@ -109,9 +113,9 @@ // The tab should be foreground and so no snapshot should exist. assertNull(getPageByClientId(firstTabClientId)); - // Note, that switching to a new tab must occur after the SnapshotController believes the - // page quality is good enough. With the debug flag, the delay after DomContentLoaded is 0 - // so we can definitely snapshot after onload (which is what |loadUrlInNewTab| waits for). + // Note: switching to a new tab must occur after the SnapshotController believes the page + // quality is good enough. With the debug flag, the delay after DomContentLoaded is 0 so we + // can definitely snapshot after onload (which is what |loadUrlInNewTab| waits for). // Switch to a new tab to cause the WebContents hidden event. loadUrlInNewTab("about:blank"); @@ -120,10 +124,10 @@ } /** - * Note: this test relies on a sleeping period because some of the taking actions are - * complicated to track otherwise, so there is the possibility of flakiness. I chose 100ms from - * local testing and I expect it to be "safe" but it flakiness is detected it might have to be - * further increased. + * Note: this test relies on a sleeping period because some of the monitored actions are + * difficult to track deterministically. A sleep time of 100 ms was chosen based on local + * testing and is expected to be "safe". Nevertheless if flakiness is detected it might have to + * be further increased. */ @CommandLineFlags.Add("short-offline-page-snapshot-delay-for-test") @MediumTest @@ -178,6 +182,83 @@ waitForPageWithClientId(firstTabClientId); } + /** + * Verifies that a snapshot created by last_n is properly deleted when the tab is navigated to + * another page. The deletion of snapshots for pages that should not be available anymore is a + * privacy requirement for last_n. + */ + @CommandLineFlags.Add("short-offline-page-snapshot-delay-for-test") + @MediumTest + public void testLastNPageIsDeletedUponNavigation() throws Exception { + // The tab of interest. + final Tab tab = loadUrlInNewTab(mTestPage); + final TabModelSelector tabModelSelector = tab.getTabModelSelector(); + + final ClientId firstTabClientId = + new ClientId(OfflinePageBridge.LAST_N_NAMESPACE, Integer.toString(tab.getId())); + + // Switch to a new tab and wait for the snapshot to be created. + loadUrlInNewTab("about:blank"); + waitForPageWithClientId(firstTabClientId); + OfflinePageItem offlinePage = getPageByClientId(firstTabClientId); + assertFalse(tab.equals(tabModelSelector.getCurrentTab())); + + // Switch back to the initial tab and install the page deletion monitor for later usage. + final OfflinePageDeletionMonitor deletionMonitor = + new OfflinePageDeletionMonitor(offlinePage.getOfflineId()); + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + TabModel tabModel = tabModelSelector.getModelForTabId(tab.getId()); + int tabIndex = TabModelUtils.getTabIndexById(tabModel, tab.getId()); + TabModelUtils.setIndex(tabModel, tabIndex); + deletionMonitor.installObserver(); + } + }); + assertEquals(tabModelSelector.getCurrentTab(), tab); + + // Navigate to a new page and confirm the previously created snapshot has been deleted. + loadUrl(mTestPage2); + deletionMonitor.assertDeleted(); + } + + /** + * Verifies that a snapshot created by last_n is properly deleted when the tab is closed. The + * deletion of snapshots for pages that should not be available anymore is a privacy requirement + * for last_n. + */ + @CommandLineFlags.Add("short-offline-page-snapshot-delay-for-test") + @MediumTest + public void testLastNPageIsDeletedUponClosure() throws Exception { + // The tab of interest. + final Tab tab = loadUrlInNewTab(mTestPage); + final TabModelSelector tabModelSelector = tab.getTabModelSelector(); + + final ClientId firstTabClientId = + new ClientId(OfflinePageBridge.LAST_N_NAMESPACE, Integer.toString(tab.getId())); + + // Switch to a new tab and wait for the snapshot to be created. + loadUrlInNewTab("about:blank"); + waitForPageWithClientId(firstTabClientId); + OfflinePageItem offlinePage = getPageByClientId(firstTabClientId); + + // Requests closing of the tab allowing for closure undo and checks it's actually closing. + final int tabId = tab.getId(); + final OfflinePageDeletionMonitor deletionMonitor = + new OfflinePageDeletionMonitor(offlinePage.getOfflineId()); + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + deletionMonitor.installObserver(); + TabModel tabModel = tabModelSelector.getModelForTabId(tabId); + tabModel.closeTab(tab, false, false, true); + tabModel.commitTabClosure(tabId); + } + }); + assertNull(tabModelSelector.getTabById(tabId)); + deletionMonitor.assertDeleted(); + } + private void waitForPageWithClientId(final ClientId clientId) throws InterruptedException { if (getPageByClientId(clientId) != null) return; @@ -199,6 +280,32 @@ assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); } + private class OfflinePageDeletionMonitor { + private final Semaphore mSemaphore = new Semaphore(0); + private final long mOfflineId; + + public OfflinePageDeletionMonitor(long offlineId) { + mOfflineId = offlineId; + } + + @MainThread + public void installObserver() { + mOfflinePageBridge.addObserver(new OfflinePageModelObserver() { + @Override + public void offlinePageDeleted(long offlineId, ClientId clientId) { + if (offlineId == mOfflineId) { + mOfflinePageBridge.removeObserver(this); + mSemaphore.release(); + } + } + }); + } + + public void assertDeleted() throws InterruptedException { + assertTrue(mSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + } + } + private OfflinePageItem getPageByClientId(ClientId clientId) throws InterruptedException { final OfflinePageItem[] result = {null}; final Semaphore semaphore = new Semaphore(0); @@ -223,4 +330,24 @@ assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); return result[0]; } + + private OfflinePageItem getPageByOfflineId(final long offlineId) throws InterruptedException { + final OfflinePageItem[] result = {null}; + final Semaphore semaphore = new Semaphore(0); + + ThreadUtils.runOnUiThread(new Runnable() { + @Override + public void run() { + mOfflinePageBridge.getPageByOfflineId(offlineId, new Callback<OfflinePageItem>() { + @Override + public void onResult(OfflinePageItem item) { + result[0] = item; + semaphore.release(); + } + }); + } + }); + assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + return result[0]; + } }
diff --git a/chrome/app/resources/locale_settings.grd b/chrome/app/resources/locale_settings.grd index 3cbcec34..897a3c7 100644 --- a/chrome/app/resources/locale_settings.grd +++ b/chrome/app/resources/locale_settings.grd
@@ -156,6 +156,16 @@ <message name="IDS_CONFLICTING_MODULE_BUBBLE_WIDTH_CHARS" use_name_for_id="true"> 46 </message> + + <!-- The width of the Text on the save password Desktop iOS promotion bubble. --> + <message name="IDS_DESKTOP_IOS_PROMOTION_SAVE_PASSWORDS_BUBBLE_TEXT_WIDTH_CHARS" use_name_for_id="true"> + 55 + </message> + + <!-- The width of the Text on the Desktop iOS promotion bubble. --> + <message name="IDS_DESKTOP_IOS_PROMOTION_TEXT_WIDTH_CHARS" use_name_for_id="true"> + 41 + </message> </if> <if expr="chromeos">
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper.cc b/chrome/browser/android/offline_pages/recent_tab_helper.cc index f248220..308afd1 100644 --- a/chrome/browser/android/offline_pages/recent_tab_helper.cc +++ b/chrome/browser/android/offline_pages/recent_tab_helper.cc
@@ -212,18 +212,27 @@ downloads_ongoing_snapshot_info_.get(), false); } + // If the previous page was saved, delete it now. + if (last_n_latest_saved_snapshot_info_) { + std::vector<int64_t> id{last_n_latest_saved_snapshot_info_->request_id}; + page_model_->DeletePagesByOfflineId(id, DeletePageCallback()); + } + // Cancel any and all in flight snapshot tasks from the previous page. - DVLOG_IF(1, last_n_ongoing_snapshot_info_) - << " - Canceling ongoing last_n snapshot"; CancelInFlightSnapshots(); downloads_snapshot_on_hold_ = false; // Always reset so that posted tasks get canceled. snapshot_controller_->Reset(); - // Check for conditions that would cause us not to snapshot. + // Check for conditions that should stop last_n from creating snapshots of + // this page: + // - It is an error page. + // - The navigation is a POST as offline pages are never loaded for them. + // - The navigated URL is not supported. + // - The page being loaded is already an offline page. bool can_save = - !navigation_handle->IsErrorPage() && + !navigation_handle->IsErrorPage() && !navigation_handle->IsPost() && OfflinePageModel::CanSaveURL(web_contents()->GetLastCommittedURL()) && OfflinePageUtils::GetOfflinePageFromWebContents(web_contents()) == nullptr; @@ -419,8 +428,12 @@ void RecentTabHelper::SavePageCallback(SnapshotProgressInfo* snapshot_info, OfflinePageModel::SavePageResult result, int64_t offline_id) { - DCHECK(snapshot_info->IsForLastN() || + DCHECK((snapshot_info->IsForLastN() && + snapshot_info->request_id == OfflinePageModel::kInvalidOfflineId) || snapshot_info->request_id == offline_id); + // Store the assigned offline_id (for downloads case it will already contain + // the same value). + snapshot_info->request_id = offline_id; ReportSnapshotCompleted(snapshot_info, result == SavePageResult::SUCCESS); } @@ -434,7 +447,12 @@ << " for: " << web_contents()->GetLastCommittedURL().spec(); if (snapshot_info->IsForLastN()) { DCHECK_EQ(snapshot_info, last_n_ongoing_snapshot_info_.get()); - last_n_ongoing_snapshot_info_.reset(); + if (success) { + last_n_latest_saved_snapshot_info_ = + std::move(last_n_ongoing_snapshot_info_); + } else { + last_n_ongoing_snapshot_info_.reset(); + } return; } @@ -481,10 +499,15 @@ } void RecentTabHelper::CancelInFlightSnapshots() { + DVLOG_IF(1, last_n_ongoing_snapshot_info_) + << " - Canceling ongoing last_n snapshot"; + DVLOG_IF(1, downloads_ongoing_snapshot_info_) + << " - Canceling ongoing downloads snapshot"; weak_ptr_factory_.InvalidateWeakPtrs(); downloads_ongoing_snapshot_info_.reset(); downloads_latest_saved_snapshot_info_.reset(); last_n_ongoing_snapshot_info_.reset(); + last_n_latest_saved_snapshot_info_.reset(); } } // namespace offline_pages
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper.h b/chrome/browser/android/offline_pages/recent_tab_helper.h index b547240..c61fbd74 100644 --- a/chrome/browser/android/offline_pages/recent_tab_helper.h +++ b/chrome/browser/android/offline_pages/recent_tab_helper.h
@@ -128,13 +128,18 @@ bool downloads_snapshot_on_hold_ = false; // Snapshot information for the last successful snapshot requested by - // downloads. Null if no successful one has ever completed. + // downloads. Null if no successful one has ever completed for the current + // page. std::unique_ptr<SnapshotProgressInfo> downloads_latest_saved_snapshot_info_; // Snapshot progress information for a last_n triggered request. Null if // last_n is not currently capturing the current page. std::unique_ptr<SnapshotProgressInfo> last_n_ongoing_snapshot_info_; + // Snapshot information for the last successful snapshot requested by + // last_n. Null if no successful one has ever completed for the current page. + std::unique_ptr<SnapshotProgressInfo> last_n_latest_saved_snapshot_info_; + // If empty, the tab does not have AndroidId and can not capture pages. std::string tab_id_;
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc index 7f97d15f..3e4c535 100644 --- a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc +++ b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc
@@ -375,8 +375,8 @@ ASSERT_EQ(1U, GetAllPages().size()); } -// Checks that last_n will not save a snapshot if the tab while the tab is -// presented as a custom tab. Download requests should be unaffected though. +// Checks that last_n will not save a snapshot while the tab is being presented +// as a custom tab. Download requests should be unaffected though. TEST_F(RecentTabHelperTest, LastNWontSaveCustomTab) { // Simulates the tab running as a custom tab. default_test_delegate()->set_is_custom_tab(true); @@ -500,15 +500,16 @@ EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url); int64_t first_offline_id = GetAllPages()[0].offline_id; - // Navigate with the same URL until the page is minimally loaded then hide the - // tab. The previous snapshot should be removed and a new one taken. + // Reload the same URL until the page is minimally loaded. The previous + // snapshot should have been removed. NavigateAndCommitTyped(kTestPageUrl); recent_tab_helper()->DocumentAvailableInMainFrame(); FastForwardSnapshotController(); EXPECT_EQ(1U, page_added_count()); - EXPECT_EQ(0U, model_removed_count()); - ASSERT_EQ(1U, GetAllPages().size()); + EXPECT_EQ(1U, model_removed_count()); + ASSERT_EQ(0U, GetAllPages().size()); + // Hide the tab and a new snapshot should be taken. recent_tab_helper()->WasHidden(); RunUntilIdle(); EXPECT_EQ(2U, page_added_count()); @@ -565,15 +566,15 @@ ASSERT_EQ(1U, GetAllPages().size()); EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url); - // Fully load the second URL then hide the tab and check for a single snapshot - // of the new page. + // Fully load the second URL. The previous snapshot should have been deleted. NavigateAndCommitTyped(kTestPageUrlOther); recent_tab_helper()->DocumentOnLoadCompletedInMainFrame(); FastForwardSnapshotController(); EXPECT_EQ(1U, page_added_count()); - EXPECT_EQ(0U, model_removed_count()); - ASSERT_EQ(1U, GetAllPages().size()); + EXPECT_EQ(1U, model_removed_count()); + ASSERT_EQ(0U, GetAllPages().size()); + // Then hide the tab and check for a single snapshot of the new page. recent_tab_helper()->WasHidden(); RunUntilIdle(); EXPECT_EQ(2U, page_added_count()); @@ -731,7 +732,7 @@ } // Simulates a download request to offline the current page made after loading -// is completed. Should end up with one offline pages. +// is completed. Should end up with one offline page. TEST_F(RecentTabHelperTest, DownloadRequestAfterFullyLoad) { NavigateAndCommit(kTestPageUrl); recent_tab_helper()->DocumentOnLoadCompletedInMainFrame(); @@ -897,7 +898,8 @@ RunUntilIdle(); ASSERT_EQ(1U, GetAllPages().size()); - // Starts a reload and hides the tab. No new snapshot should be saved. + // Starts a reload and hides the tab before it minimally load. The previous + // snapshot should be removed. controller().Reload(content::ReloadType::NORMAL, false); content::WebContentsTester* web_contents_tester = content::WebContentsTester::For(web_contents()); @@ -905,8 +907,8 @@ recent_tab_helper()->WasHidden(); RunUntilIdle(); EXPECT_EQ(1U, page_added_count()); - EXPECT_EQ(0U, model_removed_count()); - ASSERT_EQ(1U, GetAllPages().size()); + EXPECT_EQ(1U, model_removed_count()); + ASSERT_EQ(0U, GetAllPages().size()); // Finish loading and hide the tab. A new snapshot should be created. recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
diff --git a/chrome/browser/android/usb/web_usb_chooser_service_android.cc b/chrome/browser/android/usb/web_usb_chooser_service_android.cc index 5473124..d4618a0 100644 --- a/chrome/browser/android/usb/web_usb_chooser_service_android.cc +++ b/chrome/browser/android/usb/web_usb_chooser_service_android.cc
@@ -28,7 +28,7 @@ } void WebUsbChooserServiceAndroid::Bind( - mojo::InterfaceRequest<device::usb::ChooserService> request) { + mojo::InterfaceRequest<device::mojom::UsbChooserService> request) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); bindings_.AddBinding(this, std::move(request)); }
diff --git a/chrome/browser/android/usb/web_usb_chooser_service_android.h b/chrome/browser/android/usb/web_usb_chooser_service_android.h index a4aeadb..db2df4d9 100644 --- a/chrome/browser/android/usb/web_usb_chooser_service_android.h +++ b/chrome/browser/android/usb/web_usb_chooser_service_android.h
@@ -22,7 +22,7 @@ // Implementation of the public device::usb::ChooserService interface. // This interface can be used by a webpage to request permission from user // to access a certain device. -class WebUsbChooserServiceAndroid : public device::usb::ChooserService { +class WebUsbChooserServiceAndroid : public device::mojom::UsbChooserService { public: explicit WebUsbChooserServiceAndroid( content::RenderFrameHost* render_frame_host); @@ -33,11 +33,11 @@ void GetPermission(const std::vector<device::UsbDeviceFilter>& device_filters, const GetPermissionCallback& callback) override; - void Bind(mojo::InterfaceRequest<device::usb::ChooserService> request); + void Bind(mojo::InterfaceRequest<device::mojom::UsbChooserService> request); private: content::RenderFrameHost* const render_frame_host_; - mojo::BindingSet<device::usb::ChooserService> bindings_; + mojo::BindingSet<device::mojom::UsbChooserService> bindings_; std::vector<std::unique_ptr<UsbChooserDialogAndroid>> usb_chooser_dialog_android_;
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 1b36190..90d7c25 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -927,7 +927,7 @@ void CreateUsbDeviceManager( RenderFrameHost* render_frame_host, - mojo::InterfaceRequest<device::usb::DeviceManager> request) { + mojo::InterfaceRequest<device::mojom::UsbDeviceManager> request) { WebContents* web_contents = WebContents::FromRenderFrameHost(render_frame_host); if (!web_contents) { @@ -942,7 +942,7 @@ void CreateWebUsbChooserService( RenderFrameHost* render_frame_host, - mojo::InterfaceRequest<device::usb::ChooserService> request) { + mojo::InterfaceRequest<device::mojom::UsbChooserService> request) { WebContents* web_contents = WebContents::FromRenderFrameHost(render_frame_host); if (!web_contents) {
diff --git a/chrome/browser/chrome_content_browser_manifest_overlay.json b/chrome/browser/chrome_content_browser_manifest_overlay.json index 8ff6293..e57fe577 100644 --- a/chrome/browser/chrome_content_browser_manifest_overlay.json +++ b/chrome/browser/chrome_content_browser_manifest_overlay.json
@@ -39,11 +39,11 @@ "blink::mojom::InstalledAppProvider", "blink::mojom::ShareService", "bluetooth::mojom::AdapterFactory", - "chrome::mojom::PrerenderCanceler", "chrome::mojom::OpenSearchDocumentDescriptionHandler", - "device::usb::ChooserService", - "device::usb::DeviceManager", + "chrome::mojom::PrerenderCanceler", "contextual_search::mojom::ContextualSearchJsApiService", + "device::mojom::UsbChooserService", + "device::mojom::UsbDeviceManager", "dom_distiller::mojom::DistillabilityService", "dom_distiller::mojom::DistillerJavaScriptService", "extensions::KeepAlive",
diff --git a/chrome/browser/chrome_navigation_browsertest.cc b/chrome/browser/chrome_navigation_browsertest.cc index 0d243913..f12f6f06 100644 --- a/chrome/browser/chrome_navigation_browsertest.cc +++ b/chrome/browser/chrome_navigation_browsertest.cc
@@ -257,3 +257,57 @@ // prepended and one less ":" character after the host. EXPECT_EQ(GURL(), new_web_contents->GetLastCommittedURL()); } + +// A test performing two simultaneous navigations, to ensure code in chrome/, +// such as tab helpers, can handle those cases. +// This test starts a browser-initiated cross-process navigation, which is +// delayed. At the same time, the renderer does a synchronous navigation +// through pushState, which will create a separate navigation and associated +// NavigationHandle. Afterwards, the original cross-process navigation is +// resumed and confirmed to properly commit. +IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, + SlowCrossProcessNavigationWithPushState) { + const GURL kURL1 = embedded_test_server()->GetURL("/title1.html"); + const GURL kPushStateURL = + embedded_test_server()->GetURL("/title1.html#fragment"); + const GURL kURL2 = embedded_test_server()->GetURL("/title2.html"); + + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + // Navigate to the initial page. + ui_test_utils::NavigateToURL(browser(), kURL1); + + // Start navigating to the second page. + content::TestNavigationManager manager(web_contents, kURL2); + content::NavigationHandleCommitObserver navigation_observer(web_contents, + kURL2); + web_contents->GetController().LoadURL( + kURL2, content::Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); + EXPECT_TRUE(manager.WaitForRequestStart()); + + // The current page does a PushState. + content::NavigationHandleCommitObserver push_state_observer(web_contents, + kPushStateURL); + std::string push_state = + "history.pushState({}, \"title 1\", \"" + kPushStateURL.spec() + "\");"; + EXPECT_TRUE(ExecuteScript(web_contents, push_state)); + content::NavigationEntry* last_committed = + web_contents->GetController().GetLastCommittedEntry(); + EXPECT_TRUE(last_committed); + EXPECT_EQ(kPushStateURL, last_committed->GetURL()); + + EXPECT_TRUE(push_state_observer.has_committed()); + EXPECT_TRUE(push_state_observer.was_same_document()); + EXPECT_TRUE(push_state_observer.was_renderer_initiated()); + + // Let the navigation finish. It should commit successfully. + manager.WaitForNavigationFinished(); + last_committed = web_contents->GetController().GetLastCommittedEntry(); + EXPECT_TRUE(last_committed); + EXPECT_EQ(kURL2, last_committed->GetURL()); + + EXPECT_TRUE(navigation_observer.has_committed()); + EXPECT_FALSE(navigation_observer.was_same_document()); + EXPECT_FALSE(navigation_observer.was_renderer_initiated()); +}
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 65cbb34..b96f9ba 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1211,8 +1211,6 @@ "power/idle_action_warning_dialog_view.h", "power/idle_action_warning_observer.cc", "power/idle_action_warning_observer.h", - "power/login_lock_state_notifier.cc", - "power/login_lock_state_notifier.h", "power/peripheral_battery_observer.cc", "power/peripheral_battery_observer.h", "power/power_data_collector.cc",
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 802f259..87eafaca 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -76,7 +76,6 @@ #include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/power/freezer_cgroup_process_manager.h" #include "chrome/browser/chromeos/power/idle_action_warning_observer.h" -#include "chrome/browser/chromeos/power/login_lock_state_notifier.h" #include "chrome/browser/chromeos/power/peripheral_battery_observer.h" #include "chrome/browser/chromeos/power/power_data_collector.h" #include "chrome/browser/chromeos/power/power_prefs.h" @@ -830,9 +829,6 @@ // These are dependent on the ash::Shell singleton already having been // initialized. Consequently, these cannot be used when running as a mus // client. - // TODO(oshima): Remove ash dependency in LoginLockStateNotifier. - // crbug.com/408832. - login_lock_state_notifier_.reset(new LoginLockStateNotifier); data_promo_notification_.reset(new DataPromoNotification()); // TODO(mash): Support EventRewriterController; see crbug.com/647781 @@ -920,7 +916,6 @@ #endif // Detach D-Bus clients before DBusThreadManager is shut down. - login_lock_state_notifier_.reset(); idle_action_warning_observer_.reset(); if (!ash_util::IsRunningInMash())
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.h b/chrome/browser/chromeos/chrome_browser_main_chromeos.h index 7f65e8bf..3af4f647 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.h +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
@@ -30,7 +30,6 @@ class EventRewriterDelegateImpl; class ExtensionVolumeObserver; class IdleActionWarningObserver; -class LoginLockStateNotifier; class LowDiskNotification; class NetworkPrefStateObserver; class NetworkThrottlingObserver; @@ -75,7 +74,6 @@ std::unique_ptr<ExtensionVolumeObserver> extension_volume_observer_; std::unique_ptr<PeripheralBatteryObserver> peripheral_battery_observer_; std::unique_ptr<PowerPrefs> power_prefs_; - std::unique_ptr<LoginLockStateNotifier> login_lock_state_notifier_; std::unique_ptr<IdleActionWarningObserver> idle_action_warning_observer_; std::unique_ptr<DataPromoNotification> data_promo_notification_; std::unique_ptr<RendererFreezer> renderer_freezer_;
diff --git a/chrome/browser/chromeos/power/login_lock_state_notifier.cc b/chrome/browser/chromeos/power/login_lock_state_notifier.cc deleted file mode 100644 index 0c47a5c..0000000 --- a/chrome/browser/chromeos/power/login_lock_state_notifier.cc +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chromeos/power/login_lock_state_notifier.h" - -#include "ash/shell.h" -#include "base/logging.h" -#include "chrome/browser/chrome_notification_types.h" -#include "content/public/browser/notification_service.h" - -namespace ash { -class LockStateControllerDelegate; -} - -namespace chromeos { - -LoginLockStateNotifier::LoginLockStateNotifier() { - registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, - content::NotificationService::AllSources()); -} - -LoginLockStateNotifier::~LoginLockStateNotifier() {} - -void LoginLockStateNotifier::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - switch (type) { - case chrome::NOTIFICATION_APP_TERMINATING: - ash::Shell::Get()->OnAppTerminating(); - break; - default: - NOTREACHED() << "Unexpected notification " << type; - } -} - -} // namespace chromeos
diff --git a/chrome/browser/chromeos/power/login_lock_state_notifier.h b/chrome/browser/chromeos/power/login_lock_state_notifier.h deleted file mode 100644 index 21f3ed1..0000000 --- a/chrome/browser/chromeos/power/login_lock_state_notifier.h +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_CHROMEOS_POWER_LOGIN_LOCK_STATE_NOTIFIER_H_ -#define CHROME_BROWSER_CHROMEOS_POWER_LOGIN_LOCK_STATE_NOTIFIER_H_ - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" - -namespace chromeos { - -// Listens for login and screen lock events and passes them to -// the Aura shell's PowerButtonController class. -class LoginLockStateNotifier : public content::NotificationObserver { - public: - // This class registers/unregisters itself as an observer in ctor/dtor. - LoginLockStateNotifier(); - ~LoginLockStateNotifier() override; - - private: - // content::NotificationObserver implementation: - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; - - content::NotificationRegistrar registrar_; - - DISALLOW_COPY_AND_ASSIGN(LoginLockStateNotifier); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_POWER_LOGIN_LOCK_STATE_NOTIFIER_H_
diff --git a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc index 547e31e..f884de4 100644 --- a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc +++ b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc
@@ -1641,7 +1641,12 @@ EXPECT_TRUE(IsTapDraggingMenuShownOnDetailMenu()); CloseDetailMenu(); - SetLoginStatus(ash::LoginStatus::USER); + // Simulate login. + session_manager::SessionManager::Get()->CreateSession( + AccountId::FromUserEmail("owner@invalid.domain"), "owner@invalid.domain"); + session_manager::SessionManager::Get()->SessionStarted(); + // Flush to ensure the session state reaches ash and updates login status. + SessionControllerClient::FlushForTesting(); EXPECT_TRUE(CreateDetailedMenu()); EXPECT_TRUE(IsSpokenFeedbackMenuShownOnDetailMenu()); EXPECT_TRUE(IsHighContrastMenuShownOnDetailMenu()); @@ -1659,7 +1664,11 @@ EXPECT_TRUE(IsTapDraggingMenuShownOnDetailMenu()); CloseDetailMenu(); - SetLoginStatus(ash::LoginStatus::LOCKED); + // Simulate screen lock. + session_manager::SessionManager::Get()->SetSessionState( + session_manager::SessionState::LOCKED); + // Flush to ensure the session state reaches ash and updates login status. + SessionControllerClient::FlushForTesting(); EXPECT_TRUE(CreateDetailedMenu()); EXPECT_TRUE(IsSpokenFeedbackMenuShownOnDetailMenu()); EXPECT_TRUE(IsHighContrastMenuShownOnDetailMenu()); @@ -1677,11 +1686,11 @@ EXPECT_TRUE(IsTapDraggingMenuShownOnDetailMenu()); CloseDetailMenu(); + // Simulate adding multiprofile user. session_manager::SessionManager::Get()->SetSessionState( session_manager::SessionState::LOGIN_SECONDARY); // Flush to ensure the session state reaches ash and updates login status. SessionControllerClient::FlushForTesting(); - SetLoginStatus(ash::LoginStatus::USER); EXPECT_TRUE(CreateDetailedMenu()); EXPECT_TRUE(IsSpokenFeedbackMenuShownOnDetailMenu()); EXPECT_TRUE(IsHighContrastMenuShownOnDetailMenu());
diff --git a/chrome/browser/google/google_update_win.cc b/chrome/browser/google/google_update_win.cc index d965613c..2a2ca13b 100644 --- a/chrome/browser/google/google_update_win.cc +++ b/chrome/browser/google/google_update_win.cc
@@ -193,7 +193,7 @@ if (FAILED(hresult)) return hresult; - ConfigureProxyBlanket(class_factory.get()); + ConfigureProxyBlanket(class_factory.Get()); return class_factory->CreateInstance(nullptr, IID_PPV_ARGS(google_update)); } @@ -515,7 +515,7 @@ return hresult; } - ConfigureProxyBlanket(google_update_.get()); + ConfigureProxyBlanket(google_update_.Get()); } // The class was created, so all subsequent errors are reported as: @@ -533,7 +533,7 @@ return hresult; dispatch.Reset(); - ConfigureProxyBlanket(app_bundle.get()); + ConfigureProxyBlanket(app_bundle.Get()); if (!locale_.empty()) { // Ignore the result of this since, while setting the display language is @@ -578,7 +578,7 @@ hresult = dispatch.QueryInterface(app.Receive()); if (FAILED(hresult)) return hresult; - ConfigureProxyBlanket(app.get()); + ConfigureProxyBlanket(app.Get()); hresult = app_bundle->checkForUpdate(); if (FAILED(hresult)) return hresult; @@ -600,7 +600,7 @@ *hresult = dispatch.QueryInterface(current_state->Receive()); if (FAILED(*hresult)) return false; - ConfigureProxyBlanket(current_state->get()); + ConfigureProxyBlanket(current_state->Get()); LONG value = 0; *hresult = (*current_state)->get_stateValue(&value); if (FAILED(*hresult))
diff --git a/chrome/browser/importer/ie_importer_browsertest_win.cc b/chrome/browser/importer/ie_importer_browsertest_win.cc index 8907b98..e306a43 100644 --- a/chrome/browser/importer/ie_importer_browsertest_win.cc +++ b/chrome/browser/importer/ie_importer_browsertest_win.cc
@@ -174,7 +174,7 @@ if (FAILED(result)) return false; base::win::ScopedComPtr<IPersistFile> persist_file; - result = persist_file.QueryFrom(locator.get()); + result = persist_file.QueryFrom(locator.Get()); if (FAILED(result)) return false; result = locator->SetURL(url.c_str(), 0); @@ -184,7 +184,7 @@ // Write favicon url if specified. if (!favicon_url.empty()) { base::win::ScopedComPtr<IPropertySetStorage> property_set_storage; - if (FAILED(property_set_storage.QueryFrom(locator.get()))) + if (FAILED(property_set_storage.QueryFrom(locator.Get()))) return false; base::win::ScopedComPtr<IPropertyStorage> property_storage; if (FAILED(property_set_storage->Open(FMTID_Intshcut,
diff --git a/chrome/browser/io_thread_unittest.cc b/chrome/browser/io_thread_unittest.cc index a3b88eb..8ac33d2 100644 --- a/chrome/browser/io_thread_unittest.cc +++ b/chrome/browser/io_thread_unittest.cc
@@ -299,7 +299,6 @@ variations::testing::ClearAllVariationParams(); std::map<std::string, std::string> field_trial_params; - field_trial_params["disable_delay_tcp_race"] = "true"; variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params); base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); @@ -308,7 +307,6 @@ ConfigureParamsFromFieldTrialsAndCommandLine(); EXPECT_FALSE(params_.enable_quic); - EXPECT_TRUE(params_.quic_delay_tcp_race); } TEST_F(ConfigureParamsFromFieldTrialsAndCommandLineTest,
diff --git a/chrome/browser/media/webrtc/media_stream_devices_controller.cc b/chrome/browser/media/webrtc/media_stream_devices_controller.cc index 52b81f1..a063d9b 100644 --- a/chrome/browser/media/webrtc/media_stream_devices_controller.cc +++ b/chrome/browser/media/webrtc/media_stream_devices_controller.cc
@@ -82,42 +82,26 @@ const GURL&, Profile*)>; -void RecordSinglePermissionAction(const content::MediaStreamRequest& request, - ContentSettingsType content_type, - Profile* profile, - PermissionActionCallback callback) { - if (ContentTypeIsRequested(content_type, request)) { - // TODO(stefanocs): Pass the actual |gesture_type| once this file has been - // refactored into PermissionContext. - callback.Run(content_type, PermissionRequestGestureType::UNKNOWN, - request.security_origin, profile); +// Calls |action_callback| for each permission requested. +void RecordPermissionAction(bool is_asking_for_audio, + bool is_asking_for_video, + const GURL& security_origin, + Profile* profile, + PermissionActionCallback action_callback) { + // TODO(stefanocs): Pass the actual |gesture_type| once this file has been + // refactored into PermissionContext. + if (is_asking_for_audio) { + action_callback.Run(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, + PermissionRequestGestureType::UNKNOWN, security_origin, + profile); + } + if (is_asking_for_video) { + action_callback.Run(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, + PermissionRequestGestureType::UNKNOWN, security_origin, + profile); } } -// Calls |action_function| for each permission requested by |request|. -void RecordPermissionAction(const content::MediaStreamRequest& request, - Profile* profile, - PermissionActionCallback callback) { - RecordSinglePermissionAction(request, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, - profile, callback); - RecordSinglePermissionAction( - request, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, profile, callback); -} - -#if defined(OS_ANDROID) -// Callback for the permission update infobar when the site and Chrome -// permissions are mismatched on Android. -void OnPermissionConflictResolved( - std::unique_ptr<MediaStreamDevicesController> controller, - bool allowed) { - if (allowed) - controller->PermissionGranted(); - else - controller->ForcePermissionDeniedTemporarily(); -} - -#endif // defined(OS_ANDROID) - // This helper class helps to measure the number of media stream requests that // occur. It ensures that only one request will be recorded per navigation, per // frame. TODO(raymes): Remove this when https://crbug.com/526324 is fixed. @@ -254,7 +238,8 @@ MediaStreamDevicesController::~MediaStreamDevicesController() { if (!callback_.is_null()) { - RecordPermissionAction(request_, profile_, + RecordPermissionAction(IsAskingForAudio(), IsAskingForVideo(), GetOrigin(), + profile_, base::Bind(PermissionUmaUtil::PermissionIgnored)); callback_.Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN, @@ -282,15 +267,28 @@ GetOrigin(), url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)); } -void MediaStreamDevicesController::ForcePermissionDeniedTemporarily() { - set_persist(false); - // TODO(tsergeant): Determine whether it is appropriate to record permission - // action metrics here, as this is a different sort of user action. - RunCallback(CONTENT_SETTING_BLOCK, - CONTENT_SETTING_BLOCK, +#if defined(OS_ANDROID) +void MediaStreamDevicesController::AndroidOSPromptAnswered(bool allowed) { + DCHECK(old_audio_setting_ != CONTENT_SETTING_ASK && + old_video_setting_ != CONTENT_SETTING_ASK); + + ContentSetting audio_setting = old_audio_setting_; + ContentSetting video_setting = old_video_setting_; + + if (!allowed) { + // Only permissions that were previously ALLOW for a site will have had + // their android permissions requested. It's only in that case that we need + // to change the setting to BLOCK to reflect that it wasn't allowed. + if (audio_setting == CONTENT_SETTING_ALLOW) + audio_setting = CONTENT_SETTING_BLOCK; + if (video_setting == CONTENT_SETTING_ALLOW) + video_setting = CONTENT_SETTING_BLOCK; + } + + RunCallback(audio_setting, video_setting, content::MEDIA_DEVICE_PERMISSION_DENIED); - set_persist(true); } +#endif // defined(OS_ANDROID) PermissionRequest::IconId MediaStreamDevicesController::GetIconId() const { #if defined(OS_ANDROID) @@ -315,7 +313,8 @@ } void MediaStreamDevicesController::PermissionGranted() { - RecordPermissionAction(request_, profile_, + RecordPermissionAction(IsAskingForAudio(), IsAskingForVideo(), GetOrigin(), + profile_, base::Bind(PermissionUmaUtil::PermissionGranted)); RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, old_audio_setting_, CONTENT_SETTING_ALLOW), @@ -325,7 +324,8 @@ } void MediaStreamDevicesController::PermissionDenied() { - RecordPermissionAction(request_, profile_, + RecordPermissionAction(IsAskingForAudio(), IsAskingForVideo(), GetOrigin(), + profile_, base::Bind(PermissionUmaUtil::PermissionDenied)); RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, old_audio_setting_, CONTENT_SETTING_BLOCK), @@ -339,7 +339,8 @@ } void MediaStreamDevicesController::Cancelled() { - RecordPermissionAction(request_, profile_, + RecordPermissionAction(IsAskingForAudio(), IsAskingForVideo(), GetOrigin(), + profile_, base::Bind(PermissionUmaUtil::PermissionDismissed)); RunCallback(old_audio_setting_, old_video_setting_, content::MEDIA_DEVICE_PERMISSION_DISMISSED); @@ -389,7 +390,8 @@ web_contents, content_settings_types)) { PermissionUpdateInfoBarDelegate::Create( web_contents, content_settings_types, - base::Bind(&OnPermissionConflictResolved, base::Passed(&controller))); + base::Bind(&MediaStreamDevicesController::AndroidOSPromptAnswered, + base::Passed(&controller))); } #endif return;
diff --git a/chrome/browser/media/webrtc/media_stream_devices_controller.h b/chrome/browser/media/webrtc/media_stream_devices_controller.h index f8246e8..acd6b4c6 100644 --- a/chrome/browser/media/webrtc/media_stream_devices_controller.h +++ b/chrome/browser/media/webrtc/media_stream_devices_controller.h
@@ -59,14 +59,10 @@ bool IsAskingForVideo() const; base::string16 GetMessageText() const; - // Forces the permissions to be denied (without being persisted) regardless - // of what the previous state was. If the user had previously allowed the - // site video or audio access, this ignores that and informs the site it was - // denied. - // - // This differs from PermissionGranted/PermissionDenied as they only operate - // on the permissions if they are in the ASK state. - void ForcePermissionDeniedTemporarily(); +#if defined(OS_ANDROID) + // Called when the Android OS-level prompt is answered. + void AndroidOSPromptAnswered(bool allowed); +#endif // defined(OS_ANDROID) bool ShouldShowPersistenceToggle() const override;
diff --git a/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.cc b/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.cc index 338ffe0..2e6bca4a 100644 --- a/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.cc +++ b/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.cc
@@ -141,10 +141,10 @@ DCHECK(!registered_device_path.empty()); base::win::ScopedComPtr<IPortableDevice> device = media_transfer_protocol::OpenDevice(pnp_device_id); - bool init_succeeded = device.get() != NULL; + bool init_succeeded = device.Get() != NULL; if (init_succeeded) { PortableDeviceMapService::GetInstance()->AddPortableDevice( - registered_device_path, device.get()); + registered_device_path, device.Get()); } return init_succeeded; } @@ -266,7 +266,7 @@ DCHECK(file_info.size == 0 || optimal_transfer_size > 0U); file_details->set_file_info(file_info); - file_details->set_device_file_stream(file_stream.get()); + file_details->set_device_file_stream(file_stream.Get()); file_details->set_optimal_transfer_size(optimal_transfer_size); return error; }
diff --git a/chrome/browser/media_galleries/win/mtp_device_operations_util.cc b/chrome/browser/media_galleries/win/mtp_device_operations_util.cc index 4f5c49e..2bc9cd8 100644 --- a/chrome/browser/media_galleries/win/mtp_device_operations_util.cc +++ b/chrome/browser/media_galleries/win/mtp_device_operations_util.cc
@@ -75,7 +75,7 @@ DCHECK(!parent_id.empty()); base::win::ScopedComPtr<IPortableDeviceContent> content = GetDeviceContent(device); - if (!content.get()) + if (!content.Get()) return base::win::ScopedComPtr<IEnumPortableDeviceObjectIDs>(); base::win::ScopedComPtr<IEnumPortableDeviceObjectIDs> enum_object_ids; @@ -182,7 +182,7 @@ DCHECK(last_modified_time); base::win::ScopedComPtr<IPortableDeviceContent> content = GetDeviceContent(device); - if (!content.get()) + if (!content.Get()) return false; base::win::ScopedComPtr<IPortableDeviceProperties> properties; @@ -208,13 +208,13 @@ base::win::ScopedComPtr<IPortableDeviceValues> properties_values; hr = properties->GetValues(object_id.c_str(), - properties_to_read.get(), + properties_to_read.Get(), properties_values.Receive()); if (FAILED(hr)) return false; - *is_directory = IsDirectory(properties_values.get()); - *name = GetObjectName(properties_values.get()); + *is_directory = IsDirectory(properties_values.Get()); + *name = GetObjectName(properties_values.Get()); if (name->empty()) return false; @@ -227,9 +227,9 @@ } // Try to get the last modified time, but don't fail if we can't. - GetLastModifiedTime(properties_values.get(), last_modified_time); + GetLastModifiedTime(properties_values.Get(), last_modified_time); - int64_t object_size = GetObjectSize(properties_values.get()); + int64_t object_size = GetObjectSize(properties_values.Get()); if (object_size < 0) return false; *size = object_size; @@ -270,7 +270,7 @@ DCHECK(object_entries); base::win::ScopedComPtr<IEnumPortableDeviceObjectIDs> enum_object_ids = GetDeviceObjectEnumerator(device, directory_object_id); - if (!enum_object_ids.get()) + if (!enum_object_ids.Get()) return false; // Loop calling Next() while S_OK is being returned. @@ -316,7 +316,7 @@ if (FAILED(hr)) return base::win::ScopedComPtr<IPortableDevice>(); - hr = device->Open(pnp_device_id.c_str(), client_info.get()); + hr = device->Open(pnp_device_id.c_str(), client_info.Get()); if (SUCCEEDED(hr)) return device; if (hr == E_ACCESSDENIED) @@ -360,7 +360,7 @@ DCHECK(!file_object_id.empty()); base::win::ScopedComPtr<IPortableDeviceContent> content = GetDeviceContent(device); - if (!content.get()) + if (!content.Get()) return E_FAIL; base::win::ScopedComPtr<IPortableDeviceResources> resources;
diff --git a/chrome/browser/media_galleries/win/portable_device_map_service.cc b/chrome/browser/media_galleries/win/portable_device_map_service.cc index a2012ffc..612c5769 100644 --- a/chrome/browser/media_galleries/win/portable_device_map_service.cc +++ b/chrome/browser/media_galleries/win/portable_device_map_service.cc
@@ -58,7 +58,7 @@ base::AutoLock lock(lock_); PortableDeviceMap::const_iterator it = device_map_.find(device_location); return (it == device_map_.end() || it->second.scheduled_to_delete) ? - NULL : it->second.portable_device.get(); + NULL : it->second.portable_device.Get(); } PortableDeviceMapService::PortableDeviceInfo::PortableDeviceInfo()
diff --git a/chrome/browser/media_galleries/win/snapshot_file_details.h b/chrome/browser/media_galleries/win/snapshot_file_details.h index a46d0b6..6325938 100644 --- a/chrome/browser/media_galleries/win/snapshot_file_details.h +++ b/chrome/browser/media_galleries/win/snapshot_file_details.h
@@ -55,7 +55,7 @@ } IStream* device_file_stream() const { - return file_stream_.get(); + return file_stream_.Get(); } DWORD optimal_transfer_size() const {
diff --git a/chrome/browser/metrics/antivirus_metrics_provider_win.cc b/chrome/browser/metrics/antivirus_metrics_provider_win.cc index d935a14..ba039156 100644 --- a/chrome/browser/metrics/antivirus_metrics_provider_win.cc +++ b/chrome/browser/metrics/antivirus_metrics_provider_win.cc
@@ -350,7 +350,7 @@ if (FAILED(hr)) return RESULT_FAILED_TO_CONNECT_TO_WMI; - hr = ::CoSetProxyBlanket(wmi_services.get(), RPC_C_AUTHN_WINNT, + hr = ::CoSetProxyBlanket(wmi_services.Get(), RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE); if (FAILED(hr))
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc index 2c20891f..2c1ac16 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -479,7 +479,13 @@ histogram_tester_.ExpectTotalCount(internal::kHistogramDocWriteBlockCount, 0); } -IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, BadXhtml) { +// TODO(crbug.com/712935): Flaky on Linux dbg. +#if defined(OS_LINUX) && !defined(NDEBUG) +#define MAYBE_BadXhtml DISABLED_BadXhtml +#else +#define MAYBE_BadXhtml BadXhtml +#endif +IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, MAYBE_BadXhtml) { ASSERT_TRUE(embedded_test_server()->Start()); scoped_refptr<TimingUpdatedObserver> timing_observer =
diff --git a/chrome/browser/permissions/permission_manager.cc b/chrome/browser/permissions/permission_manager.cc index 19f9eb7..8d39d206 100644 --- a/chrome/browser/permissions/permission_manager.cc +++ b/chrome/browser/permissions/permission_manager.cc
@@ -391,6 +391,9 @@ int permission_id, ContentSetting content_setting) { PendingRequest* pending_request = pending_requests_.Lookup(request_id); + if (!pending_request) + return; + pending_request->SetContentSetting(permission_id, content_setting); if (!pending_request->IsComplete())
diff --git a/chrome/browser/resources/settings/internet_page/network_summary.js b/chrome/browser/resources/settings/internet_page/network_summary.js index 15e42bd..b2e8852 100644 --- a/chrome/browser/resources/settings/internet_page/network_summary.js +++ b/chrome/browser/resources/settings/internet_page/network_summary.js
@@ -55,25 +55,33 @@ networkingPrivate: Object, /** - * The device state for each network device type. + * The device state for each network device type. We initialize this to + * include a disabled WiFi type since WiFi is always present. This reduces + * the amount of visual change on first load. * @private {DeviceStateObject} */ deviceStates: { type: Object, value: function() { - return {}; + return { + WiFi: { + Type: chrome.networkingPrivate.NetworkType.WI_FI, + State: chrome.networkingPrivate.DeviceStateType.DISABLED + }, + }; }, notify: true, }, /** - * Array of active network states, one per device type. + * Array of active network states, one per device type. Initialized to + * include a default WiFi state (see deviceStates comment). * @private {!Array<!CrOnc.NetworkStateProperties>} */ activeNetworkStates_: { type: Array, value: function() { - return []; + return [{GUID: '', Type: chrome.networkingPrivate.NetworkType.WI_FI}]; }, }, @@ -84,7 +92,7 @@ networkStateLists_: { type: Object, value: function() { - return {}; + return {WiFi: []}; }, }, },
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc index 46853b8..6661fce 100644 --- a/chrome/browser/shell_integration_win.cc +++ b/chrome/browser/shell_integration_win.cc
@@ -784,7 +784,7 @@ base::win::ScopedComPtr<IPersistFile> persist_file; if (FAILED(shell_link.CreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER)) || - FAILED(persist_file.QueryFrom(shell_link.get())) || + FAILED(persist_file.QueryFrom(shell_link.Get())) || FAILED(persist_file->Load(shortcut.value().c_str(), STGM_READ))) { DLOG(WARNING) << "Failed loading shortcut at " << shortcut.value(); continue; @@ -797,7 +797,7 @@ // Validate the existing app id for the shortcut. base::win::ScopedComPtr<IPropertyStore> property_store; propvariant.Reset(); - if (FAILED(property_store.QueryFrom(shell_link.get())) || + if (FAILED(property_store.QueryFrom(shell_link.Get())) || property_store->GetValue(PKEY_AppUserModel_ID, propvariant.Receive()) != S_OK) { // When in doubt, prefer not updating the shortcut.
diff --git a/chrome/browser/speech/tts_win.cc b/chrome/browser/speech/tts_win.cc index de559b1..828a5e11 100644 --- a/chrome/browser/speech/tts_win.cc +++ b/chrome/browser/speech/tts_win.cc
@@ -93,7 +93,7 @@ std::wstring prefix; std::wstring suffix; - if (!speech_synthesizer_.get()) + if (!speech_synthesizer_.Get()) return false; SetVoiceFromName(voice.name); @@ -138,7 +138,7 @@ } bool TtsPlatformImplWin::StopSpeaking() { - if (speech_synthesizer_.get()) { + if (speech_synthesizer_.Get()) { // Clear the stream number so that any further events relating to this // utterance are ignored. stream_number_ = 0; @@ -156,7 +156,7 @@ } void TtsPlatformImplWin::Pause() { - if (speech_synthesizer_.get() && utterance_id_ && !paused_) { + if (speech_synthesizer_.Get() && utterance_id_ && !paused_) { speech_synthesizer_->Pause(); paused_ = true; TtsController::GetInstance()->OnTtsEvent( @@ -165,7 +165,7 @@ } void TtsPlatformImplWin::Resume() { - if (speech_synthesizer_.get() && utterance_id_ && paused_) { + if (speech_synthesizer_.Get() && utterance_id_ && paused_) { speech_synthesizer_->Resume(); paused_ = false; TtsController::GetInstance()->OnTtsEvent( @@ -174,7 +174,7 @@ } bool TtsPlatformImplWin::IsSpeaking() { - if (speech_synthesizer_.get()) { + if (speech_synthesizer_.Get()) { SPVOICESTATUS status; HRESULT result = speech_synthesizer_->GetStatus(&status, NULL); if (result == S_OK) { @@ -204,7 +204,7 @@ return; base::win::ScopedCoMem<WCHAR> description; - if (S_OK != SpGetDescription(voice_token.get(), &description)) + if (S_OK != SpGetDescription(voice_token.Get(), &description)) continue; voice.name = base::WideToUTF8(description.get()); @@ -300,10 +300,10 @@ return; base::win::ScopedCoMem<WCHAR> description; - if (S_OK != SpGetDescription(voice_token.get(), &description)) + if (S_OK != SpGetDescription(voice_token.Get(), &description)) continue; if (name == base::WideToUTF8(description.get())) { - speech_synthesizer_->SetVoice(voice_token.get()); + speech_synthesizer_->SetVoice(voice_token.Get()); break; } } @@ -316,7 +316,7 @@ char_position_(0), paused_(false) { speech_synthesizer_.CreateInstance(CLSID_SpVoice); - if (speech_synthesizer_.get()) { + if (speech_synthesizer_.Get()) { ULONGLONG event_mask = SPFEI(SPEI_START_INPUT_STREAM) | SPFEI(SPEI_TTS_BOOKMARK) |
diff --git a/chrome/browser/sync_file_system/local/syncable_file_system_unittest.cc b/chrome/browser/sync_file_system/local/syncable_file_system_unittest.cc index d85f4b3..bee39ec 100644 --- a/chrome/browser/sync_file_system/local/syncable_file_system_unittest.cc +++ b/chrome/browser/sync_file_system/local/syncable_file_system_unittest.cc
@@ -12,13 +12,13 @@ #include "chrome/browser/sync_file_system/local/local_file_sync_context.h" #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h" #include "chrome/browser/sync_file_system/syncable_file_system_util.h" -#include "content/public/test/sandbox_file_system_test_helper.h" #include "content/public/test/test_browser_thread_bundle.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/isolated_context.h" #include "storage/browser/quota/quota_manager.h" #include "storage/browser/test/async_file_test_helper.h" +#include "storage/browser/test/sandbox_file_system_test_helper.h" #include "storage/common/fileapi/file_system_types.h" #include "storage/common/quota/quota_types.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 403f89c..27230ce 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3289,6 +3289,8 @@ "app_list/search/webstore/webstore_provider.h", "app_list/search/webstore/webstore_result.cc", "app_list/search/webstore/webstore_result.h", + "app_list/search_answer_web_contents_delegate.cc", + "app_list/search_answer_web_contents_delegate.h", "app_list/speech_auth_helper.cc", "app_list/speech_auth_helper.h", "app_list/speech_recognizer.cc",
diff --git a/chrome/browser/ui/android/usb_chooser_dialog_android.cc b/chrome/browser/ui/android/usb_chooser_dialog_android.cc index b462ca3..b3f088a1 100644 --- a/chrome/browser/ui/android/usb_chooser_dialog_android.cc +++ b/chrome/browser/ui/android/usb_chooser_dialog_android.cc
@@ -38,11 +38,11 @@ void OnDevicePermissionRequestComplete( scoped_refptr<UsbDevice> device, - const device::usb::ChooserService::GetPermissionCallback& callback, + const device::mojom::UsbChooserService::GetPermissionCallback& callback, bool granted) { - device::usb::DeviceInfoPtr device_info; + device::mojom::UsbDeviceInfoPtr device_info; if (granted) - device_info = device::usb::DeviceInfo::From(*device); + device_info = device::mojom::UsbDeviceInfo::From(*device); callback.Run(std::move(device_info)); } @@ -51,7 +51,7 @@ UsbChooserDialogAndroid::UsbChooserDialogAndroid( const std::vector<device::UsbDeviceFilter>& filters, content::RenderFrameHost* render_frame_host, - const device::usb::ChooserService::GetPermissionCallback& callback) + const device::mojom::UsbChooserService::GetPermissionCallback& callback) : render_frame_host_(render_frame_host), callback_(callback), usb_service_observer_(this),
diff --git a/chrome/browser/ui/android/usb_chooser_dialog_android.h b/chrome/browser/ui/android/usb_chooser_dialog_android.h index cda1e176..318d835 100644 --- a/chrome/browser/ui/android/usb_chooser_dialog_android.h +++ b/chrome/browser/ui/android/usb_chooser_dialog_android.h
@@ -33,7 +33,7 @@ UsbChooserDialogAndroid( const std::vector<device::UsbDeviceFilter>& filters, content::RenderFrameHost* render_frame_host, - const device::usb::ChooserService::GetPermissionCallback& callback); + const device::mojom::UsbChooserService::GetPermissionCallback& callback); ~UsbChooserDialogAndroid() override; // device::UsbService::Observer: @@ -71,7 +71,7 @@ bool DisplayDevice(scoped_refptr<device::UsbDevice> device) const; content::RenderFrameHost* const render_frame_host_; - device::usb::ChooserService::GetPermissionCallback callback_; + device::mojom::UsbChooserService::GetPermissionCallback callback_; ScopedObserver<device::UsbService, device::UsbService::Observer> usb_service_observer_; std::vector<device::UsbDeviceFilter> filters_;
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc index 2efce5c..00f6630 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.cc +++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -24,6 +24,7 @@ #include "chrome/browser/ui/app_list/launcher_page_event_dispatcher.h" #include "chrome/browser/ui/app_list/search/search_controller_factory.h" #include "chrome/browser/ui/app_list/search/search_resource_manager.h" +#include "chrome/browser/ui/app_list/search_answer_web_contents_delegate.h" #include "chrome/browser/ui/app_list/start_page_service.h" #include "chrome/browser/ui/apps/chrome_app_delegate.h" #include "chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h" @@ -154,6 +155,7 @@ start_page_service->RemoveObserver(this); app_sync_ui_state_watcher_.reset(); model_ = NULL; + search_answer_delegate_.reset(); } template_url_service_observer_.RemoveAll(); @@ -187,6 +189,10 @@ app_sync_ui_state_watcher_.reset( new AppSyncUIStateWatcher(profile_, model_)); + search_answer_delegate_ = + base::MakeUnique<app_list::SearchAnswerWebContentsDelegate>(profile_, + model_); + SetUpSearchUI(); SetUpCustomLauncherPages(); OnTemplateURLServiceChanged(); @@ -274,6 +280,8 @@ search_controller_->Start(is_voice_query_); controller_->OnSearchStarted(); } + if (search_answer_delegate_) + search_answer_delegate_->Update(); } void AppListViewDelegate::StopSearch() { @@ -492,6 +500,10 @@ return web_views; } +views::View* AppListViewDelegate::GetSearchAnswerWebView() { + return search_answer_delegate_->web_view(); +} + void AppListViewDelegate::CustomLauncherPageAnimationChanged(double progress) { if (launcher_page_event_dispatcher_) launcher_page_event_dispatcher_->ProgressChanged(progress); @@ -519,6 +531,7 @@ SEARCH_ENGINE_GOOGLE; model_->SetSearchEngineIsGoogle(is_google); + search_answer_delegate_->Update(); app_list::StartPageService* start_page_service = app_list::StartPageService::Get(profile_);
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.h b/chrome/browser/ui/app_list/app_list_view_delegate.h index e7d0d9c..5dcdad3 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.h +++ b/chrome/browser/ui/app_list/app_list_view_delegate.h
@@ -26,6 +26,7 @@ namespace app_list { class CustomLauncherPageContents; class LauncherPageEventDispatcher; +class SearchAnswerWebContentsDelegate; class SearchController; class SearchResourceManager; class SpeechUIModel; @@ -79,6 +80,7 @@ views::View* CreateStartPageWebView(const gfx::Size& size) override; std::vector<views::View*> CreateCustomPageWebViews( const gfx::Size& size) override; + views::View* GetSearchAnswerWebView() override; void CustomLauncherPageAnimationChanged(double progress) override; void CustomLauncherPagePopSubpage() override; bool IsSpeechRecognitionEnabled() override; @@ -144,6 +146,9 @@ // Registers for NOTIFICATION_APP_TERMINATING to unload custom launcher pages. content::NotificationRegistrar registrar_; + std::unique_ptr<app_list::SearchAnswerWebContentsDelegate> + search_answer_delegate_; + DISALLOW_COPY_AND_ASSIGN(AppListViewDelegate); };
diff --git a/chrome/browser/ui/app_list/search_answer_web_contents_delegate.cc b/chrome/browser/ui/app_list/search_answer_web_contents_delegate.cc new file mode 100644 index 0000000..5eae234 --- /dev/null +++ b/chrome/browser/ui/app_list/search_answer_web_contents_delegate.cc
@@ -0,0 +1,103 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/app_list/search_answer_web_contents_delegate.h" + +#include "base/command_line.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" +#include "net/http/http_response_headers.h" +#include "net/http/http_status_code.h" +#include "ui/app_list/app_list_model.h" +#include "ui/app_list/app_list_switches.h" +#include "ui/app_list/search_box_model.h" +#include "ui/views/controls/webview/webview.h" + +namespace app_list { + +SearchAnswerWebContentsDelegate::SearchAnswerWebContentsDelegate( + content::BrowserContext* browser_context, + app_list::AppListModel* model) + : model_(model), + web_view_(base::MakeUnique<views::WebView>(browser_context)), + web_contents_( + content::WebContents::Create(content::WebContents::CreateParams( + browser_context, + content::SiteInstance::Create(browser_context)))), + answer_server_url_(switches::AnswerServerUrl()) { + Observe(web_contents_.get()); + web_view_->set_owned_by_client(); + web_view_->SetWebContents(web_contents_.get()); +} + +SearchAnswerWebContentsDelegate::~SearchAnswerWebContentsDelegate() {} + +views::View* SearchAnswerWebContentsDelegate::web_view() { + return web_view_.get(); +} + +void SearchAnswerWebContentsDelegate::Update() { + if (!answer_server_url_.is_valid()) + return; + + // Reset the state. + received_answer_ = false; + model_->SetSearchAnswerAvailable(false); + + if (!model_->search_engine_is_google()) + return; + + // Start a request to the answer server. + base::string16 query; + base::TrimWhitespace(model_->search_box()->text(), base::TRIM_ALL, &query); + if (query.empty()) + return; + + // Lifetime of |prefixed_query| should be longer than the one of + // |replacements|. + base::string16 prefixed_query(base::UTF8ToUTF16("q=") + query); + GURL::ReplacementsW replacements; + replacements.SetQueryStr(prefixed_query); + current_request_url_ = answer_server_url_.ReplaceComponents(replacements); + + web_contents_->GetController().LoadURL( + current_request_url_, content::Referrer(), + ui::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string()); + + // We are going to call WebContents::GetPreferredSize(). + web_contents_->GetRenderViewHost()->EnablePreferredSizeMode(); +} + +void SearchAnswerWebContentsDelegate::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { + if (navigation_handle->GetURL() != current_request_url_) + return; + + if (!navigation_handle->HasCommitted() || navigation_handle->IsErrorPage() || + !navigation_handle->IsInMainFrame()) { + return; + } + + const net::HttpResponseHeaders* headers = + navigation_handle->GetResponseHeaders(); + if (!headers || headers->response_code() != net::HTTP_OK || + !headers->HasHeaderValue("has_answer", "true")) { + return; + } + + received_answer_ = true; +} + +void SearchAnswerWebContentsDelegate::DidStopLoading() { + if (!received_answer_) + return; + + web_view_->SetPreferredSize(web_contents_->GetPreferredSize()); + model_->SetSearchAnswerAvailable(true); +} + +} // namespace app_list
diff --git a/chrome/browser/ui/app_list/search_answer_web_contents_delegate.h b/chrome/browser/ui/app_list/search_answer_web_contents_delegate.h new file mode 100644 index 0000000..0de6377f --- /dev/null +++ b/chrome/browser/ui/app_list/search_answer_web_contents_delegate.h
@@ -0,0 +1,76 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_ANSWER_WEB_CONTENTS_DELEGATE_H_ +#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ANSWER_WEB_CONTENTS_DELEGATE_H_ + +#include <memory> +#include <string> + +#include "content/public/browser/web_contents_observer.h" +#include "url/gurl.h" + +namespace app_list { +class AppListModel; +} + +namespace content { +class BrowserContext; +} + +namespace views { +class View; +class WebView; +} + +namespace app_list { + +// Manages the web contents for the search answer web view. +class SearchAnswerWebContentsDelegate : public content::WebContentsObserver { + public: + SearchAnswerWebContentsDelegate(content::BrowserContext* browser_context, + app_list::AppListModel* model); + + ~SearchAnswerWebContentsDelegate() override; + + // Updates the state after the query string or any other relevant condition + // changes. + void Update(); + + // Returns a pointer to the web view for the web contents managed by this + // class. The object is owned by this class and has property + // 'set_owned_by_client()' set. + views::View* web_view(); + + // content::WebContentsObserver overrides: + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override; + void DidStopLoading() override; + + private: + // Unowned pointer to app list model. + app_list::AppListModel* const model_; + + // Web view for the web contents managed by this class. + const std::unique_ptr<views::WebView> web_view_; + + // Whether have received a server response for the current query string, and + // the response contains an answer. + bool received_answer_ = false; + + // Web contents managed by this class. + const std::unique_ptr<content::WebContents> web_contents_; + + // If valid, URL of the answer server. Otherwise, search answers are disabled. + GURL answer_server_url_; + + // URL of the current answer server request. + GURL current_request_url_; + + DISALLOW_COPY_AND_ASSIGN(SearchAnswerWebContentsDelegate); +}; + +} // namespace app_list + +#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_ANSWER_WEB_CONTENTS_DELEGATE_H_
diff --git a/chrome/browser/ui/ash/session_controller_client.cc b/chrome/browser/ui/ash/session_controller_client.cc index 60d605c..3325fa21 100644 --- a/chrome/browser/ui/ash/session_controller_client.cc +++ b/chrome/browser/ui/ash/session_controller_client.cc
@@ -12,6 +12,7 @@ #include "base/bind.h" #include "base/logging.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/login/user_flow.h" #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" #include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h" @@ -24,6 +25,7 @@ #include "chromeos/dbus/session_manager_client.h" #include "components/prefs/pref_service.h" #include "components/session_manager/core/session_manager.h" +#include "content/public/browser/notification_service.h" #include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" #include "services/service_manager/public/cpp/connector.h" @@ -90,6 +92,9 @@ UserManager::Get()->AddSessionStateObserver(this); UserManager::Get()->AddObserver(this); + registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, + content::NotificationService::AllSources()); + ConnectToSessionControllerAndSetClient(); SendSessionInfoIfChanged(); // User sessions and their order will be sent via UserSessionStateObserver @@ -264,6 +269,14 @@ SendSessionInfoIfChanged(); } +void SessionControllerClient::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type); + session_controller_->NotifyChromeTerminating(); +} + void SessionControllerClient::ConnectToSessionControllerAndSetClient() { content::ServiceManagerConnection::GetForProcess() ->GetConnector()
diff --git a/chrome/browser/ui/ash/session_controller_client.h b/chrome/browser/ui/ash/session_controller_client.h index 484c2c18..ab9ba3f9 100644 --- a/chrome/browser/ui/ash/session_controller_client.h +++ b/chrome/browser/ui/ash/session_controller_client.h
@@ -10,6 +10,8 @@ #include "base/macros.h" #include "components/session_manager/core/session_manager_observer.h" #include "components/user_manager/user_manager.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" #include "mojo/public/cpp/bindings/binding.h" namespace ash { @@ -27,7 +29,8 @@ : public ash::mojom::SessionControllerClient, public user_manager::UserManager::UserSessionStateObserver, public user_manager::UserManager::Observer, - public session_manager::SessionManagerObserver { + public session_manager::SessionManagerObserver, + public content::NotificationObserver { public: SessionControllerClient(); ~SessionControllerClient() override; @@ -54,6 +57,11 @@ // session_manager::SessionManagerObserver: void OnSessionStateChanged() override; + // content::NotificationObserver: + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; + // TODO(xiyuan): Remove after SessionStateDelegateChromeOS is gone. static bool CanLockScreen(); static bool ShouldLockScreenAutomatically(); @@ -88,6 +96,9 @@ // Whether the primary user session info is sent to ash. bool primary_user_session_sent_ = false; + // For observing NOTIFICATION_APP_TERMINATING. + content::NotificationRegistrar registrar_; + ash::mojom::SessionInfoPtr last_sent_session_info_; DISALLOW_COPY_AND_ASSIGN(SessionControllerClient);
diff --git a/chrome/browser/ui/cocoa/passwords/passwords_bubble_browsertest.mm b/chrome/browser/ui/cocoa/passwords/passwords_bubble_browsertest.mm index df6a6bce..ccb44095 100644 --- a/chrome/browser/ui/cocoa/passwords/passwords_bubble_browsertest.mm +++ b/chrome/browser/ui/cocoa/passwords/passwords_bubble_browsertest.mm
@@ -68,7 +68,7 @@ return [bwc locationBarBridge]->manage_passwords_decoration(); } - ManagePasswordsIcon* view() override { return decoration()->icon(); } + ManagePasswordsIconCocoa* GetView() { return decoration()->icon(); } }; IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleTest, @@ -78,7 +78,7 @@ EXPECT_TRUE(ManagePasswordsBubbleCocoa::instance()); EXPECT_EQ([SavePendingPasswordViewController class], [controller().currentController class]); - EXPECT_TRUE(view()->active()); + EXPECT_TRUE(GetView()->active()); } IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleTest, IconClickTogglesBubble) { @@ -119,13 +119,13 @@ base::scoped_nsobject<ManagePasswordsBubbleController> bubble_controller( [controller() retain]); EXPECT_TRUE(bubble_controller); - EXPECT_TRUE(view()->active()); + EXPECT_TRUE(GetView()->active()); // Open the bubble again, the first one should be replaced. DoWithSwizzledNSWindow(^{ SetupPendingPassword(); }); EXPECT_NSNE(bubble_controller, controller()); EXPECT_TRUE(controller()); - EXPECT_TRUE(view()->active()); + EXPECT_TRUE(GetView()->active()); } IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleTest, DoubleOpenDifferentBubbles) { @@ -136,11 +136,11 @@ SetupAutoSignin(std::move(local_credentials)); }); EXPECT_TRUE(controller()); - EXPECT_TRUE(view()->active()); + EXPECT_TRUE(GetView()->active()); // Open the save bubble. The previous one is closed twice (with and without // animation). It shouldn't cause DCHECK. DoWithSwizzledNSWindow(^{ SetupPendingPassword(); }); EXPECT_TRUE(controller()); - EXPECT_TRUE(view()->active()); + EXPECT_TRUE(GetView()->active()); }
diff --git a/chrome/browser/ui/page_info/page_info_ui.cc b/chrome/browser/ui/page_info/page_info_ui.cc index c1563c8..34a289b 100644 --- a/chrome/browser/ui/page_info/page_info_ui.cc +++ b/chrome/browser/ui/page_info/page_info_ui.cc
@@ -15,6 +15,7 @@ #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" +#include "components/strings/grit/components_chromium_strings.h" #include "components/strings/grit/components_strings.h" #include "ppapi/features/features.h" #include "ui/base/l10n/l10n_util.h" @@ -135,8 +136,14 @@ switch (identity_status) { case PageInfo::SITE_IDENTITY_STATUS_INTERNAL_PAGE: - // Internal pages have their own UI implementations which should never - // call this function. +#if defined(OS_ANDROID) + // We provide identical summary and detail strings for Android, which + // deduplicates them in the UI code. + return CreateSecurityDescription(IDS_PAGE_INFO_INTERNAL_PAGE, + IDS_PAGE_INFO_INTERNAL_PAGE); +#endif + // Internal pages on desktop have their own UI implementations which + // should never call this function. NOTREACHED(); case PageInfo::SITE_IDENTITY_STATUS_CERT: case PageInfo::SITE_IDENTITY_STATUS_EV_CERT:
diff --git a/chrome/browser/ui/passwords/manage_passwords_test.h b/chrome/browser/ui/passwords/manage_passwords_test.h index 81e9573..7a67260 100644 --- a/chrome/browser/ui/passwords/manage_passwords_test.h +++ b/chrome/browser/ui/passwords/manage_passwords_test.h
@@ -18,7 +18,6 @@ #include "components/password_manager/core/common/credential_manager_types.h" #include "testing/gmock/include/gmock/gmock.h" -class ManagePasswordsIconView; class PasswordsClientUIDelegate; // Test class for the various password management view bits and pieces. Provides @@ -31,9 +30,6 @@ // InProcessBrowserTest: void SetUpOnMainThread() override; - // Get the icon view for the current WebContents. - virtual ManagePasswordsIconView* view() = 0; - // Execute the browser command to open the manage passwords bubble. void ExecuteManagePasswordsCommand();
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc index 0608c37..1c503a9 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
@@ -411,6 +411,7 @@ AddChildView(ios_promo_view_); GetWidget()->UpdateWindowIcon(); GetWidget()->UpdateWindowTitle(); - SizeToContents(); + // Resize the bubble so it has the same width as the parent bubble. + ios_promo_view_->UpdateBubbleHeight(); } #endif
diff --git a/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.cc b/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.cc index 25037710..7f72299 100644 --- a/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.cc +++ b/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.cc
@@ -10,12 +10,27 @@ #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h" #include "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h" #include "chrome/grit/generated_resources.h" +#include "chrome/grit/locale_settings.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/button/md_text_button.h" #include "ui/views/layout/grid_layout.h" +namespace { +// Returns the appropriate size for the promotion text label on the bubble. +int GetPromoBubbleTextLabelWidth( + desktop_ios_promotion::PromotionEntryPoint entry_point) { + if (entry_point == + desktop_ios_promotion::PromotionEntryPoint::SAVE_PASSWORD_BUBBLE) { + return views::Widget::GetLocalizedContentsWidth( + IDS_DESKTOP_IOS_PROMOTION_SAVE_PASSWORDS_BUBBLE_TEXT_WIDTH_CHARS); + } + return views::Widget::GetLocalizedContentsWidth( + IDS_DESKTOP_IOS_PROMOTION_TEXT_WIDTH_CHARS); +} +} // namespace + DesktopIOSPromotionBubbleView::DesktopIOSPromotionBubbleView( Profile* profile, desktop_ios_promotion::PromotionEntryPoint entry_point) @@ -25,10 +40,8 @@ base::MakeUnique<DesktopIOSPromotionController>(profile, this, entry_point)) { - int bubble_width = ManagePasswordsBubbleView::kDesiredBubbleWidth; views::GridLayout* layout = new views::GridLayout(this); ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); - layout->set_minimum_size(gfx::Size(bubble_width, 0)); layout->SetInsets( 0, provider->GetDistanceMetric(DISTANCE_PANEL_CONTENT_MARGIN) + @@ -45,7 +58,7 @@ constexpr int kLabelColumnSet = 1; views::ColumnSet* column_set = layout->AddColumnSet(kLabelColumnSet); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0, - views::GridLayout::FIXED, bubble_width, 0); + views::GridLayout::USE_PREF, 0, 0); constexpr int kDoubleButtonColumnSet = 2; column_set = layout->AddColumnSet(kDoubleButtonColumnSet); column_set->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, @@ -57,6 +70,7 @@ 0, views::GridLayout::USE_PREF, 0, 0); promotion_text_label_->SetEnabledColor(SK_ColorGRAY); promotion_text_label_->SetMultiLine(true); + promotion_text_label_->SizeToFit(GetPromoBubbleTextLabelWidth(entry_point)); promotion_text_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); layout->StartRow(0, kLabelColumnSet); layout->AddView(promotion_text_label_); @@ -82,11 +96,19 @@ GetWidget()->Close(); } +void DesktopIOSPromotionBubbleView::UpdateBubbleHeight() { + gfx::Rect old_bounds = GetWidget()->GetWindowBoundsInScreen(); + old_bounds.set_height( + GetWidget()->GetRootView()->GetHeightForWidth(old_bounds.width())); + GetWidget()->SetBounds(old_bounds); +} + void DesktopIOSPromotionBubbleView::UpdateRecoveryPhoneLabel() { std::string number = promotion_controller_->GetUsersRecoveryPhoneNumber(); if (!number.empty()) { promotion_text_label_->SetText(desktop_ios_promotion::GetPromoText( promotion_controller_->entry_point(), number)); - SizeToPreferredSize(); + Layout(); + UpdateBubbleHeight(); } }
diff --git a/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.h b/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.h index c754ef67..bcb4c22 100644 --- a/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.h +++ b/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.h
@@ -28,6 +28,9 @@ desktop_ios_promotion::PromotionEntryPoint entry_point); ~DesktopIOSPromotionBubbleView() override; + // Update Bubble Height to fit the content. + void UpdateBubbleHeight(); + // DesktopIOSPromotionView: void UpdateRecoveryPhoneLabel() override;
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc index cdf2f6eaf..cb65bf6 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
@@ -831,12 +831,19 @@ RemoveAllChildViews(true); initially_focused_view_ = NULL; CreateChild(); - // Show/hide the close button. GetWidget()->non_client_view()->ResetWindowControls(); GetWidget()->UpdateWindowIcon(); GetWidget()->UpdateWindowTitle(); - SizeToContents(); + if (model_.state() == password_manager::ui::CHROME_DESKTOP_IOS_PROMO_STATE) { + // Update the height and keep the existing width. + gfx::Rect bubble_bounds = GetWidget()->GetWindowBoundsInScreen(); + bubble_bounds.set_height( + GetWidget()->GetRootView()->GetHeightForWidth(bubble_bounds.width())); + GetWidget()->SetBounds(bubble_bounds); + } else { + SizeToContents(); + } } void ManagePasswordsBubbleView::CreateChild() {
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc index 6baa1e9..1579d11 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc
@@ -63,21 +63,7 @@ namespace metrics_util = password_manager::metrics_util; -class ManagePasswordsBubbleViewTest : public ManagePasswordsTest { - public: - ManagePasswordsBubbleViewTest() {} - ~ManagePasswordsBubbleViewTest() override {} - - ManagePasswordsIconView* view() override { - BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); - return browser_view->toolbar() - ->location_bar() - ->manage_passwords_icon_view(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(ManagePasswordsBubbleViewTest); -}; +using ManagePasswordsBubbleViewTest = ManagePasswordsTest; IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest, BasicOpenAndClose) { EXPECT_FALSE(IsBubbleShowing());
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_icon_view_interactive_uitest.cc b/chrome/browser/ui/views/passwords/manage_passwords_icon_view_interactive_uitest.cc index 1295b74..707d1b4 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_icon_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_icon_view_interactive_uitest.cc
@@ -22,16 +22,13 @@ ManagePasswordsIconViewTest() {} ~ManagePasswordsIconViewTest() override {} - ManagePasswordsIconView* view() override { - BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); - return static_cast<ManagePasswordsIconViews*>( - browser_view->toolbar()->location_bar()->manage_passwords_icon_view()); - } - password_manager::ui::State ViewState() { return GetView()->state_; } ManagePasswordsIconViews* GetView() { - return static_cast<ManagePasswordsIconViews*>(view()); + return BrowserView::GetBrowserViewForBrowser(browser()) + ->toolbar() + ->location_bar() + ->manage_passwords_icon_view(); } base::string16 GetTooltipText() {
diff --git a/chrome/browser/ui/views/status_icons/status_tray_state_changer_win.cc b/chrome/browser/ui/views/status_icons/status_tray_state_changer_win.cc index c17dafc..b5d3f83 100644 --- a/chrome/browser/ui/views/status_icons/status_tray_state_changer_win.cc +++ b/chrome/browser/ui/views/status_icons/status_tray_state_changer_win.cc
@@ -132,14 +132,14 @@ return false; base::win::ScopedComPtr<ITrayNotifyWin8> tray_notify_win8; - hr = tray_notify_win8.QueryFrom(tray_notify_.get()); + hr = tray_notify_win8.QueryFrom(tray_notify_.Get()); if (SUCCEEDED(hr)) { interface_version_ = INTERFACE_VERSION_WIN8; return true; } base::win::ScopedComPtr<ITrayNotify> tray_notify_legacy; - hr = tray_notify_legacy.QueryFrom(tray_notify_.get()); + hr = tray_notify_legacy.QueryFrom(tray_notify_.Get()); if (SUCCEEDED(hr)) { interface_version_ = INTERFACE_VERSION_LEGACY; return true; @@ -174,7 +174,7 @@ bool StatusTrayStateChangerWin::RegisterCallbackWin8() { base::win::ScopedComPtr<ITrayNotifyWin8> tray_notify_win8; - HRESULT hr = tray_notify_win8.QueryFrom(tray_notify_.get()); + HRESULT hr = tray_notify_win8.QueryFrom(tray_notify_.Get()); if (FAILED(hr)) return false; @@ -194,7 +194,7 @@ bool StatusTrayStateChangerWin::RegisterCallbackLegacy() { base::win::ScopedComPtr<ITrayNotify> tray_notify; - HRESULT hr = tray_notify.QueryFrom(tray_notify_.get()); + HRESULT hr = tray_notify.QueryFrom(tray_notify_.Get()); if (FAILED(hr)) { return false; } @@ -221,12 +221,12 @@ std::unique_ptr<NOTIFYITEM> notify_item) { if (interface_version_ == INTERFACE_VERSION_LEGACY) { base::win::ScopedComPtr<ITrayNotify> tray_notify; - HRESULT hr = tray_notify.QueryFrom(tray_notify_.get()); + HRESULT hr = tray_notify.QueryFrom(tray_notify_.Get()); if (SUCCEEDED(hr)) tray_notify->SetPreference(notify_item.get()); } else if (interface_version_ == INTERFACE_VERSION_WIN8) { base::win::ScopedComPtr<ITrayNotifyWin8> tray_notify; - HRESULT hr = tray_notify.QueryFrom(tray_notify_.get()); + HRESULT hr = tray_notify.QueryFrom(tray_notify_.Get()); if (SUCCEEDED(hr)) tray_notify->SetPreference(notify_item.get()); }
diff --git a/chrome/browser/usb/usb_browsertest.cc b/chrome/browser/usb/usb_browsertest.cc index 3a847ae2..78e4d92 100644 --- a/chrome/browser/usb/usb_browsertest.cc +++ b/chrome/browser/usb/usb_browsertest.cc
@@ -58,10 +58,10 @@ DISALLOW_COPY_AND_ASSIGN(FakeChooserView); }; -class FakeChooserService : public device::usb::ChooserService { +class FakeChooserService : public device::mojom::UsbChooserService { public: static void Create(RenderFrameHost* render_frame_host, - device::usb::ChooserServiceRequest request) { + device::mojom::UsbChooserServiceRequest request) { mojo::MakeStrongBinding( base::MakeUnique<FakeChooserService>(render_frame_host), std::move(request)); @@ -72,7 +72,7 @@ ~FakeChooserService() override {} - // device::usb::ChooserService: + // device::mojom::UsbChooserService: void GetPermission(const std::vector<device::UsbDeviceFilter>& device_filters, const GetPermissionCallback& callback) override { auto chooser_controller = base::MakeUnique<UsbChooserController>(
diff --git a/chrome/browser/usb/usb_chooser_controller.cc b/chrome/browser/usb/usb_chooser_controller.cc index a08a962..9a9cd36f 100644 --- a/chrome/browser/usb/usb_chooser_controller.cc +++ b/chrome/browser/usb/usb_chooser_controller.cc
@@ -76,7 +76,7 @@ UsbChooserController::UsbChooserController( RenderFrameHost* render_frame_host, const std::vector<UsbDeviceFilter>& device_filters, - const device::usb::ChooserService::GetPermissionCallback& callback) + const device::mojom::UsbChooserService::GetPermissionCallback& callback) : ChooserController(render_frame_host, IDS_USB_DEVICE_CHOOSER_PROMPT_ORIGIN, IDS_USB_DEVICE_CHOOSER_PROMPT_EXTENSION_NAME), @@ -160,10 +160,8 @@ requesting_origin_, embedding_origin_, devices_[index].first->guid()); } - device::usb::DeviceInfoPtr device_info_ptr = - device::usb::DeviceInfo::From(*devices_[index].first); - callback_.Run(std::move(device_info_ptr)); - callback_.Reset(); // Reset |callback_| so that it is only run once. + callback_.Run(device::mojom::UsbDeviceInfo::From(*devices_[index].first)); + callback_.Reset(); // |callback_| must only be run once. RecordWebUsbChooserClosure( devices_[index].first->serial_number().empty()
diff --git a/chrome/browser/usb/usb_chooser_controller.h b/chrome/browser/usb/usb_chooser_controller.h index b990e888..4dd1d3d 100644 --- a/chrome/browser/usb/usb_chooser_controller.h +++ b/chrome/browser/usb/usb_chooser_controller.h
@@ -37,7 +37,7 @@ UsbChooserController( content::RenderFrameHost* render_frame_host, const std::vector<device::UsbDeviceFilter>& device_filters, - const device::usb::ChooserService::GetPermissionCallback& callback); + const device::mojom::UsbChooserService::GetPermissionCallback& callback); ~UsbChooserController() override; // ChooserController: @@ -63,7 +63,7 @@ bool DisplayDevice(scoped_refptr<device::UsbDevice> device) const; std::vector<device::UsbDeviceFilter> filters_; - device::usb::ChooserService::GetPermissionCallback callback_; + device::mojom::UsbChooserService::GetPermissionCallback callback_; GURL requesting_origin_; GURL embedding_origin_; bool is_embedded_frame_;
diff --git a/chrome/browser/usb/usb_chooser_controller_unittest.cc b/chrome/browser/usb/usb_chooser_controller_unittest.cc index d0f80e7..76622dd 100644 --- a/chrome/browser/usb/usb_chooser_controller_unittest.cc +++ b/chrome/browser/usb/usb_chooser_controller_unittest.cc
@@ -48,7 +48,7 @@ ChromeRenderViewHostTestHarness::SetUp(); std::vector<device::UsbDeviceFilter> device_filters; - device::usb::ChooserService::GetPermissionCallback callback; + device::mojom::UsbChooserService::GetPermissionCallback callback; content::WebContentsTester* web_contents_tester = content::WebContentsTester::For(web_contents()); web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl));
diff --git a/chrome/browser/usb/usb_tab_helper.cc b/chrome/browser/usb/usb_tab_helper.cc index 538cb19..539e878 100644 --- a/chrome/browser/usb/usb_tab_helper.cc +++ b/chrome/browser/usb/usb_tab_helper.cc
@@ -48,7 +48,7 @@ void UsbTabHelper::CreateDeviceManager( RenderFrameHost* render_frame_host, - mojo::InterfaceRequest<device::usb::DeviceManager> request) { + mojo::InterfaceRequest<device::mojom::UsbDeviceManager> request) { DCHECK(WebContents::FromRenderFrameHost(render_frame_host) == web_contents()); device::usb::DeviceManagerImpl::Create( GetPermissionProvider(render_frame_host), std::move(request)); @@ -56,7 +56,7 @@ void UsbTabHelper::CreateChooserService( content::RenderFrameHost* render_frame_host, - mojo::InterfaceRequest<device::usb::ChooserService> request) { + mojo::InterfaceRequest<device::mojom::UsbChooserService> request) { GetChooserService(render_frame_host, std::move(request)); } @@ -119,7 +119,7 @@ void UsbTabHelper::GetChooserService( content::RenderFrameHost* render_frame_host, - mojo::InterfaceRequest<device::usb::ChooserService> request) { + mojo::InterfaceRequest<device::mojom::UsbChooserService> request) { FrameUsbServices* frame_usb_services = GetFrameUsbService(render_frame_host); if (!frame_usb_services->chooser_service) { frame_usb_services->chooser_service.reset(
diff --git a/chrome/browser/usb/usb_tab_helper.h b/chrome/browser/usb/usb_tab_helper.h index 022a05e..6a9a361 100644 --- a/chrome/browser/usb/usb_tab_helper.h +++ b/chrome/browser/usb/usb_tab_helper.h
@@ -13,9 +13,12 @@ #include "mojo/public/cpp/bindings/interface_request.h" namespace device { +namespace mojom { +class UsbChooserService; +class UsbDeviceManager; +} + namespace usb { -class ChooserService; -class DeviceManager; class PermissionProvider; } } @@ -36,11 +39,11 @@ void CreateDeviceManager( content::RenderFrameHost* render_frame_host, - mojo::InterfaceRequest<device::usb::DeviceManager> request); + mojo::InterfaceRequest<device::mojom::UsbDeviceManager> request); void CreateChooserService( content::RenderFrameHost* render_frame_host, - mojo::InterfaceRequest<device::usb::ChooserService> request); + mojo::InterfaceRequest<device::mojom::UsbChooserService> request); void IncrementConnectionCount(content::RenderFrameHost* render_frame_host); void DecrementConnectionCount(content::RenderFrameHost* render_frame_host); @@ -61,7 +64,7 @@ void GetChooserService( content::RenderFrameHost* render_frame_host, - mojo::InterfaceRequest<device::usb::ChooserService> request); + mojo::InterfaceRequest<device::mojom::UsbChooserService> request); void NotifyTabStateChanged() const;
diff --git a/chrome/browser/usb/web_usb_chooser_service.cc b/chrome/browser/usb/web_usb_chooser_service.cc index 7ad5384..2dfacec 100644 --- a/chrome/browser/usb/web_usb_chooser_service.cc +++ b/chrome/browser/usb/web_usb_chooser_service.cc
@@ -45,7 +45,7 @@ } void WebUsbChooserService::Bind( - mojo::InterfaceRequest<device::usb::ChooserService> request) { + device::mojom::UsbChooserServiceRequest request) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); bindings_.AddBinding(this, std::move(request)); }
diff --git a/chrome/browser/usb/web_usb_chooser_service.h b/chrome/browser/usb/web_usb_chooser_service.h index 3b4c0b1..9dd7e88c 100644 --- a/chrome/browser/usb/web_usb_chooser_service.h +++ b/chrome/browser/usb/web_usb_chooser_service.h
@@ -20,7 +20,7 @@ // Implementation of the public device::usb::ChooserService interface. // This interface can be used by a webpage to request permission from user // to access a certain device. -class WebUsbChooserService : public device::usb::ChooserService { +class WebUsbChooserService : public device::mojom::UsbChooserService { public: explicit WebUsbChooserService(content::RenderFrameHost* render_frame_host); @@ -30,11 +30,11 @@ void GetPermission(const std::vector<device::UsbDeviceFilter>& device_filters, const GetPermissionCallback& callback) override; - void Bind(mojo::InterfaceRequest<device::usb::ChooserService> request); + void Bind(device::mojom::UsbChooserServiceRequest request); private: content::RenderFrameHost* const render_frame_host_; - mojo::BindingSet<device::usb::ChooserService> bindings_; + mojo::BindingSet<device::mojom::UsbChooserService> bindings_; std::vector<BubbleReference> bubbles_; DISALLOW_COPY_AND_ASSIGN(WebUsbChooserService);
diff --git a/chrome/browser/win/jumplist_updater.cc b/chrome/browser/win/jumplist_updater.cc index df7c772..b4231686 100644 --- a/chrome/browser/win/jumplist_updater.cc +++ b/chrome/browser/win/jumplist_updater.cc
@@ -68,14 +68,14 @@ return false; if (!base::win::SetStringValueForPropertyStore( - property_store.get(), + property_store.Get(), PKEY_Title, item->title().c_str())) { return false; } // Add this IShellLink object to the given collection. - return SUCCEEDED(collection->AddObject(link.get())); + return SUCCEEDED(collection->AddObject(link.Get())); } } // namespace @@ -122,7 +122,7 @@ SCOPED_UMA_HISTOGRAM_TIMER("WinJumplistUpdater.BeginUpdateDuration"); // This instance is expected to be one-time-use only. - DCHECK(!destination_list_.get()); + DCHECK(!destination_list_.Get()); // Check preconditions. if (!JumpListUpdater::IsEnabled() || app_user_model_id_.empty()) @@ -160,7 +160,7 @@ // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. SCOPED_UMA_HISTOGRAM_TIMER("WinJumplistUpdater.CommitUpdateDuration"); - if (!destination_list_.get()) + if (!destination_list_.Get()) return false; // Commit this transaction and send the updated JumpList to Windows. @@ -171,7 +171,7 @@ // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. SCOPED_UMA_HISTOGRAM_TIMER("WinJumplistUpdater.AddTasksDuration"); - if (!destination_list_.get()) + if (!destination_list_.Get()) return false; // Retrieve the absolute path to "chrome.exe". @@ -202,7 +202,7 @@ if (FAILED(result)) return false; - return SUCCEEDED(destination_list_->AddUserTasks(object_array.get())); + return SUCCEEDED(destination_list_->AddUserTasks(object_array.Get())); } bool JumpListUpdater::AddCustomCategory(const std::wstring& category_name, @@ -211,7 +211,7 @@ // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. SCOPED_UMA_HISTOGRAM_TIMER("WinJumplistUpdater.AddCustomCategoryDuration"); - if (!destination_list_.get()) + if (!destination_list_.Get()) return false; // Retrieve the absolute path to "chrome.exe". @@ -253,5 +253,5 @@ return false; return SUCCEEDED(destination_list_->AppendCategory(category_name.c_str(), - object_array.get())); + object_array.Get())); }
diff --git a/chrome/browser/win/settings_app_monitor.cc b/chrome/browser/win/settings_app_monitor.cc index ed6faad..fd47977 100644 --- a/chrome/browser/win/settings_app_monitor.cc +++ b/chrome/browser/win/settings_app_monitor.cc
@@ -227,7 +227,7 @@ return base::string16(); base::win::ScopedComPtr<IUIAutomationTreeWalker> tree_walker; - result = automation->CreateTreeWalker(condition.get(), tree_walker.Receive()); + result = automation->CreateTreeWalker(condition.Get(), tree_walker.Receive()); if (FAILED(result)) return base::string16(); @@ -235,12 +235,12 @@ result = automation->CreateCacheRequest(cache_request.Receive()); if (FAILED(result)) return base::string16(); - ConfigureCacheRequest(cache_request.get()); + ConfigureCacheRequest(cache_request.Get()); // From MSDN, NormalizeElementBuildCache() "Retrieves the ancestor element // nearest to the specified Microsoft UI Automation element in the tree view". IUIAutomationElement* flyout_element = nullptr; - result = tree_walker->NormalizeElementBuildCache(element, cache_request.get(), + result = tree_walker->NormalizeElementBuildCache(element, cache_request.Get(), &flyout_element); if (FAILED(result) || !flyout_element) return base::string16(); @@ -560,7 +560,7 @@ << ", runtime id: " << IntArrayToString(GetCachedInt32ArrayValue( sender, UIA_RuntimeIdPropertyId)); - switch (DetectElementType(automation_.get(), sender)) { + switch (DetectElementType(automation_.Get(), sender)) { case ElementType::DEFAULT_BROWSER: context_runner_->PostTask( FROM_HERE, @@ -679,7 +679,7 @@ DCHECK(task_runner_->BelongsToCurrentThread()); // Duplicate focus changed events are suppressed. - ElementType element_type = DetectElementType(automation_.get(), sender.get()); + ElementType element_type = DetectElementType(automation_.Get(), sender.Get()); if (last_focused_element_ == element_type) return; last_focused_element_ = element_type; @@ -733,7 +733,7 @@ SettingsAppMonitor::Context::GetAutomationEventHandler() { DCHECK(task_runner_->BelongsToCurrentThread()); base::win::ScopedComPtr<IUIAutomationEventHandler> handler; - handler.QueryFrom(GetEventHandler().get()); + handler.QueryFrom(GetEventHandler().Get()); return handler; } @@ -741,7 +741,7 @@ SettingsAppMonitor::Context::GetFocusChangedEventHandler() { DCHECK(task_runner_->BelongsToCurrentThread()); base::win::ScopedComPtr<IUIAutomationFocusChangedEventHandler> handler; - handler.QueryFrom(GetEventHandler().get()); + handler.QueryFrom(GetEventHandler().Get()); return handler; } @@ -755,11 +755,11 @@ HRESULT result = automation_->CreateCacheRequest(cache_request.Receive()); if (FAILED(result)) return result; - ConfigureCacheRequest(cache_request.get()); + ConfigureCacheRequest(cache_request.Get()); // Observe changes in focus. result = automation_->AddFocusChangedEventHandler( - cache_request.get(), GetFocusChangedEventHandler().get()); + cache_request.Get(), GetFocusChangedEventHandler().Get()); if (FAILED(result)) return result; @@ -768,8 +768,8 @@ result = automation_->GetRootElement(desktop.Receive()); if (desktop) { result = automation_->AddAutomationEventHandler( - UIA_Invoke_InvokedEventId, desktop.get(), TreeScope_Subtree, - cache_request.get(), GetAutomationEventHandler().get()); + UIA_Invoke_InvokedEventId, desktop.Get(), TreeScope_Subtree, + cache_request.Get(), GetAutomationEventHandler().Get()); } return result;
diff --git a/chrome/installer/util/advanced_firewall_manager_win.cc b/chrome/installer/util/advanced_firewall_manager_win.cc index 5873c4e..cd4625f 100644 --- a/chrome/installer/util/advanced_firewall_manager_win.cc +++ b/chrome/installer/util/advanced_firewall_manager_win.cc
@@ -80,10 +80,10 @@ // Create the rule and add it to the rule set (only succeeds if elevated). base::win::ScopedComPtr<INetFwRule> udp_rule = CreateUDPRule(rule_name, description, port); - if (!udp_rule.get()) + if (!udp_rule.Get()) return false; - HRESULT hr = firewall_rules_->Add(udp_rule.get()); + HRESULT hr = firewall_rules_->Add(udp_rule.Get()); DLOG_IF(ERROR, FAILED(hr)) << logging::SystemErrorCodeToString(hr); return SUCCEEDED(hr); } @@ -158,7 +158,7 @@ } base::win::ScopedComPtr<IEnumVARIANT> rules_enum; - hr = rules_enum.QueryFrom(rules_enum_unknown.get()); + hr = rules_enum.QueryFrom(rules_enum_unknown.Get()); if (FAILED(hr)) { DLOG(ERROR) << logging::SystemErrorCodeToString(hr); return;
diff --git a/chrome/installer/util/legacy_firewall_manager_win.cc b/chrome/installer/util/legacy_firewall_manager_win.cc index de8fd5e4..a27a8d91 100644 --- a/chrome/installer/util/legacy_firewall_manager_win.cc +++ b/chrome/installer/util/legacy_firewall_manager_win.cc
@@ -52,7 +52,7 @@ // this chrome.exe. base::win::ScopedComPtr<INetFwAuthorizedApplications> authorized_apps( GetAuthorizedApplications()); - if (!authorized_apps.get()) + if (!authorized_apps.Get()) return false; base::win::ScopedComPtr<INetFwAuthorizedApplication> chrome_application; @@ -74,15 +74,15 @@ bool LegacyFirewallManager::SetAllowIncomingConnection(bool allow) { base::win::ScopedComPtr<INetFwAuthorizedApplications> authorized_apps( GetAuthorizedApplications()); - if (!authorized_apps.get()) + if (!authorized_apps.Get()) return false; // Authorize chrome. base::win::ScopedComPtr<INetFwAuthorizedApplication> authorization = CreateChromeAuthorization(allow); - if (!authorization.get()) + if (!authorization.Get()) return false; - HRESULT hr = authorized_apps->Add(authorization.get()); + HRESULT hr = authorized_apps->Add(authorization.Get()); DLOG_IF(ERROR, FAILED(hr)) << logging::SystemErrorCodeToString(hr); return SUCCEEDED(hr); } @@ -90,7 +90,7 @@ void LegacyFirewallManager::DeleteRule() { base::win::ScopedComPtr<INetFwAuthorizedApplications> authorized_apps( GetAuthorizedApplications()); - if (!authorized_apps.get()) + if (!authorized_apps.Get()) return; authorized_apps->Remove(base::win::ScopedBstr(app_path_.value().c_str())); }
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc index 335b3d3..2ed7b5a3 100644 --- a/chrome/installer/util/shell_util.cc +++ b/chrome/installer/util/shell_util.cc
@@ -760,7 +760,7 @@ HRESULT hr = activator.CreateInstance(CLSID_ApplicationActivationManager); if (SUCCEEDED(hr)) { DWORD pid = 0; - CoAllowSetForegroundWindow(activator.get(), nullptr); + CoAllowSetForegroundWindow(activator.Get(), nullptr); hr = activator->ActivateApplication(kControlPanelAppModelId, L"page=SettingsPageAppsDefaults", AO_NONE, &pid);
diff --git a/chrome/installer/util/wmi.cc b/chrome/installer/util/wmi.cc index fd65773..217a8c3 100644 --- a/chrome/installer/util/wmi.cc +++ b/chrome/installer/util/wmi.cc
@@ -31,7 +31,7 @@ return false; if (set_blanket) { - hr = ::CoSetProxyBlanket(wmi_services_r.get(), RPC_C_AUTHN_WINNT, + hr = ::CoSetProxyBlanket(wmi_services_r.Get(), RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); if (FAILED(hr)) @@ -62,7 +62,7 @@ if (FAILED(hr)) return false; - if (NULL == params_def.get()) { + if (NULL == params_def.Get()) { // You hit this special case if the WMI class is not a CIM class. MSDN // sometimes tells you this. Welcome to WMI hell. return false; @@ -94,20 +94,20 @@ const wchar_t class_name[] = L"Win32_Process"; const wchar_t method_name[] = L"Create"; base::win::ScopedComPtr<IWbemClassObject> process_create; - if (!WMI::CreateClassMethodObject(wmi_local.get(), class_name, method_name, + if (!WMI::CreateClassMethodObject(wmi_local.Get(), class_name, method_name, process_create.Receive())) return false; ScopedVariant b_command_line(command_line.c_str()); - if (!SetParameter(process_create.get(), L"CommandLine", + if (!SetParameter(process_create.Get(), L"CommandLine", b_command_line.AsInput())) return false; base::win::ScopedComPtr<IWbemClassObject> out_params; HRESULT hr = wmi_local->ExecMethod( base::win::ScopedBstr(class_name), base::win::ScopedBstr(method_name), 0, - NULL, process_create.get(), out_params.Receive(), NULL); + NULL, process_create.Get(), out_params.Receive(), NULL); if (FAILED(hr)) return false; @@ -141,7 +141,7 @@ query_language, query, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, enumerator.Receive()); - if (FAILED(hr) || !enumerator.get()) + if (FAILED(hr) || !enumerator.Get()) return base::string16(); base::win::ScopedComPtr<IWbemClassObject> class_object;
diff --git a/chrome/renderer/chrome_render_thread_observer.cc b/chrome/renderer/chrome_render_thread_observer.cc index 6c42add..043975d 100644 --- a/chrome/renderer/chrome_render_thread_observer.cc +++ b/chrome/renderer/chrome_render_thread_observer.cc
@@ -38,10 +38,13 @@ #include "chrome/renderer/content_settings_observer.h" #include "chrome/renderer/security_filter_peer.h" #include "components/visitedlink/renderer/visitedlink_slave.h" +#include "content/public/child/child_thread.h" #include "content/public/child/resource_dispatcher_delegate.h" #include "content/public/common/associated_interface_registry.h" #include "content/public/common/content_switches.h" +#include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" +#include "content/public/common/simple_connection_filter.h" #include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" #include "content/public/renderer/render_view_visitor.h" @@ -50,8 +53,8 @@ #include "mojo/public/cpp/bindings/strong_binding.h" #include "net/base/net_errors.h" #include "net/base/net_module.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/connector.h" -#include "services/service_manager/public/cpp/interface_registry.h" #include "third_party/WebKit/public/platform/WebCache.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebFrame.h" @@ -241,9 +244,6 @@ resource_delegate_.reset(new RendererResourceDelegate()); thread->SetResourceDispatcherDelegate(resource_delegate_.get()); - thread->GetInterfaceRegistry()->AddInterface( - base::Bind(CreateResourceUsageReporter, weak_factory_.GetWeakPtr())); - // Configure modules that need access to resources. net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider); media::SetLocalizedStringProvider( @@ -261,8 +261,18 @@ WebSecurityPolicy::RegisterURLSchemeAsNotAllowingJavascriptURLs( native_scheme); - thread->GetInterfaceRegistry()->AddInterface( - visited_link_slave_->GetBindCallback()); + auto registry = base::MakeUnique<service_manager::BinderRegistry>(); + registry->AddInterface( + base::Bind(CreateResourceUsageReporter, weak_factory_.GetWeakPtr()), + base::ThreadTaskRunnerHandle::Get()); + registry->AddInterface(visited_link_slave_->GetBindCallback(), + base::ThreadTaskRunnerHandle::Get()); + if (content::ChildThread::Get()) { + content::ChildThread::Get() + ->GetServiceManagerConnection() + ->AddConnectionFilter(base::MakeUnique<content::SimpleConnectionFilter>( + std::move(registry))); + } } ChromeRenderThreadObserver::~ChromeRenderThreadObserver() {}
diff --git a/chrome/renderer/resources/extensions/webstore_custom_bindings.js b/chrome/renderer/resources/extensions/webstore_custom_bindings.js index 89b11cc..99fae6ba 100644 --- a/chrome/renderer/resources/extensions/webstore_custom_bindings.js +++ b/chrome/renderer/resources/extensions/webstore_custom_bindings.js
@@ -5,35 +5,46 @@ // Custom binding for the webstore API. var webstoreNatives = requireNative('webstore'); -var Event = require('event_bindings').Event; + +var onInstallStageChanged; +var onDownloadProgress; function Installer() { this._pendingInstall = null; - this.onInstallStageChanged = - new Event(null, [{name: 'stage', type: 'string'}], {unmanaged: true}); - this.onDownloadProgress = - new Event(null, [{name: 'progress', type: 'number'}], {unmanaged: true}); } Installer.prototype.install = function(url, onSuccess, onFailure) { if (this._pendingInstall) throw new Error('A Chrome Web Store installation is already pending.'); - if (url !== undefined && typeof(url) !== 'string') { + + // With native bindings, these calls go through argument validation, which + // sets optional/missing arguments to null. The native webstore bindings + // expect either present or undefined, so transform null to undefined. + if (url === null) + url = undefined; + if (onSuccess === null) + onSuccess = undefined; + if (onFailure === null) + onFailure = undefined; + + if (url !== undefined && typeof url !== 'string') { throw new Error( 'The Chrome Web Store item link URL parameter must be a string.'); } - if (onSuccess !== undefined && typeof(onSuccess) !== 'function') + if (onSuccess !== undefined && typeof onSuccess !== 'function') { throw new Error('The success callback parameter must be a function.'); - if (onFailure !== undefined && typeof(onFailure) !== 'function') + } + if (onFailure !== undefined && typeof onFailure !== 'function') { throw new Error('The failure callback parameter must be a function.'); + } // Since we call Install() with a bool for if we have listeners, listeners // must be set prior to the inline installation starting (this is also // noted in the Event documentation in // chrome/common/extensions/api/webstore.json). var installId = webstoreNatives.Install( - this.onInstallStageChanged.hasListeners(), - this.onDownloadProgress.hasListeners(), + onInstallStageChanged.hasListeners(), + onDownloadProgress.hasListeners(), url, onSuccess, onFailure); @@ -68,29 +79,48 @@ }; Installer.prototype.onInstallStageChanged = function(installStage) { - this.onInstallStageChanged.dispatch(installStage); + onInstallStageChanged.dispatch(installStage); }; Installer.prototype.onDownloadProgress = function(progress) { - this.onDownloadProgress.dispatch(progress); + onDownloadProgress.dispatch(progress); }; var installer = new Installer(); -var chromeWebstore = { - install: function (url, onSuccess, onFailure) { - installer.install(url, onSuccess, onFailure); - }, - onInstallStageChanged: installer.onInstallStageChanged, - onDownloadProgress: installer.onDownloadProgress -}; -exports.$set('binding', chromeWebstore); +if (apiBridge) { + apiBridge.registerCustomHook(function(api) { + api.apiFunctions.setHandleRequest('install', + function(url, onSuccess, onFailure) { + installer.install(url, onSuccess, onFailure); + }); + + onInstallStageChanged = api.compiledApi.onInstallStageChanged; + onDownloadProgress = api.compiledApi.onDownloadProgress; + }); +} else { + var Event = require('event_bindings').Event; + onInstallStageChanged = + new Event(null, [{name: 'stage', type: 'string'}], {unmanaged: true}); + onDownloadProgress = + new Event(null, [{name: 'progress', type: 'number'}], {unmanaged: true}); + + var chromeWebstore = { + install: function (url, onSuccess, onFailure) { + installer.install(url, onSuccess, onFailure); + }, + onInstallStageChanged: onInstallStageChanged, + onDownloadProgress: onDownloadProgress, + }; + exports.$set('binding', chromeWebstore); +} // Called by webstore_bindings.cc. -exports.onInstallResponse = - Installer.prototype.onInstallResponse.bind(installer); -exports.onInstallStageChanged = - Installer.prototype.onInstallStageChanged.bind(installer); -exports.onDownloadProgress = - Installer.prototype.onDownloadProgress.bind(installer); +exports.$set('onInstallResponse', + $Function.bind(Installer.prototype.onInstallResponse, installer)); +exports.$set('onInstallStageChanged', + $Function.bind(Installer.prototype.onInstallStageChanged, + installer)); +exports.$set('onDownloadProgress', + $Function.bind(Installer.prototype.onDownloadProgress, installer));
diff --git a/chrome/service/cloud_print/print_system_win.cc b/chrome/service/cloud_print/print_system_win.cc index 292aa689..c3679e1 100644 --- a/chrome/service/cloud_print/print_system_win.cc +++ b/chrome/service/cloud_print/print_system_win.cc
@@ -361,7 +361,7 @@ // base::win::ObjectWatcher::Delegate implementation. void OnObjectSignaled(HANDLE object) override { - DCHECK(xps_print_job_.get()); + DCHECK(xps_print_job_.Get()); DCHECK(object == job_progress_event_.Get()); ResetEvent(job_progress_event_.Get()); if (!delegate_) @@ -395,7 +395,7 @@ : job_ptr_(job_ptr) { } ~PrintJobCanceler() { - if (job_ptr_ && job_ptr_->get()) { + if (job_ptr_ && job_ptr_->Get()) { (*job_ptr_)->Cancel(); job_ptr_->Reset(); } @@ -748,10 +748,10 @@ CreateStreamOnHGlobal(NULL, TRUE, result_ticket_stream.Receive()); ret = SUCCEEDED(printing::XPSModule::MergeAndValidatePrintTicket( provider, - print_ticket_stream.get(), + print_ticket_stream.Get(), NULL, kPTJobScope, - result_ticket_stream.get(), + result_ticket_stream.Get(), error.Receive())); printing::XPSModule::CloseProvider(provider); }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 58b2e22..bc1c20b 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1145,6 +1145,7 @@ "//third_party/webgl/src/sdk/tests/", # For resolve the imports in content/test/gpu/run_gpu_test.py + "//tools/perf/core/", "//tools/perf/chrome_telemetry_build/", # From telemetry_gpu_unittests.isolate
diff --git a/chrome/test/data/android/appindexing/json-ld.html b/chrome/test/data/android/appindexing/json-ld.html new file mode 100644 index 0000000..5f218b2f --- /dev/null +++ b/chrome/test/data/android/appindexing/json-ld.html
@@ -0,0 +1,11 @@ +<html> +<head> + <meta charset="utf-8"> + <title>JSON-LD for AppIndexing Test</title> + <script type="application/ld+json"> + {"@context":"http://schema.org","@type":"Hotel","name":"Hotel Name"} + </script> +</head> +<body> +</body> +</html>
diff --git a/chrome/utility/importer/ie_importer_win.cc b/chrome/utility/importer/ie_importer_win.cc index 047fb1eb..9c5fc30 100644 --- a/chrome/utility/importer/ie_importer_win.cc +++ b/chrome/utility/importer/ie_importer_win.cc
@@ -296,7 +296,7 @@ return false; base::win::ScopedComPtr<IPersistFile> persist_file; - if (FAILED(persist_file.QueryFrom(url_locator.get()))) + if (FAILED(persist_file.QueryFrom(url_locator.Get()))) return false; // Loads the Internet Shortcut from persistent storage. @@ -856,7 +856,7 @@ base::win::ScopedComPtr<IUniformResourceLocator> url_locator; if (!LoadInternetShortcut(*it, &url_locator)) continue; - GURL url = ReadURLFromInternetShortcut(url_locator.get()); + GURL url = ReadURLFromInternetShortcut(url_locator.Get()); if (!url.is_valid()) continue; // Skip default bookmarks. go.microsoft.com redirects to @@ -867,7 +867,7 @@ if (url.host() == "go.microsoft.com") continue; // Read favicon. - UpdateFaviconMap(*it, url, url_locator.get(), &favicon_map); + UpdateFaviconMap(*it, url, url_locator.Get(), &favicon_map); // Make the relative path from the Favorites folder, without the basename. // ex. Suppose that the Favorites folder is C:\Users\Foo\Favorites.
diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc index e4e35c4..100c026a 100644 --- a/chromeos/audio/cras_audio_handler.cc +++ b/chromeos/audio/cras_audio_handler.cc
@@ -37,11 +37,11 @@ const int kHDMIRediscoverGracePeriodDurationInMs = 2000; // Mixer matrix, [0.5, 0.5; 0.5, 0.5] -const std::vector<double> kStereoToMono = {0.5, 0.5, 0.5, 0.5}; +const double kStereoToMono[] = {0.5, 0.5, 0.5, 0.5}; // Mixer matrix, [1, 0; 0, 1] -const std::vector<double> kStereoToStereo = {1, 0, 0, 1}; +const double kStereoToStereo[] = {1, 0, 0, 1}; -static CrasAudioHandler* g_cras_audio_handler = nullptr; +CrasAudioHandler* g_cras_audio_handler = nullptr; bool IsSameAudioDevice(const AudioDevice& a, const AudioDevice& b) { return a.stable_device_id == b.stable_device_id && a.is_input == b.is_input && @@ -56,6 +56,15 @@ return false; } +CrasAudioClient* GetCrasAudioClient() { + return DBusThreadManager::Get()->GetCrasAudioClient(); +} + +bool HasCrasAudioClient() { + return DBusThreadManager::IsInitialized() && DBusThreadManager::Get() && + DBusThreadManager::Get()->GetCrasAudioClient(); +} + } // namespace CrasAudioHandler::AudioObserver::AudioObserver() { @@ -256,12 +265,10 @@ } int CrasAudioHandler::GetOutputVolumePercentForDevice(uint64_t device_id) { - if (device_id == active_output_node_id_) { + if (device_id == active_output_node_id_) return output_volume_; - } else { - const AudioDevice* device = GetDeviceFromId(device_id); - return static_cast<int>(audio_pref_handler_->GetOutputVolumeValue(device)); - } + const AudioDevice* device = GetDeviceFromId(device_id); + return static_cast<int>(audio_pref_handler_->GetOutputVolumeValue(device)); } int CrasAudioHandler::GetInputGainPercent() { @@ -269,12 +276,10 @@ } int CrasAudioHandler::GetInputGainPercentForDevice(uint64_t device_id) { - if (device_id == active_input_node_id_) { + if (device_id == active_input_node_id_) return input_gain_; - } else { - const AudioDevice* device = GetDeviceFromId(device_id); - return static_cast<int>(audio_pref_handler_->GetInputGainValue(device)); - } + const AudioDevice* device = GetDeviceFromId(device_id); + return static_cast<int>(audio_pref_handler_->GetInputGainValue(device)); } uint64_t CrasAudioHandler::GetPrimaryActiveOutputNode() const { @@ -333,11 +338,11 @@ } void CrasAudioHandler::ChangeActiveNodes(const NodeIdList& new_active_ids) { - chromeos::AudioDeviceList input_devices; - chromeos::AudioDeviceList output_devices; + AudioDeviceList input_devices; + AudioDeviceList output_devices; for (uint64_t id : new_active_ids) { - const chromeos::AudioDevice* device = GetDeviceFromId(id); + const AudioDevice* device = GetDeviceFromId(id); if (!device) continue; if (device->is_input) @@ -361,9 +366,9 @@ bool CrasAudioHandler::SetActiveNodes(const NodeIdList& node_ids, bool is_input) { - chromeos::AudioDeviceList devices; + AudioDeviceList devices; for (uint64_t id : node_ids) { - const chromeos::AudioDevice* device = GetDeviceFromId(id); + const AudioDevice* device = GetDeviceFromId(id); if (!device || device->is_input != is_input) return false; @@ -420,8 +425,7 @@ for (const auto& item : audio_devices_) { const AudioDevice& device = item.second; if (!device.is_input && device.type == AUDIO_TYPE_INTERNAL_SPEAKER) { - chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->SwapLeftRight( - device.id, swap); + GetCrasAudioClient()->SwapLeftRight(device.id, swap); break; } } @@ -430,11 +434,13 @@ void CrasAudioHandler::SetOutputMono(bool mono_on) { output_mono_on_ = mono_on; if (mono_on) { - chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> - SetGlobalOutputChannelRemix(output_channels_, kStereoToMono); + GetCrasAudioClient()->SetGlobalOutputChannelRemix( + output_channels_, + std::vector<double>(kStereoToMono, std::end(kStereoToMono))); } else { - chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> - SetGlobalOutputChannelRemix(output_channels_, kStereoToStereo); + GetCrasAudioClient()->SetGlobalOutputChannelRemix( + output_channels_, + std::vector<double>(kStereoToStereo, std::end(kStereoToStereo))); } for (auto& observer : observers_) @@ -516,15 +522,10 @@ void CrasAudioHandler::SetActiveDevice(const AudioDevice& active_device, bool notify, DeviceActivateType activate_by) { - if (active_device.is_input) { - chromeos::DBusThreadManager::Get() - ->GetCrasAudioClient() - ->SetActiveInputNode(active_device.id); - } else { - chromeos::DBusThreadManager::Get() - ->GetCrasAudioClient() - ->SetActiveOutputNode(active_device.id); - } + if (active_device.is_input) + GetCrasAudioClient()->SetActiveInputNode(active_device.id); + else + GetCrasAudioClient()->SetActiveOutputNode(active_device.id); if (notify) NotifyActiveNodeChanged(active_device.is_input); @@ -580,7 +581,8 @@ if (device_id == active_output_node_id_) { SetOutputMute(mute_on); return; - } else if (device_id == active_input_node_id_) { + } + if (device_id == active_input_node_id_) { VLOG(1) << "SetMuteForDevice sets active input device id=" << "0x" << std::hex << device_id << " mute=" << mute_on; SetInputMute(mute_on); @@ -640,29 +642,22 @@ return; // If the DBusThreadManager or the CrasAudioClient aren't available, there // isn't much we can do. This should only happen when running tests. - if (!chromeos::DBusThreadManager::IsInitialized() || - !chromeos::DBusThreadManager::Get() || - !chromeos::DBusThreadManager::Get()->GetCrasAudioClient()) + if (!HasCrasAudioClient()) return; - chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->AddObserver(this); + GetCrasAudioClient()->AddObserver(this); audio_pref_handler_->AddAudioPrefObserver(this); - if (chromeos::DBusThreadManager::Get()->GetSessionManagerClient()) { - chromeos::DBusThreadManager::Get()->GetSessionManagerClient()-> - AddObserver(this); - } + if (DBusThreadManager::Get()->GetSessionManagerClient()) + DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this); InitializeAudioState(); } CrasAudioHandler::~CrasAudioHandler() { hdmi_rediscover_timer_.Stop(); - if (!chromeos::DBusThreadManager::IsInitialized() || - !chromeos::DBusThreadManager::Get() || - !chromeos::DBusThreadManager::Get()->GetCrasAudioClient()) + if (!HasCrasAudioClient()) return; - chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> - RemoveObserver(this); - chromeos::DBusThreadManager::Get()->GetSessionManagerClient()-> - RemoveObserver(this); + GetCrasAudioClient()->RemoveObserver(this); + if (DBusThreadManager::Get()->GetSessionManagerClient()) + DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this); if (audio_pref_handler_.get()) audio_pref_handler_->RemoveAudioPrefObserver(this); audio_pref_handler_ = nullptr; @@ -774,8 +769,7 @@ AudioDeviceMap::const_iterator it = audio_devices_.find(device_id); if (it == audio_devices_.end()) return nullptr; - - return &(it->second); + return &it->second; } const AudioDevice* CrasAudioHandler::GetDeviceFromStableDeviceId( @@ -877,11 +871,9 @@ // Defer querying cras for GetNodes until cras service becomes available. cras_service_available_ = false; - chromeos::DBusThreadManager::Get() - ->GetCrasAudioClient() - ->WaitForServiceToBeAvailable(base::Bind( - &CrasAudioHandler::InitializeAudioAfterCrasServiceAvailable, - weak_ptr_factory_.GetWeakPtr())); + GetCrasAudioClient()->WaitForServiceToBeAvailable( + base::Bind(&CrasAudioHandler::InitializeAudioAfterCrasServiceAvailable, + weak_ptr_factory_.GetWeakPtr())); } void CrasAudioHandler::InitializeAudioAfterCrasServiceAvailable( @@ -914,8 +906,7 @@ } void CrasAudioHandler::SetOutputNodeVolume(uint64_t node_id, int volume) { - chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> - SetOutputNodeVolume(node_id, volume); + GetCrasAudioClient()->SetOutputNodeVolume(node_id, volume); } void CrasAudioHandler::SetOutputNodeVolumePercent(uint64_t node_id, @@ -941,14 +932,12 @@ return false; output_mute_on_ = mute_on; - chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> - SetOutputUserMute(mute_on); + GetCrasAudioClient()->SetOutputUserMute(mute_on); return true; } void CrasAudioHandler::SetInputNodeGain(uint64_t node_id, int gain) { - chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> - SetInputNodeGain(node_id, gain); + GetCrasAudioClient()->SetInputNodeGain(node_id, gain); } void CrasAudioHandler::SetInputNodeGainPercent(uint64_t node_id, @@ -973,12 +962,11 @@ void CrasAudioHandler::SetInputMuteInternal(bool mute_on) { input_mute_on_ = mute_on; - chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> - SetInputMute(mute_on); + GetCrasAudioClient()->SetInputMute(mute_on); } void CrasAudioHandler::GetNodes() { - chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->GetNodes( + GetCrasAudioClient()->GetNodes( base::Bind(&CrasAudioHandler::HandleGetNodes, weak_ptr_factory_.GetWeakPtr()), base::Bind(&CrasAudioHandler::HandleGetNodesError, @@ -1087,20 +1075,20 @@ << " new device: " << device.ToString() << " old device: " << device_found->ToString(); return CHANGED_DEVICE; - } else if (device.active != device_found->active) { - return CHANGED_DEVICE; } - + if (device.active != device_found->active) + return CHANGED_DEVICE; return OLD_DEVICE; } void CrasAudioHandler::NotifyActiveNodeChanged(bool is_input) { - if (is_input) + if (is_input) { for (auto& observer : observers_) observer.OnActiveInputNodeChanged(); - else + } else { for (auto& observer : observers_) observer.OnActiveOutputNodeChanged(); + } } bool CrasAudioHandler::GetActiveDeviceFromUserPref(bool is_input, @@ -1135,12 +1123,7 @@ // Choose the best one among multiple active devices from prefs. if (activate_by_user) { - if (!last_active_device_activate_by_user) { - // Device activated by user has higher priority than the one - // is not activated by user. - *active_device = device; - last_active_device_activate_by_user = true; - } else { + if (last_active_device_activate_by_user) { // If there are more than one active devices activated by user in the // prefs, most likely, after the device was shut down, and before it // is rebooted, user has plugged in some previously unplugged audio @@ -1149,6 +1132,10 @@ VLOG(1) << "Found more than one user activated devices in the prefs."; return false; } + // Device activated by user has higher priority than the one + // is not activated by user. + *active_device = device; + last_active_device_activate_by_user = true; } else if (!last_active_device_activate_by_user) { // If there are more than one active devices activated by priority in the // prefs, most likely, cras is still enumerating the audio devices @@ -1423,16 +1410,12 @@ if (device->is_input) { DCHECK(node_id != active_input_node_id_); - chromeos::DBusThreadManager::Get() - ->GetCrasAudioClient() - ->AddActiveInputNode(node_id); + GetCrasAudioClient()->AddActiveInputNode(node_id); if (notify) NotifyActiveNodeChanged(true); } else { DCHECK(node_id != active_output_node_id_); - chromeos::DBusThreadManager::Get() - ->GetCrasAudioClient() - ->AddActiveOutputNode(node_id); + GetCrasAudioClient()->AddActiveOutputNode(node_id); if (notify) NotifyActiveNodeChanged(false); } @@ -1450,17 +1433,13 @@ if (device->is_input) { if (node_id == active_input_node_id_) active_input_node_id_ = 0; - chromeos::DBusThreadManager::Get() - ->GetCrasAudioClient() - ->RemoveActiveInputNode(node_id); + GetCrasAudioClient()->RemoveActiveInputNode(node_id); if (notify) NotifyActiveNodeChanged(true); } else { if (node_id == active_output_node_id_) active_output_node_id_ = 0; - chromeos::DBusThreadManager::Get() - ->GetCrasAudioClient() - ->RemoveActiveOutputNode(node_id); + GetCrasAudioClient()->RemoveActiveOutputNode(node_id); if (notify) NotifyActiveNodeChanged(false); } @@ -1484,7 +1463,7 @@ bool CrasAudioHandler::IsHDMIPrimaryOutputDevice() const { const AudioDevice* device = GetDeviceFromId(active_output_node_id_); - return (device && device->type == chromeos::AUDIO_TYPE_HDMI); + return device && device->type == AUDIO_TYPE_HDMI; } void CrasAudioHandler::StartHDMIRediscoverGracePeriod() {
diff --git a/chromeos/dbus/update_engine_client.cc b/chromeos/dbus/update_engine_client.cc index 9f855f06..5cfe3976 100644 --- a/chromeos/dbus/update_engine_client.cc +++ b/chromeos/dbus/update_engine_client.cc
@@ -9,6 +9,7 @@ #include <algorithm> #include "base/bind.h" +#include "base/callback.h" #include "base/command_line.h" #include "base/location.h" #include "base/macros.h" @@ -105,6 +106,15 @@ } void RequestUpdateCheck(const UpdateCheckCallback& callback) override { + if (!service_available_) { + // TODO(alemate): we probably need to remember callbacks only. + // When service becomes available, we can do a single request, + // and trigger all callbacks with the same return value. + pending_tasks_.push_back( + base::Bind(&UpdateEngineClientImpl::RequestUpdateCheck, + weak_ptr_factory_.GetWeakPtr(), callback)); + return; + } dbus::MethodCall method_call( update_engine::kUpdateEngineInterface, update_engine::kAttemptUpdate); @@ -255,6 +265,13 @@ private: void OnServiceInitiallyAvailable(bool service_is_available) { if (service_is_available) { + service_available_ = true; + std::vector<base::Closure> callbacks; + callbacks.swap(pending_tasks_); + for (const auto& callback : callbacks) { + callback.Run(); + } + // Get update engine status for the initial status. Update engine won't // send StatusUpdate signal unless there is a status change. If chrome // crashes after UPDATE_STATUS_UPDATED_NEED_REBOOT status is set, @@ -262,6 +279,7 @@ GetUpdateEngineStatus(); } else { LOG(ERROR) << "Failed to wait for D-Bus service to become available"; + pending_tasks_.clear(); } } @@ -482,6 +500,13 @@ base::ObserverList<Observer> observers_; Status last_status_; + // True after update_engine's D-Bus service has become available. + bool service_available_ = false; + + // This is a list of postponed calls to update engine to be called + // after it becomes available. + std::vector<base::Closure> pending_tasks_; + // Note: This should remain the last member so it'll be destroyed and // invalidate its weak pointers before any other members are destroyed. base::WeakPtrFactory<UpdateEngineClientImpl> weak_ptr_factory_;
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java index a0958c2b..8ea6dd3d 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java
@@ -48,7 +48,6 @@ JSONObject quicParams = new JSONObject() .put("connection_options", "PACE,IW10,FOO,DEADBEEF") .put("max_server_configs_stored_in_properties", 2) - .put("delay_tcp_race", true) .put("idle_connection_timeout_seconds", 300) .put("close_sessions_on_ip_change", false) .put("migrate_sessions_on_network_change", false)
diff --git a/components/cronet/android/test/smoketests/src/org/chromium/net/smoke/QuicTest.java b/components/cronet/android/test/smoketests/src/org/chromium/net/smoke/QuicTest.java index 6c91b0a3..1c0144d 100644 --- a/components/cronet/android/test/smoketests/src/org/chromium/net/smoke/QuicTest.java +++ b/components/cronet/android/test/smoketests/src/org/chromium/net/smoke/QuicTest.java
@@ -42,15 +42,14 @@ mCronetEngineBuilder.addQuicHint(url.getHost(), url.getPort(), url.getPort()); mTestSupport.installMockCertVerifierForTesting(mCronetEngineBuilder); - JSONObject quicParams = new JSONObject().put("delay_tcp_race", true); + JSONObject quicParams = new JSONObject(); JSONObject experimentalOptions = new JSONObject().put("QUIC", quicParams); mTestSupport.addHostResolverRules(experimentalOptions); mCronetEngineBuilder.setExperimentalOptions(experimentalOptions.toString()); initCronetEngine(); - // QUIC is not guaranteed to win the race even with |delay_tcp_race| set, so try - // multiple times. + // QUIC is not guaranteed to win the race, so try multiple times. boolean quicNegotiated = false; for (int i = 0; i < 5; i++) {
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc index 340e57c..6a2f8c3 100644 --- a/components/cronet/url_request_context_config.cc +++ b/components/cronet/url_request_context_config.cc
@@ -41,7 +41,6 @@ "store_server_configs_in_properties"; const char kQuicMaxServerConfigsStoredInProperties[] = "max_server_configs_stored_in_properties"; -const char kQuicDelayTcpRace[] = "delay_tcp_race"; const char kQuicIdleConnectionTimeoutSeconds[] = "idle_connection_timeout_seconds"; const char kQuicCloseSessionsOnIpChange[] = "close_sessions_on_ip_change"; @@ -160,11 +159,6 @@ static_cast<size_t>(quic_max_server_configs_stored_in_properties)); } - bool quic_delay_tcp_race = false; - if (quic_args->GetBoolean(kQuicDelayTcpRace, &quic_delay_tcp_race)) { - context_builder->set_quic_delay_tcp_race(quic_delay_tcp_race); - } - int quic_idle_connection_timeout_seconds = 0; if (quic_args->GetInteger(kQuicIdleConnectionTimeoutSeconds, &quic_idle_connection_timeout_seconds)) {
diff --git a/components/cronet/url_request_context_config_unittest.cc b/components/cronet/url_request_context_config_unittest.cc index 7b926e4e..1e6711e 100644 --- a/components/cronet/url_request_context_config_unittest.cc +++ b/components/cronet/url_request_context_config_unittest.cc
@@ -44,7 +44,6 @@ "fake agent", // JSON encoded experimental options. "{\"QUIC\":{\"max_server_configs_stored_in_properties\":2," - "\"delay_tcp_race\":true," "\"user_agent_id\":\"Custom QUIC UAID\"," "\"idle_connection_timeout_seconds\":300," "\"close_sessions_on_ip_change\":true," @@ -98,9 +97,6 @@ // Check max_server_configs_stored_in_properties. EXPECT_EQ(2u, params->quic_max_server_configs_stored_in_properties); - // Check delay_tcp_race. - EXPECT_TRUE(params->quic_delay_tcp_race); - // Check idle_connection_timeout_seconds. EXPECT_EQ(300, params->quic_idle_connection_timeout_seconds);
diff --git a/components/network_session_configurator/network_session_configurator.cc b/components/network_session_configurator/network_session_configurator.cc index e12cc1c..a0432839 100644 --- a/components/network_session_configurator/network_session_configurator.cc +++ b/components/network_session_configurator/network_session_configurator.cc
@@ -134,44 +134,17 @@ return net::ParseQuicConnectionOptions(it->second); } -float GetQuicLoadServerInfoTimeoutSrttMultiplier( - const VariationParameters& quic_trial_params) { - double value; - if (base::StringToDouble( - GetVariationParam(quic_trial_params, "load_server_info_time_to_srtt"), - &value)) { - return static_cast<float>(value); - } - return 0.0f; -} - -bool ShouldQuicEnableConnectionRacing( - const VariationParameters& quic_trial_params) { - return base::LowerCaseEqualsASCII( - GetVariationParam(quic_trial_params, "enable_connection_racing"), "true"); -} - bool ShouldQuicEnableNonBlockingIO( const VariationParameters& quic_trial_params) { return base::LowerCaseEqualsASCII( GetVariationParam(quic_trial_params, "enable_non_blocking_io"), "true"); } -bool ShouldQuicDisableDiskCache(const VariationParameters& quic_trial_params) { - return base::LowerCaseEqualsASCII( - GetVariationParam(quic_trial_params, "disable_disk_cache"), "true"); -} - bool ShouldForceHolBlocking(const VariationParameters& quic_trial_params) { return base::LowerCaseEqualsASCII( GetVariationParam(quic_trial_params, "force_hol_blocking"), "true"); } -bool ShouldQuicDelayTcpRace(const VariationParameters& quic_trial_params) { - return !base::LowerCaseEqualsASCII( - GetVariationParam(quic_trial_params, "disable_delay_tcp_race"), "true"); -} - bool ShouldQuicCloseSessionsOnIpChange( const VariationParameters& quic_trial_params) { return base::LowerCaseEqualsASCII( @@ -300,19 +273,8 @@ ShouldRetryWithoutAltSvcOnQuicErrors(quic_trial_params); if (params->enable_quic) { - params->quic_delay_tcp_race = ShouldQuicDelayTcpRace(quic_trial_params); - float load_server_info_timeout_srtt_multiplier = - GetQuicLoadServerInfoTimeoutSrttMultiplier(quic_trial_params); - if (load_server_info_timeout_srtt_multiplier != 0) { - params->quic_load_server_info_timeout_srtt_multiplier = - load_server_info_timeout_srtt_multiplier; - } - params->quic_enable_connection_racing = - ShouldQuicEnableConnectionRacing(quic_trial_params); params->quic_enable_non_blocking_io = ShouldQuicEnableNonBlockingIO(quic_trial_params); - params->quic_disable_disk_cache = - ShouldQuicDisableDiskCache(quic_trial_params); params->quic_force_hol_blocking = ShouldForceHolBlocking(quic_trial_params); params->quic_connection_options = GetQuicConnectionOptions(quic_trial_params);
diff --git a/components/network_session_configurator/network_session_configurator_unittest.cc b/components/network_session_configurator/network_session_configurator_unittest.cc index f7b8048..b9a21af 100644 --- a/components/network_session_configurator/network_session_configurator_unittest.cc +++ b/components/network_session_configurator/network_session_configurator_unittest.cc
@@ -70,12 +70,8 @@ EXPECT_FALSE(params_.retry_without_alt_svc_on_quic_errors); EXPECT_EQ(1350u, params_.quic_max_packet_length); EXPECT_EQ(net::QuicTagVector(), params_.quic_connection_options); - EXPECT_EQ(0.25f, params_.quic_load_server_info_timeout_srtt_multiplier); - EXPECT_FALSE(params_.quic_enable_connection_racing); EXPECT_FALSE(params_.enable_server_push_cancellation); EXPECT_FALSE(params_.quic_enable_non_blocking_io); - EXPECT_FALSE(params_.quic_disable_disk_cache); - EXPECT_TRUE(params_.quic_delay_tcp_race); EXPECT_FALSE(params_.quic_close_sessions_on_ip_change); EXPECT_EQ(net::kIdleConnectionTimeoutSeconds, params_.quic_idle_connection_timeout_seconds); @@ -340,29 +336,6 @@ EXPECT_EQ(expected_settings, params_.http2_settings); } -TEST_F(NetworkSessionConfiguratorTest, - QuicLoadServerInfoTimeToSmoothedRttFromFieldTrialParams) { - std::map<std::string, std::string> field_trial_params; - field_trial_params["load_server_info_time_to_srtt"] = "0.5"; - variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params); - base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); - - ParseFieldTrials(); - - EXPECT_EQ(0.5f, params_.quic_load_server_info_timeout_srtt_multiplier); -} - -TEST_F(NetworkSessionConfiguratorTest, QuicEnableConnectionRacing) { - std::map<std::string, std::string> field_trial_params; - field_trial_params["enable_connection_racing"] = "true"; - variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params); - base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); - - ParseFieldTrials(); - - EXPECT_TRUE(params_.quic_enable_connection_racing); -} - TEST_F(NetworkSessionConfiguratorTest, QuicEnableNonBlockingIO) { std::map<std::string, std::string> field_trial_params; field_trial_params["enable_non_blocking_io"] = "true"; @@ -374,28 +347,6 @@ EXPECT_TRUE(params_.quic_enable_non_blocking_io); } -TEST_F(NetworkSessionConfiguratorTest, QuicDisableDiskCache) { - std::map<std::string, std::string> field_trial_params; - field_trial_params["disable_disk_cache"] = "true"; - variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params); - base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); - - ParseFieldTrials(); - - EXPECT_TRUE(params_.quic_disable_disk_cache); -} - -TEST_F(NetworkSessionConfiguratorTest, QuicDisableDelayTcpRace) { - std::map<std::string, std::string> field_trial_params; - field_trial_params["disable_delay_tcp_race"] = "true"; - variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params); - base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); - - ParseFieldTrials(); - - EXPECT_FALSE(params_.quic_delay_tcp_race); -} - TEST_F(NetworkSessionConfiguratorTest, TCPFastOpenHttpsEnabled) { base::FieldTrialList::CreateFieldTrial("TCPFastOpen", "HttpsEnabled");
diff --git a/components/proximity_auth/proximity_auth_system.cc b/components/proximity_auth/proximity_auth_system.cc index 50b7732..4b70d68 100644 --- a/components/proximity_auth/proximity_auth_system.cc +++ b/components/proximity_auth/proximity_auth_system.cc
@@ -12,14 +12,6 @@ namespace proximity_auth { -namespace { - -// The time to wait after the device wakes up before beginning to connect to the -// remote device. -const int kWakeUpTimeoutSeconds = 2; - -} // namespace - ProximityAuthSystem::ProximityAuthSystem( ScreenlockType screenlock_type, ProximityAuthClient* proximity_auth_client) @@ -99,22 +91,6 @@ void ProximityAuthSystem::OnSuspendDone() { PA_LOG(INFO) << "Device resumed from suspension."; DCHECK(suspended_); - - // TODO(tengs): On ChromeOS, the system's Bluetooth adapter is invalidated - // when the system suspends. However, Chrome does not receive this - // notification until a second or so after the system wakes up. That means - // using the adapter during this time will be problematic, so we wait instead. - // See crbug.com/537057. - proximity_auth_client_->UpdateScreenlockState( - ScreenlockState::BLUETOOTH_CONNECTING); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&ProximityAuthSystem::ResumeAfterWakeUpTimeout, - weak_ptr_factory_.GetWeakPtr()), - base::TimeDelta::FromSeconds(kWakeUpTimeoutSeconds)); -} - -void ProximityAuthSystem::ResumeAfterWakeUpTimeout() { - PA_LOG(INFO) << "Resume after suspend"; suspended_ = false; if (!ScreenlockBridge::Get()->IsLocked()) {
diff --git a/components/storage_monitor/portable_device_watcher_win.cc b/components/storage_monitor/portable_device_watcher_win.cc index 1fa2e23..44d2885 100644 --- a/components/storage_monitor/portable_device_watcher_win.cc +++ b/components/storage_monitor/portable_device_watcher_win.cc
@@ -158,7 +158,7 @@ return false; } - hr = (*device)->Open(pnp_device_id.c_str(), client_info.get()); + hr = (*device)->Open(pnp_device_id.c_str(), client_info.Get()); if (SUCCEEDED(hr)) return true; @@ -231,13 +231,13 @@ base::win::ScopedComPtr<IPortableDeviceValues> properties_values; if (FAILED(properties->GetValues(object_id.c_str(), - properties_to_read.get(), + properties_to_read.Get(), properties_values.Receive()))) { return false; } REFPROPERTYKEY key = GetUniqueIdPropertyKey(object_id); - return GetStringPropertyValue(properties_values.get(), key, unique_id); + return GetStringPropertyValue(properties_values.Get(), key, unique_id); } // Constructs the device storage unique identifier using |device_serial_num| and @@ -336,18 +336,18 @@ return false; base::string16 device_serial_num; - if (!GetObjectUniqueId(device.get(), WPD_DEVICE_OBJECT_ID, + if (!GetObjectUniqueId(device.Get(), WPD_DEVICE_OBJECT_ID, &device_serial_num)) { return false; } PortableDeviceWatcherWin::StorageObjectIDs storage_obj_ids; - if (!GetRemovableStorageObjectIds(device.get(), &storage_obj_ids)) + if (!GetRemovableStorageObjectIds(device.Get(), &storage_obj_ids)) return false; for (PortableDeviceWatcherWin::StorageObjectIDs::const_iterator id_iter = storage_obj_ids.begin(); id_iter != storage_obj_ids.end(); ++id_iter) { base::string16 storage_persistent_id; - if (!GetObjectUniqueId(device.get(), *id_iter, &storage_persistent_id)) + if (!GetObjectUniqueId(device.Get(), *id_iter, &storage_persistent_id)) continue; std::string device_storage_id; @@ -423,7 +423,7 @@ for (DWORD index = 0; index < pnp_device_count; ++index) { PortableDeviceWatcherWin::DeviceDetails device_details; - if (GetDeviceInfoOnBlockingThread(portable_device_mgr.get(), + if (GetDeviceInfoOnBlockingThread(portable_device_mgr.Get(), pnp_device_ids[index], &device_details)) devices->push_back(device_details); CoTaskMemFree(pnp_device_ids[index]); @@ -446,7 +446,7 @@ // Sometimes, portable device manager doesn't have the new device details. // Refresh the manager device list to update its details. portable_device_mgr->RefreshDeviceList(); - return GetDeviceInfoOnBlockingThread(portable_device_mgr.get(), pnp_device_id, + return GetDeviceInfoOnBlockingThread(portable_device_mgr.Get(), pnp_device_id, device_details); }
diff --git a/components/translate/core/common/translate_metrics.cc b/components/translate/core/common/translate_metrics.cc index ae31a23..572bcbb 100644 --- a/components/translate/core/common/translate_metrics.cc +++ b/components/translate/core/common/translate_metrics.cc
@@ -6,9 +6,11 @@ #include <stddef.h> #include <stdint.h> +#include <algorithm> #include "base/macros.h" #include "base/metrics/histogram_macros.h" +#include "base/metrics/metrics_hashes.h" #include "url/url_constants.h" namespace translate { @@ -27,6 +29,8 @@ const char kTranslateUserActionDuration[] = "Translate.UserActionDuration"; const char kTranslatePageScheme[] = "Translate.PageScheme"; const char kTranslateSimilarLanguageMatch[] = "Translate.SimilarLanguageMatch"; +const char kTranslateLanguageDetectionConflict[] = + "Translate.LanguageDetectionConflict"; struct MetricsEntry { MetricsNameIndex index; @@ -44,11 +48,17 @@ {UMA_TIME_TO_TRANSLATE, kTranslateTimeToTranslate}, {UMA_USER_ACTION_DURATION, kTranslateUserActionDuration}, {UMA_PAGE_SCHEME, kTranslatePageScheme}, - {UMA_SIMILAR_LANGUAGE_MATCH, kTranslateSimilarLanguageMatch}, }; + {UMA_SIMILAR_LANGUAGE_MATCH, kTranslateSimilarLanguageMatch}, + {UMA_LANGUAGE_DETECTION_CONFLICT, kTranslateLanguageDetectionConflict}, +}; static_assert(arraysize(kMetricsEntries) == UMA_MAX, "kMetricsEntries should have UMA_MAX elements"); +// Page languages for which we track CLD3 language conflicts. +const char* kLanguageDetectionConflictPageLangs[] = { + "en", "en-US", "en-GB", "en-CA", "en-AU", "en-NZ", "en-ZA", "en-IN"}; + LanguageCheckType GetLanguageCheckMetric(const std::string& provided_code, const std::string& revised_code) { if (provided_code.empty()) @@ -75,8 +85,7 @@ } void ReportLanguageVerification(LanguageVerificationType type) { - UMA_HISTOGRAM_ENUMERATION(kTranslateLanguageVerification, - type, + UMA_HISTOGRAM_ENUMERATION(kTranslateLanguageVerification, type, LANGUAGE_VERIFICATION_MAX); } @@ -119,6 +128,19 @@ UMA_HISTOGRAM_BOOLEAN(kTranslateSimilarLanguageMatch, match); } +void ReportLanguageDetectionConflict(const std::string& page_lang, + const std::string& cld_lang) { + const char* const* const it = + std::find(std::begin(kLanguageDetectionConflictPageLangs), + std::end(kLanguageDetectionConflictPageLangs), page_lang); + const std::string page_lang_token = + it == std::end(kLanguageDetectionConflictPageLangs) ? "other" : *it; + + UMA_HISTOGRAM_SPARSE_SLOWLY( + kTranslateLanguageDetectionConflict, + base::HashMetricName(page_lang_token + "," + cld_lang)); +} + const char* GetMetricsName(MetricsNameIndex index) { for (size_t i = 0; i < arraysize(kMetricsEntries); ++i) { if (kMetricsEntries[i].index == index)
diff --git a/components/translate/core/common/translate_metrics.h b/components/translate/core/common/translate_metrics.h index b6cc184..b1cf988 100644 --- a/components/translate/core/common/translate_metrics.h +++ b/components/translate/core/common/translate_metrics.h
@@ -24,6 +24,7 @@ UMA_USER_ACTION_DURATION, UMA_PAGE_SCHEME, UMA_SIMILAR_LANGUAGE_MATCH, + UMA_LANGUAGE_DETECTION_CONFLICT, UMA_MAX, }; @@ -96,6 +97,11 @@ // language list. void ReportSimilarLanguageMatch(bool match); +// Called when page language is "en*" and doesn't match the CLD language; i.e +// when we suspect that the page language is incorrect. +void ReportLanguageDetectionConflict(const std::string& page_lang, + const std::string& cld_lang); + // Gets UMA name for an entry specified by |index|. const char* GetMetricsName(MetricsNameIndex index);
diff --git a/components/translate/core/common/translate_metrics_unittest.cc b/components/translate/core/common/translate_metrics_unittest.cc index 42c89279..ac67025 100644 --- a/components/translate/core/common/translate_metrics_unittest.cc +++ b/components/translate/core/common/translate_metrics_unittest.cc
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/metrics/histogram.h" #include "base/metrics/histogram_samples.h" +#include "base/metrics/metrics_hashes.h" #include "base/metrics/statistics_recorder.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -286,4 +287,28 @@ recorder.CheckTotalCount(1); } +TEST(TranslateMetricsTest, ReportLanguageDetectionConflict) { + MetricsRecorder recorder( + translate::GetMetricsName(translate::UMA_LANGUAGE_DETECTION_CONFLICT)); + recorder.CheckTotalCount(0); + + translate::ReportLanguageDetectionConflict("en", "es"); + recorder.CheckTotalCount(1); + EXPECT_EQ(recorder.GetCount(base::HashMetricName("en,es")), 1); + + translate::ReportLanguageDetectionConflict("en", "es"); + recorder.CheckTotalCount(2); + EXPECT_EQ(recorder.GetCount(base::HashMetricName("en,es")), 2); + + translate::ReportLanguageDetectionConflict("en-AU", "ru-Latn"); + recorder.CheckTotalCount(3); + EXPECT_EQ(recorder.GetCount(base::HashMetricName("en-AU,ru-Latn")), 1); + + // We don't track "en-XX" or "en-YY" as page codes. + translate::ReportLanguageDetectionConflict("en-XX", "es"); + translate::ReportLanguageDetectionConflict("en-YY", "es"); + recorder.CheckTotalCount(5); + EXPECT_EQ(recorder.GetCount(base::HashMetricName("other,es")), 2); +} + } // namespace translate
diff --git a/components/translate/core/language_detection/language_detection_util.cc b/components/translate/core/language_detection/language_detection_util.cc index e989c54b..7c39356 100644 --- a/components/translate/core/language_detection/language_detection_util.cc +++ b/components/translate/core/language_detection/language_detection_util.cc
@@ -291,6 +291,13 @@ std::string language = modified_html_lang.empty() ? modified_code : modified_html_lang; + // When the page language is English, log conflicting CLD results. We will use + // these metrics to decide when to favor CLD. + if (language.substr(0, 2) == "en" && cld_language.substr(0, 2) != "en" && + cld_language != kUnknownLanguageCode) { + translate::ReportLanguageDetectionConflict(language, cld_language); + } + // If |language| is empty, just use CLD result even though it might be // translate::kUnknownLanguageCode. if (language.empty()) { @@ -324,7 +331,7 @@ } // Content-Language value might be wrong because CLD says that this page is - // written in another language with confidence. In this case, Chrome doesn't + // written in another language with confidence. In this case, Chrome doesn't // rely on any of the language codes, and gives up suggesting a translation. translate::ReportLanguageVerification( translate::LANGUAGE_VERIFICATION_CLD_DISAGREE);
diff --git a/components/update_client/background_downloader_win.cc b/components/update_client/background_downloader_win.cc index 857e2bb..cdbc519 100644 --- a/components/update_client/background_downloader_win.cc +++ b/components/update_client/background_downloader_win.cc
@@ -148,7 +148,7 @@ HRESULT RegisterInterfaceInGit(const ScopedComPtr<IGlobalInterfaceTable>& git, const ScopedComPtr<T>& p, DWORD* cookie) { - return git->RegisterInterfaceInGlobal(p.get(), __uuidof(T), cookie); + return git->RegisterInterfaceInGlobal(p.Get(), __uuidof(T), cookie); } // Returns the status code from a given BITS error. @@ -179,7 +179,7 @@ for (ULONG i = 0; i != num_files; ++i) { ScopedComPtr<IBackgroundCopyFile> file; - if (enum_files->Next(1, file.Receive(), NULL) == S_OK && file.get()) + if (enum_files->Next(1, file.Receive(), NULL) == S_OK && file.Get()) files->push_back(file); } @@ -300,9 +300,9 @@ for (ULONG i = 0; i != job_count; ++i) { ScopedComPtr<IBackgroundCopyJob> current_job; if (enum_jobs->Next(1, current_job.Receive(), NULL) == S_OK && - pred(current_job.get())) { + pred(current_job.Get())) { base::string16 job_description; - hr = GetJobDescription(current_job.get(), &job_description); + hr = GetJobDescription(current_job.Get(), &job_description); if (job_description.compare(kJobDescription) == 0) jobs->push_back(current_job); } @@ -379,7 +379,7 @@ return; for (size_t i = 0; i != files.size(); ++i) { base::string16 local_name; - HRESULT hr(GetJobFileProperties(files[i].get(), &local_name, NULL, NULL)); + HRESULT hr(GetJobFileProperties(files[i].Get(), &local_name, NULL, NULL)); if (SUCCEEDED(hr)) DeleteFileAndEmptyParentDirectory(base::FilePath(local_name)); } @@ -388,7 +388,7 @@ // Cleans up incompleted jobs that are too old. HRESULT CleanupStaleJobs( const ScopedComPtr<IBackgroundCopyManager>& bits_manager) { - if (!bits_manager.get()) + if (!bits_manager.Get()) return E_FAIL; static base::Time last_sweep; @@ -404,13 +404,13 @@ std::vector<ScopedComPtr<IBackgroundCopyJob>> jobs; HRESULT hr = FindBitsJobIf( JobCreationOlderThanDays(kPurgeStaleJobsAfterDays), - bits_manager.get(), &jobs); + bits_manager.Get(), &jobs); if (FAILED(hr)) return hr; for (size_t i = 0; i != jobs.size(); ++i) { jobs[i]->Cancel(); - CleanupJobFiles(jobs[i].get()); + CleanupJobFiles(jobs[i].Get()); } return S_OK; @@ -581,11 +581,11 @@ int64_t downloaded_bytes = -1; int64_t total_bytes = -1; - GetJobByteCount(job_.get(), &downloaded_bytes, &total_bytes); + GetJobByteCount(job_.Get(), &downloaded_bytes, &total_bytes); - if (FAILED(error) && job_.get()) { + if (FAILED(error) && job_.Get()) { job_->Cancel(); - CleanupJobFiles(job_.get()); + CleanupJobFiles(job_.Get()); } CleanupStaleJobs(bits_manager_); @@ -635,7 +635,7 @@ // be made. Cancels this job and removes it from the BITS queue. bool BackgroundDownloader::OnStateError() { HRESULT error_code = S_OK; - HRESULT hr = GetJobError(job_.get(), &error_code); + HRESULT hr = GetJobError(job_.Get(), &error_code); if (FAILED(hr)) error_code = hr; @@ -670,7 +670,7 @@ // Don't retry at all if the transient error was a 5xx. HRESULT error_code = S_OK; - HRESULT hr = GetJobError(job_.get(), &error_code); + HRESULT hr = GetJobError(job_.Get(), &error_code); if (SUCCEEDED(hr) && IsHttpServerError(GetHttpStatusFromBitsError(error_code))) { return OnStateError(); @@ -695,7 +695,7 @@ int64_t downloaded_bytes = -1; int64_t total_bytes = -1; - HRESULT hr = GetJobByteCount(job_.get(), &downloaded_bytes, &total_bytes); + HRESULT hr = GetJobByteCount(job_.Get(), &downloaded_bytes, &total_bytes); if (FAILED(hr)) return false; @@ -741,7 +741,7 @@ std::vector<ScopedComPtr<IBackgroundCopyJob>> jobs; HRESULT hr = FindBitsJobIf( JobFileUrlEqual(base::SysUTF8ToWide(url.spec())), - bits_manager_.get(), &jobs); + bits_manager_.Get(), &jobs); if (SUCCEEDED(hr) && !jobs.empty()) { *job = jobs.front().Detach(); return S_FALSE; @@ -809,7 +809,7 @@ return hr; std::vector<ScopedComPtr<IBackgroundCopyFile>> files; - hr = GetFilesInJob(job_.get(), &files); + hr = GetFilesInJob(job_.Get(), &files); if (FAILED(hr)) return hr; @@ -818,7 +818,7 @@ base::string16 local_name; BG_FILE_PROGRESS progress = {0}; - hr = GetJobFileProperties(files.front().get(), &local_name, NULL, &progress); + hr = GetJobFileProperties(files.front().Get(), &local_name, NULL, &progress); if (FAILED(hr)) return hr;
diff --git a/components/viz/frame_sinks/BUILD.gn b/components/viz/frame_sinks/BUILD.gn index 750e684..2c7012e 100644 --- a/components/viz/frame_sinks/BUILD.gn +++ b/components/viz/frame_sinks/BUILD.gn
@@ -2,9 +2,15 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("frame_sinks") { +component("frame_sinks") { + defines = [ "VIZ_IMPLEMENTATION" ] + sources = [ "display_provider.h", + "frame_eviction_manager.cc", + "frame_eviction_manager.h", + "frame_evictor.cc", + "frame_evictor.h", "gpu_compositor_frame_sink.cc", "gpu_compositor_frame_sink.h", "gpu_compositor_frame_sink_delegate.h", @@ -12,6 +18,7 @@ "gpu_root_compositor_frame_sink.h", "mojo_frame_sink_manager.cc", "mojo_frame_sink_manager.h", + "viz_export.h", ] deps = [ @@ -22,4 +29,8 @@ "//components/display_compositor", "//gpu/ipc:command_buffer", ] + + if (is_win) { + cflags = [ "/wd4267" ] # conversion from 'size_t' to 'int' on x64 (crbug.com/633312) + } }
diff --git a/components/viz/frame_sinks/DEPS b/components/viz/frame_sinks/DEPS index fc0222f..9694315 100644 --- a/components/viz/frame_sinks/DEPS +++ b/components/viz/frame_sinks/DEPS
@@ -3,4 +3,5 @@ "+cc/ipc", "+cc/surfaces", "+cc/scheduler", + "+components/display_compositor", ]
diff --git a/content/browser/renderer_host/renderer_frame_manager.cc b/components/viz/frame_sinks/frame_eviction_manager.cc similarity index 73% rename from content/browser/renderer_host/renderer_frame_manager.cc rename to components/viz/frame_sinks/frame_eviction_manager.cc index e8944e4..625f7ea 100644 --- a/content/browser/renderer_host/renderer_frame_manager.cc +++ b/components/viz/frame_sinks/frame_eviction_manager.cc
@@ -1,8 +1,8 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/renderer_frame_manager.h" +#include "components/viz/frame_sinks/frame_eviction_manager.h" #include <algorithm> @@ -16,9 +16,8 @@ #include "base/sys_info.h" #include "build/build_config.h" #include "components/display_compositor/host_shared_bitmap_manager.h" -#include "content/public/common/content_features.h" -namespace content { +namespace viz { namespace { const int kModeratePressurePercentage = 50; @@ -26,11 +25,11 @@ } // namespace -RendererFrameManager* RendererFrameManager::GetInstance() { - return base::Singleton<RendererFrameManager>::get(); +FrameEvictionManager* FrameEvictionManager::GetInstance() { + return base::Singleton<FrameEvictionManager>::get(); } -void RendererFrameManager::AddFrame(RendererFrameManagerClient* frame, +void FrameEvictionManager::AddFrame(FrameEvictionManagerClient* frame, bool locked) { RemoveFrame(frame); if (locked) @@ -40,17 +39,17 @@ CullUnlockedFrames(GetMaxNumberOfSavedFrames()); } -void RendererFrameManager::RemoveFrame(RendererFrameManagerClient* frame) { - std::map<RendererFrameManagerClient*, size_t>::iterator locked_iter = +void FrameEvictionManager::RemoveFrame(FrameEvictionManagerClient* frame) { + std::map<FrameEvictionManagerClient*, size_t>::iterator locked_iter = locked_frames_.find(frame); if (locked_iter != locked_frames_.end()) locked_frames_.erase(locked_iter); unlocked_frames_.remove(frame); } -void RendererFrameManager::LockFrame(RendererFrameManagerClient* frame) { - std::list<RendererFrameManagerClient*>::iterator unlocked_iter = - std::find(unlocked_frames_.begin(), unlocked_frames_.end(), frame); +void FrameEvictionManager::LockFrame(FrameEvictionManagerClient* frame) { + std::list<FrameEvictionManagerClient*>::iterator unlocked_iter = + std::find(unlocked_frames_.begin(), unlocked_frames_.end(), frame); if (unlocked_iter != unlocked_frames_.end()) { DCHECK(locked_frames_.find(frame) == locked_frames_.end()); unlocked_frames_.remove(frame); @@ -61,7 +60,7 @@ } } -void RendererFrameManager::UnlockFrame(RendererFrameManagerClient* frame) { +void FrameEvictionManager::UnlockFrame(FrameEvictionManagerClient* frame) { DCHECK(locked_frames_.find(frame) != locked_frames_.end()); size_t locked_count = locked_frames_[frame]; DCHECK(locked_count); @@ -74,11 +73,11 @@ } } -size_t RendererFrameManager::GetMaxNumberOfSavedFrames() const { +size_t FrameEvictionManager::GetMaxNumberOfSavedFrames() const { int percentage = 100; - if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) { - switch (base::MemoryCoordinatorProxy::GetInstance()-> - GetCurrentMemoryState()) { + auto* memory_coordinator_proxy = base::MemoryCoordinatorProxy::GetInstance(); + if (memory_coordinator_proxy) { + switch (memory_coordinator_proxy->GetCurrentMemoryState()) { case base::MemoryState::NORMAL: percentage = 100; break; @@ -114,10 +113,10 @@ return std::max(static_cast<size_t>(1), frames); } -RendererFrameManager::RendererFrameManager() - : memory_pressure_listener_(new base::MemoryPressureListener( - base::Bind(&RendererFrameManager::OnMemoryPressure, - base::Unretained(this)))) { +FrameEvictionManager::FrameEvictionManager() + : memory_pressure_listener_(new base::MemoryPressureListener( + base::Bind(&FrameEvictionManager::OnMemoryPressure, + base::Unretained(this)))) { base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this); max_number_of_saved_frames_ = #if defined(OS_ANDROID) @@ -130,9 +129,9 @@ max_handles_ = base::SharedMemory::GetHandleLimit() / 8.0f; } -RendererFrameManager::~RendererFrameManager() {} +FrameEvictionManager::~FrameEvictionManager() {} -void RendererFrameManager::CullUnlockedFrames(size_t saved_frame_limit) { +void FrameEvictionManager::CullUnlockedFrames(size_t saved_frame_limit) { if (unlocked_frames_.size() + locked_frames_.size() > 0) { float handles_per_frame = display_compositor::HostSharedBitmapManager::current() @@ -140,9 +139,8 @@ 1.0f / (unlocked_frames_.size() + locked_frames_.size()); saved_frame_limit = std::max( - 1, - static_cast<int>(std::min(static_cast<float>(saved_frame_limit), - max_handles_ / handles_per_frame))); + 1, static_cast<int>(std::min(static_cast<float>(saved_frame_limit), + max_handles_ / handles_per_frame))); } while (!unlocked_frames_.empty() && unlocked_frames_.size() + locked_frames_.size() > saved_frame_limit) { @@ -153,7 +151,7 @@ } } -void RendererFrameManager::OnMemoryPressure( +void FrameEvictionManager::OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { switch (memory_pressure_level) { case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: @@ -168,15 +166,15 @@ } } -void RendererFrameManager::OnPurgeMemory() { +void FrameEvictionManager::OnPurgeMemory() { PurgeMemory(kCriticalPressurePercentage); } -void RendererFrameManager::PurgeMemory(int percentage) { +void FrameEvictionManager::PurgeMemory(int percentage) { int saved_frame_limit = max_number_of_saved_frames_; if (saved_frame_limit <= 1) return; CullUnlockedFrames(std::max(1, (saved_frame_limit * percentage) / 100)); } -} // namespace content +} // namespace viz
diff --git a/components/viz/frame_sinks/frame_eviction_manager.h b/components/viz/frame_sinks/frame_eviction_manager.h new file mode 100644 index 0000000..884ab9f01 --- /dev/null +++ b/components/viz/frame_sinks/frame_eviction_manager.h
@@ -0,0 +1,82 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_FRAME_SINKS_FRAME_EVICTION_MANAGER_H_ +#define COMPONENTS_VIZ_FRAME_SINKS_FRAME_EVICTION_MANAGER_H_ + +#include <stddef.h> + +#include <list> +#include <map> + +#include "base/macros.h" +#include "base/memory/memory_coordinator_client.h" +#include "base/memory/memory_pressure_listener.h" +#include "base/memory/singleton.h" +#include "components/viz/frame_sinks/viz_export.h" + +namespace viz { + +class VIZ_EXPORT FrameEvictionManagerClient { + public: + virtual ~FrameEvictionManagerClient() {} + virtual void EvictCurrentFrame() = 0; +}; + +// This class is responsible for globally managing which renderers keep their +// compositor frame when offscreen. We actively discard compositor frames for +// offscreen tabs, but keep a minimum amount, as an LRU cache, to make switching +// between a small set of tabs faster. The limit is a soft limit, because +// clients can lock their frame to prevent it from being discarded, e.g. if the +// tab is visible, or while capturing a screenshot. +class VIZ_EXPORT FrameEvictionManager : public base::MemoryCoordinatorClient { + public: + static FrameEvictionManager* GetInstance(); + + void AddFrame(FrameEvictionManagerClient*, bool locked); + void RemoveFrame(FrameEvictionManagerClient*); + void LockFrame(FrameEvictionManagerClient*); + void UnlockFrame(FrameEvictionManagerClient*); + + size_t GetMaxNumberOfSavedFrames() const; + + // For testing only + void set_max_number_of_saved_frames(size_t max_number_of_saved_frames) { + max_number_of_saved_frames_ = max_number_of_saved_frames; + } + void set_max_handles(float max_handles) { max_handles_ = max_handles; } + + // React on memory pressure events to adjust the number of cached frames. + // Please make this private when crbug.com/443824 has been fixed. + void OnMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); + + private: + FrameEvictionManager(); + ~FrameEvictionManager() override; + + // base::MemoryCoordinatorClient implementation: + void OnPurgeMemory() override; + + void CullUnlockedFrames(size_t saved_frame_limit); + + void PurgeMemory(int percentage); + + friend struct base::DefaultSingletonTraits<FrameEvictionManager>; + + // Listens for system under pressure notifications and adjusts number of + // cached frames accordingly. + std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; + + std::map<FrameEvictionManagerClient*, size_t> locked_frames_; + std::list<FrameEvictionManagerClient*> unlocked_frames_; + size_t max_number_of_saved_frames_; + float max_handles_; + + DISALLOW_COPY_AND_ASSIGN(FrameEvictionManager); +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_FRAME_SINKS_FRAME_EVICTION_MANAGER_H_
diff --git a/components/viz/frame_sinks/frame_evictor.cc b/components/viz/frame_sinks/frame_evictor.cc new file mode 100644 index 0000000..0207423 --- /dev/null +++ b/components/viz/frame_sinks/frame_evictor.cc
@@ -0,0 +1,56 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/frame_sinks/frame_evictor.h" + +#include "base/logging.h" + +namespace viz { + +FrameEvictor::FrameEvictor(FrameEvictorClient* client) + : client_(client), has_frame_(false), visible_(false) {} + +FrameEvictor::~FrameEvictor() { + DiscardedFrame(); +} + +void FrameEvictor::SwappedFrame(bool visible) { + visible_ = visible; + has_frame_ = true; + FrameEvictionManager::GetInstance()->AddFrame(this, visible); +} + +void FrameEvictor::DiscardedFrame() { + FrameEvictionManager::GetInstance()->RemoveFrame(this); + has_frame_ = false; +} + +void FrameEvictor::SetVisible(bool visible) { + if (visible_ == visible) + return; + visible_ = visible; + if (has_frame_) { + if (visible) { + LockFrame(); + } else { + UnlockFrame(); + } + } +} + +void FrameEvictor::LockFrame() { + DCHECK(has_frame_); + FrameEvictionManager::GetInstance()->LockFrame(this); +} + +void FrameEvictor::UnlockFrame() { + DCHECK(has_frame_); + FrameEvictionManager::GetInstance()->UnlockFrame(this); +} + +void FrameEvictor::EvictCurrentFrame() { + client_->EvictDelegatedFrame(); +} + +} // namespace viz
diff --git a/components/viz/frame_sinks/frame_evictor.h b/components/viz/frame_sinks/frame_evictor.h new file mode 100644 index 0000000..664bb44 --- /dev/null +++ b/components/viz/frame_sinks/frame_evictor.h
@@ -0,0 +1,46 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_FRAME_SINKS_FRAME_EVICTOR_H_ +#define COMPONENTS_VIZ_FRAME_SINKS_FRAME_EVICTOR_H_ + +#include "base/macros.h" +#include "components/viz/frame_sinks/frame_eviction_manager.h" +#include "components/viz/frame_sinks/viz_export.h" + +namespace viz { + +class VIZ_EXPORT FrameEvictorClient { + public: + virtual ~FrameEvictorClient() {} + virtual void EvictDelegatedFrame() = 0; +}; + +class VIZ_EXPORT FrameEvictor : public FrameEvictionManagerClient { + public: + // |client| must outlive |this|. + explicit FrameEvictor(FrameEvictorClient* client); + ~FrameEvictor() override; + + void SwappedFrame(bool visible); + void DiscardedFrame(); + void SetVisible(bool visible); + void LockFrame(); + void UnlockFrame(); + bool HasFrame() { return has_frame_; } + + private: + // FrameEvictionManagerClient implementation. + void EvictCurrentFrame() override; + + FrameEvictorClient* client_; + bool has_frame_; + bool visible_; + + DISALLOW_COPY_AND_ASSIGN(FrameEvictor); +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_FRAME_SINKS_FRAME_EVICTOR_H_
diff --git a/components/viz/frame_sinks/mojo_frame_sink_manager.h b/components/viz/frame_sinks/mojo_frame_sink_manager.h index 53785d9..5a9d461 100644 --- a/components/viz/frame_sinks/mojo_frame_sink_manager.h +++ b/components/viz/frame_sinks/mojo_frame_sink_manager.h
@@ -17,6 +17,7 @@ #include "cc/surfaces/surface_manager.h" #include "cc/surfaces/surface_observer.h" #include "components/viz/frame_sinks/gpu_compositor_frame_sink_delegate.h" +#include "components/viz/frame_sinks/viz_export.h" #include "gpu/ipc/common/surface_handle.h" #include "mojo/public/cpp/bindings/binding.h" @@ -32,9 +33,10 @@ // will be true after the mus process split. For non-mus Chrome this will be // created in the browser process, at least until GPU implementations can be // unified. -class MojoFrameSinkManager : public cc::SurfaceObserver, - public GpuCompositorFrameSinkDelegate, - public cc::mojom::FrameSinkManager { +class VIZ_EXPORT MojoFrameSinkManager + : public cc::SurfaceObserver, + public NON_EXPORTED_BASE(GpuCompositorFrameSinkDelegate), + public NON_EXPORTED_BASE(cc::mojom::FrameSinkManager) { public: MojoFrameSinkManager(bool use_surface_references, DisplayProvider* display_provider,
diff --git a/components/viz/frame_sinks/viz_export.h b/components/viz/frame_sinks/viz_export.h new file mode 100644 index 0000000..e9d3fe8 --- /dev/null +++ b/components/viz/frame_sinks/viz_export.h
@@ -0,0 +1,29 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_FRAME_SINKS_VIZ_EXPORT_H_ +#define COMPONENTS_VIZ_FRAME_SINKS_VIZ_EXPORT_H_ + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(VIZ_IMPLEMENTATION) +#define VIZ_EXPORT __declspec(dllexport) +#else +#define VIZ_EXPORT __declspec(dllimport) +#endif // defined(VIZ_IMPLEMENTATION) + +#else // defined(WIN32) +#if defined(VIZ_IMPLEMENTATION) +#define VIZ_EXPORT __attribute__((visibility("default"))) +#else +#define VIZ_EXPORT +#endif +#endif + +#else // defined(COMPONENT_BUILD) +#define VIZ_EXPORT +#endif + +#endif // COMPONENTS_VIZ_FRAME_SINKS_VIZ_EXPORT_H_
diff --git a/components/web_cache/renderer/BUILD.gn b/components/web_cache/renderer/BUILD.gn index b386fc7..368bff45 100644 --- a/components/web_cache/renderer/BUILD.gn +++ b/components/web_cache/renderer/BUILD.gn
@@ -11,6 +11,7 @@ deps = [ "//base", "//components/web_cache/public/interfaces", + "//content/public/child", "//content/public/common", "//content/public/renderer", "//services/service_manager/public/cpp",
diff --git a/components/web_cache/renderer/DEPS b/components/web_cache/renderer/DEPS index 0672fbe..089e77b 100644 --- a/components/web_cache/renderer/DEPS +++ b/components/web_cache/renderer/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+content/public/child", "+content/public/common", "+content/public/renderer", "+mojo/public",
diff --git a/components/web_cache/renderer/web_cache_impl.cc b/components/web_cache/renderer/web_cache_impl.cc index c4e73bf..23a8154 100644 --- a/components/web_cache/renderer/web_cache_impl.cc +++ b/components/web_cache/renderer/web_cache_impl.cc
@@ -8,23 +8,31 @@ #include "base/bind.h" #include "base/numerics/safe_conversions.h" +#include "content/public/child/child_thread.h" +#include "content/public/common/service_manager_connection.h" +#include "content/public/common/simple_connection_filter.h" #include "content/public/renderer/render_thread.h" -#include "services/service_manager/public/cpp/interface_registry.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "third_party/WebKit/public/platform/WebCache.h" namespace web_cache { WebCacheImpl::WebCacheImpl() : clear_cache_state_(kInit) { - service_manager::InterfaceRegistry* registry = - content::RenderThread::Get()->GetInterfaceRegistry(); + auto registry = base::MakeUnique<service_manager::BinderRegistry>(); registry->AddInterface( - base::Bind(&WebCacheImpl::BindRequest, base::Unretained(this))); + base::Bind(&WebCacheImpl::BindRequest, base::Unretained(this)), + base::ThreadTaskRunnerHandle::Get()); + if (content::ChildThread::Get()) { + content::ChildThread::Get() + ->GetServiceManagerConnection() + ->AddConnectionFilter(base::MakeUnique<content::SimpleConnectionFilter>( + std::move(registry))); + } } WebCacheImpl::~WebCacheImpl() {} -void WebCacheImpl::BindRequest( - mojo::InterfaceRequest<mojom::WebCache> web_cache_request) { +void WebCacheImpl::BindRequest(mojom::WebCacheRequest web_cache_request) { bindings_.AddBinding(this, std::move(web_cache_request)); }
diff --git a/components/web_cache/renderer/web_cache_impl.h b/components/web_cache/renderer/web_cache_impl.h index 3b629cc..4a8a44f 100644 --- a/components/web_cache/renderer/web_cache_impl.h +++ b/components/web_cache/renderer/web_cache_impl.h
@@ -21,7 +21,7 @@ WebCacheImpl(); ~WebCacheImpl() override; - void BindRequest(mojo::InterfaceRequest<mojom::WebCache> web_cache_request); + void BindRequest(mojom::WebCacheRequest web_cache_request); // Needs to be called by RenderViews in case of navigations to execute // any 'clear cache' commands that were delayed until the next navigation.
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 1d10e46..92bfe066 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1048,8 +1048,6 @@ "renderer_host/clipboard_message_filter_mac.mm", "renderer_host/database_message_filter.cc", "renderer_host/database_message_filter.h", - "renderer_host/delegated_frame_evictor.cc", - "renderer_host/delegated_frame_evictor.h", "renderer_host/dip_util.cc", "renderer_host/dip_util.h", "renderer_host/dwrite_font_proxy_message_filter_win.cc", @@ -1248,8 +1246,6 @@ "renderer_host/render_widget_host_view_mac_dictionary_helper.mm", "renderer_host/render_widget_host_view_mac_editcommand_helper.h", "renderer_host/render_widget_host_view_mac_editcommand_helper.mm", - "renderer_host/renderer_frame_manager.cc", - "renderer_host/renderer_frame_manager.h", "renderer_host/sandbox_ipc_linux.cc", "renderer_host/sandbox_ipc_linux.h", "renderer_host/text_input_client_mac.h",
diff --git a/content/browser/accessibility/accessibility_event_recorder_win.cc b/content/browser/accessibility/accessibility_event_recorder_win.cc index cb40bfb..32fd6ae 100644 --- a/content/browser/accessibility/accessibility_event_recorder_win.cc +++ b/content/browser/accessibility/accessibility_event_recorder_win.cc
@@ -228,7 +228,7 @@ AccessibleStates ia2_state = 0; base::win::ScopedComPtr<IAccessible2> iaccessible2; - hr = QueryIAccessible2(iaccessible.get(), iaccessible2.Receive()); + hr = QueryIAccessible2(iaccessible.Get(), iaccessible2.Receive()); if (SUCCEEDED(hr)) iaccessible2->get_states(&ia2_state); @@ -246,7 +246,7 @@ // For TEXT_REMOVED and TEXT_INSERTED events, query the text that was // inserted or removed and include that in the log. base::win::ScopedComPtr<IAccessibleText> accessible_text; - hr = QueryIAccessibleText(iaccessible.get(), accessible_text.Receive()); + hr = QueryIAccessibleText(iaccessible.Get(), accessible_text.Receive()); if (SUCCEEDED(hr)) { if (event == IA2_EVENT_TEXT_REMOVED) { IA2TextSegment old_text;
diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc index 8eab2fc..7ca9e9f 100644 --- a/content/browser/accessibility/accessibility_win_browsertest.cc +++ b/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -140,22 +140,22 @@ // Retrieve the IAccessible interface for the web page. base::win::ScopedComPtr<IAccessible> document(GetRendererAccessible()); std::vector<base::win::ScopedVariant> document_children = - GetAllAccessibleChildren(document.get()); + GetAllAccessibleChildren(document.Get()); ASSERT_EQ(1u, document_children.size()); base::win::ScopedComPtr<IAccessible2> form; ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2( - GetAccessibleFromVariant(document.get(), document_children[0].AsInput()) - .get(), + GetAccessibleFromVariant(document.Get(), document_children[0].AsInput()) + .Get(), form.Receive())); std::vector<base::win::ScopedVariant> form_children = - GetAllAccessibleChildren(form.get()); + GetAllAccessibleChildren(form.Get()); ASSERT_EQ(2u, form_children.size()); // Find the input text field. base::win::ScopedComPtr<IAccessible2> input; ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2( - GetAccessibleFromVariant(form.get(), form_children[1].AsInput()).get(), + GetAccessibleFromVariant(form.Get(), form_children[1].AsInput()).Get(), input.Receive())); LONG input_role = 0; ASSERT_HRESULT_SUCCEEDED(input->role(&input_role)); @@ -191,23 +191,23 @@ // Retrieve the IAccessible interface for the web page. base::win::ScopedComPtr<IAccessible> document(GetRendererAccessible()); std::vector<base::win::ScopedVariant> document_children = - GetAllAccessibleChildren(document.get()); + GetAllAccessibleChildren(document.Get()); ASSERT_EQ(1u, document_children.size()); base::win::ScopedComPtr<IAccessible2> section; ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2( - GetAccessibleFromVariant(document.get(), document_children[0].AsInput()) - .get(), + GetAccessibleFromVariant(document.Get(), document_children[0].AsInput()) + .Get(), section.Receive())); std::vector<base::win::ScopedVariant> section_children = - GetAllAccessibleChildren(section.get()); + GetAllAccessibleChildren(section.Get()); ASSERT_EQ(1u, section_children.size()); // Find the textarea text field. base::win::ScopedComPtr<IAccessible2> textarea; ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2( - GetAccessibleFromVariant(section.get(), section_children[0].AsInput()) - .get(), + GetAccessibleFromVariant(section.Get(), section_children[0].AsInput()) + .Get(), textarea.Receive())); LONG textarea_role = 0; ASSERT_HRESULT_SUCCEEDED(textarea->role(&textarea_role)); @@ -248,13 +248,13 @@ // Retrieve the IAccessible interface for the web page. base::win::ScopedComPtr<IAccessible> document(GetRendererAccessible()); std::vector<base::win::ScopedVariant> document_children = - GetAllAccessibleChildren(document.get()); + GetAllAccessibleChildren(document.Get()); ASSERT_EQ(1u, document_children.size()); base::win::ScopedComPtr<IAccessible2> paragraph; ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2( - GetAccessibleFromVariant(document.get(), document_children[0].AsInput()) - .get(), + GetAccessibleFromVariant(document.Get(), document_children[0].AsInput()) + .Get(), paragraph.Receive())); LONG paragraph_role = 0; ASSERT_HRESULT_SUCCEEDED(paragraph->role(¶graph_role)); @@ -281,7 +281,7 @@ base::win::ScopedComPtr<IDispatch> dispatch; HRESULT hr = parent->get_accChild(*var, dispatch.Receive()); EXPECT_TRUE(SUCCEEDED(hr)); - if (dispatch.get()) + if (dispatch.Get()) dispatch.QueryInterface(ptr.Receive()); break; } @@ -337,7 +337,7 @@ GetAccessibleFromVariant(node, children[i].AsInput())); if (child_accessible) { FindNodeInAccessibilityTree( - child_accessible.get(), expected_role, expected_name, depth + 1, + child_accessible.Get(), expected_role, expected_name, depth + 1, found); if (*found) return; @@ -615,8 +615,8 @@ ++child_checker, ++child) { base::win::ScopedComPtr<IAccessible> child_accessible( GetAccessibleFromVariant(parent, child->AsInput())); - ASSERT_TRUE(child_accessible.get()); - (*child_checker)->CheckAccessible(child_accessible.get()); + ASSERT_TRUE(child_accessible.Get()); + (*child_checker)->CheckAccessible(child_accessible.Get()); } } @@ -824,7 +824,7 @@ shell()->web_contents(), kAccessibilityModeComplete, ui::AX_EVENT_BLUR)); base::win::ScopedComPtr<IAccessible> document_accessible( GetRendererAccessible()); - ASSERT_NE(document_accessible.get(), reinterpret_cast<IAccessible*>(NULL)); + ASSERT_NE(document_accessible.Get(), reinterpret_cast<IAccessible*>(NULL)); base::win::ScopedVariant childid_self(CHILDID_SELF); HRESULT hr = document_accessible->accSelect(SELFLAG_TAKEFOCUS, childid_self); ASSERT_EQ(S_OK, hr); @@ -898,7 +898,7 @@ bool found = false; FindNodeInAccessibilityTree( - browser_accessible.get(), ROLE_SYSTEM_DOCUMENT, L"MyDocument", 0, &found); + browser_accessible.Get(), ROLE_SYSTEM_DOCUMENT, L"MyDocument", 0, &found); ASSERT_EQ(found, true); } @@ -910,11 +910,11 @@ // Get the IAccessible object for the document. base::win::ScopedComPtr<IAccessible> document_accessible( GetRendererAccessible()); - ASSERT_NE(document_accessible.get(), reinterpret_cast<IAccessible*>(NULL)); + ASSERT_NE(document_accessible.Get(), reinterpret_cast<IAccessible*>(NULL)); // Get the ISimpleDOM object for the document. base::win::ScopedComPtr<IServiceProvider> service_provider; - HRESULT hr = static_cast<IAccessible*>(document_accessible.get()) + HRESULT hr = static_cast<IAccessible*>(document_accessible.Get()) ->QueryInterface(service_provider.Receive()); ASSERT_EQ(S_OK, hr); const GUID refguid = {0x0c539790, @@ -922,7 +922,7 @@ 0x11cf, {0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8}}; base::win::ScopedComPtr<ISimpleDOMNode> document_isimpledomnode; - hr = static_cast<IServiceProvider*>(service_provider.get()) + hr = static_cast<IServiceProvider*>(service_provider.Get()) ->QueryService( refguid, IID_ISimpleDOMNode, reinterpret_cast<void**>(document_isimpledomnode.Receive())); @@ -1858,21 +1858,21 @@ // Retrieve the IAccessible interface for the web page. base::win::ScopedComPtr<IAccessible> document(GetRendererAccessible()); std::vector<base::win::ScopedVariant> document_children = - GetAllAccessibleChildren(document.get()); + GetAllAccessibleChildren(document.Get()); ASSERT_EQ(1u, document_children.size()); base::win::ScopedComPtr<IAccessible2> div; ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2( - GetAccessibleFromVariant(document.get(), document_children[0].AsInput()) - .get(), + GetAccessibleFromVariant(document.Get(), document_children[0].AsInput()) + .Get(), div.Receive())); std::vector<base::win::ScopedVariant> div_children = - GetAllAccessibleChildren(div.get()); + GetAllAccessibleChildren(div.Get()); ASSERT_EQ(1u, div_children.size()); base::win::ScopedComPtr<IAccessible2> image; ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2( - GetAccessibleFromVariant(div.get(), div_children[0].AsInput()).get(), + GetAccessibleFromVariant(div.Get(), div_children[0].AsInput()).Get(), image.Receive())); LONG image_role = 0; ASSERT_HRESULT_SUCCEEDED(image->role(&image_role)); @@ -1961,14 +1961,14 @@ base::win::ScopedComPtr<IAccessible> document(GetRendererAccessible()); std::vector<base::win::ScopedVariant> document_children = - GetAllAccessibleChildren(document.get()); + GetAllAccessibleChildren(document.Get()); // There are two tables in this test file. Use only the first one. ASSERT_EQ(2u, document_children.size()); base::win::ScopedComPtr<IAccessible2> table; ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2( - GetAccessibleFromVariant(document.get(), document_children[0].AsInput()) - .get(), + GetAccessibleFromVariant(document.Get(), document_children[0].AsInput()) + .Get(), table.Receive())); LONG role = 0; ASSERT_HRESULT_SUCCEEDED(table->role(&role));
diff --git a/content/browser/fileapi/file_system_operation_impl_write_unittest.cc b/content/browser/fileapi/file_system_operation_impl_write_unittest.cc index 314aa75..b3b255b 100644 --- a/content/browser/fileapi/file_system_operation_impl_write_unittest.cc +++ b/content/browser/fileapi/file_system_operation_impl_write_unittest.cc
@@ -13,7 +13,6 @@ #include "base/memory/weak_ptr.h" #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" -#include "content/browser/fileapi/mock_file_change_observer.h" #include "content/public/test/mock_blob_url_request_context.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" @@ -26,6 +25,7 @@ #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_operation_runner.h" #include "storage/browser/fileapi/local_file_util.h" +#include "storage/browser/test/mock_file_change_observer.h" #include "storage/browser/test/mock_quota_manager.h" #include "storage/browser/test/test_file_system_backend.h" #include "storage/browser/test/test_file_system_context.h"
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc index 2823b56e8..4922360 100644 --- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -6656,34 +6656,6 @@ testing::Key("X-ExtraHeadersVsSubresources")))); } -class NavigationHandleCommitObserver : public WebContentsObserver { - public: - NavigationHandleCommitObserver(WebContents* web_contents, const GURL& url) - : WebContentsObserver(web_contents), - url_(url), - has_committed_(false), - was_same_page_(false), - was_renderer_initiated_(false) {} - - bool has_committed() const { return has_committed_; } - bool was_same_page() const { return was_same_page_; } - bool was_renderer_initiated() const { return was_renderer_initiated_; } - - private: - void DidFinishNavigation(NavigationHandle* handle) override { - if (handle->GetURL() != url_) - return; - has_committed_ = true; - was_same_page_ = handle->IsSameDocument(); - was_renderer_initiated_ = handle->IsRendererInitiated(); - } - - const GURL url_; - bool has_committed_; - bool was_same_page_; - bool was_renderer_initiated_; -}; - // Test that a same document navigation does not lead to the deletion of the // NavigationHandle for an ongoing different document navigation. IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, @@ -6732,7 +6704,7 @@ EXPECT_EQ(kPushStateURL, last_committed->GetURL()); EXPECT_TRUE(push_state_observer.has_committed()); - EXPECT_TRUE(push_state_observer.was_same_page()); + EXPECT_TRUE(push_state_observer.was_same_document()); EXPECT_TRUE(push_state_observer.was_renderer_initiated()); // This shouldn't affect the ongoing navigation. @@ -6752,7 +6724,7 @@ EXPECT_EQ(kURL2, last_committed->GetURL()); EXPECT_TRUE(navigation_observer.has_committed()); - EXPECT_FALSE(navigation_observer.was_same_page()); + EXPECT_FALSE(navigation_observer.was_same_document()); EXPECT_FALSE(navigation_observer.was_renderer_initiated()); } @@ -6774,7 +6746,7 @@ EXPECT_TRUE(NavigateToURL(shell(), kFragmentURL)); EXPECT_TRUE(handle_observer.has_committed()); - EXPECT_TRUE(handle_observer.was_same_page()); + EXPECT_TRUE(handle_observer.was_same_document()); EXPECT_FALSE(handle_observer.was_renderer_initiated()); }
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 4036937d..cf60f55 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/debug/dump_without_crashing.h" #include "base/memory/ptr_util.h" #include "content/browser/appcache/appcache_navigation_handle.h" #include "content/browser/appcache/chrome_appcache_service.h" @@ -610,6 +611,12 @@ // If the request was canceled by the user do not show an error page. if (net_error == net::ERR_ABORTED) { + // TODO(clamy): Remove this once we understand the root cause of + // crbug.com/709771. + std::string path = common_params_.url.path(); + if (path.length() >= 4 && path.substr(path.length() - 4) == ".pdf") + base::debug::DumpWithoutCrashing(); + frame_tree_node_->ResetNavigationRequest(false, true); return; }
diff --git a/content/browser/renderer_host/delegated_frame_evictor.cc b/content/browser/renderer_host/delegated_frame_evictor.cc deleted file mode 100644 index 65ae4832..0000000 --- a/content/browser/renderer_host/delegated_frame_evictor.cc +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/renderer_host/delegated_frame_evictor.h" - -#include "base/logging.h" - -namespace content { - -DelegatedFrameEvictor::DelegatedFrameEvictor( - DelegatedFrameEvictorClient* client) - : client_(client), has_frame_(false), visible_(false) { -} - -DelegatedFrameEvictor::~DelegatedFrameEvictor() { DiscardedFrame(); } - -void DelegatedFrameEvictor::SwappedFrame(bool visible) { - visible_ = visible; - has_frame_ = true; - RendererFrameManager::GetInstance()->AddFrame(this, visible); -} - -void DelegatedFrameEvictor::DiscardedFrame() { - RendererFrameManager::GetInstance()->RemoveFrame(this); - has_frame_ = false; -} - -void DelegatedFrameEvictor::SetVisible(bool visible) { - if (visible_ == visible) - return; - visible_ = visible; - if (has_frame_) { - if (visible) { - LockFrame(); - } else { - UnlockFrame(); - } - } -} - -void DelegatedFrameEvictor::LockFrame() { - DCHECK(has_frame_); - RendererFrameManager::GetInstance()->LockFrame(this); -} - -void DelegatedFrameEvictor::UnlockFrame() { - DCHECK(has_frame_); - RendererFrameManager::GetInstance()->UnlockFrame(this); -} - -void DelegatedFrameEvictor::EvictCurrentFrame() { - client_->EvictDelegatedFrame(); -} - -} // namespace content
diff --git a/content/browser/renderer_host/delegated_frame_evictor.h b/content/browser/renderer_host/delegated_frame_evictor.h deleted file mode 100644 index c1bd50e..0000000 --- a/content/browser/renderer_host/delegated_frame_evictor.h +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_DELEGATED_FRAME_EVICTOR_H_ -#define CONTENT_BROWSER_RENDERER_HOST_DELEGATED_FRAME_EVICTOR_H_ - -#include "base/macros.h" -#include "content/browser/renderer_host/renderer_frame_manager.h" -#include "content/common/content_export.h" - -namespace content { - -class CONTENT_EXPORT DelegatedFrameEvictorClient { - public: - virtual ~DelegatedFrameEvictorClient() {} - virtual void EvictDelegatedFrame() = 0; -}; - -class CONTENT_EXPORT DelegatedFrameEvictor : public RendererFrameManagerClient { - public: - // |client| must outlive |this|. - explicit DelegatedFrameEvictor(DelegatedFrameEvictorClient* client); - ~DelegatedFrameEvictor() override; - - void SwappedFrame(bool visible); - void DiscardedFrame(); - void SetVisible(bool visible); - void LockFrame(); - void UnlockFrame(); - bool HasFrame() { return has_frame_; } - - private: - // RendererFrameManagerClient implementation. - void EvictCurrentFrame() override; - - DelegatedFrameEvictorClient* client_; - bool has_frame_; - bool visible_; - - DISALLOW_COPY_AND_ASSIGN(DelegatedFrameEvictor); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_DELEGATED_FRAME_EVICTOR_H_
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index 3d2a3d3..95c2da7 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -50,7 +50,7 @@ skipped_frames_(false), background_color_(SK_ColorRED), current_scale_factor_(1.f), - delegated_frame_evictor_(new DelegatedFrameEvictor(this)) { + frame_evictor_(new viz::FrameEvictor(this)) { ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); factory->GetContextFactory()->AddObserver(this); factory->GetContextFactoryPrivate()->GetSurfaceManager()->RegisterFrameSinkId( @@ -59,7 +59,7 @@ } void DelegatedFrameHost::WasShown(const ui::LatencyInfo& latency_info) { - delegated_frame_evictor_->SetVisible(true); + frame_evictor_->SetVisible(true); if (!has_frame_ && !released_front_lock_.get()) { if (compositor_) @@ -72,11 +72,11 @@ } bool DelegatedFrameHost::HasSavedFrame() { - return delegated_frame_evictor_->HasFrame(); + return frame_evictor_->HasFrame(); } void DelegatedFrameHost::WasHidden() { - delegated_frame_evictor_->SetVisible(false); + frame_evictor_->SetVisible(false); released_front_lock_ = NULL; } @@ -482,8 +482,7 @@ } if (has_frame_) { - delegated_frame_evictor_->SwappedFrame( - client_->DelegatedFrameHostIsVisible()); + frame_evictor_->SwappedFrame(client_->DelegatedFrameHostIsVisible()); } // Note: the frame may have been evicted immediately. @@ -525,7 +524,7 @@ client_->DelegatedFrameHostGetLayer()->SetShowSolidColorContent(); support_->EvictFrame(); has_frame_ = false; - delegated_frame_evictor_->DiscardedFrame(); + frame_evictor_->DiscardedFrame(); UpdateGutters(); } @@ -811,7 +810,7 @@ void DelegatedFrameHost::LockResources() { DCHECK(local_surface_id_.is_valid()); - delegated_frame_evictor_->LockFrame(); + frame_evictor_->LockFrame(); } void DelegatedFrameHost::RequestCopyOfOutput( @@ -831,7 +830,7 @@ void DelegatedFrameHost::UnlockResources() { DCHECK(local_surface_id_.is_valid()); - delegated_frame_evictor_->UnlockFrame(); + frame_evictor_->UnlockFrame(); } void DelegatedFrameHost::CreateCompositorFrameSinkSupport() {
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h index 3ac90e8..a795ead 100644 --- a/content/browser/renderer_host/delegated_frame_host.h +++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -14,9 +14,9 @@ #include "cc/output/copy_output_result.h" #include "cc/scheduler/begin_frame_source.h" #include "cc/surfaces/compositor_frame_sink_support_client.h" +#include "components/viz/frame_sinks/frame_evictor.h" #include "content/browser/compositor/image_transport_factory.h" #include "content/browser/compositor/owned_mailbox.h" -#include "content/browser/renderer_host/delegated_frame_evictor.h" #include "content/browser/renderer_host/dip_util.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" @@ -82,7 +82,7 @@ : public ui::CompositorObserver, public ui::CompositorVSyncManager::Observer, public ui::ContextFactoryObserver, - public DelegatedFrameEvictorClient, + public viz::FrameEvictorClient, public NON_EXPORTED_BASE(cc::CompositorFrameSinkSupportClient), public base::SupportsWeakPtr<DelegatedFrameHost> { public: @@ -105,7 +105,7 @@ // ImageTransportFactoryObserver implementation. void OnLostResources() override; - // DelegatedFrameEvictorClient implementation. + // FrameEvictorClient implementation. void EvictDelegatedFrame() override; // cc::CompositorFrameSinkSupportClient implementation. @@ -324,7 +324,7 @@ cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink_ = nullptr; - std::unique_ptr<DelegatedFrameEvictor> delegated_frame_evictor_; + std::unique_ptr<viz::FrameEvictor> frame_evictor_; }; } // namespace content
diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.h b/content/browser/renderer_host/legacy_render_widget_host_win.h index 32d3875..398c633a 100644 --- a/content/browser/renderer_host/legacy_render_widget_host_win.h +++ b/content/browser/renderer_host/legacy_render_widget_host_win.h
@@ -105,7 +105,7 @@ void UpdateParent(HWND parent); HWND GetParent(); - IAccessible* window_accessible() { return window_accessible_.get(); } + IAccessible* window_accessible() { return window_accessible_.Get(); } // Functions to show and hide the window. void Show();
diff --git a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc index c6894b05..998ef8e 100644 --- a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc +++ b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
@@ -154,8 +154,18 @@ } void BrowserPpapiHostImpl::DeleteInstance(PP_Instance instance) { - int erased = instance_map_.erase(instance); - DCHECK_EQ(1, erased); + auto it = instance_map_.find(instance); + DCHECK(it != instance_map_.end()); + + // We need to tell the observers for that instance that we are destroyed + // because we won't have the opportunity to once we remove them from the + // |instance_map_|. If the instance was deleted, observers for those instances + // should never call back into the host anyway, so it is safe to tell them + // that the host is destroyed. + for (auto& observer : it->second->observer_list) + observer.OnHostDestroyed(); + + instance_map_.erase(it); } void BrowserPpapiHostImpl::AddInstanceObserver(PP_Instance instance,
diff --git a/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc index 029a9de9..b91089d 100644 --- a/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc +++ b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
@@ -86,6 +86,8 @@ is_potentially_secure_plugin_context_( host->IsPotentiallySecurePluginContext(instance)) { DCHECK(host); + DCHECK_CURRENTLY_ON(BrowserThread::IO); + ++g_num_instances; host_->AddInstanceObserver(instance_, this); if (!host->GetRenderFrameIDsForInstance( @@ -122,6 +124,7 @@ host->IsPotentiallySecurePluginContext(instance)) { DCHECK(host); DCHECK_NE(version, ppapi::TCP_SOCKET_VERSION_1_0); + DCHECK_CURRENTLY_ON(BrowserThread::IO); ++g_num_instances; host_->AddInstanceObserver(instance_, this); @@ -132,6 +135,7 @@ } PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (host_) host_->RemoveInstanceObserver(instance_, this); if (socket_) @@ -203,6 +207,7 @@ } void PepperTCPSocketMessageFilter::OnHostDestroyed() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); host_->RemoveInstanceObserver(instance_, this); host_ = nullptr; }
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index cc95a29..486b536 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -459,7 +459,7 @@ stylus_text_selector_(this), using_browser_compositor_(CompositorImpl::IsInitialized()), synchronous_compositor_client_(nullptr), - frame_evictor_(new DelegatedFrameEvictor(this)), + frame_evictor_(new viz::FrameEvictor(this)), observing_root_window_(false), prev_top_shown_pix_(0.f), prev_bottom_shown_pix_(0.f),
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index 99c5771..704204f 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -21,9 +21,9 @@ #include "cc/input/selection.h" #include "cc/output/begin_frame_args.h" #include "cc/scheduler/begin_frame_source.h" +#include "components/viz/frame_sinks/frame_evictor.h" #include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/browser/android/content_view_core_impl_observer.h" -#include "content/browser/renderer_host/delegated_frame_evictor.h" #include "content/browser/renderer_host/input/stylus_text_selector.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/renderer_host/text_input_manager.h" @@ -64,7 +64,7 @@ public ui::GestureProviderClient, public ui::ViewClient, public ui::WindowAndroidObserver, - public DelegatedFrameEvictorClient, + public viz::FrameEvictorClient, public StylusTextSelectorClient, public ui::TouchSelectionControllerClient, public content::ContentViewCoreImplObserver, @@ -202,7 +202,7 @@ void OnAttachedToWindow() override; void OnDetachedFromWindow() override; - // DelegatedFrameEvictor implementation + // viz::FrameEvictor implementation void EvictDelegatedFrame() override; // StylusTextSelectorClient implementation. @@ -404,7 +404,7 @@ SynchronousCompositorClient* synchronous_compositor_client_; - std::unique_ptr<DelegatedFrameEvictor> frame_evictor_; + std::unique_ptr<viz::FrameEvictor> frame_evictor_; bool observing_root_window_;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index ce0f2d4..e800151 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -111,6 +111,7 @@ using blink::WebTouchEvent; using blink::WebTouchPoint; using ui::WebInputEventTraits; +using viz::FrameEvictionManager; namespace content { @@ -673,14 +674,14 @@ void SimulateMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel level) { // Here should be base::MemoryPressureListener::NotifyMemoryPressure, but - // since the RendererFrameManager is installing a MemoryPressureListener + // since the FrameEvictionManager is installing a MemoryPressureListener // which uses base::ObserverListThreadSafe, which furthermore remembers the // message loop for the thread it was created in. Between tests, the - // RendererFrameManager singleton survives and and the MessageLoop gets + // FrameEvictionManager singleton survives and and the MessageLoop gets // destroyed. The correct fix would be to have base::ObserverListThreadSafe // look // up the proper message loop every time (see crbug.com/443824.) - RendererFrameManager::GetInstance()->OnMemoryPressure(level); + FrameEvictionManager::GetInstance()->OnMemoryPressure(level); } void SendInputEventACK(WebInputEvent::Type type, @@ -2670,7 +2671,7 @@ view_->InitAsChild(nullptr); size_t max_renderer_frames = - RendererFrameManager::GetInstance()->GetMaxNumberOfSavedFrames(); + FrameEvictionManager::GetInstance()->GetMaxNumberOfSavedFrames(); ASSERT_LE(2u, max_renderer_frames); size_t renderer_count = max_renderer_frames + 1; gfx::Rect view_rect(100, 100); @@ -2813,7 +2814,7 @@ // Allocate enough bitmaps so that two frames (proportionally) would be // enough hit the handle limit. int handles_per_frame = 5; - RendererFrameManager::GetInstance()->set_max_handles(handles_per_frame * 2); + FrameEvictionManager::GetInstance()->set_max_handles(handles_per_frame * 2); display_compositor::HostSharedBitmapManagerClient bitmap_client( display_compositor::HostSharedBitmapManager::current()); @@ -2831,7 +2832,7 @@ else EXPECT_TRUE(views[i]->HasFrameData()); } - RendererFrameManager::GetInstance()->set_max_handles( + FrameEvictionManager::GetInstance()->set_max_handles( base::SharedMemory::GetHandleLimit()); for (size_t i = 0; i < renderer_count; ++i) { @@ -2844,7 +2845,7 @@ view_->InitAsChild(nullptr); size_t max_renderer_frames = - RendererFrameManager::GetInstance()->GetMaxNumberOfSavedFrames(); + FrameEvictionManager::GetInstance()->GetMaxNumberOfSavedFrames(); ASSERT_LE(2u, max_renderer_frames); size_t renderer_count = max_renderer_frames + 1; gfx::Rect view_rect(100, 100); @@ -2916,7 +2917,7 @@ // this value is calculated from total physical memory and causes the test to // fail when run on hardware with < 256MB of RAM. const size_t kMaxRendererFrames = 5; - RendererFrameManager::GetInstance()->set_max_number_of_saved_frames( + FrameEvictionManager::GetInstance()->set_max_number_of_saved_frames( kMaxRendererFrames); size_t renderer_count = kMaxRendererFrames;
diff --git a/content/browser/renderer_host/renderer_frame_manager.h b/content/browser/renderer_host/renderer_frame_manager.h deleted file mode 100644 index b8600d35..0000000 --- a/content/browser/renderer_host/renderer_frame_manager.h +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDERER_FRAME_MANAGER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_RENDERER_FRAME_MANAGER_H_ - -#include <stddef.h> - -#include <list> -#include <map> - -#include "base/macros.h" -#include "base/memory/memory_coordinator_client.h" -#include "base/memory/memory_pressure_listener.h" -#include "base/memory/singleton.h" -#include "content/common/content_export.h" - -namespace content { - -class RenderWidgetHostViewAuraTest; - -class CONTENT_EXPORT RendererFrameManagerClient { - public: - virtual ~RendererFrameManagerClient() {} - virtual void EvictCurrentFrame() = 0; -}; - -// This class is responsible for globally managing which renderers keep their -// compositor frame when offscreen. We actively discard compositor frames for -// offscreen tabs, but keep a minimum amount, as an LRU cache, to make switching -// between a small set of tabs faster. The limit is a soft limit, because -// clients can lock their frame to prevent it from being discarded, e.g. if the -// tab is visible, or while capturing a screenshot. -class CONTENT_EXPORT RendererFrameManager : - public base::MemoryCoordinatorClient { - public: - static RendererFrameManager* GetInstance(); - - void AddFrame(RendererFrameManagerClient*, bool locked); - void RemoveFrame(RendererFrameManagerClient*); - void LockFrame(RendererFrameManagerClient*); - void UnlockFrame(RendererFrameManagerClient*); - - size_t GetMaxNumberOfSavedFrames() const; - - // For testing only - void set_max_number_of_saved_frames(size_t max_number_of_saved_frames) { - max_number_of_saved_frames_ = max_number_of_saved_frames; - } - void set_max_handles(float max_handles) { max_handles_ = max_handles; } - - private: - // Please remove when crbug.com/443824 has been fixed. - friend class RenderWidgetHostViewAuraTest; - - RendererFrameManager(); - ~RendererFrameManager() override; - - // base::MemoryCoordinatorClient implementation: - void OnPurgeMemory() override; - - void CullUnlockedFrames(size_t saved_frame_limit); - - // React on memory pressure events to adjust the number of cached frames. - void OnMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); - - void PurgeMemory(int percentage); - - friend struct base::DefaultSingletonTraits<RendererFrameManager>; - - // Listens for system under pressure notifications and adjusts number of - // cached frames accordingly. - std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; - - std::map<RendererFrameManagerClient*, size_t> locked_frames_; - std::list<RendererFrameManagerClient*> unlocked_frames_; - size_t max_number_of_saved_frames_; - float max_handles_; - - DISALLOW_COPY_AND_ASSIGN(RendererFrameManager); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_RENDERER_FRAME_MANAGER_H_
diff --git a/content/browser/service_worker/service_worker_context_watcher.cc b/content/browser/service_worker/service_worker_context_watcher.cc index 8d66426f..3dd810a 100644 --- a/content/browser/service_worker/service_worker_context_watcher.cc +++ b/content/browser/service_worker/service_worker_context_watcher.cc
@@ -182,7 +182,8 @@ int64_t version_id, content::EmbeddedWorkerStatus running_status) { auto it = version_info_map_.find(version_id); - DCHECK(it != version_info_map_.end()); + if (it == version_info_map_.end()) + return; ServiceWorkerVersionInfo* version = it->second.get(); if (version->running_status == running_status) return; @@ -196,7 +197,8 @@ int64_t version_id, content::ServiceWorkerVersion::Status status) { auto it = version_info_map_.find(version_id); - DCHECK(it != version_info_map_.end()); + if (it == version_info_map_.end()) + return; ServiceWorkerVersionInfo* version = it->second.get(); if (version->status == status) return; @@ -211,7 +213,8 @@ int process_id, int devtools_agent_route_id) { auto it = version_info_map_.find(version_id); - DCHECK(it != version_info_map_.end()); + if (it == version_info_map_.end()) + return; ServiceWorkerVersionInfo* version = it->second.get(); if (version->process_id == process_id && version->devtools_agent_route_id == devtools_agent_route_id) { @@ -229,7 +232,8 @@ base::Time script_response_time, base::Time script_last_modified) { auto it = version_info_map_.find(version_id); - DCHECK(it != version_info_map_.end()); + if (it == version_info_map_.end()) + return; ServiceWorkerVersionInfo* version = it->second.get(); version->script_response_time = script_response_time; version->script_last_modified = script_last_modified; @@ -274,7 +278,8 @@ int route_id, ServiceWorkerProviderType type) { auto it = version_info_map_.find(version_id); - DCHECK(it != version_info_map_.end()); + if (it == version_info_map_.end()) + return; ServiceWorkerVersionInfo* version = it->second.get(); version->clients[uuid] = ServiceWorkerVersionInfo::ClientInfo(process_id, route_id, type);
diff --git a/content/network/url_loader_impl.cc b/content/network/url_loader_impl.cc index 16bc086..79f0ce4e1 100644 --- a/content/network/url_loader_impl.cc +++ b/content/network/url_loader_impl.cc
@@ -240,9 +240,14 @@ url_loader_client_->OnReceiveRedirect(redirect_info, response->head); } -void URLLoaderImpl::OnResponseStarted(net::URLRequest* url_request) { +void URLLoaderImpl::OnResponseStarted(net::URLRequest* url_request, + int net_error) { DCHECK(url_request == url_request_.get()); + if (net_error != net::OK) { + NotifyCompleted(net_error); + return; + } // TODO: Add support for optional MIME sniffing. scoped_refptr<ResourceResponse> response = new ResourceResponse();
diff --git a/content/network/url_loader_impl.h b/content/network/url_loader_impl.h index 4ec586b..98337d9 100644 --- a/content/network/url_loader_impl.h +++ b/content/network/url_loader_impl.h
@@ -43,7 +43,7 @@ void OnReceivedRedirect(net::URLRequest* url_request, const net::RedirectInfo& redirect_info, bool* defer_redirect) override; - void OnResponseStarted(net::URLRequest* url_request) override; + void OnResponseStarted(net::URLRequest* url_request, int net_error) override; void OnReadCompleted(net::URLRequest* url_request, int bytes_read) override; private:
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 434d3f1..f49f928 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -140,6 +140,7 @@ "java/src/org/chromium/content/browser/MediaResourceGetter.java", "java/src/org/chromium/content/browser/MediaSessionImpl.java", "java/src/org/chromium/content/browser/MemoryMonitorAndroid.java", + "java/src/org/chromium/content/browser/MenuDescriptor.java", "java/src/org/chromium/content/browser/MotionEventSynthesizer.java", "java/src/org/chromium/content/browser/NfcFactory.java", "java/src/org/chromium/content/browser/PepperPluginManager.java", @@ -461,12 +462,13 @@ junit_binary("content_junit_tests") { java_files = [ + "junit/src/org/chromium/content/browser/BindingManagerImplTest.java", + "junit/src/org/chromium/content/browser/MenuDescriptorTest.java", "junit/src/org/chromium/content/browser/input/RangeTest.java", "junit/src/org/chromium/content/browser/input/TextInputStateTest.java", "junit/src/org/chromium/content/browser/input/ThreadedInputConnectionFactoryTest.java", "junit/src/org/chromium/content/browser/input/ThreadedInputConnectionTest.java", "junit/src/org/chromium/content/browser/picker/DateDialogNormalizerTest.java", - "junit/src/org/chromium/content/browser/BindingManagerImplTest.java", "junit/src/org/chromium/content/browser/installedapp/InstalledAppProviderTest.java", "junit/src/org/chromium/content/browser/installedapp/PackageHashTest.java", ]
diff --git a/content/public/android/java/src/org/chromium/content/browser/MenuDescriptor.java b/content/public/android/java/src/org/chromium/content/browser/MenuDescriptor.java new file mode 100644 index 0000000..36b9df6 --- /dev/null +++ b/content/public/android/java/src/org/chromium/content/browser/MenuDescriptor.java
@@ -0,0 +1,95 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.content.browser; + +import android.annotation.SuppressLint; +import android.graphics.drawable.Drawable; +import android.view.Menu; +import android.view.MenuItem; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * MenuDescriptor contains the information on how a menu needs to be changed relative to + * its initial (inflated) state. It can be used to modify a menu, it can also be compared + * to MenuDescriptor to figure out whether a menu needs to be changed. + */ +@SuppressLint("UseSparseArrays") +public class MenuDescriptor { + /** + * ItemDescriptor contains the information about delayed menu.add() action. + */ + private static class ItemDescriptor { + public int mItemId; + public int mGroupId; + public int mOrder; + public CharSequence mTitle; + public Drawable mIcon; + + public ItemDescriptor( + int groupId, int itemId, int order, CharSequence title, Drawable icon) { + mItemId = itemId; + mGroupId = groupId; + mOrder = order; + mTitle = title; + mIcon = icon; + } + + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof ItemDescriptor)) return false; + ItemDescriptor rhs = (ItemDescriptor) obj; + return mItemId == rhs.mItemId && mGroupId == rhs.mGroupId && mOrder == rhs.mOrder + && isTitleEqual(mTitle, rhs.mTitle); + } + + public int hashCode() { + return mItemId; + } + + private static boolean isTitleEqual(CharSequence a, CharSequence b) { + if (a == null && b == null) return true; + if (a == null || b == null) return false; + return a.toString().contentEquals(b); + } + } + + private Map<Integer, ItemDescriptor> mAdded = new HashMap<Integer, ItemDescriptor>(); + private Set<Integer> mRemoved = new HashSet<Integer>(); + + public MenuDescriptor() {} + + public void addItem(int groupId, int itemId, int order, CharSequence title, Drawable icon) { + mAdded.put(itemId, new ItemDescriptor(groupId, itemId, order, title, icon)); + } + + public void removeItem(int itemId) { + mRemoved.add(itemId); + } + + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof MenuDescriptor)) return false; + MenuDescriptor rhs = (MenuDescriptor) obj; + return mRemoved.equals(rhs.mRemoved) && mAdded.equals(rhs.mAdded); + } + + public int hashCode() { + return 1; + } + + public void apply(Menu menu) { + for (int id : mRemoved) { + menu.removeItem(id); + } + + for (Map.Entry<Integer, ItemDescriptor> entry : mAdded.entrySet()) { + ItemDescriptor descr = entry.getValue(); + MenuItem item = menu.add(descr.mGroupId, descr.mItemId, descr.mOrder, descr.mTitle); + if (descr.mIcon != null) item.setIcon(descr.mIcon); + } + } +}
diff --git a/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java b/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java index 2a96449..0012b5b 100644 --- a/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java +++ b/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java
@@ -93,6 +93,7 @@ private View mView; private ActionMode mActionMode; + private MenuDescriptor mActionMenuDescriptor; // Bit field for mappings from menu item to a flag indicating it is allowed. private int mAllowedMenuItems; @@ -337,6 +338,7 @@ // Should be nulled out in case #onDestroyActionMode() is not invoked in response. mActionMode = null; + mActionMenuDescriptor = null; } } @@ -436,41 +438,54 @@ private void createActionMenu(ActionMode mode, Menu menu) { initializeMenu(mContext, mode, menu); - updateAssistMenuItem(menu); + + mActionMenuDescriptor = createActionMenuDescriptor(); + mActionMenuDescriptor.apply(menu); + + initializeTextProcessingMenu(menu); + } + + private MenuDescriptor createActionMenuDescriptor() { + MenuDescriptor descriptor = new MenuDescriptor(); + + updateAssistMenuItem(descriptor); if (!isSelectionEditable() || !canPaste()) { - menu.removeItem(R.id.select_action_menu_paste); + descriptor.removeItem(R.id.select_action_menu_paste); } if (isInsertion()) { - menu.removeItem(R.id.select_action_menu_select_all); - menu.removeItem(R.id.select_action_menu_cut); - menu.removeItem(R.id.select_action_menu_copy); - menu.removeItem(R.id.select_action_menu_share); - menu.removeItem(R.id.select_action_menu_web_search); - return; + descriptor.removeItem(R.id.select_action_menu_select_all); + descriptor.removeItem(R.id.select_action_menu_cut); + descriptor.removeItem(R.id.select_action_menu_copy); + descriptor.removeItem(R.id.select_action_menu_share); + descriptor.removeItem(R.id.select_action_menu_web_search); + return descriptor; } if (!isSelectionEditable()) { - menu.removeItem(R.id.select_action_menu_cut); + descriptor.removeItem(R.id.select_action_menu_cut); } if (isSelectionEditable() || !isSelectActionModeAllowed(MENU_ITEM_SHARE)) { - menu.removeItem(R.id.select_action_menu_share); + descriptor.removeItem(R.id.select_action_menu_share); } if (isSelectionEditable() || isIncognito() || !isSelectActionModeAllowed(MENU_ITEM_WEB_SEARCH)) { - menu.removeItem(R.id.select_action_menu_web_search); + descriptor.removeItem(R.id.select_action_menu_web_search); } if (isSelectionPassword()) { - menu.removeItem(R.id.select_action_menu_copy); - menu.removeItem(R.id.select_action_menu_cut); - return; + descriptor.removeItem(R.id.select_action_menu_copy); + descriptor.removeItem(R.id.select_action_menu_cut); } - initializeTextProcessingMenu(menu); + return descriptor; + } + + private boolean needsActionMenuUpdate() { + return !createActionMenuDescriptor().equals(mActionMenuDescriptor); } private boolean canPaste() { @@ -479,7 +494,7 @@ return clipMgr.hasPrimaryClip(); } - private void updateAssistMenuItem(Menu menu) { + private void updateAssistMenuItem(MenuDescriptor descriptor) { // There is no Assist functionality before Android O. if (!BuildInfo.isAtLeastO() || mAssistMenuItemId == 0) return; @@ -490,9 +505,8 @@ // Android O SDK and remove |mAssistMenuItemId|. if (mClassificationResult != null && mClassificationResult.hasNamedAction()) { - menu.add(R.id.select_action_menu_default_items, mAssistMenuItemId, 1, - mClassificationResult.label) - .setIcon(mClassificationResult.icon); + descriptor.addItem(R.id.select_action_menu_default_items, mAssistMenuItemId, 1, + mClassificationResult.label, mClassificationResult.icon); } } @@ -571,6 +585,7 @@ @Override public void onDestroyActionMode() { mActionMode = null; + mActionMenuDescriptor = null; if (mUnselectAllOnDismiss) { mWebContents.dismissTextHandles(); clearSelection(); @@ -630,7 +645,8 @@ void selectAll() { mWebContents.selectAll(); mClassificationResult = null; - showActionModeOrClearOnFailure(); + if (needsActionMenuUpdate()) showActionModeOrClearOnFailure(); + // Even though the above statement logged a SelectAll user action, we want to // track whether the focus was in an editable field, so log that too. if (isSelectionEditable()) {
diff --git a/content/public/android/junit/src/org/chromium/content/browser/MenuDescriptorTest.java b/content/public/android/junit/src/org/chromium/content/browser/MenuDescriptorTest.java new file mode 100644 index 0000000..2b2caac --- /dev/null +++ b/content/public/android/junit/src/org/chromium/content/browser/MenuDescriptorTest.java
@@ -0,0 +1,101 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.content.browser; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; + +import org.chromium.base.test.util.Feature; + +/** + * Unit tests for MenuDescriptor. + */ +@RunWith(BlockJUnit4ClassRunner.class) +public class MenuDescriptorTest { + @Test + @Feature({"TextInput"}) + public void testRemoveSameItems() throws Exception { + MenuDescriptor d1 = new MenuDescriptor(); + d1.removeItem(1); + MenuDescriptor d2 = new MenuDescriptor(); + d2.removeItem(1); + Assert.assertTrue(d1.equals(d2)); + } + + @Test + @Feature({"TextInput"}) + public void testRemoveDifferentItems() throws Exception { + MenuDescriptor d1 = new MenuDescriptor(); + d1.removeItem(1); + MenuDescriptor d2 = new MenuDescriptor(); + d2.removeItem(2); + Assert.assertFalse(d1.equals(d2)); + } + + @Test + @Feature({"TextInput"}) + public void testAddSameItems() throws Exception { + MenuDescriptor d1 = new MenuDescriptor(); + d1.addItem(1, 1, 0, "title1", null); + MenuDescriptor d2 = new MenuDescriptor(); + d2.addItem(1, 1, 0, "title1", null); + Assert.assertTrue(d1.equals(d2)); + } + + @Test + @Feature({"TextInput"}) + public void testAddDifferentItemId() throws Exception { + MenuDescriptor d1 = new MenuDescriptor(); + d1.addItem(1, 1, 0, "title1", null); + MenuDescriptor d2 = new MenuDescriptor(); + d2.addItem(1, 2, 0, "title1", null); + Assert.assertFalse(d1.equals(d2)); + } + + @Test + @Feature({"TextInput"}) + public void testAddDifferentGroupId() throws Exception { + MenuDescriptor d1 = new MenuDescriptor(); + d1.addItem(1, 1, 0, "title1", null); + MenuDescriptor d2 = new MenuDescriptor(); + d2.addItem(2, 1, 0, "title1", null); + Assert.assertFalse(d1.equals(d2)); + } + + @Test + @Feature({"TextInput"}) + public void testAddDifferentOrder() throws Exception { + MenuDescriptor d1 = new MenuDescriptor(); + d1.addItem(1, 1, 0, "title1", null); + MenuDescriptor d2 = new MenuDescriptor(); + d2.addItem(1, 1, 1, "title1", null); + Assert.assertFalse(d1.equals(d2)); + } + + @Test + @Feature({"TextInput"}) + public void testAddDifferentTitle() throws Exception { + MenuDescriptor d1 = new MenuDescriptor(); + d1.addItem(1, 1, 0, "title1", null); + MenuDescriptor d2 = new MenuDescriptor(); + d2.addItem(1, 1, 0, "title2", null); + Assert.assertFalse(d1.equals(d2)); + } + + @Test + @Feature({"TextInput"}) + public void testSecondAdditionReplacesFirst() throws Exception { + MenuDescriptor d1 = new MenuDescriptor(); + d1.addItem(1, 1, 0, "title1", null); + MenuDescriptor d2 = new MenuDescriptor(); + d2.addItem(2, 1, 1, "title2", null); + // Second addition for the same item id, this time all fields are the same + // as in d1. + d2.addItem(1, 1, 0, "title1", null); + Assert.assertTrue(d1.equals(d2)); + } +}
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h index 4fed0b5..097e8c0 100644 --- a/content/public/renderer/content_renderer_client.h +++ b/content/public/renderer/content_renderer_client.h
@@ -65,10 +65,6 @@ class KeySystemProperties; } -namespace service_manager { -class InterfaceRegistry; -} - namespace content { class BrowserPluginDelegate; class MediaStreamRendererFactory; @@ -363,11 +359,6 @@ virtual void DidInitializeWorkerContextOnWorkerThread( v8::Local<v8::Context> context) {} - // Allows the client to expose interfaces from the renderer process to the - // browser process via |registry|. - virtual void ExposeInterfacesToBrowser( - service_manager::InterfaceRegistry* interface_registry) {} - // Overwrites the given URL to use an HTML5 embed if possible. // An empty URL is returned if the URL is not overriden. virtual GURL OverrideFlashEmbedWithHTML(const GURL& url);
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 9e8359c..ba92923 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -1914,6 +1914,24 @@ return true; } +NavigationHandleCommitObserver::NavigationHandleCommitObserver( + content::WebContents* web_contents, + const GURL& url) + : content::WebContentsObserver(web_contents), + url_(url), + has_committed_(false), + was_same_document_(false), + was_renderer_initiated_(false) {} + +void NavigationHandleCommitObserver::DidFinishNavigation( + content::NavigationHandle* handle) { + if (handle->GetURL() != url_) + return; + has_committed_ = true; + was_same_document_ = handle->IsSameDocument(); + was_renderer_initiated_ = handle->IsRendererInitiated(); +} + ConsoleObserverDelegate::ConsoleObserverDelegate(WebContents* web_contents, const std::string& filter) : web_contents_(web_contents),
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index f5b609b..c5219e9c 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -748,6 +748,24 @@ DISALLOW_COPY_AND_ASSIGN(TestNavigationManager); }; +class NavigationHandleCommitObserver : public content::WebContentsObserver { + public: + NavigationHandleCommitObserver(content::WebContents* web_contents, + const GURL& url); + + bool has_committed() const { return has_committed_; } + bool was_same_document() const { return was_same_document_; } + bool was_renderer_initiated() const { return was_renderer_initiated_; } + + private: + void DidFinishNavigation(content::NavigationHandle* handle) override; + + const GURL url_; + bool has_committed_; + bool was_same_document_; + bool was_renderer_initiated_; +}; + // A WebContentsDelegate that catches messages sent to the console. class ConsoleObserverDelegate : public WebContentsDelegate { public:
diff --git a/content/renderer/gpu/gpu_benchmarking_extension.cc b/content/renderer/gpu/gpu_benchmarking_extension.cc index 4ceeca4..431636eb 100644 --- a/content/renderer/gpu/gpu_benchmarking_extension.cc +++ b/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -540,7 +540,7 @@ LOG(ERROR) << "CoCreateInstance(CLSID_XpsOMObjectFactory, ...) failed:" << logging::SystemErrorCodeToString(hr); } - return SkDocument::MakeXPS(s, factory.get()); + return SkDocument::MakeXPS(s, factory.Get()); } #endif } // namespace
diff --git a/content/renderer/input/main_thread_event_queue.cc b/content/renderer/input/main_thread_event_queue.cc index a9875e9b..8c25facf3 100644 --- a/content/renderer/input/main_thread_event_queue.cc +++ b/content/renderer/input/main_thread_event_queue.cc
@@ -79,11 +79,11 @@ if (!ScopedWebInputEventWithLatencyInfo::CanCoalesceWith(other_event)) return FilterResult::StopIterating; - // If this event was blocking push the event id to the blocking - // list before updating the dispatch_type of this event. - if (dispatch_type_ == DISPATCH_TYPE_BLOCKING) { + // If the other event was blocking store its unique touch event id to + // ack later. + if (other_event.dispatch_type_ == DISPATCH_TYPE_BLOCKING) { blocking_coalesced_event_ids_.push_back( - ui::WebInputEventTraits::GetUniqueTouchEventId(event())); + ui::WebInputEventTraits::GetUniqueTouchEventId(other_event.event())); } else { non_blocking_coalesced_count_++; } @@ -91,7 +91,6 @@ last_coalesced_timestamp_ = base::TimeTicks::Now(); // The newest event (|other_item|) always wins when updating fields. - dispatch_type_ = other_event.dispatch_type_; originally_cancelable_ = other_event.originally_cancelable_; return FilterResult::CoalescedEvent;
diff --git a/content/renderer/input/main_thread_event_queue_unittest.cc b/content/renderer/input/main_thread_event_queue_unittest.cc index 81c324c..ca62245 100644 --- a/content/renderer/input/main_thread_event_queue_unittest.cc +++ b/content/renderer/input/main_thread_event_queue_unittest.cc
@@ -418,12 +418,12 @@ EXPECT_EQ(0u, event_queue().size()); EXPECT_EQ(2u, additional_acked_events_.size()); - EXPECT_EQ(kEvents[1].unique_touch_event_id, additional_acked_events_.at(0)); - EXPECT_EQ(kEvents[2].unique_touch_event_id, additional_acked_events_.at(1)); + EXPECT_EQ(kEvents[2].unique_touch_event_id, additional_acked_events_.at(0)); + EXPECT_EQ(kEvents[3].unique_touch_event_id, additional_acked_events_.at(1)); const WebTouchEvent* last_touch_event = static_cast<const WebTouchEvent*>( handled_tasks_.at(1)->taskAsEvent()->EventPointer()); - EXPECT_EQ(kEvents[3].unique_touch_event_id, + EXPECT_EQ(kEvents[1].unique_touch_event_id, last_touch_event->unique_touch_event_id); HandleEvent(kEvents[1], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING); @@ -643,14 +643,13 @@ EXPECT_FALSE(main_task_runner_->HasPendingTask()); EXPECT_EQ(0u, event_queue().size()); - // Send a discrete input event and then a continuous - // (ack required) event. The events should coalesce together - // and a post task should be on the queue at the end. - HandleEvent(kEvents[1], INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + // Send a non-blocking input event and then blocking event. + // The events should coalesce together. + HandleEvent(kEvents[0], INPUT_EVENT_ACK_STATE_NOT_CONSUMED); EXPECT_EQ(1u, event_queue().size()); EXPECT_FALSE(main_task_runner_->HasPendingTask()); EXPECT_TRUE(needs_main_frame_); - HandleEvent(kEvents[0], INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + HandleEvent(kEvents[1], INPUT_EVENT_ACK_STATE_NOT_CONSUMED); EXPECT_EQ(1u, event_queue().size()); EXPECT_FALSE(main_task_runner_->HasPendingTask()); EXPECT_TRUE(needs_main_frame_);
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index cc67973..bd4ef1a 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -83,7 +83,9 @@ #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" #include "content/public/common/renderer_preferences.h" +#include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" +#include "content/public/common/simple_connection_filter.h" #include "content/public/common/url_constants.h" #include "content/public/renderer/content_renderer_client.h" #include "content/public/renderer/render_thread_observer.h" @@ -141,9 +143,9 @@ #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/base/url_util.h" #include "ppapi/features/features.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/interface_provider.h" -#include "services/service_manager/public/cpp/interface_registry.h" #include "services/ui/public/cpp/bitmap/child_shared_bitmap_manager.h" #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h" #include "services/ui/public/interfaces/constants.mojom.h" @@ -691,11 +693,18 @@ } #endif - // Must be called before RenderThreadStarted() below. - StartServiceManagerConnection(); + auto registry = base::MakeUnique<service_manager::BinderRegistry>(); + registry->AddInterface(base::Bind(&CreateFrameFactory), + base::ThreadTaskRunnerHandle::Get()); + registry->AddInterface(base::Bind(&EmbeddedWorkerInstanceClientImpl::Create), + base::ThreadTaskRunnerHandle::Get()); + GetServiceManagerConnection()->AddConnectionFilter( + base::MakeUnique<SimpleConnectionFilter>(std::move(registry))); GetContentClient()->renderer()->RenderThreadStarted(); + StartServiceManagerConnection(); + field_trial_syncer_.InitFieldTrialObserving( *base::CommandLine::ForCurrentProcess(), switches::kSingleProcess); @@ -859,13 +868,6 @@ base::DiscardableMemoryAllocator::SetInstance( discardable_shared_memory_manager_.get()); - GetContentClient()->renderer()->ExposeInterfacesToBrowser( - GetInterfaceRegistry()); - - GetInterfaceRegistry()->AddInterface(base::Bind(&CreateFrameFactory)); - GetInterfaceRegistry()->AddInterface( - base::Bind(&EmbeddedWorkerInstanceClientImpl::Create)); - GetConnector()->BindInterface(mojom::kBrowserServiceName, mojo::MakeRequest(&storage_partition_service_));
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn index d13f4727..ccf57ca3 100644 --- a/content/shell/BUILD.gn +++ b/content/shell/BUILD.gn
@@ -170,8 +170,6 @@ "renderer/layout_test/blink_test_helpers.h", "renderer/layout_test/blink_test_runner.cc", "renderer/layout_test/blink_test_runner.h", - "renderer/layout_test/interface_registry_js_wrapper.cc", - "renderer/layout_test/interface_registry_js_wrapper.h", "renderer/layout_test/layout_test_content_renderer_client.cc", "renderer/layout_test/layout_test_content_renderer_client.h", "renderer/layout_test/layout_test_render_frame_observer.cc", @@ -239,6 +237,7 @@ "//content/test:layouttest_support", "//content/test:test_support", "//device/bluetooth", + "//device/bluetooth:fake_bluetooth", "//device/bluetooth:mocks", "//device/geolocation", "//device/sensors/public/cpp:full",
diff --git a/content/shell/browser/content_shell_browser_manifest_overlay.json b/content/shell/browser/content_shell_browser_manifest_overlay.json index 8613898e..3e5d67c 100644 --- a/content/shell/browser/content_shell_browser_manifest_overlay.json +++ b/content/shell/browser/content_shell_browser_manifest_overlay.json
@@ -4,7 +4,8 @@ "service_manager:connector": { "provides": { "renderer": [ - "content::mojom::LayoutTestBluetoothFakeAdapterSetter" + "content::mojom::LayoutTestBluetoothFakeAdapterSetter", + "bluetooth::mojom::FakeBluetooth" ] } }
diff --git a/content/shell/browser/layout_test/layout_test_content_browser_client.cc b/content/shell/browser/layout_test/layout_test_content_browser_client.cc index f5aeb06..d58245d 100644 --- a/content/shell/browser/layout_test/layout_test_content_browser_client.cc +++ b/content/shell/browser/layout_test/layout_test_content_browser_client.cc
@@ -21,6 +21,7 @@ #include "content/shell/common/layout_test/layout_test_switches.h" #include "content/shell/common/shell_messages.h" #include "content/shell/renderer/layout_test/blink_test_helpers.h" +#include "device/bluetooth/test/fake_bluetooth.h" #include "services/service_manager/public/cpp/binder_registry.h" namespace content { @@ -80,6 +81,9 @@ registry->AddInterface( base::Bind(&LayoutTestBluetoothFakeAdapterSetterImpl::Create), ui_task_runner); + + registry->AddInterface(base::Bind(&bluetooth::FakeBluetooth::Create), + ui_task_runner); } void LayoutTestContentBrowserClient::OverrideWebkitPrefs(
diff --git a/content/shell/renderer/layout_test/interface_registry_js_wrapper.cc b/content/shell/renderer/layout_test/interface_registry_js_wrapper.cc deleted file mode 100644 index 3a1458f..0000000 --- a/content/shell/renderer/layout_test/interface_registry_js_wrapper.cc +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/shell/renderer/layout_test/interface_registry_js_wrapper.h" - -#include <memory> -#include <utility> - -#include "mojo/edk/js/handle.h" -#include "services/service_manager/public/cpp/interface_registry.h" - -namespace content { - -gin::WrapperInfo InterfaceRegistryJsWrapper::kWrapperInfo = { - gin::kEmbedderNativeGin}; -const char InterfaceRegistryJsWrapper::kPerFrameModuleName[] = - "content/shell/renderer/layout_test/frame_interface_registry"; -const char InterfaceRegistryJsWrapper::kPerProcessModuleName[] = - "content/shell/renderer/layout_test/interface_registry"; - -InterfaceRegistryJsWrapper::~InterfaceRegistryJsWrapper() = default; - -// static -gin::Handle<InterfaceRegistryJsWrapper> InterfaceRegistryJsWrapper::Create( - v8::Isolate* isolate, - v8::Local<v8::Context> context, - service_manager::InterfaceRegistry* interface_registry) { - return gin::CreateHandle( - isolate, new InterfaceRegistryJsWrapper( - isolate, context, interface_registry->GetWeakPtr())); -} - -gin::ObjectTemplateBuilder InterfaceRegistryJsWrapper::GetObjectTemplateBuilder( - v8::Isolate* isolate) { - return Wrappable<InterfaceRegistryJsWrapper>::GetObjectTemplateBuilder( - isolate) - .SetMethod("getLocalInterfaceForTesting", - &InterfaceRegistryJsWrapper::GetLocalInterfaceForTesting); -} - -mojo::Handle InterfaceRegistryJsWrapper::GetLocalInterfaceForTesting( - const std::string& interface_name) { - mojo::MessagePipe pipe; - if (interface_registry_) { - service_manager::InterfaceRegistry::TestApi test_api( - interface_registry_.get()); - test_api.GetLocalInterface(interface_name, std::move(pipe.handle0)); - } - return pipe.handle1.release(); -} - -InterfaceRegistryJsWrapper::InterfaceRegistryJsWrapper( - v8::Isolate* isolate, - v8::Local<v8::Context> context, - base::WeakPtr<service_manager::InterfaceRegistry> interface_registry) - : isolate_(isolate), - context_(isolate, context), - interface_registry_(interface_registry), - weak_factory_(this) { - context_.SetWeak(this, &InterfaceRegistryJsWrapper::ClearContext, - v8::WeakCallbackType::kParameter); -} - -// static -void InterfaceRegistryJsWrapper::ClearContext( - const v8::WeakCallbackInfo<InterfaceRegistryJsWrapper>& data) { - InterfaceRegistryJsWrapper* registry = data.GetParameter(); - registry->context_.Reset(); -} - -} // namespace content
diff --git a/content/shell/renderer/layout_test/interface_registry_js_wrapper.h b/content/shell/renderer/layout_test/interface_registry_js_wrapper.h deleted file mode 100644 index e562316c..0000000 --- a/content/shell/renderer/layout_test/interface_registry_js_wrapper.h +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_SHELL_RENDERER_LAYOUT_TEST_INTERFACE_REGISTRY_JS_WRAPPER_H_ -#define CONTENT_SHELL_RENDERER_LAYOUT_TEST_INTERFACE_REGISTRY_JS_WRAPPER_H_ - -#include <string> - -#include "base/macros.h" -#include "gin/handle.h" -#include "gin/object_template_builder.h" -#include "gin/wrappable.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "v8/include/v8.h" - -namespace service_manager { -class InterfaceRegistry; -} - -namespace content { - -// A JS wrapper around service_manager::InterfaceRegistry that allows connecting -// to -// interfaces exposed by the renderer for testing. -class InterfaceRegistryJsWrapper - : public gin::Wrappable<InterfaceRegistryJsWrapper> { - public: - static gin::Handle<InterfaceRegistryJsWrapper> Create( - v8::Isolate* isolate, - v8::Local<v8::Context> context, - service_manager::InterfaceRegistry* interface_registry); - - // gin::Wrappable<InterfaceRegistryJsWrapper> overrides. - gin::ObjectTemplateBuilder GetObjectTemplateBuilder( - v8::Isolate* isolate) override; - - // JS interface implementation. - mojo::Handle GetLocalInterfaceForTesting(const std::string& interface_name); - - static gin::WrapperInfo kWrapperInfo; - static const char kPerFrameModuleName[]; - static const char kPerProcessModuleName[]; - - private: - using ScopedJsFactory = - v8::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function>>; - - InterfaceRegistryJsWrapper( - v8::Isolate* isolate, - v8::Local<v8::Context> context, - base::WeakPtr<service_manager::InterfaceRegistry> interface_registry); - ~InterfaceRegistryJsWrapper() override; - - void CallJsFactory(const ScopedJsFactory& factory, - mojo::ScopedMessagePipeHandle pipe); - - static void ClearContext( - const v8::WeakCallbackInfo<InterfaceRegistryJsWrapper>& data); - - v8::Isolate* isolate_; - v8::Global<v8::Context> context_; - base::WeakPtr<service_manager::InterfaceRegistry> interface_registry_; - - base::WeakPtrFactory<InterfaceRegistryJsWrapper> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(InterfaceRegistryJsWrapper); -}; - -} // namespace content - -#endif // CONTENT_SHELL_RENDERER_LAYOUT_TEST_INTERFACE_REGISTRY_JS_WRAPPER_H_
diff --git a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc index af5204e..8562261 100644 --- a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc +++ b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
@@ -19,7 +19,6 @@ #include "content/shell/common/shell_switches.h" #include "content/shell/renderer/layout_test/blink_test_helpers.h" #include "content/shell/renderer/layout_test/blink_test_runner.h" -#include "content/shell/renderer/layout_test/interface_registry_js_wrapper.h" #include "content/shell/renderer/layout_test/layout_test_render_frame_observer.h" #include "content/shell/renderer/layout_test/layout_test_render_thread_observer.h" #include "content/shell/renderer/layout_test/test_media_stream_renderer_factory.h" @@ -272,33 +271,6 @@ blink::WebTestingSupport::InjectInternalsObject(context); } -void LayoutTestContentRendererClient::RunScriptsAtDocumentEnd( - RenderFrame* render_frame) { - v8::Isolate* isolate = blink::MainThreadIsolate(); - v8::HandleScope handle_scope(isolate); - blink::WebLocalFrame* frame = render_frame->GetWebFrame(); - v8::Local<v8::Context> context = frame->MainWorldScriptContext(); - v8::Context::Scope context_scope(context); - - gin::ModuleRegistry* registry = gin::ModuleRegistry::From(context); - if (registry->available_modules().count( - InterfaceRegistryJsWrapper::kPerFrameModuleName)) { - return; - } - - registry->AddBuiltinModule( - isolate, InterfaceRegistryJsWrapper::kPerFrameModuleName, - InterfaceRegistryJsWrapper::Create(isolate, context, - render_frame->GetInterfaceRegistry()) - .ToV8()); - registry->AddBuiltinModule( - isolate, InterfaceRegistryJsWrapper::kPerProcessModuleName, - InterfaceRegistryJsWrapper::Create( - isolate, context, RenderThread::Get()->GetInterfaceRegistry()) - .ToV8()); - registry->AttemptToLoadMoreModules(isolate); -} - void LayoutTestContentRendererClient:: SetRuntimeFeaturesDefaultsBeforeBlinkInitialization() { // We always expose GC to layout tests.
diff --git a/content/shell/renderer/layout_test/layout_test_content_renderer_client.h b/content/shell/renderer/layout_test/layout_test_content_renderer_client.h index 3158505..7497fc9e 100644 --- a/content/shell/renderer/layout_test/layout_test_content_renderer_client.h +++ b/content/shell/renderer/layout_test/layout_test_content_renderer_client.h
@@ -38,7 +38,6 @@ std::unique_ptr<gfx::ICCProfile> GetImageDecodeColorProfile() override; void DidInitializeWorkerContextOnWorkerThread( v8::Local<v8::Context> context) override; - void RunScriptsAtDocumentEnd(RenderFrame* render_frame) override; void SetRuntimeFeaturesDefaultsBeforeBlinkInitialization() override; private:
diff --git a/content/shell/renderer/shell_content_renderer_client.cc b/content/shell/renderer/shell_content_renderer_client.cc index a8a3d62..a9e11d6b 100644 --- a/content/shell/renderer/shell_content_renderer_client.cc +++ b/content/shell/renderer/shell_content_renderer_client.cc
@@ -12,13 +12,16 @@ #include "base/macros.h" #include "components/cdm/renderer/external_clear_key_key_system_properties.h" #include "components/web_cache/renderer/web_cache_impl.h" +#include "content/public/child/child_thread.h" +#include "content/public/common/service_manager_connection.h" +#include "content/public/common/simple_connection_filter.h" #include "content/public/test/test_service.mojom.h" #include "content/shell/common/shell_switches.h" #include "content/shell/renderer/shell_render_view_observer.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/message_pipe.h" #include "ppapi/features/features.h" -#include "services/service_manager/public/cpp/interface_registry.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "third_party/WebKit/public/web/WebTestingSupport.h" #include "third_party/WebKit/public/web/WebView.h" #include "v8/include/v8.h" @@ -102,6 +105,14 @@ void ShellContentRendererClient::RenderThreadStarted() { web_cache_impl_.reset(new web_cache::WebCacheImpl()); + + auto registry = base::MakeUnique<service_manager::BinderRegistry>(); + registry->AddInterface<mojom::TestService>( + base::Bind(&CreateTestService), base::ThreadTaskRunnerHandle::Get()); + content::ChildThread::Get() + ->GetServiceManagerConnection() + ->AddConnectionFilter( + base::MakeUnique<SimpleConnectionFilter>(std::move(registry))); } void ShellContentRendererClient::RenderViewCreated(RenderView* render_view) { @@ -135,12 +146,6 @@ } } -void ShellContentRendererClient::ExposeInterfacesToBrowser( - service_manager::InterfaceRegistry* interface_registry) { - interface_registry->AddInterface<mojom::TestService>( - base::Bind(&CreateTestService)); -} - #if defined(ENABLE_MOJO_CDM) void ShellContentRendererClient::AddSupportedKeySystems( std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) {
diff --git a/content/shell/renderer/shell_content_renderer_client.h b/content/shell/renderer/shell_content_renderer_client.h index 5c4b7fb..77b20711 100644 --- a/content/shell/renderer/shell_content_renderer_client.h +++ b/content/shell/renderer/shell_content_renderer_client.h
@@ -34,9 +34,6 @@ void DidInitializeWorkerContextOnWorkerThread( v8::Local<v8::Context> context) override; - void ExposeInterfacesToBrowser( - service_manager::InterfaceRegistry* interface_registry) override; - #if defined(ENABLE_MOJO_CDM) void AddSupportedKeySystems( std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems)
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 2c30533..c4c8faae 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -92,8 +92,6 @@ "../public/test/ppapi_test_utils.h", "../public/test/render_view_test.cc", "../public/test/render_view_test.h", - "../public/test/sandbox_file_system_test_helper.cc", - "../public/test/sandbox_file_system_test_helper.h", "../public/test/test_browser_context.cc", "../public/test/test_browser_context.h", "../public/test/test_browser_thread.cc", @@ -1082,19 +1080,9 @@ "../browser/download/parallel_download_utils_unittest.cc", "../browser/download/rate_estimator_unittest.cc", "../browser/download/save_package_unittest.cc", - "../browser/fileapi/copy_or_move_operation_delegate_unittest.cc", - "../browser/fileapi/dragged_file_util_unittest.cc", - "../browser/fileapi/file_system_context_unittest.cc", - "../browser/fileapi/file_system_operation_impl_unittest.cc", "../browser/fileapi/file_system_operation_impl_write_unittest.cc", "../browser/fileapi/file_system_operation_runner_unittest.cc", "../browser/fileapi/fileapi_message_filter_unittest.cc", - "../browser/fileapi/mock_file_change_observer.cc", - "../browser/fileapi/mock_file_change_observer.h", - "../browser/fileapi/mock_file_update_observer.cc", - "../browser/fileapi/mock_file_update_observer.h", - "../browser/fileapi/obfuscated_file_util_unittest.cc", - "../browser/fileapi/recursive_operation_delegate_unittest.cc", "../browser/fileapi/sandbox_database_test_helper.cc", "../browser/fileapi/sandbox_database_test_helper.h", "../browser/fileapi/sandbox_directory_database_unittest.cc", @@ -1404,8 +1392,6 @@ "../renderer/render_widget_unittest.cc", "../renderer/scheduler/resource_dispatch_throttler_unittest.cc", "../renderer/skia_benchmarking_extension_unittest.cc", - "fileapi_test_file_set.cc", - "fileapi_test_file_set.h", "image_decoder_test.cc", "image_decoder_test.h", "navigation_simulator_unittest.cc", @@ -1452,6 +1438,7 @@ "//components/payments/mojom", "//components/payments/mojom:mojom_payment_app", "//components/rappor:test_support", + "//components/viz/frame_sinks", "//content:resources", "//content/app:both_for_content_tests", "//content/browser:for_content_tests",
diff --git a/content/test/gpu/gpu_tests/path_util.py b/content/test/gpu/gpu_tests/path_util.py index 70d1fcd..0713155 100644 --- a/content/test/gpu/gpu_tests/path_util.py +++ b/content/test/gpu/gpu_tests/path_util.py
@@ -28,9 +28,9 @@ absolute_perf_path = os.path.abspath(perf_path) sys.path.append(absolute_perf_path) - from chrome_telemetry_build import chromium_config + from core import path_util - telemetry_path = chromium_config.GetTelemetryDir() + telemetry_path = path_util.GetTelemetryDir() if telemetry_path not in sys.path: sys.path.append(telemetry_path)
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn index ea00f556..65c0f77 100644 --- a/device/bluetooth/BUILD.gn +++ b/device/bluetooth/BUILD.gn
@@ -41,6 +41,19 @@ ] } +source_set("fake_bluetooth") { + sources = [ + "test/fake_bluetooth.cc", + "test/fake_bluetooth.h", + ] + + deps = [ + ":bluetooth", + "//device/bluetooth/public/interfaces:fake_bluetooth_interfaces", + "//mojo/public/cpp/bindings", + ] +} + component("bluetooth") { sources = [ "android/bluetooth_jni_registrar.cc",
diff --git a/device/bluetooth/README.md b/device/bluetooth/README.md index f3c0ed89..0319a17 100644 --- a/device/bluetooth/README.md +++ b/device/bluetooth/README.md
@@ -43,57 +43,6 @@ Known future work is tracked in the [Refactoring meta issue](https://crbug.com/580406). - -## Testing - -Implementation of the Bluetooth component is tested via unittests. Client code -uses Mock Bluetooth objects: - - -### Cross Platform Unit Tests - -New feature development uses cross platform unit tests. This reduces test code -redundancy and produces consistency across all implementations. - -Unit tests operate at the public `device/bluetooth` API layer and the -`BluetoothTest` fixture controls fake operating system behavior as close to the -platfom as possible. The resulting test coverage spans the cross platform API, -common implementation, and platform specific implementation as close to -operating system APIs as possible. - -`test/bluetooth_test.h` defines the cross platform test fixture -`BluetoothTestBase`. Platform implementations provide subclasses, such as -`test/bluetooth_test_android.h` and typedef to the name `BluetoothTest`. - -[More testing information](https://docs.google.com/document/d/1mBipxn1sJu6jMqP0RQZpkYXC1o601bzLCpCxwTA2yGA/edit?usp=sharing) - -### Legacy Platform Specific Unit Tests - -Early code (Classic on most platforms, and Low Energy on BlueZ) was tested with -platform specific unit tests, e.g. `bluetooth_bluez_unittest.cc` & -`bluetooth_adapter_win_unittest.cc`. The BlueZ style has platform specific -methods to create fake devices and the public API is used to interact with them. - -Maintenance of these earlier implementation featuress should update tests in -place. Long term these tests should be [refactored into cross platform -tests](https://crbug.com/580403). - - -### Mock Bluetooth Objects - -`test/mock_bluetooth_*` files provide GoogleMock based fake objects for use in -client code. - - -### Chrome OS Blueooth Controller Tests - -Bluetooth controller system tests generating radio signals are run and managed -by the Chrome OS team. See: -https://chromium.googlesource.com/chromiumos/third_party/autotest/+/master/server/site_tests/ -https://chromium.googlesource.com/chromiumos/third_party/autotest/+/master/server/cros/bluetooth/ -https://chromium.googlesource.com/chromiumos/third_party/autotest/+/master/client/cros/bluetooth/ - - ## Android The android implementation requires crossing from C++ to Java using @@ -130,6 +79,8 @@ [Class]: https://sites.google.com/a/chromium.org/dev/developers/design-documents/bluetooth-design-docs/web-bluetooth-through-bluetooth-android-class-diagram +## Testing +See [test/README.md](//device/bluetooth/test/README.md) ## Design Documents
diff --git a/device/bluetooth/public/interfaces/BUILD.gn b/device/bluetooth/public/interfaces/BUILD.gn index 810489b..5e7d9c7 100644 --- a/device/bluetooth/public/interfaces/BUILD.gn +++ b/device/bluetooth/public/interfaces/BUILD.gn
@@ -10,6 +10,12 @@ ] } +mojom("fake_bluetooth_interfaces") { + sources = [ + "test/fake_bluetooth.mojom", + ] +} + mojom("experimental_interfaces") { sources = [ "adapter.mojom",
diff --git a/device/bluetooth/public/interfaces/test/OWNERS b/device/bluetooth/public/interfaces/test/OWNERS new file mode 100644 index 0000000..61b5e28 --- /dev/null +++ b/device/bluetooth/public/interfaces/test/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file
diff --git a/device/bluetooth/public/interfaces/test/README.md b/device/bluetooth/public/interfaces/test/README.md new file mode 100644 index 0000000..d91b89b --- /dev/null +++ b/device/bluetooth/public/interfaces/test/README.md
@@ -0,0 +1,12 @@ +# Bluetooth Test + +This folder contains interfaces that are useful for testing of code that uses +device/bluetooth + +## Fake Bluetooth + +`FakeBluetooth` is an interface that allows its clients to fake bluetooth events +at the platform abstraction layer. See fake_bluetooth.mojom for more information +about the interface and +[//device/bluetooth/test/README.md](//device/bluetooth/test/README.md) for +information about its implementation.
diff --git a/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom b/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom new file mode 100644 index 0000000..3ac2e80 --- /dev/null +++ b/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom
@@ -0,0 +1,19 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module bluetooth.mojom; + +// FakeBluetooth and its related interfaces allow clients to control the global +// Bluetooth State as well as simulate Bluetooth events including finding new +// devices, simulating GATT attributes and its descendants, and simulating +// success and error responses. + +// FakeBluetooth allows clients to control the global Bluetooth state. +interface FakeBluetooth { + // Set it to indicate whether the platform supports BLE. For example, Windows + // 7 is a platform that doesn't support Low Energy. On the other hand Windows + // 10 is a platform that does support LE, even if there is no Bluetooth radio + // available. + SetLESupported(bool available) => (); +};
diff --git a/device/bluetooth/test/README.md b/device/bluetooth/test/README.md new file mode 100644 index 0000000..e71787c --- /dev/null +++ b/device/bluetooth/test/README.md
@@ -0,0 +1,56 @@ +# Testing + +Implementation of the Bluetooth component is tested via unittests. Client code +uses Mock Bluetooth objects: + +## Mojo Testing Interface Implementation +See [//public/interfaces/test/README.md](//device/bluetooth/public/interfaces/test/README.md) +for details about the interface. The current implementation of this interface +creates a fake implementation of the current non-mojo C++ Bluetooth interface. +This interface is implemented across files with a "fake_" prefix. +*This interface may be removed when a Bluetooth Mojo Service is introduced, if +Web Bluetooth remains its only client. Testing code would implement the service +as needed for tests.* + +## Cross Platform Unit Tests + +New feature development uses cross platform unit tests. This reduces test code +redundancy and produces consistency across all implementations. + +Unit tests operate at the public `device/bluetooth` API layer and the +`BluetoothTest` fixture controls fake operating system behavior as close to the +platfom as possible. The resulting test coverage spans the cross platform API, +common implementation, and platform specific implementation as close to +operating system APIs as possible. + +`test/bluetooth_test.h` defines the cross platform test fixture +`BluetoothTestBase`. Platform implementations provide subclasses, such as +`test/bluetooth_test_android.h` and typedef to the name `BluetoothTest`. + +[More testing information](https://docs.google.com/document/d/1mBipxn1sJu6jMqP0RQZpkYXC1o601bzLCpCxwTA2yGA/edit?usp=sharing) + +## Legacy Platform Specific Unit Tests + +Early code (Classic on most platforms, and Low Energy on BlueZ) was tested with +platform specific unit tests, e.g. `bluetooth_bluez_unittest.cc` & +`bluetooth_adapter_win_unittest.cc`. The BlueZ style has platform specific +methods to create fake devices and the public API is used to interact with them. + +Maintenance of these earlier implementation featuress should update tests in +place. Long term these tests should be [refactored into cross platform +tests](https://crbug.com/580403). + + +## Mock Bluetooth Objects + +`test/mock_bluetooth_*` files provide GoogleMock based fake objects for use in +client code. + + +## Chrome OS Blueooth Controller Tests + +Bluetooth controller system tests generating radio signals are run and managed +by the Chrome OS team. See: +https://chromium.googlesource.com/chromiumos/third_party/autotest/+/master/server/site_tests/ +https://chromium.googlesource.com/chromiumos/third_party/autotest/+/master/server/cros/bluetooth/ +https://chromium.googlesource.com/chromiumos/third_party/autotest/+/master/client/cros/bluetooth/
diff --git a/device/bluetooth/test/fake_bluetooth.cc b/device/bluetooth/test/fake_bluetooth.cc new file mode 100644 index 0000000..e9af2b3f --- /dev/null +++ b/device/bluetooth/test/fake_bluetooth.cc
@@ -0,0 +1,30 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/test/fake_bluetooth.h" + +#include <utility> + +#include "base/memory/ptr_util.h" +#include "device/bluetooth/public/interfaces/test/fake_bluetooth.mojom.h" +#include "mojo/public/cpp/bindings/strong_binding.h" + +namespace bluetooth { + +FakeBluetooth::FakeBluetooth() {} +FakeBluetooth::~FakeBluetooth() {} + +// static +void FakeBluetooth::Create(mojom::FakeBluetoothRequest request) { + mojo::MakeStrongBinding(base::MakeUnique<FakeBluetooth>(), + std::move(request)); +} + +void FakeBluetooth::SetLESupported(bool available, + const SetLESupportedCallback& callback) { + // TODO(crbug.com/569709): Actually implement this method. + callback.Run(); +} + +} // namespace bluetooth
diff --git a/device/bluetooth/test/fake_bluetooth.h b/device/bluetooth/test/fake_bluetooth.h new file mode 100644 index 0000000..31482f0c --- /dev/null +++ b/device/bluetooth/test/fake_bluetooth.h
@@ -0,0 +1,29 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef DEVICE_BLUETOOTH_TEST_FAKE_BLUETOOTH_H_ +#define DEVICE_BLUETOOTH_TEST_FAKE_BLUETOOTH_H_ + +#include "base/compiler_specific.h" +#include "device/bluetooth/public/interfaces/test/fake_bluetooth.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" + +namespace bluetooth { + +// Implementation of FakeBluetooth in +// src/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom. +// Implemented on top of the C++ device/bluetooth API. +class FakeBluetooth : NON_EXPORTED_BASE(public mojom::FakeBluetooth) { + public: + FakeBluetooth(); + ~FakeBluetooth() override; + + static void Create(mojom::FakeBluetoothRequest request); + + void SetLESupported(bool available, + const SetLESupportedCallback& callback) override; +}; + +} // namespace bluetooth + +#endif // DEVICE_BLUETOOTH_TEST_FAKE_BLUETOOTH_H_
diff --git a/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc b/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc index 2913d65b..f3dd51d 100644 --- a/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc +++ b/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc
@@ -371,7 +371,7 @@ return S_OK; }))); - sensor_events_->OnDataUpdated(sensor_.get(), data_report.get()); + sensor_events_->OnDataUpdated(sensor_.get(), data_report.Get()); } scoped_refptr<MockISensorManager> sensor_manager_;
diff --git a/device/generic_sensor/platform_sensor_reader_win.cc b/device/generic_sensor/platform_sensor_reader_win.cc index 814afd7..566d6968 100644 --- a/device/generic_sensor/platform_sensor_reader_win.cc +++ b/device/generic_sensor/platform_sensor_reader_win.cc
@@ -439,7 +439,7 @@ if (SUCCEEDED(hr)) { base::win::ScopedComPtr<IPortableDeviceValues> return_props; - hr = sensor_->SetProperties(props.get(), return_props.Receive()); + hr = sensor_->SetProperties(props.Get(), return_props.Receive()); return SUCCEEDED(hr); } }
diff --git a/device/sensors/data_fetcher_shared_memory_win.cc b/device/sensors/data_fetcher_shared_memory_win.cc index f2fa6c852..e8ad3df4 100644 --- a/device/sensors/data_fetcher_shared_memory_win.cc +++ b/device/sensors/data_fetcher_shared_memory_win.cc
@@ -371,14 +371,14 @@ base::win::ScopedComPtr<ISensorManager> sensor_manager; HRESULT hr = sensor_manager.CreateInstance(CLSID_SensorManager); - if (FAILED(hr) || !sensor_manager.get()) + if (FAILED(hr) || !sensor_manager.Get()) return false; base::win::ScopedComPtr<ISensorCollection> sensor_collection; hr = sensor_manager->GetSensorsByType(sensor_type, sensor_collection.Receive()); - if (FAILED(hr) || !sensor_collection.get()) + if (FAILED(hr) || !sensor_collection.Get()) return false; ULONG count = 0; @@ -396,17 +396,17 @@ SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, GetInterval().InMilliseconds()))) { base::win::ScopedComPtr<IPortableDeviceValues> return_values; - (*sensor)->SetProperties(device_values.get(), return_values.Receive()); + (*sensor)->SetProperties(device_values.Get(), return_values.Receive()); } } base::win::ScopedComPtr<ISensorEvents> sensor_events; hr = event_sink->QueryInterface(__uuidof(ISensorEvents), sensor_events.ReceiveVoid()); - if (FAILED(hr) || !sensor_events.get()) + if (FAILED(hr) || !sensor_events.Get()) return false; - hr = (*sensor)->SetEventSink(sensor_events.get()); + hr = (*sensor)->SetEventSink(sensor_events.Get()); if (FAILED(hr)) return false; @@ -416,29 +416,29 @@ void DataFetcherSharedMemory::DisableSensors(ConsumerType consumer_type) { switch (consumer_type) { case CONSUMER_TYPE_ORIENTATION: - if (sensor_inclinometer_.get()) { + if (sensor_inclinometer_.Get()) { sensor_inclinometer_->SetEventSink(nullptr); sensor_inclinometer_.Reset(); } break; case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: - if (sensor_inclinometer_absolute_.get()) { + if (sensor_inclinometer_absolute_.Get()) { sensor_inclinometer_absolute_->SetEventSink(nullptr); sensor_inclinometer_absolute_.Reset(); } break; case CONSUMER_TYPE_MOTION: - if (sensor_accelerometer_.get()) { + if (sensor_accelerometer_.Get()) { sensor_accelerometer_->SetEventSink(nullptr); sensor_accelerometer_.Reset(); } - if (sensor_gyrometer_.get()) { + if (sensor_gyrometer_.Get()) { sensor_gyrometer_->SetEventSink(nullptr); sensor_gyrometer_.Reset(); } break; case CONSUMER_TYPE_LIGHT: - if (sensor_light_.get()) { + if (sensor_light_.Get()) { sensor_light_->SetEventSink(nullptr); sensor_light_.Reset(); }
diff --git a/device/usb/mojo/device_impl.cc b/device/usb/mojo/device_impl.cc index acbf468..574cb90d 100644 --- a/device/usb/mojo/device_impl.cc +++ b/device/usb/mojo/device_impl.cc
@@ -22,6 +22,10 @@ #include "net/base/io_buffer.h" namespace device { + +using mojom::UsbControlTransferParamsPtr; +using mojom::UsbControlTransferRecipient; + namespace usb { namespace { @@ -31,7 +35,7 @@ std::max(static_cast<size_t>(1u), static_cast<size_t>(size))); } -void OnTransferIn(const Device::GenericTransferInCallback& callback, +void OnTransferIn(const mojom::UsbDevice::GenericTransferInCallback& callback, UsbTransferStatus status, scoped_refptr<net::IOBuffer> buffer, size_t buffer_size) { @@ -44,23 +48,23 @@ std::copy(buffer->data(), buffer->data() + buffer_size, data.begin()); } - callback.Run(mojo::ConvertTo<TransferStatus>(status), data); + callback.Run(mojo::ConvertTo<mojom::UsbTransferStatus>(status), data); } -void OnTransferOut(const Device::GenericTransferOutCallback& callback, +void OnTransferOut(const mojom::UsbDevice::GenericTransferOutCallback& callback, UsbTransferStatus status, scoped_refptr<net::IOBuffer> buffer, size_t buffer_size) { - callback.Run(mojo::ConvertTo<TransferStatus>(status)); + callback.Run(mojo::ConvertTo<mojom::UsbTransferStatus>(status)); } -std::vector<IsochronousPacketPtr> BuildIsochronousPacketArray( +std::vector<mojom::UsbIsochronousPacketPtr> BuildIsochronousPacketArray( const std::vector<uint32_t>& packet_lengths, - TransferStatus status) { - std::vector<IsochronousPacketPtr> packets; + mojom::UsbTransferStatus status) { + std::vector<mojom::UsbIsochronousPacketPtr> packets; packets.reserve(packet_lengths.size()); for (uint32_t packet_length : packet_lengths) { - auto packet = IsochronousPacket::New(); + auto packet = mojom::UsbIsochronousPacket::New(); packet->length = packet_length; packet->status = status; packets.push_back(std::move(packet)); @@ -69,7 +73,7 @@ } void OnIsochronousTransferIn( - const Device::IsochronousTransferInCallback& callback, + const mojom::UsbDevice::IsochronousTransferInCallback& callback, scoped_refptr<net::IOBuffer> buffer, const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) { std::vector<uint8_t> data; @@ -86,23 +90,25 @@ data.resize(buffer_size); std::copy(buffer->data(), buffer->data() + buffer_size, data.begin()); } - callback.Run(data, - mojo::ConvertTo<std::vector<IsochronousPacketPtr>>(packets)); + callback.Run( + data, + mojo::ConvertTo<std::vector<mojom::UsbIsochronousPacketPtr>>(packets)); } void OnIsochronousTransferOut( - const Device::IsochronousTransferOutCallback& callback, + const mojom::UsbDevice::IsochronousTransferOutCallback& callback, scoped_refptr<net::IOBuffer> buffer, const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) { - callback.Run(mojo::ConvertTo<std::vector<IsochronousPacketPtr>>(packets)); + callback.Run( + mojo::ConvertTo<std::vector<mojom::UsbIsochronousPacketPtr>>(packets)); } } // namespace // static -void DeviceImpl::Create(scoped_refptr<UsbDevice> device, +void DeviceImpl::Create(scoped_refptr<device::UsbDevice> device, base::WeakPtr<PermissionProvider> permission_provider, - DeviceRequest request) { + mojom::UsbDeviceRequest request) { auto* device_impl = new DeviceImpl(std::move(device), std::move(permission_provider)); device_impl->binding_ = mojo::MakeStrongBinding(base::WrapUnique(device_impl), @@ -113,7 +119,7 @@ CloseHandle(); } -DeviceImpl::DeviceImpl(scoped_refptr<UsbDevice> device, +DeviceImpl::DeviceImpl(scoped_refptr<device::UsbDevice> device, base::WeakPtr<PermissionProvider> permission_provider) : device_(std::move(device)), permission_provider_(std::move(permission_provider)), @@ -133,7 +139,7 @@ } bool DeviceImpl::HasControlTransferPermission( - ControlTransferRecipient recipient, + UsbControlTransferRecipient recipient, uint16_t index) { DCHECK(device_handle_); const UsbConfigDescriptor* config = device_->active_configuration(); @@ -141,13 +147,13 @@ if (!permission_provider_) return false; - if (recipient == ControlTransferRecipient::INTERFACE || - recipient == ControlTransferRecipient::ENDPOINT) { + if (recipient == UsbControlTransferRecipient::INTERFACE || + recipient == UsbControlTransferRecipient::ENDPOINT) { if (!config) return false; const UsbInterfaceDescriptor* interface = nullptr; - if (recipient == ControlTransferRecipient::ENDPOINT) { + if (recipient == UsbControlTransferRecipient::ENDPOINT) { interface = device_handle_->FindInterfaceByEndpoint(index & 0xff); } else { auto interface_it = @@ -184,8 +190,8 @@ self->device_handle_ = std::move(handle); if (self->device_handle_ && self->permission_provider_) self->permission_provider_->IncrementConnectionCount(); - callback.Run(self->device_handle_ ? OpenDeviceError::OK - : OpenDeviceError::ACCESS_DENIED); + callback.Run(self->device_handle_ ? mojom::UsbOpenDeviceError::OK + : mojom::UsbOpenDeviceError::ACCESS_DENIED); } void DeviceImpl::OnPermissionGrantedForOpen(const OpenCallback& callback, @@ -195,13 +201,13 @@ device_->Open( base::Bind(&DeviceImpl::OnOpen, weak_factory_.GetWeakPtr(), callback)); } else { - callback.Run(OpenDeviceError::ACCESS_DENIED); + callback.Run(mojom::UsbOpenDeviceError::ACCESS_DENIED); } } void DeviceImpl::Open(const OpenCallback& callback) { if (device_handle_) { - callback.Run(OpenDeviceError::ALREADY_OPEN); + callback.Run(mojom::UsbOpenDeviceError::ALREADY_OPEN); return; } @@ -217,7 +223,7 @@ device_->Open( base::Bind(&DeviceImpl::OnOpen, weak_factory_.GetWeakPtr(), callback)); } else { - callback.Run(OpenDeviceError::ACCESS_DENIED); + callback.Run(mojom::UsbOpenDeviceError::ACCESS_DENIED); } } @@ -316,12 +322,12 @@ device_handle_->ClearHalt(endpoint, callback); } -void DeviceImpl::ControlTransferIn(ControlTransferParamsPtr params, +void DeviceImpl::ControlTransferIn(UsbControlTransferParamsPtr params, uint32_t length, uint32_t timeout, const ControlTransferInCallback& callback) { if (!device_handle_) { - callback.Run(TransferStatus::TRANSFER_ERROR, base::nullopt); + callback.Run(mojom::UsbTransferStatus::TRANSFER_ERROR, base::nullopt); return; } @@ -334,17 +340,17 @@ params->request, params->value, params->index, buffer, length, timeout, base::Bind(&OnTransferIn, callback)); } else { - callback.Run(TransferStatus::PERMISSION_DENIED, base::nullopt); + callback.Run(mojom::UsbTransferStatus::PERMISSION_DENIED, base::nullopt); } } void DeviceImpl::ControlTransferOut( - ControlTransferParamsPtr params, + UsbControlTransferParamsPtr params, const std::vector<uint8_t>& data, uint32_t timeout, const ControlTransferOutCallback& callback) { if (!device_handle_) { - callback.Run(TransferStatus::TRANSFER_ERROR); + callback.Run(mojom::UsbTransferStatus::TRANSFER_ERROR); return; } @@ -358,7 +364,7 @@ params->request, params->value, params->index, buffer, data.size(), timeout, base::Bind(&OnTransferOut, callback)); } else { - callback.Run(TransferStatus::PERMISSION_DENIED); + callback.Run(mojom::UsbTransferStatus::PERMISSION_DENIED); } } @@ -367,7 +373,7 @@ uint32_t timeout, const GenericTransferInCallback& callback) { if (!device_handle_) { - callback.Run(TransferStatus::TRANSFER_ERROR, base::nullopt); + callback.Run(mojom::UsbTransferStatus::TRANSFER_ERROR, base::nullopt); return; } @@ -384,7 +390,7 @@ uint32_t timeout, const GenericTransferOutCallback& callback) { if (!device_handle_) { - callback.Run(TransferStatus::TRANSFER_ERROR); + callback.Run(mojom::UsbTransferStatus::TRANSFER_ERROR); return; } @@ -403,8 +409,8 @@ const IsochronousTransferInCallback& callback) { if (!device_handle_) { callback.Run(base::nullopt, - BuildIsochronousPacketArray(packet_lengths, - TransferStatus::TRANSFER_ERROR)); + BuildIsochronousPacketArray( + packet_lengths, mojom::UsbTransferStatus::TRANSFER_ERROR)); return; } @@ -421,8 +427,8 @@ uint32_t timeout, const IsochronousTransferOutCallback& callback) { if (!device_handle_) { - callback.Run(BuildIsochronousPacketArray(packet_lengths, - TransferStatus::TRANSFER_ERROR)); + callback.Run(BuildIsochronousPacketArray( + packet_lengths, mojom::UsbTransferStatus::TRANSFER_ERROR)); return; } @@ -434,7 +440,7 @@ base::Bind(&OnIsochronousTransferOut, callback)); } -void DeviceImpl::OnDeviceRemoved(scoped_refptr<UsbDevice> device) { +void DeviceImpl::OnDeviceRemoved(scoped_refptr<device::UsbDevice> device) { DCHECK_EQ(device_, device); binding_->Close(); }
diff --git a/device/usb/mojo/device_impl.h b/device/usb/mojo/device_impl.h index 60a7756..02983ca 100644 --- a/device/usb/mojo/device_impl.h +++ b/device/usb/mojo/device_impl.h
@@ -27,16 +27,16 @@ // Implementation of the public Device interface. Instances of this class are // constructed by DeviceManagerImpl and are strongly bound to their MessagePipe // lifetime. -class DeviceImpl : public Device, public device::UsbDevice::Observer { +class DeviceImpl : public mojom::UsbDevice, public device::UsbDevice::Observer { public: - static void Create(scoped_refptr<UsbDevice> device, + static void Create(scoped_refptr<device::UsbDevice> device, base::WeakPtr<PermissionProvider> permission_provider, - DeviceRequest request); + mojom::UsbDeviceRequest request); ~DeviceImpl() override; private: - DeviceImpl(scoped_refptr<UsbDevice> device, + DeviceImpl(scoped_refptr<device::UsbDevice> device, base::WeakPtr<PermissionProvider> permission_provider); // Closes the device if it's open. This will always set |device_handle_| to @@ -44,8 +44,9 @@ void CloseHandle(); // Checks interface permissions for control transfers. - bool HasControlTransferPermission(ControlTransferRecipient recipient, - uint16_t index); + bool HasControlTransferPermission( + mojom::UsbControlTransferRecipient recipient, + uint16_t index); // Handles completion of an open request. static void OnOpen(base::WeakPtr<DeviceImpl> device, @@ -68,11 +69,11 @@ const SetInterfaceAlternateSettingCallback& callback) override; void Reset(const ResetCallback& callback) override; void ClearHalt(uint8_t endpoint, const ClearHaltCallback& callback) override; - void ControlTransferIn(ControlTransferParamsPtr params, + void ControlTransferIn(mojom::UsbControlTransferParamsPtr params, uint32_t length, uint32_t timeout, const ControlTransferInCallback& callback) override; - void ControlTransferOut(ControlTransferParamsPtr params, + void ControlTransferOut(mojom::UsbControlTransferParamsPtr params, const std::vector<uint8_t>& data, uint32_t timeout, const ControlTransferOutCallback& callback) override; @@ -99,7 +100,7 @@ // device::UsbDevice::Observer implementation: void OnDeviceRemoved(scoped_refptr<device::UsbDevice> device) override; - const scoped_refptr<UsbDevice> device_; + const scoped_refptr<device::UsbDevice> device_; base::WeakPtr<PermissionProvider> permission_provider_; ScopedObserver<device::UsbDevice, device::UsbDevice::Observer> observer_; @@ -107,7 +108,7 @@ // has been closed. scoped_refptr<UsbDeviceHandle> device_handle_; - mojo::StrongBindingPtr<Device> binding_; + mojo::StrongBindingPtr<mojom::UsbDevice> binding_; base::WeakPtrFactory<DeviceImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(DeviceImpl);
diff --git a/device/usb/mojo/device_impl_unittest.cc b/device/usb/mojo/device_impl_unittest.cc index 8fbf075d6..a077a81 100644 --- a/device/usb/mojo/device_impl_unittest.cc +++ b/device/usb/mojo/device_impl_unittest.cc
@@ -34,6 +34,12 @@ using ::testing::_; namespace device { + +using mojom::UsbIsochronousPacketPtr; +using mojom::UsbControlTransferRecipient; +using mojom::UsbControlTransferType; +using mojom::UsbDevicePtr; + namespace usb { namespace { @@ -58,9 +64,9 @@ UsbConfigDescriptor config_; }; -void ExpectOpenAndThen(OpenDeviceError expected, +void ExpectOpenAndThen(mojom::UsbOpenDeviceError expected, const base::Closure& continuation, - OpenDeviceError error) { + mojom::UsbOpenDeviceError error) { EXPECT_EQ(expected, error); continuation.Run(); } @@ -73,10 +79,10 @@ } void ExpectTransferInAndThen( - TransferStatus expected_status, + mojom::UsbTransferStatus expected_status, const std::vector<uint8_t>& expected_bytes, const base::Closure& continuation, - TransferStatus actual_status, + mojom::UsbTransferStatus actual_status, const base::Optional<std::vector<uint8_t>>& actual_bytes) { EXPECT_EQ(expected_status, actual_status); ASSERT_TRUE(actual_bytes); @@ -88,14 +94,15 @@ continuation.Run(); } -void ExpectPacketsOutAndThen(const std::vector<uint32_t>& expected_packets, - const base::Closure& continuation, - std::vector<IsochronousPacketPtr> actual_packets) { +void ExpectPacketsOutAndThen( + const std::vector<uint32_t>& expected_packets, + const base::Closure& continuation, + std::vector<UsbIsochronousPacketPtr> actual_packets) { ASSERT_EQ(expected_packets.size(), actual_packets.size()); for (size_t i = 0; i < expected_packets.size(); ++i) { EXPECT_EQ(expected_packets[i], actual_packets[i]->transferred_length) << "Packet lengths differ at index: " << i; - EXPECT_EQ(TransferStatus::COMPLETED, actual_packets[i]->status) + EXPECT_EQ(mojom::UsbTransferStatus::COMPLETED, actual_packets[i]->status) << "Packet at index " << i << " not completed."; } continuation.Run(); @@ -106,12 +113,12 @@ const std::vector<uint32_t>& expected_packets, const base::Closure& continuation, const base::Optional<std::vector<uint8_t>>& actual_bytes, - std::vector<IsochronousPacketPtr> actual_packets) { + std::vector<UsbIsochronousPacketPtr> actual_packets) { ASSERT_EQ(expected_packets.size(), actual_packets.size()); for (size_t i = 0; i < expected_packets.size(); ++i) { EXPECT_EQ(expected_packets[i], actual_packets[i]->transferred_length) << "Packet lengths differ at index: " << i; - EXPECT_EQ(TransferStatus::COMPLETED, actual_packets[i]->status) + EXPECT_EQ(mojom::UsbTransferStatus::COMPLETED, actual_packets[i]->status) << "Packet at index " << i << " not completed."; } ASSERT_TRUE(actual_bytes); @@ -123,9 +130,9 @@ continuation.Run(); } -void ExpectTransferStatusAndThen(TransferStatus expected_status, +void ExpectTransferStatusAndThen(mojom::UsbTransferStatus expected_status, const base::Closure& continuation, - TransferStatus actual_status) { + mojom::UsbTransferStatus actual_status) { EXPECT_EQ(expected_status, actual_status); continuation.Run(); } @@ -151,16 +158,16 @@ // Creates a mock device and binds a Device proxy to a Device service impl // wrapping the mock device. - DevicePtr GetMockDeviceProxy(uint16_t vendor_id, - uint16_t product_id, - const std::string& manufacturer, - const std::string& product, - const std::string& serial) { + UsbDevicePtr GetMockDeviceProxy(uint16_t vendor_id, + uint16_t product_id, + const std::string& manufacturer, + const std::string& product, + const std::string& serial) { mock_device_ = new MockUsbDevice(vendor_id, product_id, manufacturer, product, serial); mock_handle_ = new MockUsbDeviceHandle(mock_device_.get()); - DevicePtr proxy; + UsbDevicePtr proxy; DeviceImpl::Create(mock_device_, permission_provider_.GetWeakPtr(), mojo::MakeRequest(&proxy)); @@ -194,7 +201,7 @@ return proxy; } - DevicePtr GetMockDeviceProxy() { + UsbDevicePtr GetMockDeviceProxy() { return GetMockDeviceProxy(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF"); } @@ -425,7 +432,7 @@ } // namespace TEST_F(USBDeviceImplTest, Disconnect) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); base::RunLoop loop; device.set_connection_error_handler(loop.QuitClosure()); @@ -434,7 +441,7 @@ } TEST_F(USBDeviceImplTest, Open) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_FALSE(is_device_open()); @@ -442,14 +449,15 @@ { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::ALREADY_OPEN, + device->Open(base::Bind(&ExpectOpenAndThen, + mojom::UsbOpenDeviceError::ALREADY_OPEN, loop.QuitClosure())); loop.Run(); } @@ -458,7 +466,7 @@ } TEST_F(USBDeviceImplTest, Close) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_FALSE(is_device_open()); @@ -466,7 +474,7 @@ { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -483,13 +491,13 @@ } TEST_F(USBDeviceImplTest, SetInvalidConfiguration) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -510,13 +518,13 @@ } TEST_F(USBDeviceImplTest, SetValidConfiguration) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -540,13 +548,13 @@ // Verify that the result of Reset() reflects the underlying UsbDeviceHandle's // ResetDevice() result. TEST_F(USBDeviceImplTest, Reset) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -575,13 +583,13 @@ } TEST_F(USBDeviceImplTest, ClaimAndReleaseInterface) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -641,13 +649,13 @@ } TEST_F(USBDeviceImplTest, SetInterfaceAlternateSetting) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -679,13 +687,13 @@ } TEST_F(USBDeviceImplTest, ControlTransfer) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -715,17 +723,18 @@ EXPECT_CALL(permission_provider(), HasConfigurationPermission(1, _)); { - auto params = ControlTransferParams::New(); - params->type = ControlTransferType::STANDARD; - params->recipient = ControlTransferRecipient::DEVICE; + auto params = mojom::UsbControlTransferParams::New(); + params->type = UsbControlTransferType::STANDARD; + params->recipient = UsbControlTransferRecipient::DEVICE; params->request = 5; params->value = 6; params->index = 7; base::RunLoop loop; - device->ControlTransferIn( - std::move(params), static_cast<uint32_t>(fake_data.size()), 0, - base::Bind(&ExpectTransferInAndThen, TransferStatus::COMPLETED, - fake_data, loop.QuitClosure())); + device->ControlTransferIn(std::move(params), + static_cast<uint32_t>(fake_data.size()), 0, + base::Bind(&ExpectTransferInAndThen, + mojom::UsbTransferStatus::COMPLETED, + fake_data, loop.QuitClosure())); loop.Run(); } @@ -737,17 +746,17 @@ EXPECT_CALL(permission_provider(), HasFunctionPermission(7, 1, _)); { - auto params = ControlTransferParams::New(); - params->type = ControlTransferType::STANDARD; - params->recipient = ControlTransferRecipient::INTERFACE; + auto params = mojom::UsbControlTransferParams::New(); + params->type = UsbControlTransferType::STANDARD; + params->recipient = UsbControlTransferRecipient::INTERFACE; params->request = 5; params->value = 6; params->index = 7; base::RunLoop loop; device->ControlTransferOut( std::move(params), fake_data, 0, - base::Bind(&ExpectTransferStatusAndThen, TransferStatus::COMPLETED, - loop.QuitClosure())); + base::Bind(&ExpectTransferStatusAndThen, + mojom::UsbTransferStatus::COMPLETED, loop.QuitClosure())); loop.Run(); } @@ -755,13 +764,13 @@ } TEST_F(USBDeviceImplTest, GenericTransfer) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); } @@ -785,8 +794,8 @@ base::RunLoop loop; device->GenericTransferOut( 1, fake_outbound_data, 0, - base::Bind(&ExpectTransferStatusAndThen, TransferStatus::COMPLETED, - loop.QuitClosure())); + base::Bind(&ExpectTransferStatusAndThen, + mojom::UsbTransferStatus::COMPLETED, loop.QuitClosure())); loop.Run(); } @@ -797,8 +806,9 @@ base::RunLoop loop; device->GenericTransferIn( 1, static_cast<uint32_t>(fake_inbound_data.size()), 0, - base::Bind(&ExpectTransferInAndThen, TransferStatus::COMPLETED, - fake_inbound_data, loop.QuitClosure())); + base::Bind(&ExpectTransferInAndThen, + mojom::UsbTransferStatus::COMPLETED, fake_inbound_data, + loop.QuitClosure())); loop.Run(); } @@ -806,13 +816,13 @@ } TEST_F(USBDeviceImplTest, IsochronousTransfer) { - DevicePtr device = GetMockDeviceProxy(); + UsbDevicePtr device = GetMockDeviceProxy(); EXPECT_CALL(mock_device(), Open(_)); { base::RunLoop loop; - device->Open(base::Bind(&ExpectOpenAndThen, OpenDeviceError::OK, + device->Open(base::Bind(&ExpectOpenAndThen, mojom::UsbOpenDeviceError::OK, loop.QuitClosure())); loop.Run(); }
diff --git a/device/usb/mojo/device_manager_impl.cc b/device/usb/mojo/device_manager_impl.cc index 53a0834..31a08beb 100644 --- a/device/usb/mojo/device_manager_impl.cc +++ b/device/usb/mojo/device_manager_impl.cc
@@ -28,7 +28,7 @@ // static void DeviceManagerImpl::Create( base::WeakPtr<PermissionProvider> permission_provider, - DeviceManagerRequest request) { + mojom::UsbDeviceManagerRequest request) { DCHECK(DeviceClient::Get()); UsbService* service = DeviceClient::Get()->GetUsbService(); if (!service) @@ -56,7 +56,7 @@ DeviceManagerImpl::~DeviceManagerImpl() { } -void DeviceManagerImpl::GetDevices(EnumerationOptionsPtr options, +void DeviceManagerImpl::GetDevices(mojom::UsbEnumerationOptionsPtr options, const GetDevicesCallback& callback) { usb_service_->GetDevices(base::Bind(&DeviceManagerImpl::OnGetDevices, weak_factory_.GetWeakPtr(), @@ -64,7 +64,7 @@ } void DeviceManagerImpl::GetDevice(const std::string& guid, - DeviceRequest device_request) { + mojom::UsbDeviceRequest device_request) { scoped_refptr<UsbDevice> device = usb_service_->GetDevice(guid); if (!device) return; @@ -76,24 +76,24 @@ } } -void DeviceManagerImpl::SetClient(DeviceManagerClientPtr client) { +void DeviceManagerImpl::SetClient(mojom::UsbDeviceManagerClientPtr client) { client_ = std::move(client); } void DeviceManagerImpl::OnGetDevices( - EnumerationOptionsPtr options, + mojom::UsbEnumerationOptionsPtr options, const GetDevicesCallback& callback, const std::vector<scoped_refptr<UsbDevice>>& devices) { std::vector<UsbDeviceFilter> filters; if (options && options->filters) filters.swap(*options->filters); - std::vector<DeviceInfoPtr> device_infos; + std::vector<mojom::UsbDeviceInfoPtr> device_infos; for (const auto& device : devices) { if (UsbDeviceFilter::MatchesAny(*device, filters)) { if (permission_provider_ && permission_provider_->HasDevicePermission(device)) { - device_infos.push_back(DeviceInfo::From(*device)); + device_infos.push_back(mojom::UsbDeviceInfo::From(*device)); } } } @@ -104,13 +104,13 @@ void DeviceManagerImpl::OnDeviceAdded(scoped_refptr<UsbDevice> device) { if (client_ && permission_provider_ && permission_provider_->HasDevicePermission(device)) - client_->OnDeviceAdded(DeviceInfo::From(*device)); + client_->OnDeviceAdded(mojom::UsbDeviceInfo::From(*device)); } void DeviceManagerImpl::OnDeviceRemoved(scoped_refptr<UsbDevice> device) { if (client_ && permission_provider_ && permission_provider_->HasDevicePermission(device)) - client_->OnDeviceRemoved(DeviceInfo::From(*device)); + client_->OnDeviceRemoved(mojom::UsbDeviceInfo::From(*device)); } void DeviceManagerImpl::WillDestroyUsbService() {
diff --git a/device/usb/mojo/device_manager_impl.h b/device/usb/mojo/device_manager_impl.h index 9bb7549..52c73a93 100644 --- a/device/usb/mojo/device_manager_impl.h +++ b/device/usb/mojo/device_manager_impl.h
@@ -28,10 +28,11 @@ // Implementation of the public DeviceManager interface. This interface can be // requested from the devices app located at "devices", if available. -class DeviceManagerImpl : public DeviceManager, public UsbService::Observer { +class DeviceManagerImpl : public mojom::UsbDeviceManager, + public UsbService::Observer { public: static void Create(base::WeakPtr<PermissionProvider> permission_provider, - DeviceManagerRequest request); + mojom::UsbDeviceManagerRequest request); ~DeviceManagerImpl() override; @@ -40,14 +41,14 @@ UsbService* usb_service); // DeviceManager implementation: - void GetDevices(EnumerationOptionsPtr options, + void GetDevices(mojom::UsbEnumerationOptionsPtr options, const GetDevicesCallback& callback) override; void GetDevice(const std::string& guid, - DeviceRequest device_request) override; - void SetClient(DeviceManagerClientPtr client) override; + mojom::UsbDeviceRequest device_request) override; + void SetClient(mojom::UsbDeviceManagerClientPtr client) override; // Callbacks to handle the async responses from the underlying UsbService. - void OnGetDevices(EnumerationOptionsPtr options, + void OnGetDevices(mojom::UsbEnumerationOptionsPtr options, const GetDevicesCallback& callback, const std::vector<scoped_refptr<UsbDevice>>& devices); @@ -58,12 +59,12 @@ void MaybeRunDeviceChangesCallback(); - mojo::StrongBindingPtr<DeviceManager> binding_; + mojo::StrongBindingPtr<mojom::UsbDeviceManager> binding_; base::WeakPtr<PermissionProvider> permission_provider_; UsbService* usb_service_; ScopedObserver<UsbService, UsbService::Observer> observer_; - DeviceManagerClientPtr client_; + mojom::UsbDeviceManagerClientPtr client_; base::WeakPtrFactory<DeviceManagerImpl> weak_factory_;
diff --git a/device/usb/mojo/device_manager_impl_unittest.cc b/device/usb/mojo/device_manager_impl_unittest.cc index f3a1c9d..1a234cd 100644 --- a/device/usb/mojo/device_manager_impl_unittest.cc +++ b/device/usb/mojo/device_manager_impl_unittest.cc
@@ -30,6 +30,13 @@ using ::testing::_; namespace device { + +using mojom::UsbDevicePtr; +using mojom::UsbDeviceInfoPtr; +using mojom::UsbDeviceManagerClientPtr; +using mojom::UsbDeviceManagerPtr; +using mojom::UsbEnumerationOptionsPtr; + namespace usb { namespace { @@ -47,8 +54,8 @@ ~USBDeviceManagerImplTest() override {} protected: - DeviceManagerPtr ConnectToDeviceManager() { - DeviceManagerPtr device_manager; + UsbDeviceManagerPtr ConnectToDeviceManager() { + UsbDeviceManagerPtr device_manager; DeviceManagerImpl::Create(permission_provider_.GetWeakPtr(), mojo::MakeRequest(&device_manager)); return device_manager; @@ -61,32 +68,32 @@ std::unique_ptr<base::MessageLoop> message_loop_; }; -class MockDeviceManagerClient : public DeviceManagerClient { +class MockDeviceManagerClient : public mojom::UsbDeviceManagerClient { public: MockDeviceManagerClient() : binding_(this) {} ~MockDeviceManagerClient() {} - DeviceManagerClientPtr CreateInterfacePtrAndBind() { + UsbDeviceManagerClientPtr CreateInterfacePtrAndBind() { return binding_.CreateInterfacePtrAndBind(); } - MOCK_METHOD1(DoOnDeviceAdded, void(DeviceInfo*)); - void OnDeviceAdded(DeviceInfoPtr device_info) { + MOCK_METHOD1(DoOnDeviceAdded, void(mojom::UsbDeviceInfo*)); + void OnDeviceAdded(UsbDeviceInfoPtr device_info) { DoOnDeviceAdded(device_info.get()); } - MOCK_METHOD1(DoOnDeviceRemoved, void(DeviceInfo*)); - void OnDeviceRemoved(DeviceInfoPtr device_info) { + MOCK_METHOD1(DoOnDeviceRemoved, void(mojom::UsbDeviceInfo*)); + void OnDeviceRemoved(UsbDeviceInfoPtr device_info) { DoOnDeviceRemoved(device_info.get()); } private: - mojo::Binding<DeviceManagerClient> binding_; + mojo::Binding<mojom::UsbDeviceManagerClient> binding_; }; void ExpectDevicesAndThen(const std::set<std::string>& expected_guids, const base::Closure& continuation, - std::vector<DeviceInfoPtr> results) { + std::vector<UsbDeviceInfoPtr> results) { EXPECT_EQ(expected_guids.size(), results.size()); std::set<std::string> actual_guids; for (size_t i = 0; i < results.size(); ++i) @@ -111,9 +118,9 @@ device_client_.usb_service()->AddDevice(device1); device_client_.usb_service()->AddDevice(device2); - DeviceManagerPtr device_manager = ConnectToDeviceManager(); + UsbDeviceManagerPtr device_manager = ConnectToDeviceManager(); - EnumerationOptionsPtr options = EnumerationOptions::New(); + UsbEnumerationOptionsPtr options = mojom::UsbEnumerationOptions::New(); UsbDeviceFilter filter; filter.vendor_id = 0x1234; options->filters.emplace(); @@ -138,11 +145,11 @@ device_client_.usb_service()->AddDevice(mock_device); - DeviceManagerPtr device_manager = ConnectToDeviceManager(); + UsbDeviceManagerPtr device_manager = ConnectToDeviceManager(); { base::RunLoop loop; - DevicePtr device; + UsbDevicePtr device; device_manager->GetDevice(mock_device->guid(), mojo::MakeRequest(&device)); // Close is a no-op if the device hasn't been opened but ensures that the // pipe was successfully connected. @@ -150,7 +157,7 @@ loop.Run(); } - DevicePtr bad_device; + UsbDevicePtr bad_device; device_manager->GetDevice("not a real guid", mojo::MakeRequest(&bad_device)); { @@ -173,7 +180,7 @@ device_client_.usb_service()->AddDevice(device0); - DeviceManagerPtr device_manager = ConnectToDeviceManager(); + UsbDeviceManagerPtr device_manager = ConnectToDeviceManager(); MockDeviceManagerClient mock_client; device_manager->SetClient(mock_client.CreateInterfacePtrAndBind());
diff --git a/device/usb/mojo/type_converters.cc b/device/usb/mojo/type_converters.cc index 09b8bd9..da85613 100644 --- a/device/usb/mojo/type_converters.cc +++ b/device/usb/mojo/type_converters.cc
@@ -17,55 +17,56 @@ namespace mojo { // static -device::usb::TransferDirection -TypeConverter<device::usb::TransferDirection, device::UsbEndpointDirection>:: - Convert(const device::UsbEndpointDirection& direction) { +device::mojom::UsbTransferDirection TypeConverter< + device::mojom::UsbTransferDirection, + device::UsbEndpointDirection>::Convert(const device::UsbEndpointDirection& + direction) { if (direction == device::USB_DIRECTION_INBOUND) - return device::usb::TransferDirection::INBOUND; + return device::mojom::UsbTransferDirection::INBOUND; DCHECK(direction == device::USB_DIRECTION_OUTBOUND); - return device::usb::TransferDirection::OUTBOUND; + return device::mojom::UsbTransferDirection::OUTBOUND; } // static -device::usb::TransferStatus -TypeConverter<device::usb::TransferStatus, device::UsbTransferStatus>::Convert( - const device::UsbTransferStatus& status) { +device::mojom::UsbTransferStatus +TypeConverter<device::mojom::UsbTransferStatus, device::UsbTransferStatus>:: + Convert(const device::UsbTransferStatus& status) { switch (status) { case device::USB_TRANSFER_COMPLETED: - return device::usb::TransferStatus::COMPLETED; + return device::mojom::UsbTransferStatus::COMPLETED; case device::USB_TRANSFER_ERROR: - return device::usb::TransferStatus::TRANSFER_ERROR; + return device::mojom::UsbTransferStatus::TRANSFER_ERROR; case device::USB_TRANSFER_TIMEOUT: - return device::usb::TransferStatus::TIMEOUT; + return device::mojom::UsbTransferStatus::TIMEOUT; case device::USB_TRANSFER_CANCELLED: - return device::usb::TransferStatus::CANCELLED; + return device::mojom::UsbTransferStatus::CANCELLED; case device::USB_TRANSFER_STALLED: - return device::usb::TransferStatus::STALLED; + return device::mojom::UsbTransferStatus::STALLED; case device::USB_TRANSFER_DISCONNECT: - return device::usb::TransferStatus::DISCONNECT; + return device::mojom::UsbTransferStatus::DISCONNECT; case device::USB_TRANSFER_OVERFLOW: - return device::usb::TransferStatus::BABBLE; + return device::mojom::UsbTransferStatus::BABBLE; case device::USB_TRANSFER_LENGTH_SHORT: - return device::usb::TransferStatus::SHORT_PACKET; + return device::mojom::UsbTransferStatus::SHORT_PACKET; default: NOTREACHED(); - return device::usb::TransferStatus::TRANSFER_ERROR; + return device::mojom::UsbTransferStatus::TRANSFER_ERROR; } } // static device::UsbDeviceHandle::TransferRequestType TypeConverter<device::UsbDeviceHandle::TransferRequestType, - device::usb::ControlTransferType>:: - Convert(const device::usb::ControlTransferType& type) { + device::mojom::UsbControlTransferType>:: + Convert(const device::mojom::UsbControlTransferType& type) { switch (type) { - case device::usb::ControlTransferType::STANDARD: + case device::mojom::UsbControlTransferType::STANDARD: return device::UsbDeviceHandle::STANDARD; - case device::usb::ControlTransferType::CLASS: + case device::mojom::UsbControlTransferType::CLASS: return device::UsbDeviceHandle::CLASS; - case device::usb::ControlTransferType::VENDOR: + case device::mojom::UsbControlTransferType::VENDOR: return device::UsbDeviceHandle::VENDOR; - case device::usb::ControlTransferType::RESERVED: + case device::mojom::UsbControlTransferType::RESERVED: return device::UsbDeviceHandle::RESERVED; default: NOTREACHED(); @@ -76,16 +77,16 @@ // static device::UsbDeviceHandle::TransferRecipient TypeConverter<device::UsbDeviceHandle::TransferRecipient, - device::usb::ControlTransferRecipient>:: - Convert(const device::usb::ControlTransferRecipient& recipient) { + device::mojom::UsbControlTransferRecipient>:: + Convert(const device::mojom::UsbControlTransferRecipient& recipient) { switch (recipient) { - case device::usb::ControlTransferRecipient::DEVICE: + case device::mojom::UsbControlTransferRecipient::DEVICE: return device::UsbDeviceHandle::DEVICE; - case device::usb::ControlTransferRecipient::INTERFACE: + case device::mojom::UsbControlTransferRecipient::INTERFACE: return device::UsbDeviceHandle::INTERFACE; - case device::usb::ControlTransferRecipient::ENDPOINT: + case device::mojom::UsbControlTransferRecipient::ENDPOINT: return device::UsbDeviceHandle::ENDPOINT; - case device::usb::ControlTransferRecipient::OTHER: + case device::mojom::UsbControlTransferRecipient::OTHER: return device::UsbDeviceHandle::OTHER; default: NOTREACHED(); @@ -94,45 +95,46 @@ } // static -device::usb::EndpointType -TypeConverter<device::usb::EndpointType, device::UsbTransferType>::Convert( +device::mojom::UsbEndpointType +TypeConverter<device::mojom::UsbEndpointType, device::UsbTransferType>::Convert( const device::UsbTransferType& type) { switch (type) { case device::USB_TRANSFER_ISOCHRONOUS: - return device::usb::EndpointType::ISOCHRONOUS; + return device::mojom::UsbEndpointType::ISOCHRONOUS; case device::USB_TRANSFER_BULK: - return device::usb::EndpointType::BULK; + return device::mojom::UsbEndpointType::BULK; case device::USB_TRANSFER_INTERRUPT: - return device::usb::EndpointType::INTERRUPT; + return device::mojom::UsbEndpointType::INTERRUPT; // Note that we do not expose control transfer in the public interface // because control endpoints are implied rather than explicitly enumerated // there. default: NOTREACHED(); - return device::usb::EndpointType::BULK; + return device::mojom::UsbEndpointType::BULK; } } // static -device::usb::EndpointInfoPtr -TypeConverter<device::usb::EndpointInfoPtr, device::UsbEndpointDescriptor>:: - Convert(const device::UsbEndpointDescriptor& endpoint) { - device::usb::EndpointInfoPtr info = device::usb::EndpointInfo::New(); +device::mojom::UsbEndpointInfoPtr TypeConverter< + device::mojom::UsbEndpointInfoPtr, + device::UsbEndpointDescriptor>::Convert(const device::UsbEndpointDescriptor& + endpoint) { + auto info = device::mojom::UsbEndpointInfo::New(); info->endpoint_number = endpoint.address & 0xf; info->direction = - ConvertTo<device::usb::TransferDirection>(endpoint.direction); - info->type = ConvertTo<device::usb::EndpointType>(endpoint.transfer_type); + ConvertTo<device::mojom::UsbTransferDirection>(endpoint.direction); + info->type = + ConvertTo<device::mojom::UsbEndpointType>(endpoint.transfer_type); info->packet_size = static_cast<uint32_t>(endpoint.maximum_packet_size); return info; } // static -device::usb::AlternateInterfaceInfoPtr -TypeConverter<device::usb::AlternateInterfaceInfoPtr, +device::mojom::UsbAlternateInterfaceInfoPtr +TypeConverter<device::mojom::UsbAlternateInterfaceInfoPtr, device::UsbInterfaceDescriptor>:: Convert(const device::UsbInterfaceDescriptor& interface) { - device::usb::AlternateInterfaceInfoPtr info = - device::usb::AlternateInterfaceInfo::New(); + auto info = device::mojom::UsbAlternateInterfaceInfo::New(); info->alternate_setting = interface.alternate_setting; info->class_code = interface.interface_class; info->subclass_code = interface.interface_subclass; @@ -142,29 +144,30 @@ info->endpoints.reserve(interface.endpoints.size()); for (const auto& endpoint : interface.endpoints) { if (endpoint.transfer_type != device::USB_TRANSFER_CONTROL) - info->endpoints.push_back(device::usb::EndpointInfo::From(endpoint)); + info->endpoints.push_back(device::mojom::UsbEndpointInfo::From(endpoint)); } return info; } // static -std::vector<device::usb::InterfaceInfoPtr> -TypeConverter<std::vector<device::usb::InterfaceInfoPtr>, +std::vector<device::mojom::UsbInterfaceInfoPtr> +TypeConverter<std::vector<device::mojom::UsbInterfaceInfoPtr>, std::vector<device::UsbInterfaceDescriptor>>:: Convert(const std::vector<device::UsbInterfaceDescriptor>& interfaces) { - std::vector<device::usb::InterfaceInfoPtr> infos; + std::vector<device::mojom::UsbInterfaceInfoPtr> infos; // Aggregate each alternate setting into an InterfaceInfo corresponding to its // interface number. - std::map<uint8_t, device::usb::InterfaceInfo*> interface_map; + std::map<uint8_t, device::mojom::UsbInterfaceInfo*> interface_map; for (size_t i = 0; i < interfaces.size(); ++i) { - auto alternate = device::usb::AlternateInterfaceInfo::From(interfaces[i]); + auto alternate = + device::mojom::UsbAlternateInterfaceInfo::From(interfaces[i]); auto iter = interface_map.find(interfaces[i].interface_number); if (iter == interface_map.end()) { // This is the first time we're seeing an alternate with this interface // number, so add a new InterfaceInfo to the array and map the number. - auto info = device::usb::InterfaceInfo::New(); + auto info = device::mojom::UsbInterfaceInfo::New(); info->interface_number = interfaces[i].interface_number; iter = interface_map .insert( @@ -179,23 +182,23 @@ } // static -device::usb::ConfigurationInfoPtr -TypeConverter<device::usb::ConfigurationInfoPtr, device::UsbConfigDescriptor>:: - Convert(const device::UsbConfigDescriptor& config) { - device::usb::ConfigurationInfoPtr info = - device::usb::ConfigurationInfo::New(); +device::mojom::UsbConfigurationInfoPtr TypeConverter< + device::mojom::UsbConfigurationInfoPtr, + device::UsbConfigDescriptor>::Convert(const device::UsbConfigDescriptor& + config) { + auto info = device::mojom::UsbConfigurationInfo::New(); info->configuration_value = config.configuration_value; info->interfaces = - mojo::ConvertTo<std::vector<device::usb::InterfaceInfoPtr>>( + mojo::ConvertTo<std::vector<device::mojom::UsbInterfaceInfoPtr>>( config.interfaces); return info; } // static -device::usb::DeviceInfoPtr -TypeConverter<device::usb::DeviceInfoPtr, device::UsbDevice>::Convert( +device::mojom::UsbDeviceInfoPtr +TypeConverter<device::mojom::UsbDeviceInfoPtr, device::UsbDevice>::Convert( const device::UsbDevice& device) { - device::usb::DeviceInfoPtr info = device::usb::DeviceInfo::New(); + auto info = device::mojom::UsbDeviceInfo::New(); info->guid = device.guid(); info->usb_version_major = device.usb_version() >> 8; info->usb_version_minor = device.usb_version() >> 4 & 0xf; @@ -214,21 +217,21 @@ const device::UsbConfigDescriptor* config = device.active_configuration(); info->active_configuration = config ? config->configuration_value : 0; info->configurations = - mojo::ConvertTo<std::vector<device::usb::ConfigurationInfoPtr>>( + mojo::ConvertTo<std::vector<device::mojom::UsbConfigurationInfoPtr>>( device.configurations()); return info; } // static -device::usb::IsochronousPacketPtr -TypeConverter<device::usb::IsochronousPacketPtr, +device::mojom::UsbIsochronousPacketPtr +TypeConverter<device::mojom::UsbIsochronousPacketPtr, device::UsbDeviceHandle::IsochronousPacket>:: Convert(const device::UsbDeviceHandle::IsochronousPacket& packet) { - device::usb::IsochronousPacketPtr info = - device::usb::IsochronousPacket::New(); + auto info = device::mojom::UsbIsochronousPacket::New(); info->length = packet.length; info->transferred_length = packet.transferred_length; - info->status = mojo::ConvertTo<device::usb::TransferStatus>(packet.status); + info->status = + mojo::ConvertTo<device::mojom::UsbTransferStatus>(packet.status); return info; }
diff --git a/device/usb/mojo/type_converters.h b/device/usb/mojo/type_converters.h index cd4a405..4cee02c 100644 --- a/device/usb/mojo/type_converters.h +++ b/device/usb/mojo/type_converters.h
@@ -25,48 +25,50 @@ namespace mojo { template <> -struct TypeConverter<device::usb::TransferDirection, +struct TypeConverter<device::mojom::UsbTransferDirection, device::UsbEndpointDirection> { - static device::usb::TransferDirection Convert( + static device::mojom::UsbTransferDirection Convert( const device::UsbEndpointDirection& direction); }; template <> -struct TypeConverter<device::usb::TransferStatus, device::UsbTransferStatus> { - static device::usb::TransferStatus Convert( +struct TypeConverter<device::mojom::UsbTransferStatus, + device::UsbTransferStatus> { + static device::mojom::UsbTransferStatus Convert( const device::UsbTransferStatus& status); }; template <> struct TypeConverter<device::UsbDeviceHandle::TransferRequestType, - device::usb::ControlTransferType> { + device::mojom::UsbControlTransferType> { static device::UsbDeviceHandle::TransferRequestType Convert( - const device::usb::ControlTransferType& type); + const device::mojom::UsbControlTransferType& type); }; template <> struct TypeConverter<device::UsbDeviceHandle::TransferRecipient, - device::usb::ControlTransferRecipient> { + device::mojom::UsbControlTransferRecipient> { static device::UsbDeviceHandle::TransferRecipient Convert( - const device::usb::ControlTransferRecipient& recipient); + const device::mojom::UsbControlTransferRecipient& recipient); }; template <> -struct TypeConverter<device::usb::EndpointType, device::UsbTransferType> { - static device::usb::EndpointType Convert(const device::UsbTransferType& type); +struct TypeConverter<device::mojom::UsbEndpointType, device::UsbTransferType> { + static device::mojom::UsbEndpointType Convert( + const device::UsbTransferType& type); }; template <> -struct TypeConverter<device::usb::EndpointInfoPtr, +struct TypeConverter<device::mojom::UsbEndpointInfoPtr, device::UsbEndpointDescriptor> { - static device::usb::EndpointInfoPtr Convert( + static device::mojom::UsbEndpointInfoPtr Convert( const device::UsbEndpointDescriptor& endpoint); }; template <> -struct TypeConverter<device::usb::AlternateInterfaceInfoPtr, +struct TypeConverter<device::mojom::UsbAlternateInterfaceInfoPtr, device::UsbInterfaceDescriptor> { - static device::usb::AlternateInterfaceInfoPtr Convert( + static device::mojom::UsbAlternateInterfaceInfoPtr Convert( const device::UsbInterfaceDescriptor& iface); }; @@ -75,28 +77,29 @@ // settings, whereas InterfaceInfos contain their own sets of alternates with // a different structure type. template <> -struct TypeConverter<std::vector<device::usb::InterfaceInfoPtr>, +struct TypeConverter<std::vector<device::mojom::UsbInterfaceInfoPtr>, std::vector<device::UsbInterfaceDescriptor>> { - static std::vector<device::usb::InterfaceInfoPtr> Convert( + static std::vector<device::mojom::UsbInterfaceInfoPtr> Convert( const std::vector<device::UsbInterfaceDescriptor>& interfaces); }; template <> -struct TypeConverter<device::usb::ConfigurationInfoPtr, +struct TypeConverter<device::mojom::UsbConfigurationInfoPtr, device::UsbConfigDescriptor> { - static device::usb::ConfigurationInfoPtr Convert( + static device::mojom::UsbConfigurationInfoPtr Convert( const device::UsbConfigDescriptor& config); }; template <> -struct TypeConverter<device::usb::DeviceInfoPtr, device::UsbDevice> { - static device::usb::DeviceInfoPtr Convert(const device::UsbDevice& device); +struct TypeConverter<device::mojom::UsbDeviceInfoPtr, device::UsbDevice> { + static device::mojom::UsbDeviceInfoPtr Convert( + const device::UsbDevice& device); }; template <> -struct TypeConverter<device::usb::IsochronousPacketPtr, +struct TypeConverter<device::mojom::UsbIsochronousPacketPtr, device::UsbDeviceHandle::IsochronousPacket> { - static device::usb::IsochronousPacketPtr Convert( + static device::mojom::UsbIsochronousPacketPtr Convert( const device::UsbDeviceHandle::IsochronousPacket& packet); };
diff --git a/device/usb/public/interfaces/OWNERS b/device/usb/public/interfaces/OWNERS index ac44cd00..fda0d85 100644 --- a/device/usb/public/interfaces/OWNERS +++ b/device/usb/public/interfaces/OWNERS
@@ -3,3 +3,6 @@ per-file *_struct_traits*.*=set noparent per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS + +per-file *.typemap=set noparent +per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/device/usb/public/interfaces/chooser_service.mojom b/device/usb/public/interfaces/chooser_service.mojom index 29f130b7..d7fd2fe 100644 --- a/device/usb/public/interfaces/chooser_service.mojom +++ b/device/usb/public/interfaces/chooser_service.mojom
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module device.usb; +module device.mojom; import "device.mojom"; import "device_manager.mojom"; -interface ChooserService { +interface UsbChooserService { // Get permission from user to use the device. // // |device_filters| filters the available devices and the filtered // devices will be listed for user to grant permission. // // |result| is the device that user grants permission to use. - GetPermission(array<device.usb.DeviceFilter> device_filters) - => (device.usb.DeviceInfo? result); + GetPermission(array<device.mojom.UsbDeviceFilter> device_filters) + => (device.mojom.UsbDeviceInfo? result); };
diff --git a/device/usb/public/interfaces/device.mojom b/device/usb/public/interfaces/device.mojom index 8da2922b..e23406a 100644 --- a/device/usb/public/interfaces/device.mojom +++ b/device/usb/public/interfaces/device.mojom
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module device.usb; +module device.mojom; -enum OpenDeviceError { +enum UsbOpenDeviceError { // Opening the device succeeded. OK, @@ -15,59 +15,59 @@ ALREADY_OPEN, }; -enum TransferDirection { +enum UsbTransferDirection { INBOUND, OUTBOUND, }; -enum ControlTransferType { +enum UsbControlTransferType { STANDARD, CLASS, VENDOR, RESERVED }; -enum ControlTransferRecipient { +enum UsbControlTransferRecipient { DEVICE, INTERFACE, ENDPOINT, OTHER }; -enum EndpointType { +enum UsbEndpointType { BULK, INTERRUPT, ISOCHRONOUS, }; -struct EndpointInfo { +struct UsbEndpointInfo { uint8 endpoint_number; - TransferDirection direction; - EndpointType type; + UsbTransferDirection direction; + UsbEndpointType type; uint32 packet_size; }; -struct AlternateInterfaceInfo { +struct UsbAlternateInterfaceInfo { uint8 alternate_setting; uint8 class_code; uint8 subclass_code; uint8 protocol_code; string? interface_name; - array<EndpointInfo> endpoints; + array<UsbEndpointInfo> endpoints; }; -struct InterfaceInfo { +struct UsbInterfaceInfo { uint8 interface_number; - array<AlternateInterfaceInfo> alternates; + array<UsbAlternateInterfaceInfo> alternates; }; -struct ConfigurationInfo { +struct UsbConfigurationInfo { uint8 configuration_value; string? configuration_name; - array<InterfaceInfo> interfaces; + array<UsbInterfaceInfo> interfaces; }; -struct DeviceInfo { +struct UsbDeviceInfo { string guid; uint8 usb_version_major; uint8 usb_version_minor; @@ -84,18 +84,18 @@ string? product_name; string? serial_number; uint8 active_configuration; - array<ConfigurationInfo> configurations; + array<UsbConfigurationInfo> configurations; }; -struct ControlTransferParams { - ControlTransferType type; - ControlTransferRecipient recipient; +struct UsbControlTransferParams { + UsbControlTransferType type; + UsbControlTransferRecipient recipient; uint8 request; uint16 value; uint16 index; }; -enum TransferStatus { +enum UsbTransferStatus { // The transfer completed successfully. COMPLETED, @@ -126,15 +126,15 @@ SHORT_PACKET, }; -struct IsochronousPacket { +struct UsbIsochronousPacket { uint32 length; uint32 transferred_length; - TransferStatus status; + UsbTransferStatus status; }; -interface Device { +interface UsbDevice { // Opens the device. Methods below require the device be opened first. - Open() => (OpenDeviceError error); + Open() => (UsbOpenDeviceError error); // Closes the device. Close() => (); @@ -170,8 +170,10 @@ // |timeout| specifies the request timeout in milliseconds. A timeout of 0 // indicates no timeout: the request will remain pending indefinitely until // completed or otherwise terminated. - ControlTransferIn(ControlTransferParams params, uint32 length, uint32 timeout) - => (TransferStatus status, array<uint8>? data); + ControlTransferIn(UsbControlTransferParams params, + uint32 length, + uint32 timeout) + => (UsbTransferStatus status, array<uint8>? data); // Initiates an inbound control transfer request. |params| determine the // details of the request. Transfers to recipients other than DEVICE require a @@ -182,10 +184,10 @@ // |timeout| specifies the request timeout in milliseconds. A timeout of 0 // indicates no timeout: the request will remain pending indefinitely until // completed or otherwise terminated. - ControlTransferOut(ControlTransferParams params, + ControlTransferOut(UsbControlTransferParams params, array<uint8> data, uint32 timeout) - => (TransferStatus status); + => (UsbTransferStatus status); // Initiates an inbound generic transfer request on a specific endpoint. The // interface to which |endpoint_number| belongs must be claimed, and the @@ -201,7 +203,7 @@ // indicates no timeout: the request will remain pending indefinitely until // completed or otherwise terminated. GenericTransferIn(uint8 endpoint_number, uint32 length, uint32 timeout) - => (TransferStatus status, array<uint8>? data); + => (UsbTransferStatus status, array<uint8>? data); // Initiates an outbound generic transfer request on a specific endpoint. The // interface to which |endpoint_number| belongs must be claimed, and the @@ -215,7 +217,7 @@ // indicates no timeout: the request will remain pending indefinitely until // completed or otherwise terminated. GenericTransferOut(uint8 endpoint_number, array<uint8> data, uint32 timeout) - => (TransferStatus status); + => (UsbTransferStatus status); // Initiates an inbound isochronous transfer request on a specific endpoint. // The interface to which |endpoint_number| belongs must be claimed, and the @@ -238,7 +240,7 @@ IsochronousTransferIn(uint8 endpoint_number, array<uint32> packet_lengths, uint32 timeout) - => (array<uint8>? data, array<IsochronousPacket> packets); + => (array<uint8>? data, array<UsbIsochronousPacket> packets); // Initiates an outbound isochronous transfer request on a specific endpoint. // The interface to which |endpoint_number| belongs must be claimed, and the @@ -260,5 +262,5 @@ array<uint8> data, array<uint32> packet_lengths, uint32 timeout) - => (array<IsochronousPacket> packets); + => (array<UsbIsochronousPacket> packets); };
diff --git a/device/usb/public/interfaces/device_manager.mojom b/device/usb/public/interfaces/device_manager.mojom index c1a88ae..9e90681 100644 --- a/device/usb/public/interfaces/device_manager.mojom +++ b/device/usb/public/interfaces/device_manager.mojom
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -module device.usb; +module device.mojom; import "device.mojom"; -struct DeviceFilter { +struct UsbDeviceFilter { bool has_vendor_id; uint16 vendor_id; @@ -25,27 +25,27 @@ string? serial_number; }; -struct EnumerationOptions { - array<DeviceFilter>? filters; +struct UsbEnumerationOptions { + array<UsbDeviceFilter>? filters; }; -interface DeviceManager { +interface UsbDeviceManager { // Retrieves information about all devices available to the DeviceManager // implementation. - GetDevices(EnumerationOptions? options) => (array<DeviceInfo> results); + GetDevices(UsbEnumerationOptions? options) => (array<UsbDeviceInfo> results); // Requests a device by guid. - GetDevice(string guid, Device& device_request); + GetDevice(string guid, UsbDevice& device_request); // Sets the client for this DeviceManager service. The service will notify its // client of device events such as connection and disconnection. - SetClient(DeviceManagerClient client); + SetClient(UsbDeviceManagerClient client); }; -interface DeviceManagerClient { +interface UsbDeviceManagerClient { // Called when a device is connected to the host. - OnDeviceAdded(DeviceInfo device_info); + OnDeviceAdded(UsbDeviceInfo device_info); // Called when a device is disconnected from the host. - OnDeviceRemoved(DeviceInfo device_info); + OnDeviceRemoved(UsbDeviceInfo device_info); };
diff --git a/device/usb/public/interfaces/device_manager.typemap b/device/usb/public/interfaces/device_manager.typemap index 7c350a1..088ee80 100644 --- a/device/usb/public/interfaces/device_manager.typemap +++ b/device/usb/public/interfaces/device_manager.typemap
@@ -12,4 +12,4 @@ deps = [ "//device/usb", ] -type_mappings = [ "device.usb.DeviceFilter=device::UsbDeviceFilter" ] +type_mappings = [ "device.mojom.UsbDeviceFilter=device::UsbDeviceFilter" ]
diff --git a/device/usb/public/interfaces/device_manager_struct_traits.cc b/device/usb/public/interfaces/device_manager_struct_traits.cc index 771abda..8198152e 100644 --- a/device/usb/public/interfaces/device_manager_struct_traits.cc +++ b/device/usb/public/interfaces/device_manager_struct_traits.cc
@@ -7,9 +7,10 @@ namespace mojo { // static -bool StructTraits<device::usb::DeviceFilterDataView, device::UsbDeviceFilter>:: - Read(device::usb::DeviceFilterDataView input, - device::UsbDeviceFilter* output) { +bool StructTraits< + device::mojom::UsbDeviceFilterDataView, + device::UsbDeviceFilter>::Read(device::mojom::UsbDeviceFilterDataView input, + device::UsbDeviceFilter* output) { if (input.has_vendor_id()) output->vendor_id = input.vendor_id(); if (input.has_product_id())
diff --git a/device/usb/public/interfaces/device_manager_struct_traits.h b/device/usb/public/interfaces/device_manager_struct_traits.h index 682d5fe5..1028f66 100644 --- a/device/usb/public/interfaces/device_manager_struct_traits.h +++ b/device/usb/public/interfaces/device_manager_struct_traits.h
@@ -11,7 +11,7 @@ namespace mojo { template <> -struct StructTraits<device::usb::DeviceFilterDataView, +struct StructTraits<device::mojom::UsbDeviceFilterDataView, device::UsbDeviceFilter> { static bool has_vendor_id(const device::UsbDeviceFilter& filter) { return filter.vendor_id.has_value(); @@ -58,7 +58,7 @@ return filter.serial_number; } - static bool Read(device::usb::DeviceFilterDataView input, + static bool Read(device::mojom::UsbDeviceFilterDataView input, device::UsbDeviceFilter* output); };
diff --git a/device/usb/usb_descriptors_fuzzer.cc b/device/usb/usb_descriptors_fuzzer.cc index 560a9bf..d1a97130 100644 --- a/device/usb/usb_descriptors_fuzzer.cc +++ b/device/usb/usb_descriptors_fuzzer.cc
@@ -14,7 +14,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { device::UsbDeviceDescriptor desc; desc.Parse(std::vector<uint8_t>(data, data + size)); - mojo::ConvertTo<std::vector<device::usb::ConfigurationInfoPtr>>( + mojo::ConvertTo<std::vector<device::mojom::UsbConfigurationInfoPtr>>( desc.configurations); return 0; }
diff --git a/device/vibration/OWNERS b/device/vibration/OWNERS deleted file mode 100644 index 1eb3087..0000000 --- a/device/vibration/OWNERS +++ /dev/null
@@ -1,6 +0,0 @@ -timvolodine@chromium.org - -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS - -# COMPONENT: Blink>Vibration
diff --git a/device/vibration/vibration_export.h b/device/vibration/vibration_export.h deleted file mode 100644 index 64b85fb..0000000 --- a/device/vibration/vibration_export.h +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef DEVICE_VIBRATION_DEVICE_VIBRATION_EXPORT_H_ -#define DEVICE_VIBRATION_DEVICE_VIBRATION_EXPORT_H_ - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(DEVICE_VIBRATION_IMPLEMENTATION) -#define DEVICE_VIBRATION_EXPORT __declspec(dllexport) -#else -#define DEVICE_VIBRATION_EXPORT __declspec(dllimport) -#endif // defined(DEVICE_VIBRATION_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(DEVICE_VIBRATION_IMPLEMENTATION) -#define DEVICE_VIBRATION_EXPORT __attribute__((visibility("default"))) -#else -#define DEVICE_VIBRATION_EXPORT -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define DEVICE_VIBRATION_EXPORT -#endif - -#endif // DEVICE_VIBRATION_DEVICE_VIBRATION_EXPORT_H_
diff --git a/device/vibration/vibration_manager_impl.h b/device/vibration/vibration_manager_impl.h deleted file mode 100644 index 75260a2..0000000 --- a/device/vibration/vibration_manager_impl.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef DEVICE_VIBRATION_VIBRATION_MANAGER_IMPL_H_ -#define DEVICE_VIBRATION_VIBRATION_MANAGER_IMPL_H_ - -#include "device/vibration/vibration_export.h" -#include "device/vibration/vibration_manager.mojom.h" - -namespace device { - -class VibrationManagerImpl { - public: - DEVICE_VIBRATION_EXPORT static void Create( - mojo::InterfaceRequest<mojom::VibrationManager> request); - - DEVICE_VIBRATION_EXPORT static int64_t milli_seconds_for_testing_; - DEVICE_VIBRATION_EXPORT static bool cancelled_for_testing_; -}; - -} // namespace device - -#endif // DEVICE_VIBRATION_VIBRATION_MANAGER_IMPL_H_
diff --git a/extensions/browser/content_hash_fetcher.cc b/extensions/browser/content_hash_fetcher.cc index b637ce90..b7e0214 100644 --- a/extensions/browser/content_hash_fetcher.cc +++ b/extensions/browser/content_hash_fetcher.cc
@@ -141,6 +141,7 @@ content::BrowserThread::ID creation_thread_; // Used for fetching content signatures. + // Created and destroyed on |creation_thread_|. std::unique_ptr<net::URLFetcher> url_fetcher_; // The key used to validate verified_contents.json. @@ -218,6 +219,13 @@ } ContentHashFetcherJob::~ContentHashFetcherJob() { + // Destroy |url_fetcher_| on correct thread. + // It was possible for it to be deleted on blocking pool from + // MaybeCreateHashes(). See https://crbug.com/702300 for details. + if (url_fetcher_ && !content::BrowserThread::CurrentlyOn(creation_thread_)) { + content::BrowserThread::DeleteSoon(creation_thread_, FROM_HERE, + url_fetcher_.release()); + } } bool ContentHashFetcherJob::LoadVerifiedContents(const base::FilePath& path) { @@ -292,11 +300,14 @@ VLOG(1) << "URLFetchComplete for " << extension_id_ << " is_success:" << url_fetcher_->GetStatus().is_success() << " " << fetch_url_.possibly_invalid_spec(); + // Delete |url_fetcher_| once we no longer need it. + std::unique_ptr<net::URLFetcher> url_fetcher = std::move(url_fetcher_); + if (IsCancelled()) return; std::unique_ptr<std::string> response(new std::string); - if (!url_fetcher_->GetStatus().is_success() || - !url_fetcher_->GetResponseAsString(response.get())) { + if (!url_fetcher->GetStatus().is_success() || + !url_fetcher->GetResponseAsString(response.get())) { DoneFetchingVerifiedContents(false); return; }
diff --git a/extensions/browser/content_hash_fetcher_unittest.cc b/extensions/browser/content_hash_fetcher_unittest.cc index e54b4d6..68a1111d 100644 --- a/extensions/browser/content_hash_fetcher_unittest.cc +++ b/extensions/browser/content_hash_fetcher_unittest.cc
@@ -186,15 +186,9 @@ base::ScopedTempDir temp_dir_; }; -// Flaky on Linux and ChromeOS. https://crbug.com/702300 -#if defined(OS_LINUX) || defined(OS_CHROMEOS) -#define MAYBE_MissingVerifiedContents DISABLED_MissingVerifiedContents -#else -#define MAYBE_MissingVerifiedContents MissingVerifiedContents -#endif // This tests our ability to successfully fetch, parse, and validate a missing // verified_contents.json file for an extension. -TEST_F(ContentHashFetcherTest, MAYBE_MissingVerifiedContents) { +TEST_F(ContentHashFetcherTest, MissingVerifiedContents) { // We unzip the extension source to a temp directory to simulate it being // installed there, because the ContentHashFetcher will create the _metadata/ // directory within the extension install dir and write the fetched @@ -233,17 +227,9 @@ base::PathExists(file_util::GetVerifiedContentsPath(extension->path()))); } -// Flaky on Linux and ChromeOS. https://crbug.com/702300 -#if defined(OS_LINUX) || defined(OS_CHROMEOS) -#define MAYBE_MissingVerifiedContentsAndCorrupt \ - DISABLED_MissingVerifiedContentsAndCorrupt -#else -#define MAYBE_MissingVerifiedContentsAndCorrupt \ - MissingVerifiedContentsAndCorrupt -#endif // Similar to MissingVerifiedContents, but tests the case where the extension // actually has corruption. -TEST_F(ContentHashFetcherTest, MAYBE_MissingVerifiedContentsAndCorrupt) { +TEST_F(ContentHashFetcherTest, MissingVerifiedContentsAndCorrupt) { base::FilePath test_dir_base = GetTestPath(base::FilePath()).AppendASCII("missing_verified_contents"); scoped_refptr<Extension> extension =
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc index a546609..08eee06 100644 --- a/gpu/ipc/service/direct_composition_surface_win.cc +++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -266,7 +266,7 @@ if (FAILED(hr)) return false; - dcomp_target_->SetRoot(root_visual_.get()); + dcomp_target_->SetRoot(root_visual_.Get()); return true; } @@ -295,7 +295,7 @@ &desc, video_processor_enumerator_.Receive()); CHECK(SUCCEEDED(hr)); - hr = video_device_->CreateVideoProcessor(video_processor_enumerator_.get(), 0, + hr = video_device_->CreateVideoProcessor(video_processor_enumerator_.Get(), 0, video_processor_.Receive()); CHECK(SUCCEEDED(hr)); } @@ -391,7 +391,7 @@ out_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D; out_desc.Texture2D.MipSlice = 0; HRESULT hr = video_device_->CreateVideoProcessorOutputView( - texture.get(), video_processor_enumerator_.get(), &out_desc, + texture.Get(), video_processor_enumerator_.Get(), &out_desc, out_view_.Receive()); CHECK(SUCCEEDED(hr)); } @@ -401,14 +401,14 @@ base::win::ScopedComPtr<ID3D11VideoContext1> context1; if (SUCCEEDED(video_context_.QueryInterface(context1.Receive()))) { context1->VideoProcessorSetStreamColorSpace1( - video_processor_.get(), 0, + video_processor_.Get(), 0, gfx::ColorSpaceWin::GetDXGIColorSpace(src_color_space)); } else { // This can't handle as many different types of color spaces, so use it // only if ID3D11VideoContext1 isn't available. D3D11_VIDEO_PROCESSOR_COLOR_SPACE color_space = gfx::ColorSpaceWin::GetD3D11ColorSpace(src_color_space); - video_context_->VideoProcessorSetStreamColorSpace(video_processor_.get(), 0, + video_context_->VideoProcessorSetStreamColorSpace(video_processor_.Get(), 0, &color_space); } @@ -426,12 +426,12 @@ HRESULT hr = swap_chain3->SetColorSpace1(color_space); CHECK(SUCCEEDED(hr)); if (context1) { - context1->VideoProcessorSetOutputColorSpace1(video_processor_.get(), + context1->VideoProcessorSetOutputColorSpace1(video_processor_.Get(), color_space); } else { D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = gfx::ColorSpaceWin::GetD3D11ColorSpace(output_color_space); - video_context_->VideoProcessorSetOutputColorSpace(video_processor_.get(), + video_context_->VideoProcessorSetOutputColorSpace(video_processor_.Get(), &d3d11_color_space); } } @@ -442,7 +442,7 @@ in_desc.Texture2D.ArraySlice = (UINT)image_dxgi->level(); base::win::ScopedComPtr<ID3D11VideoProcessorInputView> in_view; HRESULT hr = video_device_->CreateVideoProcessorInputView( - image_dxgi->texture().get(), video_processor_enumerator_.get(), + image_dxgi->texture().Get(), video_processor_enumerator_.Get(), &in_desc, in_view.Receive()); CHECK(SUCCEEDED(hr)); @@ -452,21 +452,21 @@ stream.InputFrameOrField = 0; stream.PastFrames = 0; stream.FutureFrames = 0; - stream.pInputSurface = in_view.get(); + stream.pInputSurface = in_view.Get(); RECT dest_rect = gfx::Rect(swap_chain_size).ToRECT(); - video_context_->VideoProcessorSetOutputTargetRect(video_processor_.get(), + video_context_->VideoProcessorSetOutputTargetRect(video_processor_.Get(), TRUE, &dest_rect); - video_context_->VideoProcessorSetStreamDestRect(video_processor_.get(), 0, + video_context_->VideoProcessorSetStreamDestRect(video_processor_.Get(), 0, TRUE, &dest_rect); RECT source_rect = gfx::Rect(ceiled_input_size).ToRECT(); - video_context_->VideoProcessorSetStreamSourceRect(video_processor_.get(), 0, + video_context_->VideoProcessorSetStreamSourceRect(video_processor_.Get(), 0, TRUE, &source_rect); video_context_->VideoProcessorSetStreamAutoProcessingMode( - video_processor_.get(), 0, FALSE); + video_processor_.Get(), 0, FALSE); - hr = video_context_->VideoProcessorBlt(video_processor_.get(), - out_view_.get(), 0, 1, &stream); + hr = video_context_->VideoProcessorBlt(video_processor_.Get(), + out_view_.Get(), 0, 1, &stream); CHECK(SUCCEEDED(hr)); } @@ -491,7 +491,7 @@ DCHECK(SUCCEEDED(hr)); base::win::ScopedComPtr<ID3D11DeviceContext> context; d3d11_device_->GetImmediateContext(context.Receive()); - context->CopyResource(dest_texture.get(), src_texture.get()); + context->CopyResource(dest_texture.Get(), src_texture.Get()); } swap_chain_->Present(1, 0); @@ -575,7 +575,7 @@ HRESULT hr = E_FAIL; if (yuy2) { hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( - d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr, + d3d11_device_.Get(), swap_chain_handle_.Get(), &desc, nullptr, swap_chain_.Receive()); is_yuy2_swapchain_ = SUCCEEDED(hr); failed_to_create_yuy2_swapchain_ = !is_yuy2_swapchain_; @@ -589,7 +589,7 @@ desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; desc.Flags = 0; hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( - d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr, + d3d11_device_.Get(), swap_chain_handle_.Get(), &desc, nullptr, swap_chain_.Receive()); CHECK(SUCCEEDED(hr)); } @@ -606,11 +606,11 @@ dcomp_device_->CreateVisual(visual_info->clip_visual.Receive()); dcomp_device_->CreateVisual(visual.Receive()); visual_info->content_visual = visual; - visual_info->clip_visual->AddVisual(visual.get(), FALSE, nullptr); + visual_info->clip_visual->AddVisual(visual.Get(), FALSE, nullptr); IDCompositionVisual2* last_visual = - (i > 0) ? visual_info_[i - 1].clip_visual.get() : nullptr; - root_visual_->AddVisual(visual_info->clip_visual.get(), TRUE, last_visual); + (i > 0) ? visual_info_[i - 1].clip_visual.Get() : nullptr; + root_visual_->AddVisual(visual_info->clip_visual.Get(), TRUE, last_visual); } void DCLayerTree::UpdateVisualForVideo( @@ -629,7 +629,7 @@ if (visual_info->swap_chain != visual_info->swap_chain_presenter->swap_chain()) { visual_info->swap_chain = visual_info->swap_chain_presenter->swap_chain(); - dc_visual->SetContent(visual_info->swap_chain.get()); + dc_visual->SetContent(visual_info->swap_chain.Get()); } if (visual_info->swap_chain_presenter->swap_chain_scale_x() != @@ -664,7 +664,7 @@ final_transform.matrix().get(3, 0), final_transform.matrix().get(3, 1)}}}; dcomp_transform->SetMatrix(d2d_matrix); - dc_visual->SetTransform(dcomp_transform.get()); + dc_visual->SetTransform(dcomp_transform.Get()); } } @@ -680,9 +680,9 @@ visual_info->surface = surface_->dcomp_surface(); visual_info->swap_chain = surface_->swap_chain(); if (visual_info->surface) { - dc_visual->SetContent(visual_info->surface.get()); + dc_visual->SetContent(visual_info->surface.Get()); } else if (visual_info->swap_chain) { - dc_visual->SetContent(visual_info->swap_chain.get()); + dc_visual->SetContent(visual_info->swap_chain.Get()); } else { dc_visual->SetContent(nullptr); } @@ -716,7 +716,7 @@ clip->SetRight(offset_clip.right()); clip->SetBottom(offset_clip.bottom()); clip->SetTop(offset_clip.y()); - visual_info->clip_visual->SetClip(clip.get()); + visual_info->clip_visual->SetClip(clip.Get()); } else { visual_info->clip_visual->SetClip(nullptr); } @@ -744,7 +744,7 @@ while (visual_info_.size() > pending_overlays_.size()) { visual_info_.back().clip_visual->RemoveAllVisuals(); - root_visual_->RemoveVisual(visual_info_.back().clip_visual.get()); + root_visual_->RemoveVisual(visual_info_.back().clip_visual.Get()); visual_info_.pop_back(); } @@ -927,7 +927,7 @@ desc.AlphaMode = alpha_mode; desc.Flags = 0; HRESULT hr = dxgi_factory->CreateSwapChainForComposition( - d3d11_device_.get(), &desc, nullptr, swap_chain_.Receive()); + d3d11_device_.Get(), &desc, nullptr, swap_chain_.Receive()); has_been_rendered_to_ = false; first_swap_ = true; CHECK(SUCCEEDED(hr)); @@ -1080,7 +1080,7 @@ if (draw_texture_) { HRESULT hr = dcomp_surface_->ResumeDraw(); CHECK(SUCCEEDED(hr)); - g_current_surface = dcomp_surface_.get(); + g_current_surface = dcomp_surface_.Get(); } } return true; @@ -1129,7 +1129,7 @@ } has_been_rendered_to_ = true; - g_current_surface = dcomp_surface_.get(); + g_current_surface = dcomp_surface_.Get(); std::vector<EGLint> pbuffer_attribs{ EGL_WIDTH, @@ -1141,7 +1141,7 @@ EGL_NONE}; EGLClientBuffer buffer = - reinterpret_cast<EGLClientBuffer>(draw_texture_.get()); + reinterpret_cast<EGLClientBuffer>(draw_texture_.Get()); real_surface_ = eglCreatePbufferFromClientBuffer( GetDisplay(), EGL_D3D_TEXTURE_ANGLE, buffer, GetConfig(), &pbuffer_attribs[0]);
diff --git a/ios/web_view/internal/cwv_web_view.mm b/ios/web_view/internal/cwv_web_view.mm index a29d623d..157ed90 100644 --- a/ios/web_view/internal/cwv_web_view.mm +++ b/ios/web_view/internal/cwv_web_view.mm
@@ -39,6 +39,23 @@ } @interface CWVWebView ()<CRWWebStateDelegate, CRWWebStateObserver> { + // |_configuration| must come before |_webState| here to avoid crash on + // deallocating CWVWebView. This is because the destructor of |_webState| + // indirectly accesses the BrowserState instance, which is owned by + // |_configuration|. + // + // Looks like the fields of the object are deallocated in the reverse order of + // their definition. If |_webState| comes before |_configuration|, the order + // of execution is like this: + // + // 1. |_configuration| is deallocated + // 1.1. BrowserState is deallocated + // 2. |_webState| is deallocated + // 2.1. The destructor of |_webState| indirectly accesses the BrowserState + // deallocated above, causing crash. + // + // See crbug.com/712556 for the full stack trace. + CWVWebViewConfiguration* _configuration; std::unique_ptr<web::WebState> _webState; std::unique_ptr<web::WebStateDelegateBridge> _webStateDelegate; std::unique_ptr<web::WebStateObserverBridge> _webStateObserver;
diff --git a/mash/simple_wm/simple_wm.cc b/mash/simple_wm/simple_wm.cc index 1bb1d1bf..c96b0e5 100644 --- a/mash/simple_wm/simple_wm.cc +++ b/mash/simple_wm/simple_wm.cc
@@ -411,6 +411,8 @@ window_manager_client_ = client; } +void SimpleWM::OnWmConnected() {} + void SimpleWM::OnWmSetBounds(aura::Window* window, const gfx::Rect& bounds) { FrameView* frame_view = GetFrameViewForClientWindow(window); frame_view->GetWidget()->SetBounds(bounds);
diff --git a/mash/simple_wm/simple_wm.h b/mash/simple_wm/simple_wm.h index a9362937..26c2bc2 100644 --- a/mash/simple_wm/simple_wm.h +++ b/mash/simple_wm/simple_wm.h
@@ -71,6 +71,7 @@ // aura::WindowManagerDelegate: void SetWindowManagerClient(aura::WindowManagerClient* client) override; + void OnWmConnected() override; void OnWmSetBounds(aura::Window* window, const gfx::Rect& bounds) override; bool OnWmSetProperty( aura::Window* window,
diff --git a/media/audio/win/audio_device_listener_win.cc b/media/audio/win/audio_device_listener_win.cc index 2c2ecac..fb5503d1 100644 --- a/media/audio/win/audio_device_listener_win.cc +++ b/media/audio/win/audio_device_listener_win.cc
@@ -37,7 +37,7 @@ // as "Windows Server 2008 R2" where the desktop experience isn't available. ScopedComPtr<IMMDeviceEnumerator> device_enumerator( CoreAudioUtil::CreateDeviceEnumerator()); - if (!device_enumerator.get()) + if (!device_enumerator.Get()) return; HRESULT hr = device_enumerator->RegisterEndpointNotificationCallback(this); @@ -52,7 +52,7 @@ AudioDeviceListenerWin::~AudioDeviceListenerWin() { DCHECK(thread_checker_.CalledOnValidThread()); - if (device_enumerator_.get()) { + if (device_enumerator_.Get()) { HRESULT hr = device_enumerator_->UnregisterEndpointNotificationCallback(this); LOG_IF(ERROR, FAILED(hr)) << "UnregisterEndpointNotificationCallback() "
diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc index 55839a50..7fba7b0 100644 --- a/media/audio/win/audio_low_latency_input_win.cc +++ b/media/audio/win/audio_low_latency_input_win.cc
@@ -200,7 +200,7 @@ HRESULT hr = audio_client_->Start(); DLOG_IF(ERROR, FAILED(hr)) << "Failed to start input streaming."; - if (SUCCEEDED(hr) && audio_render_client_for_loopback_.get()) + if (SUCCEEDED(hr) && audio_render_client_for_loopback_.Get()) hr = audio_render_client_for_loopback_->Start(); started_ = SUCCEEDED(hr); @@ -508,7 +508,7 @@ HRESULT WASAPIAudioInputStream::SetCaptureDevice() { DCHECK_EQ(OPEN_RESULT_OK, open_result_); - DCHECK(!endpoint_device_.get()); + DCHECK(!endpoint_device_.Get()); ScopedComPtr<IMMDeviceEnumerator> enumerator; HRESULT hr = enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), NULL,
diff --git a/media/audio/win/audio_low_latency_output_win.cc b/media/audio/win/audio_low_latency_output_win.cc index 3dbb7d6b..67edec54 100644 --- a/media/audio/win/audio_low_latency_output_win.cc +++ b/media/audio/win/audio_low_latency_output_win.cc
@@ -131,8 +131,8 @@ if (opened_) return true; - DCHECK(!audio_client_.get()); - DCHECK(!audio_render_client_.get()); + DCHECK(!audio_client_.Get()); + DCHECK(!audio_render_client_.Get()); // Will be set to true if we ended up opening the default communications // device. @@ -145,16 +145,16 @@ communications_device = (device_role_ == eCommunications); } else { ScopedComPtr<IMMDevice> device(CoreAudioUtil::CreateDevice(device_id_)); - DLOG_IF(ERROR, !device.get()) << "Failed to open device: " << device_id_; - if (device.get()) - audio_client = CoreAudioUtil::CreateClient(device.get()); + DLOG_IF(ERROR, !device.Get()) << "Failed to open device: " << device_id_; + if (device.Get()) + audio_client = CoreAudioUtil::CreateClient(device.Get()); } - if (!audio_client.get()) + if (!audio_client.Get()) return false; // Extra sanity to ensure that the provided device format is still valid. - if (!CoreAudioUtil::IsFormatSupported(audio_client.get(), share_mode_, + if (!CoreAudioUtil::IsFormatSupported(audio_client.Get(), share_mode_, &format_)) { LOG(ERROR) << "Audio parameters are not supported."; return false; @@ -165,7 +165,7 @@ // Initialize the audio stream between the client and the device in shared // mode and using event-driven buffer handling. hr = CoreAudioUtil::SharedModeInitialize( - audio_client.get(), &format_, audio_samples_render_event_.Get(), + audio_client.Get(), &format_, audio_samples_render_event_.Get(), &endpoint_buffer_size_frames_, communications_device ? &kCommunicationsSessionId : NULL); if (FAILED(hr)) @@ -173,7 +173,7 @@ REFERENCE_TIME device_period = 0; if (FAILED(CoreAudioUtil::GetDevicePeriod( - audio_client.get(), AUDCLNT_SHAREMODE_SHARED, &device_period))) { + audio_client.Get(), AUDCLNT_SHAREMODE_SHARED, &device_period))) { return false; } @@ -213,7 +213,7 @@ } else { // TODO(henrika): break out to CoreAudioUtil::ExclusiveModeInitialize() // when removing the enable-exclusive-audio flag. - hr = ExclusiveModeInitialization(audio_client.get(), + hr = ExclusiveModeInitialization(audio_client.Get(), audio_samples_render_event_.Get(), &endpoint_buffer_size_frames_); if (FAILED(hr)) @@ -232,8 +232,8 @@ // The IAudioRenderClient interface enables us to write output data to // a rendering endpoint buffer. ScopedComPtr<IAudioRenderClient> audio_render_client = - CoreAudioUtil::CreateRenderClient(audio_client.get()); - if (!audio_render_client.get()) + CoreAudioUtil::CreateRenderClient(audio_client.Get()); + if (!audio_render_client.Get()) return false; // Store valid COM interfaces. @@ -267,7 +267,7 @@ // Ensure that the endpoint buffer is prepared with silence. if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) { if (!CoreAudioUtil::FillRenderEndpointBufferWithSilence( - audio_client_.get(), audio_render_client_.get())) { + audio_client_.Get(), audio_render_client_.Get())) { LOG(ERROR) << "Failed to prepare endpoint buffers with silence."; callback->OnError(this); return;
diff --git a/media/audio/win/core_audio_util_win.cc b/media/audio/win/core_audio_util_win.cc index a26841b..c6f447a 100644 --- a/media/audio/win/core_audio_util_win.cc +++ b/media/audio/win/core_audio_util_win.cc
@@ -253,7 +253,7 @@ // Create the IMMDeviceEnumerator interface. ScopedComPtr<IMMDeviceEnumerator> device_enumerator = CreateDeviceEnumerator(); - if (!device_enumerator.get()) + if (!device_enumerator.Get()) return 0; // Generate a collection of active (present and not disabled) audio endpoint @@ -287,7 +287,7 @@ // Create the IMMDeviceEnumerator interface. ScopedComPtr<IMMDeviceEnumerator> device_enumerator = CreateDeviceEnumerator(); - if (!device_enumerator.get()) + if (!device_enumerator.Get()) return endpoint_device; // Retrieve the default audio endpoint for the specified data-flow @@ -303,7 +303,7 @@ // Verify that the audio endpoint device is active, i.e., that the audio // adapter that connects to the endpoint device is present and enabled. - if (!IsDeviceActive(endpoint_device.get())) { + if (!IsDeviceActive(endpoint_device.Get())) { DVLOG(1) << "Selected endpoint device is not active"; endpoint_device.Reset(); } @@ -312,7 +312,7 @@ std::string CoreAudioUtil::GetDefaultOutputDeviceID() { ScopedComPtr<IMMDevice> device(CreateDefaultDevice(eRender, eConsole)); - return device.get() ? GetDeviceID(device.get()) : std::string(); + return device.Get() ? GetDeviceID(device.Get()) : std::string(); } ScopedComPtr<IMMDevice> CoreAudioUtil::CreateDevice( @@ -322,7 +322,7 @@ // Create the IMMDeviceEnumerator interface. ScopedComPtr<IMMDeviceEnumerator> device_enumerator = CreateDeviceEnumerator(); - if (!device_enumerator.get()) + if (!device_enumerator.Get()) return endpoint_device; // Retrieve an audio device specified by an endpoint device-identification @@ -339,7 +339,7 @@ // Verify that the audio endpoint device is active, i.e., that the audio // adapter that connects to the endpoint device is present and enabled. - if (!IsDeviceActive(endpoint_device.get())) { + if (!IsDeviceActive(endpoint_device.Get())) { DVLOG(1) << "Selected endpoint device is not active"; endpoint_device.Reset(); } @@ -430,13 +430,13 @@ input_device = CreateDevice(input_device_id); } - if (!input_device.get()) + if (!input_device.Get()) return std::string(); // See if we can get id of the associated controller. ScopedComPtr<IMMDeviceEnumerator> enumerator(CreateDeviceEnumerator()); std::string controller_id( - GetAudioControllerID(input_device.get(), enumerator.get())); + GetAudioControllerID(input_device.Get(), enumerator.Get())); if (controller_id.empty()) return std::string(); @@ -445,7 +445,7 @@ ScopedComPtr<IMMDeviceCollection> collection; enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, collection.Receive()); - if (!collection.get()) + if (!collection.Get()) return std::string(); UINT count = 0; @@ -454,22 +454,22 @@ for (UINT i = 0; i < count; ++i) { collection->Item(i, output_device.Receive()); std::string output_controller_id( - GetAudioControllerID(output_device.get(), enumerator.get())); + GetAudioControllerID(output_device.Get(), enumerator.Get())); if (output_controller_id == controller_id) break; output_device = NULL; } - return output_device.get() ? GetDeviceID(output_device.get()) : std::string(); + return output_device.Get() ? GetDeviceID(output_device.Get()) : std::string(); } std::string CoreAudioUtil::GetFriendlyName(const std::string& device_id) { ScopedComPtr<IMMDevice> audio_device = CreateDevice(device_id); - if (!audio_device.get()) + if (!audio_device.Get()) return std::string(); AudioDeviceName device_name; - HRESULT hr = GetDeviceName(audio_device.get(), &device_name); + HRESULT hr = GetDeviceName(audio_device.Get(), &device_name); if (FAILED(hr)) return std::string(); @@ -480,10 +480,10 @@ ERole role, const std::string& device_id) { ScopedComPtr<IMMDevice> device = CreateDefaultDevice(flow, role); - if (!device.get()) + if (!device.Get()) return false; - std::string str_default(GetDeviceID(device.get())); + std::string str_default(GetDeviceID(device.Get())); return device_id.compare(str_default) == 0; } @@ -520,7 +520,7 @@ ScopedComPtr<IAudioClient> CoreAudioUtil::CreateDefaultClient( EDataFlow data_flow, ERole role) { ScopedComPtr<IMMDevice> default_device(CreateDefaultDevice(data_flow, role)); - return (default_device.get() ? CreateClient(default_device.get()) + return (default_device.Get() ? CreateClient(default_device.Get()) : ScopedComPtr<IAudioClient>()); } @@ -530,10 +530,10 @@ return CreateDefaultClient(data_flow, role); ScopedComPtr<IMMDevice> device(CreateDevice(device_id)); - if (!device.get()) + if (!device.Get()) return ScopedComPtr<IAudioClient>(); - return CreateClient(device.get()); + return CreateClient(device.Get()); } HRESULT CoreAudioUtil::GetSharedModeMixFormat( @@ -579,11 +579,11 @@ ChannelLayout channel_layout) { // First, get the preferred mixing format for shared mode streams. ScopedComPtr<IAudioClient> client(CreateClient(device_id, data_flow, role)); - if (!client.get()) + if (!client.Get()) return false; WAVEFORMATPCMEX format; - HRESULT hr = GetSharedModeMixFormat(client.get(), &format); + HRESULT hr = GetSharedModeMixFormat(client.Get(), &format); if (FAILED(hr)) return false; @@ -616,7 +616,7 @@ // an even wider range of shared-mode formats where the installation package // for the audio device includes a local effects (LFX) audio processing // object (APO) that can handle format conversions. - return CoreAudioUtil::IsFormatSupported(client.get(), + return CoreAudioUtil::IsFormatSupported(client.Get(), AUDCLNT_SHAREMODE_SHARED, &format); } @@ -721,20 +721,20 @@ device = CreateDevice(device_id); } - if (!device.get()) { + if (!device.Get()) { // Map NULL-pointer to new error code which can be different from the // actual error code. The exact value is not important here. return AUDCLNT_E_DEVICE_INVALIDATED; } - ScopedComPtr<IAudioClient> client(CreateClient(device.get())); - if (!client.get()) { + ScopedComPtr<IAudioClient> client(CreateClient(device.Get())); + if (!client.Get()) { // Map NULL-pointer to new error code which can be different from the // actual error code. The exact value is not important here. return AUDCLNT_E_ENDPOINT_CREATE_FAILED; } - HRESULT hr = GetPreferredAudioParameters(client.get(), params); + HRESULT hr = GetPreferredAudioParameters(client.Get(), params); if (FAILED(hr) || is_output_device || !params->IsValid()) return hr; @@ -758,7 +758,7 @@ CreateClient(device_id, data_flow, eConsole)); WAVEFORMATPCMEX format = {}; - if (!client.get() || FAILED(GetSharedModeMixFormat(client.get(), &format))) + if (!client.Get() || FAILED(GetSharedModeMixFormat(client.Get(), &format))) return 0; return static_cast<ChannelConfig>(format.dwChannelMask);
diff --git a/media/audio/win/core_audio_util_win_unittest.cc b/media/audio/win/core_audio_util_win_unittest.cc index 03c6e4f2..6a13f26 100644 --- a/media/audio/win/core_audio_util_win_unittest.cc +++ b/media/audio/win/core_audio_util_win_unittest.cc
@@ -65,7 +65,7 @@ ScopedComPtr<IMMDeviceEnumerator> enumerator = CoreAudioUtil::CreateDeviceEnumerator(); - EXPECT_TRUE(enumerator.get()); + EXPECT_TRUE(enumerator.Get()); } TEST_F(CoreAudioUtilWinTest, CreateDefaultDevice) { @@ -88,13 +88,13 @@ for (size_t i = 0; i < arraysize(data); ++i) { audio_device = CoreAudioUtil::CreateDefaultDevice(data[i].flow, data[i].role); - EXPECT_TRUE(audio_device.get()); - EXPECT_EQ(data[i].flow, CoreAudioUtil::GetDataFlow(audio_device.get())); + EXPECT_TRUE(audio_device.Get()); + EXPECT_EQ(data[i].flow, CoreAudioUtil::GetDataFlow(audio_device.Get())); } // Only eRender and eCapture are allowed as flow parameter. audio_device = CoreAudioUtil::CreateDefaultDevice(eAll, eConsole); - EXPECT_FALSE(audio_device.get()); + EXPECT_FALSE(audio_device.Get()); } TEST_F(CoreAudioUtilWinTest, CreateDevice) { @@ -105,19 +105,19 @@ CoreAudioUtil::CreateDefaultDevice(eRender, eConsole); AudioDeviceName default_render_name; EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetDeviceName( - default_render_device.get(), &default_render_name))); + default_render_device.Get(), &default_render_name))); // Use the uniqe ID as input to CreateDevice() and create a corresponding // IMMDevice. ScopedComPtr<IMMDevice> audio_device = CoreAudioUtil::CreateDevice(default_render_name.unique_id); - EXPECT_TRUE(audio_device.get()); + EXPECT_TRUE(audio_device.Get()); // Verify that the two IMMDevice interfaces represents the same endpoint // by comparing their unique IDs. AudioDeviceName device_name; EXPECT_TRUE(SUCCEEDED( - CoreAudioUtil::GetDeviceName(audio_device.get(), &device_name))); + CoreAudioUtil::GetDeviceName(audio_device.Get(), &device_name))); EXPECT_EQ(default_render_name.unique_id, device_name.unique_id); } @@ -141,7 +141,7 @@ audio_device = CoreAudioUtil::CreateDefaultDevice(data[i].flow, data[i].role); EXPECT_TRUE(SUCCEEDED( - CoreAudioUtil::GetDeviceName(audio_device.get(), &device_name))); + CoreAudioUtil::GetDeviceName(audio_device.Get(), &device_name))); EXPECT_FALSE(device_name.device_name.empty()); EXPECT_FALSE(device_name.unique_id.empty()); } @@ -152,7 +152,7 @@ ScopedComPtr<IMMDeviceEnumerator> enumerator( CoreAudioUtil::CreateDeviceEnumerator()); - ASSERT_TRUE(enumerator.get()); + ASSERT_TRUE(enumerator.Get()); // Enumerate all active input and output devices and fetch the ID of // the associated device. @@ -167,7 +167,7 @@ ScopedComPtr<IMMDevice> device; collection->Item(j, device.Receive()); std::string controller_id( - CoreAudioUtil::GetAudioControllerID(device.get(), enumerator.get())); + CoreAudioUtil::GetAudioControllerID(device.Get(), enumerator.Get())); EXPECT_FALSE(controller_id.empty()); } } @@ -180,7 +180,7 @@ ScopedComPtr<IMMDevice> audio_device = CoreAudioUtil::CreateDefaultDevice(eCapture, eConsole); AudioDeviceName device_name; - HRESULT hr = CoreAudioUtil::GetDeviceName(audio_device.get(), &device_name); + HRESULT hr = CoreAudioUtil::GetDeviceName(audio_device.Get(), &device_name); EXPECT_TRUE(SUCCEEDED(hr)); // Use unique ID as input to GetFriendlyName() and compare the result @@ -191,7 +191,7 @@ // Same test as above but for playback. audio_device = CoreAudioUtil::CreateDefaultDevice(eRender, eConsole); - hr = CoreAudioUtil::GetDeviceName(audio_device.get(), &device_name); + hr = CoreAudioUtil::GetDeviceName(audio_device.Get(), &device_name); EXPECT_TRUE(SUCCEEDED(hr)); friendly_name = CoreAudioUtil::GetFriendlyName(device_name.unique_id); EXPECT_EQ(friendly_name, device_name.device_name); @@ -206,7 +206,7 @@ CoreAudioUtil::CreateDefaultDevice(eRender, eConsole); AudioDeviceName name; EXPECT_TRUE( - SUCCEEDED(CoreAudioUtil::GetDeviceName(audio_device.get(), &name))); + SUCCEEDED(CoreAudioUtil::GetDeviceName(audio_device.Get(), &name))); const std::string id = name.unique_id; EXPECT_TRUE(CoreAudioUtil::DeviceIsDefault(eRender, eConsole, id)); EXPECT_FALSE(CoreAudioUtil::DeviceIsDefault(eCapture, eConsole, id)); @@ -220,7 +220,7 @@ for (size_t i = 0; i < arraysize(data); ++i) { ScopedComPtr<IAudioClient> client; client = CoreAudioUtil::CreateDefaultClient(data[i], eConsole); - EXPECT_TRUE(client.get()); + EXPECT_TRUE(client.Get()); } } @@ -233,10 +233,10 @@ ScopedComPtr<IMMDevice> device; ScopedComPtr<IAudioClient> client; device = CoreAudioUtil::CreateDefaultDevice(data[i], eConsole); - EXPECT_TRUE(device.get()); - EXPECT_EQ(data[i], CoreAudioUtil::GetDataFlow(device.get())); - client = CoreAudioUtil::CreateClient(device.get()); - EXPECT_TRUE(client.get()); + EXPECT_TRUE(device.Get()); + EXPECT_EQ(data[i], CoreAudioUtil::GetDataFlow(device.Get())); + client = CoreAudioUtil::CreateClient(device.Get()); + EXPECT_TRUE(client.Get()); } } @@ -246,14 +246,14 @@ ScopedComPtr<IMMDevice> device; ScopedComPtr<IAudioClient> client; device = CoreAudioUtil::CreateDefaultDevice(eRender, eConsole); - EXPECT_TRUE(device.get()); - client = CoreAudioUtil::CreateClient(device.get()); - EXPECT_TRUE(client.get()); + EXPECT_TRUE(device.Get()); + client = CoreAudioUtil::CreateClient(device.Get()); + EXPECT_TRUE(client.Get()); // Perform a simple sanity test of the aquired format structure. WAVEFORMATPCMEX format; EXPECT_TRUE( - SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format))); + SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.Get(), &format))); EXPECT_GE(format.Format.nChannels, 1); EXPECT_GE(format.Format.nSamplesPerSec, 8000u); EXPECT_GE(format.Format.wBitsPerSample, 16); @@ -299,12 +299,12 @@ REFERENCE_TIME shared_time_period = 0; REFERENCE_TIME exclusive_time_period = 0; client = CoreAudioUtil::CreateDefaultClient(data[i], eConsole); - EXPECT_TRUE(client.get()); + EXPECT_TRUE(client.Get()); EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetDevicePeriod( - client.get(), AUDCLNT_SHAREMODE_SHARED, &shared_time_period))); + client.Get(), AUDCLNT_SHAREMODE_SHARED, &shared_time_period))); EXPECT_GT(shared_time_period, 0); EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetDevicePeriod( - client.get(), AUDCLNT_SHAREMODE_EXCLUSIVE, &exclusive_time_period))); + client.Get(), AUDCLNT_SHAREMODE_EXCLUSIVE, &exclusive_time_period))); EXPECT_GT(exclusive_time_period, 0); EXPECT_LE(exclusive_time_period, shared_time_period); } @@ -321,9 +321,9 @@ ScopedComPtr<IAudioClient> client; AudioParameters params; client = CoreAudioUtil::CreateDefaultClient(data[i], eConsole); - EXPECT_TRUE(client.get()); + EXPECT_TRUE(client.Get()); EXPECT_TRUE(SUCCEEDED( - CoreAudioUtil::GetPreferredAudioParameters(client.get(), ¶ms))); + CoreAudioUtil::GetPreferredAudioParameters(client.Get(), ¶ms))); EXPECT_TRUE(params.IsValid()); } } @@ -333,29 +333,29 @@ ScopedComPtr<IAudioClient> client; client = CoreAudioUtil::CreateDefaultClient(eRender, eConsole); - EXPECT_TRUE(client.get()); + EXPECT_TRUE(client.Get()); WAVEFORMATPCMEX format; EXPECT_TRUE( - SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format))); + SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.Get(), &format))); // Perform a shared-mode initialization without event-driven buffer handling. uint32_t endpoint_buffer_size = 0; - HRESULT hr = CoreAudioUtil::SharedModeInitialize(client.get(), &format, NULL, + HRESULT hr = CoreAudioUtil::SharedModeInitialize(client.Get(), &format, NULL, &endpoint_buffer_size, NULL); EXPECT_TRUE(SUCCEEDED(hr)); EXPECT_GT(endpoint_buffer_size, 0u); // It is only possible to create a client once. - hr = CoreAudioUtil::SharedModeInitialize(client.get(), &format, NULL, + hr = CoreAudioUtil::SharedModeInitialize(client.Get(), &format, NULL, &endpoint_buffer_size, NULL); EXPECT_FALSE(SUCCEEDED(hr)); EXPECT_EQ(hr, AUDCLNT_E_ALREADY_INITIALIZED); // Verify that it is possible to reinitialize the client after releasing it. client = CoreAudioUtil::CreateDefaultClient(eRender, eConsole); - EXPECT_TRUE(client.get()); - hr = CoreAudioUtil::SharedModeInitialize(client.get(), &format, NULL, + EXPECT_TRUE(client.Get()); + hr = CoreAudioUtil::SharedModeInitialize(client.Get(), &format, NULL, &endpoint_buffer_size, NULL); EXPECT_TRUE(SUCCEEDED(hr)); EXPECT_GT(endpoint_buffer_size, 0u); @@ -364,11 +364,11 @@ // A simple way to emulate an invalid format is to use the shared-mode // mixing format and modify the preferred sample. client = CoreAudioUtil::CreateDefaultClient(eRender, eConsole); - EXPECT_TRUE(client.get()); + EXPECT_TRUE(client.Get()); format.Format.nSamplesPerSec = format.Format.nSamplesPerSec + 1; EXPECT_FALSE(CoreAudioUtil::IsFormatSupported( - client.get(), AUDCLNT_SHAREMODE_SHARED, &format)); - hr = CoreAudioUtil::SharedModeInitialize(client.get(), &format, NULL, + client.Get(), AUDCLNT_SHAREMODE_SHARED, &format)); + hr = CoreAudioUtil::SharedModeInitialize(client.Get(), &format, NULL, &endpoint_buffer_size, NULL); EXPECT_TRUE(FAILED(hr)); EXPECT_EQ(hr, E_INVALIDARG); @@ -379,13 +379,13 @@ // The event handle should be in the nonsignaled state. base::win::ScopedHandle event_handle(::CreateEvent(NULL, TRUE, FALSE, NULL)); client = CoreAudioUtil::CreateDefaultClient(eRender, eConsole); - EXPECT_TRUE(client.get()); + EXPECT_TRUE(client.Get()); EXPECT_TRUE( - SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format))); + SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.Get(), &format))); EXPECT_TRUE(CoreAudioUtil::IsFormatSupported( - client.get(), AUDCLNT_SHAREMODE_SHARED, &format)); + client.Get(), AUDCLNT_SHAREMODE_SHARED, &format)); hr = CoreAudioUtil::SharedModeInitialize( - client.get(), &format, event_handle.Get(), &endpoint_buffer_size, NULL); + client.Get(), &format, event_handle.Get(), &endpoint_buffer_size, NULL); EXPECT_TRUE(SUCCEEDED(hr)); EXPECT_GT(endpoint_buffer_size, 0u); } @@ -404,32 +404,32 @@ ScopedComPtr<IAudioCaptureClient> capture_client; client = CoreAudioUtil::CreateDefaultClient(data[i], eConsole); - EXPECT_TRUE(client.get()); + EXPECT_TRUE(client.Get()); EXPECT_TRUE(SUCCEEDED( - CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format))); + CoreAudioUtil::GetSharedModeMixFormat(client.Get(), &format))); if (data[i] == eRender) { // It is not possible to create a render client using an unitialized // client interface. - render_client = CoreAudioUtil::CreateRenderClient(client.get()); - EXPECT_FALSE(render_client.get()); + render_client = CoreAudioUtil::CreateRenderClient(client.Get()); + EXPECT_FALSE(render_client.Get()); // Do a proper initialization and verify that it works this time. - CoreAudioUtil::SharedModeInitialize(client.get(), &format, NULL, + CoreAudioUtil::SharedModeInitialize(client.Get(), &format, NULL, &endpoint_buffer_size, NULL); - render_client = CoreAudioUtil::CreateRenderClient(client.get()); - EXPECT_TRUE(render_client.get()); + render_client = CoreAudioUtil::CreateRenderClient(client.Get()); + EXPECT_TRUE(render_client.Get()); EXPECT_GT(endpoint_buffer_size, 0u); } else if (data[i] == eCapture) { // It is not possible to create a capture client using an unitialized // client interface. - capture_client = CoreAudioUtil::CreateCaptureClient(client.get()); - EXPECT_FALSE(capture_client.get()); + capture_client = CoreAudioUtil::CreateCaptureClient(client.Get()); + EXPECT_FALSE(capture_client.Get()); // Do a proper initialization and verify that it works this time. - CoreAudioUtil::SharedModeInitialize(client.get(), &format, NULL, + CoreAudioUtil::SharedModeInitialize(client.Get(), &format, NULL, &endpoint_buffer_size, NULL); - capture_client = CoreAudioUtil::CreateCaptureClient(client.get()); - EXPECT_TRUE(capture_client.get()); + capture_client = CoreAudioUtil::CreateCaptureClient(client.Get()); + EXPECT_TRUE(capture_client.Get()); EXPECT_GT(endpoint_buffer_size, 0u); } } @@ -441,19 +441,19 @@ // Create default clients using the default mixing format for shared mode. ScopedComPtr<IAudioClient> client( CoreAudioUtil::CreateDefaultClient(eRender, eConsole)); - EXPECT_TRUE(client.get()); + EXPECT_TRUE(client.Get()); WAVEFORMATPCMEX format; uint32_t endpoint_buffer_size = 0; EXPECT_TRUE( - SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format))); - CoreAudioUtil::SharedModeInitialize(client.get(), &format, NULL, + SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.Get(), &format))); + CoreAudioUtil::SharedModeInitialize(client.Get(), &format, NULL, &endpoint_buffer_size, NULL); EXPECT_GT(endpoint_buffer_size, 0u); ScopedComPtr<IAudioRenderClient> render_client( - CoreAudioUtil::CreateRenderClient(client.get())); - EXPECT_TRUE(render_client.get()); + CoreAudioUtil::CreateRenderClient(client.Get())); + EXPECT_TRUE(render_client.Get()); // The endpoint audio buffer should not be filled up by default after being // created. @@ -466,7 +466,7 @@ // since we can't access data that has already been sent to the endpoint // buffer. EXPECT_TRUE(CoreAudioUtil::FillRenderEndpointBufferWithSilence( - client.get(), render_client.get())); + client.Get(), render_client.Get())); client->GetCurrentPadding(&num_queued_frames); EXPECT_EQ(num_queued_frames, endpoint_buffer_size); } @@ -480,7 +480,7 @@ ScopedComPtr<IMMDeviceEnumerator> enumerator( CoreAudioUtil::CreateDeviceEnumerator()); - ASSERT_TRUE(enumerator.get()); + ASSERT_TRUE(enumerator.Get()); // Enumerate all active input and output devices and fetch the ID of // the associated device.
diff --git a/media/base/win/mf_helpers.cc b/media/base/win/mf_helpers.cc index c88f571..b04ef674 100644 --- a/media/base/win/mf_helpers.cc +++ b/media/base/win/mf_helpers.cc
@@ -35,7 +35,7 @@ RETURN_ON_HR_FAILURE(hr, "Failed to create memory buffer for sample", base::win::ScopedComPtr<IMFSample>()); - hr = sample->AddBuffer(buffer.get()); + hr = sample->AddBuffer(buffer.Get()); RETURN_ON_HR_FAILURE(hr, "Failed to add buffer to sample", base::win::ScopedComPtr<IMFSample>());
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 0c886a34..cd1569a 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -2097,15 +2097,27 @@ const PipelineStatistics stats = GetPipelineStatistics(); const int64_t data_source_memory_usage = data_source_ ? data_source_->GetMemoryUsage() : 0; + + // If we have video and no video memory usage, assume the VideoFrameCompositor + // is holding onto the last frame after we've suspended the pipeline; which + // thus reports zero memory usage from the video renderer. + // + // Technically this should use the coded size, but that requires us to hop to + // the compositor to get and byte-perfect accuracy isn't important here. + const int64_t video_memory_usage = + stats.video_memory_usage + + (pipeline_metadata_.has_video && !stats.video_memory_usage + ? VideoFrame::AllocationSize(PIXEL_FORMAT_YV12, + pipeline_metadata_.natural_size) + : 0); + const int64_t current_memory_usage = - stats.audio_memory_usage + stats.video_memory_usage + - data_source_memory_usage + demuxer_memory_usage; + stats.audio_memory_usage + video_memory_usage + data_source_memory_usage + + demuxer_memory_usage; - // Note, this isn't entirely accurate, there may be VideoFrames held by the - // compositor or other resources that we're unaware of. - - DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage - << ", Video: " << stats.video_memory_usage + DVLOG(2) << "Memory Usage -- Total: " << current_memory_usage + << " Audio: " << stats.audio_memory_usage + << ", Video: " << video_memory_usage << ", DataSource: " << data_source_memory_usage << ", Demuxer: " << demuxer_memory_usage; @@ -2119,7 +2131,7 @@ } if (HasVideo()) { UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Video", - stats.video_memory_usage / 1024); + video_memory_usage / 1024); } if (data_source_) { UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.DataSource",
diff --git a/media/capture/video/win/filter_base_win.cc b/media/capture/video/win/filter_base_win.cc index 166b860..70af2f3 100644 --- a/media/capture/video/win/filter_base_win.cc +++ b/media/capture/video/win/filter_base_win.cc
@@ -93,7 +93,7 @@ } STDMETHODIMP FilterBase::QueryFilterInfo(FILTER_INFO* info) { - info->pGraph = owning_graph_.get(); + info->pGraph = owning_graph_.Get(); info->achName[0] = L'\0'; if (info->pGraph) info->pGraph->AddRef();
diff --git a/media/capture/video/win/pin_base_win.cc b/media/capture/video/win/pin_base_win.cc index 349ce26..855c613a 100644 --- a/media/capture/video/win/pin_base_win.cc +++ b/media/capture/video/win/pin_base_win.cc
@@ -144,7 +144,7 @@ } STDMETHODIMP PinBase::Disconnect() { - if (!connected_pin_.get()) + if (!connected_pin_.Get()) return S_FALSE; connected_pin_.Reset(); @@ -152,16 +152,16 @@ } STDMETHODIMP PinBase::ConnectedTo(IPin** pin) { - *pin = connected_pin_.get(); - if (!connected_pin_.get()) + *pin = connected_pin_.Get(); + if (!connected_pin_.Get()) return VFW_E_NOT_CONNECTED; - connected_pin_.get()->AddRef(); + connected_pin_.Get()->AddRef(); return S_OK; } STDMETHODIMP PinBase::ConnectionMediaType(AM_MEDIA_TYPE* media_type) { - if (!connected_pin_.get()) + if (!connected_pin_.Get()) return VFW_E_NOT_CONNECTED; *media_type = current_media_type_; return S_OK;
diff --git a/media/capture/video/win/video_capture_device_factory_win.cc b/media/capture/video/win/video_capture_device_factory_win.cc index 60f0aa3..76b2785 100644 --- a/media/capture/video/win/video_capture_device_factory_win.cc +++ b/media/capture/video/win/video_capture_device_factory_win.cc
@@ -100,7 +100,7 @@ attributes->SetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, base::SysUTF8ToWide(sym_link).c_str()); - return SUCCEEDED(MFCreateDeviceSource(attributes.get(), source)); + return SUCCEEDED(MFCreateDeviceSource(attributes.Get(), source)); } static bool EnumerateVideoDevicesMediaFoundation(IMFActivate*** devices, @@ -109,7 +109,7 @@ if (!PrepareVideoCaptureAttributesMediaFoundation(attributes.Receive(), 1)) return false; - return SUCCEEDED(MFEnumDeviceSources(attributes.get(), devices, count)); + return SUCCEEDED(MFEnumDeviceSources(attributes.Get(), devices, count)); } static bool IsDeviceBlackListed(const std::string& name) { @@ -262,16 +262,16 @@ base::win::ScopedComPtr<IBaseFilter> capture_filter; hr = VideoCaptureDeviceWin::GetDeviceFilter(descriptor.device_id, capture_filter.Receive()); - if (!capture_filter.get()) { + if (!capture_filter.Get()) { DLOG(ERROR) << "Failed to create capture filter: " << logging::SystemErrorCodeToString(hr); return; } base::win::ScopedComPtr<IPin> output_capture_pin( - VideoCaptureDeviceWin::GetPin(capture_filter.get(), PINDIR_OUTPUT, + VideoCaptureDeviceWin::GetPin(capture_filter.Get(), PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE, GUID_NULL)); - if (!output_capture_pin.get()) { + if (!output_capture_pin.Get()) { DLOG(ERROR) << "Failed to get capture output pin"; return; } @@ -340,7 +340,7 @@ base::win::ScopedComPtr<IMFSourceReader> reader; HRESULT hr = - MFCreateSourceReaderFromMediaSource(source.get(), NULL, reader.Receive()); + MFCreateSourceReaderFromMediaSource(source.Get(), NULL, reader.Receive()); if (FAILED(hr)) { DLOG(ERROR) << "MFCreateSourceReaderFromMediaSource failed: " << logging::SystemErrorCodeToString(hr); @@ -352,7 +352,7 @@ while (SUCCEEDED(reader->GetNativeMediaType(kFirstVideoStream, stream_index, type.Receive()))) { UINT32 width, height; - hr = MFGetAttributeSize(type.get(), MF_MT_FRAME_SIZE, &width, &height); + hr = MFGetAttributeSize(type.Get(), MF_MT_FRAME_SIZE, &width, &height); if (FAILED(hr)) { DLOG(ERROR) << "MFGetAttributeSize failed: " << logging::SystemErrorCodeToString(hr); @@ -362,7 +362,7 @@ capture_format.frame_size.SetSize(width, height); UINT32 numerator, denominator; - hr = MFGetAttributeRatio(type.get(), MF_MT_FRAME_RATE, &numerator, + hr = MFGetAttributeRatio(type.Get(), MF_MT_FRAME_RATE, &numerator, &denominator); if (FAILED(hr)) { DLOG(ERROR) << "MFGetAttributeSize failed: "
diff --git a/media/capture/video/win/video_capture_device_mf_win.cc b/media/capture/video/win/video_capture_device_mf_win.cc index 3489f33..ea1abd7f 100644 --- a/media/capture/video/win/video_capture_device_mf_win.cc +++ b/media/capture/video/win/video_capture_device_mf_win.cc
@@ -65,7 +65,7 @@ while (SUCCEEDED(hr = source->GetNativeMediaType( kFirstVideoStream, stream_index, type.Receive()))) { VideoCaptureFormat format; - if (FillFormat(type.get(), &format)) + if (FillFormat(type.Get(), &format)) capabilities->emplace_back(stream_index, format); type.Reset(); ++stream_index; @@ -124,7 +124,7 @@ for (DWORD i = 0; i < count; ++i) { ScopedComPtr<IMFMediaBuffer> buffer; sample->GetBufferByIndex(i, buffer.Receive()); - if (buffer.get()) { + if (buffer.Get()) { DWORD length = 0, max_length = 0; BYTE* data = NULL; buffer->Lock(&data, &max_length, &length); @@ -199,17 +199,17 @@ bool VideoCaptureDeviceMFWin::Init( const base::win::ScopedComPtr<IMFMediaSource>& source) { DCHECK(CalledOnValidThread()); - DCHECK(!reader_.get()); + DCHECK(!reader_.Get()); ScopedComPtr<IMFAttributes> attributes; MFCreateAttributes(attributes.Receive(), 1); - DCHECK(attributes.get()); + DCHECK(attributes.Get()); callback_ = new MFReaderCallback(this); attributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, callback_.get()); return SUCCEEDED(MFCreateSourceReaderFromMediaSource( - source.get(), attributes.get(), reader_.Receive())); + source.Get(), attributes.Get(), reader_.Receive())); } void VideoCaptureDeviceMFWin::AllocateAndStart( @@ -224,8 +224,8 @@ CapabilityList capabilities; HRESULT hr = S_OK; - if (reader_.get()) { - hr = FillCapabilities(reader_.get(), &capabilities); + if (reader_.Get()) { + hr = FillCapabilities(reader_.Get(), &capabilities); if (SUCCEEDED(hr)) { const CapabilityWin found_capability = GetBestMatchedCapability(params.requested_format, capabilities); @@ -233,7 +233,7 @@ hr = reader_->GetNativeMediaType( kFirstVideoStream, found_capability.stream_index, type.Receive()); if (SUCCEEDED(hr)) { - hr = reader_->SetCurrentMediaType(kFirstVideoStream, NULL, type.get()); + hr = reader_->SetCurrentMediaType(kFirstVideoStream, NULL, type.Get()); if (SUCCEEDED(hr)) { hr = reader_->ReadSample(kFirstVideoStream, 0, NULL, NULL, NULL, NULL);
diff --git a/media/capture/video/win/video_capture_device_win.cc b/media/capture/video/win/video_capture_device_win.cc index cc27b25b..4378345 100644 --- a/media/capture/video/win/video_capture_device_win.cc +++ b/media/capture/video/win/video_capture_device_win.cc
@@ -132,7 +132,7 @@ ScopedComPtr<IPin> pin; ScopedComPtr<IEnumPins> pin_enum; HRESULT hr = filter->EnumPins(pin_enum.Receive()); - if (pin_enum.get() == NULL) + if (pin_enum.Get() == NULL) return pin; // Get first unconnected pin. @@ -141,16 +141,16 @@ PIN_DIRECTION this_pin_dir = static_cast<PIN_DIRECTION>(-1); hr = pin->QueryDirection(&this_pin_dir); if (pin_dir == this_pin_dir) { - if ((category == GUID_NULL || PinMatchesCategory(pin.get(), category)) && + if ((category == GUID_NULL || PinMatchesCategory(pin.Get(), category)) && (major_type == GUID_NULL || - PinMatchesMajorType(pin.get(), major_type))) { + PinMatchesMajorType(pin.Get(), major_type))) { return pin; } } pin.Reset(); } - DCHECK(!pin.get()); + DCHECK(!pin.Get()); return pin; } @@ -234,20 +234,20 @@ VideoCaptureDeviceWin::~VideoCaptureDeviceWin() { DCHECK(thread_checker_.CalledOnValidThread()); - if (media_control_.get()) + if (media_control_.Get()) media_control_->Stop(); - if (graph_builder_.get()) { + if (graph_builder_.Get()) { if (sink_filter_.get()) { graph_builder_->RemoveFilter(sink_filter_.get()); sink_filter_ = NULL; } - if (capture_filter_.get()) - graph_builder_->RemoveFilter(capture_filter_.get()); + if (capture_filter_.Get()) + graph_builder_->RemoveFilter(capture_filter_.Get()); } - if (capture_graph_builder_.get()) + if (capture_graph_builder_.Get()) capture_graph_builder_.Reset(); } @@ -257,12 +257,12 @@ hr = GetDeviceFilter(device_descriptor_.device_id, capture_filter_.Receive()); DLOG_IF_FAILED_WITH_HRESULT("Failed to create capture filter", hr); - if (!capture_filter_.get()) + if (!capture_filter_.Get()) return false; - output_capture_pin_ = GetPin(capture_filter_.get(), PINDIR_OUTPUT, + output_capture_pin_ = GetPin(capture_filter_.Get(), PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE, GUID_NULL); - if (!output_capture_pin_.get()) { + if (!output_capture_pin_.Get()) { DLOG(ERROR) << "Failed to get capture output pin"; return false; } @@ -288,7 +288,7 @@ if (FAILED(hr)) return false; - hr = capture_graph_builder_->SetFiltergraph(graph_builder_.get()); + hr = capture_graph_builder_->SetFiltergraph(graph_builder_.Get()); DLOG_IF_FAILED_WITH_HRESULT("Failed to give graph to capture graph builder", hr); if (FAILED(hr)) @@ -299,7 +299,7 @@ if (FAILED(hr)) return false; - hr = graph_builder_->AddFilter(capture_filter_.get(), NULL); + hr = graph_builder_->AddFilter(capture_filter_.Get(), NULL); DLOG_IF_FAILED_WITH_HRESULT("Failed to add the capture device to the graph", hr); if (FAILED(hr)) @@ -318,11 +318,11 @@ base::win::ScopedComPtr<IAMStreamConfig> stream_config; hr = capture_graph_builder_->FindInterface( - &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, capture_filter_.get(), + &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, capture_filter_.Get(), IID_IAMStreamConfig, (void**)stream_config.Receive()); if (FAILED(hr)) { hr = capture_graph_builder_->FindInterface( - &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, capture_filter_.get(), + &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, capture_filter_.Get(), IID_IAMStreamConfig, (void**)stream_config.Receive()); DLOG_IF_FAILED_WITH_HRESULT("Failed to find CapFilter:IAMStreamConfig", hr); } @@ -397,11 +397,11 @@ if (media_type->subtype == kMediaSubTypeHDYC) { // HDYC pixel format, used by the DeckLink capture card, needs an AVI // decompressor filter after source, let |graph_builder_| add it. - hr = graph_builder_->Connect(output_capture_pin_.get(), - input_sink_pin_.get()); + hr = graph_builder_->Connect(output_capture_pin_.Get(), + input_sink_pin_.Get()); } else { - hr = graph_builder_->ConnectDirect(output_capture_pin_.get(), - input_sink_pin_.get(), NULL); + hr = graph_builder_->ConnectDirect(output_capture_pin_.Get(), + input_sink_pin_.Get(), NULL); } if (FAILED(hr)) { @@ -437,8 +437,8 @@ return; } - graph_builder_->Disconnect(output_capture_pin_.get()); - graph_builder_->Disconnect(input_sink_pin_.get()); + graph_builder_->Disconnect(output_capture_pin_.Get()); + graph_builder_->Disconnect(input_sink_pin_.Get()); client_.reset(); state_ = kIdle; @@ -525,12 +525,12 @@ // Try to get a better |time_per_frame| from IAMVideoControl. If not, use // the value from VIDEOINFOHEADER. REFERENCE_TIME time_per_frame = h->AvgTimePerFrame; - if (video_control.get()) { + if (video_control.Get()) { ScopedCoMem<LONGLONG> max_fps; LONG list_size = 0; const SIZE size = {format.frame_size.width(), format.frame_size.height()}; - hr = video_control->GetFrameRateList(output_capture_pin_.get(), + hr = video_control->GetFrameRateList(output_capture_pin_.Get(), stream_index, size, &list_size, &max_fps); // Can't assume the first value will return the max fps. @@ -566,7 +566,7 @@ ScopedComPtr<IKsPropertySet> ks_propset; DWORD type_support = 0; HRESULT hr; - if (SUCCEEDED(hr = ks_propset.QueryFrom(capture_filter_.get())) && + if (SUCCEEDED(hr = ks_propset.QueryFrom(capture_filter_.Get())) && SUCCEEDED(hr = ks_propset->QuerySupported( PROPSETID_VIDCAP_VIDEOPROCAMP, KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY,
diff --git a/media/gpu/d3d11_h264_accelerator.cc b/media/gpu/d3d11_h264_accelerator.cc index 49aaab34..b325f68 100644 --- a/media/gpu/d3d11_h264_accelerator.cc +++ b/media/gpu/d3d11_h264_accelerator.cc
@@ -48,7 +48,7 @@ view_desc.Texture2D.ArraySlice = (UINT)level_; HRESULT hr = video_device->CreateVideoDecoderOutputView( - texture.get(), &view_desc, output_view_.Receive()); + texture.Get(), &view_desc, output_view_.Receive()); CHECK(SUCCEEDED(hr)); EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); @@ -95,7 +95,7 @@ }; result = eglStreamPostD3DTextureNV12ANGLE(egl_display, stream_, - static_cast<void*>(texture.get()), + static_cast<void*>(texture.Get()), frame_attributes); RETURN_ON_FAILURE(result, "Could not post texture", false); result = eglStreamConsumerAcquireKHR(egl_display, stream_); @@ -153,7 +153,7 @@ HRESULT hr; hr = video_context_->DecoderBeginFrame( - video_decoder_.get(), our_pic->picture->output_view_.get(), 0, nullptr); + video_decoder_.Get(), our_pic->picture->output_view_.Get(), 0, nullptr); CHECK(SUCCEEDED(hr)); sps_ = *sps; @@ -197,7 +197,7 @@ void* buffer; UINT buffer_size; HRESULT hr = video_context_->GetDecoderBuffer( - video_decoder_.get(), D3D11_VIDEO_DECODER_BUFFER_BITSTREAM, &buffer_size, + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_BITSTREAM, &buffer_size, &buffer); bitstream_buffer_bytes_ = (uint8_t*)buffer; bitstream_buffer_size_ = buffer_size; @@ -298,13 +298,13 @@ UINT buffer_size; void* buffer; HRESULT hr = video_context_->GetDecoderBuffer( - video_decoder_.get(), D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS, + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS, &buffer_size, &buffer); CHECK(SUCCEEDED(hr)); memcpy(buffer, &pic_param, sizeof(pic_param)); hr = video_context_->ReleaseDecoderBuffer( - video_decoder_.get(), D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS); + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS); CHECK(SUCCEEDED(hr)); DXVA_Qmatrix_H264 iq_matrix_buf = {}; @@ -331,13 +331,13 @@ } } hr = video_context_->GetDecoderBuffer( - video_decoder_.get(), + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX, &buffer_size, &buffer); CHECK(SUCCEEDED(hr)); memcpy(buffer, &iq_matrix_buf, sizeof(iq_matrix_buf)); hr = video_context_->ReleaseDecoderBuffer( - video_decoder_.get(), + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX); // Ideally all slices in a frame are put in the same bitstream buffer. @@ -401,16 +401,16 @@ UINT buffer_size; void* buffer; HRESULT hr = video_context_->GetDecoderBuffer( - video_decoder_.get(), D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL, + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL, &buffer_size, &buffer); CHECK(SUCCEEDED(hr)); CHECK_LE(sizeof(slice_info_[0]) * slice_info_.size(), buffer_size); memcpy(buffer, &slice_info_[0], sizeof(slice_info_[0]) * slice_info_.size()); hr = video_context_->ReleaseDecoderBuffer( - video_decoder_.get(), D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL); + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL); hr = video_context_->ReleaseDecoderBuffer( - video_decoder_.get(), D3D11_VIDEO_DECODER_BUFFER_BITSTREAM); + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_BITSTREAM); D3D11_VIDEO_DECODER_BUFFER_DESC buffers[4] = {}; buffers[0].BufferType = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS; buffers[0].DataOffset = 0; @@ -426,7 +426,7 @@ buffers[3].DataOffset = 0; buffers[3].DataSize = (UINT)current_offset_; - hr = video_context_->SubmitDecoderBuffers(video_decoder_.get(), 4, buffers); + hr = video_context_->SubmitDecoderBuffers(video_decoder_.Get(), 4, buffers); current_offset_ = 0; slice_info_.clear(); } @@ -434,7 +434,7 @@ bool D3D11H264Accelerator::SubmitDecode(const scoped_refptr<H264Picture>& pic) { SubmitSliceData(); - HRESULT hr = video_context_->DecoderEndFrame(video_decoder_.get()); + HRESULT hr = video_context_->DecoderEndFrame(video_decoder_.Get()); CHECK(SUCCEEDED(hr)); return true;
diff --git a/media/gpu/d3d11_video_decode_accelerator_win.cc b/media/gpu/d3d11_video_decode_accelerator_win.cc index 6468797..e778931 100644 --- a/media/gpu/d3d11_video_decode_accelerator_win.cc +++ b/media/gpu/d3d11_video_decode_accelerator_win.cc
@@ -105,7 +105,7 @@ base::win::ScopedComPtr<ID3D11VideoDecoder> video_decoder; hr = video_device_->CreateVideoDecoder(&desc, &dec_config, video_decoder.Receive()); - CHECK(video_decoder.get()); + CHECK(video_decoder.Get()); h264_accelerator_.reset(new D3D11H264Accelerator( this, video_decoder, video_device_, video_context_));
diff --git a/media/gpu/dxva_picture_buffer_win.cc b/media/gpu/dxva_picture_buffer_win.cc index 4e36b913..e7394567 100644 --- a/media/gpu/dxva_picture_buffer_win.cc +++ b/media/gpu/dxva_picture_buffer_win.cc
@@ -240,12 +240,12 @@ &desc, nullptr, dx11_decoding_texture_.Receive()); RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false); if (decoder.use_keyed_mutex_) { - hr = dx11_keyed_mutex_.QueryFrom(dx11_decoding_texture_.get()); + hr = dx11_keyed_mutex_.QueryFrom(dx11_decoding_texture_.Get()); RETURN_ON_HR_FAILURE(hr, "Failed to get keyed mutex", false); } base::win::ScopedComPtr<IDXGIResource> resource; - hr = resource.QueryFrom(dx11_decoding_texture_.get()); + hr = resource.QueryFrom(dx11_decoding_texture_.Get()); DCHECK(SUCCEEDED(hr)); hr = resource->GetSharedHandle(&texture_share_handle_); RETURN_ON_FAILURE(SUCCEEDED(hr) && texture_share_handle_, @@ -286,7 +286,7 @@ // when we receive a notification that the copy was completed or when the // DXVAPictureBuffer instance is destroyed. decoder_dx11_texture_ = dx11_texture; - decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.get(), + decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.Get(), dx11_keyed_mutex_, keyed_mutex_value_, id(), input_buffer_id, color_space_); return true; @@ -323,7 +323,7 @@ decoder_surface_ = dest_surface; - decoder->CopySurface(decoder_surface_.get(), target_surface_.get(), id(), + decoder->CopySurface(decoder_surface_.Get(), target_surface_.Get(), id(), input_buffer_id, color_space_); color_space_ = gfx::ColorSpace(); return true; @@ -347,12 +347,12 @@ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); if (src_surface && dest_surface) { - DCHECK_EQ(src_surface, decoder_surface_.get()); - DCHECK_EQ(dest_surface, target_surface_.get()); + DCHECK_EQ(src_surface, decoder_surface_.Get()); + DCHECK_EQ(dest_surface, target_surface_.Get()); decoder_surface_.Reset(); target_surface_.Reset(); } else { - DCHECK(decoder_dx11_texture_.get()); + DCHECK(decoder_dx11_texture_.Get()); decoder_dx11_texture_.Reset(); } if (egl_keyed_mutex_) { @@ -486,7 +486,7 @@ RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from output sample", false); base::win::ScopedComPtr<IMFDXGIBuffer> dxgi_buffer; - hr = dxgi_buffer.QueryFrom(output_buffer.get()); + hr = dxgi_buffer.QueryFrom(output_buffer.Get()); RETURN_ON_HR_FAILURE(hr, "Failed to get DXGIBuffer from output sample", false); hr = dxgi_buffer->GetResource(IID_PPV_ARGS(dx11_decoding_texture_.Receive())); @@ -499,7 +499,7 @@ }; EGLBoolean result = eglStreamPostD3DTextureNV12ANGLE( - egl_display, stream_, static_cast<void*>(dx11_decoding_texture_.get()), + egl_display, stream_, static_cast<void*>(dx11_decoding_texture_.Get()), frame_attributes); RETURN_ON_FAILURE(result, "Could not post texture", false); result = eglStreamConsumerAcquireKHR(egl_display, stream_); @@ -588,11 +588,11 @@ &desc, nullptr, decoder_copy_texture_.Receive()); RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false); DCHECK(decoder.use_keyed_mutex_); - hr = dx11_keyed_mutex_.QueryFrom(decoder_copy_texture_.get()); + hr = dx11_keyed_mutex_.QueryFrom(decoder_copy_texture_.Get()); RETURN_ON_HR_FAILURE(hr, "Failed to get keyed mutex", false); base::win::ScopedComPtr<IDXGIResource> resource; - hr = resource.QueryFrom(decoder_copy_texture_.get()); + hr = resource.QueryFrom(decoder_copy_texture_.Get()); DCHECK(SUCCEEDED(hr)); hr = resource->GetSharedHandle(&texture_share_handle_); RETURN_ON_FAILURE(SUCCEEDED(hr) && texture_share_handle_, @@ -601,7 +601,7 @@ hr = decoder.angle_device_->OpenSharedResource( texture_share_handle_, IID_PPV_ARGS(angle_copy_texture_.Receive())); RETURN_ON_HR_FAILURE(hr, "Failed to open shared resource", false); - hr = egl_keyed_mutex_.QueryFrom(angle_copy_texture_.get()); + hr = egl_keyed_mutex_.QueryFrom(angle_copy_texture_.Get()); RETURN_ON_HR_FAILURE(hr, "Failed to get ANGLE mutex", false); return true; } @@ -618,7 +618,7 @@ // when we receive a notification that the copy was completed or when the // DXVAPictureBuffer instance is destroyed. dx11_decoding_texture_ = dx11_texture; - decoder->CopyTexture(dx11_texture, decoder_copy_texture_.get(), + decoder->CopyTexture(dx11_texture, decoder_copy_texture_.Get(), dx11_keyed_mutex_, keyed_mutex_value_, id(), input_buffer_id, color_space_); // The texture copy will acquire the current keyed mutex value and release @@ -648,7 +648,7 @@ EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); EGLBoolean result = eglStreamPostD3DTextureNV12ANGLE( - egl_display, stream_, static_cast<void*>(angle_copy_texture_.get()), + egl_display, stream_, static_cast<void*>(angle_copy_texture_.Get()), frame_attributes); RETURN_ON_FAILURE(result, "Could not post stream", false); result = eglStreamConsumerAcquireKHR(egl_display, stream_);
diff --git a/media/gpu/dxva_video_decode_accelerator_win.cc b/media/gpu/dxva_video_decode_accelerator_win.cc index 6fe936a..135d4e3 100644 --- a/media/gpu/dxva_video_decode_accelerator_win.cc +++ b/media/gpu/dxva_video_decode_accelerator_win.cc
@@ -286,7 +286,7 @@ CHECK_GT(size, 0U); base::win::ScopedComPtr<IMFSample> sample; sample = mf::CreateEmptySampleWithBuffer(std::max(min_size, size), alignment); - RETURN_ON_FAILURE(sample.get(), "Failed to create empty sample", + RETURN_ON_FAILURE(sample.Get(), "Failed to create empty sample", base::win::ScopedComPtr<IMFSample>()); base::win::ScopedComPtr<IMFMediaBuffer> buffer; @@ -649,7 +649,7 @@ bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() { TRACE_EVENT0("gpu", "DXVAVideoDecodeAccelerator_CreateD3DDevManager"); // The device may exist if the last state was a config change. - if (d3d9_.get()) + if (d3d9_.Get()) return true; HRESULT hr = E_FAIL; @@ -665,11 +665,11 @@ base::win::ScopedComPtr<IDirect3DDevice9> angle_device = gl::QueryD3D9DeviceObjectFromANGLE(); - if (angle_device.get()) + if (angle_device.Get()) using_angle_device_ = true; if (using_angle_device_) { - hr = d3d9_device_ex_.QueryFrom(angle_device.get()); + hr = d3d9_device_ex_.QueryFrom(angle_device.Get()); RETURN_ON_HR_FAILURE( hr, "QueryInterface for IDirect3DDevice9Ex from angle device failed", false); @@ -698,7 +698,7 @@ device_manager_.Receive()); RETURN_ON_HR_FAILURE(hr, "DXVA2CreateDirect3DDeviceManager9 failed", false); - hr = device_manager_->ResetDevice(d3d9_device_ex_.get(), + hr = device_manager_->ResetDevice(d3d9_device_ex_.Get(), dev_manager_reset_token_); RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); @@ -718,9 +718,9 @@ return false; // TODO(Hubbe): Don't try again if we tried and failed already. - if (video_processor_service_.get()) + if (video_processor_service_.Get()) return true; - HRESULT hr = DXVA2CreateVideoService(d3d9_device_ex_.get(), + HRESULT hr = DXVA2CreateVideoService(d3d9_device_ex_.Get(), IID_IDirectXVideoProcessorService, video_processor_service_.ReceiveVoid()); RETURN_ON_HR_FAILURE(hr, "DXVA2CreateVideoService failed", false); @@ -798,7 +798,7 @@ bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { // The device may exist if the last state was a config change. - if (d3d11_device_.get()) + if (d3d11_device_.Get()) return true; HRESULT hr = create_dxgi_device_manager_(&dx11_dev_manager_reset_token_, d3d11_device_manager_.Receive()); @@ -808,7 +808,7 @@ if (!angle_device_) copy_nv12_textures_ = false; if (share_nv12_textures_) { - RETURN_ON_FAILURE(angle_device_.get(), "Failed to get d3d11 device", false); + RETURN_ON_FAILURE(angle_device_.Get(), "Failed to get d3d11 device", false); using_angle_device_ = true; d3d11_device_ = angle_device_; @@ -883,11 +883,11 @@ // context are synchronized across threads. We have multiple threads // accessing the context, the media foundation decoder threads and the // decoder thread via the video format conversion transform. - hr = multi_threaded_.QueryFrom(d3d11_device_.get()); + hr = multi_threaded_.QueryFrom(d3d11_device_.Get()); RETURN_ON_HR_FAILURE(hr, "Failed to query ID3D10Multithread", false); multi_threaded_->SetMultithreadProtected(TRUE); - hr = d3d11_device_manager_->ResetDevice(d3d11_device_.get(), + hr = d3d11_device_manager_->ResetDevice(d3d11_device_.Get(), dx11_dev_manager_reset_token_); RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); @@ -933,7 +933,7 @@ reinterpret_cast<const uint8_t*>(shm.memory()), bitstream_buffer.size(), std::min<uint32_t>(bitstream_buffer.size(), input_stream_info_.cbSize), input_stream_info_.cbAlignment); - RETURN_AND_NOTIFY_ON_FAILURE(sample.get(), "Failed to create input sample", + RETURN_AND_NOTIFY_ON_FAILURE(sample.Get(), "Failed to create input sample", PLATFORM_FAILURE, ); RETURN_AND_NOTIFY_ON_HR_FAILURE( @@ -1304,7 +1304,7 @@ "GetMaxH264Resolution. QueryDeviceObjectFromANGLE"); device = gl::QueryD3D11DeviceObjectFromANGLE(); - if (!device.get()) + if (!device.Get()) return max_resolution; } @@ -1338,7 +1338,7 @@ // Legacy AMD drivers with UVD3 or earlier and some Intel GPU's crash while // creating surfaces larger than 1920 x 1088. - if (IsLegacyGPU(device.get())) + if (IsLegacyGPU(device.Get())) return max_resolution; // We look for the following resolutions in the driver. @@ -1374,7 +1374,7 @@ base::win::ScopedComPtr<ID3D11VideoDecoder> video_decoder; hr = video_device->CreateVideoDecoder(&desc, &config, video_decoder.Receive()); - if (!video_decoder.get()) + if (!video_decoder.Get()) return max_resolution; max_resolution = resolution_array[res_idx]; @@ -1523,12 +1523,12 @@ "Failed to initialize DX11 device and manager", PLATFORM_FAILURE, false); device_manager_to_use = - reinterpret_cast<ULONG_PTR>(d3d11_device_manager_.get()); + reinterpret_cast<ULONG_PTR>(d3d11_device_manager_.Get()); } else { RETURN_AND_NOTIFY_ON_FAILURE(CreateD3DDevManager(), "Failed to initialize D3D device and manager", PLATFORM_FAILURE, false); - device_manager_to_use = reinterpret_cast<ULONG_PTR>(device_manager_.get()); + device_manager_to_use = reinterpret_cast<ULONG_PTR>(device_manager_.Get()); } hr = decoder_->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, @@ -1663,7 +1663,7 @@ RETURN_ON_HR_FAILURE(hr, "Failed to set subtype", false); if (using_ms_vp9_mft_) { - hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, + hr = MFSetAttributeSize(media_type.Get(), MF_MT_FRAME_SIZE, config_.initial_expected_coded_size.width(), config_.initial_expected_coded_size.height()); RETURN_ON_HR_FAILURE(hr, "Failed to set attribute size", false); @@ -1679,14 +1679,14 @@ RETURN_ON_HR_FAILURE(hr, "Failed to set interlace mode", false); } - hr = decoder_->SetInputType(0, media_type.get(), 0); // No flags + hr = decoder_->SetInputType(0, media_type.Get(), 0); // No flags RETURN_ON_HR_FAILURE(hr, "Failed to set decoder input type", false); return true; } bool DXVAVideoDecodeAccelerator::SetDecoderOutputMediaType( const GUID& subtype) { - bool result = SetTransformOutputType(decoder_.get(), subtype, 0, 0); + bool result = SetTransformOutputType(decoder_.Get(), subtype, 0, 0); if (share_nv12_textures_) { base::win::ScopedComPtr<IMFAttributes> out_attributes; @@ -1846,7 +1846,7 @@ int width = 0; int height = 0; - if (!GetVideoFrameDimensions(sample.get(), &width, &height)) { + if (!GetVideoFrameDimensions(sample.Get(), &width, &height)) { RETURN_ON_FAILURE(false, "Failed to get D3D surface from output sample", false); } @@ -1888,7 +1888,7 @@ int width = 0; int height = 0; - if (!GetVideoFrameDimensions(pending_sample->output_sample.get(), &width, + if (!GetVideoFrameDimensions(pending_sample->output_sample.Get(), &width, &height)) { RETURN_AND_NOTIFY_ON_FAILURE( false, "Failed to get D3D surface from output sample", @@ -1926,7 +1926,7 @@ if (use_dx11_) { base::win::ScopedComPtr<IMFDXGIBuffer> dxgi_buffer; - hr = dxgi_buffer.QueryFrom(output_buffer.get()); + hr = dxgi_buffer.QueryFrom(output_buffer.Get()); RETURN_AND_NOTIFY_ON_HR_FAILURE( hr, "Failed to get DXGIBuffer from output sample", PLATFORM_FAILURE, ); @@ -1934,7 +1934,7 @@ __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(d3d11_texture.Receive())); } else { - hr = MFGetService(output_buffer.get(), MR_BUFFER_SERVICE, + hr = MFGetService(output_buffer.Get(), MR_BUFFER_SERVICE, IID_PPV_ARGS(surface.Receive())); } RETURN_AND_NOTIFY_ON_HR_FAILURE( @@ -1942,7 +1942,7 @@ RETURN_AND_NOTIFY_ON_FAILURE( index->second->CopyOutputSampleDataToPictureBuffer( - this, surface.get(), d3d11_texture.get(), + this, surface.Get(), d3d11_texture.Get(), pending_sample->input_buffer_id), "Failed to copy output sample", PLATFORM_FAILURE, ); } @@ -2214,7 +2214,7 @@ // reinitialize the decoder to ensure that the stream decodes correctly. bool config_changed = false; - HRESULT hr = CheckConfigChanged(sample.get(), &config_changed); + HRESULT hr = CheckConfigChanged(sample.Get(), &config_changed); RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to check video stream config", PLATFORM_FAILURE, ); @@ -2237,7 +2237,7 @@ inputs_before_decode_++; { ScopedExceptionCatcher catcher(using_ms_vp9_mft_); - hr = decoder_->ProcessInput(0, sample.get(), 0); + hr = decoder_->ProcessInput(0, sample.Get(), 0); } // As per msdn if the decoder returns MF_E_NOTACCEPTING then it means that it // has enough data to produce one or more output samples. In this case the @@ -2258,7 +2258,7 @@ (state == kStopped || state == kNormal || state == kFlushing), "Failed to process output. Unexpected decoder state: " << state, PLATFORM_FAILURE, ); - hr = decoder_->ProcessInput(0, sample.get(), 0); + hr = decoder_->ProcessInput(0, sample.Get(), 0); } // If we continue to get the MF_E_NOTACCEPTING error we do the following:- // 1. Add the input sample to the pending queue. @@ -2645,7 +2645,7 @@ DCHECK(use_dx11_); DCHECK(!!input_sample); - DCHECK(d3d11_processor_.get()); + DCHECK(d3d11_processor_.Get()); if (dest_keyed_mutex) { HRESULT hr = @@ -2661,7 +2661,7 @@ PLATFORM_FAILURE, ); base::win::ScopedComPtr<IMFDXGIBuffer> dxgi_buffer; - hr = dxgi_buffer.QueryFrom(output_buffer.get()); + hr = dxgi_buffer.QueryFrom(output_buffer.Get()); RETURN_AND_NOTIFY_ON_HR_FAILURE( hr, "Failed to get DXGIBuffer from output sample", PLATFORM_FAILURE, ); UINT index = 0; @@ -2679,7 +2679,7 @@ output_view_desc.Texture2D.MipSlice = 0; base::win::ScopedComPtr<ID3D11VideoProcessorOutputView> output_view; hr = video_device_->CreateVideoProcessorOutputView( - dest_texture, enumerator_.get(), &output_view_desc, + dest_texture, enumerator_.Get(), &output_view_desc, output_view.Receive()); RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get output view", PLATFORM_FAILURE, ); @@ -2690,17 +2690,17 @@ input_view_desc.Texture2D.MipSlice = 0; base::win::ScopedComPtr<ID3D11VideoProcessorInputView> input_view; hr = video_device_->CreateVideoProcessorInputView( - dx11_decoding_texture.get(), enumerator_.get(), &input_view_desc, + dx11_decoding_texture.Get(), enumerator_.Get(), &input_view_desc, input_view.Receive()); RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to get input view", PLATFORM_FAILURE, ); D3D11_VIDEO_PROCESSOR_STREAM streams = {0}; streams.Enable = TRUE; - streams.pInputSurface = input_view.get(); + streams.pInputSurface = input_view.Get(); - hr = video_context_->VideoProcessorBlt(d3d11_processor_.get(), - output_view.get(), 0, 1, &streams); + hr = video_context_->VideoProcessorBlt(d3d11_processor_.Get(), + output_view.Get(), 0, 1, &streams); RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "VideoProcessBlit failed", PLATFORM_FAILURE, ); @@ -2716,7 +2716,7 @@ nullptr, nullptr, picture_buffer_id, input_buffer_id)); } else { d3d11_device_context_->Flush(); - d3d11_device_context_->End(d3d11_query_.get()); + d3d11_device_context_->End(d3d11_query_.Get()); decoder_thread_task_runner_->PostDelayedTask( FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder, @@ -2753,7 +2753,7 @@ HRESULT hr = E_FAIL; if (use_dx11_) { BOOL query_data = 0; - hr = d3d11_device_context_->GetData(d3d11_query_.get(), &query_data, + hr = d3d11_device_context_->GetData(d3d11_query_.Get(), &query_data, sizeof(BOOL), 0); if (FAILED(hr)) DCHECK(false); @@ -2803,14 +2803,14 @@ RETURN_ON_HR_FAILURE(hr, "Failed to enumerate video processors", false); // TODO(Hubbe): Find correct index - hr = video_device_->CreateVideoProcessor(enumerator_.get(), 0, + hr = video_device_->CreateVideoProcessor(enumerator_.Get(), 0, d3d11_processor_.Receive()); RETURN_ON_HR_FAILURE(hr, "Failed to create video processor.", false); processor_width_ = width; processor_height_ = height; video_context_->VideoProcessorSetStreamAutoProcessingMode( - d3d11_processor_.get(), 0, false); + d3d11_processor_.Get(), 0, false); } if (copy_nv12_textures_) { @@ -2820,10 +2820,10 @@ d3d11_color_space.RGB_Range = 1; d3d11_color_space.Nominal_Range = D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_0_255; - video_context_->VideoProcessorSetOutputColorSpace(d3d11_processor_.get(), + video_context_->VideoProcessorSetOutputColorSpace(d3d11_processor_.Get(), &d3d11_color_space); - video_context_->VideoProcessorSetStreamColorSpace(d3d11_processor_.get(), 0, + video_context_->VideoProcessorSetStreamColorSpace(d3d11_processor_.Get(), 0, &d3d11_color_space); dx11_converter_output_color_space_ = color_space; } else { @@ -2852,10 +2852,10 @@ gfx::ColorSpace::MatrixID::BT709, gfx::ColorSpace::RangeID::LIMITED)) { video_context1->VideoProcessorSetStreamColorSpace1( - d3d11_processor_.get(), 0, + d3d11_processor_.Get(), 0, DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020); video_context1->VideoProcessorSetOutputColorSpace1( - d3d11_processor_.get(), + d3d11_processor_.Get(), DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020); dx11_converter_output_color_space_ = color_space.GetAsFullRangeRGB(); } else { @@ -2867,21 +2867,21 @@ << gfx::ColorSpaceWin::GetDXGIColorSpace( dx11_converter_output_color_space_); video_context1->VideoProcessorSetStreamColorSpace1( - d3d11_processor_.get(), 0, + d3d11_processor_.Get(), 0, gfx::ColorSpaceWin::GetDXGIColorSpace(color_space)); video_context1->VideoProcessorSetOutputColorSpace1( - d3d11_processor_.get(), gfx::ColorSpaceWin::GetDXGIColorSpace( + d3d11_processor_.Get(), gfx::ColorSpaceWin::GetDXGIColorSpace( dx11_converter_output_color_space_)); } } else { D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = gfx::ColorSpaceWin::GetD3D11ColorSpace(color_space); video_context_->VideoProcessorSetStreamColorSpace( - d3d11_processor_.get(), 0, &d3d11_color_space); + d3d11_processor_.Get(), 0, &d3d11_color_space); d3d11_color_space = gfx::ColorSpaceWin::GetD3D11ColorSpace( dx11_converter_output_color_space_); video_context_->VideoProcessorSetOutputColorSpace( - d3d11_processor_.get(), &d3d11_color_space); + d3d11_processor_.Get(), &d3d11_color_space); } } } @@ -2898,7 +2898,7 @@ if (use_dx11_) { base::win::ScopedComPtr<IMFDXGIBuffer> dxgi_buffer; base::win::ScopedComPtr<ID3D11Texture2D> d3d11_texture; - hr = dxgi_buffer.QueryFrom(output_buffer.get()); + hr = dxgi_buffer.QueryFrom(output_buffer.Get()); RETURN_ON_HR_FAILURE(hr, "Failed to get DXGIBuffer from output sample", false); hr = dxgi_buffer->GetResource( @@ -2913,7 +2913,7 @@ output_array_size_ = d3d11_texture_desc.ArraySize; } else { base::win::ScopedComPtr<IDirect3DSurface9> surface; - hr = MFGetService(output_buffer.get(), MR_BUFFER_SERVICE, + hr = MFGetService(output_buffer.Get(), MR_BUFFER_SERVICE, IID_PPV_ARGS(surface.Receive())); RETURN_ON_HR_FAILURE(hr, "Failed to get D3D surface from output sample", false); @@ -2942,11 +2942,11 @@ if (out_subtype == output_type) { if (width && height) { - hr = MFSetAttributeSize(media_type.get(), MF_MT_FRAME_SIZE, width, + hr = MFSetAttributeSize(media_type.Get(), MF_MT_FRAME_SIZE, width, height); RETURN_ON_HR_FAILURE(hr, "Failed to set media type attributes", false); } - hr = transform->SetOutputType(0, media_type.get(), 0); // No flags + hr = transform->SetOutputType(0, media_type.Get(), 0); // No flags RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false); return true; } @@ -2964,7 +2964,7 @@ HRESULT hr = sample->GetBufferByIndex(0, buffer.Receive()); RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from input sample", hr); - mf::MediaBufferScopedPointer scoped_media_buffer(buffer.get()); + mf::MediaBufferScopedPointer scoped_media_buffer(buffer.Get()); if (!config_change_detector_->DetectConfig( scoped_media_buffer.get(), scoped_media_buffer.current_length())) {
diff --git a/media/gpu/media_foundation_video_encode_accelerator_win.cc b/media/gpu/media_foundation_video_encode_accelerator_win.cc index 6723aa7..0ad8ba0 100644 --- a/media/gpu/media_foundation_video_encode_accelerator_win.cc +++ b/media/gpu/media_foundation_video_encode_accelerator_win.cc
@@ -357,7 +357,7 @@ DVLOG(3) << "HW encoder(s) found: " << count; hr = encoder_.CreateInstance(CLSIDs[0]); RETURN_ON_HR_FAILURE(hr, "Couldn't activate hardware encoder", false); - RETURN_ON_FAILURE((encoder_.get() != nullptr), + RETURN_ON_FAILURE((encoder_.Get() != nullptr), "No HW encoder instance created", false); return true; } @@ -399,10 +399,10 @@ RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); hr = imf_output_media_type_->SetUINT32(MF_MT_AVG_BITRATE, target_bitrate_); RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false); - hr = MFSetAttributeRatio(imf_output_media_type_.get(), MF_MT_FRAME_RATE, + hr = MFSetAttributeRatio(imf_output_media_type_.Get(), MF_MT_FRAME_RATE, frame_rate_, 1); RETURN_ON_HR_FAILURE(hr, "Couldn't set frame rate", false); - hr = MFSetAttributeSize(imf_output_media_type_.get(), MF_MT_FRAME_SIZE, + hr = MFSetAttributeSize(imf_output_media_type_.Get(), MF_MT_FRAME_SIZE, input_visible_size_.width(), input_visible_size_.height()); RETURN_ON_HR_FAILURE(hr, "Couldn't set frame size", false); @@ -412,7 +412,7 @@ hr = imf_output_media_type_->SetUINT32(MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_Base); RETURN_ON_HR_FAILURE(hr, "Couldn't set codec profile", false); - hr = encoder_->SetOutputType(output_stream_id_, imf_output_media_type_.get(), + hr = encoder_->SetOutputType(output_stream_id_, imf_output_media_type_.Get(), 0); RETURN_ON_HR_FAILURE(hr, "Couldn't set output media type", false); @@ -423,17 +423,17 @@ RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false); hr = imf_input_media_type_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_YV12); RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false); - hr = MFSetAttributeRatio(imf_input_media_type_.get(), MF_MT_FRAME_RATE, + hr = MFSetAttributeRatio(imf_input_media_type_.Get(), MF_MT_FRAME_RATE, frame_rate_, 1); RETURN_ON_HR_FAILURE(hr, "Couldn't set frame rate", false); - hr = MFSetAttributeSize(imf_input_media_type_.get(), MF_MT_FRAME_SIZE, + hr = MFSetAttributeSize(imf_input_media_type_.Get(), MF_MT_FRAME_SIZE, input_visible_size_.width(), input_visible_size_.height()); RETURN_ON_HR_FAILURE(hr, "Couldn't set frame size", false); hr = imf_input_media_type_->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); RETURN_ON_HR_FAILURE(hr, "Couldn't set interlace mode", false); - hr = encoder_->SetInputType(input_stream_id_, imf_input_media_type_.get(), 0); + hr = encoder_->SetInputType(input_stream_id_, imf_input_media_type_.Get(), 0); RETURN_ON_HR_FAILURE(hr, "Couldn't set input media type", false); return SUCCEEDED(hr); @@ -441,7 +441,7 @@ bool MediaFoundationVideoEncodeAccelerator::SetEncoderModes() { DCHECK(main_client_task_runner_->BelongsToCurrentThread()); - RETURN_ON_FAILURE((encoder_.get() != nullptr), + RETURN_ON_FAILURE((encoder_.Get() != nullptr), "No HW encoder instance created", false); HRESULT hr = encoder_.QueryInterface(codec_api_.Receive()); @@ -470,17 +470,17 @@ DCHECK(encoder_); HRESULT hr = - MFSetAttributeSize(imf_output_media_type_.get(), MF_MT_FRAME_SIZE, + MFSetAttributeSize(imf_output_media_type_.Get(), MF_MT_FRAME_SIZE, resolution.width(), resolution.height()); RETURN_ON_HR_FAILURE(hr, "Couldn't set frame size", false); - hr = encoder_->SetOutputType(output_stream_id_, imf_output_media_type_.get(), + hr = encoder_->SetOutputType(output_stream_id_, imf_output_media_type_.Get(), 0); RETURN_ON_HR_FAILURE(hr, "Couldn't set output media type", false); - hr = MFSetAttributeSize(imf_input_media_type_.get(), MF_MT_FRAME_SIZE, + hr = MFSetAttributeSize(imf_input_media_type_.Get(), MF_MT_FRAME_SIZE, resolution.width(), resolution.height()); RETURN_ON_HR_FAILURE(hr, "Couldn't set frame size", false); - hr = encoder_->SetInputType(input_stream_id_, imf_input_media_type_.get(), 0); + hr = encoder_->SetInputType(input_stream_id_, imf_input_media_type_.Get(), 0); RETURN_ON_HR_FAILURE(hr, "Couldn't set input media type", false); return true; @@ -503,7 +503,7 @@ input_sample_->GetBufferByIndex(0, input_buffer.Receive()); { - MediaBufferScopedPointer scoped_buffer(input_buffer.get()); + MediaBufferScopedPointer scoped_buffer(input_buffer.Get()); DCHECK(scoped_buffer.get()); libyuv::I420Copy(frame->visible_data(VideoFrame::kYPlane), frame->stride(VideoFrame::kYPlane), @@ -530,14 +530,14 @@ // Release frame after input is copied. frame = nullptr; - hr = encoder_->ProcessInput(input_stream_id_, input_sample_.get(), 0); + hr = encoder_->ProcessInput(input_stream_id_, input_sample_.Get(), 0); // According to MSDN, if encoder returns MF_E_NOTACCEPTING, we need to try // processing the output. This error indicates that encoder does not accept // any more input data. if (hr == MF_E_NOTACCEPTING) { DVLOG(3) << "MF_E_NOTACCEPTING"; ProcessOutput(); - hr = encoder_->ProcessInput(input_stream_id_, input_sample_.get(), 0); + hr = encoder_->ProcessInput(input_stream_id_, input_sample_.Get(), 0); if (!SUCCEEDED(hr)) { NotifyError(kPlatformFailureError); RETURN_ON_HR_FAILURE(hr, "Couldn't encode", ); @@ -567,7 +567,7 @@ output_data_buffer.dwStreamID = 0; output_data_buffer.dwStatus = 0; output_data_buffer.pEvents = NULL; - output_data_buffer.pSample = output_sample_.get(); + output_data_buffer.pSample = output_sample_.Get(); DWORD status = 0; hr = encoder_->ProcessOutput(output_stream_id_, 1, &output_data_buffer, &status); @@ -594,7 +594,7 @@ } const bool keyframe = MFGetAttributeUINT32( - output_sample_.get(), MFSampleExtension_CleanPoint, false); + output_sample_.Get(), MFSampleExtension_CleanPoint, false); DVLOG(3) << "We HAVE encoded data with size:" << size << " keyframe " << keyframe; @@ -604,7 +604,7 @@ std::unique_ptr<EncodeOutput> encode_output( new EncodeOutput(size, keyframe, timestamp)); { - MediaBufferScopedPointer scoped_buffer(output_buffer.get()); + MediaBufferScopedPointer scoped_buffer(output_buffer.Get()); memcpy(encode_output->memory(), scoped_buffer.get(), size); } encoder_output_queue_.push_back(std::move(encode_output)); @@ -616,7 +616,7 @@ bitstream_buffer_queue_.pop_front(); { - MediaBufferScopedPointer scoped_buffer(output_buffer.get()); + MediaBufferScopedPointer scoped_buffer(output_buffer.Get()); memcpy(buffer_ref->shm->memory(), scoped_buffer.get(), size); }
diff --git a/media/midi/midi_manager_winrt.cc b/media/midi/midi_manager_winrt.cc index 919e11b..14f313d2 100644 --- a/media/midi/midi_manager_winrt.cc +++ b/media/midi/midi_manager_winrt.cc
@@ -807,7 +807,7 @@ } uint8_t* p_buffer_data = nullptr; - hr = GetPointerToBufferData(buffer.get(), &p_buffer_data); + hr = GetPointerToBufferData(buffer.Get(), &p_buffer_data); if (FAILED(hr)) return hr; @@ -1026,13 +1026,13 @@ } uint8_t* p_buffer_data = nullptr; - hr = GetPointerToBufferData(buffer.get(), &p_buffer_data); + hr = GetPointerToBufferData(buffer.Get(), &p_buffer_data); if (FAILED(hr)) return; std::copy(data.begin(), data.end(), p_buffer_data); - hr = port->handle->SendBuffer(buffer.get()); + hr = port->handle->SendBuffer(buffer.Get()); if (FAILED(hr)) { VLOG(1) << "SendBuffer failed: " << PrintHr(hr); return;
diff --git a/mojo/public/cpp/bindings/tests/pickle_unittest.cc b/mojo/public/cpp/bindings/tests/pickle_unittest.cc index a5947ce9..25ee5d0 100644 --- a/mojo/public/cpp/bindings/tests/pickle_unittest.cc +++ b/mojo/public/cpp/bindings/tests/pickle_unittest.cc
@@ -184,7 +184,22 @@ } // namespace -TEST_F(PickleTest, ChromiumProxyToChromiumService) { +#if _MSC_FULL_VER == 191025017 +// Disabled due to this VS 2017 RTM code-gen bug: +// https://developercommunity.visualstudio.com/content/problem/40904/bad-code-gen-in-chromes-mojo-public-bindings-unitt.html +#define MAYBE_ChromiumProxyToChromiumService \ + DISABLED_ChromiumProxyToChromiumService +#define MAYBE_ChromiumProxyToBlinkService DISABLED_ChromiumProxyToBlinkService +#define MAYBE_BlinkProxyToBlinkService DISABLED_BlinkProxyToBlinkService +#define MAYBE_BlinkProxyToChromiumService DISABLED_BlinkProxyToChromiumService +#else +#define MAYBE_ChromiumProxyToChromiumService ChromiumProxyToChromiumService +#define MAYBE_ChromiumProxyToBlinkService ChromiumProxyToBlinkService +#define MAYBE_BlinkProxyToBlinkService BlinkProxyToBlinkService +#define MAYBE_BlinkProxyToChromiumService BlinkProxyToChromiumService +#endif + +TEST_F(PickleTest, MAYBE_ChromiumProxyToChromiumService) { auto chromium_proxy = ConnectToChromiumService(); { base::RunLoop loop; @@ -210,7 +225,7 @@ } } -TEST_F(PickleTest, ChromiumProxyToBlinkService) { +TEST_F(PickleTest, MAYBE_ChromiumProxyToBlinkService) { auto chromium_proxy = ConnectToBlinkService<PicklePasser>(); { base::RunLoop loop; @@ -258,7 +273,7 @@ } } -TEST_F(PickleTest, BlinkProxyToBlinkService) { +TEST_F(PickleTest, MAYBE_BlinkProxyToBlinkService) { auto blink_proxy = ConnectToBlinkService(); { base::RunLoop loop; @@ -277,7 +292,7 @@ } } -TEST_F(PickleTest, BlinkProxyToChromiumService) { +TEST_F(PickleTest, MAYBE_BlinkProxyToChromiumService) { auto blink_proxy = ConnectToChromiumService<blink::PicklePasser>(); { base::RunLoop loop;
diff --git a/net/BUILD.gn b/net/BUILD.gn index 28477ee..0c33989d 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -788,8 +788,6 @@ "http/bidirectional_stream_request_info.h", "http/des.cc", "http/des.h", - "http/disk_cache_based_quic_server_info.cc", - "http/disk_cache_based_quic_server_info.h", "http/failing_http_transaction_factory.cc", "http/failing_http_transaction_factory.h", "http/http_auth.cc", @@ -1267,8 +1265,6 @@ "quic/core/quic_data_writer.h", "quic/core/quic_error_codes.cc", "quic/core/quic_error_codes.h", - "quic/core/quic_flags.cc", - "quic/core/quic_flags.h", "quic/core/quic_flags_list.h", "quic/core/quic_flow_controller.cc", "quic/core/quic_flow_controller.h", @@ -1343,6 +1339,7 @@ "quic/platform/api/quic_estimate_memory_usage.h", "quic/platform/api/quic_export.h", "quic/platform/api/quic_flag_utils.h", + "quic/platform/api/quic_flags.h", "quic/platform/api/quic_hostname_utils.cc", "quic/platform/api/quic_hostname_utils.h", "quic/platform/api/quic_ip_address.cc", @@ -1374,6 +1371,8 @@ "quic/platform/impl/quic_estimate_memory_usage_impl.h", "quic/platform/impl/quic_export_impl.h", "quic/platform/impl/quic_flag_utils_impl.h", + "quic/platform/impl/quic_flags_impl.cc", + "quic/platform/impl/quic_flags_impl.h", "quic/platform/impl/quic_hostname_utils_impl.cc", "quic/platform/impl/quic_hostname_utils_impl.h", "quic/platform/impl/quic_ip_address_impl.cc", @@ -4324,7 +4323,6 @@ "ftp/ftp_util_unittest.cc", "http/bidirectional_stream_unittest.cc", "http/des_unittest.cc", - "http/disk_cache_based_quic_server_info_unittest.cc", "http/http_auth_cache_unittest.cc", "http/http_auth_challenge_tokenizer_unittest.cc", "http/http_auth_controller_unittest.cc",
diff --git a/net/http/disk_cache_based_quic_server_info.cc b/net/http/disk_cache_based_quic_server_info.cc deleted file mode 100644 index b149fc9..0000000 --- a/net/http/disk_cache_based_quic_server_info.cc +++ /dev/null
@@ -1,450 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/http/disk_cache_based_quic_server_info.h" - -#include "base/bind.h" -#include "base/callback.h" -#include "base/callback_helpers.h" -#include "base/logging.h" -#include "base/metrics/histogram_macros.h" -#include "base/stl_util.h" -#include "base/trace_event/memory_usage_estimator.h" -#include "net/base/completion_callback.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "net/http/http_cache.h" -#include "net/http/http_network_session.h" -#include "net/quic/core/quic_server_id.h" - -namespace net { - -// Some APIs inside disk_cache take a handle that the caller must keep alive -// until the API has finished its asynchronous execution. -// -// Unfortunately, DiskCacheBasedQuicServerInfo may be deleted before the -// operation completes causing a use-after-free. -// -// This data shim struct is meant to provide a location for the disk_cache -// APIs to write into even if the originating DiskCacheBasedQuicServerInfo -// object has been deleted. The lifetime for instances of this struct -// should be bound to the CompletionCallback that is passed to the disk_cache -// API. We do this by binding an instance of this struct to an unused -// parameter for OnIOComplete() using base::Owned(). -// -// This is a hack. A better fix is to make it so that the disk_cache APIs -// take a Callback to a mutator for setting the output value rather than -// writing into a raw handle. Then the caller can just pass in a Callback -// bound to WeakPtr for itself. This callback would correctly "no-op" itself -// when the DiskCacheBasedQuicServerInfo object is deleted. -// -// TODO(ajwong): Change disk_cache's API to return results via Callback. -struct DiskCacheBasedQuicServerInfo::CacheOperationDataShim { - CacheOperationDataShim() : backend(NULL), entry(NULL) {} - - disk_cache::Backend* backend; - disk_cache::Entry* entry; -}; - -DiskCacheBasedQuicServerInfo::DiskCacheBasedQuicServerInfo( - const QuicServerId& server_id, - HttpCache* http_cache) - : QuicServerInfo(server_id), - data_shim_(new CacheOperationDataShim()), - state_(GET_BACKEND), - ready_(false), - found_entry_(false), - server_id_(server_id), - http_cache_(http_cache), - backend_(NULL), - entry_(NULL), - last_failure_(NO_FAILURE), - weak_factory_(this) { - io_callback_ = - base::Bind(&DiskCacheBasedQuicServerInfo::OnIOComplete, - weak_factory_.GetWeakPtr(), - base::Owned(data_shim_)); // Ownership assigned. -} - -DiskCacheBasedQuicServerInfo::~DiskCacheBasedQuicServerInfo() { - DCHECK(wait_for_ready_callback_.is_null()); - if (entry_) - entry_->Close(); -} - -void DiskCacheBasedQuicServerInfo::Start() { - DCHECK(CalledOnValidThread()); - DCHECK_EQ(GET_BACKEND, state_); - DCHECK_EQ(last_failure_, NO_FAILURE); - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_START); - load_start_time_ = base::TimeTicks::Now(); - DoLoop(OK); -} - -int DiskCacheBasedQuicServerInfo::WaitForDataReady( - const CompletionCallback& callback) { - DCHECK(CalledOnValidThread()); - DCHECK_NE(GET_BACKEND, state_); - wait_for_data_start_time_ = base::TimeTicks::Now(); - - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY); - if (ready_) { - wait_for_data_end_time_ = base::TimeTicks::Now(); - RecordLastFailure(); - return OK; - } - - if (!callback.is_null()) { - // Prevent a new callback for WaitForDataReady overwriting an existing - // pending callback (|wait_for_ready_callback_|). - if (!wait_for_ready_callback_.is_null()) { - RecordQuicServerInfoFailure(WAIT_FOR_DATA_READY_INVALID_ARGUMENT_FAILURE); - return ERR_INVALID_ARGUMENT; - } - wait_for_ready_callback_ = callback; - } - - return ERR_IO_PENDING; -} - -void DiskCacheBasedQuicServerInfo::ResetWaitForDataReadyCallback() { - DCHECK(CalledOnValidThread()); - wait_for_ready_callback_.Reset(); -} - -void DiskCacheBasedQuicServerInfo::CancelWaitForDataReadyCallback() { - DCHECK(CalledOnValidThread()); - - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY_CANCEL); - if (!wait_for_ready_callback_.is_null()) { - RecordLastFailure(); - wait_for_ready_callback_.Reset(); - } -} - -bool DiskCacheBasedQuicServerInfo::IsDataReady() { - return ready_; -} - -bool DiskCacheBasedQuicServerInfo::IsReadyToPersist() { - // The data can be persisted if it has been loaded from the disk cache - // and there are no pending writes. - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_READY_TO_PERSIST); - if (ready_ && new_data_.empty()) - return true; - RecordQuicServerInfoFailure(READY_TO_PERSIST_FAILURE); - return false; -} - -void DiskCacheBasedQuicServerInfo::Persist() { - DCHECK(CalledOnValidThread()); - if (!IsReadyToPersist()) { - // Handle updates while a write is pending or if we haven't loaded from disk - // cache. Save the data to be written into a temporary buffer and then - // persist that data when we are ready to persist. - pending_write_data_ = Serialize(); - return; - } - PersistInternal(); -} - -void DiskCacheBasedQuicServerInfo::PersistInternal() { - DCHECK(CalledOnValidThread()); - DCHECK_NE(GET_BACKEND, state_); - DCHECK(new_data_.empty()); - CHECK(ready_); - DCHECK(wait_for_ready_callback_.is_null()); - - if (pending_write_data_.empty()) { - new_data_ = Serialize(); - } else { - new_data_ = pending_write_data_; - base::STLClearObject(&pending_write_data_); - } - - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PERSIST); - if (!backend_) { - RecordQuicServerInfoFailure(PERSIST_NO_BACKEND_FAILURE); - return; - } - - state_ = CREATE_OR_OPEN; - DoLoop(OK); -} - -void DiskCacheBasedQuicServerInfo::OnExternalCacheHit() { - DCHECK(CalledOnValidThread()); - DCHECK_NE(GET_BACKEND, state_); - - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_EXTERNAL_CACHE_HIT); - if (!backend_) { - RecordQuicServerInfoFailure(PERSIST_NO_BACKEND_FAILURE); - return; - } - - backend_->OnExternalCacheHit(key()); -} - -size_t DiskCacheBasedQuicServerInfo::EstimateMemoryUsage() const { - return base::trace_event::EstimateMemoryUsage(new_data_) + - base::trace_event::EstimateMemoryUsage(pending_write_data_) + - base::trace_event::EstimateMemoryUsage(server_id_) + - (read_buffer_ == nullptr ? 0 : read_buffer_->size()) + - (write_buffer_ == nullptr ? 0 : write_buffer_->size()) + - base::trace_event::EstimateMemoryUsage(data_); -} - -std::string DiskCacheBasedQuicServerInfo::key() const { - return "quicserverinfo:" + server_id_.ToString(); -} - -void DiskCacheBasedQuicServerInfo::OnIOComplete(CacheOperationDataShim* unused, - int rv) { - DCHECK_NE(NONE, state_); - rv = DoLoop(rv); - if (rv == ERR_IO_PENDING) - return; - - base::WeakPtr<DiskCacheBasedQuicServerInfo> weak_this = - weak_factory_.GetWeakPtr(); - - if (!wait_for_ready_callback_.is_null()) { - wait_for_data_end_time_ = base::TimeTicks::Now(); - RecordLastFailure(); - base::ResetAndReturn(&wait_for_ready_callback_).Run(rv); - } - // |wait_for_ready_callback_| could delete the object if there is an error. - // Check if |weak_this| still exists before accessing it. - if (weak_this.get() && ready_ && !pending_write_data_.empty()) { - DCHECK_EQ(NONE, state_); - PersistInternal(); - } -} - -int DiskCacheBasedQuicServerInfo::DoLoop(int rv) { - do { - switch (state_) { - case GET_BACKEND: - rv = DoGetBackend(); - break; - case GET_BACKEND_COMPLETE: - rv = DoGetBackendComplete(rv); - break; - case OPEN: - rv = DoOpen(); - break; - case OPEN_COMPLETE: - rv = DoOpenComplete(rv); - break; - case READ: - rv = DoRead(); - break; - case READ_COMPLETE: - rv = DoReadComplete(rv); - break; - case WAIT_FOR_DATA_READY_DONE: - rv = DoWaitForDataReadyDone(); - break; - case CREATE_OR_OPEN: - rv = DoCreateOrOpen(); - break; - case CREATE_OR_OPEN_COMPLETE: - rv = DoCreateOrOpenComplete(rv); - break; - case WRITE: - rv = DoWrite(); - break; - case WRITE_COMPLETE: - rv = DoWriteComplete(rv); - break; - case SET_DONE: - rv = DoSetDone(); - break; - default: - rv = OK; - NOTREACHED(); - } - } while (rv != ERR_IO_PENDING && state_ != NONE); - - return rv; -} - -int DiskCacheBasedQuicServerInfo::DoGetBackendComplete(int rv) { - if (rv == OK) { - backend_ = data_shim_->backend; - state_ = OPEN; - } else { - RecordQuicServerInfoFailure(GET_BACKEND_FAILURE); - state_ = WAIT_FOR_DATA_READY_DONE; - } - return OK; -} - -int DiskCacheBasedQuicServerInfo::DoOpenComplete(int rv) { - if (rv == OK) { - entry_ = data_shim_->entry; - state_ = READ; - found_entry_ = true; - } else { - RecordQuicServerInfoFailure(OPEN_FAILURE); - state_ = WAIT_FOR_DATA_READY_DONE; - } - - return OK; -} - -int DiskCacheBasedQuicServerInfo::DoReadComplete(int rv) { - if (rv > 0) - data_.assign(read_buffer_->data(), rv); - else if (rv < 0) - RecordQuicServerInfoFailure(READ_FAILURE); - - read_buffer_ = nullptr; - state_ = WAIT_FOR_DATA_READY_DONE; - return OK; -} - -int DiskCacheBasedQuicServerInfo::DoWriteComplete(int rv) { - if (rv < 0) - RecordQuicServerInfoFailure(WRITE_FAILURE); - write_buffer_ = nullptr; - state_ = SET_DONE; - return OK; -} - -int DiskCacheBasedQuicServerInfo::DoCreateOrOpenComplete(int rv) { - if (rv != OK) { - RecordQuicServerInfoFailure(CREATE_OR_OPEN_FAILURE); - state_ = SET_DONE; - } else { - if (!entry_) { - entry_ = data_shim_->entry; - found_entry_ = true; - } - DCHECK(entry_); - state_ = WRITE; - } - return OK; -} - -int DiskCacheBasedQuicServerInfo::DoGetBackend() { - state_ = GET_BACKEND_COMPLETE; - return http_cache_->GetBackend(&data_shim_->backend, io_callback_); -} - -int DiskCacheBasedQuicServerInfo::DoOpen() { - state_ = OPEN_COMPLETE; - return backend_->OpenEntry(key(), &data_shim_->entry, io_callback_); -} - -int DiskCacheBasedQuicServerInfo::DoRead() { - const int32_t size = entry_->GetDataSize(0 /* index */); - if (!size) { - state_ = WAIT_FOR_DATA_READY_DONE; - return OK; - } - - read_buffer_ = new IOBufferWithSize(size); - state_ = READ_COMPLETE; - return entry_->ReadData( - 0 /* index */, 0 /* offset */, read_buffer_.get(), size, io_callback_); -} - -int DiskCacheBasedQuicServerInfo::DoWrite() { - write_buffer_ = new IOBufferWithSize(new_data_.size()); - memcpy(write_buffer_->data(), new_data_.data(), new_data_.size()); - state_ = WRITE_COMPLETE; - - return entry_->WriteData(0 /* index */, - 0 /* offset */, - write_buffer_.get(), - new_data_.size(), - io_callback_, - true /* truncate */); -} - -int DiskCacheBasedQuicServerInfo::DoCreateOrOpen() { - state_ = CREATE_OR_OPEN_COMPLETE; - if (entry_) - return OK; - - if (found_entry_) { - return backend_->OpenEntry(key(), &data_shim_->entry, io_callback_); - } - - return backend_->CreateEntry(key(), &data_shim_->entry, io_callback_); -} - -int DiskCacheBasedQuicServerInfo::DoWaitForDataReadyDone() { - DCHECK(!ready_); - state_ = NONE; - ready_ = true; - // We close the entry because, if we shutdown before ::Persist is called, - // then we might leak a cache reference, which causes a DCHECK on shutdown. - if (entry_) - entry_->Close(); - entry_ = NULL; - - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PARSE); - if (!Parse(data_)) { - if (data_.empty()) - RecordQuicServerInfoFailure(PARSE_NO_DATA_FAILURE); - else - RecordQuicServerInfoFailure(PARSE_FAILURE); - } - - UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheLoadTime", - base::TimeTicks::Now() - load_start_time_); - return OK; -} - -int DiskCacheBasedQuicServerInfo::DoSetDone() { - if (entry_) - entry_->Close(); - entry_ = NULL; - base::STLClearObject(&new_data_); - state_ = NONE; - return OK; -} - -void DiskCacheBasedQuicServerInfo::RecordQuicServerInfoStatus( - QuicServerInfoAPICall call) { - if (!backend_) { - UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.NoBackend", call, - QUIC_SERVER_INFO_NUM_OF_API_CALLS); - } else if (backend_->GetCacheType() == MEMORY_CACHE) { - UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.MemoryCache", call, - QUIC_SERVER_INFO_NUM_OF_API_CALLS); - } else { - UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.DiskCache", call, - QUIC_SERVER_INFO_NUM_OF_API_CALLS); - } -} - -void DiskCacheBasedQuicServerInfo::RecordLastFailure() { - if (last_failure_ != NO_FAILURE) { - UMA_HISTOGRAM_ENUMERATION( - "Net.QuicDiskCache.FailureReason.WaitForDataReady", - last_failure_, NUM_OF_FAILURES); - } - last_failure_ = NO_FAILURE; -} - -void DiskCacheBasedQuicServerInfo::RecordQuicServerInfoFailure( - FailureReason failure) { - last_failure_ = failure; - - if (!backend_) { - UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.NoBackend", - failure, NUM_OF_FAILURES); - } else if (backend_->GetCacheType() == MEMORY_CACHE) { - UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.MemoryCache", - failure, NUM_OF_FAILURES); - } else { - UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.DiskCache", - failure, NUM_OF_FAILURES); - } -} - -} // namespace net
diff --git a/net/http/disk_cache_based_quic_server_info.h b/net/http/disk_cache_based_quic_server_info.h deleted file mode 100644 index 2396f8c..0000000 --- a/net/http/disk_cache_based_quic_server_info.h +++ /dev/null
@@ -1,135 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_HTTP_DISK_CACHE_BASED_QUIC_SERVER_INFO_H_ -#define NET_HTTP_DISK_CACHE_BASED_QUIC_SERVER_INFO_H_ - -#include <string> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/non_thread_safe.h" -#include "base/time/time.h" -#include "net/base/completion_callback.h" -#include "net/base/net_export.h" -#include "net/disk_cache/disk_cache.h" -#include "net/quic/chromium/quic_server_info.h" - -namespace net { - -class HttpCache; -class IOBufferWithSize; -class QuicServerId; - -// DiskCacheBasedQuicServerInfo fetches information about a QUIC server from -// our standard disk cache. Since the information is defined to be -// non-sensitive, it's ok for us to keep it on disk. -class NET_EXPORT_PRIVATE DiskCacheBasedQuicServerInfo - : public QuicServerInfo, - public NON_EXPORTED_BASE(base::NonThreadSafe) { - public: - DiskCacheBasedQuicServerInfo(const QuicServerId& server_id, - HttpCache* http_cache); - ~DiskCacheBasedQuicServerInfo() override; - - // QuicServerInfo implementation. - void Start() override; - int WaitForDataReady(const CompletionCallback& callback) override; - void ResetWaitForDataReadyCallback() override; - void CancelWaitForDataReadyCallback() override; - bool IsDataReady() override; - bool IsReadyToPersist() override; - void Persist() override; - void OnExternalCacheHit() override; - size_t EstimateMemoryUsage() const override; - - private: - struct CacheOperationDataShim; - - enum State { - GET_BACKEND, - GET_BACKEND_COMPLETE, - OPEN, - OPEN_COMPLETE, - READ, - READ_COMPLETE, - WAIT_FOR_DATA_READY_DONE, - CREATE_OR_OPEN, - CREATE_OR_OPEN_COMPLETE, - WRITE, - WRITE_COMPLETE, - SET_DONE, - NONE, - }; - - // Persists |pending_write_data_| if it is not empty, otherwise serializes the - // data and pesists it. - void PersistInternal(); - - std::string key() const; - - // The |unused| parameter is a small hack so that we can have the - // CacheOperationDataShim object owned by the Callback that is created for - // this method. See comment above CacheOperationDataShim for details. - void OnIOComplete(CacheOperationDataShim* unused, int rv); - - int DoLoop(int rv); - - int DoGetBackendComplete(int rv); - int DoOpenComplete(int rv); - int DoReadComplete(int rv); - int DoWriteComplete(int rv); - int DoCreateOrOpenComplete(int rv); - - int DoGetBackend(); - int DoOpen(); - int DoRead(); - int DoWrite(); - int DoCreateOrOpen(); - - // DoWaitForDataReadyDone is the terminal state of the read operation. - int DoWaitForDataReadyDone(); - - // DoSetDone is the terminal state of the write operation. - int DoSetDone(); - - // Tracks in a histogram the number of times data read/parse/write API calls - // of QuicServerInfo to and from disk cache is called. - void RecordQuicServerInfoStatus(QuicServerInfoAPICall call); - - // Tracks in a histogram the failure reasons to read/load/write of - // QuicServerInfo to and from disk cache. It also saves the |failure| in - // |last_failure_|. - void RecordQuicServerInfoFailure(FailureReason failure); - - // Tracks in a histogram if |last_failure_| is not NO_FAILURE. - void RecordLastFailure(); - - CacheOperationDataShim* data_shim_; // Owned by |io_callback_|. - CompletionCallback io_callback_; - State state_; - bool ready_; - bool found_entry_; // Controls the behavior of DoCreateOrOpen. - std::string new_data_; - std::string pending_write_data_; - const QuicServerId server_id_; - HttpCache* const http_cache_; - disk_cache::Backend* backend_; - disk_cache::Entry* entry_; - CompletionCallback wait_for_ready_callback_; - scoped_refptr<IOBufferWithSize> read_buffer_; - scoped_refptr<IOBufferWithSize> write_buffer_; - std::string data_; - base::TimeTicks load_start_time_; - FailureReason last_failure_; - - base::WeakPtrFactory<DiskCacheBasedQuicServerInfo> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(DiskCacheBasedQuicServerInfo); -}; - -} // namespace net - -#endif // NET_HTTP_DISK_CACHE_BASED_QUIC_SERVER_INFO_H_
diff --git a/net/http/disk_cache_based_quic_server_info_unittest.cc b/net/http/disk_cache_based_quic_server_info_unittest.cc deleted file mode 100644 index 55f5835..0000000 --- a/net/http/disk_cache_based_quic_server_info_unittest.cc +++ /dev/null
@@ -1,721 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/http/disk_cache_based_quic_server_info.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/run_loop.h" -#include "net/base/net_errors.h" -#include "net/http/mock_http_cache.h" -#include "net/quic/chromium/quic_server_info.h" -#include "net/quic/core/quic_server_id.h" -#include "net/test/gtest_util.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using net::test::IsError; -using net::test::IsOk; - -using std::string; - -namespace net { -namespace { - -// This is an empty transaction, needed to register the URL and the test mode. -const MockTransaction kHostInfoTransaction1 = { - "quicserverinfo:https://www.google.com:443", - "", - base::Time(), - "", - LOAD_NORMAL, - "", - "", - base::Time(), - "", - TEST_MODE_NORMAL, - nullptr, - nullptr, - nullptr, - 0, - 0, - OK, -}; - -const MockTransaction kHostInfoTransaction2 = { - "quicserverinfo:https://www.google.com:80", - "", - base::Time(), - "", - LOAD_NORMAL, - "", - "", - base::Time(), - "", - TEST_MODE_NORMAL, - nullptr, - nullptr, - nullptr, - 0, - 0, - OK, -}; - -class DeleteCacheCompletionCallback : public TestCompletionCallbackBase { - public: - explicit DeleteCacheCompletionCallback(QuicServerInfo* server_info) - : server_info_(server_info), - callback_(base::Bind(&DeleteCacheCompletionCallback::OnComplete, - base::Unretained(this))) {} - - const CompletionCallback& callback() const { return callback_; } - - private: - void OnComplete(int result) { - delete server_info_; - SetResult(result); - } - - QuicServerInfo* server_info_; - CompletionCallback callback_; - - DISALLOW_COPY_AND_ASSIGN(DeleteCacheCompletionCallback); -}; - -} // namespace - -// Tests that we can delete a DiskCacheBasedQuicServerInfo object in a -// completion callback for DiskCacheBasedQuicServerInfo::WaitForDataReady. -TEST(DiskCacheBasedQuicServerInfo, DeleteInCallback) { - // Use the blocking mock backend factory to force asynchronous completion - // of quic_server_info->WaitForDataReady(), so that the callback will run. - MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); - MockHttpCache cache(base::WrapUnique(factory), true); - QuicServerId server_id("www.verisign.com", 443, PRIVACY_MODE_DISABLED); - std::unique_ptr<QuicServerInfo> quic_server_info( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - quic_server_info->Start(); - TestCompletionCallback callback; - int rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - // Now complete the backend creation and let the callback run. - factory->FinishCreation(); - EXPECT_THAT(callback.GetResult(rv), IsOk()); -} - -// Tests the basic logic of storing, retrieving and updating data. -TEST(DiskCacheBasedQuicServerInfo, Update) { - MockHttpCache cache(true); - AddMockTransaction(&kHostInfoTransaction1); - TestCompletionCallback callback; - - QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); - std::unique_ptr<QuicServerInfo> quic_server_info( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - quic_server_info->Start(); - int rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - - QuicServerInfo::State* state = quic_server_info->mutable_state(); - EXPECT_TRUE(state->certs.empty()); - const string server_config_a = "server_config_a"; - const string source_address_token_a = "source_address_token_a"; - const string cert_sct_a = "cert_sct_a"; - const string chlo_hash_a = "chlo_hash_a"; - const string server_config_sig_a = "server_config_sig_a"; - const string cert_a = "cert_a"; - const string cert_b = "cert_b"; - - state->server_config = server_config_a; - state->source_address_token = source_address_token_a; - state->cert_sct = cert_sct_a; - state->chlo_hash = chlo_hash_a; - state->server_config_sig = server_config_sig_a; - state->certs.push_back(cert_a); - quic_server_info->Persist(); - - // Wait until Persist() does the work. - base::RunLoop().RunUntilIdle(); - - // Open the stored QuicServerInfo. - quic_server_info.reset( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - quic_server_info->Start(); - rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - - // And now update the data. - state = quic_server_info->mutable_state(); - state->certs.push_back(cert_b); - - // Fail instead of DCHECKing double creates. - cache.disk_cache()->set_double_create_check(false); - quic_server_info->Persist(); - base::RunLoop().RunUntilIdle(); - - // Verify that the state was updated. - quic_server_info.reset( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - quic_server_info->Start(); - rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - EXPECT_TRUE(quic_server_info->IsDataReady()); - - const QuicServerInfo::State& state1 = quic_server_info->state(); - EXPECT_EQ(server_config_a, state1.server_config); - EXPECT_EQ(source_address_token_a, state1.source_address_token); - EXPECT_EQ(cert_sct_a, state1.cert_sct); - EXPECT_EQ(chlo_hash_a, state1.chlo_hash); - EXPECT_EQ(server_config_sig_a, state1.server_config_sig); - EXPECT_EQ(2U, state1.certs.size()); - EXPECT_EQ(cert_a, state1.certs[0]); - EXPECT_EQ(cert_b, state1.certs[1]); - - RemoveMockTransaction(&kHostInfoTransaction1); -} - -// Test that demonstrates different info is returned when the ports differ. -TEST(DiskCacheBasedQuicServerInfo, UpdateDifferentPorts) { - MockHttpCache cache(true); - AddMockTransaction(&kHostInfoTransaction1); - AddMockTransaction(&kHostInfoTransaction2); - TestCompletionCallback callback; - - // Persist data for port 443. - QuicServerId server_id1("www.google.com", 443, PRIVACY_MODE_DISABLED); - std::unique_ptr<QuicServerInfo> quic_server_info1( - new DiskCacheBasedQuicServerInfo(server_id1, cache.http_cache())); - quic_server_info1->Start(); - int rv = quic_server_info1->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - - QuicServerInfo::State* state1 = quic_server_info1->mutable_state(); - EXPECT_TRUE(state1->certs.empty()); - const string server_config_a = "server_config_a"; - const string source_address_token_a = "source_address_token_a"; - const string cert_sct_a = "cert_sct_a"; - const string chlo_hash_a = "chlo_hash_a"; - const string server_config_sig_a = "server_config_sig_a"; - const string cert_a = "cert_a"; - - state1->server_config = server_config_a; - state1->source_address_token = source_address_token_a; - state1->cert_sct = cert_sct_a; - state1->chlo_hash = chlo_hash_a; - state1->server_config_sig = server_config_sig_a; - state1->certs.push_back(cert_a); - quic_server_info1->Persist(); - - // Wait until Persist() does the work. - base::RunLoop().RunUntilIdle(); - - // Persist data for port 80. - QuicServerId server_id2("www.google.com", 80, PRIVACY_MODE_DISABLED); - std::unique_ptr<QuicServerInfo> quic_server_info2( - new DiskCacheBasedQuicServerInfo(server_id2, cache.http_cache())); - quic_server_info2->Start(); - rv = quic_server_info2->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - - QuicServerInfo::State* state2 = quic_server_info2->mutable_state(); - EXPECT_TRUE(state2->certs.empty()); - const string server_config_b = "server_config_b"; - const string source_address_token_b = "source_address_token_b"; - const string cert_sct_b = "cert_sct_b"; - const string chlo_hash_b = "chlo_hash_b"; - const string server_config_sig_b = "server_config_sig_b"; - const string cert_b = "cert_b"; - - state2->server_config = server_config_b; - state2->source_address_token = source_address_token_b; - state2->cert_sct = cert_sct_b; - state2->chlo_hash = chlo_hash_b; - state2->server_config_sig = server_config_sig_b; - state2->certs.push_back(cert_b); - quic_server_info2->Persist(); - - // Wait until Persist() does the work. - base::RunLoop().RunUntilIdle(); - - // Verify the stored QuicServerInfo for port 443. - std::unique_ptr<QuicServerInfo> quic_server_info( - new DiskCacheBasedQuicServerInfo(server_id1, cache.http_cache())); - quic_server_info->Start(); - rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - EXPECT_TRUE(quic_server_info->IsDataReady()); - - const QuicServerInfo::State& state_a = quic_server_info->state(); - EXPECT_EQ(server_config_a, state_a.server_config); - EXPECT_EQ(source_address_token_a, state_a.source_address_token); - EXPECT_EQ(cert_sct_a, state_a.cert_sct); - EXPECT_EQ(chlo_hash_a, state_a.chlo_hash); - EXPECT_EQ(server_config_sig_a, state_a.server_config_sig); - EXPECT_EQ(1U, state_a.certs.size()); - EXPECT_EQ(cert_a, state_a.certs[0]); - - // Verify the stored QuicServerInfo for port 80. - quic_server_info.reset( - new DiskCacheBasedQuicServerInfo(server_id2, cache.http_cache())); - quic_server_info->Start(); - rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - EXPECT_TRUE(quic_server_info->IsDataReady()); - - const QuicServerInfo::State& state_b = quic_server_info->state(); - EXPECT_EQ(server_config_b, state_b.server_config); - EXPECT_EQ(source_address_token_b, state_b.source_address_token); - EXPECT_EQ(cert_sct_b, state_b.cert_sct); - EXPECT_EQ(chlo_hash_b, state_b.chlo_hash); - EXPECT_EQ(server_config_sig_b, state_b.server_config_sig); - EXPECT_EQ(1U, state_b.certs.size()); - EXPECT_EQ(cert_b, state_b.certs[0]); - - RemoveMockTransaction(&kHostInfoTransaction2); - RemoveMockTransaction(&kHostInfoTransaction1); -} - -// Test IsReadyToPersist when there is a pending write. -TEST(DiskCacheBasedQuicServerInfo, IsReadyToPersist) { - MockHttpCache cache(true); - AddMockTransaction(&kHostInfoTransaction1); - TestCompletionCallback callback; - - QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); - std::unique_ptr<QuicServerInfo> quic_server_info( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - EXPECT_FALSE(quic_server_info->IsDataReady()); - quic_server_info->Start(); - int rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - EXPECT_TRUE(quic_server_info->IsDataReady()); - - QuicServerInfo::State* state = quic_server_info->mutable_state(); - EXPECT_TRUE(state->certs.empty()); - const string server_config_a = "server_config_a"; - const string source_address_token_a = "source_address_token_a"; - const string cert_sct_a = "cert_sct_a"; - const string chlo_hash_a = "chlo_hash_a"; - const string server_config_sig_a = "server_config_sig_a"; - const string cert_a = "cert_a"; - - state->server_config = server_config_a; - state->source_address_token = source_address_token_a; - state->cert_sct = cert_sct_a; - state->chlo_hash = chlo_hash_a; - state->server_config_sig = server_config_sig_a; - state->certs.push_back(cert_a); - EXPECT_TRUE(quic_server_info->IsReadyToPersist()); - quic_server_info->Persist(); - - // Once we call Persist, IsReadyToPersist should return false until Persist - // has completed. - EXPECT_FALSE(quic_server_info->IsReadyToPersist()); - - // Wait until Persist() does the work. - base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(quic_server_info->IsReadyToPersist()); - - // Verify that the state was updated. - quic_server_info.reset( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - quic_server_info->Start(); - rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - EXPECT_TRUE(quic_server_info->IsDataReady()); - - const QuicServerInfo::State& state1 = quic_server_info->state(); - EXPECT_EQ(server_config_a, state1.server_config); - EXPECT_EQ(source_address_token_a, state1.source_address_token); - EXPECT_EQ(cert_sct_a, state1.cert_sct); - EXPECT_EQ(chlo_hash_a, state1.chlo_hash); - EXPECT_EQ(server_config_sig_a, state1.server_config_sig); - EXPECT_EQ(1U, state1.certs.size()); - EXPECT_EQ(cert_a, state1.certs[0]); - - RemoveMockTransaction(&kHostInfoTransaction1); -} - -// Test multiple calls to Persist. -TEST(DiskCacheBasedQuicServerInfo, MultiplePersist) { - MockHttpCache cache(true); - AddMockTransaction(&kHostInfoTransaction1); - TestCompletionCallback callback; - - QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); - std::unique_ptr<QuicServerInfo> quic_server_info( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - EXPECT_FALSE(quic_server_info->IsDataReady()); - quic_server_info->Start(); - int rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - EXPECT_TRUE(quic_server_info->IsDataReady()); - - // Persist data once. - QuicServerInfo::State* state = quic_server_info->mutable_state(); - EXPECT_TRUE(state->certs.empty()); - const string server_config_init = "server_config_init"; - const string source_address_token_init = "source_address_token_init"; - const string cert_sct_init = "cert_sct_init"; - const string chlo_hash_init = "chlo_hash_init"; - const string server_config_sig_init = "server_config_sig_init"; - const string cert_init = "cert_init"; - - state->server_config = server_config_init; - state->source_address_token = source_address_token_init; - state->cert_sct = cert_sct_init; - state->chlo_hash = chlo_hash_init; - state->server_config_sig = server_config_sig_init; - state->certs.push_back(cert_init); - EXPECT_TRUE(quic_server_info->IsReadyToPersist()); - quic_server_info->Persist(); - - // Once we call Persist, IsReadyToPersist should return false until Persist - // has completed. - EXPECT_FALSE(quic_server_info->IsReadyToPersist()); - - // Wait until Persist() does the work. - base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(quic_server_info->IsReadyToPersist()); - - // Persist one more time using the same |quic_server_info| object and without - // doing another Start() and WaitForDataReady. - const string server_config_a = "server_config_a"; - const string source_address_token_a = "source_address_token_a"; - const string cert_sct_a = "cert_sct_a"; - const string chlo_hash_a = "chlo_hash_a"; - const string server_config_sig_a = "server_config_sig_a"; - const string cert_a = "cert_a"; - - state->server_config = server_config_a; - state->source_address_token = source_address_token_a; - state->cert_sct = cert_sct_a; - state->chlo_hash = chlo_hash_a; - state->server_config_sig = server_config_sig_a; - state->certs.push_back(cert_a); - EXPECT_TRUE(quic_server_info->IsReadyToPersist()); - quic_server_info->Persist(); - - // Once we call Persist, IsReadyToPersist should return false until Persist - // has completed. - EXPECT_FALSE(quic_server_info->IsReadyToPersist()); - - // Wait until Persist() does the work. - base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(quic_server_info->IsReadyToPersist()); - - // Verify that the state was updated. - quic_server_info.reset( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - quic_server_info->Start(); - rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - EXPECT_TRUE(quic_server_info->IsDataReady()); - - const QuicServerInfo::State& state1 = quic_server_info->state(); - EXPECT_EQ(server_config_a, state1.server_config); - EXPECT_EQ(source_address_token_a, state1.source_address_token); - EXPECT_EQ(cert_sct_a, state1.cert_sct); - EXPECT_EQ(chlo_hash_a, state1.chlo_hash); - EXPECT_EQ(server_config_sig_a, state1.server_config_sig); - EXPECT_EQ(1U, state1.certs.size()); - EXPECT_EQ(cert_a, state1.certs[0]); - - RemoveMockTransaction(&kHostInfoTransaction1); -} - -TEST(DiskCacheBasedQuicServerInfo, CancelWaitForDataReady) { - MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); - MockHttpCache cache(base::WrapUnique(factory), true); - TestCompletionCallback callback; - QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); - std::unique_ptr<QuicServerInfo> quic_server_info( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - EXPECT_FALSE(quic_server_info->IsDataReady()); - quic_server_info->Start(); - int rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - // Now cancel the callback. - quic_server_info->CancelWaitForDataReadyCallback(); - EXPECT_FALSE(quic_server_info->IsDataReady()); - // Now complete the backend creation and let the callback run. - factory->FinishCreation(); - EXPECT_TRUE(quic_server_info->IsDataReady()); -} - -TEST(DiskCacheBasedQuicServerInfo, CancelWaitForDataReadyButDataIsReady) { - MockHttpCache cache(true); - AddMockTransaction(&kHostInfoTransaction1); - TestCompletionCallback callback; - - QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); - std::unique_ptr<QuicServerInfo> quic_server_info( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - EXPECT_FALSE(quic_server_info->IsDataReady()); - quic_server_info->Start(); - int rv = quic_server_info->WaitForDataReady(callback.callback()); - quic_server_info->CancelWaitForDataReadyCallback(); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - EXPECT_TRUE(quic_server_info->IsDataReady()); - RemoveMockTransaction(&kHostInfoTransaction1); -} - -TEST(DiskCacheBasedQuicServerInfo, CancelWaitForDataReadyAfterDeleteCache) { - std::unique_ptr<QuicServerInfo> quic_server_info; - { - MockHttpCache cache(true); - AddMockTransaction(&kHostInfoTransaction1); - TestCompletionCallback callback; - - QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); - quic_server_info.reset( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - EXPECT_FALSE(quic_server_info->IsDataReady()); - quic_server_info->Start(); - int rv = quic_server_info->WaitForDataReady(callback.callback()); - quic_server_info->CancelWaitForDataReadyCallback(); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - EXPECT_TRUE(quic_server_info->IsDataReady()); - RemoveMockTransaction(&kHostInfoTransaction1); - } - // Cancel the callback after Cache is deleted. - quic_server_info->ResetWaitForDataReadyCallback(); -} - -// Test Start() followed by Persist() without calling WaitForDataReady. -TEST(DiskCacheBasedQuicServerInfo, StartAndPersist) { - MockHttpCache cache(true); - AddMockTransaction(&kHostInfoTransaction1); - - QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); - std::unique_ptr<QuicServerInfo> quic_server_info( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - EXPECT_FALSE(quic_server_info->IsDataReady()); - quic_server_info->Start(); - // Wait until Start() does the work. - base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(quic_server_info->IsDataReady()); - - QuicServerInfo::State* state = quic_server_info->mutable_state(); - EXPECT_TRUE(state->certs.empty()); - const string server_config_a = "server_config_a"; - const string source_address_token_a = "source_address_token_a"; - const string cert_sct_a = "cert_sct_a"; - const string chlo_hash_a = "chlo_hash_a"; - const string server_config_sig_a = "server_config_sig_a"; - const string cert_a = "cert_a"; - - state->server_config = server_config_a; - state->source_address_token = source_address_token_a; - state->cert_sct = cert_sct_a; - state->chlo_hash = chlo_hash_a; - state->server_config_sig = server_config_sig_a; - state->certs.push_back(cert_a); - EXPECT_TRUE(quic_server_info->IsReadyToPersist()); - quic_server_info->Persist(); - quic_server_info->OnExternalCacheHit(); - - // Once we call Persist, IsReadyToPersist should return false until Persist - // has completed. - EXPECT_FALSE(quic_server_info->IsReadyToPersist()); - - // Wait until Persist() does the work. - base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(quic_server_info->IsReadyToPersist()); - - // Verify that the state was updated. - quic_server_info.reset( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - quic_server_info->Start(); - TestCompletionCallback callback; - int rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - EXPECT_TRUE(quic_server_info->IsDataReady()); - - const QuicServerInfo::State& state1 = quic_server_info->state(); - EXPECT_EQ(server_config_a, state1.server_config); - EXPECT_EQ(source_address_token_a, state1.source_address_token); - EXPECT_EQ(cert_sct_a, state1.cert_sct); - EXPECT_EQ(chlo_hash_a, state1.chlo_hash); - EXPECT_EQ(server_config_sig_a, state1.server_config_sig); - EXPECT_EQ(1U, state1.certs.size()); - EXPECT_EQ(cert_a, state1.certs[0]); - - RemoveMockTransaction(&kHostInfoTransaction1); -} - -// Test Persisting data when we are not ready to persist and then verify it -// persists the data when Start() finishes. -TEST(DiskCacheBasedQuicServerInfo, PersistWhenNotReadyToPersist) { - MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); - MockHttpCache cache(base::WrapUnique(factory), true); - AddMockTransaction(&kHostInfoTransaction1); - TestCompletionCallback callback; - - QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); - std::unique_ptr<QuicServerInfo> quic_server_info( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - EXPECT_FALSE(quic_server_info->IsDataReady()); - // We do a Start(), but don't call WaitForDataReady(). Because we haven't - // created the backend, we will wait and data wouldn't be ready. - quic_server_info->Start(); - EXPECT_FALSE(quic_server_info->IsDataReady()); - - // Persist data once, even though the backend is not ready. - QuicServerInfo::State* state = quic_server_info->mutable_state(); - EXPECT_TRUE(state->certs.empty()); - const string server_config_init = "server_config_init"; - const string source_address_token_init = "source_address_token_init"; - const string cert_sct_init = "cert_sct_init"; - const string chlo_hash_init = "chlo_hash_init"; - const string server_config_sig_init = "server_config_sig_init"; - const string cert_init = "cert_init"; - - state->server_config = server_config_init; - state->source_address_token = source_address_token_init; - state->cert_sct = cert_sct_init; - state->chlo_hash = chlo_hash_init; - state->server_config_sig = server_config_sig_init; - state->certs.push_back(cert_init); - EXPECT_FALSE(quic_server_info->IsReadyToPersist()); - quic_server_info->Persist(); - EXPECT_FALSE(quic_server_info->IsReadyToPersist()); - - // Now complete the backend creation and let the callback run. - factory->FinishCreation(); - EXPECT_TRUE(quic_server_info->IsDataReady()); - - // Wait until Persist() does the work. - base::RunLoop().RunUntilIdle(); - - // Verify that the state was updated. - quic_server_info.reset( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - quic_server_info->Start(); - int rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - EXPECT_TRUE(quic_server_info->IsDataReady()); - - const QuicServerInfo::State& state1 = quic_server_info->state(); - EXPECT_EQ(server_config_init, state1.server_config); - EXPECT_EQ(source_address_token_init, state1.source_address_token); - EXPECT_EQ(cert_sct_init, state1.cert_sct); - EXPECT_EQ(chlo_hash_init, state1.chlo_hash); - EXPECT_EQ(server_config_sig_init, state1.server_config_sig); - EXPECT_EQ(1U, state1.certs.size()); - EXPECT_EQ(cert_init, state1.certs[0]); - RemoveMockTransaction(&kHostInfoTransaction1); -} - -// Test multiple calls to Persist without waiting for the data to be written. -TEST(DiskCacheBasedQuicServerInfo, MultiplePersistsWithoutWaiting) { - MockHttpCache cache(true); - AddMockTransaction(&kHostInfoTransaction1); - TestCompletionCallback callback; - - QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); - std::unique_ptr<QuicServerInfo> quic_server_info( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - EXPECT_FALSE(quic_server_info->IsDataReady()); - quic_server_info->Start(); - int rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - EXPECT_TRUE(quic_server_info->IsDataReady()); - - // Persist data once. - QuicServerInfo::State* state = quic_server_info->mutable_state(); - EXPECT_TRUE(state->certs.empty()); - const string server_config_init = "server_config_init"; - const string source_address_token_init = "source_address_token_init"; - const string cert_sct_init = "cert_sct_init"; - const string chlo_hash_init = "chlo_hash_init"; - const string server_config_sig_init = "server_config_sig_init"; - const string cert_init = "cert_init"; - - state->server_config = server_config_init; - state->source_address_token = source_address_token_init; - state->cert_sct = cert_sct_init; - state->chlo_hash = chlo_hash_init; - state->server_config_sig = server_config_sig_init; - state->certs.push_back(cert_init); - EXPECT_TRUE(quic_server_info->IsReadyToPersist()); - quic_server_info->Persist(); - - // Once we call Persist, IsReadyToPersist should return false until Persist - // has completed. - EXPECT_FALSE(quic_server_info->IsReadyToPersist()); - - // Persist one more time using the same |quic_server_info| object and without - // doing another Start() and WaitForDataReady. - const string server_config_a = "server_config_a"; - const string source_address_token_a = "source_address_token_a"; - const string cert_sct_a = "cert_sct_a"; - const string chlo_hash_a = "chlo_hash_a"; - const string server_config_sig_a = "server_config_sig_a"; - const string cert_a = "cert_a"; - - state->server_config = server_config_a; - state->source_address_token = source_address_token_a; - state->cert_sct = cert_sct_a; - state->chlo_hash = chlo_hash_a; - state->server_config_sig = server_config_sig_a; - state->certs.push_back(cert_a); - EXPECT_FALSE(quic_server_info->IsReadyToPersist()); - quic_server_info->Persist(); - - // Wait until Persist() does the work. - base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(quic_server_info->IsReadyToPersist()); - - // Verify that the state was updated. - quic_server_info.reset( - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache())); - quic_server_info->Start(); - rv = quic_server_info->WaitForDataReady(callback.callback()); - EXPECT_THAT(callback.GetResult(rv), IsOk()); - EXPECT_TRUE(quic_server_info->IsDataReady()); - - // Verify the second time persisted data is persisted. - const QuicServerInfo::State& state1 = quic_server_info->state(); - EXPECT_EQ(server_config_a, state1.server_config); - EXPECT_EQ(source_address_token_a, state1.source_address_token); - EXPECT_EQ(cert_sct_a, state1.cert_sct); - EXPECT_EQ(chlo_hash_a, state1.chlo_hash); - EXPECT_EQ(server_config_sig_a, state1.server_config_sig); - EXPECT_EQ(1U, state1.certs.size()); - EXPECT_EQ(cert_a, state1.certs[0]); - - RemoveMockTransaction(&kHostInfoTransaction1); -} - -// crbug.com/439209: test deletion of QuicServerInfo object in the callback -// doesn't crash. -TEST(DiskCacheBasedQuicServerInfo, DeleteServerInfoInCallback) { - // Use the blocking mock backend factory to force asynchronous completion - // of quic_server_info->WaitForDataReady(), so that the callback will run. - MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); - MockHttpCache cache(base::WrapUnique(factory), true); - QuicServerId server_id("www.verisign.com", 443, PRIVACY_MODE_DISABLED); - QuicServerInfo* quic_server_info = - new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()); - // |cb| takes owndership and deletes |quic_server_info| when it is called. - DeleteCacheCompletionCallback cb(quic_server_info); - quic_server_info->Start(); - int rv = quic_server_info->WaitForDataReady(cb.callback()); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - // Now complete the backend creation and let the callback run. - factory->FinishCreation(); - EXPECT_THAT(cb.GetResult(rv), IsOk()); -} - -} // namespace net
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc index 93d39cc..968cffa 100644 --- a/net/http/http_cache.cc +++ b/net/http/http_cache.cc
@@ -37,7 +37,6 @@ #include "net/base/net_errors.h" #include "net/base/upload_data_stream.h" #include "net/disk_cache/disk_cache.h" -#include "net/http/disk_cache_based_quic_server_info.h" #include "net/http/http_cache_lookup_manager.h" #include "net/http/http_cache_transaction.h" #include "net/http/http_network_layer.h" @@ -303,24 +302,6 @@ } //----------------------------------------------------------------------------- - -class HttpCache::QuicServerInfoFactoryAdaptor : public QuicServerInfoFactory { - public: - explicit QuicServerInfoFactoryAdaptor(HttpCache* http_cache) - : http_cache_(http_cache) { - } - - std::unique_ptr<QuicServerInfo> GetForServer( - const QuicServerId& server_id) override { - return base::MakeUnique<DiskCacheBasedQuicServerInfo>(server_id, - http_cache_); - } - - private: - HttpCache* const http_cache_; -}; - -//----------------------------------------------------------------------------- HttpCache::HttpCache(HttpNetworkSession* session, std::unique_ptr<BackendFactory> backend_factory, bool is_main_cache) @@ -353,12 +334,6 @@ session->SetServerPushDelegate( base::MakeUnique<HttpCacheLookupManager>(this)); - - if (!session->quic_stream_factory()->has_quic_server_info_factory()) { - // QuicStreamFactory takes ownership of QuicServerInfoFactoryAdaptor. - session->quic_stream_factory()->set_quic_server_info_factory( - new QuicServerInfoFactoryAdaptor(this)); - } } HttpCache::~HttpCache() {
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 5c208946..30fa1a0 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -123,11 +123,7 @@ enable_quic(false), mark_quic_broken_when_network_blackholes(false), retry_without_alt_svc_on_quic_errors(false), - quic_load_server_info_timeout_srtt_multiplier(0.25f), - quic_enable_connection_racing(false), quic_enable_non_blocking_io(false), - quic_disable_disk_cache(false), - quic_delay_tcp_race(true), quic_max_server_configs_stored_in_properties(0u), quic_clock(nullptr), quic_random(nullptr), @@ -191,12 +187,8 @@ params.quic_max_packet_length, params.quic_user_agent_id, params.quic_supported_versions, - params.quic_load_server_info_timeout_srtt_multiplier, - params.quic_enable_connection_racing, params.quic_enable_non_blocking_io, - params.quic_disable_disk_cache, - params.quic_delay_tcp_race, - params.quic_max_server_configs_stored_in_properties, + params.quic_max_server_configs_stored_in_properties > 0, params.quic_close_sessions_on_ip_change, params.mark_quic_broken_when_network_blackholes, params.quic_idle_connection_timeout_seconds, @@ -328,12 +320,6 @@ } dict->Set("origins_to_force_quic_on", std::move(origins_to_force_quic_on)); - dict->SetDouble("load_server_info_timeout_srtt_multiplier", - params_.quic_load_server_info_timeout_srtt_multiplier); - dict->SetBoolean("enable_connection_racing", - params_.quic_enable_connection_racing); - dict->SetBoolean("disable_disk_cache", params_.quic_disable_disk_cache); - dict->SetBoolean("delay_tcp_race", params_.quic_delay_tcp_race); dict->SetInteger("max_server_configs_stored_in_properties", params_.quic_max_server_configs_stored_in_properties); dict->SetInteger("idle_connection_timeout_seconds",
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index 7765245..a2117e06 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h
@@ -122,20 +122,8 @@ // Retry requests which fail with QUIC_PROTOCOL_ERROR, and mark QUIC // broken if the retry succeeds. bool retry_without_alt_svc_on_quic_errors; - // If not zero, the task to load QUIC server configs from the disk cache - // will timeout after this value multiplied by the smoothed RTT for the - // server. - float quic_load_server_info_timeout_srtt_multiplier; - // Causes QUIC to race reading the server config from disk with - // sending an inchoate CHLO. - bool quic_enable_connection_racing; // Use non-blocking IO for UDP sockets. bool quic_enable_non_blocking_io; - // Disables using the disk cache to store QUIC server configs. - bool quic_disable_disk_cache; - // Delay starting a TCP connection when QUIC believes it can speak - // 0-RTT to a server. - bool quic_delay_tcp_race; // Maximum number of server configs that are to be stored in // HttpServerProperties, instead of the disk cache. size_t quic_max_server_configs_stored_in_properties;
diff --git a/net/http/http_stream_factory_impl_job_controller_unittest.cc b/net/http/http_stream_factory_impl_job_controller_unittest.cc index 1c00041..b32e37bc 100644 --- a/net/http/http_stream_factory_impl_job_controller_unittest.cc +++ b/net/http/http_stream_factory_impl_job_controller_unittest.cc
@@ -929,7 +929,6 @@ // Enable delayed TCP and set time delay for waiting job. QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory(); - test::QuicStreamFactoryPeer::SetDelayTcpRace(quic_stream_factory, true); quic_stream_factory->set_require_confirmation(false); ServerNetworkStats stats1; stats1.srtt = base::TimeDelta::FromMicroseconds(10); @@ -998,7 +997,6 @@ // Enable delayed TCP and set a extremely large time delay for waiting job. QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory(); - test::QuicStreamFactoryPeer::SetDelayTcpRace(quic_stream_factory, true); quic_stream_factory->set_require_confirmation(false); ServerNetworkStats stats1; stats1.srtt = base::TimeDelta::FromSeconds(100); @@ -1056,7 +1054,6 @@ // Enable delayed TCP and set time delay for waiting job. QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory(); - test::QuicStreamFactoryPeer::SetDelayTcpRace(quic_stream_factory, true); quic_stream_factory->set_require_confirmation(false); ServerNetworkStats stats1; stats1.srtt = base::TimeDelta::FromMicroseconds(10); @@ -1181,7 +1178,6 @@ // Enable delayed TCP and set time delay for waiting job. QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory(); - test::QuicStreamFactoryPeer::SetDelayTcpRace(quic_stream_factory, true); quic_stream_factory->set_require_confirmation(false); ServerNetworkStats stats1; stats1.srtt = base::TimeDelta::FromMicroseconds(10); @@ -1244,7 +1240,6 @@ // Enable delayed TCP and set time delay for waiting job. QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory(); - test::QuicStreamFactoryPeer::SetDelayTcpRace(quic_stream_factory, true); quic_stream_factory->set_require_confirmation(false); ServerNetworkStats stats1; stats1.srtt = base::TimeDelta::FromMicroseconds(300 * 1000);
diff --git a/net/http/transport_security_persister.cc b/net/http/transport_security_persister.cc index a37d237..8938b27 100644 --- a/net/http/transport_security_persister.cc +++ b/net/http/transport_security_persister.cc
@@ -9,6 +9,7 @@ #include "base/base64.h" #include "base/bind.h" +#include "base/feature_list.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/json/json_reader.h" @@ -81,6 +82,13 @@ const char kStsObserved[] = "sts_observed"; const char kPkpObserved[] = "pkp_observed"; const char kReportUri[] = "report-uri"; +// The keys below are contained in a subdictionary keyed as +// |kExpectCTSubdictionary|. +const char kExpectCTSubdictionary[] = "expect_ct"; +const char kExpectCTExpiry[] = "expect_ct_expiry"; +const char kExpectCTObserved[] = "expect_ct_observed"; +const char kExpectCTEnforce[] = "expect_ct_enforce"; +const char kExpectCTReportUri[] = "expect_ct_report_uri"; std::string LoadState(const base::FilePath& path) { std::string result; @@ -90,6 +98,191 @@ return result; } +bool IsDynamicExpectCTEnabled() { + return base::FeatureList::IsEnabled( + TransportSecurityState::kDynamicExpectCTFeature); +} + +// Populates |host| with default values for the STS and PKP states. +// These default values represent "null" states and are only useful to keep +// the entries in the resulting JSON consistent. The deserializer will ignore +// "null" states. +// TODO(davidben): This can be removed when the STS and PKP states are stored +// independently on disk. https://crbug.com/470295 +void PopulateEntryWithDefaults(base::DictionaryValue* host) { + host->Clear(); + + // STS default values. + host->SetBoolean(kStsIncludeSubdomains, false); + host->SetDouble(kStsObserved, 0.0); + host->SetDouble(kExpiry, 0.0); + host->SetString(kMode, kDefault); + + // PKP default values. + host->SetBoolean(kPkpIncludeSubdomains, false); + host->SetDouble(kPkpObserved, 0.0); + host->SetDouble(kDynamicSPKIHashesExpiry, 0.0); +} + +// Serializes STS data from |state| into |toplevel|. Any existing state in +// |toplevel| for each item is overwritten. +void SerializeSTSData(TransportSecurityState* state, + base::DictionaryValue* toplevel) { + TransportSecurityState::STSStateIterator sts_iterator(*state); + for (; sts_iterator.HasNext(); sts_iterator.Advance()) { + const std::string& hostname = sts_iterator.hostname(); + const TransportSecurityState::STSState& sts_state = + sts_iterator.domain_state(); + + const std::string key = HashedDomainToExternalString(hostname); + std::unique_ptr<base::DictionaryValue> serialized( + new base::DictionaryValue); + PopulateEntryWithDefaults(serialized.get()); + + serialized->SetBoolean(kStsIncludeSubdomains, sts_state.include_subdomains); + serialized->SetDouble(kStsObserved, sts_state.last_observed.ToDoubleT()); + serialized->SetDouble(kExpiry, sts_state.expiry.ToDoubleT()); + + switch (sts_state.upgrade_mode) { + case TransportSecurityState::STSState::MODE_FORCE_HTTPS: + serialized->SetString(kMode, kForceHTTPS); + break; + case TransportSecurityState::STSState::MODE_DEFAULT: + serialized->SetString(kMode, kDefault); + break; + default: + NOTREACHED() << "STSState with unknown mode"; + continue; + } + + toplevel->Set(key, std::move(serialized)); + } +} + +// Serializes PKP data from |state| into |toplevel|. For each PKP item in +// |state|, if |toplevel| already contains an item for that hostname, the item +// is updated with the PKP data. +void SerializePKPData(TransportSecurityState* state, + base::DictionaryValue* toplevel) { + base::Time now = base::Time::Now(); + TransportSecurityState::PKPStateIterator pkp_iterator(*state); + for (; pkp_iterator.HasNext(); pkp_iterator.Advance()) { + const std::string& hostname = pkp_iterator.hostname(); + const TransportSecurityState::PKPState& pkp_state = + pkp_iterator.domain_state(); + + // See if the current |hostname| already has STS state and, if so, update + // that entry. + const std::string key = HashedDomainToExternalString(hostname); + base::DictionaryValue* serialized = nullptr; + if (!toplevel->GetDictionary(key, &serialized)) { + std::unique_ptr<base::DictionaryValue> serialized_scoped( + new base::DictionaryValue); + serialized = serialized_scoped.get(); + PopulateEntryWithDefaults(serialized); + toplevel->Set(key, std::move(serialized_scoped)); + } + + serialized->SetBoolean(kPkpIncludeSubdomains, pkp_state.include_subdomains); + serialized->SetDouble(kPkpObserved, pkp_state.last_observed.ToDoubleT()); + serialized->SetDouble(kDynamicSPKIHashesExpiry, + pkp_state.expiry.ToDoubleT()); + + // TODO(svaldez): Historically, both SHA-1 and SHA-256 hashes were + // accepted in pins. Per spec, only SHA-256 is accepted now, however + // existing serialized pins are still processed. Migrate historical pins + // with SHA-1 hashes properly, either by dropping just the bad hashes or + // the entire pin. See https://crbug.com/448501. + if (now < pkp_state.expiry) { + serialized->Set(kDynamicSPKIHashes, + SPKIHashesToListValue(pkp_state.spki_hashes)); + } + + serialized->SetString(kReportUri, pkp_state.report_uri.spec()); + } +} + +// Serializes Expect-CT data from |state| into |toplevel|. For each Expect-CT +// item in |state|, if |toplevel| already contains an item for that hostname, +// the item is updated to include a subdictionary with key +// |kExpectCTSubdictionary|; otherwise an item is created for that hostname with +// a |kExpectCTSubdictionary| subdictionary. +void SerializeExpectCTData(TransportSecurityState* state, + base::DictionaryValue* toplevel) { + if (!IsDynamicExpectCTEnabled()) + return; + TransportSecurityState::ExpectCTStateIterator expect_ct_iterator(*state); + for (; expect_ct_iterator.HasNext(); expect_ct_iterator.Advance()) { + const std::string& hostname = expect_ct_iterator.hostname(); + const TransportSecurityState::ExpectCTState& expect_ct_state = + expect_ct_iterator.domain_state(); + + // See if the current |hostname| already has STS/PKP state and, if so, + // update that entry. + const std::string key = HashedDomainToExternalString(hostname); + base::DictionaryValue* serialized = nullptr; + if (!toplevel->GetDictionary(key, &serialized)) { + std::unique_ptr<base::DictionaryValue> serialized_scoped( + new base::DictionaryValue); + serialized = serialized_scoped.get(); + PopulateEntryWithDefaults(serialized); + toplevel->Set(key, std::move(serialized_scoped)); + } + + std::unique_ptr<base::DictionaryValue> expect_ct_subdictionary( + new base::DictionaryValue()); + expect_ct_subdictionary->SetDouble( + kExpectCTObserved, expect_ct_state.last_observed.ToDoubleT()); + expect_ct_subdictionary->SetDouble(kExpectCTExpiry, + expect_ct_state.expiry.ToDoubleT()); + expect_ct_subdictionary->SetBoolean(kExpectCTEnforce, + expect_ct_state.enforce); + expect_ct_subdictionary->SetString(kExpectCTReportUri, + expect_ct_state.report_uri.spec()); + serialized->Set(kExpectCTSubdictionary, std::move(expect_ct_subdictionary)); + } +} + +// Populates |state| with the values in the |kExpectCTSubdictionary| +// subdictionary in |parsed|. Returns false if |parsed| is malformed +// (e.g. missing a required Expect-CT key) and true otherwise. Note that true +// does not necessarily mean that Expect-CT state was present in |parsed|. +bool DeserializeExpectCTState(const base::DictionaryValue* parsed, + TransportSecurityState::ExpectCTState* state) { + const base::DictionaryValue* expect_ct_subdictionary; + if (!parsed->GetDictionary(kExpectCTSubdictionary, + &expect_ct_subdictionary)) { + // Expect-CT data is not required, so this item is not malformed. + return true; + } + double observed; + bool has_observed = + expect_ct_subdictionary->GetDouble(kExpectCTObserved, &observed); + double expiry; + bool has_expiry = + expect_ct_subdictionary->GetDouble(kExpectCTExpiry, &expiry); + bool enforce; + bool has_enforce = + expect_ct_subdictionary->GetBoolean(kExpectCTEnforce, &enforce); + std::string report_uri_str; + bool has_report_uri = + expect_ct_subdictionary->GetString(kExpectCTReportUri, &report_uri_str); + + // If an Expect-CT subdictionary is present, it must have the required keys. + if (!has_observed || !has_expiry || !has_enforce) + return false; + + state->last_observed = base::Time::FromDoubleT(observed); + state->expiry = base::Time::FromDoubleT(expiry); + state->enforce = enforce; + if (has_report_uri) { + GURL report_uri(report_uri_str); + if (report_uri.is_valid()) + state->report_uri = report_uri; + } + return true; +} + } // namespace TransportSecurityPersister::TransportSecurityPersister( @@ -121,8 +314,7 @@ transport_security_state_->SetDelegate(NULL); } -void TransportSecurityPersister::StateIsDirty( - TransportSecurityState* state) { +void TransportSecurityPersister::StateIsDirty(TransportSecurityState* state) { DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); DCHECK_EQ(transport_security_state_, state); @@ -134,77 +326,12 @@ DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); base::DictionaryValue toplevel; - base::Time now = base::Time::Now(); // TODO(davidben): Fix the serialization format by splitting the on-disk // representation of the STS and PKP states. https://crbug.com/470295. - TransportSecurityState::STSStateIterator sts_iterator( - *transport_security_state_); - for (; sts_iterator.HasNext(); sts_iterator.Advance()) { - const std::string& hostname = sts_iterator.hostname(); - const TransportSecurityState::STSState& sts_state = - sts_iterator.domain_state(); - - const std::string key = HashedDomainToExternalString(hostname); - std::unique_ptr<base::DictionaryValue> serialized( - new base::DictionaryValue); - PopulateEntryWithDefaults(serialized.get()); - - serialized->SetBoolean(kStsIncludeSubdomains, sts_state.include_subdomains); - serialized->SetDouble(kStsObserved, sts_state.last_observed.ToDoubleT()); - serialized->SetDouble(kExpiry, sts_state.expiry.ToDoubleT()); - - switch (sts_state.upgrade_mode) { - case TransportSecurityState::STSState::MODE_FORCE_HTTPS: - serialized->SetString(kMode, kForceHTTPS); - break; - case TransportSecurityState::STSState::MODE_DEFAULT: - serialized->SetString(kMode, kDefault); - break; - default: - NOTREACHED() << "STSState with unknown mode"; - continue; - } - - toplevel.Set(key, std::move(serialized)); - } - - TransportSecurityState::PKPStateIterator pkp_iterator( - *transport_security_state_); - for (; pkp_iterator.HasNext(); pkp_iterator.Advance()) { - const std::string& hostname = pkp_iterator.hostname(); - const TransportSecurityState::PKPState& pkp_state = - pkp_iterator.domain_state(); - - // See if the current |hostname| already has STS state and, if so, update - // that entry. - const std::string key = HashedDomainToExternalString(hostname); - base::DictionaryValue* serialized = nullptr; - if (!toplevel.GetDictionary(key, &serialized)) { - std::unique_ptr<base::DictionaryValue> serialized_scoped( - new base::DictionaryValue); - serialized = serialized_scoped.get(); - PopulateEntryWithDefaults(serialized); - toplevel.Set(key, std::move(serialized_scoped)); - } - - serialized->SetBoolean(kPkpIncludeSubdomains, pkp_state.include_subdomains); - serialized->SetDouble(kPkpObserved, pkp_state.last_observed.ToDoubleT()); - serialized->SetDouble(kDynamicSPKIHashesExpiry, - pkp_state.expiry.ToDoubleT()); - - // TODO(svaldez): Historically, both SHA-1 and SHA-256 hashes were - // accepted in pins. Per spec, only SHA-256 is accepted now, however - // existing serialized pins are still processed. Migrate historical pins - // with SHA-1 hashes properly, either by dropping just the bad hashes or - // the entire pin. See https://crbug.com/448501. - if (now < pkp_state.expiry) { - serialized->Set(kDynamicSPKIHashes, - SPKIHashesToListValue(pkp_state.spki_hashes)); - } - - serialized->SetString(kReportUri, pkp_state.report_uri.spec()); - } + SerializeSTSData(transport_security_state_, &toplevel); + SerializePKPData(transport_security_state_, &toplevel); + SerializeExpectCTData(transport_security_state_, &toplevel); base::JSONWriter::WriteWithOptions( toplevel, base::JSONWriter::OPTIONS_PRETTY_PRINT, output); @@ -241,6 +368,7 @@ TransportSecurityState::STSState sts_state; TransportSecurityState::PKPState pkp_state; + TransportSecurityState::ExpectCTState expect_ct_state; // kIncludeSubdomains is a legacy synonym for kStsIncludeSubdomains and // kPkpIncludeSubdomains. Parse at least one of these properties, @@ -323,13 +451,21 @@ pkp_state.last_observed = base::Time::Now(); } + if (!DeserializeExpectCTState(parsed, &expect_ct_state)) { + continue; + } + bool has_sts = sts_state.expiry > current_time && sts_state.ShouldUpgradeToSSL(); bool has_pkp = pkp_state.expiry > current_time && pkp_state.HasPublicKeyPins(); - if (!has_sts && !has_pkp) { + bool has_expect_ct = + expect_ct_state.expiry > current_time && + (expect_ct_state.enforce || !expect_ct_state.report_uri.is_empty()); + if (!has_sts && !has_pkp && !has_expect_ct) { // Make sure we dirty the state if we drop an entry. The entries can only - // be dropped when both the STS and PKP states are expired or invalid. + // be dropped when all the STS, PKP, and Expect-CT states are expired or + // invalid. dirtied = true; continue; } @@ -346,28 +482,14 @@ state->AddOrUpdateEnabledSTSHosts(hashed, sts_state); if (has_pkp) state->AddOrUpdateEnabledPKPHosts(hashed, pkp_state); + if (has_expect_ct) + state->AddOrUpdateEnabledExpectCTHosts(hashed, expect_ct_state); } *dirty = dirtied; return true; } -void TransportSecurityPersister::PopulateEntryWithDefaults( - base::DictionaryValue* host) { - host->Clear(); - - // STS default values. - host->SetBoolean(kStsIncludeSubdomains, false); - host->SetDouble(kStsObserved, 0.0); - host->SetDouble(kExpiry, 0.0); - host->SetString(kMode, kDefault); - - // PKP default values. - host->SetBoolean(kPkpIncludeSubdomains, false); - host->SetDouble(kPkpObserved, 0.0); - host->SetDouble(kDynamicSPKIHashesExpiry, 0.0); -} - void TransportSecurityPersister::CompleteLoad(const std::string& state) { DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
diff --git a/net/http/transport_security_persister.h b/net/http/transport_security_persister.h index d4e1e36a..d2fad85 100644 --- a/net/http/transport_security_persister.h +++ b/net/http/transport_security_persister.h
@@ -44,7 +44,6 @@ #include "net/http/transport_security_state.h" namespace base { -class DictionaryValue; class SequencedTaskRunner; } @@ -72,7 +71,7 @@ // ImportantFileWriter::DataSerializer: // // Serializes |transport_security_state_| into |*output|. Returns true if - // all STS and PKP states were serialized correctly. + // all STS, PKP, and Expect_CT states were serialized correctly. // // The serialization format is JSON; the JSON represents a dictionary of // host:DomainState pairs (host is a string). The DomainState contains @@ -94,6 +93,15 @@ // "bad_static_spki_hashes": list of strings // legacy key synonym "bad_preloaded_spki_hashes" // "dynamic_spki_hashes": list of strings + // "dynamic_spki_hashes_expiry": double + // "report-uri": string + // "sts_observed": double + // "pkp_observed": double + // "expect_ct": dictionary with keys: + // "expect_ct_expiry": double + // "expect_ct_observed": double + // "expect_ct_enforce": true|false + // "expect_ct_report_uri": string // // The JSON dictionary keys are strings containing // Base64(SHA256(TransportSecurityState::CanonicalizeHost(domain))). @@ -119,14 +127,6 @@ bool* dirty, TransportSecurityState* state); - // Populates |host| with default values for the STS and PKP states. - // These default values represent "null" states and are only useful to keep - // the entries in the resulting JSON consistent. The deserializer will ignore - // "null" states. - // TODO(davidben): This can be removed when the STS and PKP states are stored - // independently on disk. https://crbug.com/470295 - void PopulateEntryWithDefaults(base::DictionaryValue* host); - void CompleteLoad(const std::string& state); TransportSecurityState* transport_security_state_;
diff --git a/net/http/transport_security_persister_unittest.cc b/net/http/transport_security_persister_unittest.cc index 6e7e804..b7da5ef 100644 --- a/net/http/transport_security_persister_unittest.cc +++ b/net/http/transport_security_persister_unittest.cc
@@ -14,6 +14,7 @@ #include "base/files/scoped_temp_dir.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_feature_list.h" #include "base/threading/thread_task_runner_handle.h" #include "net/http/transport_security_state.h" #include "testing/gtest/include/gtest/gtest.h" @@ -48,6 +49,44 @@ std::unique_ptr<TransportSecurityPersister> persister_; }; +// Tests that LoadEntries() clears existing non-static entries. +TEST_F(TransportSecurityPersisterTest, LoadEntriesClearsExistingState) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + TransportSecurityState::kDynamicExpectCTFeature); + std::string output; + bool dirty; + + TransportSecurityState::STSState sts_state; + TransportSecurityState::PKPState pkp_state; + TransportSecurityState::ExpectCTState expect_ct_state; + const base::Time current_time(base::Time::Now()); + const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); + static const char kYahooDomain[] = "yahoo.com"; + + EXPECT_FALSE(state_.GetDynamicSTSState(kYahooDomain, &sts_state)); + EXPECT_FALSE(state_.GetDynamicPKPState(kYahooDomain, &pkp_state)); + + state_.AddHSTS(kYahooDomain, expiry, false /* include subdomains */); + HashValue spki(HASH_VALUE_SHA256); + memset(spki.data(), 0, spki.size()); + HashValueVector dynamic_spki_hashes; + dynamic_spki_hashes.push_back(spki); + state_.AddHPKP(kYahooDomain, expiry, false, dynamic_spki_hashes, GURL()); + state_.AddExpectCT(kYahooDomain, expiry, true /* enforce */, GURL()); + + EXPECT_TRUE(state_.GetDynamicSTSState(kYahooDomain, &sts_state)); + EXPECT_TRUE(state_.GetDynamicPKPState(kYahooDomain, &pkp_state)); + EXPECT_TRUE(state_.GetDynamicExpectCTState(kYahooDomain, &expect_ct_state)); + + EXPECT_TRUE(persister_->LoadEntries("{}", &dirty)); + EXPECT_FALSE(dirty); + + EXPECT_FALSE(state_.GetDynamicSTSState(kYahooDomain, &sts_state)); + EXPECT_FALSE(state_.GetDynamicPKPState(kYahooDomain, &pkp_state)); + EXPECT_FALSE(state_.GetDynamicExpectCTState(kYahooDomain, &expect_ct_state)); +} + TEST_F(TransportSecurityPersisterTest, SerializeData1) { std::string output; bool dirty; @@ -93,6 +132,9 @@ } TEST_F(TransportSecurityPersisterTest, SerializeData3) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + TransportSecurityState::kDynamicExpectCTFeature); const GURL report_uri(kReportUri); // Add an entry. HashValue fp1(HASH_VALUE_SHA256); @@ -108,6 +150,7 @@ state_.AddHSTS("www.example.com", expiry, include_subdomains); state_.AddHPKP("www.example.com", expiry, include_subdomains, dynamic_spki_hashes, report_uri); + state_.AddExpectCT("www.example.com", expiry, true /* enforce */, GURL()); // Add another entry. memset(fp1.data(), 2, fp1.size()); @@ -119,6 +162,8 @@ state_.AddHSTS("www.example.net", expiry, include_subdomains); state_.AddHPKP("www.example.net", expiry, include_subdomains, dynamic_spki_hashes, report_uri); + state_.AddExpectCT("www.example.net", expiry, false /* enforce */, + report_uri); // Save a copy of everything. std::set<std::string> sts_saved; @@ -135,6 +180,13 @@ pkp_iter.Advance(); } + std::set<std::string> expect_ct_saved; + TransportSecurityState::ExpectCTStateIterator expect_ct_iter(state_); + while (expect_ct_iter.HasNext()) { + expect_ct_saved.insert(expect_ct_iter.hostname()); + expect_ct_iter.Advance(); + } + std::string serialized; EXPECT_TRUE(persister_->SerializeData(&serialized)); @@ -171,6 +223,14 @@ pkp_iter2.Advance(); } EXPECT_EQ(count, pkp_saved.size()); + + count = 0; + TransportSecurityState::ExpectCTStateIterator expect_ct_iter2(state_); + while (expect_ct_iter2.HasNext()) { + count++; + expect_ct_iter2.Advance(); + } + EXPECT_EQ(count, expect_ct_saved.size()); } TEST_F(TransportSecurityPersisterTest, SerializeDataOld) { @@ -231,6 +291,119 @@ EXPECT_EQ(report_uri, new_pkp_state.report_uri); } +// Tests that dynamic Expect-CT state is serialized and deserialized correctly. +TEST_F(TransportSecurityPersisterTest, ExpectCT) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + TransportSecurityState::kDynamicExpectCTFeature); + const GURL report_uri(kReportUri); + TransportSecurityState::ExpectCTState expect_ct_state; + static const char kTestDomain[] = "example.test"; + + EXPECT_FALSE(state_.GetDynamicExpectCTState(kTestDomain, &expect_ct_state)); + + const base::Time current_time(base::Time::Now()); + const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); + state_.AddExpectCT(kTestDomain, expiry, true /* enforce */, GURL()); + std::string serialized; + EXPECT_TRUE(persister_->SerializeData(&serialized)); + bool dirty; + // LoadEntries() clears existing dynamic data before loading entries from + // |serialized|. + EXPECT_TRUE(persister_->LoadEntries(serialized, &dirty)); + + TransportSecurityState::ExpectCTState new_expect_ct_state; + EXPECT_TRUE( + state_.GetDynamicExpectCTState(kTestDomain, &new_expect_ct_state)); + EXPECT_TRUE(new_expect_ct_state.enforce); + EXPECT_TRUE(new_expect_ct_state.report_uri.is_empty()); + EXPECT_EQ(expiry, new_expect_ct_state.expiry); + + // Update the state for the domain and check that it is + // serialized/deserialized correctly. + state_.AddExpectCT(kTestDomain, expiry, false /* enforce */, report_uri); + EXPECT_TRUE(persister_->SerializeData(&serialized)); + EXPECT_TRUE(persister_->LoadEntries(serialized, &dirty)); + EXPECT_TRUE( + state_.GetDynamicExpectCTState(kTestDomain, &new_expect_ct_state)); + EXPECT_FALSE(new_expect_ct_state.enforce); + EXPECT_EQ(report_uri, new_expect_ct_state.report_uri); + EXPECT_EQ(expiry, new_expect_ct_state.expiry); +} + +// Tests that dynamic Expect-CT state is serialized and deserialized correctly +// when there is also PKP and STS data present. +TEST_F(TransportSecurityPersisterTest, ExpectCTWithSTSAndPKPDataPresent) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + TransportSecurityState::kDynamicExpectCTFeature); + const GURL report_uri(kReportUri); + TransportSecurityState::ExpectCTState expect_ct_state; + static const char kTestDomain[] = "example.test"; + + EXPECT_FALSE(state_.GetDynamicExpectCTState(kTestDomain, &expect_ct_state)); + + const base::Time current_time(base::Time::Now()); + const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); + state_.AddHSTS(kTestDomain, expiry, false /* include subdomains */); + state_.AddExpectCT(kTestDomain, expiry, true /* enforce */, GURL()); + HashValue spki_hash(HASH_VALUE_SHA256); + memset(spki_hash.data(), 0, spki_hash.size()); + HashValueVector dynamic_spki_hashes; + dynamic_spki_hashes.push_back(spki_hash); + state_.AddHPKP(kTestDomain, expiry, false /* include subdomains */, + dynamic_spki_hashes, GURL()); + + std::string serialized; + EXPECT_TRUE(persister_->SerializeData(&serialized)); + bool dirty; + // LoadEntries() clears existing dynamic data before loading entries from + // |serialized|. + EXPECT_TRUE(persister_->LoadEntries(serialized, &dirty)); + + TransportSecurityState::ExpectCTState new_expect_ct_state; + EXPECT_TRUE( + state_.GetDynamicExpectCTState(kTestDomain, &new_expect_ct_state)); + EXPECT_TRUE(new_expect_ct_state.enforce); + EXPECT_TRUE(new_expect_ct_state.report_uri.is_empty()); + EXPECT_EQ(expiry, new_expect_ct_state.expiry); + // Check that STS and PKP state are loaded properly as well. + TransportSecurityState::STSState sts_state; + EXPECT_TRUE(state_.GetDynamicSTSState(kTestDomain, &sts_state)); + EXPECT_EQ(sts_state.upgrade_mode, + TransportSecurityState::STSState::MODE_FORCE_HTTPS); + TransportSecurityState::PKPState pkp_state; + EXPECT_TRUE(state_.GetDynamicPKPState(kTestDomain, &pkp_state)); + EXPECT_EQ(1u, pkp_state.spki_hashes.size()); + EXPECT_EQ(0, memcmp(pkp_state.spki_hashes[0].data(), spki_hash.data(), + spki_hash.size())); +} + +// Tests that Expect-CT state is not serialized and persisted when the feature +// is disabled. +TEST_F(TransportSecurityPersisterTest, ExpectCTDisabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature( + TransportSecurityState::kDynamicExpectCTFeature); + const GURL report_uri(kReportUri); + TransportSecurityState::ExpectCTState expect_ct_state; + static const char kTestDomain[] = "example.test"; + + EXPECT_FALSE(state_.GetDynamicExpectCTState(kTestDomain, &expect_ct_state)); + + const base::Time current_time(base::Time::Now()); + const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); + state_.AddExpectCT(kTestDomain, expiry, true /* enforce */, GURL()); + std::string serialized; + EXPECT_TRUE(persister_->SerializeData(&serialized)); + bool dirty; + EXPECT_TRUE(persister_->LoadEntries(serialized, &dirty)); + + TransportSecurityState::ExpectCTState new_expect_ct_state; + EXPECT_FALSE( + state_.GetDynamicExpectCTState(kTestDomain, &new_expect_ct_state)); +} + } // namespace } // namespace net
diff --git a/net/http/url_security_manager_win.cc b/net/http/url_security_manager_win.cc index 614fa44..d56a1b8 100644 --- a/net/http/url_security_manager_win.cc +++ b/net/http/url_security_manager_win.cc
@@ -103,11 +103,11 @@ // TODO(cbentzel): Could CanDelegate use the security zone as well? bool URLSecurityManagerWin::EnsureSystemSecurityManager() { - if (!security_manager_.get()) { + if (!security_manager_.Get()) { HRESULT hr = CoInternetCreateSecurityManager(NULL, security_manager_.Receive(), NULL); - if (FAILED(hr) || !security_manager_.get()) { + if (FAILED(hr) || !security_manager_.Get()) { LOG(ERROR) << "Unable to create the Windows Security Manager instance"; return false; }
diff --git a/net/quic/chromium/properties_based_quic_server_info.cc b/net/quic/chromium/properties_based_quic_server_info.cc index e90331fd7..54d1b6da 100644 --- a/net/quic/chromium/properties_based_quic_server_info.cc +++ b/net/quic/chromium/properties_based_quic_server_info.cc
@@ -14,13 +14,6 @@ namespace { -void RecordQuicServerInfoStatus( - net::QuicServerInfo::QuicServerInfoAPICall call) { - UMA_HISTOGRAM_ENUMERATION( - "Net.QuicDiskCache.APICall.PropertiesBasedCache", call, - net::QuicServerInfo::QUIC_SERVER_INFO_NUM_OF_API_CALLS); -} - void RecordQuicServerInfoFailure(net::QuicServerInfo::FailureReason failure) { UMA_HISTOGRAM_ENUMERATION( "Net.QuicDiskCache.FailureReason.PropertiesBasedCache", failure, @@ -41,74 +34,33 @@ PropertiesBasedQuicServerInfo::~PropertiesBasedQuicServerInfo() {} -void PropertiesBasedQuicServerInfo::Start() { - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_START); -} - -int PropertiesBasedQuicServerInfo::WaitForDataReady( - const CompletionCallback& callback) { - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY); +bool PropertiesBasedQuicServerInfo::Load() { const string* data = http_server_properties_->GetQuicServerInfo(server_id_); string decoded; if (!data) { RecordQuicServerInfoFailure(PARSE_NO_DATA_FAILURE); - return ERR_FAILED; + return false; } if (!base::Base64Decode(*data, &decoded)) { RecordQuicServerInfoFailure(PARSE_DATA_DECODE_FAILURE); - return ERR_FAILED; + return false; } - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PARSE); if (!Parse(decoded)) { RecordQuicServerInfoFailure(PARSE_FAILURE); - return ERR_FAILED; + return false; } - return OK; -} - -void PropertiesBasedQuicServerInfo::ResetWaitForDataReadyCallback() { - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_RESET_WAIT_FOR_DATA_READY); -} - -void PropertiesBasedQuicServerInfo::CancelWaitForDataReadyCallback() { - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY_CANCEL); -} - -bool PropertiesBasedQuicServerInfo::IsDataReady() { return true; } -bool PropertiesBasedQuicServerInfo::IsReadyToPersist() { - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_READY_TO_PERSIST); - return true; -} void PropertiesBasedQuicServerInfo::Persist() { - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PERSIST); string encoded; base::Base64Encode(Serialize(), &encoded); http_server_properties_->SetQuicServerInfo(server_id_, encoded); } -void PropertiesBasedQuicServerInfo::OnExternalCacheHit() { - RecordQuicServerInfoStatus(QUIC_SERVER_INFO_EXTERNAL_CACHE_HIT); -} - size_t PropertiesBasedQuicServerInfo::EstimateMemoryUsage() const { return 0; } -PropertiesBasedQuicServerInfoFactory::PropertiesBasedQuicServerInfoFactory( - HttpServerProperties* http_server_properties) - : http_server_properties_(http_server_properties) {} - -PropertiesBasedQuicServerInfoFactory::~PropertiesBasedQuicServerInfoFactory() {} - -std::unique_ptr<QuicServerInfo> -PropertiesBasedQuicServerInfoFactory::GetForServer( - const QuicServerId& server_id) { - return base::MakeUnique<PropertiesBasedQuicServerInfo>( - server_id, http_server_properties_); -} - } // namespace net
diff --git a/net/quic/chromium/properties_based_quic_server_info.h b/net/quic/chromium/properties_based_quic_server_info.h index 35ebb9b7..df85a9d8 100644 --- a/net/quic/chromium/properties_based_quic_server_info.h +++ b/net/quic/chromium/properties_based_quic_server_info.h
@@ -30,14 +30,8 @@ ~PropertiesBasedQuicServerInfo() override; // QuicServerInfo implementation. - void Start() override; - int WaitForDataReady(const CompletionCallback& callback) override; - void ResetWaitForDataReadyCallback() override; - void CancelWaitForDataReadyCallback() override; - bool IsDataReady() override; - bool IsReadyToPersist() override; + bool Load() override; void Persist() override; - void OnExternalCacheHit() override; size_t EstimateMemoryUsage() const override; private: @@ -46,22 +40,6 @@ DISALLOW_COPY_AND_ASSIGN(PropertiesBasedQuicServerInfo); }; -class QUIC_EXPORT_PRIVATE PropertiesBasedQuicServerInfoFactory - : public QuicServerInfoFactory { - public: - explicit PropertiesBasedQuicServerInfoFactory( - HttpServerProperties* http_server_properties); - ~PropertiesBasedQuicServerInfoFactory() override; - - std::unique_ptr<QuicServerInfo> GetForServer( - const QuicServerId& server_id) override; - - private: - HttpServerProperties* http_server_properties_; - - DISALLOW_COPY_AND_ASSIGN(PropertiesBasedQuicServerInfoFactory); -}; - } // namespace net #endif // NET_QUIC_CHROMIUM_PROPERTIES_BASED_QUIC_SERVER_INFO_H_
diff --git a/net/quic/chromium/properties_based_quic_server_info_test.cc b/net/quic/chromium/properties_based_quic_server_info_test.cc index aba7c635..c4cc0638 100644 --- a/net/quic/chromium/properties_based_quic_server_info_test.cc +++ b/net/quic/chromium/properties_based_quic_server_info_test.cc
@@ -34,8 +34,6 @@ // Initialize |server_info_| object and persist it. void InitializeAndPersist() { - server_info_.Start(); - EXPECT_TRUE(server_info_.IsDataReady()); QuicServerInfo::State* state = server_info_.mutable_state(); EXPECT_TRUE(state->certs.empty()); @@ -45,11 +43,7 @@ state->cert_sct = kCertSCTA; state->chlo_hash = kChloHashA; state->certs.push_back(kCertA); - EXPECT_TRUE(server_info_.IsReadyToPersist()); server_info_.Persist(); - EXPECT_TRUE(server_info_.IsReadyToPersist()); - EXPECT_TRUE(server_info_.IsDataReady()); - server_info_.OnExternalCacheHit(); } // Verify the data that is persisted in InitializeAndPersist(). @@ -75,10 +69,7 @@ // Read the persisted data and verify we have read the data correctly. PropertiesBasedQuicServerInfo server_info1(server_id_, &http_server_properties_); - server_info1.Start(); - EXPECT_THAT(server_info1.WaitForDataReady(callback_), - IsOk()); // Read the data. - EXPECT_TRUE(server_info1.IsDataReady()); + EXPECT_TRUE(server_info1.Load()); // Verify the data. const QuicServerInfo::State& state1 = server_info1.state(); @@ -88,16 +79,12 @@ // Update the data, by adding another cert. QuicServerInfo::State* state2 = server_info1.mutable_state(); state2->certs.push_back(kCertB); - EXPECT_TRUE(server_info_.IsReadyToPersist()); server_info1.Persist(); // Read the persisted data and verify we have read the data correctly. PropertiesBasedQuicServerInfo server_info2(server_id_, &http_server_properties_); - server_info2.Start(); - EXPECT_THAT(server_info2.WaitForDataReady(callback_), - IsOk()); // Read the data. - EXPECT_TRUE(server_info1.IsDataReady()); + EXPECT_TRUE(server_info2.Load()); // Verify updated data. const QuicServerInfo::State& state3 = server_info2.state();
diff --git a/net/quic/chromium/quic_chromium_client_session.cc b/net/quic/chromium/quic_chromium_client_session.cc index ba6c37c..6913eb5 100644 --- a/net/quic/chromium/quic_chromium_client_session.cc +++ b/net/quic/chromium/quic_chromium_client_session.cc
@@ -375,24 +375,8 @@ round_trip_handshakes, 1, 3, 4); } } + const QuicConnectionStats stats = connection()->GetStats(); - if (server_info_ && stats.min_rtt_us > 0) { - base::TimeTicks wait_for_data_start_time = - server_info_->wait_for_data_start_time(); - base::TimeTicks wait_for_data_end_time = - server_info_->wait_for_data_end_time(); - if (!wait_for_data_start_time.is_null() && - !wait_for_data_end_time.is_null()) { - base::TimeDelta wait_time = - wait_for_data_end_time - wait_for_data_start_time; - const base::HistogramBase::Sample kMaxWaitToRtt = 1000; - base::HistogramBase::Sample wait_to_rtt = - static_cast<base::HistogramBase::Sample>( - 100 * wait_time.InMicroseconds() / stats.min_rtt_us); - UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicServerInfo.WaitForDataReadyToRtt", - wait_to_rtt, 1, kMaxWaitToRtt, 50); - } - } // The MTU used by QUIC is limited to a fairly small set of predefined values // (initial values and MTU discovery values), but does not fare well when @@ -561,7 +545,12 @@ return stream; } -QuicCryptoClientStream* QuicChromiumClientSession::GetCryptoStream() { +QuicCryptoClientStream* QuicChromiumClientSession::GetMutableCryptoStream() { + return crypto_stream_.get(); +} + +const QuicCryptoClientStream* QuicChromiumClientSession::GetCryptoStream() + const { return crypto_stream_.get(); } @@ -857,21 +846,6 @@ UMA_HISTOGRAM_TIMES( "Net.QuicSession.HandshakeConfirmedTime", connect_timing_.connect_end - connect_timing_.connect_start); - - if (server_info_) { - // TODO(rtenneti): Should we delete this histogram? - // Track how long it has taken to finish handshake once we start waiting - // for reading of QUIC server information from disk cache. We could use - // this data to compare total time taken if we were to cancel the disk - // cache read vs waiting for the read to complete. - base::TimeTicks wait_for_data_start_time = - server_info_->wait_for_data_start_time(); - if (!wait_for_data_start_time.is_null()) { - UMA_HISTOGRAM_TIMES( - "Net.QuicServerInfo.WaitForDataReady.HandshakeConfirmedTime", - base::TimeTicks::Now() - wait_for_data_start_time); - } - } // Track how long it has taken to finish handshake after we have finished // DNS host resolution. if (!connect_timing_.dns_end.is_null()) { @@ -886,8 +860,6 @@ ++it; observer->OnCryptoHandshakeConfirmed(); } - if (server_info_) - server_info_->OnExternalCacheHit(); } QuicSpdySession::OnCryptoHandshakeEvent(event); }
diff --git a/net/quic/chromium/quic_chromium_client_session.h b/net/quic/chromium/quic_chromium_client_session.h index 359df91..fb99d1f 100644 --- a/net/quic/chromium/quic_chromium_client_session.h +++ b/net/quic/chromium/quic_chromium_client_session.h
@@ -173,7 +173,8 @@ void OnStreamFrame(const QuicStreamFrame& frame) override; QuicChromiumClientStream* CreateOutgoingDynamicStream( SpdyPriority priority) override; - QuicCryptoClientStream* GetCryptoStream() override; + const QuicCryptoClientStream* GetCryptoStream() const override; + QuicCryptoClientStream* GetMutableCryptoStream() override; void CloseStream(QuicStreamId stream_id) override; void SendRstStream(QuicStreamId id, QuicRstStreamErrorCode error,
diff --git a/net/quic/chromium/quic_chromium_client_session_test.cc b/net/quic/chromium/quic_chromium_client_session_test.cc index e076f3b..1a5cb92 100644 --- a/net/quic/chromium/quic_chromium_client_session_test.cc +++ b/net/quic/chromium/quic_chromium_client_session_test.cc
@@ -32,8 +32,8 @@ #include "net/quic/core/crypto/quic_decrypter.h" #include "net/quic/core/crypto/quic_encrypter.h" #include "net/quic/core/quic_client_promised_info.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packet_writer.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/quic_client_promised_info_peer.h" #include "net/quic/test_tools/quic_spdy_session_peer.h" @@ -792,7 +792,8 @@ iov[0].iov_base = data; iov[0].iov_len = 4; session_->WritevData(stream, stream->id(), - QuicIOVector(iov, arraysize(iov), 4), 0, false, nullptr); + QuicIOVector(iov, arraysize(iov), 4), 0, NO_FIN, + nullptr); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed());
diff --git a/net/quic/chromium/quic_chromium_client_stream_test.cc b/net/quic/chromium/quic_chromium_client_stream_test.cc index 35b384c..95f258d 100644 --- a/net/quic/chromium/quic_chromium_client_stream_test.cc +++ b/net/quic/chromium/quic_chromium_client_stream_test.cc
@@ -66,7 +66,13 @@ QuicClientPushPromiseIndex* index); ~MockQuicClientSessionBase() override; - QuicCryptoStream* GetCryptoStream() override { return crypto_stream_.get(); } + const QuicCryptoStream* GetCryptoStream() const override { + return crypto_stream_.get(); + } + + QuicCryptoStream* GetMutableCryptoStream() override { + return crypto_stream_.get(); + } // From QuicSession. MOCK_METHOD3(OnConnectionClosed, @@ -82,7 +88,7 @@ QuicStreamId id, QuicIOVector data, QuicStreamOffset offset, - bool fin, + StreamSendingState fin, QuicReferenceCountedPointer<QuicAckListenerInterface>)); MOCK_METHOD3(SendRstStream, void(QuicStreamId stream_id, @@ -101,7 +107,7 @@ void(QuicStreamId stream_id, QuicStreamId promised_stream_id, size_t frame_len)); - MOCK_METHOD0(IsCryptoHandshakeConfirmed, bool()); + MOCK_CONST_METHOD0(IsCryptoHandshakeConfirmed, bool()); // Methods taking non-copyable types like SpdyHeaderBlock by value cannot be // mocked directly. size_t WriteHeaders(QuicStreamId id,
diff --git a/net/quic/chromium/quic_http_stream.cc b/net/quic/chromium/quic_http_stream.cc index 56672ba5..7f96c3e 100644 --- a/net/quic/chromium/quic_http_stream.cc +++ b/net/quic/chromium/quic_http_stream.cc
@@ -141,8 +141,6 @@ switch (quic_version) { case QUIC_VERSION_UNSUPPORTED: return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION; - case QUIC_VERSION_34: - return HttpResponseInfo::CONNECTION_INFO_QUIC_34; case QUIC_VERSION_35: return HttpResponseInfo::CONNECTION_INFO_QUIC_35; case QUIC_VERSION_36:
diff --git a/net/quic/chromium/quic_network_transaction_unittest.cc b/net/quic/chromium/quic_network_transaction_unittest.cc index 7feab3fb..3dbe3b9 100644 --- a/net/quic/chromium/quic_network_transaction_unittest.cc +++ b/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -3976,7 +3976,6 @@ } TEST_P(QuicNetworkTransactionTest, QuicForceHolBlocking) { - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true; params_.quic_force_hol_blocking = true; params_.origins_to_force_quic_on.insert( HostPortPair::FromString("mail.example.org:443"));
diff --git a/net/quic/chromium/quic_server_info.cc b/net/quic/chromium/quic_server_info.cc index 23f4cf8a..3e53fa5 100644 --- a/net/quic/chromium/quic_server_info.cc +++ b/net/quic/chromium/quic_server_info.cc
@@ -146,6 +146,4 @@ return string(reinterpret_cast<const char*>(p.data()), p.size()); } -QuicServerInfoFactory::~QuicServerInfoFactory() {} - } // namespace net
diff --git a/net/quic/chromium/quic_server_info.h b/net/quic/chromium/quic_server_info.h index eab5366..a818576 100644 --- a/net/quic/chromium/quic_server_info.h +++ b/net/quic/chromium/quic_server_info.h
@@ -24,20 +24,6 @@ // crypto config. class QUIC_EXPORT_PRIVATE QuicServerInfo { public: - // Enum to track number of times data read/parse/write API calls of - // QuicServerInfo to and from disk cache is called. - enum QuicServerInfoAPICall { - QUIC_SERVER_INFO_START = 0, - QUIC_SERVER_INFO_WAIT_FOR_DATA_READY = 1, - QUIC_SERVER_INFO_PARSE = 2, - QUIC_SERVER_INFO_WAIT_FOR_DATA_READY_CANCEL = 3, - QUIC_SERVER_INFO_READY_TO_PERSIST = 4, - QUIC_SERVER_INFO_PERSIST = 5, - QUIC_SERVER_INFO_EXTERNAL_CACHE_HIT = 6, - QUIC_SERVER_INFO_RESET_WAIT_FOR_DATA_READY = 7, - QUIC_SERVER_INFO_NUM_OF_API_CALLS = 8, - }; - // Enum to track failure reasons to read/load/write of QuicServerInfo to // and from disk cache. enum FailureReason { @@ -59,49 +45,13 @@ explicit QuicServerInfo(const QuicServerId& server_id); virtual ~QuicServerInfo(); - // Start will commence the lookup. This must be called before any other - // methods. By opportunistically calling this early, it may be possible to - // overlap this object's lookup and reduce latency. - virtual void Start() = 0; + // Fetches the server config from the backing store, and returns true + // if the server config was found. + virtual bool Load() = 0; - // WaitForDataReady returns OK if the fetch of the requested data has - // completed. Otherwise it returns ERR_IO_PENDING and will call |callback| on - // the current thread when ready. - // - // Only a single callback can be outstanding at a given time and, in the - // event that WaitForDataReady returns OK, it's the caller's responsibility - // to delete |callback|. - // - // |callback| may be NULL, in which case ERR_IO_PENDING may still be returned - // but, obviously, a callback will never be made. - virtual int WaitForDataReady(const CompletionCallback& callback) = 0; - - // Reset's WaitForDataReady callback. This method shouldn't have any side - // effects (could be called even if HttpCache doesn't exist). - virtual void ResetWaitForDataReadyCallback() = 0; - - // Cancel's WaitForDataReady callback. |callback| passed in WaitForDataReady - // will not be called. - virtual void CancelWaitForDataReadyCallback() = 0; - - // Returns true if data is loaded from disk cache and ready (WaitForDataReady - // doesn't have a pending callback). - virtual bool IsDataReady() = 0; - - // Returns true if the object is ready to persist data, in other words, if - // data is loaded from disk cache and ready and there are no pending writes. - virtual bool IsReadyToPersist() = 0; - - // Persist allows for the server information to be updated for future users. - // This is a fire and forget operation: the caller may drop its reference - // from this object and the store operation will still complete. This can - // only be called once WaitForDataReady has returned OK or called its - // callback. + // Persist allows for the server information to be updated for future uses. virtual void Persist() = 0; - // Called whenever an external cache reuses quic server config. - virtual void OnExternalCacheHit() = 0; - // Returns the size of dynamically allocated memory in bytes. virtual size_t EstimateMemoryUsage() const = 0; @@ -129,14 +79,6 @@ const State& state() const; State* mutable_state(); - base::TimeTicks wait_for_data_start_time() const { - return wait_for_data_start_time_; - } - - base::TimeTicks wait_for_data_end_time() const { - return wait_for_data_end_time_; - } - protected: // Parse parses pickled data and fills out the public member fields of this // object. It returns true iff the parse was successful. The public member @@ -146,10 +88,6 @@ State state_; - // Time when WaitForDataReady was called and when it has finished. - base::TimeTicks wait_for_data_start_time_; - base::TimeTicks wait_for_data_end_time_; - // This is the QUIC server (hostname, port, is_https, privacy_mode) tuple for // which we restore the crypto_config. const QuicServerId server_id_; @@ -164,20 +102,6 @@ DISALLOW_COPY_AND_ASSIGN(QuicServerInfo); }; -class QUIC_EXPORT_PRIVATE QuicServerInfoFactory { - public: - QuicServerInfoFactory() {} - virtual ~QuicServerInfoFactory(); - - // GetForServer returns a fresh, allocated QuicServerInfo for the given - // |server_id| or NULL on failure. - virtual std::unique_ptr<QuicServerInfo> GetForServer( - const QuicServerId& server_id) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(QuicServerInfoFactory); -}; - } // namespace net #endif // NET_QUIC_CHROMIUM_QUIC_SERVER_INFO_H_
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc index c3bd2fb..e334ede4 100644 --- a/net/quic/chromium/quic_stream_factory.cc +++ b/net/quic/chromium/quic_stream_factory.cc
@@ -51,8 +51,8 @@ #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/quic_client_promised_info.h" #include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/platform/api/quic_clock.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/socket/client_socket_factory.h" #include "net/socket/next_proto.h" #include "net/socket/socket_performance_watcher.h" @@ -331,16 +331,8 @@ const QuicSessionKey& key, bool was_alternative_service_recently_broken, int cert_verify_flags, - std::unique_ptr<QuicServerInfo> server_info, const NetLogWithSource& net_log); - // Creates a new job to handle the resumption of for connecting an - // existing session. - Job(QuicStreamFactory* factory, - HostResolver* host_resolver, - QuicChromiumClientSession* session, - const QuicSessionKey& key); - ~Job(); int Run(const CompletionCallback& callback); @@ -348,19 +340,13 @@ int DoLoop(int rv); int DoResolveHost(); int DoResolveHostComplete(int rv); - int DoLoadServerInfo(); - int DoLoadServerInfoComplete(int rv); int DoConnect(); int DoConnectComplete(int rv); void OnIOComplete(int rv); - void RunAuxilaryJob(); - void Cancel(); - void CancelWaitForDataReadyCallback(); - const QuicSessionKey& key() const { return key_; } const NetLogWithSource& net_log() const { return net_log_; } @@ -375,8 +361,6 @@ STATE_NONE, STATE_RESOLVE_HOST, STATE_RESOLVE_HOST_COMPLETE, - STATE_LOAD_SERVER_INFO, - STATE_LOAD_SERVER_INFO_COMPLETE, STATE_CONNECT, STATE_CONNECT_COMPLETE, }; @@ -388,8 +372,6 @@ const QuicSessionKey key_; const int cert_verify_flags_; const bool was_alternative_service_recently_broken_; - std::unique_ptr<QuicServerInfo> server_info_; - bool started_another_job_; const NetLogWithSource net_log_; int num_sent_client_hellos_; QuicChromiumClientSession* session_; @@ -406,7 +388,6 @@ const QuicSessionKey& key, bool was_alternative_service_recently_broken, int cert_verify_flags, - std::unique_ptr<QuicServerInfo> server_info, const NetLogWithSource& net_log) : io_state_(STATE_RESOLVE_HOST), factory_(factory), @@ -415,8 +396,6 @@ cert_verify_flags_(cert_verify_flags), was_alternative_service_recently_broken_( was_alternative_service_recently_broken), - server_info_(std::move(server_info)), - started_another_job_(false), net_log_( NetLogWithSource::Make(net_log.net_log(), NetLogSourceType::QUIC_STREAM_FACTORY_JOB)), @@ -438,10 +417,6 @@ QuicStreamFactory::Job::~Job() { net_log_.EndEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB); DCHECK(callback_.is_null()); - - // If disk cache has a pending WaitForDataReadyCallback, cancel that callback. - if (server_info_) - server_info_->ResetWaitForDataReadyCallback(); } int QuicStreamFactory::Job::Run(const CompletionCallback& callback) { @@ -465,13 +440,6 @@ case STATE_RESOLVE_HOST_COMPLETE: rv = DoResolveHostComplete(rv); break; - case STATE_LOAD_SERVER_INFO: - CHECK_EQ(OK, rv); - rv = DoLoadServerInfo(); - break; - case STATE_LOAD_SERVER_INFO_COMPLETE: - rv = DoLoadServerInfoComplete(rv); - break; case STATE_CONNECT: CHECK_EQ(OK, rv); rv = DoConnect(); @@ -493,13 +461,6 @@ base::ResetAndReturn(&callback_).Run(rv); } -void QuicStreamFactory::Job::RunAuxilaryJob() { - int rv = Run(base::Bind(&QuicStreamFactory::OnJobComplete, - base::Unretained(factory_), this)); - if (rv != ERR_IO_PENDING) - factory_->OnJobComplete(this, rv); -} - void QuicStreamFactory::Job::Cancel() { callback_.Reset(); if (session_) @@ -508,24 +469,12 @@ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); } -void QuicStreamFactory::Job::CancelWaitForDataReadyCallback() { - // If we are waiting for WaitForDataReadyCallback, then cancel the callback. - if (io_state_ != STATE_LOAD_SERVER_INFO_COMPLETE) - return; - server_info_->CancelWaitForDataReadyCallback(); - OnIOComplete(OK); -} - size_t QuicStreamFactory::Job::EstimateMemoryUsage() const { - return base::trace_event::EstimateMemoryUsage(key_) + - base::trace_event::EstimateMemoryUsage(server_info_); + return base::trace_event::EstimateMemoryUsage(key_); } int QuicStreamFactory::Job::DoResolveHost() { dns_resolution_start_time_ = base::TimeTicks::Now(); - // Start loading the data now, and wait for it after we resolve the host. - if (server_info_) - server_info_->Start(); io_state_ = STATE_RESOLVE_HOST_COMPLETE; return host_resolver_->Resolve( @@ -547,71 +496,6 @@ if (factory_->OnResolution(key_, address_list_)) return OK; - if (server_info_) - io_state_ = STATE_LOAD_SERVER_INFO; - else - io_state_ = STATE_CONNECT; - return OK; -} - -int QuicStreamFactory::Job::DoLoadServerInfo() { - net_log_.BeginEvent( - NetLogEventType::QUIC_STREAM_FACTORY_JOB_LOAD_SERVER_INFO); - - io_state_ = STATE_LOAD_SERVER_INFO_COMPLETE; - - DCHECK(server_info_); - - // To mitigate the effects of disk cache taking too long to load QUIC server - // information, set up a timer to cancel WaitForDataReady's callback. - if (factory_->load_server_info_timeout_srtt_multiplier_ > 0) { - const int kMaxLoadServerInfoTimeoutMs = 50; - // Wait for DiskCache a maximum of 50ms. - int64_t load_server_info_timeout_ms = - std::min(static_cast<int>( - (factory_->load_server_info_timeout_srtt_multiplier_ * - factory_->GetServerNetworkStatsSmoothedRttInMicroseconds( - key_.server_id())) / - 1000), - kMaxLoadServerInfoTimeoutMs); - if (load_server_info_timeout_ms > 0) { - factory_->task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&QuicStreamFactory::Job::CancelWaitForDataReadyCallback, - GetWeakPtr()), - base::TimeDelta::FromMilliseconds(load_server_info_timeout_ms)); - } - } - - int rv = server_info_->WaitForDataReady( - base::Bind(&QuicStreamFactory::Job::OnIOComplete, GetWeakPtr())); - if (rv == ERR_IO_PENDING && factory_->enable_connection_racing()) { - // If we are waiting to load server config from the disk cache, then start - // another job. - started_another_job_ = true; - factory_->CreateAuxilaryJob(key_, cert_verify_flags_, net_log_); - } - return rv; -} - -int QuicStreamFactory::Job::DoLoadServerInfoComplete(int rv) { - net_log_.EndEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB_LOAD_SERVER_INFO); - UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheWaitForDataReadyTime", - base::TimeTicks::Now() - dns_resolution_end_time_); - - if (rv != OK) - server_info_.reset(); - - if (started_another_job_ && - (!server_info_ || server_info_->state().server_config.empty() || - !factory_->CryptoConfigCacheIsEmpty(key_.server_id()))) { - // If we have started another job and if we didn't load the server config - // from the disk cache or if we have received a new server config from the - // server, then cancel the current job. - io_state_ = STATE_NONE; - return ERR_CONNECTION_CLOSED; - } - io_state_ = STATE_CONNECT; return OK; } @@ -625,10 +509,10 @@ NetLogEventType::QUIC_STREAM_FACTORY_JOB_CONNECT, NetLog::BoolCallback("require_confirmation", require_confirmation)); - int rv = factory_->CreateSession( - key_, cert_verify_flags_, std::move(server_info_), require_confirmation, - address_list_, dns_resolution_start_time_, dns_resolution_end_time_, - net_log_, &session_); + int rv = + factory_->CreateSession(key_, cert_verify_flags_, require_confirmation, + address_list_, dns_resolution_start_time_, + dns_resolution_end_time_, net_log_, &session_); if (rv != OK) { DCHECK(rv != ERR_IO_PENDING); DCHECK(!session_); @@ -771,12 +655,8 @@ size_t max_packet_length, const std::string& user_agent_id, const QuicVersionVector& supported_versions, - float load_server_info_timeout_srtt_multiplier, - bool enable_connection_racing, bool enable_non_blocking_io, - bool disable_disk_cache, - bool delay_tcp_race, - int max_server_configs_stored_in_properties, + bool store_server_configs_in_properties, bool close_sessions_on_ip_change, bool mark_quic_broken_when_network_blackholes, int idle_connection_timeout_seconds, @@ -814,14 +694,10 @@ transport_security_state, cert_transparency_verifier))), supported_versions_(supported_versions), - load_server_info_timeout_srtt_multiplier_( - load_server_info_timeout_srtt_multiplier), - enable_connection_racing_(enable_connection_racing), enable_non_blocking_io_(enable_non_blocking_io), - disable_disk_cache_(disable_disk_cache), mark_quic_broken_when_network_blackholes_( mark_quic_broken_when_network_blackholes), - delay_tcp_race_(delay_tcp_race), + store_server_configs_in_properties_(store_server_configs_in_properties), ping_timeout_(QuicTime::Delta::FromSeconds(kPingTimeoutSecs)), reduced_ping_timeout_( QuicTime::Delta::FromSeconds(reduced_ping_timeout_seconds)), @@ -840,7 +716,6 @@ do_not_fragment_(do_not_fragment), estimate_initial_rtt(estimate_initial_rtt), check_persisted_supports_quic_(true), - has_initialized_data_(false), num_push_streams_created_(0), task_runner_(nullptr), ssl_config_service_(ssl_config_service), @@ -868,13 +743,6 @@ has_aes_hardware_support); if (has_aes_hardware_support) crypto_config_.PreferAesGcm(); - // When disk cache is used to store the server configs, HttpCache code calls - // |set_quic_server_info_factory| if |quic_server_info_factory_| wasn't - // created. - if (max_server_configs_stored_in_properties > 0) { - quic_server_info_factory_.reset( - new PropertiesBasedQuicServerInfoFactory(http_server_properties_)); - } // migrate_sessions_early should only be set to true if // migrate_sessions_on_network_change is set to true. @@ -919,8 +787,9 @@ base::TimeDelta QuicStreamFactory::GetTimeDelayForWaitingJob( const QuicServerId& server_id) { - if (!delay_tcp_race_ || require_confirmation_) + if (require_confirmation_) return base::TimeDelta(); + int64_t srtt = 1.5 * GetServerNetworkStatsSmoothedRttInMicroseconds(server_id); // Picked 300ms based on mean time from @@ -931,11 +800,6 @@ return base::TimeDelta::FromMicroseconds(srtt); } -void QuicStreamFactory::set_quic_server_info_factory( - QuicServerInfoFactory* quic_server_info_factory) { - quic_server_info_factory_.reset(quic_server_info_factory); -} - void QuicStreamFactory::DumpMemoryStats( base::trace_event::ProcessMemoryDump* pmd, const std::string& parent_absolute_name) const { @@ -1070,25 +934,12 @@ if (!task_runner_) task_runner_ = base::ThreadTaskRunnerHandle::Get().get(); - std::unique_ptr<QuicServerInfo> quic_server_info; - if (quic_server_info_factory_.get()) { - bool load_from_disk_cache = !disable_disk_cache_; - MaybeInitialize(); - if (!base::ContainsKey(quic_supported_servers_at_startup_, destination)) { - // If there is no entry for QUIC, consider that as a new server and - // don't wait for Cache thread to load the data for that server. - load_from_disk_cache = false; - } - if (load_from_disk_cache && CryptoConfigCacheIsEmpty(server_id)) - quic_server_info = quic_server_info_factory_->GetForServer(server_id); - } - ignore_result(StartCertVerifyJob(server_id, cert_verify_flags, net_log)); QuicSessionKey key(destination, server_id); std::unique_ptr<Job> job = base::MakeUnique<Job>( this, host_resolver_, key, WasQuicRecentlyBroken(server_id), - cert_verify_flags, std::move(quic_server_info), net_log); + cert_verify_flags, net_log); int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete, base::Unretained(this), job.get())); if (rv == ERR_IO_PENDING) { @@ -1134,18 +985,6 @@ EstimateServerIdMemoryUsage(server_id_); } -void QuicStreamFactory::CreateAuxilaryJob(const QuicSessionKey& key, - int cert_verify_flags, - const NetLogWithSource& net_log) { - Job* aux_job = - new Job(this, host_resolver_, key, WasQuicRecentlyBroken(key.server_id()), - cert_verify_flags, nullptr, net_log); - active_jobs_[key.server_id()][aux_job] = base::WrapUnique(aux_job); - task_runner_->PostTask(FROM_HERE, - base::Bind(&QuicStreamFactory::Job::RunAuxilaryJob, - aux_job->GetWeakPtr())); -} - bool QuicStreamFactory::OnResolution(const QuicSessionKey& key, const AddressList& address_list) { const QuicServerId& server_id(key.server_id()); @@ -1644,7 +1483,6 @@ int QuicStreamFactory::CreateSession( const QuicSessionKey& key, int cert_verify_flags, - std::unique_ptr<QuicServerInfo> server_info, bool require_confirmation, const AddressList& address_list, base::TimeTicks dns_resolution_start_time, @@ -1673,7 +1511,13 @@ alarm_factory_.reset(new QuicChromiumAlarmFactory( base::ThreadTaskRunnerHandle::Get().get(), clock_)); } + QuicConnectionId connection_id = random_generator_->RandUint64(); + std::unique_ptr<QuicServerInfo> server_info; + if (store_server_configs_in_properties_) { + server_info = base::MakeUnique<PropertiesBasedQuicServerInfo>( + server_id, http_server_properties_); + } InitializeCachedStateInCryptoConfig(server_id, server_info, &connection_id); QuicChromiumPacketWriter* writer = new QuicChromiumPacketWriter(socket.get()); @@ -1685,7 +1529,6 @@ connection->SetMaxPacketLength(max_packet_length_); QuicConfig config = config_; - config.SetSocketReceiveBufferToSend(kQuicSocketReceiveBufferSize); config.set_max_undecryptable_packets(kMaxUndecryptablePackets); config.SetInitialSessionFlowControlWindowToSend( kQuicSessionMaxRecvWindowSize); @@ -1696,14 +1539,6 @@ if (force_hol_blocking_) config.SetForceHolBlocking(); - if (quic_server_info_factory_.get() && !server_info) { - // Start the disk cache loading so that we can persist the newer QUIC server - // information and/or inform the disk cache that we have reused - // |server_info|. - server_info = quic_server_info_factory_->GetForServer(server_id); - server_info->Start(); - } - // Use the factory to create a new socket performance watcher, and pass the // ownership to QuicChromiumClientSession. std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher; @@ -1846,20 +1681,9 @@ if (!cached->IsEmpty()) return; - // |server_info| will be NULL, if a non-empty server config already exists in - // the memory cache. - if (!server_info) + if (!server_info || !server_info->Load()) return; - // TODO(rtenneti): Delete the following histogram after collecting stats. - // If the AlternativeServiceMap contained an entry for this host, check if - // the disk cache contained an entry for it. - if (base::ContainsKey(quic_supported_servers_at_startup_, - server_id.host_port_pair())) { - UMA_HISTOGRAM_BOOLEAN("Net.QuicServerInfo.ExpectConfigMissingFromDiskCache", - server_info->state().server_config.empty()); - } - cached->Initialize(server_info->state().server_config, server_info->state().source_address_token, server_info->state().certs, server_info->state().cert_sct, @@ -1868,60 +1692,6 @@ QuicWallTime::Zero()); } -void QuicStreamFactory::MaybeInitialize() { - // We don't initialize data from HttpServerProperties in the constructor - // because HttpServerProperties has not yet initialized. We're guaranteed - // HttpServerProperties has been initialized by the first time a request is - // made. - if (has_initialized_data_) - return; - - has_initialized_data_ = true; - - // Query the proxy delegate for the default alternative proxy server. - ProxyServer default_alternative_proxy_server = - proxy_delegate_ ? proxy_delegate_->GetDefaultAlternativeProxy() - : ProxyServer(); - if (default_alternative_proxy_server.is_quic()) { - quic_supported_servers_at_startup_.insert( - default_alternative_proxy_server.host_port_pair()); - } - - for (const std::pair<const url::SchemeHostPort, AlternativeServiceInfoVector>& - key_value : http_server_properties_->alternative_service_map()) { - HostPortPair host_port_pair(key_value.first.host(), key_value.first.port()); - for (const AlternativeServiceInfo& alternative_service_info : - key_value.second) { - if (alternative_service_info.alternative_service.protocol == kProtoQUIC) { - quic_supported_servers_at_startup_.insert(host_port_pair); - break; - } - } - } - - if (http_server_properties_->max_server_configs_stored_in_properties() == 0) - return; - // Create a temporary QuicServerInfo object to deserialize and to populate the - // in-memory crypto server config cache in the MRU order. - std::unique_ptr<QuicServerInfo> server_info; - CompletionCallback callback; - // Get the list of servers to be deserialized first because WaitForDataReady - // touches quic_server_info_map. - const QuicServerInfoMap& quic_server_info_map = - http_server_properties_->quic_server_info_map(); - std::vector<QuicServerId> server_list; - for (const auto& key_value : quic_server_info_map) - server_list.push_back(key_value.first); - for (auto it = server_list.rbegin(); it != server_list.rend(); ++it) { - const QuicServerId& server_id = *it; - server_info = quic_server_info_factory_->GetForServer(server_id); - if (server_info->WaitForDataReady(callback) == OK) { - DVLOG(1) << "Initialized server config for: " << server_id.ToString(); - InitializeCachedStateInCryptoConfig(server_id, server_info, nullptr); - } - } -} - void QuicStreamFactory::ProcessGoingAwaySession( QuicChromiumClientSession* session, const QuicServerId& server_id,
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h index 6606f7c4..661cfeb 100644 --- a/net/quic/chromium/quic_stream_factory.h +++ b/net/quic/chromium/quic_stream_factory.h
@@ -66,7 +66,6 @@ class QuicCryptoClientStreamFactory; class QuicRandom; class QuicServerInfo; -class QuicServerInfoFactory; class QuicStreamFactory; class SocketPerformanceWatcherFactory; class TransportSecurityState; @@ -208,12 +207,8 @@ size_t max_packet_length, const std::string& user_agent_id, const QuicVersionVector& supported_versions, - float load_server_info_timeout_srtt_multiplier, - bool enable_connection_racing, bool enable_non_blocking_io, - bool disable_disk_cache, - bool delay_tcp_race, - int max_server_configs_stored_in_properties, + bool store_server_configs_in_properties, bool close_sessions_on_ip_change, bool mark_quic_broken_when_network_blackholes, int idle_connection_timeout_seconds, @@ -369,28 +364,10 @@ QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); } - bool has_quic_server_info_factory() const { - return quic_server_info_factory_.get() != nullptr; - } - - QuicServerInfoFactory* quic_server_info_factory() const { - return quic_server_info_factory_.get(); - } - - void set_quic_server_info_factory( - QuicServerInfoFactory* quic_server_info_factory); - void set_server_push_delegate(ServerPushDelegate* push_delegate) { push_delegate_ = push_delegate; } - bool enable_connection_racing() const { return enable_connection_racing_; } - void set_enable_connection_racing(bool enable_connection_racing) { - enable_connection_racing_ = enable_connection_racing; - } - - bool delay_tcp_race() const { return delay_tcp_race_; } - bool migrate_sessions_on_network_change() const { return migrate_sessions_on_network_change_; } @@ -423,12 +400,6 @@ typedef std::map<QuicServerId, std::unique_ptr<CertVerifierJob>> CertVerifierJobMap; - // Creates a job which doesn't wait for server config to be loaded from the - // disk cache. This job is started via a PostTask. - void CreateAuxilaryJob(const QuicSessionKey& key, - int cert_verify_flags, - const NetLogWithSource& net_log); - // Returns a newly created QuicHttpStream owned by the caller. std::unique_ptr<QuicHttpStream> CreateFromSession( QuicChromiumClientSession* session); @@ -441,7 +412,6 @@ bool HasActiveCertVerifierJob(const QuicServerId& server_id) const; int CreateSession(const QuicSessionKey& key, int cert_verify_flags, - std::unique_ptr<QuicServerInfo> quic_server_info, bool require_confirmation, const AddressList& address_list, base::TimeTicks dns_resolution_start_time, @@ -487,11 +457,6 @@ const std::unique_ptr<QuicServerInfo>& server_info, QuicConnectionId* connection_id); - // Initialize |quic_supported_servers_at_startup_| with the list of servers - // that supported QUIC at start up and also initialize in-memory cache of - // QuicServerInfo objects from HttpServerProperties. - void MaybeInitialize(); - void ProcessGoingAwaySession(QuicChromiumClientSession* session, const QuicServerId& server_id, bool was_session_active); @@ -516,7 +481,6 @@ ProxyDelegate* proxy_delegate_; TransportSecurityState* transport_security_state_; CTVerifier* cert_transparency_verifier_; - std::unique_ptr<QuicServerInfoFactory> quic_server_info_factory_; QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory_; QuicRandom* random_generator_; // Unowned. QuicClock* clock_; // Unowned. @@ -561,29 +525,15 @@ const QuicVersionVector supported_versions_; - // Specifies the ratio between time to load QUIC server information from disk - // cache to 'smoothed RTT'. This ratio is used to calculate the timeout in - // milliseconds to wait for loading of QUIC server information. If we don't - // want to timeout, set |load_server_info_timeout_srtt_multiplier_| to 0. - float load_server_info_timeout_srtt_multiplier_; - - // Set if we want to race connections - one connection that sends - // INCHOATE_HELLO and another connection that sends CHLO after loading server - // config from the disk cache. - bool enable_connection_racing_; - // Set if experimental non-blocking IO should be used on windows sockets. bool enable_non_blocking_io_; - // Set if we do not want to load server config from the disk cache. - bool disable_disk_cache_; - // True if QUIC should be marked as broken when a connection blackholes after // the handshake is confirmed. bool mark_quic_broken_when_network_blackholes_; - // Set if we do want to delay TCP connection when it is racing with QUIC. - bool delay_tcp_race_; + // Set if QUIC server configs should be stored in HttpServerProperties. + bool store_server_configs_in_properties_; // PING timeout for connections. QuicTime::Delta ping_timeout_; @@ -625,8 +575,6 @@ // Local address of socket that was created in CreateSession. IPEndPoint local_address_; bool check_persisted_supports_quic_; - bool has_initialized_data_; - std::set<HostPortPair> quic_supported_servers_at_startup_; NetworkConnection network_connection_;
diff --git a/net/quic/chromium/quic_stream_factory_peer.cc b/net/quic/chromium/quic_stream_factory_peer.cc index 6352df9..d5f4b5c 100644 --- a/net/quic/chromium/quic_stream_factory_peer.cc +++ b/net/quic/chromium/quic_stream_factory_peer.cc
@@ -80,15 +80,6 @@ return factory->ping_timeout_; } -bool QuicStreamFactoryPeer::GetDelayTcpRace(QuicStreamFactory* factory) { - return factory->delay_tcp_race_; -} - -void QuicStreamFactoryPeer::SetDelayTcpRace(QuicStreamFactory* factory, - bool delay_tcp_race) { - factory->delay_tcp_race_ = delay_tcp_race; -} - bool QuicStreamFactoryPeer::GetRaceCertVerification( QuicStreamFactory* factory) { return factory->race_cert_verification_; @@ -128,20 +119,6 @@ return it->second.size(); } -void QuicStreamFactoryPeer::MaybeInitialize(QuicStreamFactory* factory) { - factory->MaybeInitialize(); -} - -bool QuicStreamFactoryPeer::HasInitializedData(QuicStreamFactory* factory) { - return factory->has_initialized_data_; -} - -bool QuicStreamFactoryPeer::SupportsQuicAtStartUp(QuicStreamFactory* factory, - HostPortPair host_port_pair) { - return base::ContainsKey(factory->quic_supported_servers_at_startup_, - host_port_pair); -} - bool QuicStreamFactoryPeer::CryptoConfigCacheIsEmpty( QuicStreamFactory* factory, const QuicServerId& quic_server_id) {
diff --git a/net/quic/chromium/quic_stream_factory_peer.h b/net/quic/chromium/quic_stream_factory_peer.h index 822b78f..c2d3be9e 100644 --- a/net/quic/chromium/quic_stream_factory_peer.h +++ b/net/quic/chromium/quic_stream_factory_peer.h
@@ -60,10 +60,6 @@ static QuicTime::Delta GetPingTimeout(QuicStreamFactory* factory); - static bool GetDelayTcpRace(QuicStreamFactory* factory); - - static void SetDelayTcpRace(QuicStreamFactory* factory, bool delay_tcp_race); - static bool GetRaceCertVerification(QuicStreamFactory* factory); static void SetRaceCertVerification(QuicStreamFactory* factory, @@ -83,13 +79,6 @@ static size_t GetNumberOfActiveJobs(QuicStreamFactory* factory, const QuicServerId& server_id); - static void MaybeInitialize(QuicStreamFactory* factory); - - static bool HasInitializedData(QuicStreamFactory* factory); - - static bool SupportsQuicAtStartUp(QuicStreamFactory* factory, - HostPortPair host_port_pair); - static bool CryptoConfigCacheIsEmpty(QuicStreamFactory* factory, const QuicServerId& quic_server_id);
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc index 4422c2d..a426a10 100644 --- a/net/quic/chromium/quic_stream_factory_test.cc +++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -101,23 +101,18 @@ // and enable_connection_racting. struct TestParams { friend std::ostream& operator<<(std::ostream& os, const TestParams& p) { - os << "{ version: " << QuicVersionToString(p.version) - << ", enable_connection_racing: " - << (p.enable_connection_racing ? "true" : "false") << " }"; + os << "{ version: " << QuicVersionToString(p.version) << " }"; return os; } QuicVersion version; - bool enable_connection_racing; }; std::vector<TestParams> GetTestParams() { std::vector<TestParams> params; QuicVersionVector all_supported_versions = AllSupportedVersions(); - for (const QuicVersion version : all_supported_versions) { - params.push_back(TestParams{version, false}); - params.push_back(TestParams{version, true}); - } + for (const auto& version : all_supported_versions) + params.push_back(TestParams{version}); return params; } @@ -127,8 +122,6 @@ friend std::ostream& operator<<(std::ostream& os, const PoolingTestParams& p) { os << "{ version: " << QuicVersionToString(p.version) - << ", enable_connection_racing: " - << (p.enable_connection_racing ? "true" : "false") << ", destination_type: "; switch (p.destination_type) { case SAME_AS_FIRST: @@ -146,7 +139,6 @@ } QuicVersion version; - bool enable_connection_racing; DestinationType destination_type; }; @@ -154,12 +146,9 @@ std::vector<PoolingTestParams> params; QuicVersionVector all_supported_versions = AllSupportedVersions(); for (const QuicVersion version : all_supported_versions) { - params.push_back(PoolingTestParams{version, false, SAME_AS_FIRST}); - params.push_back(PoolingTestParams{version, false, SAME_AS_SECOND}); - params.push_back(PoolingTestParams{version, false, DIFFERENT}); - params.push_back(PoolingTestParams{version, true, SAME_AS_FIRST}); - params.push_back(PoolingTestParams{version, true, SAME_AS_SECOND}); - params.push_back(PoolingTestParams{version, true, DIFFERENT}); + params.push_back(PoolingTestParams{version, SAME_AS_FIRST}); + params.push_back(PoolingTestParams{version, SAME_AS_SECOND}); + params.push_back(PoolingTestParams{version, DIFFERENT}); } return params; } @@ -173,50 +162,9 @@ } }; -class MockQuicServerInfo : public QuicServerInfo { - public: - explicit MockQuicServerInfo(const QuicServerId& server_id) - : QuicServerInfo(server_id) {} - ~MockQuicServerInfo() override {} - - void Start() override {} - - int WaitForDataReady(const CompletionCallback& callback) override { - return ERR_IO_PENDING; - } - - void ResetWaitForDataReadyCallback() override {} - - void CancelWaitForDataReadyCallback() override {} - - bool IsDataReady() override { return false; } - - bool IsReadyToPersist() override { return false; } - - void Persist() override {} - - void OnExternalCacheHit() override {} - - size_t EstimateMemoryUsage() const override { - NOTREACHED(); - return 0; - } -}; - -class MockQuicServerInfoFactory : public QuicServerInfoFactory { - public: - MockQuicServerInfoFactory() {} - ~MockQuicServerInfoFactory() override {} - - std::unique_ptr<QuicServerInfo> GetForServer( - const QuicServerId& server_id) override { - return base::MakeUnique<MockQuicServerInfo>(server_id); - } -}; - class QuicStreamFactoryTestBase { protected: - QuicStreamFactoryTestBase(QuicVersion version, bool enable_connection_racing) + explicit QuicStreamFactoryTestBase(QuicVersion version) : ssl_config_service_(new MockSSLConfigService), random_generator_(0), runner_(new TestTaskRunner(&clock_)), @@ -243,11 +191,7 @@ url3_(kServer3Url), url4_(kServer4Url), privacy_mode_(PRIVACY_MODE_DISABLED), - load_server_info_timeout_srtt_multiplier_(0.0f), - enable_connection_racing_(enable_connection_racing), enable_non_blocking_io_(true), - disable_disk_cache_(false), - delay_tcp_race_(true), close_sessions_on_ip_change_(false), idle_connection_timeout_seconds_(kIdleConnectionTimeoutSeconds), reduced_ping_timeout_seconds_(kPingTimeoutSecs), @@ -272,9 +216,7 @@ /*SocketPerformanceWatcherFactory*/ nullptr, &crypto_client_stream_factory_, &random_generator_, &clock_, kDefaultMaxPacketSize, string(), SupportedVersions(version_), - load_server_info_timeout_srtt_multiplier_, enable_connection_racing_, - enable_non_blocking_io_, disable_disk_cache_, delay_tcp_race_, - /*max_server_configs_stored_in_properties*/ 0, + enable_non_blocking_io_, store_server_configs_in_properties_, close_sessions_on_ip_change_, /*mark_quic_broken_when_network_blackholes*/ false, idle_connection_timeout_seconds_, reduced_ping_timeout_seconds_, @@ -284,9 +226,6 @@ /*do_not_fragment*/ true, estimate_initial_rtt_, QuicTagVector(), /*enable_token_binding*/ false)); factory_->set_require_confirmation(false); - EXPECT_FALSE(factory_->has_quic_server_info_factory()); - factory_->set_quic_server_info_factory(new MockQuicServerInfoFactory()); - EXPECT_TRUE(factory_->has_quic_server_info_factory()); } void InitializeConnectionMigrationTest( @@ -542,10 +481,14 @@ // a non proxy server that support alternative services is added to the // HttpServerProperties map. void VerifyInitialization(bool proxy_delegate_provides_quic_supported_proxy) { + store_server_configs_in_properties_ = true; idle_connection_timeout_seconds_ = 500; Initialize(); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + crypto_client_stream_factory_.set_handshake_mode( + MockCryptoClientStream::ZERO_RTT); const QuicConfig* config = QuicStreamFactoryPeer::GetConfig(factory_.get()); EXPECT_EQ(500, config->IdleNetworkTimeout().ToSeconds()); @@ -585,14 +528,11 @@ http_server_properties_.SetMaxServerConfigsStoredInProperties( kMaxQuicServersToPersist); - QuicServerId quic_server_id(kDefaultServerHostName, 80, + QuicServerId quic_server_id(kDefaultServerHostName, 443, PRIVACY_MODE_DISABLED); - QuicServerInfoFactory* quic_server_info_factory = - new PropertiesBasedQuicServerInfoFactory(&http_server_properties_); - factory_->set_quic_server_info_factory(quic_server_info_factory); - - std::unique_ptr<QuicServerInfo> quic_server_info( - quic_server_info_factory->GetForServer(quic_server_id)); + std::unique_ptr<QuicServerInfo> quic_server_info = + base::MakeUnique<PropertiesBasedQuicServerInfo>( + quic_server_id, &http_server_properties_); // Update quic_server_info's server_config and persist it. QuicServerInfo::State* state = quic_server_info->mutable_state(); @@ -628,10 +568,10 @@ quic_server_info->Persist(); - QuicServerId quic_server_id2(kServer2HostName, 80, PRIVACY_MODE_DISABLED); - std::unique_ptr<QuicServerInfo> quic_server_info2( - quic_server_info_factory->GetForServer(quic_server_id2)); - + QuicServerId quic_server_id2(kServer2HostName, 443, PRIVACY_MODE_DISABLED); + std::unique_ptr<QuicServerInfo> quic_server_info2 = + base::MakeUnique<PropertiesBasedQuicServerInfo>( + quic_server_id2, &http_server_properties_); // Update quic_server_info2's server_config and persist it. QuicServerInfo::State* state2 = quic_server_info2->mutable_state(); @@ -668,9 +608,6 @@ quic_server_info2->Persist(); - QuicStreamFactoryPeer::MaybeInitialize(factory_.get()); - EXPECT_TRUE(QuicStreamFactoryPeer::HasInitializedData(factory_.get())); - // Verify the MRU order is maintained. const QuicServerInfoMap& quic_server_info_map = http_server_properties_.quic_server_info_map(); @@ -681,8 +618,21 @@ ++quic_server_info_map_it; EXPECT_EQ(quic_server_info_map_it->first, quic_server_id); - EXPECT_TRUE(QuicStreamFactoryPeer::SupportsQuicAtStartUp(factory_.get(), - host_port_pair_)); + host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(), + "192.168.0.1", ""); + + // Create a session and verify that the cached state is loaded. + MockQuicData socket_data; + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data.AddSocketDataToFactory(&socket_factory_); + + QuicStreamRequest request(factory_.get(), &http_server_properties_); + EXPECT_EQ(ERR_IO_PENDING, + request.Request(quic_server_id.host_port_pair(), privacy_mode_, + /*cert_verify_flags=*/0, url_, "GET", net_log_, + callback_.callback())); + EXPECT_THAT(callback_.WaitForResult(), IsOk()); + EXPECT_FALSE(QuicStreamFactoryPeer::CryptoConfigCacheIsEmpty( factory_.get(), quic_server_id)); QuicCryptoClientConfig* crypto_config = @@ -699,8 +649,24 @@ ASSERT_EQ(1U, cached->certs().size()); EXPECT_EQ(test_cert, cached->certs()[0]); - EXPECT_TRUE(QuicStreamFactoryPeer::SupportsQuicAtStartUp(factory_.get(), - host_port_pair2)); + EXPECT_TRUE(socket_data.AllWriteDataConsumed()); + + // Create a session and verify that the cached state is loaded. + MockQuicData socket_data2; + socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data2.AddSocketDataToFactory(&socket_factory_); + + host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(), + "192.168.0.2", ""); + + QuicStreamRequest request2(factory_.get(), &http_server_properties_); + EXPECT_EQ(ERR_IO_PENDING, + request2.Request(quic_server_id2.host_port_pair(), privacy_mode_, + /*cert_verify_flags=*/0, + GURL("https://mail.example.org/"), "GET", + net_log_, callback_.callback())); + EXPECT_THAT(callback_.WaitForResult(), IsOk()); + EXPECT_FALSE(QuicStreamFactoryPeer::CryptoConfigCacheIsEmpty( factory_.get(), quic_server_id2)); QuicCryptoClientConfig::CachedState* cached2 = @@ -770,11 +736,8 @@ TestCompletionCallback callback_; // Variables to configure QuicStreamFactory. - double load_server_info_timeout_srtt_multiplier_; - bool enable_connection_racing_; bool enable_non_blocking_io_; - bool disable_disk_cache_; - bool delay_tcp_race_; + bool store_server_configs_in_properties_; bool close_sessions_on_ip_change_; int idle_connection_timeout_seconds_; int reduced_ping_timeout_seconds_; @@ -790,9 +753,7 @@ class QuicStreamFactoryTest : public QuicStreamFactoryTestBase, public ::testing::TestWithParam<TestParams> { protected: - QuicStreamFactoryTest() - : QuicStreamFactoryTestBase(GetParam().version, - GetParam().enable_connection_racing) {} + QuicStreamFactoryTest() : QuicStreamFactoryTestBase(GetParam().version) {} }; INSTANTIATE_TEST_CASE_P(Version, @@ -4419,62 +4380,7 @@ } } -TEST_P(QuicStreamFactoryTest, RacingConnections) { - disable_disk_cache_ = false; - Initialize(); - ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); - crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); - - if (!enable_connection_racing_) - return; - - QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), runner_.get()); - - MockQuicData socket_data; - socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); - socket_data.AddSocketDataToFactory(&socket_factory_); - - MockQuicData socket_data2; - socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); - socket_data2.AddSocketDataToFactory(&socket_factory_); - - const AlternativeService alternative_service1( - kProtoQUIC, host_port_pair_.host(), host_port_pair_.port()); - AlternativeServiceInfoVector alternative_service_info_vector; - base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); - alternative_service_info_vector.push_back( - AlternativeServiceInfo(alternative_service1, expiration)); - - http_server_properties_.SetAlternativeServices( - url::SchemeHostPort(url_), alternative_service_info_vector); - - crypto_client_stream_factory_.set_handshake_mode( - MockCryptoClientStream::ZERO_RTT); - host_resolver_.set_synchronous_mode(true); - host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(), - "192.168.0.1", ""); - - QuicStreamRequest request(factory_.get(), &http_server_properties_); - QuicServerId server_id(host_port_pair_, privacy_mode_); - EXPECT_EQ(ERR_IO_PENDING, - request.Request(host_port_pair_, privacy_mode_, - /*cert_verify_flags=*/0, url_, "GET", net_log_, - callback_.callback())); - EXPECT_EQ(2u, QuicStreamFactoryPeer::GetNumberOfActiveJobs(factory_.get(), - server_id)); - - runner_->RunNextTask(); - - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); - EXPECT_TRUE(stream.get()); - EXPECT_TRUE(socket_data.AllReadDataConsumed()); - EXPECT_TRUE(socket_data.AllWriteDataConsumed()); - EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumberOfActiveJobs(factory_.get(), - server_id)); -} - TEST_P(QuicStreamFactoryTest, EnableNotLoadFromDiskCache) { - disable_disk_cache_ = true; Initialize(); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); @@ -4508,7 +4414,6 @@ TEST_P(QuicStreamFactoryTest, ReducePingTimeoutOnConnectionTimeOutOpenStreams) { reduced_ping_timeout_seconds_ = 10; - disable_disk_cache_ = true; Initialize(); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); @@ -4600,60 +4505,6 @@ EXPECT_TRUE(socket_data2.AllWriteDataConsumed()); } -TEST_P(QuicStreamFactoryTest, EnableDelayTcpRace) { - Initialize(); - ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); - crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); - bool delay_tcp_race = QuicStreamFactoryPeer::GetDelayTcpRace(factory_.get()); - QuicStreamFactoryPeer::SetDelayTcpRace(factory_.get(), false); - MockQuicData socket_data; - socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); - socket_data.AddWrite( - ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE, - kDefaultMaxUncompressedHeaderSize, nullptr)); - socket_data.AddSocketDataToFactory(&socket_factory_); - - ServerNetworkStats stats1; - stats1.srtt = base::TimeDelta::FromMicroseconds(10); - http_server_properties_.SetServerNetworkStats(url::SchemeHostPort(url_), - stats1); - - crypto_client_stream_factory_.set_handshake_mode( - MockCryptoClientStream::COLD_START); - host_resolver_.set_synchronous_mode(true); - host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(), - "192.168.0.1", ""); - - QuicStreamRequest request(factory_.get(), &http_server_properties_); - EXPECT_EQ(ERR_IO_PENDING, - request.Request(host_port_pair_, privacy_mode_, - /*cert_verify_flags=*/0, url_, "POST", net_log_, - callback_.callback())); - - // If we don't delay TCP connection, then time delay should be 0. - EXPECT_FALSE(factory_->delay_tcp_race()); - EXPECT_EQ(base::TimeDelta(), request.GetTimeDelayForWaitingJob()); - - // Enable |delay_tcp_race_| param and verify delay is one RTT and that - // server supports QUIC. - QuicStreamFactoryPeer::SetDelayTcpRace(factory_.get(), true); - EXPECT_TRUE(factory_->delay_tcp_race()); - EXPECT_EQ(base::TimeDelta::FromMicroseconds(15), - request.GetTimeDelayForWaitingJob()); - - // Confirm the handshake and verify that the stream is created. - crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent( - QuicSession::HANDSHAKE_CONFIRMED); - - EXPECT_THAT(callback_.WaitForResult(), IsOk()); - - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); - EXPECT_TRUE(stream.get()); - EXPECT_TRUE(socket_data.AllReadDataConsumed()); - EXPECT_TRUE(socket_data.AllWriteDataConsumed()); - QuicStreamFactoryPeer::SetDelayTcpRace(factory_.get(), delay_tcp_race); -} - // Verifies that the QUIC stream factory is initialized correctly. TEST_P(QuicStreamFactoryTest, MaybeInitialize) { VerifyInitialization(false); @@ -5005,8 +4856,7 @@ public ::testing::TestWithParam<PoolingTestParams> { protected: QuicStreamFactoryWithDestinationTest() - : QuicStreamFactoryTestBase(GetParam().version, - GetParam().enable_connection_racing), + : QuicStreamFactoryTestBase(GetParam().version), destination_type_(GetParam().destination_type), hanging_read_(SYNCHRONOUS, ERR_IO_PENDING, 0) {}
diff --git a/net/quic/core/congestion_control/bbr_sender.cc b/net/quic/core/congestion_control/bbr_sender.cc index 623cfb78..666a9d7 100644 --- a/net/quic/core/congestion_control/bbr_sender.cc +++ b/net/quic/core/congestion_control/bbr_sender.cc
@@ -10,9 +10,9 @@ #include "net/quic/core/congestion_control/rtt_stats.h" #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/proto/cached_network_parameters.pb.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net { @@ -80,9 +80,6 @@ last_sent_packet_(0), current_round_trip_end_(0), max_bandwidth_(kBandwidthWindowSize, QuicBandwidth::Zero(), 0), - max_ack_spacing_(kBandwidthWindowSize, QuicTime::Delta::Zero(), 0), - largest_acked_time_(QuicTime::Zero()), - largest_acked_sent_time_(QuicTime::Zero()), max_ack_height_(kBandwidthWindowSize, 0, 0), aggregation_epoch_start_time_(QuicTime::Zero()), aggregation_epoch_bytes_(0), @@ -96,9 +93,9 @@ pacing_gain_(1), congestion_window_gain_(1), congestion_window_gain_constant_( - static_cast<float>(base::GetFlag(FLAGS_quic_bbr_cwnd_gain))), - rtt_variance_weight_(static_cast<float>( - base::GetFlag(FLAGS_quic_bbr_rtt_variation_weight))), + static_cast<float>(GetQuicFlag(FLAGS_quic_bbr_cwnd_gain))), + rtt_variance_weight_( + static_cast<float>(GetQuicFlag(FLAGS_quic_bbr_rtt_variation_weight))), num_startup_rtts_(kRoundTripsWithoutGrowthBeforeExitingStartup), cycle_current_offset_(0), last_cycle_start_(QuicTime::Zero()), @@ -145,11 +142,21 @@ return QuicTime::Delta::Infinite(); } -QuicBandwidth BbrSender::PacingRate(QuicByteCount /*bytes_in_flight*/) const { +QuicBandwidth BbrSender::PacingRate(QuicByteCount bytes_in_flight) const { if (pacing_rate_.IsZero()) { return kHighGain * QuicBandwidth::FromBytesAndTimeDelta( initial_congestion_window_, GetMinRtt()); } + if (FLAGS_quic_reloadable_flag_quic_bbr_keep_sending_at_recent_rate && + mode_ == PROBE_BW && bytes_in_flight > congestion_window_) { + QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_keep_sending_at_recent_rate, + 1, 2); + if (pacing_gain_ > 1) { + return max_bandwidth_.GetBest(); + } else { + return max_bandwidth_.GetThirdBest(); + } + } return pacing_rate_; } @@ -166,6 +173,15 @@ return std::min(congestion_window_, recovery_window_); } + if (FLAGS_quic_reloadable_flag_quic_bbr_keep_sending_at_recent_rate && + mode_ == PROBE_BW && pacing_gain_ >= 1) { + QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_keep_sending_at_recent_rate, + 2, 2); + // Send for another SRTT at a more recently measured bandwidth. + return congestion_window_ + + max_bandwidth_.GetThirdBest() * rtt_stats_->smoothed_rtt(); + } + return congestion_window_; } @@ -197,6 +213,8 @@ return; } + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_bbr_bandwidth_resumption); + QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond( max_bandwidth_resumption ? cached_network_params.max_bandwidth_estimate_bytes_per_second() @@ -229,10 +247,6 @@ min_rtt_expired = UpdateBandwidthAndMinRtt(event_time, acked_packets); UpdateRecoveryState(last_acked_packet, !lost_packets.empty(), is_round_start); - if (FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_spacing2, 1, 2); - UpdateAckSpacing(event_time, last_acked_packet, acked_packets); - } if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes) { QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 1, 2); @@ -279,6 +293,10 @@ QuicByteCount BbrSender::GetTargetCongestionWindow(float gain) const { QuicByteCount bdp = GetMinRtt() * BandwidthEstimate(); + if (FLAGS_quic_reloadable_flag_quic_bbr_base_cwnd_on_srtt && + mode_ == PROBE_BW && gain >= 1 && !rtt_stats_->smoothed_rtt().IsZero()) { + bdp = rtt_stats_->smoothed_rtt() * BandwidthEstimate(); + } QuicByteCount congestion_window = gain * bdp; // BDP estimate will be zero if no bandwidth samples are available yet. @@ -502,42 +520,6 @@ } } -// TODO(ianswett): Move this logic into BandwidthSampler. -void BbrSender::UpdateAckSpacing(QuicTime ack_time, - QuicPacketNumber largest_newly_acked, - const CongestionVector& acked_packets) { - // Ignore acks of reordered packets. - if (largest_newly_acked < unacked_packets_->largest_observed()) { - return; - } - // Ignore acks of only one packet to filter out delayed acks. - if (acked_packets.size() == 1) { - return; - } - QuicTime largest_newly_acked_sent_time = - unacked_packets_->GetTransmissionInfo(largest_newly_acked).sent_time; - // Initialize on the first ack. - if (!largest_acked_time_.IsInitialized()) { - largest_acked_time_ = ack_time; - largest_acked_sent_time_ = largest_newly_acked_sent_time; - return; - } - QuicTime::Delta ack_delta = ack_time - largest_acked_time_; - QuicTime::Delta send_delta = - largest_newly_acked_sent_time - largest_acked_sent_time_; - largest_acked_time_ = ack_time; - largest_acked_sent_time_ = largest_newly_acked_sent_time; - if (ack_delta <= send_delta) { - return; - } - - // Limit the ack spacing to SRTT to filter outliers. - QuicTime::Delta ack_spacing = - std::min(ack_delta - send_delta, rtt_stats_->smoothed_rtt()); - max_ack_spacing_.Update(ack_spacing, round_trip_count_); -} - -// TODO(ianswett): Move this logic into BandwidthSampler. void BbrSender::UpdateAckAggregationBytes(QuicTime ack_time, QuicByteCount newly_acked_bytes) { // Compute how many bytes are expected to be delivered, assuming max bandwidth @@ -594,11 +576,6 @@ if (rtt_variance_weight_ > 0.f && !BandwidthEstimate().IsZero()) { target_window += rtt_variance_weight_ * rtt_stats_->mean_deviation() * BandwidthEstimate(); - } else if (FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2 && - is_at_full_bandwidth_) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_spacing2, 2, 2); - // Add CWND for inter-ack spacing once STARTUP has been exited. - target_window += max_ack_spacing_.GetBest() * BandwidthEstimate(); } else if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes && is_at_full_bandwidth_) { QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 2,
diff --git a/net/quic/core/congestion_control/bbr_sender.h b/net/quic/core/congestion_control/bbr_sender.h index 421f625..9a6cd7e3 100644 --- a/net/quic/core/congestion_control/bbr_sender.h +++ b/net/quic/core/congestion_control/bbr_sender.h
@@ -196,11 +196,6 @@ bool has_losses, bool is_round_start); - // Updates the ack spacing max filter if a larger value is observed. - void UpdateAckSpacing(QuicTime ack_time, - QuicPacketNumber largest_newly_acked, - const CongestionVector& acked_packets); - // Updates the ack aggregation max filter in bytes. void UpdateAckAggregationBytes(QuicTime ack_time, QuicByteCount newly_acked_bytes); @@ -236,13 +231,6 @@ // round-trips. MaxBandwidthFilter max_bandwidth_; - // Tracks the maximum spacing between two acks acknowledging in order packets. - MaxAckDelayFilter max_ack_spacing_; - - // The time the largest acked packet was acked and when it was sent. - QuicTime largest_acked_time_; - QuicTime largest_acked_sent_time_; - // Tracks the maximum number of bytes acked faster than the sending rate. MaxAckHeightFilter max_ack_height_;
diff --git a/net/quic/core/congestion_control/bbr_sender_test.cc b/net/quic/core/congestion_control/bbr_sender_test.cc index b0813e0..f89c8ad 100644 --- a/net/quic/core/congestion_control/bbr_sender_test.cc +++ b/net/quic/core/congestion_control/bbr_sender_test.cc
@@ -90,6 +90,8 @@ /*connection_id=*/GetPeerInMemoryConnectionId(43)), receiver_multiplexer_("Receiver multiplexer", {&receiver_, &competing_receiver_}) { + // TODO(ianswett): Determine why tests become flaky with CWND based on SRTT. + FLAGS_quic_reloadable_flag_quic_bbr_base_cwnd_on_srtt = false; rtt_stats_ = bbr_sender_.connection()->sent_packet_manager().GetRttStats(); sender_ = SetupBbrSender(&bbr_sender_); @@ -289,35 +291,7 @@ } // Test a simple long data transfer with 2 rtts of aggregation. -TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregation) { - QuicFlagSaver flags; - FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2 = true; - FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd = false; - CreateDefaultSetup(); - // 2 RTTs of aggregation, with a max of 10kb. - EnableAggregation(10 * 1024, 2 * kTestRtt); - - // Transfer 12MB. - DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35)); - EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode); - // It's possible to read a bandwidth as much as 50% too high with aggregation. - EXPECT_LE(kTestLinkBandwidth * 0.99f, - sender_->ExportDebugState().max_bandwidth); - // TODO(ianswett): Tighten this bound once we understand why BBR is - // overestimating bandwidth with aggregation. b/36022633 - EXPECT_GE(kTestLinkBandwidth * 1.5f, - sender_->ExportDebugState().max_bandwidth); - // TODO(ianswett): Expect 0 packets are lost once BBR no longer measures - // bandwidth higher than the link rate. - // The margin here is high, because the aggregation greatly increases - // smoothed rtt. - EXPECT_GE(kTestRtt * 4, rtt_stats_->smoothed_rtt()); - ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.1f); -} - -// Test a simple long data transfer with 2 rtts of aggregation. TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes) { - FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2 = false; FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes = true; FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd = false; CreateDefaultSetup(); @@ -343,12 +317,38 @@ ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.1f); } +TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationKeepSending) { + FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes = false; + FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd = false; + FLAGS_quic_reloadable_flag_quic_bbr_keep_sending_at_recent_rate = true; + CreateDefaultSetup(); + // 2 RTTs of aggregation, with a max of 10kb. + EnableAggregation(10 * 1024, 2 * kTestRtt); + + // Transfer 12MB. + DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35)); + EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode); + // It's possible to read a bandwidth as much as 50% too high with aggregation. + EXPECT_LE(kTestLinkBandwidth * 0.95f, + sender_->ExportDebugState().max_bandwidth); + // TODO(ianswett): Tighten this bound once we understand why BBR is + // overestimating bandwidth with aggregation. b/36022633 + EXPECT_GE(kTestLinkBandwidth * 1.5f, + sender_->ExportDebugState().max_bandwidth); + // TODO(ianswett): Expect 0 packets are lost once BBR no longer measures + // bandwidth higher than the link rate. + EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited); + // The margin here is high, because the aggregation greatly increases + // smoothed rtt. + EXPECT_GE(kTestRtt * 4.5, rtt_stats_->smoothed_rtt()); + ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.1f); +} + // Test a simple long data transfer with 2 rtts of aggregation. TEST_F(BbrSenderTest, SimpleTransferAckDecimation) { - FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2 = false; FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes = true; // Decrease the CWND gain so extra CWND is required with stretch acks. - base::SetFlag(&FLAGS_quic_bbr_cwnd_gain, 1.0); + SetQuicFlag(&FLAGS_quic_bbr_cwnd_gain, 1.0); sender_ = new BbrSender( rtt_stats_, QuicSentPacketManagerPeer::GetUnackedPacketMap( @@ -380,6 +380,43 @@ ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.1f); } +TEST_F(BbrSenderTest, SimpleTransferAckDecimationKeepSending) { + FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes = false; + FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd = true; + FLAGS_quic_reloadable_flag_quic_bbr_keep_sending_at_recent_rate = true; + // Decrease the CWND gain so extra CWND is required with stretch acks. + SetQuicFlag(&FLAGS_quic_bbr_cwnd_gain, 1.0); + sender_ = new BbrSender( + rtt_stats_, + QuicSentPacketManagerPeer::GetUnackedPacketMap( + QuicConnectionPeer::GetSentPacketManager(bbr_sender_.connection())), + kInitialCongestionWindowPackets, kDefaultMaxCongestionWindowPackets, + &random_); + QuicConnectionPeer::SetSendAlgorithm(bbr_sender_.connection(), sender_); + // Enable Ack Decimation on the receiver. + QuicConnectionPeer::SetAckMode(receiver_.connection(), + QuicConnection::AckMode::ACK_DECIMATION); + CreateDefaultSetup(); + + // Transfer 12MB. + DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35)); + EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode); + // It's possible to read a bandwidth as much as 50% too high with aggregation. + EXPECT_LE(kTestLinkBandwidth * 0.95f, + sender_->ExportDebugState().max_bandwidth); + // TODO(ianswett): Tighten this bound once we understand why BBR is + // overestimating bandwidth with aggregation. b/36022633 + EXPECT_GE(kTestLinkBandwidth * 1.5f, + sender_->ExportDebugState().max_bandwidth); + // TODO(ianswett): Expect 0 packets are lost once BBR no longer measures + // bandwidth higher than the link rate. + EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited); + // The margin here is high, because the aggregation greatly increases + // smoothed rtt. + EXPECT_GE(kTestRtt * 2, rtt_stats_->smoothed_rtt()); + ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.1f); +} + // Test the number of losses incurred by the startup phase in a situation when // the buffer is less than BDP. TEST_F(BbrSenderTest, PacketLossOnSmallBufferStartup) {
diff --git a/net/quic/core/congestion_control/cubic.cc b/net/quic/core/congestion_control/cubic.cc index 0fef6f8..4849cf9 100644 --- a/net/quic/core/congestion_control/cubic.cc +++ b/net/quic/core/congestion_control/cubic.cc
@@ -8,8 +8,8 @@ #include <cmath> #include <cstdint> -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net {
diff --git a/net/quic/core/congestion_control/cubic_bytes.cc b/net/quic/core/congestion_control/cubic_bytes.cc index e490e06..4d9807f8 100644 --- a/net/quic/core/congestion_control/cubic_bytes.cc +++ b/net/quic/core/congestion_control/cubic_bytes.cc
@@ -8,8 +8,8 @@ #include <cmath> #include <cstdint> -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net {
diff --git a/net/quic/core/congestion_control/cubic_bytes_test.cc b/net/quic/core/congestion_control/cubic_bytes_test.cc index 6cbe7ec..0214122 100644 --- a/net/quic/core/congestion_control/cubic_bytes_test.cc +++ b/net/quic/core/congestion_control/cubic_bytes_test.cc
@@ -6,7 +6,7 @@ #include <cstdint> -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_str_cat.h" #include "net/quic/test_tools/mock_clock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/net/quic/core/congestion_control/cubic_test.cc b/net/quic/core/congestion_control/cubic_test.cc index 7233566..875e851 100644 --- a/net/quic/core/congestion_control/cubic_test.cc +++ b/net/quic/core/congestion_control/cubic_test.cc
@@ -6,7 +6,7 @@ #include <cstdint> -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_str_cat.h" #include "net/quic/test_tools/mock_clock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/net/quic/core/congestion_control/general_loss_algorithm.cc b/net/quic/core/congestion_control/general_loss_algorithm.cc index 97f0c98..f71f0ed5 100644 --- a/net/quic/core/congestion_control/general_loss_algorithm.cc +++ b/net/quic/core/congestion_control/general_loss_algorithm.cc
@@ -5,10 +5,10 @@ #include "net/quic/core/congestion_control/general_loss_algorithm.h" #include "net/quic/core/congestion_control/rtt_stats.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" namespace net {
diff --git a/net/quic/core/congestion_control/general_loss_algorithm_test.cc b/net/quic/core/congestion_control/general_loss_algorithm_test.cc index 1bfb2d9..e670429 100644 --- a/net/quic/core/congestion_control/general_loss_algorithm_test.cc +++ b/net/quic/core/congestion_control/general_loss_algorithm_test.cc
@@ -9,8 +9,8 @@ #include "base/stl_util.h" #include "net/quic/core/congestion_control/rtt_stats.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_unacked_packet_map.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/test_tools/mock_clock.h" #include "net/quic/test_tools/quic_test_utils.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/net/quic/core/congestion_control/send_algorithm_interface.cc b/net/quic/core/congestion_control/send_algorithm_interface.cc index f754366..b9bb452 100644 --- a/net/quic/core/congestion_control/send_algorithm_interface.cc +++ b/net/quic/core/congestion_control/send_algorithm_interface.cc
@@ -7,9 +7,9 @@ #include "net/quic/core/congestion_control/bbr_sender.h" #include "net/quic/core/congestion_control/tcp_cubic_sender_bytes.h" #include "net/quic/core/congestion_control/tcp_cubic_sender_packets.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" namespace net {
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc b/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc index 0dbbb8dd..f22bdd02 100644 --- a/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc +++ b/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
@@ -10,8 +10,8 @@ #include "net/quic/core/congestion_control/prr_sender.h" #include "net/quic/core/congestion_control/rtt_stats.h" #include "net/quic/core/crypto/crypto_protocol.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net {
diff --git a/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc b/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc index 94154d8..74ebb2fc 100644 --- a/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc +++ b/net/quic/core/congestion_control/tcp_cubic_sender_packets.cc
@@ -9,8 +9,8 @@ #include "net/quic/core/congestion_control/prr_sender.h" #include "net/quic/core/congestion_control/rtt_stats.h" #include "net/quic/core/crypto/crypto_protocol.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net {
diff --git a/net/quic/core/crypto/crypto_server_test.cc b/net/quic/core/crypto/crypto_server_test.cc index 65cdc12c..2527882 100644 --- a/net/quic/core/crypto/crypto_server_test.cc +++ b/net/quic/core/crypto/crypto_server_test.cc
@@ -16,10 +16,10 @@ #include "net/quic/core/crypto/proof_source.h" #include "net/quic/core/crypto/quic_crypto_server_config.h" #include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_socket_address_coder.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_endian.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_string_piece.h" #include "net/quic/platform/api/quic_text_utils.h" #include "net/quic/test_tools/crypto_test_utils.h"
diff --git a/net/quic/core/crypto/quic_crypto_server_config.cc b/net/quic/core/crypto/quic_crypto_server_config.cc index b807d46..f0f40a0 100644 --- a/net/quic/core/crypto/quic_crypto_server_config.cc +++ b/net/quic/core/crypto/quic_crypto_server_config.cc
@@ -29,13 +29,13 @@ #include "net/quic/core/crypto/quic_encrypter.h" #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/proto/source_address_token.pb.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_socket_address_coder.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_clock.h" #include "net/quic/platform/api/quic_endian.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_hostname_utils.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_reference_counted.h" @@ -1751,8 +1751,8 @@ } void QuicCryptoServerConfig::SetEphemeralKeySource( - EphemeralKeySource* ephemeral_key_source) { - ephemeral_key_source_.reset(ephemeral_key_source); + std::unique_ptr<EphemeralKeySource> ephemeral_key_source) { + ephemeral_key_source_ = std::move(ephemeral_key_source); } void QuicCryptoServerConfig::set_replay_protection(bool on) {
diff --git a/net/quic/core/crypto/quic_crypto_server_config.h b/net/quic/core/crypto/quic_crypto_server_config.h index 9c30c01..4094855 100644 --- a/net/quic/core/crypto/quic_crypto_server_config.h +++ b/net/quic/core/crypto/quic_crypto_server_config.h
@@ -349,10 +349,10 @@ std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const; // SetEphemeralKeySource installs an object that can cache ephemeral keys for - // a short period of time. This object takes ownership of - // |ephemeral_key_source|. If not set then ephemeral keys will be generated + // a short period of time. If not set, ephemeral keys will be generated // per-connection. - void SetEphemeralKeySource(EphemeralKeySource* ephemeral_key_source); + void SetEphemeralKeySource( + std::unique_ptr<EphemeralKeySource> ephemeral_key_source); // set_replay_protection controls whether replay protection is enabled. If // replay protection is disabled then no strike registers are needed and
diff --git a/net/quic/core/quic_buffered_packet_store.cc b/net/quic/core/quic_buffered_packet_store.cc index 8c4ac46..c2b4a4e 100644 --- a/net/quic/core/quic_buffered_packet_store.cc +++ b/net/quic/core/quic_buffered_packet_store.cc
@@ -4,8 +4,8 @@ #include "net/quic/core/quic_buffered_packet_store.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_map_util.h" namespace net {
diff --git a/net/quic/core/quic_buffered_packet_store_test.cc b/net/quic/core/quic_buffered_packet_store_test.cc index 69831633..6ae35a6 100644 --- a/net/quic/core/quic_buffered_packet_store_test.cc +++ b/net/quic/core/quic_buffered_packet_store_test.cc
@@ -7,7 +7,7 @@ #include <list> #include <string> -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/test_tools/mock_clock.h" #include "net/quic/test_tools/quic_buffered_packet_store_peer.h" #include "net/quic/test_tools/quic_test_utils.h"
diff --git a/net/quic/core/quic_client_session_base.cc b/net/quic/core/quic_client_session_base.cc index 1c7e101..b13496d 100644 --- a/net/quic/core/quic_client_session_base.cc +++ b/net/quic/core/quic_client_session_base.cc
@@ -5,8 +5,8 @@ #include "net/quic/core/quic_client_session_base.h" #include "net/quic/core/quic_client_promised_info.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/spdy_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" using std::string;
diff --git a/net/quic/core/quic_config.cc b/net/quic/core/quic_config.cc index 9a29d94b..7453708 100644 --- a/net/quic/core/quic_config.cc +++ b/net/quic/core/quic_config.cc
@@ -8,11 +8,11 @@ #include "net/quic/core/crypto/crypto_handshake_message.h" #include "net/quic/core/crypto/crypto_protocol.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_socket_address_coder.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_string_piece.h" @@ -341,9 +341,7 @@ connection_migration_disabled_(kNCMR, PRESENCE_OPTIONAL), alternate_server_address_(kASAD, PRESENCE_OPTIONAL), force_hol_blocking_(kFHL2, PRESENCE_OPTIONAL), - support_max_header_list_size_(kSMHL, PRESENCE_OPTIONAL), - latched_no_socket_receive_buffer_( - FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { + support_max_header_list_size_(kSMHL, PRESENCE_OPTIONAL) { SetDefaults(); } @@ -544,22 +542,6 @@ return initial_session_flow_control_window_bytes_.GetReceivedValue(); } -void QuicConfig::SetSocketReceiveBufferToSend(uint32_t tcp_receive_window) { - if (latched_no_socket_receive_buffer_) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_no_socket_receive_buffer, 1, 3); - } else { - socket_receive_buffer_.SetSendValue(tcp_receive_window); - } -} - -bool QuicConfig::HasReceivedSocketReceiveBuffer() const { - return socket_receive_buffer_.HasReceivedValue(); -} - -uint32_t QuicConfig::ReceivedSocketReceiveBuffer() const { - return socket_receive_buffer_.GetReceivedValue(); -} - void QuicConfig::SetDisableConnectionMigration() { connection_migration_disabled_.SetSendValue(1); } @@ -638,11 +620,6 @@ initial_round_trip_time_us_.ToHandshakeMessage(out); initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out); initial_session_flow_control_window_bytes_.ToHandshakeMessage(out); - if (latched_no_socket_receive_buffer_) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_no_socket_receive_buffer, 2, 3); - } else { - socket_receive_buffer_.ToHandshakeMessage(out); - } connection_migration_disabled_.ToHandshakeMessage(out); connection_options_.ToHandshakeMessage(out); alternate_server_address_.ToHandshakeMessage(out); @@ -689,12 +666,6 @@ error = initial_session_flow_control_window_bytes_.ProcessPeerHello( peer_hello, hello_type, error_details); } - if (latched_no_socket_receive_buffer_) { - QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_no_socket_receive_buffer, 3, 3); - } else if (error == QUIC_NO_ERROR) { - error = socket_receive_buffer_.ProcessPeerHello(peer_hello, hello_type, - error_details); - } if (error == QUIC_NO_ERROR) { error = connection_migration_disabled_.ProcessPeerHello( peer_hello, hello_type, error_details);
diff --git a/net/quic/core/quic_config.h b/net/quic/core/quic_config.h index c1d7a89..7737689 100644 --- a/net/quic/core/quic_config.h +++ b/net/quic/core/quic_config.h
@@ -344,13 +344,6 @@ uint32_t ReceivedInitialSessionFlowControlWindowBytes() const; - // Sets socket receive buffer to transmit to the peer. - void SetSocketReceiveBufferToSend(uint32_t window_bytes); - - bool HasReceivedSocketReceiveBuffer() const; - - uint32_t ReceivedSocketReceiveBuffer() const; - void SetDisableConnectionMigration(); bool DisableConnectionMigration() const; @@ -435,9 +428,6 @@ // Whether support HTTP/2 SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame. QuicFixedUint32 support_max_header_list_size_; - - // Latched copy of FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer - bool latched_no_socket_receive_buffer_; }; } // namespace net
diff --git a/net/quic/core/quic_config_test.cc b/net/quic/core/quic_config_test.cc index 06e789d..a57a88fd 100644 --- a/net/quic/core/quic_config_test.cc +++ b/net/quic/core/quic_config_test.cc
@@ -33,9 +33,6 @@ config_.SetIdleNetworkTimeout(QuicTime::Delta::FromSeconds(5), QuicTime::Delta::FromSeconds(2)); config_.SetMaxStreamsPerConnection(4, 2); - if (!FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { - config_.SetSocketReceiveBufferToSend(kDefaultSocketReceiveBuffer); - } CryptoHandshakeMessage msg; config_.ToHandshakeMessage(&msg); @@ -55,12 +52,6 @@ error = msg.GetUint32(kCFCW, &value); EXPECT_EQ(QUIC_NO_ERROR, error); EXPECT_EQ(kInitialSessionFlowControlWindowForTest, value); - - if (!FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { - error = msg.GetUint32(kSRBF, &value); - EXPECT_EQ(QUIC_NO_ERROR, error); - EXPECT_EQ(kDefaultSocketReceiveBuffer, value); - } } TEST_F(QuicConfigTest, ProcessClientHello) { @@ -77,9 +68,6 @@ 2 * kInitialStreamFlowControlWindowForTest); client_config.SetInitialSessionFlowControlWindowToSend( 2 * kInitialSessionFlowControlWindowForTest); - if (!FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { - client_config.SetSocketReceiveBufferToSend(kDefaultSocketReceiveBuffer); - } client_config.SetForceHolBlocking(); QuicTagVector copt; copt.push_back(kTBBR); @@ -115,10 +103,6 @@ 2 * kInitialStreamFlowControlWindowForTest); EXPECT_EQ(config_.ReceivedInitialSessionFlowControlWindowBytes(), 2 * kInitialSessionFlowControlWindowForTest); - if (!FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { - EXPECT_EQ(config_.ReceivedSocketReceiveBuffer(), - kDefaultSocketReceiveBuffer); - } } TEST_F(QuicConfigTest, ProcessServerHello) { @@ -138,9 +122,6 @@ 2 * kInitialStreamFlowControlWindowForTest); server_config.SetInitialSessionFlowControlWindowToSend( 2 * kInitialSessionFlowControlWindowForTest); - if (!FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { - server_config.SetSocketReceiveBufferToSend(kDefaultSocketReceiveBuffer); - } server_config.SetAlternateServerAddressToSend(kTestServerAddress); CryptoHandshakeMessage msg; server_config.ToHandshakeMessage(&msg); @@ -158,10 +139,6 @@ 2 * kInitialStreamFlowControlWindowForTest); EXPECT_EQ(config_.ReceivedInitialSessionFlowControlWindowBytes(), 2 * kInitialSessionFlowControlWindowForTest); - if (!FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer) { - EXPECT_EQ(config_.ReceivedSocketReceiveBuffer(), - kDefaultSocketReceiveBuffer); - } EXPECT_TRUE(config_.HasReceivedAlternateServerAddress()); EXPECT_EQ(kTestServerAddress, config_.ReceivedAlternateServerAddress()); }
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc index 66f5be6..59fa781e 100644 --- a/net/quic/core/quic_connection.cc +++ b/net/quic/core/quic_connection.cc
@@ -24,12 +24,12 @@ #include "net/quic/core/proto/cached_network_parameters.pb.h" #include "net/quic/core/quic_bandwidth.h" #include "net/quic/core/quic_config.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packet_generator.h" #include "net/quic/core/quic_pending_retransmission.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_map_util.h" #include "net/quic/platform/api/quic_str_cat.h" @@ -240,6 +240,7 @@ debug_visitor_(nullptr), packet_generator_(connection_id_, &framer_, + random_generator_, helper->GetBufferAllocator(), this), idle_network_timeout_(QuicTime::Delta::Infinite()), @@ -1057,9 +1058,9 @@ QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { - if (!fin && iov.total_length == 0) { + if (state == NO_FIN && iov.total_length == 0) { QUIC_BUG << "Attempt to send empty stream frame"; return QuicConsumedData(0, false); } @@ -1074,12 +1075,12 @@ // The optimized path may be used for data only packets which fit into a // standard buffer and don't need padding. if (id != kCryptoStreamId && !packet_generator_.HasQueuedFrames() && - iov.total_length > kMaxPacketSize) { + iov.total_length > kMaxPacketSize && state != FIN_AND_PADDING) { // Use the fast path to send full data packets. - return packet_generator_.ConsumeDataFastPath(id, iov, offset, fin, - std::move(ack_listener)); + return packet_generator_.ConsumeDataFastPath( + id, iov, offset, state != NO_FIN, std::move(ack_listener)); } - return packet_generator_.ConsumeData(id, iov, offset, fin, + return packet_generator_.ConsumeData(id, iov, offset, state, std::move(ack_listener)); }
diff --git a/net/quic/core/quic_connection.h b/net/quic/core/quic_connection.h index e5bf4ca..0ff9094 100644 --- a/net/quic/core/quic_connection.h +++ b/net/quic/core/quic_connection.h
@@ -345,7 +345,7 @@ QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); // Send a RST_STREAM frame to the peer.
diff --git a/net/quic/core/quic_connection_test.cc b/net/quic/core/quic_connection_test.cc index 144f674..76cf9e4 100644 --- a/net/quic/core/quic_connection_test.cc +++ b/net/quic/core/quic_connection_test.cc
@@ -17,10 +17,10 @@ #include "net/quic/core/crypto/null_encrypter.h" #include "net/quic/core/crypto/quic_decrypter.h" #include "net/quic/core/crypto/quic_encrypter.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_simple_buffer_allocator.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_reference_counted.h" #include "net/quic/platform/api/quic_str_cat.h" @@ -59,7 +59,6 @@ const char data1[] = "foo"; const char data2[] = "bar"; -const bool kFin = true; const bool kHasStopWaiting = true; const int kDefaultRetransmissionTimeMs = 500; @@ -390,6 +389,10 @@ return framer_.ping_frames(); } + const std::vector<QuicPaddingFrame>& padding_frames() const { + return framer_.padding_frames(); + } + size_t last_packet_size() { return last_packet_size_; } const QuicVersionNegotiationPacket* version_negotiation_packet() { @@ -511,24 +514,24 @@ QuicStreamId id, QuicStringPiece data, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { if (id != kCryptoStreamId && this->encryption_level() == ENCRYPTION_NONE) { this->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); } struct iovec iov; QuicIOVector data_iov(MakeIOVector(data, &iov)); - return QuicConnection::SendStreamData(id, data_iov, offset, fin, + return QuicConnection::SendStreamData(id, data_iov, offset, state, std::move(ack_listener)); } QuicConsumedData SendStreamData3() { - return SendStreamDataWithString(kClientDataStreamId1, "food", 0, !kFin, + return SendStreamDataWithString(kClientDataStreamId1, "food", 0, NO_FIN, nullptr); } QuicConsumedData SendStreamData5() { - return SendStreamDataWithString(kClientDataStreamId2, "food2", 0, !kFin, + return SendStreamDataWithString(kClientDataStreamId2, "food2", 0, NO_FIN, nullptr); } @@ -544,7 +547,8 @@ // split needlessly across packet boundaries). As a result, we have separate // tests for some cases for this stream. QuicConsumedData SendCryptoStreamData() { - return SendStreamDataWithString(kCryptoStreamId, "chlo", 0, !kFin, nullptr); + return SendStreamDataWithString(kCryptoStreamId, "chlo", 0, NO_FIN, + nullptr); } void set_version(QuicVersion version) { @@ -885,12 +889,12 @@ QuicByteCount SendStreamDataToPeer(QuicStreamId id, QuicStringPiece data, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicPacketNumber* last_packet) { QuicByteCount packet_size; EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<3>(&packet_size), Return(true))); - connection_.SendStreamDataWithString(id, data, offset, fin, nullptr); + connection_.SendStreamDataWithString(id, data, offset, state, nullptr); if (last_packet != nullptr) { *last_packet = creator_->packet_number(); } @@ -1418,8 +1422,8 @@ TEST_P(QuicConnectionTest, OutOfOrderAckReceiptCausesNoAck) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - SendStreamDataToPeer(1, "foo", 0, !kFin, nullptr); - SendStreamDataToPeer(1, "bar", 3, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); + SendStreamDataToPeer(1, "bar", 3, NO_FIN, nullptr); EXPECT_EQ(2u, writer_->packets_write_attempts()); QuicAckFrame ack1 = InitAckFrame(1); @@ -1441,7 +1445,7 @@ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce( DoAll(SaveArg<2>(&original), SaveArg<3>(&packet_size), Return(true))); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); QuicAckFrame frame = InitAckFrame(original); NackPacket(original, &frame); // First nack triggers early retransmit. @@ -1468,7 +1472,7 @@ // indicate the high water mark needs to be raised. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)); - connection_.SendStreamDataWithString(3, "foo", 3, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 3, NO_FIN, nullptr); // No ack sent. EXPECT_EQ(1u, writer_->frame_count()); EXPECT_EQ(1u, writer_->stream_frames().size()); @@ -1478,7 +1482,7 @@ ProcessAckPacket(&frame2); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA)); - connection_.SendStreamDataWithString(3, "foo", 3, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 3, NO_FIN, nullptr); // Ack bundled. if (GetParam().no_stop_waiting) { EXPECT_EQ(2u, writer_->frame_count()); @@ -1497,7 +1501,7 @@ TEST_P(QuicConnectionTest, 20AcksCausesAckSend) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - SendStreamDataToPeer(1, "foo", 0, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); QuicAlarm* ack_alarm = QuicConnectionPeer::GetAckAlarm(&connection_); // But an ack with no missing packets will not send an ack. @@ -1516,9 +1520,9 @@ TEST_P(QuicConnectionTest, LeastUnackedLower) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - SendStreamDataToPeer(1, "foo", 0, !kFin, nullptr); - SendStreamDataToPeer(1, "bar", 3, !kFin, nullptr); - SendStreamDataToPeer(1, "eep", 6, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); + SendStreamDataToPeer(1, "bar", 3, NO_FIN, nullptr); + SendStreamDataToPeer(1, "eep", 6, NO_FIN, nullptr); // Start out saying the least unacked is 2. QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5); @@ -1553,7 +1557,7 @@ const int num_packets = kMaxTrackedPackets + 100; for (int i = 0; i < num_packets; ++i) { - SendStreamDataToPeer(1, "foo", 3 * i, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", 3 * i, NO_FIN, nullptr); } // Ack packet 1, which leaves more than the limit outstanding. @@ -1579,9 +1583,9 @@ TEST_P(QuicConnectionTest, LargestObservedLower) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - SendStreamDataToPeer(1, "foo", 0, !kFin, nullptr); - SendStreamDataToPeer(1, "bar", 3, !kFin, nullptr); - SendStreamDataToPeer(1, "eep", 6, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); + SendStreamDataToPeer(1, "bar", 3, NO_FIN, nullptr); + SendStreamDataToPeer(1, "eep", 6, NO_FIN, nullptr); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); // Start out saying the largest observed is 2. @@ -1619,7 +1623,7 @@ TEST_P(QuicConnectionTest, BasicSending) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); QuicPacketNumber last_packet; - SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1 + SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); // Packet 1 EXPECT_EQ(1u, last_packet); SendAckPacketToPeer(); // Packet 2 @@ -1638,7 +1642,7 @@ EXPECT_EQ(1u, least_unacked()); } - SendStreamDataToPeer(1, "bar", 3, !kFin, &last_packet); // Packet 4 + SendStreamDataToPeer(1, "bar", 3, NO_FIN, &last_packet); // Packet 4 EXPECT_EQ(4u, last_packet); SendAckPacketToPeer(); // Packet 5 if (GetParam().no_stop_waiting) { @@ -1691,7 +1695,7 @@ } // But if we send more data it should. - SendStreamDataToPeer(1, "eep", 6, !kFin, &last_packet); // Packet 8 + SendStreamDataToPeer(1, "eep", 6, NO_FIN, &last_packet); // Packet 8 EXPECT_EQ(8u, last_packet); SendAckPacketToPeer(); // Packet 9 if (GetParam().no_stop_waiting) { @@ -1715,7 +1719,7 @@ // First send without any pause and check the result. QuicTime expected_recorded_send_time = clock_.Now(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(expected_recorded_send_time, actual_recorded_send_time) << "Expected time = " << expected_recorded_send_time.ToDebuggingValue() << ". Actual time = " << actual_recorded_send_time.ToDebuggingValue(); @@ -1729,7 +1733,7 @@ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<0>(&actual_recorded_send_time), Return(true))); - connection_.SendStreamDataWithString(2, "baz", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(2, "baz", 0, NO_FIN, nullptr); EXPECT_EQ(expected_recorded_send_time, actual_recorded_send_time) << "Expected time = " << expected_recorded_send_time.ToDebuggingValue() << ". Actual time = " << actual_recorded_send_time.ToDebuggingValue(); @@ -1776,8 +1780,9 @@ EXPECT_FALSE(connection_.HasQueuedData()); // Parse the last packet and ensure it's the crypto stream frame. - EXPECT_EQ(1u, writer_->frame_count()); + EXPECT_EQ(2u, writer_->frame_count()); ASSERT_EQ(1u, writer_->stream_frames().size()); + ASSERT_EQ(1u, writer_->padding_frames().size()); EXPECT_EQ(kCryptoStreamId, writer_->stream_frames()[0]->stream_id); } @@ -1847,15 +1852,16 @@ iov[0].iov_len = 2; iov[1].iov_base = data + 2; iov[1].iov_len = 2; - connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, !kFin, nullptr); + connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, NO_FIN, nullptr); EXPECT_EQ(0u, connection_.NumQueuedPackets()); EXPECT_FALSE(connection_.HasQueuedData()); // Parse the last packet and ensure multiple iovector blocks have // been packed into a single stream frame from one stream. - EXPECT_EQ(1u, writer_->frame_count()); + EXPECT_EQ(2u, writer_->frame_count()); EXPECT_EQ(1u, writer_->stream_frames().size()); + EXPECT_EQ(1u, writer_->padding_frames().size()); QuicStreamFrame* frame = writer_->stream_frames()[0].get(); EXPECT_EQ(1u, frame->stream_id); EXPECT_EQ("ABCD", QuicStringPiece(frame->data_buffer, frame->data_length)); @@ -1872,7 +1878,7 @@ iov[0].iov_len = 2; iov[1].iov_base = data + 2; iov[1].iov_len = 2; - connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, !kFin, nullptr); + connection_.SendStreamData(1, QuicIOVector(iov, 2, 4), 0, NO_FIN, nullptr); EXPECT_EQ(1u, connection_.NumQueuedPackets()); EXPECT_TRUE(connection_.HasQueuedData()); @@ -1883,8 +1889,9 @@ EXPECT_EQ(0u, connection_.NumQueuedPackets()); // Parse the last packet and ensure it's one stream frame from one stream. - EXPECT_EQ(1u, writer_->frame_count()); + EXPECT_EQ(2u, writer_->frame_count()); EXPECT_EQ(1u, writer_->stream_frames().size()); + EXPECT_EQ(1u, writer_->padding_frames().size()); EXPECT_EQ(1u, writer_->stream_frames()[0]->stream_id); } @@ -1893,7 +1900,7 @@ // Send a zero byte write with a fin using writev. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); QuicIOVector empty_iov(nullptr, 0, 0); - connection_.SendStreamData(kHeadersStreamId, empty_iov, 0, kFin, nullptr); + connection_.SendStreamData(kHeadersStreamId, empty_iov, 0, FIN, nullptr); EXPECT_EQ(0u, connection_.NumQueuedPackets()); EXPECT_FALSE(connection_.HasQueuedData()); @@ -1926,7 +1933,7 @@ iov.iov_len = len; QuicIOVector iovector(&iov, 1, len); QuicConsumedData consumed = - connection_.SendStreamData(kHeadersStreamId, iovector, 0, true, nullptr); + connection_.SendStreamData(kHeadersStreamId, iovector, 0, FIN, nullptr); EXPECT_EQ(len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_EQ(0u, connection_.NumQueuedPackets()); @@ -1971,10 +1978,10 @@ TEST_P(QuicConnectionTest, RetransmitOnNack) { QuicPacketNumber last_packet; QuicByteCount second_packet_size; - SendStreamDataToPeer(3, "foo", 0, !kFin, &last_packet); // Packet 1 + SendStreamDataToPeer(3, "foo", 0, NO_FIN, &last_packet); // Packet 1 second_packet_size = - SendStreamDataToPeer(3, "foos", 3, !kFin, &last_packet); // Packet 2 - SendStreamDataToPeer(3, "fooos", 7, !kFin, &last_packet); // Packet 3 + SendStreamDataToPeer(3, "foos", 3, NO_FIN, &last_packet); // Packet 2 + SendStreamDataToPeer(3, "fooos", 7, NO_FIN, &last_packet); // Packet 3 EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); @@ -2002,7 +2009,7 @@ BlockOnNextWrite(); QuicStreamId stream_id = 2; - connection_.SendStreamDataWithString(stream_id, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(stream_id, "foo", 0, NO_FIN, nullptr); // Now that there is a queued packet, reset the stream. connection_.SendRstStream(stream_id, QUIC_ERROR_PROCESSING_STREAM, 14); @@ -2020,7 +2027,7 @@ BlockOnNextWrite(); QuicStreamId stream_id = 2; - connection_.SendStreamDataWithString(stream_id, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(stream_id, "foo", 0, NO_FIN, nullptr); // Now that there is a queued packet, reset the stream. connection_.SendRstStream(stream_id, QUIC_STREAM_NO_ERROR, 14); @@ -2037,9 +2044,9 @@ TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnNack) { QuicStreamId stream_id = 2; QuicPacketNumber last_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_packet); - SendStreamDataToPeer(stream_id, "foos", 3, !kFin, &last_packet); - SendStreamDataToPeer(stream_id, "fooos", 7, !kFin, &last_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); + SendStreamDataToPeer(stream_id, "foos", 3, NO_FIN, &last_packet); + SendStreamDataToPeer(stream_id, "fooos", 7, NO_FIN, &last_packet); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); connection_.SendRstStream(stream_id, QUIC_ERROR_PROCESSING_STREAM, 14); @@ -2057,9 +2064,9 @@ TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnNack) { QuicStreamId stream_id = 2; QuicPacketNumber last_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_packet); - SendStreamDataToPeer(stream_id, "foos", 3, !kFin, &last_packet); - SendStreamDataToPeer(stream_id, "fooos", 7, !kFin, &last_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); + SendStreamDataToPeer(stream_id, "foos", 3, NO_FIN, &last_packet); + SendStreamDataToPeer(stream_id, "fooos", 7, NO_FIN, &last_packet); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); connection_.SendRstStream(stream_id, QUIC_STREAM_NO_ERROR, 14); @@ -2080,7 +2087,7 @@ TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnRTO) { QuicStreamId stream_id = 2; QuicPacketNumber last_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); connection_.SendRstStream(stream_id, QUIC_ERROR_PROCESSING_STREAM, 14); @@ -2099,7 +2106,7 @@ TEST_P(QuicConnectionTest, CancelRetransmissionAlarmAfterResetStream) { QuicStreamId stream_id = 2; QuicPacketNumber last_data_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_data_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_data_packet); // Cancel the stream. const QuicPacketNumber rst_packet = last_data_packet + 1; @@ -2126,7 +2133,7 @@ QuicStreamId stream_id = 2; QuicPacketNumber last_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); connection_.SendRstStream(stream_id, QUIC_STREAM_NO_ERROR, 14); @@ -2144,10 +2151,10 @@ TEST_P(QuicConnectionTest, DoNotSendPendingRetransmissionForResetStream) { QuicStreamId stream_id = 2; QuicPacketNumber last_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_packet); - SendStreamDataToPeer(stream_id, "foos", 3, !kFin, &last_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); + SendStreamDataToPeer(stream_id, "foos", 3, NO_FIN, &last_packet); BlockOnNextWrite(); - connection_.SendStreamDataWithString(stream_id, "fooos", 7, !kFin, nullptr); + connection_.SendStreamDataWithString(stream_id, "fooos", 7, NO_FIN, nullptr); // Lose a packet which will trigger a pending retransmission. QuicAckFrame ack = InitAckFrame(last_packet); @@ -2173,10 +2180,10 @@ TEST_P(QuicConnectionTest, SendPendingRetransmissionForQuicRstStreamNoError) { QuicStreamId stream_id = 2; QuicPacketNumber last_packet; - SendStreamDataToPeer(stream_id, "foo", 0, !kFin, &last_packet); - SendStreamDataToPeer(stream_id, "foos", 3, !kFin, &last_packet); + SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet); + SendStreamDataToPeer(stream_id, "foos", 3, NO_FIN, &last_packet); BlockOnNextWrite(); - connection_.SendStreamDataWithString(stream_id, "fooos", 7, !kFin, nullptr); + connection_.SendStreamDataWithString(stream_id, "fooos", 7, NO_FIN, nullptr); // Lose a packet which will trigger a pending retransmission. QuicAckFrame ack = InitAckFrame(last_packet); @@ -2203,9 +2210,9 @@ TEST_P(QuicConnectionTest, RetransmitAckedPacket) { QuicPacketNumber last_packet; - SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1 - SendStreamDataToPeer(1, "foos", 3, !kFin, &last_packet); // Packet 2 - SendStreamDataToPeer(1, "fooos", 7, !kFin, &last_packet); // Packet 3 + SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); // Packet 1 + SendStreamDataToPeer(1, "foos", 3, NO_FIN, &last_packet); // Packet 2 + SendStreamDataToPeer(1, "fooos", 7, NO_FIN, &last_packet); // Packet 3 EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); @@ -2248,7 +2255,7 @@ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<2>(&largest_observed), SaveArg<3>(&packet_size), Return(true))); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); QuicAckFrame frame = InitAckFrame(1); NackPacket(largest_observed, &frame); @@ -2268,7 +2275,7 @@ for (int i = 0; i < 10; ++i) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); - connection_.SendStreamDataWithString(3, "foo", i * 3, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", i * 3, NO_FIN, nullptr); } // Block the writer and ensure they're queued. @@ -2293,7 +2300,7 @@ BlockOnNextWrite(); writer_->set_is_write_blocked_data_buffered(true); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); writer_->SetWritable(); @@ -2304,14 +2311,14 @@ TEST_P(QuicConnectionTest, WriteBlockedThenSent) { EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0); BlockOnNextWrite(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); EXPECT_EQ(1u, connection_.NumQueuedPackets()); // The second packet should also be queued, in order to ensure packets are // never sent out of order. writer_->SetWritable(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(2u, connection_.NumQueuedPackets()); // Now both are sent in order when we unblock. @@ -2322,7 +2329,7 @@ TEST_P(QuicConnectionTest, RetransmitWriteBlockedAckedOriginalThenSent) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet()); BlockOnNextWrite(); @@ -2347,7 +2354,7 @@ TEST_P(QuicConnectionTest, AlarmsWhenWriteBlocked) { // Block the connection. BlockOnNextWrite(); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(1u, writer_->packets_write_attempts()); EXPECT_TRUE(writer_->IsWriteBlocked()); @@ -2366,7 +2373,7 @@ int offset = 0; // Send packets 1 to 15. for (int i = 0; i < 15; ++i) { - SendStreamDataToPeer(1, "foo", offset, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", offset, NO_FIN, nullptr); offset += 3; } @@ -2392,16 +2399,16 @@ // Test sending multiple acks from the connection to the session. TEST_P(QuicConnectionTest, MultipleAcks) { QuicPacketNumber last_packet; - SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1 + SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); // Packet 1 EXPECT_EQ(1u, last_packet); - SendStreamDataToPeer(3, "foo", 0, !kFin, &last_packet); // Packet 2 + SendStreamDataToPeer(3, "foo", 0, NO_FIN, &last_packet); // Packet 2 EXPECT_EQ(2u, last_packet); SendAckPacketToPeer(); // Packet 3 - SendStreamDataToPeer(5, "foo", 0, !kFin, &last_packet); // Packet 4 + SendStreamDataToPeer(5, "foo", 0, NO_FIN, &last_packet); // Packet 4 EXPECT_EQ(4u, last_packet); - SendStreamDataToPeer(1, "foo", 3, !kFin, &last_packet); // Packet 5 + SendStreamDataToPeer(1, "foo", 3, NO_FIN, &last_packet); // Packet 5 EXPECT_EQ(5u, last_packet); - SendStreamDataToPeer(3, "foo", 3, !kFin, &last_packet); // Packet 6 + SendStreamDataToPeer(3, "foo", 3, NO_FIN, &last_packet); // Packet 6 EXPECT_EQ(6u, last_packet); // Client will ack packets 1, 2, [!3], 4, 5. @@ -2418,7 +2425,7 @@ } TEST_P(QuicConnectionTest, DontLatchUnackedPacket) { - SendStreamDataToPeer(1, "foo", 0, !kFin, nullptr); // Packet 1; + SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); // Packet 1; // From now on, we send acks, so the send algorithm won't mark them pending. ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillByDefault(Return(false)); @@ -2460,7 +2467,7 @@ ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillByDefault(Return(true)); - SendStreamDataToPeer(1, "bar", 3, false, nullptr); // Packet 4 + SendStreamDataToPeer(1, "bar", 3, NO_FIN, nullptr); // Packet 4 EXPECT_EQ(4u, stop_waiting()->least_unacked); ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillByDefault(Return(false)); @@ -2476,8 +2483,8 @@ // the least unacked is raised above the ack packets. ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillByDefault(Return(true)); - SendStreamDataToPeer(1, "bar", 6, false, nullptr); // Packet 6 - SendStreamDataToPeer(1, "bar", 9, false, nullptr); // Packet 7 + SendStreamDataToPeer(1, "bar", 6, NO_FIN, nullptr); // Packet 6 + SendStreamDataToPeer(1, "bar", 9, NO_FIN, nullptr); // Packet 7 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); frame = InitAckFrame(7); @@ -2491,7 +2498,7 @@ TEST_P(QuicConnectionTest, TLP) { connection_.SetMaxTailLossProbes(1); - SendStreamDataToPeer(3, "foo", 0, !kFin, nullptr); + SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(1u, stop_waiting()->least_unacked); QuicTime retransmission_time = connection_.GetRetransmissionAlarm()->deadline(); @@ -2513,7 +2520,7 @@ QuicTime default_retransmission_time = clock_.ApproximateNow() + DefaultRetransmissionTime(); - SendStreamDataToPeer(3, "foo", 0, !kFin, nullptr); + SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(1u, stop_waiting()->least_unacked); EXPECT_EQ(1u, writer_->header().packet_number); @@ -2534,12 +2541,12 @@ // A TaggingEncrypter puts kTagSize copies of the given byte (0x01 here) at // the end of the packet. We can test this to check which encrypter was used. connection_.SetEncrypter(ENCRYPTION_NONE, new TaggingEncrypter(0x01)); - SendStreamDataToPeer(kCryptoStreamId, "foo", 0, !kFin, nullptr); + SendStreamDataToPeer(kCryptoStreamId, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(0x01010101u, writer_->final_bytes_of_last_packet()); connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(0x02)); connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL); - SendStreamDataToPeer(3, "foo", 0, !kFin, nullptr); + SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet()); { @@ -2568,7 +2575,7 @@ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _)) .WillRepeatedly(testing::Return(QuicTime::Delta::Zero())); BlockOnNextWrite(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); // The packet should be serialized, but not queued. EXPECT_EQ(1u, connection_.NumQueuedPackets()); @@ -2591,7 +2598,7 @@ use_tagging_decrypter(); connection_.SetEncrypter(ENCRYPTION_NONE, new TaggingEncrypter(0x01)); QuicPacketNumber packet_number; - SendStreamDataToPeer(kCryptoStreamId, "foo", 0, !kFin, &packet_number); + SendStreamDataToPeer(kCryptoStreamId, "foo", 0, NO_FIN, &packet_number); // Simulate the retransmission alarm firing and the socket blocking. BlockOnNextWrite(); @@ -2616,12 +2623,12 @@ connection_.SetEncrypter(ENCRYPTION_NONE, new TaggingEncrypter(0x01)); connection_.SetDefaultEncryptionLevel(ENCRYPTION_NONE); - SendStreamDataToPeer(1, "foo", 0, !kFin, nullptr); + SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(0x02)); connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL); - SendStreamDataToPeer(2, "bar", 0, !kFin, nullptr); + SendStreamDataToPeer(2, "bar", 0, NO_FIN, nullptr); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); connection_.RetransmitUnackedPackets(ALL_INITIAL_RETRANSMISSION); @@ -2695,11 +2702,11 @@ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<3>(&first_packet_size), Return(true))); - connection_.SendStreamDataWithString(3, "first_packet", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "first_packet", 0, NO_FIN, nullptr); QuicByteCount second_packet_size; EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<3>(&second_packet_size), Return(true))); - connection_.SendStreamDataWithString(3, "second_packet", 12, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "second_packet", 12, NO_FIN, nullptr); EXPECT_NE(first_packet_size, second_packet_size); // Advance the clock by huge time to make sure packets will be retransmitted. clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10)); @@ -2723,7 +2730,7 @@ TEST_P(QuicConnectionTest, SetRTOAfterWritingToSocket) { BlockOnNextWrite(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); // Make sure that RTO is not started when the packet is queued. EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); @@ -2738,8 +2745,8 @@ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2); - connection_.SendStreamDataWithString(2, "foo", 0, !kFin, nullptr); - connection_.SendStreamDataWithString(3, "bar", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(2, "foo", 0, NO_FIN, nullptr); + connection_.SendStreamDataWithString(3, "bar", 0, NO_FIN, nullptr); QuicAlarm* retransmission_alarm = connection_.GetRetransmissionAlarm(); EXPECT_TRUE(retransmission_alarm->IsSet()); EXPECT_EQ(clock_.Now() + DefaultRetransmissionTime(), @@ -2781,7 +2788,7 @@ EXPECT_EQ(0u, connection_.NumQueuedPackets()); BlockOnNextWrite(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(1u, connection_.NumQueuedPackets()); // Unblock the writes and actually send. @@ -2835,7 +2842,7 @@ EXPECT_TRUE(connection_.connected()); // Send and ack new data 3 seconds later to lengthen the idle timeout. - SendStreamDataToPeer(kHeadersStreamId, "GET /", 0, kFin, nullptr); + SendStreamDataToPeer(kHeadersStreamId, "GET /", 0, FIN, nullptr); clock_.AdvanceTime(QuicTime::Delta::FromSeconds(3)); QuicAckFrame frame = InitAckFrame(1); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); @@ -2873,7 +2880,7 @@ // the ping alarm. clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); - SendStreamDataToPeer(kHeadersStreamId, "GET /", 0, kFin, nullptr); + SendStreamDataToPeer(kHeadersStreamId, "GET /", 0, FIN, nullptr); EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); EXPECT_EQ(clock_.ApproximateNow() + QuicTime::Delta::FromSeconds(15), connection_.GetPingAlarm()->deadline()); @@ -2918,7 +2925,7 @@ // the ping alarm. clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); - SendStreamDataToPeer(kHeadersStreamId, "GET /", 0, kFin, nullptr); + SendStreamDataToPeer(kHeadersStreamId, "GET /", 0, FIN, nullptr); EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); EXPECT_EQ(clock_.ApproximateNow() + QuicTime::Delta::FromSeconds(10), connection_.GetPingAlarm()->deadline()); @@ -2972,7 +2979,7 @@ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<3>(&size_before_mtu_change), Return(true))) .WillOnce(Return(true)); - connection_.SendStreamDataWithString(3, data, 0, kFin, nullptr); + connection_.SendStreamDataWithString(3, data, 0, FIN, nullptr); EXPECT_EQ(3u, creator_->packet_number()); EXPECT_EQ(kDefaultMaxPacketSize, size_before_mtu_change); @@ -2985,7 +2992,7 @@ // Send the same data again. Check that it fits into a single packet now. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); - connection_.SendStreamDataWithString(3, data, 0, kFin, nullptr); + connection_.SendStreamDataWithString(3, data, 0, FIN, nullptr); EXPECT_EQ(4u, creator_->packet_number()); } @@ -2996,7 +3003,7 @@ const QuicPacketCount number_of_packets = kPacketsBetweenMtuProbesBase * 2; for (QuicPacketCount i = 0; i < number_of_packets; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); EXPECT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); EXPECT_EQ(0u, connection_.mtu_probe_count()); } @@ -3011,13 +3018,12 @@ // Send enough packets so that the next one triggers path MTU discovery. for (QuicPacketCount i = 0; i < kPacketsBetweenMtuProbesBase - 1; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } // Trigger the probe. - SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, - /*fin=*/false, nullptr); + SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, NO_FIN, nullptr); ASSERT_TRUE(connection_.GetMtuDiscoveryAlarm()->IsSet()); QuicByteCount probe_size; EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) @@ -3038,7 +3044,7 @@ // Send more packets, and ensure that none of them sets the alarm. for (QuicPacketCount i = 0; i < 4 * kPacketsBetweenMtuProbesBase; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } @@ -3076,7 +3082,7 @@ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)) .Times(AnyNumber()); for (QuicPacketCount i = 0; i < number_of_packets; i++) { - SendStreamDataToPeer(3, "!", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, "!", i, NO_FIN, nullptr); clock_.AdvanceTime(rtt); // Receive an ACK, which marks all data packets as received, and all MTU @@ -3127,13 +3133,12 @@ // Send enough packets so that the next one triggers path MTU discovery. for (QuicPacketCount i = 0; i < kPacketsBetweenMtuProbesBase - 1; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } // Trigger the probe. - SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, - /*fin=*/false, nullptr); + SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, NO_FIN, nullptr); ASSERT_TRUE(connection_.GetMtuDiscoveryAlarm()->IsSet()); QuicByteCount probe_size; EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) @@ -3155,7 +3160,7 @@ // Send more packets, and ensure that none of them sets the alarm. for (QuicPacketCount i = 0; i < 4 * kPacketsBetweenMtuProbesBase; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } @@ -3175,13 +3180,12 @@ // Send enough packets so that the next one triggers path MTU discovery. for (QuicPacketCount i = 0; i < kPacketsBetweenMtuProbesBase - 1; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } // Trigger the probe. - SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, - /*fin=*/false, nullptr); + SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, NO_FIN, nullptr); ASSERT_TRUE(connection_.GetMtuDiscoveryAlarm()->IsSet()); writer_->SimulateNextPacketTooLarge(); connection_.GetMtuDiscoveryAlarm()->Fire(); @@ -3220,12 +3224,11 @@ // Send enough packets so that the next one triggers path MTU discovery. for (QuicPacketCount i = 0; i < kPacketsBetweenMtuProbesBase - 1; i++) { - SendStreamDataToPeer(3, ".", i, /*fin=*/false, nullptr); + SendStreamDataToPeer(3, ".", i, NO_FIN, nullptr); ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); } - SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, - /*fin=*/false, nullptr); + SendStreamDataToPeer(3, "!", kPacketsBetweenMtuProbesBase, NO_FIN, nullptr); EXPECT_TRUE(connection_.GetMtuDiscoveryAlarm()->IsSet()); EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)); @@ -3249,13 +3252,13 @@ // When we send a packet, the timeout will change to 5ms + // kInitialIdleTimeoutSecs. clock_.AdvanceTime(five_ms); - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); // Now send more data. This will not move the timeout becase // no data has been recieved since the previous write. clock_.AdvanceTime(five_ms); - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); // The original alarm will fire. We should not time out because we had a @@ -3304,7 +3307,7 @@ const QuicTime send_time = start_time + five_ms; clock_.AdvanceTime(five_ms); ASSERT_EQ(send_time, clock_.Now()); - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); // Move forward 5 ms and receive a packet, which will move the timeout @@ -3386,13 +3389,13 @@ // When we send a packet, the timeout will change to 5ms + // kInitialIdleTimeoutSecs. clock_.AdvanceTime(five_ms); - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); // Now send more data. This will not move the timeout becase // no data has been recieved since the previous write. clock_.AdvanceTime(five_ms); - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); // The original alarm will fire. We should not time out because we had a @@ -3428,9 +3431,9 @@ const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5); QuicTime default_timeout = clock_.ApproximateNow() + initial_idle_timeout; - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, NO_FIN, nullptr); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, NO_FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); @@ -3480,10 +3483,10 @@ QuicTime default_timeout = clock_.ApproximateNow() + initial_idle_timeout; EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, NO_FIN, nullptr); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, NO_FIN, nullptr); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); @@ -3513,7 +3516,7 @@ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber()); for (int i = 0; i < 100 && connection_.connected(); ++i) { QUIC_LOG(INFO) << "sending data packet"; - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, NO_FIN, nullptr); connection_.GetTimeoutAlarm()->Fire(); clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); @@ -3533,7 +3536,7 @@ connection_.SetFromConfig(config); // Send stream data. - SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, kFin, nullptr); + SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr); EXPECT_CALL(visitor_, OnPathDegrading()); // Fire the retransmission alarm 6 times, twice for TLP and 4 times for RTO. @@ -3596,7 +3599,7 @@ .WillOnce(testing::Return(QuicTime::Delta::FromMicroseconds(10))); const string payload(payload_length, 'a'); EXPECT_EQ(0u, - connection_.SendStreamDataWithString(3, payload, 0, !kFin, nullptr) + connection_.SendStreamDataWithString(3, payload, 0, NO_FIN, nullptr) .bytes_consumed); EXPECT_EQ(0u, connection_.NumQueuedPackets()); } @@ -3621,7 +3624,7 @@ // The first stream frame will have 2 fewer overhead bytes than the other six. const string payload(payload_length * 7 + 2, 'a'); EXPECT_EQ(payload.size(), - connection_.SendStreamDataWithString(1, payload, 0, !kFin, nullptr) + connection_.SendStreamDataWithString(1, payload, 0, NO_FIN, nullptr) .bytes_consumed); } @@ -3633,7 +3636,7 @@ // Now send some packets with no truncation. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2); EXPECT_EQ(payload.size(), - connection_.SendStreamDataWithString(3, payload, 0, !kFin, nullptr) + connection_.SendStreamDataWithString(3, payload, 0, NO_FIN, nullptr) .bytes_consumed); // Track the size of the second packet here. The overhead will be the largest // we see in this test, due to the non-truncated connection id. @@ -3645,7 +3648,7 @@ connection_.SetFromConfig(config); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2); EXPECT_EQ(payload.size(), - connection_.SendStreamDataWithString(3, payload, 0, !kFin, nullptr) + connection_.SendStreamDataWithString(3, payload, 0, NO_FIN, nullptr) .bytes_consumed); // Just like above, we save 8 bytes on payload, and 8 on truncation. EXPECT_EQ(non_truncated_packet_size, writer_->last_packet_size() + 8 * 2); @@ -4153,7 +4156,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckOnOutgoingPacket) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); ProcessPacket(1); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, NO_FIN, nullptr); // Check that ack is bundled with outgoing data and that delayed ack // alarm is reset. @@ -4171,14 +4174,14 @@ TEST_P(QuicConnectionTest, SendDelayedAckOnOutgoingCryptoPacket) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); ProcessPacket(1); - connection_.SendStreamDataWithString(kCryptoStreamId, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kCryptoStreamId, "foo", 0, NO_FIN, nullptr); // Check that ack is bundled with outgoing crypto data. if (GetParam().no_stop_waiting) { - EXPECT_EQ(2u, writer_->frame_count()); + EXPECT_EQ(3u, writer_->frame_count()); EXPECT_TRUE(writer_->stop_waiting_frames().empty()); } else { - EXPECT_EQ(3u, writer_->frame_count()); + EXPECT_EQ(4u, writer_->frame_count()); EXPECT_FALSE(writer_->stop_waiting_frames().empty()); } EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); @@ -4189,11 +4192,11 @@ ProcessPacket(1); BlockOnNextWrite(); writer_->set_is_write_blocked_data_buffered(true); - connection_.SendStreamDataWithString(kCryptoStreamId, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kCryptoStreamId, "foo", 0, NO_FIN, nullptr); EXPECT_TRUE(writer_->IsWriteBlocked()); EXPECT_FALSE(connection_.HasQueuedData()); - connection_.SendStreamDataWithString(kCryptoStreamId, "bar", 3, !kFin, + connection_.SendStreamDataWithString(kCryptoStreamId, "bar", 3, NO_FIN, nullptr); EXPECT_TRUE(writer_->IsWriteBlocked()); EXPECT_TRUE(connection_.HasQueuedData()); @@ -4211,13 +4214,14 @@ ProcessPacket(2); // Check that ack is sent and that delayed ack alarm is reset. if (GetParam().no_stop_waiting) { - EXPECT_EQ(2u, writer_->frame_count()); + EXPECT_EQ(3u, writer_->frame_count()); EXPECT_TRUE(writer_->stop_waiting_frames().empty()); } else { - EXPECT_EQ(3u, writer_->frame_count()); + EXPECT_EQ(4u, writer_->frame_count()); EXPECT_FALSE(writer_->stop_waiting_frames().empty()); } EXPECT_EQ(1u, writer_->stream_frames().size()); + EXPECT_EQ(1u, writer_->padding_frames().size()); EXPECT_FALSE(writer_->ack_frames().empty()); EXPECT_EQ(2u, writer_->ack_frames().front().largest_observed); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); @@ -4239,13 +4243,14 @@ } // Check that ack is sent and that delayed ack alarm is reset. if (GetParam().no_stop_waiting) { - EXPECT_EQ(2u, writer_->frame_count()); + EXPECT_EQ(3u, writer_->frame_count()); EXPECT_TRUE(writer_->stop_waiting_frames().empty()); } else { - EXPECT_EQ(3u, writer_->frame_count()); + EXPECT_EQ(4u, writer_->frame_count()); EXPECT_FALSE(writer_->stop_waiting_frames().empty()); } EXPECT_EQ(1u, writer_->stream_frames().size()); + EXPECT_EQ(1u, writer_->padding_frames().size()); EXPECT_FALSE(writer_->ack_frames().empty()); EXPECT_EQ(2u, writer_->ack_frames().front().largest_observed); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); @@ -4253,9 +4258,9 @@ TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, NO_FIN, nullptr); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 3, NO_FIN, nullptr); // Ack the second packet, which will retransmit the first packet. QuicAckFrame ack = InitAckFrame(2); @@ -4557,11 +4562,11 @@ connection_.SetMaxTailLossProbes(0); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - connection_.SendStreamDataWithString(3, "first", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "first", 0, NO_FIN, nullptr); size_t first_packet_size = writer_->last_packet_size(); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); - connection_.SendStreamDataWithString(5, "second", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(5, "second", 0, NO_FIN, nullptr); size_t second_packet_size = writer_->last_packet_size(); // 2 retransmissions due to rto, 1 due to explicit nack. @@ -4664,7 +4669,7 @@ EXPECT_FALSE(writer_->IsWriteBlocked()); // Send a packet. - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(0u, connection_.NumQueuedPackets()); EXPECT_EQ(1u, writer_->packets_write_attempts()); @@ -4681,7 +4686,7 @@ TEST_P(QuicConnectionTest, ConnectionCloseWhenWriteBlocked) { BlockOnNextWrite(); - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(1u, connection_.NumQueuedPackets()); EXPECT_EQ(1u, writer_->packets_write_attempts()); EXPECT_TRUE(writer_->IsWriteBlocked()); @@ -4697,7 +4702,7 @@ EXPECT_CALL(*listener, OnPacketAcked(_, _)).Times(1); // Send some data, which will register the listener to be notified. - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, listener); // Process an ACK from the server which should trigger the callback. EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); @@ -4714,11 +4719,11 @@ // Send some data, which will register the listener to be notified. This will // not be ACKed and so the listener should never be called. - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, listener); // Send some other data which we will ACK. - connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr); - connection_.SendStreamDataWithString(1, "bar", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN, nullptr); + connection_.SendStreamDataWithString(1, "bar", 0, NO_FIN, nullptr); // Now we receive ACK for packets 2 and 3, but importantly missing packet 1 // which we registered to be notified about. @@ -4741,10 +4746,10 @@ EXPECT_CALL(*listener, OnPacketAcked(3, _)).Times(1); // Send four packets, and register to be notified on ACK of packet 2. - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); - connection_.SendStreamDataWithString(3, "bar", 0, !kFin, listener); - connection_.SendStreamDataWithString(3, "baz", 0, !kFin, nullptr); - connection_.SendStreamDataWithString(3, "qux", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); + connection_.SendStreamDataWithString(3, "bar", 0, NO_FIN, listener); + connection_.SendStreamDataWithString(3, "baz", 0, NO_FIN, nullptr); + connection_.SendStreamDataWithString(3, "qux", 0, NO_FIN, nullptr); // Now we receive ACK for packets 1, 3, and 4 and lose 2. QuicAckFrame frame = InitAckFrame(4); @@ -4777,7 +4782,7 @@ QuicTime default_retransmission_time = clock_.ApproximateNow() + DefaultRetransmissionTime(); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, listener); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, listener); EXPECT_EQ(1u, stop_waiting()->least_unacked); EXPECT_EQ(1u, writer_->header().packet_number); @@ -4814,10 +4819,10 @@ new StrictMock<MockAckListener>()); // Send four packets, and register to be notified on ACK of packet 2. - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); - connection_.SendStreamDataWithString(3, "bar", 0, !kFin, listener); - connection_.SendStreamDataWithString(3, "baz", 0, !kFin, nullptr); - connection_.SendStreamDataWithString(3, "qux", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); + connection_.SendStreamDataWithString(3, "bar", 0, NO_FIN, listener); + connection_.SendStreamDataWithString(3, "baz", 0, NO_FIN, nullptr); + connection_.SendStreamDataWithString(3, "qux", 0, NO_FIN, nullptr); // Now we receive ACK for packets 1, 3, and 4 and lose 2. QuicAckFrame frame = InitAckFrame(4); @@ -4908,7 +4913,7 @@ // Regression test for b/18594622 QuicReferenceCountedPointer<MockAckListener> listener(new MockAckListener); EXPECT_QUIC_BUG( - connection_.SendStreamDataWithString(3, "", 0, !kFin, listener), + connection_.SendStreamDataWithString(3, "", 0, NO_FIN, listener), "Attempt to send empty stream frame"); } @@ -4923,7 +4928,7 @@ TEST_P(QuicConnectionTest, ReevaluateTimeUntilSendOnAck) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, + connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, NO_FIN, nullptr); // Evaluate CanWrite, and have it return a non-Zero value. @@ -4984,7 +4989,7 @@ _, ConnectionCloseSource::FROM_SELF)); struct iovec iov; QuicIOVector data_iov(MakeIOVector("", &iov)); - EXPECT_QUIC_BUG(connection_.SendStreamData(3, data_iov, 0, kFin, nullptr), + EXPECT_QUIC_BUG(connection_.SendStreamData(3, data_iov, 0, FIN, nullptr), "Cannot send stream data without encryption."); EXPECT_FALSE(connection_.connected()); } @@ -4995,7 +5000,7 @@ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) .WillOnce(DoAll(SaveArg<3>(&packet_size), Return(true))); - connection_.SendStreamDataWithString(3, "packet", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "packet", 0, NO_FIN, nullptr); size_t num_timeouts = kMinTimeoutsBeforePathDegrading + QuicSentPacketManagerPeer::GetMaxTailLossProbes( @@ -5071,7 +5076,7 @@ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PACKET_WRITE_ERROR, _, ConnectionCloseSource::FROM_SELF)) .Times(1); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); } TEST_P(QuicConnectionTest, AlwaysGetPacketTooLarge) { @@ -5081,7 +5086,7 @@ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PACKET_WRITE_ERROR, _, ConnectionCloseSource::FROM_SELF)) .Times(1); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); } // Verify that if connection has no outstanding data, it notifies the send @@ -5134,7 +5139,7 @@ // Simulate data packet causes write error. EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PACKET_WRITE_ERROR, _, _)); SimulateNextPacketTooLarge(); - connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr); + connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN, nullptr); EXPECT_EQ(1u, writer_->frame_count()); EXPECT_FALSE(writer_->connection_close_frames().empty()); // Ack frame is not bundled in connection close packet.
diff --git a/net/quic/core/quic_constants.h b/net/quic/core/quic_constants.h index 9cf0e6c..8fcf115 100644 --- a/net/quic/core/quic_constants.h +++ b/net/quic/core/quic_constants.h
@@ -180,6 +180,9 @@ // This will likely have to be tuned. const QuicPacketNumber kMaxPacketGap = 5000; +// The maximum number of random padding bytes to add. +const QuicByteCount kMaxNumRandomPaddingBytes = 256; + } // namespace net #endif // NET_QUIC_CORE_QUIC_CONSTANTS_H_
diff --git a/net/quic/core/quic_crypto_client_stream.cc b/net/quic/core/quic_crypto_client_stream.cc index ee8d6432..837ebeb 100644 --- a/net/quic/core/quic_crypto_client_stream.cc +++ b/net/quic/core/quic_crypto_client_stream.cc
@@ -11,10 +11,10 @@ #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/crypto/crypto_utils.h" #include "net/quic/core/crypto/null_encrypter.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_session.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_str_cat.h"
diff --git a/net/quic/core/quic_crypto_client_stream_test.cc b/net/quic/core/quic_crypto_client_stream_test.cc index d69c7c9..d117457 100644 --- a/net/quic/core/quic_crypto_client_stream_test.cc +++ b/net/quic/core/quic_crypto_client_stream_test.cc
@@ -9,10 +9,10 @@ #include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h" #include "net/quic/core/crypto/quic_decrypter.h" #include "net/quic/core/crypto/quic_encrypter.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_server_id.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/quic_stream_peer.h" #include "net/quic/test_tools/quic_stream_sequencer_peer.h" @@ -64,7 +64,9 @@ framer.ConstructHandshakeMessage(message_, perspective)); } - QuicCryptoClientStream* stream() { return session_->GetCryptoStream(); } + QuicCryptoClientStream* stream() { + return session_->GetMutableCryptoStream(); + } MockQuicConnectionHelper server_helper_; MockQuicConnectionHelper client_helper_; @@ -372,14 +374,14 @@ } QuicCryptoServerStream* server_stream() { - return server_session_->GetCryptoStream(); + return server_session_->GetMutableCryptoStream(); } void AdvanceHandshakeWithFakeServer() { - client_session_->GetCryptoStream()->CryptoConnect(); - crypto_test_utils::AdvanceHandshake(client_connection_, - client_session_->GetCryptoStream(), 0, - server_connection_, server_stream(), 0); + client_session_->GetMutableCryptoStream()->CryptoConnect(); + crypto_test_utils::AdvanceHandshake( + client_connection_, client_session_->GetMutableCryptoStream(), 0, + server_connection_, server_stream(), 0); } // Initializes the server_stream_ for stateless rejects. @@ -432,8 +434,8 @@ EXPECT_EQ(1, server_stream()->NumHandshakeMessages()); EXPECT_EQ(0, server_stream()->NumHandshakeMessagesWithServerNonces()); - EXPECT_FALSE(client_session_->GetCryptoStream()->encryption_established()); - EXPECT_FALSE(client_session_->GetCryptoStream()->handshake_confirmed()); + EXPECT_FALSE(client_session_->IsEncryptionEstablished()); + EXPECT_FALSE(client_session_->IsCryptoHandshakeConfirmed()); // Even though the handshake was not complete, the cached client_state is // complete, and can be used for a subsequent successful handshake. EXPECT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0)));
diff --git a/net/quic/core/quic_crypto_server_stream.cc b/net/quic/core/quic_crypto_server_stream.cc index 49594d67..dfd0c4ac 100644 --- a/net/quic/core/quic_crypto_server_stream.cc +++ b/net/quic/core/quic_crypto_server_stream.cc
@@ -12,9 +12,9 @@ #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/proto/cached_network_parameters.pb.h" #include "net/quic/core/quic_config.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_session.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_string_piece.h" #include "net/quic/platform/api/quic_text_utils.h" @@ -143,8 +143,7 @@ } if (validate_client_hello_cb_ != nullptr || - (base::GetFlag(FLAGS_quic_reloadable_flag_fix_quic_callback_crash) && - process_client_hello_cb_ != nullptr)) { + process_client_hello_cb_ != nullptr) { // Already processing some other handshake message. The protocol // does not allow for clients to send multiple handshake messages // before the server has a chance to respond.
diff --git a/net/quic/core/quic_crypto_server_stream_test.cc b/net/quic/core/quic_crypto_server_stream_test.cc index d6e845c6..6bd69fb 100644 --- a/net/quic/core/quic_crypto_server_stream_test.cc +++ b/net/quic/core/quic_crypto_server_stream_test.cc
@@ -18,9 +18,9 @@ #include "net/quic/core/crypto/quic_encrypter.h" #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/quic_crypto_client_stream.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_session.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_socket_address.h" @@ -106,11 +106,11 @@ } QuicCryptoServerStream* server_stream() { - return server_session_->GetCryptoStream(); + return server_session_->GetMutableCryptoStream(); } QuicCryptoClientStream* client_stream() { - return client_session_->GetCryptoStream(); + return client_session_->GetMutableCryptoStream(); } // Initializes a fake client, and all its associated state, for @@ -535,7 +535,6 @@ TEST_P(QuicCryptoServerStreamTestWithFakeProofSource, MultipleChlo) { Initialize(); GetFakeProofSource()->Activate(); - base::SetFlag(&FLAGS_quic_reloadable_flag_fix_quic_callback_crash, true); EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _)) .WillOnce(testing::Return(true));
diff --git a/net/quic/core/quic_crypto_stream.cc b/net/quic/core/quic_crypto_stream.cc index ee8660a8..60ab843 100644 --- a/net/quic/core/quic_crypto_stream.cc +++ b/net/quic/core/quic_crypto_stream.cc
@@ -9,10 +9,10 @@ #include "net/quic/core/crypto/crypto_handshake.h" #include "net/quic/core/crypto/crypto_utils.h" #include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_session.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" using std::string;
diff --git a/net/quic/core/quic_data_reader.cc b/net/quic/core/quic_data_reader.cc index 0f728c9..77ea70a 100644 --- a/net/quic/core/quic_data_reader.cc +++ b/net/quic/core/quic_data_reader.cc
@@ -5,11 +5,11 @@ #include "net/quic/core/quic_data_reader.h" #include "net/base/int128.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_endian.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net {
diff --git a/net/quic/core/quic_data_writer.cc b/net/quic/core/quic_data_writer.cc index 28791917..9b1c426 100644 --- a/net/quic/core/quic_data_writer.cc +++ b/net/quic/core/quic_data_writer.cc
@@ -7,9 +7,9 @@ #include <algorithm> #include <limits> -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_endian.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" namespace net {
diff --git a/net/quic/core/quic_data_writer_test.cc b/net/quic/core/quic_data_writer_test.cc index 893ff42c..3e32ef9 100644 --- a/net/quic/core/quic_data_writer_test.cc +++ b/net/quic/core/quic_data_writer_test.cc
@@ -7,8 +7,8 @@ #include <cstdint> #include "net/quic/core/quic_data_reader.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/test_tools/quic_test_utils.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/net/quic/core/quic_flags.h b/net/quic/core/quic_flags.h deleted file mode 100644 index a1a5ff36..0000000 --- a/net/quic/core/quic_flags.h +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_QUIC_CORE_QUIC_FLAGS_H_ -#define NET_QUIC_CORE_QUIC_FLAGS_H_ - -#include <cstdint> -#include <string> - -#include "net/quic/platform/api/quic_export.h" - -#define QUIC_FLAG(type, flag, value) QUIC_EXPORT_PRIVATE extern type flag; -#include "net/quic/core/quic_flags_list.h" -#undef QUIC_FLAG - -// API compatibility with new-style flags. -namespace base { - -inline bool GetFlag(bool flag) { - return flag; -} -inline int32_t GetFlag(int32_t flag) { - return flag; -} -inline int64_t GetFlag(int64_t flag) { - return flag; -} -inline uint64_t GetFlag(uint64_t flag) { - return flag; -} -inline double GetFlag(double flag) { - return flag; -} -inline std::string GetFlag(const std::string& flag) { - return flag; -} - -inline void SetFlag(bool* f, bool v) { - *f = v; -} -inline void SetFlag(int32_t* f, int32_t v) { - *f = v; -} -inline void SetFlag(int64_t* f, int64_t v) { - *f = v; -} -inline void SetFlag(uint64_t* f, uint64_t v) { - *f = v; -} -inline void SetFlag(double* f, double v) { - *f = v; -} -inline void SetFlag(std::string* f, const std::string& v) { - *f = v; -} - -} // namespace base - -#endif // NET_QUIC_CORE_QUIC_FLAGS_H_
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h index 087ec25..e59f187 100644 --- a/net/quic/core/quic_flags_list.h +++ b/net/quic/core/quic_flags_list.h
@@ -62,9 +62,6 @@ FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame, true) -// If true, re-enables QUIC_VERSION_36. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_36_v3, true) - // If true, only open limited number of quic sessions per epoll event. Leave the // rest to next event. QUIC_FLAG(bool, @@ -119,19 +116,9 @@ FLAGS_quic_reloadable_flag_quic_fix_cubic_bytes_quantization, false) -// If true, Makes GFE respect the connection options for initial flow control -// window larger than 32 KB. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_large_ifw_options, true) - // If true, fix Cubic\'s use of kBetaLastMax for n-connection emulation. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_beta_last_max, false) -// If true, enable QUIC v37. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_37, true) - -// If true, disables QUIC v34. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_34, true) - // If greater than zero, mean RTT variation is multiplied by the specified // factor and added to the congestion window limit. QUIC_FLAG(double, FLAGS_quic_bbr_rtt_variation_weight, 0.0f) @@ -146,7 +133,7 @@ // If true, allows the 1RTT and 2RTT connection options to reduce the time // in BBR STARTUP to 1 or 2 RTTs with no bandwidth increase from 3. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_allow_2_rtt_bbr_startup, false) +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_allow_2_rtt_bbr_startup, true) // If true, do not send or process stop waiting frames in QUIC if the NSTP // connection option is provided. @@ -155,9 +142,6 @@ // Allows one self address change. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_allow_one_address_change, false) -// If true, no longer send or process the SRBF value in QuicConfig. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_no_socket_receive_buffer, false) - // If true, multipath bit is not used in public flag. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_remove_multipath_bit, false) @@ -167,10 +151,6 @@ FLAGS_quic_reloadable_flag_quic_flow_control_faster_autotune, true) -// Only consider using the ack spacing in QUIC BBR if 2 packets are acked at -// once. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_ack_spacing2, false) - // If true, QUIC BBR stores a max filtered number of bytes delivered at a rate // faster than the sending rate. QUIC_FLAG(bool, @@ -189,10 +169,6 @@ // Add the equivalent number of bytes as 3 TCP TSO segments to QUIC's BBR CWND. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd, false) -// Fix a crash that occurs when a client sends multiple CHLOs close together on -// the same connection. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_fix_quic_callback_crash, true) - // If true, enable version 38 which supports new PADDING frame and respects NSTP // connection option. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_38, true) @@ -215,3 +191,16 @@ // Simplify QUIC\'s adaptive time loss detection to measure the necessary // reordering window for every spurious retransmit. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_adaptive_time_loss, false) + +// In QUIC BBR, keep sending at the max bandwidth observed in the previous 2 +// RTTs for another SRTT. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_bbr_keep_sending_at_recent_rate, + false) + +// Base CWND on SRTT instead of min_rtt for QUIC BBR. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_base_cwnd_on_srtt, false) + +// If true, enable random padding of size [1, 256] when response body is +// compressed for QUIC version >= 38. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_random_padding, false)
diff --git a/net/quic/core/quic_flow_controller.cc b/net/quic/core/quic_flow_controller.cc index 1c27276..e95027eb 100644 --- a/net/quic/core/quic_flow_controller.cc +++ b/net/quic/core/quic_flow_controller.cc
@@ -7,10 +7,10 @@ #include <cstdint> #include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_str_cat.h" @@ -250,9 +250,12 @@ << " current offset: " << send_window_offset_ << " bytes_sent: " << bytes_sent_; - const bool blocked = IsBlocked(); + // The flow is now unblocked but could have also been unblocked + // before. Return true iff this update caused a change from blocked + // to unblocked. + const bool was_previously_blocked = IsBlocked(); send_window_offset_ = new_send_window_offset; - return blocked; + return was_previously_blocked; } void QuicFlowController::EnsureWindowAtLeast(QuicByteCount window_size) {
diff --git a/net/quic/core/quic_flow_controller.h b/net/quic/core/quic_flow_controller.h index 6f9acb3b..97c6fda 100644 --- a/net/quic/core/quic_flow_controller.h +++ b/net/quic/core/quic_flow_controller.h
@@ -62,8 +62,10 @@ // Called when bytes are sent to the peer. void AddBytesSent(QuicByteCount bytes_sent); - // Set a new send window offset. - // Returns true if this increases send_window_offset_ and is now blocked. + // Increases |send_window_offset_| if |new_send_window_offset| is + // greater than the current value. Returns true if this increase + // also causes us to change from a blocked state to unblocked. In + // all other cases, returns false. bool UpdateSendWindowOffset(QuicStreamOffset new_send_window_offset); // QuicFlowControllerInterface.
diff --git a/net/quic/core/quic_framer.cc b/net/quic/core/quic_framer.cc index 18102be..0fa3442 100644 --- a/net/quic/core/quic_framer.cc +++ b/net/quic/core/quic_framer.cc
@@ -17,12 +17,12 @@ #include "net/quic/core/crypto/quic_encrypter.h" #include "net/quic/core/quic_data_reader.h" #include "net/quic/core/quic_data_writer.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_socket_address_coder.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_aligned.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_map_util.h" #include "net/quic/platform/api/quic_ptr_util.h"
diff --git a/net/quic/core/quic_framer_test.cc b/net/quic/core/quic_framer_test.cc index 916127c..a39a272 100644 --- a/net/quic/core/quic_framer_test.cc +++ b/net/quic/core/quic_framer_test.cc
@@ -15,9 +15,9 @@ #include "net/quic/core/crypto/null_encrypter.h" #include "net/quic/core/crypto/quic_decrypter.h" #include "net/quic/core/crypto/quic_encrypter.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/test_tools/quic_framer_peer.h"
diff --git a/net/quic/core/quic_header_list.cc b/net/quic/core/quic_header_list.cc index ad8f999b..6c8c9a8 100644 --- a/net/quic/core/quic_header_list.cc +++ b/net/quic/core/quic_header_list.cc
@@ -4,8 +4,8 @@ #include "net/quic/core/quic_header_list.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/platform/api/quic_flags.h" using std::string;
diff --git a/net/quic/core/quic_header_list_test.cc b/net/quic/core/quic_header_list_test.cc index 42e2c4f..579c028 100644 --- a/net/quic/core/quic_header_list_test.cc +++ b/net/quic/core/quic_header_list_test.cc
@@ -4,7 +4,7 @@ #include "net/quic/core/quic_header_list.h" -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/test_tools/quic_test_utils.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/net/quic/core/quic_headers_stream.cc b/net/quic/core/quic_headers_stream.cc index 00c769c..38e3ff48 100644 --- a/net/quic/core/quic_headers_stream.cc +++ b/net/quic/core/quic_headers_stream.cc
@@ -4,8 +4,8 @@ #include "net/quic/core/quic_headers_stream.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_spdy_session.h" +#include "net/quic/platform/api/quic_flags.h" namespace net {
diff --git a/net/quic/core/quic_headers_stream_test.cc b/net/quic/core/quic_headers_stream_test.cc index 056f34b..3ef923d 100644 --- a/net/quic/core/quic_headers_stream_test.cc +++ b/net/quic/core/quic_headers_stream_test.cc
@@ -10,10 +10,10 @@ #include <tuple> #include <utility> -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_utils.h" #include "net/quic/core/spdy_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_str_cat.h" @@ -317,7 +317,7 @@ bool is_request) { // Write the headers and capture the outgoing data EXPECT_CALL(session_, - WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) + WritevData(headers_stream_, kHeadersStreamId, _, _, NO_FIN, _)) .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov))); QuicSpdySessionPeer::WriteHeadersImpl( &session_, stream_id, headers_.Clone(), fin, priority, nullptr); @@ -433,8 +433,8 @@ QuicStreamId promised_stream_id = NextPromisedStreamId(); if (perspective() == Perspective::IS_SERVER) { // Write the headers and capture the outgoing data - EXPECT_CALL(session_, - WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) + EXPECT_CALL(session_, WritevData(headers_stream_, kHeadersStreamId, _, _, + NO_FIN, _)) .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov))); session_.WritePushPromise(stream_id, promised_stream_id, headers_.Clone()); @@ -539,9 +539,8 @@ "Unsupported field of HTTP/2 SETTINGS frame: 2", _)); } headers_stream_->OnStreamFrame(stream_frame_); - EXPECT_EQ( - session_.server_push_enabled(), - (perspective() == Perspective::IS_CLIENT && version() > QUIC_VERSION_34)); + EXPECT_EQ(session_.server_push_enabled(), + perspective() == Perspective::IS_CLIENT); } TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) { @@ -944,8 +943,8 @@ if (use_ack_listener) { ack_listener = new ForceHolAckListener(); } - EXPECT_CALL(session_, - WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) + EXPECT_CALL(session_, WritevData(headers_stream_, kHeadersStreamId, _, _, + NO_FIN, _)) .WillRepeatedly(WithArgs<2, 5>(Invoke( this, &QuicHeadersStreamTest::SaveIovAndNotifyAckListener))); @@ -983,7 +982,7 @@ string data; EXPECT_CALL(session_, - WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) + WritevData(headers_stream_, kHeadersStreamId, _, _, NO_FIN, _)) .WillOnce(WithArgs<2, 5>( Invoke(this, &QuicHeadersStreamTest::SaveIovAndNotifyAckListener))); @@ -1015,7 +1014,7 @@ // In that case, |WritevStreamData| should consume just one // HTTP/2 data frame's worth of data. EXPECT_CALL(session_, - WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) + WritevData(headers_stream_, kHeadersStreamId, _, _, NO_FIN, _)) .WillOnce( WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIovShort)));
diff --git a/net/quic/core/quic_packet_creator.cc b/net/quic/core/quic_packet_creator.cc index bcafa95..6ee4217 100644 --- a/net/quic/core/quic_packet_creator.cc +++ b/net/quic/core/quic_packet_creator.cc
@@ -10,10 +10,11 @@ #include "base/macros.h" #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/quic_data_writer.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_aligned.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_string_piece.h" @@ -44,7 +45,9 @@ connection_id_(connection_id), packet_(0, PACKET_1BYTE_PACKET_NUMBER, nullptr, 0, false, false), latched_flag_no_stop_waiting_frames_( - FLAGS_quic_reloadable_flag_quic_no_stop_waiting_frames) { + FLAGS_quic_reloadable_flag_quic_no_stop_waiting_frames), + pending_padding_bytes_(0), + needs_full_padding_(false) { SetMaxPacketLength(kDefaultMaxPacketSize); } @@ -150,8 +153,9 @@ return false; } if (needs_full_padding) { - packet_.num_padding_bytes = -1; + needs_full_padding_ = true; } + return true; } @@ -279,7 +283,11 @@ // Temporarily set the packet number length and change the encryption level. packet_.packet_number_length = retransmission.packet_number_length; - packet_.num_padding_bytes = retransmission.num_padding_bytes; + if (retransmission.num_padding_bytes == -1) { + // Only retransmit padding when original packet needs full padding. Padding + // from pending_padding_bytes_ are not retransmitted. + needs_full_padding_ = true; + } // Only preserve the original encryption level if it's a handshake packet or // if we haven't gone forward secure. if (retransmission.has_crypto_handshake || @@ -307,7 +315,7 @@ } void QuicPacketCreator::Flush() { - if (!HasPendingFrames()) { + if (!HasPendingFrames() && pending_padding_bytes_ == 0) { return; } @@ -342,6 +350,7 @@ DCHECK(packet_.retransmittable_frames.empty()); packet_.listeners.clear(); packet_.largest_acked = 0; + needs_full_padding_ = false; } void QuicPacketCreator::CreateAndSerializeStreamFrame( @@ -455,7 +464,7 @@ bool QuicPacketCreator::AddPaddedSavedFrame(const QuicFrame& frame) { if (AddFrame(frame, /*save_retransmittable_frames=*/true)) { - packet_.num_padding_bytes = -1; + needs_full_padding_ = true; return true; } return false; @@ -471,7 +480,8 @@ void QuicPacketCreator::SerializePacket(char* encrypted_buffer, size_t encrypted_buffer_len) { DCHECK_LT(0u, encrypted_buffer_len); - QUIC_BUG_IF(queued_frames_.empty()) << "Attempt to serialize empty packet"; + QUIC_BUG_IF(queued_frames_.empty() && pending_padding_bytes_ == 0) + << "Attempt to serialize empty packet"; QuicPacketHeader header; // FillPacketHeader increments packet_number_. FillPacketHeader(&header); @@ -616,15 +626,29 @@ } void QuicPacketCreator::MaybeAddPadding() { - if (packet_.num_padding_bytes == 0) { - return; - } - + // The current packet should have no padding bytes because padding is only + // added when this method is called just before the packet is serialized. + DCHECK_EQ(0, packet_.num_padding_bytes); if (BytesFree() == 0) { // Don't pad full packets. return; } + if (!needs_full_padding_ && pending_padding_bytes_ == 0) { + // Do not need padding. + return; + } + + if (needs_full_padding_) { + // Full padding does not consume pending padding bytes. + packet_.num_padding_bytes = -1; + } else { + packet_.num_padding_bytes = + std::min<int16_t>(pending_padding_bytes_, BytesFree()); + pending_padding_bytes_ -= packet_.num_padding_bytes; + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_enable_random_padding); + } + bool success = AddFrame(QuicFrame(QuicPaddingFrame(packet_.num_padding_bytes)), false); DCHECK(success); @@ -635,4 +659,8 @@ packet_.encryption_level == ENCRYPTION_INITIAL; } +void QuicPacketCreator::AddPendingPadding(QuicByteCount size) { + pending_padding_bytes_ += size; +} + } // namespace net
diff --git a/net/quic/core/quic_packet_creator.h b/net/quic/core/quic_packet_creator.h index 68b70d4..33b81d2 100644 --- a/net/quic/core/quic_packet_creator.h +++ b/net/quic/core/quic_packet_creator.h
@@ -202,6 +202,10 @@ // Sets the maximum packet length. void SetMaxPacketLength(QuicByteCount length); + // Increases pending_padding_bytes by |size|. Pending padding will be sent by + // MaybeAddPadding(). + void AddPendingPadding(QuicByteCount size); + void set_debug_delegate(DebugDelegate* debug_delegate) { debug_delegate_ = debug_delegate; } @@ -210,6 +214,8 @@ return latched_flag_no_stop_waiting_frames_; } + QuicByteCount pending_padding_bytes() const { return pending_padding_bytes_; } + private: friend class test::QuicPacketCreatorPeer; @@ -242,9 +248,8 @@ // saves the |frame| in the next SerializedPacket. bool AddFrame(const QuicFrame& frame, bool save_retransmittable_frames); - // Adds a padding frame to the current packet only if the current packet - // contains a handshake message, and there is sufficient room to fit a - // padding frame. + // Adds a padding frame to the current packet (if there is space) when (1) + // current packet needs full padding or (2) there are pending paddings. void MaybeAddPadding(); // Serializes all frames which have been added and adds any which should be @@ -303,6 +308,16 @@ // The latched value of FLAGS_quic_reloadable_flag_quic_no_stop_waiting_frames bool latched_flag_no_stop_waiting_frames_; + // Pending padding bytes to send. Pending padding bytes will be sent in next + // packet(s) (after all other frames) if current constructed packet does not + // have room to send all of them. + QuicByteCount pending_padding_bytes_; + + // Indicates whether current constructed packet needs full padding to max + // packet size. Please note, full padding does not consume pending padding + // bytes. + bool needs_full_padding_; + DISALLOW_COPY_AND_ASSIGN(QuicPacketCreator); };
diff --git a/net/quic/core/quic_packet_creator_test.cc b/net/quic/core/quic_packet_creator_test.cc index 69cf24d..41a1593 100644 --- a/net/quic/core/quic_packet_creator_test.cc +++ b/net/quic/core/quic_packet_creator_test.cc
@@ -359,7 +359,7 @@ delete frame.stream_frame; } -TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSpecifiedPadding) { +TEST_P(QuicPacketCreatorTest, DoNotRetransmitPendingPadding) { QuicFrame frame; QuicIOVector io_vector(MakeIOVectorFromStringPiece("fake message data")); QuicPacketCreatorPeer::CreateStreamFrame(&creator_, kCryptoStreamId, @@ -381,6 +381,20 @@ packet_size = serialized_packet_.encrypted_length; } + { + InSequence s; + EXPECT_CALL(framer_visitor_, OnPacket()); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_)); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_)); + EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); + EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); + EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); + // Pending paddings are not retransmitted. + EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)).Times(0); + EXPECT_CALL(framer_visitor_, OnPacketComplete()); + } + ProcessPacket(serialized_packet_); + const int kNumPaddingBytes2 = 44; QuicFrames frames; frames.push_back(frame); @@ -393,8 +407,7 @@ .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); creator_.ReserializeAllFrames(retransmission, buffer, kMaxPacketSize); - EXPECT_EQ(packet_size + kNumPaddingBytes2 - kNumPaddingBytes1, - serialized_packet_.encrypted_length); + EXPECT_EQ(packet_size, serialized_packet_.encrypted_length); delete frame.stream_frame; } @@ -853,6 +866,169 @@ "Client hello won't fit in a single packet."); } +TEST_P(QuicPacketCreatorTest, PendingPadding) { + EXPECT_EQ(0u, creator_.pending_padding_bytes()); + creator_.AddPendingPadding(kMaxNumRandomPaddingBytes * 10); + EXPECT_EQ(kMaxNumRandomPaddingBytes * 10, creator_.pending_padding_bytes()); + + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly( + Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + // Flush all paddings. + while (creator_.pending_padding_bytes() > 0) { + creator_.Flush(); + { + InSequence s; + EXPECT_CALL(framer_visitor_, OnPacket()); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_)); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_)); + EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); + EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); + EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)); + EXPECT_CALL(framer_visitor_, OnPacketComplete()); + } + // Packet only contains padding. + ProcessPacket(serialized_packet_); + } + EXPECT_EQ(0u, creator_.pending_padding_bytes()); +} + +TEST_P(QuicPacketCreatorTest, FullPaddingDoesNotConsumePendingPadding) { + creator_.AddPendingPadding(kMaxNumRandomPaddingBytes); + QuicFrame frame; + QuicIOVector io_vector(MakeIOVectorFromStringPiece("test")); + ASSERT_TRUE(creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, 0u, false, + /*needs_full_padding=*/true, &frame)); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.Flush(); + EXPECT_EQ(kMaxNumRandomPaddingBytes, creator_.pending_padding_bytes()); +} + +TEST_P(QuicPacketCreatorTest, SendPendingPaddingInRetransmission) { + QuicStreamFrame* stream_frame = new QuicStreamFrame( + kCryptoStreamId, /*fin=*/false, 0u, QuicStringPiece()); + QuicFrames frames; + frames.push_back(QuicFrame(stream_frame)); + char buffer[kMaxPacketSize]; + QuicPendingRetransmission retransmission( + CreateRetransmission(frames, true, /*num_padding_bytes=*/0, + ENCRYPTION_NONE, PACKET_1BYTE_PACKET_NUMBER)); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.AddPendingPadding(kMaxNumRandomPaddingBytes); + creator_.ReserializeAllFrames(retransmission, buffer, kMaxPacketSize); + EXPECT_EQ(0u, creator_.pending_padding_bytes()); + { + InSequence s; + EXPECT_CALL(framer_visitor_, OnPacket()); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_)); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_)); + EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); + EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); + EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); + EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)); + EXPECT_CALL(framer_visitor_, OnPacketComplete()); + } + ProcessPacket(serialized_packet_); + delete stream_frame; +} + +TEST_P(QuicPacketCreatorTest, SendPacketAfterFullPaddingRetransmission) { + // Making sure needs_full_padding gets reset after a full padding + // retransmission. + EXPECT_EQ(0u, creator_.pending_padding_bytes()); + QuicFrame frame; + QuicIOVector io_vector( + MakeIOVectorFromStringPiece("fake handshake message data")); + QuicPacketCreatorPeer::CreateStreamFrame(&creator_, kCryptoStreamId, + io_vector, 0u, 0u, false, &frame); + QuicFrames frames; + frames.push_back(frame); + char buffer[kMaxPacketSize]; + QuicPendingRetransmission retransmission(CreateRetransmission( + frames, true, /*num_padding_bytes=*/-1, ENCRYPTION_NONE, + QuicPacketCreatorPeer::GetPacketNumberLength(&creator_))); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly( + Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.ReserializeAllFrames(retransmission, buffer, kMaxPacketSize); + EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet_.encrypted_length); + { + InSequence s; + EXPECT_CALL(framer_visitor_, OnPacket()); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_)); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_)); + EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); + EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); + EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); + // Full padding. + EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)); + EXPECT_CALL(framer_visitor_, OnPacketComplete()); + } + ProcessPacket(serialized_packet_); + delete frame.stream_frame; + + creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, 0u, false, false, + &frame); + creator_.Flush(); + { + InSequence s; + EXPECT_CALL(framer_visitor_, OnPacket()); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_)); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_)); + EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); + EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); + EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); + // needs_full_padding gets reset. + EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)).Times(0); + EXPECT_CALL(framer_visitor_, OnPacketComplete()); + } + ProcessPacket(serialized_packet_); +} + +TEST_P(QuicPacketCreatorTest, ConsumeDataAndRandomPadding) { + const QuicByteCount kStreamFramePayloadSize = 100u; + // Set the packet size be enough for one stream frame with 0 stream offset + + // 1. + size_t length = GetPacketHeaderOverhead(client_framer_.version()) + + GetEncryptionOverhead() + + QuicFramer::GetMinStreamFrameSize( + kCryptoStreamId, 0, /*last_frame_in_packet=*/false) + + kStreamFramePayloadSize + 1; + creator_.SetMaxPacketLength(length); + creator_.AddPendingPadding(kMaxNumRandomPaddingBytes); + QuicByteCount pending_padding_bytes = creator_.pending_padding_bytes(); + QuicFrame frame; + char buf[kStreamFramePayloadSize + 1] = {}; + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly( + Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + // Send stream frame of size kStreamFramePayloadSize. + creator_.ConsumeData(kCryptoStreamId, + MakeIOVectorFromStringPiece( + QuicStringPiece(buf, kStreamFramePayloadSize)), + 0u, 0u, false, false, &frame); + creator_.Flush(); + delete frame.stream_frame; + // 1 byte padding is sent. + EXPECT_EQ(pending_padding_bytes - 1, creator_.pending_padding_bytes()); + // Send stream frame of size kStreamFramePayloadSize + 1. + creator_.ConsumeData(kCryptoStreamId, + MakeIOVectorFromStringPiece( + QuicStringPiece(buf, kStreamFramePayloadSize + 1)), + 0u, 0u, false, false, &frame); + // No padding is sent. + creator_.Flush(); + delete frame.stream_frame; + EXPECT_EQ(pending_padding_bytes - 1, creator_.pending_padding_bytes()); + // Flush all paddings. + while (creator_.pending_padding_bytes() > 0) { + creator_.Flush(); + } + EXPECT_EQ(0u, creator_.pending_padding_bytes()); +} + } // namespace } // namespace test } // namespace net
diff --git a/net/quic/core/quic_packet_generator.cc b/net/quic/core/quic_packet_generator.cc index 025b54d5..dc68d253 100644 --- a/net/quic/core/quic_packet_generator.cc +++ b/net/quic/core/quic_packet_generator.cc
@@ -6,6 +6,7 @@ #include <cstdint> +#include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_logging.h" @@ -14,13 +15,15 @@ QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id, QuicFramer* framer, + QuicRandom* random_generator, QuicBufferAllocator* buffer_allocator, DelegateInterface* delegate) : delegate_(delegate), packet_creator_(connection_id, framer, buffer_allocator, delegate), batch_mode_(false), should_send_ack_(false), - should_send_stop_waiting_(false) {} + should_send_stop_waiting_(false), + random_generator_(random_generator) {} QuicPacketGenerator::~QuicPacketGenerator() { DeleteFrames(&queued_control_frames_); @@ -51,9 +54,10 @@ QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { bool has_handshake = (id == kCryptoStreamId); + bool fin = state != NO_FIN; QUIC_BUG_IF(has_handshake && fin) << "Handshake packets should never send a fin"; // To make reasoning about crypto frames easier, we don't combine them with @@ -93,6 +97,9 @@ } total_bytes_consumed += bytes_consumed; fin_consumed = fin && total_bytes_consumed == iov.total_length; + if (fin_consumed && state == FIN_AND_PADDING) { + AddRandomPadding(); + } DCHECK(total_bytes_consumed == iov.total_length || (bytes_consumed > 0 && packet_creator_.HasPendingFrames())); @@ -174,9 +181,10 @@ } bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const { - DCHECK(HasPendingFrames()); + DCHECK(HasPendingFrames() || packet_creator_.pending_padding_bytes() > 0); HasRetransmittableData retransmittable = - (should_send_ack_ || should_send_stop_waiting_) + (should_send_ack_ || should_send_stop_waiting_ || + packet_creator_.pending_padding_bytes() > 0) ? NO_RETRANSMITTABLE_DATA : HAS_RETRANSMITTABLE_DATA; if (retransmittable == HAS_RETRANSMITTABLE_DATA) { @@ -222,6 +230,7 @@ void QuicPacketGenerator::FinishBatchOperations() { batch_mode_ = false; SendQueuedFrames(/*flush=*/false); + SendRemainingPendingPadding(); } void QuicPacketGenerator::FlushAllQueuedFrames() { @@ -327,4 +336,16 @@ packet_creator_.SetEncrypter(level, encrypter); } +void QuicPacketGenerator::AddRandomPadding() { + packet_creator_.AddPendingPadding( + random_generator_->RandUint64() % kMaxNumRandomPaddingBytes + 1); +} + +void QuicPacketGenerator::SendRemainingPendingPadding() { + while (packet_creator_.pending_padding_bytes() > 0 && !HasQueuedFrames() && + CanSendWithNextPendingFrameAddition()) { + packet_creator_.Flush(); + } +} + } // namespace net
diff --git a/net/quic/core/quic_packet_generator.h b/net/quic/core/quic_packet_generator.h index 676691c..bd4604c 100644 --- a/net/quic/core/quic_packet_generator.h +++ b/net/quic/core/quic_packet_generator.h
@@ -73,6 +73,7 @@ QuicPacketGenerator(QuicConnectionId connection_id, QuicFramer* framer, + QuicRandom* random_generator, QuicBufferAllocator* buffer_allocator, DelegateInterface* delegate); @@ -92,11 +93,14 @@ // mode, these packets will also be sent during this call. // |delegate| (if not nullptr) will be informed once all packets sent as a // result of this call are ACKed by the peer. + // When |state| is FIN_AND_PADDING, random padding of size [1, 256] will be + // added after stream frames. If current constructed packet cannot + // accommodate, the padding will overflow to the next packet(s). QuicConsumedData ConsumeData( QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); // Sends as many data only packets as allowed by the send algorithm and the @@ -196,6 +200,13 @@ // fit into current open packet. bool AddNextPendingFrame(); + // Adds a random amount of padding (between 1 to 256 bytes). + void AddRandomPadding(); + + // Sends remaining pending padding. + // Pending paddings should only be sent when there is nothing else to send. + void SendRemainingPendingPadding(); + DelegateInterface* delegate_; QuicPacketCreator packet_creator_; @@ -213,6 +224,8 @@ // retransmitted. QuicStopWaitingFrame pending_stop_waiting_frame_; + QuicRandom* random_generator_; + DISALLOW_COPY_AND_ASSIGN(QuicPacketGenerator); };
diff --git a/net/quic/core/quic_packet_generator_test.cc b/net/quic/core/quic_packet_generator_test.cc index b7b4c7e..514d6df4 100644 --- a/net/quic/core/quic_packet_generator_test.cc +++ b/net/quic/core/quic_packet_generator_test.cc
@@ -17,6 +17,7 @@ #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_socket_address.h" #include "net/quic/platform/api/quic_string_piece.h" +#include "net/quic/test_tools/mock_random.h" #include "net/quic/test_tools/quic_packet_creator_peer.h" #include "net/quic/test_tools/quic_packet_generator_peer.h" #include "net/quic/test_tools/quic_test_utils.h" @@ -85,7 +86,8 @@ num_stop_waiting_frames(0), num_stream_frames(0), num_ping_frames(0), - num_mtu_discovery_frames(0) {} + num_mtu_discovery_frames(0), + num_padding_frames(0) {} size_t num_ack_frames; size_t num_connection_close_frames; @@ -95,6 +97,7 @@ size_t num_stream_frames; size_t num_ping_frames; size_t num_mtu_discovery_frames; + size_t num_padding_frames; }; } // namespace @@ -105,7 +108,11 @@ : framer_(AllSupportedVersions(), QuicTime::Zero(), Perspective::IS_CLIENT), - generator_(42, &framer_, &buffer_allocator_, &delegate_), + generator_(42, + &framer_, + &random_generator_, + &buffer_allocator_, + &delegate_), creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)) { creator_->SetEncrypter(ENCRYPTION_FORWARD_SECURE, new NullEncrypter(Perspective::IS_CLIENT)); @@ -145,7 +152,8 @@ contents.num_ping_frames; size_t num_frames = contents.num_ack_frames + contents.num_stop_waiting_frames + - contents.num_mtu_discovery_frames + num_retransmittable_frames; + contents.num_mtu_discovery_frames + contents.num_padding_frames + + num_retransmittable_frames; if (num_retransmittable_frames == 0) { ASSERT_TRUE(packet.retransmittable_frames.empty()); @@ -170,6 +178,8 @@ simple_framer_.stream_frames().size()); EXPECT_EQ(contents.num_stop_waiting_frames, simple_framer_.stop_waiting_frames().size()); + EXPECT_EQ(contents.num_padding_frames, + simple_framer_.padding_frames().size()); // From the receiver's perspective, MTU discovery frames are ping frames. EXPECT_EQ(contents.num_ping_frames + contents.num_mtu_discovery_frames, @@ -207,6 +217,7 @@ } QuicFramer framer_; + MockRandom random_generator_; SimpleBufferAllocator buffer_allocator_; StrictMock<MockDelegate> delegate_; QuicPacketGenerator generator_; @@ -342,7 +353,7 @@ delegate_.SetCanNotWrite(); QuicConsumedData consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, true, nullptr); + kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, FIN, nullptr); EXPECT_EQ(0u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -353,7 +364,7 @@ generator_.StartBatchOperations(); QuicConsumedData consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, true, nullptr); + kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, FIN, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); @@ -365,7 +376,7 @@ EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); QuicConsumedData consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, true, nullptr); + kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 2, FIN, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -385,12 +396,13 @@ EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); QuicConsumedData consumed = generator_.ConsumeData( - kCryptoStreamId, MakeIOVectorFromStringPiece("foo"), 0, false, nullptr); + kCryptoStreamId, MakeIOVectorFromStringPiece("foo"), 0, NO_FIN, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); PacketContents contents; contents.num_stream_frames = 1; + contents.num_padding_frames = 1; CheckPacketContains(contents, 0); ASSERT_EQ(1u, packets_.size()); @@ -401,7 +413,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_EmptyData) { EXPECT_QUIC_BUG( generator_.ConsumeData(kHeadersStreamId, MakeIOVectorFromStringPiece(""), - 0, false, nullptr), + 0, NO_FIN, nullptr), "Attempt to consume empty data without FIN."); } @@ -411,9 +423,9 @@ generator_.StartBatchOperations(); generator_.ConsumeData(kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), - 2, true, nullptr); + 2, FIN, nullptr); QuicConsumedData consumed = generator_.ConsumeData( - 3, MakeIOVectorFromStringPiece("quux"), 7, false, nullptr); + 3, MakeIOVectorFromStringPiece("quux"), 7, NO_FIN, nullptr); EXPECT_EQ(4u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); @@ -424,9 +436,9 @@ generator_.StartBatchOperations(); generator_.ConsumeData(kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), - 2, true, nullptr); + 2, FIN, nullptr); QuicConsumedData consumed = generator_.ConsumeData( - 3, MakeIOVectorFromStringPiece("quux"), 7, false, nullptr); + 3, MakeIOVectorFromStringPiece("quux"), 7, NO_FIN, nullptr); EXPECT_EQ(4u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); @@ -468,7 +480,7 @@ // Queue enough data to prevent a stream frame with a non-zero offset from // fitting. QuicConsumedData consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 0, false, nullptr); + kHeadersStreamId, MakeIOVectorFromStringPiece("foo"), 0, NO_FIN, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); @@ -476,7 +488,7 @@ // This frame will not fit with the existing frame, causing the queued frame // to be serialized, and it will be added to a new open packet. consumed = generator_.ConsumeData( - kHeadersStreamId, MakeIOVectorFromStringPiece("bar"), 3, true, nullptr); + kHeadersStreamId, MakeIOVectorFromStringPiece("bar"), 3, FIN, nullptr); EXPECT_EQ(3u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); @@ -524,7 +536,7 @@ .WillOnce(Return(QuicFrame(&ack_frame_))); // Send some data and a control frame - generator_.ConsumeData(3, MakeIOVectorFromStringPiece("quux"), 7, false, + generator_.ConsumeData(3, MakeIOVectorFromStringPiece("quux"), 7, NO_FIN, nullptr); generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame())); @@ -569,7 +581,7 @@ // Send enough data to exceed one packet size_t data_len = kDefaultMaxPacketSize + 100; QuicConsumedData consumed = - generator_.ConsumeData(3, CreateData(data_len), 0, true, nullptr); + generator_.ConsumeData(3, CreateData(data_len), 0, FIN, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame())); @@ -618,8 +630,7 @@ .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); QuicConsumedData consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), - /*offset=*/2, - /*fin=*/true, nullptr); + /*offset=*/2, FIN, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -653,8 +664,7 @@ // Send two packets before packet size change. QuicConsumedData consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), - /*offset=*/2, - /*fin=*/false, nullptr); + /*offset=*/2, NO_FIN, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -668,8 +678,7 @@ // Send a packet after packet size change. consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), - 2 + data_len, - /*fin=*/true, nullptr); + 2 + data_len, FIN, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -697,8 +706,7 @@ // should not cause packet serialization. QuicConsumedData consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(first_write_len), - /*offset=*/2, - /*fin=*/false, nullptr); + /*offset=*/2, NO_FIN, nullptr); EXPECT_EQ(first_write_len, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); @@ -727,8 +735,7 @@ // trigger serialization of one packet, and queue another one. consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(second_write_len), - /*offset=*/2 + first_write_len, - /*fin=*/true, nullptr); + /*offset=*/2 + first_write_len, FIN, nullptr); EXPECT_EQ(second_write_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_TRUE(generator_.HasQueuedFrames()); @@ -761,6 +768,7 @@ PacketContents contents; contents.num_mtu_discovery_frames = 1; + contents.num_padding_frames = 1; CheckPacketContains(contents, 0); } @@ -785,8 +793,7 @@ // Send data before the MTU probe. QuicConsumedData consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), - /*offset=*/2, - /*fin=*/false, nullptr); + /*offset=*/2, NO_FIN, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -797,8 +804,7 @@ // Send data after the MTU probe. consumed = generator_.ConsumeData(kHeadersStreamId, CreateData(data_len), - /*offset=*/2 + data_len, - /*fin=*/true, nullptr); + /*offset=*/2 + data_len, FIN, nullptr); EXPECT_EQ(data_len, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); EXPECT_FALSE(generator_.HasQueuedFrames()); @@ -810,6 +816,7 @@ PacketContents probe_contents; probe_contents.num_mtu_discovery_frames = 1; + probe_contents.num_padding_frames = 1; CheckPacketHasSingleStreamFrame(0); CheckPacketHasSingleStreamFrame(1); @@ -862,5 +869,142 @@ EXPECT_TRUE(generator_.HasQueuedFrames()); } +TEST_F(QuicPacketGeneratorTest, RandomPaddingAfterFinSingleStreamSinglePacket) { + const QuicByteCount kStreamFramePayloadSize = 100u; + char buf[kStreamFramePayloadSize] = {}; + const QuicStreamId kDataStreamId = 5; + // Set the packet size be enough for one stream frame with 0 stream offset and + // max size of random padding. + size_t length = NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) + + GetPacketHeaderSize( + framer_.version(), creator_->connection_id_length(), + kIncludeVersion, !kIncludeDiversificationNonce, + QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) + + QuicFramer::GetMinStreamFrameSize( + kDataStreamId, 0, /*last_frame_in_packet=*/false) + + kStreamFramePayloadSize + kMaxNumRandomPaddingBytes; + generator_.SetMaxPacketLength(length); + delegate_.SetCanWriteAnything(); + generator_.StartBatchOperations(); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); + QuicConsumedData consumed = + generator_.ConsumeData(kDataStreamId, + MakeIOVectorFromStringPiece( + QuicStringPiece(buf, kStreamFramePayloadSize)), + 0, FIN_AND_PADDING, nullptr); + generator_.FinishBatchOperations(); + EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed); + EXPECT_FALSE(generator_.HasQueuedFrames()); + + EXPECT_EQ(1u, packets_.size()); + PacketContents contents; + // The packet has both stream and padding frames. + contents.num_padding_frames = 1; + contents.num_stream_frames = 1; + CheckPacketContains(contents, 0); +} + +TEST_F(QuicPacketGeneratorTest, + RandomPaddingAfterFinSingleStreamMultiplePackets) { + const QuicByteCount kStreamFramePayloadSize = 100u; + char buf[kStreamFramePayloadSize] = {}; + const QuicStreamId kDataStreamId = 5; + // Set the packet size be enough for one stream frame with 0 stream offset + + // 1. One or more packets will accommodate. + size_t length = NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) + + GetPacketHeaderSize( + framer_.version(), creator_->connection_id_length(), + kIncludeVersion, !kIncludeDiversificationNonce, + QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) + + QuicFramer::GetMinStreamFrameSize( + kDataStreamId, 0, /*last_frame_in_packet=*/false) + + kStreamFramePayloadSize + 1; + generator_.SetMaxPacketLength(length); + delegate_.SetCanWriteAnything(); + generator_.StartBatchOperations(); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); + QuicConsumedData consumed = + generator_.ConsumeData(kDataStreamId, + MakeIOVectorFromStringPiece( + QuicStringPiece(buf, kStreamFramePayloadSize)), + 0, FIN_AND_PADDING, nullptr); + generator_.FinishBatchOperations(); + EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed); + EXPECT_FALSE(generator_.HasQueuedFrames()); + + EXPECT_LE(1u, packets_.size()); + PacketContents contents; + // The first packet has both stream and padding frames. + contents.num_stream_frames = 1; + contents.num_padding_frames = 1; + CheckPacketContains(contents, 0); + + for (size_t i = 1; i < packets_.size(); ++i) { + // Following packets only have paddings. + contents.num_stream_frames = 0; + contents.num_padding_frames = 1; + CheckPacketContains(contents, i); + } +} + +TEST_F(QuicPacketGeneratorTest, + RandomPaddingAfterFinMultipleStreamsMultiplePackets) { + const QuicByteCount kStreamFramePayloadSize = 100u; + char buf[kStreamFramePayloadSize] = {}; + const QuicStreamId kDataStreamId1 = 5; + const QuicStreamId kDataStreamId2 = 6; + // Set the packet size be enough for first frame with 0 stream offset + second + // frame + 1 byte payload. two or more packets will accommodate. + size_t length = NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) + + GetPacketHeaderSize( + framer_.version(), creator_->connection_id_length(), + kIncludeVersion, !kIncludeDiversificationNonce, + QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) + + QuicFramer::GetMinStreamFrameSize( + kDataStreamId1, 0, /*last_frame_in_packet=*/false) + + kStreamFramePayloadSize + + QuicFramer::GetMinStreamFrameSize( + kDataStreamId1, 0, /*last_frame_in_packet=*/false) + + 1; + generator_.SetMaxPacketLength(length); + delegate_.SetCanWriteAnything(); + generator_.StartBatchOperations(); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); + QuicConsumedData consumed = + generator_.ConsumeData(kDataStreamId1, + MakeIOVectorFromStringPiece( + QuicStringPiece(buf, kStreamFramePayloadSize)), + 0, FIN_AND_PADDING, nullptr); + EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed); + consumed = generator_.ConsumeData(kDataStreamId2, + MakeIOVectorFromStringPiece(QuicStringPiece( + buf, kStreamFramePayloadSize)), + 0, FIN_AND_PADDING, nullptr); + EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed); + generator_.FinishBatchOperations(); + EXPECT_FALSE(generator_.HasQueuedFrames()); + + EXPECT_LE(2u, packets_.size()); + PacketContents contents; + // The first packet has two stream frames. + contents.num_stream_frames = 2; + CheckPacketContains(contents, 0); + + // The second packet has one stream frame and padding frames. + contents.num_stream_frames = 1; + contents.num_padding_frames = 1; + CheckPacketContains(contents, 1); + + for (size_t i = 2; i < packets_.size(); ++i) { + // Following packets only have paddings. + contents.num_stream_frames = 0; + contents.num_padding_frames = 1; + CheckPacketContains(contents, i); + } +} + } // namespace test } // namespace net
diff --git a/net/quic/core/quic_packets.cc b/net/quic/core/quic_packets.cc index cdd63256..9075165 100644 --- a/net/quic/core/quic_packets.cc +++ b/net/quic/core/quic_packets.cc
@@ -4,9 +4,9 @@ #include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_utils.h" #include "net/quic/core/quic_versions.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_str_cat.h" #include "net/quic/platform/api/quic_text_utils.h"
diff --git a/net/quic/core/quic_sent_packet_manager.cc b/net/quic/core/quic_sent_packet_manager.cc index a308473..afb8eff 100644 --- a/net/quic/core/quic_sent_packet_manager.cc +++ b/net/quic/core/quic_sent_packet_manager.cc
@@ -13,9 +13,9 @@ #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/proto/cached_network_parameters.pb.h" #include "net/quic/core/quic_connection_stats.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_pending_retransmission.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_map_util.h"
diff --git a/net/quic/core/quic_sent_packet_manager_test.cc b/net/quic/core/quic_sent_packet_manager_test.cc index 9a544a2..f8b37581 100644 --- a/net/quic/core/quic_sent_packet_manager_test.cc +++ b/net/quic/core/quic_sent_packet_manager_test.cc
@@ -6,7 +6,8 @@ #include <memory> -#include "net/quic/core/quic_flags.h" +#include "net/quic/core/quic_pending_retransmission.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_string_piece.h" #include "net/quic/test_tools/quic_config_peer.h"
diff --git a/net/quic/core/quic_server_session_base.cc b/net/quic/core/quic_server_session_base.cc index 60e6794..6562ba9 100644 --- a/net/quic/core/quic_server_session_base.cc +++ b/net/quic/core/quic_server_session_base.cc
@@ -6,9 +6,9 @@ #include "net/quic/core/proto/cached_network_parameters.pb.h" #include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_stream.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_string_piece.h" @@ -227,7 +227,12 @@ return true; } -QuicCryptoServerStreamBase* QuicServerSessionBase::GetCryptoStream() { +QuicCryptoServerStreamBase* QuicServerSessionBase::GetMutableCryptoStream() { + return crypto_stream_.get(); +} + +const QuicCryptoServerStreamBase* QuicServerSessionBase::GetCryptoStream() + const { return crypto_stream_.get(); }
diff --git a/net/quic/core/quic_server_session_base.h b/net/quic/core/quic_server_session_base.h index 6b41e657..2fbe9762 100644 --- a/net/quic/core/quic_server_session_base.h +++ b/net/quic/core/quic_server_session_base.h
@@ -69,7 +69,9 @@ protected: // QuicSession methods(override them with return type of QuicSpdyStream*): - QuicCryptoServerStreamBase* GetCryptoStream() override; + QuicCryptoServerStreamBase* GetMutableCryptoStream() override; + + const QuicCryptoServerStreamBase* GetCryptoStream() const override; // If an outgoing stream can be created, return true. // Return false when connection is closed or forward secure encryption hasn't
diff --git a/net/quic/core/quic_server_session_base_test.cc b/net/quic/core/quic_server_session_base_test.cc index 8002891..e0fd26f 100644 --- a/net/quic/core/quic_server_session_base_test.cc +++ b/net/quic/core/quic_server_session_base_test.cc
@@ -14,6 +14,7 @@ #include "net/quic/core/quic_connection.h" #include "net/quic/core/quic_crypto_server_stream.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_socket_address.h" #include "net/quic/test_tools/crypto_test_utils.h" @@ -193,11 +194,7 @@ session_->config()->HasReceivedConnectionOptions() && ContainsQuicTag(session_->config()->ReceivedConnectionOptions(), kSPSH)); session_->OnConfigNegotiated(); - if (GetParam() <= QUIC_VERSION_34) { - EXPECT_FALSE(session_->server_push_enabled()); - } else { - EXPECT_TRUE(session_->server_push_enabled()); - } + EXPECT_TRUE(session_->server_push_enabled()); } TEST_P(QuicServerSessionBaseTest, CloseStreamDueToReset) { @@ -277,10 +274,6 @@ // streams. The server accepts slightly more than the negotiated stream limit // to deal with rare cases where a client FIN/RST is lost. - if (GetParam() <= QUIC_VERSION_34) { - EXPECT_EQ(kMaxStreamsForTest, session_->max_open_incoming_streams()); - } - // The slightly increased stream limit is set during config negotiation. It // is either an increase of 10 over negotiated limit, or a fixed percentage // scaling, whichever is larger. Test both before continuing. @@ -319,10 +312,6 @@ // streams available. The server accepts slightly more than the negotiated // stream limit to deal with rare cases where a client FIN/RST is lost. - if (GetParam() <= QUIC_VERSION_34) { - // The slightly increased stream limit is set during config negotiation. - EXPECT_EQ(kMaxStreamsForTest, session_->max_open_incoming_streams()); - } session_->OnConfigNegotiated(); const size_t kAvailableStreamLimit = session_->MaxAvailableStreams(); EXPECT_EQ( @@ -525,7 +514,7 @@ QuicTime::Delta::FromSeconds(kNumSecondsPerHour + 1)); QuicCryptoServerStream* crypto_stream = static_cast<QuicCryptoServerStream*>( - QuicSessionPeer::GetCryptoStream(session_.get())); + QuicSessionPeer::GetMutableCryptoStream(session_.get())); // No effect if no CachedNetworkParameters provided. EXPECT_CALL(*connection_, ResumeConnectionState(_, _)).Times(0);
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc index 453d3b7..9508fe39 100644 --- a/net/quic/core/quic_session.cc +++ b/net/quic/core/quic_session.cc
@@ -8,9 +8,9 @@ #include <utility> #include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_flow_controller.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_map_util.h" #include "net/quic/platform/api/quic_str_cat.h" @@ -50,8 +50,8 @@ connection_->set_visitor(this); connection_->SetFromConfig(config_); - DCHECK_EQ(kCryptoStreamId, GetCryptoStream()->id()); - static_stream_map_[kCryptoStreamId] = GetCryptoStream(); + DCHECK_EQ(kCryptoStreamId, GetMutableCryptoStream()->id()); + static_stream_map_[kCryptoStreamId] = GetMutableCryptoStream(); } QuicSession::~QuicSession() { @@ -288,14 +288,14 @@ QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { // This check is an attempt to deal with potential memory corruption // in which |id| ends up set to 1 (the crypto stream id). If this happen // it might end up resulting in unencrypted stream data being sent. // While this is impossible to avoid given sufficient corruption, this // seems like a reasonable mitigation. - if (id == kCryptoStreamId && stream != GetCryptoStream()) { + if (id == kCryptoStreamId && stream != GetMutableCryptoStream()) { QUIC_BUG << "Stream id mismatch"; connection_->CloseConnection( QUIC_INTERNAL_ERROR, @@ -308,7 +308,7 @@ // up write blocked until OnCanWrite is next called. return QuicConsumedData(0, false); } - QuicConsumedData data = connection_->SendStreamData(id, iov, offset, fin, + QuicConsumedData data = connection_->SendStreamData(id, iov, offset, state, std::move(ack_listener)); write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed); return data; @@ -425,28 +425,25 @@ } } -bool QuicSession::IsEncryptionEstablished() { +bool QuicSession::IsEncryptionEstablished() const { return GetCryptoStream()->encryption_established(); } -bool QuicSession::IsCryptoHandshakeConfirmed() { +bool QuicSession::IsCryptoHandshakeConfirmed() const { return GetCryptoStream()->handshake_confirmed(); } void QuicSession::OnConfigNegotiated() { connection_->SetFromConfig(config_); - const QuicVersion version = connection()->version(); uint32_t max_streams = 0; - if (version > QUIC_VERSION_34 && - config_.HasReceivedMaxIncomingDynamicStreams()) { + if (config_.HasReceivedMaxIncomingDynamicStreams()) { max_streams = config_.ReceivedMaxIncomingDynamicStreams(); } else { max_streams = config_.MaxStreamsPerConnection(); } set_max_open_outgoing_streams(max_streams); - if (FLAGS_quic_reloadable_flag_quic_large_ifw_options && - perspective() == Perspective::IS_SERVER) { + if (perspective() == Perspective::IS_SERVER) { if (config_.HasReceivedConnectionOptions()) { // The following variations change the initial receive flow control // window sizes. @@ -468,25 +465,18 @@ } } - if (version <= QUIC_VERSION_34) { - // A small number of additional incoming streams beyond the limit should be - // allowed. This helps avoid early connection termination when FIN/RSTs for - // old streams are lost or arrive out of order. - // Use a minimum number of additional streams, or a percentage increase, - // whichever is larger. - uint32_t max_incoming_streams = - std::max(max_streams + kMaxStreamsMinimumIncrement, - static_cast<uint32_t>(max_streams * kMaxStreamsMultiplier)); - set_max_open_incoming_streams(max_incoming_streams); - } else { - uint32_t max_incoming_streams_to_send = - config_.GetMaxIncomingDynamicStreamsToSend(); - uint32_t max_incoming_streams = - std::max(max_incoming_streams_to_send + kMaxStreamsMinimumIncrement, - static_cast<uint32_t>(max_incoming_streams_to_send * - kMaxStreamsMultiplier)); - set_max_open_incoming_streams(max_incoming_streams); - } + // A small number of additional incoming streams beyond the limit should be + // allowed. This helps avoid early connection termination when FIN/RSTs for + // old streams are lost or arrive out of order. + // Use a minimum number of additional streams, or a percentage increase, + // whichever is larger. + uint32_t max_incoming_streams_to_send = + config_.GetMaxIncomingDynamicStreamsToSend(); + uint32_t max_incoming_streams = + std::max(max_incoming_streams_to_send + kMaxStreamsMinimumIncrement, + static_cast<uint32_t>(max_incoming_streams_to_send * + kMaxStreamsMultiplier)); + set_max_open_incoming_streams(max_incoming_streams); if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) { // Streams which were created before the SHLO was received (0-RTT
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h index 5eaa169..5fa9dcd3 100644 --- a/net/quic/core/quic_session.h +++ b/net/quic/core/quic_session.h
@@ -122,7 +122,7 @@ QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); // Called by streams when they want to close the stream in both directions. @@ -138,11 +138,11 @@ // Returns true if outgoing packets will be encrypted, even if the server // hasn't confirmed the handshake yet. - virtual bool IsEncryptionEstablished(); + virtual bool IsEncryptionEstablished() const; // For a client, returns true if the server has confirmed our handshake. For // a server, returns true if a full, valid client hello has been received. - virtual bool IsCryptoHandshakeConfirmed(); + virtual bool IsCryptoHandshakeConfirmed() const; // Called by the QuicCryptoStream when a new QuicConfig has been negotiated. virtual void OnConfigNegotiated(); @@ -267,7 +267,10 @@ virtual QuicStream* CreateOutgoingDynamicStream(SpdyPriority priority) = 0; // Return the reserved crypto stream. - virtual QuicCryptoStream* GetCryptoStream() = 0; + virtual QuicCryptoStream* GetMutableCryptoStream() = 0; + + // Return the reserved crypto stream as a constant pointer. + virtual const QuicCryptoStream* GetCryptoStream() const = 0; // Adds |stream| to the dynamic stream map. virtual void ActivateStream(std::unique_ptr<QuicStream> stream);
diff --git a/net/quic/core/quic_session_test.cc b/net/quic/core/quic_session_test.cc index a5451e7..b157c1b 100644 --- a/net/quic/core/quic_session_test.cc +++ b/net/quic/core/quic_session_test.cc
@@ -13,10 +13,10 @@ #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/crypto/null_encrypter.h" #include "net/quic/core/quic_crypto_stream.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_stream.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_map_util.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_str_cat.h" @@ -125,7 +125,13 @@ ~TestSession() override { delete connection(); } - TestCryptoStream* GetCryptoStream() override { return &crypto_stream_; } + TestCryptoStream* GetMutableCryptoStream() override { + return &crypto_stream_; + } + + const TestCryptoStream* GetCryptoStream() const override { + return &crypto_stream_; + } TestStream* CreateOutgoingDynamicStream(SpdyPriority priority) override { TestStream* stream = new TestStream(GetNextOutgoingStreamId(), this); @@ -167,12 +173,13 @@ QuicStreamId id, QuicIOVector data, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) override { + bool fin = state != NO_FIN; QuicConsumedData consumed(data.total_length, fin); if (!writev_consumes_all_data_) { - consumed = QuicSession::WritevData(stream, id, data, offset, fin, + consumed = QuicSession::WritevData(stream, id, data, offset, state, std::move(ack_listener)); } stream->set_stream_bytes_written(stream->stream_bytes_written() + @@ -194,9 +201,8 @@ if (stream->id() != kCryptoStreamId) { this->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); } - QuicConsumedData consumed = - WritevData(stream, stream->id(), MakeIOVector("not empty", &iov), 0, - true, nullptr); + QuicConsumedData consumed = WritevData( + stream, stream->id(), MakeIOVector("not empty", &iov), 0, FIN, nullptr); return consumed; } @@ -206,7 +212,7 @@ iov.iov_base = nullptr; // should not be read. iov.iov_len = static_cast<size_t>(bytes); return WritevData(stream, stream->id(), QuicIOVector(&iov, 1, bytes), 0, - true, nullptr); + FIN, nullptr); } using QuicSession::PostProcessAfterData; @@ -304,7 +310,7 @@ TEST_P(QuicSessionTestServer, IsCryptoHandshakeConfirmed) { EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed()); CryptoHandshakeMessage message; - session_.GetCryptoStream()->OnHandshakeMessage(message); + session_.GetMutableCryptoStream()->OnHandshakeMessage(message); EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed()); } @@ -525,7 +531,7 @@ EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)) .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0))); } - session_.GetCryptoStream()->OnHandshakeMessage(msg); + session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); // Drive congestion control manually. MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>; @@ -680,7 +686,7 @@ // Due to prioritization, we *should* be asked to write the crypto stream // first. // Don't re-register the crypto stream (which signals complete writing). - TestCryptoStream* crypto_stream = session_.GetCryptoStream(); + TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream(); EXPECT_CALL(*crypto_stream, OnCanWrite()); EXPECT_CALL(*stream2, OnCanWrite()) @@ -754,7 +760,7 @@ // The crypto and headers streams should be called even though we are // connection flow control blocked. - TestCryptoStream* crypto_stream = session_.GetCryptoStream(); + TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream(); EXPECT_CALL(*crypto_stream, OnCanWrite()); TestHeadersStream* headers_stream = new TestHeadersStream(&session_); QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream); @@ -789,7 +795,7 @@ EXPECT_EQ(kInitialIdleTimeoutSecs + 3, QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); CryptoHandshakeMessage msg; - session_.GetCryptoStream()->OnHandshakeMessage(msg); + session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); EXPECT_EQ(kMaximumIdleTimeoutSecs + 3, QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); } @@ -836,7 +842,7 @@ // Now complete the crypto handshake, resulting in an increased flow control // send window. CryptoHandshakeMessage msg; - session_.GetCryptoStream()->OnHandshakeMessage(msg); + session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); // Stream is now unblocked. EXPECT_FALSE(stream2->flow_controller()->IsBlocked()); @@ -848,7 +854,7 @@ // Test that if the crypto stream is flow control blocked, then if the SHLO // contains a larger send window offset, the stream becomes unblocked. session_.set_writev_consumes_all_data(true); - TestCryptoStream* crypto_stream = session_.GetCryptoStream(); + TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream(); EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); @@ -881,7 +887,7 @@ // Now complete the crypto handshake, resulting in an increased flow control // send window. CryptoHandshakeMessage msg; - session_.GetCryptoStream()->OnHandshakeMessage(msg); + session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); // Stream is now unblocked and will no longer have buffered data. EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); @@ -900,7 +906,7 @@ // Test that if the header stream is flow control blocked, then if the SHLO // contains a larger send window offset, the stream becomes unblocked. session_.set_writev_consumes_all_data(true); - TestCryptoStream* crypto_stream = session_.GetCryptoStream(); + TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream(); EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked()); EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); @@ -935,7 +941,7 @@ // Now complete the crypto handshake, resulting in an increased flow control // send window. CryptoHandshakeMessage msg; - session_.GetCryptoStream()->OnHandshakeMessage(msg); + session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); // Stream is now unblocked and will no longer have buffered data. EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked()); @@ -1094,7 +1100,6 @@ // Test negotiation of custom server initial flow control window. TEST_P(QuicSessionTestServer, CustomFlowControlWindow) { - FLAGS_quic_reloadable_flag_quic_large_ifw_options = true; QuicTagVector copt; copt.push_back(kIFW7); QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
diff --git a/net/quic/core/quic_spdy_session.cc b/net/quic/core/quic_spdy_session.cc index 61d16c90..77cd2cb 100644 --- a/net/quic/core/quic_spdy_session.cc +++ b/net/quic/core/quic_spdy_session.cc
@@ -9,9 +9,9 @@ #include <string> #include <utility> -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_headers_stream.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_str_cat.h" @@ -609,10 +609,8 @@ kStreamReceiveWindowLimit); } - if (version > QUIC_VERSION_34) { - server_push_enabled_ = - FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default; - } + server_push_enabled_ = + FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default; } void QuicSpdySession::OnStreamFrameData(QuicStreamId stream_id,
diff --git a/net/quic/core/quic_spdy_stream.h b/net/quic/core/quic_spdy_stream.h index 247af4d..8465339 100644 --- a/net/quic/core/quic_spdy_stream.h +++ b/net/quic/core/quic_spdy_stream.h
@@ -17,12 +17,12 @@ #include "base/macros.h" #include "net/base/iovec.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_header_list.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_stream.h" #include "net/quic/core/quic_stream_sequencer.h" #include "net/quic/platform/api/quic_export.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_socket_address.h" #include "net/spdy/spdy_framer.h"
diff --git a/net/quic/core/quic_stream.cc b/net/quic/core/quic_stream.cc index d402b4e..733a805 100644 --- a/net/quic/core/quic_stream.cc +++ b/net/quic/core/quic_stream.cc
@@ -73,7 +73,8 @@ session_->flow_controller()), connection_flow_controller_(session_->flow_controller()), stream_contributes_to_connection_flow_control_(true), - busy_counter_(0) { + busy_counter_(0), + add_random_padding_after_fin_(false) { SetFromConfig(); } @@ -356,7 +357,11 @@ QuicStreamOffset offset, bool fin, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { - return session()->WritevData(this, id(), iov, offset, fin, + StreamSendingState state = fin ? FIN : NO_FIN; + if (fin && add_random_padding_after_fin_) { + state = FIN_AND_PADDING; + } + return session()->WritevData(this, id(), iov, offset, state, std::move(ack_listener)); } @@ -483,4 +488,8 @@ } } +void QuicStream::AddRandomPaddingAfterFin() { + add_random_padding_after_fin_ = true; +} + } // namespace net
diff --git a/net/quic/core/quic_stream.h b/net/quic/core/quic_stream.h index 5133fa9..df1ebf02 100644 --- a/net/quic/core/quic_stream.h +++ b/net/quic/core/quic_stream.h
@@ -186,6 +186,9 @@ bool fin, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); + // Adds random padding after the fin is consumed for this stream. + void AddRandomPaddingAfterFin(); + protected: // Sends as many bytes in the first |count| buffers of |iov| to the connection // as the connection will consume. @@ -317,6 +320,10 @@ // For debugging only. size_t busy_counter_; + // Indicates whether paddings will be added after the fin is consumed for this + // stream. + bool add_random_padding_after_fin_; + DISALLOW_COPY_AND_ASSIGN(QuicStream); };
diff --git a/net/quic/core/quic_stream_sequencer_buffer.cc b/net/quic/core/quic_stream_sequencer_buffer.cc index 09fd43d3..3706d388 100644 --- a/net/quic/core/quic_stream_sequencer_buffer.cc +++ b/net/quic/core/quic_stream_sequencer_buffer.cc
@@ -5,8 +5,9 @@ #include "net/quic/core/quic_stream_sequencer_buffer.h" #include "base/format_macros.h" -#include "net/quic/core/quic_flags.h" +#include "net/quic/core/quic_constants.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_str_cat.h"
diff --git a/net/quic/core/quic_stream_test.cc b/net/quic/core/quic_stream_test.cc index 4c7ade920..69e28f4 100644 --- a/net/quic/core/quic_stream_test.cc +++ b/net/quic/core/quic_stream_test.cc
@@ -7,10 +7,10 @@ #include <memory> #include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_utils.h" #include "net/quic/core/quic_write_blocked_list.h" #include "net/quic/core/spdy_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/test_tools/quic_config_peer.h" @@ -142,7 +142,7 @@ QuicStreamId id, QuicIOVector /*iov*/, QuicStreamOffset /*offset*/, - bool /*fin*/, + StreamSendingState /*state*/, const QuicReferenceCountedPointer< QuicAckListenerInterface>& /*ack_listener*/) { session_->CloseStream(id);
diff --git a/net/quic/core/quic_types.h b/net/quic/core/quic_types.h index 758081a6..ed978cf4 100644 --- a/net/quic/core/quic_types.h +++ b/net/quic/core/quic_types.h
@@ -261,6 +261,16 @@ IPV6_TO_IPV6_CHANGE, }; +enum StreamSendingState { + // Sender has more data to send on this stream. + NO_FIN, + // Sender is done sending on this stream. + FIN, + // Sender is done sending on this stream and random padding needs to be + // appended after all stream frames. + FIN_AND_PADDING, +}; + } // namespace net #endif // NET_QUIC_CORE_QUIC_TYPES_H_
diff --git a/net/quic/core/quic_utils.cc b/net/quic/core/quic_utils.cc index b7f3183..87f914f 100644 --- a/net/quic/core/quic_utils.cc +++ b/net/quic/core/quic_utils.cc
@@ -11,7 +11,7 @@ #include "base/containers/adapters.h" #include "base/logging.h" #include "net/quic/core/quic_constants.h" -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" using std::string;
diff --git a/net/quic/core/quic_version_manager.cc b/net/quic/core/quic_version_manager.cc index 7b11073..fb8bdf0 100644 --- a/net/quic/core/quic_version_manager.cc +++ b/net/quic/core/quic_version_manager.cc
@@ -4,17 +4,14 @@ #include "net/quic/core/quic_version_manager.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_versions.h" +#include "net/quic/platform/api/quic_flags.h" namespace net { QuicVersionManager::QuicVersionManager(QuicVersionVector supported_versions) - : enable_version_39_(base::GetFlag(FLAGS_quic_enable_version_39)), + : enable_version_39_(GetQuicFlag(FLAGS_quic_enable_version_39)), enable_version_38_(FLAGS_quic_reloadable_flag_quic_enable_version_38), - enable_version_37_(FLAGS_quic_reloadable_flag_quic_enable_version_37), - enable_version_36_(FLAGS_quic_reloadable_flag_quic_enable_version_36_v3), - disable_version_34_(FLAGS_quic_reloadable_flag_quic_disable_version_34), allowed_supported_versions_(supported_versions), filtered_supported_versions_( FilterSupportedVersions(supported_versions)) {} @@ -27,18 +24,10 @@ } void QuicVersionManager::MaybeRefilterSupportedVersions() { - if (enable_version_39_ != base::GetFlag(FLAGS_quic_enable_version_39) || - enable_version_38_ != FLAGS_quic_reloadable_flag_quic_enable_version_38 || - enable_version_37_ != FLAGS_quic_reloadable_flag_quic_enable_version_37 || - enable_version_36_ != - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 || - disable_version_34_ != - FLAGS_quic_reloadable_flag_quic_disable_version_34) { - enable_version_39_ = base::GetFlag(FLAGS_quic_enable_version_39); + if (enable_version_39_ != GetQuicFlag(FLAGS_quic_enable_version_39) || + enable_version_38_ != FLAGS_quic_reloadable_flag_quic_enable_version_38) { + enable_version_39_ = GetQuicFlag(FLAGS_quic_enable_version_39); enable_version_38_ = FLAGS_quic_reloadable_flag_quic_enable_version_38; - enable_version_37_ = FLAGS_quic_reloadable_flag_quic_enable_version_37; - enable_version_36_ = FLAGS_quic_reloadable_flag_quic_enable_version_36_v3; - disable_version_34_ = FLAGS_quic_reloadable_flag_quic_disable_version_34; RefilterSupportedVersions(); } }
diff --git a/net/quic/core/quic_version_manager.h b/net/quic/core/quic_version_manager.h index d6664b8..d658d8da 100644 --- a/net/quic/core/quic_version_manager.h +++ b/net/quic/core/quic_version_manager.h
@@ -35,12 +35,6 @@ bool enable_version_39_; // FLAGS_quic_reloadable_flag_quic_enable_version_38 bool enable_version_38_; - // FLAGS_quic_reloadable_flag_quic_enable_version_37 - bool enable_version_37_; - // FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 - bool enable_version_36_; - // FLAGS_quic_reloadable_flag_quic_disable_version_34 - bool disable_version_34_; // The list of versions that may be supported. QuicVersionVector allowed_supported_versions_; // This vector contains QUIC versions which are currently supported based on
diff --git a/net/quic/core/quic_version_manager_test.cc b/net/quic/core/quic_version_manager_test.cc index bd259cb..05691b55 100644 --- a/net/quic/core/quic_version_manager_test.cc +++ b/net/quic/core/quic_version_manager_test.cc
@@ -4,8 +4,8 @@ #include "net/quic/core/quic_version_manager.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_versions.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/test_tools/quic_test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -16,53 +16,30 @@ TEST(QuicVersionManagerTest, QuicVersionManager) { QuicFlagSaver flags; - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = false; FLAGS_quic_reloadable_flag_quic_enable_version_38 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_37 = false; - FLAGS_quic_reloadable_flag_quic_disable_version_34 = false; QuicVersionManager manager(AllSupportedVersions()); EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), manager.GetSupportedVersions()); - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true; - EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), - manager.GetSupportedVersions()); - ASSERT_EQ(3u, manager.GetSupportedVersions().size()); - EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[0]); - EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[1]); - EXPECT_EQ(QUIC_VERSION_34, manager.GetSupportedVersions()[2]); - - FLAGS_quic_reloadable_flag_quic_enable_version_37 = true; - EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), - manager.GetSupportedVersions()); - ASSERT_EQ(4u, manager.GetSupportedVersions().size()); - EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[0]); - EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[1]); - EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[2]); - EXPECT_EQ(QUIC_VERSION_34, manager.GetSupportedVersions()[3]); - FLAGS_quic_reloadable_flag_quic_enable_version_38 = true; EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), manager.GetSupportedVersions()); - ASSERT_EQ(5u, manager.GetSupportedVersions().size()); + ASSERT_EQ(4u, manager.GetSupportedVersions().size()); EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[0]); EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[1]); EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[2]); EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[3]); - EXPECT_EQ(QUIC_VERSION_34, manager.GetSupportedVersions()[4]); - base::SetFlag(&FLAGS_quic_enable_version_39, true); + SetQuicFlag(&FLAGS_quic_enable_version_39, true); EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), manager.GetSupportedVersions()); - ASSERT_EQ(6u, manager.GetSupportedVersions().size()); + ASSERT_EQ(5u, manager.GetSupportedVersions().size()); EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[0]); EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[1]); EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[2]); EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[3]); EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[4]); - EXPECT_EQ(QUIC_VERSION_34, manager.GetSupportedVersions()[5]); - FLAGS_quic_reloadable_flag_quic_disable_version_34 = true; EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), manager.GetSupportedVersions()); ASSERT_EQ(5u, manager.GetSupportedVersions().size());
diff --git a/net/quic/core/quic_versions.cc b/net/quic/core/quic_versions.cc index 6873776..b94997d 100644 --- a/net/quic/core/quic_versions.cc +++ b/net/quic/core/quic_versions.cc
@@ -5,9 +5,9 @@ #include "net/quic/core/quic_versions.h" #include "net/quic/core/quic_error_codes.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_tag.h" #include "net/quic/core/quic_types.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" using std::string; @@ -31,29 +31,12 @@ filtered_versions.clear(); // Guaranteed by spec not to change capacity. for (QuicVersion version : versions) { if (version == QUIC_VERSION_39) { - if (base::GetFlag(FLAGS_quic_enable_version_39) && - FLAGS_quic_reloadable_flag_quic_enable_version_38 && - FLAGS_quic_reloadable_flag_quic_enable_version_37 && - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3) { + if (GetQuicFlag(FLAGS_quic_enable_version_39) && + FLAGS_quic_reloadable_flag_quic_enable_version_38) { filtered_versions.push_back(version); } } else if (version == QUIC_VERSION_38) { - if (FLAGS_quic_reloadable_flag_quic_enable_version_38 && - FLAGS_quic_reloadable_flag_quic_enable_version_37 && - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3) { - filtered_versions.push_back(version); - } - } else if (version == QUIC_VERSION_37) { - if (FLAGS_quic_reloadable_flag_quic_enable_version_37 && - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3) { - filtered_versions.push_back(version); - } - } else if (version == QUIC_VERSION_36) { - if (FLAGS_quic_reloadable_flag_quic_enable_version_36_v3) { - filtered_versions.push_back(version); - } - } else if (version == QUIC_VERSION_34) { - if (!FLAGS_quic_reloadable_flag_quic_disable_version_34) { + if (FLAGS_quic_reloadable_flag_quic_enable_version_38) { filtered_versions.push_back(version); } } else { @@ -76,8 +59,6 @@ QuicTag QuicVersionToQuicTag(const QuicVersion version) { switch (version) { - case QUIC_VERSION_34: - return MakeQuicTag('Q', '0', '3', '4'); case QUIC_VERSION_35: return MakeQuicTag('Q', '0', '3', '5'); case QUIC_VERSION_36: @@ -114,7 +95,6 @@ string QuicVersionToString(const QuicVersion version) { switch (version) { - RETURN_STRING_LITERAL(QUIC_VERSION_34); RETURN_STRING_LITERAL(QUIC_VERSION_35); RETURN_STRING_LITERAL(QUIC_VERSION_36); RETURN_STRING_LITERAL(QUIC_VERSION_37);
diff --git a/net/quic/core/quic_versions.h b/net/quic/core/quic_versions.h index 9d3e457c..d228b41 100644 --- a/net/quic/core/quic_versions.h +++ b/net/quic/core/quic_versions.h
@@ -24,8 +24,6 @@ // Special case to indicate unknown/unsupported QUIC version. QUIC_VERSION_UNSUPPORTED = 0, - QUIC_VERSION_34 = 34, // Deprecates entropy, removes private flag from packet - // header, uses new ack and stop waiting wire format. QUIC_VERSION_35 = 35, // Allows endpoints to independently set stream limit. QUIC_VERSION_36 = 36, // Add support to force HOL blocking. QUIC_VERSION_37 = 37, // Add perspective into null encryption. @@ -46,8 +44,8 @@ // IMPORTANT: if you are adding to this list, follow the instructions at // http://sites/quic/adding-and-removing-versions static const QuicVersion kSupportedQuicVersions[] = { - QUIC_VERSION_39, QUIC_VERSION_38, QUIC_VERSION_37, - QUIC_VERSION_36, QUIC_VERSION_35, QUIC_VERSION_34}; + QUIC_VERSION_39, QUIC_VERSION_38, QUIC_VERSION_37, QUIC_VERSION_36, + QUIC_VERSION_35}; typedef std::vector<QuicVersion> QuicVersionVector;
diff --git a/net/quic/core/quic_versions_test.cc b/net/quic/core/quic_versions_test.cc index cb2df31..0b392a9e 100644 --- a/net/quic/core/quic_versions_test.cc +++ b/net/quic/core/quic_versions_test.cc
@@ -4,8 +4,9 @@ #include "net/quic/core/quic_versions.h" -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/test_tools/quic_test_utils.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -25,8 +26,8 @@ #endif // Explicitly test a specific version. - EXPECT_EQ(MakeQuicTag('Q', '0', '3', '4'), - QuicVersionToQuicTag(QUIC_VERSION_34)); + EXPECT_EQ(MakeQuicTag('Q', '0', '3', '5'), + QuicVersionToQuicTag(QUIC_VERSION_35)); // Loop over all supported versions and make sure that we never hit the // default case (i.e. all supported versions should be successfully converted @@ -65,8 +66,8 @@ #endif // Explicitly test specific versions. - EXPECT_EQ(QUIC_VERSION_34, - QuicTagToQuicVersion(MakeQuicTag('Q', '0', '3', '4'))); + EXPECT_EQ(QUIC_VERSION_35, + QuicTagToQuicVersion(MakeQuicTag('Q', '0', '3', '5'))); for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) { QuicVersion version = kSupportedQuicVersions[i]; @@ -99,23 +100,23 @@ } TEST(QuicVersionsTest, QuicVersionToString) { - EXPECT_EQ("QUIC_VERSION_34", QuicVersionToString(QUIC_VERSION_34)); + EXPECT_EQ("QUIC_VERSION_35", QuicVersionToString(QUIC_VERSION_35)); EXPECT_EQ("QUIC_VERSION_UNSUPPORTED", QuicVersionToString(QUIC_VERSION_UNSUPPORTED)); - QuicVersion single_version[] = {QUIC_VERSION_34}; + QuicVersion single_version[] = {QUIC_VERSION_35}; QuicVersionVector versions_vector; for (size_t i = 0; i < arraysize(single_version); ++i) { versions_vector.push_back(single_version[i]); } - EXPECT_EQ("QUIC_VERSION_34", QuicVersionVectorToString(versions_vector)); + EXPECT_EQ("QUIC_VERSION_35", QuicVersionVectorToString(versions_vector)); - QuicVersion multiple_versions[] = {QUIC_VERSION_UNSUPPORTED, QUIC_VERSION_34}; + QuicVersion multiple_versions[] = {QUIC_VERSION_UNSUPPORTED, QUIC_VERSION_35}; versions_vector.clear(); for (size_t i = 0; i < arraysize(multiple_versions); ++i) { versions_vector.push_back(multiple_versions[i]); } - EXPECT_EQ("QUIC_VERSION_UNSUPPORTED,QUIC_VERSION_34", + EXPECT_EQ("QUIC_VERSION_UNSUPPORTED,QUIC_VERSION_35", QuicVersionVectorToString(versions_vector)); // Make sure that all supported versions are present in QuicVersionToString. @@ -125,67 +126,54 @@ } } -TEST(QuicVersionsTest, FilterSupportedVersionsNo34) { +TEST(QuicVersionsTest, FilterSupportedVersionsNo38) { QuicFlagSaver flags; - QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35, - QUIC_VERSION_36, QUIC_VERSION_37}; + QuicVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_36, + QUIC_VERSION_37, QUIC_VERSION_38, + QUIC_VERSION_39}; - FLAGS_quic_reloadable_flag_quic_disable_version_34 = true; - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_37 = false; - - QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions); - ASSERT_EQ(1u, filtered_versions.size()); - EXPECT_EQ(QUIC_VERSION_35, filtered_versions[0]); -} - -TEST(QuicVersionsTest, FilterSupportedVersionsNo36) { - QuicFlagSaver flags; - QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35, - QUIC_VERSION_36, QUIC_VERSION_37}; - - FLAGS_quic_reloadable_flag_quic_disable_version_34 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_37 = false; - - QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions); - ASSERT_EQ(2u, filtered_versions.size()); - EXPECT_EQ(QUIC_VERSION_34, filtered_versions[0]); - EXPECT_EQ(QUIC_VERSION_35, filtered_versions[1]); -} - -TEST(QuicVersionsTest, FilterSupportedVersionsNo37) { - QuicFlagSaver flags; - QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35, - QUIC_VERSION_36, QUIC_VERSION_37}; - - FLAGS_quic_reloadable_flag_quic_disable_version_34 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true; - FLAGS_quic_reloadable_flag_quic_enable_version_37 = false; + FLAGS_quic_reloadable_flag_quic_enable_version_38 = false; QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions); ASSERT_EQ(3u, filtered_versions.size()); - EXPECT_EQ(QUIC_VERSION_34, filtered_versions[0]); - EXPECT_EQ(QUIC_VERSION_35, filtered_versions[1]); - EXPECT_EQ(QUIC_VERSION_36, filtered_versions[2]); + EXPECT_EQ(QUIC_VERSION_35, filtered_versions[0]); + EXPECT_EQ(QUIC_VERSION_36, filtered_versions[1]); + EXPECT_EQ(QUIC_VERSION_37, filtered_versions[2]); +} + +TEST(QuicVersionsTest, FilterSupportedVersionsNo39) { + QuicVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_36, + QUIC_VERSION_37, QUIC_VERSION_38, + QUIC_VERSION_39}; + + FLAGS_quic_reloadable_flag_quic_enable_version_38 = true; + SetQuicFlag(&FLAGS_quic_enable_version_39, false); + + QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions); + ASSERT_EQ(4u, filtered_versions.size()); + EXPECT_EQ(QUIC_VERSION_35, filtered_versions[0]); + EXPECT_EQ(QUIC_VERSION_36, filtered_versions[1]); + EXPECT_EQ(QUIC_VERSION_37, filtered_versions[2]); + EXPECT_EQ(QUIC_VERSION_38, filtered_versions[3]); } TEST(QuicVersionsTest, FilterSupportedVersionsAllVersions) { QuicFlagSaver flags; - QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35, - QUIC_VERSION_36, QUIC_VERSION_37}; + QuicVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_36, + QUIC_VERSION_37, QUIC_VERSION_38, + QUIC_VERSION_39}; - FLAGS_quic_reloadable_flag_quic_disable_version_34 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true; - FLAGS_quic_reloadable_flag_quic_enable_version_37 = true; + FLAGS_quic_reloadable_flag_quic_enable_version_38 = true; + SetQuicFlag(&FLAGS_quic_enable_version_39, true); QuicVersionVector filtered_versions = FilterSupportedVersions(all_versions); ASSERT_EQ(all_versions, filtered_versions); } TEST(QuicVersionsTest, LookUpVersionByIndex) { - QuicVersionVector all_versions = {QUIC_VERSION_34, QUIC_VERSION_35, - QUIC_VERSION_36, QUIC_VERSION_37}; + QuicVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_36, + QUIC_VERSION_37, QUIC_VERSION_38, + QUIC_VERSION_39}; int version_count = all_versions.size(); for (int i = -5; i <= version_count + 1; ++i) { if (i >= 0 && i < version_count) {
diff --git a/net/quic/platform/api/quic_flags.h b/net/quic/platform/api/quic_flags.h new file mode 100644 index 0000000..1739e37c --- /dev/null +++ b/net/quic/platform/api/quic_flags.h
@@ -0,0 +1,13 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_QUIC_PLATFORM_API_QUIC_FLAGS_H_ +#define NET_QUIC_PLATFORM_API_QUIC_FLAGS_H_ + +#include "net/quic/platform/impl/quic_flags_impl.h" + +#define GetQuicFlag(flag) GetQuicFlagImpl(flag) +#define SetQuicFlag(flag, value) SetQuicFlagImpl(flag, value) + +#endif // NET_QUIC_PLATFORM_API_QUIC_FLAGS_H_
diff --git a/net/quic/core/quic_flags.cc b/net/quic/platform/impl/quic_flags_impl.cc similarity index 83% rename from net/quic/core/quic_flags.cc rename to net/quic/platform/impl/quic_flags_impl.cc index f53537d..cd6ef46 100644 --- a/net/quic/core/quic_flags.cc +++ b/net/quic/platform/impl/quic_flags_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/impl/quic_flags_impl.h" #define QUIC_FLAG(type, flag, value) type flag = value; #include "net/quic/core/quic_flags_list.h"
diff --git a/net/quic/platform/impl/quic_flags_impl.h b/net/quic/platform/impl/quic_flags_impl.h new file mode 100644 index 0000000..ebec713 --- /dev/null +++ b/net/quic/platform/impl/quic_flags_impl.h
@@ -0,0 +1,60 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_FLAGS_IMPL_H_ +#define NET_QUIC_PLATFORM_IMPL_QUIC_FLAGS_IMPL_H_ + +#include <cstdint> +#include <string> + +#include "net/quic/platform/api/quic_export.h" + +#define QUIC_FLAG(type, flag, value) QUIC_EXPORT_PRIVATE extern type flag; +#include "net/quic/core/quic_flags_list.h" +#undef QUIC_FLAG + +// API compatibility with new-style flags. +namespace net { + +inline bool GetQuicFlagImpl(bool flag) { + return flag; +} +inline int32_t GetQuicFlagImpl(int32_t flag) { + return flag; +} +inline int64_t GetQuicFlagImpl(int64_t flag) { + return flag; +} +inline uint64_t GetQuicFlagImpl(uint64_t flag) { + return flag; +} +inline double GetQuicFlagImpl(double flag) { + return flag; +} +inline std::string GetQuicFlagImpl(const std::string& flag) { + return flag; +} + +inline void SetQuicFlagImpl(bool* f, bool v) { + *f = v; +} +inline void SetQuicFlagImpl(int32_t* f, int32_t v) { + *f = v; +} +inline void SetQuicFlagImpl(int64_t* f, int64_t v) { + *f = v; +} +inline void SetQuicFlagImpl(uint64_t* f, uint64_t v) { + *f = v; +} +inline void SetQuicFlagImpl(double* f, double v) { + *f = v; +} +inline void SetQuicFlagImpl(std::string* f, const std::string& v) { + *f = v; +} + +} // namespace net + +#endif // NET_QUIC_PLATFORM_IMPL_QUIC_FLAGS_IMPL_H_
diff --git a/net/quic/quartc/quartc_session.cc b/net/quic/quartc/quartc_session.cc index 826e4d6..d3f3f5e 100644 --- a/net/quic/quartc/quartc_session.cc +++ b/net/quic/quartc/quartc_session.cc
@@ -132,7 +132,11 @@ QuartcSession::~QuartcSession() {} -QuicCryptoStream* QuartcSession::GetCryptoStream() { +const QuicCryptoStream* QuartcSession::GetCryptoStream() const { + return crypto_stream_.get(); +} + +QuicCryptoStream* QuartcSession::GetMutableCryptoStream() { return crypto_stream_.get(); }
diff --git a/net/quic/quartc/quartc_session.h b/net/quic/quartc/quartc_session.h index 2b3fa4bd..7996a1f 100644 --- a/net/quic/quartc/quartc_session.h +++ b/net/quic/quartc/quartc_session.h
@@ -40,7 +40,8 @@ ~QuartcSession() override; // QuicSession overrides. - QuicCryptoStream* GetCryptoStream() override; + const QuicCryptoStream* GetCryptoStream() const override; + QuicCryptoStream* GetMutableCryptoStream() override; QuartcStream* CreateOutgoingDynamicStream(SpdyPriority priority) override;
diff --git a/net/quic/quartc/quartc_stream_test.cc b/net/quic/quartc/quartc_stream_test.cc index c074be8a..0f6f041 100644 --- a/net/quic/quartc/quartc_stream_test.cc +++ b/net/quic/quartc/quartc_stream_test.cc
@@ -37,7 +37,7 @@ QuicStreamId id, QuicIOVector iovector, QuicStreamOffset offset, - bool fin, + StreamSendingState fin, QuicReferenceCountedPointer< QuicAckListenerInterface> /*ack_notifier_delegate*/) override { if (!writable_) { @@ -47,7 +47,7 @@ const char* data = reinterpret_cast<const char*>(iovector.iov->iov_base); size_t len = iovector.total_length; write_buffer_->append(data, len); - return QuicConsumedData(len, fin); + return QuicConsumedData(len, fin != NO_FIN); } QuartcStream* CreateIncomingDynamicStream(QuicStreamId id) override { @@ -58,7 +58,8 @@ return nullptr; } - QuicCryptoStream* GetCryptoStream() override { return nullptr; } + const QuicCryptoStream* GetCryptoStream() const override { return nullptr; } + QuicCryptoStream* GetMutableCryptoStream() override { return nullptr; } // Called by QuicStream when they want to close stream. void SendRstStream(QuicStreamId id,
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc index 8d28de7..08b2949 100644 --- a/net/quic/test_tools/crypto_test_utils.cc +++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -403,8 +403,8 @@ CHECK_NE(0u, client_conn->encrypted_packets_.size()); CommunicateHandshakeMessages(client_conn, client, server_conn, - server_session.GetCryptoStream()); - CompareClientAndServerKeys(client, server_session.GetCryptoStream()); + server_session.GetMutableCryptoStream()); + CompareClientAndServerKeys(client, server_session.GetMutableCryptoStream()); return client->num_sent_client_hellos(); } @@ -438,15 +438,15 @@ EXPECT_CALL(client_session, OnProofValid(testing::_)) .Times(testing::AnyNumber()); - client_session.GetCryptoStream()->CryptoConnect(); + client_session.GetMutableCryptoStream()->CryptoConnect(); CHECK_EQ(1u, client_conn->encrypted_packets_.size()); CommunicateHandshakeMessagesAndRunCallbacks( - client_conn, client_session.GetCryptoStream(), server_conn, server, + client_conn, client_session.GetMutableCryptoStream(), server_conn, server, async_channel_id_source); if (server->handshake_confirmed() && server->encryption_established()) { - CompareClientAndServerKeys(client_session.GetCryptoStream(), server); + CompareClientAndServerKeys(client_session.GetMutableCryptoStream(), server); if (options.channel_id_enabled) { std::unique_ptr<ChannelIDKey> channel_id_key;
diff --git a/net/quic/test_tools/quic_connection_peer.cc b/net/quic/test_tools/quic_connection_peer.cc index d96b9914..11da9495 100644 --- a/net/quic/test_tools/quic_connection_peer.cc +++ b/net/quic/test_tools/quic_connection_peer.cc
@@ -5,9 +5,9 @@ #include "net/quic/test_tools/quic_connection_peer.h" #include "net/quic/core/congestion_control/send_algorithm_interface.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packet_writer.h" #include "net/quic/core/quic_received_packet_manager.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/test_tools/quic_framer_peer.h" #include "net/quic/test_tools/quic_packet_generator_peer.h" #include "net/quic/test_tools/quic_sent_packet_manager_peer.h"
diff --git a/net/quic/test_tools/quic_session_peer.cc b/net/quic/test_tools/quic_session_peer.cc index 1e35b96..b744aa3 100644 --- a/net/quic/test_tools/quic_session_peer.cc +++ b/net/quic/test_tools/quic_session_peer.cc
@@ -35,8 +35,9 @@ } // static -QuicCryptoStream* QuicSessionPeer::GetCryptoStream(QuicSession* session) { - return session->GetCryptoStream(); +QuicCryptoStream* QuicSessionPeer::GetMutableCryptoStream( + QuicSession* session) { + return session->GetMutableCryptoStream(); } // static
diff --git a/net/quic/test_tools/quic_session_peer.h b/net/quic/test_tools/quic_session_peer.h index a5915e8..f89238b1 100644 --- a/net/quic/test_tools/quic_session_peer.h +++ b/net/quic/test_tools/quic_session_peer.h
@@ -30,7 +30,7 @@ uint32_t max_streams); static void SetMaxOpenOutgoingStreams(QuicSession* session, uint32_t max_streams); - static QuicCryptoStream* GetCryptoStream(QuicSession* session); + static QuicCryptoStream* GetMutableCryptoStream(QuicSession* session); static QuicWriteBlockedList* GetWriteBlockedStreams(QuicSession* session); static QuicStream* GetOrCreateDynamicStream(QuicSession* session, QuicStreamId stream_id);
diff --git a/net/quic/test_tools/quic_stream_sequencer_buffer_peer.cc b/net/quic/test_tools/quic_stream_sequencer_buffer_peer.cc index a759104..e521c5e4 100644 --- a/net/quic/test_tools/quic_stream_sequencer_buffer_peer.cc +++ b/net/quic/test_tools/quic_stream_sequencer_buffer_peer.cc
@@ -4,7 +4,7 @@ #include "net/quic/test_tools/quic_stream_sequencer_buffer_peer.h" -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/test/gtest_util.h"
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc index d9e3da8..63eb3c9 100644 --- a/net/quic/test_tools/quic_test_utils.cc +++ b/net/quic/test_tools/quic_test_utils.cc
@@ -14,11 +14,11 @@ #include "net/quic/core/crypto/quic_decrypter.h" #include "net/quic/core/crypto/quic_encrypter.h" #include "net/quic/core/quic_data_writer.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_framer.h" #include "net/quic/core/quic_packet_creator.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_endian.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/test_tools/crypto_test_utils.h" @@ -84,7 +84,7 @@ QuicFlagSaver::QuicFlagSaver() { #define QUIC_FLAG(type, flag, value) \ - CHECK_EQ(value, base::GetFlag(flag)) \ + CHECK_EQ(value, GetQuicFlag(flag)) \ << "Flag set to an unexpected value. A prior test is likely " \ << "setting a flag without using a QuicFlagSaver"; #include "net/quic/core/quic_flags_list.h" @@ -92,7 +92,7 @@ } QuicFlagSaver::~QuicFlagSaver() { -#define QUIC_FLAG(type, flag, value) base::SetFlag(&flag, value); +#define QUIC_FLAG(type, flag, value) SetQuicFlag(&flag, value); #include "net/quic/core/quic_flags_list.h" #undef QUIC_FLAG } @@ -394,10 +394,10 @@ QuicStreamId /*id*/, const QuicIOVector& data, QuicStreamOffset /*offset*/, - bool fin, + StreamSendingState state, const QuicReferenceCountedPointer< QuicAckListenerInterface>& /*ack_listener*/) { - return QuicConsumedData(data.total_length, fin); + return QuicConsumedData(data.total_length, state != NO_FIN); } MockQuicSpdySession::MockQuicSpdySession(QuicConnection* connection) @@ -445,8 +445,14 @@ &helper_); } -QuicCryptoServerStream* TestQuicSpdyServerSession::GetCryptoStream() { +QuicCryptoServerStream* TestQuicSpdyServerSession::GetMutableCryptoStream() { return static_cast<QuicCryptoServerStream*>( + QuicServerSessionBase::GetMutableCryptoStream()); +} + +const QuicCryptoServerStream* TestQuicSpdyServerSession::GetCryptoStream() + const { + return static_cast<const QuicCryptoServerStream*>( QuicServerSessionBase::GetCryptoStream()); } @@ -468,7 +474,12 @@ return true; } -QuicCryptoClientStream* TestQuicSpdyClientSession::GetCryptoStream() { +QuicCryptoClientStream* TestQuicSpdyClientSession::GetMutableCryptoStream() { + return crypto_stream_.get(); +} + +const QuicCryptoClientStream* TestQuicSpdyClientSession::GetCryptoStream() + const { return crypto_stream_.get(); }
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h index 6c046d0..1eb3868e 100644 --- a/net/quic/test_tools/quic_test_utils.h +++ b/net/quic/test_tools/quic_test_utils.h
@@ -476,7 +476,13 @@ explicit MockQuicSession(QuicConnection* connection); ~MockQuicSession() override; - QuicCryptoStream* GetCryptoStream() override { return crypto_stream_.get(); } + QuicCryptoStream* GetMutableCryptoStream() override { + return crypto_stream_.get(); + } + + const QuicCryptoStream* GetCryptoStream() const override { + return crypto_stream_.get(); + } MOCK_METHOD3(OnConnectionClosed, void(QuicErrorCode error, @@ -492,7 +498,7 @@ QuicStreamId id, QuicIOVector data, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface>)); MOCK_METHOD3(SendRstStream, @@ -506,7 +512,7 @@ void(QuicStreamId stream_id, SpdyPriority priority)); MOCK_METHOD3(OnStreamHeadersComplete, void(QuicStreamId stream_id, bool fin, size_t frame_len)); - MOCK_METHOD0(IsCryptoHandshakeConfirmed, bool()); + MOCK_CONST_METHOD0(IsCryptoHandshakeConfirmed, bool()); using QuicSession::ActivateStream; @@ -517,7 +523,7 @@ QuicStreamId id, const QuicIOVector& data, QuicStreamOffset offset, - bool fin, + StreamSendingState state, const QuicReferenceCountedPointer<QuicAckListenerInterface>& ack_listener); @@ -533,7 +539,12 @@ explicit MockQuicSpdySession(QuicConnection* connection); ~MockQuicSpdySession() override; - QuicCryptoStream* GetCryptoStream() override { return crypto_stream_.get(); } + QuicCryptoStream* GetMutableCryptoStream() override { + return crypto_stream_.get(); + } + const QuicCryptoStream* GetCryptoStream() const override { + return crypto_stream_.get(); + } const SpdyHeaderBlock& GetWriteHeaders() { return write_headers_; } // From QuicSession. @@ -553,7 +564,7 @@ QuicStreamId id, QuicIOVector data, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener)); MOCK_METHOD3(SendRstStream, @@ -572,7 +583,7 @@ bool fin, size_t frame_len, const QuicHeaderList& header_list)); - MOCK_METHOD0(IsCryptoHandshakeConfirmed, bool()); + MOCK_CONST_METHOD0(IsCryptoHandshakeConfirmed, bool()); MOCK_METHOD2(OnPromiseHeaders, void(QuicStreamId stream_id, QuicStringPiece headers_data)); MOCK_METHOD3(OnPromiseHeadersComplete, @@ -633,7 +644,9 @@ const QuicCryptoServerConfig* crypto_config, QuicCompressedCertsCache* compressed_certs_cache) override; - QuicCryptoServerStream* GetCryptoStream() override; + QuicCryptoServerStream* GetMutableCryptoStream() override; + + const QuicCryptoServerStream* GetCryptoStream() const override; MockQuicCryptoServerStreamHelper* helper() { return &helper_; } @@ -689,7 +702,8 @@ MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(QuicStreamId id)); MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool()); - QuicCryptoClientStream* GetCryptoStream() override; + QuicCryptoClientStream* GetMutableCryptoStream() override; + const QuicCryptoClientStream* GetCryptoStream() const override; private: std::unique_ptr<QuicCryptoClientStream> crypto_stream_;
diff --git a/net/quic/test_tools/simple_quic_framer.cc b/net/quic/test_tools/simple_quic_framer.cc index 734b1dc..cf2df6e0 100644 --- a/net/quic/test_tools/simple_quic_framer.cc +++ b/net/quic/test_tools/simple_quic_framer.cc
@@ -126,6 +126,9 @@ return stop_waiting_frames_; } const std::vector<QuicPingFrame>& ping_frames() const { return ping_frames_; } + const std::vector<QuicPaddingFrame>& padding_frames() const { + return padding_frames_; + } const QuicVersionNegotiationPacket* version_negotiation_packet() const { return version_negotiation_packet_.get(); } @@ -192,7 +195,7 @@ return ack_frames().size() + goaway_frames().size() + rst_stream_frames().size() + stop_waiting_frames().size() + stream_frames().size() + ping_frames().size() + - connection_close_frames().size(); + connection_close_frames().size() + padding_frames().size(); } const std::vector<QuicAckFrame>& SimpleQuicFramer::ack_frames() const { @@ -227,5 +230,9 @@ return visitor_->connection_close_frames(); } +const std::vector<QuicPaddingFrame>& SimpleQuicFramer::padding_frames() const { + return visitor_->padding_frames(); +} + } // namespace test } // namespace net
diff --git a/net/quic/test_tools/simple_quic_framer.h b/net/quic/test_tools/simple_quic_framer.h index ba9e988d..e231bda 100644 --- a/net/quic/test_tools/simple_quic_framer.h +++ b/net/quic/test_tools/simple_quic_framer.h
@@ -41,6 +41,7 @@ const std::vector<QuicGoAwayFrame>& goaway_frames() const; const std::vector<QuicRstStreamFrame>& rst_stream_frames() const; const std::vector<std::unique_ptr<QuicStreamFrame>>& stream_frames() const; + const std::vector<QuicPaddingFrame>& padding_frames() const; const QuicVersionNegotiationPacket* version_negotiation_packet() const; QuicFramer* framer();
diff --git a/net/quic/test_tools/simulator/quic_endpoint.cc b/net/quic/test_tools/simulator/quic_endpoint.cc index 638ad2e..6e810d43 100644 --- a/net/quic/test_tools/simulator/quic_endpoint.cc +++ b/net/quic/test_tools/simulator/quic_endpoint.cc
@@ -233,7 +233,7 @@ QuicIOVector io_vector(&iov, 1, transmission_size); QuicConsumedData consumed_data = connection_.SendStreamData( - kDataStream, io_vector, bytes_transferred_, false, nullptr); + kDataStream, io_vector, bytes_transferred_, NO_FIN, nullptr); DCHECK(consumed_data.bytes_consumed <= transmission_size); bytes_transferred_ += consumed_data.bytes_consumed;
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc index a96b361..6a0ea255 100644 --- a/net/spdy/spdy_framer.cc +++ b/net/spdy/spdy_framer.cc
@@ -20,7 +20,7 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/spdy/hpack/hpack_constants.h" #include "net/spdy/hpack/hpack_decoder.h" #include "net/spdy/hpack/hpack_decoder3.h"
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc index db731815..7f8061c 100644 --- a/net/spdy/spdy_framer_test.cc +++ b/net/spdy/spdy_framer_test.cc
@@ -20,7 +20,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/spdy/array_output_buffer.h" #include "net/spdy/hpack/hpack_constants.h" #include "net/spdy/mock_spdy_framer_visitor.h"
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc index 08d2e43..db3b8f9 100644 --- a/net/tools/quic/end_to_end_test.cc +++ b/net/tools/quic/end_to_end_test.cc
@@ -22,13 +22,13 @@ #include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h" #include "net/quic/core/crypto/null_encrypter.h" #include "net/quic/core/quic_client_session_base.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_framer.h" #include "net/quic/core/quic_packet_creator.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_server_id.h" #include "net/quic/core/quic_session.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_socket_address.h" @@ -153,9 +153,8 @@ QuicVersionVector version_buckets[1]; for (const QuicVersion version : all_supported_versions) { - // Versions: 34+ - // QUIC_VERSION_34 deprecates entropy and uses new ack and stop waiting - // wire formats. + // Versions: 35+ + // QUIC_VERSION_35 allows endpoints to independently set stream limit. version_buckets[0].push_back(version); } @@ -634,7 +633,7 @@ ASSERT_TRUE(Initialize()); EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); QuicCryptoStream* crypto_stream = - QuicSessionPeer::GetCryptoStream(client_->client()->session()); + QuicSessionPeer::GetMutableCryptoStream(client_->client()->session()); QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(crypto_stream); EXPECT_NE(FLAGS_quic_reloadable_flag_quic_release_crypto_stream_buffer, QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer)); @@ -642,7 +641,7 @@ QuicDispatcher* dispatcher = QuicServerPeer::GetDispatcher(server_thread_->server()); QuicSession* server_session = dispatcher->session_map().begin()->second.get(); - crypto_stream = QuicSessionPeer::GetCryptoStream(server_session); + crypto_stream = QuicSessionPeer::GetMutableCryptoStream(server_session); sequencer = QuicStreamPeer::sequencer(crypto_stream); EXPECT_NE(FLAGS_quic_reloadable_flag_quic_release_crypto_stream_buffer, QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer)); @@ -1279,41 +1278,6 @@ } } -TEST_P(EndToEndTest, NegotiateMaxOpenStreams) { - // Negotiate 1 max open stream. - client_config_.SetMaxStreamsPerConnection(1, 1); - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - if (negotiated_version_ > QUIC_VERSION_34) { - // Newer versions use max incoming dynamic streams. - return; - } - - // Make the client misbehave after negotiation. - const int kServerMaxStreams = kMaxStreamsMinimumIncrement + 1; - QuicSessionPeer::SetMaxOpenOutgoingStreams(client_->client()->session(), - kServerMaxStreams + 1); - - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - headers["content-length"] = "3"; - - // The server supports a small number of additional streams beyond the - // negotiated limit. Open enough streams to go beyond that limit. - for (int i = 0; i < kServerMaxStreams + 1; ++i) { - client_->SendMessage(headers, "", /*fin=*/false); - } - client_->WaitForResponse(); - - EXPECT_TRUE(client_->connected()); - EXPECT_EQ(QUIC_REFUSED_STREAM, client_->stream_error()); - EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error()); -} - TEST_P(EndToEndTest, MaxIncomingDynamicStreamsLimitRespected) { // Set a limit on maximum number of incoming dynamic streams. // Make sure the limit is respected. @@ -1323,11 +1287,6 @@ ASSERT_TRUE(Initialize()); EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - if (negotiated_version_ <= QUIC_VERSION_34) { - // Earlier versions negotiated max open streams. - return; - } - // Make the client misbehave after negotiation. const int kServerMaxStreams = kMaxStreamsMinimumIncrement + kServerMaxIncomingDynamicStreams; @@ -1364,11 +1323,6 @@ ASSERT_TRUE(Initialize()); EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - if (negotiated_version_ <= QUIC_VERSION_34) { - // Earlier versions negotiated max open streams. - return; - } - // The client has received the server's limit and vice versa. EXPECT_EQ(kServerMaxIncomingDynamicStreams, client_->client()->session()->max_open_outgoing_streams()); @@ -1409,22 +1363,6 @@ server_thread_->Resume(); } -TEST_P(EndToEndTest, LimitMaxOpenStreams) { - // Server limits the number of max streams to 2. - server_config_.SetMaxStreamsPerConnection(2, 2); - // Client tries to negotiate for 10. - client_config_.SetMaxStreamsPerConnection(10, 5); - - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - if (negotiated_version_ > QUIC_VERSION_34) { - // No negotiated max streams beyond version 34. - return; - } - QuicConfig* client_negotiated_config = client_->client()->session()->config(); - EXPECT_EQ(2u, client_negotiated_config->MaxStreamsPerConnection()); -} - TEST_P(EndToEndTest, ClientSuggestsRTT) { // Client suggests initial RTT, verify it is used. const uint32_t kInitialRTT = 20000; @@ -1764,8 +1702,6 @@ // Test negotiation of IFWA connection option. TEST_P(EndToEndTest, NegotiatedServerInitialFlowControlWindow) { - FLAGS_quic_reloadable_flag_quic_large_ifw_options = true; - const uint32_t kClientStreamIFCW = 123456; const uint32_t kClientSessionIFCW = 234567; set_client_initial_stream_flow_control_receive_window(kClientStreamIFCW); @@ -1828,7 +1764,7 @@ server_thread_->WaitForCryptoHandshakeConfirmed(); QuicCryptoStream* crypto_stream = - QuicSessionPeer::GetCryptoStream(client_->client()->session()); + QuicSessionPeer::GetMutableCryptoStream(client_->client()->session()); EXPECT_LT( QuicFlowControllerPeer::SendWindowSize(crypto_stream->flow_controller()), kStreamIFCW); @@ -1879,8 +1815,10 @@ ExpectFlowControlsSynced(client_session->flow_controller(), server_session->flow_controller()); ExpectFlowControlsSynced( - QuicSessionPeer::GetCryptoStream(client_session)->flow_controller(), - QuicSessionPeer::GetCryptoStream(server_session)->flow_controller()); + QuicSessionPeer::GetMutableCryptoStream(client_session) + ->flow_controller(), + QuicSessionPeer::GetMutableCryptoStream(server_session) + ->flow_controller()); SpdyFramer spdy_framer(SpdyFramer::ENABLE_COMPRESSION); SpdySettingsIR settings_frame; settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE,
diff --git a/net/tools/quic/platform/impl/quic_socket_utils.cc b/net/tools/quic/platform/impl/quic_socket_utils.cc index bb1fcbd..d602ac35 100644 --- a/net/tools/quic/platform/impl/quic_socket_utils.cc +++ b/net/tools/quic/platform/impl/quic_socket_utils.cc
@@ -12,9 +12,9 @@ #include <sys/uio.h> #include <string> -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_socket_address.h"
diff --git a/net/tools/quic/quic_client_base.cc b/net/tools/quic/quic_client_base.cc index 77e945c..b08f144 100644 --- a/net/tools/quic/quic_client_base.cc +++ b/net/tools/quic/quic_client_base.cc
@@ -5,9 +5,9 @@ #include "net/tools/quic/quic_client_base.h" #include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_server_id.h" #include "net/quic/core/spdy_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_text_utils.h"
diff --git a/net/tools/quic/quic_client_bin.cc b/net/tools/quic/quic_client_bin.cc index 286f51d..af2bbfd7 100644 --- a/net/tools/quic/quic_client_bin.cc +++ b/net/tools/quic/quic_client_bin.cc
@@ -51,9 +51,9 @@ #include "net/cert/multi_log_ct_verifier.h" #include "net/http/transport_security_state.h" #include "net/quic/chromium/crypto/proof_verifier_chromium.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_server_id.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_socket_address.h" #include "net/quic/platform/api/quic_str_cat.h" #include "net/quic/platform/api/quic_string_piece.h"
diff --git a/net/tools/quic/quic_client_session.cc b/net/tools/quic/quic_client_session.cc index 8a8e3f0..d1808d7 100644 --- a/net/tools/quic/quic_client_session.cc +++ b/net/tools/quic/quic_client_session.cc
@@ -75,7 +75,11 @@ return QuicMakeUnique<QuicSpdyClientStream>(GetNextOutgoingStreamId(), this); } -QuicCryptoClientStreamBase* QuicClientSession::GetCryptoStream() { +QuicCryptoClientStreamBase* QuicClientSession::GetMutableCryptoStream() { + return crypto_stream_.get(); +} + +const QuicCryptoClientStreamBase* QuicClientSession::GetCryptoStream() const { return crypto_stream_.get(); }
diff --git a/net/tools/quic/quic_client_session.h b/net/tools/quic/quic_client_session.h index 055fb1c24..8dbdf2c 100644 --- a/net/tools/quic/quic_client_session.h +++ b/net/tools/quic/quic_client_session.h
@@ -37,7 +37,8 @@ // QuicSession methods: QuicSpdyClientStream* CreateOutgoingDynamicStream( SpdyPriority priority) override; - QuicCryptoClientStreamBase* GetCryptoStream() override; + QuicCryptoClientStreamBase* GetMutableCryptoStream() override; + const QuicCryptoClientStreamBase* GetCryptoStream() const override; bool IsAuthorized(const std::string& authority) override;
diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_client_session_test.cc index 82c20e60..b60833dab 100644 --- a/net/tools/quic/quic_client_session_test.cc +++ b/net/tools/quic/quic_client_session_test.cc
@@ -7,8 +7,8 @@ #include <vector> #include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/spdy_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_socket_address.h" #include "net/quic/platform/api/quic_str_cat.h" @@ -102,8 +102,8 @@ void CompleteCryptoHandshake(uint32_t server_max_incoming_streams) { session_->CryptoConnect(); - QuicCryptoClientStream* stream = - static_cast<QuicCryptoClientStream*>(session_->GetCryptoStream()); + QuicCryptoClientStream* stream = static_cast<QuicCryptoClientStream*>( + session_->GetMutableCryptoStream()); crypto_test_utils::FakeServerOptions options; QuicConfig config = DefaultQuicConfig(); config.SetMaxIncomingDynamicStreamsToSend(server_max_incoming_streams); @@ -153,7 +153,7 @@ CryptoHandshakeMessage rej; crypto_test_utils::FillInDummyReject(&rej, /* stateless */ false); EXPECT_TRUE(session_->IsEncryptionEstablished()); - session_->GetCryptoStream()->OnHandshakeMessage(rej); + session_->GetMutableCryptoStream()->OnHandshakeMessage(rej); EXPECT_FALSE(session_->IsEncryptionEstablished()); EXPECT_EQ(ENCRYPTION_NONE, QuicPacketCreatorPeer::GetEncryptionLevel( @@ -166,7 +166,7 @@ struct iovec iov = {data, arraysize(data)}; QuicIOVector iovector(&iov, 1, iov.iov_len); QuicConsumedData consumed = - session_->WritevData(stream, stream->id(), iovector, 0, false, nullptr); + session_->WritevData(stream, stream->id(), iovector, 0, NO_FIN, nullptr); EXPECT_FALSE(consumed.fin_consumed); EXPECT_EQ(0u, consumed.bytes_consumed); } @@ -174,15 +174,8 @@ TEST_P(QuicClientSessionTest, MaxNumStreamsWithNoFinOrRst) { EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(AnyNumber()); - if (GetParam() <= QUIC_VERSION_34) { - session_->config()->SetMaxStreamsPerConnection(1, 1); - - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - } else { - const uint32_t kServerMaxIncomingStreams = 1; - CompleteCryptoHandshake(kServerMaxIncomingStreams); - } + const uint32_t kServerMaxIncomingStreams = 1; + CompleteCryptoHandshake(kServerMaxIncomingStreams); QuicSpdyClientStream* stream = session_->CreateOutgoingDynamicStream(kDefaultPriority); @@ -201,15 +194,8 @@ TEST_P(QuicClientSessionTest, MaxNumStreamsWithRst) { EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(AnyNumber()); - if (GetParam() <= QUIC_VERSION_34) { - session_->config()->SetMaxStreamsPerConnection(1, 1); - - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - } else { - const uint32_t kServerMaxIncomingStreams = 1; - CompleteCryptoHandshake(kServerMaxIncomingStreams); - } + const uint32_t kServerMaxIncomingStreams = 1; + CompleteCryptoHandshake(kServerMaxIncomingStreams); QuicSpdyClientStream* stream = session_->CreateOutgoingDynamicStream(kDefaultPriority);
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc index 38a4445..6721c07 100644 --- a/net/tools/quic/quic_dispatcher.cc +++ b/net/tools/quic/quic_dispatcher.cc
@@ -8,10 +8,10 @@ #include "base/macros.h" #include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_flag_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_stack_trace.h"
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc index 3c78e671..3f3f235 100644 --- a/net/tools/quic/quic_dispatcher_test.cc +++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -13,8 +13,8 @@ #include "net/quic/core/crypto/quic_crypto_server_config.h" #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/quic_crypto_stream.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_str_cat.h" #include "net/quic/test_tools/crypto_test_utils.h" @@ -68,7 +68,7 @@ nullptr, crypto_config, compressed_certs_cache), - crypto_stream_(QuicServerSessionBase::GetCryptoStream()) {} + crypto_stream_(QuicServerSessionBase::GetMutableCryptoStream()) {} ~TestQuicSpdyServerSession() override { delete connection(); }; @@ -93,7 +93,11 @@ crypto_stream_ = crypto_stream; } - QuicCryptoServerStreamBase* GetCryptoStream() override { + QuicCryptoServerStreamBase* GetMutableCryptoStream() override { + return crypto_stream_; + } + + const QuicCryptoServerStreamBase* GetCryptoStream() const override { return crypto_stream_; } @@ -528,13 +532,10 @@ } TEST_F(QuicDispatcherTest, SupportedVersionsChangeInFlight) { - static_assert(arraysize(kSupportedQuicVersions) == 6u, + static_assert(arraysize(kSupportedQuicVersions) == 5u, "Supported versions out of sync"); - FLAGS_quic_reloadable_flag_quic_disable_version_34 = false; - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true; - FLAGS_quic_reloadable_flag_quic_enable_version_37 = true; FLAGS_quic_reloadable_flag_quic_enable_version_38 = true; - base::SetFlag(&FLAGS_quic_enable_version_39, true); + SetQuicFlag(&FLAGS_quic_enable_version_39, true); QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5); QuicConnectionId connection_id = 1; @@ -574,7 +575,7 @@ PACKET_6BYTE_PACKET_NUMBER, 1); // Turn off version 39. - base::SetFlag(&FLAGS_quic_enable_version_39, false); + SetQuicFlag(&FLAGS_quic_enable_version_39, false); ++connection_id; EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) .Times(0); @@ -583,7 +584,7 @@ PACKET_6BYTE_PACKET_NUMBER, 1); // Turn on version 39. - base::SetFlag(&FLAGS_quic_enable_version_39, true); + SetQuicFlag(&FLAGS_quic_enable_version_39, true); ++connection_id; EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) .WillOnce(testing::Return(CreateSession( @@ -598,58 +599,6 @@ ProcessPacket(client_address, connection_id, true, QUIC_VERSION_39, SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, 1); - - // Turn off version 36. - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = false; - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) - .Times(0); - ProcessPacket(client_address, connection_id, true, QUIC_VERSION_36, - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_6BYTE_PACKET_NUMBER, 1); - - // Turn on version 36. - FLAGS_quic_reloadable_flag_quic_enable_version_36_v3 = true; - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, connection_id, client_address, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(testing::WithArgs<2>( - Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, - base::Unretained(this), connection_id)))); - ProcessPacket(client_address, connection_id, true, QUIC_VERSION_35, - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_6BYTE_PACKET_NUMBER, 1); - - // Turn off version 34. - FLAGS_quic_reloadable_flag_quic_disable_version_34 = true; - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) - .Times(0); - ProcessPacket(client_address, connection_id, true, QUIC_VERSION_34, - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_6BYTE_PACKET_NUMBER, 1); - - // Turn on version 34. - FLAGS_quic_reloadable_flag_quic_disable_version_34 = false; - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, connection_id, client_address, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(testing::WithArgs<2>( - Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, - base::Unretained(this), connection_id)))); - ProcessPacket(client_address, connection_id, true, QUIC_VERSION_34, - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_6BYTE_PACKET_NUMBER, 1); } // Enables mocking of the handshake-confirmation for stateless rejects.
diff --git a/net/tools/quic/quic_packet_reader.cc b/net/tools/quic/quic_packet_reader.cc index 27deb96..e4cbbf34 100644 --- a/net/tools/quic/quic_packet_reader.cc +++ b/net/tools/quic/quic_packet_reader.cc
@@ -11,8 +11,8 @@ #endif #include <string.h> -#include "net/quic/core/quic_flags.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_socket_address.h" #include "net/tools/quic/platform/impl/quic_socket_utils.h"
diff --git a/net/tools/quic/quic_server.cc b/net/tools/quic/quic_server.cc index 91b11a318..60adc461 100644 --- a/net/tools/quic/quic_server.cc +++ b/net/tools/quic/quic_server.cc
@@ -18,6 +18,8 @@ #include "net/quic/core/quic_crypto_stream.h" #include "net/quic/core/quic_data_reader.h" #include "net/quic/core/quic_packets.h" +#include "net/quic/platform/api/quic_clock.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/tools/quic/platform/impl/quic_epoll_clock.h" #include "net/tools/quic/platform/impl/quic_socket_utils.h"
diff --git a/net/tools/quic/quic_server_test.cc b/net/tools/quic/quic_server_test.cc index d880dcc..ec1bcae 100644 --- a/net/tools/quic/quic_server_test.cc +++ b/net/tools/quic/quic_server_test.cc
@@ -6,6 +6,7 @@ #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_socket_address.h" #include "net/quic/test_tools/crypto_test_utils.h"
diff --git a/net/tools/quic/quic_simple_client.cc b/net/tools/quic/quic_simple_client.cc index ee277bd..70c7503 100644 --- a/net/tools/quic/quic_simple_client.cc +++ b/net/tools/quic/quic_simple_client.cc
@@ -20,10 +20,10 @@ #include "net/quic/chromium/quic_chromium_packet_writer.h" #include "net/quic/core/crypto/quic_random.h" #include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_server_id.h" #include "net/quic/core/spdy_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/socket/udp_client_socket.h" #include "net/spdy/spdy_header_block.h" #include "net/spdy/spdy_http_utils.h"
diff --git a/net/tools/quic/quic_simple_server_session.cc b/net/tools/quic/quic_simple_server_session.cc index 5f60d7427..4f3ed4b4 100644 --- a/net/tools/quic/quic_simple_server_session.cc +++ b/net/tools/quic/quic_simple_server_session.cc
@@ -8,7 +8,7 @@ #include "net/quic/core/proto/cached_network_parameters.pb.h" #include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_flags.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/tools/quic/quic_simple_server_stream.h"
diff --git a/net/tools/quic/quic_simple_server_session_test.cc b/net/tools/quic/quic_simple_server_session_test.cc index 4cc0329..cf1af8a 100644 --- a/net/tools/quic/quic_simple_server_session_test.cc +++ b/net/tools/quic/quic_simple_server_session_test.cc
@@ -14,6 +14,7 @@ #include "net/quic/core/quic_connection.h" #include "net/quic/core/quic_crypto_server_stream.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_socket_address.h" #include "net/quic/platform/api/quic_string_piece.h" #include "net/quic/platform/api/quic_text_utils.h" @@ -123,7 +124,7 @@ QuicStreamId id, QuicIOVector iov, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener)); }; @@ -490,7 +491,7 @@ // Since flow control window is smaller than response body, not the // whole body will be sent. if (!session_->force_hol_blocking()) { - EXPECT_CALL(*connection_, SendStreamData(stream_id, _, 0, false, _)) + EXPECT_CALL(*connection_, SendStreamData(stream_id, _, 0, NO_FIN, _)) .WillOnce(Return( QuicConsumedData(kStreamFlowControlWindowSize, false))); EXPECT_CALL(*connection_, SendBlocked(stream_id)); @@ -499,7 +500,7 @@ // HTTP/2 DATA frames within the headers stream. HTTP/2 // DATA frames are limited to a max size of 16KB, so the // 64KB body will be fragemented into four DATA frames. - EXPECT_CALL(*connection_, SendStreamData(_, _, _, false, _)) + EXPECT_CALL(*connection_, SendStreamData(_, _, _, NO_FIN, _)) .Times(body_size / 16384) .WillOnce(Return(QuicConsumedData(9 + 16394, false))) .WillOnce(Return(QuicConsumedData(9 + 16394, false))) @@ -548,7 +549,7 @@ EXPECT_CALL(*session_, WriteHeadersMock(next_out_going_stream_id, _, false, kDefaultPriority, _)); EXPECT_CALL(*connection_, - SendStreamData(next_out_going_stream_id, _, 0, false, _)) + SendStreamData(next_out_going_stream_id, _, 0, NO_FIN, _)) .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false))); EXPECT_CALL(*connection_, SendBlocked(next_out_going_stream_id)); session_->StreamDraining(2); @@ -585,7 +586,7 @@ InSequence s; EXPECT_CALL(*session_, WriteHeadersMock(stream_not_reset, _, false, kDefaultPriority, _)); - EXPECT_CALL(*connection_, SendStreamData(stream_not_reset, _, 0, false, _)) + EXPECT_CALL(*connection_, SendStreamData(stream_not_reset, _, 0, NO_FIN, _)) .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false))); EXPECT_CALL(*connection_, SendBlocked(stream_not_reset)); EXPECT_CALL(*session_, @@ -614,7 +615,7 @@ SendRstStream(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT, _)); EXPECT_CALL(*session_, WriteHeadersMock(stream_to_open, _, false, kDefaultPriority, _)); - EXPECT_CALL(*connection_, SendStreamData(stream_to_open, _, 0, false, _)) + EXPECT_CALL(*connection_, SendStreamData(stream_to_open, _, 0, NO_FIN, _)) .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false))); EXPECT_CALL(*connection_, SendBlocked(stream_to_open));
diff --git a/net/tools/quic/quic_simple_server_stream.cc b/net/tools/quic/quic_simple_server_stream.cc index 14f2407..3b9f85b 100644 --- a/net/tools/quic/quic_simple_server_stream.cc +++ b/net/tools/quic/quic_simple_server_stream.cc
@@ -7,10 +7,10 @@ #include <list> #include <utility> -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_spdy_stream.h" #include "net/quic/core/spdy_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_map_util.h" #include "net/quic/platform/api/quic_text_utils.h"
diff --git a/net/tools/quic/quic_simple_server_stream_test.cc b/net/tools/quic/quic_simple_server_stream_test.cc index 86b27d13..69567f6 100644 --- a/net/tools/quic/quic_simple_server_stream_test.cc +++ b/net/tools/quic/quic_simple_server_stream_test.cc
@@ -108,7 +108,7 @@ QuicStreamId id, QuicIOVector data, QuicStreamOffset offset, - bool fin, + StreamSendingState state, QuicReferenceCountedPointer<QuicAckListenerInterface>)); MOCK_METHOD4(OnStreamHeaderList, void(QuicStreamId stream_id,
diff --git a/net/tools/quic/quic_time_wait_list_manager.cc b/net/tools/quic/quic_time_wait_list_manager.cc index 35c1e39..4fa077f 100644 --- a/net/tools/quic/quic_time_wait_list_manager.cc +++ b/net/tools/quic/quic_time_wait_list_manager.cc
@@ -12,11 +12,11 @@ #include "net/quic/core/crypto/crypto_protocol.h" #include "net/quic/core/crypto/quic_decrypter.h" #include "net/quic/core/crypto/quic_encrypter.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_framer.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_utils.h" #include "net/quic/platform/api/quic_clock.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_map_util.h" #include "net/quic/platform/api/quic_ptr_util.h"
diff --git a/net/tools/quic/quic_time_wait_list_manager.h b/net/tools/quic/quic_time_wait_list_manager.h index 998bb36..6e611796 100644 --- a/net/tools/quic/quic_time_wait_list_manager.h +++ b/net/tools/quic/quic_time_wait_list_manager.h
@@ -22,6 +22,7 @@ #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_session.h" #include "net/quic/platform/api/quic_containers.h" +#include "net/quic/platform/api/quic_flags.h" namespace net {
diff --git a/net/tools/quic/quic_time_wait_list_manager_test.cc b/net/tools/quic/quic_time_wait_list_manager_test.cc index 6ff7b87..96d74d0d 100644 --- a/net/tools/quic/quic_time_wait_list_manager_test.cc +++ b/net/tools/quic/quic_time_wait_list_manager_test.cc
@@ -13,11 +13,11 @@ #include "net/quic/core/crypto/quic_decrypter.h" #include "net/quic/core/crypto/quic_encrypter.h" #include "net/quic/core/quic_data_reader.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_framer.h" #include "net/quic/core/quic_packet_writer.h" #include "net/quic/core/quic_packets.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/test_tools/quic_test_utils.h" #include "net/quic/test_tools/quic_time_wait_list_manager_peer.h" #include "net/tools/quic/quic_epoll_alarm_factory.h"
diff --git a/net/tools/quic/stateless_rejector.cc b/net/tools/quic/stateless_rejector.cc index 8c6cb980..a0fc1c56 100644 --- a/net/tools/quic/stateless_rejector.cc +++ b/net/tools/quic/stateless_rejector.cc
@@ -5,8 +5,8 @@ #include "net/tools/quic/stateless_rejector.h" #include "net/quic/core/quic_crypto_server_stream.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/platform/api/quic_bug_tracker.h" +#include "net/quic/platform/api/quic_flags.h" namespace net {
diff --git a/net/tools/quic/stateless_rejector_test.cc b/net/tools/quic/stateless_rejector_test.cc index ea1ec24..50b5a83 100644 --- a/net/tools/quic/stateless_rejector_test.cc +++ b/net/tools/quic/stateless_rejector_test.cc
@@ -10,6 +10,7 @@ #include "net/quic/core/crypto/crypto_handshake_message.h" #include "net/quic/core/crypto/proof_source.h" #include "net/quic/core/quic_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_str_cat.h"
diff --git a/net/tools/quic/test_tools/packet_dropping_test_writer.cc b/net/tools/quic/test_tools/packet_dropping_test_writer.cc index c350c6b..3de6dba 100644 --- a/net/tools/quic/test_tools/packet_dropping_test_writer.cc +++ b/net/tools/quic/test_tools/packet_dropping_test_writer.cc
@@ -181,8 +181,8 @@ delayed_packets_.begin()->send_time = iter->send_time; } - QUIC_DLOG(INFO) << "Releasing packet. " << (delayed_packets_.size() - 1) - << " remaining."; + QUIC_DVLOG(1) << "Releasing packet. " << (delayed_packets_.size() - 1) + << " remaining."; // Grab the next one off the queue and send it. QuicPacketWriterWrapper::WritePacket( iter->buffer.data(), iter->buffer.length(), iter->self_address,
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc index 893b6b81..3e86670 100644 --- a/net/tools/quic/test_tools/quic_test_client.cc +++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -9,10 +9,10 @@ #include <vector> #include "net/quic/core/crypto/proof_verifier.h" -#include "net/quic/core/quic_flags.h" #include "net/quic/core/quic_server_id.h" #include "net/quic/core/quic_utils.h" #include "net/quic/core/spdy_utils.h" +#include "net/quic/platform/api/quic_flags.h" #include "net/quic/platform/api/quic_logging.h" #include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_stack_trace.h"
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc index 61d7a4a..a64544eb 100644 --- a/net/url_request/url_request_context_builder.cc +++ b/net/url_request/url_request_context_builder.cc
@@ -188,7 +188,6 @@ enable_http2(true), enable_quic(false), quic_max_server_configs_stored_in_properties(0), - quic_delay_tcp_race(true), quic_idle_connection_timeout_seconds(kIdleConnectionTimeoutSeconds), quic_close_sessions_on_ip_change(false), quic_migrate_sessions_on_network_change(false), @@ -422,8 +421,6 @@ network_session_params.enable_quic = http_network_session_params_.enable_quic; network_session_params.quic_max_server_configs_stored_in_properties = http_network_session_params_.quic_max_server_configs_stored_in_properties; - network_session_params.quic_delay_tcp_race = - http_network_session_params_.quic_delay_tcp_race; network_session_params.quic_idle_connection_timeout_seconds = http_network_session_params_.quic_idle_connection_timeout_seconds; network_session_params.quic_connection_options =
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h index 10c6fca..53c0ec8 100644 --- a/net/url_request/url_request_context_builder.h +++ b/net/url_request/url_request_context_builder.h
@@ -96,7 +96,6 @@ bool enable_quic; std::string quic_user_agent_id; int quic_max_server_configs_stored_in_properties; - bool quic_delay_tcp_race; int quic_idle_connection_timeout_seconds; QuicTagVector quic_connection_options; bool quic_close_sessions_on_ip_change; @@ -229,10 +228,6 @@ quic_max_server_configs_stored_in_properties; } - void set_quic_delay_tcp_race(bool quic_delay_tcp_race) { - http_network_session_params_.quic_delay_tcp_race = quic_delay_tcp_race; - } - void set_quic_idle_connection_timeout_seconds( int quic_idle_connection_timeout_seconds) { http_network_session_params_.quic_idle_connection_timeout_seconds =
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 1eb9711..7282a0e5 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -7868,127 +7868,6 @@ EXPECT_EQ(LOW, job_priority); } -TEST_F(URLRequestTest, QuicServerInfoFactoryTest) { - HttpNetworkSession::Params params; - - MockClientSocketFactory socket_factory; - MockCryptoClientStreamFactory crypto_client_stream_factory; - MockHostResolver host_resolver; - MockCertVerifier cert_verifier; - CTPolicyEnforcer ct_policy_enforcer; - TransportSecurityState transport_security_state; - std::unique_ptr<CTVerifier> cert_transparency_verifier( - new MultiLogCTVerifier()); - std::unique_ptr<ProxyService> proxy_service = ProxyService::CreateDirect(); - scoped_refptr<SSLConfigServiceDefaults> ssl_config_service( - new SSLConfigServiceDefaults); - HttpServerPropertiesImpl http_server_properties; - // Set up the quic stream factory. - params.enable_quic = true; - params.client_socket_factory = &socket_factory; - params.quic_crypto_client_stream_factory = &crypto_client_stream_factory; - params.host_resolver = &host_resolver; - params.cert_verifier = &cert_verifier; - params.ct_policy_enforcer = &ct_policy_enforcer; - params.transport_security_state = &transport_security_state; - params.cert_transparency_verifier = cert_transparency_verifier.get(); - - params.proxy_service = proxy_service.get(); - params.ssl_config_service = ssl_config_service.get(); - params.http_server_properties = &http_server_properties; - - HttpNetworkSession session(params); - DCHECK(session.quic_stream_factory()); - - std::unique_ptr<HttpNetworkLayer> network_layer1( - new HttpNetworkLayer(&session)); - - HttpCache main_cache(std::move(network_layer1), - HttpCache::DefaultBackend::InMemory(0), - true /* is_main_cache */); - - EXPECT_TRUE(session.quic_stream_factory()->has_quic_server_info_factory()); - - default_context_.set_http_transaction_factory(&main_cache); - - QuicServerInfoFactory* quic_server_info_factory = - session.quic_stream_factory()->quic_server_info_factory(); - DCHECK(quic_server_info_factory); - - QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); - const string server_config_a = "server_config_a"; - const string source_address_token_a = "source_address_token_a"; - const string cert_sct_a = "cert_sct_a"; - const string chlo_hash_a = "chlo_hash_a"; - const string server_config_sig_a = "server_config_sig_a"; - const string cert_a = "cert_a"; - const string cert_b = "cert_b"; - - { - // Store a QuicServerInfo to the quic server info factory. - TestCompletionCallback cb; - std::unique_ptr<QuicServerInfo> quic_server_info = - quic_server_info_factory->GetForServer(server_id); - quic_server_info->Start(); - int rv = quic_server_info->WaitForDataReady(cb.callback()); - EXPECT_THAT(cb.GetResult(rv), IsOk()); - - QuicServerInfo::State* state = quic_server_info->mutable_state(); - EXPECT_TRUE(state->certs.empty()); - - state->server_config = server_config_a; - state->source_address_token = source_address_token_a; - state->cert_sct = cert_sct_a; - state->chlo_hash = chlo_hash_a; - state->server_config_sig = server_config_sig_a; - state->certs.push_back(cert_a); - quic_server_info->Persist(); - base::RunLoop().RunUntilIdle(); - } - - // Retrieve the QuicServerInfo from the quic server info factory and verify - // the data is correct. - { - TestCompletionCallback cb; - std::unique_ptr<QuicServerInfo> quic_server_info = - quic_server_info_factory->GetForServer(server_id); - quic_server_info->Start(); - int rv = quic_server_info->WaitForDataReady(cb.callback()); - EXPECT_THAT(cb.GetResult(rv), IsOk()); - - QuicServerInfo::State* state = quic_server_info->mutable_state(); - EXPECT_TRUE(quic_server_info->IsDataReady()); - EXPECT_EQ(server_config_a, state->server_config); - EXPECT_EQ(source_address_token_a, state->source_address_token); - EXPECT_EQ(cert_sct_a, state->cert_sct); - EXPECT_EQ(chlo_hash_a, state->chlo_hash); - EXPECT_EQ(server_config_sig_a, state->server_config_sig); - EXPECT_EQ(1U, state->certs.size()); - EXPECT_EQ(cert_a, state->certs[0]); - - // Update the data. - state->certs.push_back(cert_b); - quic_server_info->Persist(); - base::RunLoop().RunUntilIdle(); - } - - { - // Verify data has been successfully updated. - TestCompletionCallback cb; - std::unique_ptr<QuicServerInfo> quic_server_info = - quic_server_info_factory->GetForServer(server_id); - quic_server_info->Start(); - int rv = quic_server_info->WaitForDataReady(cb.callback()); - EXPECT_THAT(cb.GetResult(rv), IsOk()); - - QuicServerInfo::State* state = quic_server_info->mutable_state(); - EXPECT_TRUE(quic_server_info->IsDataReady()); - EXPECT_EQ(2U, state->certs.size()); - EXPECT_EQ(cert_a, state->certs[0]); - EXPECT_EQ(cert_b, state->certs[1]); - } -} - // Check that creating a network request while entering/exiting suspend mode // fails as it should. This is the only case where an HttpTransactionFactory // does not return an HttpTransaction.
diff --git a/printing/backend/print_backend_win.cc b/printing/backend/print_backend_win.cc index 39760867..0466bb5 100644 --- a/printing/backend/print_backend_win.cc +++ b/printing/backend/print_backend_win.cc
@@ -324,15 +324,15 @@ hr = CreateStreamOnHGlobal(NULL, TRUE, print_capabilities_stream.Receive()); DCHECK(SUCCEEDED(hr)); - if (print_capabilities_stream.get()) { + if (print_capabilities_stream.Get()) { base::win::ScopedBstr error; hr = XPSModule::GetPrintCapabilities( - provider, NULL, print_capabilities_stream.get(), error.Receive()); + provider, NULL, print_capabilities_stream.Get(), error.Receive()); DCHECK(SUCCEEDED(hr)); if (FAILED(hr)) { return false; } - hr = StreamOnHGlobalToString(print_capabilities_stream.get(), + hr = StreamOnHGlobalToString(print_capabilities_stream.Get(), &printer_info->printer_capabilities); DCHECK(SUCCEEDED(hr)); printer_info->caps_mime_type = "text/xml"; @@ -347,14 +347,14 @@ hr = CreateStreamOnHGlobal(NULL, TRUE, printer_defaults_stream.Receive()); DCHECK(SUCCEEDED(hr)); - if (printer_defaults_stream.get()) { + if (printer_defaults_stream.Get()) { DWORD dm_size = devmode_out->dmSize + devmode_out->dmDriverExtra; hr = XPSModule::ConvertDevModeToPrintTicket( provider, dm_size, devmode_out.get(), kPTJobScope, - printer_defaults_stream.get()); + printer_defaults_stream.Get()); DCHECK(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { - hr = StreamOnHGlobalToString(printer_defaults_stream.get(), + hr = StreamOnHGlobalToString(printer_defaults_stream.Get(), &printer_info->printer_defaults); DCHECK(SUCCEEDED(hr)); printer_info->defaults_mime_type = "text/xml";
diff --git a/printing/backend/win_helper.cc b/printing/backend/win_helper.cc index 99d0e6f..693fc1e7 100644 --- a/printing/backend/win_helper.cc +++ b/printing/backend/win_helper.cc
@@ -416,7 +416,7 @@ DEVMODE* dm = NULL; // Use kPTJobScope, because kPTDocumentScope breaks duplex. hr = printing::XPSModule::ConvertPrintTicketToDevMode( - provider, pt_stream.get(), kUserDefaultDevmode, kPTJobScope, &size, &dm, + provider, pt_stream.Get(), kUserDefaultDevmode, kPTJobScope, &size, &dm, NULL); if (SUCCEEDED(hr)) { // Correct DEVMODE using DocumentProperties. See documentation for
diff --git a/remoting/host/audio_capturer_win.cc b/remoting/host/audio_capturer_win.cc index 8e238db..70bc0b0 100644 --- a/remoting/host/audio_capturer_win.cc +++ b/remoting/host/audio_capturer_win.cc
@@ -146,10 +146,10 @@ } bool AudioCapturerWin::Initialize() { - DCHECK(!audio_capture_client_.get()); - DCHECK(!audio_client_.get()); - DCHECK(!mm_device_.get()); - DCHECK(!audio_volume_.get()); + DCHECK(!audio_capture_client_.Get()); + DCHECK(!audio_client_.Get()); + DCHECK(!mm_device_.Get()); + DCHECK(!audio_volume_.Get()); DCHECK(static_cast<PWAVEFORMATEX>(wave_format_ex_) == nullptr); DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/remoting/host/desktop_session_win.cc b/remoting/host/desktop_session_win.cc index eff9158b..77b30603 100644 --- a/remoting/host/desktop_session_win.cc +++ b/remoting/host/desktop_session_win.cc
@@ -308,7 +308,7 @@ result = rdp_desktop_session_->Connect(host_size.width(), host_size.height(), kDefaultRdpDpi, kDefaultRdpDpi, terminal_id, server_port, - event_handler.get()); + event_handler.Get()); if (FAILED(result)) { LOG(ERROR) << "RdpSession::Create() failed, 0x" << std::hex << result << std::dec << ".";
diff --git a/remoting/host/setup/win/auth_code_getter.cc b/remoting/host/setup/win/auth_code_getter.cc index 3cf6c8c..e255b74 100644 --- a/remoting/host/setup/win/auth_code_getter.cc +++ b/remoting/host/setup/win/auth_code_getter.cc
@@ -27,7 +27,7 @@ void AuthCodeGetter::GetAuthCode( base::Callback<void(const std::string&)> on_auth_code) { - if (browser_.get()) { + if (browser_.Get()) { on_auth_code.Run(""); return; } @@ -67,7 +67,7 @@ bool AuthCodeGetter::TestBrowserUrl(std::string* auth_code) { *auth_code = ""; - if (!browser_.get()) { + if (!browser_.Get()) { return true; } base::win::ScopedBstr url; @@ -86,7 +86,7 @@ } void AuthCodeGetter::KillBrowser() { - if (browser_.get()) { + if (browser_.Get()) { browser_->Quit(); browser_.Reset(); }
diff --git a/remoting/host/win/rdp_client_window.cc b/remoting/host/win/rdp_client_window.cc index fc49e96b..bf58ec5 100644 --- a/remoting/host/win/rdp_client_window.cc +++ b/remoting/host/win/rdp_client_window.cc
@@ -131,9 +131,9 @@ DestroyWindow(); } - DCHECK(!client_.get()); - DCHECK(!client_9_.get()); - DCHECK(!client_settings_.get()); + DCHECK(!client_.Get()); + DCHECK(!client_9_.Get()); + DCHECK(!client_settings_.Get()); } bool RdpClientWindow::Connect(const ScreenResolution& resolution) { @@ -234,7 +234,7 @@ } void RdpClientWindow::OnClose() { - if (!client_.get()) { + if (!client_.Get()) { NotifyDisconnected(); return; }
diff --git a/services/device/BUILD.gn b/services/device/BUILD.gn index 3f781a7..1e75403b 100644 --- a/services/device/BUILD.gn +++ b/services/device/BUILD.gn
@@ -29,11 +29,11 @@ "//device/generic_sensor", "//device/sensors", "//device/sensors/public/interfaces", - "//device/vibration:mojo_bindings", "//device/wake_lock", "//services/device/fingerprint", "//services/device/power_monitor", "//services/device/public/cpp:device_features", + "//services/device/public/interfaces", "//services/device/screen_orientation", "//services/device/time_zone_monitor", "//services/service_manager/public/cpp", @@ -49,7 +49,7 @@ } else { deps += [ "//device/battery", - "//device/vibration", + "//services/device/vibration", ] } } @@ -67,7 +67,6 @@ ":test_support", "//base", "//base/test:test_support", - "//device/vibration:mojo_bindings", "//mojo/public/cpp/bindings", "//services/device/power_monitor", "//services/device/public/cpp/power_monitor", @@ -80,14 +79,11 @@ } if (is_android) { - deps += [ - ":device_service_jni_headers", - "//device/vibration/android:vibration_jni_headers", - ] + deps += [ "//services/device/vibration/android:vibration_jni_headers" ] } else { deps += [ "//device/battery", - "//device/vibration", + "//services/device/vibration", ] } } @@ -152,13 +148,13 @@ "//base:base_java", "//device/battery:mojo_bindings_java", "//device/battery/android:battery_monitor_java", - "//device/vibration:mojo_bindings_java", - "//device/vibration/android:vibration_manager_java", "//mojo/android:system_java", "//mojo/public/java:bindings_java", "//mojo/public/java:system_java", + "//services/device/public/interfaces:interfaces_java", "//services/device/screen_orientation:java", "//services/device/time_zone_monitor:java", + "//services/device/vibration/android:vibration_manager_java", "//services/service_manager/public/interfaces:interfaces_java", "//services/service_manager/public/java:service_manager_java", ]
diff --git a/services/device/device_service.cc b/services/device/device_service.cc index 5578cf5..106a29a 100644 --- a/services/device/device_service.cc +++ b/services/device/device_service.cc
@@ -34,7 +34,7 @@ #include "services/device/android/register_jni.h" #include "services/device/screen_orientation/screen_orientation_listener_android.h" #else -#include "device/vibration/vibration_manager_impl.h" +#include "services/device/vibration/vibration_manager_impl.h" #endif namespace device {
diff --git a/services/device/device_service.h b/services/device/device_service.h index cd38c236..952dc64 100644 --- a/services/device/device_service.h +++ b/services/device/device_service.h
@@ -12,13 +12,13 @@ #include "device/sensors/public/interfaces/light.mojom.h" #include "device/sensors/public/interfaces/motion.mojom.h" #include "device/sensors/public/interfaces/orientation.mojom.h" -#include "device/vibration/vibration_manager.mojom.h" #include "device/wake_lock/public/interfaces/wake_lock_context_provider.mojom.h" #include "device/wake_lock/wake_lock_service_context.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/device/public/interfaces/fingerprint.mojom.h" #include "services/device/public/interfaces/power_monitor.mojom.h" #include "services/device/public/interfaces/time_zone_monitor.mojom.h" +#include "services/device/public/interfaces/vibration_manager.mojom.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/interface_factory.h" #include "services/service_manager/public/cpp/interface_provider.h"
diff --git a/services/device/public/interfaces/BUILD.gn b/services/device/public/interfaces/BUILD.gn index 8e9b2503..705dc5d 100644 --- a/services/device/public/interfaces/BUILD.gn +++ b/services/device/public/interfaces/BUILD.gn
@@ -9,6 +9,7 @@ "fingerprint.mojom", "power_monitor.mojom", "time_zone_monitor.mojom", + "vibration_manager.mojom", ] public_deps = [
diff --git a/device/vibration/vibration_manager.mojom b/services/device/public/interfaces/vibration_manager.mojom similarity index 100% rename from device/vibration/vibration_manager.mojom rename to services/device/public/interfaces/vibration_manager.mojom
diff --git a/device/vibration/BUILD.gn b/services/device/vibration/BUILD.gn similarity index 70% rename from device/vibration/BUILD.gn rename to services/device/vibration/BUILD.gn index d9a9913a..737c90e 100644 --- a/device/vibration/BUILD.gn +++ b/services/device/vibration/BUILD.gn
@@ -7,28 +7,25 @@ # On android, VibrationManager mojo interface is implemented directly in Java. if (!is_android) { - component("vibration") { - output_name = "device_vibration" + source_set("vibration") { + visibility = [ + "//services/device:lib", + "//services/device:tests", + ] sources = [ - "vibration_export.h", "vibration_manager_impl.h", "vibration_manager_impl_default.cc", ] - defines = [ "DEVICE_VIBRATION_IMPLEMENTATION" ] + public_deps = [ + "//services/device/public/interfaces", + ] deps = [ - ":mojo_bindings", "//base", "//base/third_party/dynamic_annotations", "//mojo/public/cpp/bindings", ] } } - -mojom("mojo_bindings") { - sources = [ - "vibration_manager.mojom", - ] -}
diff --git a/services/device/vibration/OWNERS b/services/device/vibration/OWNERS new file mode 100644 index 0000000..0834219 --- /dev/null +++ b/services/device/vibration/OWNERS
@@ -0,0 +1,4 @@ +blundell@chromium.org +timvolodine@chromium.org + +# COMPONENT: Blink>Vibration
diff --git a/device/vibration/android/BUILD.gn b/services/device/vibration/android/BUILD.gn similarity index 87% rename from device/vibration/android/BUILD.gn rename to services/device/vibration/android/BUILD.gn index 5b3ae0a..caa084f 100644 --- a/device/vibration/android/BUILD.gn +++ b/services/device/vibration/android/BUILD.gn
@@ -13,14 +13,16 @@ } android_library("vibration_manager_java") { + visibility = [ "//services/device:*" ] + java_files = [ "java/src/org/chromium/device/vibration/VibrationManagerImpl.java" ] deps = [ "//base:base_java", - "//device/vibration:mojo_bindings_java", "//mojo/public/java:bindings_java", "//mojo/public/java:system_java", + "//services/device/public/interfaces:interfaces_java", "//services/service_manager/public/java:service_manager_java", ] }
diff --git a/device/vibration/android/java/src/org/chromium/device/vibration/VibrationManagerImpl.java b/services/device/vibration/android/java/src/org/chromium/device/vibration/VibrationManagerImpl.java similarity index 95% rename from device/vibration/android/java/src/org/chromium/device/vibration/VibrationManagerImpl.java rename to services/device/vibration/android/java/src/org/chromium/device/vibration/VibrationManagerImpl.java index e781f71d..0f23f0f 100644 --- a/device/vibration/android/java/src/org/chromium/device/vibration/VibrationManagerImpl.java +++ b/services/device/vibration/android/java/src/org/chromium/device/vibration/VibrationManagerImpl.java
@@ -8,8 +8,8 @@ import android.content.pm.PackageManager; import android.media.AudioManager; import android.os.Vibrator; -import android.util.Log; +import org.chromium.base.Log; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.device.mojom.VibrationManager; @@ -17,8 +17,8 @@ import org.chromium.services.service_manager.InterfaceFactory; /** - * Android implementation of the vibration manager service defined in - * device/vibration/vibration_manager.mojom. + * Android implementation of the VibrationManager interface defined in + * services/device/public/interfaces/vibration_manager.mojom. */ @JNINamespace("device") public class VibrationManagerImpl implements VibrationManager {
diff --git a/services/device/vibration/vibration_manager_impl.h b/services/device/vibration/vibration_manager_impl.h new file mode 100644 index 0000000..175ffa90 --- /dev/null +++ b/services/device/vibration/vibration_manager_impl.h
@@ -0,0 +1,22 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_DEVICE_VIBRATION_VIBRATION_MANAGER_IMPL_H_ +#define SERVICES_DEVICE_VIBRATION_VIBRATION_MANAGER_IMPL_H_ + +#include "services/device/public/interfaces/vibration_manager.mojom.h" + +namespace device { + +class VibrationManagerImpl { + public: + static void Create(mojo::InterfaceRequest<mojom::VibrationManager> request); + + static int64_t milli_seconds_for_testing_; + static bool cancelled_for_testing_; +}; + +} // namespace device + +#endif // SERVICES_DEVICE_VIBRATION_VIBRATION_MANAGER_IMPL_H_
diff --git a/device/vibration/vibration_manager_impl_default.cc b/services/device/vibration/vibration_manager_impl_default.cc similarity index 94% rename from device/vibration/vibration_manager_impl_default.cc rename to services/device/vibration/vibration_manager_impl_default.cc index c073f69a..60bfd11 100644 --- a/device/vibration/vibration_manager_impl_default.cc +++ b/services/device/vibration/vibration_manager_impl_default.cc
@@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "services/device/vibration/vibration_manager_impl.h" + #include <stdint.h> #include <utility> #include "base/memory/ptr_util.h" -#include "device/vibration/vibration_manager_impl.h" #include "mojo/public/cpp/bindings/strong_binding.h" namespace device {
diff --git a/services/device/vibration/vibration_manager_impl_unittest.cc b/services/device/vibration/vibration_manager_impl_unittest.cc index d54a771c..78039dcc 100644 --- a/services/device/vibration/vibration_manager_impl_unittest.cc +++ b/services/device/vibration/vibration_manager_impl_unittest.cc
@@ -3,15 +3,15 @@ // found in the LICENSE file. #include "base/run_loop.h" -#include "device/vibration/vibration_manager.mojom.h" #include "services/device/device_service_test_base.h" #include "services/device/public/interfaces/constants.mojom.h" +#include "services/device/public/interfaces/vibration_manager.mojom.h" #if defined(OS_ANDROID) #include "base/android/jni_android.h" #include "jni/VibrationManagerImpl_jni.h" #else -#include "device/vibration/vibration_manager_impl.h" +#include "services/device/vibration/vibration_manager_impl.h" #endif namespace device {
diff --git a/services/ui/test_wm/test_wm.cc b/services/ui/test_wm/test_wm.cc index 3fb4269..557fb0e 100644 --- a/services/ui/test_wm/test_wm.cc +++ b/services/ui/test_wm/test_wm.cc
@@ -96,6 +96,7 @@ void SetWindowManagerClient(aura::WindowManagerClient* client) override { window_manager_client_ = client; } + void OnWmConnected() override {} void OnWmSetBounds(aura::Window* window, const gfx::Rect& bounds) override { window->SetBounds(bounds); }
diff --git a/services/ui/ws/window_manager_client_unittest.cc b/services/ui/ws/window_manager_client_unittest.cc index 1f24a88..6b16f73 100644 --- a/services/ui/ws/window_manager_client_unittest.cc +++ b/services/ui/ws/window_manager_client_unittest.cc
@@ -45,6 +45,7 @@ // WindowManagerDelegate: void SetWindowManagerClient(aura::WindowManagerClient* client) override {} + void OnWmConnected() override {} void OnWmSetBounds(aura::Window* window, const gfx::Rect& bounds) override {} bool OnWmSetProperty( aura::Window* window,
diff --git a/services/ui/ws/window_server_test_base.cc b/services/ui/ws/window_server_test_base.cc index 2062520..01dda2d 100644 --- a/services/ui/ws/window_server_test_base.cc +++ b/services/ui/ws/window_server_test_base.cc
@@ -154,6 +154,8 @@ window_manager_client_ = client; } +void WindowServerTestBase::OnWmConnected() {} + void WindowServerTestBase::OnWmSetBounds(aura::Window* window, const gfx::Rect& bounds) { if (!window_manager_delegate_)
diff --git a/services/ui/ws/window_server_test_base.h b/services/ui/ws/window_server_test_base.h index d5b0ec3..5e64a193 100644 --- a/services/ui/ws/window_server_test_base.h +++ b/services/ui/ws/window_server_test_base.h
@@ -90,6 +90,7 @@ // WindowManagerDelegate: void SetWindowManagerClient(aura::WindowManagerClient* client) override; + void OnWmConnected() override; void OnWmSetBounds(aura::Window* window, const gfx::Rect& bounds) override; bool OnWmSetProperty( aura::Window* window,
diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn index e569c844..68537a8 100644 --- a/storage/browser/BUILD.gn +++ b/storage/browser/BUILD.gn
@@ -238,10 +238,14 @@ "database/database_quota_client_unittest.cc", "database/database_util_unittest.cc", "database/databases_table_unittest.cc", + "fileapi/copy_or_move_operation_delegate_unittest.cc", "fileapi/copy_or_move_file_validator_unittest.cc", + "fileapi/dragged_file_util_unittest.cc", "fileapi/external_mount_points_unittest.cc", + "fileapi/file_system_context_unittest.cc", "fileapi/file_system_dir_url_request_job_unittest.cc", "fileapi/file_system_file_stream_reader_unittest.cc", + "fileapi/file_system_operation_impl_unittest.cc", "fileapi/file_system_quota_client_unittest.cc", "fileapi/file_system_url_request_job_unittest.cc", "fileapi/file_system_url_unittest.cc", @@ -252,6 +256,8 @@ "fileapi/local_file_stream_writer_unittest.cc", "fileapi/local_file_util_unittest.cc", "fileapi/native_file_util_unittest.cc", + "fileapi/obfuscated_file_util_unittest.cc", + "fileapi/recursive_operation_delegate_unittest.cc", "fileapi/plugin_private_file_system_backend_unittest.cc", "fileapi/quota/quota_backend_impl_unittest.cc", "fileapi/quota/quota_reservation_manager_unittest.cc", @@ -287,6 +293,12 @@ sources = [ "test/async_file_test_helper.cc", "test/async_file_test_helper.h", + "test/fileapi_test_file_set.cc", + "test/fileapi_test_file_set.h", + "test/mock_file_change_observer.cc", + "test/mock_file_change_observer.h", + "test/mock_file_update_observer.cc", + "test/mock_file_update_observer.h", "test/mock_quota_manager.cc", "test/mock_quota_manager.h", "test/mock_quota_manager_proxy.cc", @@ -295,6 +307,8 @@ "test/mock_special_storage_policy.h", "test/mock_storage_client.cc", "test/mock_storage_client.h", + "test/sandbox_file_system_test_helper.cc", + "test/sandbox_file_system_test_helper.h", "test/test_file_system_backend.cc", "test/test_file_system_backend.h", "test/test_file_system_context.cc",
diff --git a/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc similarity index 99% rename from content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc rename to storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc index 87d9db6..ce836b2 100644 --- a/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc +++ b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
@@ -17,7 +17,6 @@ #include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "base/threading/thread_task_runner_handle.h" -#include "content/test/fileapi_test_file_set.h" #include "storage/browser/fileapi/copy_or_move_file_validator.h" #include "storage/browser/fileapi/copy_or_move_operation_delegate.h" #include "storage/browser/fileapi/file_stream_reader.h" @@ -28,6 +27,7 @@ #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/quota/quota_manager.h" #include "storage/browser/test/async_file_test_helper.h" +#include "storage/browser/test/fileapi_test_file_set.h" #include "storage/browser/test/mock_quota_manager.h" #include "storage/browser/test/mock_quota_manager_proxy.h" #include "storage/browser/test/test_file_system_backend.h"
diff --git a/content/browser/fileapi/dragged_file_util_unittest.cc b/storage/browser/fileapi/dragged_file_util_unittest.cc similarity index 99% rename from content/browser/fileapi/dragged_file_util_unittest.cc rename to storage/browser/fileapi/dragged_file_util_unittest.cc index cc34832..5d53cfc 100644 --- a/content/browser/fileapi/dragged_file_util_unittest.cc +++ b/storage/browser/fileapi/dragged_file_util_unittest.cc
@@ -20,7 +20,6 @@ #include "base/message_loop/message_loop.h" #include "base/time/time.h" #include "build/build_config.h" -#include "content/test/fileapi_test_file_set.h" #include "storage/browser/fileapi/dragged_file_util.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation_context.h" @@ -28,6 +27,7 @@ #include "storage/browser/fileapi/local_file_util.h" #include "storage/browser/fileapi/native_file_util.h" #include "storage/browser/test/async_file_test_helper.h" +#include "storage/browser/test/fileapi_test_file_set.h" #include "storage/browser/test/test_file_system_context.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/browser/fileapi/file_system_context_unittest.cc b/storage/browser/fileapi/file_system_context_unittest.cc similarity index 100% rename from content/browser/fileapi/file_system_context_unittest.cc rename to storage/browser/fileapi/file_system_context_unittest.cc
diff --git a/content/browser/fileapi/file_system_operation_impl_unittest.cc b/storage/browser/fileapi/file_system_operation_impl_unittest.cc similarity index 99% rename from content/browser/fileapi/file_system_operation_impl_unittest.cc rename to storage/browser/fileapi/file_system_operation_impl_unittest.cc index 2db460b..55da6da 100644 --- a/content/browser/fileapi/file_system_operation_impl_unittest.cc +++ b/storage/browser/fileapi/file_system_operation_impl_unittest.cc
@@ -19,9 +19,6 @@ #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" -#include "content/browser/fileapi/mock_file_change_observer.h" -#include "content/browser/fileapi/mock_file_update_observer.h" -#include "content/public/test/sandbox_file_system_test_helper.h" #include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_file_util.h" @@ -31,8 +28,11 @@ #include "storage/browser/quota/quota_manager.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/test/async_file_test_helper.h" +#include "storage/browser/test/mock_file_change_observer.h" +#include "storage/browser/test/mock_file_update_observer.h" #include "storage/browser/test/mock_quota_manager.h" #include "storage/browser/test/mock_quota_manager_proxy.h" +#include "storage/browser/test/sandbox_file_system_test_helper.h" #include "storage/common/fileapi/file_system_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h"
diff --git a/content/browser/fileapi/obfuscated_file_util_unittest.cc b/storage/browser/fileapi/obfuscated_file_util_unittest.cc similarity index 99% rename from content/browser/fileapi/obfuscated_file_util_unittest.cc rename to storage/browser/fileapi/obfuscated_file_util_unittest.cc index 31c99cd..fa6ec78 100644 --- a/content/browser/fileapi/obfuscated_file_util_unittest.cc +++ b/storage/browser/fileapi/obfuscated_file_util_unittest.cc
@@ -21,9 +21,6 @@ #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" -#include "content/browser/fileapi/mock_file_change_observer.h" -#include "content/public/test/sandbox_file_system_test_helper.h" -#include "content/test/fileapi_test_file_set.h" #include "storage/browser/fileapi/external_mount_points.h" #include "storage/browser/fileapi/file_system_backend.h" #include "storage/browser/fileapi/file_system_context.h" @@ -36,7 +33,10 @@ #include "storage/browser/fileapi/sandbox_origin_database.h" #include "storage/browser/quota/quota_manager.h" #include "storage/browser/test/async_file_test_helper.h" +#include "storage/browser/test/fileapi_test_file_set.h" +#include "storage/browser/test/mock_file_change_observer.h" #include "storage/browser/test/mock_special_storage_policy.h" +#include "storage/browser/test/sandbox_file_system_test_helper.h" #include "storage/browser/test/test_file_system_context.h" #include "storage/common/database/database_identifier.h" #include "storage/common/quota/quota_types.h"
diff --git a/content/browser/fileapi/recursive_operation_delegate_unittest.cc b/storage/browser/fileapi/recursive_operation_delegate_unittest.cc similarity index 99% rename from content/browser/fileapi/recursive_operation_delegate_unittest.cc rename to storage/browser/fileapi/recursive_operation_delegate_unittest.cc index 0bd38075..34026337 100644 --- a/content/browser/fileapi/recursive_operation_delegate_unittest.cc +++ b/storage/browser/fileapi/recursive_operation_delegate_unittest.cc
@@ -17,10 +17,10 @@ #include "base/single_thread_task_runner.h" #include "base/test/scoped_task_environment.h" #include "base/threading/thread_task_runner_handle.h" -#include "content/public/test/sandbox_file_system_test_helper.h" #include "storage/browser/fileapi/file_system_file_util.h" #include "storage/browser/fileapi/file_system_operation.h" #include "storage/browser/fileapi/file_system_operation_runner.h" +#include "storage/browser/test/sandbox_file_system_test_helper.h" #include "testing/gtest/include/gtest/gtest.h" using storage::FileSystemContext;
diff --git a/content/test/fileapi_test_file_set.cc b/storage/browser/test/fileapi_test_file_set.cc similarity index 97% rename from content/test/fileapi_test_file_set.cc rename to storage/browser/test/fileapi_test_file_set.cc index f9ad337..7b2b676 100644 --- a/content/test/fileapi_test_file_set.cc +++ b/storage/browser/test/fileapi_test_file_set.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/test/fileapi_test_file_set.h" +#include "storage/browser/test/fileapi_test_file_set.h" #include <stdint.h>
diff --git a/content/test/fileapi_test_file_set.h b/storage/browser/test/fileapi_test_file_set.h similarity index 100% rename from content/test/fileapi_test_file_set.h rename to storage/browser/test/fileapi_test_file_set.h
diff --git a/content/browser/fileapi/mock_file_change_observer.cc b/storage/browser/test/mock_file_change_observer.cc similarity index 95% rename from content/browser/fileapi/mock_file_change_observer.cc rename to storage/browser/test/mock_file_change_observer.cc index 56c3943..81db69e 100644 --- a/content/browser/fileapi/mock_file_change_observer.cc +++ b/storage/browser/test/mock_file_change_observer.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/fileapi/mock_file_change_observer.h" +#include "storage/browser/test/mock_file_change_observer.h" #include "base/threading/thread_task_runner_handle.h"
diff --git a/content/browser/fileapi/mock_file_change_observer.h b/storage/browser/test/mock_file_change_observer.h similarity index 100% rename from content/browser/fileapi/mock_file_change_observer.h rename to storage/browser/test/mock_file_change_observer.h
diff --git a/content/browser/fileapi/mock_file_update_observer.cc b/storage/browser/test/mock_file_update_observer.cc similarity index 94% rename from content/browser/fileapi/mock_file_update_observer.cc rename to storage/browser/test/mock_file_update_observer.cc index 9b8d6110b..91743e7 100644 --- a/content/browser/fileapi/mock_file_update_observer.cc +++ b/storage/browser/test/mock_file_update_observer.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/threading/thread_task_runner_handle.h" -#include "content/browser/fileapi/mock_file_update_observer.h" +#include "storage/browser/test/mock_file_update_observer.h" #include "testing/gtest/include/gtest/gtest.h" namespace storage {
diff --git a/content/browser/fileapi/mock_file_update_observer.h b/storage/browser/test/mock_file_update_observer.h similarity index 100% rename from content/browser/fileapi/mock_file_update_observer.h rename to storage/browser/test/mock_file_update_observer.h
diff --git a/content/public/test/sandbox_file_system_test_helper.cc b/storage/browser/test/sandbox_file_system_test_helper.cc similarity index 98% rename from content/public/test/sandbox_file_system_test_helper.cc rename to storage/browser/test/sandbox_file_system_test_helper.cc index ae23196..f63ccb2 100644 --- a/content/public/test/sandbox_file_system_test_helper.cc +++ b/storage/browser/test/sandbox_file_system_test_helper.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/public/test/sandbox_file_system_test_helper.h" +#include "storage/browser/test/sandbox_file_system_test_helper.h" #include <memory>
diff --git a/content/public/test/sandbox_file_system_test_helper.h b/storage/browser/test/sandbox_file_system_test_helper.h similarity index 100% rename from content/public/test/sandbox_file_system_test_helper.h rename to storage/browser/test/sandbox_file_system_test_helper.h
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json index 1e18c5e..96f62c1 100644 --- a/testing/buildbot/chromium.perf.fyi.json +++ b/testing/buildbot/chromium.perf.fyi.json
@@ -21,7 +21,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -51,7 +51,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -80,7 +80,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -110,7 +110,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -139,7 +139,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build248-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -169,7 +169,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build248-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -198,7 +198,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device4", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -228,7 +228,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device4", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -257,7 +257,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -287,7 +287,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -316,7 +316,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -346,7 +346,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -375,7 +375,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -405,7 +405,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -434,7 +434,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -464,7 +464,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -493,7 +493,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -523,7 +523,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -552,7 +552,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -582,7 +582,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -611,7 +611,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device2", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -641,7 +641,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device2", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -670,7 +670,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -700,7 +700,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -729,7 +729,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -759,7 +759,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -788,7 +788,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -818,7 +818,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -847,7 +847,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -877,7 +877,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -906,7 +906,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -936,7 +936,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -1083,7 +1083,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -1113,7 +1113,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -1142,7 +1142,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build248-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -1172,7 +1172,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build248-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -1201,7 +1201,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -1231,7 +1231,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -1260,7 +1260,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -1290,7 +1290,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -1319,7 +1319,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -1349,7 +1349,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -1378,7 +1378,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -1408,7 +1408,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -1437,7 +1437,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -1467,7 +1467,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -1496,7 +1496,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -1526,7 +1526,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -1555,7 +1555,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -1585,7 +1585,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -1614,7 +1614,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -1644,7 +1644,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -1673,7 +1673,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device2", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -1703,7 +1703,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device2", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -1732,7 +1732,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device2", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -1762,7 +1762,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device2", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -1791,7 +1791,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -1821,7 +1821,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -1850,7 +1850,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -1880,7 +1880,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -1909,7 +1909,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -1939,7 +1939,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -1968,7 +1968,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -1998,7 +1998,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -2027,7 +2027,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -2057,7 +2057,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -2086,7 +2086,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device2", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -2116,7 +2116,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device2", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -2204,7 +2204,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -2234,7 +2234,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -2263,7 +2263,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -2293,7 +2293,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -2322,7 +2322,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -2352,7 +2352,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -2381,7 +2381,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build248-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -2411,7 +2411,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build248-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -2440,7 +2440,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -2470,7 +2470,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -2499,7 +2499,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -2529,7 +2529,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -2558,7 +2558,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -2588,7 +2588,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -2617,7 +2617,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build245-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -2647,7 +2647,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build245-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -2676,7 +2676,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -2706,7 +2706,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -2735,7 +2735,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -2765,7 +2765,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -2853,7 +2853,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -2883,7 +2883,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -2912,7 +2912,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -2942,7 +2942,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -2971,7 +2971,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -3001,7 +3001,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -3089,7 +3089,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -3119,7 +3119,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -3148,7 +3148,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -3178,7 +3178,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -3207,7 +3207,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -3237,7 +3237,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -3266,7 +3266,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -3296,7 +3296,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -3325,7 +3325,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -3355,7 +3355,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -3384,7 +3384,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build245-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -3414,7 +3414,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build245-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -3443,7 +3443,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build245-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -3473,7 +3473,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build245-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -3502,7 +3502,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -3532,7 +3532,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -3561,7 +3561,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -3591,7 +3591,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -3620,7 +3620,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -3650,7 +3650,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -3679,7 +3679,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -3709,7 +3709,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -3738,7 +3738,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -3768,7 +3768,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -3797,7 +3797,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device4", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -3827,7 +3827,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device4", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -3915,7 +3915,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -3945,7 +3945,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -3974,7 +3974,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -4004,7 +4004,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -4033,7 +4033,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -4063,7 +4063,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -4092,7 +4092,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -4122,7 +4122,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -4151,7 +4151,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -4181,7 +4181,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -4210,7 +4210,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -4240,7 +4240,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -4269,7 +4269,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -4299,7 +4299,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -4328,7 +4328,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build248-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -4358,7 +4358,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build248-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -4387,7 +4387,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device2", + "id": "build245-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -4417,7 +4417,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device2", + "id": "build245-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -4446,7 +4446,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -4476,7 +4476,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -4505,7 +4505,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -4535,7 +4535,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -4564,7 +4564,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -4594,7 +4594,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -4623,7 +4623,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device3", + "id": "build245-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -4653,7 +4653,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device3", + "id": "build245-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -4682,7 +4682,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -4712,7 +4712,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -4741,7 +4741,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -4771,7 +4771,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -4800,7 +4800,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -4829,7 +4829,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -4859,7 +4859,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -4888,7 +4888,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -4918,7 +4918,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -4947,7 +4947,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -4977,7 +4977,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -5065,7 +5065,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -5095,7 +5095,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -5124,7 +5124,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -5154,7 +5154,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -5183,7 +5183,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device3", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -5213,7 +5213,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device3", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -5242,7 +5242,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -5272,7 +5272,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -5301,7 +5301,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -5331,7 +5331,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -5360,7 +5360,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -5390,7 +5390,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -5419,7 +5419,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -5449,7 +5449,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -5478,7 +5478,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -5508,7 +5508,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -5537,7 +5537,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -5567,7 +5567,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -5596,7 +5596,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -5626,7 +5626,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -5655,7 +5655,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -5685,7 +5685,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -5714,7 +5714,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -5744,7 +5744,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -5773,7 +5773,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -5803,7 +5803,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -5832,7 +5832,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -5862,7 +5862,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -5891,7 +5891,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -5921,7 +5921,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -5950,7 +5950,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -5980,7 +5980,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -6009,7 +6009,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -6039,7 +6039,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -6068,7 +6068,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -6098,7 +6098,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -6127,7 +6127,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -6157,7 +6157,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -6186,7 +6186,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -6216,7 +6216,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -6245,7 +6245,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -6275,7 +6275,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -6304,7 +6304,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -6334,7 +6334,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -6363,7 +6363,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -6393,7 +6393,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -6422,7 +6422,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -6452,7 +6452,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -6481,7 +6481,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -6511,7 +6511,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -6540,7 +6540,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device1", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -6570,7 +6570,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device1", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -6599,7 +6599,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -6629,7 +6629,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -6658,7 +6658,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -6688,7 +6688,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -6717,7 +6717,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -6747,7 +6747,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -6776,7 +6776,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device2", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -6806,7 +6806,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device2", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -6835,7 +6835,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -6865,7 +6865,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -6894,7 +6894,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -6924,7 +6924,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -6953,7 +6953,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -6983,7 +6983,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build248-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -7012,7 +7012,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -7042,7 +7042,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -7071,7 +7071,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -7101,7 +7101,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -7130,7 +7130,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -7160,7 +7160,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -7189,7 +7189,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -7219,7 +7219,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -7248,7 +7248,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -7278,7 +7278,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -7307,7 +7307,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build245-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -7337,7 +7337,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build245-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -7366,7 +7366,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -7396,7 +7396,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -7425,7 +7425,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -7455,7 +7455,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build248-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -7484,7 +7484,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -7514,7 +7514,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -7543,7 +7543,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -7573,7 +7573,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -7602,7 +7602,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -7632,7 +7632,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -7661,7 +7661,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -7690,7 +7690,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -7720,7 +7720,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -7749,7 +7749,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build245-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -7779,7 +7779,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build245-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -7809,7 +7809,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -7838,7 +7838,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -7868,7 +7868,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -7897,7 +7897,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -7927,7 +7927,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -7956,7 +7956,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -7986,7 +7986,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -8015,7 +8015,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -8045,7 +8045,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -8133,7 +8133,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device2", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -8163,7 +8163,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device2", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -8192,7 +8192,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -8222,7 +8222,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -8251,7 +8251,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -8281,7 +8281,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -8428,7 +8428,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -8458,7 +8458,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -8487,7 +8487,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -8517,7 +8517,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -8546,7 +8546,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device4", + "id": "build245-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -8576,7 +8576,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device4", + "id": "build245-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -8605,7 +8605,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -8635,7 +8635,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -8664,7 +8664,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device1", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -8694,7 +8694,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device1", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -8723,7 +8723,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device1", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -8753,7 +8753,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device1", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -8782,7 +8782,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -8812,7 +8812,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -8841,7 +8841,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build245-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -8871,7 +8871,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build245-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -8900,7 +8900,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -8930,7 +8930,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -8959,7 +8959,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device3", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -8989,7 +8989,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device3", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -9018,7 +9018,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -9048,7 +9048,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device3", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -9077,7 +9077,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -9107,7 +9107,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -9136,7 +9136,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -9166,7 +9166,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -9254,7 +9254,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build245-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -9284,7 +9284,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build245-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -9313,7 +9313,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -9343,7 +9343,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -9372,7 +9372,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -9402,7 +9402,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -9431,7 +9431,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build245-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -9461,7 +9461,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device5", + "id": "build245-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -9490,7 +9490,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -9520,7 +9520,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device7", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -9549,7 +9549,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -9579,7 +9579,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -9608,7 +9608,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device2", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -9638,7 +9638,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device2", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -9667,7 +9667,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -9697,7 +9697,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device1", + "id": "build249-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -9726,7 +9726,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -9756,7 +9756,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device2", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -9785,7 +9785,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device2", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -9815,7 +9815,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device2", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -9844,7 +9844,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -9874,7 +9874,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -9903,7 +9903,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -9933,7 +9933,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -9962,7 +9962,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -9992,7 +9992,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -10021,7 +10021,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -10051,7 +10051,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -10080,7 +10080,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -10110,7 +10110,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -10139,7 +10139,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -10169,7 +10169,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -10198,7 +10198,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -10228,7 +10228,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build249-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -10257,7 +10257,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device4", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -10287,7 +10287,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device4", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -10316,7 +10316,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -10346,7 +10346,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build248-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -10375,7 +10375,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -10405,7 +10405,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -10434,7 +10434,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -10464,7 +10464,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build248-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -10493,7 +10493,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -10523,7 +10523,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -10552,7 +10552,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -10582,7 +10582,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -10611,7 +10611,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -10641,7 +10641,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -10670,7 +10670,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -10700,7 +10700,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -10729,7 +10729,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -10759,7 +10759,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -10788,7 +10788,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -10818,7 +10818,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device5", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -10847,7 +10847,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -10877,7 +10877,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device1", + "id": "build249-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -10906,7 +10906,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device3", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -10936,7 +10936,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device3", + "id": "build249-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -10965,7 +10965,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build245-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -10995,7 +10995,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device6", + "id": "build245-m4--device5", "os": "Android", "pool": "Chrome-perf" } @@ -11024,7 +11024,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -11053,7 +11053,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -11083,7 +11083,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device6", + "id": "build249-m4--device4", "os": "Android", "pool": "Chrome-perf" } @@ -11112,7 +11112,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device4", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -11142,7 +11142,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device4", + "id": "build245-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -11172,7 +11172,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device3", + "id": "build245-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -11201,7 +11201,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -11231,7 +11231,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device4", + "id": "build249-m4--device1", "os": "Android", "pool": "Chrome-perf" } @@ -11260,7 +11260,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -11290,7 +11290,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device7", + "id": "build245-m4--device7", "os": "Android", "pool": "Chrome-perf" } @@ -11378,7 +11378,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build248-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -11408,7 +11408,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device5", + "id": "build248-m4--device2", "os": "Android", "pool": "Chrome-perf" } @@ -11437,7 +11437,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -11467,7 +11467,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build249-m4--device6", + "id": "build248-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -11496,7 +11496,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -11526,7 +11526,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build248-m4--device4", + "id": "build249-m4--device3", "os": "Android", "pool": "Chrome-perf" } @@ -11555,7 +11555,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" } @@ -11585,7 +11585,7 @@ "dimension_sets": [ { "android_devices": "1", - "id": "build245-m4--device7", + "id": "build248-m4--device6", "os": "Android", "pool": "Chrome-perf" }
diff --git a/testing/libfuzzer/fuzzers/skia_color_space_fuzzer.cc b/testing/libfuzzer/fuzzers/skia_color_space_fuzzer.cc index 850f73f4..c53f474 100644 --- a/testing/libfuzzer/fuzzers/skia_color_space_fuzzer.cc +++ b/testing/libfuzzer/fuzzers/skia_color_space_fuzzer.cc
@@ -7,7 +7,6 @@ #include <random> #include "base/logging.h" -#include "base/strings/string_piece.h" #include "testing/libfuzzer/fuzzers/color_space_data.h" #include "third_party/skia/include/core/SkColorSpace.h" #include "third_party/skia/include/core/SkColorSpaceXform.h" @@ -63,8 +62,10 @@ return profiles[hash & 7]; } -inline size_t Hash(const char* data, size_t size) { - return base::StringPieceHash()(base::StringPiece(data, size)); +inline size_t Hash(const char* data, size_t size, size_t hash = ~0) { + for (size_t i = 0; i < size; ++i) + hash = hash * 131 + *data++; + return hash; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 5c5edb7..7244db8f 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1255,9 +1255,6 @@ crbug.com/665577 [ Linux Win ] virtual/threaded/fast/scroll-behavior/smooth-scroll/mousewheel-scroll-interrupted.html [ Pass Failure ] crbug.com/665577 [ Linux Win ] virtual/threaded/fast/scroll-behavior/smooth-scroll/track-scroll.html [ Pass Failure ] -crbug.com/480769 http/tests/inspector/service-workers/service-workers-redundant.html [ Pass Failure ] -crbug.com/480769 virtual/mojo-loading/http/tests/inspector/service-workers/service-workers-redundant.html [ Pass Failure ] - crbug.com/599670 [ Win Linux ] http/tests/inspector/resource-parameters-ipv6.html [ Failure Pass ] crbug.com/599670 [ Win Linux ] virtual/mojo-loading/http/tests/inspector/resource-parameters-ipv6.html [ Failure Pass ] crbug.com/472330 fast/borders/border-image-outset-split-inline-vertical-lr.html [ Failure ] @@ -2659,8 +2656,6 @@ crbug.com/659139 [ Mac ] shapedetection/detection-ImageData.html [ Skip ] crbug.com/659139 [ Mac ] shapedetection/detection-options.html [ Skip ] -crbug.com/685951 css2.1/t040304-c64-uri-00-a-g.html [ Failure Pass ] - # Importing 'fetch' tests from WPT. crbug.com/705490 external/wpt/fetch/api/basic/error-after-response.html [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/le-not-supported.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/le-not-supported.html new file mode 100644 index 0000000..aaf9289c --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/le-not-supported.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../../resources/mojo-helpers.js"></script> +<script src="../../resources/bluetooth/web-bluetooth-test.js"></script> +<script src="../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(t => { + return navigator.bluetooth.test.setLESupported(false) + .then(() => promise_rejects(t, 'NotFoundError', + requestDeviceWithKeyDown({acceptAllDevices: true}))); +}, 'Reject with NotFoundError if bluetooth is not supported.'); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 580995a..0169b6d3 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -132400,7 +132400,7 @@ "support" ], "./README.md": [ - "8b7d5a19ca22280bea4475be804faee03bbe237d", + "a5a62e25369497e37f04f7870b7b470b2eb7f8af", "support" ], "./check_stability.py": [ @@ -176404,11 +176404,11 @@ "support" ], "html/browsers/the-window-object/window-indexed-properties-strict.html": [ - "57a32c2a9c636762b2d77301c9a6258a4773190c", + "ac9d401368b75e00adbdf80ee42dd8dce1e48e13", "testharness" ], "html/browsers/the-window-object/window-indexed-properties.html": [ - "bf31e152c35b33c32366950fa84837fab74a6bec", + "22d5cb06bfc4724d27f565b8ffa2280bf2e8538b", "testharness" ], "html/browsers/the-window-object/window-named-properties-expected.txt": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/README.md b/third_party/WebKit/LayoutTests/external/wpt/README.md index 94e26a2a..7553e10 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/README.md +++ b/third_party/WebKit/LayoutTests/external/wpt/README.md
@@ -257,8 +257,8 @@ [contributing]: https://github.com/w3c/web-platform-tests/blob/master/CONTRIBUTING.md [ircw3org]: https://www.w3.org/wiki/IRC -[ircarchive]: http://krijnhoetmer.nl/irc-logs/testing/ -[mailarchive]: http://lists.w3.org/Archives/Public/public-test-infra/ +[ircarchive]: http://logs.glob.uno/?c=w3%23testing +[mailarchive]: https://lists.w3.org/Archives/Public/public-test-infra/ Documentation =============
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-expected.txt new file mode 100644 index 0000000..f053637 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-expected.txt
@@ -0,0 +1,7 @@ +This is a testharness.js-based test. +PASS Indexed properties of the window object (non-strict mode) +FAIL Indexed properties of the window object (non-strict mode) 1 assert_throws: function "() => Object.defineProperty(window, 0, { value: "bar" })" did not throw +FAIL Indexed properties of the window object (non-strict mode) 2 assert_throws: function "() => Object.defineProperty(window, 1, { value: "bar" })" did not throw +PASS Indexed properties of the window object (non-strict mode) 3 +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-strict.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-strict.html index 610941f..e059b12 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-strict.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties-strict.html
@@ -23,15 +23,24 @@ assert_throws(new TypeError(), function() { window[0] = "foo"; }); + assert_throws(new TypeError(), () => Object.defineProperty(window, 0, { value: "bar" })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 0, { get() { return "baz" } })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 0, { set(v) { return "qux" } })) assert_equals(window[0], document.getElementsByTagName("iframe")[0].contentWindow); + assert_throws(new TypeError(), () => delete window[0]); }); test(function() { "use strict"; assert_throws(new TypeError(), function() { window[1] = "foo"; }); + assert_throws(new TypeError(), () => Object.defineProperty(window, 1, { value: "bar" })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 1, { get() { return "baz" } })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 1, { set(v) { return "qux" } })) assert_equals(window[1], undefined); + assert_equals(Object.getOwnPropertyDescriptor(window, 1), undefined); + assert_equals(delete window[1], true); }); test(function() { "use strict";
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties.html index 9577ab8..17d0eb7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-indexed-properties.html
@@ -19,12 +19,21 @@ }); test(function() { window[0] = "foo"; + assert_throws(new TypeError(), () => Object.defineProperty(window, 0, { value: "bar" })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 0, { get() { return "baz" } })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 0, { set() { return "quz" } })) assert_equals(window[0], document.getElementsByTagName("iframe")[0].contentWindow); + assert_equals(delete window[0], false); }); test(function() { window[1] = "foo"; + assert_throws(new TypeError(), () => Object.defineProperty(window, 1, { value: "bar" })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 1, { get() { return "baz" } })) + assert_throws(new TypeError(), () => Object.defineProperty(window, 1, { set(v) { return "quz" } })) assert_equals(window[1], undefined); + assert_equals(Object.getOwnPropertyDescriptor(window, 1), undefined); + assert_equals(delete window[1], true); }); test(function() { var proto = Window.prototype;
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-redundant-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-redundant-expected.txt index ea8fe199..20423ed 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-redundant-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-redundant-expected.txt
@@ -8,9 +8,11 @@ Sync Unregister Source +changing-worker.php +Received Status -#N installing -12/31/1969, 4:00:00 PM +#N activated and is running +stop Clients Errors 0 @@ -30,8 +32,9 @@ Status #N activated and is running stop -#N installing -12/31/1969, 4:00:00 PM +#N waiting to activate +skipWaiting +Received Clients http://127.0.0.1:8000/inspector/service-workers/service-workers-redundant.html focus @@ -61,13 +64,21 @@ ============================ DevTools frontend is reopened. ==== ServiceWorkersView ==== +http://127.0.0.1:8000/inspector/service-workers/resources/service-worker-redundant-scope/ Update Push Sync Unregister Source +changing-worker.php +Received Status +#N activated and is running +stop Clients Errors +0 +details +clear ============================
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-redundant.html b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-redundant.html index 092bdbf..979acbe9 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-redundant.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-redundant.html
@@ -27,6 +27,7 @@ var step = 0; var firstVersionId = -1; var secondVersionId = -1; + Resources.ServiceWorkersView._noThrottle = true; InspectorTest.evaluateInPage("frontendReopeningCount", function(result) { if (result._description == "0") { @@ -68,11 +69,11 @@ InspectorTest.evaluateInPage("reopenFrontend()"); } } - UI.panels.resources.serviceWorkersTreeElement.select(); + UI.panels.resources._sidebar.serviceWorkersTreeElement.select(); InspectorTest.registerServiceWorker(scriptURL, scope); } else { InspectorTest.addResult("DevTools frontend is reopened."); - UI.panels.resources.serviceWorkersTreeElement.select(); + UI.panels.resources._sidebar.serviceWorkersTreeElement.select(); InspectorTest.addResult("==== ServiceWorkersView ===="); InspectorTest.addResult(InspectorTest.dumpServiceWorkersView([scope])); InspectorTest.addResult("============================");
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/local-attachment-background-li-crash.html b/third_party/WebKit/LayoutTests/paint/invalidation/local-attachment-background-li-crash.html new file mode 100644 index 0000000..b621395 --- /dev/null +++ b/third_party/WebKit/LayoutTests/paint/invalidation/local-attachment-background-li-crash.html
@@ -0,0 +1,5 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script>test(function(){});</script> +<li style="background-attachment: local; border-image-source: url(#a); contain: strict"></li>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css2.1/t040304-c64-uri-00-a-g-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css2.1/t040304-c64-uri-00-a-g-expected.png index f157d48a..edd1492 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/css2.1/t040304-c64-uri-00-a-g-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/css2.1/t040304-c64-uri-00-a-g-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css2.1/t040304-c64-uri-00-a-g-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/css2.1/t040304-c64-uri-00-a-g-expected.txt index 1da7120d..95af65f 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/css2.1/t040304-c64-uri-00-a-g-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/css2.1/t040304-c64-uri-00-a-g-expected.txt
@@ -4,14 +4,14 @@ LayoutBlockFlow {HTML} at (0,0) size 800x160 LayoutBlockFlow {BODY} at (8,16) size 784x128 LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 242x19 - text run at (0,0) width 242: "There should be three green lines below." + LayoutText {#text} at (0,0) size 255x19 + text run at (0,0) width 255: "There should be three green lines below." LayoutBlockFlow {P} at (0,36) size 784x20 [color=#FFFFFF] [bgcolor=#FF0000] - LayoutText {#text} at (0,0) size 152x19 - text run at (0,0) width 152: "This line should be green." + LayoutText {#text} at (0,0) size 163x19 + text run at (0,0) width 163: "This line should be green." LayoutBlockFlow {P} at (0,72) size 784x20 [color=#FFFFFF] [bgcolor=#FF0000] - LayoutText {#text} at (0,0) size 152x19 - text run at (0,0) width 152: "This line should be green." + LayoutText {#text} at (0,0) size 163x19 + text run at (0,0) width 163: "This line should be green." LayoutBlockFlow {P} at (0,108) size 784x20 [color=#FFFFFF] [bgcolor=#FF0000] - LayoutText {#text} at (0,0) size 152x19 - text run at (0,0) width 152: "This line should be green." + LayoutText {#text} at (0,0) size 163x19 + text run at (0,0) width 163: "This line should be green."
diff --git a/third_party/WebKit/LayoutTests/platform/win/css2.1/t040304-c64-uri-00-a-g-expected.png b/third_party/WebKit/LayoutTests/platform/win/css2.1/t040304-c64-uri-00-a-g-expected.png index e9b3457..212fc8e 100644 --- a/third_party/WebKit/LayoutTests/platform/win/css2.1/t040304-c64-uri-00-a-g-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/css2.1/t040304-c64-uri-00-a-g-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css2.1/t040304-c64-uri-00-a-g-expected.txt b/third_party/WebKit/LayoutTests/platform/win/css2.1/t040304-c64-uri-00-a-g-expected.txt index 0803253..1da7120d 100644 --- a/third_party/WebKit/LayoutTests/platform/win/css2.1/t040304-c64-uri-00-a-g-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/css2.1/t040304-c64-uri-00-a-g-expected.txt
@@ -1,17 +1,17 @@ layer at (0,0) size 800x600 LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x152 - LayoutBlockFlow {HTML} at (0,0) size 800x152 - LayoutBlockFlow {BODY} at (8,16) size 784x120 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 259x17 - text run at (0,0) width 259: "There should be three green lines below." - LayoutBlockFlow {P} at (0,34) size 784x18 [color=#FFFFFF] [bgcolor=#FF0000] - LayoutText {#text} at (0,0) size 166x17 - text run at (0,0) width 166: "This line should be green." - LayoutBlockFlow {P} at (0,68) size 784x18 [color=#FFFFFF] [bgcolor=#FF0000] - LayoutText {#text} at (0,0) size 166x17 - text run at (0,0) width 166: "This line should be green." - LayoutBlockFlow {P} at (0,102) size 784x18 [color=#FFFFFF] [bgcolor=#FF0000] - LayoutText {#text} at (0,0) size 166x17 - text run at (0,0) width 166: "This line should be green." +layer at (0,0) size 800x160 + LayoutBlockFlow {HTML} at (0,0) size 800x160 + LayoutBlockFlow {BODY} at (8,16) size 784x128 + LayoutBlockFlow {P} at (0,0) size 784x20 + LayoutText {#text} at (0,0) size 242x19 + text run at (0,0) width 242: "There should be three green lines below." + LayoutBlockFlow {P} at (0,36) size 784x20 [color=#FFFFFF] [bgcolor=#FF0000] + LayoutText {#text} at (0,0) size 152x19 + text run at (0,0) width 152: "This line should be green." + LayoutBlockFlow {P} at (0,72) size 784x20 [color=#FFFFFF] [bgcolor=#FF0000] + LayoutText {#text} at (0,0) size 152x19 + text run at (0,0) width 152: "This line should be green." + LayoutBlockFlow {P} at (0,108) size 784x20 [color=#FFFFFF] [bgcolor=#FF0000] + LayoutText {#text} at (0,0) size 152x19 + text run at (0,0) width 152: "This line should be green."
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js b/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js new file mode 100644 index 0000000..d391827 --- /dev/null +++ b/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js
@@ -0,0 +1,60 @@ +(() => { + let mojo_; + + async function loadFakeBluetoothInterfaces() { + if(typeof mojo_ !== 'undefined') { + return mojo_; + } + + if (typeof loadMojoModules === 'undefined') { + throw 'Mojo is required for this API.' + } + + mojo_ = await loadMojoModules('fakeBluetooth', [ + 'mojo/public/js/bindings', + 'device/bluetooth/public/interfaces/test/fake_bluetooth.mojom' + ]); + + [mojo_.bindings, mojo_.FakeBluetooth] = mojo_.modules; + return mojo_; + } + + class FakeBluetooth { + constructor() { + this.fake_bluetooth_ptr_ = undefined; + } + + // Set it to indicate whether the platform supports BLE. For example, + // Windows 7 is a platform that doesn't support Low Energy. On the other + // hand Windows 10 is a platform that does support LE, even if there is no + // Bluetooth radio available. + async setLESupported(available) { + if (typeof available !== 'boolean') throw 'Type Not Supported'; + await (await this.getFakeBluetoothInterface_()).setLESupported(available); + + // TODO(crbug.com/569709): Remove once FakeBluetooth.setLESupported is + // implemented in the browser. + navigator.bluetooth.requestDevice = function() { + return Promise.reject(new DOMException( + 'Bluetooth Low Energy is not supported on this platform.', + 'NotFoundError')); + }; + } + + async getFakeBluetoothInterface_() { + if (typeof this.fake_bluetooth_ptr_ !== 'undefined') { + return this.fake_bluetooth_ptr_; + } + + let mojo = await loadFakeBluetoothInterfaces(); + + this.fake_bluetooth_ptr_ = new mojo.FakeBluetooth.FakeBluetoothPtr( + mojo.interfaces.getInterface( + mojo.FakeBluetooth.FakeBluetooth.name)); + + return this.fake_bluetooth_ptr_; + } + } + + navigator.bluetooth.test = new FakeBluetooth(); +})();
diff --git a/third_party/WebKit/LayoutTests/resources/mojo-helpers.js b/third_party/WebKit/LayoutTests/resources/mojo-helpers.js index 95c1c60f..30ea489 100644 --- a/third_party/WebKit/LayoutTests/resources/mojo-helpers.js +++ b/third_party/WebKit/LayoutTests/resources/mojo-helpers.js
@@ -36,11 +36,8 @@ 'content/public/renderer/connector', 'content/public/renderer/frame_interfaces', 'content/public/renderer/interfaces', - 'content/shell/renderer/layout_test/frame_interface_registry', - 'content/shell/renderer/layout_test/interface_registry', ], - (core, router, support, connector, frameInterfaces, interfaces, - frameInterfaceRegistry, interfaceRegistry) => { + (core, router, support, connector, frameInterfaces, interfaces) => { let tearDown = () => { connector.clearInterfaceOverridesForTesting(); frameInterfaces.clearInterfaceOverridesForTesting(); @@ -56,9 +53,7 @@ support, connector, frameInterfaces, - frameInterfaceRegistry, interfaces, - interfaceRegistry, }; });
diff --git a/third_party/WebKit/LayoutTests/usb/resources/fake-devices.js b/third_party/WebKit/LayoutTests/usb/resources/fake-devices.js index 5a9e280c..975d224 100644 --- a/third_party/WebKit/LayoutTests/usb/resources/fake-devices.js +++ b/third_party/WebKit/LayoutTests/usb/resources/fake-devices.js
@@ -1,125 +1,5 @@ 'use strict'; -function fakeUsbDevices() { - return define('Fake USB Devices', [ - 'device/usb/public/interfaces/device.mojom', - ], device => Promise.resolve([ - { - guid: 'CD9FA048-FC9B-7A71-DBFC-FD44B78D6397', - usb_version_major: 2, - usb_version_minor: 0, - usb_version_subminor: 0, - class_code: 7, - subclass_code: 1, - protocol_code: 2, - vendor_id: 0x18d1, - product_id: 0xf00d, - device_version_major: 1, - device_version_minor: 2, - device_version_subminor: 3, - manufacturer_name: 'Google, Inc.', - product_name: 'The amazing imaginary printer', - serial_number: '4', - active_configuration: 0, - configurations: [ - { - configuration_value: 1, - configuration_name: 'Printer Mode', - interfaces: [ - { - interface_number: 0, - alternates: [ - { - alternate_setting: 0, - class_code: 0xff, - subclass_code: 0x01, - protocol_code: 0x01, - interface_name: 'Control', - endpoints: [ - { - endpoint_number: 1, - direction: device.TransferDirection.INBOUND, - type: device.EndpointType.INTERRUPT, - packet_size: 8 - } - ] - } - ] - }, - { - interface_number: 1, - alternates: [ - { - alternate_setting: 0, - class_code: 0xff, - subclass_code: 0x02, - protocol_code: 0x01, - interface_name: 'Data', - endpoints: [ - { - endpoint_number: 2, - direction: device.TransferDirection.INBOUND, - type: device.EndpointType.BULK, - packet_size: 1024 - }, - { - endpoint_number: 2, - direction: device.TransferDirection.OUTBOUND, - type: device.EndpointType.BULK, - packet_size: 1024 - } - ] - } - ] - } - ] - }, - { - configuration_value: 2, - configuration_name: 'Fighting Robot Mode', - interfaces: [ - { - interface_number: 0, - alternates: [ - { - alternate_setting: 0, - class_code: 0xff, - subclass_code: 0x42, - protocol_code: 0x01, - interface_name: 'Disabled', - endpoints: [] - }, - { - alternate_setting: 1, - class_code: 0xff, - subclass_code: 0x42, - protocol_code: 0x01, - interface_name: 'Activate!', - endpoints: [ - { - endpoint_number: 1, - direction: device.TransferDirection.INBOUND, - type: device.EndpointType.ISOCHRONOUS, - packet_size: 1024 - }, - { - endpoint_number: 1, - direction: device.TransferDirection.OUTBOUND, - type: device.EndpointType.ISOCHRONOUS, - packet_size: 1024 - } - ] - } - ] - }, - ] - } - ], - webusb_allowed_origins: { origins: [], configurations: [] }, - } - ])); -} - let fakeDeviceInit = { usbVersionMajor: 2, usbVersionMinor: 0,
diff --git a/third_party/WebKit/LayoutTests/usb/resources/webusb-test.js b/third_party/WebKit/LayoutTests/usb/resources/webusb-test.js index bec6876..112a780 100644 --- a/third_party/WebKit/LayoutTests/usb/resources/webusb-test.js +++ b/third_party/WebKit/LayoutTests/usb/resources/webusb-test.js
@@ -128,21 +128,21 @@ }; switch (endpoint.direction) { case "in": - endpointInfo.direction = mojo.device.TransferDirection.INBOUND; + endpointInfo.direction = mojo.device.UsbTransferDirection.INBOUND; break; case "out": - endpointInfo.direction = mojo.device.TransferDirection.OUTBOUND; + endpointInfo.direction = mojo.device.UsbTransferDirection.OUTBOUND; break; } switch (endpoint.type) { case "bulk": - endpointInfo.type = mojo.device.EndpointType.BULK; + endpointInfo.type = mojo.device.UsbEndpointType.BULK; break; case "interrupt": - endpointInfo.type = mojo.device.EndpointType.INTERRUPT; + endpointInfo.type = mojo.device.UsbEndpointType.INTERRUPT; break; case "isochronous": - endpointInfo.type = mojo.device.EndpointType.ISOCHRONOUS; + endpointInfo.type = mojo.device.UsbEndpointType.ISOCHRONOUS; break; } alternateInfo.endpoints.push(endpointInfo); @@ -201,7 +201,7 @@ open() { assert_false(this.opened_); this.opened_ = true; - return Promise.resolve({ error: mojo.device.OpenDeviceError.OK }); + return Promise.resolve({ error: mojo.device.UsbOpenDeviceError.OK }); } close() { @@ -273,7 +273,7 @@ assert_true(this.opened_); assert_false(this.currentConfiguration_ == null, 'device configured'); return Promise.resolve({ - status: mojo.device.TransferStatus.OK, + status: mojo.device.UsbTransferStatus.OK, data: [length >> 8, length & 0xff, params.request, params.value >> 8, params.value & 0xff, params.index >> 8, params.index & 0xff] }); @@ -283,7 +283,7 @@ assert_true(this.opened_); assert_false(this.currentConfiguration_ == null, 'device configured'); return Promise.resolve({ - status: mojo.device.TransferStatus.OK, + status: mojo.device.UsbTransferStatus.OK, bytesWritten: data.byteLength }); } @@ -296,7 +296,7 @@ for (let i = 0; i < length; ++i) data[i] = i & 0xff; return Promise.resolve({ - status: mojo.device.TransferStatus.OK, + status: mojo.device.UsbTransferStatus.OK, data: data }); } @@ -306,7 +306,7 @@ assert_false(this.currentConfiguration_ == null, 'device configured'); // TODO(reillyg): Assert that endpoint is valid. return Promise.resolve({ - status: mojo.device.TransferStatus.OK, + status: mojo.device.UsbTransferStatus.OK, bytesWritten: data.byteLength }); } @@ -324,7 +324,7 @@ packets[i] = { length: packetLengths[i], transferred_length: packetLengths[i], - status: mojo.device.TransferStatus.OK + status: mojo.device.UsbTransferStatus.OK }; } return Promise.resolve({ data: data, packets: packets }); @@ -339,7 +339,7 @@ packets[i] = { length: packetLengths[i], transferred_length: packetLengths[i], - status: mojo.device.TransferStatus.OK + status: mojo.device.UsbTransferStatus.OK }; } return Promise.resolve({ packets: packets }); @@ -349,7 +349,7 @@ class FakeDeviceManager { constructor() { this.bindingSet_ = - new mojo.bindings.BindingSet(mojo.deviceManager.DeviceManager); + new mojo.bindings.BindingSet(mojo.deviceManager.UsbDeviceManager); this.devices_ = new Map(); this.devicesByGuid_ = new Map(); this.client_ = null; @@ -411,7 +411,7 @@ let device = this.devicesByGuid_.get(guid); if (device) { let binding = new mojo.bindings.Binding( - mojo.device.Device, new FakeDevice(device.info), request); + mojo.device.UsbDevice, new FakeDevice(device.info), request); binding.setConnectionErrorHandler(() => { if (g_closeListener) g_closeListener(device.fakeDevice); @@ -430,7 +430,7 @@ class FakeChooserService { constructor() { this.bindingSet_ = new mojo.bindings.BindingSet( - mojo.chooserService.ChooserService); + mojo.chooserService.UsbChooserService); this.chosenDevice_ = null; this.lastFilters_ = null; } @@ -497,12 +497,12 @@ g_deviceManager = new FakeDeviceManager(); mojo.frameInterfaces.addInterfaceOverrideForTesting( - mojo.deviceManager.DeviceManager.name, + mojo.deviceManager.UsbDeviceManager.name, handle => g_deviceManager.addBinding(handle)); g_chooserService = new FakeChooserService(); mojo.frameInterfaces.addInterfaceOverrideForTesting( - mojo.chooserService.ChooserService.name, + mojo.chooserService.UsbChooserService.name, handle => g_chooserService.addBinding(handle)); addEventListener('unload', () => { @@ -527,10 +527,10 @@ 'content/public/renderer/frame_interfaces' ], frameInterfaces => { frameInterfaces.addInterfaceOverrideForTesting( - mojo.deviceManager.DeviceManager.name, + mojo.deviceManager.UsbDeviceManager.name, handle => g_deviceManager.addBinding(handle)); frameInterfaces.addInterfaceOverrideForTesting( - mojo.chooserService.ChooserService.name, + mojo.chooserService.UsbChooserService.name, handle => g_chooserService.addBinding(handle)); resolve(); });
diff --git a/third_party/WebKit/LayoutTests/vibration/resources/vibration-helpers.js b/third_party/WebKit/LayoutTests/vibration/resources/vibration-helpers.js index ad72e00..2f36ca5c 100644 --- a/third_party/WebKit/LayoutTests/vibration/resources/vibration-helpers.js +++ b/third_party/WebKit/LayoutTests/vibration/resources/vibration-helpers.js
@@ -5,10 +5,10 @@ 'VibrationManager mocks', [ 'mojo/public/js/bindings', - 'device/vibration/vibration_manager.mojom', 'services/device/public/interfaces/constants.mojom', + 'services/device/public/interfaces/vibration_manager.mojom', ], - (bindings, vibrationManager, deviceConstants) => { + (bindings, deviceConstants, vibrationManager) => { class MockVibrationManager { constructor() { this.bindingSet =
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index 7cfac542..f96ccc36 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1185,6 +1185,7 @@ "dom/ExecutionContextTaskTest.cpp", "dom/IdleDeadlineTest.cpp", "dom/LayoutTreeBuilderTraversalTest.cpp", + "dom/MockScriptElementBase.h", "dom/ModulatorTest.cpp", "dom/ModuleMapTest.cpp", "dom/MutationObserverTest.cpp",
diff --git a/third_party/WebKit/Source/core/dom/MockScriptElementBase.h b/third_party/WebKit/Source/core/dom/MockScriptElementBase.h new file mode 100644 index 0000000..f468804 --- /dev/null +++ b/third_party/WebKit/Source/core/dom/MockScriptElementBase.h
@@ -0,0 +1,53 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "bindings/core/v8/HTMLScriptElementOrSVGScriptElement.h" +#include "core/dom/Document.h" +#include "core/dom/ScriptElementBase.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace blink { + +class MockScriptElementBase + : public GarbageCollectedFinalized<MockScriptElementBase>, + public ScriptElementBase { + USING_GARBAGE_COLLECTED_MIXIN(MockScriptElementBase); + + public: + static MockScriptElementBase* Create() { + return new testing::StrictMock<MockScriptElementBase>(); + } + + MOCK_METHOD0(DispatchLoadEvent, void()); + MOCK_METHOD0(DispatchErrorEvent, void()); + MOCK_CONST_METHOD0(AsyncAttributeValue, bool()); + MOCK_CONST_METHOD0(CharsetAttributeValue, String()); + MOCK_CONST_METHOD0(CrossOriginAttributeValue, String()); + MOCK_CONST_METHOD0(DeferAttributeValue, bool()); + MOCK_CONST_METHOD0(EventAttributeValue, String()); + MOCK_CONST_METHOD0(ForAttributeValue, String()); + MOCK_CONST_METHOD0(IntegrityAttributeValue, String()); + MOCK_CONST_METHOD0(LanguageAttributeValue, String()); + MOCK_CONST_METHOD0(SourceAttributeValue, String()); + MOCK_CONST_METHOD0(TypeAttributeValue, String()); + + MOCK_METHOD0(TextFromChildren, String()); + MOCK_CONST_METHOD0(TextContent, String()); + MOCK_CONST_METHOD0(HasSourceAttribute, bool()); + MOCK_CONST_METHOD0(IsConnected, bool()); + MOCK_CONST_METHOD0(HasChildren, bool()); + MOCK_CONST_METHOD0(IsNonceableElement, bool()); + MOCK_CONST_METHOD0(InitiatorName, AtomicString()); + MOCK_METHOD3(AllowInlineScriptForCSP, + bool(const AtomicString&, + const WTF::OrdinalNumber&, + const String&)); + MOCK_CONST_METHOD0(GetDocument, Document&()); + MOCK_METHOD1(SetScriptElementForBinding, + void(HTMLScriptElementOrSVGScriptElement&)); + + DEFINE_INLINE_VIRTUAL_TRACE() { ScriptElementBase::Trace(visitor); } +}; + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp index b7ffc14f..35e2953 100644 --- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp +++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -42,9 +42,9 @@ #include "core/frame/LocalFrame.h" #include "core/frame/SubresourceIntegrity.h" #include "core/frame/csp/ContentSecurityPolicy.h" -#include "core/html/CrossOriginAttribute.h" #include "core/html/imports/HTMLImport.h" #include "core/html/parser/HTMLParserIdioms.h" +#include "core/loader/resource/ScriptResource.h" #include "platform/WebFrameScheduler.h" #include "platform/loader/fetch/AccessControlStatus.h" #include "platform/loader/fetch/FetchParameters.h" @@ -157,10 +157,12 @@ SetHaveFiredLoadEvent(true); } -bool ScriptLoader::IsValidScriptTypeAndLanguage( +namespace { + +bool IsValidClassicScriptTypeAndLanguage( const String& type, const String& language, - LegacyTypeSupport support_legacy_types) { + ScriptLoader::LegacyTypeSupport support_legacy_types) { // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used // here to maintain backwards compatibility with existing layout tests. The // specific violations are: @@ -173,12 +175,10 @@ MIMETypeRegistry::IsSupportedJavaScriptMIMEType("text/" + language) || MIMETypeRegistry::IsLegacySupportedJavaScriptLanguage(language); - } else if (RuntimeEnabledFeatures::moduleScriptsEnabled() && - type == "module") { - return true; } else if (MIMETypeRegistry::IsSupportedJavaScriptMIMEType( type.StripWhiteSpace()) || - (support_legacy_types == kAllowLegacyTypeInTypeAttribute && + (support_legacy_types == + ScriptLoader::kAllowLegacyTypeInTypeAttribute && MIMETypeRegistry::IsLegacySupportedJavaScriptLanguage(type))) { return true; } @@ -186,11 +186,40 @@ return false; } -bool ScriptLoader::IsScriptTypeSupported( - LegacyTypeSupport support_legacy_types) const { +} // namespace + +// Step 6 of https://html.spec.whatwg.org/#prepare-a-script +bool ScriptLoader::IsValidScriptTypeAndLanguage( + const String& type, + const String& language, + LegacyTypeSupport support_legacy_types, + ScriptType& out_script_type) { + if (IsValidClassicScriptTypeAndLanguage(type, language, + support_legacy_types)) { + // - "If the script block's type string is an ASCII case-insensitive match + // for any JavaScript MIME type, the script's type is "classic"." + // TODO(hiroshige): Annotate and/or cleanup this step. + out_script_type = ScriptType::kClassic; + return true; + } + + if (RuntimeEnabledFeatures::moduleScriptsEnabled() && type == "module") { + // - "If the script block's type string is an ASCII case-insensitive match + // for the string "module", the script's type is "module"." + out_script_type = ScriptType::kModule; + return true; + } + + // - "If neither of the above conditions are true, then abort these steps + // at this point. No script is executed." + return false; +} + +bool ScriptLoader::IsScriptTypeSupported(LegacyTypeSupport support_legacy_types, + ScriptType& out_script_type) const { return IsValidScriptTypeAndLanguage(element_->TypeAttributeValue(), element_->LanguageAttributeValue(), - support_legacy_types); + support_legacy_types, out_script_type); } // https://html.spec.whatwg.org/#prepare-a-script @@ -231,9 +260,9 @@ if (!element_->IsConnected()) return false; - // 6. - // TODO(hiroshige): Annotate and/or cleanup this step. - if (!IsScriptTypeSupported(support_legacy_types)) + // 6. "Determine the script's type as follows:" + // |script_type_| is set here. + if (!IsScriptTypeSupported(support_legacy_types, script_type_)) return false; // 7. "If was-parser-inserted is true, @@ -264,36 +293,124 @@ if (!context_document->CanExecuteScripts(kAboutToExecuteScript)) return false; + // 11. "If the script element has a nomodule content attribute + // and the script's type is "classic", then abort these steps. + // The script is not executed." + // TODO(japhet): Implement this step. + // 13. if (!IsScriptForEventSupported()) return false; - // 14. "If the script element has a charset attribute, - // then let encoding be the result of - // getting an encoding from the value of the charset attribute." - // "If the script element does not have a charset attribute, - // or if getting an encoding failed, let encoding - // be the same as the encoding of the script element's node document." - // TODO(hiroshige): Should we handle failure in getting an encoding? - String encoding; - if (!element_->CharsetAttributeValue().IsEmpty()) - encoding = element_->CharsetAttributeValue(); - else - encoding = element_document.characterSet(); + // 14. is handled below. - // Steps 15--20 are handled in fetchScript(). + // 15. "Let CORS setting be the current state of the element's + // crossorigin content attribute." + CrossOriginAttributeValue cross_origin = + GetCrossOriginAttributeValue(element_->CrossOriginAttributeValue()); + + // 16. will be handled below once module script support is implemented. + + // 17. "If the script element has a nonce attribute, + // then let cryptographic nonce be that attribute's value. + // Otherwise, let cryptographic nonce be the empty string." + String nonce; + if (element_->IsNonceableElement()) + nonce = element_->nonce(); + + // 18. is handled below. + + // 19. "Let parser state be "parser-inserted" + // if the script element has been flagged as "parser-inserted", + // and "not parser-inserted" otherwise." + ParserDisposition parser_state = + IsParserInserted() ? kParserInserted : kNotParserInserted; // 21. "If the element has a src content attribute, run these substeps:" if (element_->HasSourceAttribute()) { - FetchParameters::DeferOption defer = FetchParameters::kNoDefer; - if (!parser_inserted_ || element_->AsyncAttributeValue() || - element_->DeferAttributeValue()) - defer = FetchParameters::kLazyLoad; - if (document_write_intervention_ == - DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) - defer = FetchParameters::kIdleLoad; - if (!FetchScript(element_->SourceAttributeValue(), encoding, defer)) + // 21.1. Let src be the value of the element's src attribute. + String src = + StripLeadingAndTrailingHTMLSpaces(element_->SourceAttributeValue()); + + // 21.2. "If src is the empty string, queue a task to + // fire an event named error at the element, and abort these steps." + if (src.IsEmpty()) { + // TODO(hiroshige): Make this asynchronous. Currently we fire the error + // event synchronously to keep the existing behavior. + DispatchErrorEvent(); return false; + } + + // 21.3. "Set the element's from an external file flag." + is_external_script_ = true; + + // 21.4. "Parse src relative to the element's node document." + // TODO(hiroshige): Use CompleteURL(src) instead. + KURL url = element_document.CompleteURL(element_->SourceAttributeValue()); + + // 21.5. "If the previous step failed, queue a task to + // fire an event named error at the element, and abort these steps." + if (!url.IsValid()) { + // TODO(hiroshige): Make this asynchronous. Currently we fire the error + // event synchronously to keep the existing behavior. + DispatchErrorEvent(); + return false; + } + + DCHECK(!resource_); + + // 21.6. "Switch on the script's type:" + // - "classic": + + // 14. "If the script element has a charset attribute, + // then let encoding be the result of + // getting an encoding from the value of the charset attribute." + // "If the script element does not have a charset attribute, + // or if getting an encoding failed, let encoding + // be the same as the encoding of the script element's node + // document." + // TODO(hiroshige): Should we handle failure in getting an encoding? + String encoding; + if (!element_->CharsetAttributeValue().IsEmpty()) + encoding = element_->CharsetAttributeValue(); + else + encoding = element_document.characterSet(); + + // Step 16 is skipped because "module script credentials" is not used + // for classic scripts. + + // 18. "If the script element has an integrity attribute, + // then let integrity metadata be that attribute's value. + // Otherwise, let integrity metadata be the empty string." + String integrity_attr = element_->IntegrityAttributeValue(); + IntegrityMetadataSet integrity_metadata; + if (!integrity_attr.IsEmpty()) { + SubresourceIntegrity::ParseIntegrityAttribute( + integrity_attr, integrity_metadata, &element_document); + } + + if (!FetchClassicScript(url, element_document.Fetcher(), nonce, + integrity_metadata, parser_state, cross_origin, + element_document.GetSecurityOrigin(), encoding)) { + // TODO(hiroshige): Make this asynchronous. Currently we fire the error + // event synchronously to keep the existing behavior. + DispatchErrorEvent(); + return false; + } + + DCHECK(resource_); + + // - "module": + // TODO(hiroshige): Implement this. + + // "When the chosen algorithm asynchronously completes, set + // the script's script to the result. At that time, the script is ready." + // When the script is ready, PendingScriptClient::pendingScriptFinished() + // is used as the notification, and the action to take when + // the script is ready is specified later, in + // - ScriptLoader::PrepareScript(), or + // - HTMLParserScriptRunner, + // depending on the conditions in Step 23 of "prepare a script". } // 22. "If the element does not have a src content attribute, @@ -477,109 +594,63 @@ return true; } -// Steps 15--21 of https://html.spec.whatwg.org/#prepare-a-script -bool ScriptLoader::FetchScript(const String& source_url, - const String& encoding, - FetchParameters::DeferOption defer) { - Document* element_document = &(element_->GetDocument()); - if (!element_->IsConnected() || element_->GetDocument() != element_document) - return false; +bool ScriptLoader::FetchClassicScript( + const KURL& url, + ResourceFetcher* fetcher, + const String& nonce, + const IntegrityMetadataSet& integrity_metadata, + ParserDisposition parser_state, + CrossOriginAttributeValue cross_origin, + SecurityOrigin* security_origin, + const String& encoding) { + // https://html.spec.whatwg.org/#prepare-a-script + // 21.6, "classic": + // "Fetch a classic script given url, settings, ..." + ResourceRequest resource_request(url); - DCHECK(!resource_); - // 21. "If the element has a src content attribute, run these substeps:" - if (!StripLeadingAndTrailingHTMLSpaces(source_url).IsEmpty()) { - // 21.4. "Parse src relative to the element's node document." - ResourceRequest resource_request(element_document->CompleteURL(source_url)); - - // [Intervention] - if (document_write_intervention_ == - DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { - resource_request.SetHTTPHeaderField( - "Intervention", - "<https://www.chromestatus.com/feature/5718547946799104>"); - } - - FetchParameters params(resource_request, element_->InitiatorName()); - - // 15. "Let CORS setting be the current state of the element's - // crossorigin content attribute." - CrossOriginAttributeValue cross_origin = - GetCrossOriginAttributeValue(element_->CrossOriginAttributeValue()); - - // 16. "Let module script credentials mode be determined by switching - // on CORS setting:" - // TODO(hiroshige): Implement this step for "module". - - // 21.6, "classic": "Fetch a classic script given ... CORS setting - // ... and encoding." - if (cross_origin != kCrossOriginAttributeNotSet) { - params.SetCrossOriginAccessControl(element_document->GetSecurityOrigin(), - cross_origin); - } - - params.SetCharset(encoding); - - // 17. "If the script element has a nonce attribute, - // then let cryptographic nonce be that attribute's value. - // Otherwise, let cryptographic nonce be the empty string." - if (element_->IsNonceableElement()) - params.SetContentSecurityPolicyNonce(element_->nonce()); - - // 19. "Let parser state be "parser-inserted" - // if the script element has been flagged as "parser-inserted", - // and "not parser-inserted" otherwise." - params.SetParserDisposition(IsParserInserted() ? kParserInserted - : kNotParserInserted); - - params.SetDefer(defer); - - // 18. "If the script element has an integrity attribute, - // then let integrity metadata be that attribute's value. - // Otherwise, let integrity metadata be the empty string." - String integrity_attr = element_->IntegrityAttributeValue(); - if (!integrity_attr.IsEmpty()) { - IntegrityMetadataSet metadata_set; - SubresourceIntegrity::ParseIntegrityAttribute( - integrity_attr, metadata_set, element_document); - params.SetIntegrityMetadata(metadata_set); - } - - // 21.6. "Switch on the script's type:" - - // - "classic": - // "Fetch a classic script given url, settings, cryptographic nonce, - // integrity metadata, parser state, CORS setting, and encoding." - resource_ = ScriptResource::Fetch(params, element_document->Fetcher()); - - // - "module": - // "Fetch a module script graph given url, settings, "script", - // cryptographic nonce, parser state, and - // module script credentials mode." - // TODO(kouhei, hiroshige): Implement this. - - // "When the chosen algorithm asynchronously completes, set - // the script's script to the result. At that time, the script is ready." - // When the script is ready, PendingScriptClient::pendingScriptFinished() - // is used as the notification, and the action to take when - // the script is ready is specified later, in - // - ScriptLoader::prepareScript(), or - // - HTMLParserScriptRunner, - // depending on the conditions in Step 23 of "prepare a script". - - // 21.3. "Set the element's from an external file flag." - is_external_script_ = true; + // [Intervention] + if (document_write_intervention_ == + DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { + resource_request.SetHTTPHeaderField( + "Intervention", + "<https://www.chromestatus.com/feature/5718547946799104>"); } - if (!resource_) { - // 21.2. "If src is the empty string, queue a task to - // fire an event named error at the element, and abort these steps." - // 21.5. "If the previous step failed, queue a task to - // fire an event named error at the element, and abort these steps." - // TODO(hiroshige): Make this asynchronous. - DispatchErrorEvent(); - return false; + FetchParameters params(resource_request, element_->InitiatorName()); + + // "... cryptographic nonce, ..." + params.SetContentSecurityPolicyNonce(nonce); + + // "... integrity metadata, ..." + params.SetIntegrityMetadata(integrity_metadata); + + // "... parser state, ..." + params.SetParserDisposition(parser_state); + + // "... CORS setting, ..." + if (cross_origin != kCrossOriginAttributeNotSet) { + params.SetCrossOriginAccessControl(security_origin, cross_origin); } + // "... and encoding." + params.SetCharset(encoding); + + // This DeferOption logic is only for classic scripts, as we always set + // |kLazyLoad| for module scripts in ModuleScriptLoader. + FetchParameters::DeferOption defer = FetchParameters::kNoDefer; + if (!parser_inserted_ || element_->AsyncAttributeValue() || + element_->DeferAttributeValue()) + defer = FetchParameters::kLazyLoad; + if (document_write_intervention_ == + DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) + defer = FetchParameters::kIdleLoad; + params.SetDefer(defer); + + resource_ = ScriptResource::Fetch(params, fetcher); + + if (!resource_) + return false; + // [Intervention] if (created_during_document_write_ && resource_->GetResourceRequest().GetCachePolicy() ==
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.h b/third_party/WebKit/Source/core/dom/ScriptLoader.h index 1aa042e..ec3032b 100644 --- a/third_party/WebKit/Source/core/dom/ScriptLoader.h +++ b/third_party/WebKit/Source/core/dom/ScriptLoader.h
@@ -23,18 +23,22 @@ #include "core/CoreExport.h" #include "core/dom/PendingScript.h" +#include "core/dom/Script.h" #include "core/dom/ScriptRunner.h" -#include "core/loader/resource/ScriptResource.h" -#include "platform/loader/fetch/FetchParameters.h" -#include "platform/loader/fetch/ResourceClient.h" +#include "core/html/CrossOriginAttribute.h" +#include "platform/loader/fetch/ResourceLoaderOptions.h" #include "platform/wtf/text/TextPosition.h" #include "platform/wtf/text/WTFString.h" +#include "public/platform/WebURLRequest.h" namespace blink { class ScriptElementBase; class Script; +class ResourceFetcher; +class ScriptResource; + class CORE_EXPORT ScriptLoader : public GarbageCollectedFinalized<ScriptLoader>, public PendingScriptClient { USING_GARBAGE_COLLECTED_MIXIN(ScriptLoader); @@ -58,7 +62,8 @@ static bool IsValidScriptTypeAndLanguage( const String& type_attribute_value, const String& language_attribute_value, - LegacyTypeSupport support_legacy_types); + LegacyTypeSupport support_legacy_types, + ScriptType& out_script_type); // https://html.spec.whatwg.org/#prepare-a-script bool PrepareScript(const TextPosition& script_start_position = @@ -68,7 +73,7 @@ String ScriptContent() const; // Creates a PendingScript for external script whose fetch is started in - // fetchScript(). + // FetchClassicScript(). PendingScript* CreatePendingScript(); // Returns false if and only if execution was blocked. @@ -78,7 +83,8 @@ // XML parser calls these void DispatchLoadEvent(); void DispatchErrorEvent(); - bool IsScriptTypeSupported(LegacyTypeSupport) const; + bool IsScriptTypeSupported(LegacyTypeSupport, + ScriptType& out_script_type) const; bool HaveFiredLoadEvent() const { return have_fired_load_; } bool WillBeParserExecuted() const { return will_be_parser_executed_; } @@ -94,6 +100,7 @@ bool IsParserInserted() const { return parser_inserted_; } bool AlreadyStarted() const { return already_started_; } bool IsNonBlocking() const { return non_blocking_; } + ScriptType GetScriptType() const { return script_type_; } // Helper functions used by our parent classes. void DidNotifySubtreeInsertionsToDocument(); @@ -128,9 +135,20 @@ bool IgnoresLoadRequest() const; bool IsScriptForEventSupported() const; - bool FetchScript(const String& source_url, - const String& encoding, - FetchParameters::DeferOption); + // FetchClassicScript corresponds to Step 21.6 of + // https://html.spec.whatwg.org/#prepare-a-script + // and must NOT be called from outside of PendingScript(). + // + // https://html.spec.whatwg.org/#fetch-a-classic-script + bool FetchClassicScript(const KURL&, + ResourceFetcher*, + const String& nonce, + const IntegrityMetadataSet&, + ParserDisposition, + CrossOriginAttributeValue, + SecurityOrigin*, + const String& encoding); + bool DoExecuteScript(const Script*); // Clears the connection to the PendingScript. @@ -163,7 +181,11 @@ bool ready_to_be_parser_executed_ = false; // https://html.spec.whatwg.org/#concept-script-type - // TODO(hiroshige): Implement "script's type". + // "It is determined when the script is prepared" + // TODO(hiroshige): Currently |script_type_| is set but ignored, and + // thus is handled as if it is a classic script even if type is "module" + // and module scripts is enabled. + ScriptType script_type_ = ScriptType::kClassic; // https://html.spec.whatwg.org/#concept-script-external // "It is determined when the script is prepared"
diff --git a/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp b/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp index 5d48d96..cf6caf0 100644 --- a/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp +++ b/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp
@@ -4,8 +4,7 @@ #include "core/dom/ScriptRunner.h" -#include "bindings/core/v8/HTMLScriptElementOrSVGScriptElement.h" -#include "core/dom/Document.h" +#include "core/dom/MockScriptElementBase.h" #include "core/dom/ScriptLoader.h" #include "platform/heap/Handle.h" #include "platform/testing/TestingPlatformSupport.h" @@ -22,47 +21,6 @@ namespace blink { -class MockScriptElementBase - : public GarbageCollectedFinalized<MockScriptElementBase>, - public ScriptElementBase { - USING_GARBAGE_COLLECTED_MIXIN(MockScriptElementBase); - - public: - static MockScriptElementBase* Create() { - return new testing::StrictMock<MockScriptElementBase>(); - } - - MOCK_METHOD0(DispatchLoadEvent, void()); - MOCK_METHOD0(DispatchErrorEvent, void()); - MOCK_CONST_METHOD0(AsyncAttributeValue, bool()); - MOCK_CONST_METHOD0(CharsetAttributeValue, String()); - MOCK_CONST_METHOD0(CrossOriginAttributeValue, String()); - MOCK_CONST_METHOD0(DeferAttributeValue, bool()); - MOCK_CONST_METHOD0(EventAttributeValue, String()); - MOCK_CONST_METHOD0(ForAttributeValue, String()); - MOCK_CONST_METHOD0(IntegrityAttributeValue, String()); - MOCK_CONST_METHOD0(LanguageAttributeValue, String()); - MOCK_CONST_METHOD0(SourceAttributeValue, String()); - MOCK_CONST_METHOD0(TypeAttributeValue, String()); - - MOCK_METHOD0(TextFromChildren, String()); - MOCK_CONST_METHOD0(TextContent, String()); - MOCK_CONST_METHOD0(HasSourceAttribute, bool()); - MOCK_CONST_METHOD0(IsConnected, bool()); - MOCK_CONST_METHOD0(HasChildren, bool()); - MOCK_CONST_METHOD0(IsNonceableElement, bool()); - MOCK_CONST_METHOD0(InitiatorName, AtomicString()); - MOCK_METHOD3(AllowInlineScriptForCSP, - bool(const AtomicString&, - const WTF::OrdinalNumber&, - const String&)); - MOCK_CONST_METHOD0(GetDocument, Document&()); - MOCK_METHOD1(SetScriptElementForBinding, - void(HTMLScriptElementOrSVGScriptElement&)); - - DEFINE_INLINE_VIRTUAL_TRACE() { ScriptElementBase::Trace(visitor); } -}; - class MockScriptLoader final : public ScriptLoader { public: static MockScriptLoader* Create() { return new MockScriptLoader(); }
diff --git a/third_party/WebKit/Source/core/events/Event.h b/third_party/WebKit/Source/core/events/Event.h index e9929cd..affe81af 100644 --- a/third_party/WebKit/Source/core/events/Event.h +++ b/third_party/WebKit/Source/core/events/Event.h
@@ -81,9 +81,6 @@ static Event* Create() { return new Event; } - // A factory for a simple event. The event doesn't bubble, and isn't - // cancelable. - // http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#fire-a-simple-event static Event* Create(const AtomicString& type) { return new Event(type, false, false); }
diff --git a/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp b/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp index 4834fe7..ce37590 100644 --- a/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp
@@ -104,9 +104,10 @@ Node::InsertionNotificationRequest HTMLScriptElement::InsertedInto( ContainerNode* insertion_point) { + ScriptType script_type = ScriptType::kClassic; if (insertion_point->isConnected() && HasSourceAttribute() && !Loader()->IsScriptTypeSupported( - ScriptLoader::kDisallowLegacyTypeInTypeAttribute)) + ScriptLoader::kDisallowLegacyTypeInTypeAttribute, script_type)) UseCounter::Count(GetDocument(), UseCounter::kScriptElementWithInvalidTypeHasSrc); HTMLElement::InsertedInto(insertion_point);
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp index 05ffc6b4..67f8516 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp
@@ -521,10 +521,11 @@ return ShouldPreloadLink(type); if (Match(tag_impl_, inputTag) && !input_is_image_) return false; + ScriptType script_type = ScriptType::kClassic; if (Match(tag_impl_, scriptTag) && !ScriptLoader::IsValidScriptTypeAndLanguage( type_attribute_value_, language_attribute_value_, - ScriptLoader::kAllowLegacyTypeInTypeAttribute)) { + ScriptLoader::kAllowLegacyTypeInTypeAttribute, script_type)) { return false; } return true;
diff --git a/third_party/WebKit/Source/core/layout/BUILD.gn b/third_party/WebKit/Source/core/layout/BUILD.gn index 45b0320..21e945f5 100644 --- a/third_party/WebKit/Source/core/layout/BUILD.gn +++ b/third_party/WebKit/Source/core/layout/BUILD.gn
@@ -343,6 +343,8 @@ "ng/geometry/ng_static_position.h", "ng/inline/ng_bidi_paragraph.cc", "ng/inline/ng_bidi_paragraph.h", + "ng/inline/ng_inline_box_state.cc", + "ng/inline/ng_inline_box_state.h", "ng/inline/ng_inline_break_token.cc", "ng/inline/ng_inline_break_token.h", "ng/inline/ng_inline_layout_algorithm.cc",
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_box_state.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_box_state.cc new file mode 100644 index 0000000..a6cd187 --- /dev/null +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_box_state.cc
@@ -0,0 +1,173 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/layout/ng/inline/ng_inline_box_state.h" + +#include "core/layout/ng/inline/ng_inline_node.h" +#include "core/layout/ng/inline/ng_line_box_fragment_builder.h" +#include "core/layout/ng/inline/ng_text_fragment_builder.h" +#include "core/style/ComputedStyle.h" + +namespace blink { + +void NGInlineBoxState::ComputeTextMetrics(const NGLayoutInlineItem& item, + FontBaseline baseline_type) { + const ComputedStyle& style = *item.Style(); + text_metrics = NGLineHeightMetrics(style, baseline_type); + text_top = -text_metrics.ascent; + text_metrics.AddLeading(style.ComputedLineHeightAsFixed()); + metrics.Unite(text_metrics); + + include_used_fonts = style.LineHeight().IsNegative(); +} + +NGInlineBoxState* NGInlineLayoutStateStack::OnBeginPlaceItems( + const ComputedStyle* line_style) { + if (stack_.IsEmpty()) { + // For the first line, push a box state for the line itself. + stack_.Resize(1); + NGInlineBoxState* box = &stack_.back(); + box->fragment_start = 0; + box->style = line_style; + return box; + } + + // For the following lines, clear states that are not shared across lines. + for (auto& box : stack_) { + box.fragment_start = 0; + box.metrics = NGLineHeightMetrics(); + DCHECK(box.pending_descendants.IsEmpty()); + } + return &stack_.back(); +} + +NGInlineBoxState* NGInlineLayoutStateStack::OnOpenTag( + const NGLayoutInlineItem& item, + NGLineBoxFragmentBuilder* line_box, + NGTextFragmentBuilder* text_builder) { + stack_.Resize(stack_.size() + 1); + NGInlineBoxState* box = &stack_.back(); + box->fragment_start = line_box->Children().size(); + box->style = item.Style(); + text_builder->SetDirection(box->style->Direction()); + return box; +} + +NGInlineBoxState* NGInlineLayoutStateStack::OnCloseTag( + const NGLayoutInlineItem& item, + NGLineBoxFragmentBuilder* line_box, + NGInlineBoxState* box) { + EndBoxState(box, line_box); + // TODO(kojii): When the algorithm restarts from a break token, the stack may + // underflow. We need either synthesize a missing box state, or push all + // parents on initialize. + stack_.pop_back(); + return &stack_.back(); +} + +void NGInlineLayoutStateStack::OnEndPlaceItems( + NGLineBoxFragmentBuilder* line_box) { + for (auto it = stack_.rbegin(); it != stack_.rend(); ++it) { + NGInlineBoxState* box = &(*it); + EndBoxState(box, line_box); + } + line_box->UniteMetrics(stack_.front().metrics); +} + +void NGInlineLayoutStateStack::EndBoxState(NGInlineBoxState* box, + NGLineBoxFragmentBuilder* line_box) { + ApplyBaselineShift(box, line_box); + + // Unite the metrics to the parent box. + if (box != stack_.begin()) { + box[-1].metrics.Unite(box->metrics); + } +} + +void NGInlineLayoutStateStack::ApplyBaselineShift( + NGInlineBoxState* box, + NGLineBoxFragmentBuilder* line_box) { + // Compute descendants that depend on the layout size of this box if any. + LayoutUnit baseline_shift; + if (!box->pending_descendants.IsEmpty()) { + for (const auto& child : box->pending_descendants) { + switch (child.vertical_align) { + case EVerticalAlign::kTextTop: + case EVerticalAlign::kTop: + baseline_shift = child.metrics.ascent - box->metrics.ascent; + break; + case EVerticalAlign::kTextBottom: + case EVerticalAlign::kBottom: + baseline_shift = box->metrics.descent - child.metrics.descent; + break; + default: + NOTREACHED(); + continue; + } + line_box->MoveChildrenInBlockDirection( + baseline_shift, child.fragment_start, child.fragment_end); + } + box->pending_descendants.Clear(); + } + + const ComputedStyle& style = *box->style; + EVerticalAlign vertical_align = style.VerticalAlign(); + if (vertical_align == EVerticalAlign::kBaseline) + return; + + // 'vertical-align' aplies only to inline-level elements. + if (box == stack_.begin()) + return; + + // Check if there are any fragments to move. + unsigned fragment_end = line_box->Children().size(); + if (box->fragment_start == fragment_end) + return; + + switch (vertical_align) { + case EVerticalAlign::kSub: + baseline_shift = style.ComputedFontSizeAsFixed() / 5 + 1; + break; + case EVerticalAlign::kSuper: + baseline_shift = -(style.ComputedFontSizeAsFixed() / 3 + 1); + break; + case EVerticalAlign::kLength: { + // 'Percentages: refer to the 'line-height' of the element itself'. + // https://www.w3.org/TR/CSS22/visudet.html#propdef-vertical-align + const Length& length = style.GetVerticalAlignLength(); + LayoutUnit line_height = length.IsPercentOrCalc() + ? style.ComputedLineHeightAsFixed() + : box->text_metrics.LineHeight(); + baseline_shift = -ValueForLength(length, line_height); + break; + } + case EVerticalAlign::kMiddle: + baseline_shift = (box->metrics.ascent - box->metrics.descent) / 2; + if (const SimpleFontData* font_data = style.GetFont().PrimaryFont()) { + baseline_shift -= LayoutUnit::FromFloatRound( + font_data->GetFontMetrics().XHeight() / 2); + } + break; + case EVerticalAlign::kBaselineMiddle: + baseline_shift = (box->metrics.ascent - box->metrics.descent) / 2; + break; + case EVerticalAlign::kTop: + case EVerticalAlign::kBottom: + // 'top' and 'bottom' require the layout size of the line box. + stack_.front().pending_descendants.push_back(NGPendingPositions{ + box->fragment_start, fragment_end, box->metrics, vertical_align}); + return; + default: + // Other values require the layout size of the parent box. + SECURITY_CHECK(box != stack_.begin()); + box[-1].pending_descendants.push_back(NGPendingPositions{ + box->fragment_start, fragment_end, box->metrics, vertical_align}); + return; + } + box->metrics.Move(baseline_shift); + line_box->MoveChildrenInBlockDirection(baseline_shift, box->fragment_start, + fragment_end); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_box_state.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_box_state.h new file mode 100644 index 0000000..c09b91e1 --- /dev/null +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_box_state.h
@@ -0,0 +1,87 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NGInlineBoxState_h +#define NGInlineBoxState_h + +#include "core/CoreExport.h" +#include "core/layout/ng/inline/ng_line_height_metrics.h" +#include "core/style/ComputedStyleConstants.h" +#include "platform/LayoutUnit.h" +#include "platform/fonts/FontBaseline.h" +#include "platform/wtf/Vector.h" + +namespace blink { + +class NGLayoutInlineItem; +class NGLineBoxFragmentBuilder; +class NGTextFragmentBuilder; + +// Fragments that require the layout position/size of ancestor are packed in +// this struct. +struct NGPendingPositions { + unsigned fragment_start; + unsigned fragment_end; + NGLineHeightMetrics metrics; + EVerticalAlign vertical_align; +}; + +// Represents the current box while NGInlineLayoutAlgorithm performs layout. +// Used 1) to cache common values for a box, and 2) to layout children that +// require ancestor position or size. +struct NGInlineBoxState { + unsigned fragment_start; + const ComputedStyle* style; + NGLineHeightMetrics metrics; + NGLineHeightMetrics text_metrics; + LayoutUnit text_top; + Vector<NGPendingPositions> pending_descendants; + bool include_used_fonts = false; + + // Compute text metrics for a box. All text in a box share the same metrics. + void ComputeTextMetrics(const NGLayoutInlineItem&, FontBaseline); +}; + +// Represents the inline tree structure. This class provides: +// 1) Allow access to fragments belonging to the current box. +// 2) Performs layout when the positin/size of a box was computed. +// 3) Cache common values for a box. +class NGInlineLayoutStateStack { + public: + // Initialize the box state stack for a new line. + // @return The initial box state for the line. + NGInlineBoxState* OnBeginPlaceItems(const ComputedStyle*); + + // Push a box state stack. + NGInlineBoxState* OnOpenTag(const NGLayoutInlineItem&, + NGLineBoxFragmentBuilder*, + NGTextFragmentBuilder*); + + // Pop a box state stack. + NGInlineBoxState* OnCloseTag(const NGLayoutInlineItem&, + NGLineBoxFragmentBuilder*, + NGInlineBoxState*); + + // Compute all the pending positioning at the end of a line. + void OnEndPlaceItems(NGLineBoxFragmentBuilder*); + + private: + // End of a box state, either explicitly by close tag, or implicitly at the + // end of a line. + void EndBoxState(NGInlineBoxState*, NGLineBoxFragmentBuilder*); + + // Compute vertical position for the 'vertical-align' property. + // The timing to apply varies by values; some values apply at the layout of + // the box was computed. Other values apply when the layout of the parent or + // the line box was computed. + // https://www.w3.org/TR/CSS22/visudet.html#propdef-vertical-align + // https://www.w3.org/TR/css-inline-3/#propdef-vertical-align + void ApplyBaselineShift(NGInlineBoxState*, NGLineBoxFragmentBuilder*); + + Vector<NGInlineBoxState, 4> stack_; +}; + +} // namespace blink + +#endif // NGInlineBoxState_h
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc index d78d6b07..922c983 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -271,6 +271,11 @@ // |last_break_opportunity|. start_index_ = last_break_opportunity_index_; start_offset_ = last_break_opportunity_offset_; + // If the offset is at the end of the item, move to the next item. + if (start_offset_ == items[start_index_].EndOffset() && + start_index_ < items.size() - 1) { + start_index_++; + } DCHECK_GE(end_position_, last_break_opportunity_position_); end_position_ -= last_break_opportunity_position_; last_break_opportunity_position_ = LayoutUnit(); @@ -304,8 +309,9 @@ // runs instead of characters. Vector<UBiDiLevel, 32> levels; levels.ReserveInitialCapacity(line_item_chunks->size()); + const Vector<NGLayoutInlineItem>& items = Node()->Items(); for (const auto& chunk : *line_item_chunks) - levels.push_back(Node()->Items()[chunk.index].BidiLevel()); + levels.push_back(items[chunk.index].BidiLevel()); Vector<int32_t, 32> indices_in_visual_order(line_item_chunks->size()); NGBidiParagraph::IndicesInVisualOrder(levels, &indices_in_visual_order); @@ -318,6 +324,23 @@ line_item_chunks_in_visual_order[visual_index] = (*line_item_chunks)[logical_index]; } + + // Keep Open before Close in the visual order. + HashMap<LayoutObject*, unsigned> first_index; + for (unsigned i = 0; i < line_item_chunks_in_visual_order.size(); i++) { + LineItemChunk& chunk = line_item_chunks_in_visual_order[i]; + const NGLayoutInlineItem& item = items[chunk.index]; + if (item.Type() != NGLayoutInlineItem::kOpenTag && + item.Type() != NGLayoutInlineItem::kCloseTag) { + continue; + } + auto result = first_index.insert(item.GetLayoutObject(), i); + if (!result.is_new_entry && item.Type() == NGLayoutInlineItem::kOpenTag) { + std::swap(line_item_chunks_in_visual_order[i], + line_item_chunks_in_visual_order[result.stored_value->value]); + } + } + line_item_chunks->Swap(line_item_chunks_in_visual_order); } @@ -383,35 +406,29 @@ // Compute heights of all inline items by placing the dominant baseline at 0. // The baseline is adjusted after the height of the line box is computed. NGTextFragmentBuilder text_builder(Node()); + NGInlineBoxState* box = box_states_.OnBeginPlaceItems(&LineStyle()); LayoutUnit inline_size; for (const auto& line_item_chunk : line_item_chunks) { const NGLayoutInlineItem& item = items[line_item_chunk.index]; - // Skip bidi controls. - if (!item.GetLayoutObject()) - continue; - - LayoutUnit block_start; + LayoutUnit line_top; if (item.Type() == NGLayoutInlineItem::kText) { DCHECK(item.GetLayoutObject()->IsText()); - const ComputedStyle* style = item.Style(); - // The direction of a fragment is the CSS direction to resolve logical - // properties, not the resolved bidi direction. - text_builder.SetDirection(style->Direction()) - .SetInlineSize(line_item_chunk.inline_size); - - // |InlineTextBoxPainter| sets the baseline at |top + - // ascent-of-primary-font|. Compute |top| to match. - NGLineHeightMetrics metrics(*style, baseline_type_); - block_start = -metrics.ascent; - metrics.AddLeading(style->ComputedLineHeightAsFixed()); - text_builder.SetBlockSize(metrics.LineHeight()); - line_box.UniteMetrics(metrics); - + if (box->text_metrics.IsEmpty()) + box->ComputeTextMetrics(item, baseline_type_); + line_top = box->text_top; + text_builder.SetSize( + {line_item_chunk.inline_size, box->text_metrics.LineHeight()}); // Take all used fonts into account if 'line-height: normal'. - if (style->LineHeight().IsNegative()) + if (box->include_used_fonts) AccumulateUsedFonts(item, line_item_chunk, &line_box); + } else if (item.Type() == NGLayoutInlineItem::kOpenTag) { + box = box_states_.OnOpenTag(item, &line_box, &text_builder); + continue; + } else if (item.Type() == NGLayoutInlineItem::kCloseTag) { + box = box_states_.OnCloseTag(item, &line_box, box); + continue; } else if (item.Type() == NGLayoutInlineItem::kAtomicInline) { - block_start = PlaceAtomicInline(item, &line_box, &text_builder); + line_top = PlaceAtomicInline(item, &line_box, box, &text_builder); } else if (item.Type() == NGLayoutInlineItem::kOutOfFlowPositioned) { // TODO(layout-dev): Report the correct static position for the out of // flow descendant. We can't do this here yet as it doesn't know the @@ -435,7 +452,7 @@ NGLogicalOffset logical_offset( inline_size + current_opportunity_.InlineStartOffset() - ConstraintSpace().BfcOffset().inline_offset, - block_start); + line_top); line_box.AddChild(std::move(text_fragment), logical_offset); inline_size += line_item_chunk.inline_size; } @@ -444,6 +461,8 @@ return true; // The line was empty. } + box_states_.OnEndPlaceItems(&line_box); + // The baselines are always placed at pixel boundaries. Not doing so results // in incorrect layout of text decorations, most notably underlines. LayoutUnit baseline = content_size_ + line_box.Metrics().ascent; @@ -498,6 +517,7 @@ LayoutUnit NGInlineLayoutAlgorithm::PlaceAtomicInline( const NGLayoutInlineItem& item, NGLineBoxFragmentBuilder* line_box, + NGInlineBoxState* state, NGTextFragmentBuilder* text_builder) { NGBoxFragment fragment( ConstraintSpace().WritingMode(), @@ -508,21 +528,23 @@ // TODO(kojii): Try to eliminate the wrapping text fragment and use the // |fragment| directly. Currently |CopyFragmentDataToLayoutBlockFlow| // requires a text fragment. - text_builder->SetInlineSize(fragment.InlineSize()).SetBlockSize(block_size); + text_builder->SetSize({fragment.InlineSize(), block_size}); // TODO(kojii): Add baseline position to NGPhysicalFragment. - LayoutBox* box = ToLayoutBox(item.GetLayoutObject()); + LayoutBox* layout_box = ToLayoutBox(item.GetLayoutObject()); LineDirectionMode line_direction_mode = IsHorizontalWritingMode() ? LineDirectionMode::kHorizontalLine : LineDirectionMode::kVerticalLine; - LayoutUnit baseline_offset(box->BaselinePosition( + LayoutUnit baseline_offset(layout_box->BaselinePosition( baseline_type_, IsFirstLine(), line_direction_mode)); - line_box->UniteMetrics({baseline_offset, block_size - baseline_offset}); + + NGLineHeightMetrics metrics(baseline_offset, block_size - baseline_offset); + state->metrics.Unite(metrics); // TODO(kojii): Figure out what to do with OOF in NGLayoutResult. // Floats are ok because atomic inlines are BFC? - return -baseline_offset; + return -metrics.ascent; } void NGInlineLayoutAlgorithm::FindNextLayoutOpportunity() {
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.h index e369232d..5639fc9 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.h +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.h
@@ -7,6 +7,7 @@ #include "core/CoreExport.h" #include "core/layout/ng/geometry/ng_logical_offset.h" +#include "core/layout/ng/inline/ng_inline_box_state.h" #include "core/layout/ng/inline/ng_inline_break_token.h" #include "core/layout/ng/inline/ng_line_height_metrics.h" #include "core/layout/ng/ng_constraint_space_builder.h" @@ -135,12 +136,14 @@ NGLineBoxFragmentBuilder*); LayoutUnit PlaceAtomicInline(const NGLayoutInlineItem&, NGLineBoxFragmentBuilder*, + NGInlineBoxState*, NGTextFragmentBuilder*); // Finds the next layout opportunity for the next text fragment. void FindNextLayoutOpportunity(); Vector<RefPtr<NGLayoutResult>, 32> layout_results_; + NGInlineLayoutStateStack box_states_; unsigned start_index_ = 0; unsigned start_offset_ = 0; unsigned last_index_ = 0;
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.h index a2288f0..ce9c9d7f 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.h +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.h
@@ -61,6 +61,7 @@ } Vector<NGLayoutInlineItem>& Items() { return items_; } + const Vector<NGLayoutInlineItem>& Items() const { return items_; } NGLayoutInlineItemRange Items(unsigned start_index, unsigned end_index); void GetLayoutTextOffsets(Vector<unsigned, 32>*);
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_box_fragment_builder.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_box_fragment_builder.cc index 94564fe..baeab067 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_box_fragment_builder.cc +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_box_fragment_builder.cc
@@ -44,6 +44,13 @@ offset.block_offset += delta; } +void NGLineBoxFragmentBuilder::MoveChildrenInBlockDirection(LayoutUnit delta, + unsigned start, + unsigned end) { + for (unsigned index = start; index < end; index++) + offsets_[index].block_offset += delta; +} + void NGLineBoxFragmentBuilder::UniteMetrics( const NGLineHeightMetrics& metrics) { metrics_.Unite(metrics);
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_box_fragment_builder.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_box_fragment_builder.h index 492e0e3..c1e0c89 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_box_fragment_builder.h +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_box_fragment_builder.h
@@ -6,12 +6,12 @@ #define NGLineBoxFragmentBuilder_h #include "core/layout/ng/geometry/ng_logical_offset.h" +#include "core/layout/ng/inline/ng_inline_break_token.h" #include "core/layout/ng/inline/ng_line_height_metrics.h" #include "platform/wtf/Allocator.h" namespace blink { -class NGInlineBreakToken; class NGInlineNode; class NGPhysicalFragment; class NGPhysicalLineBoxFragment; @@ -29,6 +29,7 @@ NGLineBoxFragmentBuilder& AddChild(RefPtr<NGPhysicalFragment>, const NGLogicalOffset&); void MoveChildrenInBlockDirection(LayoutUnit); + void MoveChildrenInBlockDirection(LayoutUnit, unsigned start, unsigned end); const Vector<RefPtr<NGPhysicalFragment>>& Children() const { return children_;
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_height_metrics.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_height_metrics.cc index a3258a0..a6d4c437 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_height_metrics.cc +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_height_metrics.cc
@@ -27,6 +27,7 @@ } void NGLineHeightMetrics::AddLeading(LayoutUnit line_height) { + DCHECK(!IsEmpty()); LayoutUnit half_leading = (line_height - (ascent + descent)) / 2; // TODO(kojii): floor() is to make text dump compatible with legacy test // results. Revisit when we paint. @@ -34,6 +35,12 @@ descent = line_height - ascent; } +void NGLineHeightMetrics::Move(LayoutUnit delta) { + DCHECK(!IsEmpty()); + ascent -= delta; + descent += delta; +} + void NGLineHeightMetrics::Unite(const NGLineHeightMetrics& other) { ascent = std::max(ascent, other.ascent); descent = std::max(descent, other.descent);
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_height_metrics.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_height_metrics.h index 46125ce..8c171a17 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_height_metrics.h +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_height_metrics.h
@@ -19,7 +19,8 @@ // compute metrics for line boxes. // https://drafts.csswg.org/css2/visudet.html#line-height struct NGLineHeightMetrics { - NGLineHeightMetrics() {} + NGLineHeightMetrics() + : ascent(LayoutUnit::Min()), descent(LayoutUnit::Min()) {} NGLineHeightMetrics(LayoutUnit initial_ascent, LayoutUnit initial_descent) : ascent(initial_ascent), descent(initial_descent) {} @@ -30,10 +31,15 @@ // Compute from FontMetrics. The leading is not included. NGLineHeightMetrics(const FontMetrics&, FontBaseline); + bool IsEmpty() const { return ascent == LayoutUnit::Min(); } + // Add the leading. Half the leading is added to ascent and descent each. // https://drafts.csswg.org/css2/visudet.html#leading void AddLeading(LayoutUnit line_height); + // Move the metrics by the specified amount, in line progression direction. + void Move(LayoutUnit); + // Unite a metrics for an inline box to a metrics for a line box. void Unite(const NGLineHeightMetrics&);
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_text_fragment_builder.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_text_fragment_builder.cc index 1abebb4..0e8f6b4 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_text_fragment_builder.cc +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_text_fragment_builder.cc
@@ -20,13 +20,9 @@ return *this; } -NGTextFragmentBuilder& NGTextFragmentBuilder::SetInlineSize(LayoutUnit size) { - size_.inline_size = size; - return *this; -} - -NGTextFragmentBuilder& NGTextFragmentBuilder::SetBlockSize(LayoutUnit size) { - size_.block_size = size; +NGTextFragmentBuilder& NGTextFragmentBuilder::SetSize( + const NGLogicalSize& size) { + size_ = size; return *this; }
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_text_fragment_builder.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_text_fragment_builder.h index 4837398..c88c307e 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_text_fragment_builder.h +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_text_fragment_builder.h
@@ -23,8 +23,7 @@ NGTextFragmentBuilder& SetDirection(TextDirection); - NGTextFragmentBuilder& SetInlineSize(LayoutUnit); - NGTextFragmentBuilder& SetBlockSize(LayoutUnit); + NGTextFragmentBuilder& SetSize(const NGLogicalSize&); void UniteMetrics(const NGLineHeightMetrics&); const NGLineHeightMetrics& Metrics() const { return metrics_; }
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.cpp index a84c91b..c76436d 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.cpp
@@ -234,12 +234,6 @@ return rect; } -LayoutRect LayoutSVGRoot::OverflowClipRect(const LayoutPoint& location, - OverlayScrollbarClipBehavior) const { - return LayoutRect(PixelSnappedIntRect(LayoutReplaced::OverflowClipRect( - location, kIgnorePlatformOverlayScrollbarSize))); -} - void LayoutSVGRoot::PaintReplaced(const PaintInfo& paint_info, const LayoutPoint& paint_offset) const { SVGRootPainter(*this).PaintReplaced(paint_info, paint_offset);
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.h index 60c759e..0cd1777 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.h +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGRoot.h
@@ -88,10 +88,6 @@ } LayoutRect VisualOverflowRect() const override; - LayoutRect OverflowClipRect( - const LayoutPoint& location, - OverlayScrollbarClipBehavior = - kIgnorePlatformOverlayScrollbarSize) const override; bool HasNonIsolatedBlendingDescendants() const final;
diff --git a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp index f3ecacd..7051025 100644 --- a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp +++ b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp
@@ -217,8 +217,9 @@ old_layout_overflow, new_layout_overflow); if (!paints_onto_scrolling_contents_layer) { if (should_fully_invalidate) { - box_.GetMutableForPainting().SetShouldDoFullPaintInvalidation( - kPaintInvalidationLayoutOverflowBoxChange); + box_.GetMutableForPainting() + .SetShouldDoFullPaintInvalidationWithoutGeometryChange( + kPaintInvalidationLayoutOverflowBoxChange); } return; }
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp index b41fdfe..62cd610 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp
@@ -66,14 +66,8 @@ EXPECT_EQ(LayoutRect(FloatRect(8.25, 8.35, 200, 300)), background_rect.Rect()); - if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) { - EXPECT_EQ(LayoutRect(FloatRect(8.25, 8.35, 199.75, 299.66)), - foreground_rect.Rect()); - } else { - // TODO(chrishtr): this is off by 0.25px because - // LayoutSVGRoot::OverflowClipRect incorrectly does pixel-snapping. - EXPECT_EQ(LayoutRect(FloatRect(8, 8, 200, 300)), foreground_rect.Rect()); - } + EXPECT_EQ(LayoutRect(FloatRect(8.25, 8.35, 200, 300)), + foreground_rect.Rect()); EXPECT_EQ(LayoutRect(FloatRect(8.25, 8.35, 200, 300)), layer_bounds); }
diff --git a/third_party/WebKit/Source/devtools/front_end/coverage/CoverageListView.js b/third_party/WebKit/Source/devtools/front_end/coverage/CoverageListView.js index 53aa60b4..a7fe3ff1 100644 --- a/third_party/WebKit/Source/devtools/front_end/coverage/CoverageListView.js +++ b/third_party/WebKit/Source/devtools/front_end/coverage/CoverageListView.js
@@ -213,7 +213,7 @@ var unusedSizeBar = barContainer.createChild('div', 'bar bar-unused-size'); unusedSizeBar.style.width = Math.ceil(100 * this._coverageInfo.unusedSize() / this._maxSize) + '%'; var usedSizeBar = barContainer.createChild('div', 'bar bar-used-size'); - usedSizeBar.style.width = Math.ceil(100 * this._coverageInfo.usedSize() / this._maxSize) + '%'; + usedSizeBar.style.width = Math.floor(100 * this._coverageInfo.usedSize() / this._maxSize) + '%'; } return cell; }
diff --git a/third_party/WebKit/Source/devtools/front_end/help/ReleaseNoteText.js b/third_party/WebKit/Source/devtools/front_end/help/ReleaseNoteText.js index 3681961d..cac4efb 100644 --- a/third_party/WebKit/Source/devtools/front_end/help/ReleaseNoteText.js +++ b/third_party/WebKit/Source/devtools/front_end/help/ReleaseNoteText.js
@@ -38,12 +38,7 @@ title: 'Unified Command Menu', subtitle: 'Execute commands and open files from the newly-unified Command Menu (' + commandMenuShortcut + ').', link: 'https://developers.google.com/web/updates/2017/04/devtools-release-notes#command-menu', - }, - { - title: 'Workspaces 2.0', - subtitle: 'Check out the new UX for using DevTools as your code editor.', - link: 'https://developers.google.com/web/updates/2017/04/devtools-release-notes#workspaces', - }, + } ], link: 'https://developers.google.com/web/updates/2017/04/devtools-release-notes', },
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js index 616ed1b2..3bde351 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/Main.js +++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -105,7 +105,6 @@ Runtime.experiments.register('networkGroupingRequests', 'Network request groups support', true); Runtime.experiments.register('objectPreviews', 'Object previews', true); Runtime.experiments.register('persistence2', 'Persistence 2.0'); - Runtime.experiments.register('persistenceValidation', 'Persistence validation'); Runtime.experiments.register('sourceDiff', 'Source diff'); Runtime.experiments.register('terminalInDrawer', 'Terminal in drawer', true); @@ -138,7 +137,7 @@ Runtime.experiments.enableForTest('liveSASS'); } - Runtime.experiments.setDefaultExperiments(['persistenceValidation', 'persistence2', 'continueToLocationMarkers']); + Runtime.experiments.setDefaultExperiments(['continueToLocationMarkers']); } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/network_group_lookup/NetworkProductGroupLookup.js b/third_party/WebKit/Source/devtools/front_end/network_group_lookup/NetworkProductGroupLookup.js index cdee8495..92302ff 100644 --- a/third_party/WebKit/Source/devtools/front_end/network_group_lookup/NetworkProductGroupLookup.js +++ b/third_party/WebKit/Source/devtools/front_end/network_group_lookup/NetworkProductGroupLookup.js
@@ -127,12 +127,12 @@ if (!request || !element) return; var typeName = ProductRegistry.typeForUrl(request.parsedURL); - if (!typeName) + if (typeName === null) return; var icon = UI.Icon.create('smallicon-network-product'); - if (typeName === 'Tracking') + if (typeName === 1) icon.style.filter = 'hue-rotate(220deg) brightness(1.5)'; - if (typeName === 'CDN') + if (typeName === 2) icon.style.filter = 'hue-rotate(-90deg) brightness(1.5)'; node.setIconForColumn('product-extension', icon); }
diff --git a/third_party/WebKit/Source/devtools/front_end/persistence/Persistence.js b/third_party/WebKit/Source/devtools/front_end/persistence/Persistence.js index a3e76fd..9c0d80b 100644 --- a/third_party/WebKit/Source/devtools/front_end/persistence/Persistence.js +++ b/third_party/WebKit/Source/devtools/front_end/persistence/Persistence.js
@@ -43,7 +43,7 @@ * @param {!Persistence.PersistenceBinding} binding */ _validateBinding(binding) { - if (!Runtime.experiments.isEnabled('persistenceValidation') || binding.network.contentType().isFromSourceMap() || + if (!Runtime.experiments.isEnabled('persistence2') || binding.network.contentType().isFromSourceMap() || !binding.fileSystem.contentType().isTextType()) { this._establishBinding(binding); return;
diff --git a/third_party/WebKit/Source/devtools/front_end/product_registry/ProductNameForURL.js b/third_party/WebKit/Source/devtools/front_end/product_registry/ProductNameForURL.js index 29c6dcd1..271157a 100644 --- a/third_party/WebKit/Source/devtools/front_end/product_registry/ProductNameForURL.js +++ b/third_party/WebKit/Source/devtools/front_end/product_registry/ProductNameForURL.js
@@ -54,7 +54,7 @@ /** * @param {!Common.ParsedURL} parsedUrl - * @return {?string} + * @return {?number} */ ProductRegistry.typeForUrl = function(parsedUrl) { var entry = ProductRegistry.entryForUrl(parsedUrl); @@ -72,28 +72,23 @@ }; /** - * @param {!Array<string>} productTypes * @param {!Array<string>} productNames * @param {!Array<!{hash: string, prefixes: !Object<string, !{product: number, type: (number|undefined)}>}>} data */ -ProductRegistry.register = function(productTypes, productNames, data) { - var typesMap = /** @type {!Map<number, string>} */ (new Map()); - for (var i = 0; i < productTypes.length; i++) - typesMap.set(i, productTypes[i]); - +ProductRegistry.register = function(productNames, data) { for (var i = 0; i < data.length; i++) { var entry = data[i]; var prefixes = {}; for (var prefix in entry.prefixes) { var prefixEntry = entry.prefixes[prefix]; - var type = prefixEntry.type !== undefined ? (typesMap.get(prefixEntry.type) || null) : null; + var type = prefixEntry.type !== undefined ? prefixEntry.type : null; prefixes[prefix] = {name: productNames[prefixEntry.product], type: type}; } ProductRegistry._productsByDomainHash.set(entry.hash, prefixes); } }; -/** @typedef {!{name: string, type: ?string}} */ +/** @typedef {!{name: string, type: ?number}} */ ProductRegistry.ProductEntry; /** @type {!Map<string, !Object<string, !ProductRegistry.ProductEntry>>}} */
diff --git a/third_party/WebKit/Source/devtools/front_end/product_registry/ProductRegistryData.js b/third_party/WebKit/Source/devtools/front_end/product_registry/ProductRegistryData.js index fe780fa..ed6e469 100644 --- a/third_party/WebKit/Source/devtools/front_end/product_registry/ProductRegistryData.js +++ b/third_party/WebKit/Source/devtools/front_end/product_registry/ProductRegistryData.js
@@ -4,8 +4,6 @@ // clang-format off /* eslint-disable */ ProductRegistry.register([ -], -[ "1&1 Internet AG", "A9", "AdGenie", @@ -1501,1393 +1499,1393 @@ "4Info, Inc." ], [ - {"hash":"20d393bb0e5c4de5","prefixes":{"*":{"product":0}}}, // [1&1 Internet AG] - {"hash":"583365b5f9d44cae","prefixes":{"*":{"product":0}}}, // [1&1 Internet AG] - {"hash":"dcde9b6a7ed731d0","prefixes":{"*":{"product":0}}}, // [1&1 Internet AG] - {"hash":"0b618d2d6d12ff65","prefixes":{"*":{"product":0}}}, // [1&1 Internet AG] - {"hash":"5ca7dfe6f0741d1b","prefixes":{"*":{"product":0}}}, // [1&1 Internet AG] - {"hash":"f10aac9be30b9153","prefixes":{"*":{"product":0}}}, // [1&1 Internet AG] - {"hash":"a29e3fb3581debcc","prefixes":{"*":{"product":0}}}, // [1&1 Internet AG] - {"hash":"586a404a027dd51d","prefixes":{"*":{"product":0}}}, // [1&1 Internet AG] - {"hash":"b772cd4d229b926f","prefixes":{"*":{"product":0}}}, // [1&1 Internet AG] - {"hash":"5f153f573d601ed5","prefixes":{"*":{"product":0}}}, // [1&1 Internet AG] - {"hash":"d08d00723aa41a8b","prefixes":{"*":{"product":0}}}, // [1&1 Internet AG] - {"hash":"154c00442038842c","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"bb5191c2744e5157","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"24f8ee8d41010340","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"dde97a25d741083b","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"c40e51f0d4308aef","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"dafae404fe4bf9e0","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"2965d60c41f24692","prefixes":{"*":{"product":2}}}, // [AdGenie] - {"hash":"947df9bf1ccc5af0","prefixes":{"":{"product":3}}}, // [Affilinet GmbH] - {"hash":"5874ab2040fd92e5","prefixes":{"":{"product":3}}}, // [Affilinet GmbH] - {"hash":"12c9a3fc47eec655","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"ff950154b65538b5","prefixes":{"":{"product":5}}}, // [Conversant Ad Server] - {"hash":"cca88c18c3a955c3","prefixes":{"*":{"product":6}}}, // [Napster Luxemburg SARL] - {"hash":"cf583a4f1b85a63d","prefixes":{"*":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"b1f24fb9f4e82bc4","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"7ed3ef3bd9b7964c","prefixes":{"":{"product":8}}}, // [Research Now Limited] - {"hash":"802185637db97f57","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"69ac52e6452dcdcc","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"99d6e276a9f3dce4","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"20cea422f633f132","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"abac0e92b7c09189","prefixes":{"":{"product":12}}}, // [Madeleine Mode GmbH] - {"hash":"ab6d5bcfcb13c98c","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"17c760570121cb8e","prefixes":{"":{"product":14}}}, // [Telefonica UK / O2 UK] - {"hash":"cca991b6ab7e6463","prefixes":{"":{"product":15}}}, // [Tamome] - {"hash":"b24aab8ad8822e3b","prefixes":{"":{"product":15}}}, // [Tamome] - {"hash":"e068190951dbb5ef","prefixes":{"":{"product":15}}}, // [Tamome] - {"hash":"c5a5fd495c44b8e2","prefixes":{"":{"product":15}}}, // [Tamome] - {"hash":"95305154969e81b9","prefixes":{"":{"product":15}}}, // [Tamome] - {"hash":"f40a7549c998fd96","prefixes":{"":{"product":16}}}, // [TUI UK Limited] - {"hash":"96eeaa2c9afb8955","prefixes":{"":{"product":16}}}, // [TUI UK Limited] - {"hash":"bfeca1a08eac1f5e","prefixes":{"*":{"product":17}}}, // [iJento] + {"hash":"20d393bb0e5c4de5","prefixes":{"*":{"product":0,"type":1}}}, // [1&1 Internet AG] + {"hash":"583365b5f9d44cae","prefixes":{"*":{"product":0,"type":1}}}, // [1&1 Internet AG] + {"hash":"dcde9b6a7ed731d0","prefixes":{"*":{"product":0,"type":1}}}, // [1&1 Internet AG] + {"hash":"0b618d2d6d12ff65","prefixes":{"*":{"product":0,"type":1}}}, // [1&1 Internet AG] + {"hash":"5ca7dfe6f0741d1b","prefixes":{"*":{"product":0,"type":1}}}, // [1&1 Internet AG] + {"hash":"f10aac9be30b9153","prefixes":{"*":{"product":0,"type":1}}}, // [1&1 Internet AG] + {"hash":"a29e3fb3581debcc","prefixes":{"*":{"product":0,"type":1}}}, // [1&1 Internet AG] + {"hash":"586a404a027dd51d","prefixes":{"*":{"product":0,"type":1}}}, // [1&1 Internet AG] + {"hash":"b772cd4d229b926f","prefixes":{"*":{"product":0,"type":1}}}, // [1&1 Internet AG] + {"hash":"5f153f573d601ed5","prefixes":{"*":{"product":0,"type":1}}}, // [1&1 Internet AG] + {"hash":"d08d00723aa41a8b","prefixes":{"*":{"product":0,"type":1}}}, // [1&1 Internet AG] + {"hash":"154c00442038842c","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"bb5191c2744e5157","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"24f8ee8d41010340","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"dde97a25d741083b","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"c40e51f0d4308aef","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"dafae404fe4bf9e0","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"2965d60c41f24692","prefixes":{"*":{"product":2,"type":0}}}, // [AdGenie] + {"hash":"947df9bf1ccc5af0","prefixes":{"":{"product":3,"type":1}}}, // [Affilinet GmbH] + {"hash":"5874ab2040fd92e5","prefixes":{"":{"product":3,"type":1}}}, // [Affilinet GmbH] + {"hash":"12c9a3fc47eec655","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"ff950154b65538b5","prefixes":{"":{"product":5,"type":0}}}, // [Conversant Ad Server] + {"hash":"cca88c18c3a955c3","prefixes":{"*":{"product":6,"type":1}}}, // [Napster Luxemburg SARL] + {"hash":"cf583a4f1b85a63d","prefixes":{"*":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"b1f24fb9f4e82bc4","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"7ed3ef3bd9b7964c","prefixes":{"":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"802185637db97f57","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"69ac52e6452dcdcc","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"99d6e276a9f3dce4","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"20cea422f633f132","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"abac0e92b7c09189","prefixes":{"":{"product":12,"type":1}}}, // [Madeleine Mode GmbH] + {"hash":"ab6d5bcfcb13c98c","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"17c760570121cb8e","prefixes":{"":{"product":14,"type":1}}}, // [Telefonica UK / O2 UK] + {"hash":"cca991b6ab7e6463","prefixes":{"":{"product":15,"type":0}}}, // [Tamome] + {"hash":"b24aab8ad8822e3b","prefixes":{"":{"product":15,"type":0}}}, // [Tamome] + {"hash":"e068190951dbb5ef","prefixes":{"":{"product":15,"type":0}}}, // [Tamome] + {"hash":"c5a5fd495c44b8e2","prefixes":{"":{"product":15,"type":0}}}, // [Tamome] + {"hash":"95305154969e81b9","prefixes":{"":{"product":15,"type":0}}}, // [Tamome] + {"hash":"f40a7549c998fd96","prefixes":{"":{"product":16,"type":0}}}, // [TUI UK Limited] + {"hash":"96eeaa2c9afb8955","prefixes":{"":{"product":16,"type":0}}}, // [TUI UK Limited] + {"hash":"bfeca1a08eac1f5e","prefixes":{"*":{"product":17,"type":1}}}, // [iJento] {"hash":"cfbb894fdba5489a","prefixes":{"":{"product":18}}}, // [McCann Erikson] - {"hash":"4ce21296b7adb20d","prefixes":{"":{"product":19}}}, // [Tribes Research Limited] - {"hash":"72b12a834f93bbd1","prefixes":{"":{"product":20}}}, // [On Device Research Ltd.] - {"hash":"5a885783941e6540","prefixes":{"*":{"product":21}}}, // [SuperVista AG] + {"hash":"4ce21296b7adb20d","prefixes":{"":{"product":19,"type":1}}}, // [Tribes Research Limited] + {"hash":"72b12a834f93bbd1","prefixes":{"":{"product":20,"type":1}}}, // [On Device Research Ltd.] + {"hash":"5a885783941e6540","prefixes":{"*":{"product":21,"type":1}}}, // [SuperVista AG] {"hash":"382734d54ddf7100","prefixes":{"":{"product":22}}}, // [National Lottery] - {"hash":"397eccbf74cd0328","prefixes":{"*":{"product":0}}}, // [1&1 Internet AG] - {"hash":"bf0f9d6566d29693","prefixes":{"*":{"product":0}}}, // [1&1 Internet AG] - {"hash":"8fd259996da5f3d8","prefixes":{"":{"product":23}}}, // [AppNexus Open AdStream] - {"hash":"56837fe2597a4f9e","prefixes":{"":{"product":23}}}, // [AppNexus Open AdStream] - {"hash":"fb4ddfafadb387cf","prefixes":{"":{"product":23}}}, // [AppNexus Open AdStream] - {"hash":"07a11d9d007c60f8","prefixes":{"":{"product":23}}}, // [AppNexus Open AdStream] - {"hash":"9f36fc0bb2911046","prefixes":{"":{"product":23}}}, // [AppNexus Open AdStream] - {"hash":"57c7af60819b3f3e","prefixes":{"":{"product":23}}}, // [AppNexus Open AdStream] - {"hash":"c3363b1ccf0e2ab6","prefixes":{"":{"product":24}}}, // [Interworks Media, Inc.] - {"hash":"9d16bd99e929eccd","prefixes":{"":{"product":24}}}, // [Interworks Media, Inc.] - {"hash":"211d3b9ea9bf8f2e","prefixes":{"":{"product":25}}}, // [Action Exchange, Inc.] - {"hash":"414adfe007d3587f","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"4486e584990f9603","prefixes":{"":{"product":26}}}, // [FSN ASIA PRIVATE LIMITED] - {"hash":"8cfb66b1b7bbe43b","prefixes":{"":{"product":27}}}, // [iPromote] - {"hash":"fba2a0cd626a5289","prefixes":{"":{"product":27}}}, // [iPromote] - {"hash":"113620ff3bb3ea60","prefixes":{"":{"product":27}}}, // [iPromote] - {"hash":"b5f6b4570a07977c","prefixes":{"*":{"product":28}}}, // [33Across Inc.] - {"hash":"877f3b2ffe34bf4a","prefixes":{"*":{"product":29}}}, // [8thBridge] - {"hash":"bc5882cc43d24a0b","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"5506a3935677620c","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"4a8f0380d8c0ee22","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"54e1d163948509ad","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"534e3733e4e5309d","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"c7db8e0e25c7df2d","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"222afdeb29be30ca","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"a082f434d9ec1f91","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"e00092cf7fb8c74a","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"6b3557e54073f90d","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"b825724682d4bd41","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"62a0c6b3cd3ed567","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"7e5f80275a654f93","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"426c5ded1145b847","prefixes":{"*":{"product":1}}}, // [A9] - {"hash":"14f8bb92c4036403","prefixes":{"*":{"product":1}}}, // [A9] - {"hash":"8aaada51ee8ebb86","prefixes":{"*":{"product":1}}}, // [A9] - {"hash":"38eac8937b706b6f","prefixes":{"*":{"product":1}}}, // [A9] - {"hash":"7e1d4edc3530e448","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"c0bf2b011199054e","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"b4dd68c5d9b68922","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"8d943586f8f86d04","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"f60b51325cdf4f80","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"080dea15fa602a8c","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"a01c9f1f745acb3b","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"eae49b84950db230","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"dabd2bc95093ab29","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"8912c7bdde481292","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"c735e4adfc754475","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"297bba8cd045b252","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"b4ee04e1cb1b0cb0","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"1f9925b611b3db5e","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"e63f21a01153ba8c","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"5df92c4776ddb318","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"995e4fe402d230d4","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"f27bb2795a31311c","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"7ef41a846501bb38","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"f69c9d0a6726d8a2","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"fbe82cac507c4685","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"b30108dc4fef7d3d","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"3db91f22497fff29","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"8c93f288d1c9adaa","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"dd3abfa7756f945e","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"562f4260ff4f65a6","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"94d8ddce749b5392","prefixes":{"*":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"031269afdaee38ca","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"0c0ba1aaf374eac4","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"cb1dbab4bb9d139b","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"144dac73c5669441","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"b6b232e5fbf868f0","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"3c15562b6abc1319","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"722c811d70136506","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"78a792effa9e4967","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"a59637a7ca9dc579","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"6b3ce5ea793ecbbf","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"2b5bd0c505a178d0","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"c41cefa39852e538","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"e572b55cf0c6834b","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"80d0b8e46094b1c9","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"343036881041aa23","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"2559ed3163479794","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"95acf3d42f565375","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"a3fe80607786880e","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"b7629e7fab881e7a","prefixes":{"":{"product":31}}}, // [Retailigence] - {"hash":"03ec1a841574bd4d","prefixes":{"":{"product":32}}}, // [Logly DSP] - {"hash":"7ff5ce1768464e16","prefixes":{"":{"product":32}}}, // [Logly DSP] + {"hash":"397eccbf74cd0328","prefixes":{"*":{"product":0,"type":1}}}, // [1&1 Internet AG] + {"hash":"bf0f9d6566d29693","prefixes":{"*":{"product":0,"type":1}}}, // [1&1 Internet AG] + {"hash":"8fd259996da5f3d8","prefixes":{"":{"product":23,"type":0}}}, // [AppNexus Open AdStream] + {"hash":"56837fe2597a4f9e","prefixes":{"":{"product":23,"type":0}}}, // [AppNexus Open AdStream] + {"hash":"fb4ddfafadb387cf","prefixes":{"":{"product":23,"type":0}}}, // [AppNexus Open AdStream] + {"hash":"07a11d9d007c60f8","prefixes":{"":{"product":23,"type":0}}}, // [AppNexus Open AdStream] + {"hash":"9f36fc0bb2911046","prefixes":{"":{"product":23,"type":0}}}, // [AppNexus Open AdStream] + {"hash":"57c7af60819b3f3e","prefixes":{"":{"product":23,"type":0}}}, // [AppNexus Open AdStream] + {"hash":"c3363b1ccf0e2ab6","prefixes":{"":{"product":24,"type":0}}}, // [Interworks Media, Inc.] + {"hash":"9d16bd99e929eccd","prefixes":{"":{"product":24,"type":0}}}, // [Interworks Media, Inc.] + {"hash":"211d3b9ea9bf8f2e","prefixes":{"":{"product":25,"type":0}}}, // [Action Exchange, Inc.] + {"hash":"414adfe007d3587f","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"4486e584990f9603","prefixes":{"":{"product":26,"type":0}}}, // [FSN ASIA PRIVATE LIMITED] + {"hash":"8cfb66b1b7bbe43b","prefixes":{"":{"product":27,"type":0}}}, // [iPromote] + {"hash":"fba2a0cd626a5289","prefixes":{"":{"product":27,"type":0}}}, // [iPromote] + {"hash":"113620ff3bb3ea60","prefixes":{"":{"product":27,"type":0}}}, // [iPromote] + {"hash":"b5f6b4570a07977c","prefixes":{"*":{"product":28,"type":0}}}, // [33Across Inc.] + {"hash":"877f3b2ffe34bf4a","prefixes":{"*":{"product":29,"type":0}}}, // [8thBridge] + {"hash":"bc5882cc43d24a0b","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"5506a3935677620c","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"4a8f0380d8c0ee22","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"54e1d163948509ad","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"534e3733e4e5309d","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"c7db8e0e25c7df2d","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"222afdeb29be30ca","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"a082f434d9ec1f91","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"e00092cf7fb8c74a","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"6b3557e54073f90d","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"b825724682d4bd41","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"62a0c6b3cd3ed567","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"7e5f80275a654f93","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"426c5ded1145b847","prefixes":{"*":{"product":1,"type":0}}}, // [A9] + {"hash":"14f8bb92c4036403","prefixes":{"*":{"product":1,"type":0}}}, // [A9] + {"hash":"8aaada51ee8ebb86","prefixes":{"*":{"product":1,"type":0}}}, // [A9] + {"hash":"38eac8937b706b6f","prefixes":{"*":{"product":1,"type":0}}}, // [A9] + {"hash":"7e1d4edc3530e448","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"c0bf2b011199054e","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"b4dd68c5d9b68922","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"8d943586f8f86d04","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"f60b51325cdf4f80","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"080dea15fa602a8c","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"a01c9f1f745acb3b","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"eae49b84950db230","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"dabd2bc95093ab29","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"8912c7bdde481292","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"c735e4adfc754475","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"297bba8cd045b252","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"b4ee04e1cb1b0cb0","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"1f9925b611b3db5e","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"e63f21a01153ba8c","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"5df92c4776ddb318","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"995e4fe402d230d4","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"f27bb2795a31311c","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"7ef41a846501bb38","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"f69c9d0a6726d8a2","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"fbe82cac507c4685","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"b30108dc4fef7d3d","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"3db91f22497fff29","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"8c93f288d1c9adaa","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"dd3abfa7756f945e","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"562f4260ff4f65a6","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"94d8ddce749b5392","prefixes":{"*":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"031269afdaee38ca","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"0c0ba1aaf374eac4","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"cb1dbab4bb9d139b","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"144dac73c5669441","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"b6b232e5fbf868f0","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"3c15562b6abc1319","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"722c811d70136506","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"78a792effa9e4967","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"a59637a7ca9dc579","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"6b3ce5ea793ecbbf","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"2b5bd0c505a178d0","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"c41cefa39852e538","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"e572b55cf0c6834b","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"80d0b8e46094b1c9","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"343036881041aa23","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"2559ed3163479794","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"95acf3d42f565375","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"a3fe80607786880e","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"b7629e7fab881e7a","prefixes":{"":{"product":31,"type":0}}}, // [Retailigence] + {"hash":"03ec1a841574bd4d","prefixes":{"":{"product":32,"type":0}}}, // [Logly DSP] + {"hash":"7ff5ce1768464e16","prefixes":{"":{"product":32,"type":0}}}, // [Logly DSP] {"hash":"10fb9dcb49e1abe6","prefixes":{"":{"product":33}}}, // [App-CM Inc.] {"hash":"6d3713ad37a0966c","prefixes":{"":{"product":33}}}, // [App-CM Inc.] {"hash":"41670ff004a04f19","prefixes":{"":{"product":33}}}, // [App-CM Inc.] - {"hash":"cd681b4891935464","prefixes":{"":{"product":34}}}, // [Yahoo! Japan Corporation] - {"hash":"b97383320b594f18","prefixes":{"":{"product":34}}}, // [Yahoo! Japan Corporation] - {"hash":"e2fff6e598b3035e","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"cb3ceda4f0c38995","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"a218e065250d793c","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"deb1ce911dfb392b","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"de5ead15f1d0f171","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"92615d394883ce3c","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"6cd842b12d20b208","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"dc6acfacad6c1026","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"81aa25ff76990996","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"1254067a80cf3d7b","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"31e2549e82b92770","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"be41bb940608434e","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"05a4ab4a11bd1fbf","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"05677aca712e9b65","prefixes":{"":{"product":1}}}, // [A9] - {"hash":"00620801050945d1","prefixes":{"":{"product":35}}}, // [Oggifinogi] - {"hash":"c0ceae7cfc4144c6","prefixes":{"":{"product":36}}}, // [PaperG] - {"hash":"996c3990310cfc19","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"14210f0f0a8d71cb","prefixes":{"":{"product":38}}}, // [The Trade Desk Inc.] - {"hash":"0f07ec261c73a8fb","prefixes":{"*":{"product":39},"":{"product":40}}}, // [Amazon] [F# Inc.] - {"hash":"736b87f504b5e113","prefixes":{"":{"product":41}}}, // [Airpush, Inc.] - {"hash":"0bcef81372eadfe9","prefixes":{"":{"product":42}}}, // [Clinch.co] - {"hash":"9ea6769e672968e9","prefixes":{"":{"product":40}}}, // [F# Inc.] - {"hash":"0fde612c20c42c6f","prefixes":{"":{"product":43}}}, // [Transout Inc.] - {"hash":"5ed995763ce85029","prefixes":{"":{"product":44}}}, // [ADZIP] - {"hash":"497082972c1c0dfd","prefixes":{"":{"product":45}}}, // [Adways SAS] - {"hash":"6d7e4a203b969d9e","prefixes":{"":{"product":46}}}, // [Opera Mediaworks Inc.] - {"hash":"d3a9057528c14a56","prefixes":{"":{"product":47}}}, // [DistroScale Inc.] - {"hash":"479d2f8d9b7a2efe","prefixes":{"":{"product":48}}}, // [Enzymic Consultancy] - {"hash":"6f7f9fb0065f745f","prefixes":{"":{"product":48}}}, // [Enzymic Consultancy] - {"hash":"893d967f4540bb44","prefixes":{"":{"product":49}}}, // [Fluct Inc.] - {"hash":"3830f0b6ca460fe9","prefixes":{"*":{"product":50}}}, // [Acuity Ads] - {"hash":"e917237ee7b0ad79","prefixes":{"":{"product":50}}}, // [Acuity Ads] - {"hash":"e0792ffd5eca94d8","prefixes":{"":{"product":50}}}, // [Acuity Ads] - {"hash":"29beee316a393584","prefixes":{"":{"product":50}}}, // [Acuity Ads] - {"hash":"ce9e7bf17bba4aae","prefixes":{"":{"product":50}}}, // [Acuity Ads] - {"hash":"fcf604f90166bb66","prefixes":{"":{"product":50}}}, // [Acuity Ads] - {"hash":"f11d9059950b4a07","prefixes":{"":{"product":50}}}, // [Acuity Ads] - {"hash":"7d142a85f84f3402","prefixes":{"":{"product":50}}}, // [Acuity Ads] - {"hash":"83c0bb224cb5622f","prefixes":{"*":{"product":51}}}, // [iLead] - {"hash":"27841e5ac1581a67","prefixes":{"":{"product":52}}}, // [Canned Banners LLC] - {"hash":"83fbdce4f2519684","prefixes":{"":{"product":52}}}, // [Canned Banners LLC] - {"hash":"db7bac94f2b2d2b7","prefixes":{"":{"product":53}}}, // [AdBroker GmbH] - {"hash":"e0de5430253205fc","prefixes":{"":{"product":53}}}, // [AdBroker GmbH] - {"hash":"bde57b6011499edf","prefixes":{"":{"product":53}}}, // [AdBroker GmbH] - {"hash":"077ad042e29c79fb","prefixes":{"":{"product":53}}}, // [AdBroker GmbH] - {"hash":"d3c6fc5ff77f0d5c","prefixes":{"":{"product":53}}}, // [AdBroker GmbH] - {"hash":"b88fb01ba215894e","prefixes":{"*":{"product":54}}}, // [InMind Opinion Media] - {"hash":"3d509f557aeca6de","prefixes":{"*":{"product":55}}}, // [Adcentric] - {"hash":"3a9959c8cadd20af","prefixes":{"*":{"product":56}}}, // [AdClear GmbH] - {"hash":"e8adb806a39f661d","prefixes":{"":{"product":57}}}, // [DeinDeal AG] - {"hash":"da7343c16a51f1d4","prefixes":{"":{"product":58}}}, // [Sixt Leasing SE] - {"hash":"5b4d4595453d5b23","prefixes":{"":{"product":59}}}, // [Air Berlin] - {"hash":"b5085d3a3ede7503","prefixes":{"":{"product":60}}}, // [Aegon ESPAÑA, S.A. de Seguros y Reaseguros, Uniper] - {"hash":"076e39b7aa354c83","prefixes":{"":{"product":56}}}, // [AdClear GmbH] - {"hash":"61c6a6d15b340f45","prefixes":{"":{"product":61}}}, // [Adform DSP] - {"hash":"36f5cb213a4d1469","prefixes":{"":{"product":61}}}, // [Adform DSP] - {"hash":"95b61c012402be18","prefixes":{"":{"product":61}}}, // [Adform DSP] - {"hash":"34e291794974e891","prefixes":{"":{"product":61}}}, // [Adform DSP] - {"hash":"1d0d393655ae7ce4","prefixes":{"*":{"product":62}}}, // [Adconion Media Group] - {"hash":"dbeb328acc5a5a14","prefixes":{"*":{"product":62}}}, // [Adconion Media Group] - {"hash":"9e6e5f626bc3d43c","prefixes":{"":{"product":62}}}, // [Adconion Media Group] - {"hash":"66659e79ff807f39","prefixes":{"":{"product":62}}}, // [Adconion Media Group] - {"hash":"ce965bb06760436e","prefixes":{"":{"product":62}}}, // [Adconion Media Group] - {"hash":"ca8e04a5cdd8fd1f","prefixes":{"":{"product":62}}}, // [Adconion Media Group] - {"hash":"1084f1e2b04f5f93","prefixes":{"":{"product":62}}}, // [Adconion Media Group] - {"hash":"04b3778457a3ba99","prefixes":{"*":{"product":62}}}, // [Adconion Media Group] - {"hash":"1b843f2f1a39c98b","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"8c7beead1ea37382","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"2b59e3efe59d97d5","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"518308907f5f69a2","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"07d4474fae9c6b06","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"47c590566f0c869a","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"409240a38e5e72b9","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"98421a6d07f5517b","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"4f00fb001635132a","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"c6ba94708f6d7d53","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"caae109e8a3bec4f","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"9137b5cdfcb54ca8","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"ae96d818a0674db2","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"f67fecc339ee273d","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"763cc84e4a6c6fce","prefixes":{"":{"product":63}}}, // [Adform] - {"hash":"170707627205d14d","prefixes":{"*":{"product":64}}}, // [Adition] - {"hash":"4b3783127a962269","prefixes":{"":{"product":64}}}, // [Adition] - {"hash":"457cb5e9c72500bd","prefixes":{"":{"product":64}}}, // [Adition] - {"hash":"0f529dc32c1b9057","prefixes":{"":{"product":64}}}, // [Adition] - {"hash":"e63845bad50263e0","prefixes":{"":{"product":65}}}, // [Active Agent] - {"hash":"08b8d8e397848984","prefixes":{"":{"product":65}}}, // [Active Agent] - {"hash":"146ac0ff21924e7d","prefixes":{"*":{"product":64}}}, // [Adition] - {"hash":"a51da6855de3a256","prefixes":{"":{"product":66}}}, // [mov.ad GmbH] - {"hash":"150498b9d10f053f","prefixes":{"*":{"product":64}}}, // [Adition] - {"hash":"fa1803e00adafe6b","prefixes":{"":{"product":66}}}, // [mov.ad GmbH] - {"hash":"ba820e9bd3ccd291","prefixes":{"":{"product":66}}}, // [mov.ad GmbH] - {"hash":"73f70045beea25cc","prefixes":{"":{"product":66}}}, // [mov.ad GmbH] - {"hash":"14725cb7b6e3ed94","prefixes":{"":{"product":66}}}, // [mov.ad GmbH] - {"hash":"fd2740cbee10696e","prefixes":{"":{"product":66}}}, // [mov.ad GmbH] - {"hash":"e150d6342c6a3952","prefixes":{"*":{"product":67}}}, // [AdJug] - {"hash":"50b8b93a8b536983","prefixes":{"*":{"product":68}}}, // [AdJuggler] - {"hash":"85335d83efc9839b","prefixes":{"*":{"product":68}}}, // [AdJuggler] - {"hash":"08f0bb45326cffe3","prefixes":{"*":{"product":69}}}, // [AdKeeper] - {"hash":"5e2b2393dad3f5eb","prefixes":{"*":{"product":69}}}, // [AdKeeper] - {"hash":"da818bcf61df9002","prefixes":{"*":{"product":69}}}, // [AdKeeper] - {"hash":"846fc96edd68e2f8","prefixes":{"*":{"product":70}}}, // [AdKnife] - {"hash":"914d48df3d7aeaae","prefixes":{"*":{"product":71}}}, // [Adku] - {"hash":"8a5b58174cc938bf","prefixes":{"*":{"product":72}}}, // [AdLantic Online Advertising] - {"hash":"218eb49612488266","prefixes":{"":{"product":73}}}, // [Adloox] - {"hash":"85c9a55ea5b2a32a","prefixes":{"data":{"product":73},"am":{"product":73}}}, // [Adloox] [Adloox] - {"hash":"9827ba4725b53982","prefixes":{"":{"product":73}}}, // [Adloox] - {"hash":"bfbbf6b81b109b36","prefixes":{"*":{"product":74}}}, // [adMarketplace] - {"hash":"006d6718806b7562","prefixes":{"*":{"product":75}}}, // [AdMotion] - {"hash":"43871f2ce46890ca","prefixes":{"":{"product":76}}}, // [AdMotion USA Inc.] - {"hash":"2648f20c5fa7ee09","prefixes":{"":{"product":76}}}, // [AdMotion USA Inc.] - {"hash":"63e0b0f085a8b214","prefixes":{"*":{"product":77}}}, // [Digilant] - {"hash":"7288a07f340911e5","prefixes":{"":{"product":78}}}, // [Adnologies GmbH] - {"hash":"a9fe843107d85e5c","prefixes":{"":{"product":78}}}, // [Adnologies GmbH] - {"hash":"230c59512261d73d","prefixes":{"cdn-":{"product":78}}}, // [Adnologies GmbH] - {"hash":"8ca4fb13619b77f1","prefixes":{"*":{"product":79}}}, // [Adometry by Google] - {"hash":"18652cba5445b34f","prefixes":{"":{"product":80}}}, // [Adperium BV] - {"hash":"6d09f83aefc4501e","prefixes":{"*":{"product":81}}}, // [AdPredictive] - {"hash":"70732e61af9adb0a","prefixes":{"":{"product":82}}}, // [Usemax] - {"hash":"b4ede094fe706ace","prefixes":{"*":{"product":83}}}, // [Adrime] - {"hash":"b19cfc95f67d0fa7","prefixes":{"*":{"product":83}}}, // [Adrime] - {"hash":"a6e49b6248014fa6","prefixes":{"*":{"product":84}}}, // [AdRiver] - {"hash":"4a53a59490c4a38e","prefixes":{"*":{"product":85}}}, // [Adroit Interactive] - {"hash":"683e22cafa5f3bd9","prefixes":{"":{"product":85}}}, // [Adroit Interactive] - {"hash":"02e8a15ca61fbc33","prefixes":{"":{"product":86}}}, // [MediaMath Inc.] - {"hash":"a3c3a62c565da599","prefixes":{"":{"product":86}}}, // [MediaMath Inc.] - {"hash":"73e23ad84157f244","prefixes":{"":{"product":86}}}, // [MediaMath Inc.] - {"hash":"b8bd71aaaa715a18","prefixes":{"":{"product":86}}}, // [MediaMath Inc.] - {"hash":"34049e798c80bbab","prefixes":{"":{"product":86}}}, // [MediaMath Inc.] - {"hash":"838eef1c1fe8af0c","prefixes":{"":{"product":86}}}, // [MediaMath Inc.] - {"hash":"3a7e3dfea00e8162","prefixes":{"":{"product":86}}}, // [MediaMath Inc.] - {"hash":"0173cd7bab46f6fd","prefixes":{"":{"product":86}}}, // [MediaMath Inc.] - {"hash":"c14663d78cbafed8","prefixes":{"":{"product":86}}}, // [MediaMath Inc.] - {"hash":"308a1884ba632254","prefixes":{"":{"product":86}}}, // [MediaMath Inc.] - {"hash":"0e219f63d92e9f36","prefixes":{"":{"product":86}}}, // [MediaMath Inc.] - {"hash":"f01c179c5f1e71ec","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"37523eaeb9b1fe5b","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"65eb7e97acb7c098","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"3caa5b10b768447a","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"c8ca517332beacb1","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"8af902c81b793154","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"38ed924c01545a3b","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"5b57e356a62d6828","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"4281a0a413796f1b","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"66e356358c42a9dd","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"ebe26069a0940456","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"9d2283ab81bb7a35","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"d5e05919c2d72fad","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"519afd00add32a74","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"88d48f3ceb8d02bb","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"d93b7d2660301b12","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"6a71009da4358f28","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"71f627786ab80897","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"f1b3147102656b41","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"1a3040f79f3eda5d","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"1c81402568ca4c6f","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"5a0f681f5d3714ed","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"fb3d4d280f621627","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"6811c6e8c717b25b","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"2b559615c990392b","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"d8447dd40d9ce63f","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"98a32e82bd6110c6","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"e3ff44ab0bbc3669","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"d8a244effa85d1e6","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"fa65d62c20cc94bb","prefixes":{"":{"product":88}}}, // [Integral Ad Science Firewall] - {"hash":"1d55dfbdf9f318d1","prefixes":{"":{"product":88}}}, // [Integral Ad Science Firewall] - {"hash":"e06269227a02ae45","prefixes":{"":{"product":88}}}, // [Integral Ad Science Firewall] - {"hash":"2d2bf9a9cb6e9f86","prefixes":{"":{"product":88}}}, // [Integral Ad Science Firewall] - {"hash":"0adbf6085946bbf6","prefixes":{"":{"product":88}}}, // [Integral Ad Science Firewall] - {"hash":"61d2d4f25972fccd","prefixes":{"":{"product":88}}}, // [Integral Ad Science Firewall] - {"hash":"d9506dcf3ab8ec68","prefixes":{"":{"product":88}}}, // [Integral Ad Science Firewall] - {"hash":"61448b088aea7146","prefixes":{"":{"product":88}}}, // [Integral Ad Science Firewall] - {"hash":"12b1ed92371498e2","prefixes":{"":{"product":88}}}, // [Integral Ad Science Firewall] - {"hash":"b8f763d46b3d230a","prefixes":{"":{"product":88}}}, // [Integral Ad Science Firewall] - {"hash":"d4033ecbe069d318","prefixes":{"":{"product":87}}}, // [Campaign Monitor] - {"hash":"b45ea1eb9c9290a1","prefixes":{"*":{"product":89}}}, // [AdShuffle] - {"hash":"333bed71fe872c88","prefixes":{"":{"product":90}}}, // [ADSOVO] - {"hash":"ad77e48d841a15a8","prefixes":{"":{"product":90}}}, // [ADSOVO] - {"hash":"f822525b349866b4","prefixes":{"*":{"product":91}}}, // [ADTECH GmbH] - {"hash":"6cda8dd1b92f6c35","prefixes":{"*":{"product":91}}}, // [ADTECH GmbH] - {"hash":"4d592efbff40197f","prefixes":{"*":{"product":92}}}, // [Adtelligence] - {"hash":"0f57dc611a2e469e","prefixes":{"":{"product":93}}}, // [Adverline] - {"hash":"ef6cb8337223cbd6","prefixes":{"*":{"product":93}}}, // [Adverline] - {"hash":"1902c407bbf1add8","prefixes":{"*":{"product":94}}}, // [AOL Advertising.com] - {"hash":"c0956c63084023a8","prefixes":{"":{"product":95}}}, // [Adap.tv Inc. (AdX)] - {"hash":"f029d231882ed252","prefixes":{"":{"product":95}}}, // [Adap.tv Inc. (AdX)] - {"hash":"ee175aa478efb9b3","prefixes":{"*":{"product":94}}}, // [AOL Advertising.com] - {"hash":"c0fff6b8232710c4","prefixes":{"*":{"product":94}}}, // [AOL Advertising.com] - {"hash":"a846e3340ac27ada","prefixes":{"":{"product":96}}}, // [Convertro Inc] - {"hash":"548e9e34dbc275b6","prefixes":{"":{"product":97}}}, // [Tacoda] - {"hash":"e9695f56eaa054e2","prefixes":{"":{"product":94}}}, // [AOL Advertising.com] - {"hash":"f7f6bc8c4345347a","prefixes":{"*":{"product":98}}}, // [Digital Control GmbH (Advolution)] - {"hash":"484a656ace404140","prefixes":{"":{"product":98}}}, // [Digital Control GmbH (Advolution)] - {"hash":"a224f896601ec717","prefixes":{"":{"product":98}}}, // [Digital Control GmbH (Advolution)] - {"hash":"3a79a6d9af12ef9a","prefixes":{"*":{"product":99}}}, // [AdXcel] - {"hash":"b3dec77d20a55dcb","prefixes":{"*":{"product":99}}}, // [AdXcel] - {"hash":"1f25b55eca65221c","prefixes":{"":{"product":99}}}, // [AdXcel] - {"hash":"f531a655b1982ee7","prefixes":{"":{"product":100}}}, // [Alenty S.A.S] - {"hash":"b884f71dddd78a28","prefixes":{"":{"product":101}}}, // [DoubleClick Bid Manager] - {"hash":"839eb75d0e9ef128","prefixes":{"":{"product":102}}}, // [BigaBid Media Ltd.] - {"hash":"ad920773d5c3e050","prefixes":{"":{"product":103}}}, // [Cogo Labs, Inc.] - {"hash":"6cbe6bc5d5fed35c","prefixes":{"":{"product":104}}}, // [AudienceProject] - {"hash":"98bc51a23a37253c","prefixes":{"*":{"product":39}}}, // [Amazon] - {"hash":"78cfcb50606e44f8","prefixes":{"":{"product":105}}}, // [Rockabox Media Ltd] - {"hash":"37f3aa55bd48760c","prefixes":{"":{"product":106}}}, // [PocketMath] - {"hash":"fa92c520ca116999","prefixes":{"":{"product":107}}}, // [Kpsule] - {"hash":"26d760f54a265d93","prefixes":{"":{"product":107}}}, // [Kpsule] - {"hash":"c046bec428f602d5","prefixes":{"":{"product":107}}}, // [Kpsule] - {"hash":"7fbe2c9290629394","prefixes":{"":{"product":107}}}, // [Kpsule] - {"hash":"16d261a6c03c3de9","prefixes":{"":{"product":108}}}, // [Immedium, Inc.] - {"hash":"1787c49522ce0278","prefixes":{"":{"product":109}}}, // [Fractional Media, LLC] - {"hash":"45ccf99ac2ed3af1","prefixes":{"":{"product":109}}}, // [Fractional Media, LLC] - {"hash":"8c431268cc5c116b","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"645dd2a279a77bf5","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"53aaf4b4f2f2cc8b","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"a6175c31fc587fa2","prefixes":{"":{"product":111}}}, // [Epic Combo Malta Ltd.] - {"hash":"c0e7c2ad3d5d28a0","prefixes":{"":{"product":111}}}, // [Epic Combo Malta Ltd.] - {"hash":"b6a3ce0dea65f762","prefixes":{"":{"product":112}}}, // [Quixey] - {"hash":"29e07de898fa18f4","prefixes":{"":{"product":112}}}, // [Quixey] - {"hash":"1959efaae117c9fa","prefixes":{"":{"product":113}}}, // [YOOX NET-A-PORTER GROUP SPA] - {"hash":"0a59c33253f15970","prefixes":{"":{"product":114}}}, // [TapTap Networks S.L.] - {"hash":"383161133467d12b","prefixes":{"":{"product":45}}}, // [Adways SAS] - {"hash":"e2e18e4ba75c8e58","prefixes":{"":{"product":45}}}, // [Adways SAS] - {"hash":"1f9da694ae6dd7cf","prefixes":{"":{"product":45}}}, // [Adways SAS] - {"hash":"5038b4de783848d4","prefixes":{"":{"product":45}}}, // [Adways SAS] - {"hash":"3542b95dcaa08c84","prefixes":{"":{"product":115}}}, // [ComScore (AdXpose)] - {"hash":"7bbbdfeb3d7b8ad3","prefixes":{"*":{"product":116}}}, // [AdYard] - {"hash":"2ff57c503c5f110d","prefixes":{"":{"product":117}}}, // [Affectv] - {"hash":"7558d4293841e1f0","prefixes":{"":{"product":117}}}, // [Affectv] - {"hash":"a8adad05a6ff5945","prefixes":{"":{"product":117}}}, // [Affectv] - {"hash":"cd1a91dee22478d6","prefixes":{"":{"product":117}}}, // [Affectv] - {"hash":"ebca243af085210f","prefixes":{"":{"product":117}}}, // [Affectv] - {"hash":"bc7fe0dc5bf3e869","prefixes":{"":{"product":3}}}, // [Affilinet GmbH] - {"hash":"c894a0e3f6a6b627","prefixes":{"":{"product":3}}}, // [Affilinet GmbH] - {"hash":"bfdba513f8cb5b8b","prefixes":{"":{"product":3}}}, // [Affilinet GmbH] - {"hash":"1227c609f898a707","prefixes":{"":{"product":3}}}, // [Affilinet GmbH] - {"hash":"4f884065e1e88de2","prefixes":{"":{"product":3}}}, // [Affilinet GmbH] - {"hash":"93d5950ea0bfe437","prefixes":{"":{"product":3}}}, // [Affilinet GmbH] - {"hash":"560c5b8e23e29733","prefixes":{"":{"product":3}}}, // [Affilinet GmbH] - {"hash":"28d74bfc94c9635f","prefixes":{"":{"product":3}}}, // [Affilinet GmbH] - {"hash":"8f7f83e4f5f9e2c0","prefixes":{"":{"product":3}}}, // [Affilinet GmbH] - {"hash":"fd2b5d860fd44749","prefixes":{"*":{"product":3}}}, // [Affilinet GmbH] - {"hash":"1d0953961a14d2fc","prefixes":{"*":{"product":118}}}, // [SET.tv] - {"hash":"5edf63353d8e0fcd","prefixes":{"":{"product":118}}}, // [SET.tv] - {"hash":"e4e5eb11299f703e","prefixes":{"*":{"product":119}}}, // [Adroit Digital Solutions (ADS)] - {"hash":"e5cf3445847fef93","prefixes":{"*":{"product":119}}}, // [Adroit Digital Solutions (ADS)] - {"hash":"8441a2216167c3d4","prefixes":{"at":{"product":100}}}, // [Alenty S.A.S] - {"hash":"b9dab57457cf6477","prefixes":{"":{"product":100}}}, // [Alenty S.A.S] - {"hash":"94b55596aadb2893","prefixes":{"":{"product":100}}}, // [Alenty S.A.S] - {"hash":"16b31027fd40c9ad","prefixes":{"":{"product":100}}}, // [Alenty S.A.S] - {"hash":"bb4adabba7b0b6b8","prefixes":{"*":{"product":120}}}, // [AppNexus Inc] - {"hash":"3b2105469f3563e3","prefixes":{"*":{"product":121}}}, // [Adfusion] - {"hash":"2f29d38052b5a8a6","prefixes":{"":{"product":122}}}, // [ARC Media Group] + {"hash":"cd681b4891935464","prefixes":{"":{"product":34,"type":1}}}, // [Yahoo! Japan Corporation] + {"hash":"b97383320b594f18","prefixes":{"":{"product":34,"type":1}}}, // [Yahoo! Japan Corporation] + {"hash":"e2fff6e598b3035e","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"cb3ceda4f0c38995","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"a218e065250d793c","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"deb1ce911dfb392b","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"de5ead15f1d0f171","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"92615d394883ce3c","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"6cd842b12d20b208","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"dc6acfacad6c1026","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"81aa25ff76990996","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"1254067a80cf3d7b","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"31e2549e82b92770","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"be41bb940608434e","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"05a4ab4a11bd1fbf","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"05677aca712e9b65","prefixes":{"":{"product":1,"type":0}}}, // [A9] + {"hash":"00620801050945d1","prefixes":{"":{"product":35,"type":0}}}, // [Oggifinogi] + {"hash":"c0ceae7cfc4144c6","prefixes":{"":{"product":36,"type":0}}}, // [PaperG] + {"hash":"996c3990310cfc19","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"14210f0f0a8d71cb","prefixes":{"":{"product":38,"type":0}}}, // [The Trade Desk Inc.] + {"hash":"0f07ec261c73a8fb","prefixes":{"*":{"product":39,"type":2},"":{"product":40,"type":0}}}, // [Amazon] [F# Inc.] + {"hash":"736b87f504b5e113","prefixes":{"":{"product":41,"type":0}}}, // [Airpush, Inc.] + {"hash":"0bcef81372eadfe9","prefixes":{"":{"product":42,"type":0}}}, // [Clinch.co] + {"hash":"9ea6769e672968e9","prefixes":{"":{"product":40,"type":0}}}, // [F# Inc.] + {"hash":"0fde612c20c42c6f","prefixes":{"":{"product":43,"type":0}}}, // [Transout Inc.] + {"hash":"5ed995763ce85029","prefixes":{"":{"product":44,"type":0}}}, // [ADZIP] + {"hash":"497082972c1c0dfd","prefixes":{"":{"product":45,"type":0}}}, // [Adways SAS] + {"hash":"6d7e4a203b969d9e","prefixes":{"":{"product":46,"type":0}}}, // [Opera Mediaworks Inc.] + {"hash":"d3a9057528c14a56","prefixes":{"":{"product":47,"type":0}}}, // [DistroScale Inc.] + {"hash":"479d2f8d9b7a2efe","prefixes":{"":{"product":48,"type":0}}}, // [Enzymic Consultancy] + {"hash":"6f7f9fb0065f745f","prefixes":{"":{"product":48,"type":0}}}, // [Enzymic Consultancy] + {"hash":"893d967f4540bb44","prefixes":{"":{"product":49,"type":0}}}, // [Fluct Inc.] + {"hash":"3830f0b6ca460fe9","prefixes":{"*":{"product":50,"type":0}}}, // [Acuity Ads] + {"hash":"e917237ee7b0ad79","prefixes":{"":{"product":50,"type":0}}}, // [Acuity Ads] + {"hash":"e0792ffd5eca94d8","prefixes":{"":{"product":50,"type":0}}}, // [Acuity Ads] + {"hash":"29beee316a393584","prefixes":{"":{"product":50,"type":0}}}, // [Acuity Ads] + {"hash":"ce9e7bf17bba4aae","prefixes":{"":{"product":50,"type":0}}}, // [Acuity Ads] + {"hash":"fcf604f90166bb66","prefixes":{"":{"product":50,"type":0}}}, // [Acuity Ads] + {"hash":"f11d9059950b4a07","prefixes":{"":{"product":50,"type":0}}}, // [Acuity Ads] + {"hash":"7d142a85f84f3402","prefixes":{"":{"product":50,"type":0}}}, // [Acuity Ads] + {"hash":"83c0bb224cb5622f","prefixes":{"*":{"product":51,"type":0}}}, // [iLead] + {"hash":"27841e5ac1581a67","prefixes":{"":{"product":52,"type":0}}}, // [Canned Banners LLC] + {"hash":"83fbdce4f2519684","prefixes":{"":{"product":52,"type":0}}}, // [Canned Banners LLC] + {"hash":"db7bac94f2b2d2b7","prefixes":{"":{"product":53,"type":0}}}, // [AdBroker GmbH] + {"hash":"e0de5430253205fc","prefixes":{"":{"product":53,"type":0}}}, // [AdBroker GmbH] + {"hash":"bde57b6011499edf","prefixes":{"":{"product":53,"type":0}}}, // [AdBroker GmbH] + {"hash":"077ad042e29c79fb","prefixes":{"":{"product":53,"type":0}}}, // [AdBroker GmbH] + {"hash":"d3c6fc5ff77f0d5c","prefixes":{"":{"product":53,"type":0}}}, // [AdBroker GmbH] + {"hash":"b88fb01ba215894e","prefixes":{"*":{"product":54,"type":1}}}, // [InMind Opinion Media] + {"hash":"3d509f557aeca6de","prefixes":{"*":{"product":55,"type":0}}}, // [Adcentric] + {"hash":"3a9959c8cadd20af","prefixes":{"*":{"product":56,"type":1}}}, // [AdClear GmbH] + {"hash":"e8adb806a39f661d","prefixes":{"":{"product":57,"type":1}}}, // [DeinDeal AG] + {"hash":"da7343c16a51f1d4","prefixes":{"":{"product":58,"type":1}}}, // [Sixt Leasing SE] + {"hash":"5b4d4595453d5b23","prefixes":{"":{"product":59,"type":1}}}, // [Air Berlin] + {"hash":"b5085d3a3ede7503","prefixes":{"":{"product":60,"type":1}}}, // [Aegon ESPAÑA, S.A. de Seguros y Reaseguros, Uniper] + {"hash":"076e39b7aa354c83","prefixes":{"":{"product":56,"type":1}}}, // [AdClear GmbH] + {"hash":"61c6a6d15b340f45","prefixes":{"":{"product":61,"type":0}}}, // [Adform DSP] + {"hash":"36f5cb213a4d1469","prefixes":{"":{"product":61,"type":0}}}, // [Adform DSP] + {"hash":"95b61c012402be18","prefixes":{"":{"product":61,"type":0}}}, // [Adform DSP] + {"hash":"34e291794974e891","prefixes":{"":{"product":61,"type":0}}}, // [Adform DSP] + {"hash":"1d0d393655ae7ce4","prefixes":{"*":{"product":62,"type":0}}}, // [Adconion Media Group] + {"hash":"dbeb328acc5a5a14","prefixes":{"*":{"product":62,"type":0}}}, // [Adconion Media Group] + {"hash":"9e6e5f626bc3d43c","prefixes":{"":{"product":62,"type":0}}}, // [Adconion Media Group] + {"hash":"66659e79ff807f39","prefixes":{"":{"product":62,"type":0}}}, // [Adconion Media Group] + {"hash":"ce965bb06760436e","prefixes":{"":{"product":62,"type":0}}}, // [Adconion Media Group] + {"hash":"ca8e04a5cdd8fd1f","prefixes":{"":{"product":62,"type":0}}}, // [Adconion Media Group] + {"hash":"1084f1e2b04f5f93","prefixes":{"":{"product":62,"type":0}}}, // [Adconion Media Group] + {"hash":"04b3778457a3ba99","prefixes":{"*":{"product":62,"type":0}}}, // [Adconion Media Group] + {"hash":"1b843f2f1a39c98b","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"8c7beead1ea37382","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"2b59e3efe59d97d5","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"518308907f5f69a2","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"07d4474fae9c6b06","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"47c590566f0c869a","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"409240a38e5e72b9","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"98421a6d07f5517b","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"4f00fb001635132a","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"c6ba94708f6d7d53","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"caae109e8a3bec4f","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"9137b5cdfcb54ca8","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"ae96d818a0674db2","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"f67fecc339ee273d","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"763cc84e4a6c6fce","prefixes":{"":{"product":63,"type":0}}}, // [Adform] + {"hash":"170707627205d14d","prefixes":{"*":{"product":64,"type":0}}}, // [Adition] + {"hash":"4b3783127a962269","prefixes":{"":{"product":64,"type":0}}}, // [Adition] + {"hash":"457cb5e9c72500bd","prefixes":{"":{"product":64,"type":0}}}, // [Adition] + {"hash":"0f529dc32c1b9057","prefixes":{"":{"product":64,"type":0}}}, // [Adition] + {"hash":"e63845bad50263e0","prefixes":{"":{"product":65,"type":0}}}, // [Active Agent] + {"hash":"08b8d8e397848984","prefixes":{"":{"product":65,"type":0}}}, // [Active Agent] + {"hash":"146ac0ff21924e7d","prefixes":{"*":{"product":64,"type":0}}}, // [Adition] + {"hash":"a51da6855de3a256","prefixes":{"":{"product":66,"type":0}}}, // [mov.ad GmbH] + {"hash":"150498b9d10f053f","prefixes":{"*":{"product":64,"type":0}}}, // [Adition] + {"hash":"fa1803e00adafe6b","prefixes":{"":{"product":66,"type":0}}}, // [mov.ad GmbH] + {"hash":"ba820e9bd3ccd291","prefixes":{"":{"product":66,"type":0}}}, // [mov.ad GmbH] + {"hash":"73f70045beea25cc","prefixes":{"":{"product":66,"type":0}}}, // [mov.ad GmbH] + {"hash":"14725cb7b6e3ed94","prefixes":{"":{"product":66,"type":0}}}, // [mov.ad GmbH] + {"hash":"fd2740cbee10696e","prefixes":{"":{"product":66,"type":0}}}, // [mov.ad GmbH] + {"hash":"e150d6342c6a3952","prefixes":{"*":{"product":67,"type":0}}}, // [AdJug] + {"hash":"50b8b93a8b536983","prefixes":{"*":{"product":68,"type":0}}}, // [AdJuggler] + {"hash":"85335d83efc9839b","prefixes":{"*":{"product":68,"type":0}}}, // [AdJuggler] + {"hash":"08f0bb45326cffe3","prefixes":{"*":{"product":69,"type":0}}}, // [AdKeeper] + {"hash":"5e2b2393dad3f5eb","prefixes":{"*":{"product":69,"type":0}}}, // [AdKeeper] + {"hash":"da818bcf61df9002","prefixes":{"*":{"product":69,"type":0}}}, // [AdKeeper] + {"hash":"846fc96edd68e2f8","prefixes":{"*":{"product":70,"type":0}}}, // [AdKnife] + {"hash":"914d48df3d7aeaae","prefixes":{"*":{"product":71,"type":0}}}, // [Adku] + {"hash":"8a5b58174cc938bf","prefixes":{"*":{"product":72,"type":0}}}, // [AdLantic Online Advertising] + {"hash":"218eb49612488266","prefixes":{"":{"product":73,"type":1}}}, // [Adloox] + {"hash":"85c9a55ea5b2a32a","prefixes":{"data":{"product":73,"type":1},"am":{"product":73,"type":1}}}, // [Adloox] [Adloox] + {"hash":"9827ba4725b53982","prefixes":{"":{"product":73,"type":1}}}, // [Adloox] + {"hash":"bfbbf6b81b109b36","prefixes":{"*":{"product":74,"type":0}}}, // [adMarketplace] + {"hash":"006d6718806b7562","prefixes":{"*":{"product":75,"type":0}}}, // [AdMotion] + {"hash":"43871f2ce46890ca","prefixes":{"":{"product":76,"type":0}}}, // [AdMotion USA Inc.] + {"hash":"2648f20c5fa7ee09","prefixes":{"":{"product":76,"type":0}}}, // [AdMotion USA Inc.] + {"hash":"63e0b0f085a8b214","prefixes":{"*":{"product":77,"type":0}}}, // [Digilant] + {"hash":"7288a07f340911e5","prefixes":{"":{"product":78,"type":0}}}, // [Adnologies GmbH] + {"hash":"a9fe843107d85e5c","prefixes":{"":{"product":78,"type":0}}}, // [Adnologies GmbH] + {"hash":"230c59512261d73d","prefixes":{"cdn-":{"product":78,"type":0}}}, // [Adnologies GmbH] + {"hash":"8ca4fb13619b77f1","prefixes":{"*":{"product":79,"type":1}}}, // [Adometry by Google] + {"hash":"18652cba5445b34f","prefixes":{"":{"product":80,"type":0}}}, // [Adperium BV] + {"hash":"6d09f83aefc4501e","prefixes":{"*":{"product":81,"type":0}}}, // [AdPredictive] + {"hash":"70732e61af9adb0a","prefixes":{"":{"product":82,"type":0}}}, // [Usemax] + {"hash":"b4ede094fe706ace","prefixes":{"*":{"product":83,"type":0}}}, // [Adrime] + {"hash":"b19cfc95f67d0fa7","prefixes":{"*":{"product":83,"type":0}}}, // [Adrime] + {"hash":"a6e49b6248014fa6","prefixes":{"*":{"product":84,"type":0}}}, // [AdRiver] + {"hash":"4a53a59490c4a38e","prefixes":{"*":{"product":85,"type":1}}}, // [Adroit Interactive] + {"hash":"683e22cafa5f3bd9","prefixes":{"":{"product":85,"type":1}}}, // [Adroit Interactive] + {"hash":"02e8a15ca61fbc33","prefixes":{"":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"a3c3a62c565da599","prefixes":{"":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"73e23ad84157f244","prefixes":{"":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"b8bd71aaaa715a18","prefixes":{"":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"34049e798c80bbab","prefixes":{"":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"838eef1c1fe8af0c","prefixes":{"":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"3a7e3dfea00e8162","prefixes":{"":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"0173cd7bab46f6fd","prefixes":{"":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"c14663d78cbafed8","prefixes":{"":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"308a1884ba632254","prefixes":{"":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"0e219f63d92e9f36","prefixes":{"":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"f01c179c5f1e71ec","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"37523eaeb9b1fe5b","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"65eb7e97acb7c098","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"3caa5b10b768447a","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"c8ca517332beacb1","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"8af902c81b793154","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"38ed924c01545a3b","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"5b57e356a62d6828","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"4281a0a413796f1b","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"66e356358c42a9dd","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"ebe26069a0940456","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"9d2283ab81bb7a35","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"d5e05919c2d72fad","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"519afd00add32a74","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"88d48f3ceb8d02bb","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"d93b7d2660301b12","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"6a71009da4358f28","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"71f627786ab80897","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"f1b3147102656b41","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"1a3040f79f3eda5d","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"1c81402568ca4c6f","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"5a0f681f5d3714ed","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"fb3d4d280f621627","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"6811c6e8c717b25b","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"2b559615c990392b","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"d8447dd40d9ce63f","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"98a32e82bd6110c6","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"e3ff44ab0bbc3669","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"d8a244effa85d1e6","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"fa65d62c20cc94bb","prefixes":{"":{"product":88,"type":0}}}, // [Integral Ad Science Firewall] + {"hash":"1d55dfbdf9f318d1","prefixes":{"":{"product":88,"type":0}}}, // [Integral Ad Science Firewall] + {"hash":"e06269227a02ae45","prefixes":{"":{"product":88,"type":0}}}, // [Integral Ad Science Firewall] + {"hash":"2d2bf9a9cb6e9f86","prefixes":{"":{"product":88,"type":0}}}, // [Integral Ad Science Firewall] + {"hash":"0adbf6085946bbf6","prefixes":{"":{"product":88,"type":0}}}, // [Integral Ad Science Firewall] + {"hash":"61d2d4f25972fccd","prefixes":{"":{"product":88,"type":0}}}, // [Integral Ad Science Firewall] + {"hash":"d9506dcf3ab8ec68","prefixes":{"":{"product":88,"type":0}}}, // [Integral Ad Science Firewall] + {"hash":"61448b088aea7146","prefixes":{"":{"product":88,"type":0}}}, // [Integral Ad Science Firewall] + {"hash":"12b1ed92371498e2","prefixes":{"":{"product":88,"type":0}}}, // [Integral Ad Science Firewall] + {"hash":"b8f763d46b3d230a","prefixes":{"":{"product":88,"type":0}}}, // [Integral Ad Science Firewall] + {"hash":"d4033ecbe069d318","prefixes":{"":{"product":87,"type":1}}}, // [Campaign Monitor] + {"hash":"b45ea1eb9c9290a1","prefixes":{"*":{"product":89,"type":0}}}, // [AdShuffle] + {"hash":"333bed71fe872c88","prefixes":{"":{"product":90,"type":0}}}, // [ADSOVO] + {"hash":"ad77e48d841a15a8","prefixes":{"":{"product":90,"type":0}}}, // [ADSOVO] + {"hash":"f822525b349866b4","prefixes":{"*":{"product":91,"type":0}}}, // [ADTECH GmbH] + {"hash":"6cda8dd1b92f6c35","prefixes":{"*":{"product":91,"type":0}}}, // [ADTECH GmbH] + {"hash":"4d592efbff40197f","prefixes":{"*":{"product":92,"type":0}}}, // [Adtelligence] + {"hash":"0f57dc611a2e469e","prefixes":{"":{"product":93,"type":0}}}, // [Adverline] + {"hash":"ef6cb8337223cbd6","prefixes":{"*":{"product":93,"type":0}}}, // [Adverline] + {"hash":"1902c407bbf1add8","prefixes":{"*":{"product":94,"type":0}}}, // [AOL Advertising.com] + {"hash":"c0956c63084023a8","prefixes":{"":{"product":95,"type":0}}}, // [Adap.tv Inc. (AdX)] + {"hash":"f029d231882ed252","prefixes":{"":{"product":95,"type":0}}}, // [Adap.tv Inc. (AdX)] + {"hash":"ee175aa478efb9b3","prefixes":{"*":{"product":94,"type":0}}}, // [AOL Advertising.com] + {"hash":"c0fff6b8232710c4","prefixes":{"*":{"product":94,"type":0}}}, // [AOL Advertising.com] + {"hash":"a846e3340ac27ada","prefixes":{"":{"product":96,"type":1}}}, // [Convertro Inc] + {"hash":"548e9e34dbc275b6","prefixes":{"":{"product":97,"type":0}}}, // [Tacoda] + {"hash":"e9695f56eaa054e2","prefixes":{"":{"product":94,"type":0}}}, // [AOL Advertising.com] + {"hash":"f7f6bc8c4345347a","prefixes":{"*":{"product":98,"type":0}}}, // [Digital Control GmbH (Advolution)] + {"hash":"484a656ace404140","prefixes":{"":{"product":98,"type":0}}}, // [Digital Control GmbH (Advolution)] + {"hash":"a224f896601ec717","prefixes":{"":{"product":98,"type":0}}}, // [Digital Control GmbH (Advolution)] + {"hash":"3a79a6d9af12ef9a","prefixes":{"*":{"product":99,"type":0}}}, // [AdXcel] + {"hash":"b3dec77d20a55dcb","prefixes":{"*":{"product":99,"type":0}}}, // [AdXcel] + {"hash":"1f25b55eca65221c","prefixes":{"":{"product":99,"type":0}}}, // [AdXcel] + {"hash":"f531a655b1982ee7","prefixes":{"":{"product":100,"type":1}}}, // [Alenty S.A.S] + {"hash":"b884f71dddd78a28","prefixes":{"":{"product":101,"type":0}}}, // [DoubleClick Bid Manager] + {"hash":"839eb75d0e9ef128","prefixes":{"":{"product":102,"type":0}}}, // [BigaBid Media Ltd.] + {"hash":"ad920773d5c3e050","prefixes":{"":{"product":103,"type":0}}}, // [Cogo Labs, Inc.] + {"hash":"6cbe6bc5d5fed35c","prefixes":{"":{"product":104,"type":1}}}, // [AudienceProject] + {"hash":"98bc51a23a37253c","prefixes":{"*":{"product":39,"type":2}}}, // [Amazon] + {"hash":"78cfcb50606e44f8","prefixes":{"":{"product":105,"type":0}}}, // [Rockabox Media Ltd] + {"hash":"37f3aa55bd48760c","prefixes":{"":{"product":106,"type":0}}}, // [PocketMath] + {"hash":"fa92c520ca116999","prefixes":{"":{"product":107,"type":0}}}, // [Kpsule] + {"hash":"26d760f54a265d93","prefixes":{"":{"product":107,"type":0}}}, // [Kpsule] + {"hash":"c046bec428f602d5","prefixes":{"":{"product":107,"type":0}}}, // [Kpsule] + {"hash":"7fbe2c9290629394","prefixes":{"":{"product":107,"type":0}}}, // [Kpsule] + {"hash":"16d261a6c03c3de9","prefixes":{"":{"product":108,"type":0}}}, // [Immedium, Inc.] + {"hash":"1787c49522ce0278","prefixes":{"":{"product":109,"type":0}}}, // [Fractional Media, LLC] + {"hash":"45ccf99ac2ed3af1","prefixes":{"":{"product":109,"type":0}}}, // [Fractional Media, LLC] + {"hash":"8c431268cc5c116b","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"645dd2a279a77bf5","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"53aaf4b4f2f2cc8b","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"a6175c31fc587fa2","prefixes":{"":{"product":111,"type":0}}}, // [Epic Combo Malta Ltd.] + {"hash":"c0e7c2ad3d5d28a0","prefixes":{"":{"product":111,"type":0}}}, // [Epic Combo Malta Ltd.] + {"hash":"b6a3ce0dea65f762","prefixes":{"":{"product":112,"type":0}}}, // [Quixey] + {"hash":"29e07de898fa18f4","prefixes":{"":{"product":112,"type":0}}}, // [Quixey] + {"hash":"1959efaae117c9fa","prefixes":{"":{"product":113,"type":0}}}, // [YOOX NET-A-PORTER GROUP SPA] + {"hash":"0a59c33253f15970","prefixes":{"":{"product":114,"type":0}}}, // [TapTap Networks S.L.] + {"hash":"383161133467d12b","prefixes":{"":{"product":45,"type":0}}}, // [Adways SAS] + {"hash":"e2e18e4ba75c8e58","prefixes":{"":{"product":45,"type":0}}}, // [Adways SAS] + {"hash":"1f9da694ae6dd7cf","prefixes":{"":{"product":45,"type":0}}}, // [Adways SAS] + {"hash":"5038b4de783848d4","prefixes":{"":{"product":45,"type":0}}}, // [Adways SAS] + {"hash":"3542b95dcaa08c84","prefixes":{"":{"product":115,"type":1}}}, // [ComScore (AdXpose)] + {"hash":"7bbbdfeb3d7b8ad3","prefixes":{"*":{"product":116,"type":0}}}, // [AdYard] + {"hash":"2ff57c503c5f110d","prefixes":{"":{"product":117,"type":0}}}, // [Affectv] + {"hash":"7558d4293841e1f0","prefixes":{"":{"product":117,"type":0}}}, // [Affectv] + {"hash":"a8adad05a6ff5945","prefixes":{"":{"product":117,"type":0}}}, // [Affectv] + {"hash":"cd1a91dee22478d6","prefixes":{"":{"product":117,"type":0}}}, // [Affectv] + {"hash":"ebca243af085210f","prefixes":{"":{"product":117,"type":0}}}, // [Affectv] + {"hash":"bc7fe0dc5bf3e869","prefixes":{"":{"product":3,"type":1}}}, // [Affilinet GmbH] + {"hash":"c894a0e3f6a6b627","prefixes":{"":{"product":3,"type":1}}}, // [Affilinet GmbH] + {"hash":"bfdba513f8cb5b8b","prefixes":{"":{"product":3,"type":1}}}, // [Affilinet GmbH] + {"hash":"1227c609f898a707","prefixes":{"":{"product":3,"type":1}}}, // [Affilinet GmbH] + {"hash":"4f884065e1e88de2","prefixes":{"":{"product":3,"type":1}}}, // [Affilinet GmbH] + {"hash":"93d5950ea0bfe437","prefixes":{"":{"product":3,"type":1}}}, // [Affilinet GmbH] + {"hash":"560c5b8e23e29733","prefixes":{"":{"product":3,"type":1}}}, // [Affilinet GmbH] + {"hash":"28d74bfc94c9635f","prefixes":{"":{"product":3,"type":1}}}, // [Affilinet GmbH] + {"hash":"8f7f83e4f5f9e2c0","prefixes":{"":{"product":3,"type":1}}}, // [Affilinet GmbH] + {"hash":"fd2b5d860fd44749","prefixes":{"*":{"product":3,"type":1}}}, // [Affilinet GmbH] + {"hash":"1d0953961a14d2fc","prefixes":{"*":{"product":118,"type":0}}}, // [SET.tv] + {"hash":"5edf63353d8e0fcd","prefixes":{"":{"product":118,"type":0}}}, // [SET.tv] + {"hash":"e4e5eb11299f703e","prefixes":{"*":{"product":119,"type":0}}}, // [Adroit Digital Solutions (ADS)] + {"hash":"e5cf3445847fef93","prefixes":{"*":{"product":119,"type":0}}}, // [Adroit Digital Solutions (ADS)] + {"hash":"8441a2216167c3d4","prefixes":{"at":{"product":100,"type":1}}}, // [Alenty S.A.S] + {"hash":"b9dab57457cf6477","prefixes":{"":{"product":100,"type":1}}}, // [Alenty S.A.S] + {"hash":"94b55596aadb2893","prefixes":{"":{"product":100,"type":1}}}, // [Alenty S.A.S] + {"hash":"16b31027fd40c9ad","prefixes":{"":{"product":100,"type":1}}}, // [Alenty S.A.S] + {"hash":"bb4adabba7b0b6b8","prefixes":{"*":{"product":120,"type":0}}}, // [AppNexus Inc] + {"hash":"3b2105469f3563e3","prefixes":{"*":{"product":121,"type":0}}}, // [Adfusion] + {"hash":"2f29d38052b5a8a6","prefixes":{"":{"product":122,"type":0}}}, // [ARC Media Group] {"hash":"c133787bd9e605a7","prefixes":{"":{"product":123}}}, // [Semasio GmbH] - {"hash":"b9a83d8bd4f31543","prefixes":{"":{"product":124}}}, // [Mojiva] - {"hash":"2a1b04ad13f24350","prefixes":{"":{"product":124}}}, // [Mojiva] - {"hash":"a3c6b5ffd4fe1547","prefixes":{"":{"product":125}}}, // [Mocean mobile, Inc.] - {"hash":"0d52aafa33281228","prefixes":{"":{"product":126}}}, // [Phluant] - {"hash":"655e31ecb8719994","prefixes":{"":{"product":126}}}, // [Phluant] - {"hash":"dca17bd2f3edb917","prefixes":{"":{"product":126}}}, // [Phluant] - {"hash":"53de58004f88a1c2","prefixes":{"*":{"product":127}}}, // [AdSpirit] - {"hash":"6a1ebf671194b458","prefixes":{"*":{"product":127}}}, // [AdSpirit] - {"hash":"6ae5a4877aab564f","prefixes":{"":{"product":127}}}, // [AdSpirit] - {"hash":"9dcf8d17ea42466e","prefixes":{"*":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"32e0acbf3d2ecfcf","prefixes":{"*":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"708d275466f5230b","prefixes":{"*":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"7532d83428e05417","prefixes":{"*":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"3258e49c5f504307","prefixes":{"*":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"2c381faaa3144a37","prefixes":{"*":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"776a64cc3a9c6f81","prefixes":{"*":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"d38247a8e8d14a7c","prefixes":{"*":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"50e5ca70dbb69c03","prefixes":{"":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"c1dfde405c173e3b","prefixes":{"":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"5bce52b0f221aac2","prefixes":{"":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"5a0e5730145156e2","prefixes":{"":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"c081c626ad2c0f1f","prefixes":{"":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"a31f53c0c58e67c0","prefixes":{"":{"product":129}}}, // [ATK Media GmbH] - {"hash":"514b4f19cbdabb49","prefixes":{"":{"product":129}}}, // [ATK Media GmbH] - {"hash":"264493bb5046087f","prefixes":{"":{"product":129}}}, // [ATK Media GmbH] - {"hash":"f4e40d6832493420","prefixes":{"":{"product":129}}}, // [ATK Media GmbH] - {"hash":"126b6492c0b1b53a","prefixes":{"*":{"product":130}}}, // [Atlas] - {"hash":"0493e6c92c59fd4d","prefixes":{"":{"product":130}}}, // [Atlas] - {"hash":"d6d40b4417fefcf6","prefixes":{"":{"product":130}}}, // [Atlas] - {"hash":"0b16a7cf8dcb70ee","prefixes":{"*":{"product":131}}}, // [AudienceScience] - {"hash":"edbae80f2449aaee","prefixes":{"":{"product":132}}}, // [BeWebMedia] - {"hash":"c1196b1418bf9de9","prefixes":{"*":{"product":133}}}, // [Bidalpha Inc.] - {"hash":"87016c0f34162bc6","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"2db3b8adb9c37590","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"a10756ccfb034a50","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"1ea7188c5cc22ccf","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"c70dfe98c3735972","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"05aa49d024d6d67c","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"27c08401857f47aa","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"9a569266b426d074","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"5a764c1f870e4e38","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"64b993405c35034f","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"afe660eca2d01217","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"cd398b1d3fe6caf4","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"bb2cf5a27552ba10","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"b79ee8778f5b56d6","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"cae97638b357a30e","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"2c552297aa3abdf1","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"75bbf901ed30d891","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"365bc710167be24c","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"49849f3497cc7ff5","prefixes":{"":{"product":134}}}, // [AdGear Technologies Inc.] - {"hash":"14bb8555907973f5","prefixes":{"":{"product":135}}}, // [BlueKai] - {"hash":"db6cb381e20a210a","prefixes":{"":{"product":135}}}, // [BlueKai] - {"hash":"8e4e07437ae4b61c","prefixes":{"*":{"product":136}}}, // [Bluestreak] - {"hash":"4bb6a17c8b5ec2e7","prefixes":{"":{"product":137}}}, // [blurbIQ] - {"hash":"4aefb106f857a0de","prefixes":{"":{"product":137}}}, // [blurbIQ] - {"hash":"a7b4452428f93120","prefixes":{"":{"product":137}}}, // [blurbIQ] - {"hash":"38f01d050feb50e8","prefixes":{"":{"product":137}}}, // [blurbIQ] - {"hash":"d4ab70ba7caf1ed7","prefixes":{"":{"product":138}}}, // [Brand.net] - {"hash":"94655d9cadd8e829","prefixes":{"":{"product":138}}}, // [Brand.net] - {"hash":"f3347a75843fd9c6","prefixes":{"":{"product":138}}}, // [Brand.net] - {"hash":"60e2856d32c1da23","prefixes":{"*":{"product":139}}}, // [Brandscreen Inc.] - {"hash":"16460b1ac6e3b229","prefixes":{"*":{"product":140}}}, // [BrightRoll Inc.] - {"hash":"814fef93d6498b58","prefixes":{"*":{"product":140}}}, // [BrightRoll Inc.] - {"hash":"72fc1d7c40b9af03","prefixes":{"":{"product":141}}}, // [Brightroll Inc.] - {"hash":"80f8944423cc936c","prefixes":{"*":{"product":142}}}, // [Vindico] - {"hash":"bf2db20b09960c7b","prefixes":{"":{"product":142}}}, // [Vindico] - {"hash":"e180a56826bf4ba6","prefixes":{"*":{"product":143}}}, // [Edgesuite] - {"hash":"1e90c625da6683a5","prefixes":{"":{"product":144}}}, // [Spark Flow S.A.] - {"hash":"d385e514fe92e6d9","prefixes":{"":{"product":145}}}, // [Aarki, Inc.] - {"hash":"4646e46d55455ffe","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"a8c5f49831b36ab9","prefixes":{"*":{"product":147}}}, // [Burst Media LLC d/b/a AdConductor] - {"hash":"f22276edaf005231","prefixes":{"*":{"product":148}}}, // [Advertising.com Dynamic Retargeter] - {"hash":"220db526eb84992d","prefixes":{"*":{"product":149}}}, // [NetAffiliation] - {"hash":"cda3d9612026866c","prefixes":{"*":{"product":149}}}, // [NetAffiliation] - {"hash":"9f8018bcbf15a592","prefixes":{"*":{"product":150}}}, // [C3 Metrics Inc.] - {"hash":"78ec342986654215","prefixes":{"":{"product":150}}}, // [C3 Metrics Inc.] - {"hash":"e4ad94837095a9bc","prefixes":{"*":{"product":150}}}, // [C3 Metrics Inc.] - {"hash":"32401b2118eff57a","prefixes":{"":{"product":151}}}, // [CAPITALDATA (SARL)] - {"hash":"a5f9db92cb5aeb3e","prefixes":{"":{"product":151}}}, // [CAPITALDATA (SARL)] - {"hash":"ae12db7e0621ec0b","prefixes":{"*":{"product":151}}}, // [CAPITALDATA (SARL)] - {"hash":"d7c4970fde31fd62","prefixes":{"*":{"product":152}}}, // [e-Planning] - {"hash":"20cadab7abdae752","prefixes":{"*":{"product":153}}}, // [Chango Inc.] - {"hash":"38363f7ac872a916","prefixes":{"":{"product":154}}}, // [Chango] - {"hash":"114215c6a5b66e37","prefixes":{"":{"product":154}}}, // [Chango] - {"hash":"1ab7b29d135c11fc","prefixes":{"":{"product":155}}}, // [Channel Intelligence] - {"hash":"6e8e21cf50387d5b","prefixes":{"":{"product":155}}}, // [Channel Intelligence] - {"hash":"cbd8c46855691ac9","prefixes":{"*":{"product":155}}}, // [Channel Intelligence] - {"hash":"8bde0d3ba731b24b","prefixes":{"":{"product":155}}}, // [Channel Intelligence] - {"hash":"d415664f4794184e","prefixes":{"":{"product":155}}}, // [Channel Intelligence] - {"hash":"bc8edad5208e36aa","prefixes":{"*":{"product":155}}}, // [Channel Intelligence] - {"hash":"00900e4af3795b7d","prefixes":{"":{"product":156}}}, // [Chartbeat Inc] - {"hash":"dddd416675de98d6","prefixes":{"":{"product":156}}}, // [Chartbeat Inc] - {"hash":"085835cbbea3af5b","prefixes":{"":{"product":156}}}, // [Chartbeat Inc] - {"hash":"0a5fd555ed989cf1","prefixes":{"":{"product":156}}}, // [Chartbeat Inc] - {"hash":"38e6dfa04599d610","prefixes":{"":{"product":156}}}, // [Chartbeat Inc] - {"hash":"282ab213b57d8196","prefixes":{"":{"product":156}}}, // [Chartbeat Inc] - {"hash":"465922959fd197de","prefixes":{"*":{"product":157}}}, // [Choicestream Inc.] - {"hash":"07b64c6d94aaeede","prefixes":{"*":{"product":158}}}, // [AddThis, Inc] - {"hash":"8285ed75ebbab1bf","prefixes":{"*":{"product":158}}}, // [AddThis, Inc] - {"hash":"397da235f9c6c4dc","prefixes":{"*":{"product":159}}}, // [Platform 161] - {"hash":"3e4380669a97a9da","prefixes":{"":{"product":159}}}, // [Platform 161] - {"hash":"0cf7c3db283e4fde","prefixes":{"":{"product":160}}}, // [ClickPoint] - {"hash":"e3f610966ee4998e","prefixes":{"":{"product":161}}}, // [Cobalt Group] - {"hash":"5458332ef0eff5a0","prefixes":{"":{"product":161}}}, // [Cobalt Group] - {"hash":"755391831ca3c171","prefixes":{"*":{"product":161}}}, // [Cobalt Group] - {"hash":"82d7785d13750576","prefixes":{"*":{"product":161}}}, // [Cobalt Group] - {"hash":"f1b10b28e8a1e8a9","prefixes":{"*":{"product":161}}}, // [Cobalt Group] - {"hash":"ca9dc80141cf19b5","prefixes":{"*":{"product":162}}}, // [Cognitive Match Limited] - {"hash":"d02173b857f779a2","prefixes":{"*":{"product":162}}}, // [Cognitive Match Limited] - {"hash":"987bec8a1c07a02f","prefixes":{"*":{"product":162}}}, // [Cognitive Match Limited] - {"hash":"da18ae94f7dd99ab","prefixes":{"":{"product":163}}}, // [Tagtoo Tech Limited] - {"hash":"5e1256c5e919daf9","prefixes":{"":{"product":164}}}, // [wayStorm Co., Ltd.] - {"hash":"9e92efa06a26b83d","prefixes":{"*":{"product":162}}}, // [Cognitive Match Limited] - {"hash":"cf3c8c24a0eb24a6","prefixes":{"*":{"product":162}}}, // [Cognitive Match Limited] - {"hash":"eac24a30a92872f1","prefixes":{"":{"product":162}}}, // [Cognitive Match Limited] - {"hash":"a508105d922876fe","prefixes":{"":{"product":162}}}, // [Cognitive Match Limited] - {"hash":"b7f1551e6c1615df","prefixes":{"":{"product":162}}}, // [Cognitive Match Limited] - {"hash":"e56a388aae6f063e","prefixes":{"*":{"product":165}}}, // [Collective Media LLC] - {"hash":"adc75d0087df3e89","prefixes":{"":{"product":166}}}, // [ComScore Campaign Essentials (CE)] - {"hash":"6f0ca09cdc147fb0","prefixes":{"":{"product":166}}}, // [ComScore Campaign Essentials (CE)] - {"hash":"11f6ca20d229d8ad","prefixes":{"":{"product":166}}}, // [ComScore Campaign Essentials (CE)] - {"hash":"e4d55634b8d3126d","prefixes":{"":{"product":166}}}, // [ComScore Campaign Essentials (CE)] - {"hash":"6100cc0a622faa8e","prefixes":{"":{"product":167}}}, // [ComScore Validated Campaign Essentials (vCE)] - {"hash":"a30e99f000f781c7","prefixes":{"":{"product":167}}}, // [ComScore Validated Campaign Essentials (vCE)] - {"hash":"1ee7cb55ae2cb071","prefixes":{"":{"product":166}}}, // [ComScore Campaign Essentials (CE)] - {"hash":"7dfd981d4c018953","prefixes":{"":{"product":167}}}, // [ComScore Validated Campaign Essentials (vCE)] - {"hash":"5011cb94579baba5","prefixes":{"*":{"product":168}}}, // [VoiceFive (ComScore)] - {"hash":"a0cff89b286fc309","prefixes":{"":{"product":168}}}, // [VoiceFive (ComScore)] - {"hash":"4782e75d195d3144","prefixes":{"":{"product":168}}}, // [VoiceFive (ComScore)] - {"hash":"e63472329b04aab9","prefixes":{"":{"product":168}}}, // [VoiceFive (ComScore)] - {"hash":"5814e7da11d65131","prefixes":{"":{"product":168}}}, // [VoiceFive (ComScore)] - {"hash":"26c9b653ef6bfb53","prefixes":{"*":{"product":169}}}, // [Connexity LLC] - {"hash":"eb38b3659a232a56","prefixes":{"":{"product":169}}}, // [Connexity LLC] - {"hash":"08abcdb9184877f9","prefixes":{"":{"product":169}}}, // [Connexity LLC] - {"hash":"65a439ff09c9f7dc","prefixes":{"":{"product":169}}}, // [Connexity LLC] - {"hash":"b3afc505f1f5487b","prefixes":{"":{"product":169}}}, // [Connexity LLC] - {"hash":"b35a41328f2a6830","prefixes":{"*":{"product":170}}}, // [Constant Contact] - {"hash":"e7a596af94ad559e","prefixes":{"":{"product":171}}}, // [ContextWeb Inc.] - {"hash":"25ccc25c112607e9","prefixes":{"":{"product":171}}}, // [ContextWeb Inc.] - {"hash":"44e652990824ddee","prefixes":{"":{"product":171}}}, // [ContextWeb Inc.] - {"hash":"8eac48fda4ccaec8","prefixes":{"":{"product":171}}}, // [ContextWeb Inc.] - {"hash":"0b4eee92ed72b991","prefixes":{"ant-":{"product":172}}}, // [Conversive BV] - {"hash":"dae78afe5d5cc699","prefixes":{"":{"product":172}}}, // [Conversive BV] - {"hash":"7729d423a7fc3adf","prefixes":{"*":{"product":96}}}, // [Convertro Inc] - {"hash":"cdff1e442509fafe","prefixes":{"":{"product":173}}}, // [IBM Digital Analytics] - {"hash":"a07829ef9a9d6762","prefixes":{"*":{"product":174}}}, // [Crimtan] - {"hash":"43c19f0523939982","prefixes":{"":{"product":174}}}, // [Crimtan] - {"hash":"2c4f3b76ebfafe80","prefixes":{"":{"product":174}}}, // [Crimtan] - {"hash":"078603692b0949b1","prefixes":{"":{"product":174}}}, // [Crimtan] - {"hash":"aa8844a1d3e7c3aa","prefixes":{"":{"product":174}}}, // [Crimtan] - {"hash":"15ef2aafaa03e60b","prefixes":{"":{"product":174}}}, // [Crimtan] - {"hash":"5f1ef71046a359f7","prefixes":{"":{"product":174}}}, // [Crimtan] - {"hash":"2fb5d0d81abd43be","prefixes":{"":{"product":174}}}, // [Crimtan] - {"hash":"75ce1d1edaf8f426","prefixes":{"":{"product":174}}}, // [Crimtan] - {"hash":"a7b80b09927034f7","prefixes":{"*":{"product":175}}}, // [Criteo] - {"hash":"3a96f385ff402ab6","prefixes":{"*":{"product":175}}}, // [Criteo] - {"hash":"189c3bab631d09cf","prefixes":{"":{"product":176}}}, // [D.A. Consortium Inc. (EffectiveOne)] - {"hash":"3d9109a2e81eee2d","prefixes":{"":{"product":176}}}, // [D.A. Consortium Inc. (EffectiveOne)] - {"hash":"e7170acff5d6fda1","prefixes":{"":{"product":176}}}, // [D.A. Consortium Inc. (EffectiveOne)] - {"hash":"e0496c88da22371f","prefixes":{"":{"product":176}}}, // [D.A. Consortium Inc. (EffectiveOne)] - {"hash":"59ab4e7744543242","prefixes":{"":{"product":177}}}, // [Platform One] - {"hash":"f6b2b21a0a0417b3","prefixes":{"":{"product":177}}}, // [Platform One] - {"hash":"4384a84e6276861a","prefixes":{"*":{"product":178}}}, // [Dapper Inc.] - {"hash":"1ccbc5b91f4c5fc9","prefixes":{"*":{"product":179}}}, // [DataXu Inc.] - {"hash":"4840192a8cb4b1ca","prefixes":{"*":{"product":179}}}, // [DataXu Inc.] - {"hash":"b50faf8c7e5fc38c","prefixes":{"":{"product":180}}}, // [Aperture] - {"hash":"bdcf8ed53f1b3802","prefixes":{"*":{"product":181}}}, // [Rakuten Attribution] - {"hash":"d31e7c4efd1a5191","prefixes":{"*":{"product":181}}}, // [Rakuten Attribution] - {"hash":"68318c6d8f72133b","prefixes":{"*":{"product":181}}}, // [Rakuten Attribution] - {"hash":"c0c4eb0ce58ef4b1","prefixes":{"*":{"product":181}}}, // [Rakuten Attribution] - {"hash":"ae713ee10231204e","prefixes":{"*":{"product":182}}}, // [AdAction] - {"hash":"e4282cef85ee5728","prefixes":{"":{"product":183}}}, // [Demandbase Inc.] - {"hash":"79f6c3d16c278e94","prefixes":{"":{"product":183}}}, // [Demandbase Inc.] - {"hash":"13e7a7b6c40ef05b","prefixes":{"":{"product":183}}}, // [Demandbase Inc.] - {"hash":"57e736fc045f8fbd","prefixes":{"":{"product":183}}}, // [Demandbase Inc.] - {"hash":"82137a4a2aa17f33","prefixes":{"*":{"product":184}}}, // [Omniture] - {"hash":"ddc305710749f5b7","prefixes":{"*":{"product":184}}}, // [Omniture] - {"hash":"3cd74441fc237226","prefixes":{"*":{"product":184}}}, // [Omniture] - {"hash":"5b40000c858b730d","prefixes":{"":{"product":185}}}, // [Rovion, Inc.] - {"hash":"47d66d29363322cd","prefixes":{"":{"product":186}}}, // [AdHui.com LLC] - {"hash":"10a0efb999eedf90","prefixes":{"":{"product":186}}}, // [AdHui.com LLC] - {"hash":"b1bf29ae383ea0cd","prefixes":{"":{"product":187}}}, // [Bidlab sp. z o.o] - {"hash":"baa26df04dbce196","prefixes":{"":{"product":187}}}, // [Bidlab sp. z o.o] - {"hash":"c3f807fb12d64ef3","prefixes":{"":{"product":188}}}, // [CyberAgent Inc.] - {"hash":"8caed248711d066a","prefixes":{"":{"product":188}}}, // [CyberAgent Inc.] - {"hash":"03524472b71baf6f","prefixes":{"":{"product":189}}}, // [Relay42 Technology B.V.] - {"hash":"c26a754afcf8496d","prefixes":{"":{"product":189}}}, // [Relay42 Technology B.V.] - {"hash":"fa7ea4c2400b9304","prefixes":{"":{"product":189}}}, // [Relay42 Technology B.V.] - {"hash":"f91d12ea09409395","prefixes":{"":{"product":189}}}, // [Relay42 Technology B.V.] - {"hash":"a3404139a451726c","prefixes":{"":{"product":190}}}, // [Nielsen Digital Ad Ratings (JS)] - {"hash":"072f7bf8cea1803c","prefixes":{"":{"product":190}}}, // [Nielsen Digital Ad Ratings (JS)] - {"hash":"8a6e324bbf4e02dc","prefixes":{"":{"product":190}}}, // [Nielsen Digital Ad Ratings (JS)] - {"hash":"e59faa8d364c3ad2","prefixes":{"":{"product":190}}}, // [Nielsen Digital Ad Ratings (JS)] - {"hash":"fe39de2cc1550ee8","prefixes":{"":{"product":190}}}, // [Nielsen Digital Ad Ratings (JS)] - {"hash":"41808f1a9bcd4cdf","prefixes":{"":{"product":190}}}, // [Nielsen Digital Ad Ratings (JS)] - {"hash":"1774fa7feee9a3ba","prefixes":{"":{"product":191}}}, // [Nielsen (Audience Measurement Platform)] - {"hash":"8bcfafa30bb9a496","prefixes":{"":{"product":192}}}, // [Nielsen OBE (Vizu)] - {"hash":"04a15100eebd5238","prefixes":{"":{"product":193}}}, // [Nielsen (Sales Effect)] - {"hash":"37669b02a11574d6","prefixes":{"":{"product":193}}}, // [Nielsen (Sales Effect)] - {"hash":"b0e609cae76778ef","prefixes":{"":{"product":193}}}, // [Nielsen (Sales Effect)] - {"hash":"8602961190244c78","prefixes":{"":{"product":193}}}, // [Nielsen (Sales Effect)] - {"hash":"cf6160cc55083e3f","prefixes":{"":{"product":193}}}, // [Nielsen (Sales Effect)] - {"hash":"d8e0147c7067e033","prefixes":{"":{"product":193}}}, // [Nielsen (Sales Effect)] - {"hash":"fa4e638adbad854a","prefixes":{"":{"product":193}}}, // [Nielsen (Sales Effect)] - {"hash":"bfc104d8ae540578","prefixes":{"":{"product":193}}}, // [Nielsen (Sales Effect)] - {"hash":"a77b609ecb948524","prefixes":{"":{"product":193}}}, // [Nielsen (Sales Effect)] - {"hash":"5b2d6c6512b90826","prefixes":{"":{"product":193}}}, // [Nielsen (Sales Effect)] - {"hash":"3f0eefad5865a4ed","prefixes":{"":{"product":194}}}, // [Ohana Media India Private Limited] - {"hash":"ba149fc47bfe9e3c","prefixes":{"":{"product":194}}}, // [Ohana Media India Private Limited] - {"hash":"cfe9fa124d3faa0b","prefixes":{"*":{"product":195}}}, // [DisplayCDN] - {"hash":"3f8d8705aeaf2a69","prefixes":{"":{"product":196}}}, // [Avail Intelligence] - {"hash":"3aa373d150e55bb8","prefixes":{"":{"product":196}}}, // [Avail Intelligence] - {"hash":"01168e37c54407ec","prefixes":{"":{"product":196}}}, // [Avail Intelligence] - {"hash":"9d0088e875d03291","prefixes":{"":{"product":197}}}, // [Adobe Scene 7] - {"hash":"7892719f65634daf","prefixes":{"":{"product":198}}}, // [Asda] - {"hash":"76913c314e7299f2","prefixes":{"":{"product":199}}}, // [Adsfactor Limited] - {"hash":"ec3d301a1049a29c","prefixes":{"":{"product":200}}}, // [Trademob GmbH] - {"hash":"0407237113d1e01a","prefixes":{"":{"product":201}}}, // [Zamplus Technology Co., Ltd.] - {"hash":"3c2b08727db96f57","prefixes":{"":{"product":201}}}, // [Zamplus Technology Co., Ltd.] - {"hash":"28d8cdf30ea5e75d","prefixes":{"":{"product":201}}}, // [Zamplus Technology Co., Ltd.] - {"hash":"4ba6006c59a0afb3","prefixes":{"":{"product":201}}}, // [Zamplus Technology Co., Ltd.] - {"hash":"34b0d82da56a6e14","prefixes":{"":{"product":201}}}, // [Zamplus Technology Co., Ltd.] - {"hash":"c9293b8324f3a30f","prefixes":{"":{"product":201}}}, // [Zamplus Technology Co., Ltd.] - {"hash":"78ad5395bf22ddd5","prefixes":{"":{"product":201}}}, // [Zamplus Technology Co., Ltd.] - {"hash":"b0a5ecf647236d2a","prefixes":{"*":{"product":202}}}, // [Telemetry Limited] - {"hash":"7d7cd86e56968411","prefixes":{"*":{"product":202}}}, // [Telemetry Limited] - {"hash":"ccaf0946d1809711","prefixes":{"*":{"product":202}}}, // [Telemetry Limited] - {"hash":"d08bcd58e153f333","prefixes":{"*":{"product":203}}}, // [AdPilot] - {"hash":"c1ee73ca85937956","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"b3ee9fcc7f773476","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"0dededd99d2513e4","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"efd59a0198028c96","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"b43b6c20f3008842","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"5d96f09a039b26e6","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"039408a17f3d50d7","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"16d696fe52cae068","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"ebb9da6e533fc7e4","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"c8afb150eb1b6ac1","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"1e21c92ae4d08330","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"07ef420d707be72c","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"3d9fb95e3108b648","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"938e971e186be4f8","prefixes":{"":{"product":203}}}, // [AdPilot] - {"hash":"94682de65e11f128","prefixes":{"":{"product":204}}}, // [ebookers] - {"hash":"32548cc45dcf9e95","prefixes":{"":{"product":204}}}, // [ebookers] - {"hash":"baa9bf6209e38821","prefixes":{"":{"product":204}}}, // [ebookers] - {"hash":"25a263451425f7e3","prefixes":{"*":{"product":205}}}, // [Mashero GmbH] - {"hash":"4871ba81fe73b693","prefixes":{"":{"product":206}}}, // [4wMarketPlace Srl] - {"hash":"f95f038fea1148ab","prefixes":{"*":{"product":207}}}, // [Meetic Partners] - {"hash":"8c555d8aa0a96ecc","prefixes":{"*":{"product":208}}}, // [Adara Media] - {"hash":"a31f9bce31634750","prefixes":{"":{"product":209}}}, // [Adledge] - {"hash":"bb0d6b4eac177896","prefixes":{"":{"product":209}}}, // [Adledge] - {"hash":"02712dc83414bc52","prefixes":{"":{"product":209}}}, // [Adledge] - {"hash":"03cfa92cdadd6c20","prefixes":{"":{"product":209}}}, // [Adledge] - {"hash":"4d8640e955380082","prefixes":{"":{"product":209}}}, // [Adledge] - {"hash":"42ab78ba8d28d0d9","prefixes":{"":{"product":209}}}, // [Adledge] - {"hash":"113f35a595990303","prefixes":{"":{"product":209}}}, // [Adledge] - {"hash":"9566d797c39bca8e","prefixes":{"":{"product":209}}}, // [Adledge] - {"hash":"caab6878aaf1b900","prefixes":{"":{"product":209}}}, // [Adledge] - {"hash":"13581af42d29c3fd","prefixes":{"":{"product":209}}}, // [Adledge] - {"hash":"8ad4e9b59b6cfebf","prefixes":{"":{"product":209}}}, // [Adledge] - {"hash":"025223bda779fb50","prefixes":{"":{"product":210}}}, // [Adledge: Ad Swapping] - {"hash":"6c7970d8fe11d946","prefixes":{"":{"product":211}}}, // [LifeStreet Corportation] - {"hash":"226c377d19c24dca","prefixes":{"":{"product":211}}}, // [LifeStreet Corportation] - {"hash":"bc64475cc35aba69","prefixes":{"":{"product":211}}}, // [LifeStreet Corportation] - {"hash":"8a184297457cd4e1","prefixes":{"":{"product":211}}}, // [LifeStreet Corportation] - {"hash":"900f97a5320abcc7","prefixes":{"":{"product":212}}}, // [AdCirrus] - {"hash":"39b102bb2f01d1b4","prefixes":{"":{"product":213}}}, // [Dimestore] - {"hash":"a144c6442bbc8a0a","prefixes":{"":{"product":213}}}, // [Dimestore] - {"hash":"8020cac4e8fee023","prefixes":{"":{"product":213}}}, // [Dimestore] - {"hash":"2dcefe5fe106e478","prefixes":{"*":{"product":214}}}, // [GfK SE] - {"hash":"d8f9a95c0ea00853","prefixes":{"*":{"product":213}}}, // [Dimestore] - {"hash":"829fbeefc45bca87","prefixes":{"*":{"product":215}}}, // [Conversant CRM] - {"hash":"357a04f93d25ae56","prefixes":{"cdn":{"product":216},"log":{"product":216},"tps":{"product":216},"rtb":{"product":217}}}, // [DoubleVerify Inc.] [DoubleVerify Inc.] [DoubleVerify Inc.] [DoubleVerify Inc. (BrandShield): Ad Swapping] - {"hash":"e88f040d82035294","prefixes":{"":{"product":216}}}, // [DoubleVerify Inc.] - {"hash":"a378f9f7b3d5241c","prefixes":{"*":{"product":218}}}, // [Dynamic Video LLC] - {"hash":"665ab90fa95fb304","prefixes":{"":{"product":218}}}, // [Dynamic Video LLC] - {"hash":"1358623e271c4d67","prefixes":{"":{"product":218}}}, // [Dynamic Video LLC] - {"hash":"a11e7a579fa98970","prefixes":{"*":{"product":219}}}, // [Think RealTime, LLC] - {"hash":"9225aaedf058b2a2","prefixes":{"":{"product":220}}}, // [Effective Measure] - {"hash":"36703887ac49b84b","prefixes":{"":{"product":220}}}, // [Effective Measure] - {"hash":"eabfdf13f38b7671","prefixes":{"*":{"product":221}}}, // [Adobe Media Optimizer] - {"hash":"e6c60b5e8bab7589","prefixes":{"*":{"product":221}}}, // [Adobe Media Optimizer] - {"hash":"d4ca4e6c8a0bedf0","prefixes":{"*":{"product":221}}}, // [Adobe Media Optimizer] - {"hash":"2e2899c7688fb6b3","prefixes":{"":{"product":222}}}, // [Effiliation] - {"hash":"3a8f463e807ab596","prefixes":{"":{"product":222}}}, // [Effiliation] - {"hash":"4c49524999954857","prefixes":{"":{"product":222}}}, // [Effiliation] - {"hash":"99a4dc2c14dac648","prefixes":{"*":{"product":223}}}, // [EmediateAd] - {"hash":"eb4d633002c35102","prefixes":{"*":{"product":223}}}, // [EmediateAd] - {"hash":"a4155988849d9899","prefixes":{"":{"product":223}}}, // [EmediateAd] - {"hash":"a29dc15ab67e4109","prefixes":{"*":{"product":223}}}, // [EmediateAd] - {"hash":"244ed2f383a41c11","prefixes":{"*":{"product":223}}}, // [EmediateAd] - {"hash":"f1d41523d742a4c4","prefixes":{"*":{"product":224}}}, // [engage:BDR Inc.] - {"hash":"0c985c5bee46dcca","prefixes":{"":{"product":224}}}, // [engage:BDR Inc.] - {"hash":"6f92a4165360659f","prefixes":{"":{"product":224}}}, // [engage:BDR Inc.] - {"hash":"e65b14b1de797d5e","prefixes":{"":{"product":224}}}, // [engage:BDR Inc.] - {"hash":"8908058eec675b88","prefixes":{"*":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"dae357b5105fb541","prefixes":{"*":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"7e5c5286bc6286af","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"6459463a599e26cf","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"d49c14999963fa7c","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"f7508ecdfd1b76f8","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"747ac3c2114de916","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"5445e9650966f2c9","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"b701368b6964f28f","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"b8d4853208b3d665","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"a3c05ce1535a1bb0","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"4113e02fa7f80330","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"1ec6c8299f47c92d","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"6213db1c94ff78b4","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"afdce1f639f05293","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"c00800107f132ba6","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"f989cf5678a6cd73","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"7248d6bb2e2d2812","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"5decec320495d46c","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"ffffd176ae6095cd","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"a0ead46cc7797fc4","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"d1b36183709cf97c","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"f08e0f4d46762277","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"1082450fce471aec","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"0c44a72359ff962b","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"c6ced7239fa526b8","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"bcd4afcb16a1bf83","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"c4629483e0f61849","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"3a8a51dc5059eb82","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"10d4846e0b0f6213","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"8e03e96054cde307","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"d1c591453eeceb89","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"a9ee5e0b07924cbe","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"4909d0f68d7f7dd5","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"1954dcac7d36e9a9","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"855fab1b44b2cc38","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"9a977de69b69e767","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"32c7999b9a328d48","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"675aab76d51e4be4","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"454f35d478088b2f","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"af6f37ce228476e6","prefixes":{"*":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"dfa2565386557dbb","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"7bdee1b08b69b7fa","prefixes":{"*":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"259e3811976143d2","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"29633cedc9fc7e43","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"758fea4a1e3ad80f","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"cf9bd7435c526efc","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"913928e477b69d4d","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] - {"hash":"391c770feaa49fc6","prefixes":{"":{"product":4}}}, // [Eulerian Technologies SARL] + {"hash":"b9a83d8bd4f31543","prefixes":{"":{"product":124,"type":0}}}, // [Mojiva] + {"hash":"2a1b04ad13f24350","prefixes":{"":{"product":124,"type":0}}}, // [Mojiva] + {"hash":"a3c6b5ffd4fe1547","prefixes":{"":{"product":125,"type":0}}}, // [Mocean mobile, Inc.] + {"hash":"0d52aafa33281228","prefixes":{"":{"product":126,"type":0}}}, // [Phluant] + {"hash":"655e31ecb8719994","prefixes":{"":{"product":126,"type":0}}}, // [Phluant] + {"hash":"dca17bd2f3edb917","prefixes":{"":{"product":126,"type":0}}}, // [Phluant] + {"hash":"53de58004f88a1c2","prefixes":{"*":{"product":127,"type":0}}}, // [AdSpirit] + {"hash":"6a1ebf671194b458","prefixes":{"*":{"product":127,"type":0}}}, // [AdSpirit] + {"hash":"6ae5a4877aab564f","prefixes":{"":{"product":127,"type":0}}}, // [AdSpirit] + {"hash":"9dcf8d17ea42466e","prefixes":{"*":{"product":128,"type":0}}}, // [ConvertMedia Ltd.] + {"hash":"32e0acbf3d2ecfcf","prefixes":{"*":{"product":128,"type":0}}}, // [ConvertMedia Ltd.] + {"hash":"708d275466f5230b","prefixes":{"*":{"product":128,"type":0}}}, // [ConvertMedia Ltd.] + {"hash":"7532d83428e05417","prefixes":{"*":{"product":128,"type":0}}}, // [ConvertMedia Ltd.] + {"hash":"3258e49c5f504307","prefixes":{"*":{"product":128,"type":0}}}, // [ConvertMedia Ltd.] + {"hash":"2c381faaa3144a37","prefixes":{"*":{"product":128,"type":0}}}, // [ConvertMedia Ltd.] + {"hash":"776a64cc3a9c6f81","prefixes":{"*":{"product":128,"type":0}}}, // [ConvertMedia Ltd.] + {"hash":"d38247a8e8d14a7c","prefixes":{"*":{"product":128,"type":0}}}, // [ConvertMedia Ltd.] + {"hash":"50e5ca70dbb69c03","prefixes":{"":{"product":128,"type":0}}}, // [ConvertMedia Ltd.] + {"hash":"c1dfde405c173e3b","prefixes":{"":{"product":128,"type":0}}}, // [ConvertMedia Ltd.] + {"hash":"5bce52b0f221aac2","prefixes":{"":{"product":128,"type":0}}}, // [ConvertMedia Ltd.] + {"hash":"5a0e5730145156e2","prefixes":{"":{"product":128,"type":0}}}, // [ConvertMedia Ltd.] + {"hash":"c081c626ad2c0f1f","prefixes":{"":{"product":128,"type":0}}}, // [ConvertMedia Ltd.] + {"hash":"a31f53c0c58e67c0","prefixes":{"":{"product":129,"type":0}}}, // [ATK Media GmbH] + {"hash":"514b4f19cbdabb49","prefixes":{"":{"product":129,"type":0}}}, // [ATK Media GmbH] + {"hash":"264493bb5046087f","prefixes":{"":{"product":129,"type":0}}}, // [ATK Media GmbH] + {"hash":"f4e40d6832493420","prefixes":{"":{"product":129,"type":0}}}, // [ATK Media GmbH] + {"hash":"126b6492c0b1b53a","prefixes":{"*":{"product":130,"type":0}}}, // [Atlas] + {"hash":"0493e6c92c59fd4d","prefixes":{"":{"product":130,"type":0}}}, // [Atlas] + {"hash":"d6d40b4417fefcf6","prefixes":{"":{"product":130,"type":0}}}, // [Atlas] + {"hash":"0b16a7cf8dcb70ee","prefixes":{"*":{"product":131,"type":0}}}, // [AudienceScience] + {"hash":"edbae80f2449aaee","prefixes":{"":{"product":132,"type":0}}}, // [BeWebMedia] + {"hash":"c1196b1418bf9de9","prefixes":{"*":{"product":133,"type":0}}}, // [Bidalpha Inc.] + {"hash":"87016c0f34162bc6","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"2db3b8adb9c37590","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"a10756ccfb034a50","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"1ea7188c5cc22ccf","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"c70dfe98c3735972","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"05aa49d024d6d67c","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"27c08401857f47aa","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"9a569266b426d074","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"5a764c1f870e4e38","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"64b993405c35034f","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"afe660eca2d01217","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"cd398b1d3fe6caf4","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"bb2cf5a27552ba10","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"b79ee8778f5b56d6","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"cae97638b357a30e","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"2c552297aa3abdf1","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"75bbf901ed30d891","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"365bc710167be24c","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"49849f3497cc7ff5","prefixes":{"":{"product":134,"type":0}}}, // [AdGear Technologies Inc.] + {"hash":"14bb8555907973f5","prefixes":{"":{"product":135,"type":1}}}, // [BlueKai] + {"hash":"db6cb381e20a210a","prefixes":{"":{"product":135,"type":1}}}, // [BlueKai] + {"hash":"8e4e07437ae4b61c","prefixes":{"*":{"product":136,"type":0}}}, // [Bluestreak] + {"hash":"4bb6a17c8b5ec2e7","prefixes":{"":{"product":137,"type":0}}}, // [blurbIQ] + {"hash":"4aefb106f857a0de","prefixes":{"":{"product":137,"type":0}}}, // [blurbIQ] + {"hash":"a7b4452428f93120","prefixes":{"":{"product":137,"type":0}}}, // [blurbIQ] + {"hash":"38f01d050feb50e8","prefixes":{"":{"product":137,"type":0}}}, // [blurbIQ] + {"hash":"d4ab70ba7caf1ed7","prefixes":{"":{"product":138,"type":0}}}, // [Brand.net] + {"hash":"94655d9cadd8e829","prefixes":{"":{"product":138,"type":0}}}, // [Brand.net] + {"hash":"f3347a75843fd9c6","prefixes":{"":{"product":138,"type":0}}}, // [Brand.net] + {"hash":"60e2856d32c1da23","prefixes":{"*":{"product":139,"type":0}}}, // [Brandscreen Inc.] + {"hash":"16460b1ac6e3b229","prefixes":{"*":{"product":140,"type":0}}}, // [BrightRoll Inc.] + {"hash":"814fef93d6498b58","prefixes":{"*":{"product":140,"type":0}}}, // [BrightRoll Inc.] + {"hash":"72fc1d7c40b9af03","prefixes":{"":{"product":141,"type":0}}}, // [Brightroll Inc.] + {"hash":"80f8944423cc936c","prefixes":{"*":{"product":142,"type":0}}}, // [Vindico] + {"hash":"bf2db20b09960c7b","prefixes":{"":{"product":142,"type":0}}}, // [Vindico] + {"hash":"e180a56826bf4ba6","prefixes":{"*":{"product":143,"type":2}}}, // [Edgesuite] + {"hash":"1e90c625da6683a5","prefixes":{"":{"product":144,"type":0}}}, // [Spark Flow S.A.] + {"hash":"d385e514fe92e6d9","prefixes":{"":{"product":145,"type":0}}}, // [Aarki, Inc.] + {"hash":"4646e46d55455ffe","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"a8c5f49831b36ab9","prefixes":{"*":{"product":147,"type":0}}}, // [Burst Media LLC d/b/a AdConductor] + {"hash":"f22276edaf005231","prefixes":{"*":{"product":148,"type":0}}}, // [Advertising.com Dynamic Retargeter] + {"hash":"220db526eb84992d","prefixes":{"*":{"product":149,"type":0}}}, // [NetAffiliation] + {"hash":"cda3d9612026866c","prefixes":{"*":{"product":149,"type":0}}}, // [NetAffiliation] + {"hash":"9f8018bcbf15a592","prefixes":{"*":{"product":150,"type":1}}}, // [C3 Metrics Inc.] + {"hash":"78ec342986654215","prefixes":{"":{"product":150,"type":1}}}, // [C3 Metrics Inc.] + {"hash":"e4ad94837095a9bc","prefixes":{"*":{"product":150,"type":1}}}, // [C3 Metrics Inc.] + {"hash":"32401b2118eff57a","prefixes":{"":{"product":151,"type":0}}}, // [CAPITALDATA (SARL)] + {"hash":"a5f9db92cb5aeb3e","prefixes":{"":{"product":151,"type":0}}}, // [CAPITALDATA (SARL)] + {"hash":"ae12db7e0621ec0b","prefixes":{"*":{"product":151,"type":0}}}, // [CAPITALDATA (SARL)] + {"hash":"d7c4970fde31fd62","prefixes":{"*":{"product":152,"type":0}}}, // [e-Planning] + {"hash":"20cadab7abdae752","prefixes":{"*":{"product":153,"type":0}}}, // [Chango Inc.] + {"hash":"38363f7ac872a916","prefixes":{"":{"product":154,"type":0}}}, // [Chango] + {"hash":"114215c6a5b66e37","prefixes":{"":{"product":154,"type":0}}}, // [Chango] + {"hash":"1ab7b29d135c11fc","prefixes":{"":{"product":155,"type":1}}}, // [Channel Intelligence] + {"hash":"6e8e21cf50387d5b","prefixes":{"":{"product":155,"type":1}}}, // [Channel Intelligence] + {"hash":"cbd8c46855691ac9","prefixes":{"*":{"product":155,"type":1}}}, // [Channel Intelligence] + {"hash":"8bde0d3ba731b24b","prefixes":{"":{"product":155,"type":1}}}, // [Channel Intelligence] + {"hash":"d415664f4794184e","prefixes":{"":{"product":155,"type":1}}}, // [Channel Intelligence] + {"hash":"bc8edad5208e36aa","prefixes":{"*":{"product":155,"type":1}}}, // [Channel Intelligence] + {"hash":"00900e4af3795b7d","prefixes":{"":{"product":156,"type":1}}}, // [Chartbeat Inc] + {"hash":"dddd416675de98d6","prefixes":{"":{"product":156,"type":1}}}, // [Chartbeat Inc] + {"hash":"085835cbbea3af5b","prefixes":{"":{"product":156,"type":1}}}, // [Chartbeat Inc] + {"hash":"0a5fd555ed989cf1","prefixes":{"":{"product":156,"type":1}}}, // [Chartbeat Inc] + {"hash":"38e6dfa04599d610","prefixes":{"":{"product":156,"type":1}}}, // [Chartbeat Inc] + {"hash":"282ab213b57d8196","prefixes":{"":{"product":156,"type":1}}}, // [Chartbeat Inc] + {"hash":"465922959fd197de","prefixes":{"*":{"product":157,"type":0}}}, // [Choicestream Inc.] + {"hash":"07b64c6d94aaeede","prefixes":{"*":{"product":158,"type":0}}}, // [AddThis, Inc] + {"hash":"8285ed75ebbab1bf","prefixes":{"*":{"product":158,"type":0}}}, // [AddThis, Inc] + {"hash":"397da235f9c6c4dc","prefixes":{"*":{"product":159,"type":0}}}, // [Platform 161] + {"hash":"3e4380669a97a9da","prefixes":{"":{"product":159,"type":0}}}, // [Platform 161] + {"hash":"0cf7c3db283e4fde","prefixes":{"":{"product":160,"type":0}}}, // [ClickPoint] + {"hash":"e3f610966ee4998e","prefixes":{"":{"product":161,"type":0}}}, // [Cobalt Group] + {"hash":"5458332ef0eff5a0","prefixes":{"":{"product":161,"type":0}}}, // [Cobalt Group] + {"hash":"755391831ca3c171","prefixes":{"*":{"product":161,"type":0}}}, // [Cobalt Group] + {"hash":"82d7785d13750576","prefixes":{"*":{"product":161,"type":0}}}, // [Cobalt Group] + {"hash":"f1b10b28e8a1e8a9","prefixes":{"*":{"product":161,"type":0}}}, // [Cobalt Group] + {"hash":"ca9dc80141cf19b5","prefixes":{"*":{"product":162,"type":0}}}, // [Cognitive Match Limited] + {"hash":"d02173b857f779a2","prefixes":{"*":{"product":162,"type":0}}}, // [Cognitive Match Limited] + {"hash":"987bec8a1c07a02f","prefixes":{"*":{"product":162,"type":0}}}, // [Cognitive Match Limited] + {"hash":"da18ae94f7dd99ab","prefixes":{"":{"product":163,"type":0}}}, // [Tagtoo Tech Limited] + {"hash":"5e1256c5e919daf9","prefixes":{"":{"product":164,"type":0}}}, // [wayStorm Co., Ltd.] + {"hash":"9e92efa06a26b83d","prefixes":{"*":{"product":162,"type":0}}}, // [Cognitive Match Limited] + {"hash":"cf3c8c24a0eb24a6","prefixes":{"*":{"product":162,"type":0}}}, // [Cognitive Match Limited] + {"hash":"eac24a30a92872f1","prefixes":{"":{"product":162,"type":0}}}, // [Cognitive Match Limited] + {"hash":"a508105d922876fe","prefixes":{"":{"product":162,"type":0}}}, // [Cognitive Match Limited] + {"hash":"b7f1551e6c1615df","prefixes":{"":{"product":162,"type":0}}}, // [Cognitive Match Limited] + {"hash":"e56a388aae6f063e","prefixes":{"*":{"product":165,"type":0}}}, // [Collective Media LLC] + {"hash":"adc75d0087df3e89","prefixes":{"":{"product":166,"type":1}}}, // [ComScore Campaign Essentials (CE)] + {"hash":"6f0ca09cdc147fb0","prefixes":{"":{"product":166,"type":1}}}, // [ComScore Campaign Essentials (CE)] + {"hash":"11f6ca20d229d8ad","prefixes":{"":{"product":166,"type":1}}}, // [ComScore Campaign Essentials (CE)] + {"hash":"e4d55634b8d3126d","prefixes":{"":{"product":166,"type":1}}}, // [ComScore Campaign Essentials (CE)] + {"hash":"6100cc0a622faa8e","prefixes":{"":{"product":167,"type":1}}}, // [ComScore Validated Campaign Essentials (vCE)] + {"hash":"a30e99f000f781c7","prefixes":{"":{"product":167,"type":1}}}, // [ComScore Validated Campaign Essentials (vCE)] + {"hash":"1ee7cb55ae2cb071","prefixes":{"":{"product":166,"type":1}}}, // [ComScore Campaign Essentials (CE)] + {"hash":"7dfd981d4c018953","prefixes":{"":{"product":167,"type":1}}}, // [ComScore Validated Campaign Essentials (vCE)] + {"hash":"5011cb94579baba5","prefixes":{"*":{"product":168,"type":1}}}, // [VoiceFive (ComScore)] + {"hash":"a0cff89b286fc309","prefixes":{"":{"product":168,"type":1}}}, // [VoiceFive (ComScore)] + {"hash":"4782e75d195d3144","prefixes":{"":{"product":168,"type":1}}}, // [VoiceFive (ComScore)] + {"hash":"e63472329b04aab9","prefixes":{"":{"product":168,"type":1}}}, // [VoiceFive (ComScore)] + {"hash":"5814e7da11d65131","prefixes":{"":{"product":168,"type":1}}}, // [VoiceFive (ComScore)] + {"hash":"26c9b653ef6bfb53","prefixes":{"*":{"product":169,"type":0}}}, // [Connexity LLC] + {"hash":"eb38b3659a232a56","prefixes":{"":{"product":169,"type":0}}}, // [Connexity LLC] + {"hash":"08abcdb9184877f9","prefixes":{"":{"product":169,"type":0}}}, // [Connexity LLC] + {"hash":"65a439ff09c9f7dc","prefixes":{"":{"product":169,"type":0}}}, // [Connexity LLC] + {"hash":"b3afc505f1f5487b","prefixes":{"":{"product":169,"type":0}}}, // [Connexity LLC] + {"hash":"b35a41328f2a6830","prefixes":{"*":{"product":170,"type":1}}}, // [Constant Contact] + {"hash":"e7a596af94ad559e","prefixes":{"":{"product":171,"type":0}}}, // [ContextWeb Inc.] + {"hash":"25ccc25c112607e9","prefixes":{"":{"product":171,"type":0}}}, // [ContextWeb Inc.] + {"hash":"44e652990824ddee","prefixes":{"":{"product":171,"type":0}}}, // [ContextWeb Inc.] + {"hash":"8eac48fda4ccaec8","prefixes":{"":{"product":171,"type":0}}}, // [ContextWeb Inc.] + {"hash":"0b4eee92ed72b991","prefixes":{"ant-":{"product":172,"type":0}}}, // [Conversive BV] + {"hash":"dae78afe5d5cc699","prefixes":{"":{"product":172,"type":0}}}, // [Conversive BV] + {"hash":"7729d423a7fc3adf","prefixes":{"*":{"product":96,"type":1}}}, // [Convertro Inc] + {"hash":"cdff1e442509fafe","prefixes":{"":{"product":173,"type":1}}}, // [IBM Digital Analytics] + {"hash":"a07829ef9a9d6762","prefixes":{"*":{"product":174,"type":0}}}, // [Crimtan] + {"hash":"43c19f0523939982","prefixes":{"":{"product":174,"type":0}}}, // [Crimtan] + {"hash":"2c4f3b76ebfafe80","prefixes":{"":{"product":174,"type":0}}}, // [Crimtan] + {"hash":"078603692b0949b1","prefixes":{"":{"product":174,"type":0}}}, // [Crimtan] + {"hash":"aa8844a1d3e7c3aa","prefixes":{"":{"product":174,"type":0}}}, // [Crimtan] + {"hash":"15ef2aafaa03e60b","prefixes":{"":{"product":174,"type":0}}}, // [Crimtan] + {"hash":"5f1ef71046a359f7","prefixes":{"":{"product":174,"type":0}}}, // [Crimtan] + {"hash":"2fb5d0d81abd43be","prefixes":{"":{"product":174,"type":0}}}, // [Crimtan] + {"hash":"75ce1d1edaf8f426","prefixes":{"":{"product":174,"type":0}}}, // [Crimtan] + {"hash":"a7b80b09927034f7","prefixes":{"*":{"product":175,"type":0}}}, // [Criteo] + {"hash":"3a96f385ff402ab6","prefixes":{"*":{"product":175,"type":0}}}, // [Criteo] + {"hash":"189c3bab631d09cf","prefixes":{"":{"product":176,"type":0}}}, // [D.A. Consortium Inc. (EffectiveOne)] + {"hash":"3d9109a2e81eee2d","prefixes":{"":{"product":176,"type":0}}}, // [D.A. Consortium Inc. (EffectiveOne)] + {"hash":"e7170acff5d6fda1","prefixes":{"":{"product":176,"type":0}}}, // [D.A. Consortium Inc. (EffectiveOne)] + {"hash":"e0496c88da22371f","prefixes":{"":{"product":176,"type":0}}}, // [D.A. Consortium Inc. (EffectiveOne)] + {"hash":"59ab4e7744543242","prefixes":{"":{"product":177,"type":0}}}, // [Platform One] + {"hash":"f6b2b21a0a0417b3","prefixes":{"":{"product":177,"type":0}}}, // [Platform One] + {"hash":"4384a84e6276861a","prefixes":{"*":{"product":178,"type":0}}}, // [Dapper Inc.] + {"hash":"1ccbc5b91f4c5fc9","prefixes":{"*":{"product":179,"type":0}}}, // [DataXu Inc.] + {"hash":"4840192a8cb4b1ca","prefixes":{"*":{"product":179,"type":0}}}, // [DataXu Inc.] + {"hash":"b50faf8c7e5fc38c","prefixes":{"":{"product":180,"type":1}}}, // [Aperture] + {"hash":"bdcf8ed53f1b3802","prefixes":{"*":{"product":181,"type":1}}}, // [Rakuten Attribution] + {"hash":"d31e7c4efd1a5191","prefixes":{"*":{"product":181,"type":1}}}, // [Rakuten Attribution] + {"hash":"68318c6d8f72133b","prefixes":{"*":{"product":181,"type":1}}}, // [Rakuten Attribution] + {"hash":"c0c4eb0ce58ef4b1","prefixes":{"*":{"product":181,"type":1}}}, // [Rakuten Attribution] + {"hash":"ae713ee10231204e","prefixes":{"*":{"product":182,"type":0}}}, // [AdAction] + {"hash":"e4282cef85ee5728","prefixes":{"":{"product":183,"type":0}}}, // [Demandbase Inc.] + {"hash":"79f6c3d16c278e94","prefixes":{"":{"product":183,"type":0}}}, // [Demandbase Inc.] + {"hash":"13e7a7b6c40ef05b","prefixes":{"":{"product":183,"type":0}}}, // [Demandbase Inc.] + {"hash":"57e736fc045f8fbd","prefixes":{"":{"product":183,"type":0}}}, // [Demandbase Inc.] + {"hash":"82137a4a2aa17f33","prefixes":{"*":{"product":184,"type":0}}}, // [Omniture] + {"hash":"ddc305710749f5b7","prefixes":{"*":{"product":184,"type":0}}}, // [Omniture] + {"hash":"3cd74441fc237226","prefixes":{"*":{"product":184,"type":0}}}, // [Omniture] + {"hash":"5b40000c858b730d","prefixes":{"":{"product":185,"type":0}}}, // [Rovion, Inc.] + {"hash":"47d66d29363322cd","prefixes":{"":{"product":186,"type":0}}}, // [AdHui.com LLC] + {"hash":"10a0efb999eedf90","prefixes":{"":{"product":186,"type":0}}}, // [AdHui.com LLC] + {"hash":"b1bf29ae383ea0cd","prefixes":{"":{"product":187,"type":0}}}, // [Bidlab sp. z o.o] + {"hash":"baa26df04dbce196","prefixes":{"":{"product":187,"type":0}}}, // [Bidlab sp. z o.o] + {"hash":"c3f807fb12d64ef3","prefixes":{"":{"product":188,"type":0}}}, // [CyberAgent Inc.] + {"hash":"8caed248711d066a","prefixes":{"":{"product":188,"type":0}}}, // [CyberAgent Inc.] + {"hash":"03524472b71baf6f","prefixes":{"":{"product":189,"type":0}}}, // [Relay42 Technology B.V.] + {"hash":"c26a754afcf8496d","prefixes":{"":{"product":189,"type":0}}}, // [Relay42 Technology B.V.] + {"hash":"fa7ea4c2400b9304","prefixes":{"":{"product":189,"type":0}}}, // [Relay42 Technology B.V.] + {"hash":"f91d12ea09409395","prefixes":{"":{"product":189,"type":0}}}, // [Relay42 Technology B.V.] + {"hash":"a3404139a451726c","prefixes":{"":{"product":190,"type":1}}}, // [Nielsen Digital Ad Ratings (JS)] + {"hash":"072f7bf8cea1803c","prefixes":{"":{"product":190,"type":1}}}, // [Nielsen Digital Ad Ratings (JS)] + {"hash":"8a6e324bbf4e02dc","prefixes":{"":{"product":190,"type":1}}}, // [Nielsen Digital Ad Ratings (JS)] + {"hash":"e59faa8d364c3ad2","prefixes":{"":{"product":190,"type":1}}}, // [Nielsen Digital Ad Ratings (JS)] + {"hash":"fe39de2cc1550ee8","prefixes":{"":{"product":190,"type":1}}}, // [Nielsen Digital Ad Ratings (JS)] + {"hash":"41808f1a9bcd4cdf","prefixes":{"":{"product":190,"type":1}}}, // [Nielsen Digital Ad Ratings (JS)] + {"hash":"1774fa7feee9a3ba","prefixes":{"":{"product":191,"type":1}}}, // [Nielsen (Audience Measurement Platform)] + {"hash":"8bcfafa30bb9a496","prefixes":{"":{"product":192,"type":1}}}, // [Nielsen OBE (Vizu)] + {"hash":"04a15100eebd5238","prefixes":{"":{"product":193,"type":1}}}, // [Nielsen (Sales Effect)] + {"hash":"37669b02a11574d6","prefixes":{"":{"product":193,"type":1}}}, // [Nielsen (Sales Effect)] + {"hash":"b0e609cae76778ef","prefixes":{"":{"product":193,"type":1}}}, // [Nielsen (Sales Effect)] + {"hash":"8602961190244c78","prefixes":{"":{"product":193,"type":1}}}, // [Nielsen (Sales Effect)] + {"hash":"cf6160cc55083e3f","prefixes":{"":{"product":193,"type":1}}}, // [Nielsen (Sales Effect)] + {"hash":"d8e0147c7067e033","prefixes":{"":{"product":193,"type":1}}}, // [Nielsen (Sales Effect)] + {"hash":"fa4e638adbad854a","prefixes":{"":{"product":193,"type":1}}}, // [Nielsen (Sales Effect)] + {"hash":"bfc104d8ae540578","prefixes":{"":{"product":193,"type":1}}}, // [Nielsen (Sales Effect)] + {"hash":"a77b609ecb948524","prefixes":{"":{"product":193,"type":1}}}, // [Nielsen (Sales Effect)] + {"hash":"5b2d6c6512b90826","prefixes":{"":{"product":193,"type":1}}}, // [Nielsen (Sales Effect)] + {"hash":"3f0eefad5865a4ed","prefixes":{"":{"product":194,"type":0}}}, // [Ohana Media India Private Limited] + {"hash":"ba149fc47bfe9e3c","prefixes":{"":{"product":194,"type":0}}}, // [Ohana Media India Private Limited] + {"hash":"cfe9fa124d3faa0b","prefixes":{"*":{"product":195,"type":0}}}, // [DisplayCDN] + {"hash":"3f8d8705aeaf2a69","prefixes":{"":{"product":196,"type":0}}}, // [Avail Intelligence] + {"hash":"3aa373d150e55bb8","prefixes":{"":{"product":196,"type":0}}}, // [Avail Intelligence] + {"hash":"01168e37c54407ec","prefixes":{"":{"product":196,"type":0}}}, // [Avail Intelligence] + {"hash":"9d0088e875d03291","prefixes":{"":{"product":197,"type":2}}}, // [Adobe Scene 7] + {"hash":"7892719f65634daf","prefixes":{"":{"product":198,"type":0}}}, // [Asda] + {"hash":"76913c314e7299f2","prefixes":{"":{"product":199,"type":0}}}, // [Adsfactor Limited] + {"hash":"ec3d301a1049a29c","prefixes":{"":{"product":200,"type":0}}}, // [Trademob GmbH] + {"hash":"0407237113d1e01a","prefixes":{"":{"product":201,"type":0}}}, // [Zamplus Technology Co., Ltd.] + {"hash":"3c2b08727db96f57","prefixes":{"":{"product":201,"type":0}}}, // [Zamplus Technology Co., Ltd.] + {"hash":"28d8cdf30ea5e75d","prefixes":{"":{"product":201,"type":0}}}, // [Zamplus Technology Co., Ltd.] + {"hash":"4ba6006c59a0afb3","prefixes":{"":{"product":201,"type":0}}}, // [Zamplus Technology Co., Ltd.] + {"hash":"34b0d82da56a6e14","prefixes":{"":{"product":201,"type":0}}}, // [Zamplus Technology Co., Ltd.] + {"hash":"c9293b8324f3a30f","prefixes":{"":{"product":201,"type":0}}}, // [Zamplus Technology Co., Ltd.] + {"hash":"78ad5395bf22ddd5","prefixes":{"":{"product":201,"type":0}}}, // [Zamplus Technology Co., Ltd.] + {"hash":"b0a5ecf647236d2a","prefixes":{"*":{"product":202,"type":0}}}, // [Telemetry Limited] + {"hash":"7d7cd86e56968411","prefixes":{"*":{"product":202,"type":0}}}, // [Telemetry Limited] + {"hash":"ccaf0946d1809711","prefixes":{"*":{"product":202,"type":0}}}, // [Telemetry Limited] + {"hash":"d08bcd58e153f333","prefixes":{"*":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"c1ee73ca85937956","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"b3ee9fcc7f773476","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"0dededd99d2513e4","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"efd59a0198028c96","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"b43b6c20f3008842","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"5d96f09a039b26e6","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"039408a17f3d50d7","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"16d696fe52cae068","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"ebb9da6e533fc7e4","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"c8afb150eb1b6ac1","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"1e21c92ae4d08330","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"07ef420d707be72c","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"3d9fb95e3108b648","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"938e971e186be4f8","prefixes":{"":{"product":203,"type":0}}}, // [AdPilot] + {"hash":"94682de65e11f128","prefixes":{"":{"product":204,"type":0}}}, // [ebookers] + {"hash":"32548cc45dcf9e95","prefixes":{"":{"product":204,"type":0}}}, // [ebookers] + {"hash":"baa9bf6209e38821","prefixes":{"":{"product":204,"type":0}}}, // [ebookers] + {"hash":"25a263451425f7e3","prefixes":{"*":{"product":205,"type":0}}}, // [Mashero GmbH] + {"hash":"4871ba81fe73b693","prefixes":{"":{"product":206,"type":0}}}, // [4wMarketPlace Srl] + {"hash":"f95f038fea1148ab","prefixes":{"*":{"product":207,"type":0}}}, // [Meetic Partners] + {"hash":"8c555d8aa0a96ecc","prefixes":{"*":{"product":208,"type":0}}}, // [Adara Media] + {"hash":"a31f9bce31634750","prefixes":{"":{"product":209,"type":1}}}, // [Adledge] + {"hash":"bb0d6b4eac177896","prefixes":{"":{"product":209,"type":1}}}, // [Adledge] + {"hash":"02712dc83414bc52","prefixes":{"":{"product":209,"type":1}}}, // [Adledge] + {"hash":"03cfa92cdadd6c20","prefixes":{"":{"product":209,"type":1}}}, // [Adledge] + {"hash":"4d8640e955380082","prefixes":{"":{"product":209,"type":1}}}, // [Adledge] + {"hash":"42ab78ba8d28d0d9","prefixes":{"":{"product":209,"type":1}}}, // [Adledge] + {"hash":"113f35a595990303","prefixes":{"":{"product":209,"type":1}}}, // [Adledge] + {"hash":"9566d797c39bca8e","prefixes":{"":{"product":209,"type":1}}}, // [Adledge] + {"hash":"caab6878aaf1b900","prefixes":{"":{"product":209,"type":1}}}, // [Adledge] + {"hash":"13581af42d29c3fd","prefixes":{"":{"product":209,"type":1}}}, // [Adledge] + {"hash":"8ad4e9b59b6cfebf","prefixes":{"":{"product":209,"type":1}}}, // [Adledge] + {"hash":"025223bda779fb50","prefixes":{"":{"product":210,"type":0}}}, // [Adledge: Ad Swapping] + {"hash":"6c7970d8fe11d946","prefixes":{"":{"product":211,"type":0}}}, // [LifeStreet Corportation] + {"hash":"226c377d19c24dca","prefixes":{"":{"product":211,"type":0}}}, // [LifeStreet Corportation] + {"hash":"bc64475cc35aba69","prefixes":{"":{"product":211,"type":0}}}, // [LifeStreet Corportation] + {"hash":"8a184297457cd4e1","prefixes":{"":{"product":211,"type":0}}}, // [LifeStreet Corportation] + {"hash":"900f97a5320abcc7","prefixes":{"":{"product":212,"type":0}}}, // [AdCirrus] + {"hash":"39b102bb2f01d1b4","prefixes":{"":{"product":213,"type":1}}}, // [Dimestore] + {"hash":"a144c6442bbc8a0a","prefixes":{"":{"product":213,"type":1}}}, // [Dimestore] + {"hash":"8020cac4e8fee023","prefixes":{"":{"product":213,"type":1}}}, // [Dimestore] + {"hash":"2dcefe5fe106e478","prefixes":{"*":{"product":214,"type":1}}}, // [GfK SE] + {"hash":"d8f9a95c0ea00853","prefixes":{"*":{"product":213,"type":1}}}, // [Dimestore] + {"hash":"829fbeefc45bca87","prefixes":{"*":{"product":215,"type":0}}}, // [Conversant CRM] + {"hash":"357a04f93d25ae56","prefixes":{"cdn":{"product":216},"log":{"product":216},"tps":{"product":216},"rtb":{"product":217,"type":0}}}, // [DoubleVerify Inc.] [DoubleVerify Inc.] [DoubleVerify Inc.] [DoubleVerify Inc. (BrandShield): Ad Swapping] + {"hash":"e88f040d82035294","prefixes":{"":{"product":216,"type":1}}}, // [DoubleVerify Inc.] + {"hash":"a378f9f7b3d5241c","prefixes":{"*":{"product":218,"type":0}}}, // [Dynamic Video LLC] + {"hash":"665ab90fa95fb304","prefixes":{"":{"product":218,"type":0}}}, // [Dynamic Video LLC] + {"hash":"1358623e271c4d67","prefixes":{"":{"product":218,"type":0}}}, // [Dynamic Video LLC] + {"hash":"a11e7a579fa98970","prefixes":{"*":{"product":219,"type":0}}}, // [Think RealTime, LLC] + {"hash":"9225aaedf058b2a2","prefixes":{"":{"product":220,"type":1}}}, // [Effective Measure] + {"hash":"36703887ac49b84b","prefixes":{"":{"product":220,"type":1}}}, // [Effective Measure] + {"hash":"eabfdf13f38b7671","prefixes":{"*":{"product":221,"type":0}}}, // [Adobe Media Optimizer] + {"hash":"e6c60b5e8bab7589","prefixes":{"*":{"product":221,"type":0}}}, // [Adobe Media Optimizer] + {"hash":"d4ca4e6c8a0bedf0","prefixes":{"*":{"product":221,"type":0}}}, // [Adobe Media Optimizer] + {"hash":"2e2899c7688fb6b3","prefixes":{"":{"product":222,"type":0}}}, // [Effiliation] + {"hash":"3a8f463e807ab596","prefixes":{"":{"product":222,"type":0}}}, // [Effiliation] + {"hash":"4c49524999954857","prefixes":{"":{"product":222,"type":0}}}, // [Effiliation] + {"hash":"99a4dc2c14dac648","prefixes":{"*":{"product":223,"type":0}}}, // [EmediateAd] + {"hash":"eb4d633002c35102","prefixes":{"*":{"product":223,"type":0}}}, // [EmediateAd] + {"hash":"a4155988849d9899","prefixes":{"":{"product":223,"type":0}}}, // [EmediateAd] + {"hash":"a29dc15ab67e4109","prefixes":{"*":{"product":223,"type":0}}}, // [EmediateAd] + {"hash":"244ed2f383a41c11","prefixes":{"*":{"product":223,"type":0}}}, // [EmediateAd] + {"hash":"f1d41523d742a4c4","prefixes":{"*":{"product":224,"type":0}}}, // [engage:BDR Inc.] + {"hash":"0c985c5bee46dcca","prefixes":{"":{"product":224,"type":0}}}, // [engage:BDR Inc.] + {"hash":"6f92a4165360659f","prefixes":{"":{"product":224,"type":0}}}, // [engage:BDR Inc.] + {"hash":"e65b14b1de797d5e","prefixes":{"":{"product":224,"type":0}}}, // [engage:BDR Inc.] + {"hash":"8908058eec675b88","prefixes":{"*":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"dae357b5105fb541","prefixes":{"*":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"7e5c5286bc6286af","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"6459463a599e26cf","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"d49c14999963fa7c","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"f7508ecdfd1b76f8","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"747ac3c2114de916","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"5445e9650966f2c9","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"b701368b6964f28f","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"b8d4853208b3d665","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"a3c05ce1535a1bb0","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"4113e02fa7f80330","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"1ec6c8299f47c92d","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"6213db1c94ff78b4","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"afdce1f639f05293","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"c00800107f132ba6","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"f989cf5678a6cd73","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"7248d6bb2e2d2812","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"5decec320495d46c","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"ffffd176ae6095cd","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"a0ead46cc7797fc4","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"d1b36183709cf97c","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"f08e0f4d46762277","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"1082450fce471aec","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"0c44a72359ff962b","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"c6ced7239fa526b8","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"bcd4afcb16a1bf83","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"c4629483e0f61849","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"3a8a51dc5059eb82","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"10d4846e0b0f6213","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"8e03e96054cde307","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"d1c591453eeceb89","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"a9ee5e0b07924cbe","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"4909d0f68d7f7dd5","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"1954dcac7d36e9a9","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"855fab1b44b2cc38","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"9a977de69b69e767","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"32c7999b9a328d48","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"675aab76d51e4be4","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"454f35d478088b2f","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"af6f37ce228476e6","prefixes":{"*":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"dfa2565386557dbb","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"7bdee1b08b69b7fa","prefixes":{"*":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"259e3811976143d2","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"29633cedc9fc7e43","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"758fea4a1e3ad80f","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"cf9bd7435c526efc","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"913928e477b69d4d","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] + {"hash":"391c770feaa49fc6","prefixes":{"":{"product":4,"type":0}}}, // [Eulerian Technologies SARL] {"hash":"9aea11673c37df0c","prefixes":{"*":{"product":225}}}, // [Ghostery Enterprise] - {"hash":"5efff70d6937c916","prefixes":{"*":{"product":226}}}, // [Experteer GmbH] - {"hash":"070f9075bd0072ca","prefixes":{"":{"product":227}}}, // [Action Allocator] - {"hash":"2a8c1779456949e3","prefixes":{"":{"product":228}}}, // [AdTraxx] - {"hash":"0d3994abeed42b53","prefixes":{"*":{"product":229}}}, // [eyeDemand] - {"hash":"f804a9a8eb6b2828","prefixes":{"*":{"product":230}}}, // [EyeReturn Marketing] - {"hash":"e7b16a7fe9d18804","prefixes":{"*":{"product":230}}}, // [EyeReturn Marketing] - {"hash":"9a826150ea3a7b3d","prefixes":{"*":{"product":231}}}, // [EyeView Inc.] - {"hash":"00f40aaf7abec691","prefixes":{"":{"product":232}}}, // [EyeView, Inc] - {"hash":"a47b1640e108c4e8","prefixes":{"":{"product":232}}}, // [EyeView, Inc] - {"hash":"73c2e89f340530ca","prefixes":{"*":{"product":233}}}, // [Eyewonder Inc.] - {"hash":"ab1869399e555ac8","prefixes":{"":{"product":234}}}, // [MLB Advanced Media, L.P.] - {"hash":"6792c3d3132bf7d7","prefixes":{"":{"product":234}}}, // [MLB Advanced Media, L.P.] - {"hash":"3d02d3a5042f5ad8","prefixes":{"":{"product":234}}}, // [MLB Advanced Media, L.P.] - {"hash":"c75b8641d2e585d7","prefixes":{"*":{"product":235}}}, // [Facilitate For Agencies (FFA)] - {"hash":"535ecf05ae26ef66","prefixes":{"*":{"product":235}}}, // [Facilitate For Agencies (FFA)] - {"hash":"2393220aafcd7f07","prefixes":{"*":{"product":235}}}, // [Facilitate For Agencies (FFA)] - {"hash":"ead2626488917d96","prefixes":{"*":{"product":235}}}, // [Facilitate For Agencies (FFA)] - {"hash":"82402af773d46078","prefixes":{"*":{"product":235}}}, // [Facilitate For Agencies (FFA)] - {"hash":"0afacf5097d4ca72","prefixes":{"*":{"product":236}}}, // [Flashtalking] - {"hash":"5215ee9300af8125","prefixes":{"":{"product":237}}}, // [Hostelworld.com Limited] - {"hash":"e8d6e54e3ce31711","prefixes":{"":{"product":238}}}, // [Knorex Pte. Ltd.] - {"hash":"a8ac5a522ae936d9","prefixes":{"":{"product":238}}}, // [Knorex Pte. Ltd.] - {"hash":"c88080a9090fa828","prefixes":{"":{"product":238}}}, // [Knorex Pte. Ltd.] - {"hash":"90727ba23e427206","prefixes":{"":{"product":238}}}, // [Knorex Pte. Ltd.] - {"hash":"d496e8a41b845c1e","prefixes":{"":{"product":238}}}, // [Knorex Pte. Ltd.] - {"hash":"e3463a0b0d9d0b84","prefixes":{"*":{"product":239}}}, // [Flite Inc.] - {"hash":"93eff417d773ad79","prefixes":{"*":{"product":239}}}, // [Flite Inc.] - {"hash":"48c727cb39130203","prefixes":{"*":{"product":239}}}, // [Flite Inc.] - {"hash":"1f8b889072fc177c","prefixes":{"*":{"product":240}}}, // [Forbes Media LLC] - {"hash":"830e0f5dd1181234","prefixes":{"":{"product":241}}}, // [Scene Stealer Ltd.] - {"hash":"daf4edc7545d5166","prefixes":{"":{"product":241}}}, // [Scene Stealer Ltd.] - {"hash":"f786c1dcc4eb883e","prefixes":{"":{"product":241}}}, // [Scene Stealer Ltd.] - {"hash":"82534a9af0bc48e0","prefixes":{"":{"product":241}}}, // [Scene Stealer Ltd.] - {"hash":"091c6487b80c3425","prefixes":{"":{"product":241}}}, // [Scene Stealer Ltd.] - {"hash":"5250da9f53cd928c","prefixes":{"":{"product":241}}}, // [Scene Stealer Ltd.] - {"hash":"9a8514c0fd5d6754","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"ad91bc98d2a8be55","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"91e5780ca48d75cc","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"481acfc271cd8a12","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"ef2a23dc677d8426","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"c6c8ce28b06bbda5","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"2bb2e1ea24146c0b","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"a0f3f5041ae3893c","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"4d6c5ce49301c775","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"747c952599211285","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"59f1e6a6110f9a68","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"f76895f67d1585b2","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"a2e125e235d1ffd4","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"17cbbfe7617725b3","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"1c118cc87c632e94","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"a48217ad66a56eb4","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"949fd73ca6fcc6f5","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"7d647d3164d8e6e2","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"e6d9d61b6785d883","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"aad9a81ea12d3c42","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"f0d9b5588abc50f9","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"dcb3db79fcab6476","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"1985d21c9c0b8366","prefixes":{"":{"product":242}}}, // [FreakOut Inc.] - {"hash":"a268d22dc85b4108","prefixes":{"*":{"product":243}}}, // [FreeWheel] - {"hash":"a796f300b3d2c84e","prefixes":{"*":{"product":244}}}, // [Fringe81 Inc.] + {"hash":"5efff70d6937c916","prefixes":{"*":{"product":226,"type":0}}}, // [Experteer GmbH] + {"hash":"070f9075bd0072ca","prefixes":{"":{"product":227,"type":1}}}, // [Action Allocator] + {"hash":"2a8c1779456949e3","prefixes":{"":{"product":228,"type":1}}}, // [AdTraxx] + {"hash":"0d3994abeed42b53","prefixes":{"*":{"product":229,"type":0}}}, // [eyeDemand] + {"hash":"f804a9a8eb6b2828","prefixes":{"*":{"product":230,"type":0}}}, // [EyeReturn Marketing] + {"hash":"e7b16a7fe9d18804","prefixes":{"*":{"product":230,"type":0}}}, // [EyeReturn Marketing] + {"hash":"9a826150ea3a7b3d","prefixes":{"*":{"product":231,"type":0}}}, // [EyeView Inc.] + {"hash":"00f40aaf7abec691","prefixes":{"":{"product":232,"type":0}}}, // [EyeView, Inc] + {"hash":"a47b1640e108c4e8","prefixes":{"":{"product":232,"type":0}}}, // [EyeView, Inc] + {"hash":"73c2e89f340530ca","prefixes":{"*":{"product":233,"type":0}}}, // [Eyewonder Inc.] + {"hash":"ab1869399e555ac8","prefixes":{"":{"product":234,"type":0}}}, // [MLB Advanced Media, L.P.] + {"hash":"6792c3d3132bf7d7","prefixes":{"":{"product":234,"type":0}}}, // [MLB Advanced Media, L.P.] + {"hash":"3d02d3a5042f5ad8","prefixes":{"":{"product":234,"type":0}}}, // [MLB Advanced Media, L.P.] + {"hash":"c75b8641d2e585d7","prefixes":{"*":{"product":235,"type":0}}}, // [Facilitate For Agencies (FFA)] + {"hash":"535ecf05ae26ef66","prefixes":{"*":{"product":235,"type":0}}}, // [Facilitate For Agencies (FFA)] + {"hash":"2393220aafcd7f07","prefixes":{"*":{"product":235,"type":0}}}, // [Facilitate For Agencies (FFA)] + {"hash":"ead2626488917d96","prefixes":{"*":{"product":235,"type":0}}}, // [Facilitate For Agencies (FFA)] + {"hash":"82402af773d46078","prefixes":{"*":{"product":235,"type":0}}}, // [Facilitate For Agencies (FFA)] + {"hash":"0afacf5097d4ca72","prefixes":{"*":{"product":236,"type":0}}}, // [Flashtalking] + {"hash":"5215ee9300af8125","prefixes":{"":{"product":237,"type":0}}}, // [Hostelworld.com Limited] + {"hash":"e8d6e54e3ce31711","prefixes":{"":{"product":238,"type":0}}}, // [Knorex Pte. Ltd.] + {"hash":"a8ac5a522ae936d9","prefixes":{"":{"product":238,"type":0}}}, // [Knorex Pte. Ltd.] + {"hash":"c88080a9090fa828","prefixes":{"":{"product":238,"type":0}}}, // [Knorex Pte. Ltd.] + {"hash":"90727ba23e427206","prefixes":{"":{"product":238,"type":0}}}, // [Knorex Pte. Ltd.] + {"hash":"d496e8a41b845c1e","prefixes":{"":{"product":238,"type":0}}}, // [Knorex Pte. Ltd.] + {"hash":"e3463a0b0d9d0b84","prefixes":{"*":{"product":239,"type":0}}}, // [Flite Inc.] + {"hash":"93eff417d773ad79","prefixes":{"*":{"product":239,"type":0}}}, // [Flite Inc.] + {"hash":"48c727cb39130203","prefixes":{"*":{"product":239,"type":0}}}, // [Flite Inc.] + {"hash":"1f8b889072fc177c","prefixes":{"*":{"product":240,"type":0}}}, // [Forbes Media LLC] + {"hash":"830e0f5dd1181234","prefixes":{"":{"product":241,"type":0}}}, // [Scene Stealer Ltd.] + {"hash":"daf4edc7545d5166","prefixes":{"":{"product":241,"type":0}}}, // [Scene Stealer Ltd.] + {"hash":"f786c1dcc4eb883e","prefixes":{"":{"product":241,"type":0}}}, // [Scene Stealer Ltd.] + {"hash":"82534a9af0bc48e0","prefixes":{"":{"product":241,"type":0}}}, // [Scene Stealer Ltd.] + {"hash":"091c6487b80c3425","prefixes":{"":{"product":241,"type":0}}}, // [Scene Stealer Ltd.] + {"hash":"5250da9f53cd928c","prefixes":{"":{"product":241,"type":0}}}, // [Scene Stealer Ltd.] + {"hash":"9a8514c0fd5d6754","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"ad91bc98d2a8be55","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"91e5780ca48d75cc","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"481acfc271cd8a12","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"ef2a23dc677d8426","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"c6c8ce28b06bbda5","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"2bb2e1ea24146c0b","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"a0f3f5041ae3893c","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"4d6c5ce49301c775","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"747c952599211285","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"59f1e6a6110f9a68","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"f76895f67d1585b2","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"a2e125e235d1ffd4","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"17cbbfe7617725b3","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"1c118cc87c632e94","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"a48217ad66a56eb4","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"949fd73ca6fcc6f5","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"7d647d3164d8e6e2","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"e6d9d61b6785d883","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"aad9a81ea12d3c42","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"f0d9b5588abc50f9","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"dcb3db79fcab6476","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"1985d21c9c0b8366","prefixes":{"":{"product":242,"type":0}}}, // [FreakOut Inc.] + {"hash":"a268d22dc85b4108","prefixes":{"*":{"product":243,"type":0}}}, // [FreeWheel] + {"hash":"a796f300b3d2c84e","prefixes":{"*":{"product":244,"type":0}}}, // [Fringe81 Inc.] {"hash":"bb563c63d09f3d76","prefixes":{"":{"product":245}}}, // [Fringe81 - IBV] {"hash":"c6ac10cc9ddfb3e7","prefixes":{"":{"product":245}}}, // [Fringe81 - IBV] - {"hash":"48983a0d5a27b120","prefixes":{"*":{"product":246}}}, // [FuseBox Inc.] - {"hash":"6f59caebdaac019e","prefixes":{"":{"product":246}}}, // [FuseBox Inc.] - {"hash":"8090c608651eca30","prefixes":{"*":{"product":247}}}, // [gemiusDirectEffect+] - {"hash":"e7b75209bd73a1d9","prefixes":{"*":{"product":248}}}, // [AdOcean Ltd] - {"hash":"24fb4ed27ae8cf88","prefixes":{"*":{"product":249}}}, // [Intomart GfK (GfK Daphne)] - {"hash":"91571a34ff0fcf44","prefixes":{"*":{"product":250}}}, // [Gigya] - {"hash":"bd66201f4f935a9d","prefixes":{"*":{"product":251}}}, // [Global Market Insite Inc.] - {"hash":"c0854a371610fbf2","prefixes":{"*":{"product":251}}}, // [Global Market Insite Inc.] - {"hash":"4a32fa997117f00d","prefixes":{"*":{"product":252},"":{"product":253}}}, // [DoubleClick Campaign Manager] [DoubleClick Bidder Pilot for Networks] - {"hash":"68d0356c33bd8ec4","prefixes":{"*":{"product":252},"":{"product":253}}}, // [DoubleClick Campaign Manager] [DoubleClick Bidder Pilot for Networks] - {"hash":"813ca9ac3483af55","prefixes":{"*":{"product":252},"":{"product":253}}}, // [DoubleClick Campaign Manager] [DoubleClick Bidder Pilot for Networks] - {"hash":"ee88383142da014d","prefixes":{"*":{"product":252},"":{"product":253}}}, // [DoubleClick Campaign Manager] [DoubleClick Bidder Pilot for Networks] - {"hash":"1332f3da43091ed3","prefixes":{"":{"product":252},"*":{"product":254}}}, // [DoubleClick Campaign Manager] [DoubleClick for Publishers Premium] - {"hash":"f04082d14282d452","prefixes":{"":{"product":252}}}, // [DoubleClick Campaign Manager] - {"hash":"c6ad6c580aef6ce5","prefixes":{"":{"product":252}}}, // [DoubleClick Campaign Manager] - {"hash":"642706b0b0335500","prefixes":{"":{"product":252}}}, // [DoubleClick Campaign Manager] - {"hash":"baea954b95731c68","prefixes":{"*":{"product":255}}}, // [Google CDN] - {"hash":"8e23699963552b18","prefixes":{"*":{"product":252}}}, // [DoubleClick Campaign Manager] - {"hash":"bafedfe69ed92305","prefixes":{"*":{"product":253}}}, // [DoubleClick Bidder Pilot for Networks] - {"hash":"f2b999c597cd97af","prefixes":{"*":{"product":253}}}, // [DoubleClick Bidder Pilot for Networks] - {"hash":"66399889a04f9513","prefixes":{"cdn":{"product":256},"ads":{"product":256},"db":{"product":256},"img":{"product":256},"ssl":{"product":256}}}, // [GroovinAds] [GroovinAds] [GroovinAds] [GroovinAds] [GroovinAds] - {"hash":"ea8510cdf6991d43","prefixes":{"":{"product":256}}}, // [GroovinAds] - {"hash":"fc2e03aac9426552","prefixes":{"":{"product":257}}}, // [Reddion] - {"hash":"6db39bcc7e0f7fed","prefixes":{"":{"product":258}}}, // [HQ GmbH] - {"hash":"4de0590ca954b13b","prefixes":{"*":{"product":259}}}, // [Performance Display Advertising] - {"hash":"44f4a1b16ff856e5","prefixes":{"":{"product":5}}}, // [Conversant Ad Server] - {"hash":"127f97cfaedd763a","prefixes":{"":{"product":5}}}, // [Conversant Ad Server] - {"hash":"508035bfa2d95844","prefixes":{"*":{"product":5}}}, // [Conversant Ad Server] - {"hash":"6ea225859ddfba18","prefixes":{"*":{"product":5}}}, // [Conversant Ad Server] - {"hash":"600a5a5f53775d42","prefixes":{"*":{"product":216}}}, // [DoubleVerify Inc.] - {"hash":"cabba15c5ee8f039","prefixes":{"*":{"product":260}}}, // [Avazu Inc.] - {"hash":"ec98881ed60ffe62","prefixes":{"":{"product":91}}}, // [ADTECH GmbH] - {"hash":"b1e5dca23b928251","prefixes":{"":{"product":91}}}, // [ADTECH GmbH] - {"hash":"87e919d72e293303","prefixes":{"*":{"product":261}}}, // [Aerify Media] - {"hash":"652d7fe0079512a8","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"8e1afef4fbf079f4","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"3f697fb2c06659ac","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"cb5ae4cc94e8cb57","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"3cd44a0f52d69fed","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"fd87dfe8678e2630","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"274e4476c8fbfe0c","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"e3f56a006c4f8fc8","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"11d582be18893073","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"54768ce9ed6664fc","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"6de580016869f523","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"7fc8a77e5f366b6d","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"06838afa0ce9cde5","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"d788f92161d75b72","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"bd27e9c073c7b133","prefixes":{"":{"product":262}}}, // [IClick Interactive Ltd.] - {"hash":"71096991891dc36f","prefixes":{"*":{"product":263}}}, // [iCrossing] - {"hash":"0a48c6448ca1af83","prefixes":{"":{"product":263}}}, // [iCrossing] - {"hash":"23cce2ff5ce35111","prefixes":{"*":{"product":264}}}, // [Impact Engine Inc.] + {"hash":"48983a0d5a27b120","prefixes":{"*":{"product":246,"type":0}}}, // [FuseBox Inc.] + {"hash":"6f59caebdaac019e","prefixes":{"":{"product":246,"type":0}}}, // [FuseBox Inc.] + {"hash":"8090c608651eca30","prefixes":{"*":{"product":247,"type":1}}}, // [gemiusDirectEffect+] + {"hash":"e7b75209bd73a1d9","prefixes":{"*":{"product":248,"type":0}}}, // [AdOcean Ltd] + {"hash":"24fb4ed27ae8cf88","prefixes":{"*":{"product":249,"type":1}}}, // [Intomart GfK (GfK Daphne)] + {"hash":"91571a34ff0fcf44","prefixes":{"*":{"product":250,"type":0}}}, // [Gigya] + {"hash":"bd66201f4f935a9d","prefixes":{"*":{"product":251,"type":1}}}, // [Global Market Insite Inc.] + {"hash":"c0854a371610fbf2","prefixes":{"*":{"product":251,"type":1}}}, // [Global Market Insite Inc.] + {"hash":"4a32fa997117f00d","prefixes":{"*":{"product":252,"type":0},"":{"product":253,"type":0}}}, // [DoubleClick Campaign Manager] [DoubleClick Bidder Pilot for Networks] + {"hash":"68d0356c33bd8ec4","prefixes":{"*":{"product":252,"type":0},"":{"product":253,"type":0}}}, // [DoubleClick Campaign Manager] [DoubleClick Bidder Pilot for Networks] + {"hash":"813ca9ac3483af55","prefixes":{"*":{"product":252,"type":0},"":{"product":253,"type":0}}}, // [DoubleClick Campaign Manager] [DoubleClick Bidder Pilot for Networks] + {"hash":"ee88383142da014d","prefixes":{"*":{"product":252,"type":0},"":{"product":253,"type":0}}}, // [DoubleClick Campaign Manager] [DoubleClick Bidder Pilot for Networks] + {"hash":"1332f3da43091ed3","prefixes":{"":{"product":252,"type":0},"*":{"product":254,"type":0}}}, // [DoubleClick Campaign Manager] [DoubleClick for Publishers Premium] + {"hash":"f04082d14282d452","prefixes":{"":{"product":252,"type":0}}}, // [DoubleClick Campaign Manager] + {"hash":"c6ad6c580aef6ce5","prefixes":{"":{"product":252,"type":0}}}, // [DoubleClick Campaign Manager] + {"hash":"642706b0b0335500","prefixes":{"":{"product":252,"type":0}}}, // [DoubleClick Campaign Manager] + {"hash":"baea954b95731c68","prefixes":{"*":{"product":255,"type":2}}}, // [Google CDN] + {"hash":"8e23699963552b18","prefixes":{"*":{"product":252,"type":0}}}, // [DoubleClick Campaign Manager] + {"hash":"bafedfe69ed92305","prefixes":{"*":{"product":253,"type":0}}}, // [DoubleClick Bidder Pilot for Networks] + {"hash":"f2b999c597cd97af","prefixes":{"*":{"product":253,"type":0}}}, // [DoubleClick Bidder Pilot for Networks] + {"hash":"66399889a04f9513","prefixes":{"cdn":{"product":256,"type":0},"ads":{"product":256,"type":0},"db":{"product":256,"type":0},"img":{"product":256,"type":0},"ssl":{"product":256,"type":0}}}, // [GroovinAds] [GroovinAds] [GroovinAds] [GroovinAds] [GroovinAds] + {"hash":"ea8510cdf6991d43","prefixes":{"":{"product":256,"type":0}}}, // [GroovinAds] + {"hash":"fc2e03aac9426552","prefixes":{"":{"product":257,"type":0}}}, // [Reddion] + {"hash":"6db39bcc7e0f7fed","prefixes":{"":{"product":258,"type":0}}}, // [HQ GmbH] + {"hash":"4de0590ca954b13b","prefixes":{"*":{"product":259,"type":0}}}, // [Performance Display Advertising] + {"hash":"44f4a1b16ff856e5","prefixes":{"":{"product":5,"type":0}}}, // [Conversant Ad Server] + {"hash":"127f97cfaedd763a","prefixes":{"":{"product":5,"type":0}}}, // [Conversant Ad Server] + {"hash":"508035bfa2d95844","prefixes":{"*":{"product":5,"type":0}}}, // [Conversant Ad Server] + {"hash":"6ea225859ddfba18","prefixes":{"*":{"product":5,"type":0}}}, // [Conversant Ad Server] + {"hash":"600a5a5f53775d42","prefixes":{"*":{"product":216,"type":1}}}, // [DoubleVerify Inc.] + {"hash":"cabba15c5ee8f039","prefixes":{"*":{"product":260,"type":0}}}, // [Avazu Inc.] + {"hash":"ec98881ed60ffe62","prefixes":{"":{"product":91,"type":0}}}, // [ADTECH GmbH] + {"hash":"b1e5dca23b928251","prefixes":{"":{"product":91,"type":0}}}, // [ADTECH GmbH] + {"hash":"87e919d72e293303","prefixes":{"*":{"product":261,"type":0}}}, // [Aerify Media] + {"hash":"652d7fe0079512a8","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"8e1afef4fbf079f4","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"3f697fb2c06659ac","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"cb5ae4cc94e8cb57","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"3cd44a0f52d69fed","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"fd87dfe8678e2630","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"274e4476c8fbfe0c","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"e3f56a006c4f8fc8","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"11d582be18893073","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"54768ce9ed6664fc","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"6de580016869f523","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"7fc8a77e5f366b6d","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"06838afa0ce9cde5","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"d788f92161d75b72","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"bd27e9c073c7b133","prefixes":{"":{"product":262,"type":0}}}, // [IClick Interactive Ltd.] + {"hash":"71096991891dc36f","prefixes":{"*":{"product":263,"type":0}}}, // [iCrossing] + {"hash":"0a48c6448ca1af83","prefixes":{"":{"product":263,"type":0}}}, // [iCrossing] + {"hash":"23cce2ff5ce35111","prefixes":{"*":{"product":264,"type":0}}}, // [Impact Engine Inc.] {"hash":"b63329d63303bcac","prefixes":{"*":{"product":265}}}, // [Inadco Inc.] {"hash":"9dab6f7b066953b6","prefixes":{"":{"product":265}}}, // [Inadco Inc.] - {"hash":"83efdfb00e5e0bb5","prefixes":{"":{"product":266}}}, // [Innity Singapore Pte Ltd.] - {"hash":"5cdf5c58d4a95757","prefixes":{"":{"product":266}}}, // [Innity Singapore Pte Ltd.] - {"hash":"e84e4c75279b444c","prefixes":{"":{"product":266}}}, // [Innity Singapore Pte Ltd.] - {"hash":"0ad278b0f1bf83c7","prefixes":{"":{"product":267}}}, // [Insight Express (Cross Media - Ignite)] - {"hash":"75089fef153b99d9","prefixes":{"":{"product":267}}}, // [Insight Express (Cross Media - Ignite)] - {"hash":"17e48170b29e8c55","prefixes":{"":{"product":268}}}, // [intelliAd Media GmbH] - {"hash":"8ff3a159f3a3dd37","prefixes":{"":{"product":268}}}, // [intelliAd Media GmbH] - {"hash":"d5ad6ce37d416c20","prefixes":{"":{"product":268}}}, // [intelliAd Media GmbH] - {"hash":"829116e73bbd766e","prefixes":{"*":{"product":269}}}, // [DePauli AG] - {"hash":"58b6a73b811a6744","prefixes":{"":{"product":268}}}, // [intelliAd Media GmbH] - {"hash":"1b02753d1ebc5935","prefixes":{"":{"product":270}}}, // [Intelliad] - {"hash":"2d4767b28a0a3dc9","prefixes":{"":{"product":270}}}, // [Intelliad] - {"hash":"04e4138ad91eba43","prefixes":{"*":{"product":271}}}, // [Genome] - {"hash":"a80259001a08f5fe","prefixes":{"":{"product":271}}}, // [Genome] - {"hash":"bccc7d85fcbd6406","prefixes":{"*":{"product":272}}}, // [Intergi LLC dba PlaywireMedia] - {"hash":"c0e12f3f6483d539","prefixes":{"":{"product":273}}}, // [Intermundo Media LLC] - {"hash":"aa0d2346396993dc","prefixes":{"*":{"product":274}}}, // [Interpolls] - {"hash":"391f02c89579c41e","prefixes":{"*":{"product":275}}}, // [Intelligent Reach (Intuitive Search Technologies)] - {"hash":"dd7ece8c8b4dd4db","prefixes":{"*":{"product":275}}}, // [Intelligent Reach (Intuitive Search Technologies)] - {"hash":"51beebfd5a677c74","prefixes":{"":{"product":275}}}, // [Intelligent Reach (Intuitive Search Technologies)] - {"hash":"15a557d1be0b55bc","prefixes":{"*":{"product":276}}}, // [IPONWEB Limited] - {"hash":"ab800ebb45ab5e96","prefixes":{"":{"product":276}}}, // [IPONWEB Limited] - {"hash":"cf6003cf8be11c49","prefixes":{"*":{"product":276}}}, // [IPONWEB Limited] - {"hash":"bd97f2dac673ccef","prefixes":{"*":{"product":277}}}, // [JasperLabs Inc.] - {"hash":"833a1bb3e47002bf","prefixes":{"":{"product":278}}}, // [Jivox Corporation] - {"hash":"925afb63a81d22ae","prefixes":{"":{"product":278}}}, // [Jivox Corporation] - {"hash":"e3546ee6177ce1af","prefixes":{"":{"product":278}}}, // [Jivox Corporation] - {"hash":"a6e81a993b0dc090","prefixes":{"":{"product":278}}}, // [Jivox Corporation] - {"hash":"57cf72a6bcc6ed09","prefixes":{"":{"product":278}}}, // [Jivox Corporation] - {"hash":"aef508a87f7b9342","prefixes":{"":{"product":278}}}, // [Jivox Corporation] - {"hash":"a1a0984cf6e12596","prefixes":{"":{"product":278}}}, // [Jivox Corporation] - {"hash":"c1b82a9e7564881f","prefixes":{"*":{"product":279}}}, // [Joinville AB] - {"hash":"e20dd6e83cbd14d9","prefixes":{"":{"product":280}}}, // [KliKKicom Oy] - {"hash":"a1f03f455fc97850","prefixes":{"":{"product":281}}}, // [Komli Media Inc.] - {"hash":"fb87830648f1fe7c","prefixes":{"":{"product":281}}}, // [Komli Media Inc.] - {"hash":"93a6bcd7660ef88b","prefixes":{"":{"product":281}}}, // [Komli Media Inc.] - {"hash":"14fba951393c4cc1","prefixes":{"":{"product":281}}}, // [Komli Media Inc.] - {"hash":"96bf72901db53556","prefixes":{"":{"product":281}}}, // [Komli Media Inc.] - {"hash":"00ceea10fed6f827","prefixes":{"":{"product":281}}}, // [Komli Media Inc.] - {"hash":"5deb6288aeb4b20d","prefixes":{"":{"product":281}}}, // [Komli Media Inc.] - {"hash":"30a9e5cf761c2db9","prefixes":{"":{"product":281}}}, // [Komli Media Inc.] - {"hash":"b49fda322943ed64","prefixes":{"":{"product":281}}}, // [Komli Media Inc.] - {"hash":"30067241c16c9f88","prefixes":{"*":{"product":282}}}, // [Koninklijke Luchtvaart Maatschappij N.V.] - {"hash":"06076b672be3af43","prefixes":{"*":{"product":283}}}, // [J.D. Power O2O] - {"hash":"1e23ff61443f919a","prefixes":{"*":{"product":284}}}, // [Kwanzoo Inc.] - {"hash":"32327b1f6a21f5e3","prefixes":{"":{"product":285}}}, // [Legolas Media Inc.] - {"hash":"0a98bd3ecf6d4f39","prefixes":{"":{"product":285}}}, // [Legolas Media Inc.] - {"hash":"4141a8162aadd52a","prefixes":{"":{"product":285}}}, // [Legolas Media Inc.] - {"hash":"9562185c6a06e194","prefixes":{"*":{"product":286}}}, // [Undertone Ad System (UAS)] - {"hash":"d8be1c121ccbdb84","prefixes":{"":{"product":287}}}, // [LEVEL Studios] - {"hash":"1b274516ac601c1d","prefixes":{"*":{"product":288}}}, // [LinkedIn Corporation] - {"hash":"a9aceb9b28670518","prefixes":{"*":{"product":288}}}, // [LinkedIn Corporation] - {"hash":"f202e32e7503e766","prefixes":{"":{"product":288}}}, // [LinkedIn Corporation] - {"hash":"cf2094771b42b367","prefixes":{"*":{"product":288}}}, // [LinkedIn Corporation] - {"hash":"ad94f98bfc0092ce","prefixes":{"*":{"product":289}}}, // [Content Directions, Inc. dba Linkstorm] - {"hash":"2c97a2e1f7f59cde","prefixes":{"*":{"product":290}}}, // [Liverail Inc.] - {"hash":"562dd0a17776cfc3","prefixes":{"*":{"product":291}}}, // [Lotame Solutions Inc.] - {"hash":"85c409cdb78a6fec","prefixes":{"*":{"product":292}}}, // [LucidMedia Networks Inc.] - {"hash":"25cdc372f14aa636","prefixes":{"":{"product":293}}}, // [Magnetic Media Online Inc.] - {"hash":"490a692feb4f5f83","prefixes":{"":{"product":293}}}, // [Magnetic Media Online Inc.] - {"hash":"8cd182ca413a6770","prefixes":{"":{"product":293}}}, // [Magnetic Media Online Inc.] - {"hash":"891ff79862603ca1","prefixes":{"*":{"product":294}}}, // [Mate1.com] - {"hash":"ae4598324ee10cb2","prefixes":{"":{"product":295}}}, // [MaxPoint Interactive Inc.] - {"hash":"66eafecb064a6d3f","prefixes":{"*":{"product":296}}}, // [Media Armor Inc.] - {"hash":"d9921090d75b28f3","prefixes":{"*":{"product":297}}}, // [Xaxis, Inc] - {"hash":"4c897372b3205c67","prefixes":{"*":{"product":298}}}, // [Dstillery] - {"hash":"78172051b147ff71","prefixes":{"*":{"product":298}}}, // [Dstillery] - {"hash":"3e32e501635bb994","prefixes":{"*":{"product":299}}}, // [Rakuten MediaForge] - {"hash":"ab3637f7ff19f3be","prefixes":{"*":{"product":86}}}, // [MediaMath Inc.] - {"hash":"eacb348c2bfde7c6","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"6ec884dc33afd8e3","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"6a0b44c268e0ea34","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"5ec2ba6f16455240","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"f6a166105958340d","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"1bafa194e1b43948","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"c4c10492cf3f1e5c","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"fb29996f4dbe86a3","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"33cba419c0d99c36","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"1471e355753e333a","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"8445471e74aaf1ad","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"fe448fc8fa6792c7","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"7142d0f7c95e6c11","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"f71e7939a3a06b85","prefixes":{"":{"product":300}}}, // [Sizmek] - {"hash":"25c9493f4ceef0b3","prefixes":{"*":{"product":300}}}, // [Sizmek] - {"hash":"1c0486f5c9ddccc1","prefixes":{"":{"product":301}}}, // [MediaMind] - {"hash":"511f53552d7c07f9","prefixes":{"*":{"product":302}}}, // [Paypal] - {"hash":"c23b8169e8d6f935","prefixes":{"*":{"product":302}}}, // [Paypal] - {"hash":"4cb72fa17c1e6b21","prefixes":{"*":{"product":303}}}, // [ZEDO Inc.] - {"hash":"1f5866beb3a2da29","prefixes":{"":{"product":304}}}, // [Contobox] - {"hash":"ab4011df7412e85a","prefixes":{"":{"product":304}}}, // [Contobox] - {"hash":"4c55c99f7e731e4a","prefixes":{"":{"product":304}}}, // [Contobox] - {"hash":"b32dad95de4864bb","prefixes":{"":{"product":304}}}, // [Contobox] - {"hash":"e0636cdabf7592eb","prefixes":{"":{"product":305}}}, // [Melt Tecnologia e Informatica S.A] - {"hash":"9e011383339e65c3","prefixes":{"":{"product":305}}}, // [Melt Tecnologia e Informatica S.A] - {"hash":"c7f6b97c8a7defa6","prefixes":{"":{"product":305}}}, // [Melt Tecnologia e Informatica S.A] - {"hash":"ba29743e534631a5","prefixes":{"":{"product":305}}}, // [Melt Tecnologia e Informatica S.A] - {"hash":"df986bbd43ef130c","prefixes":{"":{"product":305}}}, // [Melt Tecnologia e Informatica S.A] - {"hash":"32e39349c0434e31","prefixes":{"":{"product":305}}}, // [Melt Tecnologia e Informatica S.A] - {"hash":"4b920fabf61fd6f3","prefixes":{"":{"product":305}}}, // [Melt Tecnologia e Informatica S.A] - {"hash":"068f3a0cd7e03112","prefixes":{"":{"product":305}}}, // [Melt Tecnologia e Informatica S.A] - {"hash":"95cce4f80c49239f","prefixes":{"*":{"product":306}}}, // [MeMo2 / Hottraffic] - {"hash":"7672c0e258e0a20b","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"065ac7f58737b759","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"f0c15855e3418345","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"45068fe6a5fe83c0","prefixes":{"*":{"product":308}}}, // [Mercado Livre.com Atividades de Internet Ltda] - {"hash":"a3fbfa83663a40a6","prefixes":{"*":{"product":308}}}, // [Mercado Livre.com Atividades de Internet Ltda] - {"hash":"5241d2ae86ff307f","prefixes":{"":{"product":309}}}, // [Merchenta Limited] - {"hash":"7b92690c1232eb23","prefixes":{"":{"product":309}}}, // [Merchenta Limited] - {"hash":"e5b1a15c3a7a1ee6","prefixes":{"":{"product":309}}}, // [Merchenta Limited] - {"hash":"f0b40488d9ecd9a2","prefixes":{"":{"product":309}}}, // [Merchenta Limited] - {"hash":"63600c9242f10b0d","prefixes":{"":{"product":309}}}, // [Merchenta Limited] - {"hash":"e89e81c1ed314cc1","prefixes":{"":{"product":310}}}, // [Metapeople GmbH] - {"hash":"297f0571158ef576","prefixes":{"":{"product":310}}}, // [Metapeople GmbH] - {"hash":"2228e5ce36c007c1","prefixes":{"":{"product":310}}}, // [Metapeople GmbH] - {"hash":"798bcbf9415873df","prefixes":{"":{"product":310}}}, // [Metapeople GmbH] - {"hash":"ab03f3b496037843","prefixes":{"":{"product":310}}}, // [Metapeople GmbH] - {"hash":"eca01f0508fbf30b","prefixes":{"":{"product":310}}}, // [Metapeople GmbH] - {"hash":"0d839898fade319a","prefixes":{"":{"product":310}}}, // [Metapeople GmbH] - {"hash":"4fc010b1e52ce252","prefixes":{"":{"product":310}}}, // [Metapeople GmbH] - {"hash":"31e7fb81bf0ec52f","prefixes":{"":{"product":310}}}, // [Metapeople GmbH] - {"hash":"a6edfa074ceff9c5","prefixes":{"":{"product":310}}}, // [Metapeople GmbH] - {"hash":"289dc75a912dcc97","prefixes":{"":{"product":310}}}, // [Metapeople GmbH] - {"hash":"5a8de8926c410758","prefixes":{"":{"product":310}}}, // [Metapeople GmbH] - {"hash":"79c798a9d8e32afc","prefixes":{"":{"product":311}}}, // [MetrixLab B.V.] - {"hash":"61617058e6206283","prefixes":{"":{"product":311}}}, // [MetrixLab B.V.] - {"hash":"cf945767a2fa79f3","prefixes":{"*":{"product":312}}}, // [Mixpo Inc.] - {"hash":"541f85cbc710f2b3","prefixes":{"":{"product":313}}}, // [Monsoon Ads Pvt. Ltd.] - {"hash":"c800e798e160fe89","prefixes":{"*":{"product":314}}}, // [Monster] - {"hash":"775035c4c49057eb","prefixes":{"":{"product":314}}}, // [Monster] - {"hash":"2a26221290e24a08","prefixes":{"":{"product":314}}}, // [Monster] - {"hash":"fda966b5c6ec2b2f","prefixes":{"":{"product":314}}}, // [Monster] - {"hash":"887d148a8ae98b2e","prefixes":{"*":{"product":315}}}, // [neckermann.de GmbH] - {"hash":"35c76c9165e3349f","prefixes":{"*":{"product":316}}}, // [Ad.agio] - {"hash":"d5c7d1240bf8989e","prefixes":{"":{"product":316}}}, // [Ad.agio] - {"hash":"1e5ea56690a0716d","prefixes":{"*":{"product":316}}}, // [Ad.agio] - {"hash":"a54661777ef51189","prefixes":{"*":{"product":317}}}, // [Netmining LLC] - {"hash":"cc673c90c8abe830","prefixes":{"*":{"product":318}}}, // [AdoTube] - {"hash":"5f4b0cbb95552b3f","prefixes":{"*":{"product":319}}}, // [Next Audience GmbH] - {"hash":"a78e1096b3c03fbc","prefixes":{"":{"product":319}}}, // [Next Audience GmbH] - {"hash":"582d973b69391ebe","prefixes":{"":{"product":319}}}, // [Next Audience GmbH] - {"hash":"18585076a5b0c6dd","prefixes":{"":{"product":319}}}, // [Next Audience GmbH] - {"hash":"1df4ee86fc680406","prefixes":{"":{"product":319}}}, // [Next Audience GmbH] - {"hash":"ecd80a6a46f6a1ce","prefixes":{"":{"product":319}}}, // [Next Audience GmbH] - {"hash":"8ee876aaaaf537e0","prefixes":{"":{"product":319}}}, // [Next Audience GmbH] - {"hash":"92bc4f011133f05a","prefixes":{"*":{"product":320}}}, // [Nextperf] - {"hash":"b10d35d6cde76082","prefixes":{"*":{"product":320}}}, // [Nextperf] - {"hash":"8e6e5d6dc4720f98","prefixes":{"":{"product":320}}}, // [Nextperf] - {"hash":"edc7f4e87a8ea4a3","prefixes":{"":{"product":320}}}, // [Nextperf] - {"hash":"f0c76e07985c56c5","prefixes":{"":{"product":320}}}, // [Nextperf] - {"hash":"cff1b3137482e5e3","prefixes":{"":{"product":320}}}, // [Nextperf] - {"hash":"33f28c5ebbd4525e","prefixes":{"":{"product":320}}}, // [Nextperf] - {"hash":"849c8324d4c32ea5","prefixes":{"*":{"product":321}}}, // [Calibex] - {"hash":"0bbcc61ed60a63c7","prefixes":{"*":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"7da7b69cf130f867","prefixes":{"*":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"524bf7ee34882325","prefixes":{"*":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"0fc0858e8d42a096","prefixes":{"*":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"94d1d06666f458b2","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"9515f9226eae0ee6","prefixes":{"":{"product":8}}}, // [Research Now Limited] - {"hash":"c610850a50287c6c","prefixes":{"":{"product":322}}}, // [ViziAds for Advertisers] - {"hash":"1324d12fd047205a","prefixes":{"":{"product":322}}}, // [ViziAds for Advertisers] - {"hash":"922df75b11e4bdb8","prefixes":{"":{"product":322}}}, // [ViziAds for Advertisers] - {"hash":"94be9a0ad636acc1","prefixes":{"":{"product":322}}}, // [ViziAds for Advertisers] - {"hash":"921f858655989bdb","prefixes":{"":{"product":322}}}, // [ViziAds for Advertisers] - {"hash":"0f44f6f2024007e3","prefixes":{"":{"product":323}}}, // [FinanceGenerator] - {"hash":"c5d545736ea3f40c","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"c5190fb3c11efd5c","prefixes":{"":{"product":324}}}, // [Telstra Corporation] - {"hash":"f8e19bba6ecb9d4d","prefixes":{"":{"product":324}}}, // [Telstra Corporation] - {"hash":"78cb9e34e18a70c6","prefixes":{"":{"product":324}}}, // [Telstra Corporation] - {"hash":"555b77a6dbc1077b","prefixes":{"":{"product":324}}}, // [Telstra Corporation] - {"hash":"04cd318d8c9e0aa1","prefixes":{"":{"product":325}}}, // [The Online Research Unit] - {"hash":"44b28a9d35489468","prefixes":{"":{"product":326}}}, // [Webling Pty Ltd] - {"hash":"ce2a97a2bc3975b0","prefixes":{"*":{"product":327}}}, // [Lasoo Pty Ltd] - {"hash":"70c03e717046730c","prefixes":{"":{"product":327}}}, // [Lasoo Pty Ltd] - {"hash":"a1956c55f379362a","prefixes":{"":{"product":327}}}, // [Lasoo Pty Ltd] - {"hash":"78761e0920b86d00","prefixes":{"":{"product":327}}}, // [Lasoo Pty Ltd] - {"hash":"fb49a17ebf575b4b","prefixes":{"":{"product":327}}}, // [Lasoo Pty Ltd] - {"hash":"3ba767e322876167","prefixes":{"":{"product":327}}}, // [Lasoo Pty Ltd] - {"hash":"db60b4edeb07e6e0","prefixes":{"*":{"product":328}}}, // [Salefinder Ltd.] - {"hash":"1a2b2619e15f81ed","prefixes":{"":{"product":329}}}, // [The Monkeys Pty Ltd] + {"hash":"83efdfb00e5e0bb5","prefixes":{"":{"product":266,"type":0}}}, // [Innity Singapore Pte Ltd.] + {"hash":"5cdf5c58d4a95757","prefixes":{"":{"product":266,"type":0}}}, // [Innity Singapore Pte Ltd.] + {"hash":"e84e4c75279b444c","prefixes":{"":{"product":266,"type":0}}}, // [Innity Singapore Pte Ltd.] + {"hash":"0ad278b0f1bf83c7","prefixes":{"":{"product":267,"type":1}}}, // [Insight Express (Cross Media - Ignite)] + {"hash":"75089fef153b99d9","prefixes":{"":{"product":267,"type":1}}}, // [Insight Express (Cross Media - Ignite)] + {"hash":"17e48170b29e8c55","prefixes":{"":{"product":268,"type":0}}}, // [intelliAd Media GmbH] + {"hash":"8ff3a159f3a3dd37","prefixes":{"":{"product":268,"type":0}}}, // [intelliAd Media GmbH] + {"hash":"d5ad6ce37d416c20","prefixes":{"":{"product":268,"type":0}}}, // [intelliAd Media GmbH] + {"hash":"829116e73bbd766e","prefixes":{"*":{"product":269,"type":1}}}, // [DePauli AG] + {"hash":"58b6a73b811a6744","prefixes":{"":{"product":268,"type":0}}}, // [intelliAd Media GmbH] + {"hash":"1b02753d1ebc5935","prefixes":{"":{"product":270,"type":0}}}, // [Intelliad] + {"hash":"2d4767b28a0a3dc9","prefixes":{"":{"product":270,"type":0}}}, // [Intelliad] + {"hash":"04e4138ad91eba43","prefixes":{"*":{"product":271,"type":0}}}, // [Genome] + {"hash":"a80259001a08f5fe","prefixes":{"":{"product":271,"type":0}}}, // [Genome] + {"hash":"bccc7d85fcbd6406","prefixes":{"*":{"product":272,"type":0}}}, // [Intergi LLC dba PlaywireMedia] + {"hash":"c0e12f3f6483d539","prefixes":{"":{"product":273,"type":0}}}, // [Intermundo Media LLC] + {"hash":"aa0d2346396993dc","prefixes":{"*":{"product":274,"type":0}}}, // [Interpolls] + {"hash":"391f02c89579c41e","prefixes":{"*":{"product":275,"type":1}}}, // [Intelligent Reach (Intuitive Search Technologies)] + {"hash":"dd7ece8c8b4dd4db","prefixes":{"*":{"product":275,"type":1}}}, // [Intelligent Reach (Intuitive Search Technologies)] + {"hash":"51beebfd5a677c74","prefixes":{"":{"product":275,"type":1}}}, // [Intelligent Reach (Intuitive Search Technologies)] + {"hash":"15a557d1be0b55bc","prefixes":{"*":{"product":276,"type":0}}}, // [IPONWEB Limited] + {"hash":"ab800ebb45ab5e96","prefixes":{"":{"product":276,"type":0}}}, // [IPONWEB Limited] + {"hash":"cf6003cf8be11c49","prefixes":{"*":{"product":276,"type":0}}}, // [IPONWEB Limited] + {"hash":"bd97f2dac673ccef","prefixes":{"*":{"product":277,"type":0}}}, // [JasperLabs Inc.] + {"hash":"833a1bb3e47002bf","prefixes":{"":{"product":278,"type":0}}}, // [Jivox Corporation] + {"hash":"925afb63a81d22ae","prefixes":{"":{"product":278,"type":0}}}, // [Jivox Corporation] + {"hash":"e3546ee6177ce1af","prefixes":{"":{"product":278,"type":0}}}, // [Jivox Corporation] + {"hash":"a6e81a993b0dc090","prefixes":{"":{"product":278,"type":0}}}, // [Jivox Corporation] + {"hash":"57cf72a6bcc6ed09","prefixes":{"":{"product":278,"type":0}}}, // [Jivox Corporation] + {"hash":"aef508a87f7b9342","prefixes":{"":{"product":278,"type":0}}}, // [Jivox Corporation] + {"hash":"a1a0984cf6e12596","prefixes":{"":{"product":278,"type":0}}}, // [Jivox Corporation] + {"hash":"c1b82a9e7564881f","prefixes":{"*":{"product":279,"type":0}}}, // [Joinville AB] + {"hash":"e20dd6e83cbd14d9","prefixes":{"":{"product":280,"type":0}}}, // [KliKKicom Oy] + {"hash":"a1f03f455fc97850","prefixes":{"":{"product":281,"type":0}}}, // [Komli Media Inc.] + {"hash":"fb87830648f1fe7c","prefixes":{"":{"product":281,"type":0}}}, // [Komli Media Inc.] + {"hash":"93a6bcd7660ef88b","prefixes":{"":{"product":281,"type":0}}}, // [Komli Media Inc.] + {"hash":"14fba951393c4cc1","prefixes":{"":{"product":281,"type":0}}}, // [Komli Media Inc.] + {"hash":"96bf72901db53556","prefixes":{"":{"product":281,"type":0}}}, // [Komli Media Inc.] + {"hash":"00ceea10fed6f827","prefixes":{"":{"product":281,"type":0}}}, // [Komli Media Inc.] + {"hash":"5deb6288aeb4b20d","prefixes":{"":{"product":281,"type":0}}}, // [Komli Media Inc.] + {"hash":"30a9e5cf761c2db9","prefixes":{"":{"product":281,"type":0}}}, // [Komli Media Inc.] + {"hash":"b49fda322943ed64","prefixes":{"":{"product":281,"type":0}}}, // [Komli Media Inc.] + {"hash":"30067241c16c9f88","prefixes":{"*":{"product":282,"type":1}}}, // [Koninklijke Luchtvaart Maatschappij N.V.] + {"hash":"06076b672be3af43","prefixes":{"*":{"product":283,"type":1}}}, // [J.D. Power O2O] + {"hash":"1e23ff61443f919a","prefixes":{"*":{"product":284,"type":0}}}, // [Kwanzoo Inc.] + {"hash":"32327b1f6a21f5e3","prefixes":{"":{"product":285,"type":0}}}, // [Legolas Media Inc.] + {"hash":"0a98bd3ecf6d4f39","prefixes":{"":{"product":285,"type":0}}}, // [Legolas Media Inc.] + {"hash":"4141a8162aadd52a","prefixes":{"":{"product":285,"type":0}}}, // [Legolas Media Inc.] + {"hash":"9562185c6a06e194","prefixes":{"*":{"product":286,"type":0}}}, // [Undertone Ad System (UAS)] + {"hash":"d8be1c121ccbdb84","prefixes":{"":{"product":287,"type":0}}}, // [LEVEL Studios] + {"hash":"1b274516ac601c1d","prefixes":{"*":{"product":288,"type":0}}}, // [LinkedIn Corporation] + {"hash":"a9aceb9b28670518","prefixes":{"*":{"product":288,"type":0}}}, // [LinkedIn Corporation] + {"hash":"f202e32e7503e766","prefixes":{"":{"product":288,"type":0}}}, // [LinkedIn Corporation] + {"hash":"cf2094771b42b367","prefixes":{"*":{"product":288,"type":0}}}, // [LinkedIn Corporation] + {"hash":"ad94f98bfc0092ce","prefixes":{"*":{"product":289,"type":0}}}, // [Content Directions, Inc. dba Linkstorm] + {"hash":"2c97a2e1f7f59cde","prefixes":{"*":{"product":290,"type":1}}}, // [Liverail Inc.] + {"hash":"562dd0a17776cfc3","prefixes":{"*":{"product":291,"type":1}}}, // [Lotame Solutions Inc.] + {"hash":"85c409cdb78a6fec","prefixes":{"*":{"product":292,"type":0}}}, // [LucidMedia Networks Inc.] + {"hash":"25cdc372f14aa636","prefixes":{"":{"product":293,"type":0}}}, // [Magnetic Media Online Inc.] + {"hash":"490a692feb4f5f83","prefixes":{"":{"product":293,"type":0}}}, // [Magnetic Media Online Inc.] + {"hash":"8cd182ca413a6770","prefixes":{"":{"product":293,"type":0}}}, // [Magnetic Media Online Inc.] + {"hash":"891ff79862603ca1","prefixes":{"*":{"product":294,"type":1}}}, // [Mate1.com] + {"hash":"ae4598324ee10cb2","prefixes":{"":{"product":295,"type":0}}}, // [MaxPoint Interactive Inc.] + {"hash":"66eafecb064a6d3f","prefixes":{"*":{"product":296,"type":0}}}, // [Media Armor Inc.] + {"hash":"d9921090d75b28f3","prefixes":{"*":{"product":297,"type":1}}}, // [Xaxis, Inc] + {"hash":"4c897372b3205c67","prefixes":{"*":{"product":298,"type":0}}}, // [Dstillery] + {"hash":"78172051b147ff71","prefixes":{"*":{"product":298,"type":0}}}, // [Dstillery] + {"hash":"3e32e501635bb994","prefixes":{"*":{"product":299,"type":0}}}, // [Rakuten MediaForge] + {"hash":"ab3637f7ff19f3be","prefixes":{"*":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"eacb348c2bfde7c6","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"6ec884dc33afd8e3","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"6a0b44c268e0ea34","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"5ec2ba6f16455240","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"f6a166105958340d","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"1bafa194e1b43948","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"c4c10492cf3f1e5c","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"fb29996f4dbe86a3","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"33cba419c0d99c36","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"1471e355753e333a","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"8445471e74aaf1ad","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"fe448fc8fa6792c7","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"7142d0f7c95e6c11","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"f71e7939a3a06b85","prefixes":{"":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"25c9493f4ceef0b3","prefixes":{"*":{"product":300,"type":0}}}, // [Sizmek] + {"hash":"1c0486f5c9ddccc1","prefixes":{"":{"product":301,"type":0}}}, // [MediaMind] + {"hash":"511f53552d7c07f9","prefixes":{"*":{"product":302,"type":0}}}, // [Paypal] + {"hash":"c23b8169e8d6f935","prefixes":{"*":{"product":302,"type":0}}}, // [Paypal] + {"hash":"4cb72fa17c1e6b21","prefixes":{"*":{"product":303,"type":0}}}, // [ZEDO Inc.] + {"hash":"1f5866beb3a2da29","prefixes":{"":{"product":304,"type":0}}}, // [Contobox] + {"hash":"ab4011df7412e85a","prefixes":{"":{"product":304,"type":0}}}, // [Contobox] + {"hash":"4c55c99f7e731e4a","prefixes":{"":{"product":304,"type":0}}}, // [Contobox] + {"hash":"b32dad95de4864bb","prefixes":{"":{"product":304,"type":0}}}, // [Contobox] + {"hash":"e0636cdabf7592eb","prefixes":{"":{"product":305,"type":0}}}, // [Melt Tecnologia e Informatica S.A] + {"hash":"9e011383339e65c3","prefixes":{"":{"product":305,"type":0}}}, // [Melt Tecnologia e Informatica S.A] + {"hash":"c7f6b97c8a7defa6","prefixes":{"":{"product":305,"type":0}}}, // [Melt Tecnologia e Informatica S.A] + {"hash":"ba29743e534631a5","prefixes":{"":{"product":305,"type":0}}}, // [Melt Tecnologia e Informatica S.A] + {"hash":"df986bbd43ef130c","prefixes":{"":{"product":305,"type":0}}}, // [Melt Tecnologia e Informatica S.A] + {"hash":"32e39349c0434e31","prefixes":{"":{"product":305,"type":0}}}, // [Melt Tecnologia e Informatica S.A] + {"hash":"4b920fabf61fd6f3","prefixes":{"":{"product":305,"type":0}}}, // [Melt Tecnologia e Informatica S.A] + {"hash":"068f3a0cd7e03112","prefixes":{"":{"product":305,"type":0}}}, // [Melt Tecnologia e Informatica S.A] + {"hash":"95cce4f80c49239f","prefixes":{"*":{"product":306,"type":1}}}, // [MeMo2 / Hottraffic] + {"hash":"7672c0e258e0a20b","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"065ac7f58737b759","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"f0c15855e3418345","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"45068fe6a5fe83c0","prefixes":{"*":{"product":308,"type":0}}}, // [Mercado Livre.com Atividades de Internet Ltda] + {"hash":"a3fbfa83663a40a6","prefixes":{"*":{"product":308,"type":0}}}, // [Mercado Livre.com Atividades de Internet Ltda] + {"hash":"5241d2ae86ff307f","prefixes":{"":{"product":309,"type":0}}}, // [Merchenta Limited] + {"hash":"7b92690c1232eb23","prefixes":{"":{"product":309,"type":0}}}, // [Merchenta Limited] + {"hash":"e5b1a15c3a7a1ee6","prefixes":{"":{"product":309,"type":0}}}, // [Merchenta Limited] + {"hash":"f0b40488d9ecd9a2","prefixes":{"":{"product":309,"type":0}}}, // [Merchenta Limited] + {"hash":"63600c9242f10b0d","prefixes":{"":{"product":309,"type":0}}}, // [Merchenta Limited] + {"hash":"e89e81c1ed314cc1","prefixes":{"":{"product":310,"type":0}}}, // [Metapeople GmbH] + {"hash":"297f0571158ef576","prefixes":{"":{"product":310,"type":0}}}, // [Metapeople GmbH] + {"hash":"2228e5ce36c007c1","prefixes":{"":{"product":310,"type":0}}}, // [Metapeople GmbH] + {"hash":"798bcbf9415873df","prefixes":{"":{"product":310,"type":0}}}, // [Metapeople GmbH] + {"hash":"ab03f3b496037843","prefixes":{"":{"product":310,"type":0}}}, // [Metapeople GmbH] + {"hash":"eca01f0508fbf30b","prefixes":{"":{"product":310,"type":0}}}, // [Metapeople GmbH] + {"hash":"0d839898fade319a","prefixes":{"":{"product":310,"type":0}}}, // [Metapeople GmbH] + {"hash":"4fc010b1e52ce252","prefixes":{"":{"product":310,"type":0}}}, // [Metapeople GmbH] + {"hash":"31e7fb81bf0ec52f","prefixes":{"":{"product":310,"type":0}}}, // [Metapeople GmbH] + {"hash":"a6edfa074ceff9c5","prefixes":{"":{"product":310,"type":0}}}, // [Metapeople GmbH] + {"hash":"289dc75a912dcc97","prefixes":{"":{"product":310,"type":0}}}, // [Metapeople GmbH] + {"hash":"5a8de8926c410758","prefixes":{"":{"product":310,"type":0}}}, // [Metapeople GmbH] + {"hash":"79c798a9d8e32afc","prefixes":{"":{"product":311,"type":1}}}, // [MetrixLab B.V.] + {"hash":"61617058e6206283","prefixes":{"":{"product":311,"type":1}}}, // [MetrixLab B.V.] + {"hash":"cf945767a2fa79f3","prefixes":{"*":{"product":312,"type":0}}}, // [Mixpo Inc.] + {"hash":"541f85cbc710f2b3","prefixes":{"":{"product":313,"type":1}}}, // [Monsoon Ads Pvt. Ltd.] + {"hash":"c800e798e160fe89","prefixes":{"*":{"product":314,"type":0}}}, // [Monster] + {"hash":"775035c4c49057eb","prefixes":{"":{"product":314,"type":0}}}, // [Monster] + {"hash":"2a26221290e24a08","prefixes":{"":{"product":314,"type":0}}}, // [Monster] + {"hash":"fda966b5c6ec2b2f","prefixes":{"":{"product":314,"type":0}}}, // [Monster] + {"hash":"887d148a8ae98b2e","prefixes":{"*":{"product":315,"type":1}}}, // [neckermann.de GmbH] + {"hash":"35c76c9165e3349f","prefixes":{"*":{"product":316,"type":1}}}, // [Ad.agio] + {"hash":"d5c7d1240bf8989e","prefixes":{"":{"product":316,"type":1}}}, // [Ad.agio] + {"hash":"1e5ea56690a0716d","prefixes":{"*":{"product":316,"type":0}}}, // [Ad.agio] + {"hash":"a54661777ef51189","prefixes":{"*":{"product":317,"type":0}}}, // [Netmining LLC] + {"hash":"cc673c90c8abe830","prefixes":{"*":{"product":318,"type":0}}}, // [AdoTube] + {"hash":"5f4b0cbb95552b3f","prefixes":{"*":{"product":319,"type":0}}}, // [Next Audience GmbH] + {"hash":"a78e1096b3c03fbc","prefixes":{"":{"product":319,"type":0}}}, // [Next Audience GmbH] + {"hash":"582d973b69391ebe","prefixes":{"":{"product":319,"type":0}}}, // [Next Audience GmbH] + {"hash":"18585076a5b0c6dd","prefixes":{"":{"product":319,"type":0}}}, // [Next Audience GmbH] + {"hash":"1df4ee86fc680406","prefixes":{"":{"product":319,"type":0}}}, // [Next Audience GmbH] + {"hash":"ecd80a6a46f6a1ce","prefixes":{"":{"product":319,"type":0}}}, // [Next Audience GmbH] + {"hash":"8ee876aaaaf537e0","prefixes":{"":{"product":319,"type":0}}}, // [Next Audience GmbH] + {"hash":"92bc4f011133f05a","prefixes":{"*":{"product":320,"type":0}}}, // [Nextperf] + {"hash":"b10d35d6cde76082","prefixes":{"*":{"product":320,"type":0}}}, // [Nextperf] + {"hash":"8e6e5d6dc4720f98","prefixes":{"":{"product":320,"type":0}}}, // [Nextperf] + {"hash":"edc7f4e87a8ea4a3","prefixes":{"":{"product":320,"type":0}}}, // [Nextperf] + {"hash":"f0c76e07985c56c5","prefixes":{"":{"product":320,"type":0}}}, // [Nextperf] + {"hash":"cff1b3137482e5e3","prefixes":{"":{"product":320,"type":0}}}, // [Nextperf] + {"hash":"33f28c5ebbd4525e","prefixes":{"":{"product":320,"type":0}}}, // [Nextperf] + {"hash":"849c8324d4c32ea5","prefixes":{"*":{"product":321,"type":0}}}, // [Calibex] + {"hash":"0bbcc61ed60a63c7","prefixes":{"*":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"7da7b69cf130f867","prefixes":{"*":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"524bf7ee34882325","prefixes":{"*":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"0fc0858e8d42a096","prefixes":{"*":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"94d1d06666f458b2","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"9515f9226eae0ee6","prefixes":{"":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"c610850a50287c6c","prefixes":{"":{"product":322,"type":1}}}, // [ViziAds for Advertisers] + {"hash":"1324d12fd047205a","prefixes":{"":{"product":322,"type":1}}}, // [ViziAds for Advertisers] + {"hash":"922df75b11e4bdb8","prefixes":{"":{"product":322,"type":1}}}, // [ViziAds for Advertisers] + {"hash":"94be9a0ad636acc1","prefixes":{"":{"product":322,"type":1}}}, // [ViziAds for Advertisers] + {"hash":"921f858655989bdb","prefixes":{"":{"product":322,"type":1}}}, // [ViziAds for Advertisers] + {"hash":"0f44f6f2024007e3","prefixes":{"":{"product":323,"type":0}}}, // [FinanceGenerator] + {"hash":"c5d545736ea3f40c","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"c5190fb3c11efd5c","prefixes":{"":{"product":324,"type":1}}}, // [Telstra Corporation] + {"hash":"f8e19bba6ecb9d4d","prefixes":{"":{"product":324,"type":1}}}, // [Telstra Corporation] + {"hash":"78cb9e34e18a70c6","prefixes":{"":{"product":324,"type":1}}}, // [Telstra Corporation] + {"hash":"555b77a6dbc1077b","prefixes":{"":{"product":324,"type":1}}}, // [Telstra Corporation] + {"hash":"04cd318d8c9e0aa1","prefixes":{"":{"product":325,"type":1}}}, // [The Online Research Unit] + {"hash":"44b28a9d35489468","prefixes":{"":{"product":326,"type":0}}}, // [Webling Pty Ltd] + {"hash":"ce2a97a2bc3975b0","prefixes":{"*":{"product":327,"type":0}}}, // [Lasoo Pty Ltd] + {"hash":"70c03e717046730c","prefixes":{"":{"product":327,"type":0}}}, // [Lasoo Pty Ltd] + {"hash":"a1956c55f379362a","prefixes":{"":{"product":327,"type":0}}}, // [Lasoo Pty Ltd] + {"hash":"78761e0920b86d00","prefixes":{"":{"product":327,"type":0}}}, // [Lasoo Pty Ltd] + {"hash":"fb49a17ebf575b4b","prefixes":{"":{"product":327,"type":0}}}, // [Lasoo Pty Ltd] + {"hash":"3ba767e322876167","prefixes":{"":{"product":327,"type":0}}}, // [Lasoo Pty Ltd] + {"hash":"db60b4edeb07e6e0","prefixes":{"*":{"product":328,"type":0}}}, // [Salefinder Ltd.] + {"hash":"1a2b2619e15f81ed","prefixes":{"":{"product":329,"type":1}}}, // [The Monkeys Pty Ltd] {"hash":"d33c5423234580d2","prefixes":{"":{"product":330}}}, // [Louder Digital Pty Ltd] - {"hash":"35c305dfff8e956a","prefixes":{"":{"product":331}}}, // [Publisher’s Internationale Pty Ltd] - {"hash":"ab95fd39f34e1919","prefixes":{"*":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"e394eac0c09e952a","prefixes":{"*":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"d754759cedf098a4","prefixes":{"*":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"469abb509832dcba","prefixes":{"":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"089ade7154cdafd2","prefixes":{"":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"7c4e77c7146bc27c","prefixes":{"":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"27943a61af56578c","prefixes":{"":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"5b9d47d01e06e207","prefixes":{"":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"efae037999b8354a","prefixes":{"":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"64b1c22f19588e65","prefixes":{"*":{"product":7}}}, // [Wize Commerce, Inc.] - {"hash":"1b500703c376dccf","prefixes":{"":{"product":332}}}, // [NowSpots] - {"hash":"0b8a5111da2a18e6","prefixes":{"":{"product":332}}}, // [NowSpots] - {"hash":"6cbd63b4b5a258e2","prefixes":{"":{"product":333}}}, // [Ocapi] - {"hash":"2ecb3e4de562d83f","prefixes":{"*":{"product":334}}}, // [Predicta] - {"hash":"b0032d1f28de6b8e","prefixes":{"*":{"product":334}}}, // [Predicta] - {"hash":"495b10f97369710c","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"07b876ce04abdfc9","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"bd1d888d58054387","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"deb9a6a0e78770f8","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"3d9897472cebdff7","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"a036e7b2680b1720","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"ae8e27c2a1195c9d","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"685a4ece024544f3","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"d705e49e2ecfc500","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"4fd0a4a032a34191","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"2640f60d445d4d0d","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"0067af133fbf162f","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"62e23e8e0a53b097","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"57643f79e10fdc91","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"fe70aef371b87e0d","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"c80b88907c4da662","prefixes":{"":{"product":335}}}, // [Comune SA] - {"hash":"3c027bef12167411","prefixes":{"":{"product":336}}}, // [EuroAds Group A/S] - {"hash":"9e7ef06636d0b122","prefixes":{"":{"product":337}}}, // [Hotwords Informação LTDA] - {"hash":"ac577d2ba001c2f9","prefixes":{"":{"product":337}}}, // [Hotwords Informação LTDA] - {"hash":"8baa23f77cec98d3","prefixes":{"":{"product":337}}}, // [Hotwords Informação LTDA] - {"hash":"86e7352358e7a0a1","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"461a9aacd5db8b62","prefixes":{"":{"product":42}}}, // [Clinch.co] - {"hash":"4523c8dd39cb10d8","prefixes":{"":{"product":338}}}, // [uMotion] - {"hash":"a7eaf4ae4152200d","prefixes":{"":{"product":338}}}, // [uMotion] - {"hash":"1874ed5aa610db51","prefixes":{"*":{"product":339}}}, // [Google Zoo] - {"hash":"0dc9eb6c8b1c77fa","prefixes":{"*":{"product":35}}}, // [Oggifinogi] - {"hash":"60d67cd6819e7de4","prefixes":{"*":{"product":340}}}, // [Audience Manager] - {"hash":"2ae524eac16b06f8","prefixes":{"":{"product":341}}}, // [ONDCP] - {"hash":"8210c1a27bdc1916","prefixes":{"*":{"product":143}}}, // [Edgesuite] - {"hash":"ca8cb9c623002dc9","prefixes":{"*":{"product":143}}}, // [Edgesuite] - {"hash":"3ba6cc7216a7d5ae","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"24267a212835b827","prefixes":{"*":{"product":143}}}, // [Edgesuite] - {"hash":"060ee4c312a8e977","prefixes":{"":{"product":342}}}, // [LOKA Research inc.] - {"hash":"c7e974006ec125b7","prefixes":{"*":{"product":343}}}, // [OpenX OnRamp] - {"hash":"a985fc121086ead8","prefixes":{"*":{"product":344}}}, // [OpenX Ad Server] - {"hash":"402ca9fbb308a1c5","prefixes":{"*":{"product":36}}}, // [PaperG] - {"hash":"53f1cd9b06aea643","prefixes":{"*":{"product":36}}}, // [PaperG] - {"hash":"36b3ccfb92c2fb71","prefixes":{"*":{"product":345}}}, // [Parship] - {"hash":"28832d626c0b0925","prefixes":{"*":{"product":346}}}, // [pauldirekt GmbH] - {"hash":"1d474301c170499d","prefixes":{"*":{"product":347}}}, // [Pictela Inc.] - {"hash":"fd1aa96507b2bf44","prefixes":{"":{"product":347}}}, // [Pictela Inc.] - {"hash":"7f890c0fd0c6a4d9","prefixes":{"":{"product":348}}}, // [Pilot 1/0 GmbH & Co KG] - {"hash":"549e294957d756d8","prefixes":{"":{"product":348}}}, // [Pilot 1/0 GmbH & Co KG] - {"hash":"5dc046f77f32adf1","prefixes":{"*":{"product":349}}}, // [Piximedia] - {"hash":"637b449ba51266a3","prefixes":{"*":{"product":349}}}, // [Piximedia] - {"hash":"013ba3dd6b18ee4a","prefixes":{"*":{"product":350}}}, // [Pointroll] - {"hash":"d96024cf9bafa9d0","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"4f0c9093d18b4ecd","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"d63f961e0c8cc056","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"1bcfb023adee2b08","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"6ed6fb838bd994d7","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"9fd07c030d45578d","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"5370f7b026779f44","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"c367910d58376fa0","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"670926f337b85492","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"77d7124c8aa87819","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"3726ef9236aeff59","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"84078980dc7d0310","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"496666ed92d32be6","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"3e8a19db4e7dd91a","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"33cfdc955bd4ab90","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"543046798ae8e38d","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"54537a7d4ce6fc35","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"242ab5d44fae500c","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"e81d4aa82d04d068","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"7c7f55d8a75cb9bc","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"e4a82caa59141478","prefixes":{"":{"product":351}}}, // [Beijing PinYou Interactive Information Technology] - {"hash":"caf06dc269e4cbd7","prefixes":{"":{"product":352}}}, // [YoYi Interactive] - {"hash":"70584cd7bcb88744","prefixes":{"":{"product":352}}}, // [YoYi Interactive] - {"hash":"c9cabfef49bb4ec1","prefixes":{"":{"product":352}}}, // [YoYi Interactive] - {"hash":"993089a2d306632e","prefixes":{"":{"product":352}}}, // [YoYi Interactive] - {"hash":"cf04aaaa5ae5f383","prefixes":{"":{"product":352}}}, // [YoYi Interactive] - {"hash":"a1cd6a668ae89bc8","prefixes":{"*":{"product":353}}}, // [AdMaster] - {"hash":"f72dd5293eba3ca3","prefixes":{"":{"product":353}}}, // [AdMaster] - {"hash":"e946e6b718e0e81a","prefixes":{"":{"product":353}}}, // [AdMaster] - {"hash":"01b5e469f3b6d1d9","prefixes":{"":{"product":354}}}, // [D.A.Consortium Beijing (Platform One China)] - {"hash":"f091b3175305cced","prefixes":{"":{"product":354}}}, // [D.A.Consortium Beijing (Platform One China)] - {"hash":"1a095d1901f0940b","prefixes":{"":{"product":355}}}, // [New Allyes Information Technology (winmax)] - {"hash":"f66f99ee20105c2c","prefixes":{"*":{"product":356}}}, // [PurposeLab] - {"hash":"86c250cf0da31481","prefixes":{"":{"product":356}}}, // [PurposeLab] - {"hash":"8f204c79d6b23736","prefixes":{"*":{"product":334}}}, // [Predicta] - {"hash":"43d06db6d6527876","prefixes":{"":{"product":357}}}, // [Proclivity Systems] - {"hash":"5f76990173953807","prefixes":{"":{"product":357}}}, // [Proclivity Systems] - {"hash":"7d3947ee9533bf30","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"fb241396adc3ebde","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"b8c5f46fb8945332","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"ade9cbc2becb390f","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"874cfa4e9fe27233","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"2cd6bee614e910f1","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"854f37cd1f444e62","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"19a83c7a2b673a6d","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"ca312e078723d178","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"4aa2d41fa2878d8f","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"8931cc3c2d6bbbff","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"e67e88dcc0afe050","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"3f6c08baf48fa0ae","prefixes":{"":{"product":37}}}, // [Public-Idées] - {"hash":"6303a58061eaabd1","prefixes":{"*":{"product":358}}}, // [Viewbix] - {"hash":"4fdc8f2ff122ce2e","prefixes":{"":{"product":358}}}, // [Viewbix] - {"hash":"ba78a984ad7a8c06","prefixes":{"":{"product":358}}}, // [Viewbix] - {"hash":"00885ce869b93eab","prefixes":{"":{"product":358}}}, // [Viewbix] - {"hash":"eb59f3a64b415670","prefixes":{"":{"product":359}}}, // [Quantcast Inc.] - {"hash":"243c70f61da9731c","prefixes":{"":{"product":359}}}, // [Quantcast Inc.] - {"hash":"ed6b204d6b8f351e","prefixes":{"":{"product":359}}}, // [Quantcast Inc.] - {"hash":"e6888b5be4ecca23","prefixes":{"":{"product":359}}}, // [Quantcast Inc.] - {"hash":"8034327c12c77172","prefixes":{"":{"product":359}}}, // [Quantcast Inc.] - {"hash":"d48f950e0036e4ee","prefixes":{"*":{"product":360}}}, // [QuinStreet] - {"hash":"6118e4e0e4001349","prefixes":{"*":{"product":361}}}, // [Quisma GmbH] - {"hash":"1b2f3dadf0889c1c","prefixes":{"":{"product":362}}}, // [Quismatch / Quisma Tracker] - {"hash":"491acc9692437dcc","prefixes":{"":{"product":362}}}, // [Quismatch / Quisma Tracker] - {"hash":"95be38e789f1c074","prefixes":{"":{"product":362}}}, // [Quismatch / Quisma Tracker] - {"hash":"7d13c9a93867cfd5","prefixes":{"":{"product":362}}}, // [Quismatch / Quisma Tracker] - {"hash":"aee8b719a85b0392","prefixes":{"":{"product":362}}}, // [Quismatch / Quisma Tracker] - {"hash":"03c0d3572439e910","prefixes":{"":{"product":362}}}, // [Quismatch / Quisma Tracker] - {"hash":"42c10737e9d2eb44","prefixes":{"":{"product":362}}}, // [Quismatch / Quisma Tracker] - {"hash":"1ece70926dbb1e9c","prefixes":{"*":{"product":362}}}, // [Quismatch / Quisma Tracker] - {"hash":"15b1b56db686d6b8","prefixes":{"":{"product":362}}}, // [Quismatch / Quisma Tracker] - {"hash":"6f2fb017c596785a","prefixes":{"*":{"product":363}}}, // [Qwobl Inc.] - {"hash":"45bd1c4bac827eb4","prefixes":{"*":{"product":364}}}, // [RadiumOne Inc.] - {"hash":"a4cc28a873663be4","prefixes":{"*":{"product":365}}}, // [Core Audience, Inc] - {"hash":"b1b347108c9875ae","prefixes":{"*":{"product":366}}}, // [The Reach Group] - {"hash":"9680c32132a31294","prefixes":{"":{"product":367}}}, // [revenue cloud] - {"hash":"4654f1b3d29f0a2a","prefixes":{"":{"product":367}}}, // [revenue cloud] - {"hash":"c8daf5a2befc762c","prefixes":{"":{"product":367}}}, // [revenue cloud] - {"hash":"cd7c04dcaab54cf3","prefixes":{"":{"product":366}}}, // [The Reach Group] - {"hash":"6a7ac3b20a8267da","prefixes":{"*":{"product":368}}}, // [Register.it] - {"hash":"24064a7ef37c0464","prefixes":{"":{"product":369}}}, // [ReleStar] - {"hash":"28a4e40561f9acae","prefixes":{"":{"product":369}}}, // [ReleStar] - {"hash":"3de1987cea55e4a5","prefixes":{"":{"product":369}}}, // [ReleStar] - {"hash":"827fd98c61df481c","prefixes":{"":{"product":369}}}, // [ReleStar] - {"hash":"eec1a8a2a7fb129b","prefixes":{"":{"product":369}}}, // [ReleStar] - {"hash":"6c1b7209cced7033","prefixes":{"*":{"product":370}}}, // [Research Horizons LLC dba Phoenix Marketing] - {"hash":"c946c0fe5eecd55f","prefixes":{"":{"product":8}}}, // [Research Now Limited] - {"hash":"2feb43f5f97da585","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"4847977384b78f1d","prefixes":{"":{"product":8}}}, // [Research Now Limited] - {"hash":"308241d0fe4d6897","prefixes":{"":{"product":8}}}, // [Research Now Limited] - {"hash":"2cb30990aa0823eb","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"2c25ebde178886b1","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"d4eeb4a4736e8358","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"12498108d00bd104","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"c7437019688a5c87","prefixes":{"":{"product":8}}}, // [Research Now Limited] - {"hash":"ebc599442a1e60e0","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"ab9c2a8a5ed26375","prefixes":{"":{"product":8}}}, // [Research Now Limited] - {"hash":"c9473e1a1e9213bc","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"a15bca05fb29201f","prefixes":{"":{"product":8}}}, // [Research Now Limited] - {"hash":"8c2336c1a87e9c7e","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"67f7079b53ce160f","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"a07c7ea743bca71c","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"ce0849726cb792fb","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"6d2feeb6316bf983","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"056132328ebc8a3b","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"c0dd251eb151bbdd","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"02e6b230a73d95aa","prefixes":{"":{"product":8}}}, // [Research Now Limited] - {"hash":"62cef89124c9831e","prefixes":{"*":{"product":8}}}, // [Research Now Limited] - {"hash":"1bb2fad94e9dfd9e","prefixes":{"":{"product":8}}}, // [Research Now Limited] - {"hash":"0bca341ab2881187","prefixes":{"":{"product":8}}}, // [Research Now Limited] - {"hash":"fb725c5783121bc4","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"6d442fcb13dbd9da","prefixes":{"":{"product":8}}}, // [Research Now Limited] - {"hash":"6020c585ae546ba6","prefixes":{"":{"product":8}}}, // [Research Now Limited] - {"hash":"bf994d767fc23e27","prefixes":{"":{"product":371}}}, // [Retention Media Inc.] - {"hash":"5c801bba74bf0884","prefixes":{"":{"product":372}}}, // [Suite 66] - {"hash":"f727f4c8af36c75c","prefixes":{"":{"product":373}}}, // [Dynamic Logic / Safecount (AdIndex)] - {"hash":"d0ffa461035bdf6a","prefixes":{"":{"product":373}}}, // [Dynamic Logic / Safecount (AdIndex)] - {"hash":"f1381513cbb99bf4","prefixes":{"":{"product":373}}}, // [Dynamic Logic / Safecount (AdIndex)] - {"hash":"2b675a4d048f6d58","prefixes":{"":{"product":373}}}, // [Dynamic Logic / Safecount (AdIndex)] - {"hash":"ff9153951d29d7eb","prefixes":{"":{"product":373}}}, // [Dynamic Logic / Safecount (AdIndex)] - {"hash":"9a2d88a64367054f","prefixes":{"":{"product":373}}}, // [Dynamic Logic / Safecount (AdIndex)] - {"hash":"22fc5e00cc71b2ca","prefixes":{"":{"product":373}}}, // [Dynamic Logic / Safecount (AdIndex)] - {"hash":"d680287680a3b47b","prefixes":{"*":{"product":374}}}, // [BridgeTrack] - {"hash":"6659ffe0ec0db1a1","prefixes":{"*":{"product":375}}}, // [adnanny.com GmbH] - {"hash":"cdef303f827a483a","prefixes":{"":{"product":375}}}, // [adnanny.com GmbH] - {"hash":"d37d706078f5ef0e","prefixes":{"":{"product":375}}}, // [adnanny.com GmbH] - {"hash":"cefa23f603f78274","prefixes":{"":{"product":375}}}, // [adnanny.com GmbH] - {"hash":"9beed54a2448f091","prefixes":{"*":{"product":376}}}, // [AdRoll] - {"hash":"131ff02cd8b2b585","prefixes":{"*":{"product":377}}}, // [AdExtent] - {"hash":"7b03a999ce62649a","prefixes":{"*":{"product":377}}}, // [AdExtent] - {"hash":"d888444955526bb9","prefixes":{"*":{"product":378}}}, // [ShareThis Inc.] - {"hash":"24bedaecde8de52e","prefixes":{"*":{"product":379}}}, // [Shirtinator] - {"hash":"b2227832d5aab97c","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"29d1a1af90fe4764","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"55d58888ac21e28e","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"15a0a565c098bb6c","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"c740f7042a936f94","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"83b6131729d98b9a","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"df61075a3761234c","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"31d664b6a0c86fc5","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"b3f1fda5ca08f66c","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"a505bd8c5fdbe348","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"ff4b6ade85c0fa47","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"55fbb05b573abfc0","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"7509d096b740a94e","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"3e05ad70e7b857f6","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"f3122b05b916b4d8","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"7df77439ca0af167","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"7b6f3b92d848f180","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"c50b3a11c75c1de2","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"42bd2bd016c36072","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"d964e110e03add5e","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"b2f31dc5aea81475","prefixes":{"":{"product":380}}}, // [Simplifi Holdings Inc.] - {"hash":"fd3e5505c689b1bc","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"e21937d0011ae5da","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"0f5e4a0353dbf996","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"0ece74eb8682685e","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"3d8ea3f0d5d389d5","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"b5602307e99e9538","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"c13decc96884eb9a","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"b815964fd4b63ffe","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"a49f2db509757639","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"a3ff80b45a2b0087","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"b1b2c1399cbf19be","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"ba44917903f4a6c0","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"ad5130e5aa2d0bcd","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"ceb371583c3948ee","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"5d5d4fe496a7b543","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"30e80084c1e7285e","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"d1d0fc6a034973b5","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"e2814abcd5399a68","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"9d4acd34336a73d4","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"dcbf7d7841f88317","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"c19fe37a92d8a1f4","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"dd502cbc700beb03","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"a76947b64ea18232","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"75875c5fcc471f0e","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"5323dbf9f56befc9","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"fd3df839224700c5","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"dc544506e0acf31c","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"fbadeeb25ac766a9","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"f344fa72c3acea98","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"e0d1929f5490ba3c","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"150d5c444034d16f","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"63c9992c37df81e6","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"9a2f65999a2602e7","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"b13d21bc9d60e3cf","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"36778688c2c8550d","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"7764641665318d7a","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"137839bac6b52f11","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"75b17e7427d84ec0","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"f576b8f6b5698927","prefixes":{"":{"product":381}}}, // [Centro DSP] - {"hash":"a0bef488713fd8ba","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"c4f4b5d7a3bc8772","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"652de2e0257cc6f9","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"e1eb84d2322dd53f","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"0759e6e60e23806b","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"b97f9d3a0092f5df","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"6f7d322aac5f6093","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"d6d2092af97f6672","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"700b4497422246d3","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"24758e00974c4842","prefixes":{"*":{"product":382}}}, // [Smart Adserver] - {"hash":"229fb1e217ec3254","prefixes":{"*":{"product":382}}}, // [Smart Adserver] - {"hash":"24f84ec66db45f3d","prefixes":{"":{"product":383}}}, // [smartclip Holding AG] - {"hash":"7bce0d8d711753ea","prefixes":{"":{"product":383}}}, // [smartclip Holding AG] - {"hash":"f748f5ce8e9c4b7d","prefixes":{"*":{"product":384}}}, // [Snap Technologies Inc.] - {"hash":"c17d7dedc318749c","prefixes":{"":{"product":385}}}, // [So-net Media Networks] - {"hash":"d3a65eea99debc9b","prefixes":{"":{"product":385}}}, // [So-net Media Networks] - {"hash":"f28c7fc4a06bcfa7","prefixes":{"*":{"product":386}}}, // [SocialMedia.com] - {"hash":"17591c31cbbe7cf8","prefixes":{"":{"product":387}}}, // [Content to Emotion (CTE)] - {"hash":"7c350f8bcf5a54b9","prefixes":{"":{"product":387}}}, // [Content to Emotion (CTE)] - {"hash":"e003938122f9ac4f","prefixes":{"":{"product":387}}}, // [Content to Emotion (CTE)] - {"hash":"6deac101ca463319","prefixes":{"static":{"product":387}}}, // [Content to Emotion (CTE)] - {"hash":"304e631663a87e67","prefixes":{"*":{"product":388}}}, // [Sociomantic.com] - {"hash":"e86474f9c6ad794d","prefixes":{"":{"product":389}}}, // [AdSpeed] - {"hash":"de0816aa39c8b153","prefixes":{"*":{"product":390}}}, // [Sophus3] - {"hash":"df8355613a445a85","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"a72f2b989760c8dc","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"fbdc1704c28873c8","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"d4674ccaf8fb7e31","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"f184677fb7e2abca","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"e7d695bf507e45d5","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"ea3f746342f05dbf","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"96ce83a8f0d84d99","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"62c6410f3e4000d8","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"b5172a6eee01acbe","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"36f9ba3a735ea443","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"f4d96ab5c7d0f720","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"7c8204a143e83abb","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"cb5b72c4fdc90b38","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"01c1382916f7a580","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"49505fd99e787062","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"a931030a5dbd7346","prefixes":{"":{"product":9}}}, // [Spartoo] - {"hash":"3a09b22266ba0b12","prefixes":{"*":{"product":391}}}, // [Specific Media Inc.] - {"hash":"2136a3b6f6600ad0","prefixes":{"*":{"product":391}}}, // [Specific Media Inc.] - {"hash":"600e429523014251","prefixes":{"*":{"product":391}}}, // [Specific Media Inc.] - {"hash":"e8b1c9274a662ad3","prefixes":{"":{"product":392}}}, // [Metrigo GmbH] - {"hash":"d0ffd80eda189780","prefixes":{"":{"product":392}}}, // [Metrigo GmbH] - {"hash":"e4ab3c31faef2b98","prefixes":{"":{"product":392}}}, // [Metrigo GmbH] - {"hash":"97db8dd1bcbc33b8","prefixes":{"*":{"product":393}}}, // [SpongeCell] - {"hash":"363a0f26e680d077","prefixes":{"":{"product":394}}}, // [SpngeCell LLC] - {"hash":"fbef9c1b28b0cb05","prefixes":{"*":{"product":393}}}, // [SpongeCell] - {"hash":"2218b5ce1e656e21","prefixes":{"":{"product":395}}}, // [SpotXchange] - {"hash":"a520f16cf6177ebd","prefixes":{"":{"product":395}}}, // [SpotXchange] - {"hash":"cda310d3654d07a5","prefixes":{"":{"product":395}}}, // [SpotXchange] - {"hash":"2fc5567578510af6","prefixes":{"":{"product":396}}}, // [Spotxchange] - {"hash":"abab2d20e98c266d","prefixes":{"":{"product":395}}}, // [SpotXchange] - {"hash":"0d78cf3b068120c3","prefixes":{"":{"product":395}}}, // [SpotXchange] - {"hash":"6da7c1b25ca845b3","prefixes":{"":{"product":395}}}, // [SpotXchange] - {"hash":"c824df0fb0fdf482","prefixes":{"":{"product":397}}}, // [Encore Attribution Platform] - {"hash":"9796e014709ccbec","prefixes":{"":{"product":397}}}, // [Encore Attribution Platform] - {"hash":"fced1a8e32fb989c","prefixes":{"*":{"product":398}}}, // [Steelhouse] - {"hash":"314523d1c217734f","prefixes":{"*":{"product":399}}}, // [Strike New Media Limited] - {"hash":"276a5e6003750c07","prefixes":{"*":{"product":400}}}, // [Struq Limited] - {"hash":"e5652beb11c7fceb","prefixes":{"*":{"product":401}}}, // [SundaySky Inc.] - {"hash":"173a426f6562928a","prefixes":{"":{"product":402}}}, // [Symphony Advanced Media] - {"hash":"81a2745fc67a8ecf","prefixes":{"":{"product":402}}}, // [Symphony Advanced Media] - {"hash":"0aea8cde58b4f14e","prefixes":{"":{"product":402}}}, // [Symphony Advanced Media] - {"hash":"b73e77077b022d36","prefixes":{"":{"product":402}}}, // [Symphony Advanced Media] - {"hash":"fcf0d2e1f5fa003b","prefixes":{"":{"product":402}}}, // [Symphony Advanced Media] - {"hash":"361c645b41a96807","prefixes":{"":{"product":402}}}, // [Symphony Advanced Media] - {"hash":"81df9375fed9172e","prefixes":{"":{"product":402}}}, // [Symphony Advanced Media] - {"hash":"c1493a0cd3b358a5","prefixes":{"":{"product":402}}}, // [Symphony Advanced Media] - {"hash":"bdedb9447527960a","prefixes":{"":{"product":402}}}, // [Symphony Advanced Media] - {"hash":"1cb83aa94e1a92ed","prefixes":{"":{"product":402}}}, // [Symphony Advanced Media] - {"hash":"2172731c879fab72","prefixes":{"":{"product":402}}}, // [Symphony Advanced Media] - {"hash":"7dd683bf50ce5c95","prefixes":{"":{"product":402}}}, // [Symphony Advanced Media] - {"hash":"aa47b70219d2ee5e","prefixes":{"*":{"product":403}}}, // [TagMan Ltd.] - {"hash":"097edb88beda9a20","prefixes":{"":{"product":404}}}, // [Taobao] - {"hash":"bc65fc5f46cd88c9","prefixes":{"":{"product":404}}}, // [Taobao] - {"hash":"a4d1bf696dde4d0b","prefixes":{"":{"product":404}}}, // [Taobao] - {"hash":"c94f9318ace953f1","prefixes":{"":{"product":404}}}, // [Taobao] - {"hash":"9e2b38828859944c","prefixes":{"":{"product":404}}}, // [Taobao] - {"hash":"02319fc6286418de","prefixes":{"":{"product":404}}}, // [Taobao] - {"hash":"dacc570e07ffd91a","prefixes":{"img":{"product":404}}}, // [Taobao] - {"hash":"e8ccbc8f652e85a2","prefixes":{"*":{"product":404}}}, // [Taobao] - {"hash":"da1ba7cc516336c0","prefixes":{"":{"product":404}}}, // [Taobao] - {"hash":"41035e7733acf867","prefixes":{"":{"product":405}}}, // [Target.com] - {"hash":"0509bdf297db5010","prefixes":{"*":{"product":406}}}, // [Teadma] - {"hash":"69925c7888575612","prefixes":{"":{"product":407}}}, // [BannerConnect BV] - {"hash":"4d44c3cec23aea09","prefixes":{"":{"product":407}}}, // [BannerConnect BV] - {"hash":"447ea46d0797b32f","prefixes":{"*":{"product":408}}}, // [Teracent Corporation] - {"hash":"26ca7e33d194e46e","prefixes":{"":{"product":408}}}, // [Teracent Corporation] - {"hash":"b49b79e2e870c3e9","prefixes":{"":{"product":408}}}, // [Teracent Corporation] - {"hash":"3a555db76a46f881","prefixes":{"*":{"product":38}}}, // [The Trade Desk Inc.] - {"hash":"c4684dd3ef28687a","prefixes":{"*":{"product":409}}}, // [The Travelers Indemnity Company] - {"hash":"1c38e7ac2dcf5d58","prefixes":{"":{"product":410}}}, // [Videology] - {"hash":"4872cdec0944a698","prefixes":{"":{"product":410}}}, // [Videology] - {"hash":"d4e30248b2920988","prefixes":{"*":{"product":411}}}, // [TNS Custom Research Inc.] - {"hash":"48a3c2e049507f03","prefixes":{"*":{"product":412}}}, // [TrackingSoft LLC] - {"hash":"4c5b26902a10b85b","prefixes":{"*":{"product":412}}}, // [TrackingSoft LLC] - {"hash":"51a48ea23568f817","prefixes":{"*":{"product":413}}}, // [Tradedoubler] - {"hash":"14251708a577d8c0","prefixes":{"*":{"product":414}}}, // [Epic Marketplace] - {"hash":"20f50db7213cc9ee","prefixes":{"*":{"product":415}}}, // [Tribal Fusion] - {"hash":"37b92f46ce8d0fa5","prefixes":{"":{"product":415}}}, // [Tribal Fusion] - {"hash":"218cac8e116dcf7a","prefixes":{"":{"product":416}}}, // [Triggit] + {"hash":"35c305dfff8e956a","prefixes":{"":{"product":331,"type":0}}}, // [Publisher’s Internationale Pty Ltd] + {"hash":"ab95fd39f34e1919","prefixes":{"*":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"e394eac0c09e952a","prefixes":{"*":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"d754759cedf098a4","prefixes":{"*":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"469abb509832dcba","prefixes":{"":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"089ade7154cdafd2","prefixes":{"":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"7c4e77c7146bc27c","prefixes":{"":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"27943a61af56578c","prefixes":{"":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"5b9d47d01e06e207","prefixes":{"":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"efae037999b8354a","prefixes":{"":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"64b1c22f19588e65","prefixes":{"*":{"product":7,"type":0}}}, // [Wize Commerce, Inc.] + {"hash":"1b500703c376dccf","prefixes":{"":{"product":332,"type":0}}}, // [NowSpots] + {"hash":"0b8a5111da2a18e6","prefixes":{"":{"product":332,"type":0}}}, // [NowSpots] + {"hash":"6cbd63b4b5a258e2","prefixes":{"":{"product":333,"type":0}}}, // [Ocapi] + {"hash":"2ecb3e4de562d83f","prefixes":{"*":{"product":334,"type":0}}}, // [Predicta] + {"hash":"b0032d1f28de6b8e","prefixes":{"*":{"product":334,"type":0}}}, // [Predicta] + {"hash":"495b10f97369710c","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"07b876ce04abdfc9","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"bd1d888d58054387","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"deb9a6a0e78770f8","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"3d9897472cebdff7","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"a036e7b2680b1720","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"ae8e27c2a1195c9d","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"685a4ece024544f3","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"d705e49e2ecfc500","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"4fd0a4a032a34191","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"2640f60d445d4d0d","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"0067af133fbf162f","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"62e23e8e0a53b097","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"57643f79e10fdc91","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"fe70aef371b87e0d","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"c80b88907c4da662","prefixes":{"":{"product":335,"type":0}}}, // [Comune SA] + {"hash":"3c027bef12167411","prefixes":{"":{"product":336,"type":0}}}, // [EuroAds Group A/S] + {"hash":"9e7ef06636d0b122","prefixes":{"":{"product":337,"type":0}}}, // [Hotwords Informação LTDA] + {"hash":"ac577d2ba001c2f9","prefixes":{"":{"product":337,"type":0}}}, // [Hotwords Informação LTDA] + {"hash":"8baa23f77cec98d3","prefixes":{"":{"product":337,"type":0}}}, // [Hotwords Informação LTDA] + {"hash":"86e7352358e7a0a1","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"461a9aacd5db8b62","prefixes":{"":{"product":42,"type":0}}}, // [Clinch.co] + {"hash":"4523c8dd39cb10d8","prefixes":{"":{"product":338,"type":0}}}, // [uMotion] + {"hash":"a7eaf4ae4152200d","prefixes":{"":{"product":338,"type":0}}}, // [uMotion] + {"hash":"1874ed5aa610db51","prefixes":{"*":{"product":339,"type":1}}}, // [Google Zoo] + {"hash":"0dc9eb6c8b1c77fa","prefixes":{"*":{"product":35,"type":0}}}, // [Oggifinogi] + {"hash":"60d67cd6819e7de4","prefixes":{"*":{"product":340,"type":1}}}, // [Audience Manager] + {"hash":"2ae524eac16b06f8","prefixes":{"":{"product":341,"type":0}}}, // [ONDCP] + {"hash":"8210c1a27bdc1916","prefixes":{"*":{"product":143,"type":2}}}, // [Edgesuite] + {"hash":"ca8cb9c623002dc9","prefixes":{"*":{"product":143,"type":2}}}, // [Edgesuite] + {"hash":"3ba6cc7216a7d5ae","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"24267a212835b827","prefixes":{"*":{"product":143,"type":2}}}, // [Edgesuite] + {"hash":"060ee4c312a8e977","prefixes":{"":{"product":342,"type":0}}}, // [LOKA Research inc.] + {"hash":"c7e974006ec125b7","prefixes":{"*":{"product":343,"type":0}}}, // [OpenX OnRamp] + {"hash":"a985fc121086ead8","prefixes":{"*":{"product":344,"type":0}}}, // [OpenX Ad Server] + {"hash":"402ca9fbb308a1c5","prefixes":{"*":{"product":36,"type":0}}}, // [PaperG] + {"hash":"53f1cd9b06aea643","prefixes":{"*":{"product":36,"type":0}}}, // [PaperG] + {"hash":"36b3ccfb92c2fb71","prefixes":{"*":{"product":345,"type":0}}}, // [Parship] + {"hash":"28832d626c0b0925","prefixes":{"*":{"product":346,"type":1}}}, // [pauldirekt GmbH] + {"hash":"1d474301c170499d","prefixes":{"*":{"product":347,"type":0}}}, // [Pictela Inc.] + {"hash":"fd1aa96507b2bf44","prefixes":{"":{"product":347,"type":0}}}, // [Pictela Inc.] + {"hash":"7f890c0fd0c6a4d9","prefixes":{"":{"product":348,"type":0}}}, // [Pilot 1/0 GmbH & Co KG] + {"hash":"549e294957d756d8","prefixes":{"":{"product":348,"type":0}}}, // [Pilot 1/0 GmbH & Co KG] + {"hash":"5dc046f77f32adf1","prefixes":{"*":{"product":349,"type":0}}}, // [Piximedia] + {"hash":"637b449ba51266a3","prefixes":{"*":{"product":349,"type":0}}}, // [Piximedia] + {"hash":"013ba3dd6b18ee4a","prefixes":{"*":{"product":350,"type":0}}}, // [Pointroll] + {"hash":"d96024cf9bafa9d0","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"4f0c9093d18b4ecd","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"d63f961e0c8cc056","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"1bcfb023adee2b08","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"6ed6fb838bd994d7","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"9fd07c030d45578d","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"5370f7b026779f44","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"c367910d58376fa0","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"670926f337b85492","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"77d7124c8aa87819","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"3726ef9236aeff59","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"84078980dc7d0310","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"496666ed92d32be6","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"3e8a19db4e7dd91a","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"33cfdc955bd4ab90","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"543046798ae8e38d","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"54537a7d4ce6fc35","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"242ab5d44fae500c","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"e81d4aa82d04d068","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"7c7f55d8a75cb9bc","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"e4a82caa59141478","prefixes":{"":{"product":351,"type":0}}}, // [Beijing PinYou Interactive Information Technology] + {"hash":"caf06dc269e4cbd7","prefixes":{"":{"product":352,"type":0}}}, // [YoYi Interactive] + {"hash":"70584cd7bcb88744","prefixes":{"":{"product":352,"type":0}}}, // [YoYi Interactive] + {"hash":"c9cabfef49bb4ec1","prefixes":{"":{"product":352,"type":0}}}, // [YoYi Interactive] + {"hash":"993089a2d306632e","prefixes":{"":{"product":352,"type":0}}}, // [YoYi Interactive] + {"hash":"cf04aaaa5ae5f383","prefixes":{"":{"product":352,"type":0}}}, // [YoYi Interactive] + {"hash":"a1cd6a668ae89bc8","prefixes":{"*":{"product":353,"type":1}}}, // [AdMaster] + {"hash":"f72dd5293eba3ca3","prefixes":{"":{"product":353,"type":1}}}, // [AdMaster] + {"hash":"e946e6b718e0e81a","prefixes":{"":{"product":353,"type":1}}}, // [AdMaster] + {"hash":"01b5e469f3b6d1d9","prefixes":{"":{"product":354,"type":0}}}, // [D.A.Consortium Beijing (Platform One China)] + {"hash":"f091b3175305cced","prefixes":{"":{"product":354,"type":0}}}, // [D.A.Consortium Beijing (Platform One China)] + {"hash":"1a095d1901f0940b","prefixes":{"":{"product":355,"type":0}}}, // [New Allyes Information Technology (winmax)] + {"hash":"f66f99ee20105c2c","prefixes":{"*":{"product":356,"type":0}}}, // [PurposeLab] + {"hash":"86c250cf0da31481","prefixes":{"":{"product":356,"type":0}}}, // [PurposeLab] + {"hash":"8f204c79d6b23736","prefixes":{"*":{"product":334,"type":0}}}, // [Predicta] + {"hash":"43d06db6d6527876","prefixes":{"":{"product":357,"type":0}}}, // [Proclivity Systems] + {"hash":"5f76990173953807","prefixes":{"":{"product":357,"type":0}}}, // [Proclivity Systems] + {"hash":"7d3947ee9533bf30","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"fb241396adc3ebde","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"b8c5f46fb8945332","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"ade9cbc2becb390f","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"874cfa4e9fe27233","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"2cd6bee614e910f1","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"854f37cd1f444e62","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"19a83c7a2b673a6d","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"ca312e078723d178","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"4aa2d41fa2878d8f","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"8931cc3c2d6bbbff","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"e67e88dcc0afe050","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"3f6c08baf48fa0ae","prefixes":{"":{"product":37,"type":0}}}, // [Public-Idées] + {"hash":"6303a58061eaabd1","prefixes":{"*":{"product":358,"type":0}}}, // [Viewbix] + {"hash":"4fdc8f2ff122ce2e","prefixes":{"":{"product":358,"type":0}}}, // [Viewbix] + {"hash":"ba78a984ad7a8c06","prefixes":{"":{"product":358,"type":0}}}, // [Viewbix] + {"hash":"00885ce869b93eab","prefixes":{"":{"product":358,"type":0}}}, // [Viewbix] + {"hash":"eb59f3a64b415670","prefixes":{"":{"product":359,"type":1}}}, // [Quantcast Inc.] + {"hash":"243c70f61da9731c","prefixes":{"":{"product":359,"type":1}}}, // [Quantcast Inc.] + {"hash":"ed6b204d6b8f351e","prefixes":{"":{"product":359,"type":1}}}, // [Quantcast Inc.] + {"hash":"e6888b5be4ecca23","prefixes":{"":{"product":359,"type":0}}}, // [Quantcast Inc.] + {"hash":"8034327c12c77172","prefixes":{"":{"product":359,"type":0}}}, // [Quantcast Inc.] + {"hash":"d48f950e0036e4ee","prefixes":{"*":{"product":360,"type":0}}}, // [QuinStreet] + {"hash":"6118e4e0e4001349","prefixes":{"*":{"product":361,"type":0}}}, // [Quisma GmbH] + {"hash":"1b2f3dadf0889c1c","prefixes":{"":{"product":362,"type":0}}}, // [Quismatch / Quisma Tracker] + {"hash":"491acc9692437dcc","prefixes":{"":{"product":362,"type":0}}}, // [Quismatch / Quisma Tracker] + {"hash":"95be38e789f1c074","prefixes":{"":{"product":362,"type":0}}}, // [Quismatch / Quisma Tracker] + {"hash":"7d13c9a93867cfd5","prefixes":{"":{"product":362,"type":0}}}, // [Quismatch / Quisma Tracker] + {"hash":"aee8b719a85b0392","prefixes":{"":{"product":362,"type":0}}}, // [Quismatch / Quisma Tracker] + {"hash":"03c0d3572439e910","prefixes":{"":{"product":362,"type":0}}}, // [Quismatch / Quisma Tracker] + {"hash":"42c10737e9d2eb44","prefixes":{"":{"product":362,"type":0}}}, // [Quismatch / Quisma Tracker] + {"hash":"1ece70926dbb1e9c","prefixes":{"*":{"product":362,"type":0}}}, // [Quismatch / Quisma Tracker] + {"hash":"15b1b56db686d6b8","prefixes":{"":{"product":362,"type":0}}}, // [Quismatch / Quisma Tracker] + {"hash":"6f2fb017c596785a","prefixes":{"*":{"product":363,"type":0}}}, // [Qwobl Inc.] + {"hash":"45bd1c4bac827eb4","prefixes":{"*":{"product":364,"type":0}}}, // [RadiumOne Inc.] + {"hash":"a4cc28a873663be4","prefixes":{"*":{"product":365,"type":0}}}, // [Core Audience, Inc] + {"hash":"b1b347108c9875ae","prefixes":{"*":{"product":366,"type":0}}}, // [The Reach Group] + {"hash":"9680c32132a31294","prefixes":{"":{"product":367,"type":0}}}, // [revenue cloud] + {"hash":"4654f1b3d29f0a2a","prefixes":{"":{"product":367,"type":0}}}, // [revenue cloud] + {"hash":"c8daf5a2befc762c","prefixes":{"":{"product":367,"type":0}}}, // [revenue cloud] + {"hash":"cd7c04dcaab54cf3","prefixes":{"":{"product":366,"type":0}}}, // [The Reach Group] + {"hash":"6a7ac3b20a8267da","prefixes":{"*":{"product":368,"type":0}}}, // [Register.it] + {"hash":"24064a7ef37c0464","prefixes":{"":{"product":369,"type":0}}}, // [ReleStar] + {"hash":"28a4e40561f9acae","prefixes":{"":{"product":369,"type":0}}}, // [ReleStar] + {"hash":"3de1987cea55e4a5","prefixes":{"":{"product":369,"type":0}}}, // [ReleStar] + {"hash":"827fd98c61df481c","prefixes":{"":{"product":369,"type":0}}}, // [ReleStar] + {"hash":"eec1a8a2a7fb129b","prefixes":{"":{"product":369,"type":0}}}, // [ReleStar] + {"hash":"6c1b7209cced7033","prefixes":{"*":{"product":370,"type":1}}}, // [Research Horizons LLC dba Phoenix Marketing] + {"hash":"c946c0fe5eecd55f","prefixes":{"":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"2feb43f5f97da585","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"4847977384b78f1d","prefixes":{"":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"308241d0fe4d6897","prefixes":{"":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"2cb30990aa0823eb","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"2c25ebde178886b1","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"d4eeb4a4736e8358","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"12498108d00bd104","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"c7437019688a5c87","prefixes":{"":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"ebc599442a1e60e0","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"ab9c2a8a5ed26375","prefixes":{"":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"c9473e1a1e9213bc","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"a15bca05fb29201f","prefixes":{"":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"8c2336c1a87e9c7e","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"67f7079b53ce160f","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"a07c7ea743bca71c","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"ce0849726cb792fb","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"6d2feeb6316bf983","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"056132328ebc8a3b","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"c0dd251eb151bbdd","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"02e6b230a73d95aa","prefixes":{"":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"62cef89124c9831e","prefixes":{"*":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"1bb2fad94e9dfd9e","prefixes":{"":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"0bca341ab2881187","prefixes":{"":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"fb725c5783121bc4","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"6d442fcb13dbd9da","prefixes":{"":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"6020c585ae546ba6","prefixes":{"":{"product":8,"type":1}}}, // [Research Now Limited] + {"hash":"bf994d767fc23e27","prefixes":{"":{"product":371,"type":0}}}, // [Retention Media Inc.] + {"hash":"5c801bba74bf0884","prefixes":{"":{"product":372,"type":0}}}, // [Suite 66] + {"hash":"f727f4c8af36c75c","prefixes":{"":{"product":373,"type":1}}}, // [Dynamic Logic / Safecount (AdIndex)] + {"hash":"d0ffa461035bdf6a","prefixes":{"":{"product":373,"type":1}}}, // [Dynamic Logic / Safecount (AdIndex)] + {"hash":"f1381513cbb99bf4","prefixes":{"":{"product":373,"type":1}}}, // [Dynamic Logic / Safecount (AdIndex)] + {"hash":"2b675a4d048f6d58","prefixes":{"":{"product":373,"type":1}}}, // [Dynamic Logic / Safecount (AdIndex)] + {"hash":"ff9153951d29d7eb","prefixes":{"":{"product":373,"type":1}}}, // [Dynamic Logic / Safecount (AdIndex)] + {"hash":"9a2d88a64367054f","prefixes":{"":{"product":373,"type":1}}}, // [Dynamic Logic / Safecount (AdIndex)] + {"hash":"22fc5e00cc71b2ca","prefixes":{"":{"product":373,"type":1}}}, // [Dynamic Logic / Safecount (AdIndex)] + {"hash":"d680287680a3b47b","prefixes":{"*":{"product":374,"type":0}}}, // [BridgeTrack] + {"hash":"6659ffe0ec0db1a1","prefixes":{"*":{"product":375,"type":0}}}, // [adnanny.com GmbH] + {"hash":"cdef303f827a483a","prefixes":{"":{"product":375,"type":0}}}, // [adnanny.com GmbH] + {"hash":"d37d706078f5ef0e","prefixes":{"":{"product":375,"type":0}}}, // [adnanny.com GmbH] + {"hash":"cefa23f603f78274","prefixes":{"":{"product":375,"type":0}}}, // [adnanny.com GmbH] + {"hash":"9beed54a2448f091","prefixes":{"*":{"product":376,"type":0}}}, // [AdRoll] + {"hash":"131ff02cd8b2b585","prefixes":{"*":{"product":377,"type":0}}}, // [AdExtent] + {"hash":"7b03a999ce62649a","prefixes":{"*":{"product":377,"type":0}}}, // [AdExtent] + {"hash":"d888444955526bb9","prefixes":{"*":{"product":378,"type":0}}}, // [ShareThis Inc.] + {"hash":"24bedaecde8de52e","prefixes":{"*":{"product":379,"type":1}}}, // [Shirtinator] + {"hash":"b2227832d5aab97c","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"29d1a1af90fe4764","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"55d58888ac21e28e","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"15a0a565c098bb6c","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"c740f7042a936f94","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"83b6131729d98b9a","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"df61075a3761234c","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"31d664b6a0c86fc5","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"b3f1fda5ca08f66c","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"a505bd8c5fdbe348","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"ff4b6ade85c0fa47","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"55fbb05b573abfc0","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"7509d096b740a94e","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"3e05ad70e7b857f6","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"f3122b05b916b4d8","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"7df77439ca0af167","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"7b6f3b92d848f180","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"c50b3a11c75c1de2","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"42bd2bd016c36072","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"d964e110e03add5e","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"b2f31dc5aea81475","prefixes":{"":{"product":380,"type":0}}}, // [Simplifi Holdings Inc.] + {"hash":"fd3e5505c689b1bc","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"e21937d0011ae5da","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"0f5e4a0353dbf996","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"0ece74eb8682685e","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"3d8ea3f0d5d389d5","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"b5602307e99e9538","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"c13decc96884eb9a","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"b815964fd4b63ffe","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"a49f2db509757639","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"a3ff80b45a2b0087","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"b1b2c1399cbf19be","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"ba44917903f4a6c0","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"ad5130e5aa2d0bcd","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"ceb371583c3948ee","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"5d5d4fe496a7b543","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"30e80084c1e7285e","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"d1d0fc6a034973b5","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"e2814abcd5399a68","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"9d4acd34336a73d4","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"dcbf7d7841f88317","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"c19fe37a92d8a1f4","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"dd502cbc700beb03","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"a76947b64ea18232","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"75875c5fcc471f0e","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"5323dbf9f56befc9","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"fd3df839224700c5","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"dc544506e0acf31c","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"fbadeeb25ac766a9","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"f344fa72c3acea98","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"e0d1929f5490ba3c","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"150d5c444034d16f","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"63c9992c37df81e6","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"9a2f65999a2602e7","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"b13d21bc9d60e3cf","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"36778688c2c8550d","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"7764641665318d7a","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"137839bac6b52f11","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"75b17e7427d84ec0","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"f576b8f6b5698927","prefixes":{"":{"product":381,"type":0}}}, // [Centro DSP] + {"hash":"a0bef488713fd8ba","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"c4f4b5d7a3bc8772","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"652de2e0257cc6f9","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"e1eb84d2322dd53f","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"0759e6e60e23806b","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"b97f9d3a0092f5df","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"6f7d322aac5f6093","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"d6d2092af97f6672","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"700b4497422246d3","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"24758e00974c4842","prefixes":{"*":{"product":382,"type":0}}}, // [Smart Adserver] + {"hash":"229fb1e217ec3254","prefixes":{"*":{"product":382,"type":0}}}, // [Smart Adserver] + {"hash":"24f84ec66db45f3d","prefixes":{"":{"product":383,"type":0}}}, // [smartclip Holding AG] + {"hash":"7bce0d8d711753ea","prefixes":{"":{"product":383,"type":0}}}, // [smartclip Holding AG] + {"hash":"f748f5ce8e9c4b7d","prefixes":{"*":{"product":384,"type":0}}}, // [Snap Technologies Inc.] + {"hash":"c17d7dedc318749c","prefixes":{"":{"product":385,"type":0}}}, // [So-net Media Networks] + {"hash":"d3a65eea99debc9b","prefixes":{"":{"product":385,"type":0}}}, // [So-net Media Networks] + {"hash":"f28c7fc4a06bcfa7","prefixes":{"*":{"product":386,"type":0}}}, // [SocialMedia.com] + {"hash":"17591c31cbbe7cf8","prefixes":{"":{"product":387,"type":0}}}, // [Content to Emotion (CTE)] + {"hash":"7c350f8bcf5a54b9","prefixes":{"":{"product":387,"type":0}}}, // [Content to Emotion (CTE)] + {"hash":"e003938122f9ac4f","prefixes":{"":{"product":387,"type":0}}}, // [Content to Emotion (CTE)] + {"hash":"6deac101ca463319","prefixes":{"static":{"product":387,"type":0}}}, // [Content to Emotion (CTE)] + {"hash":"304e631663a87e67","prefixes":{"*":{"product":388,"type":0}}}, // [Sociomantic.com] + {"hash":"e86474f9c6ad794d","prefixes":{"":{"product":389,"type":0}}}, // [AdSpeed] + {"hash":"de0816aa39c8b153","prefixes":{"*":{"product":390,"type":1}}}, // [Sophus3] + {"hash":"df8355613a445a85","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"a72f2b989760c8dc","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"fbdc1704c28873c8","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"d4674ccaf8fb7e31","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"f184677fb7e2abca","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"e7d695bf507e45d5","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"ea3f746342f05dbf","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"96ce83a8f0d84d99","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"62c6410f3e4000d8","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"b5172a6eee01acbe","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"36f9ba3a735ea443","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"f4d96ab5c7d0f720","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"7c8204a143e83abb","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"cb5b72c4fdc90b38","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"01c1382916f7a580","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"49505fd99e787062","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"a931030a5dbd7346","prefixes":{"":{"product":9,"type":0}}}, // [Spartoo] + {"hash":"3a09b22266ba0b12","prefixes":{"*":{"product":391,"type":0}}}, // [Specific Media Inc.] + {"hash":"2136a3b6f6600ad0","prefixes":{"*":{"product":391,"type":0}}}, // [Specific Media Inc.] + {"hash":"600e429523014251","prefixes":{"*":{"product":391,"type":0}}}, // [Specific Media Inc.] + {"hash":"e8b1c9274a662ad3","prefixes":{"":{"product":392,"type":0}}}, // [Metrigo GmbH] + {"hash":"d0ffd80eda189780","prefixes":{"":{"product":392,"type":0}}}, // [Metrigo GmbH] + {"hash":"e4ab3c31faef2b98","prefixes":{"":{"product":392,"type":0}}}, // [Metrigo GmbH] + {"hash":"97db8dd1bcbc33b8","prefixes":{"*":{"product":393,"type":0}}}, // [SpongeCell] + {"hash":"363a0f26e680d077","prefixes":{"":{"product":394,"type":0}}}, // [SpngeCell LLC] + {"hash":"fbef9c1b28b0cb05","prefixes":{"*":{"product":393,"type":0}}}, // [SpongeCell] + {"hash":"2218b5ce1e656e21","prefixes":{"":{"product":395,"type":0}}}, // [SpotXchange] + {"hash":"a520f16cf6177ebd","prefixes":{"":{"product":395,"type":0}}}, // [SpotXchange] + {"hash":"cda310d3654d07a5","prefixes":{"":{"product":395,"type":0}}}, // [SpotXchange] + {"hash":"2fc5567578510af6","prefixes":{"":{"product":396,"type":0}}}, // [Spotxchange] + {"hash":"abab2d20e98c266d","prefixes":{"":{"product":395,"type":0}}}, // [SpotXchange] + {"hash":"0d78cf3b068120c3","prefixes":{"":{"product":395,"type":0}}}, // [SpotXchange] + {"hash":"6da7c1b25ca845b3","prefixes":{"":{"product":395,"type":0}}}, // [SpotXchange] + {"hash":"c824df0fb0fdf482","prefixes":{"":{"product":397,"type":0}}}, // [Encore Attribution Platform] + {"hash":"9796e014709ccbec","prefixes":{"":{"product":397,"type":1}}}, // [Encore Attribution Platform] + {"hash":"fced1a8e32fb989c","prefixes":{"*":{"product":398,"type":0}}}, // [Steelhouse] + {"hash":"314523d1c217734f","prefixes":{"*":{"product":399,"type":0}}}, // [Strike New Media Limited] + {"hash":"276a5e6003750c07","prefixes":{"*":{"product":400,"type":0}}}, // [Struq Limited] + {"hash":"e5652beb11c7fceb","prefixes":{"*":{"product":401,"type":0}}}, // [SundaySky Inc.] + {"hash":"173a426f6562928a","prefixes":{"":{"product":402,"type":1}}}, // [Symphony Advanced Media] + {"hash":"81a2745fc67a8ecf","prefixes":{"":{"product":402,"type":1}}}, // [Symphony Advanced Media] + {"hash":"0aea8cde58b4f14e","prefixes":{"":{"product":402,"type":1}}}, // [Symphony Advanced Media] + {"hash":"b73e77077b022d36","prefixes":{"":{"product":402,"type":1}}}, // [Symphony Advanced Media] + {"hash":"fcf0d2e1f5fa003b","prefixes":{"":{"product":402,"type":1}}}, // [Symphony Advanced Media] + {"hash":"361c645b41a96807","prefixes":{"":{"product":402,"type":1}}}, // [Symphony Advanced Media] + {"hash":"81df9375fed9172e","prefixes":{"":{"product":402,"type":1}}}, // [Symphony Advanced Media] + {"hash":"c1493a0cd3b358a5","prefixes":{"":{"product":402,"type":1}}}, // [Symphony Advanced Media] + {"hash":"bdedb9447527960a","prefixes":{"":{"product":402,"type":1}}}, // [Symphony Advanced Media] + {"hash":"1cb83aa94e1a92ed","prefixes":{"":{"product":402,"type":1}}}, // [Symphony Advanced Media] + {"hash":"2172731c879fab72","prefixes":{"":{"product":402,"type":1}}}, // [Symphony Advanced Media] + {"hash":"7dd683bf50ce5c95","prefixes":{"":{"product":402,"type":1}}}, // [Symphony Advanced Media] + {"hash":"aa47b70219d2ee5e","prefixes":{"*":{"product":403,"type":1}}}, // [TagMan Ltd.] + {"hash":"097edb88beda9a20","prefixes":{"":{"product":404,"type":0}}}, // [Taobao] + {"hash":"bc65fc5f46cd88c9","prefixes":{"":{"product":404,"type":0}}}, // [Taobao] + {"hash":"a4d1bf696dde4d0b","prefixes":{"":{"product":404,"type":0}}}, // [Taobao] + {"hash":"c94f9318ace953f1","prefixes":{"":{"product":404,"type":0}}}, // [Taobao] + {"hash":"9e2b38828859944c","prefixes":{"":{"product":404,"type":0}}}, // [Taobao] + {"hash":"02319fc6286418de","prefixes":{"":{"product":404,"type":0}}}, // [Taobao] + {"hash":"dacc570e07ffd91a","prefixes":{"img":{"product":404,"type":0}}}, // [Taobao] + {"hash":"e8ccbc8f652e85a2","prefixes":{"*":{"product":404,"type":0}}}, // [Taobao] + {"hash":"da1ba7cc516336c0","prefixes":{"":{"product":404,"type":0}}}, // [Taobao] + {"hash":"41035e7733acf867","prefixes":{"":{"product":405,"type":1}}}, // [Target.com] + {"hash":"0509bdf297db5010","prefixes":{"*":{"product":406,"type":0}}}, // [Teadma] + {"hash":"69925c7888575612","prefixes":{"":{"product":407,"type":0}}}, // [BannerConnect BV] + {"hash":"4d44c3cec23aea09","prefixes":{"":{"product":407,"type":0}}}, // [BannerConnect BV] + {"hash":"447ea46d0797b32f","prefixes":{"*":{"product":408,"type":0}}}, // [Teracent Corporation] + {"hash":"26ca7e33d194e46e","prefixes":{"":{"product":408,"type":0}}}, // [Teracent Corporation] + {"hash":"b49b79e2e870c3e9","prefixes":{"":{"product":408,"type":0}}}, // [Teracent Corporation] + {"hash":"3a555db76a46f881","prefixes":{"*":{"product":38,"type":0}}}, // [The Trade Desk Inc.] + {"hash":"c4684dd3ef28687a","prefixes":{"*":{"product":409,"type":1}}}, // [The Travelers Indemnity Company] + {"hash":"1c38e7ac2dcf5d58","prefixes":{"":{"product":410,"type":0}}}, // [Videology] + {"hash":"4872cdec0944a698","prefixes":{"":{"product":410,"type":0}}}, // [Videology] + {"hash":"d4e30248b2920988","prefixes":{"*":{"product":411,"type":1}}}, // [TNS Custom Research Inc.] + {"hash":"48a3c2e049507f03","prefixes":{"*":{"product":412,"type":0}}}, // [TrackingSoft LLC] + {"hash":"4c5b26902a10b85b","prefixes":{"*":{"product":412,"type":0}}}, // [TrackingSoft LLC] + {"hash":"51a48ea23568f817","prefixes":{"*":{"product":413,"type":0}}}, // [Tradedoubler] + {"hash":"14251708a577d8c0","prefixes":{"*":{"product":414,"type":0}}}, // [Epic Marketplace] + {"hash":"20f50db7213cc9ee","prefixes":{"*":{"product":415,"type":0}}}, // [Tribal Fusion] + {"hash":"37b92f46ce8d0fa5","prefixes":{"":{"product":415,"type":0}}}, // [Tribal Fusion] + {"hash":"218cac8e116dcf7a","prefixes":{"":{"product":416,"type":0}}}, // [Triggit] {"hash":"135ee5dfe108d144","prefixes":{"":{"product":417}}}, // [True Ultimate Standards Everywhere Inc.] {"hash":"f6afa26369731900","prefixes":{"":{"product":417}}}, // [True Ultimate Standards Everywhere Inc.] {"hash":"600a58efa4b0a4fa","prefixes":{"":{"product":417}}}, // [True Ultimate Standards Everywhere Inc.] @@ -2898,912 +2896,912 @@ {"hash":"2966c06482ab340c","prefixes":{"":{"product":417}}}, // [True Ultimate Standards Everywhere Inc.] {"hash":"1320f91c88734ed7","prefixes":{"":{"product":417}}}, // [True Ultimate Standards Everywhere Inc.] {"hash":"49e73f2dfe503088","prefixes":{"":{"product":417}}}, // [True Ultimate Standards Everywhere Inc.] - {"hash":"345de3574a5cef61","prefixes":{"":{"product":418}}}, // [CarMax Business Services LLC] - {"hash":"8aba77355315b602","prefixes":{"":{"product":419}}}, // [Charter Communications] - {"hash":"f7e3882cd37d1a5b","prefixes":{"":{"product":419}}}, // [Charter Communications] - {"hash":"a62179d5dc8551f8","prefixes":{"":{"product":419}}}, // [Charter Communications] - {"hash":"ac3760dc99259bf9","prefixes":{"":{"product":420}}}, // [General Nutrition Centers Inc.] - {"hash":"e1c51fbf9b39950a","prefixes":{"":{"product":421}}}, // [Hamilton Beach] - {"hash":"68a80c829eb9c95e","prefixes":{"":{"product":422}}}, // [JacquieLawson.com] - {"hash":"a02b27c9af68c051","prefixes":{"":{"product":423}}}, // [TruEffect] - {"hash":"76b54dcac102ae32","prefixes":{"":{"product":423}}}, // [TruEffect] - {"hash":"f36743b8c729a3e5","prefixes":{"":{"product":424}}}, // [American Greetings] - {"hash":"0d479c4b1d2026b9","prefixes":{"":{"product":425}}}, // [BlueMountain] - {"hash":"c442eae221355ece","prefixes":{"":{"product":426}}}, // [Cardstore] - {"hash":"1277d75c5bace94e","prefixes":{"":{"product":427}}}, // [Chemistry.com] - {"hash":"2534adb635b0540f","prefixes":{"":{"product":428}}}, // [Donald J Pliner] - {"hash":"6e81f110e25ceba1","prefixes":{"*":{"product":429}}}, // [Gevalia] - {"hash":"58cb024039904795","prefixes":{"":{"product":430}}}, // [GSI Media] - {"hash":"36b7a450ddb92a81","prefixes":{"":{"product":431}}}, // [Match.com] - {"hash":"7f6a517c8eef7bf6","prefixes":{"":{"product":431}}}, // [Match.com] - {"hash":"b5aa9057f4ab3a79","prefixes":{"":{"product":431}}}, // [Match.com] - {"hash":"177eb410b9eee3c2","prefixes":{"":{"product":431}}}, // [Match.com] - {"hash":"5a75e9cff48a157c","prefixes":{"":{"product":431}}}, // [Match.com] - {"hash":"e561536f4b9b0f5e","prefixes":{"*":{"product":432}}}, // [Optimum Response] - {"hash":"3aaed06dec8e119b","prefixes":{"":{"product":433}}}, // [Oreck] - {"hash":"e7b19cb5471c10b3","prefixes":{"":{"product":434}}}, // [Tassimo] - {"hash":"5eca8c8aa7c01b0e","prefixes":{"*":{"product":435}}}, // [uSwitch] - {"hash":"974734b3e01eab8f","prefixes":{"*":{"product":436}}}, // [TubeMogul Inc.] - {"hash":"9f562a308fffc5c4","prefixes":{"*":{"product":437}}}, // [Tumri] - {"hash":"09845e50cbc70b8a","prefixes":{"*":{"product":182}}}, // [AdAction] - {"hash":"82ae5c9a96804ec8","prefixes":{"":{"product":102}}}, // [BigaBid Media Ltd.] - {"hash":"b91b0c7d1d3bb786","prefixes":{"":{"product":102}}}, // [BigaBid Media Ltd.] - {"hash":"2804070c2606fca7","prefixes":{"":{"product":102}}}, // [BigaBid Media Ltd.] - {"hash":"d601d362a989dcf9","prefixes":{"":{"product":438}}}, // [iMarker] - {"hash":"0a0084b896887917","prefixes":{"":{"product":438}}}, // [iMarker] - {"hash":"64596506e8398578","prefixes":{"":{"product":438}}}, // [iMarker] - {"hash":"4af3f67573bdbad8","prefixes":{"":{"product":438}}}, // [iMarker] - {"hash":"1348f7d07273dfcf","prefixes":{"":{"product":438}}}, // [iMarker] - {"hash":"4329a4ad527e4779","prefixes":{"":{"product":438}}}, // [iMarker] - {"hash":"5eca470b27725f28","prefixes":{"*":{"product":439}}}, // [Turn Inc.] - {"hash":"83807aae08d0747f","prefixes":{"*":{"product":439}}}, // [Turn Inc.] - {"hash":"a0542aaf969b6041","prefixes":{"*":{"product":440}}}, // [Twelvefold Media] - {"hash":"7837c4e8623f0409","prefixes":{"":{"product":440}}}, // [Twelvefold Media] - {"hash":"13c46ea92caeecf8","prefixes":{"":{"product":441}}}, // [Tynt] - {"hash":"5f7c83b68361da73","prefixes":{"*":{"product":442}}}, // [Unica an IBM Company] - {"hash":"bd242bcdc493f1d5","prefixes":{"*":{"product":443}}}, // [Unicast] - {"hash":"58ad481190b46e2e","prefixes":{"":{"product":444}}}, // [UniQlick] - {"hash":"7f5d2102ab11e53c","prefixes":{"":{"product":444}}}, // [UniQlick] - {"hash":"c9dd94a27435350b","prefixes":{"":{"product":444}}}, // [UniQlick] - {"hash":"4ba8d85cfc1bf5de","prefixes":{"*":{"product":445}}}, // [United Virtualities] - {"hash":"0e4c474511c6dfff","prefixes":{"":{"product":446}}}, // [VideoHub] - {"hash":"875bbc4dbaee8734","prefixes":{"":{"product":446}}}, // [VideoHub] - {"hash":"58b08ddd9e3cccf9","prefixes":{"":{"product":446}}}, // [VideoHub] - {"hash":"356603d457828911","prefixes":{"":{"product":446}}}, // [VideoHub] - {"hash":"77c85cb3240da7c5","prefixes":{"":{"product":446}}}, // [VideoHub] - {"hash":"010912cf400592bc","prefixes":{"":{"product":446}}}, // [VideoHub] - {"hash":"28e6d587198883be","prefixes":{"":{"product":446}}}, // [VideoHub] - {"hash":"e64d00be64f97a79","prefixes":{"":{"product":446}}}, // [VideoHub] - {"hash":"fa0271d4d3cf41f2","prefixes":{"":{"product":446}}}, // [VideoHub] - {"hash":"a227d04cd3bf04f7","prefixes":{"":{"product":446}}}, // [VideoHub] - {"hash":"b69205c5372d2357","prefixes":{"":{"product":446}}}, // [VideoHub] - {"hash":"da30259edef87286","prefixes":{"*":{"product":447}}}, // [Visible Measures Corp.] - {"hash":"46ff1406588e7ceb","prefixes":{"":{"product":192}}}, // [Nielsen OBE (Vizu)] - {"hash":"32ca2bff73328a83","prefixes":{"":{"product":192}}}, // [Nielsen OBE (Vizu)] - {"hash":"3fc1dc351d4952c8","prefixes":{"":{"product":192}}}, // [Nielsen OBE (Vizu)] - {"hash":"80d2379485452f29","prefixes":{"":{"product":192}}}, // [Nielsen OBE (Vizu)] - {"hash":"35183abb3e2c864c","prefixes":{"":{"product":192}}}, // [Nielsen OBE (Vizu)] - {"hash":"3b235045cc005d15","prefixes":{"":{"product":192}}}, // [Nielsen OBE (Vizu)] - {"hash":"34e6561d9300f451","prefixes":{"":{"product":192}}}, // [Nielsen OBE (Vizu)] - {"hash":"08980f63c2ca7971","prefixes":{"":{"product":192}}}, // [Nielsen OBE (Vizu)] - {"hash":"327755ab5ee91d4e","prefixes":{"":{"product":192}}}, // [Nielsen OBE (Vizu)] - {"hash":"c3d3383046b5690f","prefixes":{"":{"product":192}}}, // [Nielsen OBE (Vizu)] - {"hash":"d196d3b7e439011e","prefixes":{"":{"product":192}}}, // [Nielsen OBE (Vizu)] - {"hash":"09582bb8c4f0bdcd","prefixes":{"*":{"product":448}}}, // [Vizury Interactive Solutions Pvt. Ltd.] - {"hash":"ccbe4ed34be8ea01","prefixes":{"":{"product":449}}}, // [Markit On Demand (Adhesion)] - {"hash":"5c0c23d6d5b2aa7d","prefixes":{"":{"product":449}}}, // [Markit On Demand (Adhesion)] - {"hash":"6fe5393d68aec474","prefixes":{"":{"product":449}}}, // [Markit On Demand (Adhesion)] - {"hash":"24de99047e3e2592","prefixes":{"":{"product":449}}}, // [Markit On Demand (Adhesion)] - {"hash":"a1d810c22ef4c8c1","prefixes":{"":{"product":449}}}, // [Markit On Demand (Adhesion)] - {"hash":"a961c235191ccc5c","prefixes":{"":{"product":449}}}, // [Markit On Demand (Adhesion)] - {"hash":"30327e228a69909d","prefixes":{"":{"product":450}}}, // [WebMetro Inc] - {"hash":"1440114026d0b8a7","prefixes":{"*":{"product":451}}}, // [Weborama Campaign Manager (former name AdPerf)] - {"hash":"178b8b7280deb93c","prefixes":{"":{"product":451}}}, // [Weborama Campaign Manager (former name AdPerf)] - {"hash":"8398687ebe990cf1","prefixes":{"":{"product":451}}}, // [Weborama Campaign Manager (former name AdPerf)] - {"hash":"5cad65c27ef8d2b4","prefixes":{"":{"product":451}}}, // [Weborama Campaign Manager (former name AdPerf)] - {"hash":"f28574a110053221","prefixes":{"":{"product":451}}}, // [Weborama Campaign Manager (former name AdPerf)] - {"hash":"64eae6bdfc8cc1be","prefixes":{"":{"product":451}}}, // [Weborama Campaign Manager (former name AdPerf)] - {"hash":"36b0c30f5f967ffd","prefixes":{"":{"product":451}}}, // [Weborama Campaign Manager (former name AdPerf)] - {"hash":"10c282544a39807b","prefixes":{"":{"product":451}}}, // [Weborama Campaign Manager (former name AdPerf)] - {"hash":"ce2ed22191804ffa","prefixes":{"":{"product":451}}}, // [Weborama Campaign Manager (former name AdPerf)] - {"hash":"bd56114f26a64020","prefixes":{"":{"product":451}}}, // [Weborama Campaign Manager (former name AdPerf)] - {"hash":"54e283b8884709c3","prefixes":{"":{"product":451}}}, // [Weborama Campaign Manager (former name AdPerf)] - {"hash":"313822ab7be9585a","prefixes":{"":{"product":451}}}, // [Weborama Campaign Manager (former name AdPerf)] - {"hash":"d54943c8060334b5","prefixes":{"":{"product":452}}}, // [Weborama Campaign Manager] - {"hash":"7928274bf854b28b","prefixes":{"*":{"product":451}}}, // [Weborama Campaign Manager (former name AdPerf)] - {"hash":"80415fbb74db7704","prefixes":{"":{"product":453}}}, // [Shopping Network] - {"hash":"0840f634995e25fb","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"5fd40859cc837b00","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"c58731043a973263","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"ee286fbf0440d595","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"660d555331a8be68","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"c412040c18d978ce","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"667b34ab71cb2381","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"b888d9e69003de82","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"38dafaa727179ef7","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"78da2db9d3a51f98","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"94a731a76dd26bfc","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"c4ca9b6aebf488dc","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"0a42e116235fec6e","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"ac4d0bcf3017cc3d","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"6653125411676c31","prefixes":{"":{"product":454}}}, // [Shanghai WiseMedia Technology Co. Ltd.] - {"hash":"062b10abe02277c1","prefixes":{"":{"product":455}}}, // [XA.net] - {"hash":"b0e3a57e8f415aec","prefixes":{"":{"product":455}}}, // [XA.net] - {"hash":"6e1bb44d175a20af","prefixes":{"":{"product":455}}}, // [XA.net] - {"hash":"34984bab025a1372","prefixes":{"":{"product":455}}}, // [XA.net] - {"hash":"d9eb2f654e80ebc6","prefixes":{"*":{"product":456}}}, // [Xaxis LLC] - {"hash":"b86d63843110e02a","prefixes":{"*":{"product":457}}}, // [Net Edge] - {"hash":"8b526a29c7f2b3dc","prefixes":{"*":{"product":458}}}, // [Xplusone Solutions Inc.] - {"hash":"fe0ea2a1c212cfde","prefixes":{"":{"product":459}}}, // [Yahoo! Ad Exchange] - {"hash":"dc06a1403eb499df","prefixes":{"":{"product":459}}}, // [Yahoo! Ad Exchange] - {"hash":"5a36dbbd382aa12c","prefixes":{"":{"product":459}}}, // [Yahoo! Ad Exchange] - {"hash":"c8fd15f0a5fc19aa","prefixes":{"":{"product":459}}}, // [Yahoo! Ad Exchange] - {"hash":"ce63a8ab511ec5bb","prefixes":{"":{"product":459}}}, // [Yahoo! Ad Exchange] - {"hash":"a6d2abe55f73bc22","prefixes":{"":{"product":460}}}, // [Yahoo Ad Manager Plus] - {"hash":"707a11e6dcfa57db","prefixes":{"":{"product":460}}}, // [Yahoo Ad Manager Plus] - {"hash":"f75439bd7693fa84","prefixes":{"":{"product":460}}}, // [Yahoo Ad Manager Plus] - {"hash":"2f7feb27a1b93524","prefixes":{"":{"product":460}}}, // [Yahoo Ad Manager Plus] - {"hash":"f801c9750710d30a","prefixes":{"":{"product":460}}}, // [Yahoo Ad Manager Plus] - {"hash":"9b96f7700d727da9","prefixes":{"":{"product":461}}}, // [APT from Yahoo!] - {"hash":"e4de2f3b2c06e193","prefixes":{"":{"product":461}}}, // [APT from Yahoo!] - {"hash":"21aa62a45ef75fb2","prefixes":{"*":{"product":462}}}, // [Yieldr] - {"hash":"85bf1ed3ee6ee615","prefixes":{"":{"product":462}}}, // [Yieldr] - {"hash":"2cf45ce27d0b73c2","prefixes":{"":{"product":462}}}, // [Yieldr] - {"hash":"e8595ade1fd26e2f","prefixes":{"":{"product":462}}}, // [Yieldr] - {"hash":"5660279fe13cfe3b","prefixes":{"":{"product":462}}}, // [Yieldr] - {"hash":"ad26a995ee586915","prefixes":{"":{"product":462}}}, // [Yieldr] - {"hash":"23412da5a5a538cc","prefixes":{"":{"product":462}}}, // [Yieldr] - {"hash":"6b333dd78d119434","prefixes":{"":{"product":462}}}, // [Yieldr] - {"hash":"f3621ca5777d61d5","prefixes":{"":{"product":462}}}, // [Yieldr] - {"hash":"cafa71178e1de4db","prefixes":{"":{"product":352}}}, // [YoYi Interactive] - {"hash":"2ca490afaa90c2b3","prefixes":{"":{"product":352}}}, // [YoYi Interactive] - {"hash":"8f0dd7539cf77aa5","prefixes":{"":{"product":352}}}, // [YoYi Interactive] - {"hash":"005700973b435023","prefixes":{"":{"product":463}}}, // [YuMe Inc.] - {"hash":"bd83427751c351a9","prefixes":{"":{"product":463}}}, // [YuMe Inc.] - {"hash":"e504ebfcb6b2722e","prefixes":{"":{"product":463}}}, // [YuMe Inc.] - {"hash":"8080438b5792b260","prefixes":{"":{"product":464}}}, // [Ebuzzing] - {"hash":"274889e98fbfc776","prefixes":{"":{"product":464}}}, // [Ebuzzing] - {"hash":"b62ee5e77fde7ec7","prefixes":{"":{"product":464}}}, // [Ebuzzing] - {"hash":"cc6a7a565374c257","prefixes":{"":{"product":464}}}, // [Ebuzzing] - {"hash":"e02936a6a6a2cb94","prefixes":{"":{"product":465}}}, // [Ziff Davis] - {"hash":"223b94a95f6849cf","prefixes":{"":{"product":465}}}, // [Ziff Davis] - {"hash":"a8742ddae80b031b","prefixes":{"":{"product":466}}}, // [DataPoint Media Inc.] - {"hash":"fd4a16bf59718107","prefixes":{"":{"product":467}}}, // [Simplytics Limited] - {"hash":"a3d523521bc4ba12","prefixes":{"":{"product":467}}}, // [Simplytics Limited] - {"hash":"9da8a1153308d7f2","prefixes":{"":{"product":468}}}, // [Makazi] - {"hash":"d9cc216c8d482336","prefixes":{"":{"product":468}}}, // [Makazi] - {"hash":"166c65d7776be9f8","prefixes":{"":{"product":468}}}, // [Makazi] - {"hash":"55f15e5b7746999f","prefixes":{"":{"product":468}}}, // [Makazi] - {"hash":"213194bd445e551d","prefixes":{"":{"product":468}}}, // [Makazi] - {"hash":"31406bff4dc35eea","prefixes":{"":{"product":468}}}, // [Makazi] - {"hash":"ea9607b28f4238c2","prefixes":{"":{"product":468}}}, // [Makazi] - {"hash":"707d5310f27d0dd2","prefixes":{"":{"product":469}}}, // [Rich Relevance] - {"hash":"59fa19b8a48477fe","prefixes":{"":{"product":470}}}, // [MainADV] - {"hash":"efb9b464f6ebaa1d","prefixes":{"":{"product":470}}}, // [MainADV] - {"hash":"8848350bd85fffe4","prefixes":{"":{"product":470}}}, // [MainADV] - {"hash":"519275c83a5a1c92","prefixes":{"":{"product":470}}}, // [MainADV] - {"hash":"fc92bec8fbcb03ef","prefixes":{"":{"product":470}}}, // [MainADV] - {"hash":"91fa39bc27e156b4","prefixes":{"":{"product":470}}}, // [MainADV] - {"hash":"408d55e8995335ad","prefixes":{"":{"product":470}}}, // [MainADV] - {"hash":"d0efa7323c77b1a5","prefixes":{"":{"product":470}}}, // [MainADV] - {"hash":"baa5cf88a0176bc6","prefixes":{"":{"product":471}}}, // [MediaV Advertising] - {"hash":"3ea0854e74c32c87","prefixes":{"":{"product":471}}}, // [MediaV Advertising] - {"hash":"88a70c2ebfe38ffe","prefixes":{"":{"product":471}}}, // [MediaV Advertising] - {"hash":"dc0b1dfe6de6a967","prefixes":{"":{"product":471}}}, // [MediaV Advertising] - {"hash":"cb234228af27fa32","prefixes":{"":{"product":471}}}, // [MediaV Advertising] - {"hash":"c7abee58863b27a4","prefixes":{"":{"product":472}}}, // [MicroAd Inc.] - {"hash":"7e34b0d37ded49ed","prefixes":{"":{"product":472}}}, // [MicroAd Inc.] - {"hash":"d7255d3135b0294d","prefixes":{"":{"product":472}}}, // [MicroAd Inc.] - {"hash":"e21264db24be060c","prefixes":{"":{"product":472}}}, // [MicroAd Inc.] - {"hash":"466676eb4c2066ac","prefixes":{"":{"product":472}}}, // [MicroAd Inc.] - {"hash":"2505a55ead3f2266","prefixes":{"":{"product":472}}}, // [MicroAd Inc.] - {"hash":"e97b9e2d31ac962d","prefixes":{"":{"product":472}}}, // [MicroAd Inc.] - {"hash":"906215055f6880fa","prefixes":{"":{"product":472}}}, // [MicroAd Inc.] - {"hash":"df04046f11aea628","prefixes":{"*":{"product":473}}}, // [Platform ID Inc.] - {"hash":"9fe8e93d55562003","prefixes":{"":{"product":474}}}, // [Xrost] - {"hash":"6b29d401833f79d8","prefixes":{"":{"product":473}}}, // [Platform ID Inc.] - {"hash":"00928c6f847a4785","prefixes":{"":{"product":475}}}, // [Sociocast Networks LLC D/B/A Velos] - {"hash":"c3964f299adbe862","prefixes":{"":{"product":476}}}, // [Trend Research] - {"hash":"76b5ddb10f769c6b","prefixes":{"*":{"product":248}}}, // [AdOcean Ltd] - {"hash":"f52edd3926705507","prefixes":{"":{"product":477}}}, // [Black Swan Verification] - {"hash":"d63e38f4eba51f77","prefixes":{"":{"product":478}}}, // [Momentum K.K] - {"hash":"6c0f8db03b28099b","prefixes":{"":{"product":477}}}, // [Black Swan Verification] - {"hash":"248772911542d550","prefixes":{"*":{"product":479}}}, // [Betgenius Limited] - {"hash":"38a72a4924027d8f","prefixes":{"*":{"product":480}}}, // [AT Internet] - {"hash":"255b63d169bd9d10","prefixes":{"*":{"product":480}}}, // [AT Internet] - {"hash":"3a7fbbad166769ad","prefixes":{"":{"product":481}}}, // [DataLab] - {"hash":"fe64230a84967d3c","prefixes":{"":{"product":482}}}, // [Innovid Inc.] - {"hash":"a91296d609efe0b4","prefixes":{"":{"product":482}}}, // [Innovid Inc.] - {"hash":"947fa5564eccc0b2","prefixes":{"":{"product":482}}}, // [Innovid Inc.] - {"hash":"89a64fe46687237f","prefixes":{"":{"product":482}}}, // [Innovid Inc.] - {"hash":"ce1cd4220063df2d","prefixes":{"":{"product":482}}}, // [Innovid Inc.] - {"hash":"1c489f83a79301c6","prefixes":{"":{"product":482}}}, // [Innovid Inc.] - {"hash":"9dc25ef9b3ed3e5d","prefixes":{"":{"product":482}}}, // [Innovid Inc.] - {"hash":"9898ab0c57d683ae","prefixes":{"":{"product":482}}}, // [Innovid Inc.] - {"hash":"0229fe19979f88b0","prefixes":{"":{"product":482}}}, // [Innovid Inc.] - {"hash":"6dedd3fca4d243ac","prefixes":{"":{"product":482}}}, // [Innovid Inc.] - {"hash":"cbc23a15e9f02987","prefixes":{"":{"product":482}}}, // [Innovid Inc.] - {"hash":"95119cbc05f9e42a","prefixes":{"":{"product":482}}}, // [Innovid Inc.] - {"hash":"784647d3eb0236dc","prefixes":{"*":{"product":483}}}, // [Adacado] - {"hash":"4be5d3939998bc39","prefixes":{"":{"product":483}}}, // [Adacado] - {"hash":"cec4d2059bbb1365","prefixes":{"*":{"product":484}}}, // [NetDNA, LLC] - {"hash":"87a9bf2f660b2673","prefixes":{"":{"product":478}}}, // [Momentum K.K] - {"hash":"33f6a4c9eb1313f6","prefixes":{"":{"product":478}}}, // [Momentum K.K] - {"hash":"38afcf5464d4a46e","prefixes":{"":{"product":478}}}, // [Momentum K.K] - {"hash":"4a13b10532de4033","prefixes":{"*":{"product":485}}}, // [Pipewave Inc.] - {"hash":"a703750c918980b9","prefixes":{"":{"product":486}}}, // [US Media Consulting] - {"hash":"77b351109047edb2","prefixes":{"":{"product":487}}}, // [SKYTOUCH TECHNOLOGY CO., LIMITED] - {"hash":"f9f554c96902397e","prefixes":{"":{"product":487}}}, // [SKYTOUCH TECHNOLOGY CO., LIMITED] - {"hash":"e8f2c7f5eb75983e","prefixes":{"":{"product":487}}}, // [SKYTOUCH TECHNOLOGY CO., LIMITED] - {"hash":"f8680fe819857e65","prefixes":{"image":{"product":487}}}, // [SKYTOUCH TECHNOLOGY CO., LIMITED] - {"hash":"fe12b35f78c433a6","prefixes":{"":{"product":487}}}, // [SKYTOUCH TECHNOLOGY CO., LIMITED] - {"hash":"531f5c369a189473","prefixes":{"":{"product":488}}}, // [Hanesbrands Direct LLC] - {"hash":"4bfbc25da5ec8116","prefixes":{"":{"product":489}}}, // [A1platform] - {"hash":"56cea5c2b408989a","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"2c24b521f38d28dd","prefixes":{"":{"product":10}}}, // [eBay] - {"hash":"d6449351ee8e33eb","prefixes":{"*":{"product":490}}}, // [Agency.com] - {"hash":"5e040f7b958d9ee5","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"379ed8ab1690a74c","prefixes":{"":{"product":10}}}, // [eBay] - {"hash":"6ed4dac9c333ef4b","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"b4a9e54654a6de08","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"687aa30619ec8e7f","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"5ac823af612c4492","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"ce4e70466c43ade3","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"c865cf822ab64a71","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"083c339aac7e418c","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"8d689bf60029c98f","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"19d0e1eba389dfe1","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"b789395149868329","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"25e9f5191f3d2397","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"82a743999425aaad","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"97a729e5b41fd4ed","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"0db7dee9d3c756cc","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"10981271cb66af25","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"8c86bc9ba67482c6","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"d36efad270e3e7c6","prefixes":{"*":{"product":10}}}, // [eBay] - {"hash":"b709ca3f38e77645","prefixes":{"":{"product":491}}}, // [Adap.tv Inc. (AdWords/YouTube)] - {"hash":"3cba207e4aa9d6c6","prefixes":{"":{"product":491}}}, // [Adap.tv Inc. (AdWords/YouTube)] - {"hash":"fd8da92d6de2518b","prefixes":{"":{"product":491}}}, // [Adap.tv Inc. (AdWords/YouTube)] - {"hash":"d9e4d4444ebd418f","prefixes":{"":{"product":491}}}, // [Adap.tv Inc. (AdWords/YouTube)] - {"hash":"4c1c4999d1501943","prefixes":{"":{"product":491}}}, // [Adap.tv Inc. (AdWords/YouTube)] - {"hash":"a635762b8125bba5","prefixes":{"":{"product":491}}}, // [Adap.tv Inc. (AdWords/YouTube)] - {"hash":"99818fe6fd4c4a9c","prefixes":{"":{"product":491}}}, // [Adap.tv Inc. (AdWords/YouTube)] - {"hash":"cae59de4e054a5a8","prefixes":{"":{"product":491}}}, // [Adap.tv Inc. (AdWords/YouTube)] - {"hash":"d1ec771fe9489a9f","prefixes":{"":{"product":491}}}, // [Adap.tv Inc. (AdWords/YouTube)] - {"hash":"d9effad74da2b097","prefixes":{"*":{"product":491}}}, // [Adap.tv Inc. (AdWords/YouTube)] - {"hash":"46b1fc5fe9da3681","prefixes":{"*":{"product":492}}}, // [Fjord Technologies S.A.S.] - {"hash":"e0b6d05a8e75e14a","prefixes":{"*":{"product":492}}}, // [Fjord Technologies S.A.S.] - {"hash":"11a89bdf6bc5cf28","prefixes":{"":{"product":493}}}, // [Refined Ads] - {"hash":"8e6414939f586d4c","prefixes":{"":{"product":493}}}, // [Refined Ads] - {"hash":"6462a1b97a382278","prefixes":{"":{"product":493}}}, // [Refined Ads] - {"hash":"9f99479854cea2e7","prefixes":{"":{"product":493}}}, // [Refined Ads] - {"hash":"72b40aacd2b4e226","prefixes":{"":{"product":493}}}, // [Refined Ads] + {"hash":"345de3574a5cef61","prefixes":{"":{"product":418,"type":0}}}, // [CarMax Business Services LLC] + {"hash":"8aba77355315b602","prefixes":{"":{"product":419,"type":0}}}, // [Charter Communications] + {"hash":"f7e3882cd37d1a5b","prefixes":{"":{"product":419,"type":0}}}, // [Charter Communications] + {"hash":"a62179d5dc8551f8","prefixes":{"":{"product":419,"type":0}}}, // [Charter Communications] + {"hash":"ac3760dc99259bf9","prefixes":{"":{"product":420,"type":0}}}, // [General Nutrition Centers Inc.] + {"hash":"e1c51fbf9b39950a","prefixes":{"":{"product":421,"type":0}}}, // [Hamilton Beach] + {"hash":"68a80c829eb9c95e","prefixes":{"":{"product":422,"type":0}}}, // [JacquieLawson.com] + {"hash":"a02b27c9af68c051","prefixes":{"":{"product":423,"type":0}}}, // [TruEffect] + {"hash":"76b54dcac102ae32","prefixes":{"":{"product":423,"type":0}}}, // [TruEffect] + {"hash":"f36743b8c729a3e5","prefixes":{"":{"product":424,"type":0}}}, // [American Greetings] + {"hash":"0d479c4b1d2026b9","prefixes":{"":{"product":425,"type":0}}}, // [BlueMountain] + {"hash":"c442eae221355ece","prefixes":{"":{"product":426,"type":0}}}, // [Cardstore] + {"hash":"1277d75c5bace94e","prefixes":{"":{"product":427,"type":0}}}, // [Chemistry.com] + {"hash":"2534adb635b0540f","prefixes":{"":{"product":428,"type":0}}}, // [Donald J Pliner] + {"hash":"6e81f110e25ceba1","prefixes":{"*":{"product":429,"type":0}}}, // [Gevalia] + {"hash":"58cb024039904795","prefixes":{"":{"product":430,"type":0}}}, // [GSI Media] + {"hash":"36b7a450ddb92a81","prefixes":{"":{"product":431,"type":0}}}, // [Match.com] + {"hash":"7f6a517c8eef7bf6","prefixes":{"":{"product":431,"type":0}}}, // [Match.com] + {"hash":"b5aa9057f4ab3a79","prefixes":{"":{"product":431,"type":0}}}, // [Match.com] + {"hash":"177eb410b9eee3c2","prefixes":{"":{"product":431,"type":0}}}, // [Match.com] + {"hash":"5a75e9cff48a157c","prefixes":{"":{"product":431,"type":0}}}, // [Match.com] + {"hash":"e561536f4b9b0f5e","prefixes":{"*":{"product":432,"type":0}}}, // [Optimum Response] + {"hash":"3aaed06dec8e119b","prefixes":{"":{"product":433,"type":0}}}, // [Oreck] + {"hash":"e7b19cb5471c10b3","prefixes":{"":{"product":434,"type":0}}}, // [Tassimo] + {"hash":"5eca8c8aa7c01b0e","prefixes":{"*":{"product":435,"type":0}}}, // [uSwitch] + {"hash":"974734b3e01eab8f","prefixes":{"*":{"product":436,"type":0}}}, // [TubeMogul Inc.] + {"hash":"9f562a308fffc5c4","prefixes":{"*":{"product":437,"type":0}}}, // [Tumri] + {"hash":"09845e50cbc70b8a","prefixes":{"*":{"product":182,"type":0}}}, // [AdAction] + {"hash":"82ae5c9a96804ec8","prefixes":{"":{"product":102,"type":0}}}, // [BigaBid Media Ltd.] + {"hash":"b91b0c7d1d3bb786","prefixes":{"":{"product":102,"type":0}}}, // [BigaBid Media Ltd.] + {"hash":"2804070c2606fca7","prefixes":{"":{"product":102,"type":0}}}, // [BigaBid Media Ltd.] + {"hash":"d601d362a989dcf9","prefixes":{"":{"product":438,"type":0}}}, // [iMarker] + {"hash":"0a0084b896887917","prefixes":{"":{"product":438,"type":0}}}, // [iMarker] + {"hash":"64596506e8398578","prefixes":{"":{"product":438,"type":0}}}, // [iMarker] + {"hash":"4af3f67573bdbad8","prefixes":{"":{"product":438,"type":0}}}, // [iMarker] + {"hash":"1348f7d07273dfcf","prefixes":{"":{"product":438,"type":0}}}, // [iMarker] + {"hash":"4329a4ad527e4779","prefixes":{"":{"product":438,"type":0}}}, // [iMarker] + {"hash":"5eca470b27725f28","prefixes":{"*":{"product":439,"type":0}}}, // [Turn Inc.] + {"hash":"83807aae08d0747f","prefixes":{"*":{"product":439,"type":0}}}, // [Turn Inc.] + {"hash":"a0542aaf969b6041","prefixes":{"*":{"product":440,"type":0}}}, // [Twelvefold Media] + {"hash":"7837c4e8623f0409","prefixes":{"":{"product":440,"type":0}}}, // [Twelvefold Media] + {"hash":"13c46ea92caeecf8","prefixes":{"":{"product":441,"type":0}}}, // [Tynt] + {"hash":"5f7c83b68361da73","prefixes":{"*":{"product":442,"type":1}}}, // [Unica an IBM Company] + {"hash":"bd242bcdc493f1d5","prefixes":{"*":{"product":443,"type":0}}}, // [Unicast] + {"hash":"58ad481190b46e2e","prefixes":{"":{"product":444,"type":0}}}, // [UniQlick] + {"hash":"7f5d2102ab11e53c","prefixes":{"":{"product":444,"type":0}}}, // [UniQlick] + {"hash":"c9dd94a27435350b","prefixes":{"":{"product":444,"type":0}}}, // [UniQlick] + {"hash":"4ba8d85cfc1bf5de","prefixes":{"*":{"product":445,"type":0}}}, // [United Virtualities] + {"hash":"0e4c474511c6dfff","prefixes":{"":{"product":446,"type":1}}}, // [VideoHub] + {"hash":"875bbc4dbaee8734","prefixes":{"":{"product":446,"type":1}}}, // [VideoHub] + {"hash":"58b08ddd9e3cccf9","prefixes":{"":{"product":446,"type":1}}}, // [VideoHub] + {"hash":"356603d457828911","prefixes":{"":{"product":446,"type":1}}}, // [VideoHub] + {"hash":"77c85cb3240da7c5","prefixes":{"":{"product":446,"type":1}}}, // [VideoHub] + {"hash":"010912cf400592bc","prefixes":{"":{"product":446,"type":1}}}, // [VideoHub] + {"hash":"28e6d587198883be","prefixes":{"":{"product":446,"type":1}}}, // [VideoHub] + {"hash":"e64d00be64f97a79","prefixes":{"":{"product":446,"type":1}}}, // [VideoHub] + {"hash":"fa0271d4d3cf41f2","prefixes":{"":{"product":446,"type":1}}}, // [VideoHub] + {"hash":"a227d04cd3bf04f7","prefixes":{"":{"product":446,"type":1}}}, // [VideoHub] + {"hash":"b69205c5372d2357","prefixes":{"":{"product":446,"type":1}}}, // [VideoHub] + {"hash":"da30259edef87286","prefixes":{"*":{"product":447,"type":1}}}, // [Visible Measures Corp.] + {"hash":"46ff1406588e7ceb","prefixes":{"":{"product":192,"type":1}}}, // [Nielsen OBE (Vizu)] + {"hash":"32ca2bff73328a83","prefixes":{"":{"product":192,"type":1}}}, // [Nielsen OBE (Vizu)] + {"hash":"3fc1dc351d4952c8","prefixes":{"":{"product":192,"type":1}}}, // [Nielsen OBE (Vizu)] + {"hash":"80d2379485452f29","prefixes":{"":{"product":192,"type":1}}}, // [Nielsen OBE (Vizu)] + {"hash":"35183abb3e2c864c","prefixes":{"":{"product":192,"type":1}}}, // [Nielsen OBE (Vizu)] + {"hash":"3b235045cc005d15","prefixes":{"":{"product":192,"type":1}}}, // [Nielsen OBE (Vizu)] + {"hash":"34e6561d9300f451","prefixes":{"":{"product":192,"type":1}}}, // [Nielsen OBE (Vizu)] + {"hash":"08980f63c2ca7971","prefixes":{"":{"product":192,"type":1}}}, // [Nielsen OBE (Vizu)] + {"hash":"327755ab5ee91d4e","prefixes":{"":{"product":192,"type":1}}}, // [Nielsen OBE (Vizu)] + {"hash":"c3d3383046b5690f","prefixes":{"":{"product":192,"type":1}}}, // [Nielsen OBE (Vizu)] + {"hash":"d196d3b7e439011e","prefixes":{"":{"product":192,"type":1}}}, // [Nielsen OBE (Vizu)] + {"hash":"09582bb8c4f0bdcd","prefixes":{"*":{"product":448,"type":0}}}, // [Vizury Interactive Solutions Pvt. Ltd.] + {"hash":"ccbe4ed34be8ea01","prefixes":{"":{"product":449,"type":0}}}, // [Markit On Demand (Adhesion)] + {"hash":"5c0c23d6d5b2aa7d","prefixes":{"":{"product":449,"type":0}}}, // [Markit On Demand (Adhesion)] + {"hash":"6fe5393d68aec474","prefixes":{"":{"product":449,"type":0}}}, // [Markit On Demand (Adhesion)] + {"hash":"24de99047e3e2592","prefixes":{"":{"product":449,"type":0}}}, // [Markit On Demand (Adhesion)] + {"hash":"a1d810c22ef4c8c1","prefixes":{"":{"product":449,"type":0}}}, // [Markit On Demand (Adhesion)] + {"hash":"a961c235191ccc5c","prefixes":{"":{"product":449,"type":0}}}, // [Markit On Demand (Adhesion)] + {"hash":"30327e228a69909d","prefixes":{"":{"product":450,"type":1}}}, // [WebMetro Inc] + {"hash":"1440114026d0b8a7","prefixes":{"*":{"product":451,"type":0}}}, // [Weborama Campaign Manager (former name AdPerf)] + {"hash":"178b8b7280deb93c","prefixes":{"":{"product":451,"type":0}}}, // [Weborama Campaign Manager (former name AdPerf)] + {"hash":"8398687ebe990cf1","prefixes":{"":{"product":451,"type":0}}}, // [Weborama Campaign Manager (former name AdPerf)] + {"hash":"5cad65c27ef8d2b4","prefixes":{"":{"product":451,"type":0}}}, // [Weborama Campaign Manager (former name AdPerf)] + {"hash":"f28574a110053221","prefixes":{"":{"product":451,"type":0}}}, // [Weborama Campaign Manager (former name AdPerf)] + {"hash":"64eae6bdfc8cc1be","prefixes":{"":{"product":451,"type":0}}}, // [Weborama Campaign Manager (former name AdPerf)] + {"hash":"36b0c30f5f967ffd","prefixes":{"":{"product":451,"type":0}}}, // [Weborama Campaign Manager (former name AdPerf)] + {"hash":"10c282544a39807b","prefixes":{"":{"product":451,"type":0}}}, // [Weborama Campaign Manager (former name AdPerf)] + {"hash":"ce2ed22191804ffa","prefixes":{"":{"product":451,"type":0}}}, // [Weborama Campaign Manager (former name AdPerf)] + {"hash":"bd56114f26a64020","prefixes":{"":{"product":451,"type":0}}}, // [Weborama Campaign Manager (former name AdPerf)] + {"hash":"54e283b8884709c3","prefixes":{"":{"product":451,"type":0}}}, // [Weborama Campaign Manager (former name AdPerf)] + {"hash":"313822ab7be9585a","prefixes":{"":{"product":451,"type":0}}}, // [Weborama Campaign Manager (former name AdPerf)] + {"hash":"d54943c8060334b5","prefixes":{"":{"product":452,"type":0}}}, // [Weborama Campaign Manager] + {"hash":"7928274bf854b28b","prefixes":{"*":{"product":451,"type":0}}}, // [Weborama Campaign Manager (former name AdPerf)] + {"hash":"80415fbb74db7704","prefixes":{"":{"product":453,"type":0}}}, // [Shopping Network] + {"hash":"0840f634995e25fb","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"5fd40859cc837b00","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"c58731043a973263","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"ee286fbf0440d595","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"660d555331a8be68","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"c412040c18d978ce","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"667b34ab71cb2381","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"b888d9e69003de82","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"38dafaa727179ef7","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"78da2db9d3a51f98","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"94a731a76dd26bfc","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"c4ca9b6aebf488dc","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"0a42e116235fec6e","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"ac4d0bcf3017cc3d","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"6653125411676c31","prefixes":{"":{"product":454,"type":0}}}, // [Shanghai WiseMedia Technology Co. Ltd.] + {"hash":"062b10abe02277c1","prefixes":{"":{"product":455,"type":0}}}, // [XA.net] + {"hash":"b0e3a57e8f415aec","prefixes":{"":{"product":455,"type":0}}}, // [XA.net] + {"hash":"6e1bb44d175a20af","prefixes":{"":{"product":455,"type":0}}}, // [XA.net] + {"hash":"34984bab025a1372","prefixes":{"":{"product":455,"type":0}}}, // [XA.net] + {"hash":"d9eb2f654e80ebc6","prefixes":{"*":{"product":456,"type":0}}}, // [Xaxis LLC] + {"hash":"b86d63843110e02a","prefixes":{"*":{"product":457,"type":0}}}, // [Net Edge] + {"hash":"8b526a29c7f2b3dc","prefixes":{"*":{"product":458,"type":0}}}, // [Xplusone Solutions Inc.] + {"hash":"fe0ea2a1c212cfde","prefixes":{"":{"product":459,"type":0}}}, // [Yahoo! Ad Exchange] + {"hash":"dc06a1403eb499df","prefixes":{"":{"product":459,"type":0}}}, // [Yahoo! Ad Exchange] + {"hash":"5a36dbbd382aa12c","prefixes":{"":{"product":459,"type":0}}}, // [Yahoo! Ad Exchange] + {"hash":"c8fd15f0a5fc19aa","prefixes":{"":{"product":459,"type":0}}}, // [Yahoo! Ad Exchange] + {"hash":"ce63a8ab511ec5bb","prefixes":{"":{"product":459,"type":0}}}, // [Yahoo! Ad Exchange] + {"hash":"a6d2abe55f73bc22","prefixes":{"":{"product":460,"type":0}}}, // [Yahoo Ad Manager Plus] + {"hash":"707a11e6dcfa57db","prefixes":{"":{"product":460,"type":0}}}, // [Yahoo Ad Manager Plus] + {"hash":"f75439bd7693fa84","prefixes":{"":{"product":460,"type":0}}}, // [Yahoo Ad Manager Plus] + {"hash":"2f7feb27a1b93524","prefixes":{"":{"product":460,"type":0}}}, // [Yahoo Ad Manager Plus] + {"hash":"f801c9750710d30a","prefixes":{"":{"product":460,"type":0}}}, // [Yahoo Ad Manager Plus] + {"hash":"9b96f7700d727da9","prefixes":{"":{"product":461,"type":0}}}, // [APT from Yahoo!] + {"hash":"e4de2f3b2c06e193","prefixes":{"":{"product":461,"type":0}}}, // [APT from Yahoo!] + {"hash":"21aa62a45ef75fb2","prefixes":{"*":{"product":462,"type":0}}}, // [Yieldr] + {"hash":"85bf1ed3ee6ee615","prefixes":{"":{"product":462,"type":0}}}, // [Yieldr] + {"hash":"2cf45ce27d0b73c2","prefixes":{"":{"product":462,"type":0}}}, // [Yieldr] + {"hash":"e8595ade1fd26e2f","prefixes":{"":{"product":462,"type":0}}}, // [Yieldr] + {"hash":"5660279fe13cfe3b","prefixes":{"":{"product":462,"type":0}}}, // [Yieldr] + {"hash":"ad26a995ee586915","prefixes":{"":{"product":462,"type":0}}}, // [Yieldr] + {"hash":"23412da5a5a538cc","prefixes":{"":{"product":462,"type":0}}}, // [Yieldr] + {"hash":"6b333dd78d119434","prefixes":{"":{"product":462,"type":0}}}, // [Yieldr] + {"hash":"f3621ca5777d61d5","prefixes":{"":{"product":462,"type":0}}}, // [Yieldr] + {"hash":"cafa71178e1de4db","prefixes":{"":{"product":352,"type":0}}}, // [YoYi Interactive] + {"hash":"2ca490afaa90c2b3","prefixes":{"":{"product":352,"type":0}}}, // [YoYi Interactive] + {"hash":"8f0dd7539cf77aa5","prefixes":{"":{"product":352,"type":0}}}, // [YoYi Interactive] + {"hash":"005700973b435023","prefixes":{"":{"product":463,"type":0}}}, // [YuMe Inc.] + {"hash":"bd83427751c351a9","prefixes":{"":{"product":463,"type":0}}}, // [YuMe Inc.] + {"hash":"e504ebfcb6b2722e","prefixes":{"":{"product":463,"type":0}}}, // [YuMe Inc.] + {"hash":"8080438b5792b260","prefixes":{"":{"product":464,"type":0}}}, // [Ebuzzing] + {"hash":"274889e98fbfc776","prefixes":{"":{"product":464,"type":0}}}, // [Ebuzzing] + {"hash":"b62ee5e77fde7ec7","prefixes":{"":{"product":464,"type":0}}}, // [Ebuzzing] + {"hash":"cc6a7a565374c257","prefixes":{"":{"product":464,"type":0}}}, // [Ebuzzing] + {"hash":"e02936a6a6a2cb94","prefixes":{"":{"product":465,"type":0}}}, // [Ziff Davis] + {"hash":"223b94a95f6849cf","prefixes":{"":{"product":465,"type":0}}}, // [Ziff Davis] + {"hash":"a8742ddae80b031b","prefixes":{"":{"product":466,"type":0}}}, // [DataPoint Media Inc.] + {"hash":"fd4a16bf59718107","prefixes":{"":{"product":467,"type":0}}}, // [Simplytics Limited] + {"hash":"a3d523521bc4ba12","prefixes":{"":{"product":467,"type":0}}}, // [Simplytics Limited] + {"hash":"9da8a1153308d7f2","prefixes":{"":{"product":468,"type":0}}}, // [Makazi] + {"hash":"d9cc216c8d482336","prefixes":{"":{"product":468,"type":0}}}, // [Makazi] + {"hash":"166c65d7776be9f8","prefixes":{"":{"product":468,"type":0}}}, // [Makazi] + {"hash":"55f15e5b7746999f","prefixes":{"":{"product":468,"type":0}}}, // [Makazi] + {"hash":"213194bd445e551d","prefixes":{"":{"product":468,"type":0}}}, // [Makazi] + {"hash":"31406bff4dc35eea","prefixes":{"":{"product":468,"type":0}}}, // [Makazi] + {"hash":"ea9607b28f4238c2","prefixes":{"":{"product":468,"type":0}}}, // [Makazi] + {"hash":"707d5310f27d0dd2","prefixes":{"":{"product":469,"type":0}}}, // [Rich Relevance] + {"hash":"59fa19b8a48477fe","prefixes":{"":{"product":470,"type":0}}}, // [MainADV] + {"hash":"efb9b464f6ebaa1d","prefixes":{"":{"product":470,"type":0}}}, // [MainADV] + {"hash":"8848350bd85fffe4","prefixes":{"":{"product":470,"type":0}}}, // [MainADV] + {"hash":"519275c83a5a1c92","prefixes":{"":{"product":470,"type":0}}}, // [MainADV] + {"hash":"fc92bec8fbcb03ef","prefixes":{"":{"product":470,"type":0}}}, // [MainADV] + {"hash":"91fa39bc27e156b4","prefixes":{"":{"product":470,"type":0}}}, // [MainADV] + {"hash":"408d55e8995335ad","prefixes":{"":{"product":470,"type":0}}}, // [MainADV] + {"hash":"d0efa7323c77b1a5","prefixes":{"":{"product":470,"type":0}}}, // [MainADV] + {"hash":"baa5cf88a0176bc6","prefixes":{"":{"product":471,"type":0}}}, // [MediaV Advertising] + {"hash":"3ea0854e74c32c87","prefixes":{"":{"product":471,"type":0}}}, // [MediaV Advertising] + {"hash":"88a70c2ebfe38ffe","prefixes":{"":{"product":471,"type":0}}}, // [MediaV Advertising] + {"hash":"dc0b1dfe6de6a967","prefixes":{"":{"product":471,"type":0}}}, // [MediaV Advertising] + {"hash":"cb234228af27fa32","prefixes":{"":{"product":471,"type":0}}}, // [MediaV Advertising] + {"hash":"c7abee58863b27a4","prefixes":{"":{"product":472,"type":0}}}, // [MicroAd Inc.] + {"hash":"7e34b0d37ded49ed","prefixes":{"":{"product":472,"type":0}}}, // [MicroAd Inc.] + {"hash":"d7255d3135b0294d","prefixes":{"":{"product":472,"type":0}}}, // [MicroAd Inc.] + {"hash":"e21264db24be060c","prefixes":{"":{"product":472,"type":0}}}, // [MicroAd Inc.] + {"hash":"466676eb4c2066ac","prefixes":{"":{"product":472,"type":0}}}, // [MicroAd Inc.] + {"hash":"2505a55ead3f2266","prefixes":{"":{"product":472,"type":0}}}, // [MicroAd Inc.] + {"hash":"e97b9e2d31ac962d","prefixes":{"":{"product":472,"type":0}}}, // [MicroAd Inc.] + {"hash":"906215055f6880fa","prefixes":{"":{"product":472,"type":0}}}, // [MicroAd Inc.] + {"hash":"df04046f11aea628","prefixes":{"*":{"product":473,"type":0}}}, // [Platform ID Inc.] + {"hash":"9fe8e93d55562003","prefixes":{"":{"product":474,"type":0}}}, // [Xrost] + {"hash":"6b29d401833f79d8","prefixes":{"":{"product":473,"type":0}}}, // [Platform ID Inc.] + {"hash":"00928c6f847a4785","prefixes":{"":{"product":475,"type":1}}}, // [Sociocast Networks LLC D/B/A Velos] + {"hash":"c3964f299adbe862","prefixes":{"":{"product":476,"type":1}}}, // [Trend Research] + {"hash":"76b5ddb10f769c6b","prefixes":{"*":{"product":248,"type":0}}}, // [AdOcean Ltd] + {"hash":"f52edd3926705507","prefixes":{"":{"product":477,"type":0}}}, // [Black Swan Verification] + {"hash":"d63e38f4eba51f77","prefixes":{"":{"product":478,"type":0}}}, // [Momentum K.K] + {"hash":"6c0f8db03b28099b","prefixes":{"":{"product":477,"type":0}}}, // [Black Swan Verification] + {"hash":"248772911542d550","prefixes":{"*":{"product":479,"type":0}}}, // [Betgenius Limited] + {"hash":"38a72a4924027d8f","prefixes":{"*":{"product":480,"type":1}}}, // [AT Internet] + {"hash":"255b63d169bd9d10","prefixes":{"*":{"product":480,"type":1}}}, // [AT Internet] + {"hash":"3a7fbbad166769ad","prefixes":{"":{"product":481,"type":1}}}, // [DataLab] + {"hash":"fe64230a84967d3c","prefixes":{"":{"product":482,"type":1}}}, // [Innovid Inc.] + {"hash":"a91296d609efe0b4","prefixes":{"":{"product":482,"type":1}}}, // [Innovid Inc.] + {"hash":"947fa5564eccc0b2","prefixes":{"":{"product":482,"type":1}}}, // [Innovid Inc.] + {"hash":"89a64fe46687237f","prefixes":{"":{"product":482,"type":1}}}, // [Innovid Inc.] + {"hash":"ce1cd4220063df2d","prefixes":{"":{"product":482,"type":1}}}, // [Innovid Inc.] + {"hash":"1c489f83a79301c6","prefixes":{"":{"product":482,"type":1}}}, // [Innovid Inc.] + {"hash":"9dc25ef9b3ed3e5d","prefixes":{"":{"product":482,"type":1}}}, // [Innovid Inc.] + {"hash":"9898ab0c57d683ae","prefixes":{"":{"product":482,"type":1}}}, // [Innovid Inc.] + {"hash":"0229fe19979f88b0","prefixes":{"":{"product":482,"type":1}}}, // [Innovid Inc.] + {"hash":"6dedd3fca4d243ac","prefixes":{"":{"product":482,"type":1}}}, // [Innovid Inc.] + {"hash":"cbc23a15e9f02987","prefixes":{"":{"product":482,"type":1}}}, // [Innovid Inc.] + {"hash":"95119cbc05f9e42a","prefixes":{"":{"product":482,"type":1}}}, // [Innovid Inc.] + {"hash":"784647d3eb0236dc","prefixes":{"*":{"product":483,"type":0}}}, // [Adacado] + {"hash":"4be5d3939998bc39","prefixes":{"":{"product":483,"type":0}}}, // [Adacado] + {"hash":"cec4d2059bbb1365","prefixes":{"*":{"product":484,"type":0}}}, // [NetDNA, LLC] + {"hash":"87a9bf2f660b2673","prefixes":{"":{"product":478,"type":0}}}, // [Momentum K.K] + {"hash":"33f6a4c9eb1313f6","prefixes":{"":{"product":478,"type":0}}}, // [Momentum K.K] + {"hash":"38afcf5464d4a46e","prefixes":{"":{"product":478,"type":0}}}, // [Momentum K.K] + {"hash":"4a13b10532de4033","prefixes":{"*":{"product":485,"type":0}}}, // [Pipewave Inc.] + {"hash":"a703750c918980b9","prefixes":{"":{"product":486,"type":0}}}, // [US Media Consulting] + {"hash":"77b351109047edb2","prefixes":{"":{"product":487,"type":0}}}, // [SKYTOUCH TECHNOLOGY CO., LIMITED] + {"hash":"f9f554c96902397e","prefixes":{"":{"product":487,"type":0}}}, // [SKYTOUCH TECHNOLOGY CO., LIMITED] + {"hash":"e8f2c7f5eb75983e","prefixes":{"":{"product":487,"type":0}}}, // [SKYTOUCH TECHNOLOGY CO., LIMITED] + {"hash":"f8680fe819857e65","prefixes":{"image":{"product":487,"type":0}}}, // [SKYTOUCH TECHNOLOGY CO., LIMITED] + {"hash":"fe12b35f78c433a6","prefixes":{"":{"product":487,"type":0}}}, // [SKYTOUCH TECHNOLOGY CO., LIMITED] + {"hash":"531f5c369a189473","prefixes":{"":{"product":488,"type":0}}}, // [Hanesbrands Direct LLC] + {"hash":"4bfbc25da5ec8116","prefixes":{"":{"product":489,"type":0}}}, // [A1platform] + {"hash":"56cea5c2b408989a","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"2c24b521f38d28dd","prefixes":{"":{"product":10,"type":0}}}, // [eBay] + {"hash":"d6449351ee8e33eb","prefixes":{"*":{"product":490,"type":0}}}, // [Agency.com] + {"hash":"5e040f7b958d9ee5","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"379ed8ab1690a74c","prefixes":{"":{"product":10,"type":0}}}, // [eBay] + {"hash":"6ed4dac9c333ef4b","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"b4a9e54654a6de08","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"687aa30619ec8e7f","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"5ac823af612c4492","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"ce4e70466c43ade3","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"c865cf822ab64a71","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"083c339aac7e418c","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"8d689bf60029c98f","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"19d0e1eba389dfe1","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"b789395149868329","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"25e9f5191f3d2397","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"82a743999425aaad","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"97a729e5b41fd4ed","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"0db7dee9d3c756cc","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"10981271cb66af25","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"8c86bc9ba67482c6","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"d36efad270e3e7c6","prefixes":{"*":{"product":10,"type":0}}}, // [eBay] + {"hash":"b709ca3f38e77645","prefixes":{"":{"product":491,"type":0}}}, // [Adap.tv Inc. (AdWords/YouTube)] + {"hash":"3cba207e4aa9d6c6","prefixes":{"":{"product":491,"type":0}}}, // [Adap.tv Inc. (AdWords/YouTube)] + {"hash":"fd8da92d6de2518b","prefixes":{"":{"product":491,"type":0}}}, // [Adap.tv Inc. (AdWords/YouTube)] + {"hash":"d9e4d4444ebd418f","prefixes":{"":{"product":491,"type":0}}}, // [Adap.tv Inc. (AdWords/YouTube)] + {"hash":"4c1c4999d1501943","prefixes":{"":{"product":491,"type":0}}}, // [Adap.tv Inc. (AdWords/YouTube)] + {"hash":"a635762b8125bba5","prefixes":{"":{"product":491,"type":0}}}, // [Adap.tv Inc. (AdWords/YouTube)] + {"hash":"99818fe6fd4c4a9c","prefixes":{"":{"product":491,"type":0}}}, // [Adap.tv Inc. (AdWords/YouTube)] + {"hash":"cae59de4e054a5a8","prefixes":{"":{"product":491,"type":0}}}, // [Adap.tv Inc. (AdWords/YouTube)] + {"hash":"d1ec771fe9489a9f","prefixes":{"":{"product":491,"type":0}}}, // [Adap.tv Inc. (AdWords/YouTube)] + {"hash":"d9effad74da2b097","prefixes":{"*":{"product":491,"type":0}}}, // [Adap.tv Inc. (AdWords/YouTube)] + {"hash":"46b1fc5fe9da3681","prefixes":{"*":{"product":492,"type":1}}}, // [Fjord Technologies S.A.S.] + {"hash":"e0b6d05a8e75e14a","prefixes":{"*":{"product":492,"type":1}}}, // [Fjord Technologies S.A.S.] + {"hash":"11a89bdf6bc5cf28","prefixes":{"":{"product":493,"type":1}}}, // [Refined Ads] + {"hash":"8e6414939f586d4c","prefixes":{"":{"product":493,"type":1}}}, // [Refined Ads] + {"hash":"6462a1b97a382278","prefixes":{"":{"product":493,"type":1}}}, // [Refined Ads] + {"hash":"9f99479854cea2e7","prefixes":{"":{"product":493,"type":1}}}, // [Refined Ads] + {"hash":"72b40aacd2b4e226","prefixes":{"":{"product":493,"type":1}}}, // [Refined Ads] {"hash":"67401ef133d2ed76","prefixes":{"":{"product":494}}}, // [nugg.ad AG] - {"hash":"696757eb9e07845f","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"c84660fcf8a4c99c","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"df10c5e0e18fda2b","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"c71dfe726124b24c","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"f603a3b56996fe4c","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"149593d24f74e3e1","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"a1b9a8ff7b829f8f","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"37cb27fb57319c52","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"16e50e7e7b499ab7","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"c10f5df1adb6160f","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"df3ea734f608dc0d","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"3014b8652e4fd340","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"68034e41a59505be","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"4ff550d2f5a384d7","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"266c6cb54cc8f810","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"c174c4c7c469cbb9","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"19b8f26cb5987d86","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"0301de7ebef3ded7","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"5f6ccacecc90b6ab","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"cee43a3e7001e664","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"27d64efa61e9fb8c","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"05eae7c7a976d6b2","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"da375ad9bc86ad05","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"1a62d22c13d4f003","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"65f8018fc9a58ba7","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"c790c87ca2abbb6c","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"5aefca188560242d","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"eaa7adee1317cb7d","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"db5afb1288bacbff","prefixes":{"*":{"product":496}}}, // [Meetrics GmbH] - {"hash":"7d618e8de39f548c","prefixes":{"*":{"product":496}}}, // [Meetrics GmbH] - {"hash":"b5c30978f10b1f56","prefixes":{"s":{"product":496},"":{"product":497}}}, // [Meetrics GmbH] [Meetrics] - {"hash":"5c4a10a5bc0897c7","prefixes":{"":{"product":498}}}, // [Digital Control GmbH & Co. KG] - {"hash":"38d57267aeada6cc","prefixes":{"":{"product":498}}}, // [Digital Control GmbH & Co. KG] - {"hash":"7dc82de98d234295","prefixes":{"":{"product":499}}}, // [Dedicated Media] - {"hash":"98cac3ed2db221c5","prefixes":{"":{"product":499}}}, // [Dedicated Media] - {"hash":"74da617dd78c4c25","prefixes":{"":{"product":499}}}, // [Dedicated Media] - {"hash":"ad829d4fccaec076","prefixes":{"":{"product":499}}}, // [Dedicated Media] - {"hash":"93214296470961ea","prefixes":{"":{"product":500}}}, // [Accuen] - {"hash":"fb8e16c2a3413e04","prefixes":{"*":{"product":501}}}, // [Pulse 360, Inc.] - {"hash":"56de3497c2b187f9","prefixes":{"*":{"product":501}}}, // [Pulse 360, Inc.] - {"hash":"1763cb8cd4ecb455","prefixes":{"*":{"product":502}}}, // [ZANOX AG] - {"hash":"dd420134fd0b31f7","prefixes":{"*":{"product":502}}}, // [ZANOX AG] - {"hash":"f942b375b4c9d301","prefixes":{"":{"product":503}}}, // [Webgains Ltd] - {"hash":"03b41741559a5775","prefixes":{"":{"product":504}}}, // [Virgin Media Limited] - {"hash":"e01702c3ace07a42","prefixes":{"*":{"product":505}}}, // [MyBuys MyAds] - {"hash":"a09aa03b7ab4a6a0","prefixes":{"*":{"product":506}}}, // [VCCP Search LTD] - {"hash":"8ae53030752d70fd","prefixes":{"":{"product":507}}}, // [Conversant Media] - {"hash":"3f911ef887ffe5a7","prefixes":{"":{"product":507}}}, // [Conversant Media] - {"hash":"dd0195d7ab665db3","prefixes":{"":{"product":507}}}, // [Conversant Media] - {"hash":"6ac275e8e99e5fb3","prefixes":{"":{"product":507}}}, // [Conversant Media] - {"hash":"5960f055d64bd6fb","prefixes":{"":{"product":507}}}, // [Conversant Media] - {"hash":"d07a0c93a2f5da33","prefixes":{"":{"product":507}}}, // [Conversant Media] - {"hash":"b7e7f7ab4a600ced","prefixes":{"":{"product":508}}}, // [Up-Value GmbH & Co. KG] - {"hash":"e92a06c68de2a79d","prefixes":{"":{"product":509}}}, // [Unruly Media] - {"hash":"789659215cb1620d","prefixes":{"":{"product":509}}}, // [Unruly Media] - {"hash":"b61a48cd46cb7b06","prefixes":{"*":{"product":510}}}, // [Underdog Media LLC] - {"hash":"eea5fa46bce35e24","prefixes":{"":{"product":511}}}, // [SVG Media Pvt. Ltd.] - {"hash":"9b346c0d77f1fcf2","prefixes":{"*":{"product":512}}}, // [TRAFFIQ LLC] - {"hash":"51324f52aa5eb734","prefixes":{"*":{"product":513}}}, // [TellApart Inc.] - {"hash":"26e3ca8cc9a6afd8","prefixes":{"":{"product":513}}}, // [TellApart Inc.] - {"hash":"2e9a57a3dcc61e3e","prefixes":{"":{"product":513}}}, // [TellApart Inc.] - {"hash":"2e6202e113ae62e3","prefixes":{"":{"product":513}}}, // [TellApart Inc.] - {"hash":"9a1d6d8445e2cce9","prefixes":{"":{"product":513}}}, // [TellApart Inc.] - {"hash":"88015c5982735097","prefixes":{"":{"product":513}}}, // [TellApart Inc.] - {"hash":"9cf10e72a2db48a9","prefixes":{"":{"product":513}}}, // [TellApart Inc.] - {"hash":"cf5ba41c477d8aa5","prefixes":{"":{"product":513}}}, // [TellApart Inc.] - {"hash":"fe50c8a7f665cf78","prefixes":{"":{"product":513}}}, // [TellApart Inc.] - {"hash":"5c9fb160269ccb5c","prefixes":{"":{"product":513}}}, // [TellApart Inc.] - {"hash":"366f4f435bfb9255","prefixes":{"":{"product":513}}}, // [TellApart Inc.] - {"hash":"5dde0b5371aae6bb","prefixes":{"":{"product":513}}}, // [TellApart Inc.] - {"hash":"ebd682e181b553a7","prefixes":{"":{"product":513}}}, // [TellApart Inc.] - {"hash":"df61db1cec60b5a1","prefixes":{"":{"product":513}}}, // [TellApart Inc.] - {"hash":"bdf8043c482f8afd","prefixes":{"*":{"product":514}}}, // [Shopzilla Inc.] - {"hash":"83ce758172dc68fb","prefixes":{"*":{"product":514}}}, // [Shopzilla Inc.] - {"hash":"45cc9e8ea0e405cc","prefixes":{"*":{"product":514}}}, // [Shopzilla Inc.] - {"hash":"bc8d543772676fe4","prefixes":{"*":{"product":514}}}, // [Shopzilla Inc.] - {"hash":"6a51a8a28265901e","prefixes":{"*":{"product":515}}}, // [Reactivpub] - {"hash":"b03903f1abac9b82","prefixes":{"*":{"product":515}}}, // [Reactivpub] - {"hash":"14281bd870fa9e85","prefixes":{"*":{"product":515}}}, // [Reactivpub] - {"hash":"52c9dfb471edf4de","prefixes":{"*":{"product":515}}}, // [Reactivpub] - {"hash":"b9cf807aee694b90","prefixes":{"*":{"product":516}}}, // [Netseer Inc.] - {"hash":"720c7cdaeb3d3edf","prefixes":{"":{"product":516}}}, // [Netseer Inc.] - {"hash":"a7e82477ddc48f23","prefixes":{"*":{"product":517}}}, // [eBay Enterprise] - {"hash":"c35bcff10cd62a44","prefixes":{"":{"product":518}}}, // [Goodway Group] - {"hash":"a45b6c7292b7b560","prefixes":{"":{"product":518}}}, // [Goodway Group] - {"hash":"d76efc82324fb8d5","prefixes":{"":{"product":518}}}, // [Goodway Group] - {"hash":"5eb742c77c59dd05","prefixes":{"":{"product":518}}}, // [Goodway Group] - {"hash":"33f9a4e4a440eeda","prefixes":{"*":{"product":519}}}, // [Double Positive Marketing Group Inc.] - {"hash":"285da2e20d7ae651","prefixes":{"*":{"product":520}}}, // [Chitika Inc.] - {"hash":"9ac26bc76037dd72","prefixes":{"*":{"product":521}}}, // [Scigineer Inc.] - {"hash":"11971f02aee2996f","prefixes":{"*":{"product":522}}}, // [Sales Spider Inc.] - {"hash":"0dfb620c1f99f67a","prefixes":{"*":{"product":522}}}, // [Sales Spider Inc.] - {"hash":"dee182aa38b90802","prefixes":{"":{"product":523}}}, // [Rocket Fuel Inc.] - {"hash":"ee4bb512aa7bff3f","prefixes":{"":{"product":523}}}, // [Rocket Fuel Inc.] - {"hash":"051b6a2f5170871a","prefixes":{"":{"product":523}}}, // [Rocket Fuel Inc.] - {"hash":"ef2266eab416e344","prefixes":{"":{"product":523}}}, // [Rocket Fuel Inc.] - {"hash":"40701593c87a2a6d","prefixes":{"":{"product":523}}}, // [Rocket Fuel Inc.] - {"hash":"4dfd82e7fcbfe056","prefixes":{"":{"product":523}}}, // [Rocket Fuel Inc.] - {"hash":"2848c783f1d69118","prefixes":{"":{"product":523}}}, // [Rocket Fuel Inc.] - {"hash":"26fd0c0c1bbdf578","prefixes":{"":{"product":523}}}, // [Rocket Fuel Inc.] - {"hash":"9362d437c6649ac0","prefixes":{"":{"product":524}}}, // [RTBlab] - {"hash":"83cd554cdc78cc1c","prefixes":{"":{"product":524}}}, // [RTBlab] - {"hash":"e4e3ec12949d311d","prefixes":{"":{"product":524}}}, // [RTBlab] - {"hash":"9db675ca1ddbc25e","prefixes":{"":{"product":524}}}, // [RTBlab] - {"hash":"c407f5eb4837736a","prefixes":{"":{"product":524}}}, // [RTBlab] - {"hash":"27e52d41a00bf2fd","prefixes":{"":{"product":524}}}, // [RTBlab] - {"hash":"efa545dd9d577a82","prefixes":{"":{"product":525}}}, // [abilicom GmbH] - {"hash":"f690d50313c4d883","prefixes":{"":{"product":525}}}, // [abilicom GmbH] - {"hash":"e59063ed858c1ac6","prefixes":{"":{"product":525}}}, // [abilicom GmbH] - {"hash":"08ecd0f7d816b029","prefixes":{"":{"product":30}}}, // [Rakuten Display] - {"hash":"6321d1d2e3ff13cf","prefixes":{"":{"product":526}}}, // [Pulpo Media Inc] - {"hash":"68778ff49de5f6b7","prefixes":{"":{"product":526}}}, // [Pulpo Media Inc] - {"hash":"4fe62a295bf7110a","prefixes":{"*":{"product":527}}}, // [OneSpot] - {"hash":"0a03e9309eac6fef","prefixes":{"*":{"product":528}}}, // [MyThings UK Ltd] - {"hash":"aefee6cf21fb21d0","prefixes":{"*":{"product":528}}}, // [MyThings UK Ltd] - {"hash":"013cf49561a61d0a","prefixes":{"":{"product":529}}}, // [Exactag] - {"hash":"a5db93b0474bf88a","prefixes":{"":{"product":529}}}, // [Exactag] - {"hash":"8eaf146d58acaea3","prefixes":{"":{"product":353}}}, // [AdMaster] - {"hash":"62f9a92e2fa55157","prefixes":{"":{"product":353}}}, // [AdMaster] - {"hash":"2246fe417fb594d4","prefixes":{"":{"product":353}}}, // [AdMaster] - {"hash":"46be6b3d05c938b5","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"b588a450d30940dc","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"9013d3536e80f01a","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"705829297e5108ae","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"bfd58f70292d02ab","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"ff5875b2546d8499","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"ccc16a9e8656612f","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"a764b52c155c440b","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"a8a184b600fd3af1","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"6c106d279e66ed61","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"7c8663ad744aeec9","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"c3860e5673290a36","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"485e37ef683e6da8","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"03c59eef464ffa9d","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"e8d28d6ae9ed1064","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"1fc896b89972c4a3","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"89d45cf6716d92c4","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"c374b8ef2cc0a6d3","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"e0a60df6ec972762","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"dfd819866072d81c","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"dbaab38c6254fc44","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"25e404b1d7cfa7b3","prefixes":{"":{"product":530}}}, // [Kyocera Communication Systems Co. Ltd.] - {"hash":"f9b4a878a9f66629","prefixes":{"":{"product":531}}}, // [Beijing LangTaoJin Interactive] - {"hash":"5be19b5ec9da0217","prefixes":{"":{"product":531}}}, // [Beijing LangTaoJin Interactive] - {"hash":"c3dd7532c047b725","prefixes":{"":{"product":532}}}, // [Conversant Mobile Media] - {"hash":"fd89a621a7abcb21","prefixes":{"":{"product":532}}}, // [Conversant Mobile Media] - {"hash":"8b03c1ce3a37af3e","prefixes":{"":{"product":533}}}, // [MM1X.nl] - {"hash":"51f16f2963b5ab62","prefixes":{"":{"product":533}}}, // [MM1X.nl] - {"hash":"a34aa5b1e90b35d0","prefixes":{"":{"product":534}}}, // [Trivu Media Inc.] - {"hash":"f5fe0a711d905029","prefixes":{"":{"product":534}}}, // [Trivu Media Inc.] - {"hash":"284614e662fae11d","prefixes":{"*":{"product":535}}}, // [BlueCava Inc.] - {"hash":"cd9e8f6b8e3bb0bb","prefixes":{"":{"product":536}}}, // [Beijing Gridsum Technology Co. Ltd.] - {"hash":"97de03485c681efe","prefixes":{"":{"product":536}}}, // [Beijing Gridsum Technology Co. Ltd.] - {"hash":"6c624568b77c2f15","prefixes":{"":{"product":536}}}, // [Beijing Gridsum Technology Co. Ltd.] - {"hash":"2b74e65baabdf4a8","prefixes":{"":{"product":537}}}, // [Adsvana DSP] - {"hash":"fcd2a83347336f39","prefixes":{"":{"product":537}}}, // [Adsvana DSP] - {"hash":"7cadddba30cbf68b","prefixes":{"":{"product":367}}}, // [revenue cloud] - {"hash":"39fe4b58f8d0c85a","prefixes":{"":{"product":538}}}, // [Target Performance] - {"hash":"219259d49fac1ccb","prefixes":{"":{"product":539}}}, // [Content Spread] - {"hash":"ca8d76b63fdfd7e7","prefixes":{"":{"product":367}}}, // [revenue cloud] - {"hash":"ed86b10928624d27","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"205f80e614b45d0c","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"88c9d142721a0010","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"c918497df4612dee","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"ecc68ce18bc92eac","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"acd6e7d757515791","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"611fb7a1125a9f9d","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"b47f7e78adfcce8c","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"e7d6867de133fef3","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"022353c9ab0821d7","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"2571a0502f188936","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"f1efca13f787818a","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"1c982ec87cdd98c7","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"ffa62eae8604dfb9","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"8c7ba8485b195fda","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"188fb424b02d01b3","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"92807e8eb5ceed53","prefixes":{"":{"product":540}}}, // [Datamind Effective Media] - {"hash":"b01a0f9c920b194e","prefixes":{"":{"product":541}}}, // [ScaleOut Inc.] - {"hash":"da51b7d5383143f5","prefixes":{"":{"product":541}}}, // [ScaleOut Inc.] - {"hash":"acca27df7ac50ef3","prefixes":{"":{"product":541}}}, // [ScaleOut Inc.] - {"hash":"8a45863cac015863","prefixes":{"":{"product":541}}}, // [ScaleOut Inc.] - {"hash":"ae50046a864ceafd","prefixes":{"":{"product":541}}}, // [ScaleOut Inc.] - {"hash":"de57dfdaf9a2c48a","prefixes":{"":{"product":542}}}, // [Ensighten] - {"hash":"b1235d3bdac69ad1","prefixes":{"":{"product":542}}}, // [Ensighten] - {"hash":"b2717d6d54a069e3","prefixes":{"":{"product":542}}}, // [Ensighten] - {"hash":"d7152b8a7fbdcfd9","prefixes":{"":{"product":542}}}, // [Ensighten] - {"hash":"66d946b524ae15cb","prefixes":{"":{"product":542}}}, // [Ensighten] - {"hash":"cb87adb62a805e43","prefixes":{"":{"product":542}}}, // [Ensighten] - {"hash":"64b417a15cd2caba","prefixes":{"":{"product":542}}}, // [Ensighten] - {"hash":"fe5fbbb5f87923ec","prefixes":{"":{"product":542}}}, // [Ensighten] - {"hash":"7955dee10fac2b43","prefixes":{"":{"product":543}}}, // [Sony Electronics Inc.] - {"hash":"18b842a485714b88","prefixes":{"":{"product":543}}}, // [Sony Electronics Inc.] - {"hash":"5e881c11a6141a0e","prefixes":{"*":{"product":544}}}, // [Gravity Research and Development LTD] - {"hash":"eb0586aa7b44d1a7","prefixes":{"":{"product":545}}}, // [Project SunBlock] - {"hash":"e49a615e7e072e05","prefixes":{"":{"product":546}}}, // [Novem sp. z o.o.] - {"hash":"c36795d664275022","prefixes":{"*":{"product":547}}}, // [Econda GmbH] - {"hash":"1dafa12902626628","prefixes":{"":{"product":548}}}, // [AdMaxim LLC] - {"hash":"ddc49ed0d5adc099","prefixes":{"":{"product":548}}}, // [AdMaxim LLC] - {"hash":"43e36030afe70656","prefixes":{"":{"product":548}}}, // [AdMaxim LLC] - {"hash":"f4acd265af4a8b2c","prefixes":{"":{"product":548}}}, // [AdMaxim LLC] - {"hash":"2d00af9d31137b46","prefixes":{"":{"product":548}}}, // [AdMaxim LLC] - {"hash":"6330d2d69fac5592","prefixes":{"":{"product":548}}}, // [AdMaxim LLC] - {"hash":"07924db4fbf62ed8","prefixes":{"":{"product":548}}}, // [AdMaxim LLC] - {"hash":"40fa76b0dfe6cba9","prefixes":{"":{"product":548}}}, // [AdMaxim LLC] - {"hash":"cb5e5323270dac31","prefixes":{"":{"product":548}}}, // [AdMaxim LLC] - {"hash":"644395b50223d6f0","prefixes":{"":{"product":78}}}, // [Adnologies GmbH] - {"hash":"e816f89057c8ad52","prefixes":{"":{"product":78}}}, // [Adnologies GmbH] - {"hash":"8d2b1cab5958796f","prefixes":{"":{"product":549}}}, // [Alliance Health Networks] - {"hash":"3568ed34edbd0a3b","prefixes":{"":{"product":550}}}, // [Adsame Advertising Co., Ltd] - {"hash":"5fd75bdc8d48469a","prefixes":{"":{"product":550}}}, // [Adsame Advertising Co., Ltd] - {"hash":"f24f098ee46d7e52","prefixes":{"":{"product":550}}}, // [Adsame Advertising Co., Ltd] - {"hash":"695c924af8b7be90","prefixes":{"":{"product":551}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] - {"hash":"8c21b1544107f44b","prefixes":{"":{"product":552}}}, // [PK Online Ventures Limited] - {"hash":"b709e5fa7a0a3284","prefixes":{"":{"product":553}}}, // [Bigpoint Gmbh] - {"hash":"54393b0479bf4296","prefixes":{"":{"product":553}}}, // [Bigpoint Gmbh] - {"hash":"0228e75fa4f7ba29","prefixes":{"":{"product":553}}}, // [Bigpoint Gmbh] - {"hash":"161b02c3430e8493","prefixes":{"":{"product":554}}}, // [Mirapodo GmbH] - {"hash":"cbfa294f671394f5","prefixes":{"":{"product":555}}}, // [Digitize New Media Ltd.] - {"hash":"126e76895e35030f","prefixes":{"":{"product":556}}}, // [AdSage] - {"hash":"d1a3397960a0c962","prefixes":{"":{"product":556}}}, // [AdSage] - {"hash":"27111f31c7f7870c","prefixes":{"":{"product":556}}}, // [AdSage] - {"hash":"5066a54cd7ed6242","prefixes":{"":{"product":556}}}, // [AdSage] - {"hash":"5447e7edfecbefc9","prefixes":{"":{"product":556}}}, // [AdSage] - {"hash":"763e1c5a534cdce1","prefixes":{"":{"product":556}}}, // [AdSage] - {"hash":"664f6761d6e1bdc5","prefixes":{"":{"product":556}}}, // [AdSage] - {"hash":"85dc2dbb9cf8ba01","prefixes":{"":{"product":556}}}, // [AdSage] - {"hash":"efd9939ccbcea7ca","prefixes":{"":{"product":556}}}, // [AdSage] - {"hash":"5095b815554d166d","prefixes":{"":{"product":556}}}, // [AdSage] - {"hash":"bbd5220662a5b37e","prefixes":{"":{"product":556}}}, // [AdSage] - {"hash":"ad929f7cd3353264","prefixes":{"":{"product":556}}}, // [AdSage] - {"hash":"aebf7b2a7ee1ff12","prefixes":{"":{"product":557}}}, // [Fingereach] - {"hash":"01ef28aab34283cc","prefixes":{"":{"product":557}}}, // [Fingereach] - {"hash":"c075f26f4aa57d43","prefixes":{"":{"product":557}}}, // [Fingereach] - {"hash":"f651f54211351ca7","prefixes":{"":{"product":557}}}, // [Fingereach] - {"hash":"98e7e8f01b1e7221","prefixes":{"":{"product":557}}}, // [Fingereach] - {"hash":"7f46832cdf7b45db","prefixes":{"":{"product":557}}}, // [Fingereach] - {"hash":"4a37345bf96b65b5","prefixes":{"":{"product":557}}}, // [Fingereach] - {"hash":"ee9f377ce8711040","prefixes":{"":{"product":557}}}, // [Fingereach] - {"hash":"f6f6db9a07009087","prefixes":{"":{"product":557}}}, // [Fingereach] - {"hash":"37414a33ff3de4a0","prefixes":{"":{"product":557}}}, // [Fingereach] - {"hash":"7cc06f83f0710408","prefixes":{"":{"product":557}}}, // [Fingereach] - {"hash":"beb1894d6a5dd8d5","prefixes":{"":{"product":557}}}, // [Fingereach] - {"hash":"ab305fad96c94e68","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"abb33b12777d693c","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"cf57baa1fe60d65d","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"1e230cd699b878e6","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"0e9f493079696ce3","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"7d3350cd22011e53","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"f50b2ec037f5428b","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"c171c26c4996ef48","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"558975de73dc2727","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"ee6b8472f5558865","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"8183f3c56cedc5d3","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"9e46a78131a70a25","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"9805160753b78db8","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"9665241d465c8ced","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"0886098ece10411f","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"1b9aa72e21da1cf9","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"75eaf92a0259fced","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"6647ef959a9060b1","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"55bbd43420c048ba","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"769a3492166f2234","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"88bf787fe78aa617","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"62db61a5802ee5f9","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"ecc8b48b5b165bff","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"3b713a488717f579","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"7d501d2362243528","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"1e2c100fab457dce","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"7adb32ad76289644","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"3f4747021104b435","prefixes":{"":{"product":307}}}, // [DMA Institute dba Hottraffic] - {"hash":"55ade41cc24f1b54","prefixes":{"":{"product":558}}}, // [Calvin Klein] - {"hash":"210f025e6c6b8122","prefixes":{"":{"product":559}}}, // [Medialets Servo] - {"hash":"233555f3daf9abb0","prefixes":{"":{"product":559}}}, // [Medialets Servo] - {"hash":"eea93545b322651b","prefixes":{"":{"product":559}}}, // [Medialets Servo] - {"hash":"d9fe49eeaf35eb01","prefixes":{"":{"product":559}}}, // [Medialets Servo] - {"hash":"ea41698b95338591","prefixes":{"s-cdn-":{"product":559}}}, // [Medialets Servo] - {"hash":"5f4e90726b181c95","prefixes":{"":{"product":560}}}, // [Webmoblink Inc.] - {"hash":"9d51efd26ab44317","prefixes":{"":{"product":31}}}, // [Retailigence] - {"hash":"32440ed26b61d14a","prefixes":{"":{"product":31}}}, // [Retailigence] - {"hash":"8234d0306d8984eb","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"e35bf94930bc4d1a","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"aec3f56c7f99151f","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"ef395b96d922c238","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"5a053ab1bcfcfb41","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"2cf811bb8aa279b5","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"cd383e750e6cfcdb","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"c30fc77cd822188e","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"fb9678eef7ea227d","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"102facb286a88bbe","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"aa39a58ff4ed2114","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"e33908ca9604cfa4","prefixes":{"*":{"product":561},"":{"product":562}}}, // [Moat Inc.] [Bannerflow AB] - {"hash":"31902ac0cc3e362b","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"796535f10f1e1ea0","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"681a390e8faf08c1","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"1ef04ebc565a6f48","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"1461b89b1a4a5e39","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"a7c34fe979c7afe2","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"30142bb0f24faa5a","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"dc8fdd8b9daae8d5","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"80a2d23602bd08d7","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"e8713f2da85d0fff","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"08fe20173c2a758a","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"105d629b41621e8f","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"c2c8a87c65874f50","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"ecc3d954923aa593","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"313e3d29b4712d5d","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"bf332f1705b05b91","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"c2fac5215807677b","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"b1db7fe55b719fd0","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"c405962725b0a49f","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"f30974f87632ff65","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"c3a0f51c7a475e24","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"470beffefc05bd89","prefixes":{"":{"product":561}}}, // [Moat Inc.] - {"hash":"44c6bfd7fd3ae379","prefixes":{"*":{"product":561}}}, // [Moat Inc.] - {"hash":"ed26e1a4862cb993","prefixes":{"":{"product":563}}}, // [Batch Media Gmbh] - {"hash":"8cc35cd28ab69e7b","prefixes":{"":{"product":563}}}, // [Batch Media Gmbh] - {"hash":"b480ee3cdb39aba3","prefixes":{"":{"product":563}}}, // [Batch Media Gmbh] - {"hash":"42b8cf3c1fba5649","prefixes":{"":{"product":563}}}, // [Batch Media Gmbh] - {"hash":"9c59afa20426083f","prefixes":{"":{"product":564}}}, // [Twenga] - {"hash":"96fa4f0d4282b74b","prefixes":{"":{"product":564}}}, // [Twenga] - {"hash":"147ff4cde8f7b63b","prefixes":{"":{"product":564}}}, // [Twenga] - {"hash":"e6d43f305d0372aa","prefixes":{"":{"product":565}}}, // [TraceAd] - {"hash":"e2a94bb0b8f09309","prefixes":{"":{"product":566}}}, // [Speed Shift Media] - {"hash":"7b17e990632021fb","prefixes":{"":{"product":566}}}, // [Speed Shift Media] - {"hash":"c82cc94c761aff4f","prefixes":{"":{"product":566}}}, // [Speed Shift Media] - {"hash":"9bb0143d6745a1fc","prefixes":{"":{"product":566}}}, // [Speed Shift Media] - {"hash":"9906e8d23a282ab0","prefixes":{"":{"product":566}}}, // [Speed Shift Media] - {"hash":"c29531bb7c2a5a95","prefixes":{"":{"product":566}}}, // [Speed Shift Media] - {"hash":"53972f8a807a3522","prefixes":{"":{"product":566}}}, // [Speed Shift Media] - {"hash":"d8acabec202014c0","prefixes":{"":{"product":566}}}, // [Speed Shift Media] - {"hash":"4062ceb50584895d","prefixes":{"":{"product":566}}}, // [Speed Shift Media] - {"hash":"776d48fd287f99c8","prefixes":{"":{"product":566}}}, // [Speed Shift Media] - {"hash":"caf4c25a1be2f9cc","prefixes":{"":{"product":566}}}, // [Speed Shift Media] - {"hash":"ad66fb580dfc0f61","prefixes":{"*":{"product":567}}}, // [CCB Paris] - {"hash":"2cd1c0997e13f343","prefixes":{"":{"product":568}}}, // [Nielsen Digital Ad Ratings] - {"hash":"cc67f7e32922d026","prefixes":{"*":{"product":569}}}, // [OpenDSP] - {"hash":"37ac881f55f6b624","prefixes":{"":{"product":551}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] - {"hash":"6eaeb2fb0379f719","prefixes":{"":{"product":551}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] - {"hash":"0f37e190c3f7659c","prefixes":{"":{"product":551}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] - {"hash":"cd5e1f475a9a9cb9","prefixes":{"":{"product":551}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] - {"hash":"70dae8af3c6cb2af","prefixes":{"":{"product":551}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] - {"hash":"60e90d920044304d","prefixes":{"":{"product":551}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] - {"hash":"9d34d5e680004543","prefixes":{"":{"product":551}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] - {"hash":"b4b546c24d350673","prefixes":{"":{"product":570}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] - {"hash":"d0b7581f4a3ff9b8","prefixes":{"":{"product":570}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] - {"hash":"0c865d217e1f18f3","prefixes":{"":{"product":570}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] - {"hash":"6333a18d75125edb","prefixes":{"":{"product":570}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] - {"hash":"ed4cdc36d8829848","prefixes":{"":{"product":570}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] - {"hash":"3643c909d7cbe0b8","prefixes":{"":{"product":570}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] - {"hash":"296c21a7001df348","prefixes":{"":{"product":570}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] - {"hash":"97079bad5fb6ead8","prefixes":{"":{"product":570}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] - {"hash":"7b936711dd1e9a43","prefixes":{"":{"product":571}}}, // [Mediarithmics] - {"hash":"c1d09d8bf99adaae","prefixes":{"":{"product":572}}}, // [RUN, INC.] - {"hash":"c1a2559db78be890","prefixes":{"":{"product":572}}}, // [RUN, INC.] - {"hash":"99a2370c6cb03aad","prefixes":{"":{"product":572}}}, // [RUN, INC.] - {"hash":"58188c996594e74c","prefixes":{"":{"product":573}}}, // [Shanghai Menlo Network Technologies Co.,Ltd] - {"hash":"ae01937a71f3c8ec","prefixes":{"":{"product":574}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] - {"hash":"bb20b492d8e895ee","prefixes":{"":{"product":574}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] - {"hash":"a174c7ffc06f1430","prefixes":{"":{"product":574}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] - {"hash":"b04d26682765cf0f","prefixes":{"":{"product":574}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] - {"hash":"3d8976d50a72415a","prefixes":{"":{"product":574}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] - {"hash":"0b937695e283332d","prefixes":{"":{"product":574}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] - {"hash":"5a633d8ed4134176","prefixes":{"":{"product":574}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] - {"hash":"a3d5abb1d31313bb","prefixes":{"":{"product":574}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] - {"hash":"651fcbfafdaa1c3b","prefixes":{"":{"product":574}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] - {"hash":"210045798925d1ec","prefixes":{"":{"product":574}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] - {"hash":"cb9c94ed4430c0d7","prefixes":{"":{"product":574}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] - {"hash":"eb42b6b78e25a31e","prefixes":{"":{"product":574}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] - {"hash":"e21aeaa35d9e4534","prefixes":{"*":{"product":575}}}, // [NET-Metrix-Audit] - {"hash":"d563d7cb84148f5b","prefixes":{"":{"product":576}}}, // [New Allyes Information Technology (Quantone)] - {"hash":"881b6320fa6c5a13","prefixes":{"":{"product":576}}}, // [New Allyes Information Technology (Quantone)] - {"hash":"648b287843959e5a","prefixes":{"":{"product":576}}}, // [New Allyes Information Technology (Quantone)] - {"hash":"aa60743a7bfcd1af","prefixes":{"":{"product":355}}}, // [New Allyes Information Technology (winmax)] - {"hash":"afa7ee2a02f86074","prefixes":{"":{"product":355}}}, // [New Allyes Information Technology (winmax)] - {"hash":"3b21af5a3fa47754","prefixes":{"":{"product":355}}}, // [New Allyes Information Technology (winmax)] - {"hash":"e8f690279ec23223","prefixes":{"":{"product":355}}}, // [New Allyes Information Technology (winmax)] - {"hash":"8763304c40959465","prefixes":{"":{"product":576}}}, // [New Allyes Information Technology (Quantone)] - {"hash":"97be7bbbd0aa71f1","prefixes":{"":{"product":576}}}, // [New Allyes Information Technology (Quantone)] - {"hash":"1610ab8331e9fa67","prefixes":{"":{"product":576}}}, // [New Allyes Information Technology (Quantone)] - {"hash":"5cf6c3a758fb5a50","prefixes":{"":{"product":576}}}, // [New Allyes Information Technology (Quantone)] - {"hash":"753372717104cecb","prefixes":{"":{"product":355}}}, // [New Allyes Information Technology (winmax)] - {"hash":"9868ccc3384ca704","prefixes":{"":{"product":355}}}, // [New Allyes Information Technology (winmax)] - {"hash":"834fc9317bd55432","prefixes":{"":{"product":355}}}, // [New Allyes Information Technology (winmax)] - {"hash":"77a58434eda65f1d","prefixes":{"":{"product":355}}}, // [New Allyes Information Technology (winmax)] - {"hash":"d6c8f549569824c7","prefixes":{"":{"product":355}}}, // [New Allyes Information Technology (winmax)] - {"hash":"605f200bf3a42aec","prefixes":{"":{"product":355}}}, // [New Allyes Information Technology (winmax)] - {"hash":"24475a888daf195d","prefixes":{"":{"product":355}}}, // [New Allyes Information Technology (winmax)] - {"hash":"577626a5c9b3a87c","prefixes":{"":{"product":577}}}, // [Resonate Networks, Inc] - {"hash":"c258f6da0cd8b8cb","prefixes":{"":{"product":577}}}, // [Resonate Networks, Inc] - {"hash":"d9483fc3fe68e764","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"7caa53e1a6ec2bae","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"dcd74656fa3b323d","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"10fa95c5f15310d2","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"6f83daf020ab465f","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"d3d1a09a28024ddc","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"9b208cc58454fb78","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"4645c6078dc34d50","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"b238cbc325c6ef22","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"49deee4d32200263","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"773d9411487a25e3","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"0f6cf491f7eb2baa","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"8dfcd3664fa1302b","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"800bb9e7968e58aa","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"b05b363e5a0511e8","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"20c70723848457f0","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"66114e4ff94b609f","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"f2d188b48acaeb7f","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"409d1c85462adead","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"4d380a7d15d0a78a","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"d5449f5767bfafa7","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"bd39dc0af22a3152","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"f86c1368c7c5eb92","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"e8f74e435e9df1dd","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"9b5fa6e2f606ce7d","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"9a9e03501130b17a","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"2a12549f5c240468","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"215711257cc47c2c","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"77f3f7c79d95de48","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"6d31870e0469ddc6","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"d43e8e7f0b7db722","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"cf4d5bbc8b02dc1c","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"fa69e0b93ab494f2","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"5df810b59c15eb88","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"1bad3858e6b1db68","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"1f0663d5a32c3b7d","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"0accadb2b8868065","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"29fa86d0b3c09f26","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"6c3481a4787dc989","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"dd2cdf0ae459961c","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"b7ddbc93720778f5","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"65db5bf588a1552c","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"d63dadf02badb9bc","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"12a0ac899815d56b","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"4e73ffb09594e8a6","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"7bd28c9beb85782f","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"e5a3c52df181ad93","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"5db249180904a1af","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"f33943be4b14e2cc","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"3304828c6a87914b","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"0dee81e461b3c8bb","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"23282a1244ed862f","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"8b1d859efda195f4","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"e22129fd14c58ef7","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"c11b0627d1105ed8","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] - {"hash":"fee7a2b84c23b6bb","prefixes":{"":{"product":11}}}, // [advanced STORE GmbH] + {"hash":"696757eb9e07845f","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"c84660fcf8a4c99c","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"df10c5e0e18fda2b","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"c71dfe726124b24c","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"f603a3b56996fe4c","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"149593d24f74e3e1","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"a1b9a8ff7b829f8f","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"37cb27fb57319c52","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"16e50e7e7b499ab7","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"c10f5df1adb6160f","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"df3ea734f608dc0d","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"3014b8652e4fd340","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"68034e41a59505be","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"4ff550d2f5a384d7","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"266c6cb54cc8f810","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"c174c4c7c469cbb9","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"19b8f26cb5987d86","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"0301de7ebef3ded7","prefixes":{"":{"product":495,"type":1}}}, // [Miaozhen Systems] + {"hash":"5f6ccacecc90b6ab","prefixes":{"":{"product":495,"type":0}}}, // [Miaozhen Systems] + {"hash":"cee43a3e7001e664","prefixes":{"":{"product":495,"type":0}}}, // [Miaozhen Systems] + {"hash":"27d64efa61e9fb8c","prefixes":{"":{"product":495,"type":0}}}, // [Miaozhen Systems] + {"hash":"05eae7c7a976d6b2","prefixes":{"":{"product":495,"type":0}}}, // [Miaozhen Systems] + {"hash":"da375ad9bc86ad05","prefixes":{"":{"product":495,"type":0}}}, // [Miaozhen Systems] + {"hash":"1a62d22c13d4f003","prefixes":{"":{"product":495,"type":0}}}, // [Miaozhen Systems] + {"hash":"65f8018fc9a58ba7","prefixes":{"":{"product":495,"type":0}}}, // [Miaozhen Systems] + {"hash":"c790c87ca2abbb6c","prefixes":{"":{"product":495,"type":0}}}, // [Miaozhen Systems] + {"hash":"5aefca188560242d","prefixes":{"":{"product":495,"type":0}}}, // [Miaozhen Systems] + {"hash":"eaa7adee1317cb7d","prefixes":{"":{"product":495,"type":0}}}, // [Miaozhen Systems] + {"hash":"db5afb1288bacbff","prefixes":{"*":{"product":496,"type":1}}}, // [Meetrics GmbH] + {"hash":"7d618e8de39f548c","prefixes":{"*":{"product":496,"type":1}}}, // [Meetrics GmbH] + {"hash":"b5c30978f10b1f56","prefixes":{"s":{"product":496,"type":1},"":{"product":497,"type":0}}}, // [Meetrics GmbH] [Meetrics] + {"hash":"5c4a10a5bc0897c7","prefixes":{"":{"product":498,"type":1}}}, // [Digital Control GmbH & Co. KG] + {"hash":"38d57267aeada6cc","prefixes":{"":{"product":498,"type":1}}}, // [Digital Control GmbH & Co. KG] + {"hash":"7dc82de98d234295","prefixes":{"":{"product":499,"type":1}}}, // [Dedicated Media] + {"hash":"98cac3ed2db221c5","prefixes":{"":{"product":499,"type":1}}}, // [Dedicated Media] + {"hash":"74da617dd78c4c25","prefixes":{"":{"product":499,"type":1}}}, // [Dedicated Media] + {"hash":"ad829d4fccaec076","prefixes":{"":{"product":499,"type":1}}}, // [Dedicated Media] + {"hash":"93214296470961ea","prefixes":{"":{"product":500,"type":1}}}, // [Accuen] + {"hash":"fb8e16c2a3413e04","prefixes":{"*":{"product":501,"type":0}}}, // [Pulse 360, Inc.] + {"hash":"56de3497c2b187f9","prefixes":{"*":{"product":501,"type":0}}}, // [Pulse 360, Inc.] + {"hash":"1763cb8cd4ecb455","prefixes":{"*":{"product":502,"type":0}}}, // [ZANOX AG] + {"hash":"dd420134fd0b31f7","prefixes":{"*":{"product":502,"type":0}}}, // [ZANOX AG] + {"hash":"f942b375b4c9d301","prefixes":{"":{"product":503,"type":0}}}, // [Webgains Ltd] + {"hash":"03b41741559a5775","prefixes":{"":{"product":504,"type":0}}}, // [Virgin Media Limited] + {"hash":"e01702c3ace07a42","prefixes":{"*":{"product":505,"type":0}}}, // [MyBuys MyAds] + {"hash":"a09aa03b7ab4a6a0","prefixes":{"*":{"product":506,"type":0}}}, // [VCCP Search LTD] + {"hash":"8ae53030752d70fd","prefixes":{"":{"product":507,"type":0}}}, // [Conversant Media] + {"hash":"3f911ef887ffe5a7","prefixes":{"":{"product":507,"type":0}}}, // [Conversant Media] + {"hash":"dd0195d7ab665db3","prefixes":{"":{"product":507,"type":0}}}, // [Conversant Media] + {"hash":"6ac275e8e99e5fb3","prefixes":{"":{"product":507,"type":0}}}, // [Conversant Media] + {"hash":"5960f055d64bd6fb","prefixes":{"":{"product":507,"type":0}}}, // [Conversant Media] + {"hash":"d07a0c93a2f5da33","prefixes":{"":{"product":507,"type":0}}}, // [Conversant Media] + {"hash":"b7e7f7ab4a600ced","prefixes":{"":{"product":508,"type":0}}}, // [Up-Value GmbH & Co. KG] + {"hash":"e92a06c68de2a79d","prefixes":{"":{"product":509,"type":0}}}, // [Unruly Media] + {"hash":"789659215cb1620d","prefixes":{"":{"product":509,"type":0}}}, // [Unruly Media] + {"hash":"b61a48cd46cb7b06","prefixes":{"*":{"product":510,"type":0}}}, // [Underdog Media LLC] + {"hash":"eea5fa46bce35e24","prefixes":{"":{"product":511,"type":0}}}, // [SVG Media Pvt. Ltd.] + {"hash":"9b346c0d77f1fcf2","prefixes":{"*":{"product":512,"type":0}}}, // [TRAFFIQ LLC] + {"hash":"51324f52aa5eb734","prefixes":{"*":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"26e3ca8cc9a6afd8","prefixes":{"":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"2e9a57a3dcc61e3e","prefixes":{"":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"2e6202e113ae62e3","prefixes":{"":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"9a1d6d8445e2cce9","prefixes":{"":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"88015c5982735097","prefixes":{"":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"9cf10e72a2db48a9","prefixes":{"":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"cf5ba41c477d8aa5","prefixes":{"":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"fe50c8a7f665cf78","prefixes":{"":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"5c9fb160269ccb5c","prefixes":{"":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"366f4f435bfb9255","prefixes":{"":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"5dde0b5371aae6bb","prefixes":{"":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"ebd682e181b553a7","prefixes":{"":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"df61db1cec60b5a1","prefixes":{"":{"product":513,"type":0}}}, // [TellApart Inc.] + {"hash":"bdf8043c482f8afd","prefixes":{"*":{"product":514,"type":0}}}, // [Shopzilla Inc.] + {"hash":"83ce758172dc68fb","prefixes":{"*":{"product":514,"type":0}}}, // [Shopzilla Inc.] + {"hash":"45cc9e8ea0e405cc","prefixes":{"*":{"product":514,"type":0}}}, // [Shopzilla Inc.] + {"hash":"bc8d543772676fe4","prefixes":{"*":{"product":514,"type":0}}}, // [Shopzilla Inc.] + {"hash":"6a51a8a28265901e","prefixes":{"*":{"product":515,"type":0}}}, // [Reactivpub] + {"hash":"b03903f1abac9b82","prefixes":{"*":{"product":515,"type":0}}}, // [Reactivpub] + {"hash":"14281bd870fa9e85","prefixes":{"*":{"product":515,"type":0}}}, // [Reactivpub] + {"hash":"52c9dfb471edf4de","prefixes":{"*":{"product":515,"type":0}}}, // [Reactivpub] + {"hash":"b9cf807aee694b90","prefixes":{"*":{"product":516,"type":0}}}, // [Netseer Inc.] + {"hash":"720c7cdaeb3d3edf","prefixes":{"":{"product":516,"type":0}}}, // [Netseer Inc.] + {"hash":"a7e82477ddc48f23","prefixes":{"*":{"product":517,"type":0}}}, // [eBay Enterprise] + {"hash":"c35bcff10cd62a44","prefixes":{"":{"product":518,"type":0}}}, // [Goodway Group] + {"hash":"a45b6c7292b7b560","prefixes":{"":{"product":518,"type":0}}}, // [Goodway Group] + {"hash":"d76efc82324fb8d5","prefixes":{"":{"product":518,"type":0}}}, // [Goodway Group] + {"hash":"5eb742c77c59dd05","prefixes":{"":{"product":518,"type":0}}}, // [Goodway Group] + {"hash":"33f9a4e4a440eeda","prefixes":{"*":{"product":519,"type":0}}}, // [Double Positive Marketing Group Inc.] + {"hash":"285da2e20d7ae651","prefixes":{"*":{"product":520,"type":0}}}, // [Chitika Inc.] + {"hash":"9ac26bc76037dd72","prefixes":{"*":{"product":521,"type":0}}}, // [Scigineer Inc.] + {"hash":"11971f02aee2996f","prefixes":{"*":{"product":522,"type":0}}}, // [Sales Spider Inc.] + {"hash":"0dfb620c1f99f67a","prefixes":{"*":{"product":522,"type":0}}}, // [Sales Spider Inc.] + {"hash":"dee182aa38b90802","prefixes":{"":{"product":523,"type":0}}}, // [Rocket Fuel Inc.] + {"hash":"ee4bb512aa7bff3f","prefixes":{"":{"product":523,"type":0}}}, // [Rocket Fuel Inc.] + {"hash":"051b6a2f5170871a","prefixes":{"":{"product":523,"type":0}}}, // [Rocket Fuel Inc.] + {"hash":"ef2266eab416e344","prefixes":{"":{"product":523,"type":0}}}, // [Rocket Fuel Inc.] + {"hash":"40701593c87a2a6d","prefixes":{"":{"product":523,"type":0}}}, // [Rocket Fuel Inc.] + {"hash":"4dfd82e7fcbfe056","prefixes":{"":{"product":523,"type":0}}}, // [Rocket Fuel Inc.] + {"hash":"2848c783f1d69118","prefixes":{"":{"product":523,"type":0}}}, // [Rocket Fuel Inc.] + {"hash":"26fd0c0c1bbdf578","prefixes":{"":{"product":523,"type":0}}}, // [Rocket Fuel Inc.] + {"hash":"9362d437c6649ac0","prefixes":{"":{"product":524,"type":0}}}, // [RTBlab] + {"hash":"83cd554cdc78cc1c","prefixes":{"":{"product":524,"type":0}}}, // [RTBlab] + {"hash":"e4e3ec12949d311d","prefixes":{"":{"product":524,"type":0}}}, // [RTBlab] + {"hash":"9db675ca1ddbc25e","prefixes":{"":{"product":524,"type":0}}}, // [RTBlab] + {"hash":"c407f5eb4837736a","prefixes":{"":{"product":524,"type":0}}}, // [RTBlab] + {"hash":"27e52d41a00bf2fd","prefixes":{"":{"product":524,"type":0}}}, // [RTBlab] + {"hash":"efa545dd9d577a82","prefixes":{"":{"product":525,"type":0}}}, // [abilicom GmbH] + {"hash":"f690d50313c4d883","prefixes":{"":{"product":525,"type":0}}}, // [abilicom GmbH] + {"hash":"e59063ed858c1ac6","prefixes":{"":{"product":525,"type":0}}}, // [abilicom GmbH] + {"hash":"08ecd0f7d816b029","prefixes":{"":{"product":30,"type":0}}}, // [Rakuten Display] + {"hash":"6321d1d2e3ff13cf","prefixes":{"":{"product":526,"type":0}}}, // [Pulpo Media Inc] + {"hash":"68778ff49de5f6b7","prefixes":{"":{"product":526,"type":0}}}, // [Pulpo Media Inc] + {"hash":"4fe62a295bf7110a","prefixes":{"*":{"product":527,"type":0}}}, // [OneSpot] + {"hash":"0a03e9309eac6fef","prefixes":{"*":{"product":528,"type":0}}}, // [MyThings UK Ltd] + {"hash":"aefee6cf21fb21d0","prefixes":{"*":{"product":528,"type":0}}}, // [MyThings UK Ltd] + {"hash":"013cf49561a61d0a","prefixes":{"":{"product":529,"type":0}}}, // [Exactag] + {"hash":"a5db93b0474bf88a","prefixes":{"":{"product":529,"type":0}}}, // [Exactag] + {"hash":"8eaf146d58acaea3","prefixes":{"":{"product":353,"type":1}}}, // [AdMaster] + {"hash":"62f9a92e2fa55157","prefixes":{"":{"product":353,"type":1}}}, // [AdMaster] + {"hash":"2246fe417fb594d4","prefixes":{"":{"product":353,"type":1}}}, // [AdMaster] + {"hash":"46be6b3d05c938b5","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"b588a450d30940dc","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"9013d3536e80f01a","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"705829297e5108ae","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"bfd58f70292d02ab","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"ff5875b2546d8499","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"ccc16a9e8656612f","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"a764b52c155c440b","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"a8a184b600fd3af1","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"6c106d279e66ed61","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"7c8663ad744aeec9","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"c3860e5673290a36","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"485e37ef683e6da8","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"03c59eef464ffa9d","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"e8d28d6ae9ed1064","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"1fc896b89972c4a3","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"89d45cf6716d92c4","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"c374b8ef2cc0a6d3","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"e0a60df6ec972762","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"dfd819866072d81c","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"dbaab38c6254fc44","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"25e404b1d7cfa7b3","prefixes":{"":{"product":530,"type":0}}}, // [Kyocera Communication Systems Co. Ltd.] + {"hash":"f9b4a878a9f66629","prefixes":{"":{"product":531,"type":0}}}, // [Beijing LangTaoJin Interactive] + {"hash":"5be19b5ec9da0217","prefixes":{"":{"product":531,"type":0}}}, // [Beijing LangTaoJin Interactive] + {"hash":"c3dd7532c047b725","prefixes":{"":{"product":532,"type":0}}}, // [Conversant Mobile Media] + {"hash":"fd89a621a7abcb21","prefixes":{"":{"product":532,"type":0}}}, // [Conversant Mobile Media] + {"hash":"8b03c1ce3a37af3e","prefixes":{"":{"product":533,"type":0}}}, // [MM1X.nl] + {"hash":"51f16f2963b5ab62","prefixes":{"":{"product":533,"type":0}}}, // [MM1X.nl] + {"hash":"a34aa5b1e90b35d0","prefixes":{"":{"product":534,"type":0}}}, // [Trivu Media Inc.] + {"hash":"f5fe0a711d905029","prefixes":{"":{"product":534,"type":0}}}, // [Trivu Media Inc.] + {"hash":"284614e662fae11d","prefixes":{"*":{"product":535,"type":0}}}, // [BlueCava Inc.] + {"hash":"cd9e8f6b8e3bb0bb","prefixes":{"":{"product":536,"type":1}}}, // [Beijing Gridsum Technology Co. Ltd.] + {"hash":"97de03485c681efe","prefixes":{"":{"product":536,"type":1}}}, // [Beijing Gridsum Technology Co. Ltd.] + {"hash":"6c624568b77c2f15","prefixes":{"":{"product":536,"type":1}}}, // [Beijing Gridsum Technology Co. Ltd.] + {"hash":"2b74e65baabdf4a8","prefixes":{"":{"product":537,"type":0}}}, // [Adsvana DSP] + {"hash":"fcd2a83347336f39","prefixes":{"":{"product":537,"type":0}}}, // [Adsvana DSP] + {"hash":"7cadddba30cbf68b","prefixes":{"":{"product":367,"type":0}}}, // [revenue cloud] + {"hash":"39fe4b58f8d0c85a","prefixes":{"":{"product":538,"type":0}}}, // [Target Performance] + {"hash":"219259d49fac1ccb","prefixes":{"":{"product":539,"type":1}}}, // [Content Spread] + {"hash":"ca8d76b63fdfd7e7","prefixes":{"":{"product":367,"type":0}}}, // [revenue cloud] + {"hash":"ed86b10928624d27","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"205f80e614b45d0c","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"88c9d142721a0010","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"c918497df4612dee","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"ecc68ce18bc92eac","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"acd6e7d757515791","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"611fb7a1125a9f9d","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"b47f7e78adfcce8c","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"e7d6867de133fef3","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"022353c9ab0821d7","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"2571a0502f188936","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"f1efca13f787818a","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"1c982ec87cdd98c7","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"ffa62eae8604dfb9","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"8c7ba8485b195fda","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"188fb424b02d01b3","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"92807e8eb5ceed53","prefixes":{"":{"product":540,"type":0}}}, // [Datamind Effective Media] + {"hash":"b01a0f9c920b194e","prefixes":{"":{"product":541,"type":0}}}, // [ScaleOut Inc.] + {"hash":"da51b7d5383143f5","prefixes":{"":{"product":541,"type":0}}}, // [ScaleOut Inc.] + {"hash":"acca27df7ac50ef3","prefixes":{"":{"product":541,"type":0}}}, // [ScaleOut Inc.] + {"hash":"8a45863cac015863","prefixes":{"":{"product":541,"type":0}}}, // [ScaleOut Inc.] + {"hash":"ae50046a864ceafd","prefixes":{"":{"product":541,"type":0}}}, // [ScaleOut Inc.] + {"hash":"de57dfdaf9a2c48a","prefixes":{"":{"product":542,"type":1}}}, // [Ensighten] + {"hash":"b1235d3bdac69ad1","prefixes":{"":{"product":542,"type":1}}}, // [Ensighten] + {"hash":"b2717d6d54a069e3","prefixes":{"":{"product":542,"type":1}}}, // [Ensighten] + {"hash":"d7152b8a7fbdcfd9","prefixes":{"":{"product":542,"type":1}}}, // [Ensighten] + {"hash":"66d946b524ae15cb","prefixes":{"":{"product":542,"type":1}}}, // [Ensighten] + {"hash":"cb87adb62a805e43","prefixes":{"":{"product":542,"type":1}}}, // [Ensighten] + {"hash":"64b417a15cd2caba","prefixes":{"":{"product":542,"type":1}}}, // [Ensighten] + {"hash":"fe5fbbb5f87923ec","prefixes":{"":{"product":542,"type":1}}}, // [Ensighten] + {"hash":"7955dee10fac2b43","prefixes":{"":{"product":543,"type":1}}}, // [Sony Electronics Inc.] + {"hash":"18b842a485714b88","prefixes":{"":{"product":543,"type":1}}}, // [Sony Electronics Inc.] + {"hash":"5e881c11a6141a0e","prefixes":{"*":{"product":544,"type":0}}}, // [Gravity Research and Development LTD] + {"hash":"eb0586aa7b44d1a7","prefixes":{"":{"product":545,"type":1}}}, // [Project SunBlock] + {"hash":"e49a615e7e072e05","prefixes":{"":{"product":546,"type":0}}}, // [Novem sp. z o.o.] + {"hash":"c36795d664275022","prefixes":{"*":{"product":547,"type":1}}}, // [Econda GmbH] + {"hash":"1dafa12902626628","prefixes":{"":{"product":548,"type":0}}}, // [AdMaxim LLC] + {"hash":"ddc49ed0d5adc099","prefixes":{"":{"product":548,"type":0}}}, // [AdMaxim LLC] + {"hash":"43e36030afe70656","prefixes":{"":{"product":548,"type":0}}}, // [AdMaxim LLC] + {"hash":"f4acd265af4a8b2c","prefixes":{"":{"product":548,"type":0}}}, // [AdMaxim LLC] + {"hash":"2d00af9d31137b46","prefixes":{"":{"product":548,"type":0}}}, // [AdMaxim LLC] + {"hash":"6330d2d69fac5592","prefixes":{"":{"product":548,"type":0}}}, // [AdMaxim LLC] + {"hash":"07924db4fbf62ed8","prefixes":{"":{"product":548,"type":0}}}, // [AdMaxim LLC] + {"hash":"40fa76b0dfe6cba9","prefixes":{"":{"product":548,"type":0}}}, // [AdMaxim LLC] + {"hash":"cb5e5323270dac31","prefixes":{"":{"product":548,"type":0}}}, // [AdMaxim LLC] + {"hash":"644395b50223d6f0","prefixes":{"":{"product":78,"type":0}}}, // [Adnologies GmbH] + {"hash":"e816f89057c8ad52","prefixes":{"":{"product":78,"type":0}}}, // [Adnologies GmbH] + {"hash":"8d2b1cab5958796f","prefixes":{"":{"product":549,"type":0}}}, // [Alliance Health Networks] + {"hash":"3568ed34edbd0a3b","prefixes":{"":{"product":550,"type":0}}}, // [Adsame Advertising Co., Ltd] + {"hash":"5fd75bdc8d48469a","prefixes":{"":{"product":550,"type":0}}}, // [Adsame Advertising Co., Ltd] + {"hash":"f24f098ee46d7e52","prefixes":{"":{"product":550,"type":0}}}, // [Adsame Advertising Co., Ltd] + {"hash":"695c924af8b7be90","prefixes":{"":{"product":551,"type":0}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] + {"hash":"8c21b1544107f44b","prefixes":{"":{"product":552,"type":0}}}, // [PK Online Ventures Limited] + {"hash":"b709e5fa7a0a3284","prefixes":{"":{"product":553,"type":0}}}, // [Bigpoint Gmbh] + {"hash":"54393b0479bf4296","prefixes":{"":{"product":553,"type":0}}}, // [Bigpoint Gmbh] + {"hash":"0228e75fa4f7ba29","prefixes":{"":{"product":553,"type":0}}}, // [Bigpoint Gmbh] + {"hash":"161b02c3430e8493","prefixes":{"":{"product":554,"type":0}}}, // [Mirapodo GmbH] + {"hash":"cbfa294f671394f5","prefixes":{"":{"product":555,"type":0}}}, // [Digitize New Media Ltd.] + {"hash":"126e76895e35030f","prefixes":{"":{"product":556,"type":0}}}, // [AdSage] + {"hash":"d1a3397960a0c962","prefixes":{"":{"product":556,"type":0}}}, // [AdSage] + {"hash":"27111f31c7f7870c","prefixes":{"":{"product":556,"type":0}}}, // [AdSage] + {"hash":"5066a54cd7ed6242","prefixes":{"":{"product":556,"type":0}}}, // [AdSage] + {"hash":"5447e7edfecbefc9","prefixes":{"":{"product":556,"type":0}}}, // [AdSage] + {"hash":"763e1c5a534cdce1","prefixes":{"":{"product":556,"type":0}}}, // [AdSage] + {"hash":"664f6761d6e1bdc5","prefixes":{"":{"product":556,"type":0}}}, // [AdSage] + {"hash":"85dc2dbb9cf8ba01","prefixes":{"":{"product":556,"type":0}}}, // [AdSage] + {"hash":"efd9939ccbcea7ca","prefixes":{"":{"product":556,"type":0}}}, // [AdSage] + {"hash":"5095b815554d166d","prefixes":{"":{"product":556,"type":0}}}, // [AdSage] + {"hash":"bbd5220662a5b37e","prefixes":{"":{"product":556,"type":0}}}, // [AdSage] + {"hash":"ad929f7cd3353264","prefixes":{"":{"product":556,"type":0}}}, // [AdSage] + {"hash":"aebf7b2a7ee1ff12","prefixes":{"":{"product":557,"type":0}}}, // [Fingereach] + {"hash":"01ef28aab34283cc","prefixes":{"":{"product":557,"type":0}}}, // [Fingereach] + {"hash":"c075f26f4aa57d43","prefixes":{"":{"product":557,"type":0}}}, // [Fingereach] + {"hash":"f651f54211351ca7","prefixes":{"":{"product":557,"type":0}}}, // [Fingereach] + {"hash":"98e7e8f01b1e7221","prefixes":{"":{"product":557,"type":0}}}, // [Fingereach] + {"hash":"7f46832cdf7b45db","prefixes":{"":{"product":557,"type":0}}}, // [Fingereach] + {"hash":"4a37345bf96b65b5","prefixes":{"":{"product":557,"type":0}}}, // [Fingereach] + {"hash":"ee9f377ce8711040","prefixes":{"":{"product":557,"type":0}}}, // [Fingereach] + {"hash":"f6f6db9a07009087","prefixes":{"":{"product":557,"type":0}}}, // [Fingereach] + {"hash":"37414a33ff3de4a0","prefixes":{"":{"product":557,"type":0}}}, // [Fingereach] + {"hash":"7cc06f83f0710408","prefixes":{"":{"product":557,"type":0}}}, // [Fingereach] + {"hash":"beb1894d6a5dd8d5","prefixes":{"":{"product":557,"type":0}}}, // [Fingereach] + {"hash":"ab305fad96c94e68","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"abb33b12777d693c","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"cf57baa1fe60d65d","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"1e230cd699b878e6","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"0e9f493079696ce3","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"7d3350cd22011e53","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"f50b2ec037f5428b","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"c171c26c4996ef48","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"558975de73dc2727","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"ee6b8472f5558865","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"8183f3c56cedc5d3","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"9e46a78131a70a25","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"9805160753b78db8","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"9665241d465c8ced","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"0886098ece10411f","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"1b9aa72e21da1cf9","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"75eaf92a0259fced","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"6647ef959a9060b1","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"55bbd43420c048ba","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"769a3492166f2234","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"88bf787fe78aa617","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"62db61a5802ee5f9","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"ecc8b48b5b165bff","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"3b713a488717f579","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"7d501d2362243528","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"1e2c100fab457dce","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"7adb32ad76289644","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"3f4747021104b435","prefixes":{"":{"product":307,"type":1}}}, // [DMA Institute dba Hottraffic] + {"hash":"55ade41cc24f1b54","prefixes":{"":{"product":558,"type":0}}}, // [Calvin Klein] + {"hash":"210f025e6c6b8122","prefixes":{"":{"product":559,"type":0}}}, // [Medialets Servo] + {"hash":"233555f3daf9abb0","prefixes":{"":{"product":559,"type":0}}}, // [Medialets Servo] + {"hash":"eea93545b322651b","prefixes":{"":{"product":559,"type":0}}}, // [Medialets Servo] + {"hash":"d9fe49eeaf35eb01","prefixes":{"":{"product":559,"type":0}}}, // [Medialets Servo] + {"hash":"ea41698b95338591","prefixes":{"s-cdn-":{"product":559,"type":0}}}, // [Medialets Servo] + {"hash":"5f4e90726b181c95","prefixes":{"":{"product":560,"type":0}}}, // [Webmoblink Inc.] + {"hash":"9d51efd26ab44317","prefixes":{"":{"product":31,"type":0}}}, // [Retailigence] + {"hash":"32440ed26b61d14a","prefixes":{"":{"product":31,"type":0}}}, // [Retailigence] + {"hash":"8234d0306d8984eb","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"e35bf94930bc4d1a","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"aec3f56c7f99151f","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"ef395b96d922c238","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"5a053ab1bcfcfb41","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"2cf811bb8aa279b5","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"cd383e750e6cfcdb","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"c30fc77cd822188e","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"fb9678eef7ea227d","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"102facb286a88bbe","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"aa39a58ff4ed2114","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"e33908ca9604cfa4","prefixes":{"*":{"product":561,"type":1},"":{"product":562,"type":0}}}, // [Moat Inc.] [Bannerflow AB] + {"hash":"31902ac0cc3e362b","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"796535f10f1e1ea0","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"681a390e8faf08c1","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"1ef04ebc565a6f48","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"1461b89b1a4a5e39","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"a7c34fe979c7afe2","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"30142bb0f24faa5a","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"dc8fdd8b9daae8d5","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"80a2d23602bd08d7","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"e8713f2da85d0fff","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"08fe20173c2a758a","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"105d629b41621e8f","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"c2c8a87c65874f50","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"ecc3d954923aa593","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"313e3d29b4712d5d","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"bf332f1705b05b91","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"c2fac5215807677b","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"b1db7fe55b719fd0","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"c405962725b0a49f","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"f30974f87632ff65","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"c3a0f51c7a475e24","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"470beffefc05bd89","prefixes":{"":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"44c6bfd7fd3ae379","prefixes":{"*":{"product":561,"type":1}}}, // [Moat Inc.] + {"hash":"ed26e1a4862cb993","prefixes":{"":{"product":563,"type":1}}}, // [Batch Media Gmbh] + {"hash":"8cc35cd28ab69e7b","prefixes":{"":{"product":563,"type":1}}}, // [Batch Media Gmbh] + {"hash":"b480ee3cdb39aba3","prefixes":{"":{"product":563,"type":1}}}, // [Batch Media Gmbh] + {"hash":"42b8cf3c1fba5649","prefixes":{"":{"product":563,"type":1}}}, // [Batch Media Gmbh] + {"hash":"9c59afa20426083f","prefixes":{"":{"product":564,"type":0}}}, // [Twenga] + {"hash":"96fa4f0d4282b74b","prefixes":{"":{"product":564,"type":0}}}, // [Twenga] + {"hash":"147ff4cde8f7b63b","prefixes":{"":{"product":564,"type":0}}}, // [Twenga] + {"hash":"e6d43f305d0372aa","prefixes":{"":{"product":565,"type":0}}}, // [TraceAd] + {"hash":"e2a94bb0b8f09309","prefixes":{"":{"product":566,"type":0}}}, // [Speed Shift Media] + {"hash":"7b17e990632021fb","prefixes":{"":{"product":566,"type":0}}}, // [Speed Shift Media] + {"hash":"c82cc94c761aff4f","prefixes":{"":{"product":566,"type":0}}}, // [Speed Shift Media] + {"hash":"9bb0143d6745a1fc","prefixes":{"":{"product":566,"type":0}}}, // [Speed Shift Media] + {"hash":"9906e8d23a282ab0","prefixes":{"":{"product":566,"type":0}}}, // [Speed Shift Media] + {"hash":"c29531bb7c2a5a95","prefixes":{"":{"product":566,"type":0}}}, // [Speed Shift Media] + {"hash":"53972f8a807a3522","prefixes":{"":{"product":566,"type":0}}}, // [Speed Shift Media] + {"hash":"d8acabec202014c0","prefixes":{"":{"product":566,"type":0}}}, // [Speed Shift Media] + {"hash":"4062ceb50584895d","prefixes":{"":{"product":566,"type":0}}}, // [Speed Shift Media] + {"hash":"776d48fd287f99c8","prefixes":{"":{"product":566,"type":0}}}, // [Speed Shift Media] + {"hash":"caf4c25a1be2f9cc","prefixes":{"":{"product":566,"type":0}}}, // [Speed Shift Media] + {"hash":"ad66fb580dfc0f61","prefixes":{"*":{"product":567,"type":0}}}, // [CCB Paris] + {"hash":"2cd1c0997e13f343","prefixes":{"":{"product":568,"type":1}}}, // [Nielsen Digital Ad Ratings] + {"hash":"cc67f7e32922d026","prefixes":{"*":{"product":569,"type":0}}}, // [OpenDSP] + {"hash":"37ac881f55f6b624","prefixes":{"":{"product":551,"type":0}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] + {"hash":"6eaeb2fb0379f719","prefixes":{"":{"product":551,"type":0}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] + {"hash":"0f37e190c3f7659c","prefixes":{"":{"product":551,"type":0}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] + {"hash":"cd5e1f475a9a9cb9","prefixes":{"":{"product":551,"type":0}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] + {"hash":"70dae8af3c6cb2af","prefixes":{"":{"product":551,"type":0}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] + {"hash":"60e90d920044304d","prefixes":{"":{"product":551,"type":0}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] + {"hash":"9d34d5e680004543","prefixes":{"":{"product":551,"type":0}}}, // [Guangzhou Shunfei Infomation Technology Corporatio] + {"hash":"b4b546c24d350673","prefixes":{"":{"product":570,"type":0}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] + {"hash":"d0b7581f4a3ff9b8","prefixes":{"":{"product":570,"type":0}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] + {"hash":"0c865d217e1f18f3","prefixes":{"":{"product":570,"type":0}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] + {"hash":"6333a18d75125edb","prefixes":{"":{"product":570,"type":0}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] + {"hash":"ed4cdc36d8829848","prefixes":{"":{"product":570,"type":0}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] + {"hash":"3643c909d7cbe0b8","prefixes":{"":{"product":570,"type":0}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] + {"hash":"296c21a7001df348","prefixes":{"":{"product":570,"type":0}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] + {"hash":"97079bad5fb6ead8","prefixes":{"":{"product":570,"type":0}}}, // [Beijing NetEase YouDao Computer System Co., Ltd.] + {"hash":"7b936711dd1e9a43","prefixes":{"":{"product":571,"type":0}}}, // [Mediarithmics] + {"hash":"c1d09d8bf99adaae","prefixes":{"":{"product":572,"type":0}}}, // [RUN, INC.] + {"hash":"c1a2559db78be890","prefixes":{"":{"product":572,"type":0}}}, // [RUN, INC.] + {"hash":"99a2370c6cb03aad","prefixes":{"":{"product":572,"type":0}}}, // [RUN, INC.] + {"hash":"58188c996594e74c","prefixes":{"":{"product":573,"type":0}}}, // [Shanghai Menlo Network Technologies Co.,Ltd] + {"hash":"ae01937a71f3c8ec","prefixes":{"":{"product":574,"type":0}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] + {"hash":"bb20b492d8e895ee","prefixes":{"":{"product":574,"type":0}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] + {"hash":"a174c7ffc06f1430","prefixes":{"":{"product":574,"type":0}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] + {"hash":"b04d26682765cf0f","prefixes":{"":{"product":574,"type":0}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] + {"hash":"3d8976d50a72415a","prefixes":{"":{"product":574,"type":0}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] + {"hash":"0b937695e283332d","prefixes":{"":{"product":574,"type":0}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] + {"hash":"5a633d8ed4134176","prefixes":{"":{"product":574,"type":0}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] + {"hash":"a3d5abb1d31313bb","prefixes":{"":{"product":574,"type":0}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] + {"hash":"651fcbfafdaa1c3b","prefixes":{"":{"product":574,"type":0}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] + {"hash":"210045798925d1ec","prefixes":{"":{"product":574,"type":0}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] + {"hash":"cb9c94ed4430c0d7","prefixes":{"":{"product":574,"type":0}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] + {"hash":"eb42b6b78e25a31e","prefixes":{"":{"product":574,"type":0}}}, // [Beijing Oasis Technology Co. Ltd (Mjoys)] + {"hash":"e21aeaa35d9e4534","prefixes":{"*":{"product":575,"type":1}}}, // [NET-Metrix-Audit] + {"hash":"d563d7cb84148f5b","prefixes":{"":{"product":576,"type":0}}}, // [New Allyes Information Technology (Quantone)] + {"hash":"881b6320fa6c5a13","prefixes":{"":{"product":576,"type":0}}}, // [New Allyes Information Technology (Quantone)] + {"hash":"648b287843959e5a","prefixes":{"":{"product":576,"type":0}}}, // [New Allyes Information Technology (Quantone)] + {"hash":"aa60743a7bfcd1af","prefixes":{"":{"product":355,"type":0}}}, // [New Allyes Information Technology (winmax)] + {"hash":"afa7ee2a02f86074","prefixes":{"":{"product":355,"type":0}}}, // [New Allyes Information Technology (winmax)] + {"hash":"3b21af5a3fa47754","prefixes":{"":{"product":355,"type":0}}}, // [New Allyes Information Technology (winmax)] + {"hash":"e8f690279ec23223","prefixes":{"":{"product":355,"type":0}}}, // [New Allyes Information Technology (winmax)] + {"hash":"8763304c40959465","prefixes":{"":{"product":576,"type":0}}}, // [New Allyes Information Technology (Quantone)] + {"hash":"97be7bbbd0aa71f1","prefixes":{"":{"product":576,"type":0}}}, // [New Allyes Information Technology (Quantone)] + {"hash":"1610ab8331e9fa67","prefixes":{"":{"product":576,"type":0}}}, // [New Allyes Information Technology (Quantone)] + {"hash":"5cf6c3a758fb5a50","prefixes":{"":{"product":576,"type":0}}}, // [New Allyes Information Technology (Quantone)] + {"hash":"753372717104cecb","prefixes":{"":{"product":355,"type":0}}}, // [New Allyes Information Technology (winmax)] + {"hash":"9868ccc3384ca704","prefixes":{"":{"product":355,"type":0}}}, // [New Allyes Information Technology (winmax)] + {"hash":"834fc9317bd55432","prefixes":{"":{"product":355,"type":0}}}, // [New Allyes Information Technology (winmax)] + {"hash":"77a58434eda65f1d","prefixes":{"":{"product":355,"type":0}}}, // [New Allyes Information Technology (winmax)] + {"hash":"d6c8f549569824c7","prefixes":{"":{"product":355,"type":0}}}, // [New Allyes Information Technology (winmax)] + {"hash":"605f200bf3a42aec","prefixes":{"":{"product":355,"type":0}}}, // [New Allyes Information Technology (winmax)] + {"hash":"24475a888daf195d","prefixes":{"":{"product":355,"type":0}}}, // [New Allyes Information Technology (winmax)] + {"hash":"577626a5c9b3a87c","prefixes":{"":{"product":577,"type":1}}}, // [Resonate Networks, Inc] + {"hash":"c258f6da0cd8b8cb","prefixes":{"":{"product":577,"type":1}}}, // [Resonate Networks, Inc] + {"hash":"d9483fc3fe68e764","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"7caa53e1a6ec2bae","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"dcd74656fa3b323d","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"10fa95c5f15310d2","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"6f83daf020ab465f","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"d3d1a09a28024ddc","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"9b208cc58454fb78","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"4645c6078dc34d50","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"b238cbc325c6ef22","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"49deee4d32200263","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"773d9411487a25e3","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"0f6cf491f7eb2baa","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"8dfcd3664fa1302b","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"800bb9e7968e58aa","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"b05b363e5a0511e8","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"20c70723848457f0","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"66114e4ff94b609f","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"f2d188b48acaeb7f","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"409d1c85462adead","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"4d380a7d15d0a78a","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"d5449f5767bfafa7","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"bd39dc0af22a3152","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"f86c1368c7c5eb92","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"e8f74e435e9df1dd","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"9b5fa6e2f606ce7d","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"9a9e03501130b17a","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"2a12549f5c240468","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"215711257cc47c2c","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"77f3f7c79d95de48","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"6d31870e0469ddc6","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"d43e8e7f0b7db722","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"cf4d5bbc8b02dc1c","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"fa69e0b93ab494f2","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"5df810b59c15eb88","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"1bad3858e6b1db68","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"1f0663d5a32c3b7d","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"0accadb2b8868065","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"29fa86d0b3c09f26","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"6c3481a4787dc989","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"dd2cdf0ae459961c","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"b7ddbc93720778f5","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"65db5bf588a1552c","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"d63dadf02badb9bc","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"12a0ac899815d56b","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"4e73ffb09594e8a6","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"7bd28c9beb85782f","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"e5a3c52df181ad93","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"5db249180904a1af","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"f33943be4b14e2cc","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"3304828c6a87914b","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"0dee81e461b3c8bb","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"23282a1244ed862f","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"8b1d859efda195f4","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"e22129fd14c58ef7","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"c11b0627d1105ed8","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] + {"hash":"fee7a2b84c23b6bb","prefixes":{"":{"product":11,"type":0}}}, // [advanced STORE GmbH] {"hash":"3f3d4a96d97bc12a","prefixes":{"":{"product":578}}}, // [Triple Lift, Inc.] {"hash":"7e4d08be26af0913","prefixes":{"":{"product":578}}}, // [Triple Lift, Inc.] {"hash":"ab1718aa8ada6ceb","prefixes":{"":{"product":578}}}, // [Triple Lift, Inc.] {"hash":"00810432ca3a5adf","prefixes":{"":{"product":578}}}, // [Triple Lift, Inc.] {"hash":"e597ba5088abb36a","prefixes":{"":{"product":578}}}, // [Triple Lift, Inc.] - {"hash":"d206640e7ca174cd","prefixes":{"":{"product":579}}}, // [Indie Ads] - {"hash":"d8ed39f1e603b870","prefixes":{"":{"product":580}}}, // [Ocean Park Interactive] - {"hash":"a241e76a04cef012","prefixes":{"":{"product":580}}}, // [Ocean Park Interactive] - {"hash":"dcc0a9d204aaa55d","prefixes":{"":{"product":580}}}, // [Ocean Park Interactive] - {"hash":"8372761b0392f8a9","prefixes":{"":{"product":580}}}, // [Ocean Park Interactive] - {"hash":"e7b8261c49b1fbf6","prefixes":{"":{"product":580}}}, // [Ocean Park Interactive] - {"hash":"d5094d4667f378a7","prefixes":{"":{"product":580}}}, // [Ocean Park Interactive] - {"hash":"4091c3043c2da68a","prefixes":{"":{"product":581}}}, // [Impulse Media Pvt. Ltd.] - {"hash":"6eb5dacfebab8b02","prefixes":{"":{"product":582}}}, // [CrowdTwist] - {"hash":"123db0626c48324c","prefixes":{"":{"product":582}}}, // [CrowdTwist] - {"hash":"4f356e0d187085b0","prefixes":{"":{"product":583}}}, // [Adzerk Inc.] - {"hash":"79c1600f16f0c0ad","prefixes":{"":{"product":583}}}, // [Adzerk Inc.] - {"hash":"170c4bddaa53e87c","prefixes":{"":{"product":584}}}, // [Adtarget.me] - {"hash":"b514da98fbd70da7","prefixes":{"":{"product":584}}}, // [Adtarget.me] - {"hash":"e585ef712f906ce4","prefixes":{"":{"product":584}}}, // [Adtarget.me] - {"hash":"ed5e6e621b9e9e9e","prefixes":{"":{"product":584}}}, // [Adtarget.me] - {"hash":"904a8c71f0ac4b5c","prefixes":{"":{"product":584}}}, // [Adtarget.me] - {"hash":"138d782ff8ef8b3d","prefixes":{"":{"product":585}}}, // [Recruit Marketing Partners Co.,Ltd] - {"hash":"8899c2499d762095","prefixes":{"":{"product":586}}}, // [Beijing Emar Online Technology Co.,Ltd] - {"hash":"29f87adefe40afd5","prefixes":{"":{"product":586}}}, // [Beijing Emar Online Technology Co.,Ltd] - {"hash":"1f57d0a967ca4f30","prefixes":{"":{"product":586}}}, // [Beijing Emar Online Technology Co.,Ltd] - {"hash":"378c4fbbd1d161e2","prefixes":{"":{"product":587}}}, // [AdMagnet] - {"hash":"bb42bdad4318ee55","prefixes":{"":{"product":587}}}, // [AdMagnet] - {"hash":"71d1cec71f53e140","prefixes":{"":{"product":587}}}, // [AdMagnet] - {"hash":"e3bad45f1f3d21a5","prefixes":{"":{"product":587}}}, // [AdMagnet] - {"hash":"aa63c60aa73e9d29","prefixes":{"":{"product":588}}}, // [Momondo A/S] - {"hash":"b34444583646725a","prefixes":{"*":{"product":588}}}, // [Momondo A/S] - {"hash":"cbf8a85fbf4c22e5","prefixes":{"*":{"product":589}}}, // [DKK Agency] - {"hash":"e775e327a7a42402","prefixes":{"":{"product":590}}}, // [OneScreen Inc.] - {"hash":"080fcbb984e6ecdd","prefixes":{"":{"product":590}}}, // [OneScreen Inc.] - {"hash":"8c1ae0a34a3df5d0","prefixes":{"":{"product":590}}}, // [OneScreen Inc.] - {"hash":"ba491e57276128df","prefixes":{"":{"product":591}}}, // [AdElement Media Solutions Pvt Ltd] - {"hash":"620a368e66b0d054","prefixes":{"":{"product":591}}}, // [AdElement Media Solutions Pvt Ltd] - {"hash":"f100a71a63d2ccfa","prefixes":{"":{"product":591}}}, // [AdElement Media Solutions Pvt Ltd] - {"hash":"636877d8cc1827f4","prefixes":{"":{"product":592}}}, // [Beijing Sheng Jin Lan Advertising Co., Ltd.] - {"hash":"e066625a70a1d5c0","prefixes":{"":{"product":592}}}, // [Beijing Sheng Jin Lan Advertising Co., Ltd.] - {"hash":"117aaf00ef5036e3","prefixes":{"":{"product":592}}}, // [Beijing Sheng Jin Lan Advertising Co., Ltd.] - {"hash":"4f795b8396901621","prefixes":{"":{"product":592}}}, // [Beijing Sheng Jin Lan Advertising Co., Ltd.] - {"hash":"b8da1e9feb0bc01d","prefixes":{"":{"product":592}}}, // [Beijing Sheng Jin Lan Advertising Co., Ltd.] - {"hash":"433e8fe3ca1684d7","prefixes":{"":{"product":592}}}, // [Beijing Sheng Jin Lan Advertising Co., Ltd.] - {"hash":"f2fc51beddbeb4a9","prefixes":{"":{"product":593}}}, // [Adsit Media Advertising Ltd. Co., (AdMan)] - {"hash":"ba7f680031ef6ba6","prefixes":{"":{"product":594}}}, // [AdMan] - {"hash":"cba16dd5f4409e30","prefixes":{"":{"product":594}}}, // [AdMan] - {"hash":"3e32b1ab3e9c66b6","prefixes":{"":{"product":593}}}, // [Adsit Media Advertising Ltd. Co., (AdMan)] - {"hash":"59225b3e2dce506e","prefixes":{"":{"product":595}}}, // [MicroAd Inc. (China)] - {"hash":"8a3b315693f80801","prefixes":{"":{"product":595}}}, // [MicroAd Inc. (China)] - {"hash":"9ecae05881ad91ad","prefixes":{"":{"product":595}}}, // [MicroAd Inc. (China)] - {"hash":"86a1bc63ec059f25","prefixes":{"":{"product":596}}}, // [Adfonic] - {"hash":"ea28de00a6512e88","prefixes":{"":{"product":596}}}, // [Adfonic] - {"hash":"42bb8749687dee83","prefixes":{"":{"product":597}}}, // [OwnerIQ Inc.] - {"hash":"125539a4b58c9087","prefixes":{"":{"product":597}}}, // [OwnerIQ Inc.] - {"hash":"895ef87fbdd546df","prefixes":{"":{"product":598}}}, // [Mobile Space Ltd] - {"hash":"55e398544c3aeb40","prefixes":{"":{"product":598}}}, // [Mobile Space Ltd] - {"hash":"c5e19d61efa129d7","prefixes":{"ap":{"product":598},"e":{"product":598},"":{"product":599}}}, // [Mobile Space Ltd] [Mobile Space Ltd] [Jaduda GmbH] - {"hash":"3668b933b223ee50","prefixes":{"":{"product":600}}}, // [Omotenashi Banner] - {"hash":"209fb323c4db09ef","prefixes":{"":{"product":600}}}, // [Omotenashi Banner] - {"hash":"d95ee45ed75216b1","prefixes":{"":{"product":600}}}, // [Omotenashi Banner] - {"hash":"7fb039cd298570d4","prefixes":{"":{"product":600}}}, // [Omotenashi Banner] - {"hash":"a7d0a34772320297","prefixes":{"":{"product":600}}}, // [Omotenashi Banner] - {"hash":"a86ff9f748f6a5ab","prefixes":{"":{"product":600}}}, // [Omotenashi Banner] - {"hash":"046d69c93f0ab29e","prefixes":{"":{"product":601}}}, // [Infectious Media Ltd.] - {"hash":"735a86882c4fccc6","prefixes":{"":{"product":602}}}, // [One97 Communications Limited (Ad Works)] - {"hash":"c454c081e737b7e2","prefixes":{"":{"product":602}}}, // [One97 Communications Limited (Ad Works)] - {"hash":"1e8ed560dc22bbb5","prefixes":{"":{"product":602}}}, // [One97 Communications Limited (Ad Works)] - {"hash":"3a57d7982ec36d46","prefixes":{"":{"product":602}}}, // [One97 Communications Limited (Ad Works)] - {"hash":"282d5dfa72aee67e","prefixes":{"":{"product":603}}}, // [Walk Light Media Inc.] - {"hash":"350189fcd66d737d","prefixes":{"":{"product":604}}}, // [AdBrite Inc.] - {"hash":"727c2c9dbde23217","prefixes":{"":{"product":604}}}, // [AdBrite Inc.] - {"hash":"f0011932876966b7","prefixes":{"":{"product":605}}}, // [Hi-Media] - {"hash":"49a154fb3339d1c9","prefixes":{"":{"product":605}}}, // [Hi-Media] - {"hash":"bc9403b31553c2c3","prefixes":{"":{"product":605}}}, // [Hi-Media] - {"hash":"4a763539fb83a309","prefixes":{"":{"product":605}}}, // [Hi-Media] - {"hash":"ad517dcc393c2311","prefixes":{"":{"product":605}}}, // [Hi-Media] - {"hash":"ea321c60d183257c","prefixes":{"":{"product":606}}}, // [Adlabs] - {"hash":"44405675d1af2241","prefixes":{"":{"product":606}}}, // [Adlabs] - {"hash":"703f39c13b597e32","prefixes":{"":{"product":606}}}, // [Adlabs] - {"hash":"5bdae611f2bbe659","prefixes":{"":{"product":606}}}, // [Adlabs] - {"hash":"87862d3ee53095a7","prefixes":{"":{"product":606}}}, // [Adlabs] - {"hash":"376d93acf5e8d717","prefixes":{"":{"product":606}}}, // [Adlabs] - {"hash":"3f0e8ced0049c1d6","prefixes":{"":{"product":606}}}, // [Adlabs] - {"hash":"a04ea3bd56ab64bb","prefixes":{"":{"product":607}}}, // [Arth Salutions] - {"hash":"b6ce2c8ae8e9a415","prefixes":{"":{"product":608}}}, // [Konverta] - {"hash":"ebd466a03db9081b","prefixes":{"":{"product":608}}}, // [Konverta] - {"hash":"2df213fa126d1ca4","prefixes":{"":{"product":608}}}, // [Konverta] - {"hash":"901ec1b8062c3af6","prefixes":{"":{"product":608}}}, // [Konverta] - {"hash":"3cdfbabfa37b6bd8","prefixes":{"":{"product":608}}}, // [Konverta] - {"hash":"4a23a2c45d1e92c3","prefixes":{"":{"product":608}}}, // [Konverta] - {"hash":"72784278d856920c","prefixes":{"":{"product":608}}}, // [Konverta] - {"hash":"61aa8fff3eb4e893","prefixes":{"":{"product":103}}}, // [Cogo Labs, Inc.] - {"hash":"def94469bdc7241e","prefixes":{"":{"product":103}}}, // [Cogo Labs, Inc.] - {"hash":"f17d17eabacc3756","prefixes":{"":{"product":103}}}, // [Cogo Labs, Inc.] - {"hash":"8644dbe4c2172593","prefixes":{"":{"product":609}}}, // [Shopall] - {"hash":"4b55c6a7d9c2a9a2","prefixes":{"":{"product":609}}}, // [Shopall] - {"hash":"305615cf8dbc9be2","prefixes":{"":{"product":610}}}, // [targeting360 GmbH] - {"hash":"bed5b722b1bc1ba5","prefixes":{"":{"product":611}}}, // [xplosion interactive GmbH] - {"hash":"1528f8323f342e8b","prefixes":{"":{"product":611}}}, // [xplosion interactive GmbH] - {"hash":"3c0f20ff410483fa","prefixes":{"":{"product":611}}}, // [xplosion interactive GmbH] - {"hash":"929748002c9b8ecf","prefixes":{"":{"product":611}}}, // [xplosion interactive GmbH] - {"hash":"da8d84b561cc6dae","prefixes":{"":{"product":611}}}, // [xplosion interactive GmbH] - {"hash":"4d73c36d7413bcac","prefixes":{"":{"product":611}}}, // [xplosion interactive GmbH] - {"hash":"fa03c22fb3892bf3","prefixes":{"":{"product":611}}}, // [xplosion interactive GmbH] - {"hash":"9671a9ac26a91d0a","prefixes":{"":{"product":611}}}, // [xplosion interactive GmbH] - {"hash":"ca13edee3fffee4e","prefixes":{"":{"product":612}}}, // [Hubrus LLC] - {"hash":"e6c8579483f7b40c","prefixes":{"":{"product":612}}}, // [Hubrus LLC] - {"hash":"5426e12fbea3fce8","prefixes":{"":{"product":612}}}, // [Hubrus LLC] - {"hash":"e1b8d2118c9dc529","prefixes":{"":{"product":613}}}, // [Here Media Inc.] - {"hash":"6ab38da002eadbc3","prefixes":{"":{"product":614}}}, // [Silver Egg Technology Co., Ltd.] - {"hash":"8ef09da008fcfae7","prefixes":{"":{"product":614}}}, // [Silver Egg Technology Co., Ltd.] - {"hash":"f09f918279f1e9ac","prefixes":{"":{"product":614}}}, // [Silver Egg Technology Co., Ltd.] - {"hash":"ddfd965ee920e41c","prefixes":{"":{"product":614}}}, // [Silver Egg Technology Co., Ltd.] - {"hash":"47758f4c45a57ea4","prefixes":{"":{"product":614}}}, // [Silver Egg Technology Co., Ltd.] - {"hash":"9b402085270b3ed3","prefixes":{"":{"product":614}}}, // [Silver Egg Technology Co., Ltd.] - {"hash":"5a4e20d5da4d99f0","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"1a32d33420507504","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"c841d6764f10305d","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"c0be785071fbf1f8","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"a48b68d5e7caa5da","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"93764efbaea60a26","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"2d1e1dbc88160b0a","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"49c9a4898d7eda62","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"51f27880010fd487","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"1930e597dd2d66f9","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"9138d5d361766aa2","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"942211eb94fc3c91","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"ac957255586d114c","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"1174020d0986b7c7","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"1386eff7c87966ca","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"d3c3497dc1813ac6","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"ec8bb52d56c92778","prefixes":{"":{"product":615}}}, // [QuarticOn.com] - {"hash":"b999321725f081a5","prefixes":{"":{"product":616}}}, // [Kavanga LLC] - {"hash":"43f2f88cac5c1e66","prefixes":{"":{"product":617}}}, // [Vodafone D2 GmbH] - {"hash":"71f43d2f0436d908","prefixes":{"":{"product":617}}}, // [Vodafone D2 GmbH] - {"hash":"4b13b8a28b6556d3","prefixes":{"":{"product":617}}}, // [Vodafone D2 GmbH] - {"hash":"b9c154f4d363eebc","prefixes":{"":{"product":618}}}, // [Qubit Digital Ltd] - {"hash":"f3c32c6c7e1ac882","prefixes":{"":{"product":538},"ad":{"product":619},"tm":{"product":619}}}, // [Target Performance] [NEORY GmbH] [NEORY GmbH] - {"hash":"728524adefe77058","prefixes":{"static-":{"product":620}}}, // [Populis Ireland Limited] - {"hash":"7f78aff31bba38ad","prefixes":{"":{"product":620}}}, // [Populis Ireland Limited] - {"hash":"cacb07348e9e3ca3","prefixes":{"":{"product":620}}}, // [Populis Ireland Limited] - {"hash":"ce069e74d10aa948","prefixes":{"":{"product":621}}}, // [LiquidM Technology GmbH] - {"hash":"b6284e5bbeacee78","prefixes":{"":{"product":622}}}, // [Celtra Inc.] - {"hash":"f71102b0f2425eb8","prefixes":{"":{"product":622}}}, // [Celtra Inc.] - {"hash":"da76d0a397ab42fc","prefixes":{"":{"product":622}}}, // [Celtra Inc.] - {"hash":"d30b0fd7cd3dc387","prefixes":{"":{"product":622}}}, // [Celtra Inc.] - {"hash":"d3643510dc9a55a3","prefixes":{"":{"product":622}}}, // [Celtra Inc.] - {"hash":"f74f9b96eb974ad7","prefixes":{"":{"product":622}}}, // [Celtra Inc.] - {"hash":"538d09650aaff88b","prefixes":{"":{"product":622}}}, // [Celtra Inc.] - {"hash":"7533124cd83c8651","prefixes":{"":{"product":622}}}, // [Celtra Inc.] - {"hash":"8413a3afa447ddd6","prefixes":{"":{"product":623}}}, // [Adfox] - {"hash":"28b1ebc0a8b51b58","prefixes":{"":{"product":623}}}, // [Adfox] - {"hash":"0c6cea5dd49d0361","prefixes":{"sd":{"product":623},"rt":{"product":623}}}, // [Adfox] [Adfox] - {"hash":"2e3df7d60b00392d","prefixes":{"":{"product":623}}}, // [Adfox] - {"hash":"4cdee950d7417a19","prefixes":{"":{"product":623}}}, // [Adfox] - {"hash":"2060d81c3f4dbace","prefixes":{"":{"product":624}}}, // [Accordant Media LLC] - {"hash":"f2c07b1834365ee5","prefixes":{"":{"product":625}}}, // [Fiksu DSP] - {"hash":"c61068cc57f0f219","prefixes":{"":{"product":625}}}, // [Fiksu DSP] - {"hash":"a1f4b4a83add949d","prefixes":{"":{"product":625}}}, // [Fiksu DSP] - {"hash":"70b9063aeb27d88a","prefixes":{"":{"product":625}}}, // [Fiksu DSP] - {"hash":"f66693ef14e4cd79","prefixes":{"":{"product":625}}}, // [Fiksu DSP] - {"hash":"7f9c748aa884dba0","prefixes":{"":{"product":626}}}, // [MdotM, Inc.] - {"hash":"13c8f5f12f3b9ca6","prefixes":{"":{"product":626}}}, // [MdotM, Inc.] - {"hash":"c47f6172a03d7b4c","prefixes":{"":{"product":627}}}, // [TNS GALLUP ADFACT, ZAO] - {"hash":"f9a74c430e157e57","prefixes":{"":{"product":627}}}, // [TNS GALLUP ADFACT, ZAO] - {"hash":"534ec1b9f199f18a","prefixes":{"":{"product":628}}}, // [MicroAd Inc. (APAC)] - {"hash":"98bec02f53970649","prefixes":{"":{"product":628}}}, // [MicroAd Inc. (APAC)] - {"hash":"dab5b2f5150fe52c","prefixes":{"*":{"product":629}}}, // [ECRITEL SARL] - {"hash":"039caee3c590ef51","prefixes":{"*":{"product":629}}}, // [ECRITEL SARL] - {"hash":"56d4c8e77cf378ca","prefixes":{"*":{"product":629}}}, // [ECRITEL SARL] - {"hash":"ea054eef4a7b535d","prefixes":{"*":{"product":629}}}, // [ECRITEL SARL] - {"hash":"503f3e019cf902f7","prefixes":{"":{"product":104}}}, // [AudienceProject] - {"hash":"d07ac29d5418a5a2","prefixes":{"":{"product":104}}}, // [AudienceProject] + {"hash":"d206640e7ca174cd","prefixes":{"":{"product":579,"type":0}}}, // [Indie Ads] + {"hash":"d8ed39f1e603b870","prefixes":{"":{"product":580,"type":0}}}, // [Ocean Park Interactive] + {"hash":"a241e76a04cef012","prefixes":{"":{"product":580,"type":0}}}, // [Ocean Park Interactive] + {"hash":"dcc0a9d204aaa55d","prefixes":{"":{"product":580,"type":0}}}, // [Ocean Park Interactive] + {"hash":"8372761b0392f8a9","prefixes":{"":{"product":580,"type":0}}}, // [Ocean Park Interactive] + {"hash":"e7b8261c49b1fbf6","prefixes":{"":{"product":580,"type":0}}}, // [Ocean Park Interactive] + {"hash":"d5094d4667f378a7","prefixes":{"":{"product":580,"type":0}}}, // [Ocean Park Interactive] + {"hash":"4091c3043c2da68a","prefixes":{"":{"product":581,"type":0}}}, // [Impulse Media Pvt. Ltd.] + {"hash":"6eb5dacfebab8b02","prefixes":{"":{"product":582,"type":1}}}, // [CrowdTwist] + {"hash":"123db0626c48324c","prefixes":{"":{"product":582,"type":1}}}, // [CrowdTwist] + {"hash":"4f356e0d187085b0","prefixes":{"":{"product":583,"type":0}}}, // [Adzerk Inc.] + {"hash":"79c1600f16f0c0ad","prefixes":{"":{"product":583,"type":0}}}, // [Adzerk Inc.] + {"hash":"170c4bddaa53e87c","prefixes":{"":{"product":584,"type":0}}}, // [Adtarget.me] + {"hash":"b514da98fbd70da7","prefixes":{"":{"product":584,"type":0}}}, // [Adtarget.me] + {"hash":"e585ef712f906ce4","prefixes":{"":{"product":584,"type":0}}}, // [Adtarget.me] + {"hash":"ed5e6e621b9e9e9e","prefixes":{"":{"product":584,"type":0}}}, // [Adtarget.me] + {"hash":"904a8c71f0ac4b5c","prefixes":{"":{"product":584,"type":0}}}, // [Adtarget.me] + {"hash":"138d782ff8ef8b3d","prefixes":{"":{"product":585,"type":1}}}, // [Recruit Marketing Partners Co.,Ltd] + {"hash":"8899c2499d762095","prefixes":{"":{"product":586,"type":0}}}, // [Beijing Emar Online Technology Co.,Ltd] + {"hash":"29f87adefe40afd5","prefixes":{"":{"product":586,"type":0}}}, // [Beijing Emar Online Technology Co.,Ltd] + {"hash":"1f57d0a967ca4f30","prefixes":{"":{"product":586,"type":0}}}, // [Beijing Emar Online Technology Co.,Ltd] + {"hash":"378c4fbbd1d161e2","prefixes":{"":{"product":587,"type":0}}}, // [AdMagnet] + {"hash":"bb42bdad4318ee55","prefixes":{"":{"product":587,"type":0}}}, // [AdMagnet] + {"hash":"71d1cec71f53e140","prefixes":{"":{"product":587,"type":0}}}, // [AdMagnet] + {"hash":"e3bad45f1f3d21a5","prefixes":{"":{"product":587,"type":0}}}, // [AdMagnet] + {"hash":"aa63c60aa73e9d29","prefixes":{"":{"product":588,"type":0}}}, // [Momondo A/S] + {"hash":"b34444583646725a","prefixes":{"*":{"product":588,"type":0}}}, // [Momondo A/S] + {"hash":"cbf8a85fbf4c22e5","prefixes":{"*":{"product":589,"type":0}}}, // [DKK Agency] + {"hash":"e775e327a7a42402","prefixes":{"":{"product":590,"type":0}}}, // [OneScreen Inc.] + {"hash":"080fcbb984e6ecdd","prefixes":{"":{"product":590,"type":0}}}, // [OneScreen Inc.] + {"hash":"8c1ae0a34a3df5d0","prefixes":{"":{"product":590,"type":0}}}, // [OneScreen Inc.] + {"hash":"ba491e57276128df","prefixes":{"":{"product":591,"type":0}}}, // [AdElement Media Solutions Pvt Ltd] + {"hash":"620a368e66b0d054","prefixes":{"":{"product":591,"type":0}}}, // [AdElement Media Solutions Pvt Ltd] + {"hash":"f100a71a63d2ccfa","prefixes":{"":{"product":591,"type":0}}}, // [AdElement Media Solutions Pvt Ltd] + {"hash":"636877d8cc1827f4","prefixes":{"":{"product":592,"type":0}}}, // [Beijing Sheng Jin Lan Advertising Co., Ltd.] + {"hash":"e066625a70a1d5c0","prefixes":{"":{"product":592,"type":0}}}, // [Beijing Sheng Jin Lan Advertising Co., Ltd.] + {"hash":"117aaf00ef5036e3","prefixes":{"":{"product":592,"type":0}}}, // [Beijing Sheng Jin Lan Advertising Co., Ltd.] + {"hash":"4f795b8396901621","prefixes":{"":{"product":592,"type":0}}}, // [Beijing Sheng Jin Lan Advertising Co., Ltd.] + {"hash":"b8da1e9feb0bc01d","prefixes":{"":{"product":592,"type":0}}}, // [Beijing Sheng Jin Lan Advertising Co., Ltd.] + {"hash":"433e8fe3ca1684d7","prefixes":{"":{"product":592,"type":0}}}, // [Beijing Sheng Jin Lan Advertising Co., Ltd.] + {"hash":"f2fc51beddbeb4a9","prefixes":{"":{"product":593,"type":0}}}, // [Adsit Media Advertising Ltd. Co., (AdMan)] + {"hash":"ba7f680031ef6ba6","prefixes":{"":{"product":594,"type":1}}}, // [AdMan] + {"hash":"cba16dd5f4409e30","prefixes":{"":{"product":594,"type":1}}}, // [AdMan] + {"hash":"3e32b1ab3e9c66b6","prefixes":{"":{"product":593,"type":0}}}, // [Adsit Media Advertising Ltd. Co., (AdMan)] + {"hash":"59225b3e2dce506e","prefixes":{"":{"product":595,"type":0}}}, // [MicroAd Inc. (China)] + {"hash":"8a3b315693f80801","prefixes":{"":{"product":595,"type":0}}}, // [MicroAd Inc. (China)] + {"hash":"9ecae05881ad91ad","prefixes":{"":{"product":595,"type":0}}}, // [MicroAd Inc. (China)] + {"hash":"86a1bc63ec059f25","prefixes":{"":{"product":596,"type":0}}}, // [Adfonic] + {"hash":"ea28de00a6512e88","prefixes":{"":{"product":596,"type":0}}}, // [Adfonic] + {"hash":"42bb8749687dee83","prefixes":{"":{"product":597,"type":0}}}, // [OwnerIQ Inc.] + {"hash":"125539a4b58c9087","prefixes":{"":{"product":597,"type":0}}}, // [OwnerIQ Inc.] + {"hash":"895ef87fbdd546df","prefixes":{"":{"product":598,"type":0}}}, // [Mobile Space Ltd] + {"hash":"55e398544c3aeb40","prefixes":{"":{"product":598,"type":0}}}, // [Mobile Space Ltd] + {"hash":"c5e19d61efa129d7","prefixes":{"ap":{"product":598,"type":0},"e":{"product":598,"type":0},"":{"product":599,"type":0}}}, // [Mobile Space Ltd] [Mobile Space Ltd] [Jaduda GmbH] + {"hash":"3668b933b223ee50","prefixes":{"":{"product":600,"type":0}}}, // [Omotenashi Banner] + {"hash":"209fb323c4db09ef","prefixes":{"":{"product":600,"type":0}}}, // [Omotenashi Banner] + {"hash":"d95ee45ed75216b1","prefixes":{"":{"product":600,"type":0}}}, // [Omotenashi Banner] + {"hash":"7fb039cd298570d4","prefixes":{"":{"product":600,"type":0}}}, // [Omotenashi Banner] + {"hash":"a7d0a34772320297","prefixes":{"":{"product":600,"type":0}}}, // [Omotenashi Banner] + {"hash":"a86ff9f748f6a5ab","prefixes":{"":{"product":600,"type":0}}}, // [Omotenashi Banner] + {"hash":"046d69c93f0ab29e","prefixes":{"":{"product":601,"type":0}}}, // [Infectious Media Ltd.] + {"hash":"735a86882c4fccc6","prefixes":{"":{"product":602,"type":0}}}, // [One97 Communications Limited (Ad Works)] + {"hash":"c454c081e737b7e2","prefixes":{"":{"product":602,"type":0}}}, // [One97 Communications Limited (Ad Works)] + {"hash":"1e8ed560dc22bbb5","prefixes":{"":{"product":602,"type":0}}}, // [One97 Communications Limited (Ad Works)] + {"hash":"3a57d7982ec36d46","prefixes":{"":{"product":602,"type":0}}}, // [One97 Communications Limited (Ad Works)] + {"hash":"282d5dfa72aee67e","prefixes":{"":{"product":603,"type":0}}}, // [Walk Light Media Inc.] + {"hash":"350189fcd66d737d","prefixes":{"":{"product":604,"type":0}}}, // [AdBrite Inc.] + {"hash":"727c2c9dbde23217","prefixes":{"":{"product":604,"type":0}}}, // [AdBrite Inc.] + {"hash":"f0011932876966b7","prefixes":{"":{"product":605,"type":0}}}, // [Hi-Media] + {"hash":"49a154fb3339d1c9","prefixes":{"":{"product":605,"type":0}}}, // [Hi-Media] + {"hash":"bc9403b31553c2c3","prefixes":{"":{"product":605,"type":0}}}, // [Hi-Media] + {"hash":"4a763539fb83a309","prefixes":{"":{"product":605,"type":0}}}, // [Hi-Media] + {"hash":"ad517dcc393c2311","prefixes":{"":{"product":605,"type":0}}}, // [Hi-Media] + {"hash":"ea321c60d183257c","prefixes":{"":{"product":606,"type":0}}}, // [Adlabs] + {"hash":"44405675d1af2241","prefixes":{"":{"product":606,"type":0}}}, // [Adlabs] + {"hash":"703f39c13b597e32","prefixes":{"":{"product":606,"type":0}}}, // [Adlabs] + {"hash":"5bdae611f2bbe659","prefixes":{"":{"product":606,"type":0}}}, // [Adlabs] + {"hash":"87862d3ee53095a7","prefixes":{"":{"product":606,"type":0}}}, // [Adlabs] + {"hash":"376d93acf5e8d717","prefixes":{"":{"product":606,"type":0}}}, // [Adlabs] + {"hash":"3f0e8ced0049c1d6","prefixes":{"":{"product":606,"type":0}}}, // [Adlabs] + {"hash":"a04ea3bd56ab64bb","prefixes":{"":{"product":607,"type":0}}}, // [Arth Salutions] + {"hash":"b6ce2c8ae8e9a415","prefixes":{"":{"product":608,"type":0}}}, // [Konverta] + {"hash":"ebd466a03db9081b","prefixes":{"":{"product":608,"type":0}}}, // [Konverta] + {"hash":"2df213fa126d1ca4","prefixes":{"":{"product":608,"type":0}}}, // [Konverta] + {"hash":"901ec1b8062c3af6","prefixes":{"":{"product":608,"type":0}}}, // [Konverta] + {"hash":"3cdfbabfa37b6bd8","prefixes":{"":{"product":608,"type":0}}}, // [Konverta] + {"hash":"4a23a2c45d1e92c3","prefixes":{"":{"product":608,"type":0}}}, // [Konverta] + {"hash":"72784278d856920c","prefixes":{"":{"product":608,"type":0}}}, // [Konverta] + {"hash":"61aa8fff3eb4e893","prefixes":{"":{"product":103,"type":0}}}, // [Cogo Labs, Inc.] + {"hash":"def94469bdc7241e","prefixes":{"":{"product":103,"type":0}}}, // [Cogo Labs, Inc.] + {"hash":"f17d17eabacc3756","prefixes":{"":{"product":103,"type":0}}}, // [Cogo Labs, Inc.] + {"hash":"8644dbe4c2172593","prefixes":{"":{"product":609,"type":0}}}, // [Shopall] + {"hash":"4b55c6a7d9c2a9a2","prefixes":{"":{"product":609,"type":0}}}, // [Shopall] + {"hash":"305615cf8dbc9be2","prefixes":{"":{"product":610,"type":0}}}, // [targeting360 GmbH] + {"hash":"bed5b722b1bc1ba5","prefixes":{"":{"product":611,"type":0}}}, // [xplosion interactive GmbH] + {"hash":"1528f8323f342e8b","prefixes":{"":{"product":611,"type":0}}}, // [xplosion interactive GmbH] + {"hash":"3c0f20ff410483fa","prefixes":{"":{"product":611,"type":0}}}, // [xplosion interactive GmbH] + {"hash":"929748002c9b8ecf","prefixes":{"":{"product":611,"type":0}}}, // [xplosion interactive GmbH] + {"hash":"da8d84b561cc6dae","prefixes":{"":{"product":611,"type":0}}}, // [xplosion interactive GmbH] + {"hash":"4d73c36d7413bcac","prefixes":{"":{"product":611,"type":0}}}, // [xplosion interactive GmbH] + {"hash":"fa03c22fb3892bf3","prefixes":{"":{"product":611,"type":0}}}, // [xplosion interactive GmbH] + {"hash":"9671a9ac26a91d0a","prefixes":{"":{"product":611,"type":0}}}, // [xplosion interactive GmbH] + {"hash":"ca13edee3fffee4e","prefixes":{"":{"product":612,"type":0}}}, // [Hubrus LLC] + {"hash":"e6c8579483f7b40c","prefixes":{"":{"product":612,"type":0}}}, // [Hubrus LLC] + {"hash":"5426e12fbea3fce8","prefixes":{"":{"product":612,"type":0}}}, // [Hubrus LLC] + {"hash":"e1b8d2118c9dc529","prefixes":{"":{"product":613,"type":0}}}, // [Here Media Inc.] + {"hash":"6ab38da002eadbc3","prefixes":{"":{"product":614,"type":0}}}, // [Silver Egg Technology Co., Ltd.] + {"hash":"8ef09da008fcfae7","prefixes":{"":{"product":614,"type":0}}}, // [Silver Egg Technology Co., Ltd.] + {"hash":"f09f918279f1e9ac","prefixes":{"":{"product":614,"type":0}}}, // [Silver Egg Technology Co., Ltd.] + {"hash":"ddfd965ee920e41c","prefixes":{"":{"product":614,"type":0}}}, // [Silver Egg Technology Co., Ltd.] + {"hash":"47758f4c45a57ea4","prefixes":{"":{"product":614,"type":0}}}, // [Silver Egg Technology Co., Ltd.] + {"hash":"9b402085270b3ed3","prefixes":{"":{"product":614,"type":0}}}, // [Silver Egg Technology Co., Ltd.] + {"hash":"5a4e20d5da4d99f0","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"1a32d33420507504","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"c841d6764f10305d","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"c0be785071fbf1f8","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"a48b68d5e7caa5da","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"93764efbaea60a26","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"2d1e1dbc88160b0a","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"49c9a4898d7eda62","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"51f27880010fd487","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"1930e597dd2d66f9","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"9138d5d361766aa2","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"942211eb94fc3c91","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"ac957255586d114c","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"1174020d0986b7c7","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"1386eff7c87966ca","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"d3c3497dc1813ac6","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"ec8bb52d56c92778","prefixes":{"":{"product":615,"type":0}}}, // [QuarticOn.com] + {"hash":"b999321725f081a5","prefixes":{"":{"product":616,"type":0}}}, // [Kavanga LLC] + {"hash":"43f2f88cac5c1e66","prefixes":{"":{"product":617,"type":1}}}, // [Vodafone D2 GmbH] + {"hash":"71f43d2f0436d908","prefixes":{"":{"product":617,"type":1}}}, // [Vodafone D2 GmbH] + {"hash":"4b13b8a28b6556d3","prefixes":{"":{"product":617,"type":1}}}, // [Vodafone D2 GmbH] + {"hash":"b9c154f4d363eebc","prefixes":{"":{"product":618,"type":1}}}, // [Qubit Digital Ltd] + {"hash":"f3c32c6c7e1ac882","prefixes":{"":{"product":538,"type":0},"ad":{"product":619,"type":0},"tm":{"product":619,"type":0}}}, // [Target Performance] [NEORY GmbH] [NEORY GmbH] + {"hash":"728524adefe77058","prefixes":{"static-":{"product":620,"type":0}}}, // [Populis Ireland Limited] + {"hash":"7f78aff31bba38ad","prefixes":{"":{"product":620,"type":0}}}, // [Populis Ireland Limited] + {"hash":"cacb07348e9e3ca3","prefixes":{"":{"product":620,"type":0}}}, // [Populis Ireland Limited] + {"hash":"ce069e74d10aa948","prefixes":{"":{"product":621,"type":0}}}, // [LiquidM Technology GmbH] + {"hash":"b6284e5bbeacee78","prefixes":{"":{"product":622,"type":0}}}, // [Celtra Inc.] + {"hash":"f71102b0f2425eb8","prefixes":{"":{"product":622,"type":0}}}, // [Celtra Inc.] + {"hash":"da76d0a397ab42fc","prefixes":{"":{"product":622,"type":0}}}, // [Celtra Inc.] + {"hash":"d30b0fd7cd3dc387","prefixes":{"":{"product":622,"type":0}}}, // [Celtra Inc.] + {"hash":"d3643510dc9a55a3","prefixes":{"":{"product":622,"type":0}}}, // [Celtra Inc.] + {"hash":"f74f9b96eb974ad7","prefixes":{"":{"product":622,"type":0}}}, // [Celtra Inc.] + {"hash":"538d09650aaff88b","prefixes":{"":{"product":622,"type":0}}}, // [Celtra Inc.] + {"hash":"7533124cd83c8651","prefixes":{"":{"product":622,"type":0}}}, // [Celtra Inc.] + {"hash":"8413a3afa447ddd6","prefixes":{"":{"product":623,"type":0}}}, // [Adfox] + {"hash":"28b1ebc0a8b51b58","prefixes":{"":{"product":623,"type":0}}}, // [Adfox] + {"hash":"0c6cea5dd49d0361","prefixes":{"sd":{"product":623,"type":0},"rt":{"product":623,"type":0}}}, // [Adfox] [Adfox] + {"hash":"2e3df7d60b00392d","prefixes":{"":{"product":623,"type":0}}}, // [Adfox] + {"hash":"4cdee950d7417a19","prefixes":{"":{"product":623,"type":0}}}, // [Adfox] + {"hash":"2060d81c3f4dbace","prefixes":{"":{"product":624,"type":0}}}, // [Accordant Media LLC] + {"hash":"f2c07b1834365ee5","prefixes":{"":{"product":625,"type":0}}}, // [Fiksu DSP] + {"hash":"c61068cc57f0f219","prefixes":{"":{"product":625,"type":0}}}, // [Fiksu DSP] + {"hash":"a1f4b4a83add949d","prefixes":{"":{"product":625,"type":0}}}, // [Fiksu DSP] + {"hash":"70b9063aeb27d88a","prefixes":{"":{"product":625,"type":0}}}, // [Fiksu DSP] + {"hash":"f66693ef14e4cd79","prefixes":{"":{"product":625,"type":0}}}, // [Fiksu DSP] + {"hash":"7f9c748aa884dba0","prefixes":{"":{"product":626,"type":0}}}, // [MdotM, Inc.] + {"hash":"13c8f5f12f3b9ca6","prefixes":{"":{"product":626,"type":0}}}, // [MdotM, Inc.] + {"hash":"c47f6172a03d7b4c","prefixes":{"":{"product":627,"type":1}}}, // [TNS GALLUP ADFACT, ZAO] + {"hash":"f9a74c430e157e57","prefixes":{"":{"product":627,"type":1}}}, // [TNS GALLUP ADFACT, ZAO] + {"hash":"534ec1b9f199f18a","prefixes":{"":{"product":628,"type":0}}}, // [MicroAd Inc. (APAC)] + {"hash":"98bec02f53970649","prefixes":{"":{"product":628,"type":0}}}, // [MicroAd Inc. (APAC)] + {"hash":"dab5b2f5150fe52c","prefixes":{"*":{"product":629,"type":2}}}, // [ECRITEL SARL] + {"hash":"039caee3c590ef51","prefixes":{"*":{"product":629,"type":2}}}, // [ECRITEL SARL] + {"hash":"56d4c8e77cf378ca","prefixes":{"*":{"product":629,"type":2}}}, // [ECRITEL SARL] + {"hash":"ea054eef4a7b535d","prefixes":{"*":{"product":629,"type":2}}}, // [ECRITEL SARL] + {"hash":"503f3e019cf902f7","prefixes":{"":{"product":104,"type":1}}}, // [AudienceProject] + {"hash":"d07ac29d5418a5a2","prefixes":{"":{"product":104,"type":1}}}, // [AudienceProject] {"hash":"252a5f53fef3adef","prefixes":{"":{"product":630}}}, // [Gloto Corp.] {"hash":"c45cf16c98289ef3","prefixes":{"":{"product":630}}}, // [Gloto Corp.] - {"hash":"43869a9fbc1e93ac","prefixes":{"":{"product":631}}}, // [OOO GPM-Digital] - {"hash":"4334255596024dac","prefixes":{"*":{"product":632}}}, // [adverserve digital advertising services] - {"hash":"c1cbc8c1a131b486","prefixes":{"":{"product":633}}}, // [Abstract] - {"hash":"f0a24e1beb2ff006","prefixes":{"":{"product":633}}}, // [Abstract] - {"hash":"5d7848291e6b2aac","prefixes":{"":{"product":633}}}, // [Abstract] - {"hash":"678875d741d45390","prefixes":{"":{"product":634}}}, // [Adscale GmbH] - {"hash":"bdf162f8a955792f","prefixes":{"":{"product":634}}}, // [Adscale GmbH] - {"hash":"e2aa93ef150b6625","prefixes":{"":{"product":634}}}, // [Adscale GmbH] - {"hash":"fbecc41bd388e9da","prefixes":{"":{"product":634}}}, // [Adscale GmbH] - {"hash":"33d677c1746e032b","prefixes":{"":{"product":634}}}, // [Adscale GmbH] - {"hash":"7b632e1d26173d9a","prefixes":{"":{"product":635}}}, // [Weebly, Inc.] - {"hash":"d60691434c15d686","prefixes":{"":{"product":636}}}, // [KPI Solutions Co.,Ltd.] - {"hash":"6bcb40c428dea82d","prefixes":{"*":{"product":636}}}, // [KPI Solutions Co.,Ltd.] - {"hash":"a7261ab41534a5a9","prefixes":{"":{"product":637}}}, // [LuckyBrand.com] - {"hash":"8ade692ce59ddf24","prefixes":{"":{"product":638}}}, // [Bedrijvenweb.nl] - {"hash":"4f925a01c20725e2","prefixes":{"":{"product":639}}}, // [CacheFly] - {"hash":"bd7deac394b9d8ec","prefixes":{"*":{"product":640}}}, // [EdgeCast Networks Inc.] - {"hash":"d14784769a5e3e32","prefixes":{"*":{"product":640}}}, // [EdgeCast Networks Inc.] - {"hash":"eeb0b9405b4e70a9","prefixes":{"*":{"product":640}}}, // [EdgeCast Networks Inc.] - {"hash":"799a922119603cf7","prefixes":{"":{"product":641}}}, // [AdFrontier] - {"hash":"b99f16bd08f23e1d","prefixes":{"":{"product":642}}}, // [NFQ] - {"hash":"55b741a8d993b7af","prefixes":{"":{"product":642}}}, // [NFQ] - {"hash":"7733707370fb05c7","prefixes":{"":{"product":642}}}, // [NFQ] + {"hash":"43869a9fbc1e93ac","prefixes":{"":{"product":631,"type":0}}}, // [OOO GPM-Digital] + {"hash":"4334255596024dac","prefixes":{"*":{"product":632,"type":2}}}, // [adverserve digital advertising services] + {"hash":"c1cbc8c1a131b486","prefixes":{"":{"product":633,"type":0}}}, // [Abstract] + {"hash":"f0a24e1beb2ff006","prefixes":{"":{"product":633,"type":0}}}, // [Abstract] + {"hash":"5d7848291e6b2aac","prefixes":{"":{"product":633,"type":0}}}, // [Abstract] + {"hash":"678875d741d45390","prefixes":{"":{"product":634,"type":0}}}, // [Adscale GmbH] + {"hash":"bdf162f8a955792f","prefixes":{"":{"product":634,"type":0}}}, // [Adscale GmbH] + {"hash":"e2aa93ef150b6625","prefixes":{"":{"product":634,"type":0}}}, // [Adscale GmbH] + {"hash":"fbecc41bd388e9da","prefixes":{"":{"product":634,"type":0}}}, // [Adscale GmbH] + {"hash":"33d677c1746e032b","prefixes":{"":{"product":634,"type":0}}}, // [Adscale GmbH] + {"hash":"7b632e1d26173d9a","prefixes":{"":{"product":635,"type":0}}}, // [Weebly, Inc.] + {"hash":"d60691434c15d686","prefixes":{"":{"product":636,"type":0}}}, // [KPI Solutions Co.,Ltd.] + {"hash":"6bcb40c428dea82d","prefixes":{"*":{"product":636,"type":0}}}, // [KPI Solutions Co.,Ltd.] + {"hash":"a7261ab41534a5a9","prefixes":{"":{"product":637,"type":0}}}, // [LuckyBrand.com] + {"hash":"8ade692ce59ddf24","prefixes":{"":{"product":638,"type":0}}}, // [Bedrijvenweb.nl] + {"hash":"4f925a01c20725e2","prefixes":{"":{"product":639,"type":0}}}, // [CacheFly] + {"hash":"bd7deac394b9d8ec","prefixes":{"*":{"product":640,"type":0}}}, // [EdgeCast Networks Inc.] + {"hash":"d14784769a5e3e32","prefixes":{"*":{"product":640,"type":0}}}, // [EdgeCast Networks Inc.] + {"hash":"eeb0b9405b4e70a9","prefixes":{"*":{"product":640,"type":0}}}, // [EdgeCast Networks Inc.] + {"hash":"799a922119603cf7","prefixes":{"":{"product":641,"type":0}}}, // [AdFrontier] + {"hash":"b99f16bd08f23e1d","prefixes":{"":{"product":642,"type":0}}}, // [NFQ] + {"hash":"55b741a8d993b7af","prefixes":{"":{"product":642,"type":0}}}, // [NFQ] + {"hash":"7733707370fb05c7","prefixes":{"":{"product":642,"type":0}}}, // [NFQ] {"hash":"9a42cb5421abffa9","prefixes":{"":{"product":643}}}, // [DataLogix, Inc.] {"hash":"47ee3c7f6cf3211f","prefixes":{"":{"product":643}}}, // [DataLogix, Inc.] {"hash":"5e4b5dd08e9b52fd","prefixes":{"":{"product":643}}}, // [DataLogix, Inc.] @@ -3811,1858 +3809,1858 @@ {"hash":"18656382f2827e60","prefixes":{"":{"product":643}}}, // [DataLogix, Inc.] {"hash":"c73db0ed241d269e","prefixes":{"":{"product":643}}}, // [DataLogix, Inc.] {"hash":"bc0f02a06b74b7a3","prefixes":{"":{"product":643}}}, // [DataLogix, Inc.] - {"hash":"0405bea2af551e19","prefixes":{"":{"product":643}}}, // [DataLogix, Inc.] - {"hash":"c35511ecd49cebb7","prefixes":{"":{"product":644}}}, // [Brightcove] - {"hash":"22bfe38898977ed4","prefixes":{"":{"product":644}}}, // [Brightcove] + {"hash":"0405bea2af551e19","prefixes":{"":{"product":643,"type":1}}}, // [DataLogix, Inc.] + {"hash":"c35511ecd49cebb7","prefixes":{"":{"product":644,"type":0}}}, // [Brightcove] + {"hash":"22bfe38898977ed4","prefixes":{"":{"product":644,"type":0}}}, // [Brightcove] {"hash":"c095755780478f7e","prefixes":{"":{"product":645}}}, // [Experian] - {"hash":"0f2014a09acf7abd","prefixes":{"*":{"product":646}}}, // [Facebook Connect] - {"hash":"b7c70898d90f5bb3","prefixes":{"*":{"product":646}}}, // [Facebook Connect] - {"hash":"18562cb1149fda1e","prefixes":{"*":{"product":647}}}, // [Disqus] - {"hash":"37b749b8858eb61b","prefixes":{"*":{"product":648}}}, // [Namecheap.com] - {"hash":"3d59be0f5f7101a0","prefixes":{"":{"product":649}}}, // [Polldaddy] - {"hash":"510cff549d2cb397","prefixes":{"":{"product":650}}}, // [Outbrain Inc.] - {"hash":"e23ebc9959ce4873","prefixes":{"":{"product":650}}}, // [Outbrain Inc.] - {"hash":"623fd0210b11d4fb","prefixes":{"":{"product":651}}}, // [Lijit Networks, Inc.] - {"hash":"686b7accbfa398fa","prefixes":{"":{"product":651}}}, // [Lijit Networks, Inc.] - {"hash":"85c44f0602598dd8","prefixes":{"":{"product":651}}}, // [Lijit Networks, Inc.] - {"hash":"a107b1fdcffae5b9","prefixes":{"*":{"product":484}}}, // [NetDNA, LLC] - {"hash":"7f37823a3f5c76b3","prefixes":{"*":{"product":652}}}, // [PubMatic] - {"hash":"6d306315a1fecfda","prefixes":{"":{"product":653}}}, // [Say Media Inc.] - {"hash":"c2568516b08f0d3d","prefixes":{"":{"product":653}}}, // [Say Media Inc.] - {"hash":"308d3a8d1ca52ff3","prefixes":{"":{"product":653}}}, // [Say Media Inc.] - {"hash":"59e488c5f151e7c3","prefixes":{"":{"product":653}}}, // [Say Media Inc.] - {"hash":"7efe6908db5a1d44","prefixes":{"":{"product":654}}}, // [Rubicon Project Turing, Inc. (SSP)] - {"hash":"c6ee8faaa7d6734c","prefixes":{"":{"product":655}}}, // [Rubicon Project Edison, Inc. (DSP)] - {"hash":"d93c07cc68e53d91","prefixes":{"":{"product":655}}}, // [Rubicon Project Edison, Inc. (DSP)] - {"hash":"86ae2b216def9790","prefixes":{"":{"product":655}}}, // [Rubicon Project Edison, Inc. (DSP)] - {"hash":"1267f5857549a6ab","prefixes":{"":{"product":655}}}, // [Rubicon Project Edison, Inc. (DSP)] - {"hash":"367db80c0776f6d8","prefixes":{"":{"product":655}}}, // [Rubicon Project Edison, Inc. (DSP)] - {"hash":"c4c762a7e666da1c","prefixes":{"":{"product":655}}}, // [Rubicon Project Edison, Inc. (DSP)] - {"hash":"bb66261f843823d5","prefixes":{"":{"product":656}}}, // [Wordpress Stats] - {"hash":"a0f3bb8dcd67010e","prefixes":{"":{"product":656}}}, // [Wordpress Stats] - {"hash":"4a423f1da960eda6","prefixes":{"*":{"product":657}}}, // [Twitter] - {"hash":"465806fbb3547c25","prefixes":{"*":{"product":657}}}, // [Twitter] - {"hash":"13c55ef8102cbdbb","prefixes":{"":{"product":658}}}, // [Yandex LLC] - {"hash":"db546baba3acb079","prefixes":{"":{"product":658}}}, // [Yandex LLC] - {"hash":"3dd0667dbad0af61","prefixes":{"":{"product":658}}}, // [Yandex LLC] - {"hash":"78e224c91aabe6de","prefixes":{"":{"product":659}}}, // [Rutarget / Segmento] - {"hash":"75acb8a5a60ef63d","prefixes":{"":{"product":659}}}, // [Rutarget / Segmento] - {"hash":"6f7720a054c19a2b","prefixes":{"":{"product":659}}}, // [Rutarget / Segmento] - {"hash":"dbd76c26579bf2b1","prefixes":{"":{"product":659}}}, // [Rutarget / Segmento] - {"hash":"2cd7f311595e164e","prefixes":{"":{"product":659}}}, // [Rutarget / Segmento] - {"hash":"b08380cf2fcb4415","prefixes":{"":{"product":659}}}, // [Rutarget / Segmento] - {"hash":"59ac14277edec497","prefixes":{"":{"product":659}}}, // [Rutarget / Segmento] - {"hash":"88893eeb26e546a0","prefixes":{"":{"product":659}}}, // [Rutarget / Segmento] - {"hash":"da151dbe8b815dfb","prefixes":{"":{"product":660}}}, // [Addoor LatinMarkets, SL] - {"hash":"b2a44f920e268749","prefixes":{"":{"product":661}}}, // [Kate Spade] - {"hash":"96a8c3ab1740bf2f","prefixes":{"":{"product":97}}}, // [Tacoda] + {"hash":"0f2014a09acf7abd","prefixes":{"*":{"product":646,"type":1}}}, // [Facebook Connect] + {"hash":"b7c70898d90f5bb3","prefixes":{"*":{"product":646,"type":1}}}, // [Facebook Connect] + {"hash":"18562cb1149fda1e","prefixes":{"*":{"product":647,"type":1}}}, // [Disqus] + {"hash":"37b749b8858eb61b","prefixes":{"*":{"product":648,"type":0}}}, // [Namecheap.com] + {"hash":"3d59be0f5f7101a0","prefixes":{"":{"product":649,"type":1}}}, // [Polldaddy] + {"hash":"510cff549d2cb397","prefixes":{"":{"product":650,"type":1}}}, // [Outbrain Inc.] + {"hash":"e23ebc9959ce4873","prefixes":{"":{"product":650,"type":1}}}, // [Outbrain Inc.] + {"hash":"623fd0210b11d4fb","prefixes":{"":{"product":651,"type":0}}}, // [Lijit Networks, Inc.] + {"hash":"686b7accbfa398fa","prefixes":{"":{"product":651,"type":0}}}, // [Lijit Networks, Inc.] + {"hash":"85c44f0602598dd8","prefixes":{"":{"product":651,"type":0}}}, // [Lijit Networks, Inc.] + {"hash":"a107b1fdcffae5b9","prefixes":{"*":{"product":484,"type":0}}}, // [NetDNA, LLC] + {"hash":"7f37823a3f5c76b3","prefixes":{"*":{"product":652,"type":0}}}, // [PubMatic] + {"hash":"6d306315a1fecfda","prefixes":{"":{"product":653,"type":0}}}, // [Say Media Inc.] + {"hash":"c2568516b08f0d3d","prefixes":{"":{"product":653,"type":0}}}, // [Say Media Inc.] + {"hash":"308d3a8d1ca52ff3","prefixes":{"":{"product":653,"type":0}}}, // [Say Media Inc.] + {"hash":"59e488c5f151e7c3","prefixes":{"":{"product":653,"type":0}}}, // [Say Media Inc.] + {"hash":"7efe6908db5a1d44","prefixes":{"":{"product":654,"type":0}}}, // [Rubicon Project Turing, Inc. (SSP)] + {"hash":"c6ee8faaa7d6734c","prefixes":{"":{"product":655,"type":0}}}, // [Rubicon Project Edison, Inc. (DSP)] + {"hash":"d93c07cc68e53d91","prefixes":{"":{"product":655,"type":0}}}, // [Rubicon Project Edison, Inc. (DSP)] + {"hash":"86ae2b216def9790","prefixes":{"":{"product":655,"type":0}}}, // [Rubicon Project Edison, Inc. (DSP)] + {"hash":"1267f5857549a6ab","prefixes":{"":{"product":655,"type":0}}}, // [Rubicon Project Edison, Inc. (DSP)] + {"hash":"367db80c0776f6d8","prefixes":{"":{"product":655,"type":0}}}, // [Rubicon Project Edison, Inc. (DSP)] + {"hash":"c4c762a7e666da1c","prefixes":{"":{"product":655,"type":0}}}, // [Rubicon Project Edison, Inc. (DSP)] + {"hash":"bb66261f843823d5","prefixes":{"":{"product":656,"type":1}}}, // [Wordpress Stats] + {"hash":"a0f3bb8dcd67010e","prefixes":{"":{"product":656,"type":1}}}, // [Wordpress Stats] + {"hash":"4a423f1da960eda6","prefixes":{"*":{"product":657,"type":1}}}, // [Twitter] + {"hash":"465806fbb3547c25","prefixes":{"*":{"product":657,"type":1}}}, // [Twitter] + {"hash":"13c55ef8102cbdbb","prefixes":{"":{"product":658,"type":0}}}, // [Yandex LLC] + {"hash":"db546baba3acb079","prefixes":{"":{"product":658,"type":0}}}, // [Yandex LLC] + {"hash":"3dd0667dbad0af61","prefixes":{"":{"product":658,"type":0}}}, // [Yandex LLC] + {"hash":"78e224c91aabe6de","prefixes":{"":{"product":659,"type":0}}}, // [Rutarget / Segmento] + {"hash":"75acb8a5a60ef63d","prefixes":{"":{"product":659,"type":0}}}, // [Rutarget / Segmento] + {"hash":"6f7720a054c19a2b","prefixes":{"":{"product":659,"type":0}}}, // [Rutarget / Segmento] + {"hash":"dbd76c26579bf2b1","prefixes":{"":{"product":659,"type":0}}}, // [Rutarget / Segmento] + {"hash":"2cd7f311595e164e","prefixes":{"":{"product":659,"type":0}}}, // [Rutarget / Segmento] + {"hash":"b08380cf2fcb4415","prefixes":{"":{"product":659,"type":0}}}, // [Rutarget / Segmento] + {"hash":"59ac14277edec497","prefixes":{"":{"product":659,"type":0}}}, // [Rutarget / Segmento] + {"hash":"88893eeb26e546a0","prefixes":{"":{"product":659,"type":0}}}, // [Rutarget / Segmento] + {"hash":"da151dbe8b815dfb","prefixes":{"":{"product":660,"type":2}}}, // [Addoor LatinMarkets, SL] + {"hash":"b2a44f920e268749","prefixes":{"":{"product":661,"type":0}}}, // [Kate Spade] + {"hash":"96a8c3ab1740bf2f","prefixes":{"":{"product":97,"type":0}}}, // [Tacoda] {"hash":"95e85e3cbd858779","prefixes":{"":{"product":662}}}, // [TARGUSinfo] - {"hash":"dbf2963c9bf26f55","prefixes":{"":{"product":663}}}, // [Adblade] - {"hash":"8064758f6c80afed","prefixes":{"":{"product":663}}}, // [Adblade] - {"hash":"b7aaa083e4151ca8","prefixes":{"":{"product":663}}}, // [Adblade] - {"hash":"f4d5f13eb7d1ba2b","prefixes":{"":{"product":663}}}, // [Adblade] - {"hash":"eca68f2e6cd8a07e","prefixes":{"":{"product":664}}}, // [Adiant] - {"hash":"30f4c3f682592add","prefixes":{"":{"product":665}}}, // [AddToAny] + {"hash":"dbf2963c9bf26f55","prefixes":{"":{"product":663,"type":0}}}, // [Adblade] + {"hash":"8064758f6c80afed","prefixes":{"":{"product":663,"type":0}}}, // [Adblade] + {"hash":"b7aaa083e4151ca8","prefixes":{"":{"product":663,"type":0}}}, // [Adblade] + {"hash":"f4d5f13eb7d1ba2b","prefixes":{"":{"product":663,"type":0}}}, // [Adblade] + {"hash":"eca68f2e6cd8a07e","prefixes":{"":{"product":664,"type":0}}}, // [Adiant] + {"hash":"30f4c3f682592add","prefixes":{"":{"product":665,"type":1}}}, // [AddToAny] {"hash":"39b76d24e28075d4","prefixes":{"*":{"product":666}}}, // [Bizo Inc] - {"hash":"dabe4d73219c06e0","prefixes":{"":{"product":667}}}, // [Google Analytics] - {"hash":"f8c6758a214299be","prefixes":{"":{"product":668}}}, // [Gravatar] - {"hash":"0a130612d187bc06","prefixes":{"":{"product":668}}}, // [Gravatar] - {"hash":"6802f0145385df51","prefixes":{"":{"product":669}}}, // [MediaGlu] - {"hash":"ccbeaf028d3c721b","prefixes":{"":{"product":669}}}, // [MediaGlu] - {"hash":"1d7daeed381c33aa","prefixes":{"":{"product":669}}}, // [MediaGlu] - {"hash":"038b4d8cab2d2a58","prefixes":{"":{"product":669}}}, // [MediaGlu] - {"hash":"bd4919274e19987e","prefixes":{"":{"product":669}}}, // [MediaGlu] - {"hash":"dcdf95e5abf7c100","prefixes":{"":{"product":670}}}, // [Tapstream Network Inc.] - {"hash":"1f751fd80b11ad3c","prefixes":{"":{"product":671}}}, // [HUNT Mobile Ads] - {"hash":"de1c8591006ce969","prefixes":{"":{"product":672}}}, // [Apsalar, Inc.] - {"hash":"9fd29903977b5176","prefixes":{"":{"product":672}}}, // [Apsalar, Inc.] - {"hash":"c3930fc2f4cd70df","prefixes":{"*":{"product":673}}}, // [Videology DSP] - {"hash":"8924b56175f6f114","prefixes":{"":{"product":674}}}, // [Videostrip] - {"hash":"f4b2d76af9987952","prefixes":{"":{"product":675}}}, // [Affinity – Hostway Corporation] - {"hash":"b11ec5ee5b26491a","prefixes":{"*":{"product":241},"":{"product":676}}}, // [Scene Stealer Ltd.] [Rackspace, US Inc.] - {"hash":"5177084498d58bac","prefixes":{"":{"product":676}}}, // [Rackspace, US Inc.] - {"hash":"3a0fe0aeaa847996","prefixes":{"*":{"product":676}}}, // [Rackspace, US Inc.] - {"hash":"2b344a3d6c766cb7","prefixes":{"":{"product":676}}}, // [Rackspace, US Inc.] - {"hash":"a0b6774e583d1787","prefixes":{"":{"product":677}}}, // [Taptica] - {"hash":"e6ad999a7fc77500","prefixes":{"":{"product":241}}}, // [Scene Stealer Ltd.] - {"hash":"4056609d04bfec9c","prefixes":{"":{"product":241}}}, // [Scene Stealer Ltd.] - {"hash":"d1f59501d08f217a","prefixes":{"":{"product":241}}}, // [Scene Stealer Ltd.] - {"hash":"bd467d941e65225d","prefixes":{"":{"product":241}}}, // [Scene Stealer Ltd.] - {"hash":"0de83b2d387d2a84","prefixes":{"*":{"product":241}}}, // [Scene Stealer Ltd.] - {"hash":"227a1699196d5009","prefixes":{"":{"product":678}}}, // [LiveRamp, Inc.] - {"hash":"2077744d64232ddc","prefixes":{"":{"product":678}}}, // [LiveRamp, Inc.] - {"hash":"5ff42e5327d8c926","prefixes":{"":{"product":679}}}, // [Plista GmbH] - {"hash":"1d36941de87ee056","prefixes":{"":{"product":679}}}, // [Plista GmbH] - {"hash":"0534ec41ce34cced","prefixes":{"":{"product":679}}}, // [Plista GmbH] - {"hash":"c5ca32bf780ff41c","prefixes":{"":{"product":680}}}, // [Netquest Ad Tracking] - {"hash":"fcb4d508b7c17d00","prefixes":{"":{"product":681}}}, // [Mediasmart Mobile S.L.] - {"hash":"32de5cdddc7878d9","prefixes":{"":{"product":681}}}, // [Mediasmart Mobile S.L.] - {"hash":"832d7e03cfa50775","prefixes":{"":{"product":682}}}, // [Netshelter Technology Media, Inc.] - {"hash":"5d0747bdde7700a5","prefixes":{"":{"product":682}}}, // [Netshelter Technology Media, Inc.] - {"hash":"6cda89e3ca547147","prefixes":{"":{"product":682}}}, // [Netshelter Technology Media, Inc.] - {"hash":"6825c9c2052b6d49","prefixes":{"":{"product":682}}}, // [Netshelter Technology Media, Inc.] - {"hash":"dac91e433fa392a8","prefixes":{"":{"product":682}}}, // [Netshelter Technology Media, Inc.] - {"hash":"5112708cd650c1bf","prefixes":{"":{"product":682}}}, // [Netshelter Technology Media, Inc.] - {"hash":"8c56edbaad9d7666","prefixes":{"":{"product":682}}}, // [Netshelter Technology Media, Inc.] - {"hash":"e3f867313a3a22ff","prefixes":{"*":{"product":683}}}, // [Mixmarket Affiliate Network] - {"hash":"337d4f2254b699bd","prefixes":{"":{"product":683}}}, // [Mixmarket Affiliate Network] - {"hash":"7dd6cb3709637812","prefixes":{"*":{"product":684}}}, // [Turbobytes] - {"hash":"b42ea914a5e25208","prefixes":{"":{"product":685}}}, // [Voodoo Video AG] - {"hash":"441e902171e2e03a","prefixes":{"*":{"product":255}}}, // [Google CDN] - {"hash":"ed45a52fc3b3ded7","prefixes":{"*":{"product":255}}}, // [Google CDN] - {"hash":"b70fc2e7ac8321a4","prefixes":{"*":{"product":255}}}, // [Google CDN] - {"hash":"a7ab005368d54a08","prefixes":{"*":{"product":255}}}, // [Google CDN] - {"hash":"b3808fd8fb0b9d9b","prefixes":{"*":{"product":255}}}, // [Google CDN] - {"hash":"273fe37ef5880422","prefixes":{"lh":{"product":255},"geo":{"product":255}}}, // [Google CDN] [Google CDN] - {"hash":"cf71755ff09e2183","prefixes":{"":{"product":255}}}, // [Google CDN] - {"hash":"3a32bf25eec1a95b","prefixes":{"*":{"product":686}}}, // [Full Performance] + {"hash":"dabe4d73219c06e0","prefixes":{"":{"product":667,"type":1}}}, // [Google Analytics] + {"hash":"f8c6758a214299be","prefixes":{"":{"product":668,"type":1}}}, // [Gravatar] + {"hash":"0a130612d187bc06","prefixes":{"":{"product":668,"type":1}}}, // [Gravatar] + {"hash":"6802f0145385df51","prefixes":{"":{"product":669,"type":0}}}, // [MediaGlu] + {"hash":"ccbeaf028d3c721b","prefixes":{"":{"product":669,"type":0}}}, // [MediaGlu] + {"hash":"1d7daeed381c33aa","prefixes":{"":{"product":669,"type":0}}}, // [MediaGlu] + {"hash":"038b4d8cab2d2a58","prefixes":{"":{"product":669,"type":0}}}, // [MediaGlu] + {"hash":"bd4919274e19987e","prefixes":{"":{"product":669,"type":0}}}, // [MediaGlu] + {"hash":"dcdf95e5abf7c100","prefixes":{"":{"product":670,"type":0}}}, // [Tapstream Network Inc.] + {"hash":"1f751fd80b11ad3c","prefixes":{"":{"product":671,"type":0}}}, // [HUNT Mobile Ads] + {"hash":"de1c8591006ce969","prefixes":{"":{"product":672,"type":0}}}, // [Apsalar, Inc.] + {"hash":"9fd29903977b5176","prefixes":{"":{"product":672,"type":0}}}, // [Apsalar, Inc.] + {"hash":"c3930fc2f4cd70df","prefixes":{"*":{"product":673,"type":0}}}, // [Videology DSP] + {"hash":"8924b56175f6f114","prefixes":{"":{"product":674,"type":0}}}, // [Videostrip] + {"hash":"f4b2d76af9987952","prefixes":{"":{"product":675,"type":0}}}, // [Affinity – Hostway Corporation] + {"hash":"b11ec5ee5b26491a","prefixes":{"*":{"product":241,"type":0},"":{"product":676,"type":2}}}, // [Scene Stealer Ltd.] [Rackspace, US Inc.] + {"hash":"5177084498d58bac","prefixes":{"":{"product":676,"type":2}}}, // [Rackspace, US Inc.] + {"hash":"3a0fe0aeaa847996","prefixes":{"*":{"product":676,"type":2}}}, // [Rackspace, US Inc.] + {"hash":"2b344a3d6c766cb7","prefixes":{"":{"product":676,"type":2}}}, // [Rackspace, US Inc.] + {"hash":"a0b6774e583d1787","prefixes":{"":{"product":677,"type":0}}}, // [Taptica] + {"hash":"e6ad999a7fc77500","prefixes":{"":{"product":241,"type":0}}}, // [Scene Stealer Ltd.] + {"hash":"4056609d04bfec9c","prefixes":{"":{"product":241,"type":0}}}, // [Scene Stealer Ltd.] + {"hash":"d1f59501d08f217a","prefixes":{"":{"product":241,"type":0}}}, // [Scene Stealer Ltd.] + {"hash":"bd467d941e65225d","prefixes":{"":{"product":241,"type":0}}}, // [Scene Stealer Ltd.] + {"hash":"0de83b2d387d2a84","prefixes":{"*":{"product":241,"type":0}}}, // [Scene Stealer Ltd.] + {"hash":"227a1699196d5009","prefixes":{"":{"product":678,"type":1}}}, // [LiveRamp, Inc.] + {"hash":"2077744d64232ddc","prefixes":{"":{"product":678,"type":1}}}, // [LiveRamp, Inc.] + {"hash":"5ff42e5327d8c926","prefixes":{"":{"product":679,"type":0}}}, // [Plista GmbH] + {"hash":"1d36941de87ee056","prefixes":{"":{"product":679,"type":0}}}, // [Plista GmbH] + {"hash":"0534ec41ce34cced","prefixes":{"":{"product":679,"type":0}}}, // [Plista GmbH] + {"hash":"c5ca32bf780ff41c","prefixes":{"":{"product":680,"type":1}}}, // [Netquest Ad Tracking] + {"hash":"fcb4d508b7c17d00","prefixes":{"":{"product":681,"type":0}}}, // [Mediasmart Mobile S.L.] + {"hash":"32de5cdddc7878d9","prefixes":{"":{"product":681,"type":0}}}, // [Mediasmart Mobile S.L.] + {"hash":"832d7e03cfa50775","prefixes":{"":{"product":682,"type":0}}}, // [Netshelter Technology Media, Inc.] + {"hash":"5d0747bdde7700a5","prefixes":{"":{"product":682,"type":0}}}, // [Netshelter Technology Media, Inc.] + {"hash":"6cda89e3ca547147","prefixes":{"":{"product":682,"type":0}}}, // [Netshelter Technology Media, Inc.] + {"hash":"6825c9c2052b6d49","prefixes":{"":{"product":682,"type":0}}}, // [Netshelter Technology Media, Inc.] + {"hash":"dac91e433fa392a8","prefixes":{"":{"product":682,"type":0}}}, // [Netshelter Technology Media, Inc.] + {"hash":"5112708cd650c1bf","prefixes":{"":{"product":682,"type":0}}}, // [Netshelter Technology Media, Inc.] + {"hash":"8c56edbaad9d7666","prefixes":{"":{"product":682,"type":0}}}, // [Netshelter Technology Media, Inc.] + {"hash":"e3f867313a3a22ff","prefixes":{"*":{"product":683,"type":0}}}, // [Mixmarket Affiliate Network] + {"hash":"337d4f2254b699bd","prefixes":{"":{"product":683,"type":0}}}, // [Mixmarket Affiliate Network] + {"hash":"7dd6cb3709637812","prefixes":{"*":{"product":684,"type":0}}}, // [Turbobytes] + {"hash":"b42ea914a5e25208","prefixes":{"":{"product":685,"type":0}}}, // [Voodoo Video AG] + {"hash":"441e902171e2e03a","prefixes":{"*":{"product":255,"type":2}}}, // [Google CDN] + {"hash":"ed45a52fc3b3ded7","prefixes":{"*":{"product":255,"type":2}}}, // [Google CDN] + {"hash":"b70fc2e7ac8321a4","prefixes":{"*":{"product":255,"type":2}}}, // [Google CDN] + {"hash":"a7ab005368d54a08","prefixes":{"*":{"product":255,"type":2}}}, // [Google CDN] + {"hash":"b3808fd8fb0b9d9b","prefixes":{"*":{"product":255,"type":2}}}, // [Google CDN] + {"hash":"273fe37ef5880422","prefixes":{"lh":{"product":255,"type":2},"geo":{"product":255,"type":2}}}, // [Google CDN] [Google CDN] + {"hash":"cf71755ff09e2183","prefixes":{"":{"product":255,"type":2}}}, // [Google CDN] + {"hash":"3a32bf25eec1a95b","prefixes":{"*":{"product":686,"type":1}}}, // [Full Performance] {"hash":"783c5679a80d5c10","prefixes":{"":{"product":687}}}, // [eXelate Inc.] {"hash":"40f709f76b1af3f1","prefixes":{"":{"product":687}}}, // [eXelate Inc.] - {"hash":"a97762efe739bb85","prefixes":{"*":{"product":688}}}, // [Oreck Canada] - {"hash":"f3460c4c9a5112cc","prefixes":{"":{"product":689}}}, // [Beijing WuShuang Technology Ltd. (AGrant)] - {"hash":"1c1f6d178312c71a","prefixes":{"*":{"product":690}}}, // [Limelight] - {"hash":"227010fe11d13050","prefixes":{"":{"product":691}}}, // [Aniview LTD.] + {"hash":"a97762efe739bb85","prefixes":{"*":{"product":688,"type":0}}}, // [Oreck Canada] + {"hash":"f3460c4c9a5112cc","prefixes":{"":{"product":689,"type":0}}}, // [Beijing WuShuang Technology Ltd. (AGrant)] + {"hash":"1c1f6d178312c71a","prefixes":{"*":{"product":690,"type":0}}}, // [Limelight] + {"hash":"227010fe11d13050","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] {"hash":"5460e19d75ae0d01","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"f132b41fc3fed2c5","prefixes":{"":{"product":692}}}, // [Matomy Media] - {"hash":"930103c79d1886c9","prefixes":{"":{"product":693}}}, // [Mail.Ru Group] - {"hash":"befa931c2b772e6d","prefixes":{"":{"product":693}}}, // [Mail.Ru Group] - {"hash":"e1a46a5a294589c8","prefixes":{"":{"product":693}}}, // [Mail.Ru Group] - {"hash":"7aaf1724444529c4","prefixes":{"":{"product":693}}}, // [Mail.Ru Group] - {"hash":"a8e6cfd540b8a74b","prefixes":{"":{"product":693}}}, // [Mail.Ru Group] - {"hash":"4dd30b722c120fe4","prefixes":{"":{"product":693}}}, // [Mail.Ru Group] - {"hash":"5785365f3a4da9e4","prefixes":{"":{"product":693}}}, // [Mail.Ru Group] - {"hash":"b4cbadcc4ab58981","prefixes":{"":{"product":694}}}, // [LSi - Lionsoft Studios, spol. s r.o.] - {"hash":"a41a0099a363da99","prefixes":{"":{"product":695}}}, // [Adelphic Inc.] - {"hash":"9a9d3ceef9c489c7","prefixes":{"":{"product":695}}}, // [Adelphic Inc.] - {"hash":"8c652e1d454ab3a2","prefixes":{"":{"product":695}}}, // [Adelphic Inc.] - {"hash":"36e0703b50fb3eed","prefixes":{"":{"product":695}}}, // [Adelphic Inc.] - {"hash":"a437c97b4d64cafd","prefixes":{"":{"product":696}}}, // [Lincoln Technical Institute, Inc.] - {"hash":"f69a68a2d09d0720","prefixes":{"":{"product":697}}}, // [Smartstream.tv] - {"hash":"26dfb2b8bad92f4f","prefixes":{"":{"product":697}}}, // [Smartstream.tv] - {"hash":"dc67b62ecf5a9b08","prefixes":{"":{"product":697}}}, // [Smartstream.tv] - {"hash":"23b6f2b40a209645","prefixes":{"":{"product":697}}}, // [Smartstream.tv] - {"hash":"40536f7cc3f3bcdb","prefixes":{"":{"product":697}}}, // [Smartstream.tv] - {"hash":"7eab1c802c1cb708","prefixes":{"*":{"product":697}}}, // [Smartstream.tv] - {"hash":"8381e43653c976d7","prefixes":{"":{"product":697}}}, // [Smartstream.tv] - {"hash":"010611867004fb28","prefixes":{"":{"product":698}}}, // [Reklamport] - {"hash":"8c138e749437f931","prefixes":{"":{"product":698}}}, // [Reklamport] - {"hash":"735ef6cfbe0d0549","prefixes":{"":{"product":699}}}, // [Fattext LLC (DBA Moolah Media)] - {"hash":"7a17aa6bfdfb3de1","prefixes":{"":{"product":699}}}, // [Fattext LLC (DBA Moolah Media)] - {"hash":"3c593814e40d8a9e","prefixes":{"":{"product":700}}}, // [MoGo Marketing & Media Inc.] - {"hash":"0f36027c1644631a","prefixes":{"":{"product":701}}}, // [SA Media, llc] - {"hash":"ec8b441e84a18442","prefixes":{"":{"product":701}}}, // [SA Media, llc] - {"hash":"b923ca8213dfa24a","prefixes":{"":{"product":701}}}, // [SA Media, llc] - {"hash":"fe0b93fc6d0ad89a","prefixes":{"":{"product":701}}}, // [SA Media, llc] - {"hash":"b7164c05e2fb0d2f","prefixes":{"":{"product":701}}}, // [SA Media, llc] - {"hash":"6e085b0ec37b404f","prefixes":{"":{"product":701}}}, // [SA Media, llc] - {"hash":"d282ecf2666110dd","prefixes":{"":{"product":701}}}, // [SA Media, llc] - {"hash":"131054b9a54841da","prefixes":{"":{"product":701}}}, // [SA Media, llc] - {"hash":"556351c03849a4c1","prefixes":{"":{"product":701}}}, // [SA Media, llc] - {"hash":"bebf7033727205d4","prefixes":{"":{"product":701}}}, // [SA Media, llc] - {"hash":"e77b9add119d1d72","prefixes":{"":{"product":701}}}, // [SA Media, llc] - {"hash":"fbcb122264bcdbda","prefixes":{"":{"product":701}}}, // [SA Media, llc] - {"hash":"10f64b8265e0b1be","prefixes":{"":{"product":702}}}, // [Barons Media LLC] - {"hash":"cc468e0676f36482","prefixes":{"":{"product":702}}}, // [Barons Media LLC] - {"hash":"a445930c60af8d98","prefixes":{"":{"product":702}}}, // [Barons Media LLC] - {"hash":"63e594feafaae08b","prefixes":{"":{"product":702}}}, // [Barons Media LLC] - {"hash":"045d86072bc5dc10","prefixes":{"":{"product":702}}}, // [Barons Media LLC] - {"hash":"ea9d0ea08d06528d","prefixes":{"":{"product":702}}}, // [Barons Media LLC] - {"hash":"94bc93c21ca5d014","prefixes":{"":{"product":702}}}, // [Barons Media LLC] - {"hash":"bcfa082cf700866c","prefixes":{"":{"product":702}}}, // [Barons Media LLC] - {"hash":"17f352a8e88349c9","prefixes":{"":{"product":702}}}, // [Barons Media LLC] - {"hash":"8b18a83b14ef8906","prefixes":{"":{"product":703}}}, // [apprupt GmbH] - {"hash":"46ba596945892a31","prefixes":{"":{"product":703}}}, // [apprupt GmbH] - {"hash":"b0780943092b032a","prefixes":{"":{"product":703}}}, // [apprupt GmbH] - {"hash":"7d76822bfe9ffcd9","prefixes":{"":{"product":703}}}, // [apprupt GmbH] - {"hash":"87582b95561cf002","prefixes":{"":{"product":703}}}, // [apprupt GmbH] - {"hash":"eb0a0cd03ec7f57b","prefixes":{"":{"product":704}}}, // [PropellerADs media Ltd] - {"hash":"73009a8d32988e92","prefixes":{"*":{"product":705}}}, // [CJ Affiliate by Conversant] - {"hash":"698b1ec9df8d6759","prefixes":{"*":{"product":705}}}, // [CJ Affiliate by Conversant] - {"hash":"00e17f99243707e9","prefixes":{"":{"product":706}}}, // [Millennial Media Inc] - {"hash":"62ddc5a87d328e5a","prefixes":{"":{"product":706}}}, // [Millennial Media Inc] - {"hash":"0e02d11afea79a5e","prefixes":{"":{"product":707}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] - {"hash":"56b1e984216b464b","prefixes":{"":{"product":707}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] - {"hash":"815a3c2c1ed6f999","prefixes":{"":{"product":707}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] - {"hash":"28175ac65441fbce","prefixes":{"":{"product":707}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] - {"hash":"fe775b2f045dcced","prefixes":{"":{"product":707}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] - {"hash":"d47b0a700d84bfba","prefixes":{"":{"product":707}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] - {"hash":"1c34827419405aee","prefixes":{"":{"product":707}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] - {"hash":"7e99ada6b2533f54","prefixes":{"":{"product":707}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] - {"hash":"2c5ac4af628363a6","prefixes":{"*":{"product":708}}}, // [Manage.com Group, Inc.] + {"hash":"f132b41fc3fed2c5","prefixes":{"":{"product":692,"type":2}}}, // [Matomy Media] + {"hash":"930103c79d1886c9","prefixes":{"":{"product":693,"type":0}}}, // [Mail.Ru Group] + {"hash":"befa931c2b772e6d","prefixes":{"":{"product":693,"type":0}}}, // [Mail.Ru Group] + {"hash":"e1a46a5a294589c8","prefixes":{"":{"product":693,"type":0}}}, // [Mail.Ru Group] + {"hash":"7aaf1724444529c4","prefixes":{"":{"product":693,"type":0}}}, // [Mail.Ru Group] + {"hash":"a8e6cfd540b8a74b","prefixes":{"":{"product":693,"type":0}}}, // [Mail.Ru Group] + {"hash":"4dd30b722c120fe4","prefixes":{"":{"product":693,"type":0}}}, // [Mail.Ru Group] + {"hash":"5785365f3a4da9e4","prefixes":{"":{"product":693,"type":0}}}, // [Mail.Ru Group] + {"hash":"b4cbadcc4ab58981","prefixes":{"":{"product":694,"type":0}}}, // [LSi - Lionsoft Studios, spol. s r.o.] + {"hash":"a41a0099a363da99","prefixes":{"":{"product":695,"type":0}}}, // [Adelphic Inc.] + {"hash":"9a9d3ceef9c489c7","prefixes":{"":{"product":695,"type":0}}}, // [Adelphic Inc.] + {"hash":"8c652e1d454ab3a2","prefixes":{"":{"product":695,"type":0}}}, // [Adelphic Inc.] + {"hash":"36e0703b50fb3eed","prefixes":{"":{"product":695,"type":0}}}, // [Adelphic Inc.] + {"hash":"a437c97b4d64cafd","prefixes":{"":{"product":696,"type":0}}}, // [Lincoln Technical Institute, Inc.] + {"hash":"f69a68a2d09d0720","prefixes":{"":{"product":697,"type":0}}}, // [Smartstream.tv] + {"hash":"26dfb2b8bad92f4f","prefixes":{"":{"product":697,"type":0}}}, // [Smartstream.tv] + {"hash":"dc67b62ecf5a9b08","prefixes":{"":{"product":697,"type":0}}}, // [Smartstream.tv] + {"hash":"23b6f2b40a209645","prefixes":{"":{"product":697,"type":0}}}, // [Smartstream.tv] + {"hash":"40536f7cc3f3bcdb","prefixes":{"":{"product":697,"type":0}}}, // [Smartstream.tv] + {"hash":"7eab1c802c1cb708","prefixes":{"*":{"product":697,"type":0}}}, // [Smartstream.tv] + {"hash":"8381e43653c976d7","prefixes":{"":{"product":697,"type":0}}}, // [Smartstream.tv] + {"hash":"010611867004fb28","prefixes":{"":{"product":698,"type":0}}}, // [Reklamport] + {"hash":"8c138e749437f931","prefixes":{"":{"product":698,"type":0}}}, // [Reklamport] + {"hash":"735ef6cfbe0d0549","prefixes":{"":{"product":699,"type":0}}}, // [Fattext LLC (DBA Moolah Media)] + {"hash":"7a17aa6bfdfb3de1","prefixes":{"":{"product":699,"type":0}}}, // [Fattext LLC (DBA Moolah Media)] + {"hash":"3c593814e40d8a9e","prefixes":{"":{"product":700,"type":0}}}, // [MoGo Marketing & Media Inc.] + {"hash":"0f36027c1644631a","prefixes":{"":{"product":701,"type":0}}}, // [SA Media, llc] + {"hash":"ec8b441e84a18442","prefixes":{"":{"product":701,"type":0}}}, // [SA Media, llc] + {"hash":"b923ca8213dfa24a","prefixes":{"":{"product":701,"type":0}}}, // [SA Media, llc] + {"hash":"fe0b93fc6d0ad89a","prefixes":{"":{"product":701,"type":0}}}, // [SA Media, llc] + {"hash":"b7164c05e2fb0d2f","prefixes":{"":{"product":701,"type":0}}}, // [SA Media, llc] + {"hash":"6e085b0ec37b404f","prefixes":{"":{"product":701,"type":0}}}, // [SA Media, llc] + {"hash":"d282ecf2666110dd","prefixes":{"":{"product":701,"type":0}}}, // [SA Media, llc] + {"hash":"131054b9a54841da","prefixes":{"":{"product":701,"type":1}}}, // [SA Media, llc] + {"hash":"556351c03849a4c1","prefixes":{"":{"product":701,"type":1}}}, // [SA Media, llc] + {"hash":"bebf7033727205d4","prefixes":{"":{"product":701,"type":0}}}, // [SA Media, llc] + {"hash":"e77b9add119d1d72","prefixes":{"":{"product":701,"type":0}}}, // [SA Media, llc] + {"hash":"fbcb122264bcdbda","prefixes":{"":{"product":701,"type":0}}}, // [SA Media, llc] + {"hash":"10f64b8265e0b1be","prefixes":{"":{"product":702,"type":0}}}, // [Barons Media LLC] + {"hash":"cc468e0676f36482","prefixes":{"":{"product":702,"type":0}}}, // [Barons Media LLC] + {"hash":"a445930c60af8d98","prefixes":{"":{"product":702,"type":0}}}, // [Barons Media LLC] + {"hash":"63e594feafaae08b","prefixes":{"":{"product":702,"type":0}}}, // [Barons Media LLC] + {"hash":"045d86072bc5dc10","prefixes":{"":{"product":702,"type":0}}}, // [Barons Media LLC] + {"hash":"ea9d0ea08d06528d","prefixes":{"":{"product":702,"type":0}}}, // [Barons Media LLC] + {"hash":"94bc93c21ca5d014","prefixes":{"":{"product":702,"type":0}}}, // [Barons Media LLC] + {"hash":"bcfa082cf700866c","prefixes":{"":{"product":702,"type":0}}}, // [Barons Media LLC] + {"hash":"17f352a8e88349c9","prefixes":{"":{"product":702,"type":0}}}, // [Barons Media LLC] + {"hash":"8b18a83b14ef8906","prefixes":{"":{"product":703,"type":0}}}, // [apprupt GmbH] + {"hash":"46ba596945892a31","prefixes":{"":{"product":703,"type":0}}}, // [apprupt GmbH] + {"hash":"b0780943092b032a","prefixes":{"":{"product":703,"type":0}}}, // [apprupt GmbH] + {"hash":"7d76822bfe9ffcd9","prefixes":{"":{"product":703,"type":0}}}, // [apprupt GmbH] + {"hash":"87582b95561cf002","prefixes":{"":{"product":703,"type":0}}}, // [apprupt GmbH] + {"hash":"eb0a0cd03ec7f57b","prefixes":{"":{"product":704,"type":0}}}, // [PropellerADs media Ltd] + {"hash":"73009a8d32988e92","prefixes":{"*":{"product":705,"type":0}}}, // [CJ Affiliate by Conversant] + {"hash":"698b1ec9df8d6759","prefixes":{"*":{"product":705,"type":0}}}, // [CJ Affiliate by Conversant] + {"hash":"00e17f99243707e9","prefixes":{"":{"product":706,"type":0}}}, // [Millennial Media Inc] + {"hash":"62ddc5a87d328e5a","prefixes":{"":{"product":706,"type":0}}}, // [Millennial Media Inc] + {"hash":"0e02d11afea79a5e","prefixes":{"":{"product":707,"type":0}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] + {"hash":"56b1e984216b464b","prefixes":{"":{"product":707,"type":0}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] + {"hash":"815a3c2c1ed6f999","prefixes":{"":{"product":707,"type":0}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] + {"hash":"28175ac65441fbce","prefixes":{"":{"product":707,"type":0}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] + {"hash":"fe775b2f045dcced","prefixes":{"":{"product":707,"type":0}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] + {"hash":"d47b0a700d84bfba","prefixes":{"":{"product":707,"type":0}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] + {"hash":"1c34827419405aee","prefixes":{"":{"product":707,"type":0}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] + {"hash":"7e99ada6b2533f54","prefixes":{"":{"product":707,"type":0}}}, // [BEIJING BEHE SCIENCE & TECHNOLOGY Co., Ltd] + {"hash":"2c5ac4af628363a6","prefixes":{"*":{"product":708,"type":0}}}, // [Manage.com Group, Inc.] {"hash":"f05737fe4b72d22f","prefixes":{"":{"product":709}}}, // [CloudFlare, Inc.] - {"hash":"1b728798f387160d","prefixes":{"":{"product":710}}}, // [MASSMOTIONMEDIA SARL] - {"hash":"fb80c91c77673741","prefixes":{"":{"product":711}}}, // [Brainworks Sp. z.o.o.] - {"hash":"6ff7dff7c1404e1b","prefixes":{"":{"product":711}}}, // [Brainworks Sp. z.o.o.] - {"hash":"bd6c259e3bb98101","prefixes":{"":{"product":711}}}, // [Brainworks Sp. z.o.o.] - {"hash":"0dcb02764319e823","prefixes":{"":{"product":711}}}, // [Brainworks Sp. z.o.o.] - {"hash":"258ec0f081f1c767","prefixes":{"":{"product":711}}}, // [Brainworks Sp. z.o.o.] - {"hash":"518594f7ef9754dc","prefixes":{"*":{"product":712}}}, // [Media Intelligence Platform (Aggregate Knowledge)] - {"hash":"223b1b79a6de9f04","prefixes":{"*":{"product":712}}}, // [Media Intelligence Platform (Aggregate Knowledge)] - {"hash":"848f45768ee0ad4e","prefixes":{"":{"product":713}}}, // [S4M] - {"hash":"77b7e5f4ec17a6e5","prefixes":{"":{"product":713}}}, // [S4M] - {"hash":"f965c1f8d2cce837","prefixes":{"":{"product":713}}}, // [S4M] - {"hash":"3e327352cea146b3","prefixes":{"":{"product":713}}}, // [S4M] - {"hash":"0658ca5e4baec224","prefixes":{"":{"product":713}}}, // [S4M] - {"hash":"f2e7a2604319636b","prefixes":{"":{"product":713}}}, // [S4M] + {"hash":"1b728798f387160d","prefixes":{"":{"product":710,"type":0}}}, // [MASSMOTIONMEDIA SARL] + {"hash":"fb80c91c77673741","prefixes":{"":{"product":711,"type":0}}}, // [Brainworks Sp. z.o.o.] + {"hash":"6ff7dff7c1404e1b","prefixes":{"":{"product":711,"type":0}}}, // [Brainworks Sp. z.o.o.] + {"hash":"bd6c259e3bb98101","prefixes":{"":{"product":711,"type":0}}}, // [Brainworks Sp. z.o.o.] + {"hash":"0dcb02764319e823","prefixes":{"":{"product":711,"type":0}}}, // [Brainworks Sp. z.o.o.] + {"hash":"258ec0f081f1c767","prefixes":{"":{"product":711,"type":0}}}, // [Brainworks Sp. z.o.o.] + {"hash":"518594f7ef9754dc","prefixes":{"*":{"product":712,"type":1}}}, // [Media Intelligence Platform (Aggregate Knowledge)] + {"hash":"223b1b79a6de9f04","prefixes":{"*":{"product":712,"type":1}}}, // [Media Intelligence Platform (Aggregate Knowledge)] + {"hash":"848f45768ee0ad4e","prefixes":{"":{"product":713,"type":0}}}, // [S4M] + {"hash":"77b7e5f4ec17a6e5","prefixes":{"":{"product":713,"type":0}}}, // [S4M] + {"hash":"f965c1f8d2cce837","prefixes":{"":{"product":713,"type":0}}}, // [S4M] + {"hash":"3e327352cea146b3","prefixes":{"":{"product":713,"type":0}}}, // [S4M] + {"hash":"0658ca5e4baec224","prefixes":{"":{"product":713,"type":0}}}, // [S4M] + {"hash":"f2e7a2604319636b","prefixes":{"":{"product":713,"type":0}}}, // [S4M] {"hash":"c825977950596abc","prefixes":{"":{"product":713}}}, // [S4M] {"hash":"b55fc4c23b864e56","prefixes":{"":{"product":713}}}, // [S4M] - {"hash":"3eddbbcdb5a13a1b","prefixes":{"":{"product":714}}}, // [Sobmag LTD] - {"hash":"f133f36dd9e9688d","prefixes":{"":{"product":714}}}, // [Sobmag LTD] - {"hash":"06ead346af8ecc6d","prefixes":{"":{"product":714}}}, // [Sobmag LTD] - {"hash":"16a442ad35246027","prefixes":{"":{"product":714}}}, // [Sobmag LTD] - {"hash":"778068a948335ee6","prefixes":{"":{"product":714}}}, // [Sobmag LTD] - {"hash":"2bb088766e0a77ce","prefixes":{"":{"product":714}}}, // [Sobmag LTD] - {"hash":"f54b41faf3e29ddb","prefixes":{"":{"product":714}}}, // [Sobmag LTD] - {"hash":"3d71c7985374fc62","prefixes":{"":{"product":714}}}, // [Sobmag LTD] - {"hash":"de336679348d46a5","prefixes":{"":{"product":714}}}, // [Sobmag LTD] - {"hash":"6818fc4cb694f0d4","prefixes":{"*":{"product":715}}}, // [Netbooster] - {"hash":"5682fbd14ad230ca","prefixes":{"":{"product":716}}}, // [Musikhaus Thomann e.K.] - {"hash":"abbb14ff2ab0311d","prefixes":{"":{"product":716}}}, // [Musikhaus Thomann e.K.] - {"hash":"578726cfc508157e","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"a141aaa30beb2f05","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"9161fa28951da89a","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"2e52f74b27e9eb2f","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"0ecdef2f55913790","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"409546c7e7a9ce63","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"3dceafc40a01cd8c","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"e748a008fcd2910c","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"499e3537aead5990","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"aad99655e792b7af","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"df381181135b37f3","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"49fe77e073f907d5","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"fe445db4579e7177","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"f7038d35f22c32db","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"184913b8eec78f63","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"4db6f08af3d6cf66","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"0a71646e475ff9c1","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"7847dd8c5608a507","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"cde33b0511f42c7c","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"6a5ae5d2380647dc","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"0821cc1422e91328","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"0e157baa999502bc","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"cb93fe6df3fe4097","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"657c19e08d899173","prefixes":{"":{"product":146}}}, // [SiteScout AdServer] - {"hash":"e411fd988f243d89","prefixes":{"":{"product":717}}}, // [Trovit] - {"hash":"1ea512003540106b","prefixes":{"":{"product":717}}}, // [Trovit] - {"hash":"48255f09ec2021d3","prefixes":{"":{"product":717}}}, // [Trovit] - {"hash":"7b5b7cfa3d62a886","prefixes":{"":{"product":717}}}, // [Trovit] - {"hash":"1235b8279a106276","prefixes":{"":{"product":718}}}, // [O2online] - {"hash":"cf76706eea2f0be6","prefixes":{"":{"product":719}}}, // [E-Plus Mobilfunk GmbH & Co. KG] - {"hash":"766b747f8dec4417","prefixes":{"":{"product":720}}}, // [Meteora] - {"hash":"270677f86b7f115b","prefixes":{"":{"product":720}}}, // [Meteora] - {"hash":"0a500f94a8a562f0","prefixes":{"":{"product":721}}}, // [Madison Logic, Inc.] - {"hash":"764d3a17a9512438","prefixes":{"":{"product":721}}}, // [Madison Logic, Inc.] - {"hash":"38c3aac1b79f0478","prefixes":{"":{"product":721}}}, // [Madison Logic, Inc.] - {"hash":"babcc401d384553f","prefixes":{"":{"product":722}}}, // [万相DSP(IZP Technologies)] - {"hash":"2ddae58a55ab72ef","prefixes":{"":{"product":722}}}, // [万相DSP(IZP Technologies)] - {"hash":"db564708d2871d3a","prefixes":{"":{"product":722}}}, // [万相DSP(IZP Technologies)] - {"hash":"a4199cfcbe70d7f5","prefixes":{"":{"product":722}}}, // [万相DSP(IZP Technologies)] - {"hash":"e6f5851275bc1fb3","prefixes":{"":{"product":722}}}, // [万相DSP(IZP Technologies)] - {"hash":"16e6d7e84ad7fa3a","prefixes":{"":{"product":722}}}, // [万相DSP(IZP Technologies)] - {"hash":"58ae73a3bb4327d7","prefixes":{"":{"product":722}}}, // [万相DSP(IZP Technologies)] - {"hash":"366a0ad35670aef5","prefixes":{"":{"product":722}}}, // [万相DSP(IZP Technologies)] - {"hash":"5b30682b9dfa7060","prefixes":{"":{"product":722}}}, // [万相DSP(IZP Technologies)] - {"hash":"67128a22cdd1a7cd","prefixes":{"":{"product":23}}}, // [AppNexus Open AdStream] - {"hash":"db56992e1a1a3f90","prefixes":{"":{"product":723}}}, // [righTarget] - {"hash":"479ab75d77a40d72","prefixes":{"":{"product":723}}}, // [righTarget] - {"hash":"17bcd2af46fb1fe6","prefixes":{"":{"product":723}}}, // [righTarget] - {"hash":"45681f09a76fe33e","prefixes":{"":{"product":724}}}, // [e.QQ.com] - {"hash":"612f6aab80bc21df","prefixes":{"":{"product":724}}}, // [e.QQ.com] - {"hash":"ab7e80409519ca9d","prefixes":{"":{"product":724}}}, // [e.QQ.com] - {"hash":"a3ae7b8a84f28040","prefixes":{"":{"product":724}}}, // [e.QQ.com] - {"hash":"b25f21b316565014","prefixes":{"":{"product":724}}}, // [e.QQ.com] - {"hash":"cc9eeba2126e4261","prefixes":{"":{"product":724}}}, // [e.QQ.com] - {"hash":"9d4819b235a5272b","prefixes":{"":{"product":724}}}, // [e.QQ.com] - {"hash":"78bb032f283d8f48","prefixes":{"":{"product":725}}}, // [Shen Zhen ShiJi KaiXuan Technology Company Ltd.] - {"hash":"de11a5b150526c21","prefixes":{"":{"product":725}}}, // [Shen Zhen ShiJi KaiXuan Technology Company Ltd.] - {"hash":"bbd9e4a668c4e348","prefixes":{"":{"product":725}}}, // [Shen Zhen ShiJi KaiXuan Technology Company Ltd.] - {"hash":"c38a1d9eab08d787","prefixes":{"*":{"product":724}}}, // [e.QQ.com] - {"hash":"5b2c8d90176bd14e","prefixes":{"":{"product":724}}}, // [e.QQ.com] - {"hash":"62980dc2fa42e1e0","prefixes":{"*":{"product":724}}}, // [e.QQ.com] - {"hash":"9b37bab01bf28d39","prefixes":{"*":{"product":726}}}, // [Bannercockpit] - {"hash":"01ec60ee4671b195","prefixes":{"":{"product":727}}}, // [Outrigger Media Inc.] - {"hash":"4be86c0a73547960","prefixes":{"":{"product":727}}}, // [Outrigger Media Inc.] - {"hash":"e3ab574adac96838","prefixes":{"":{"product":105}}}, // [Rockabox Media Ltd] - {"hash":"91bb53a0f22994f8","prefixes":{"":{"product":105}}}, // [Rockabox Media Ltd] - {"hash":"fd65eb28a70ed09a","prefixes":{"":{"product":105}}}, // [Rockabox Media Ltd] - {"hash":"9f41f821ddcb5092","prefixes":{"":{"product":105}}}, // [Rockabox Media Ltd] - {"hash":"ee70168f83fb2cce","prefixes":{"":{"product":105}}}, // [Rockabox Media Ltd] - {"hash":"c15fc4a18b25e6d3","prefixes":{"":{"product":105}}}, // [Rockabox Media Ltd] - {"hash":"f5f66dfaf3d2d2a3","prefixes":{"":{"product":105}}}, // [Rockabox Media Ltd] - {"hash":"e6e8716836c8a21d","prefixes":{"":{"product":105}}}, // [Rockabox Media Ltd] - {"hash":"da37db68457e2782","prefixes":{"*":{"product":728}}}, // [shopLocal] - {"hash":"ab8c1ee046adfbb1","prefixes":{"*":{"product":729}}}, // [Impact Radius] - {"hash":"0e8c1ff7462c1084","prefixes":{"*":{"product":729}}}, // [Impact Radius] - {"hash":"8f228d8317e4718d","prefixes":{"":{"product":729}}}, // [Impact Radius] - {"hash":"29d7e31af4b1be0b","prefixes":{"":{"product":730}}}, // [Unister AdServer] - {"hash":"efeab3df1fe3849a","prefixes":{"":{"product":730}}}, // [Unister AdServer] - {"hash":"8f2fea31a1c79b34","prefixes":{"":{"product":730}}}, // [Unister AdServer] - {"hash":"9cda8eeaf1e150bf","prefixes":{"":{"product":730}}}, // [Unister AdServer] - {"hash":"714091c1b8581de0","prefixes":{"":{"product":731}}}, // [Unister Media GmbH] - {"hash":"c7002b2b9e4b5370","prefixes":{"":{"product":730}}}, // [Unister AdServer] - {"hash":"1802591342537dae","prefixes":{"":{"product":730}}}, // [Unister AdServer] - {"hash":"787cbd14bb54b647","prefixes":{"":{"product":730}}}, // [Unister AdServer] - {"hash":"084ef5666af6a26c","prefixes":{"":{"product":730}}}, // [Unister AdServer] - {"hash":"df72b5eb4be388d1","prefixes":{"":{"product":732}}}, // [TLV Media Online Ltd] - {"hash":"64ffcabaf6ec2bcf","prefixes":{"":{"product":733}}}, // [d3media AG] - {"hash":"a6d58332a182c9f4","prefixes":{"":{"product":733}}}, // [d3media AG] - {"hash":"0bbd108959983b32","prefixes":{"":{"product":734}}}, // [Innovative Metrics] - {"hash":"80eab7dfc5e4cc5f","prefixes":{"*":{"product":735}}}, // [AthenaHealth] - {"hash":"131ce36599fa0d6c","prefixes":{"":{"product":736}}}, // [TAPVALUE SAS] - {"hash":"9181181a015040bc","prefixes":{"":{"product":736}}}, // [TAPVALUE SAS] - {"hash":"fca830abc4829657","prefixes":{"":{"product":736}}}, // [TAPVALUE SAS] - {"hash":"e78333a733c1b05a","prefixes":{"":{"product":736}}}, // [TAPVALUE SAS] - {"hash":"3f82423bd28a526a","prefixes":{"":{"product":736}}}, // [TAPVALUE SAS] - {"hash":"f2da501e4086afa3","prefixes":{"":{"product":736}}}, // [TAPVALUE SAS] - {"hash":"719080d33b283abc","prefixes":{"":{"product":736}}}, // [TAPVALUE SAS] + {"hash":"3eddbbcdb5a13a1b","prefixes":{"":{"product":714,"type":0}}}, // [Sobmag LTD] + {"hash":"f133f36dd9e9688d","prefixes":{"":{"product":714,"type":0}}}, // [Sobmag LTD] + {"hash":"06ead346af8ecc6d","prefixes":{"":{"product":714,"type":0}}}, // [Sobmag LTD] + {"hash":"16a442ad35246027","prefixes":{"":{"product":714,"type":0}}}, // [Sobmag LTD] + {"hash":"778068a948335ee6","prefixes":{"":{"product":714,"type":0}}}, // [Sobmag LTD] + {"hash":"2bb088766e0a77ce","prefixes":{"":{"product":714,"type":0}}}, // [Sobmag LTD] + {"hash":"f54b41faf3e29ddb","prefixes":{"":{"product":714,"type":0}}}, // [Sobmag LTD] + {"hash":"3d71c7985374fc62","prefixes":{"":{"product":714,"type":0}}}, // [Sobmag LTD] + {"hash":"de336679348d46a5","prefixes":{"":{"product":714,"type":0}}}, // [Sobmag LTD] + {"hash":"6818fc4cb694f0d4","prefixes":{"*":{"product":715,"type":2}}}, // [Netbooster] + {"hash":"5682fbd14ad230ca","prefixes":{"":{"product":716,"type":2}}}, // [Musikhaus Thomann e.K.] + {"hash":"abbb14ff2ab0311d","prefixes":{"":{"product":716,"type":2}}}, // [Musikhaus Thomann e.K.] + {"hash":"578726cfc508157e","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"a141aaa30beb2f05","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"9161fa28951da89a","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"2e52f74b27e9eb2f","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"0ecdef2f55913790","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"409546c7e7a9ce63","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"3dceafc40a01cd8c","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"e748a008fcd2910c","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"499e3537aead5990","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"aad99655e792b7af","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"df381181135b37f3","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"49fe77e073f907d5","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"fe445db4579e7177","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"f7038d35f22c32db","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"184913b8eec78f63","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"4db6f08af3d6cf66","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"0a71646e475ff9c1","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"7847dd8c5608a507","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"cde33b0511f42c7c","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"6a5ae5d2380647dc","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"0821cc1422e91328","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"0e157baa999502bc","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"cb93fe6df3fe4097","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"657c19e08d899173","prefixes":{"":{"product":146,"type":0}}}, // [SiteScout AdServer] + {"hash":"e411fd988f243d89","prefixes":{"":{"product":717,"type":0}}}, // [Trovit] + {"hash":"1ea512003540106b","prefixes":{"":{"product":717,"type":0}}}, // [Trovit] + {"hash":"48255f09ec2021d3","prefixes":{"":{"product":717,"type":0}}}, // [Trovit] + {"hash":"7b5b7cfa3d62a886","prefixes":{"":{"product":717,"type":0}}}, // [Trovit] + {"hash":"1235b8279a106276","prefixes":{"":{"product":718,"type":1}}}, // [O2online] + {"hash":"cf76706eea2f0be6","prefixes":{"":{"product":719,"type":0}}}, // [E-Plus Mobilfunk GmbH & Co. KG] + {"hash":"766b747f8dec4417","prefixes":{"":{"product":720,"type":0}}}, // [Meteora] + {"hash":"270677f86b7f115b","prefixes":{"":{"product":720,"type":0}}}, // [Meteora] + {"hash":"0a500f94a8a562f0","prefixes":{"":{"product":721,"type":0}}}, // [Madison Logic, Inc.] + {"hash":"764d3a17a9512438","prefixes":{"":{"product":721,"type":0}}}, // [Madison Logic, Inc.] + {"hash":"38c3aac1b79f0478","prefixes":{"":{"product":721,"type":0}}}, // [Madison Logic, Inc.] + {"hash":"babcc401d384553f","prefixes":{"":{"product":722,"type":0}}}, // [万相DSP(IZP Technologies)] + {"hash":"2ddae58a55ab72ef","prefixes":{"":{"product":722,"type":0}}}, // [万相DSP(IZP Technologies)] + {"hash":"db564708d2871d3a","prefixes":{"":{"product":722,"type":0}}}, // [万相DSP(IZP Technologies)] + {"hash":"a4199cfcbe70d7f5","prefixes":{"":{"product":722,"type":0}}}, // [万相DSP(IZP Technologies)] + {"hash":"e6f5851275bc1fb3","prefixes":{"":{"product":722,"type":0}}}, // [万相DSP(IZP Technologies)] + {"hash":"16e6d7e84ad7fa3a","prefixes":{"":{"product":722,"type":0}}}, // [万相DSP(IZP Technologies)] + {"hash":"58ae73a3bb4327d7","prefixes":{"":{"product":722,"type":0}}}, // [万相DSP(IZP Technologies)] + {"hash":"366a0ad35670aef5","prefixes":{"":{"product":722,"type":0}}}, // [万相DSP(IZP Technologies)] + {"hash":"5b30682b9dfa7060","prefixes":{"":{"product":722,"type":0}}}, // [万相DSP(IZP Technologies)] + {"hash":"67128a22cdd1a7cd","prefixes":{"":{"product":23,"type":0}}}, // [AppNexus Open AdStream] + {"hash":"db56992e1a1a3f90","prefixes":{"":{"product":723,"type":0}}}, // [righTarget] + {"hash":"479ab75d77a40d72","prefixes":{"":{"product":723,"type":0}}}, // [righTarget] + {"hash":"17bcd2af46fb1fe6","prefixes":{"":{"product":723,"type":0}}}, // [righTarget] + {"hash":"45681f09a76fe33e","prefixes":{"":{"product":724,"type":0}}}, // [e.QQ.com] + {"hash":"612f6aab80bc21df","prefixes":{"":{"product":724,"type":0}}}, // [e.QQ.com] + {"hash":"ab7e80409519ca9d","prefixes":{"":{"product":724,"type":0}}}, // [e.QQ.com] + {"hash":"a3ae7b8a84f28040","prefixes":{"":{"product":724,"type":0}}}, // [e.QQ.com] + {"hash":"b25f21b316565014","prefixes":{"":{"product":724,"type":0}}}, // [e.QQ.com] + {"hash":"cc9eeba2126e4261","prefixes":{"":{"product":724,"type":0}}}, // [e.QQ.com] + {"hash":"9d4819b235a5272b","prefixes":{"":{"product":724,"type":0}}}, // [e.QQ.com] + {"hash":"78bb032f283d8f48","prefixes":{"":{"product":725,"type":0}}}, // [Shen Zhen ShiJi KaiXuan Technology Company Ltd.] + {"hash":"de11a5b150526c21","prefixes":{"":{"product":725,"type":0}}}, // [Shen Zhen ShiJi KaiXuan Technology Company Ltd.] + {"hash":"bbd9e4a668c4e348","prefixes":{"":{"product":725,"type":0}}}, // [Shen Zhen ShiJi KaiXuan Technology Company Ltd.] + {"hash":"c38a1d9eab08d787","prefixes":{"*":{"product":724,"type":0}}}, // [e.QQ.com] + {"hash":"5b2c8d90176bd14e","prefixes":{"":{"product":724,"type":0}}}, // [e.QQ.com] + {"hash":"62980dc2fa42e1e0","prefixes":{"*":{"product":724,"type":0}}}, // [e.QQ.com] + {"hash":"9b37bab01bf28d39","prefixes":{"*":{"product":726,"type":0}}}, // [Bannercockpit] + {"hash":"01ec60ee4671b195","prefixes":{"":{"product":727,"type":0}}}, // [Outrigger Media Inc.] + {"hash":"4be86c0a73547960","prefixes":{"":{"product":727,"type":0}}}, // [Outrigger Media Inc.] + {"hash":"e3ab574adac96838","prefixes":{"":{"product":105,"type":0}}}, // [Rockabox Media Ltd] + {"hash":"91bb53a0f22994f8","prefixes":{"":{"product":105,"type":0}}}, // [Rockabox Media Ltd] + {"hash":"fd65eb28a70ed09a","prefixes":{"":{"product":105,"type":0}}}, // [Rockabox Media Ltd] + {"hash":"9f41f821ddcb5092","prefixes":{"":{"product":105,"type":0}}}, // [Rockabox Media Ltd] + {"hash":"ee70168f83fb2cce","prefixes":{"":{"product":105,"type":0}}}, // [Rockabox Media Ltd] + {"hash":"c15fc4a18b25e6d3","prefixes":{"":{"product":105,"type":0}}}, // [Rockabox Media Ltd] + {"hash":"f5f66dfaf3d2d2a3","prefixes":{"":{"product":105,"type":0}}}, // [Rockabox Media Ltd] + {"hash":"e6e8716836c8a21d","prefixes":{"":{"product":105,"type":0}}}, // [Rockabox Media Ltd] + {"hash":"da37db68457e2782","prefixes":{"*":{"product":728,"type":0}}}, // [shopLocal] + {"hash":"ab8c1ee046adfbb1","prefixes":{"*":{"product":729,"type":1}}}, // [Impact Radius] + {"hash":"0e8c1ff7462c1084","prefixes":{"*":{"product":729,"type":1}}}, // [Impact Radius] + {"hash":"8f228d8317e4718d","prefixes":{"":{"product":729,"type":1}}}, // [Impact Radius] + {"hash":"29d7e31af4b1be0b","prefixes":{"":{"product":730,"type":0}}}, // [Unister AdServer] + {"hash":"efeab3df1fe3849a","prefixes":{"":{"product":730,"type":0}}}, // [Unister AdServer] + {"hash":"8f2fea31a1c79b34","prefixes":{"":{"product":730,"type":0}}}, // [Unister AdServer] + {"hash":"9cda8eeaf1e150bf","prefixes":{"":{"product":730,"type":0}}}, // [Unister AdServer] + {"hash":"714091c1b8581de0","prefixes":{"":{"product":731,"type":0}}}, // [Unister Media GmbH] + {"hash":"c7002b2b9e4b5370","prefixes":{"":{"product":730,"type":0}}}, // [Unister AdServer] + {"hash":"1802591342537dae","prefixes":{"":{"product":730,"type":0}}}, // [Unister AdServer] + {"hash":"787cbd14bb54b647","prefixes":{"":{"product":730,"type":0}}}, // [Unister AdServer] + {"hash":"084ef5666af6a26c","prefixes":{"":{"product":730,"type":0}}}, // [Unister AdServer] + {"hash":"df72b5eb4be388d1","prefixes":{"":{"product":732,"type":0}}}, // [TLV Media Online Ltd] + {"hash":"64ffcabaf6ec2bcf","prefixes":{"":{"product":733,"type":0}}}, // [d3media AG] + {"hash":"a6d58332a182c9f4","prefixes":{"":{"product":733,"type":0}}}, // [d3media AG] + {"hash":"0bbd108959983b32","prefixes":{"":{"product":734,"type":0}}}, // [Innovative Metrics] + {"hash":"80eab7dfc5e4cc5f","prefixes":{"*":{"product":735,"type":0}}}, // [AthenaHealth] + {"hash":"131ce36599fa0d6c","prefixes":{"":{"product":736,"type":0}}}, // [TAPVALUE SAS] + {"hash":"9181181a015040bc","prefixes":{"":{"product":736,"type":0}}}, // [TAPVALUE SAS] + {"hash":"fca830abc4829657","prefixes":{"":{"product":736,"type":0}}}, // [TAPVALUE SAS] + {"hash":"e78333a733c1b05a","prefixes":{"":{"product":736,"type":0}}}, // [TAPVALUE SAS] + {"hash":"3f82423bd28a526a","prefixes":{"":{"product":736,"type":0}}}, // [TAPVALUE SAS] + {"hash":"f2da501e4086afa3","prefixes":{"":{"product":736,"type":0}}}, // [TAPVALUE SAS] + {"hash":"719080d33b283abc","prefixes":{"":{"product":736,"type":0}}}, // [TAPVALUE SAS] {"hash":"3502e0d544b9b739","prefixes":{"":{"product":737}}}, // [Meteor Worldwide LLC.] {"hash":"a6227ad6f805c298","prefixes":{"":{"product":737}}}, // [Meteor Worldwide LLC.] - {"hash":"0933cf49bb328213","prefixes":{"*":{"product":189}}}, // [Relay42 Technology B.V.] - {"hash":"bea1d6b2a32d3927","prefixes":{"*":{"product":189}}}, // [Relay42 Technology B.V.] - {"hash":"8d1313bfd522fcf6","prefixes":{"":{"product":738}}}, // [Audience2Media Limited] - {"hash":"ec4f449051680a17","prefixes":{"":{"product":738}}}, // [Audience2Media Limited] - {"hash":"9badeeb4c9cff3b3","prefixes":{"":{"product":739}}}, // [HRB Digital LLC.] - {"hash":"e0e362bb66a6c5dd","prefixes":{"*":{"product":740}}}, // [!NOOB] - {"hash":"e1e1866cde6f23c7","prefixes":{"":{"product":163}}}, // [Tagtoo Tech Limited] - {"hash":"60a41acd40c494b4","prefixes":{"":{"product":163}}}, // [Tagtoo Tech Limited] - {"hash":"4dbc45b703241615","prefixes":{"":{"product":163}}}, // [Tagtoo Tech Limited] - {"hash":"d11722ff46ba063b","prefixes":{"":{"product":163}}}, // [Tagtoo Tech Limited] - {"hash":"706cd1e56e4ca9f0","prefixes":{"":{"product":163}}}, // [Tagtoo Tech Limited] - {"hash":"eabe2f56a564ea71","prefixes":{"":{"product":125}}}, // [Mocean mobile, Inc.] - {"hash":"9ab3f80172f06a67","prefixes":{"":{"product":125}}}, // [Mocean mobile, Inc.] - {"hash":"19c44c882811c0bd","prefixes":{"":{"product":741}}}, // [OSV online] - {"hash":"1f888bdc491d19c5","prefixes":{"":{"product":742}}}, // [Addroid™] - {"hash":"3259bacc0853f3ce","prefixes":{"":{"product":742}}}, // [Addroid™] - {"hash":"4a7fe8ed74a69bb1","prefixes":{"":{"product":742}}}, // [Addroid™] - {"hash":"72680bf564258b75","prefixes":{"":{"product":742}}}, // [Addroid™] - {"hash":"d25a0b5dd4617071","prefixes":{"":{"product":742}}}, // [Addroid™] - {"hash":"4e53e370f5c0d9c8","prefixes":{"":{"product":742}}}, // [Addroid™] - {"hash":"2585ec8519ec2a03","prefixes":{"":{"product":742}}}, // [Addroid™] - {"hash":"9ebfdd26621d46c7","prefixes":{"":{"product":742}}}, // [Addroid™] - {"hash":"083fd3b939cbd105","prefixes":{"":{"product":742}}}, // [Addroid™] - {"hash":"3fd28ace41da6736","prefixes":{"":{"product":742}}}, // [Addroid™] - {"hash":"3f5d8ed1881e0849","prefixes":{"":{"product":742}}}, // [Addroid™] - {"hash":"4f0f13d0fae2b262","prefixes":{"":{"product":743}}}, // [AdAccess] - {"hash":"5a40dbdf15bc0d0c","prefixes":{"":{"product":743}}}, // [AdAccess] - {"hash":"0eff5ff163f074f0","prefixes":{"":{"product":743}}}, // [AdAccess] - {"hash":"f5ce32de4ea8770e","prefixes":{"":{"product":743}}}, // [AdAccess] - {"hash":"8a367cea803ead3b","prefixes":{"":{"product":743}}}, // [AdAccess] - {"hash":"960b38f18a31bf7f","prefixes":{"":{"product":743}}}, // [AdAccess] - {"hash":"45b03c5f8881301a","prefixes":{"":{"product":744}}}, // [Yabuka Media, Inc.] - {"hash":"c2875e9f5741c896","prefixes":{"":{"product":744}}}, // [Yabuka Media, Inc.] - {"hash":"46751092d6f82d66","prefixes":{"":{"product":744}}}, // [Yabuka Media, Inc.] - {"hash":"379f0fda3a2142b3","prefixes":{"*":{"product":745}}}, // [Highwinds CDN] - {"hash":"5033b8e8796bc944","prefixes":{"":{"product":746}}}, // [Bridgewell Incorporated] - {"hash":"fcbb4f6f5d116bcf","prefixes":{"":{"product":746}}}, // [Bridgewell Incorporated] - {"hash":"6d68bbc023aff7a8","prefixes":{"":{"product":746}}}, // [Bridgewell Incorporated] - {"hash":"98a17e63899d6f0f","prefixes":{"":{"product":746}}}, // [Bridgewell Incorporated] - {"hash":"1cae38f50bbcbe1a","prefixes":{"":{"product":746}}}, // [Bridgewell Incorporated] - {"hash":"df13ce542b6c0e84","prefixes":{"":{"product":747}}}, // [Bidtheatre AB] - {"hash":"f9e2fc82f27f7b60","prefixes":{"":{"product":747}}}, // [Bidtheatre AB] - {"hash":"0d324dc8c79d8b3c","prefixes":{"":{"product":747}}}, // [Bidtheatre AB] - {"hash":"1d9569d0ee02dcee","prefixes":{"":{"product":748}}}, // [AdMoment] - {"hash":"73bd54b1be5e9df1","prefixes":{"":{"product":748}}}, // [AdMoment] - {"hash":"dae6130e1d796d90","prefixes":{"":{"product":748}}}, // [AdMoment] - {"hash":"53335dc721cbee0b","prefixes":{"":{"product":748}}}, // [AdMoment] - {"hash":"ae279eee4c5b4941","prefixes":{"":{"product":748}}}, // [AdMoment] - {"hash":"684276719f3b5728","prefixes":{"":{"product":748}}}, // [AdMoment] - {"hash":"b7376659acddae09","prefixes":{"":{"product":748}}}, // [AdMoment] - {"hash":"aa7f623da51e1603","prefixes":{"":{"product":748}}}, // [AdMoment] - {"hash":"6785583c4297f7c5","prefixes":{"":{"product":748}}}, // [AdMoment] - {"hash":"20138e51a97d179b","prefixes":{"":{"product":748}}}, // [AdMoment] - {"hash":"cc3a77dca011bc78","prefixes":{"":{"product":748}}}, // [AdMoment] - {"hash":"6d441f7565cc5de4","prefixes":{"":{"product":749}}}, // [UDG München GmbH] - {"hash":"f8c1c6199f46e722","prefixes":{"":{"product":749}}}, // [UDG München GmbH] - {"hash":"151a96d84e31a957","prefixes":{"":{"product":749}}}, // [UDG München GmbH] - {"hash":"5d34fdb93148d891","prefixes":{"":{"product":750}}}, // [Pixalate, Inc.] - {"hash":"6855407f17ce6aec","prefixes":{"":{"product":750}}}, // [Pixalate, Inc.] - {"hash":"b9f9a074ce5d4d07","prefixes":{"":{"product":750}}}, // [Pixalate, Inc.] - {"hash":"41ddcdd6ba9e42fe","prefixes":{"":{"product":750}}}, // [Pixalate, Inc.] - {"hash":"c72923bea1fa64ce","prefixes":{"":{"product":751}}}, // [InMobi Inc.] - {"hash":"9085e035c617887b","prefixes":{"":{"product":751}}}, // [InMobi Inc.] - {"hash":"0f7037ee4e476493","prefixes":{"":{"product":751}}}, // [InMobi Inc.] - {"hash":"bdfbe6247c640d80","prefixes":{"":{"product":752}}}, // [Crisp Media Inc.] - {"hash":"2cb723bdc82533b2","prefixes":{"":{"product":752}}}, // [Crisp Media Inc.] - {"hash":"be72bf3ef3e3bd14","prefixes":{"":{"product":752}}}, // [Crisp Media Inc.] - {"hash":"3af5f91fedb0e598","prefixes":{"":{"product":752}}}, // [Crisp Media Inc.] - {"hash":"9feb6dbe57a5ab9b","prefixes":{"":{"product":752}}}, // [Crisp Media Inc.] + {"hash":"0933cf49bb328213","prefixes":{"*":{"product":189,"type":0}}}, // [Relay42 Technology B.V.] + {"hash":"bea1d6b2a32d3927","prefixes":{"*":{"product":189,"type":0}}}, // [Relay42 Technology B.V.] + {"hash":"8d1313bfd522fcf6","prefixes":{"":{"product":738,"type":0}}}, // [Audience2Media Limited] + {"hash":"ec4f449051680a17","prefixes":{"":{"product":738,"type":0}}}, // [Audience2Media Limited] + {"hash":"9badeeb4c9cff3b3","prefixes":{"":{"product":739,"type":0}}}, // [HRB Digital LLC.] + {"hash":"e0e362bb66a6c5dd","prefixes":{"*":{"product":740,"type":0}}}, // [!NOOB] + {"hash":"e1e1866cde6f23c7","prefixes":{"":{"product":163,"type":0}}}, // [Tagtoo Tech Limited] + {"hash":"60a41acd40c494b4","prefixes":{"":{"product":163,"type":0}}}, // [Tagtoo Tech Limited] + {"hash":"4dbc45b703241615","prefixes":{"":{"product":163,"type":0}}}, // [Tagtoo Tech Limited] + {"hash":"d11722ff46ba063b","prefixes":{"":{"product":163,"type":0}}}, // [Tagtoo Tech Limited] + {"hash":"706cd1e56e4ca9f0","prefixes":{"":{"product":163,"type":0}}}, // [Tagtoo Tech Limited] + {"hash":"eabe2f56a564ea71","prefixes":{"":{"product":125,"type":0}}}, // [Mocean mobile, Inc.] + {"hash":"9ab3f80172f06a67","prefixes":{"":{"product":125,"type":0}}}, // [Mocean mobile, Inc.] + {"hash":"19c44c882811c0bd","prefixes":{"":{"product":741,"type":1}}}, // [OSV online] + {"hash":"1f888bdc491d19c5","prefixes":{"":{"product":742,"type":0}}}, // [Addroid™] + {"hash":"3259bacc0853f3ce","prefixes":{"":{"product":742,"type":0}}}, // [Addroid™] + {"hash":"4a7fe8ed74a69bb1","prefixes":{"":{"product":742,"type":0}}}, // [Addroid™] + {"hash":"72680bf564258b75","prefixes":{"":{"product":742,"type":0}}}, // [Addroid™] + {"hash":"d25a0b5dd4617071","prefixes":{"":{"product":742,"type":0}}}, // [Addroid™] + {"hash":"4e53e370f5c0d9c8","prefixes":{"":{"product":742,"type":0}}}, // [Addroid™] + {"hash":"2585ec8519ec2a03","prefixes":{"":{"product":742,"type":0}}}, // [Addroid™] + {"hash":"9ebfdd26621d46c7","prefixes":{"":{"product":742,"type":0}}}, // [Addroid™] + {"hash":"083fd3b939cbd105","prefixes":{"":{"product":742,"type":0}}}, // [Addroid™] + {"hash":"3fd28ace41da6736","prefixes":{"":{"product":742,"type":0}}}, // [Addroid™] + {"hash":"3f5d8ed1881e0849","prefixes":{"":{"product":742,"type":0}}}, // [Addroid™] + {"hash":"4f0f13d0fae2b262","prefixes":{"":{"product":743,"type":0}}}, // [AdAccess] + {"hash":"5a40dbdf15bc0d0c","prefixes":{"":{"product":743,"type":0}}}, // [AdAccess] + {"hash":"0eff5ff163f074f0","prefixes":{"":{"product":743,"type":0}}}, // [AdAccess] + {"hash":"f5ce32de4ea8770e","prefixes":{"":{"product":743,"type":0}}}, // [AdAccess] + {"hash":"8a367cea803ead3b","prefixes":{"":{"product":743,"type":0}}}, // [AdAccess] + {"hash":"960b38f18a31bf7f","prefixes":{"":{"product":743,"type":0}}}, // [AdAccess] + {"hash":"45b03c5f8881301a","prefixes":{"":{"product":744,"type":0}}}, // [Yabuka Media, Inc.] + {"hash":"c2875e9f5741c896","prefixes":{"":{"product":744,"type":0}}}, // [Yabuka Media, Inc.] + {"hash":"46751092d6f82d66","prefixes":{"":{"product":744,"type":0}}}, // [Yabuka Media, Inc.] + {"hash":"379f0fda3a2142b3","prefixes":{"*":{"product":745,"type":2}}}, // [Highwinds CDN] + {"hash":"5033b8e8796bc944","prefixes":{"":{"product":746,"type":0}}}, // [Bridgewell Incorporated] + {"hash":"fcbb4f6f5d116bcf","prefixes":{"":{"product":746,"type":0}}}, // [Bridgewell Incorporated] + {"hash":"6d68bbc023aff7a8","prefixes":{"":{"product":746,"type":0}}}, // [Bridgewell Incorporated] + {"hash":"98a17e63899d6f0f","prefixes":{"":{"product":746,"type":0}}}, // [Bridgewell Incorporated] + {"hash":"1cae38f50bbcbe1a","prefixes":{"":{"product":746,"type":0}}}, // [Bridgewell Incorporated] + {"hash":"df13ce542b6c0e84","prefixes":{"":{"product":747,"type":0}}}, // [Bidtheatre AB] + {"hash":"f9e2fc82f27f7b60","prefixes":{"":{"product":747,"type":0}}}, // [Bidtheatre AB] + {"hash":"0d324dc8c79d8b3c","prefixes":{"":{"product":747,"type":0}}}, // [Bidtheatre AB] + {"hash":"1d9569d0ee02dcee","prefixes":{"":{"product":748,"type":0}}}, // [AdMoment] + {"hash":"73bd54b1be5e9df1","prefixes":{"":{"product":748,"type":0}}}, // [AdMoment] + {"hash":"dae6130e1d796d90","prefixes":{"":{"product":748,"type":0}}}, // [AdMoment] + {"hash":"53335dc721cbee0b","prefixes":{"":{"product":748,"type":0}}}, // [AdMoment] + {"hash":"ae279eee4c5b4941","prefixes":{"":{"product":748,"type":0}}}, // [AdMoment] + {"hash":"684276719f3b5728","prefixes":{"":{"product":748,"type":0}}}, // [AdMoment] + {"hash":"b7376659acddae09","prefixes":{"":{"product":748,"type":0}}}, // [AdMoment] + {"hash":"aa7f623da51e1603","prefixes":{"":{"product":748,"type":0}}}, // [AdMoment] + {"hash":"6785583c4297f7c5","prefixes":{"":{"product":748,"type":0}}}, // [AdMoment] + {"hash":"20138e51a97d179b","prefixes":{"":{"product":748,"type":0}}}, // [AdMoment] + {"hash":"cc3a77dca011bc78","prefixes":{"":{"product":748,"type":0}}}, // [AdMoment] + {"hash":"6d441f7565cc5de4","prefixes":{"":{"product":749,"type":1}}}, // [UDG München GmbH] + {"hash":"f8c1c6199f46e722","prefixes":{"":{"product":749,"type":1}}}, // [UDG München GmbH] + {"hash":"151a96d84e31a957","prefixes":{"":{"product":749,"type":1}}}, // [UDG München GmbH] + {"hash":"5d34fdb93148d891","prefixes":{"":{"product":750,"type":1}}}, // [Pixalate, Inc.] + {"hash":"6855407f17ce6aec","prefixes":{"":{"product":750,"type":1}}}, // [Pixalate, Inc.] + {"hash":"b9f9a074ce5d4d07","prefixes":{"":{"product":750,"type":1}}}, // [Pixalate, Inc.] + {"hash":"41ddcdd6ba9e42fe","prefixes":{"":{"product":750,"type":1}}}, // [Pixalate, Inc.] + {"hash":"c72923bea1fa64ce","prefixes":{"":{"product":751,"type":0}}}, // [InMobi Inc.] + {"hash":"9085e035c617887b","prefixes":{"":{"product":751,"type":0}}}, // [InMobi Inc.] + {"hash":"0f7037ee4e476493","prefixes":{"":{"product":751,"type":0}}}, // [InMobi Inc.] + {"hash":"bdfbe6247c640d80","prefixes":{"":{"product":752,"type":0}}}, // [Crisp Media Inc.] + {"hash":"2cb723bdc82533b2","prefixes":{"":{"product":752,"type":0}}}, // [Crisp Media Inc.] + {"hash":"be72bf3ef3e3bd14","prefixes":{"":{"product":752,"type":0}}}, // [Crisp Media Inc.] + {"hash":"3af5f91fedb0e598","prefixes":{"":{"product":752,"type":0}}}, // [Crisp Media Inc.] + {"hash":"9feb6dbe57a5ab9b","prefixes":{"":{"product":752,"type":0}}}, // [Crisp Media Inc.] {"hash":"1953012d699dc24e","prefixes":{"":{"product":753}}}, // [Choozle, Inc.] {"hash":"560479fb0478e76e","prefixes":{"":{"product":753}}}, // [Choozle, Inc.] - {"hash":"fb3c191358de9e97","prefixes":{"*":{"product":754}}}, // [Tapad] - {"hash":"faa63745af097785","prefixes":{"*":{"product":755}}}, // [ReachLocal, Inc] - {"hash":"c6a0024a8fdbd244","prefixes":{"":{"product":756}}}, // [OpenX Ad Exchange] - {"hash":"1b09e9588e619f63","prefixes":{"":{"product":756}}}, // [OpenX Ad Exchange] - {"hash":"c923ecff86d0026f","prefixes":{"":{"product":756}}}, // [OpenX Ad Exchange] - {"hash":"0b38e9ab66f134b5","prefixes":{"":{"product":756}}}, // [OpenX Ad Exchange] - {"hash":"b07b0a6a32b39c67","prefixes":{"rtb-":{"product":756}}}, // [OpenX Ad Exchange] - {"hash":"a66019bd1d8d6523","prefixes":{"":{"product":757}}}, // [OpenX] - {"hash":"3461a8e14dfa7234","prefixes":{"*":{"product":756}}}, // [OpenX Ad Exchange] - {"hash":"50f406d696ea09e2","prefixes":{"*":{"product":756}}}, // [OpenX Ad Exchange] - {"hash":"28f15a404c22c5ae","prefixes":{"":{"product":758}}}, // [Placester, Inc.] - {"hash":"2eabf2a9cc47f6db","prefixes":{"":{"product":758}}}, // [Placester, Inc.] - {"hash":"04e56c0e39ffb379","prefixes":{"":{"product":759}}}, // [Spiceworks, Inc] - {"hash":"a342cde98acae2a3","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"816943ad229d59bd","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"9aeccecf18437372","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"e24006f3d8614cdf","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"2678adb8d16c1bd0","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"690b9d06ee7b618c","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"ba64173aac6883fa","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"3f334c96b9489b6f","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"4acb6ede5efaa0ce","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"f848368a90033112","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"fc58526ac2c34887","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"bcec64a939aa6248","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"2237ba07a36c2440","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"9b1bd3e45cc8d37b","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"f9447e97a352a2e8","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"4aa3c10d0fa51575","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"edb1b5b0a2ecd2b9","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"3eee53fed713d5b2","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"5562c787acd84d8d","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"27d45cd108fe99b4","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"06da026d99fd30c4","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"43e91c0e2d266107","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"2b8ee71c143b611a","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"31773affdbc2f93f","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"24f5edbbeab30fc6","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"b1275f1680c5e050","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"1f0e98fd24844df9","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"207973ef90437496","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"5e573612b3181547","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"5237a5b231dbf245","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"b4872bd493703ef0","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"7268f40680faccfd","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"f18cc00e2cfb170d","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"2be692602def45f7","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"5d15e875488cccd1","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"7da3afc36d1c6b59","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"e0767b1a03a64ce6","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"202d0d2b1168aeb8","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"5e070df0dbe151e6","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"e4337ec6681cbc61","prefixes":{"":{"product":760}}}, // [WapStart] - {"hash":"944f2609259bac7c","prefixes":{"":{"product":761}}}, // [Ambercrow (Epayments)] - {"hash":"8bcd6f943c02d066","prefixes":{"":{"product":761}}}, // [Ambercrow (Epayments)] - {"hash":"f0529ee08a090045","prefixes":{"":{"product":761}}}, // [Ambercrow (Epayments)] - {"hash":"f44423b0de62f78e","prefixes":{"":{"product":761}}}, // [Ambercrow (Epayments)] - {"hash":"00fb6871b70e1fd9","prefixes":{"":{"product":761}}}, // [Ambercrow (Epayments)] - {"hash":"588e459942f9f953","prefixes":{"":{"product":762}}}, // [Audiencevalue Pte Ltd] - {"hash":"2b94a7bb996b3a9c","prefixes":{"":{"product":762}}}, // [Audiencevalue Pte Ltd] - {"hash":"5796b5e246266e0c","prefixes":{"":{"product":763}}}, // [UNITED. Inc.] - {"hash":"aa1ee475645d94b7","prefixes":{"":{"product":763}}}, // [UNITED. Inc.] - {"hash":"716f227b7327feba","prefixes":{"":{"product":763}}}, // [UNITED. Inc.] + {"hash":"fb3c191358de9e97","prefixes":{"*":{"product":754,"type":1}}}, // [Tapad] + {"hash":"faa63745af097785","prefixes":{"*":{"product":755,"type":1}}}, // [ReachLocal, Inc] + {"hash":"c6a0024a8fdbd244","prefixes":{"":{"product":756,"type":0}}}, // [OpenX Ad Exchange] + {"hash":"1b09e9588e619f63","prefixes":{"":{"product":756,"type":0}}}, // [OpenX Ad Exchange] + {"hash":"c923ecff86d0026f","prefixes":{"":{"product":756,"type":0}}}, // [OpenX Ad Exchange] + {"hash":"0b38e9ab66f134b5","prefixes":{"":{"product":756,"type":0}}}, // [OpenX Ad Exchange] + {"hash":"b07b0a6a32b39c67","prefixes":{"rtb-":{"product":756,"type":0}}}, // [OpenX Ad Exchange] + {"hash":"a66019bd1d8d6523","prefixes":{"":{"product":757,"type":0}}}, // [OpenX] + {"hash":"3461a8e14dfa7234","prefixes":{"*":{"product":756,"type":0}}}, // [OpenX Ad Exchange] + {"hash":"50f406d696ea09e2","prefixes":{"*":{"product":756,"type":0}}}, // [OpenX Ad Exchange] + {"hash":"28f15a404c22c5ae","prefixes":{"":{"product":758,"type":0}}}, // [Placester, Inc.] + {"hash":"2eabf2a9cc47f6db","prefixes":{"":{"product":758,"type":0}}}, // [Placester, Inc.] + {"hash":"04e56c0e39ffb379","prefixes":{"":{"product":759,"type":0}}}, // [Spiceworks, Inc] + {"hash":"a342cde98acae2a3","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"816943ad229d59bd","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"9aeccecf18437372","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"e24006f3d8614cdf","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"2678adb8d16c1bd0","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"690b9d06ee7b618c","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"ba64173aac6883fa","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"3f334c96b9489b6f","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"4acb6ede5efaa0ce","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"f848368a90033112","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"fc58526ac2c34887","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"bcec64a939aa6248","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"2237ba07a36c2440","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"9b1bd3e45cc8d37b","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"f9447e97a352a2e8","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"4aa3c10d0fa51575","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"edb1b5b0a2ecd2b9","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"3eee53fed713d5b2","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"5562c787acd84d8d","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"27d45cd108fe99b4","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"06da026d99fd30c4","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"43e91c0e2d266107","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"2b8ee71c143b611a","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"31773affdbc2f93f","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"24f5edbbeab30fc6","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"b1275f1680c5e050","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"1f0e98fd24844df9","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"207973ef90437496","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"5e573612b3181547","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"5237a5b231dbf245","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"b4872bd493703ef0","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"7268f40680faccfd","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"f18cc00e2cfb170d","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"2be692602def45f7","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"5d15e875488cccd1","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"7da3afc36d1c6b59","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"e0767b1a03a64ce6","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"202d0d2b1168aeb8","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"5e070df0dbe151e6","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"e4337ec6681cbc61","prefixes":{"":{"product":760,"type":0}}}, // [WapStart] + {"hash":"944f2609259bac7c","prefixes":{"":{"product":761,"type":0}}}, // [Ambercrow (Epayments)] + {"hash":"8bcd6f943c02d066","prefixes":{"":{"product":761,"type":0}}}, // [Ambercrow (Epayments)] + {"hash":"f0529ee08a090045","prefixes":{"":{"product":761,"type":0}}}, // [Ambercrow (Epayments)] + {"hash":"f44423b0de62f78e","prefixes":{"":{"product":761,"type":0}}}, // [Ambercrow (Epayments)] + {"hash":"00fb6871b70e1fd9","prefixes":{"":{"product":761,"type":0}}}, // [Ambercrow (Epayments)] + {"hash":"588e459942f9f953","prefixes":{"":{"product":762,"type":0}}}, // [Audiencevalue Pte Ltd] + {"hash":"2b94a7bb996b3a9c","prefixes":{"":{"product":762,"type":0}}}, // [Audiencevalue Pte Ltd] + {"hash":"5796b5e246266e0c","prefixes":{"":{"product":763,"type":0}}}, // [UNITED. Inc.] + {"hash":"aa1ee475645d94b7","prefixes":{"":{"product":763,"type":0}}}, // [UNITED. Inc.] + {"hash":"716f227b7327feba","prefixes":{"":{"product":763,"type":0}}}, // [UNITED. Inc.] {"hash":"44c3a88f2dcdee6f","prefixes":{"":{"product":764}}}, // [United Bypass Tech] - {"hash":"0f010d866f5763fa","prefixes":{"":{"product":765}}}, // [SAS Naoplay] - {"hash":"6a978d7b8efc594d","prefixes":{"":{"product":765}}}, // [SAS Naoplay] - {"hash":"d3e10ee4fc900d26","prefixes":{"":{"product":765}}}, // [SAS Naoplay] - {"hash":"e83a4038aff02b6e","prefixes":{"":{"product":765}}}, // [SAS Naoplay] - {"hash":"acce217e5e09149a","prefixes":{"":{"product":765}}}, // [SAS Naoplay] - {"hash":"3a93fbc111c8603f","prefixes":{"":{"product":766}}}, // [CuriosityStream] - {"hash":"065426aaa5552ffe","prefixes":{"":{"product":767}}}, // [Alliance Internet (ntree)] - {"hash":"9a843715746291f3","prefixes":{"":{"product":767}}}, // [Alliance Internet (ntree)] - {"hash":"2d4ed5b7f85f950a","prefixes":{"n":{"product":767}}}, // [Alliance Internet (ntree)] - {"hash":"86f628e66b67be4d","prefixes":{"":{"product":768}}}, // [Centraltag] - {"hash":"419e8a03b3f16a8c","prefixes":{"":{"product":769}}}, // [eTargeting] - {"hash":"b9ee79ef4e8c15f5","prefixes":{"":{"product":769}}}, // [eTargeting] - {"hash":"46e3b67ae4549155","prefixes":{"":{"product":769}}}, // [eTargeting] - {"hash":"3064ccb85e72d2df","prefixes":{"":{"product":769}}}, // [eTargeting] - {"hash":"1b58e47cefd5e220","prefixes":{"":{"product":769}}}, // [eTargeting] - {"hash":"93b3f973b09c5513","prefixes":{"":{"product":769}}}, // [eTargeting] - {"hash":"607d4f0311eec7af","prefixes":{"":{"product":769}}}, // [eTargeting] - {"hash":"311502ef7317df7d","prefixes":{"":{"product":769}}}, // [eTargeting] - {"hash":"cdf3897e12242607","prefixes":{"":{"product":769}}}, // [eTargeting] - {"hash":"a5a0d71d2f6b631c","prefixes":{"":{"product":769}}}, // [eTargeting] - {"hash":"10f5415b8d24f2b0","prefixes":{"":{"product":769}}}, // [eTargeting] - {"hash":"c126382fcba55688","prefixes":{"":{"product":769}}}, // [eTargeting] - {"hash":"a92d9d96a9338816","prefixes":{"":{"product":769}}}, // [eTargeting] - {"hash":"74549e43319467f8","prefixes":{"":{"product":770}}}, // [Walmart Inc] - {"hash":"3d8d433ae123d216","prefixes":{"":{"product":770}}}, // [Walmart Inc] - {"hash":"6baa1cd3500dc43f","prefixes":{"":{"product":771}}}, // [Walmart.com] + {"hash":"0f010d866f5763fa","prefixes":{"":{"product":765,"type":0}}}, // [SAS Naoplay] + {"hash":"6a978d7b8efc594d","prefixes":{"":{"product":765,"type":0}}}, // [SAS Naoplay] + {"hash":"d3e10ee4fc900d26","prefixes":{"":{"product":765,"type":0}}}, // [SAS Naoplay] + {"hash":"e83a4038aff02b6e","prefixes":{"":{"product":765,"type":0}}}, // [SAS Naoplay] + {"hash":"acce217e5e09149a","prefixes":{"":{"product":765,"type":0}}}, // [SAS Naoplay] + {"hash":"3a93fbc111c8603f","prefixes":{"":{"product":766,"type":0}}}, // [CuriosityStream] + {"hash":"065426aaa5552ffe","prefixes":{"":{"product":767,"type":0}}}, // [Alliance Internet (ntree)] + {"hash":"9a843715746291f3","prefixes":{"":{"product":767,"type":0}}}, // [Alliance Internet (ntree)] + {"hash":"2d4ed5b7f85f950a","prefixes":{"n":{"product":767,"type":0}}}, // [Alliance Internet (ntree)] + {"hash":"86f628e66b67be4d","prefixes":{"":{"product":768,"type":0}}}, // [Centraltag] + {"hash":"419e8a03b3f16a8c","prefixes":{"":{"product":769,"type":0}}}, // [eTargeting] + {"hash":"b9ee79ef4e8c15f5","prefixes":{"":{"product":769,"type":0}}}, // [eTargeting] + {"hash":"46e3b67ae4549155","prefixes":{"":{"product":769,"type":0}}}, // [eTargeting] + {"hash":"3064ccb85e72d2df","prefixes":{"":{"product":769,"type":0}}}, // [eTargeting] + {"hash":"1b58e47cefd5e220","prefixes":{"":{"product":769,"type":0}}}, // [eTargeting] + {"hash":"93b3f973b09c5513","prefixes":{"":{"product":769,"type":0}}}, // [eTargeting] + {"hash":"607d4f0311eec7af","prefixes":{"":{"product":769,"type":0}}}, // [eTargeting] + {"hash":"311502ef7317df7d","prefixes":{"":{"product":769,"type":0}}}, // [eTargeting] + {"hash":"cdf3897e12242607","prefixes":{"":{"product":769,"type":0}}}, // [eTargeting] + {"hash":"a5a0d71d2f6b631c","prefixes":{"":{"product":769,"type":0}}}, // [eTargeting] + {"hash":"10f5415b8d24f2b0","prefixes":{"":{"product":769,"type":0}}}, // [eTargeting] + {"hash":"c126382fcba55688","prefixes":{"":{"product":769,"type":0}}}, // [eTargeting] + {"hash":"a92d9d96a9338816","prefixes":{"":{"product":769,"type":0}}}, // [eTargeting] + {"hash":"74549e43319467f8","prefixes":{"":{"product":770,"type":1}}}, // [Walmart Inc] + {"hash":"3d8d433ae123d216","prefixes":{"":{"product":770,"type":1}}}, // [Walmart Inc] + {"hash":"6baa1cd3500dc43f","prefixes":{"":{"product":771,"type":0}}}, // [Walmart.com] {"hash":"12bc009e74ca3655","prefixes":{"":{"product":770}}}, // [Walmart Inc] - {"hash":"abb8ec1b9995e7db","prefixes":{"":{"product":772}}}, // [Extreme Reach, Inc.] - {"hash":"a489082dd8c6d1b0","prefixes":{"":{"product":772}}}, // [Extreme Reach, Inc.] - {"hash":"b8eaffd4f3298628","prefixes":{"":{"product":772}}}, // [Extreme Reach, Inc.] - {"hash":"fa888dd08124e8f6","prefixes":{"":{"product":772}}}, // [Extreme Reach, Inc.] - {"hash":"d33163e42a34ac6b","prefixes":{"":{"product":773}}}, // [Extreme Reach Digital (ER Digital)] - {"hash":"26271fd98d79e29f","prefixes":{"":{"product":772}}}, // [Extreme Reach, Inc.] - {"hash":"f958e80b82fbeb15","prefixes":{"":{"product":772}}}, // [Extreme Reach, Inc.] - {"hash":"0efc1cccd29292d2","prefixes":{"*":{"product":772}}}, // [Extreme Reach, Inc.] - {"hash":"ec1cfeb7c8ad8e74","prefixes":{"*":{"product":772}}}, // [Extreme Reach, Inc.] - {"hash":"06ea295dea974069","prefixes":{"":{"product":772}}}, // [Extreme Reach, Inc.] - {"hash":"166f6d9041d2cffe","prefixes":{"":{"product":772}}}, // [Extreme Reach, Inc.] - {"hash":"d209952bca4546fc","prefixes":{"":{"product":772}}}, // [Extreme Reach, Inc.] - {"hash":"8977e19e27e82a31","prefixes":{"":{"product":772}}}, // [Extreme Reach, Inc.] - {"hash":"f276cc84c3030bf7","prefixes":{"":{"product":774}}}, // [Netflix] - {"hash":"cf97c9d0a75da1fb","prefixes":{"":{"product":774}}}, // [Netflix] - {"hash":"acf43321c04d641b","prefixes":{"":{"product":774}}}, // [Netflix] - {"hash":"bb55681ae13b2fa8","prefixes":{"":{"product":774}}}, // [Netflix] - {"hash":"2d5400efd94a66d0","prefixes":{"":{"product":774}}}, // [Netflix] - {"hash":"c4a2daa282a0af48","prefixes":{"":{"product":774}}}, // [Netflix] - {"hash":"670a8e12f579ee63","prefixes":{"":{"product":775}}}, // [Netflix, Inc.] - {"hash":"15b7e69ddffa3a8c","prefixes":{"":{"product":775}}}, // [Netflix, Inc.] - {"hash":"7b7add7c969d93fe","prefixes":{"*":{"product":776}}}, // [Scarab Personalized Ads] - {"hash":"4e1907aa0eb0ff71","prefixes":{"":{"product":776}}}, // [Scarab Personalized Ads] - {"hash":"a3315978597aa707","prefixes":{"":{"product":777}}}, // [CrowdMob Inc.] - {"hash":"452715cede41650c","prefixes":{"":{"product":778}}}, // [Gruvi Ltd.] - {"hash":"36ce2eb140f75f32","prefixes":{"":{"product":777}}}, // [CrowdMob Inc.] - {"hash":"ae6b13daf4bc714d","prefixes":{"":{"product":106}}}, // [PocketMath] - {"hash":"13696777dabedeae","prefixes":{"":{"product":779}}}, // [Macromill, Inc.] - {"hash":"9971928c88e3fa4e","prefixes":{"*":{"product":780}}}, // [Nielsen (Cross Platform Brand Effect [IAG/TVBE])] - {"hash":"65df6515d4615cea","prefixes":{"f":{"product":781},"vast-":{"product":781},"ivid-":{"product":781}}}, // [GetIntent] [GetIntent] [GetIntent] - {"hash":"b54db54df2c407f8","prefixes":{"":{"product":781}}}, // [GetIntent] - {"hash":"2258062bb1ab01dd","prefixes":{"":{"product":781}}}, // [GetIntent] - {"hash":"630338f7109ea305","prefixes":{"*":{"product":781}}}, // [GetIntent] + {"hash":"abb8ec1b9995e7db","prefixes":{"":{"product":772,"type":0}}}, // [Extreme Reach, Inc.] + {"hash":"a489082dd8c6d1b0","prefixes":{"":{"product":772,"type":0}}}, // [Extreme Reach, Inc.] + {"hash":"b8eaffd4f3298628","prefixes":{"":{"product":772,"type":0}}}, // [Extreme Reach, Inc.] + {"hash":"fa888dd08124e8f6","prefixes":{"":{"product":772,"type":0}}}, // [Extreme Reach, Inc.] + {"hash":"d33163e42a34ac6b","prefixes":{"":{"product":773,"type":1}}}, // [Extreme Reach Digital (ER Digital)] + {"hash":"26271fd98d79e29f","prefixes":{"":{"product":772,"type":0}}}, // [Extreme Reach, Inc.] + {"hash":"f958e80b82fbeb15","prefixes":{"":{"product":772,"type":0}}}, // [Extreme Reach, Inc.] + {"hash":"0efc1cccd29292d2","prefixes":{"*":{"product":772,"type":0}}}, // [Extreme Reach, Inc.] + {"hash":"ec1cfeb7c8ad8e74","prefixes":{"*":{"product":772,"type":0}}}, // [Extreme Reach, Inc.] + {"hash":"06ea295dea974069","prefixes":{"":{"product":772,"type":0}}}, // [Extreme Reach, Inc.] + {"hash":"166f6d9041d2cffe","prefixes":{"":{"product":772,"type":0}}}, // [Extreme Reach, Inc.] + {"hash":"d209952bca4546fc","prefixes":{"":{"product":772,"type":0}}}, // [Extreme Reach, Inc.] + {"hash":"8977e19e27e82a31","prefixes":{"":{"product":772,"type":0}}}, // [Extreme Reach, Inc.] + {"hash":"f276cc84c3030bf7","prefixes":{"":{"product":774,"type":1}}}, // [Netflix] + {"hash":"cf97c9d0a75da1fb","prefixes":{"":{"product":774,"type":1}}}, // [Netflix] + {"hash":"acf43321c04d641b","prefixes":{"":{"product":774,"type":1}}}, // [Netflix] + {"hash":"bb55681ae13b2fa8","prefixes":{"":{"product":774,"type":1}}}, // [Netflix] + {"hash":"2d5400efd94a66d0","prefixes":{"":{"product":774,"type":1}}}, // [Netflix] + {"hash":"c4a2daa282a0af48","prefixes":{"":{"product":774,"type":1}}}, // [Netflix] + {"hash":"670a8e12f579ee63","prefixes":{"":{"product":775,"type":0}}}, // [Netflix, Inc.] + {"hash":"15b7e69ddffa3a8c","prefixes":{"":{"product":775,"type":0}}}, // [Netflix, Inc.] + {"hash":"7b7add7c969d93fe","prefixes":{"*":{"product":776,"type":0}}}, // [Scarab Personalized Ads] + {"hash":"4e1907aa0eb0ff71","prefixes":{"":{"product":776,"type":0}}}, // [Scarab Personalized Ads] + {"hash":"a3315978597aa707","prefixes":{"":{"product":777,"type":0}}}, // [CrowdMob Inc.] + {"hash":"452715cede41650c","prefixes":{"":{"product":778,"type":0}}}, // [Gruvi Ltd.] + {"hash":"36ce2eb140f75f32","prefixes":{"":{"product":777,"type":0}}}, // [CrowdMob Inc.] + {"hash":"ae6b13daf4bc714d","prefixes":{"":{"product":106,"type":0}}}, // [PocketMath] + {"hash":"13696777dabedeae","prefixes":{"":{"product":779,"type":1}}}, // [Macromill, Inc.] + {"hash":"9971928c88e3fa4e","prefixes":{"*":{"product":780,"type":1}}}, // [Nielsen (Cross Platform Brand Effect [IAG/TVBE])] + {"hash":"65df6515d4615cea","prefixes":{"f":{"product":781,"type":0},"vast-":{"product":781,"type":0},"ivid-":{"product":781}}}, // [GetIntent] [GetIntent] [GetIntent] + {"hash":"b54db54df2c407f8","prefixes":{"":{"product":781,"type":0}}}, // [GetIntent] + {"hash":"2258062bb1ab01dd","prefixes":{"":{"product":781,"type":0}}}, // [GetIntent] + {"hash":"630338f7109ea305","prefixes":{"*":{"product":781,"type":0}}}, // [GetIntent] {"hash":"b3c93c6142991123","prefixes":{"":{"product":781}}}, // [GetIntent] {"hash":"6ef8d315575de4c7","prefixes":{"":{"product":781}}}, // [GetIntent] {"hash":"b7769b25a2035147","prefixes":{"vid-":{"product":781}}}, // [GetIntent] - {"hash":"2e2859be7da1ee82","prefixes":{"":{"product":782}}}, // [Belboon] - {"hash":"ff591094a6a13480","prefixes":{"*":{"product":783}}}, // [Ozone Media Solutions Pvt Ltd] - {"hash":"3bd09c8fad6ac0cd","prefixes":{"*":{"product":783}}}, // [Ozone Media Solutions Pvt Ltd] - {"hash":"41385cd812900dd3","prefixes":{"*":{"product":783}}}, // [Ozone Media Solutions Pvt Ltd] - {"hash":"78bdf43617c9f3ed","prefixes":{"":{"product":784}}}, // [Hindustan Times Mobile Solutions Limited] - {"hash":"f669a1035330e753","prefixes":{"*":{"product":783}}}, // [Ozone Media Solutions Pvt Ltd] - {"hash":"74c5a373ee6172a1","prefixes":{"":{"product":785}}}, // [SoftLayer Technologies, Inc.] - {"hash":"3762c6694e48ada4","prefixes":{"":{"product":785}}}, // [SoftLayer Technologies, Inc.] - {"hash":"885e91388dd960b6","prefixes":{"":{"product":785}}}, // [SoftLayer Technologies, Inc.] - {"hash":"f6a553969be0331b","prefixes":{"":{"product":785}}}, // [SoftLayer Technologies, Inc.] - {"hash":"48d6fc29b318593f","prefixes":{"":{"product":785}}}, // [SoftLayer Technologies, Inc.] - {"hash":"1e571da94b4242ba","prefixes":{"":{"product":785}}}, // [SoftLayer Technologies, Inc.] - {"hash":"e6770fd6222ae990","prefixes":{"":{"product":785}}}, // [SoftLayer Technologies, Inc.] - {"hash":"20b17ee9acc1afb9","prefixes":{"":{"product":785}}}, // [SoftLayer Technologies, Inc.] - {"hash":"c483854c67d0c950","prefixes":{"":{"product":785}}}, // [SoftLayer Technologies, Inc.] - {"hash":"5214f14e27a71d7f","prefixes":{"":{"product":786}}}, // [GoldSpot Media] - {"hash":"61c576ffa8275ef3","prefixes":{"":{"product":786}}}, // [GoldSpot Media] - {"hash":"c6af9ddc14757f86","prefixes":{"":{"product":786}}}, // [GoldSpot Media] - {"hash":"86e9128d66cc0207","prefixes":{"":{"product":786}}}, // [GoldSpot Media] - {"hash":"c71d0bd2e6f83f82","prefixes":{"":{"product":786}}}, // [GoldSpot Media] - {"hash":"97be67a3b0baedf9","prefixes":{"":{"product":786}}}, // [GoldSpot Media] - {"hash":"9622fe3e417564fb","prefixes":{"":{"product":786}}}, // [GoldSpot Media] - {"hash":"a63ebe94fca61ed9","prefixes":{"":{"product":786}}}, // [GoldSpot Media] - {"hash":"bbc1dd12d3cdb0b4","prefixes":{"":{"product":786}}}, // [GoldSpot Media] - {"hash":"962da7f5c63ff169","prefixes":{"":{"product":786}}}, // [GoldSpot Media] - {"hash":"94bb51394747c625","prefixes":{"":{"product":786}}}, // [GoldSpot Media] - {"hash":"3ff8867b3d239d21","prefixes":{"":{"product":786}}}, // [GoldSpot Media] - {"hash":"a970a6e82a98c461","prefixes":{"":{"product":787}}}, // [Zeeto Media] - {"hash":"4c975affcaea9100","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"dfd86d0838962249","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"91f2b2338b35b7b2","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"3bec5ca280ea1b83","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"3d88758bd6e0003a","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"5c4e7b396a2ff6d6","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"a95488bd107fec32","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"aa8e84bd80448410","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"63a0cca4218135c9","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"91a1733ac5874a1c","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"5c8abc657915fd35","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"917cc91081fe5b07","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"a53545381bdd0cbf","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"4bc186645ccbf442","prefixes":{"":{"product":788}}}, // [DYNADMIC SAS] - {"hash":"3d6ddf04f9124237","prefixes":{"":{"product":789}}}, // [Yoc Mobile Advertising GmbH] - {"hash":"ec5fe7560209f819","prefixes":{"":{"product":359}}}, // [Quantcast Inc.] - {"hash":"5fe3e321ae6e4bf6","prefixes":{"":{"product":359}}}, // [Quantcast Inc.] + {"hash":"2e2859be7da1ee82","prefixes":{"":{"product":782,"type":0}}}, // [Belboon] + {"hash":"ff591094a6a13480","prefixes":{"*":{"product":783,"type":0}}}, // [Ozone Media Solutions Pvt Ltd] + {"hash":"3bd09c8fad6ac0cd","prefixes":{"*":{"product":783,"type":0}}}, // [Ozone Media Solutions Pvt Ltd] + {"hash":"41385cd812900dd3","prefixes":{"*":{"product":783,"type":0}}}, // [Ozone Media Solutions Pvt Ltd] + {"hash":"78bdf43617c9f3ed","prefixes":{"":{"product":784,"type":0}}}, // [Hindustan Times Mobile Solutions Limited] + {"hash":"f669a1035330e753","prefixes":{"*":{"product":783,"type":0}}}, // [Ozone Media Solutions Pvt Ltd] + {"hash":"74c5a373ee6172a1","prefixes":{"":{"product":785,"type":0}}}, // [SoftLayer Technologies, Inc.] + {"hash":"3762c6694e48ada4","prefixes":{"":{"product":785,"type":0}}}, // [SoftLayer Technologies, Inc.] + {"hash":"885e91388dd960b6","prefixes":{"":{"product":785,"type":0}}}, // [SoftLayer Technologies, Inc.] + {"hash":"f6a553969be0331b","prefixes":{"":{"product":785,"type":0}}}, // [SoftLayer Technologies, Inc.] + {"hash":"48d6fc29b318593f","prefixes":{"":{"product":785,"type":0}}}, // [SoftLayer Technologies, Inc.] + {"hash":"1e571da94b4242ba","prefixes":{"":{"product":785,"type":0}}}, // [SoftLayer Technologies, Inc.] + {"hash":"e6770fd6222ae990","prefixes":{"":{"product":785,"type":0}}}, // [SoftLayer Technologies, Inc.] + {"hash":"20b17ee9acc1afb9","prefixes":{"":{"product":785,"type":0}}}, // [SoftLayer Technologies, Inc.] + {"hash":"c483854c67d0c950","prefixes":{"":{"product":785,"type":0}}}, // [SoftLayer Technologies, Inc.] + {"hash":"5214f14e27a71d7f","prefixes":{"":{"product":786,"type":0}}}, // [GoldSpot Media] + {"hash":"61c576ffa8275ef3","prefixes":{"":{"product":786,"type":0}}}, // [GoldSpot Media] + {"hash":"c6af9ddc14757f86","prefixes":{"":{"product":786,"type":0}}}, // [GoldSpot Media] + {"hash":"86e9128d66cc0207","prefixes":{"":{"product":786,"type":0}}}, // [GoldSpot Media] + {"hash":"c71d0bd2e6f83f82","prefixes":{"":{"product":786,"type":0}}}, // [GoldSpot Media] + {"hash":"97be67a3b0baedf9","prefixes":{"":{"product":786,"type":0}}}, // [GoldSpot Media] + {"hash":"9622fe3e417564fb","prefixes":{"":{"product":786,"type":0}}}, // [GoldSpot Media] + {"hash":"a63ebe94fca61ed9","prefixes":{"":{"product":786,"type":0}}}, // [GoldSpot Media] + {"hash":"bbc1dd12d3cdb0b4","prefixes":{"":{"product":786,"type":0}}}, // [GoldSpot Media] + {"hash":"962da7f5c63ff169","prefixes":{"":{"product":786,"type":0}}}, // [GoldSpot Media] + {"hash":"94bb51394747c625","prefixes":{"":{"product":786,"type":0}}}, // [GoldSpot Media] + {"hash":"3ff8867b3d239d21","prefixes":{"":{"product":786,"type":0}}}, // [GoldSpot Media] + {"hash":"a970a6e82a98c461","prefixes":{"":{"product":787,"type":0}}}, // [Zeeto Media] + {"hash":"4c975affcaea9100","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"dfd86d0838962249","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"91f2b2338b35b7b2","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"3bec5ca280ea1b83","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"3d88758bd6e0003a","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"5c4e7b396a2ff6d6","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"a95488bd107fec32","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"aa8e84bd80448410","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"63a0cca4218135c9","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"91a1733ac5874a1c","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"5c8abc657915fd35","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"917cc91081fe5b07","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"a53545381bdd0cbf","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"4bc186645ccbf442","prefixes":{"":{"product":788,"type":0}}}, // [DYNADMIC SAS] + {"hash":"3d6ddf04f9124237","prefixes":{"":{"product":789,"type":0}}}, // [Yoc Mobile Advertising GmbH] + {"hash":"ec5fe7560209f819","prefixes":{"":{"product":359,"type":0}}}, // [Quantcast Inc.] + {"hash":"5fe3e321ae6e4bf6","prefixes":{"":{"product":359,"type":0}}}, // [Quantcast Inc.] {"hash":"8be056c242dd9d72","prefixes":{"":{"product":359}}}, // [Quantcast Inc.] - {"hash":"f8ee5abf7ea1abc7","prefixes":{"":{"product":790}}}, // [Velti] - {"hash":"59f840ce07769698","prefixes":{"":{"product":790}}}, // [Velti] - {"hash":"e013843f461a8d4b","prefixes":{"":{"product":790}}}, // [Velti] - {"hash":"bfe3cf089cc18922","prefixes":{"":{"product":790}}}, // [Velti] - {"hash":"9bd20c9549f20865","prefixes":{"":{"product":791}}}, // [Lockon] - {"hash":"f24f331de69a707a","prefixes":{"":{"product":791}}}, // [Lockon] - {"hash":"566f866251bd714e","prefixes":{"":{"product":791}}}, // [Lockon] - {"hash":"4baa350d3cc68f76","prefixes":{"":{"product":792}}}, // [Recruit Co., Ltd. Communications] - {"hash":"9bc564a146df07e7","prefixes":{"":{"product":792}}}, // [Recruit Co., Ltd. Communications] - {"hash":"35c56cfd7e378fad","prefixes":{"":{"product":793}}}, // [RECRUIT Communications] - {"hash":"6b9aad5cb94eb206","prefixes":{"":{"product":793}}}, // [RECRUIT Communications] - {"hash":"671a4bc2e5c9113e","prefixes":{"":{"product":794}}}, // [Hatena Co., Ltd] - {"hash":"6d3fdce985f31bd4","prefixes":{"":{"product":795}}}, // [Trafmag] - {"hash":"1a311d346529c16b","prefixes":{"":{"product":795}}}, // [Trafmag] - {"hash":"cd26b0ae13c2440e","prefixes":{"":{"product":796}}}, // [Pagewoo] - {"hash":"06e9b4b216458951","prefixes":{"":{"product":797}}}, // [Adnet Media] - {"hash":"cc0e43344ef5e735","prefixes":{"":{"product":797}}}, // [Adnet Media] - {"hash":"2bff36578242b6b3","prefixes":{"":{"product":797}}}, // [Adnet Media] - {"hash":"6bcb758317103435","prefixes":{"":{"product":797}}}, // [Adnet Media] - {"hash":"5819339a3e48afa9","prefixes":{"":{"product":797}}}, // [Adnet Media] - {"hash":"4249805768b5eaf7","prefixes":{"":{"product":798}}}, // [Ligatus GmbH] - {"hash":"c5d5cf4beb6462cf","prefixes":{"":{"product":798}}}, // [Ligatus GmbH] - {"hash":"41b628c1a22b441e","prefixes":{"":{"product":798}}}, // [Ligatus GmbH] - {"hash":"88d751d3810273e3","prefixes":{"":{"product":798}}}, // [Ligatus GmbH] - {"hash":"41ec9f7d9d627e03","prefixes":{"":{"product":798}}}, // [Ligatus GmbH] - {"hash":"02eb3f21dd6df789","prefixes":{"":{"product":798}}}, // [Ligatus GmbH] - {"hash":"6b48a245a94ab12a","prefixes":{"":{"product":798}}}, // [Ligatus GmbH] - {"hash":"41d07cfbdb75024a","prefixes":{"":{"product":799}}}, // [Webtrekk GmbH] - {"hash":"be359c4fcc3f3a06","prefixes":{"":{"product":799}}}, // [Webtrekk GmbH] - {"hash":"6f767739019dd808","prefixes":{"":{"product":799}}}, // [Webtrekk GmbH] - {"hash":"f253ef05e042b018","prefixes":{"":{"product":800}}}, // [Kantar World Panel] - {"hash":"d01896485cd39018","prefixes":{"":{"product":800}}}, // [Kantar World Panel] - {"hash":"0e0818ed2e61ee95","prefixes":{"":{"product":801}}}, // [PubSquared LLC] - {"hash":"b05f21964e55a827","prefixes":{"":{"product":802}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] - {"hash":"d333d9afb4898681","prefixes":{"":{"product":802}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] - {"hash":"1639db8eb5956a46","prefixes":{"":{"product":802}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] - {"hash":"5549a4c097f9b83d","prefixes":{"":{"product":802}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] - {"hash":"1dbbc11fea26048b","prefixes":{"":{"product":802}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] - {"hash":"098ed47c32246e74","prefixes":{"":{"product":802}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] - {"hash":"48556c67606eaf5a","prefixes":{"":{"product":802}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] - {"hash":"e9846bc3bb03a920","prefixes":{"":{"product":802}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] - {"hash":"49353a0b9f2b5bb5","prefixes":{"":{"product":802}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] - {"hash":"96bcc9c54b64eb5b","prefixes":{"":{"product":802}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] - {"hash":"f6e1c581da74f06c","prefixes":{"":{"product":803}}}, // [travel audience GmbH] - {"hash":"a00eb1259ded5bb1","prefixes":{"":{"product":803}}}, // [travel audience GmbH] - {"hash":"8026726dce357c58","prefixes":{"":{"product":804}}}, // [Krux Digital, Inc.] - {"hash":"95e17daf76b8a492","prefixes":{"":{"product":804}}}, // [Krux Digital, Inc.] - {"hash":"e2aedb8e35ba9ad0","prefixes":{"":{"product":804}}}, // [Krux Digital, Inc.] - {"hash":"7e954379b20a3955","prefixes":{"":{"product":804}}}, // [Krux Digital, Inc.] - {"hash":"bb2cd97362773074","prefixes":{"":{"product":804}}}, // [Krux Digital, Inc.] - {"hash":"5f545b8ac29b5d2d","prefixes":{"":{"product":805}}}, // [The Weather Channel] - {"hash":"188340d4038f111f","prefixes":{"":{"product":805}}}, // [The Weather Channel] - {"hash":"88ce1340354cf56f","prefixes":{"":{"product":805}}}, // [The Weather Channel] - {"hash":"6aa9e1031d5ce5ea","prefixes":{"":{"product":806}}}, // [Social Quantum] - {"hash":"924b0bbf98095055","prefixes":{"":{"product":806}}}, // [Social Quantum] - {"hash":"a8316ec9f577d677","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"4987a53ffae0e799","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"afafb80716e16e29","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"d0487d64f040dbfa","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"2c543734a4cbc5dd","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"067045f689cb5363","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"7ff291f0586a3dca","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"0a19a7d8484e10da","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"4614ce2d8cea29b5","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"c3164e283cfacd29","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"a1df629f546b9e31","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"6cbf35f72f18a347","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"1cb0768d21f55dd6","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"085272e0502f18c3","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"64b888da84877b17","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"c579af2db70b5cc0","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"306de8baaf32da18","prefixes":{"":{"product":807}}}, // [AdVentori SAS] - {"hash":"1e9f7eb550327800","prefixes":{"":{"product":808}}}, // [MindTake Research GmbH] - {"hash":"1c922be621564b9b","prefixes":{"":{"product":808}}}, // [MindTake Research GmbH] - {"hash":"b3f33aa4d02b6fb2","prefixes":{"":{"product":809}}}, // [Leger Marketing] - {"hash":"eead3245cdc680da","prefixes":{"":{"product":809}}}, // [Leger Marketing] - {"hash":"1239f4aeb30a0c6e","prefixes":{"":{"product":810}}}, // [BlisMedia Limited] - {"hash":"544a45aa905f9c6e","prefixes":{"":{"product":810}}}, // [BlisMedia Limited] - {"hash":"c5e4c8510e3cac80","prefixes":{"":{"product":811}}}, // [Double6] - {"hash":"d0fa41ada692b1b9","prefixes":{"":{"product":812}}}, // [TRADEADS INTERACTIVE] - {"hash":"3db0a72bcd75db25","prefixes":{"":{"product":813}}}, // [Epigrams, Inc.] - {"hash":"f42d4e28510cfcb3","prefixes":{"":{"product":813}}}, // [Epigrams, Inc.] - {"hash":"22d2d672aad6f400","prefixes":{"":{"product":814}}}, // [Activecore Inc.] - {"hash":"1ab5c06bec002a04","prefixes":{"":{"product":814}}}, // [Activecore Inc.] - {"hash":"c34010f1f0a2a2bd","prefixes":{"":{"product":814}}}, // [Activecore Inc.] - {"hash":"b274e3909d6409ff","prefixes":{"":{"product":815}}}, // [Activecore,Inc.] - {"hash":"1bdc7aff17b34632","prefixes":{"":{"product":815}}}, // [Activecore,Inc.] - {"hash":"a5f385ad8794bbf7","prefixes":{"":{"product":816}}}, // [ADCASH] - {"hash":"7fbf5ab845c319c3","prefixes":{"":{"product":816}}}, // [ADCASH] - {"hash":"636714c3598df906","prefixes":{"":{"product":816}}}, // [ADCASH] - {"hash":"9e6785892cd34bdd","prefixes":{"":{"product":816}}}, // [ADCASH] - {"hash":"047573e0075b371a","prefixes":{"":{"product":816}}}, // [ADCASH] - {"hash":"30468687bd7540d7","prefixes":{"":{"product":816}}}, // [ADCASH] - {"hash":"d38c33250529e4cf","prefixes":{"":{"product":816}}}, // [ADCASH] - {"hash":"311b59743017ebda","prefixes":{"":{"product":816}}}, // [ADCASH] - {"hash":"fceae2ba76fa56d8","prefixes":{"":{"product":816}}}, // [ADCASH] - {"hash":"e3e53a304101f0b8","prefixes":{"*":{"product":817}}}, // [Videoplaza] - {"hash":"66ae7f0627345a0e","prefixes":{"":{"product":818}}}, // [Targetix LLC] - {"hash":"f2825950bbc13084","prefixes":{"":{"product":818}}}, // [Targetix LLC] - {"hash":"5844bebbb6ebc2c8","prefixes":{"":{"product":818}}}, // [Targetix LLC] - {"hash":"af1d9e1f4d4a29ee","prefixes":{"":{"product":818}}}, // [Targetix LLC] - {"hash":"eabbec12e479563f","prefixes":{"":{"product":818}}}, // [Targetix LLC] - {"hash":"063e5c59c898b6b2","prefixes":{"":{"product":818}}}, // [Targetix LLC] - {"hash":"768e497f05eb9210","prefixes":{"":{"product":819}}}, // [Adriver LLC] - {"hash":"a3e9e1ffdc9ef6f3","prefixes":{"":{"product":820}}}, // [Beso] - {"hash":"dc3b4a3bb1a98472","prefixes":{"*":{"product":821}}}, // [Voopter.com] - {"hash":"608c4fc0e1249087","prefixes":{"":{"product":822}}}, // [Hostbasket] - {"hash":"ec50bd1f8e55703a","prefixes":{"":{"product":823}}}, // [Rollad] - {"hash":"75f08f4a618e4c29","prefixes":{"":{"product":823}}}, // [Rollad] - {"hash":"5e28845a397448ed","prefixes":{"":{"product":823}}}, // [Rollad] - {"hash":"43baf1a2f5c604eb","prefixes":{"":{"product":823}}}, // [Rollad] - {"hash":"9113c91f7c97eda8","prefixes":{"":{"product":823}}}, // [Rollad] - {"hash":"6e46faf33af4223b","prefixes":{"":{"product":823}}}, // [Rollad] - {"hash":"b8629ee4f4882cf4","prefixes":{"":{"product":823}}}, // [Rollad] - {"hash":"c580bf68b5705ecc","prefixes":{"":{"product":823}}}, // [Rollad] - {"hash":"30c1badbfab295cc","prefixes":{"":{"product":823}}}, // [Rollad] - {"hash":"07206ed226f7d186","prefixes":{"":{"product":824}}}, // [hdtMedia] - {"hash":"af031421c35c12bb","prefixes":{"":{"product":824}}}, // [hdtMedia] - {"hash":"c1e9215522e84feb","prefixes":{"":{"product":824}}}, // [hdtMedia] - {"hash":"f99b1e1004ffe36c","prefixes":{"":{"product":824}}}, // [hdtMedia] - {"hash":"cc5aed10326009cd","prefixes":{"":{"product":824}}}, // [hdtMedia] - {"hash":"a59bac0d7936d725","prefixes":{"":{"product":824}}}, // [hdtMedia] - {"hash":"85c92ca45eb6137a","prefixes":{"":{"product":824}}}, // [hdtMedia] - {"hash":"ecfa86f147eea591","prefixes":{"":{"product":824}}}, // [hdtMedia] - {"hash":"89c418c61cc46dbf","prefixes":{"":{"product":825}}}, // [DXP Media] - {"hash":"36712fa880f9f4fd","prefixes":{"":{"product":826}}}, // [ebuilders BV] - {"hash":"77af178b53829cee","prefixes":{"":{"product":826}}}, // [ebuilders BV] - {"hash":"19e3098ce56eae94","prefixes":{"":{"product":826}}}, // [ebuilders BV] - {"hash":"605d50a0c132e0b5","prefixes":{"":{"product":826}}}, // [ebuilders BV] - {"hash":"9cb69b24762928be","prefixes":{"":{"product":826}}}, // [ebuilders BV] - {"hash":"7ad4195e3856bc8b","prefixes":{"":{"product":826}}}, // [ebuilders BV] - {"hash":"a1f419f69f83a3cb","prefixes":{"":{"product":826}}}, // [ebuilders BV] - {"hash":"a8184454cf33a5e3","prefixes":{"":{"product":826}}}, // [ebuilders BV] - {"hash":"8c22c5755c763066","prefixes":{"":{"product":826}}}, // [ebuilders BV] - {"hash":"862c4454fe07929d","prefixes":{"":{"product":826}}}, // [ebuilders BV] - {"hash":"ac0afa5e86463dcf","prefixes":{"":{"product":827}}}, // [COADVERTISE] - {"hash":"049d375ddb03cca6","prefixes":{"":{"product":827}}}, // [COADVERTISE] - {"hash":"2ce968c3c01dac2b","prefixes":{"":{"product":828}}}, // [Blizzard] - {"hash":"6e4734c6df5289ef","prefixes":{"":{"product":828}}}, // [Blizzard] - {"hash":"9fe6f25a55c854ab","prefixes":{"":{"product":829}}}, // [Adgibbon] - {"hash":"008bfe35bcbd016d","prefixes":{"":{"product":829}}}, // [Adgibbon] - {"hash":"084705198bf3893b","prefixes":{"":{"product":829}}}, // [Adgibbon] - {"hash":"a1b65ade9cc861cb","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"42f9c0b081bf4152","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"ea90626af94135dd","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"ae4cfcc8964ff838","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"29ed865d96c2134b","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"f0ad420cd06e916d","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"02fa3036dfdd1f55","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"2e1689e37ca87292","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"e0f93c05dad3c3c6","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"3a2e2804dc9fbb61","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"deed6c9248e53552","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"c4597285474e8048","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"e127ffe380012cba","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"2f548a00d118d32e","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"015756b75eb89403","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"35d2e95d1522b0c5","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"a43e409504b254d3","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"5a4147bb67b5b23c","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"9866a49aaacb720e","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"f101934b33880c8d","prefixes":{"":{"product":830}}}, // [Wider Planet, Inc.] - {"hash":"5fc0aea809357158","prefixes":{"":{"product":107}}}, // [Kpsule] - {"hash":"ed7b8006e50dc195","prefixes":{"":{"product":107}}}, // [Kpsule] - {"hash":"fe112ea448efa84b","prefixes":{"":{"product":107}}}, // [Kpsule] - {"hash":"807a0ad2ef7d844d","prefixes":{"":{"product":107}}}, // [Kpsule] - {"hash":"24daf2e5c1e30aeb","prefixes":{"":{"product":107}}}, // [Kpsule] + {"hash":"f8ee5abf7ea1abc7","prefixes":{"":{"product":790,"type":0}}}, // [Velti] + {"hash":"59f840ce07769698","prefixes":{"":{"product":790,"type":0}}}, // [Velti] + {"hash":"e013843f461a8d4b","prefixes":{"":{"product":790,"type":0}}}, // [Velti] + {"hash":"bfe3cf089cc18922","prefixes":{"":{"product":790,"type":0}}}, // [Velti] + {"hash":"9bd20c9549f20865","prefixes":{"":{"product":791,"type":0}}}, // [Lockon] + {"hash":"f24f331de69a707a","prefixes":{"":{"product":791,"type":0}}}, // [Lockon] + {"hash":"566f866251bd714e","prefixes":{"":{"product":791,"type":0}}}, // [Lockon] + {"hash":"4baa350d3cc68f76","prefixes":{"":{"product":792,"type":0}}}, // [Recruit Co., Ltd. Communications] + {"hash":"9bc564a146df07e7","prefixes":{"":{"product":792,"type":0}}}, // [Recruit Co., Ltd. Communications] + {"hash":"35c56cfd7e378fad","prefixes":{"":{"product":793,"type":0}}}, // [RECRUIT Communications] + {"hash":"6b9aad5cb94eb206","prefixes":{"":{"product":793,"type":0}}}, // [RECRUIT Communications] + {"hash":"671a4bc2e5c9113e","prefixes":{"":{"product":794,"type":1}}}, // [Hatena Co., Ltd] + {"hash":"6d3fdce985f31bd4","prefixes":{"":{"product":795,"type":0}}}, // [Trafmag] + {"hash":"1a311d346529c16b","prefixes":{"":{"product":795,"type":0}}}, // [Trafmag] + {"hash":"cd26b0ae13c2440e","prefixes":{"":{"product":796,"type":0}}}, // [Pagewoo] + {"hash":"06e9b4b216458951","prefixes":{"":{"product":797,"type":0}}}, // [Adnet Media] + {"hash":"cc0e43344ef5e735","prefixes":{"":{"product":797,"type":0}}}, // [Adnet Media] + {"hash":"2bff36578242b6b3","prefixes":{"":{"product":797,"type":0}}}, // [Adnet Media] + {"hash":"6bcb758317103435","prefixes":{"":{"product":797,"type":0}}}, // [Adnet Media] + {"hash":"5819339a3e48afa9","prefixes":{"":{"product":797,"type":0}}}, // [Adnet Media] + {"hash":"4249805768b5eaf7","prefixes":{"":{"product":798,"type":0}}}, // [Ligatus GmbH] + {"hash":"c5d5cf4beb6462cf","prefixes":{"":{"product":798,"type":0}}}, // [Ligatus GmbH] + {"hash":"41b628c1a22b441e","prefixes":{"":{"product":798,"type":0}}}, // [Ligatus GmbH] + {"hash":"88d751d3810273e3","prefixes":{"":{"product":798,"type":0}}}, // [Ligatus GmbH] + {"hash":"41ec9f7d9d627e03","prefixes":{"":{"product":798,"type":0}}}, // [Ligatus GmbH] + {"hash":"02eb3f21dd6df789","prefixes":{"":{"product":798,"type":0}}}, // [Ligatus GmbH] + {"hash":"6b48a245a94ab12a","prefixes":{"":{"product":798,"type":0}}}, // [Ligatus GmbH] + {"hash":"41d07cfbdb75024a","prefixes":{"":{"product":799,"type":0}}}, // [Webtrekk GmbH] + {"hash":"be359c4fcc3f3a06","prefixes":{"":{"product":799,"type":0}}}, // [Webtrekk GmbH] + {"hash":"6f767739019dd808","prefixes":{"":{"product":799,"type":0}}}, // [Webtrekk GmbH] + {"hash":"f253ef05e042b018","prefixes":{"":{"product":800,"type":1}}}, // [Kantar World Panel] + {"hash":"d01896485cd39018","prefixes":{"":{"product":800,"type":1}}}, // [Kantar World Panel] + {"hash":"0e0818ed2e61ee95","prefixes":{"":{"product":801,"type":0}}}, // [PubSquared LLC] + {"hash":"b05f21964e55a827","prefixes":{"":{"product":802,"type":0}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] + {"hash":"d333d9afb4898681","prefixes":{"":{"product":802,"type":0}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] + {"hash":"1639db8eb5956a46","prefixes":{"":{"product":802,"type":0}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] + {"hash":"5549a4c097f9b83d","prefixes":{"":{"product":802,"type":0}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] + {"hash":"1dbbc11fea26048b","prefixes":{"":{"product":802,"type":0}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] + {"hash":"098ed47c32246e74","prefixes":{"":{"product":802,"type":0}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] + {"hash":"48556c67606eaf5a","prefixes":{"":{"product":802,"type":0}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] + {"hash":"e9846bc3bb03a920","prefixes":{"":{"product":802,"type":0}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] + {"hash":"49353a0b9f2b5bb5","prefixes":{"":{"product":802,"type":0}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] + {"hash":"96bcc9c54b64eb5b","prefixes":{"":{"product":802,"type":0}}}, // [Baidu.com Times Technology (Beijing) Co., Ltd] + {"hash":"f6e1c581da74f06c","prefixes":{"":{"product":803,"type":0}}}, // [travel audience GmbH] + {"hash":"a00eb1259ded5bb1","prefixes":{"":{"product":803,"type":0}}}, // [travel audience GmbH] + {"hash":"8026726dce357c58","prefixes":{"":{"product":804,"type":1}}}, // [Krux Digital, Inc.] + {"hash":"95e17daf76b8a492","prefixes":{"":{"product":804,"type":1}}}, // [Krux Digital, Inc.] + {"hash":"e2aedb8e35ba9ad0","prefixes":{"":{"product":804,"type":1}}}, // [Krux Digital, Inc.] + {"hash":"7e954379b20a3955","prefixes":{"":{"product":804,"type":1}}}, // [Krux Digital, Inc.] + {"hash":"bb2cd97362773074","prefixes":{"":{"product":804,"type":1}}}, // [Krux Digital, Inc.] + {"hash":"5f545b8ac29b5d2d","prefixes":{"":{"product":805,"type":0}}}, // [The Weather Channel] + {"hash":"188340d4038f111f","prefixes":{"":{"product":805,"type":0}}}, // [The Weather Channel] + {"hash":"88ce1340354cf56f","prefixes":{"":{"product":805,"type":0}}}, // [The Weather Channel] + {"hash":"6aa9e1031d5ce5ea","prefixes":{"":{"product":806,"type":1}}}, // [Social Quantum] + {"hash":"924b0bbf98095055","prefixes":{"":{"product":806,"type":1}}}, // [Social Quantum] + {"hash":"a8316ec9f577d677","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"4987a53ffae0e799","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"afafb80716e16e29","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"d0487d64f040dbfa","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"2c543734a4cbc5dd","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"067045f689cb5363","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"7ff291f0586a3dca","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"0a19a7d8484e10da","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"4614ce2d8cea29b5","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"c3164e283cfacd29","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"a1df629f546b9e31","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"6cbf35f72f18a347","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"1cb0768d21f55dd6","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"085272e0502f18c3","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"64b888da84877b17","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"c579af2db70b5cc0","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"306de8baaf32da18","prefixes":{"":{"product":807,"type":0}}}, // [AdVentori SAS] + {"hash":"1e9f7eb550327800","prefixes":{"":{"product":808,"type":1}}}, // [MindTake Research GmbH] + {"hash":"1c922be621564b9b","prefixes":{"":{"product":808,"type":1}}}, // [MindTake Research GmbH] + {"hash":"b3f33aa4d02b6fb2","prefixes":{"":{"product":809,"type":1}}}, // [Leger Marketing] + {"hash":"eead3245cdc680da","prefixes":{"":{"product":809,"type":1}}}, // [Leger Marketing] + {"hash":"1239f4aeb30a0c6e","prefixes":{"":{"product":810,"type":0}}}, // [BlisMedia Limited] + {"hash":"544a45aa905f9c6e","prefixes":{"":{"product":810,"type":0}}}, // [BlisMedia Limited] + {"hash":"c5e4c8510e3cac80","prefixes":{"":{"product":811,"type":1}}}, // [Double6] + {"hash":"d0fa41ada692b1b9","prefixes":{"":{"product":812,"type":0}}}, // [TRADEADS INTERACTIVE] + {"hash":"3db0a72bcd75db25","prefixes":{"":{"product":813,"type":0}}}, // [Epigrams, Inc.] + {"hash":"f42d4e28510cfcb3","prefixes":{"":{"product":813,"type":0}}}, // [Epigrams, Inc.] + {"hash":"22d2d672aad6f400","prefixes":{"":{"product":814,"type":1}}}, // [Activecore Inc.] + {"hash":"1ab5c06bec002a04","prefixes":{"":{"product":814,"type":1}}}, // [Activecore Inc.] + {"hash":"c34010f1f0a2a2bd","prefixes":{"":{"product":814,"type":1}}}, // [Activecore Inc.] + {"hash":"b274e3909d6409ff","prefixes":{"":{"product":815,"type":0}}}, // [Activecore,Inc.] + {"hash":"1bdc7aff17b34632","prefixes":{"":{"product":815,"type":0}}}, // [Activecore,Inc.] + {"hash":"a5f385ad8794bbf7","prefixes":{"":{"product":816,"type":0}}}, // [ADCASH] + {"hash":"7fbf5ab845c319c3","prefixes":{"":{"product":816,"type":0}}}, // [ADCASH] + {"hash":"636714c3598df906","prefixes":{"":{"product":816,"type":0}}}, // [ADCASH] + {"hash":"9e6785892cd34bdd","prefixes":{"":{"product":816,"type":0}}}, // [ADCASH] + {"hash":"047573e0075b371a","prefixes":{"":{"product":816,"type":0}}}, // [ADCASH] + {"hash":"30468687bd7540d7","prefixes":{"":{"product":816,"type":0}}}, // [ADCASH] + {"hash":"d38c33250529e4cf","prefixes":{"":{"product":816,"type":0}}}, // [ADCASH] + {"hash":"311b59743017ebda","prefixes":{"":{"product":816,"type":0}}}, // [ADCASH] + {"hash":"fceae2ba76fa56d8","prefixes":{"":{"product":816,"type":0}}}, // [ADCASH] + {"hash":"e3e53a304101f0b8","prefixes":{"*":{"product":817,"type":0}}}, // [Videoplaza] + {"hash":"66ae7f0627345a0e","prefixes":{"":{"product":818,"type":0}}}, // [Targetix LLC] + {"hash":"f2825950bbc13084","prefixes":{"":{"product":818,"type":0}}}, // [Targetix LLC] + {"hash":"5844bebbb6ebc2c8","prefixes":{"":{"product":818,"type":0}}}, // [Targetix LLC] + {"hash":"af1d9e1f4d4a29ee","prefixes":{"":{"product":818,"type":0}}}, // [Targetix LLC] + {"hash":"eabbec12e479563f","prefixes":{"":{"product":818,"type":0}}}, // [Targetix LLC] + {"hash":"063e5c59c898b6b2","prefixes":{"":{"product":818,"type":0}}}, // [Targetix LLC] + {"hash":"768e497f05eb9210","prefixes":{"":{"product":819,"type":1}}}, // [Adriver LLC] + {"hash":"a3e9e1ffdc9ef6f3","prefixes":{"":{"product":820,"type":0}}}, // [Beso] + {"hash":"dc3b4a3bb1a98472","prefixes":{"*":{"product":821,"type":0}}}, // [Voopter.com] + {"hash":"608c4fc0e1249087","prefixes":{"":{"product":822,"type":0}}}, // [Hostbasket] + {"hash":"ec50bd1f8e55703a","prefixes":{"":{"product":823,"type":0}}}, // [Rollad] + {"hash":"75f08f4a618e4c29","prefixes":{"":{"product":823,"type":0}}}, // [Rollad] + {"hash":"5e28845a397448ed","prefixes":{"":{"product":823,"type":0}}}, // [Rollad] + {"hash":"43baf1a2f5c604eb","prefixes":{"":{"product":823,"type":0}}}, // [Rollad] + {"hash":"9113c91f7c97eda8","prefixes":{"":{"product":823,"type":0}}}, // [Rollad] + {"hash":"6e46faf33af4223b","prefixes":{"":{"product":823,"type":0}}}, // [Rollad] + {"hash":"b8629ee4f4882cf4","prefixes":{"":{"product":823,"type":0}}}, // [Rollad] + {"hash":"c580bf68b5705ecc","prefixes":{"":{"product":823,"type":0}}}, // [Rollad] + {"hash":"30c1badbfab295cc","prefixes":{"":{"product":823,"type":0}}}, // [Rollad] + {"hash":"07206ed226f7d186","prefixes":{"":{"product":824,"type":0}}}, // [hdtMedia] + {"hash":"af031421c35c12bb","prefixes":{"":{"product":824,"type":0}}}, // [hdtMedia] + {"hash":"c1e9215522e84feb","prefixes":{"":{"product":824,"type":0}}}, // [hdtMedia] + {"hash":"f99b1e1004ffe36c","prefixes":{"":{"product":824,"type":0}}}, // [hdtMedia] + {"hash":"cc5aed10326009cd","prefixes":{"":{"product":824,"type":0}}}, // [hdtMedia] + {"hash":"a59bac0d7936d725","prefixes":{"":{"product":824,"type":0}}}, // [hdtMedia] + {"hash":"85c92ca45eb6137a","prefixes":{"":{"product":824,"type":0}}}, // [hdtMedia] + {"hash":"ecfa86f147eea591","prefixes":{"":{"product":824,"type":0}}}, // [hdtMedia] + {"hash":"89c418c61cc46dbf","prefixes":{"":{"product":825,"type":0}}}, // [DXP Media] + {"hash":"36712fa880f9f4fd","prefixes":{"":{"product":826,"type":2}}}, // [ebuilders BV] + {"hash":"77af178b53829cee","prefixes":{"":{"product":826,"type":2}}}, // [ebuilders BV] + {"hash":"19e3098ce56eae94","prefixes":{"":{"product":826,"type":2}}}, // [ebuilders BV] + {"hash":"605d50a0c132e0b5","prefixes":{"":{"product":826,"type":2}}}, // [ebuilders BV] + {"hash":"9cb69b24762928be","prefixes":{"":{"product":826,"type":2}}}, // [ebuilders BV] + {"hash":"7ad4195e3856bc8b","prefixes":{"":{"product":826,"type":2}}}, // [ebuilders BV] + {"hash":"a1f419f69f83a3cb","prefixes":{"":{"product":826,"type":2}}}, // [ebuilders BV] + {"hash":"a8184454cf33a5e3","prefixes":{"":{"product":826,"type":2}}}, // [ebuilders BV] + {"hash":"8c22c5755c763066","prefixes":{"":{"product":826,"type":2}}}, // [ebuilders BV] + {"hash":"862c4454fe07929d","prefixes":{"":{"product":826,"type":2}}}, // [ebuilders BV] + {"hash":"ac0afa5e86463dcf","prefixes":{"":{"product":827,"type":0}}}, // [COADVERTISE] + {"hash":"049d375ddb03cca6","prefixes":{"":{"product":827,"type":0}}}, // [COADVERTISE] + {"hash":"2ce968c3c01dac2b","prefixes":{"":{"product":828,"type":2}}}, // [Blizzard] + {"hash":"6e4734c6df5289ef","prefixes":{"":{"product":828,"type":2}}}, // [Blizzard] + {"hash":"9fe6f25a55c854ab","prefixes":{"":{"product":829,"type":0}}}, // [Adgibbon] + {"hash":"008bfe35bcbd016d","prefixes":{"":{"product":829,"type":0}}}, // [Adgibbon] + {"hash":"084705198bf3893b","prefixes":{"":{"product":829,"type":0}}}, // [Adgibbon] + {"hash":"a1b65ade9cc861cb","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"42f9c0b081bf4152","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"ea90626af94135dd","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"ae4cfcc8964ff838","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"29ed865d96c2134b","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"f0ad420cd06e916d","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"02fa3036dfdd1f55","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"2e1689e37ca87292","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"e0f93c05dad3c3c6","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"3a2e2804dc9fbb61","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"deed6c9248e53552","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"c4597285474e8048","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"e127ffe380012cba","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"2f548a00d118d32e","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"015756b75eb89403","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"35d2e95d1522b0c5","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"a43e409504b254d3","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"5a4147bb67b5b23c","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"9866a49aaacb720e","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"f101934b33880c8d","prefixes":{"":{"product":830,"type":0}}}, // [Wider Planet, Inc.] + {"hash":"5fc0aea809357158","prefixes":{"":{"product":107,"type":0}}}, // [Kpsule] + {"hash":"ed7b8006e50dc195","prefixes":{"":{"product":107,"type":0}}}, // [Kpsule] + {"hash":"fe112ea448efa84b","prefixes":{"":{"product":107,"type":0}}}, // [Kpsule] + {"hash":"807a0ad2ef7d844d","prefixes":{"":{"product":107,"type":0}}}, // [Kpsule] + {"hash":"24daf2e5c1e30aeb","prefixes":{"":{"product":107,"type":0}}}, // [Kpsule] {"hash":"9091656f8979f5f0","prefixes":{"":{"product":107}}}, // [Kpsule] - {"hash":"bb5ef61e19944a06","prefixes":{"":{"product":831}}}, // [ResponsiveAds, Inc] - {"hash":"ef4fefbe73da4a59","prefixes":{"":{"product":831}}}, // [ResponsiveAds, Inc] - {"hash":"e78ef2faad563e6b","prefixes":{"":{"product":831}}}, // [ResponsiveAds, Inc] - {"hash":"20e99abfa9e5de7c","prefixes":{"":{"product":831}}}, // [ResponsiveAds, Inc] - {"hash":"0dedc650dbf5d391","prefixes":{"":{"product":831}}}, // [ResponsiveAds, Inc] - {"hash":"5bdaec9fd3ff4dac","prefixes":{"":{"product":832}}}, // [Duepuntozero Research SRL] - {"hash":"318bfe954294ea40","prefixes":{"":{"product":833}}}, // [AdMovate, Inc.] - {"hash":"e24259ffed4d244f","prefixes":{"":{"product":833}}}, // [AdMovate, Inc.] - {"hash":"c39b0621d7a8b616","prefixes":{"":{"product":834}}}, // [go.pl] - {"hash":"29c359aefdd48c40","prefixes":{"":{"product":834}}}, // [go.pl] - {"hash":"6ecf3c2aeb5aec2b","prefixes":{"":{"product":834}}}, // [go.pl] - {"hash":"eea1a3478557a7a6","prefixes":{"":{"product":834}}}, // [go.pl] - {"hash":"0b0e365de9c89436","prefixes":{"":{"product":834}}}, // [go.pl] - {"hash":"875d9d8b11a6dff7","prefixes":{"":{"product":834}}}, // [go.pl] - {"hash":"5edb8f1a6337d5d0","prefixes":{"":{"product":834}}}, // [go.pl] - {"hash":"435808ca4dd1dce5","prefixes":{"":{"product":834}}}, // [go.pl] - {"hash":"fd43d007391147de","prefixes":{"":{"product":710}}}, // [MASSMOTIONMEDIA SARL] - {"hash":"633236a94b694dd7","prefixes":{"":{"product":710}}}, // [MASSMOTIONMEDIA SARL] - {"hash":"a076e91e809efc28","prefixes":{"*":{"product":835}}}, // [AppLovin Corporation] - {"hash":"14c26da0caac0796","prefixes":{"":{"product":836}}}, // [twentysix ltd] - {"hash":"1f8d7bcebd64d2c9","prefixes":{"":{"product":15}}}, // [Tamome] - {"hash":"41f4c0bf12c8f029","prefixes":{"":{"product":336}}}, // [EuroAds Group A/S] - {"hash":"e674b14a061bb7d7","prefixes":{"":{"product":336}}}, // [EuroAds Group A/S] - {"hash":"f485e2bb528d3147","prefixes":{"":{"product":336}}}, // [EuroAds Group A/S] - {"hash":"82c09e315af7d70c","prefixes":{"":{"product":336}}}, // [EuroAds Group A/S] - {"hash":"fc2b985669148068","prefixes":{"":{"product":336}}}, // [EuroAds Group A/S] - {"hash":"cf9a9377bc72c2e4","prefixes":{"":{"product":336}}}, // [EuroAds Group A/S] - {"hash":"d550149a2d5cfdde","prefixes":{"":{"product":336}}}, // [EuroAds Group A/S] - {"hash":"d51c2c24cd771a6a","prefixes":{"":{"product":837}}}, // [Epsilon International SA] - {"hash":"d34cf98578200c93","prefixes":{"":{"product":838}}}, // [Zebestof] - {"hash":"44c2302577bd8e84","prefixes":{"":{"product":838}}}, // [Zebestof] - {"hash":"52b835c5657206c1","prefixes":{"":{"product":838}}}, // [Zebestof] - {"hash":"caa0c94cf57e2295","prefixes":{"":{"product":838}}}, // [Zebestof] - {"hash":"02e54ec6b0aca548","prefixes":{"":{"product":839}}}, // [SOL UTD Benelux BV] - {"hash":"1cf1a7f5c323d6e0","prefixes":{"":{"product":840}}}, // [M,P,NEWMEDIA, GmbH] - {"hash":"079a647886a5afa5","prefixes":{"":{"product":840}}}, // [M,P,NEWMEDIA, GmbH] - {"hash":"ec320d28ebdfac8c","prefixes":{"":{"product":840}}}, // [M,P,NEWMEDIA, GmbH] - {"hash":"e59449da7e642b45","prefixes":{"":{"product":840}}}, // [M,P,NEWMEDIA, GmbH] - {"hash":"1d61751db94dfc15","prefixes":{"":{"product":840}}}, // [M,P,NEWMEDIA, GmbH] - {"hash":"43f7746544162324","prefixes":{"":{"product":840}}}, // [M,P,NEWMEDIA, GmbH] - {"hash":"4f80c8700c459a79","prefixes":{"":{"product":840}}}, // [M,P,NEWMEDIA, GmbH] - {"hash":"23f62ba113f0fa4f","prefixes":{"":{"product":841}}}, // [MediaCrossing Inc.] - {"hash":"62fc0fc3102b918b","prefixes":{"":{"product":842}}}, // [MBR Targeting Gmbh] - {"hash":"0066f0743ade259b","prefixes":{"":{"product":842}}}, // [MBR Targeting Gmbh] - {"hash":"4288d021c49b7e1b","prefixes":{"":{"product":842}}}, // [MBR Targeting Gmbh] - {"hash":"6620a58a1f4cd480","prefixes":{"":{"product":843}}}, // [VivaKi] - {"hash":"47db57aade94670f","prefixes":{"":{"product":843}}}, // [VivaKi] - {"hash":"2924b77c1d7eab3b","prefixes":{"":{"product":843}}}, // [VivaKi] - {"hash":"d2143dbf1699f4fa","prefixes":{"":{"product":844}}}, // [Affiliate Window] - {"hash":"13c2a94c46886705","prefixes":{"":{"product":844}}}, // [Affiliate Window] - {"hash":"c0d30b023dc9139f","prefixes":{"*":{"product":845}}}, // [TubeMogul Inc. (AdWords/YouTube)] - {"hash":"108d788939e4b7a4","prefixes":{"":{"product":825}}}, // [DXP Media] - {"hash":"6fdc121917e19eb9","prefixes":{"":{"product":825}}}, // [DXP Media] - {"hash":"5262a88cfa363303","prefixes":{"":{"product":825}}}, // [DXP Media] - {"hash":"b597af924fe5ff97","prefixes":{"":{"product":825}}}, // [DXP Media] - {"hash":"dca60f44a70d5d38","prefixes":{"":{"product":825}}}, // [DXP Media] - {"hash":"c44308d5c2e3bb8a","prefixes":{"":{"product":825}}}, // [DXP Media] - {"hash":"90f5b971c961816f","prefixes":{"":{"product":825}}}, // [DXP Media] - {"hash":"5d64c1152c075739","prefixes":{"":{"product":846}}}, // [Way2traffic Polska S.A.] - {"hash":"01b13121d2ce9699","prefixes":{"":{"product":846}}}, // [Way2traffic Polska S.A.] - {"hash":"f48791a2746e2a93","prefixes":{"":{"product":847}}}, // [TNS Sifo AB] - {"hash":"935b8079b74f344c","prefixes":{"":{"product":847}}}, // [TNS Sifo AB] - {"hash":"24e5b8b342d1b1fe","prefixes":{"":{"product":848}}}, // [3xchange/Hunkal] - {"hash":"ad8c8bc165611bf2","prefixes":{"":{"product":848}}}, // [3xchange/Hunkal] - {"hash":"b1b5bdd82d143e90","prefixes":{"":{"product":849}}}, // [Emerse Sverige AB] - {"hash":"aeddaa071ba3b313","prefixes":{"":{"product":849}}}, // [Emerse Sverige AB] - {"hash":"474802ea42555e39","prefixes":{"":{"product":849}}}, // [Emerse Sverige AB] - {"hash":"b28e42ea18df1c00","prefixes":{"":{"product":849}}}, // [Emerse Sverige AB] - {"hash":"826635800b12eb0c","prefixes":{"":{"product":849}}}, // [Emerse Sverige AB] - {"hash":"22c10728f555913e","prefixes":{"":{"product":849}}}, // [Emerse Sverige AB] - {"hash":"0b7f364ef0beed45","prefixes":{"":{"product":849}}}, // [Emerse Sverige AB] - {"hash":"8d31e79105c5380a","prefixes":{"":{"product":850}}}, // [Sokno Media] - {"hash":"037264ef7d8383f6","prefixes":{"":{"product":850}}}, // [Sokno Media] - {"hash":"ff6372e6621d88ba","prefixes":{"":{"product":851}}}, // [Blackheart, a division of Hot Topic, Inc.] - {"hash":"37742852c2a4ccc8","prefixes":{"":{"product":852}}}, // [Torrid] - {"hash":"a86786ce90b23e3f","prefixes":{"":{"product":853}}}, // [Hot Topic, Inc.] - {"hash":"93e1c22a4427a32f","prefixes":{"":{"product":854}}}, // [WebHue LLC] - {"hash":"fca0a42aad108345","prefixes":{"static":{"product":855},"img":{"product":855},"log":{"product":855}}}, // [Content to Emotion] [Content to Emotion] [Content to Emotion] - {"hash":"15948cae619c2e58","prefixes":{"":{"product":855}}}, // [Content to Emotion] - {"hash":"db2a81c15837ddbd","prefixes":{"":{"product":856}}}, // [Adman Interactive SL] - {"hash":"accf1565984e2899","prefixes":{"":{"product":856}}}, // [Adman Interactive SL] - {"hash":"45351e5c4862b2dd","prefixes":{"":{"product":856}}}, // [Adman Interactive SL] - {"hash":"ba3196c50e6c1be4","prefixes":{"":{"product":856}}}, // [Adman Interactive SL] - {"hash":"eab724fbba4f83d6","prefixes":{"":{"product":856}}}, // [Adman Interactive SL] - {"hash":"0edc8e7b8a8fe3ee","prefixes":{"":{"product":857}}}, // [AudienceFUEL, Inc.] - {"hash":"dfa423315ab48813","prefixes":{"":{"product":858}}}, // [TapCommerce LLC] - {"hash":"777b0f4301aa1643","prefixes":{"":{"product":858}}}, // [TapCommerce LLC] - {"hash":"294cba0ae232447c","prefixes":{"":{"product":859}}}, // [AdTheorent, Inc.] - {"hash":"ba7ad5da6db014c7","prefixes":{"":{"product":860}}}, // [AdTheorent, Inc] - {"hash":"09bfc8a7f1c7896f","prefixes":{"":{"product":859}}}, // [AdTheorent, Inc.] - {"hash":"362136e847a35f7e","prefixes":{"":{"product":859}}}, // [AdTheorent, Inc.] - {"hash":"5492d77bb75e6380","prefixes":{"":{"product":861}}}, // [Barometric] - {"hash":"94bb816c4a375220","prefixes":{"":{"product":862}}}, // [CrossInstall, Inc] - {"hash":"f10e1a418576d219","prefixes":{"":{"product":862}}}, // [CrossInstall, Inc] - {"hash":"245fc951b0a9ce59","prefixes":{"":{"product":862}}}, // [CrossInstall, Inc] - {"hash":"babdceabca3ae2b8","prefixes":{"":{"product":862}}}, // [CrossInstall, Inc] - {"hash":"c6474114ede3195a","prefixes":{"":{"product":862}}}, // [CrossInstall, Inc] - {"hash":"26faef64bd072723","prefixes":{"":{"product":862}}}, // [CrossInstall, Inc] - {"hash":"0a19b1f547a3a935","prefixes":{"":{"product":862}}}, // [CrossInstall, Inc] - {"hash":"b4ef56642916cc60","prefixes":{"":{"product":862}}}, // [CrossInstall, Inc] - {"hash":"c1fc9d245fa85b02","prefixes":{"":{"product":862}}}, // [CrossInstall, Inc] - {"hash":"0e3ddb4868b0e99f","prefixes":{"":{"product":863}}}, // [Theorem Inc.] - {"hash":"976d4ea6507dfd2e","prefixes":{"":{"product":863}}}, // [Theorem Inc.] - {"hash":"70a3fe87d3bbbae9","prefixes":{"":{"product":863}}}, // [Theorem Inc.] - {"hash":"1cf1ec002a07d6a4","prefixes":{"":{"product":864}}}, // [KeyVersion] - {"hash":"b2c480f3bc7b03b6","prefixes":{"":{"product":864}}}, // [KeyVersion] - {"hash":"c94dbc0a3ffc6eda","prefixes":{"":{"product":865}}}, // [Ancestry] - {"hash":"04fb46af993df556","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"b9adf25b55c4d0f3","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"1c1211c84dbee054","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"575fafb094c71d93","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"f2b020b3d3861db2","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"609d13c5cd3771c8","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"aeae313934102cfe","prefixes":{"":{"product":867}}}, // [Shanghai Lijing Advertising Co., Ltd] - {"hash":"f8721bcf4d9f6196","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"09e5f7c9f30f4fd6","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"a1ce57d387427206","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"bb4b6377666172c4","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"d6a6a6cd062bc76e","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"0313ce8a9851d837","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"6862450d2314df40","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"0a34c9f6f0cf9556","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"8e311fce80eccafd","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"296fdad7e8336d5a","prefixes":{"":{"product":866}}}, // [Shanghai Lijing Advertising Co., Ltd.] - {"hash":"27c0e177312a3c0f","prefixes":{"":{"product":108}}}, // [Immedium, Inc.] - {"hash":"fc3c7114081863bd","prefixes":{"":{"product":108}}}, // [Immedium, Inc.] - {"hash":"811582f5df157ff9","prefixes":{"":{"product":868}}}, // [KissNoFrog.com] - {"hash":"284d8a4f9b174bab","prefixes":{"":{"product":869}}}, // [DigiEQ] - {"hash":"aa0e7b7a1fe279dc","prefixes":{"":{"product":869}}}, // [DigiEQ] - {"hash":"1f551f934400f81e","prefixes":{"":{"product":86}}}, // [MediaMath Inc.] - {"hash":"1c3b94cabbbc5b8c","prefixes":{"":{"product":86}}}, // [MediaMath Inc.] - {"hash":"505b194aeebd6baf","prefixes":{"":{"product":870}}}, // [Mobile Professinals BV] - {"hash":"8f2e12e9677e4d41","prefixes":{"":{"product":870}}}, // [Mobile Professinals BV] - {"hash":"e2a3fe5e482432e8","prefixes":{"":{"product":870}}}, // [Mobile Professinals BV] - {"hash":"7d03cd1b92c167a8","prefixes":{"":{"product":870}}}, // [Mobile Professinals BV] - {"hash":"532402cd3ab13402","prefixes":{"":{"product":870}}}, // [Mobile Professinals BV] - {"hash":"48e577ba3e61c748","prefixes":{"":{"product":870}}}, // [Mobile Professinals BV] - {"hash":"1480a6580cb81dde","prefixes":{"":{"product":870}}}, // [Mobile Professinals BV] - {"hash":"b1ec46dd2c4c824e","prefixes":{"*":{"product":109}}}, // [Fractional Media, LLC] - {"hash":"6c6240697771befd","prefixes":{"*":{"product":109}}}, // [Fractional Media, LLC] - {"hash":"f2e16038c0d83b85","prefixes":{"":{"product":871}}}, // [Decisive, Inc.] - {"hash":"654da4ed85d77fb9","prefixes":{"":{"product":871}}}, // [Decisive, Inc.] - {"hash":"c9e2ea0486216534","prefixes":{"":{"product":871}}}, // [Decisive, Inc.] - {"hash":"546a2acb9b2363f2","prefixes":{"*":{"product":872}}}, // [Microsoft Security Essentials] - {"hash":"9e4f5b2f200fbb25","prefixes":{"":{"product":873}}}, // [Tumi, Inc. US] - {"hash":"4378c60894195c4f","prefixes":{"":{"product":874}}}, // [Tumi, Inc. UK] - {"hash":"61e82c5e74c5ce7c","prefixes":{"":{"product":875}}}, // [Tumi, Inc. DE] - {"hash":"712f010eb9792fa4","prefixes":{"":{"product":876}}}, // [Nanigans, Inc] - {"hash":"589eceaef79619dd","prefixes":{"":{"product":876}}}, // [Nanigans, Inc] - {"hash":"1d66f17c949dbaee","prefixes":{"":{"product":876}}}, // [Nanigans, Inc] - {"hash":"6dbd7b9480163af0","prefixes":{"":{"product":876}}}, // [Nanigans, Inc] - {"hash":"41d56e0870364212","prefixes":{"":{"product":139}}}, // [Brandscreen Inc.] - {"hash":"2d701495cf72af5b","prefixes":{"*":{"product":877}}}, // [AdSniper LLC] - {"hash":"0bd14e8d5a6b2f2d","prefixes":{"":{"product":877}}}, // [AdSniper LLC] - {"hash":"9b504cc586da72e5","prefixes":{"":{"product":877}}}, // [AdSniper LLC] - {"hash":"a89d4cb4490b4286","prefixes":{"":{"product":877}}}, // [AdSniper LLC] - {"hash":"dce925353cbc1dbe","prefixes":{"":{"product":877}}}, // [AdSniper LLC] - {"hash":"ff8d26679ce7dafc","prefixes":{"":{"product":877}}}, // [AdSniper LLC] - {"hash":"11db2fec76a76647","prefixes":{"":{"product":877}}}, // [AdSniper LLC] - {"hash":"00a09e8788ee6f2b","prefixes":{"":{"product":877}}}, // [AdSniper LLC] - {"hash":"709d79bfe214aa48","prefixes":{"":{"product":877}}}, // [AdSniper LLC] - {"hash":"7a37fa5ff1a37799","prefixes":{"":{"product":877}}}, // [AdSniper LLC] - {"hash":"42a24e1ab1c2d947","prefixes":{"":{"product":877}}}, // [AdSniper LLC] - {"hash":"63f4e4d315bc085b","prefixes":{"":{"product":878}}}, // [Fabric Worldwide Inc] - {"hash":"b9c11e67d7eb2963","prefixes":{"":{"product":878}}}, // [Fabric Worldwide Inc] - {"hash":"e3882e6bc0c2e382","prefixes":{"":{"product":879}}}, // [Vorwerk Deutschland Stiftung & Co. KG] - {"hash":"944d86d40b9ae089","prefixes":{"":{"product":879}}}, // [Vorwerk Deutschland Stiftung & Co. KG] - {"hash":"ebd456010571b5ae","prefixes":{"":{"product":879}}}, // [Vorwerk Deutschland Stiftung & Co. KG] - {"hash":"4456fa769be90ba2","prefixes":{"":{"product":65}}}, // [Active Agent] - {"hash":"84d65f5782dd26d6","prefixes":{"":{"product":880}}}, // [Chico Distribution Services, LLC] - {"hash":"a6185f46e2849f58","prefixes":{"":{"product":881}}}, // [12Mnkys GmbH] - {"hash":"bf874935c6972629","prefixes":{"":{"product":881}}}, // [12Mnkys GmbH] - {"hash":"094b301a712414f2","prefixes":{"":{"product":881}}}, // [12Mnkys GmbH] - {"hash":"56ee8d67408b2316","prefixes":{"":{"product":881}}}, // [12Mnkys GmbH] - {"hash":"d62d9c20c47ec863","prefixes":{"":{"product":881}}}, // [12Mnkys GmbH] - {"hash":"bb716a8269a2e79c","prefixes":{"":{"product":882}}}, // [Spacyz, Inc.] - {"hash":"5a6ff8a620bb8de1","prefixes":{"":{"product":882}}}, // [Spacyz, Inc.] - {"hash":"61cf0a8426083e54","prefixes":{"":{"product":882}}}, // [Spacyz, Inc.] - {"hash":"4cf4aa4b0e37fdfd","prefixes":{"":{"product":719}}}, // [E-Plus Mobilfunk GmbH & Co. KG] - {"hash":"745acee8f5973f56","prefixes":{"":{"product":719}}}, // [E-Plus Mobilfunk GmbH & Co. KG] - {"hash":"9a834a1cc05cb878","prefixes":{"":{"product":883}}}, // [MBuy, Inc.] - {"hash":"73cd161c10ebcf69","prefixes":{"":{"product":884}}}, // [FullSpeed Inc.] - {"hash":"75c72b5cc4c40c16","prefixes":{"":{"product":884}}}, // [FullSpeed Inc.] - {"hash":"33c5c398130ddfec","prefixes":{"":{"product":884}}}, // [FullSpeed Inc.] - {"hash":"1c0653651245a014","prefixes":{"":{"product":884}}}, // [FullSpeed Inc.] - {"hash":"271d057b15f67166","prefixes":{"":{"product":884}}}, // [FullSpeed Inc.] - {"hash":"e9723a229b8b9eeb","prefixes":{"":{"product":884}}}, // [FullSpeed Inc.] - {"hash":"8e3c99c5cc10c217","prefixes":{"":{"product":355}}}, // [New Allyes Information Technology (winmax)] - {"hash":"07141bfb96faa93c","prefixes":{"":{"product":885}}}, // [Madhouse Co. Limited (OptiMad)] - {"hash":"1d7294abbaa26e26","prefixes":{"":{"product":885}}}, // [Madhouse Co. Limited (OptiMad)] - {"hash":"6872272e097d2cd9","prefixes":{"":{"product":885}}}, // [Madhouse Co. Limited (OptiMad)] - {"hash":"66ec8aa560cf2231","prefixes":{"":{"product":885}}}, // [Madhouse Co. Limited (OptiMad)] - {"hash":"17cd9dcba702b7e6","prefixes":{"":{"product":885}}}, // [Madhouse Co. Limited (OptiMad)] - {"hash":"2347e9e88f6ead88","prefixes":{"":{"product":886}}}, // [Nano Interactive / Audiencemanager] - {"hash":"7f19740ff86dc642","prefixes":{"":{"product":886}}}, // [Nano Interactive / Audiencemanager] - {"hash":"18f553670e23734b","prefixes":{"":{"product":886}}}, // [Nano Interactive / Audiencemanager] - {"hash":"ca862d199926ad1c","prefixes":{"":{"product":886}}}, // [Nano Interactive / Audiencemanager] - {"hash":"2238776218564026","prefixes":{"":{"product":886}}}, // [Nano Interactive / Audiencemanager] - {"hash":"d7e222c8d7ba68d8","prefixes":{"*":{"product":887}}}, // [Youtube, LLC] - {"hash":"edff9009064b3fa4","prefixes":{"*":{"product":887}}}, // [Youtube, LLC] - {"hash":"0d60795f6997311e","prefixes":{"":{"product":888}}}, // [Omnibus co. Ltd] - {"hash":"f32008e13be0f96e","prefixes":{"":{"product":888}}}, // [Omnibus co. Ltd] - {"hash":"dd5533aa2d49cc10","prefixes":{"":{"product":889}}}, // [Omnibus co. Ltd.] - {"hash":"3bcd500b684d5142","prefixes":{"":{"product":888}}}, // [Omnibus co. Ltd] - {"hash":"14eef63a2889c8da","prefixes":{"":{"product":888}}}, // [Omnibus co. Ltd] - {"hash":"53f31e427551538d","prefixes":{"":{"product":888}}}, // [Omnibus co. Ltd] - {"hash":"5296819de63f3444","prefixes":{"":{"product":888}}}, // [Omnibus co. Ltd] - {"hash":"d8389fea989da8d7","prefixes":{"":{"product":41}}}, // [Airpush, Inc.] - {"hash":"e251b17a002b679b","prefixes":{"":{"product":890}}}, // [Education Management Corporation] - {"hash":"ec35188a522b7db9","prefixes":{"*":{"product":891}}}, // [Screen6 (s6.io)] - {"hash":"8ee1cf907bbca914","prefixes":{"":{"product":892}}}, // [LINK Marketing Services AG] - {"hash":"18a5decf96e8c80d","prefixes":{"":{"product":893}}}, // [TiqIQ] - {"hash":"8927e5364d1bf1d1","prefixes":{"":{"product":893}}}, // [TiqIQ] - {"hash":"86292c524ac79685","prefixes":{"":{"product":893}}}, // [TiqIQ] - {"hash":"52562df3f7208c8f","prefixes":{"":{"product":893}}}, // [TiqIQ] - {"hash":"a7d6fe32ab078e86","prefixes":{"":{"product":893}}}, // [TiqIQ] - {"hash":"497857c899894a0f","prefixes":{"":{"product":893}}}, // [TiqIQ] - {"hash":"0d8c5ad133d4c83e","prefixes":{"":{"product":894}}}, // [Ibibo Group Private Limited] - {"hash":"a8c10e41d2d4b31a","prefixes":{"":{"product":894}}}, // [Ibibo Group Private Limited] - {"hash":"9699d29520d1b9b8","prefixes":{"":{"product":894}}}, // [Ibibo Group Private Limited] - {"hash":"103308c15ca4c459","prefixes":{"":{"product":889}}}, // [Omnibus co. Ltd.] - {"hash":"d7a1b3fc5e1252ce","prefixes":{"":{"product":889}}}, // [Omnibus co. Ltd.] - {"hash":"ee40bf7c9bae2361","prefixes":{"":{"product":895}}}, // [justAd TV LTD] - {"hash":"8755d187f8ffb5e9","prefixes":{"":{"product":895}}}, // [justAd TV LTD] - {"hash":"1bdf54cf79d18915","prefixes":{"":{"product":895}}}, // [justAd TV LTD] - {"hash":"ed61950d43d99717","prefixes":{"":{"product":895}}}, // [justAd TV LTD] - {"hash":"aff928fc58637cb3","prefixes":{"":{"product":896}}}, // [Appier Inc.] - {"hash":"797f76218537ad5d","prefixes":{"*":{"product":896}}}, // [Appier Inc.] - {"hash":"6bdcdb03ff6173af","prefixes":{"*":{"product":896}}}, // [Appier Inc.] - {"hash":"6a3dec8b5a467987","prefixes":{"*":{"product":896}}}, // [Appier Inc.] - {"hash":"a3d5f58bbde56b12","prefixes":{"":{"product":896}}}, // [Appier Inc.] - {"hash":"7d0adb9089ff21ca","prefixes":{"":{"product":896}}}, // [Appier Inc.] - {"hash":"c241f36263ea7c84","prefixes":{"":{"product":897}}}, // [Kate Spade Saturday] - {"hash":"79dd595e79611766","prefixes":{"":{"product":898}}}, // [Teufel GmbH] - {"hash":"df829b8e840c11e1","prefixes":{"":{"product":898}}}, // [Teufel GmbH] - {"hash":"c3004b48539587e5","prefixes":{"":{"product":898}}}, // [Teufel GmbH] - {"hash":"08eb365a3723ee17","prefixes":{"":{"product":898}}}, // [Teufel GmbH] - {"hash":"71bc88c0bd0dc170","prefixes":{"":{"product":898}}}, // [Teufel GmbH] - {"hash":"fb208e41a565430a","prefixes":{"":{"product":899}}}, // [Aitarget LLC] - {"hash":"6121d39232612f56","prefixes":{"":{"product":899}}}, // [Aitarget LLC] - {"hash":"0ef54a01a72fdbaf","prefixes":{"*":{"product":676}}}, // [Rackspace, US Inc.] - {"hash":"532febae5cf9194f","prefixes":{"":{"product":900}}}, // [Engage Lab Ltd.] - {"hash":"fbfff8f12503c208","prefixes":{"":{"product":901}}}, // [Signal Digital, Inc dba Signal] - {"hash":"14afd1fc2da14d71","prefixes":{"":{"product":902}}}, // [Motrixi Media Group LLC] - {"hash":"aa674bd59dee4716","prefixes":{"":{"product":902}}}, // [Motrixi Media Group LLC] - {"hash":"7fd4fa8a06589cab","prefixes":{"":{"product":902}}}, // [Motrixi Media Group LLC] - {"hash":"56f94b2620357eb5","prefixes":{"":{"product":902}}}, // [Motrixi Media Group LLC] - {"hash":"32ddc8b6874f030b","prefixes":{"":{"product":903}}}, // [WHITE HOUSE | BLACK MARKET, Chico Brands, Inc.] - {"hash":"fea26de6b70aafb9","prefixes":{"":{"product":904}}}, // [Liftoff Mobile, Inc.] - {"hash":"4687be4922e9d22e","prefixes":{"":{"product":905}}}, // [etracker GmbH] - {"hash":"b41f235329fba677","prefixes":{"*":{"product":906}}}, // [MezzoMedia] - {"hash":"3362cc82ba37c826","prefixes":{"":{"product":906}}}, // [MezzoMedia] - {"hash":"7c5cbde65c1f0a61","prefixes":{"":{"product":907}}}, // [Eyeota Limited] - {"hash":"d85ebb0a3c0bdef4","prefixes":{"":{"product":908}}}, // [Beijing PageChoice Network Technology co., Ltd.] - {"hash":"52d134e034c55e1d","prefixes":{"":{"product":908}}}, // [Beijing PageChoice Network Technology co., Ltd.] - {"hash":"9d9805e510965156","prefixes":{"":{"product":908}}}, // [Beijing PageChoice Network Technology co., Ltd.] - {"hash":"5ed6426649a5142e","prefixes":{"":{"product":908}}}, // [Beijing PageChoice Network Technology co., Ltd.] - {"hash":"e629bb2b2df81562","prefixes":{"":{"product":908}}}, // [Beijing PageChoice Network Technology co., Ltd.] - {"hash":"37a1384fb3fc6090","prefixes":{"":{"product":270}}}, // [Intelliad] - {"hash":"9d931008b4067d12","prefixes":{"":{"product":909}}}, // [Padopolis, Inc.] - {"hash":"2e0eb051f10f4fe7","prefixes":{"":{"product":909}}}, // [Padopolis, Inc.] - {"hash":"e4e066ee012dd820","prefixes":{"":{"product":910}}}, // [Republic Project, Inc.] - {"hash":"6bda23da60f6517c","prefixes":{"":{"product":910}}}, // [Republic Project, Inc.] - {"hash":"8af361ef2f58932e","prefixes":{"":{"product":910}}}, // [Republic Project, Inc.] - {"hash":"9cf685ac4bd3c1a0","prefixes":{"":{"product":910}}}, // [Republic Project, Inc.] - {"hash":"ceb2ae18496c4062","prefixes":{"":{"product":910}}}, // [Republic Project, Inc.] - {"hash":"a1c74be312c1e501","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"e2305a44231103a0","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"e9ea3f2053ff0ac5","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"18f65ffdee8f8402","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"dc902603963cc6c8","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"6addef0844f148c5","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"c2889776656d63b3","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"1a1ac1eeae181fe7","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"fa03396d4a303d45","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"f632f69c34840122","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"082e62ce70aa66fc","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"775c7d89c606cd3c","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"74b282bb3c686219","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"a8e1956c97315aaf","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"26dc9f78ec72cc0c","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"c4ef7b6eeeda12ce","prefixes":{"":{"product":911}}}, // [C8 Network] - {"hash":"e78c2b0997dfa249","prefixes":{"":{"product":912}}}, // [Data Artist Inc.] - {"hash":"41045058078214c7","prefixes":{"":{"product":912}}}, // [Data Artist Inc.] - {"hash":"c3b23588f42fedff","prefixes":{"":{"product":912}}}, // [Data Artist Inc.] - {"hash":"5e94c742d87aa747","prefixes":{"":{"product":912}}}, // [Data Artist Inc.] - {"hash":"52632067f5495750","prefixes":{"":{"product":913}}}, // [AirFrance] - {"hash":"0b27c948dba1fda0","prefixes":{"":{"product":914}}}, // [YDigital Media] - {"hash":"7e30f931dbb7180a","prefixes":{"":{"product":915}}}, // [Zentrick] - {"hash":"b3e2285b6fc03e5c","prefixes":{"":{"product":915}}}, // [Zentrick] - {"hash":"e2f247795ad2ad87","prefixes":{"":{"product":915}}}, // [Zentrick] - {"hash":"1c9e4d1810e659fa","prefixes":{"":{"product":915}}}, // [Zentrick] - {"hash":"57511b10e2ed4785","prefixes":{"":{"product":915}}}, // [Zentrick] - {"hash":"c012faa898c62e0b","prefixes":{"":{"product":916}}}, // [FreeBit Co. Ltd.] - {"hash":"41b7f33c961162f8","prefixes":{"":{"product":916}}}, // [FreeBit Co. Ltd.] - {"hash":"ffac4f6c5fa1aa82","prefixes":{"":{"product":916}}}, // [FreeBit Co. Ltd.] - {"hash":"a23bae62ab25e2c1","prefixes":{"":{"product":916}}}, // [FreeBit Co. Ltd.] - {"hash":"ae08459757b76c12","prefixes":{"":{"product":916}}}, // [FreeBit Co. Ltd.] - {"hash":"83efb7fcb7770789","prefixes":{"":{"product":917}}}, // [Dennoo Inc.] - {"hash":"042456e26a44a268","prefixes":{"":{"product":917}}}, // [Dennoo Inc.] - {"hash":"cb0b16dd50ba9d7d","prefixes":{"":{"product":917}}}, // [Dennoo Inc.] - {"hash":"541a895df01d2b2c","prefixes":{"":{"product":917}}}, // [Dennoo Inc.] - {"hash":"8f01887bb7405ab5","prefixes":{"":{"product":918}}}, // [Adbrain] - {"hash":"33734a86766d25a9","prefixes":{"*":{"product":919}}}, // [MSI-ACI Europe BV] - {"hash":"f66543f279b3e1e7","prefixes":{"":{"product":920}}}, // [A.Mob] - {"hash":"74ee8c0f2fb31813","prefixes":{"":{"product":920}}}, // [A.Mob] - {"hash":"584db20b69521f40","prefixes":{"":{"product":921}}}, // [Toys R Us] - {"hash":"6a001e8bc99fede6","prefixes":{"":{"product":922}}}, // [Geniee,Inc] - {"hash":"b8ff7bd604535ea9","prefixes":{"":{"product":922}}}, // [Geniee,Inc] - {"hash":"3e005c1dfdc23488","prefixes":{"":{"product":923}}}, // [Adsecure] - {"hash":"ddef7bb2f5930121","prefixes":{"":{"product":923}}}, // [Adsecure] - {"hash":"424399e643b329b8","prefixes":{"":{"product":923}}}, // [Adsecure] - {"hash":"23df92e04ec66406","prefixes":{"":{"product":923}}}, // [Adsecure] - {"hash":"06f0caf4a4fe6ed1","prefixes":{"":{"product":923}}}, // [Adsecure] - {"hash":"9697a0818cbd79bd","prefixes":{"":{"product":923}}}, // [Adsecure] - {"hash":"ec7f61f2511ae20e","prefixes":{"":{"product":923}}}, // [Adsecure] - {"hash":"fb4e7ecb8304ade4","prefixes":{"":{"product":924}}}, // [Kimia Solutions SL] - {"hash":"84f5d0f934bd60f1","prefixes":{"":{"product":924}}}, // [Kimia Solutions SL] - {"hash":"b3fcc22fcd382f3b","prefixes":{"":{"product":924}}}, // [Kimia Solutions SL] - {"hash":"4eca8c3218b372ae","prefixes":{"":{"product":925}}}, // [Sojern] - {"hash":"9636bfb4feaef839","prefixes":{"":{"product":925}}}, // [Sojern] - {"hash":"a525b67906a4cb94","prefixes":{"":{"product":926}}}, // [Where 2 Get It, Inc.] - {"hash":"6c959985d7181026","prefixes":{"":{"product":926}}}, // [Where 2 Get It, Inc.] - {"hash":"7843db8d760e28cb","prefixes":{"":{"product":927}}}, // [Tomoko Cloud] - {"hash":"eb7b756fc1f88aa1","prefixes":{"":{"product":927}}}, // [Tomoko Cloud] - {"hash":"ed4d672687c27603","prefixes":{"":{"product":927}}}, // [Tomoko Cloud] - {"hash":"b156b34e4d693e49","prefixes":{"":{"product":927}}}, // [Tomoko Cloud] - {"hash":"16e146e87e7d0383","prefixes":{"":{"product":928}}}, // [RevenueMantra] - {"hash":"1457bcbc098b2864","prefixes":{"":{"product":928}}}, // [RevenueMantra] - {"hash":"450eb4f9273a5014","prefixes":{"":{"product":929}}}, // [Automobile Ltd.] - {"hash":"436e4eaa95b23fcb","prefixes":{"":{"product":929}}}, // [Automobile Ltd.] - {"hash":"a47ee9f00ca4f855","prefixes":{"":{"product":929}}}, // [Automobile Ltd.] - {"hash":"889ab5643c83668a","prefixes":{"":{"product":929}}}, // [Automobile Ltd.] - {"hash":"4ea96f1e0388da92","prefixes":{"":{"product":930}}}, // [Big Mobile Group Pty Ltd] - {"hash":"ae895a18cc8c416e","prefixes":{"":{"product":930}}}, // [Big Mobile Group Pty Ltd] - {"hash":"bbb46a7f5062448e","prefixes":{"":{"product":931}}}, // [ADMIZED AG] - {"hash":"0b4e26a40cc2e647","prefixes":{"":{"product":932}}}, // [Sparks47 s.r.l.] - {"hash":"745030cd7ac80402","prefixes":{"":{"product":933}}}, // [Between Digital dba Intency DSP] - {"hash":"55db959f7c533183","prefixes":{"":{"product":933}}}, // [Between Digital dba Intency DSP] - {"hash":"15b9a82ccbf2d7ff","prefixes":{"":{"product":933}}}, // [Between Digital dba Intency DSP] - {"hash":"c63156716e201b52","prefixes":{"":{"product":933}}}, // [Between Digital dba Intency DSP] - {"hash":"801d43da2c97866b","prefixes":{"":{"product":933}}}, // [Between Digital dba Intency DSP] - {"hash":"d9f810d72012d4c4","prefixes":{"":{"product":934}}}, // [eprofessional GmbH] - {"hash":"23c665bb68cc30cc","prefixes":{"":{"product":934}}}, // [eprofessional GmbH] - {"hash":"8439b0c8f73daf02","prefixes":{"":{"product":934}}}, // [eprofessional GmbH] - {"hash":"6a17378968b598f2","prefixes":{"":{"product":934}}}, // [eprofessional GmbH] - {"hash":"4e157cd578931a97","prefixes":{"":{"product":935}}}, // [Channel Factory, LLC] - {"hash":"9cdf7d74bee2159f","prefixes":{"":{"product":935}}}, // [Channel Factory, LLC] - {"hash":"58c684b764b4dcab","prefixes":{"":{"product":935}}}, // [Channel Factory, LLC] - {"hash":"85218b0017b8f452","prefixes":{"":{"product":935}}}, // [Channel Factory, LLC] - {"hash":"9f790c0c14fa8f4d","prefixes":{"":{"product":935}}}, // [Channel Factory, LLC] - {"hash":"e7518acf5c44d0a4","prefixes":{"":{"product":935}}}, // [Channel Factory, LLC] - {"hash":"ec763282f8f41299","prefixes":{"":{"product":935}}}, // [Channel Factory, LLC] - {"hash":"41a0870b895e73b4","prefixes":{"":{"product":936}}}, // [ConvertStar Incorporated] - {"hash":"f0134a17d368f3d8","prefixes":{"":{"product":936}}}, // [ConvertStar Incorporated] - {"hash":"58f6c00f44fb69a4","prefixes":{"":{"product":936}}}, // [ConvertStar Incorporated] + {"hash":"bb5ef61e19944a06","prefixes":{"":{"product":831,"type":0}}}, // [ResponsiveAds, Inc] + {"hash":"ef4fefbe73da4a59","prefixes":{"":{"product":831,"type":0}}}, // [ResponsiveAds, Inc] + {"hash":"e78ef2faad563e6b","prefixes":{"":{"product":831,"type":0}}}, // [ResponsiveAds, Inc] + {"hash":"20e99abfa9e5de7c","prefixes":{"":{"product":831,"type":0}}}, // [ResponsiveAds, Inc] + {"hash":"0dedc650dbf5d391","prefixes":{"":{"product":831,"type":0}}}, // [ResponsiveAds, Inc] + {"hash":"5bdaec9fd3ff4dac","prefixes":{"":{"product":832,"type":1}}}, // [Duepuntozero Research SRL] + {"hash":"318bfe954294ea40","prefixes":{"":{"product":833,"type":0}}}, // [AdMovate, Inc.] + {"hash":"e24259ffed4d244f","prefixes":{"":{"product":833,"type":0}}}, // [AdMovate, Inc.] + {"hash":"c39b0621d7a8b616","prefixes":{"":{"product":834,"type":0}}}, // [go.pl] + {"hash":"29c359aefdd48c40","prefixes":{"":{"product":834,"type":0}}}, // [go.pl] + {"hash":"6ecf3c2aeb5aec2b","prefixes":{"":{"product":834,"type":0}}}, // [go.pl] + {"hash":"eea1a3478557a7a6","prefixes":{"":{"product":834,"type":0}}}, // [go.pl] + {"hash":"0b0e365de9c89436","prefixes":{"":{"product":834,"type":0}}}, // [go.pl] + {"hash":"875d9d8b11a6dff7","prefixes":{"":{"product":834,"type":0}}}, // [go.pl] + {"hash":"5edb8f1a6337d5d0","prefixes":{"":{"product":834,"type":0}}}, // [go.pl] + {"hash":"435808ca4dd1dce5","prefixes":{"":{"product":834,"type":0}}}, // [go.pl] + {"hash":"fd43d007391147de","prefixes":{"":{"product":710,"type":1}}}, // [MASSMOTIONMEDIA SARL] + {"hash":"633236a94b694dd7","prefixes":{"":{"product":710,"type":1}}}, // [MASSMOTIONMEDIA SARL] + {"hash":"a076e91e809efc28","prefixes":{"*":{"product":835,"type":0}}}, // [AppLovin Corporation] + {"hash":"14c26da0caac0796","prefixes":{"":{"product":836,"type":1}}}, // [twentysix ltd] + {"hash":"1f8d7bcebd64d2c9","prefixes":{"":{"product":15,"type":0}}}, // [Tamome] + {"hash":"41f4c0bf12c8f029","prefixes":{"":{"product":336,"type":0}}}, // [EuroAds Group A/S] + {"hash":"e674b14a061bb7d7","prefixes":{"":{"product":336,"type":0}}}, // [EuroAds Group A/S] + {"hash":"f485e2bb528d3147","prefixes":{"":{"product":336,"type":0}}}, // [EuroAds Group A/S] + {"hash":"82c09e315af7d70c","prefixes":{"":{"product":336,"type":0}}}, // [EuroAds Group A/S] + {"hash":"fc2b985669148068","prefixes":{"":{"product":336,"type":0}}}, // [EuroAds Group A/S] + {"hash":"cf9a9377bc72c2e4","prefixes":{"":{"product":336,"type":0}}}, // [EuroAds Group A/S] + {"hash":"d550149a2d5cfdde","prefixes":{"":{"product":336,"type":0}}}, // [EuroAds Group A/S] + {"hash":"d51c2c24cd771a6a","prefixes":{"":{"product":837,"type":0}}}, // [Epsilon International SA] + {"hash":"d34cf98578200c93","prefixes":{"":{"product":838,"type":0}}}, // [Zebestof] + {"hash":"44c2302577bd8e84","prefixes":{"":{"product":838,"type":0}}}, // [Zebestof] + {"hash":"52b835c5657206c1","prefixes":{"":{"product":838,"type":0}}}, // [Zebestof] + {"hash":"caa0c94cf57e2295","prefixes":{"":{"product":838,"type":0}}}, // [Zebestof] + {"hash":"02e54ec6b0aca548","prefixes":{"":{"product":839,"type":1}}}, // [SOL UTD Benelux BV] + {"hash":"1cf1a7f5c323d6e0","prefixes":{"":{"product":840,"type":0}}}, // [M,P,NEWMEDIA, GmbH] + {"hash":"079a647886a5afa5","prefixes":{"":{"product":840,"type":0}}}, // [M,P,NEWMEDIA, GmbH] + {"hash":"ec320d28ebdfac8c","prefixes":{"":{"product":840,"type":0}}}, // [M,P,NEWMEDIA, GmbH] + {"hash":"e59449da7e642b45","prefixes":{"":{"product":840,"type":0}}}, // [M,P,NEWMEDIA, GmbH] + {"hash":"1d61751db94dfc15","prefixes":{"":{"product":840,"type":0}}}, // [M,P,NEWMEDIA, GmbH] + {"hash":"43f7746544162324","prefixes":{"":{"product":840,"type":0}}}, // [M,P,NEWMEDIA, GmbH] + {"hash":"4f80c8700c459a79","prefixes":{"":{"product":840,"type":0}}}, // [M,P,NEWMEDIA, GmbH] + {"hash":"23f62ba113f0fa4f","prefixes":{"":{"product":841,"type":1}}}, // [MediaCrossing Inc.] + {"hash":"62fc0fc3102b918b","prefixes":{"":{"product":842,"type":0}}}, // [MBR Targeting Gmbh] + {"hash":"0066f0743ade259b","prefixes":{"":{"product":842,"type":0}}}, // [MBR Targeting Gmbh] + {"hash":"4288d021c49b7e1b","prefixes":{"":{"product":842,"type":0}}}, // [MBR Targeting Gmbh] + {"hash":"6620a58a1f4cd480","prefixes":{"":{"product":843,"type":1}}}, // [VivaKi] + {"hash":"47db57aade94670f","prefixes":{"":{"product":843,"type":1}}}, // [VivaKi] + {"hash":"2924b77c1d7eab3b","prefixes":{"":{"product":843,"type":1}}}, // [VivaKi] + {"hash":"d2143dbf1699f4fa","prefixes":{"":{"product":844,"type":1}}}, // [Affiliate Window] + {"hash":"13c2a94c46886705","prefixes":{"":{"product":844,"type":1}}}, // [Affiliate Window] + {"hash":"c0d30b023dc9139f","prefixes":{"*":{"product":845,"type":0}}}, // [TubeMogul Inc. (AdWords/YouTube)] + {"hash":"108d788939e4b7a4","prefixes":{"":{"product":825,"type":0}}}, // [DXP Media] + {"hash":"6fdc121917e19eb9","prefixes":{"":{"product":825,"type":0}}}, // [DXP Media] + {"hash":"5262a88cfa363303","prefixes":{"":{"product":825,"type":0}}}, // [DXP Media] + {"hash":"b597af924fe5ff97","prefixes":{"":{"product":825,"type":0}}}, // [DXP Media] + {"hash":"dca60f44a70d5d38","prefixes":{"":{"product":825,"type":0}}}, // [DXP Media] + {"hash":"c44308d5c2e3bb8a","prefixes":{"":{"product":825,"type":0}}}, // [DXP Media] + {"hash":"90f5b971c961816f","prefixes":{"":{"product":825,"type":0}}}, // [DXP Media] + {"hash":"5d64c1152c075739","prefixes":{"":{"product":846,"type":0}}}, // [Way2traffic Polska S.A.] + {"hash":"01b13121d2ce9699","prefixes":{"":{"product":846,"type":0}}}, // [Way2traffic Polska S.A.] + {"hash":"f48791a2746e2a93","prefixes":{"":{"product":847,"type":1}}}, // [TNS Sifo AB] + {"hash":"935b8079b74f344c","prefixes":{"":{"product":847,"type":1}}}, // [TNS Sifo AB] + {"hash":"24e5b8b342d1b1fe","prefixes":{"":{"product":848,"type":1}}}, // [3xchange/Hunkal] + {"hash":"ad8c8bc165611bf2","prefixes":{"":{"product":848,"type":1}}}, // [3xchange/Hunkal] + {"hash":"b1b5bdd82d143e90","prefixes":{"":{"product":849,"type":0}}}, // [Emerse Sverige AB] + {"hash":"aeddaa071ba3b313","prefixes":{"":{"product":849,"type":0}}}, // [Emerse Sverige AB] + {"hash":"474802ea42555e39","prefixes":{"":{"product":849,"type":0}}}, // [Emerse Sverige AB] + {"hash":"b28e42ea18df1c00","prefixes":{"":{"product":849,"type":0}}}, // [Emerse Sverige AB] + {"hash":"826635800b12eb0c","prefixes":{"":{"product":849,"type":0}}}, // [Emerse Sverige AB] + {"hash":"22c10728f555913e","prefixes":{"":{"product":849,"type":0}}}, // [Emerse Sverige AB] + {"hash":"0b7f364ef0beed45","prefixes":{"":{"product":849,"type":0}}}, // [Emerse Sverige AB] + {"hash":"8d31e79105c5380a","prefixes":{"":{"product":850,"type":0}}}, // [Sokno Media] + {"hash":"037264ef7d8383f6","prefixes":{"":{"product":850,"type":0}}}, // [Sokno Media] + {"hash":"ff6372e6621d88ba","prefixes":{"":{"product":851,"type":0}}}, // [Blackheart, a division of Hot Topic, Inc.] + {"hash":"37742852c2a4ccc8","prefixes":{"":{"product":852,"type":0}}}, // [Torrid] + {"hash":"a86786ce90b23e3f","prefixes":{"":{"product":853,"type":0}}}, // [Hot Topic, Inc.] + {"hash":"93e1c22a4427a32f","prefixes":{"":{"product":854,"type":1}}}, // [WebHue LLC] + {"hash":"fca0a42aad108345","prefixes":{"static":{"product":855,"type":0},"img":{"product":855,"type":0},"log":{"product":855,"type":0}}}, // [Content to Emotion] [Content to Emotion] [Content to Emotion] + {"hash":"15948cae619c2e58","prefixes":{"":{"product":855,"type":0}}}, // [Content to Emotion] + {"hash":"db2a81c15837ddbd","prefixes":{"":{"product":856,"type":0}}}, // [Adman Interactive SL] + {"hash":"accf1565984e2899","prefixes":{"":{"product":856,"type":0}}}, // [Adman Interactive SL] + {"hash":"45351e5c4862b2dd","prefixes":{"":{"product":856,"type":0}}}, // [Adman Interactive SL] + {"hash":"ba3196c50e6c1be4","prefixes":{"":{"product":856,"type":0}}}, // [Adman Interactive SL] + {"hash":"eab724fbba4f83d6","prefixes":{"":{"product":856,"type":0}}}, // [Adman Interactive SL] + {"hash":"0edc8e7b8a8fe3ee","prefixes":{"":{"product":857,"type":0}}}, // [AudienceFUEL, Inc.] + {"hash":"dfa423315ab48813","prefixes":{"":{"product":858,"type":0}}}, // [TapCommerce LLC] + {"hash":"777b0f4301aa1643","prefixes":{"":{"product":858,"type":0}}}, // [TapCommerce LLC] + {"hash":"294cba0ae232447c","prefixes":{"":{"product":859,"type":0}}}, // [AdTheorent, Inc.] + {"hash":"ba7ad5da6db014c7","prefixes":{"":{"product":860,"type":0}}}, // [AdTheorent, Inc] + {"hash":"09bfc8a7f1c7896f","prefixes":{"":{"product":859,"type":0}}}, // [AdTheorent, Inc.] + {"hash":"362136e847a35f7e","prefixes":{"":{"product":859,"type":0}}}, // [AdTheorent, Inc.] + {"hash":"5492d77bb75e6380","prefixes":{"":{"product":861,"type":0}}}, // [Barometric] + {"hash":"94bb816c4a375220","prefixes":{"":{"product":862,"type":0}}}, // [CrossInstall, Inc] + {"hash":"f10e1a418576d219","prefixes":{"":{"product":862,"type":0}}}, // [CrossInstall, Inc] + {"hash":"245fc951b0a9ce59","prefixes":{"":{"product":862,"type":0}}}, // [CrossInstall, Inc] + {"hash":"babdceabca3ae2b8","prefixes":{"":{"product":862,"type":0}}}, // [CrossInstall, Inc] + {"hash":"c6474114ede3195a","prefixes":{"":{"product":862,"type":0}}}, // [CrossInstall, Inc] + {"hash":"26faef64bd072723","prefixes":{"":{"product":862,"type":0}}}, // [CrossInstall, Inc] + {"hash":"0a19b1f547a3a935","prefixes":{"":{"product":862,"type":0}}}, // [CrossInstall, Inc] + {"hash":"b4ef56642916cc60","prefixes":{"":{"product":862,"type":0}}}, // [CrossInstall, Inc] + {"hash":"c1fc9d245fa85b02","prefixes":{"":{"product":862,"type":0}}}, // [CrossInstall, Inc] + {"hash":"0e3ddb4868b0e99f","prefixes":{"":{"product":863,"type":0}}}, // [Theorem Inc.] + {"hash":"976d4ea6507dfd2e","prefixes":{"":{"product":863,"type":0}}}, // [Theorem Inc.] + {"hash":"70a3fe87d3bbbae9","prefixes":{"":{"product":863,"type":0}}}, // [Theorem Inc.] + {"hash":"1cf1ec002a07d6a4","prefixes":{"":{"product":864,"type":0}}}, // [KeyVersion] + {"hash":"b2c480f3bc7b03b6","prefixes":{"":{"product":864,"type":0}}}, // [KeyVersion] + {"hash":"c94dbc0a3ffc6eda","prefixes":{"":{"product":865,"type":0}}}, // [Ancestry] + {"hash":"04fb46af993df556","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"b9adf25b55c4d0f3","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"1c1211c84dbee054","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"575fafb094c71d93","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"f2b020b3d3861db2","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"609d13c5cd3771c8","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"aeae313934102cfe","prefixes":{"":{"product":867,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd] + {"hash":"f8721bcf4d9f6196","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"09e5f7c9f30f4fd6","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"a1ce57d387427206","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"bb4b6377666172c4","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"d6a6a6cd062bc76e","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"0313ce8a9851d837","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"6862450d2314df40","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"0a34c9f6f0cf9556","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"8e311fce80eccafd","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"296fdad7e8336d5a","prefixes":{"":{"product":866,"type":0}}}, // [Shanghai Lijing Advertising Co., Ltd.] + {"hash":"27c0e177312a3c0f","prefixes":{"":{"product":108,"type":0}}}, // [Immedium, Inc.] + {"hash":"fc3c7114081863bd","prefixes":{"":{"product":108,"type":0}}}, // [Immedium, Inc.] + {"hash":"811582f5df157ff9","prefixes":{"":{"product":868,"type":1}}}, // [KissNoFrog.com] + {"hash":"284d8a4f9b174bab","prefixes":{"":{"product":869,"type":1}}}, // [DigiEQ] + {"hash":"aa0e7b7a1fe279dc","prefixes":{"":{"product":869,"type":1}}}, // [DigiEQ] + {"hash":"1f551f934400f81e","prefixes":{"":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"1c3b94cabbbc5b8c","prefixes":{"":{"product":86,"type":0}}}, // [MediaMath Inc.] + {"hash":"505b194aeebd6baf","prefixes":{"":{"product":870,"type":0}}}, // [Mobile Professinals BV] + {"hash":"8f2e12e9677e4d41","prefixes":{"":{"product":870,"type":0}}}, // [Mobile Professinals BV] + {"hash":"e2a3fe5e482432e8","prefixes":{"":{"product":870,"type":0}}}, // [Mobile Professinals BV] + {"hash":"7d03cd1b92c167a8","prefixes":{"":{"product":870,"type":0}}}, // [Mobile Professinals BV] + {"hash":"532402cd3ab13402","prefixes":{"":{"product":870,"type":0}}}, // [Mobile Professinals BV] + {"hash":"48e577ba3e61c748","prefixes":{"":{"product":870,"type":0}}}, // [Mobile Professinals BV] + {"hash":"1480a6580cb81dde","prefixes":{"":{"product":870,"type":0}}}, // [Mobile Professinals BV] + {"hash":"b1ec46dd2c4c824e","prefixes":{"*":{"product":109,"type":0}}}, // [Fractional Media, LLC] + {"hash":"6c6240697771befd","prefixes":{"*":{"product":109,"type":0}}}, // [Fractional Media, LLC] + {"hash":"f2e16038c0d83b85","prefixes":{"":{"product":871,"type":0}}}, // [Decisive, Inc.] + {"hash":"654da4ed85d77fb9","prefixes":{"":{"product":871,"type":0}}}, // [Decisive, Inc.] + {"hash":"c9e2ea0486216534","prefixes":{"":{"product":871,"type":0}}}, // [Decisive, Inc.] + {"hash":"546a2acb9b2363f2","prefixes":{"*":{"product":872,"type":0}}}, // [Microsoft Security Essentials] + {"hash":"9e4f5b2f200fbb25","prefixes":{"":{"product":873,"type":0}}}, // [Tumi, Inc. US] + {"hash":"4378c60894195c4f","prefixes":{"":{"product":874,"type":0}}}, // [Tumi, Inc. UK] + {"hash":"61e82c5e74c5ce7c","prefixes":{"":{"product":875,"type":0}}}, // [Tumi, Inc. DE] + {"hash":"712f010eb9792fa4","prefixes":{"":{"product":876,"type":0}}}, // [Nanigans, Inc] + {"hash":"589eceaef79619dd","prefixes":{"":{"product":876,"type":0}}}, // [Nanigans, Inc] + {"hash":"1d66f17c949dbaee","prefixes":{"":{"product":876,"type":0}}}, // [Nanigans, Inc] + {"hash":"6dbd7b9480163af0","prefixes":{"":{"product":876,"type":0}}}, // [Nanigans, Inc] + {"hash":"41d56e0870364212","prefixes":{"":{"product":139,"type":0}}}, // [Brandscreen Inc.] + {"hash":"2d701495cf72af5b","prefixes":{"*":{"product":877,"type":0}}}, // [AdSniper LLC] + {"hash":"0bd14e8d5a6b2f2d","prefixes":{"":{"product":877,"type":0}}}, // [AdSniper LLC] + {"hash":"9b504cc586da72e5","prefixes":{"":{"product":877,"type":0}}}, // [AdSniper LLC] + {"hash":"a89d4cb4490b4286","prefixes":{"":{"product":877,"type":0}}}, // [AdSniper LLC] + {"hash":"dce925353cbc1dbe","prefixes":{"":{"product":877,"type":0}}}, // [AdSniper LLC] + {"hash":"ff8d26679ce7dafc","prefixes":{"":{"product":877,"type":0}}}, // [AdSniper LLC] + {"hash":"11db2fec76a76647","prefixes":{"":{"product":877,"type":0}}}, // [AdSniper LLC] + {"hash":"00a09e8788ee6f2b","prefixes":{"":{"product":877,"type":0}}}, // [AdSniper LLC] + {"hash":"709d79bfe214aa48","prefixes":{"":{"product":877,"type":0}}}, // [AdSniper LLC] + {"hash":"7a37fa5ff1a37799","prefixes":{"":{"product":877,"type":0}}}, // [AdSniper LLC] + {"hash":"42a24e1ab1c2d947","prefixes":{"":{"product":877,"type":0}}}, // [AdSniper LLC] + {"hash":"63f4e4d315bc085b","prefixes":{"":{"product":878,"type":1}}}, // [Fabric Worldwide Inc] + {"hash":"b9c11e67d7eb2963","prefixes":{"":{"product":878,"type":1}}}, // [Fabric Worldwide Inc] + {"hash":"e3882e6bc0c2e382","prefixes":{"":{"product":879,"type":1}}}, // [Vorwerk Deutschland Stiftung & Co. KG] + {"hash":"944d86d40b9ae089","prefixes":{"":{"product":879,"type":1}}}, // [Vorwerk Deutschland Stiftung & Co. KG] + {"hash":"ebd456010571b5ae","prefixes":{"":{"product":879,"type":1}}}, // [Vorwerk Deutschland Stiftung & Co. KG] + {"hash":"4456fa769be90ba2","prefixes":{"":{"product":65,"type":0}}}, // [Active Agent] + {"hash":"84d65f5782dd26d6","prefixes":{"":{"product":880,"type":0}}}, // [Chico Distribution Services, LLC] + {"hash":"a6185f46e2849f58","prefixes":{"":{"product":881,"type":0}}}, // [12Mnkys GmbH] + {"hash":"bf874935c6972629","prefixes":{"":{"product":881,"type":0}}}, // [12Mnkys GmbH] + {"hash":"094b301a712414f2","prefixes":{"":{"product":881,"type":0}}}, // [12Mnkys GmbH] + {"hash":"56ee8d67408b2316","prefixes":{"":{"product":881,"type":0}}}, // [12Mnkys GmbH] + {"hash":"d62d9c20c47ec863","prefixes":{"":{"product":881,"type":0}}}, // [12Mnkys GmbH] + {"hash":"bb716a8269a2e79c","prefixes":{"":{"product":882,"type":0}}}, // [Spacyz, Inc.] + {"hash":"5a6ff8a620bb8de1","prefixes":{"":{"product":882,"type":0}}}, // [Spacyz, Inc.] + {"hash":"61cf0a8426083e54","prefixes":{"":{"product":882,"type":0}}}, // [Spacyz, Inc.] + {"hash":"4cf4aa4b0e37fdfd","prefixes":{"":{"product":719,"type":0}}}, // [E-Plus Mobilfunk GmbH & Co. KG] + {"hash":"745acee8f5973f56","prefixes":{"":{"product":719,"type":0}}}, // [E-Plus Mobilfunk GmbH & Co. KG] + {"hash":"9a834a1cc05cb878","prefixes":{"":{"product":883,"type":1}}}, // [MBuy, Inc.] + {"hash":"73cd161c10ebcf69","prefixes":{"":{"product":884,"type":0}}}, // [FullSpeed Inc.] + {"hash":"75c72b5cc4c40c16","prefixes":{"":{"product":884,"type":0}}}, // [FullSpeed Inc.] + {"hash":"33c5c398130ddfec","prefixes":{"":{"product":884,"type":0}}}, // [FullSpeed Inc.] + {"hash":"1c0653651245a014","prefixes":{"":{"product":884,"type":0}}}, // [FullSpeed Inc.] + {"hash":"271d057b15f67166","prefixes":{"":{"product":884,"type":0}}}, // [FullSpeed Inc.] + {"hash":"e9723a229b8b9eeb","prefixes":{"":{"product":884,"type":0}}}, // [FullSpeed Inc.] + {"hash":"8e3c99c5cc10c217","prefixes":{"":{"product":355,"type":0}}}, // [New Allyes Information Technology (winmax)] + {"hash":"07141bfb96faa93c","prefixes":{"":{"product":885,"type":0}}}, // [Madhouse Co. Limited (OptiMad)] + {"hash":"1d7294abbaa26e26","prefixes":{"":{"product":885,"type":0}}}, // [Madhouse Co. Limited (OptiMad)] + {"hash":"6872272e097d2cd9","prefixes":{"":{"product":885,"type":0}}}, // [Madhouse Co. Limited (OptiMad)] + {"hash":"66ec8aa560cf2231","prefixes":{"":{"product":885,"type":0}}}, // [Madhouse Co. Limited (OptiMad)] + {"hash":"17cd9dcba702b7e6","prefixes":{"":{"product":885,"type":0}}}, // [Madhouse Co. Limited (OptiMad)] + {"hash":"2347e9e88f6ead88","prefixes":{"":{"product":886,"type":0}}}, // [Nano Interactive / Audiencemanager] + {"hash":"7f19740ff86dc642","prefixes":{"":{"product":886,"type":0}}}, // [Nano Interactive / Audiencemanager] + {"hash":"18f553670e23734b","prefixes":{"":{"product":886,"type":0}}}, // [Nano Interactive / Audiencemanager] + {"hash":"ca862d199926ad1c","prefixes":{"":{"product":886,"type":0}}}, // [Nano Interactive / Audiencemanager] + {"hash":"2238776218564026","prefixes":{"":{"product":886,"type":0}}}, // [Nano Interactive / Audiencemanager] + {"hash":"d7e222c8d7ba68d8","prefixes":{"*":{"product":887,"type":0}}}, // [Youtube, LLC] + {"hash":"edff9009064b3fa4","prefixes":{"*":{"product":887,"type":0}}}, // [Youtube, LLC] + {"hash":"0d60795f6997311e","prefixes":{"":{"product":888,"type":0}}}, // [Omnibus co. Ltd] + {"hash":"f32008e13be0f96e","prefixes":{"":{"product":888,"type":0}}}, // [Omnibus co. Ltd] + {"hash":"dd5533aa2d49cc10","prefixes":{"":{"product":889,"type":1}}}, // [Omnibus co. Ltd.] + {"hash":"3bcd500b684d5142","prefixes":{"":{"product":888,"type":0}}}, // [Omnibus co. Ltd] + {"hash":"14eef63a2889c8da","prefixes":{"":{"product":888,"type":0}}}, // [Omnibus co. Ltd] + {"hash":"53f31e427551538d","prefixes":{"":{"product":888,"type":0}}}, // [Omnibus co. Ltd] + {"hash":"5296819de63f3444","prefixes":{"":{"product":888,"type":0}}}, // [Omnibus co. Ltd] + {"hash":"d8389fea989da8d7","prefixes":{"":{"product":41,"type":0}}}, // [Airpush, Inc.] + {"hash":"e251b17a002b679b","prefixes":{"":{"product":890,"type":1}}}, // [Education Management Corporation] + {"hash":"ec35188a522b7db9","prefixes":{"*":{"product":891,"type":1}}}, // [Screen6 (s6.io)] + {"hash":"8ee1cf907bbca914","prefixes":{"":{"product":892,"type":1}}}, // [LINK Marketing Services AG] + {"hash":"18a5decf96e8c80d","prefixes":{"":{"product":893,"type":0}}}, // [TiqIQ] + {"hash":"8927e5364d1bf1d1","prefixes":{"":{"product":893,"type":0}}}, // [TiqIQ] + {"hash":"86292c524ac79685","prefixes":{"":{"product":893,"type":0}}}, // [TiqIQ] + {"hash":"52562df3f7208c8f","prefixes":{"":{"product":893,"type":0}}}, // [TiqIQ] + {"hash":"a7d6fe32ab078e86","prefixes":{"":{"product":893,"type":0}}}, // [TiqIQ] + {"hash":"497857c899894a0f","prefixes":{"":{"product":893,"type":0}}}, // [TiqIQ] + {"hash":"0d8c5ad133d4c83e","prefixes":{"":{"product":894,"type":0}}}, // [Ibibo Group Private Limited] + {"hash":"a8c10e41d2d4b31a","prefixes":{"":{"product":894,"type":0}}}, // [Ibibo Group Private Limited] + {"hash":"9699d29520d1b9b8","prefixes":{"":{"product":894,"type":0}}}, // [Ibibo Group Private Limited] + {"hash":"103308c15ca4c459","prefixes":{"":{"product":889,"type":1}}}, // [Omnibus co. Ltd.] + {"hash":"d7a1b3fc5e1252ce","prefixes":{"":{"product":889,"type":1}}}, // [Omnibus co. Ltd.] + {"hash":"ee40bf7c9bae2361","prefixes":{"":{"product":895,"type":0}}}, // [justAd TV LTD] + {"hash":"8755d187f8ffb5e9","prefixes":{"":{"product":895,"type":0}}}, // [justAd TV LTD] + {"hash":"1bdf54cf79d18915","prefixes":{"":{"product":895,"type":0}}}, // [justAd TV LTD] + {"hash":"ed61950d43d99717","prefixes":{"":{"product":895,"type":0}}}, // [justAd TV LTD] + {"hash":"aff928fc58637cb3","prefixes":{"":{"product":896,"type":0}}}, // [Appier Inc.] + {"hash":"797f76218537ad5d","prefixes":{"*":{"product":896,"type":0}}}, // [Appier Inc.] + {"hash":"6bdcdb03ff6173af","prefixes":{"*":{"product":896,"type":0}}}, // [Appier Inc.] + {"hash":"6a3dec8b5a467987","prefixes":{"*":{"product":896,"type":0}}}, // [Appier Inc.] + {"hash":"a3d5f58bbde56b12","prefixes":{"":{"product":896,"type":0}}}, // [Appier Inc.] + {"hash":"7d0adb9089ff21ca","prefixes":{"":{"product":896,"type":0}}}, // [Appier Inc.] + {"hash":"c241f36263ea7c84","prefixes":{"":{"product":897,"type":0}}}, // [Kate Spade Saturday] + {"hash":"79dd595e79611766","prefixes":{"":{"product":898,"type":0}}}, // [Teufel GmbH] + {"hash":"df829b8e840c11e1","prefixes":{"":{"product":898,"type":0}}}, // [Teufel GmbH] + {"hash":"c3004b48539587e5","prefixes":{"":{"product":898,"type":0}}}, // [Teufel GmbH] + {"hash":"08eb365a3723ee17","prefixes":{"":{"product":898,"type":0}}}, // [Teufel GmbH] + {"hash":"71bc88c0bd0dc170","prefixes":{"":{"product":898,"type":0}}}, // [Teufel GmbH] + {"hash":"fb208e41a565430a","prefixes":{"":{"product":899,"type":0}}}, // [Aitarget LLC] + {"hash":"6121d39232612f56","prefixes":{"":{"product":899,"type":0}}}, // [Aitarget LLC] + {"hash":"0ef54a01a72fdbaf","prefixes":{"*":{"product":676,"type":2}}}, // [Rackspace, US Inc.] + {"hash":"532febae5cf9194f","prefixes":{"":{"product":900,"type":0}}}, // [Engage Lab Ltd.] + {"hash":"fbfff8f12503c208","prefixes":{"":{"product":901,"type":1}}}, // [Signal Digital, Inc dba Signal] + {"hash":"14afd1fc2da14d71","prefixes":{"":{"product":902,"type":0}}}, // [Motrixi Media Group LLC] + {"hash":"aa674bd59dee4716","prefixes":{"":{"product":902,"type":0}}}, // [Motrixi Media Group LLC] + {"hash":"7fd4fa8a06589cab","prefixes":{"":{"product":902,"type":0}}}, // [Motrixi Media Group LLC] + {"hash":"56f94b2620357eb5","prefixes":{"":{"product":902,"type":0}}}, // [Motrixi Media Group LLC] + {"hash":"32ddc8b6874f030b","prefixes":{"":{"product":903,"type":0}}}, // [WHITE HOUSE | BLACK MARKET, Chico Brands, Inc.] + {"hash":"fea26de6b70aafb9","prefixes":{"":{"product":904,"type":0}}}, // [Liftoff Mobile, Inc.] + {"hash":"4687be4922e9d22e","prefixes":{"":{"product":905,"type":1}}}, // [etracker GmbH] + {"hash":"b41f235329fba677","prefixes":{"*":{"product":906,"type":1}}}, // [MezzoMedia] + {"hash":"3362cc82ba37c826","prefixes":{"":{"product":906,"type":1}}}, // [MezzoMedia] + {"hash":"7c5cbde65c1f0a61","prefixes":{"":{"product":907,"type":1}}}, // [Eyeota Limited] + {"hash":"d85ebb0a3c0bdef4","prefixes":{"":{"product":908,"type":0}}}, // [Beijing PageChoice Network Technology co., Ltd.] + {"hash":"52d134e034c55e1d","prefixes":{"":{"product":908,"type":0}}}, // [Beijing PageChoice Network Technology co., Ltd.] + {"hash":"9d9805e510965156","prefixes":{"":{"product":908,"type":0}}}, // [Beijing PageChoice Network Technology co., Ltd.] + {"hash":"5ed6426649a5142e","prefixes":{"":{"product":908,"type":0}}}, // [Beijing PageChoice Network Technology co., Ltd.] + {"hash":"e629bb2b2df81562","prefixes":{"":{"product":908,"type":0}}}, // [Beijing PageChoice Network Technology co., Ltd.] + {"hash":"37a1384fb3fc6090","prefixes":{"":{"product":270,"type":0}}}, // [Intelliad] + {"hash":"9d931008b4067d12","prefixes":{"":{"product":909,"type":0}}}, // [Padopolis, Inc.] + {"hash":"2e0eb051f10f4fe7","prefixes":{"":{"product":909,"type":0}}}, // [Padopolis, Inc.] + {"hash":"e4e066ee012dd820","prefixes":{"":{"product":910,"type":0}}}, // [Republic Project, Inc.] + {"hash":"6bda23da60f6517c","prefixes":{"":{"product":910,"type":0}}}, // [Republic Project, Inc.] + {"hash":"8af361ef2f58932e","prefixes":{"":{"product":910,"type":0}}}, // [Republic Project, Inc.] + {"hash":"9cf685ac4bd3c1a0","prefixes":{"":{"product":910,"type":0}}}, // [Republic Project, Inc.] + {"hash":"ceb2ae18496c4062","prefixes":{"":{"product":910,"type":0}}}, // [Republic Project, Inc.] + {"hash":"a1c74be312c1e501","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"e2305a44231103a0","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"e9ea3f2053ff0ac5","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"18f65ffdee8f8402","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"dc902603963cc6c8","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"6addef0844f148c5","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"c2889776656d63b3","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"1a1ac1eeae181fe7","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"fa03396d4a303d45","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"f632f69c34840122","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"082e62ce70aa66fc","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"775c7d89c606cd3c","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"74b282bb3c686219","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"a8e1956c97315aaf","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"26dc9f78ec72cc0c","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"c4ef7b6eeeda12ce","prefixes":{"":{"product":911,"type":0}}}, // [C8 Network] + {"hash":"e78c2b0997dfa249","prefixes":{"":{"product":912,"type":0}}}, // [Data Artist Inc.] + {"hash":"41045058078214c7","prefixes":{"":{"product":912,"type":0}}}, // [Data Artist Inc.] + {"hash":"c3b23588f42fedff","prefixes":{"":{"product":912,"type":0}}}, // [Data Artist Inc.] + {"hash":"5e94c742d87aa747","prefixes":{"":{"product":912,"type":0}}}, // [Data Artist Inc.] + {"hash":"52632067f5495750","prefixes":{"":{"product":913,"type":0}}}, // [AirFrance] + {"hash":"0b27c948dba1fda0","prefixes":{"":{"product":914,"type":1}}}, // [YDigital Media] + {"hash":"7e30f931dbb7180a","prefixes":{"":{"product":915,"type":2}}}, // [Zentrick] + {"hash":"b3e2285b6fc03e5c","prefixes":{"":{"product":915,"type":2}}}, // [Zentrick] + {"hash":"e2f247795ad2ad87","prefixes":{"":{"product":915,"type":2}}}, // [Zentrick] + {"hash":"1c9e4d1810e659fa","prefixes":{"":{"product":915,"type":2}}}, // [Zentrick] + {"hash":"57511b10e2ed4785","prefixes":{"":{"product":915,"type":2}}}, // [Zentrick] + {"hash":"c012faa898c62e0b","prefixes":{"":{"product":916,"type":0}}}, // [FreeBit Co. Ltd.] + {"hash":"41b7f33c961162f8","prefixes":{"":{"product":916,"type":0}}}, // [FreeBit Co. Ltd.] + {"hash":"ffac4f6c5fa1aa82","prefixes":{"":{"product":916,"type":0}}}, // [FreeBit Co. Ltd.] + {"hash":"a23bae62ab25e2c1","prefixes":{"":{"product":916,"type":0}}}, // [FreeBit Co. Ltd.] + {"hash":"ae08459757b76c12","prefixes":{"":{"product":916,"type":0}}}, // [FreeBit Co. Ltd.] + {"hash":"83efb7fcb7770789","prefixes":{"":{"product":917,"type":0}}}, // [Dennoo Inc.] + {"hash":"042456e26a44a268","prefixes":{"":{"product":917,"type":0}}}, // [Dennoo Inc.] + {"hash":"cb0b16dd50ba9d7d","prefixes":{"":{"product":917,"type":0}}}, // [Dennoo Inc.] + {"hash":"541a895df01d2b2c","prefixes":{"":{"product":917,"type":0}}}, // [Dennoo Inc.] + {"hash":"8f01887bb7405ab5","prefixes":{"":{"product":918,"type":0}}}, // [Adbrain] + {"hash":"33734a86766d25a9","prefixes":{"*":{"product":919,"type":1}}}, // [MSI-ACI Europe BV] + {"hash":"f66543f279b3e1e7","prefixes":{"":{"product":920,"type":0}}}, // [A.Mob] + {"hash":"74ee8c0f2fb31813","prefixes":{"":{"product":920,"type":0}}}, // [A.Mob] + {"hash":"584db20b69521f40","prefixes":{"":{"product":921,"type":0}}}, // [Toys R Us] + {"hash":"6a001e8bc99fede6","prefixes":{"":{"product":922,"type":0}}}, // [Geniee,Inc] + {"hash":"b8ff7bd604535ea9","prefixes":{"":{"product":922,"type":0}}}, // [Geniee,Inc] + {"hash":"3e005c1dfdc23488","prefixes":{"":{"product":923,"type":1}}}, // [Adsecure] + {"hash":"ddef7bb2f5930121","prefixes":{"":{"product":923,"type":1}}}, // [Adsecure] + {"hash":"424399e643b329b8","prefixes":{"":{"product":923,"type":1}}}, // [Adsecure] + {"hash":"23df92e04ec66406","prefixes":{"":{"product":923,"type":1}}}, // [Adsecure] + {"hash":"06f0caf4a4fe6ed1","prefixes":{"":{"product":923,"type":1}}}, // [Adsecure] + {"hash":"9697a0818cbd79bd","prefixes":{"":{"product":923,"type":1}}}, // [Adsecure] + {"hash":"ec7f61f2511ae20e","prefixes":{"":{"product":923,"type":1}}}, // [Adsecure] + {"hash":"fb4e7ecb8304ade4","prefixes":{"":{"product":924,"type":0}}}, // [Kimia Solutions SL] + {"hash":"84f5d0f934bd60f1","prefixes":{"":{"product":924,"type":0}}}, // [Kimia Solutions SL] + {"hash":"b3fcc22fcd382f3b","prefixes":{"":{"product":924,"type":0}}}, // [Kimia Solutions SL] + {"hash":"4eca8c3218b372ae","prefixes":{"":{"product":925,"type":1}}}, // [Sojern] + {"hash":"9636bfb4feaef839","prefixes":{"":{"product":925,"type":1}}}, // [Sojern] + {"hash":"a525b67906a4cb94","prefixes":{"":{"product":926,"type":0}}}, // [Where 2 Get It, Inc.] + {"hash":"6c959985d7181026","prefixes":{"":{"product":926,"type":0}}}, // [Where 2 Get It, Inc.] + {"hash":"7843db8d760e28cb","prefixes":{"":{"product":927,"type":0}}}, // [Tomoko Cloud] + {"hash":"eb7b756fc1f88aa1","prefixes":{"":{"product":927,"type":0}}}, // [Tomoko Cloud] + {"hash":"ed4d672687c27603","prefixes":{"":{"product":927,"type":0}}}, // [Tomoko Cloud] + {"hash":"b156b34e4d693e49","prefixes":{"":{"product":927,"type":0}}}, // [Tomoko Cloud] + {"hash":"16e146e87e7d0383","prefixes":{"":{"product":928,"type":0}}}, // [RevenueMantra] + {"hash":"1457bcbc098b2864","prefixes":{"":{"product":928,"type":0}}}, // [RevenueMantra] + {"hash":"450eb4f9273a5014","prefixes":{"":{"product":929,"type":0}}}, // [Automobile Ltd.] + {"hash":"436e4eaa95b23fcb","prefixes":{"":{"product":929,"type":0}}}, // [Automobile Ltd.] + {"hash":"a47ee9f00ca4f855","prefixes":{"":{"product":929,"type":0}}}, // [Automobile Ltd.] + {"hash":"889ab5643c83668a","prefixes":{"":{"product":929,"type":0}}}, // [Automobile Ltd.] + {"hash":"4ea96f1e0388da92","prefixes":{"":{"product":930,"type":0}}}, // [Big Mobile Group Pty Ltd] + {"hash":"ae895a18cc8c416e","prefixes":{"":{"product":930,"type":0}}}, // [Big Mobile Group Pty Ltd] + {"hash":"bbb46a7f5062448e","prefixes":{"":{"product":931,"type":0}}}, // [ADMIZED AG] + {"hash":"0b4e26a40cc2e647","prefixes":{"":{"product":932,"type":0}}}, // [Sparks47 s.r.l.] + {"hash":"745030cd7ac80402","prefixes":{"":{"product":933,"type":0}}}, // [Between Digital dba Intency DSP] + {"hash":"55db959f7c533183","prefixes":{"":{"product":933,"type":0}}}, // [Between Digital dba Intency DSP] + {"hash":"15b9a82ccbf2d7ff","prefixes":{"":{"product":933,"type":0}}}, // [Between Digital dba Intency DSP] + {"hash":"c63156716e201b52","prefixes":{"":{"product":933,"type":0}}}, // [Between Digital dba Intency DSP] + {"hash":"801d43da2c97866b","prefixes":{"":{"product":933,"type":0}}}, // [Between Digital dba Intency DSP] + {"hash":"d9f810d72012d4c4","prefixes":{"":{"product":934,"type":1}}}, // [eprofessional GmbH] + {"hash":"23c665bb68cc30cc","prefixes":{"":{"product":934,"type":1}}}, // [eprofessional GmbH] + {"hash":"8439b0c8f73daf02","prefixes":{"":{"product":934,"type":1}}}, // [eprofessional GmbH] + {"hash":"6a17378968b598f2","prefixes":{"":{"product":934,"type":1}}}, // [eprofessional GmbH] + {"hash":"4e157cd578931a97","prefixes":{"":{"product":935,"type":0}}}, // [Channel Factory, LLC] + {"hash":"9cdf7d74bee2159f","prefixes":{"":{"product":935,"type":0}}}, // [Channel Factory, LLC] + {"hash":"58c684b764b4dcab","prefixes":{"":{"product":935,"type":0}}}, // [Channel Factory, LLC] + {"hash":"85218b0017b8f452","prefixes":{"":{"product":935,"type":0}}}, // [Channel Factory, LLC] + {"hash":"9f790c0c14fa8f4d","prefixes":{"":{"product":935,"type":0}}}, // [Channel Factory, LLC] + {"hash":"e7518acf5c44d0a4","prefixes":{"":{"product":935,"type":0}}}, // [Channel Factory, LLC] + {"hash":"ec763282f8f41299","prefixes":{"":{"product":935,"type":0}}}, // [Channel Factory, LLC] + {"hash":"41a0870b895e73b4","prefixes":{"":{"product":936,"type":0}}}, // [ConvertStar Incorporated] + {"hash":"f0134a17d368f3d8","prefixes":{"":{"product":936,"type":0}}}, // [ConvertStar Incorporated] + {"hash":"58f6c00f44fb69a4","prefixes":{"":{"product":936,"type":0}}}, // [ConvertStar Incorporated] {"hash":"ff266e088e3010a8","prefixes":{"":{"product":937}}}, // [VisualDNA (Imagini)] {"hash":"9748c01f8dcd17ee","prefixes":{"":{"product":937}}}, // [VisualDNA (Imagini)] {"hash":"8e588a0818c4fcfe","prefixes":{"":{"product":937}}}, // [VisualDNA (Imagini)] {"hash":"b499a754cc7d2c9b","prefixes":{"":{"product":937}}}, // [VisualDNA (Imagini)] - {"hash":"12d363fa8ee6c4d3","prefixes":{"":{"product":938}}}, // [Avocet] - {"hash":"a8bc7b6f66702489","prefixes":{"":{"product":938}}}, // [Avocet] - {"hash":"5166d9515e755f19","prefixes":{"":{"product":939}}}, // [Auction.com, LLC] - {"hash":"3adf8560ada830b8","prefixes":{"":{"product":939}}}, // [Auction.com, LLC] - {"hash":"f24f87c799e92ae5","prefixes":{"":{"product":939}}}, // [Auction.com, LLC] - {"hash":"a60dedada0fd44b6","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"5d0f226850d2e68c","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"e4c703070b535b17","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"bc640a9c42502b35","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"defb06aab760992e","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"9bb069524856b34b","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"ef253518584f013f","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"e100ba963ad8ecf2","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"05b625ee62d8685f","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"5a88fb5abffcefc9","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"a31c0b568cc8ade8","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"3498894fbeac8341","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"1b82605c41d8b709","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"8138ad98ed0394e9","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"751c9ebb221bb5f9","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"8e3793804d9cdab5","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"a6ecf1a95c24b6a3","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"d27fe0e9834e648b","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"2a0c1b5a904b36c1","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"f0d6c35febee8008","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"3c01a29e3c9c7264","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"4a74fdfd9b816fe8","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"aac8184f18b04958","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"368da19a90db3ad7","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"116d46403c6e95b7","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"808bb76ca34e4d1b","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"b19f61f6e35aaa6a","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"9afc01573e38d021","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"11d7bce194c54912","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"a28be439cad08ebb","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"968792ffe85f5d2d","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"d3bc9343531e6c0c","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"a11d6b37b0382222","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"4bf65fa3bba0c55b","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"4e1d992a76cf0b41","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"b09978a8e01fdbca","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"7394b2453f854b55","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"a76d4645267ff0be","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"7e60860df0c8945b","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"ed9d4b0db5598264","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"466d1d16f3a935fb","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"21ac8963bf026e1a","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"e04f72461a1fdf7d","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"549860a6933e906e","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"ddc7313241f77312","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"d89759a9687ad368","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"343ad98c7f4d71ed","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"2cb5047919d88ce8","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"e9739ef3b0403f17","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"2b8ce30f483d90da","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"1d1295f1cdac7503","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"57fd3c09e35ca17e","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"050dd41acc3ac3be","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"1b853fb5c08c8727","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"1c3db6034ad5c3e7","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"4b87160668f51e71","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"d0875bc7510fbaa1","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"a46257724ca67bc0","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"c93d397e8d1ed4fe","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"2cc9ae96e6b56fc3","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"051e72fcceee74d6","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"c24b55da2a7095df","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"88981afd076ecf48","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"1ac94ef8a4d9ad5b","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"a57f0b4ed1a21743","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"ff1f4076329cb91c","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"1ea1f1044008a0b2","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"5a9b4bfa6d03c94b","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"16bcde8365ddf2a8","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"7d3732d8588ffedb","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"fb6a6a06e4463001","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"e357e4b19a11617f","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"ee8aa73feac66773","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"8aa426bd808ed75a","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"e5eed224f946f11b","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"3b812696a50c7061","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"a04facc89859d775","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"37413c9d9331953b","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"d5713942d78606a2","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"52e5d6a64f47f9e8","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"bb49554e8d0ea27b","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"9943d790e614f45a","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"b318da3bafca323e","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"8a6b3193ebf16daf","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"9a4e890c561b1f49","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"38f8c78460d0c171","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"ceb269cfcbfb3737","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"6fc86b42fa2194c7","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"948868ae3f88e79e","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"f78a9daa44503acf","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"f065b37e2901ab44","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"03f33a24e5022801","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"db26cef88e3879aa","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"496f2ff2ad72eb56","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"a33121c16f5e4d20","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"1b5947476f3297ae","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"ebaf8ad16d676e4c","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"5ec7e2368a41e7d1","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"f69cbc017c2bee73","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"e2095571b8a4a9ea","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"8e8d9589ff612ccb","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"4acd7b14907d2eab","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"00b864b32ca6962f","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"0e7fd376997e0ce6","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"8947ab8c7604a712","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"12ae4c62954fb4d7","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"5c70a05c3b20c460","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"7920d4521fc31742","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"14d71824a114fae5","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"5c58f35ad11ea36d","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"c68ff69ac1086025","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"bfb4d21e0325cd27","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"1c5328ce70a7d781","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"3a27002f3a51c391","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"15c536b247ddda9b","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"b8dfd3383dc85e16","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"d834384f74b37311","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"33ad4a447e65fe4c","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"5f92334372103621","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"3b36a0673402ddea","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"b8e5c9de8614511a","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"d6f7d0951a76b20f","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"dc731362e0a22c79","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"c37ce29a12797b87","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"b7f8903cecd3c417","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"e9aea7737083ea26","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"ca849c611df2249c","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"eba969c354d1a2b6","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"828d340d34a88e86","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"18a6bfdbc9b1999c","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"ea6de81ee5ad1594","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"46f992eaa836ef3e","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"a6c162781ee3a889","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"926d3b6bfe6e1943","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"7e15147781f2b0b4","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"221d9d61291eac74","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"d1c16d1fc4dc5998","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"25596ab30bae8f45","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"6f03c0e16553edcf","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"af7ab58246b4c2a5","prefixes":{"":{"product":940}}}, // [White Ops, Inc.] - {"hash":"82a102dc6f580854","prefixes":{"":{"product":773}}}, // [Extreme Reach Digital (ER Digital)] - {"hash":"35f665efa0e2a55c","prefixes":{"":{"product":773}}}, // [Extreme Reach Digital (ER Digital)] - {"hash":"3a48f18bf340e74a","prefixes":{"":{"product":773}}}, // [Extreme Reach Digital (ER Digital)] - {"hash":"ee365433c62a5c89","prefixes":{"":{"product":773}}}, // [Extreme Reach Digital (ER Digital)] - {"hash":"abe6370bd088dcf4","prefixes":{"":{"product":941}}}, // [Hangzhou Qiguan Network Technology Co., Ltd.] - {"hash":"92dba1cdcba82d8a","prefixes":{"":{"product":941}}}, // [Hangzhou Qiguan Network Technology Co., Ltd.] - {"hash":"ee0ccb57505565f7","prefixes":{"":{"product":941}}}, // [Hangzhou Qiguan Network Technology Co., Ltd.] - {"hash":"f25f5e4909b9792c","prefixes":{"":{"product":941}}}, // [Hangzhou Qiguan Network Technology Co., Ltd.] - {"hash":"8a9e6f7beeb084c5","prefixes":{"":{"product":941}}}, // [Hangzhou Qiguan Network Technology Co., Ltd.] - {"hash":"94542c85cf399cbd","prefixes":{"":{"product":323}}}, // [FinanceGenerator] - {"hash":"46ea052a92233562","prefixes":{"":{"product":942}}}, // [Admetrics] - {"hash":"ea5d2271464ca35f","prefixes":{"":{"product":942}}}, // [Admetrics] - {"hash":"286ad0ac5bca5d03","prefixes":{"":{"product":943}}}, // [Admetrics GmbH] - {"hash":"ff1ffc67b7e3f33a","prefixes":{"":{"product":944}}}, // [Amobee Inc. d/b/a Gradient X] - {"hash":"72cbc5ba1ec93b34","prefixes":{"":{"product":944}}}, // [Amobee Inc. d/b/a Gradient X] - {"hash":"a6fc31f82c22f31e","prefixes":{"":{"product":25}}}, // [Action Exchange, Inc.] - {"hash":"1ba64e5bb4889fc8","prefixes":{"":{"product":25}}}, // [Action Exchange, Inc.] - {"hash":"1d75cb11df01626e","prefixes":{"":{"product":25}}}, // [Action Exchange, Inc.] - {"hash":"91e1e972e2691a51","prefixes":{"":{"product":25}}}, // [Action Exchange, Inc.] - {"hash":"23c68afb7d193b79","prefixes":{"":{"product":25}}}, // [Action Exchange, Inc.] - {"hash":"63d64a70ef1c102e","prefixes":{"":{"product":792}}}, // [Recruit Co., Ltd. Communications] - {"hash":"5e5fd982d3646780","prefixes":{"":{"product":793}}}, // [RECRUIT Communications] - {"hash":"405787e06ebc6f4c","prefixes":{"dc":{"product":945}}}, // [Datalicious Pty Ltd] - {"hash":"cddbf4fe7458433c","prefixes":{"":{"product":945}}}, // [Datalicious Pty Ltd] - {"hash":"1c6b7ff16564ebc9","prefixes":{"":{"product":945}}}, // [Datalicious Pty Ltd] - {"hash":"8b00b076af37f543","prefixes":{"":{"product":945}}}, // [Datalicious Pty Ltd] - {"hash":"688a0b3764e1741b","prefixes":{"":{"product":946}}}, // [Intent Media] - {"hash":"04bba28fa6468b07","prefixes":{"":{"product":947}}}, // [AdNear Pte Ltd.] - {"hash":"c10761fe93bddd5e","prefixes":{"":{"product":948}}}, // [Zhejiang MediaAdx Network Technology Co., Ltd] - {"hash":"3b0fa4efa209ebfa","prefixes":{"":{"product":948}}}, // [Zhejiang MediaAdx Network Technology Co., Ltd] - {"hash":"e1b43b2549b03858","prefixes":{"":{"product":949}}}, // [Harris Interactive] - {"hash":"6ade6d73b73295b2","prefixes":{"":{"product":949}}}, // [Harris Interactive] - {"hash":"63efa9155999d096","prefixes":{"":{"product":950}}}, // [BuzzCity Pte Ltd] - {"hash":"564ef19eef7254cf","prefixes":{"":{"product":950}}}, // [BuzzCity Pte Ltd] - {"hash":"6bbdf3ce8eec6f52","prefixes":{"":{"product":950}}}, // [BuzzCity Pte Ltd] - {"hash":"436cc9ab781b357d","prefixes":{"":{"product":950}}}, // [BuzzCity Pte Ltd] - {"hash":"e8cc8c7d43c80259","prefixes":{"":{"product":951}}}, // [Sputnyx] - {"hash":"2150e4c3d0f193b2","prefixes":{"":{"product":951}}}, // [Sputnyx] - {"hash":"54d8f3466d5879bc","prefixes":{"":{"product":951}}}, // [Sputnyx] - {"hash":"b930b780e12735dc","prefixes":{"":{"product":951}}}, // [Sputnyx] - {"hash":"5817597124959a0f","prefixes":{"":{"product":952}}}, // [CyberZ, Inc] - {"hash":"52a82bf3bc55f753","prefixes":{"":{"product":953}}}, // [Spark Networks USA, LLC] - {"hash":"de87290af2710dce","prefixes":{"*":{"product":954}}}, // [Ezakus] - {"hash":"9fa7220a9c513b82","prefixes":{"":{"product":955}}}, // [V4x SAS] - {"hash":"cdea2314328db64c","prefixes":{"":{"product":955}}}, // [V4x SAS] - {"hash":"9ab122baee7ffef0","prefixes":{"":{"product":955}}}, // [V4x SAS] - {"hash":"5b7763887f62f0e2","prefixes":{"":{"product":956}}}, // [Tapjoy Inc.] - {"hash":"c476f40a640ceb50","prefixes":{"":{"product":12}}}, // [Madeleine Mode GmbH] - {"hash":"b03d8c48bc51a903","prefixes":{"":{"product":12}}}, // [Madeleine Mode GmbH] - {"hash":"6ccfc9d681f1cce4","prefixes":{"":{"product":12}}}, // [Madeleine Mode GmbH] - {"hash":"519e706c784712cd","prefixes":{"":{"product":12}}}, // [Madeleine Mode GmbH] - {"hash":"4b99f5579a32d2ac","prefixes":{"":{"product":957}}}, // [EXEBID] - {"hash":"7bb686f653faf750","prefixes":{"":{"product":957}}}, // [EXEBID] - {"hash":"59bac04b09eb1850","prefixes":{"":{"product":957}}}, // [EXEBID] - {"hash":"c7c593cac7252275","prefixes":{"":{"product":957}}}, // [EXEBID] - {"hash":"9a2642b29d01ad5a","prefixes":{"":{"product":957}}}, // [EXEBID] - {"hash":"19e7f2b697047d0f","prefixes":{"":{"product":957}}}, // [EXEBID] - {"hash":"9ccde0a8ec3f9703","prefixes":{"":{"product":957}}}, // [EXEBID] - {"hash":"a81ee6b474d31f53","prefixes":{"":{"product":957}}}, // [EXEBID] - {"hash":"3b743b2fda71dd5f","prefixes":{"":{"product":957}}}, // [EXEBID] - {"hash":"6378b3090ceafcf5","prefixes":{"*":{"product":562}}}, // [Bannerflow AB] - {"hash":"09de5d9c8a08a419","prefixes":{"":{"product":958}}}, // [Exposebox Ltd] - {"hash":"d88faf97f4f01be0","prefixes":{"":{"product":958}}}, // [Exposebox Ltd] - {"hash":"1b7a8075387597c8","prefixes":{"":{"product":958}}}, // [Exposebox Ltd] - {"hash":"42127ec758c4891f","prefixes":{"":{"product":959}}}, // [MotoMiner] - {"hash":"f5fe6be8ffc65b45","prefixes":{"":{"product":960}}}, // [BuySellAds.com Inc.] - {"hash":"4b9190a98d317014","prefixes":{"":{"product":960}}}, // [BuySellAds.com Inc.] - {"hash":"3b55d9e306cf9e3c","prefixes":{"":{"product":960}}}, // [BuySellAds.com Inc.] - {"hash":"a9da15f40498a6f3","prefixes":{"":{"product":961}}}, // [Viking River Cruises] - {"hash":"e2a8d45a4c55dae6","prefixes":{"":{"product":962}}}, // [Sittercity Incorporated] - {"hash":"5dd667d71a34b766","prefixes":{"":{"product":963}}}, // [Facetz] - {"hash":"00776ec1c54574db","prefixes":{"":{"product":964}}}, // [YOOSE Pte. Ltd.] - {"hash":"f8c3b8f01c62da3c","prefixes":{"":{"product":965}}}, // [AdYapper, Inc.] - {"hash":"6c1804db5b6679a9","prefixes":{"":{"product":965}}}, // [AdYapper, Inc.] - {"hash":"a361de3d2fcba609","prefixes":{"":{"product":965}}}, // [AdYapper, Inc.] - {"hash":"1f805f58db63a12d","prefixes":{"":{"product":965}}}, // [AdYapper, Inc.] - {"hash":"7090e79d9ec26768","prefixes":{"":{"product":965}}}, // [AdYapper, Inc.] - {"hash":"727b3d1100b7d374","prefixes":{"":{"product":965}}}, // [AdYapper, Inc.] - {"hash":"17b396141b96c236","prefixes":{"":{"product":799}}}, // [Webtrekk GmbH] - {"hash":"b0149857f43862d9","prefixes":{"":{"product":144}}}, // [Spark Flow S.A.] - {"hash":"f9c00c55ede792e2","prefixes":{"":{"product":144}}}, // [Spark Flow S.A.] - {"hash":"8eb24e3340b4c707","prefixes":{"":{"product":966}}}, // [Clickky LLP DBA Clickky] - {"hash":"2d27319a70fb6262","prefixes":{"":{"product":966}}}, // [Clickky LLP DBA Clickky] - {"hash":"b140173de591dc64","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"7e2351ba05fefcce","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"88a66ce20c2df5e5","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"705049ea1378adbd","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"eadabb19d68f0e02","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"684343b8f00b5425","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"fedb0d981d151071","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"eb26cb8958b84143","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"b4f42222ff48d611","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"3ef4c3e15c3889aa","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"346ac90e489a0d27","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"f0685c9d889a4dcb","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"d2ae279176821009","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"98746e3eb9075cc5","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"f4e7d8ca3f73252e","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"145b69a5570cf0e6","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"b96e6d8a02aabe0f","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"5f7def46ec1776af","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"075bdf0eaa8a2d8a","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"374ddadb8b59c656","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"e75f11f13cf01278","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"fa9f043b6f9f0225","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"51046da25aac136a","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"e3d9117eacb00b04","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"2291e11d2ca518c2","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"208af3ccccac3a8a","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"8a7e7a7c9510a539","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"d62dab4e5ba19318","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"9faead99b5b9e15b","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"21ad4e7e6897e7be","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"5f6e332f4f7ad081","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"28c87295fd99d9b2","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"ec4d1f8447f0f153","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"bcdb0c5a6199a121","prefixes":{"":{"product":967}}}, // [eRate Online Measurement Solutions Ltd.] - {"hash":"dc1424820d5085bc","prefixes":{"":{"product":967}}}, // [eRate Online Measurement Solutions Ltd.] - {"hash":"d110aae732b1c80d","prefixes":{"":{"product":967}}}, // [eRate Online Measurement Solutions Ltd.] - {"hash":"d461527c3648da49","prefixes":{"":{"product":968}}}, // [Baumann Ber Rivnay] - {"hash":"da8fb21c56d3c224","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"abb93e258191198a","prefixes":{"":{"product":13}}}, // [TripAdvisor LLC] - {"hash":"67ce1b0bfa972cc4","prefixes":{"":{"product":969}}}, // [TUI Connect GmbH] - {"hash":"63c1158e18a5ea27","prefixes":{"":{"product":970}}}, // [INFOnline GmbH] - {"hash":"46a40e7a328ffee7","prefixes":{"":{"product":971}}}, // [Adizio] - {"hash":"c5ca269d09b7c25f","prefixes":{"*":{"product":972}}}, // [Joystick Interactive] - {"hash":"93d3775dcb79f65b","prefixes":{"":{"product":973}}}, // [EngageClick Inc] - {"hash":"0af466da8ca75d0b","prefixes":{"":{"product":973}}}, // [EngageClick Inc] - {"hash":"111ffa6b19238149","prefixes":{"":{"product":974}}}, // [GeeeN, Inc.] - {"hash":"46313b1a2b164e11","prefixes":{"":{"product":974}}}, // [GeeeN, Inc.] - {"hash":"edeaec47d1406cde","prefixes":{"":{"product":974}}}, // [GeeeN, Inc.] - {"hash":"e4fa03e71e81c717","prefixes":{"":{"product":975}}}, // [Arbigo Inc.] - {"hash":"b05d395ad43a6851","prefixes":{"":{"product":975}}}, // [Arbigo Inc.] - {"hash":"babf6252b4c60056","prefixes":{"":{"product":975}}}, // [Arbigo Inc.] - {"hash":"db86fc0d97ddf866","prefixes":{"":{"product":975}}}, // [Arbigo Inc.] - {"hash":"ea61f7fa94bc2f36","prefixes":{"":{"product":975}}}, // [Arbigo Inc.] - {"hash":"495d58c312a856b7","prefixes":{"":{"product":975}}}, // [Arbigo Inc.] - {"hash":"ce854368c8ba8c24","prefixes":{"":{"product":975}}}, // [Arbigo Inc.] - {"hash":"7c1ebbe2aa48388d","prefixes":{"":{"product":975}}}, // [Arbigo Inc.] - {"hash":"0ac9c5956a237913","prefixes":{"":{"product":975}}}, // [Arbigo Inc.] - {"hash":"5e22bf81f1721d99","prefixes":{"":{"product":975}}}, // [Arbigo Inc.] - {"hash":"ad1ab56f3a151112","prefixes":{"":{"product":976}}}, // [FlxOne BV] - {"hash":"6c833f73351e1f63","prefixes":{"":{"product":976}}}, // [FlxOne BV] - {"hash":"82f8d328de710cff","prefixes":{"":{"product":976}}}, // [FlxOne BV] - {"hash":"95c33537789a441f","prefixes":{"":{"product":976}}}, // [FlxOne BV] - {"hash":"712c817d06c0d8c6","prefixes":{"":{"product":976}}}, // [FlxOne BV] + {"hash":"12d363fa8ee6c4d3","prefixes":{"":{"product":938,"type":0}}}, // [Avocet] + {"hash":"a8bc7b6f66702489","prefixes":{"":{"product":938,"type":0}}}, // [Avocet] + {"hash":"5166d9515e755f19","prefixes":{"":{"product":939,"type":0}}}, // [Auction.com, LLC] + {"hash":"3adf8560ada830b8","prefixes":{"":{"product":939,"type":0}}}, // [Auction.com, LLC] + {"hash":"f24f87c799e92ae5","prefixes":{"":{"product":939,"type":0}}}, // [Auction.com, LLC] + {"hash":"a60dedada0fd44b6","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"5d0f226850d2e68c","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"e4c703070b535b17","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"bc640a9c42502b35","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"defb06aab760992e","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"9bb069524856b34b","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"ef253518584f013f","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"e100ba963ad8ecf2","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"05b625ee62d8685f","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"5a88fb5abffcefc9","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"a31c0b568cc8ade8","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"3498894fbeac8341","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"1b82605c41d8b709","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"8138ad98ed0394e9","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"751c9ebb221bb5f9","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"8e3793804d9cdab5","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"a6ecf1a95c24b6a3","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"d27fe0e9834e648b","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"2a0c1b5a904b36c1","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"f0d6c35febee8008","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"3c01a29e3c9c7264","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"4a74fdfd9b816fe8","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"aac8184f18b04958","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"368da19a90db3ad7","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"116d46403c6e95b7","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"808bb76ca34e4d1b","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"b19f61f6e35aaa6a","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"9afc01573e38d021","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"11d7bce194c54912","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"a28be439cad08ebb","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"968792ffe85f5d2d","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"d3bc9343531e6c0c","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"a11d6b37b0382222","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"4bf65fa3bba0c55b","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"4e1d992a76cf0b41","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"b09978a8e01fdbca","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"7394b2453f854b55","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"a76d4645267ff0be","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"7e60860df0c8945b","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"ed9d4b0db5598264","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"466d1d16f3a935fb","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"21ac8963bf026e1a","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"e04f72461a1fdf7d","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"549860a6933e906e","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"ddc7313241f77312","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"d89759a9687ad368","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"343ad98c7f4d71ed","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"2cb5047919d88ce8","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"e9739ef3b0403f17","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"2b8ce30f483d90da","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"1d1295f1cdac7503","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"57fd3c09e35ca17e","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"050dd41acc3ac3be","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"1b853fb5c08c8727","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"1c3db6034ad5c3e7","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"4b87160668f51e71","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"d0875bc7510fbaa1","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"a46257724ca67bc0","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"c93d397e8d1ed4fe","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"2cc9ae96e6b56fc3","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"051e72fcceee74d6","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"c24b55da2a7095df","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"88981afd076ecf48","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"1ac94ef8a4d9ad5b","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"a57f0b4ed1a21743","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"ff1f4076329cb91c","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"1ea1f1044008a0b2","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"5a9b4bfa6d03c94b","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"16bcde8365ddf2a8","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"7d3732d8588ffedb","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"fb6a6a06e4463001","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"e357e4b19a11617f","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"ee8aa73feac66773","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"8aa426bd808ed75a","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"e5eed224f946f11b","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"3b812696a50c7061","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"a04facc89859d775","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"37413c9d9331953b","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"d5713942d78606a2","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"52e5d6a64f47f9e8","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"bb49554e8d0ea27b","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"9943d790e614f45a","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"b318da3bafca323e","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"8a6b3193ebf16daf","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"9a4e890c561b1f49","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"38f8c78460d0c171","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"ceb269cfcbfb3737","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"6fc86b42fa2194c7","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"948868ae3f88e79e","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"f78a9daa44503acf","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"f065b37e2901ab44","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"03f33a24e5022801","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"db26cef88e3879aa","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"496f2ff2ad72eb56","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"a33121c16f5e4d20","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"1b5947476f3297ae","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"ebaf8ad16d676e4c","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"5ec7e2368a41e7d1","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"f69cbc017c2bee73","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"e2095571b8a4a9ea","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"8e8d9589ff612ccb","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"4acd7b14907d2eab","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"00b864b32ca6962f","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"0e7fd376997e0ce6","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"8947ab8c7604a712","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"12ae4c62954fb4d7","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"5c70a05c3b20c460","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"7920d4521fc31742","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"14d71824a114fae5","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"5c58f35ad11ea36d","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"c68ff69ac1086025","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"bfb4d21e0325cd27","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"1c5328ce70a7d781","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"3a27002f3a51c391","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"15c536b247ddda9b","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"b8dfd3383dc85e16","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"d834384f74b37311","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"33ad4a447e65fe4c","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"5f92334372103621","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"3b36a0673402ddea","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"b8e5c9de8614511a","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"d6f7d0951a76b20f","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"dc731362e0a22c79","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"c37ce29a12797b87","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"b7f8903cecd3c417","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"e9aea7737083ea26","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"ca849c611df2249c","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"eba969c354d1a2b6","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"828d340d34a88e86","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"18a6bfdbc9b1999c","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"ea6de81ee5ad1594","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"46f992eaa836ef3e","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"a6c162781ee3a889","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"926d3b6bfe6e1943","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"7e15147781f2b0b4","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"221d9d61291eac74","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"d1c16d1fc4dc5998","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"25596ab30bae8f45","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"6f03c0e16553edcf","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"af7ab58246b4c2a5","prefixes":{"":{"product":940,"type":1}}}, // [White Ops, Inc.] + {"hash":"82a102dc6f580854","prefixes":{"":{"product":773,"type":0}}}, // [Extreme Reach Digital (ER Digital)] + {"hash":"35f665efa0e2a55c","prefixes":{"":{"product":773,"type":0}}}, // [Extreme Reach Digital (ER Digital)] + {"hash":"3a48f18bf340e74a","prefixes":{"":{"product":773,"type":0}}}, // [Extreme Reach Digital (ER Digital)] + {"hash":"ee365433c62a5c89","prefixes":{"":{"product":773,"type":0}}}, // [Extreme Reach Digital (ER Digital)] + {"hash":"abe6370bd088dcf4","prefixes":{"":{"product":941,"type":0}}}, // [Hangzhou Qiguan Network Technology Co., Ltd.] + {"hash":"92dba1cdcba82d8a","prefixes":{"":{"product":941,"type":0}}}, // [Hangzhou Qiguan Network Technology Co., Ltd.] + {"hash":"ee0ccb57505565f7","prefixes":{"":{"product":941,"type":0}}}, // [Hangzhou Qiguan Network Technology Co., Ltd.] + {"hash":"f25f5e4909b9792c","prefixes":{"":{"product":941,"type":0}}}, // [Hangzhou Qiguan Network Technology Co., Ltd.] + {"hash":"8a9e6f7beeb084c5","prefixes":{"":{"product":941,"type":0}}}, // [Hangzhou Qiguan Network Technology Co., Ltd.] + {"hash":"94542c85cf399cbd","prefixes":{"":{"product":323,"type":0}}}, // [FinanceGenerator] + {"hash":"46ea052a92233562","prefixes":{"":{"product":942,"type":1}}}, // [Admetrics] + {"hash":"ea5d2271464ca35f","prefixes":{"":{"product":942,"type":1}}}, // [Admetrics] + {"hash":"286ad0ac5bca5d03","prefixes":{"":{"product":943,"type":0}}}, // [Admetrics GmbH] + {"hash":"ff1ffc67b7e3f33a","prefixes":{"":{"product":944,"type":0}}}, // [Amobee Inc. d/b/a Gradient X] + {"hash":"72cbc5ba1ec93b34","prefixes":{"":{"product":944,"type":0}}}, // [Amobee Inc. d/b/a Gradient X] + {"hash":"a6fc31f82c22f31e","prefixes":{"":{"product":25,"type":0}}}, // [Action Exchange, Inc.] + {"hash":"1ba64e5bb4889fc8","prefixes":{"":{"product":25,"type":0}}}, // [Action Exchange, Inc.] + {"hash":"1d75cb11df01626e","prefixes":{"":{"product":25,"type":0}}}, // [Action Exchange, Inc.] + {"hash":"91e1e972e2691a51","prefixes":{"":{"product":25,"type":0}}}, // [Action Exchange, Inc.] + {"hash":"23c68afb7d193b79","prefixes":{"":{"product":25,"type":0}}}, // [Action Exchange, Inc.] + {"hash":"63d64a70ef1c102e","prefixes":{"":{"product":792,"type":0}}}, // [Recruit Co., Ltd. Communications] + {"hash":"5e5fd982d3646780","prefixes":{"":{"product":793,"type":0}}}, // [RECRUIT Communications] + {"hash":"405787e06ebc6f4c","prefixes":{"dc":{"product":945,"type":1}}}, // [Datalicious Pty Ltd] + {"hash":"cddbf4fe7458433c","prefixes":{"":{"product":945,"type":1}}}, // [Datalicious Pty Ltd] + {"hash":"1c6b7ff16564ebc9","prefixes":{"":{"product":945,"type":1}}}, // [Datalicious Pty Ltd] + {"hash":"8b00b076af37f543","prefixes":{"":{"product":945,"type":1}}}, // [Datalicious Pty Ltd] + {"hash":"688a0b3764e1741b","prefixes":{"":{"product":946,"type":1}}}, // [Intent Media] + {"hash":"04bba28fa6468b07","prefixes":{"":{"product":947,"type":0}}}, // [AdNear Pte Ltd.] + {"hash":"c10761fe93bddd5e","prefixes":{"":{"product":948,"type":1}}}, // [Zhejiang MediaAdx Network Technology Co., Ltd] + {"hash":"3b0fa4efa209ebfa","prefixes":{"":{"product":948,"type":1}}}, // [Zhejiang MediaAdx Network Technology Co., Ltd] + {"hash":"e1b43b2549b03858","prefixes":{"":{"product":949,"type":1}}}, // [Harris Interactive] + {"hash":"6ade6d73b73295b2","prefixes":{"":{"product":949,"type":1}}}, // [Harris Interactive] + {"hash":"63efa9155999d096","prefixes":{"":{"product":950,"type":0}}}, // [BuzzCity Pte Ltd] + {"hash":"564ef19eef7254cf","prefixes":{"":{"product":950,"type":0}}}, // [BuzzCity Pte Ltd] + {"hash":"6bbdf3ce8eec6f52","prefixes":{"":{"product":950,"type":0}}}, // [BuzzCity Pte Ltd] + {"hash":"436cc9ab781b357d","prefixes":{"":{"product":950,"type":0}}}, // [BuzzCity Pte Ltd] + {"hash":"e8cc8c7d43c80259","prefixes":{"":{"product":951,"type":0}}}, // [Sputnyx] + {"hash":"2150e4c3d0f193b2","prefixes":{"":{"product":951,"type":0}}}, // [Sputnyx] + {"hash":"54d8f3466d5879bc","prefixes":{"":{"product":951,"type":0}}}, // [Sputnyx] + {"hash":"b930b780e12735dc","prefixes":{"":{"product":951,"type":0}}}, // [Sputnyx] + {"hash":"5817597124959a0f","prefixes":{"":{"product":952,"type":0}}}, // [CyberZ, Inc] + {"hash":"52a82bf3bc55f753","prefixes":{"":{"product":953,"type":1}}}, // [Spark Networks USA, LLC] + {"hash":"de87290af2710dce","prefixes":{"*":{"product":954,"type":1}}}, // [Ezakus] + {"hash":"9fa7220a9c513b82","prefixes":{"":{"product":955,"type":0}}}, // [V4x SAS] + {"hash":"cdea2314328db64c","prefixes":{"":{"product":955,"type":0}}}, // [V4x SAS] + {"hash":"9ab122baee7ffef0","prefixes":{"":{"product":955,"type":0}}}, // [V4x SAS] + {"hash":"5b7763887f62f0e2","prefixes":{"":{"product":956,"type":0}}}, // [Tapjoy Inc.] + {"hash":"c476f40a640ceb50","prefixes":{"":{"product":12,"type":1}}}, // [Madeleine Mode GmbH] + {"hash":"b03d8c48bc51a903","prefixes":{"":{"product":12,"type":1}}}, // [Madeleine Mode GmbH] + {"hash":"6ccfc9d681f1cce4","prefixes":{"":{"product":12,"type":1}}}, // [Madeleine Mode GmbH] + {"hash":"519e706c784712cd","prefixes":{"":{"product":12,"type":1}}}, // [Madeleine Mode GmbH] + {"hash":"4b99f5579a32d2ac","prefixes":{"":{"product":957,"type":0}}}, // [EXEBID] + {"hash":"7bb686f653faf750","prefixes":{"":{"product":957,"type":0}}}, // [EXEBID] + {"hash":"59bac04b09eb1850","prefixes":{"":{"product":957,"type":0}}}, // [EXEBID] + {"hash":"c7c593cac7252275","prefixes":{"":{"product":957,"type":0}}}, // [EXEBID] + {"hash":"9a2642b29d01ad5a","prefixes":{"":{"product":957,"type":0}}}, // [EXEBID] + {"hash":"19e7f2b697047d0f","prefixes":{"":{"product":957,"type":0}}}, // [EXEBID] + {"hash":"9ccde0a8ec3f9703","prefixes":{"":{"product":957,"type":0}}}, // [EXEBID] + {"hash":"a81ee6b474d31f53","prefixes":{"":{"product":957,"type":0}}}, // [EXEBID] + {"hash":"3b743b2fda71dd5f","prefixes":{"":{"product":957,"type":0}}}, // [EXEBID] + {"hash":"6378b3090ceafcf5","prefixes":{"*":{"product":562,"type":0}}}, // [Bannerflow AB] + {"hash":"09de5d9c8a08a419","prefixes":{"":{"product":958,"type":0}}}, // [Exposebox Ltd] + {"hash":"d88faf97f4f01be0","prefixes":{"":{"product":958,"type":0}}}, // [Exposebox Ltd] + {"hash":"1b7a8075387597c8","prefixes":{"":{"product":958,"type":0}}}, // [Exposebox Ltd] + {"hash":"42127ec758c4891f","prefixes":{"":{"product":959,"type":0}}}, // [MotoMiner] + {"hash":"f5fe6be8ffc65b45","prefixes":{"":{"product":960,"type":0}}}, // [BuySellAds.com Inc.] + {"hash":"4b9190a98d317014","prefixes":{"":{"product":960,"type":0}}}, // [BuySellAds.com Inc.] + {"hash":"3b55d9e306cf9e3c","prefixes":{"":{"product":960,"type":0}}}, // [BuySellAds.com Inc.] + {"hash":"a9da15f40498a6f3","prefixes":{"":{"product":961,"type":0}}}, // [Viking River Cruises] + {"hash":"e2a8d45a4c55dae6","prefixes":{"":{"product":962,"type":0}}}, // [Sittercity Incorporated] + {"hash":"5dd667d71a34b766","prefixes":{"":{"product":963,"type":1}}}, // [Facetz] + {"hash":"00776ec1c54574db","prefixes":{"":{"product":964,"type":0}}}, // [YOOSE Pte. Ltd.] + {"hash":"f8c3b8f01c62da3c","prefixes":{"":{"product":965,"type":1}}}, // [AdYapper, Inc.] + {"hash":"6c1804db5b6679a9","prefixes":{"":{"product":965,"type":1}}}, // [AdYapper, Inc.] + {"hash":"a361de3d2fcba609","prefixes":{"":{"product":965,"type":1}}}, // [AdYapper, Inc.] + {"hash":"1f805f58db63a12d","prefixes":{"":{"product":965,"type":1}}}, // [AdYapper, Inc.] + {"hash":"7090e79d9ec26768","prefixes":{"":{"product":965,"type":1}}}, // [AdYapper, Inc.] + {"hash":"727b3d1100b7d374","prefixes":{"":{"product":965,"type":1}}}, // [AdYapper, Inc.] + {"hash":"17b396141b96c236","prefixes":{"":{"product":799,"type":1}}}, // [Webtrekk GmbH] + {"hash":"b0149857f43862d9","prefixes":{"":{"product":144,"type":0}}}, // [Spark Flow S.A.] + {"hash":"f9c00c55ede792e2","prefixes":{"":{"product":144,"type":0}}}, // [Spark Flow S.A.] + {"hash":"8eb24e3340b4c707","prefixes":{"":{"product":966,"type":0}}}, // [Clickky LLP DBA Clickky] + {"hash":"2d27319a70fb6262","prefixes":{"":{"product":966,"type":0}}}, // [Clickky LLP DBA Clickky] + {"hash":"b140173de591dc64","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"7e2351ba05fefcce","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"88a66ce20c2df5e5","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"705049ea1378adbd","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"eadabb19d68f0e02","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"684343b8f00b5425","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"fedb0d981d151071","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"eb26cb8958b84143","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"b4f42222ff48d611","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"3ef4c3e15c3889aa","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"346ac90e489a0d27","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"f0685c9d889a4dcb","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"d2ae279176821009","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"98746e3eb9075cc5","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"f4e7d8ca3f73252e","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"145b69a5570cf0e6","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"b96e6d8a02aabe0f","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"5f7def46ec1776af","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"075bdf0eaa8a2d8a","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"374ddadb8b59c656","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"e75f11f13cf01278","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"fa9f043b6f9f0225","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"51046da25aac136a","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"e3d9117eacb00b04","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"2291e11d2ca518c2","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"208af3ccccac3a8a","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"8a7e7a7c9510a539","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"d62dab4e5ba19318","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"9faead99b5b9e15b","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"21ad4e7e6897e7be","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"5f6e332f4f7ad081","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"28c87295fd99d9b2","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"ec4d1f8447f0f153","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"bcdb0c5a6199a121","prefixes":{"":{"product":967,"type":0}}}, // [eRate Online Measurement Solutions Ltd.] + {"hash":"dc1424820d5085bc","prefixes":{"":{"product":967,"type":0}}}, // [eRate Online Measurement Solutions Ltd.] + {"hash":"d110aae732b1c80d","prefixes":{"":{"product":967,"type":0}}}, // [eRate Online Measurement Solutions Ltd.] + {"hash":"d461527c3648da49","prefixes":{"":{"product":968,"type":2}}}, // [Baumann Ber Rivnay] + {"hash":"da8fb21c56d3c224","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"abb93e258191198a","prefixes":{"":{"product":13,"type":1}}}, // [TripAdvisor LLC] + {"hash":"67ce1b0bfa972cc4","prefixes":{"":{"product":969,"type":0}}}, // [TUI Connect GmbH] + {"hash":"63c1158e18a5ea27","prefixes":{"":{"product":970,"type":1}}}, // [INFOnline GmbH] + {"hash":"46a40e7a328ffee7","prefixes":{"":{"product":971,"type":0}}}, // [Adizio] + {"hash":"c5ca269d09b7c25f","prefixes":{"*":{"product":972,"type":1}}}, // [Joystick Interactive] + {"hash":"93d3775dcb79f65b","prefixes":{"":{"product":973,"type":0}}}, // [EngageClick Inc] + {"hash":"0af466da8ca75d0b","prefixes":{"":{"product":973,"type":0}}}, // [EngageClick Inc] + {"hash":"111ffa6b19238149","prefixes":{"":{"product":974,"type":0}}}, // [GeeeN, Inc.] + {"hash":"46313b1a2b164e11","prefixes":{"":{"product":974,"type":0}}}, // [GeeeN, Inc.] + {"hash":"edeaec47d1406cde","prefixes":{"":{"product":974,"type":0}}}, // [GeeeN, Inc.] + {"hash":"e4fa03e71e81c717","prefixes":{"":{"product":975,"type":1}}}, // [Arbigo Inc.] + {"hash":"b05d395ad43a6851","prefixes":{"":{"product":975,"type":1}}}, // [Arbigo Inc.] + {"hash":"babf6252b4c60056","prefixes":{"":{"product":975,"type":1}}}, // [Arbigo Inc.] + {"hash":"db86fc0d97ddf866","prefixes":{"":{"product":975,"type":1}}}, // [Arbigo Inc.] + {"hash":"ea61f7fa94bc2f36","prefixes":{"":{"product":975,"type":1}}}, // [Arbigo Inc.] + {"hash":"495d58c312a856b7","prefixes":{"":{"product":975,"type":1}}}, // [Arbigo Inc.] + {"hash":"ce854368c8ba8c24","prefixes":{"":{"product":975,"type":1}}}, // [Arbigo Inc.] + {"hash":"7c1ebbe2aa48388d","prefixes":{"":{"product":975,"type":1}}}, // [Arbigo Inc.] + {"hash":"0ac9c5956a237913","prefixes":{"":{"product":975,"type":1}}}, // [Arbigo Inc.] + {"hash":"5e22bf81f1721d99","prefixes":{"":{"product":975,"type":1}}}, // [Arbigo Inc.] + {"hash":"ad1ab56f3a151112","prefixes":{"":{"product":976,"type":1}}}, // [FlxOne BV] + {"hash":"6c833f73351e1f63","prefixes":{"":{"product":976,"type":1}}}, // [FlxOne BV] + {"hash":"82f8d328de710cff","prefixes":{"":{"product":976,"type":1}}}, // [FlxOne BV] + {"hash":"95c33537789a441f","prefixes":{"":{"product":976,"type":1}}}, // [FlxOne BV] + {"hash":"712c817d06c0d8c6","prefixes":{"":{"product":976,"type":1}}}, // [FlxOne BV] {"hash":"63446ae2652818ab","prefixes":{"":{"product":10}}}, // [eBay] - {"hash":"45b598cd3bc42672","prefixes":{"":{"product":977}}}, // [ExtendTV, Inc.] - {"hash":"372fde25faa1c878","prefixes":{"":{"product":977}}}, // [ExtendTV, Inc.] - {"hash":"db1da0ef7de3e1e6","prefixes":{"":{"product":978}}}, // [momentM, Inc] - {"hash":"5710705dc9e3a971","prefixes":{"":{"product":978}}}, // [momentM, Inc] - {"hash":"4ee3d75e96c8e3aa","prefixes":{"":{"product":978}}}, // [momentM, Inc] - {"hash":"b329682f26e4fcc6","prefixes":{"":{"product":978}}}, // [momentM, Inc] - {"hash":"71215c2931d79d35","prefixes":{"":{"product":978}}}, // [momentM, Inc] - {"hash":"667a4fe4b59238b9","prefixes":{"":{"product":978}}}, // [momentM, Inc] - {"hash":"a7fbeec4fb43f9d9","prefixes":{"*":{"product":979}}}, // [OnCard Marketing dba RevTrax] + {"hash":"45b598cd3bc42672","prefixes":{"":{"product":977,"type":1}}}, // [ExtendTV, Inc.] + {"hash":"372fde25faa1c878","prefixes":{"":{"product":977,"type":1}}}, // [ExtendTV, Inc.] + {"hash":"db1da0ef7de3e1e6","prefixes":{"":{"product":978,"type":0}}}, // [momentM, Inc] + {"hash":"5710705dc9e3a971","prefixes":{"":{"product":978,"type":0}}}, // [momentM, Inc] + {"hash":"4ee3d75e96c8e3aa","prefixes":{"":{"product":978,"type":0}}}, // [momentM, Inc] + {"hash":"b329682f26e4fcc6","prefixes":{"":{"product":978,"type":0}}}, // [momentM, Inc] + {"hash":"71215c2931d79d35","prefixes":{"":{"product":978,"type":0}}}, // [momentM, Inc] + {"hash":"667a4fe4b59238b9","prefixes":{"":{"product":978,"type":0}}}, // [momentM, Inc] + {"hash":"a7fbeec4fb43f9d9","prefixes":{"*":{"product":979,"type":1}}}, // [OnCard Marketing dba RevTrax] {"hash":"48a825a8c5ef9edd","prefixes":{"*":{"product":980}}}, // [Youtube - API] - {"hash":"19459fb447ce4de4","prefixes":{"*":{"product":981}}}, // [Thirdpresence Ltd] - {"hash":"f079f0a998c56593","prefixes":{"":{"product":981}}}, // [Thirdpresence Ltd] - {"hash":"108dd21ceba53008","prefixes":{"":{"product":982}}}, // [Visual IQ, Inc.] - {"hash":"7b0dec2d8c1ec967","prefixes":{"":{"product":982}}}, // [Visual IQ, Inc.] - {"hash":"b5c3f2f3c1c37850","prefixes":{"":{"product":982}}}, // [Visual IQ, Inc.] - {"hash":"ba9b4eca15987843","prefixes":{"":{"product":982}}}, // [Visual IQ, Inc.] - {"hash":"4e521b3e57d76700","prefixes":{"":{"product":982}}}, // [Visual IQ, Inc.] - {"hash":"29ab2715e00761b0","prefixes":{"":{"product":982}}}, // [Visual IQ, Inc.] - {"hash":"688071d177180274","prefixes":{"":{"product":982}}}, // [Visual IQ, Inc.] - {"hash":"4e682c7f7f2ebda9","prefixes":{"":{"product":983}}}, // [Appreciate] - {"hash":"4b6451297bd74247","prefixes":{"":{"product":983}}}, // [Appreciate] - {"hash":"95d75ced1262ecda","prefixes":{"":{"product":983}}}, // [Appreciate] - {"hash":"ac94d70ffcad5c63","prefixes":{"":{"product":983}}}, // [Appreciate] - {"hash":"578591a9eb9652f2","prefixes":{"":{"product":983}}}, // [Appreciate] - {"hash":"5528666c72c7c71c","prefixes":{"":{"product":983}}}, // [Appreciate] - {"hash":"3deb1cd39233765c","prefixes":{"":{"product":983}}}, // [Appreciate] - {"hash":"4e05303df9f07532","prefixes":{"":{"product":983}}}, // [Appreciate] - {"hash":"99936e7e455c77b7","prefixes":{"":{"product":983}}}, // [Appreciate] - {"hash":"f0e5986dc65416fd","prefixes":{"":{"product":983}}}, // [Appreciate] - {"hash":"5095285a4ab05444","prefixes":{"":{"product":983}}}, // [Appreciate] - {"hash":"670fdb8ea86ee233","prefixes":{"":{"product":983}}}, // [Appreciate] - {"hash":"ad2de628bc6fd483","prefixes":{"":{"product":984},"lodeo-":{"product":985}}}, // [CyberAgent d/b/a GameLogic] [Lodeo] - {"hash":"66e26f9703f2dd67","prefixes":{"":{"product":984}}}, // [CyberAgent d/b/a GameLogic] - {"hash":"80451e302607b653","prefixes":{"":{"product":984}}}, // [CyberAgent d/b/a GameLogic] - {"hash":"bb7f7e8ab7b99724","prefixes":{"":{"product":984}}}, // [CyberAgent d/b/a GameLogic] - {"hash":"51dbfc01b5f86601","prefixes":{"":{"product":984}}}, // [CyberAgent d/b/a GameLogic] - {"hash":"2a8926ec16272a9b","prefixes":{"":{"product":984}}}, // [CyberAgent d/b/a GameLogic] - {"hash":"4e2334aabf3b7af7","prefixes":{"":{"product":984}}}, // [CyberAgent d/b/a GameLogic] - {"hash":"1bbabf05900a894f","prefixes":{"":{"product":984}}}, // [CyberAgent d/b/a GameLogic] - {"hash":"a45a66788779b9bc","prefixes":{"":{"product":984}}}, // [CyberAgent d/b/a GameLogic] - {"hash":"c4d101005526e2ef","prefixes":{"":{"product":984}}}, // [CyberAgent d/b/a GameLogic] - {"hash":"7f43400e381d40ff","prefixes":{"":{"product":984}}}, // [CyberAgent d/b/a GameLogic] - {"hash":"e323697c02e1a841","prefixes":{"":{"product":986}}}, // [CyberAgent d/b/a Dynalyst] - {"hash":"11c505e6e21eefdb","prefixes":{"":{"product":986}}}, // [CyberAgent d/b/a Dynalyst] - {"hash":"afc246433e1284d8","prefixes":{"":{"product":986}}}, // [CyberAgent d/b/a Dynalyst] - {"hash":"c7322cd1ad0df953","prefixes":{"":{"product":986}}}, // [CyberAgent d/b/a Dynalyst] - {"hash":"a090f61c3ee5e028","prefixes":{"":{"product":986}}}, // [CyberAgent d/b/a Dynalyst] + {"hash":"19459fb447ce4de4","prefixes":{"*":{"product":981,"type":0}}}, // [Thirdpresence Ltd] + {"hash":"f079f0a998c56593","prefixes":{"":{"product":981,"type":0}}}, // [Thirdpresence Ltd] + {"hash":"108dd21ceba53008","prefixes":{"":{"product":982,"type":1}}}, // [Visual IQ, Inc.] + {"hash":"7b0dec2d8c1ec967","prefixes":{"":{"product":982,"type":1}}}, // [Visual IQ, Inc.] + {"hash":"b5c3f2f3c1c37850","prefixes":{"":{"product":982,"type":1}}}, // [Visual IQ, Inc.] + {"hash":"ba9b4eca15987843","prefixes":{"":{"product":982,"type":1}}}, // [Visual IQ, Inc.] + {"hash":"4e521b3e57d76700","prefixes":{"":{"product":982,"type":1}}}, // [Visual IQ, Inc.] + {"hash":"29ab2715e00761b0","prefixes":{"":{"product":982,"type":1}}}, // [Visual IQ, Inc.] + {"hash":"688071d177180274","prefixes":{"":{"product":982,"type":1}}}, // [Visual IQ, Inc.] + {"hash":"4e682c7f7f2ebda9","prefixes":{"":{"product":983,"type":0}}}, // [Appreciate] + {"hash":"4b6451297bd74247","prefixes":{"":{"product":983,"type":0}}}, // [Appreciate] + {"hash":"95d75ced1262ecda","prefixes":{"":{"product":983,"type":0}}}, // [Appreciate] + {"hash":"ac94d70ffcad5c63","prefixes":{"":{"product":983,"type":0}}}, // [Appreciate] + {"hash":"578591a9eb9652f2","prefixes":{"":{"product":983,"type":0}}}, // [Appreciate] + {"hash":"5528666c72c7c71c","prefixes":{"":{"product":983,"type":0}}}, // [Appreciate] + {"hash":"3deb1cd39233765c","prefixes":{"":{"product":983,"type":0}}}, // [Appreciate] + {"hash":"4e05303df9f07532","prefixes":{"":{"product":983,"type":0}}}, // [Appreciate] + {"hash":"99936e7e455c77b7","prefixes":{"":{"product":983,"type":0}}}, // [Appreciate] + {"hash":"f0e5986dc65416fd","prefixes":{"":{"product":983,"type":0}}}, // [Appreciate] + {"hash":"5095285a4ab05444","prefixes":{"":{"product":983,"type":0}}}, // [Appreciate] + {"hash":"670fdb8ea86ee233","prefixes":{"":{"product":983,"type":0}}}, // [Appreciate] + {"hash":"ad2de628bc6fd483","prefixes":{"":{"product":984,"type":0},"lodeo-":{"product":985}}}, // [CyberAgent d/b/a GameLogic] [Lodeo] + {"hash":"66e26f9703f2dd67","prefixes":{"":{"product":984,"type":0}}}, // [CyberAgent d/b/a GameLogic] + {"hash":"80451e302607b653","prefixes":{"":{"product":984,"type":0}}}, // [CyberAgent d/b/a GameLogic] + {"hash":"bb7f7e8ab7b99724","prefixes":{"":{"product":984,"type":0}}}, // [CyberAgent d/b/a GameLogic] + {"hash":"51dbfc01b5f86601","prefixes":{"":{"product":984,"type":0}}}, // [CyberAgent d/b/a GameLogic] + {"hash":"2a8926ec16272a9b","prefixes":{"":{"product":984,"type":0}}}, // [CyberAgent d/b/a GameLogic] + {"hash":"4e2334aabf3b7af7","prefixes":{"":{"product":984,"type":0}}}, // [CyberAgent d/b/a GameLogic] + {"hash":"1bbabf05900a894f","prefixes":{"":{"product":984,"type":0}}}, // [CyberAgent d/b/a GameLogic] + {"hash":"a45a66788779b9bc","prefixes":{"":{"product":984,"type":0}}}, // [CyberAgent d/b/a GameLogic] + {"hash":"c4d101005526e2ef","prefixes":{"":{"product":984,"type":0}}}, // [CyberAgent d/b/a GameLogic] + {"hash":"7f43400e381d40ff","prefixes":{"":{"product":984,"type":0}}}, // [CyberAgent d/b/a GameLogic] + {"hash":"e323697c02e1a841","prefixes":{"":{"product":986,"type":0}}}, // [CyberAgent d/b/a Dynalyst] + {"hash":"11c505e6e21eefdb","prefixes":{"":{"product":986,"type":0}}}, // [CyberAgent d/b/a Dynalyst] + {"hash":"afc246433e1284d8","prefixes":{"":{"product":986,"type":0}}}, // [CyberAgent d/b/a Dynalyst] + {"hash":"c7322cd1ad0df953","prefixes":{"":{"product":986,"type":0}}}, // [CyberAgent d/b/a Dynalyst] + {"hash":"a090f61c3ee5e028","prefixes":{"":{"product":986,"type":0}}}, // [CyberAgent d/b/a Dynalyst] {"hash":"846ea0c461560421","prefixes":{"":{"product":985}}}, // [Lodeo] - {"hash":"b433db4fe5f6ed8d","prefixes":{"":{"product":987}}}, // [LTD "RTB-MEDIA"] - {"hash":"e5b814009c134495","prefixes":{"":{"product":987}}}, // [LTD "RTB-MEDIA"] - {"hash":"ce6b2c64ce23d14b","prefixes":{"":{"product":988}}}, // [Maverick., inc.] - {"hash":"32ef8d9c49285e19","prefixes":{"":{"product":988}}}, // [Maverick., inc.] - {"hash":"ac99e3b588f1d521","prefixes":{"":{"product":989}}}, // [FuelX] - {"hash":"da9e2cf59b85610c","prefixes":{"":{"product":989}}}, // [FuelX] - {"hash":"d86ff177f1095173","prefixes":{"":{"product":989}}}, // [FuelX] - {"hash":"7853aedd1a267ffb","prefixes":{"":{"product":989}}}, // [FuelX] - {"hash":"5f505217689c7174","prefixes":{"":{"product":989}}}, // [FuelX] - {"hash":"27be294cbea039f9","prefixes":{"":{"product":989}}}, // [FuelX] + {"hash":"b433db4fe5f6ed8d","prefixes":{"":{"product":987,"type":1}}}, // [LTD "RTB-MEDIA"] + {"hash":"e5b814009c134495","prefixes":{"":{"product":987,"type":1}}}, // [LTD "RTB-MEDIA"] + {"hash":"ce6b2c64ce23d14b","prefixes":{"":{"product":988,"type":0}}}, // [Maverick., inc.] + {"hash":"32ef8d9c49285e19","prefixes":{"":{"product":988,"type":0}}}, // [Maverick., inc.] + {"hash":"ac99e3b588f1d521","prefixes":{"":{"product":989,"type":0}}}, // [FuelX] + {"hash":"da9e2cf59b85610c","prefixes":{"":{"product":989,"type":0}}}, // [FuelX] + {"hash":"d86ff177f1095173","prefixes":{"":{"product":989,"type":0}}}, // [FuelX] + {"hash":"7853aedd1a267ffb","prefixes":{"":{"product":989,"type":0}}}, // [FuelX] + {"hash":"5f505217689c7174","prefixes":{"":{"product":989,"type":0}}}, // [FuelX] + {"hash":"27be294cbea039f9","prefixes":{"":{"product":989,"type":0}}}, // [FuelX] {"hash":"bae6c7f50fff772d","prefixes":{"":{"product":989}}}, // [FuelX] - {"hash":"63f51428712678ec","prefixes":{"":{"product":324}}}, // [Telstra Corporation] - {"hash":"f1d920cc5a16b3a9","prefixes":{"":{"product":986}}}, // [CyberAgent d/b/a Dynalyst] - {"hash":"12a7d7495eb7a91f","prefixes":{"":{"product":986}}}, // [CyberAgent d/b/a Dynalyst] - {"hash":"6ca28320c4765235","prefixes":{"":{"product":986}}}, // [CyberAgent d/b/a Dynalyst] - {"hash":"aeb171f5cad96320","prefixes":{"":{"product":990}}}, // [Tutor.com] - {"hash":"5de1c09366f03919","prefixes":{"":{"product":164}}}, // [wayStorm Co., Ltd.] - {"hash":"9977349a2c52c1b6","prefixes":{"":{"product":164}}}, // [wayStorm Co., Ltd.] - {"hash":"3304d732f88c9ebe","prefixes":{"":{"product":164}}}, // [wayStorm Co., Ltd.] - {"hash":"8b1b0e966a643448","prefixes":{"":{"product":164}}}, // [wayStorm Co., Ltd.] - {"hash":"852a445ec03b1224","prefixes":{"":{"product":991}}}, // [Rebelmouse] - {"hash":"ebef84a02e75b037","prefixes":{"*":{"product":991}}}, // [Rebelmouse] - {"hash":"6ff0ad7b4d4ee2ef","prefixes":{"":{"product":992}}}, // [Adviator DSP] - {"hash":"c28458e1bac3bb75","prefixes":{"":{"product":992}}}, // [Adviator DSP] - {"hash":"041403702e0ae9f0","prefixes":{"":{"product":992}}}, // [Adviator DSP] - {"hash":"31890d74ba2e0eca","prefixes":{"":{"product":525}}}, // [abilicom GmbH] + {"hash":"63f51428712678ec","prefixes":{"":{"product":324,"type":1}}}, // [Telstra Corporation] + {"hash":"f1d920cc5a16b3a9","prefixes":{"":{"product":986,"type":0}}}, // [CyberAgent d/b/a Dynalyst] + {"hash":"12a7d7495eb7a91f","prefixes":{"":{"product":986,"type":0}}}, // [CyberAgent d/b/a Dynalyst] + {"hash":"6ca28320c4765235","prefixes":{"":{"product":986,"type":0}}}, // [CyberAgent d/b/a Dynalyst] + {"hash":"aeb171f5cad96320","prefixes":{"":{"product":990,"type":0}}}, // [Tutor.com] + {"hash":"5de1c09366f03919","prefixes":{"":{"product":164,"type":0}}}, // [wayStorm Co., Ltd.] + {"hash":"9977349a2c52c1b6","prefixes":{"":{"product":164,"type":0}}}, // [wayStorm Co., Ltd.] + {"hash":"3304d732f88c9ebe","prefixes":{"":{"product":164,"type":0}}}, // [wayStorm Co., Ltd.] + {"hash":"8b1b0e966a643448","prefixes":{"":{"product":164,"type":0}}}, // [wayStorm Co., Ltd.] + {"hash":"852a445ec03b1224","prefixes":{"":{"product":991,"type":0}}}, // [Rebelmouse] + {"hash":"ebef84a02e75b037","prefixes":{"*":{"product":991,"type":0}}}, // [Rebelmouse] + {"hash":"6ff0ad7b4d4ee2ef","prefixes":{"":{"product":992,"type":0}}}, // [Adviator DSP] + {"hash":"c28458e1bac3bb75","prefixes":{"":{"product":992,"type":0}}}, // [Adviator DSP] + {"hash":"041403702e0ae9f0","prefixes":{"":{"product":992,"type":0}}}, // [Adviator DSP] + {"hash":"31890d74ba2e0eca","prefixes":{"":{"product":525,"type":0}}}, // [abilicom GmbH] {"hash":"16f2a07aea3c767b","prefixes":{"":{"product":993}}}, // [Acens Technologies, S.L.] - {"hash":"4d628548402f2933","prefixes":{"":{"product":994}}}, // [Yashi, Inc] - {"hash":"6f97eb7dc578c1d3","prefixes":{"":{"product":677}}}, // [Taptica] - {"hash":"843cc26d64f855e3","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"7f81eef44c27fceb","prefixes":{"":{"product":495}}}, // [Miaozhen Systems] - {"hash":"f36b5e4d896bf9fc","prefixes":{"":{"product":995}}}, // [Flaminem Inc] - {"hash":"ec10935d7141abb2","prefixes":{"":{"product":996}}}, // [Mediahead AG] - {"hash":"d074e5017286d25a","prefixes":{"":{"product":996}}}, // [Mediahead AG] - {"hash":"e7aa39274c05edf9","prefixes":{"":{"product":996}}}, // [Mediahead AG] - {"hash":"06d3dae2f13a3dcb","prefixes":{"":{"product":996}}}, // [Mediahead AG] - {"hash":"1cc1098f16d364e0","prefixes":{"":{"product":996}}}, // [Mediahead AG] - {"hash":"15ee5953d4c74d48","prefixes":{"":{"product":996}}}, // [Mediahead AG] - {"hash":"b434b094029a84a8","prefixes":{"":{"product":997}}}, // [Admixer] - {"hash":"766b3c24fb448820","prefixes":{"":{"product":998}}}, // [Communication Services Tele2 GmbH] - {"hash":"35e369c14d37cb1c","prefixes":{"*":{"product":999}}}, // [99click] - {"hash":"c5b7e1faef274865","prefixes":{"":{"product":1000}}}, // [Ströer Mobile Media GmbH] - {"hash":"dc01aead4f784e4d","prefixes":{"":{"product":1000}}}, // [Ströer Mobile Media GmbH] - {"hash":"39525c5c19a8a044","prefixes":{"":{"product":1000}}}, // [Ströer Mobile Media GmbH] - {"hash":"397c77c97b7945f8","prefixes":{"":{"product":1000}}}, // [Ströer Mobile Media GmbH] - {"hash":"3097a79ab689b320","prefixes":{"":{"product":1000}}}, // [Ströer Mobile Media GmbH] - {"hash":"c27b66085df0c0da","prefixes":{"":{"product":1001}}}, // [LLC "Life Style"] - {"hash":"3a7913ff0ce0cc21","prefixes":{"":{"product":1001}}}, // [LLC "Life Style"] - {"hash":"9d1661dae6ff9304","prefixes":{"":{"product":1001}}}, // [LLC "Life Style"] - {"hash":"cdd266d878d3e9d5","prefixes":{"":{"product":1001}}}, // [LLC "Life Style"] - {"hash":"d3c08bf02865217e","prefixes":{"":{"product":1002}}}, // [2Y Media SAS (adserverpub)] - {"hash":"bbfe70399cd3fcb3","prefixes":{"":{"product":1002}}}, // [2Y Media SAS (adserverpub)] - {"hash":"a17b33aa94234849","prefixes":{"":{"product":1002}}}, // [2Y Media SAS (adserverpub)] - {"hash":"8e073ea44074ec93","prefixes":{"":{"product":1002}}}, // [2Y Media SAS (adserverpub)] - {"hash":"12afa442e09a07c9","prefixes":{"":{"product":1002}}}, // [2Y Media SAS (adserverpub)] - {"hash":"7fa5ca05a3a0b474","prefixes":{"":{"product":1003}}}, // [Platform IQ] - {"hash":"f6f0f65947909d69","prefixes":{"":{"product":1003}}}, // [Platform IQ] - {"hash":"77b586602e5dec3f","prefixes":{"":{"product":1003}}}, // [Platform IQ] - {"hash":"bba327f348a4693e","prefixes":{"":{"product":1003}}}, // [Platform IQ] - {"hash":"a544a3b25c4d5113","prefixes":{"":{"product":1004}}}, // [Silveredge Inc] - {"hash":"037cb4c9598870ee","prefixes":{"":{"product":1004}}}, // [Silveredge Inc] - {"hash":"2a6ed7c1b6a78509","prefixes":{"":{"product":1004}}}, // [Silveredge Inc] - {"hash":"06d23751a7963710","prefixes":{"":{"product":1005}}}, // [SMADEX] - {"hash":"0a84ed2865a74b8a","prefixes":{"":{"product":1005}}}, // [SMADEX] - {"hash":"e97a828dc740d645","prefixes":{"":{"product":1005}}}, // [SMADEX] - {"hash":"aa964a10a9ccda5b","prefixes":{"":{"product":1005}}}, // [SMADEX] - {"hash":"d7675b344c153db3","prefixes":{"":{"product":1005}}}, // [SMADEX] - {"hash":"76eaf06fcd95e8e8","prefixes":{"":{"product":1006}}}, // [Suzu Muchi] - {"hash":"fcf26d7eec95d72d","prefixes":{"":{"product":342}}}, // [LOKA Research inc.] - {"hash":"3b238a232cbc26bd","prefixes":{"":{"product":342}}}, // [LOKA Research inc.] - {"hash":"a544c76e7ec01862","prefixes":{"":{"product":342}}}, // [LOKA Research inc.] - {"hash":"7922cb2f11972c85","prefixes":{"":{"product":342}}}, // [LOKA Research inc.] - {"hash":"613551ec99bec944","prefixes":{"":{"product":1007}}}, // [PlannTo Technologies Private Limited] - {"hash":"bb07eb5de3d95038","prefixes":{"":{"product":1007}}}, // [PlannTo Technologies Private Limited] - {"hash":"729165b2ebbc6996","prefixes":{"":{"product":1007}}}, // [PlannTo Technologies Private Limited] - {"hash":"187629571e0338cf","prefixes":{"":{"product":1007}}}, // [PlannTo Technologies Private Limited] - {"hash":"bdd2e20221d7e507","prefixes":{"":{"product":1008}}}, // [Viator, Inc] - {"hash":"1caf0cb7a05c5941","prefixes":{"":{"product":474}}}, // [Xrost] - {"hash":"4c6513300966da08","prefixes":{"":{"product":1009}}}, // [NODDINGTON TECHNOLOGIES LIMITED] - {"hash":"2c1d6a203788af2b","prefixes":{"":{"product":1010}}}, // [Plan Blue Ltd] - {"hash":"3c0da2d4356e18a5","prefixes":{"":{"product":1010}}}, // [Plan Blue Ltd] - {"hash":"2568d0917d238964","prefixes":{"":{"product":1011}}}, // [Addictive Mobility] - {"hash":"f79c822ab2cca8ee","prefixes":{"":{"product":1011}}}, // [Addictive Mobility] - {"hash":"c610b5ae3df923cd","prefixes":{"":{"product":1011}}}, // [Addictive Mobility] - {"hash":"a614ab43bf2d906b","prefixes":{"":{"product":1011}}}, // [Addictive Mobility] - {"hash":"747eeca86822f19c","prefixes":{"":{"product":1012}}}, // [A6 Corporation] - {"hash":"cbdfdaeff8b7d933","prefixes":{"":{"product":1013}}}, // [Mobusi Mobile Advertising] - {"hash":"5b2d082c7811bead","prefixes":{"":{"product":1014}}}, // [Wishabi] - {"hash":"c811726b56670631","prefixes":{"":{"product":1014}}}, // [Wishabi] - {"hash":"09d3b27d380d43a0","prefixes":{"":{"product":1014}}}, // [Wishabi] - {"hash":"eecab68f555d1f9f","prefixes":{"":{"product":1015}}}, // [onAd GmbH] - {"hash":"d05b20f38e3bb984","prefixes":{"":{"product":1016}}}, // [Media Decision GmbH] - {"hash":"4a9b8dddd4c7567c","prefixes":{"":{"product":1016}}}, // [Media Decision GmbH] - {"hash":"5121142c1b8676fd","prefixes":{"":{"product":1016}}}, // [Media Decision GmbH] - {"hash":"e083b93d5a87c743","prefixes":{"":{"product":1017}}}, // [Unitymedia NRW] - {"hash":"c665046a783daa9d","prefixes":{"":{"product":1018}}}, // [Nowspots INC, dba Perfect Audience] - {"hash":"663d5fdbc3a52729","prefixes":{"":{"product":1018}}}, // [Nowspots INC, dba Perfect Audience] - {"hash":"991e96310871571b","prefixes":{"":{"product":1018}}}, // [Nowspots INC, dba Perfect Audience] - {"hash":"0503d775704af4a2","prefixes":{"":{"product":1018}}}, // [Nowspots INC, dba Perfect Audience] - {"hash":"2c55a4ef41531200","prefixes":{"":{"product":1019}}}, // [Avis] - {"hash":"62817a7d196cbdcf","prefixes":{"":{"product":1020}}}, // [Comcast] - {"hash":"2e4bb1f4d07f3180","prefixes":{"":{"product":1021}}}, // [Jack Spade] - {"hash":"e7d369c24971784a","prefixes":{"":{"product":1022}}}, // [Dollar General] - {"hash":"a8c9b93aae571ed5","prefixes":{"":{"product":1023}}}, // [Care.com] - {"hash":"713775b7bc737116","prefixes":{"":{"product":1024}}}, // [Clickagy, LLC] - {"hash":"8b6b45c1c86cd84b","prefixes":{"":{"product":1024}}}, // [Clickagy, LLC] - {"hash":"34376185507c9ae0","prefixes":{"":{"product":1025}}}, // [GlobalWebIndex] - {"hash":"8b17254892b590e3","prefixes":{"":{"product":1026}}}, // [King.com] - {"hash":"8516f044f19bb3ae","prefixes":{"":{"product":1026}}}, // [King.com] - {"hash":"d811179454fad251","prefixes":{"":{"product":1026}}}, // [King.com] - {"hash":"946611fa2f4b067a","prefixes":{"":{"product":1027}}}, // [Proquire LLC - Accenture] - {"hash":"cfa0e9025fcd5712","prefixes":{"":{"product":1028}}}, // [Dynamic Yield] - {"hash":"b01c0239af74e72e","prefixes":{"":{"product":1028}}}, // [Dynamic Yield] - {"hash":"e480d03a980d3bfc","prefixes":{"":{"product":1028}}}, // [Dynamic Yield] - {"hash":"f22fe7e17c58b562","prefixes":{"":{"product":1028}}}, // [Dynamic Yield] - {"hash":"f8da77c2fdcad106","prefixes":{"":{"product":1028}}}, // [Dynamic Yield] - {"hash":"cea3bf4afe576984","prefixes":{"":{"product":1029}}}, // [Charter business] - {"hash":"f8029c009186163f","prefixes":{"":{"product":1030}}}, // [The ADEX] - {"hash":"61b09f5d40722e69","prefixes":{"":{"product":1031}}}, // [OneDigitalAd Technologies] - {"hash":"aa63151485efa109","prefixes":{"":{"product":1031}}}, // [OneDigitalAd Technologies] - {"hash":"ed37e98f45f10404","prefixes":{"":{"product":1031}}}, // [OneDigitalAd Technologies] - {"hash":"f9fda879239cf155","prefixes":{"":{"product":1031}}}, // [OneDigitalAd Technologies] - {"hash":"2dfe9124b3439d80","prefixes":{"":{"product":1031}}}, // [OneDigitalAd Technologies] - {"hash":"93a9e29ac238b380","prefixes":{"":{"product":1031}}}, // [OneDigitalAd Technologies] - {"hash":"5e080b13877f5de7","prefixes":{"":{"product":1031}}}, // [OneDigitalAd Technologies] - {"hash":"eb22d59d4594e6d3","prefixes":{"":{"product":1031}}}, // [OneDigitalAd Technologies] - {"hash":"a28e072f804db6a0","prefixes":{"":{"product":1031}}}, // [OneDigitalAd Technologies] - {"hash":"945f948eacea62c9","prefixes":{"":{"product":1031}}}, // [OneDigitalAd Technologies] - {"hash":"b85074a47da33b83","prefixes":{"":{"product":1032}}}, // [ADJUST] - {"hash":"9f369deb4f045364","prefixes":{"":{"product":1032}}}, // [ADJUST] - {"hash":"2d6ceeb3eef38c27","prefixes":{"":{"product":1032}}}, // [ADJUST] - {"hash":"65240dfe37410021","prefixes":{"":{"product":1032}}}, // [ADJUST] - {"hash":"8d3dfcbf705f1191","prefixes":{"":{"product":1032}}}, // [ADJUST] - {"hash":"a2d35afc9c960448","prefixes":{"":{"product":1033}}}, // [ADmantX, SPA] - {"hash":"3d3bc7f00b0ef8d3","prefixes":{"":{"product":1034}}}, // [Sogou.com] - {"hash":"9eb0737a130a6f08","prefixes":{"":{"product":1035}}}, // [xAd, Inc.] - {"hash":"a9ff22250a3c29a1","prefixes":{"":{"product":1036}}}, // [VideoBlocks] - {"hash":"61f27a00f3821730","prefixes":{"":{"product":1037}}}, // [GraphicStocks] - {"hash":"f0792974945e7184","prefixes":{"":{"product":1038}}}, // [Microsoft Advertising] - {"hash":"81f27cb33d47894b","prefixes":{"":{"product":1039}}}, // [Rontar LTD] - {"hash":"e8ae13fee2796336","prefixes":{"":{"product":1039}}}, // [Rontar LTD] - {"hash":"d979ed3048a9dc3d","prefixes":{"":{"product":1039}}}, // [Rontar LTD] - {"hash":"187c7e948b323b3a","prefixes":{"dsp":{"product":1039}}}, // [Rontar LTD] - {"hash":"1a5cfb3f08b31682","prefixes":{"":{"product":1040}}}, // [Torrential, Inc.] - {"hash":"99bb29582234b47b","prefixes":{"":{"product":1041}}}, // [AMoAd, Inc.] - {"hash":"14a0b2d821feb403","prefixes":{"":{"product":1041}}}, // [AMoAd, Inc.] - {"hash":"4bfb576f457b3ad4","prefixes":{"":{"product":1041}}}, // [AMoAd, Inc.] - {"hash":"d2e32e6a4c73344a","prefixes":{"":{"product":1041}}}, // [AMoAd, Inc.] - {"hash":"3c8aa320c0f5fb9d","prefixes":{"":{"product":1041}}}, // [AMoAd, Inc.] - {"hash":"8c3cae9472fcd43a","prefixes":{"":{"product":1041}}}, // [AMoAd, Inc.] - {"hash":"18d673cc147eaba5","prefixes":{"":{"product":1041}}}, // [AMoAd, Inc.] - {"hash":"fb4f3dd591cba22f","prefixes":{"bid":{"product":1041}}}, // [AMoAd, Inc.] - {"hash":"49aef0b488ab5024","prefixes":{"":{"product":1041}}}, // [AMoAd, Inc.] - {"hash":"2b7a17458f44228d","prefixes":{"":{"product":1041}}}, // [AMoAd, Inc.] - {"hash":"7458cceedc9f812a","prefixes":{"":{"product":1042}}}, // [Tukmob Information Technology(Shanghai)Co. Ltd] - {"hash":"dd47f178c7a055b8","prefixes":{"":{"product":1042}}}, // [Tukmob Information Technology(Shanghai)Co. Ltd] - {"hash":"db975b73da86c8ce","prefixes":{"":{"product":1042}}}, // [Tukmob Information Technology(Shanghai)Co. Ltd] - {"hash":"6216946891299e23","prefixes":{"":{"product":1042}}}, // [Tukmob Information Technology(Shanghai)Co. Ltd] - {"hash":"52ee7c22862a74b6","prefixes":{"":{"product":1042}}}, // [Tukmob Information Technology(Shanghai)Co. Ltd] - {"hash":"3cc39e801c92ea89","prefixes":{"":{"product":1043}}}, // [Jampp/Devego S.A.] - {"hash":"31fb8bdf6d2b85d2","prefixes":{"":{"product":1044}}}, // [Placed] - {"hash":"a6ff57032773fe41","prefixes":{"*":{"product":1045}}}, // [Digitas Health] - {"hash":"caeb7a071a866e17","prefixes":{"*":{"product":1045}}}, // [Digitas Health] - {"hash":"6e946f5fac72b0b4","prefixes":{"":{"product":1046}}}, // [Answer Media, LLC] - {"hash":"31c3d7ef1499fd26","prefixes":{"":{"product":1046}}}, // [Answer Media, LLC] - {"hash":"d681f06391c7f861","prefixes":{"":{"product":1047}}}, // [1000mercis] - {"hash":"1549387212aaa6a3","prefixes":{"":{"product":1048}}}, // [Upstart Network, Inc.] - {"hash":"e48f63d27d0c24c7","prefixes":{"":{"product":1049}}}, // [Forensiq, LLC] - {"hash":"7579b1341b228f93","prefixes":{"":{"product":1049}}}, // [Forensiq, LLC] - {"hash":"f2e570ecd2540399","prefixes":{"":{"product":1050}}}, // [LoopMe Ltd] - {"hash":"7d4e3b90001a044e","prefixes":{"":{"product":1050}}}, // [LoopMe Ltd] - {"hash":"528167a286d8ccf8","prefixes":{"":{"product":1051}}}, // [Bannerlink (Liquidus)] - {"hash":"0b2d528c0dce5bba","prefixes":{"":{"product":1051}}}, // [Bannerlink (Liquidus)] - {"hash":"758cc459053712cf","prefixes":{"":{"product":1051}}}, // [Bannerlink (Liquidus)] - {"hash":"57951d4b34add1a9","prefixes":{"":{"product":1051}}}, // [Bannerlink (Liquidus)] - {"hash":"3d93ddd2b1dc8083","prefixes":{"":{"product":1051}}}, // [Bannerlink (Liquidus)] - {"hash":"88f0b992c4b99c65","prefixes":{"":{"product":1052}}}, // [Dell Inc.] - {"hash":"f8820430b42f89f8","prefixes":{"":{"product":1053}}}, // [My Perfect Resume] - {"hash":"6f018db6d7a12f5e","prefixes":{"":{"product":1054}}}, // [Ajillion Max Ltd] - {"hash":"b591ab0baccecd52","prefixes":{"":{"product":1054}}}, // [Ajillion Max Ltd] - {"hash":"35d86d0121dbd41a","prefixes":{"":{"product":1055}}}, // [Swelen France SA.] - {"hash":"25b09dd0e8d2977a","prefixes":{"":{"product":1055}}}, // [Swelen France SA.] - {"hash":"f5cb853eba61193a","prefixes":{"":{"product":1056}}}, // [Sleeptrain] - {"hash":"c620109c65610aeb","prefixes":{"":{"product":1057}}}, // [Sleepcountry] - {"hash":"9c6554ebebdbfa08","prefixes":{"":{"product":1058}}}, // [Hoover] - {"hash":"f34ddb2b65330794","prefixes":{"":{"product":1059}}}, // [Bidtellect] - {"hash":"5d9eb2a8dc1a1687","prefixes":{"":{"product":1059}}}, // [Bidtellect] - {"hash":"e2207dc37f1b89e8","prefixes":{"":{"product":1059}}}, // [Bidtellect] - {"hash":"682ec1b47db930b9","prefixes":{"":{"product":1059}}}, // [Bidtellect] - {"hash":"638a2c2dc53d2ab7","prefixes":{"":{"product":1060}}}, // [Mocoplex Inc.] - {"hash":"ee330ed89897a55c","prefixes":{"":{"product":1060}}}, // [Mocoplex Inc.] - {"hash":"60ab035f28a35e30","prefixes":{"":{"product":1060}}}, // [Mocoplex Inc.] - {"hash":"5929f2c289d9e073","prefixes":{"":{"product":778}}}, // [Gruvi Ltd.] - {"hash":"c16c02248018a374","prefixes":{"":{"product":778}}}, // [Gruvi Ltd.] - {"hash":"e6eb2d1c03d2be83","prefixes":{"":{"product":778}}}, // [Gruvi Ltd.] - {"hash":"95fa4396cadc336e","prefixes":{"":{"product":778}}}, // [Gruvi Ltd.] - {"hash":"2604a7d96f168c84","prefixes":{"":{"product":1061}}}, // [Brightsparc Technologies Pty Ltd trading as Native] - {"hash":"294fdebfd41771a8","prefixes":{"":{"product":1061}}}, // [Brightsparc Technologies Pty Ltd trading as Native] - {"hash":"c6beb451fe4c58c2","prefixes":{"":{"product":1061}}}, // [Brightsparc Technologies Pty Ltd trading as Native] - {"hash":"b0f5f51210e6f2af","prefixes":{"":{"product":1061}}}, // [Brightsparc Technologies Pty Ltd trading as Native] - {"hash":"ab3da2eb1a35cba6","prefixes":{"":{"product":1062}}}, // [Verengo Solar] - {"hash":"c3bf5a10743772ec","prefixes":{"*":{"product":1063}}}, // [Mobile Professionals BV] - {"hash":"d22325b6d6b04918","prefixes":{"*":{"product":1064}}}, // [APNIC Pty Ltd] - {"hash":"27966131215e508a","prefixes":{"*":{"product":1064}}}, // [APNIC Pty Ltd] - {"hash":"80022b9d8ddaffde","prefixes":{"*":{"product":1064}}}, // [APNIC Pty Ltd] - {"hash":"9352d77ba286c03d","prefixes":{"":{"product":1065}}}, // [Dun and Bradstreet Corporation] - {"hash":"74b7ef01f42d93ee","prefixes":{"":{"product":1066}}}, // [UpToLike] - {"hash":"f2a78bb802dc4abd","prefixes":{"":{"product":1066}}}, // [UpToLike] - {"hash":"f885798eaaace647","prefixes":{"":{"product":1067}}}, // [Mobile360 Sdn Bhd] - {"hash":"3bc813f113908f06","prefixes":{"":{"product":1067}}}, // [Mobile360 Sdn Bhd] - {"hash":"e1a6852c86da418c","prefixes":{"":{"product":1067}}}, // [Mobile360 Sdn Bhd] - {"hash":"0343b65d010db4b2","prefixes":{"":{"product":1067}}}, // [Mobile360 Sdn Bhd] - {"hash":"a9b74e1bcb339dd0","prefixes":{"":{"product":1067}}}, // [Mobile360 Sdn Bhd] - {"hash":"e8d325d7be0f046b","prefixes":{"*":{"product":1067}}}, // [Mobile360 Sdn Bhd] - {"hash":"f7ccb1753b9ae2ed","prefixes":{"":{"product":1067}}}, // [Mobile360 Sdn Bhd] - {"hash":"4a96db729cb9dd47","prefixes":{"":{"product":1067}}}, // [Mobile360 Sdn Bhd] - {"hash":"afde8c2ebcc380c8","prefixes":{"":{"product":1067}}}, // [Mobile360 Sdn Bhd] - {"hash":"05840eb3ff4432a8","prefixes":{"":{"product":1067}}}, // [Mobile360 Sdn Bhd] - {"hash":"3e5f0f83b0e34391","prefixes":{"":{"product":1067}}}, // [Mobile360 Sdn Bhd] - {"hash":"f79fe1474c475ade","prefixes":{"":{"product":1068}}}, // [Elite Fixtures] - {"hash":"b8b63e29130d798a","prefixes":{"":{"product":1069}}}, // [Advanse Ads] - {"hash":"662442a875d5ae62","prefixes":{"":{"product":1069}}}, // [Advanse Ads] - {"hash":"d8487e4c88a21c7f","prefixes":{"":{"product":1069}}}, // [Advanse Ads] - {"hash":"37694729baf29aa5","prefixes":{"":{"product":1070}}}, // [Insurance Step] - {"hash":"0153c16587a0c97c","prefixes":{"":{"product":1071}}}, // [Causal Impact] - {"hash":"c7bcca7e8dc820fe","prefixes":{"":{"product":1071}}}, // [Causal Impact] - {"hash":"2176b8c755bbab42","prefixes":{"":{"product":1071}}}, // [Causal Impact] - {"hash":"1979b33f68eb0ded","prefixes":{"":{"product":1071}}}, // [Causal Impact] - {"hash":"32a9ea6936225587","prefixes":{"":{"product":1071}}}, // [Causal Impact] - {"hash":"16fec67040bf3ff7","prefixes":{"":{"product":1071}}}, // [Causal Impact] - {"hash":"ed89b325a7c3ac6d","prefixes":{"":{"product":1071}}}, // [Causal Impact] - {"hash":"ae3bc4690ef89e8d","prefixes":{"":{"product":1071}}}, // [Causal Impact] - {"hash":"ed9a2a4f49ad4647","prefixes":{"":{"product":1071}}}, // [Causal Impact] - {"hash":"398d36669a77aca6","prefixes":{"":{"product":1071}}}, // [Causal Impact] - {"hash":"5bf9c0f450f9eb14","prefixes":{"":{"product":1071}}}, // [Causal Impact] - {"hash":"30e7de1e277c7698","prefixes":{"":{"product":145}}}, // [Aarki, Inc.] - {"hash":"888d9446d621d82f","prefixes":{"":{"product":145}}}, // [Aarki, Inc.] - {"hash":"3061a4cd653ea2dc","prefixes":{"*":{"product":1072}}}, // [Pixnet] - {"hash":"06daa5b82ebfa413","prefixes":{"":{"product":1073}}}, // [Zapp360] - {"hash":"6f0f9a90c798715d","prefixes":{"":{"product":1074}}}, // [Kijiji] - {"hash":"0259cba89f8f9676","prefixes":{"":{"product":1075}}}, // [Spotad LTD.] - {"hash":"0ca2babbaeeca3bf","prefixes":{"":{"product":1075}}}, // [Spotad LTD.] - {"hash":"e9a9d4fd1b468042","prefixes":{"":{"product":1075}}}, // [Spotad LTD.] - {"hash":"6a79ac93cddc0cc5","prefixes":{"":{"product":1075}}}, // [Spotad LTD.] - {"hash":"685b17838f2d9b82","prefixes":{"":{"product":1076}}}, // [Go Daddy] - {"hash":"aa66f01be33256d0","prefixes":{"":{"product":1077}}}, // [Bilendi] - {"hash":"3b8dfd79ab921d9b","prefixes":{"":{"product":1078}}}, // [Hitokuse] - {"hash":"1992e397e0dff18d","prefixes":{"":{"product":1078}}}, // [Hitokuse] - {"hash":"03eb230cd9f67c73","prefixes":{"":{"product":1078}}}, // [Hitokuse] - {"hash":"0a75c26f5c580b3a","prefixes":{"*":{"product":1079}}}, // [MGID Inc.] - {"hash":"4466d73d5d5dce19","prefixes":{"*":{"product":1079}}}, // [MGID Inc.] - {"hash":"10bfb2327400e2ea","prefixes":{"":{"product":1079}}}, // [MGID Inc.] - {"hash":"121b77f4b4412c85","prefixes":{"":{"product":1079}}}, // [MGID Inc.] - {"hash":"e46ec8aa62f3f432","prefixes":{"":{"product":1080}}}, // [AreaOne] - {"hash":"9849db4d4a694f16","prefixes":{"t":{"product":1081},"s":{"product":1081},"sna":{"product":1081}}}, // [DynAd] [DynAd] [DynAd] - {"hash":"5fc0aef37d5fffca","prefixes":{"":{"product":1082}}}, // [Loop Pay] - {"hash":"4cc75be32553222a","prefixes":{"":{"product":1083}}}, // [Remerge GmbH] - {"hash":"b1a90d2aaa32932c","prefixes":{"":{"product":1083}}}, // [Remerge GmbH] - {"hash":"3bea81bc90640751","prefixes":{"":{"product":1084}}}, // [Audience Trading Platform LTD] - {"hash":"d193540bb7540e5c","prefixes":{"":{"product":1085}}}, // [Whisla] - {"hash":"abd1c2a37733128b","prefixes":{"":{"product":1085}}}, // [Whisla] - {"hash":"9546fe15199cbce1","prefixes":{"":{"product":1085}}}, // [Whisla] - {"hash":"f43c40d1949f2c52","prefixes":{"":{"product":1086}}}, // [Bridgevine] - {"hash":"28577f7c17c55b0f","prefixes":{"":{"product":1087}}}, // [ADgraph DMP] - {"hash":"fa0c51dc55faddc6","prefixes":{"":{"product":1088}}}, // [Gravity4 Inc.] - {"hash":"6dea119c4c95aaa8","prefixes":{"":{"product":1088}}}, // [Gravity4 Inc.] - {"hash":"79b4752426dedd83","prefixes":{"":{"product":1089}}}, // [Hipmunk] - {"hash":"ccba9f3966eabe6b","prefixes":{"*":{"product":1090}}}, // [VideoHub DSP] - {"hash":"a6baef75f126450e","prefixes":{"":{"product":1091}}}, // [DuMedia] - {"hash":"cf45efd3feda1ba3","prefixes":{"":{"product":1091}}}, // [DuMedia] - {"hash":"efebf8c1ea6bab87","prefixes":{"":{"product":1092}}}, // [F@N Communications, Inc.] - {"hash":"a866ff2bfe3133e7","prefixes":{"":{"product":1092}}}, // [F@N Communications, Inc.] - {"hash":"49b89555382dac9e","prefixes":{"":{"product":1092}}}, // [F@N Communications, Inc.] - {"hash":"e2d2b1537271ff61","prefixes":{"":{"product":1092}}}, // [F@N Communications, Inc.] - {"hash":"5804e7cf2cdbbda0","prefixes":{"":{"product":1092}}}, // [F@N Communications, Inc.] - {"hash":"db0ef2b4eff25274","prefixes":{"":{"product":1092}}}, // [F@N Communications, Inc.] - {"hash":"d960535fd30704f8","prefixes":{"":{"product":1092}}}, // [F@N Communications, Inc.] - {"hash":"258915df4406fd06","prefixes":{"":{"product":1092}}}, // [F@N Communications, Inc.] - {"hash":"b34a1e3fd51aadb9","prefixes":{"":{"product":1092}}}, // [F@N Communications, Inc.] - {"hash":"c0ad7ec6e1d46299","prefixes":{"":{"product":1093}}}, // [VIVALU GmbH] - {"hash":"65c049a517720b5c","prefixes":{"":{"product":1093}}}, // [VIVALU GmbH] - {"hash":"b60b2426028baba5","prefixes":{"":{"product":1094}}}, // [Advertising Technologies LTD] - {"hash":"6d2df95e2bf52046","prefixes":{"":{"product":1094}}}, // [Advertising Technologies LTD] - {"hash":"b4ad6ea6ca336f55","prefixes":{"":{"product":1094}}}, // [Advertising Technologies LTD] - {"hash":"b750311cbd5c4013","prefixes":{"":{"product":1095}}}, // [Authenticated Digital Inc] - {"hash":"aa634a3d8862b3be","prefixes":{"":{"product":1095}}}, // [Authenticated Digital Inc] - {"hash":"361eefdfa29ada10","prefixes":{"":{"product":1096}}}, // [PaeDae, Inc., DBA The Mobile Majority] - {"hash":"8a5c2c8d21fc6dd4","prefixes":{"":{"product":1096}}}, // [PaeDae, Inc., DBA The Mobile Majority] - {"hash":"13b3d2e0ed78e518","prefixes":{"":{"product":1097}}}, // [METROPCS] - {"hash":"c9b29fe277a47b8d","prefixes":{"":{"product":1098}}}, // [PapayaMobile Inc.] - {"hash":"60f32eaa9335e4b9","prefixes":{"":{"product":1098}}}, // [PapayaMobile Inc.] - {"hash":"c8f49035cb273e42","prefixes":{"":{"product":1098}}}, // [PapayaMobile Inc.] - {"hash":"92d9e360f16ecdc9","prefixes":{"":{"product":1098}}}, // [PapayaMobile Inc.] - {"hash":"2d3b5566afb5350b","prefixes":{"":{"product":1098}}}, // [PapayaMobile Inc.] - {"hash":"0ca3b2088de2514c","prefixes":{"":{"product":1098}}}, // [PapayaMobile Inc.] - {"hash":"67da96d5ae99faa0","prefixes":{"":{"product":1098}}}, // [PapayaMobile Inc.] - {"hash":"347e898491d027ee","prefixes":{"":{"product":1099}}}, // [Raumfeld] - {"hash":"ae3f27ad4a4f2f7d","prefixes":{"":{"product":1099}}}, // [Raumfeld] - {"hash":"cd0c8a5dd793ee52","prefixes":{"":{"product":1099}}}, // [Raumfeld] - {"hash":"451f4083f03028e0","prefixes":{"":{"product":1099}}}, // [Raumfeld] - {"hash":"e1b048e4fa37eef2","prefixes":{"":{"product":1099}}}, // [Raumfeld] - {"hash":"837ae92d9cf6b933","prefixes":{"":{"product":1099}}}, // [Raumfeld] - {"hash":"6ae82aac87db94d3","prefixes":{"":{"product":1099}}}, // [Raumfeld] - {"hash":"84ddfa5a2e93cb69","prefixes":{"":{"product":1100}}}, // [GREE Ads DSP] - {"hash":"a7201f5a80824242","prefixes":{"":{"product":1100}}}, // [GREE Ads DSP] - {"hash":"2ec22ca05310362a","prefixes":{"":{"product":1101}}}, // [Tender Industries AB] - {"hash":"d159abbaeda22e7c","prefixes":{"":{"product":1102}}}, // [BySide] - {"hash":"426783d6fe8d039e","prefixes":{"":{"product":1103}}}, // [Sentrant Security Inc.] - {"hash":"d270ad50bb53fb01","prefixes":{"":{"product":1103}}}, // [Sentrant Security Inc.] - {"hash":"49c693058534be83","prefixes":{"":{"product":1104}}}, // [Locon Solutions Pvt. Ltd.] - {"hash":"a2b9f627da8737de","prefixes":{"":{"product":1105}}}, // [Interrogare GmbH] - {"hash":"13b73169540642e5","prefixes":{"":{"product":1105}}}, // [Interrogare GmbH] - {"hash":"afaa106d11846fa4","prefixes":{"*":{"product":1106}}}, // [ChannelAdvisor] - {"hash":"b8b4eadeb5d3a123","prefixes":{"":{"product":1107}}}, // [VideoAmp] - {"hash":"43546e9f6ff5bf2a","prefixes":{"":{"product":1107}}}, // [VideoAmp] - {"hash":"61a9edb9af3769cf","prefixes":{"":{"product":1107}}}, // [VideoAmp] - {"hash":"f76b3fe7048e93e2","prefixes":{"":{"product":1107}}}, // [VideoAmp] - {"hash":"57263424c0e88a92","prefixes":{"track":{"product":1108}}}, // [The Bridge] - {"hash":"516e9fc5ede4af0d","prefixes":{"":{"product":1108}}}, // [The Bridge] - {"hash":"6bc0303a4262cb67","prefixes":{"":{"product":1108}}}, // [The Bridge] - {"hash":"30a32fe2a89dccd8","prefixes":{"":{"product":1109}}}, // [Pharmaca Integrative Pharmacy] - {"hash":"7881da604383a640","prefixes":{"":{"product":673}}}, // [Videology DSP] - {"hash":"dec02c663bb06094","prefixes":{"":{"product":1110}}}, // [Scrutineer] - {"hash":"6e2098af577c671d","prefixes":{"":{"product":1111}}}, // [TF1 - FR] - {"hash":"60774075776e2612","prefixes":{"":{"product":1112}}}, // [Core Digital] - {"hash":"79a775eea6a902e6","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"c0576db5cf4ba20b","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"d90fda985e3fb6bf","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"ee49dcf9326e853f","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"5b3c6abcd44de720","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"f97a320480541a27","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"57fc36302e0bde3c","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"736a8a8a0cef7bdf","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"36263b4a0d607a71","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"226480bf58f4fd1c","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"58379bd623597d70","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"f68e3a544a7397be","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"0f2880d71794e516","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"4ef52741fc1ade73","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"97d6a93635d72af0","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"ab75a46dc8bf2c1e","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"efeb8f966db03b87","prefixes":{"":{"product":110}}}, // [Bonzai Digital Pvt. Ltd] - {"hash":"2a4d804c0fb397c1","prefixes":{"":{"product":1113}}}, // [Adventive, Inc.] - {"hash":"29d370caa59b4ecc","prefixes":{"":{"product":1113}}}, // [Adventive, Inc.] + {"hash":"4d628548402f2933","prefixes":{"":{"product":994,"type":0}}}, // [Yashi, Inc] + {"hash":"6f97eb7dc578c1d3","prefixes":{"":{"product":677,"type":0}}}, // [Taptica] + {"hash":"843cc26d64f855e3","prefixes":{"":{"product":495,"type":0}}}, // [Miaozhen Systems] + {"hash":"7f81eef44c27fceb","prefixes":{"":{"product":495,"type":0}}}, // [Miaozhen Systems] + {"hash":"f36b5e4d896bf9fc","prefixes":{"":{"product":995,"type":0}}}, // [Flaminem Inc] + {"hash":"ec10935d7141abb2","prefixes":{"":{"product":996,"type":0}}}, // [Mediahead AG] + {"hash":"d074e5017286d25a","prefixes":{"":{"product":996,"type":0}}}, // [Mediahead AG] + {"hash":"e7aa39274c05edf9","prefixes":{"":{"product":996,"type":0}}}, // [Mediahead AG] + {"hash":"06d3dae2f13a3dcb","prefixes":{"":{"product":996,"type":0}}}, // [Mediahead AG] + {"hash":"1cc1098f16d364e0","prefixes":{"":{"product":996,"type":0}}}, // [Mediahead AG] + {"hash":"15ee5953d4c74d48","prefixes":{"":{"product":996,"type":0}}}, // [Mediahead AG] + {"hash":"b434b094029a84a8","prefixes":{"":{"product":997,"type":0}}}, // [Admixer] + {"hash":"766b3c24fb448820","prefixes":{"":{"product":998,"type":1}}}, // [Communication Services Tele2 GmbH] + {"hash":"35e369c14d37cb1c","prefixes":{"*":{"product":999,"type":1}}}, // [99click] + {"hash":"c5b7e1faef274865","prefixes":{"":{"product":1000,"type":0}}}, // [Ströer Mobile Media GmbH] + {"hash":"dc01aead4f784e4d","prefixes":{"":{"product":1000,"type":0}}}, // [Ströer Mobile Media GmbH] + {"hash":"39525c5c19a8a044","prefixes":{"":{"product":1000,"type":0}}}, // [Ströer Mobile Media GmbH] + {"hash":"397c77c97b7945f8","prefixes":{"":{"product":1000,"type":0}}}, // [Ströer Mobile Media GmbH] + {"hash":"3097a79ab689b320","prefixes":{"":{"product":1000,"type":0}}}, // [Ströer Mobile Media GmbH] + {"hash":"c27b66085df0c0da","prefixes":{"":{"product":1001,"type":0}}}, // [LLC "Life Style"] + {"hash":"3a7913ff0ce0cc21","prefixes":{"":{"product":1001,"type":0}}}, // [LLC "Life Style"] + {"hash":"9d1661dae6ff9304","prefixes":{"":{"product":1001,"type":0}}}, // [LLC "Life Style"] + {"hash":"cdd266d878d3e9d5","prefixes":{"":{"product":1001,"type":0}}}, // [LLC "Life Style"] + {"hash":"d3c08bf02865217e","prefixes":{"":{"product":1002,"type":0}}}, // [2Y Media SAS (adserverpub)] + {"hash":"bbfe70399cd3fcb3","prefixes":{"":{"product":1002,"type":0}}}, // [2Y Media SAS (adserverpub)] + {"hash":"a17b33aa94234849","prefixes":{"":{"product":1002,"type":0}}}, // [2Y Media SAS (adserverpub)] + {"hash":"8e073ea44074ec93","prefixes":{"":{"product":1002,"type":0}}}, // [2Y Media SAS (adserverpub)] + {"hash":"12afa442e09a07c9","prefixes":{"":{"product":1002,"type":0}}}, // [2Y Media SAS (adserverpub)] + {"hash":"7fa5ca05a3a0b474","prefixes":{"":{"product":1003,"type":0}}}, // [Platform IQ] + {"hash":"f6f0f65947909d69","prefixes":{"":{"product":1003,"type":0}}}, // [Platform IQ] + {"hash":"77b586602e5dec3f","prefixes":{"":{"product":1003,"type":0}}}, // [Platform IQ] + {"hash":"bba327f348a4693e","prefixes":{"":{"product":1003,"type":0}}}, // [Platform IQ] + {"hash":"a544a3b25c4d5113","prefixes":{"":{"product":1004,"type":0}}}, // [Silveredge Inc] + {"hash":"037cb4c9598870ee","prefixes":{"":{"product":1004,"type":0}}}, // [Silveredge Inc] + {"hash":"2a6ed7c1b6a78509","prefixes":{"":{"product":1004,"type":0}}}, // [Silveredge Inc] + {"hash":"06d23751a7963710","prefixes":{"":{"product":1005,"type":0}}}, // [SMADEX] + {"hash":"0a84ed2865a74b8a","prefixes":{"":{"product":1005,"type":0}}}, // [SMADEX] + {"hash":"e97a828dc740d645","prefixes":{"":{"product":1005,"type":0}}}, // [SMADEX] + {"hash":"aa964a10a9ccda5b","prefixes":{"":{"product":1005,"type":0}}}, // [SMADEX] + {"hash":"d7675b344c153db3","prefixes":{"":{"product":1005,"type":0}}}, // [SMADEX] + {"hash":"76eaf06fcd95e8e8","prefixes":{"":{"product":1006,"type":0}}}, // [Suzu Muchi] + {"hash":"fcf26d7eec95d72d","prefixes":{"":{"product":342,"type":0}}}, // [LOKA Research inc.] + {"hash":"3b238a232cbc26bd","prefixes":{"":{"product":342,"type":0}}}, // [LOKA Research inc.] + {"hash":"a544c76e7ec01862","prefixes":{"":{"product":342,"type":0}}}, // [LOKA Research inc.] + {"hash":"7922cb2f11972c85","prefixes":{"":{"product":342,"type":0}}}, // [LOKA Research inc.] + {"hash":"613551ec99bec944","prefixes":{"":{"product":1007,"type":0}}}, // [PlannTo Technologies Private Limited] + {"hash":"bb07eb5de3d95038","prefixes":{"":{"product":1007,"type":0}}}, // [PlannTo Technologies Private Limited] + {"hash":"729165b2ebbc6996","prefixes":{"":{"product":1007,"type":0}}}, // [PlannTo Technologies Private Limited] + {"hash":"187629571e0338cf","prefixes":{"":{"product":1007,"type":0}}}, // [PlannTo Technologies Private Limited] + {"hash":"bdd2e20221d7e507","prefixes":{"":{"product":1008,"type":1}}}, // [Viator, Inc] + {"hash":"1caf0cb7a05c5941","prefixes":{"":{"product":474,"type":0}}}, // [Xrost] + {"hash":"4c6513300966da08","prefixes":{"":{"product":1009,"type":1}}}, // [NODDINGTON TECHNOLOGIES LIMITED] + {"hash":"2c1d6a203788af2b","prefixes":{"":{"product":1010,"type":0}}}, // [Plan Blue Ltd] + {"hash":"3c0da2d4356e18a5","prefixes":{"":{"product":1010,"type":0}}}, // [Plan Blue Ltd] + {"hash":"2568d0917d238964","prefixes":{"":{"product":1011,"type":0}}}, // [Addictive Mobility] + {"hash":"f79c822ab2cca8ee","prefixes":{"":{"product":1011,"type":0}}}, // [Addictive Mobility] + {"hash":"c610b5ae3df923cd","prefixes":{"":{"product":1011,"type":0}}}, // [Addictive Mobility] + {"hash":"a614ab43bf2d906b","prefixes":{"":{"product":1011,"type":0}}}, // [Addictive Mobility] + {"hash":"747eeca86822f19c","prefixes":{"":{"product":1012,"type":1}}}, // [A6 Corporation] + {"hash":"cbdfdaeff8b7d933","prefixes":{"":{"product":1013,"type":0}}}, // [Mobusi Mobile Advertising] + {"hash":"5b2d082c7811bead","prefixes":{"":{"product":1014,"type":0}}}, // [Wishabi] + {"hash":"c811726b56670631","prefixes":{"":{"product":1014,"type":0}}}, // [Wishabi] + {"hash":"09d3b27d380d43a0","prefixes":{"":{"product":1014,"type":0}}}, // [Wishabi] + {"hash":"eecab68f555d1f9f","prefixes":{"":{"product":1015,"type":0}}}, // [onAd GmbH] + {"hash":"d05b20f38e3bb984","prefixes":{"":{"product":1016,"type":0}}}, // [Media Decision GmbH] + {"hash":"4a9b8dddd4c7567c","prefixes":{"":{"product":1016,"type":0}}}, // [Media Decision GmbH] + {"hash":"5121142c1b8676fd","prefixes":{"":{"product":1016,"type":0}}}, // [Media Decision GmbH] + {"hash":"e083b93d5a87c743","prefixes":{"":{"product":1017,"type":1}}}, // [Unitymedia NRW] + {"hash":"c665046a783daa9d","prefixes":{"":{"product":1018,"type":0}}}, // [Nowspots INC, dba Perfect Audience] + {"hash":"663d5fdbc3a52729","prefixes":{"":{"product":1018,"type":0}}}, // [Nowspots INC, dba Perfect Audience] + {"hash":"991e96310871571b","prefixes":{"":{"product":1018,"type":0}}}, // [Nowspots INC, dba Perfect Audience] + {"hash":"0503d775704af4a2","prefixes":{"":{"product":1018,"type":0}}}, // [Nowspots INC, dba Perfect Audience] + {"hash":"2c55a4ef41531200","prefixes":{"":{"product":1019,"type":0}}}, // [Avis] + {"hash":"62817a7d196cbdcf","prefixes":{"":{"product":1020,"type":0}}}, // [Comcast] + {"hash":"2e4bb1f4d07f3180","prefixes":{"":{"product":1021,"type":0}}}, // [Jack Spade] + {"hash":"e7d369c24971784a","prefixes":{"":{"product":1022,"type":0}}}, // [Dollar General] + {"hash":"a8c9b93aae571ed5","prefixes":{"":{"product":1023,"type":0}}}, // [Care.com] + {"hash":"713775b7bc737116","prefixes":{"":{"product":1024,"type":0}}}, // [Clickagy, LLC] + {"hash":"8b6b45c1c86cd84b","prefixes":{"":{"product":1024,"type":0}}}, // [Clickagy, LLC] + {"hash":"34376185507c9ae0","prefixes":{"":{"product":1025,"type":1}}}, // [GlobalWebIndex] + {"hash":"8b17254892b590e3","prefixes":{"":{"product":1026,"type":0}}}, // [King.com] + {"hash":"8516f044f19bb3ae","prefixes":{"":{"product":1026,"type":0}}}, // [King.com] + {"hash":"d811179454fad251","prefixes":{"":{"product":1026,"type":0}}}, // [King.com] + {"hash":"946611fa2f4b067a","prefixes":{"":{"product":1027,"type":1}}}, // [Proquire LLC - Accenture] + {"hash":"cfa0e9025fcd5712","prefixes":{"":{"product":1028,"type":0}}}, // [Dynamic Yield] + {"hash":"b01c0239af74e72e","prefixes":{"":{"product":1028,"type":0}}}, // [Dynamic Yield] + {"hash":"e480d03a980d3bfc","prefixes":{"":{"product":1028,"type":0}}}, // [Dynamic Yield] + {"hash":"f22fe7e17c58b562","prefixes":{"":{"product":1028,"type":0}}}, // [Dynamic Yield] + {"hash":"f8da77c2fdcad106","prefixes":{"":{"product":1028,"type":0}}}, // [Dynamic Yield] + {"hash":"cea3bf4afe576984","prefixes":{"":{"product":1029,"type":0}}}, // [Charter business] + {"hash":"f8029c009186163f","prefixes":{"":{"product":1030,"type":1}}}, // [The ADEX] + {"hash":"61b09f5d40722e69","prefixes":{"":{"product":1031,"type":0}}}, // [OneDigitalAd Technologies] + {"hash":"aa63151485efa109","prefixes":{"":{"product":1031,"type":0}}}, // [OneDigitalAd Technologies] + {"hash":"ed37e98f45f10404","prefixes":{"":{"product":1031,"type":0}}}, // [OneDigitalAd Technologies] + {"hash":"f9fda879239cf155","prefixes":{"":{"product":1031,"type":0}}}, // [OneDigitalAd Technologies] + {"hash":"2dfe9124b3439d80","prefixes":{"":{"product":1031,"type":0}}}, // [OneDigitalAd Technologies] + {"hash":"93a9e29ac238b380","prefixes":{"":{"product":1031,"type":0}}}, // [OneDigitalAd Technologies] + {"hash":"5e080b13877f5de7","prefixes":{"":{"product":1031,"type":0}}}, // [OneDigitalAd Technologies] + {"hash":"eb22d59d4594e6d3","prefixes":{"":{"product":1031,"type":0}}}, // [OneDigitalAd Technologies] + {"hash":"a28e072f804db6a0","prefixes":{"":{"product":1031,"type":0}}}, // [OneDigitalAd Technologies] + {"hash":"945f948eacea62c9","prefixes":{"":{"product":1031,"type":0}}}, // [OneDigitalAd Technologies] + {"hash":"b85074a47da33b83","prefixes":{"":{"product":1032,"type":0}}}, // [ADJUST] + {"hash":"9f369deb4f045364","prefixes":{"":{"product":1032,"type":0}}}, // [ADJUST] + {"hash":"2d6ceeb3eef38c27","prefixes":{"":{"product":1032,"type":0}}}, // [ADJUST] + {"hash":"65240dfe37410021","prefixes":{"":{"product":1032,"type":0}}}, // [ADJUST] + {"hash":"8d3dfcbf705f1191","prefixes":{"":{"product":1032,"type":0}}}, // [ADJUST] + {"hash":"a2d35afc9c960448","prefixes":{"":{"product":1033,"type":1}}}, // [ADmantX, SPA] + {"hash":"3d3bc7f00b0ef8d3","prefixes":{"":{"product":1034,"type":0}}}, // [Sogou.com] + {"hash":"9eb0737a130a6f08","prefixes":{"":{"product":1035,"type":0}}}, // [xAd, Inc.] + {"hash":"a9ff22250a3c29a1","prefixes":{"":{"product":1036,"type":0}}}, // [VideoBlocks] + {"hash":"61f27a00f3821730","prefixes":{"":{"product":1037,"type":0}}}, // [GraphicStocks] + {"hash":"f0792974945e7184","prefixes":{"":{"product":1038,"type":1}}}, // [Microsoft Advertising] + {"hash":"81f27cb33d47894b","prefixes":{"":{"product":1039,"type":0}}}, // [Rontar LTD] + {"hash":"e8ae13fee2796336","prefixes":{"":{"product":1039,"type":0}}}, // [Rontar LTD] + {"hash":"d979ed3048a9dc3d","prefixes":{"":{"product":1039,"type":0}}}, // [Rontar LTD] + {"hash":"187c7e948b323b3a","prefixes":{"dsp":{"product":1039,"type":0}}}, // [Rontar LTD] + {"hash":"1a5cfb3f08b31682","prefixes":{"":{"product":1040,"type":0}}}, // [Torrential, Inc.] + {"hash":"99bb29582234b47b","prefixes":{"":{"product":1041,"type":0}}}, // [AMoAd, Inc.] + {"hash":"14a0b2d821feb403","prefixes":{"":{"product":1041,"type":0}}}, // [AMoAd, Inc.] + {"hash":"4bfb576f457b3ad4","prefixes":{"":{"product":1041,"type":0}}}, // [AMoAd, Inc.] + {"hash":"d2e32e6a4c73344a","prefixes":{"":{"product":1041,"type":0}}}, // [AMoAd, Inc.] + {"hash":"3c8aa320c0f5fb9d","prefixes":{"":{"product":1041,"type":0}}}, // [AMoAd, Inc.] + {"hash":"8c3cae9472fcd43a","prefixes":{"":{"product":1041,"type":0}}}, // [AMoAd, Inc.] + {"hash":"18d673cc147eaba5","prefixes":{"":{"product":1041,"type":0}}}, // [AMoAd, Inc.] + {"hash":"fb4f3dd591cba22f","prefixes":{"bid":{"product":1041,"type":0}}}, // [AMoAd, Inc.] + {"hash":"49aef0b488ab5024","prefixes":{"":{"product":1041,"type":0}}}, // [AMoAd, Inc.] + {"hash":"2b7a17458f44228d","prefixes":{"":{"product":1041,"type":0}}}, // [AMoAd, Inc.] + {"hash":"7458cceedc9f812a","prefixes":{"":{"product":1042,"type":0}}}, // [Tukmob Information Technology(Shanghai)Co. Ltd] + {"hash":"dd47f178c7a055b8","prefixes":{"":{"product":1042,"type":0}}}, // [Tukmob Information Technology(Shanghai)Co. Ltd] + {"hash":"db975b73da86c8ce","prefixes":{"":{"product":1042,"type":0}}}, // [Tukmob Information Technology(Shanghai)Co. Ltd] + {"hash":"6216946891299e23","prefixes":{"":{"product":1042,"type":0}}}, // [Tukmob Information Technology(Shanghai)Co. Ltd] + {"hash":"52ee7c22862a74b6","prefixes":{"":{"product":1042,"type":0}}}, // [Tukmob Information Technology(Shanghai)Co. Ltd] + {"hash":"3cc39e801c92ea89","prefixes":{"":{"product":1043,"type":0}}}, // [Jampp/Devego S.A.] + {"hash":"31fb8bdf6d2b85d2","prefixes":{"":{"product":1044,"type":1}}}, // [Placed] + {"hash":"a6ff57032773fe41","prefixes":{"*":{"product":1045,"type":1}}}, // [Digitas Health] + {"hash":"caeb7a071a866e17","prefixes":{"*":{"product":1045,"type":1}}}, // [Digitas Health] + {"hash":"6e946f5fac72b0b4","prefixes":{"":{"product":1046,"type":0}}}, // [Answer Media, LLC] + {"hash":"31c3d7ef1499fd26","prefixes":{"":{"product":1046,"type":0}}}, // [Answer Media, LLC] + {"hash":"d681f06391c7f861","prefixes":{"":{"product":1047,"type":1}}}, // [1000mercis] + {"hash":"1549387212aaa6a3","prefixes":{"":{"product":1048,"type":0}}}, // [Upstart Network, Inc.] + {"hash":"e48f63d27d0c24c7","prefixes":{"":{"product":1049,"type":1}}}, // [Forensiq, LLC] + {"hash":"7579b1341b228f93","prefixes":{"":{"product":1049,"type":1}}}, // [Forensiq, LLC] + {"hash":"f2e570ecd2540399","prefixes":{"":{"product":1050,"type":0}}}, // [LoopMe Ltd] + {"hash":"7d4e3b90001a044e","prefixes":{"":{"product":1050,"type":0}}}, // [LoopMe Ltd] + {"hash":"528167a286d8ccf8","prefixes":{"":{"product":1051,"type":0}}}, // [Bannerlink (Liquidus)] + {"hash":"0b2d528c0dce5bba","prefixes":{"":{"product":1051,"type":0}}}, // [Bannerlink (Liquidus)] + {"hash":"758cc459053712cf","prefixes":{"":{"product":1051,"type":0}}}, // [Bannerlink (Liquidus)] + {"hash":"57951d4b34add1a9","prefixes":{"":{"product":1051,"type":0}}}, // [Bannerlink (Liquidus)] + {"hash":"3d93ddd2b1dc8083","prefixes":{"":{"product":1051,"type":0}}}, // [Bannerlink (Liquidus)] + {"hash":"88f0b992c4b99c65","prefixes":{"":{"product":1052,"type":1}}}, // [Dell Inc.] + {"hash":"f8820430b42f89f8","prefixes":{"":{"product":1053,"type":0}}}, // [My Perfect Resume] + {"hash":"6f018db6d7a12f5e","prefixes":{"":{"product":1054,"type":0}}}, // [Ajillion Max Ltd] + {"hash":"b591ab0baccecd52","prefixes":{"":{"product":1054,"type":0}}}, // [Ajillion Max Ltd] + {"hash":"35d86d0121dbd41a","prefixes":{"":{"product":1055,"type":0}}}, // [Swelen France SA.] + {"hash":"25b09dd0e8d2977a","prefixes":{"":{"product":1055,"type":0}}}, // [Swelen France SA.] + {"hash":"f5cb853eba61193a","prefixes":{"":{"product":1056,"type":0}}}, // [Sleeptrain] + {"hash":"c620109c65610aeb","prefixes":{"":{"product":1057,"type":0}}}, // [Sleepcountry] + {"hash":"9c6554ebebdbfa08","prefixes":{"":{"product":1058,"type":0}}}, // [Hoover] + {"hash":"f34ddb2b65330794","prefixes":{"":{"product":1059,"type":0}}}, // [Bidtellect] + {"hash":"5d9eb2a8dc1a1687","prefixes":{"":{"product":1059,"type":0}}}, // [Bidtellect] + {"hash":"e2207dc37f1b89e8","prefixes":{"":{"product":1059,"type":0}}}, // [Bidtellect] + {"hash":"682ec1b47db930b9","prefixes":{"":{"product":1059,"type":0}}}, // [Bidtellect] + {"hash":"638a2c2dc53d2ab7","prefixes":{"":{"product":1060,"type":0}}}, // [Mocoplex Inc.] + {"hash":"ee330ed89897a55c","prefixes":{"":{"product":1060,"type":0}}}, // [Mocoplex Inc.] + {"hash":"60ab035f28a35e30","prefixes":{"":{"product":1060,"type":0}}}, // [Mocoplex Inc.] + {"hash":"5929f2c289d9e073","prefixes":{"":{"product":778,"type":0}}}, // [Gruvi Ltd.] + {"hash":"c16c02248018a374","prefixes":{"":{"product":778,"type":0}}}, // [Gruvi Ltd.] + {"hash":"e6eb2d1c03d2be83","prefixes":{"":{"product":778,"type":0}}}, // [Gruvi Ltd.] + {"hash":"95fa4396cadc336e","prefixes":{"":{"product":778,"type":0}}}, // [Gruvi Ltd.] + {"hash":"2604a7d96f168c84","prefixes":{"":{"product":1061,"type":0}}}, // [Brightsparc Technologies Pty Ltd trading as Native] + {"hash":"294fdebfd41771a8","prefixes":{"":{"product":1061,"type":0}}}, // [Brightsparc Technologies Pty Ltd trading as Native] + {"hash":"c6beb451fe4c58c2","prefixes":{"":{"product":1061,"type":0}}}, // [Brightsparc Technologies Pty Ltd trading as Native] + {"hash":"b0f5f51210e6f2af","prefixes":{"":{"product":1061,"type":0}}}, // [Brightsparc Technologies Pty Ltd trading as Native] + {"hash":"ab3da2eb1a35cba6","prefixes":{"":{"product":1062,"type":0}}}, // [Verengo Solar] + {"hash":"c3bf5a10743772ec","prefixes":{"*":{"product":1063,"type":0}}}, // [Mobile Professionals BV] + {"hash":"d22325b6d6b04918","prefixes":{"*":{"product":1064,"type":1}}}, // [APNIC Pty Ltd] + {"hash":"27966131215e508a","prefixes":{"*":{"product":1064,"type":1}}}, // [APNIC Pty Ltd] + {"hash":"80022b9d8ddaffde","prefixes":{"*":{"product":1064,"type":1}}}, // [APNIC Pty Ltd] + {"hash":"9352d77ba286c03d","prefixes":{"":{"product":1065,"type":0}}}, // [Dun and Bradstreet Corporation] + {"hash":"74b7ef01f42d93ee","prefixes":{"":{"product":1066,"type":0}}}, // [UpToLike] + {"hash":"f2a78bb802dc4abd","prefixes":{"":{"product":1066,"type":0}}}, // [UpToLike] + {"hash":"f885798eaaace647","prefixes":{"":{"product":1067,"type":0}}}, // [Mobile360 Sdn Bhd] + {"hash":"3bc813f113908f06","prefixes":{"":{"product":1067,"type":0}}}, // [Mobile360 Sdn Bhd] + {"hash":"e1a6852c86da418c","prefixes":{"":{"product":1067,"type":0}}}, // [Mobile360 Sdn Bhd] + {"hash":"0343b65d010db4b2","prefixes":{"":{"product":1067,"type":0}}}, // [Mobile360 Sdn Bhd] + {"hash":"a9b74e1bcb339dd0","prefixes":{"":{"product":1067,"type":0}}}, // [Mobile360 Sdn Bhd] + {"hash":"e8d325d7be0f046b","prefixes":{"*":{"product":1067,"type":0}}}, // [Mobile360 Sdn Bhd] + {"hash":"f7ccb1753b9ae2ed","prefixes":{"":{"product":1067,"type":0}}}, // [Mobile360 Sdn Bhd] + {"hash":"4a96db729cb9dd47","prefixes":{"":{"product":1067,"type":0}}}, // [Mobile360 Sdn Bhd] + {"hash":"afde8c2ebcc380c8","prefixes":{"":{"product":1067,"type":0}}}, // [Mobile360 Sdn Bhd] + {"hash":"05840eb3ff4432a8","prefixes":{"":{"product":1067,"type":0}}}, // [Mobile360 Sdn Bhd] + {"hash":"3e5f0f83b0e34391","prefixes":{"":{"product":1067,"type":0}}}, // [Mobile360 Sdn Bhd] + {"hash":"f79fe1474c475ade","prefixes":{"":{"product":1068,"type":0}}}, // [Elite Fixtures] + {"hash":"b8b63e29130d798a","prefixes":{"":{"product":1069,"type":0}}}, // [Advanse Ads] + {"hash":"662442a875d5ae62","prefixes":{"":{"product":1069,"type":0}}}, // [Advanse Ads] + {"hash":"d8487e4c88a21c7f","prefixes":{"":{"product":1069,"type":0}}}, // [Advanse Ads] + {"hash":"37694729baf29aa5","prefixes":{"":{"product":1070,"type":0}}}, // [Insurance Step] + {"hash":"0153c16587a0c97c","prefixes":{"":{"product":1071,"type":1}}}, // [Causal Impact] + {"hash":"c7bcca7e8dc820fe","prefixes":{"":{"product":1071,"type":1}}}, // [Causal Impact] + {"hash":"2176b8c755bbab42","prefixes":{"":{"product":1071,"type":1}}}, // [Causal Impact] + {"hash":"1979b33f68eb0ded","prefixes":{"":{"product":1071,"type":1}}}, // [Causal Impact] + {"hash":"32a9ea6936225587","prefixes":{"":{"product":1071,"type":1}}}, // [Causal Impact] + {"hash":"16fec67040bf3ff7","prefixes":{"":{"product":1071,"type":1}}}, // [Causal Impact] + {"hash":"ed89b325a7c3ac6d","prefixes":{"":{"product":1071,"type":1}}}, // [Causal Impact] + {"hash":"ae3bc4690ef89e8d","prefixes":{"":{"product":1071,"type":1}}}, // [Causal Impact] + {"hash":"ed9a2a4f49ad4647","prefixes":{"":{"product":1071,"type":1}}}, // [Causal Impact] + {"hash":"398d36669a77aca6","prefixes":{"":{"product":1071,"type":1}}}, // [Causal Impact] + {"hash":"5bf9c0f450f9eb14","prefixes":{"":{"product":1071,"type":1}}}, // [Causal Impact] + {"hash":"30e7de1e277c7698","prefixes":{"":{"product":145,"type":0}}}, // [Aarki, Inc.] + {"hash":"888d9446d621d82f","prefixes":{"":{"product":145,"type":0}}}, // [Aarki, Inc.] + {"hash":"3061a4cd653ea2dc","prefixes":{"*":{"product":1072,"type":0}}}, // [Pixnet] + {"hash":"06daa5b82ebfa413","prefixes":{"":{"product":1073,"type":0}}}, // [Zapp360] + {"hash":"6f0f9a90c798715d","prefixes":{"":{"product":1074,"type":0}}}, // [Kijiji] + {"hash":"0259cba89f8f9676","prefixes":{"":{"product":1075,"type":0}}}, // [Spotad LTD.] + {"hash":"0ca2babbaeeca3bf","prefixes":{"":{"product":1075,"type":0}}}, // [Spotad LTD.] + {"hash":"e9a9d4fd1b468042","prefixes":{"":{"product":1075,"type":0}}}, // [Spotad LTD.] + {"hash":"6a79ac93cddc0cc5","prefixes":{"":{"product":1075,"type":0}}}, // [Spotad LTD.] + {"hash":"685b17838f2d9b82","prefixes":{"":{"product":1076,"type":0}}}, // [Go Daddy] + {"hash":"aa66f01be33256d0","prefixes":{"":{"product":1077,"type":1}}}, // [Bilendi] + {"hash":"3b8dfd79ab921d9b","prefixes":{"":{"product":1078,"type":0}}}, // [Hitokuse] + {"hash":"1992e397e0dff18d","prefixes":{"":{"product":1078,"type":0}}}, // [Hitokuse] + {"hash":"03eb230cd9f67c73","prefixes":{"":{"product":1078,"type":0}}}, // [Hitokuse] + {"hash":"0a75c26f5c580b3a","prefixes":{"*":{"product":1079,"type":0}}}, // [MGID Inc.] + {"hash":"4466d73d5d5dce19","prefixes":{"*":{"product":1079,"type":0}}}, // [MGID Inc.] + {"hash":"10bfb2327400e2ea","prefixes":{"":{"product":1079,"type":0}}}, // [MGID Inc.] + {"hash":"121b77f4b4412c85","prefixes":{"":{"product":1079,"type":0}}}, // [MGID Inc.] + {"hash":"e46ec8aa62f3f432","prefixes":{"":{"product":1080,"type":0}}}, // [AreaOne] + {"hash":"9849db4d4a694f16","prefixes":{"t":{"product":1081,"type":0},"s":{"product":1081,"type":0},"sna":{"product":1081,"type":0}}}, // [DynAd] [DynAd] [DynAd] + {"hash":"5fc0aef37d5fffca","prefixes":{"":{"product":1082,"type":0}}}, // [Loop Pay] + {"hash":"4cc75be32553222a","prefixes":{"":{"product":1083,"type":0}}}, // [Remerge GmbH] + {"hash":"b1a90d2aaa32932c","prefixes":{"":{"product":1083,"type":0}}}, // [Remerge GmbH] + {"hash":"3bea81bc90640751","prefixes":{"":{"product":1084,"type":1}}}, // [Audience Trading Platform LTD] + {"hash":"d193540bb7540e5c","prefixes":{"":{"product":1085,"type":0}}}, // [Whisla] + {"hash":"abd1c2a37733128b","prefixes":{"":{"product":1085,"type":0}}}, // [Whisla] + {"hash":"9546fe15199cbce1","prefixes":{"":{"product":1085,"type":0}}}, // [Whisla] + {"hash":"f43c40d1949f2c52","prefixes":{"":{"product":1086,"type":0}}}, // [Bridgevine] + {"hash":"28577f7c17c55b0f","prefixes":{"":{"product":1087,"type":1}}}, // [ADgraph DMP] + {"hash":"fa0c51dc55faddc6","prefixes":{"":{"product":1088,"type":0}}}, // [Gravity4 Inc.] + {"hash":"6dea119c4c95aaa8","prefixes":{"":{"product":1088,"type":0}}}, // [Gravity4 Inc.] + {"hash":"79b4752426dedd83","prefixes":{"":{"product":1089,"type":0}}}, // [Hipmunk] + {"hash":"ccba9f3966eabe6b","prefixes":{"*":{"product":1090,"type":0}}}, // [VideoHub DSP] + {"hash":"a6baef75f126450e","prefixes":{"":{"product":1091,"type":1}}}, // [DuMedia] + {"hash":"cf45efd3feda1ba3","prefixes":{"":{"product":1091,"type":1}}}, // [DuMedia] + {"hash":"efebf8c1ea6bab87","prefixes":{"":{"product":1092,"type":0}}}, // [F@N Communications, Inc.] + {"hash":"a866ff2bfe3133e7","prefixes":{"":{"product":1092,"type":0}}}, // [F@N Communications, Inc.] + {"hash":"49b89555382dac9e","prefixes":{"":{"product":1092,"type":0}}}, // [F@N Communications, Inc.] + {"hash":"e2d2b1537271ff61","prefixes":{"":{"product":1092,"type":0}}}, // [F@N Communications, Inc.] + {"hash":"5804e7cf2cdbbda0","prefixes":{"":{"product":1092,"type":0}}}, // [F@N Communications, Inc.] + {"hash":"db0ef2b4eff25274","prefixes":{"":{"product":1092,"type":0}}}, // [F@N Communications, Inc.] + {"hash":"d960535fd30704f8","prefixes":{"":{"product":1092,"type":0}}}, // [F@N Communications, Inc.] + {"hash":"258915df4406fd06","prefixes":{"":{"product":1092,"type":0}}}, // [F@N Communications, Inc.] + {"hash":"b34a1e3fd51aadb9","prefixes":{"":{"product":1092,"type":0}}}, // [F@N Communications, Inc.] + {"hash":"c0ad7ec6e1d46299","prefixes":{"":{"product":1093,"type":0}}}, // [VIVALU GmbH] + {"hash":"65c049a517720b5c","prefixes":{"":{"product":1093,"type":0}}}, // [VIVALU GmbH] + {"hash":"b60b2426028baba5","prefixes":{"":{"product":1094,"type":0}}}, // [Advertising Technologies LTD] + {"hash":"6d2df95e2bf52046","prefixes":{"":{"product":1094,"type":0}}}, // [Advertising Technologies LTD] + {"hash":"b4ad6ea6ca336f55","prefixes":{"":{"product":1094,"type":0}}}, // [Advertising Technologies LTD] + {"hash":"b750311cbd5c4013","prefixes":{"":{"product":1095,"type":1}}}, // [Authenticated Digital Inc] + {"hash":"aa634a3d8862b3be","prefixes":{"":{"product":1095,"type":1}}}, // [Authenticated Digital Inc] + {"hash":"361eefdfa29ada10","prefixes":{"":{"product":1096,"type":0}}}, // [PaeDae, Inc., DBA The Mobile Majority] + {"hash":"8a5c2c8d21fc6dd4","prefixes":{"":{"product":1096,"type":0}}}, // [PaeDae, Inc., DBA The Mobile Majority] + {"hash":"13b3d2e0ed78e518","prefixes":{"":{"product":1097,"type":0}}}, // [METROPCS] + {"hash":"c9b29fe277a47b8d","prefixes":{"":{"product":1098,"type":0}}}, // [PapayaMobile Inc.] + {"hash":"60f32eaa9335e4b9","prefixes":{"":{"product":1098,"type":0}}}, // [PapayaMobile Inc.] + {"hash":"c8f49035cb273e42","prefixes":{"":{"product":1098,"type":0}}}, // [PapayaMobile Inc.] + {"hash":"92d9e360f16ecdc9","prefixes":{"":{"product":1098,"type":0}}}, // [PapayaMobile Inc.] + {"hash":"2d3b5566afb5350b","prefixes":{"":{"product":1098,"type":0}}}, // [PapayaMobile Inc.] + {"hash":"0ca3b2088de2514c","prefixes":{"":{"product":1098,"type":0}}}, // [PapayaMobile Inc.] + {"hash":"67da96d5ae99faa0","prefixes":{"":{"product":1098,"type":0}}}, // [PapayaMobile Inc.] + {"hash":"347e898491d027ee","prefixes":{"":{"product":1099,"type":0}}}, // [Raumfeld] + {"hash":"ae3f27ad4a4f2f7d","prefixes":{"":{"product":1099,"type":0}}}, // [Raumfeld] + {"hash":"cd0c8a5dd793ee52","prefixes":{"":{"product":1099,"type":0}}}, // [Raumfeld] + {"hash":"451f4083f03028e0","prefixes":{"":{"product":1099,"type":0}}}, // [Raumfeld] + {"hash":"e1b048e4fa37eef2","prefixes":{"":{"product":1099,"type":0}}}, // [Raumfeld] + {"hash":"837ae92d9cf6b933","prefixes":{"":{"product":1099,"type":0}}}, // [Raumfeld] + {"hash":"6ae82aac87db94d3","prefixes":{"":{"product":1099,"type":0}}}, // [Raumfeld] + {"hash":"84ddfa5a2e93cb69","prefixes":{"":{"product":1100,"type":0}}}, // [GREE Ads DSP] + {"hash":"a7201f5a80824242","prefixes":{"":{"product":1100,"type":0}}}, // [GREE Ads DSP] + {"hash":"2ec22ca05310362a","prefixes":{"":{"product":1101,"type":0}}}, // [Tender Industries AB] + {"hash":"d159abbaeda22e7c","prefixes":{"":{"product":1102,"type":1}}}, // [BySide] + {"hash":"426783d6fe8d039e","prefixes":{"":{"product":1103,"type":1}}}, // [Sentrant Security Inc.] + {"hash":"d270ad50bb53fb01","prefixes":{"":{"product":1103,"type":1}}}, // [Sentrant Security Inc.] + {"hash":"49c693058534be83","prefixes":{"":{"product":1104,"type":0}}}, // [Locon Solutions Pvt. Ltd.] + {"hash":"a2b9f627da8737de","prefixes":{"":{"product":1105,"type":1}}}, // [Interrogare GmbH] + {"hash":"13b73169540642e5","prefixes":{"":{"product":1105,"type":1}}}, // [Interrogare GmbH] + {"hash":"afaa106d11846fa4","prefixes":{"*":{"product":1106,"type":1}}}, // [ChannelAdvisor] + {"hash":"b8b4eadeb5d3a123","prefixes":{"":{"product":1107,"type":0}}}, // [VideoAmp] + {"hash":"43546e9f6ff5bf2a","prefixes":{"":{"product":1107,"type":0}}}, // [VideoAmp] + {"hash":"61a9edb9af3769cf","prefixes":{"":{"product":1107,"type":0}}}, // [VideoAmp] + {"hash":"f76b3fe7048e93e2","prefixes":{"":{"product":1107,"type":0}}}, // [VideoAmp] + {"hash":"57263424c0e88a92","prefixes":{"track":{"product":1108,"type":0}}}, // [The Bridge] + {"hash":"516e9fc5ede4af0d","prefixes":{"":{"product":1108,"type":0}}}, // [The Bridge] + {"hash":"6bc0303a4262cb67","prefixes":{"":{"product":1108,"type":0}}}, // [The Bridge] + {"hash":"30a32fe2a89dccd8","prefixes":{"":{"product":1109,"type":0}}}, // [Pharmaca Integrative Pharmacy] + {"hash":"7881da604383a640","prefixes":{"":{"product":673,"type":0}}}, // [Videology DSP] + {"hash":"dec02c663bb06094","prefixes":{"":{"product":1110,"type":0}}}, // [Scrutineer] + {"hash":"6e2098af577c671d","prefixes":{"":{"product":1111,"type":1}}}, // [TF1 - FR] + {"hash":"60774075776e2612","prefixes":{"":{"product":1112,"type":0}}}, // [Core Digital] + {"hash":"79a775eea6a902e6","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"c0576db5cf4ba20b","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"d90fda985e3fb6bf","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"ee49dcf9326e853f","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"5b3c6abcd44de720","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"f97a320480541a27","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"57fc36302e0bde3c","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"736a8a8a0cef7bdf","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"36263b4a0d607a71","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"226480bf58f4fd1c","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"58379bd623597d70","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"f68e3a544a7397be","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"0f2880d71794e516","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"4ef52741fc1ade73","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"97d6a93635d72af0","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"ab75a46dc8bf2c1e","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"efeb8f966db03b87","prefixes":{"":{"product":110,"type":0}}}, // [Bonzai Digital Pvt. Ltd] + {"hash":"2a4d804c0fb397c1","prefixes":{"":{"product":1113,"type":0}}}, // [Adventive, Inc.] + {"hash":"29d370caa59b4ecc","prefixes":{"":{"product":1113,"type":0}}}, // [Adventive, Inc.] {"hash":"a06632ec1be82319","prefixes":{"":{"product":1114}}}, // [Turner Sports Interactive, Inc.] {"hash":"bf10e40bae047225","prefixes":{"":{"product":1114}}}, // [Turner Sports Interactive, Inc.] {"hash":"67dbd4ebfca8ed7c","prefixes":{"":{"product":1114}}}, // [Turner Sports Interactive, Inc.] {"hash":"3ccffb010a6151f8","prefixes":{"":{"product":1115}}}, // [SnappyTV] - {"hash":"7d838005a39552d8","prefixes":{"":{"product":1116}}}, // [Target Media Partners] - {"hash":"003b7537bd9a7cfe","prefixes":{"":{"product":1116}}}, // [Target Media Partners] - {"hash":"26b33a79482ab7ab","prefixes":{"":{"product":1117}}}, // [KAIZEN platform Inc.] - {"hash":"15cdc1963890a6a2","prefixes":{"":{"product":1117}}}, // [KAIZEN platform Inc.] - {"hash":"1f36b920b7ac4ebb","prefixes":{"":{"product":1118}}}, // [Bidstalk Pte Ltd] - {"hash":"a59afaa1821362bd","prefixes":{"":{"product":1119}}}, // [ESPN] - {"hash":"e0edcd5fafde3e7a","prefixes":{"":{"product":1119}}}, // [ESPN] - {"hash":"7bd48d6255130db4","prefixes":{"":{"product":1120}}}, // [Online Media Group] - {"hash":"88c41fbe0db9a483","prefixes":{"":{"product":1120}}}, // [Online Media Group] - {"hash":"fc1080dbf4fae3f9","prefixes":{"":{"product":1120}}}, // [Online Media Group] - {"hash":"37fc205007f7a040","prefixes":{"":{"product":1120}}}, // [Online Media Group] - {"hash":"60c02a2ea01a737e","prefixes":{"":{"product":1121}}}, // [Luxury Link] - {"hash":"24108d30b52b9587","prefixes":{"":{"product":1122}}}, // [ESKIMI] + {"hash":"7d838005a39552d8","prefixes":{"":{"product":1116,"type":0}}}, // [Target Media Partners] + {"hash":"003b7537bd9a7cfe","prefixes":{"":{"product":1116,"type":0}}}, // [Target Media Partners] + {"hash":"26b33a79482ab7ab","prefixes":{"":{"product":1117,"type":0}}}, // [KAIZEN platform Inc.] + {"hash":"15cdc1963890a6a2","prefixes":{"":{"product":1117,"type":0}}}, // [KAIZEN platform Inc.] + {"hash":"1f36b920b7ac4ebb","prefixes":{"":{"product":1118,"type":0}}}, // [Bidstalk Pte Ltd] + {"hash":"a59afaa1821362bd","prefixes":{"":{"product":1119,"type":0}}}, // [ESPN] + {"hash":"e0edcd5fafde3e7a","prefixes":{"":{"product":1119,"type":0}}}, // [ESPN] + {"hash":"7bd48d6255130db4","prefixes":{"":{"product":1120,"type":0}}}, // [Online Media Group] + {"hash":"88c41fbe0db9a483","prefixes":{"":{"product":1120,"type":0}}}, // [Online Media Group] + {"hash":"fc1080dbf4fae3f9","prefixes":{"":{"product":1120,"type":0}}}, // [Online Media Group] + {"hash":"37fc205007f7a040","prefixes":{"":{"product":1120,"type":0}}}, // [Online Media Group] + {"hash":"60c02a2ea01a737e","prefixes":{"":{"product":1121,"type":0}}}, // [Luxury Link] + {"hash":"24108d30b52b9587","prefixes":{"":{"product":1122,"type":0}}}, // [ESKIMI] {"hash":"9de510a2d7f81a6e","prefixes":{"":{"product":1122}}}, // [ESKIMI] - {"hash":"d0e18c7e72b51bf3","prefixes":{"":{"product":1122}}}, // [ESKIMI] - {"hash":"6dbe16f5894e20af","prefixes":{"":{"product":1123}}}, // [AdsYolo Media] - {"hash":"5292ef4ba83623a8","prefixes":{"":{"product":1124}}}, // [Arrivalist] - {"hash":"b94285ae50bcb48e","prefixes":{"":{"product":1124}}}, // [Arrivalist] - {"hash":"cd7b432729ab016a","prefixes":{"":{"product":1124}}}, // [Arrivalist] - {"hash":"ae0442a300ebce47","prefixes":{"":{"product":1124}}}, // [Arrivalist] - {"hash":"3c8cc56d5b514ec5","prefixes":{"":{"product":1124}}}, // [Arrivalist] - {"hash":"794b2a51546b4f7f","prefixes":{"":{"product":1125}}}, // [MobileWebAdz Ltd] - {"hash":"223eacf97254c888","prefixes":{"":{"product":1125}}}, // [MobileWebAdz Ltd] - {"hash":"a3c5eeef285517f3","prefixes":{"":{"product":1125}}}, // [MobileWebAdz Ltd] - {"hash":"b222f9498fcdb24c","prefixes":{"":{"product":1126}}}, // [Demand Side Science, Inc.] - {"hash":"87af9974b30c5872","prefixes":{"":{"product":1126}}}, // [Demand Side Science, Inc.] - {"hash":"db4cd3e487418898","prefixes":{"":{"product":1126}}}, // [Demand Side Science, Inc.] - {"hash":"3fca6191597f44f2","prefixes":{"":{"product":1127}}}, // [SOCIETE FRANCAISE DU RADIOTELEPHONE] - {"hash":"6873487b11c1952e","prefixes":{"":{"product":1127}}}, // [SOCIETE FRANCAISE DU RADIOTELEPHONE] - {"hash":"d4b4ed3e1d07b00e","prefixes":{"":{"product":1127}}}, // [SOCIETE FRANCAISE DU RADIOTELEPHONE] - {"hash":"e647f502df0429f5","prefixes":{"":{"product":1128}}}, // [Mobitrans FZ LLC] - {"hash":"34f8fc43e14bad03","prefixes":{"":{"product":1128}}}, // [Mobitrans FZ LLC] - {"hash":"5f43507f5a877784","prefixes":{"":{"product":1128}}}, // [Mobitrans FZ LLC] - {"hash":"1466e6f77352194a","prefixes":{"":{"product":1128}}}, // [Mobitrans FZ LLC] - {"hash":"e097497d606d17ed","prefixes":{"":{"product":1128}}}, // [Mobitrans FZ LLC] - {"hash":"05c9b2eb92c8b5ba","prefixes":{"":{"product":1128}}}, // [Mobitrans FZ LLC] - {"hash":"ce3bfbe09ddeb858","prefixes":{"":{"product":1128}}}, // [Mobitrans FZ LLC] - {"hash":"3aa96b751d2c0d1c","prefixes":{"":{"product":1128}}}, // [Mobitrans FZ LLC] - {"hash":"289e565c9c686515","prefixes":{"":{"product":1129}}}, // [CoCo Reef] + {"hash":"d0e18c7e72b51bf3","prefixes":{"":{"product":1122,"type":0}}}, // [ESKIMI] + {"hash":"6dbe16f5894e20af","prefixes":{"":{"product":1123,"type":0}}}, // [AdsYolo Media] + {"hash":"5292ef4ba83623a8","prefixes":{"":{"product":1124,"type":0}}}, // [Arrivalist] + {"hash":"b94285ae50bcb48e","prefixes":{"":{"product":1124,"type":0}}}, // [Arrivalist] + {"hash":"cd7b432729ab016a","prefixes":{"":{"product":1124,"type":0}}}, // [Arrivalist] + {"hash":"ae0442a300ebce47","prefixes":{"":{"product":1124,"type":0}}}, // [Arrivalist] + {"hash":"3c8cc56d5b514ec5","prefixes":{"":{"product":1124,"type":0}}}, // [Arrivalist] + {"hash":"794b2a51546b4f7f","prefixes":{"":{"product":1125,"type":0}}}, // [MobileWebAdz Ltd] + {"hash":"223eacf97254c888","prefixes":{"":{"product":1125,"type":0}}}, // [MobileWebAdz Ltd] + {"hash":"a3c5eeef285517f3","prefixes":{"":{"product":1125,"type":0}}}, // [MobileWebAdz Ltd] + {"hash":"b222f9498fcdb24c","prefixes":{"":{"product":1126,"type":0}}}, // [Demand Side Science, Inc.] + {"hash":"87af9974b30c5872","prefixes":{"":{"product":1126,"type":0}}}, // [Demand Side Science, Inc.] + {"hash":"db4cd3e487418898","prefixes":{"":{"product":1126,"type":0}}}, // [Demand Side Science, Inc.] + {"hash":"3fca6191597f44f2","prefixes":{"":{"product":1127,"type":1}}}, // [SOCIETE FRANCAISE DU RADIOTELEPHONE] + {"hash":"6873487b11c1952e","prefixes":{"":{"product":1127,"type":1}}}, // [SOCIETE FRANCAISE DU RADIOTELEPHONE] + {"hash":"d4b4ed3e1d07b00e","prefixes":{"":{"product":1127,"type":1}}}, // [SOCIETE FRANCAISE DU RADIOTELEPHONE] + {"hash":"e647f502df0429f5","prefixes":{"":{"product":1128,"type":0}}}, // [Mobitrans FZ LLC] + {"hash":"34f8fc43e14bad03","prefixes":{"":{"product":1128,"type":0}}}, // [Mobitrans FZ LLC] + {"hash":"5f43507f5a877784","prefixes":{"":{"product":1128,"type":0}}}, // [Mobitrans FZ LLC] + {"hash":"1466e6f77352194a","prefixes":{"":{"product":1128,"type":0}}}, // [Mobitrans FZ LLC] + {"hash":"e097497d606d17ed","prefixes":{"":{"product":1128,"type":0}}}, // [Mobitrans FZ LLC] + {"hash":"05c9b2eb92c8b5ba","prefixes":{"":{"product":1128,"type":0}}}, // [Mobitrans FZ LLC] + {"hash":"ce3bfbe09ddeb858","prefixes":{"":{"product":1128,"type":0}}}, // [Mobitrans FZ LLC] + {"hash":"3aa96b751d2c0d1c","prefixes":{"":{"product":1128,"type":0}}}, // [Mobitrans FZ LLC] + {"hash":"289e565c9c686515","prefixes":{"":{"product":1129,"type":0}}}, // [CoCo Reef] {"hash":"0b6740b395a65857","prefixes":{"":{"product":1130}}}, // [Kumma DP LTD] - {"hash":"c00365ed4d1c464c","prefixes":{"":{"product":1131}}}, // [Cablato Limited] - {"hash":"9ee2a07ebdef206f","prefixes":{"":{"product":1131}}}, // [Cablato Limited] - {"hash":"e270375f27c5f31c","prefixes":{"":{"product":1131}}}, // [Cablato Limited] - {"hash":"0ebf573ebb6b30e1","prefixes":{"":{"product":1131}}}, // [Cablato Limited] - {"hash":"e28b4c253b1f854f","prefixes":{"":{"product":1132}}}, // [EURO DISNEY SCA] - {"hash":"3c8900c851ba9b28","prefixes":{"":{"product":1133}}}, // [Norstat] - {"hash":"39518e51adbe0cd7","prefixes":{"":{"product":1133}}}, // [Norstat] - {"hash":"2c5efd1ea532f0eb","prefixes":{"":{"product":1134}}}, // [John Varvatos] - {"hash":"5679368e6b2bb34c","prefixes":{"":{"product":1135}}}, // [Spritz Technology, Inc.] - {"hash":"60be7d8a6a76b62f","prefixes":{"":{"product":1135}}}, // [Spritz Technology, Inc.] - {"hash":"cefbe9240a377d95","prefixes":{"":{"product":1136}}}, // [Wix.com] - {"hash":"a56824227bb496f7","prefixes":{"*":{"product":1137}}}, // [TapTap Networks] - {"hash":"41f2ae7d2d6939ae","prefixes":{"":{"product":1137}}}, // [TapTap Networks] - {"hash":"51fd8b1d5b983b31","prefixes":{"":{"product":1138}}}, // [Permodo] - {"hash":"12c3d246c6d4e6b1","prefixes":{"":{"product":1138}}}, // [Permodo] - {"hash":"69da2bfa4e414e2c","prefixes":{"":{"product":1138}}}, // [Permodo] - {"hash":"67bb1e3460d8e2eb","prefixes":{"":{"product":1138}}}, // [Permodo] - {"hash":"38912558a11ff73e","prefixes":{"":{"product":1138}}}, // [Permodo] - {"hash":"eb4d36cf5e4909c1","prefixes":{"":{"product":1139}}}, // [Gaiam, Inc.] - {"hash":"16578371f24a5e90","prefixes":{"":{"product":1140}}}, // [Plusing interactive co.,Ltd] - {"hash":"ecdb68bd2622aa9e","prefixes":{"":{"product":42}}}, // [Clinch.co] - {"hash":"8adccb3847cc8b0f","prefixes":{"":{"product":42}}}, // [Clinch.co] - {"hash":"2b5433780334b542","prefixes":{"":{"product":42}}}, // [Clinch.co] - {"hash":"c853c92986d0cc90","prefixes":{"":{"product":42}}}, // [Clinch.co] - {"hash":"388da33e7f0adca1","prefixes":{"":{"product":42}}}, // [Clinch.co] - {"hash":"03d7a65aa1bc87bc","prefixes":{"":{"product":1141}}}, // [Paypersale] - {"hash":"176eb71c0938f4a5","prefixes":{"":{"product":111}}}, // [Epic Combo Malta Ltd.] - {"hash":"4366ec3ae9f41f7c","prefixes":{"":{"product":111}}}, // [Epic Combo Malta Ltd.] - {"hash":"2e9617ef727ff0b5","prefixes":{"":{"product":1142}}}, // [OCP Collective Corp. (d/b/a AdCade)] - {"hash":"11d6d13e3eb48a86","prefixes":{"":{"product":1142}}}, // [OCP Collective Corp. (d/b/a AdCade)] - {"hash":"20e14ef573248fec","prefixes":{"":{"product":1142}}}, // [OCP Collective Corp. (d/b/a AdCade)] - {"hash":"234345fe3c0da842","prefixes":{"":{"product":1142}}}, // [OCP Collective Corp. (d/b/a AdCade)] - {"hash":"30fb60c9c450221d","prefixes":{"":{"product":1142}}}, // [OCP Collective Corp. (d/b/a AdCade)] - {"hash":"69ddc7852224e18f","prefixes":{"":{"product":1143}}}, // [ESV Digital] - {"hash":"240174bad001108d","prefixes":{"":{"product":1144}}}, // [RevJet LLC.] - {"hash":"5250a7a3f2e4f73a","prefixes":{"":{"product":1144}}}, // [RevJet LLC.] - {"hash":"590feb6b793ba20a","prefixes":{"":{"product":1144}}}, // [RevJet LLC.] - {"hash":"23db13cb66f769e3","prefixes":{"":{"product":1145}}}, // [GET IT Mobile, Inc] - {"hash":"cd7cd6c16f714024","prefixes":{"":{"product":1145}}}, // [GET IT Mobile, Inc] - {"hash":"00ea35d76275dbeb","prefixes":{"":{"product":1145}}}, // [GET IT Mobile, Inc] - {"hash":"5239cdae00ff02ea","prefixes":{"":{"product":1146}}}, // [IBM] - {"hash":"e2c539bef8d2970c","prefixes":{"":{"product":1147}}}, // [Lucid Holdings, LLC] - {"hash":"7078be8707b5ec93","prefixes":{"":{"product":1147}}}, // [Lucid Holdings, LLC] - {"hash":"d65fe9ed9f23afbd","prefixes":{"":{"product":1148}}}, // [Stratio Big Data Inc.] - {"hash":"9ccfc7f2ecfbaeec","prefixes":{"":{"product":1148}}}, // [Stratio Big Data Inc.] - {"hash":"54e80254bbf4e20b","prefixes":{"":{"product":1149}}}, // [Tripping.com] + {"hash":"c00365ed4d1c464c","prefixes":{"":{"product":1131,"type":0}}}, // [Cablato Limited] + {"hash":"9ee2a07ebdef206f","prefixes":{"":{"product":1131,"type":0}}}, // [Cablato Limited] + {"hash":"e270375f27c5f31c","prefixes":{"":{"product":1131,"type":0}}}, // [Cablato Limited] + {"hash":"0ebf573ebb6b30e1","prefixes":{"":{"product":1131,"type":0}}}, // [Cablato Limited] + {"hash":"e28b4c253b1f854f","prefixes":{"":{"product":1132,"type":1}}}, // [EURO DISNEY SCA] + {"hash":"3c8900c851ba9b28","prefixes":{"":{"product":1133,"type":1}}}, // [Norstat] + {"hash":"39518e51adbe0cd7","prefixes":{"":{"product":1133,"type":1}}}, // [Norstat] + {"hash":"2c5efd1ea532f0eb","prefixes":{"":{"product":1134,"type":0}}}, // [John Varvatos] + {"hash":"5679368e6b2bb34c","prefixes":{"":{"product":1135,"type":0}}}, // [Spritz Technology, Inc.] + {"hash":"60be7d8a6a76b62f","prefixes":{"":{"product":1135,"type":0}}}, // [Spritz Technology, Inc.] + {"hash":"cefbe9240a377d95","prefixes":{"":{"product":1136,"type":1}}}, // [Wix.com] + {"hash":"a56824227bb496f7","prefixes":{"*":{"product":1137,"type":0}}}, // [TapTap Networks] + {"hash":"41f2ae7d2d6939ae","prefixes":{"":{"product":1137,"type":0}}}, // [TapTap Networks] + {"hash":"51fd8b1d5b983b31","prefixes":{"":{"product":1138,"type":0}}}, // [Permodo] + {"hash":"12c3d246c6d4e6b1","prefixes":{"":{"product":1138,"type":0}}}, // [Permodo] + {"hash":"69da2bfa4e414e2c","prefixes":{"":{"product":1138,"type":0}}}, // [Permodo] + {"hash":"67bb1e3460d8e2eb","prefixes":{"":{"product":1138,"type":0}}}, // [Permodo] + {"hash":"38912558a11ff73e","prefixes":{"":{"product":1138,"type":0}}}, // [Permodo] + {"hash":"eb4d36cf5e4909c1","prefixes":{"":{"product":1139,"type":0}}}, // [Gaiam, Inc.] + {"hash":"16578371f24a5e90","prefixes":{"":{"product":1140,"type":0}}}, // [Plusing interactive co.,Ltd] + {"hash":"ecdb68bd2622aa9e","prefixes":{"":{"product":42,"type":0}}}, // [Clinch.co] + {"hash":"8adccb3847cc8b0f","prefixes":{"":{"product":42,"type":0}}}, // [Clinch.co] + {"hash":"2b5433780334b542","prefixes":{"":{"product":42,"type":0}}}, // [Clinch.co] + {"hash":"c853c92986d0cc90","prefixes":{"":{"product":42,"type":0}}}, // [Clinch.co] + {"hash":"388da33e7f0adca1","prefixes":{"":{"product":42,"type":0}}}, // [Clinch.co] + {"hash":"03d7a65aa1bc87bc","prefixes":{"":{"product":1141,"type":0}}}, // [Paypersale] + {"hash":"176eb71c0938f4a5","prefixes":{"":{"product":111,"type":0}}}, // [Epic Combo Malta Ltd.] + {"hash":"4366ec3ae9f41f7c","prefixes":{"":{"product":111,"type":0}}}, // [Epic Combo Malta Ltd.] + {"hash":"2e9617ef727ff0b5","prefixes":{"":{"product":1142,"type":0}}}, // [OCP Collective Corp. (d/b/a AdCade)] + {"hash":"11d6d13e3eb48a86","prefixes":{"":{"product":1142,"type":0}}}, // [OCP Collective Corp. (d/b/a AdCade)] + {"hash":"20e14ef573248fec","prefixes":{"":{"product":1142,"type":0}}}, // [OCP Collective Corp. (d/b/a AdCade)] + {"hash":"234345fe3c0da842","prefixes":{"":{"product":1142,"type":0}}}, // [OCP Collective Corp. (d/b/a AdCade)] + {"hash":"30fb60c9c450221d","prefixes":{"":{"product":1142,"type":0}}}, // [OCP Collective Corp. (d/b/a AdCade)] + {"hash":"69ddc7852224e18f","prefixes":{"":{"product":1143,"type":1}}}, // [ESV Digital] + {"hash":"240174bad001108d","prefixes":{"":{"product":1144,"type":0}}}, // [RevJet LLC.] + {"hash":"5250a7a3f2e4f73a","prefixes":{"":{"product":1144,"type":0}}}, // [RevJet LLC.] + {"hash":"590feb6b793ba20a","prefixes":{"":{"product":1144,"type":0}}}, // [RevJet LLC.] + {"hash":"23db13cb66f769e3","prefixes":{"":{"product":1145,"type":0}}}, // [GET IT Mobile, Inc] + {"hash":"cd7cd6c16f714024","prefixes":{"":{"product":1145,"type":0}}}, // [GET IT Mobile, Inc] + {"hash":"00ea35d76275dbeb","prefixes":{"":{"product":1145,"type":0}}}, // [GET IT Mobile, Inc] + {"hash":"5239cdae00ff02ea","prefixes":{"":{"product":1146,"type":0}}}, // [IBM] + {"hash":"e2c539bef8d2970c","prefixes":{"":{"product":1147,"type":1}}}, // [Lucid Holdings, LLC] + {"hash":"7078be8707b5ec93","prefixes":{"":{"product":1147,"type":1}}}, // [Lucid Holdings, LLC] + {"hash":"d65fe9ed9f23afbd","prefixes":{"":{"product":1148,"type":1}}}, // [Stratio Big Data Inc.] + {"hash":"9ccfc7f2ecfbaeec","prefixes":{"":{"product":1148,"type":1}}}, // [Stratio Big Data Inc.] + {"hash":"54e80254bbf4e20b","prefixes":{"":{"product":1149,"type":0}}}, // [Tripping.com] {"hash":"4aaf263b4bae6cd1","prefixes":{"":{"product":1150}}}, // [Vidible] {"hash":"b782d6c10170e732","prefixes":{"":{"product":1150}}}, // [Vidible] {"hash":"ceef29c52329c405","prefixes":{"":{"product":1150}}}, // [Vidible] @@ -5671,569 +5669,569 @@ {"hash":"b2529b7ebc0cbb27","prefixes":{"":{"product":1150}}}, // [Vidible] {"hash":"14ebf9b0cbed945c","prefixes":{"":{"product":1150}}}, // [Vidible] {"hash":"048147eea378ee03","prefixes":{"":{"product":1150}}}, // [Vidible] - {"hash":"7b61440491bd2a65","prefixes":{"":{"product":1151}}}, // [MiMTiD Corp] - {"hash":"036455e7801e853e","prefixes":{"":{"product":1151}}}, // [MiMTiD Corp] - {"hash":"e631f0342d59176b","prefixes":{"":{"product":1152}}}, // [Moloco, Inc.] - {"hash":"87938522c669c682","prefixes":{"":{"product":1152}}}, // [Moloco, Inc.] - {"hash":"a102c87f9921beb6","prefixes":{"":{"product":1153}}}, // [MEC SP. Z O.O] - {"hash":"f9133e4a069a0f4f","prefixes":{"":{"product":1153}}}, // [MEC SP. Z O.O] - {"hash":"6c7737c0ecbf0d91","prefixes":{"":{"product":1153}}}, // [MEC SP. Z O.O] - {"hash":"a82a0c18f6dfb959","prefixes":{"":{"product":1153}}}, // [MEC SP. Z O.O] - {"hash":"e1bea08ea38dc600","prefixes":{"":{"product":1154}}}, // [Abudantia LLC] - {"hash":"d60e1ada8dfa48fa","prefixes":{"":{"product":1154}}}, // [Abudantia LLC] - {"hash":"b57f7b99f9deda72","prefixes":{"":{"product":1154}}}, // [Abudantia LLC] - {"hash":"63f93976910e4aff","prefixes":{"":{"product":1154}}}, // [Abudantia LLC] - {"hash":"93a75f3f5174e472","prefixes":{"":{"product":1154}}}, // [Abudantia LLC] - {"hash":"ba1500537064494c","prefixes":{"":{"product":1155}}}, // [Realzeit] - {"hash":"ce1c3e183853dec6","prefixes":{"":{"product":1156}}}, // [Shanghai DigitalMatrix Information Technology Co.] - {"hash":"697384881bfb9a85","prefixes":{"":{"product":1156}}}, // [Shanghai DigitalMatrix Information Technology Co.] - {"hash":"3b5e1e5d71bb095f","prefixes":{"":{"product":1156}}}, // [Shanghai DigitalMatrix Information Technology Co.] - {"hash":"a55289ec43a1fd1c","prefixes":{"":{"product":1156}}}, // [Shanghai DigitalMatrix Information Technology Co.] - {"hash":"0ea122741b5a296d","prefixes":{"":{"product":1156}}}, // [Shanghai DigitalMatrix Information Technology Co.] - {"hash":"139c147db4a66d45","prefixes":{"":{"product":1156}}}, // [Shanghai DigitalMatrix Information Technology Co.] - {"hash":"91a98ad80489e2aa","prefixes":{"":{"product":1156}}}, // [Shanghai DigitalMatrix Information Technology Co.] - {"hash":"276f5a9d0ed20d4a","prefixes":{"":{"product":1156}}}, // [Shanghai DigitalMatrix Information Technology Co.] - {"hash":"8408cf6c93d2f24f","prefixes":{"":{"product":1157}}}, // [Alkemics] - {"hash":"658222dab2aa692d","prefixes":{"":{"product":1157}}}, // [Alkemics] - {"hash":"8835156415ef5c70","prefixes":{"":{"product":1157}}}, // [Alkemics] - {"hash":"7d76d0b7c2c49e1c","prefixes":{"":{"product":1158}}}, // [Sodel Software Solutions Pvt. Ltd.] - {"hash":"26b315a19bf762cb","prefixes":{"":{"product":1159}}}, // [Clearstream.TV, Inc] - {"hash":"80ce05889af3bb0e","prefixes":{"":{"product":1159}}}, // [Clearstream.TV, Inc] - {"hash":"2d9798f06f3cd0f8","prefixes":{"":{"product":1159}}}, // [Clearstream.TV, Inc] - {"hash":"4724e51f601e7bfa","prefixes":{"":{"product":1160}}}, // [KuaiziTech] - {"hash":"e0f93294ef7c3cb7","prefixes":{"":{"product":1160}}}, // [KuaiziTech] - {"hash":"ed1e0f5237be934f","prefixes":{"":{"product":1160}}}, // [KuaiziTech] - {"hash":"4a0011b21f8d95f9","prefixes":{"":{"product":1160}}}, // [KuaiziTech] - {"hash":"1af9efa73c3b3b29","prefixes":{"":{"product":1160}}}, // [KuaiziTech] - {"hash":"49eea06f0c13da7f","prefixes":{"":{"product":1160}}}, // [KuaiziTech] - {"hash":"584459c8cfe5595f","prefixes":{"":{"product":1160}}}, // [KuaiziTech] - {"hash":"3b72d8e306588e71","prefixes":{"":{"product":1160}}}, // [KuaiziTech] - {"hash":"f8d6e6d127d9c894","prefixes":{"":{"product":1161}}}, // [Adluxe] - {"hash":"93d864f5e43a3230","prefixes":{"":{"product":1161}}}, // [Adluxe] - {"hash":"793d5c9c5c35b0d9","prefixes":{"":{"product":1161}}}, // [Adluxe] - {"hash":"7b9c5864364d5f5e","prefixes":{"*":{"product":1162}}}, // [NinthDecimal] - {"hash":"7c86152a561c4b4b","prefixes":{"*":{"product":1162}}}, // [NinthDecimal] - {"hash":"ec998efdf99b0c51","prefixes":{"*":{"product":1163}}}, // [RICH MEDIA STUDIO] - {"hash":"e83c01ec741a261e","prefixes":{"":{"product":1164}}}, // [TenMax Co., Ltd.] - {"hash":"e333d70ac6d1acda","prefixes":{"":{"product":1165}}}, // [twiago GmbH] - {"hash":"bb81d5fd8a052b7f","prefixes":{"":{"product":1166}}}, // [Ad Dynamo International (Pty) Ltd] - {"hash":"55b2516509252adb","prefixes":{"":{"product":1166}}}, // [Ad Dynamo International (Pty) Ltd] - {"hash":"59e4e15b4fe6dccd","prefixes":{"":{"product":1166}}}, // [Ad Dynamo International (Pty) Ltd] - {"hash":"f5005d7a14ac0a47","prefixes":{"":{"product":1166}}}, // [Ad Dynamo International (Pty) Ltd] - {"hash":"ecf3dd9926cbe25e","prefixes":{"":{"product":1166}}}, // [Ad Dynamo International (Pty) Ltd] - {"hash":"2ccdffccbbf20e3f","prefixes":{"":{"product":1167}}}, // [Swarm Enterprises Inc] - {"hash":"bf0dd6fdbc53dfee","prefixes":{"":{"product":112}}}, // [Quixey] - {"hash":"ac6a75f10f9f0391","prefixes":{"":{"product":1168}}}, // [Media Forum] - {"hash":"2b5f5e731d08116b","prefixes":{"":{"product":1168}}}, // [Media Forum] - {"hash":"8bf2fe7f00b3c760","prefixes":{"":{"product":1169}}}, // [Beeswax.io] - {"hash":"480bd3bc762861ae","prefixes":{"":{"product":1170}}}, // [Varick Media Management] - {"hash":"d9faa36410c39273","prefixes":{"":{"product":1170}}}, // [Varick Media Management] - {"hash":"6114cbf7f45fd639","prefixes":{"":{"product":1171}}}, // [JD] - {"hash":"739568f083f383e2","prefixes":{"":{"product":1171}}}, // [JD] - {"hash":"1fc63d36c1d330fa","prefixes":{"":{"product":1171}}}, // [JD] - {"hash":"bdb07c050de0bbd2","prefixes":{"":{"product":1171}}}, // [JD] - {"hash":"6b6a891a61b05435","prefixes":{"":{"product":1172}}}, // [Lotlinx Inc.] - {"hash":"b7831e02a1168f7b","prefixes":{"":{"product":1172}}}, // [Lotlinx Inc.] + {"hash":"7b61440491bd2a65","prefixes":{"":{"product":1151,"type":0}}}, // [MiMTiD Corp] + {"hash":"036455e7801e853e","prefixes":{"":{"product":1151,"type":0}}}, // [MiMTiD Corp] + {"hash":"e631f0342d59176b","prefixes":{"":{"product":1152,"type":0}}}, // [Moloco, Inc.] + {"hash":"87938522c669c682","prefixes":{"":{"product":1152,"type":0}}}, // [Moloco, Inc.] + {"hash":"a102c87f9921beb6","prefixes":{"":{"product":1153,"type":1}}}, // [MEC SP. Z O.O] + {"hash":"f9133e4a069a0f4f","prefixes":{"":{"product":1153,"type":1}}}, // [MEC SP. Z O.O] + {"hash":"6c7737c0ecbf0d91","prefixes":{"":{"product":1153,"type":1}}}, // [MEC SP. Z O.O] + {"hash":"a82a0c18f6dfb959","prefixes":{"":{"product":1153,"type":1}}}, // [MEC SP. Z O.O] + {"hash":"e1bea08ea38dc600","prefixes":{"":{"product":1154,"type":0}}}, // [Abudantia LLC] + {"hash":"d60e1ada8dfa48fa","prefixes":{"":{"product":1154,"type":0}}}, // [Abudantia LLC] + {"hash":"b57f7b99f9deda72","prefixes":{"":{"product":1154,"type":0}}}, // [Abudantia LLC] + {"hash":"63f93976910e4aff","prefixes":{"":{"product":1154,"type":0}}}, // [Abudantia LLC] + {"hash":"93a75f3f5174e472","prefixes":{"":{"product":1154,"type":0}}}, // [Abudantia LLC] + {"hash":"ba1500537064494c","prefixes":{"":{"product":1155,"type":0}}}, // [Realzeit] + {"hash":"ce1c3e183853dec6","prefixes":{"":{"product":1156,"type":0}}}, // [Shanghai DigitalMatrix Information Technology Co.] + {"hash":"697384881bfb9a85","prefixes":{"":{"product":1156,"type":0}}}, // [Shanghai DigitalMatrix Information Technology Co.] + {"hash":"3b5e1e5d71bb095f","prefixes":{"":{"product":1156,"type":0}}}, // [Shanghai DigitalMatrix Information Technology Co.] + {"hash":"a55289ec43a1fd1c","prefixes":{"":{"product":1156,"type":0}}}, // [Shanghai DigitalMatrix Information Technology Co.] + {"hash":"0ea122741b5a296d","prefixes":{"":{"product":1156,"type":0}}}, // [Shanghai DigitalMatrix Information Technology Co.] + {"hash":"139c147db4a66d45","prefixes":{"":{"product":1156,"type":0}}}, // [Shanghai DigitalMatrix Information Technology Co.] + {"hash":"91a98ad80489e2aa","prefixes":{"":{"product":1156,"type":0}}}, // [Shanghai DigitalMatrix Information Technology Co.] + {"hash":"276f5a9d0ed20d4a","prefixes":{"":{"product":1156,"type":0}}}, // [Shanghai DigitalMatrix Information Technology Co.] + {"hash":"8408cf6c93d2f24f","prefixes":{"":{"product":1157,"type":1}}}, // [Alkemics] + {"hash":"658222dab2aa692d","prefixes":{"":{"product":1157,"type":1}}}, // [Alkemics] + {"hash":"8835156415ef5c70","prefixes":{"":{"product":1157,"type":1}}}, // [Alkemics] + {"hash":"7d76d0b7c2c49e1c","prefixes":{"":{"product":1158,"type":0}}}, // [Sodel Software Solutions Pvt. Ltd.] + {"hash":"26b315a19bf762cb","prefixes":{"":{"product":1159,"type":0}}}, // [Clearstream.TV, Inc] + {"hash":"80ce05889af3bb0e","prefixes":{"":{"product":1159,"type":0}}}, // [Clearstream.TV, Inc] + {"hash":"2d9798f06f3cd0f8","prefixes":{"":{"product":1159,"type":0}}}, // [Clearstream.TV, Inc] + {"hash":"4724e51f601e7bfa","prefixes":{"":{"product":1160,"type":0}}}, // [KuaiziTech] + {"hash":"e0f93294ef7c3cb7","prefixes":{"":{"product":1160,"type":0}}}, // [KuaiziTech] + {"hash":"ed1e0f5237be934f","prefixes":{"":{"product":1160,"type":0}}}, // [KuaiziTech] + {"hash":"4a0011b21f8d95f9","prefixes":{"":{"product":1160,"type":0}}}, // [KuaiziTech] + {"hash":"1af9efa73c3b3b29","prefixes":{"":{"product":1160,"type":0}}}, // [KuaiziTech] + {"hash":"49eea06f0c13da7f","prefixes":{"":{"product":1160,"type":0}}}, // [KuaiziTech] + {"hash":"584459c8cfe5595f","prefixes":{"":{"product":1160,"type":0}}}, // [KuaiziTech] + {"hash":"3b72d8e306588e71","prefixes":{"":{"product":1160,"type":0}}}, // [KuaiziTech] + {"hash":"f8d6e6d127d9c894","prefixes":{"":{"product":1161,"type":0}}}, // [Adluxe] + {"hash":"93d864f5e43a3230","prefixes":{"":{"product":1161,"type":0}}}, // [Adluxe] + {"hash":"793d5c9c5c35b0d9","prefixes":{"":{"product":1161,"type":0}}}, // [Adluxe] + {"hash":"7b9c5864364d5f5e","prefixes":{"*":{"product":1162,"type":1}}}, // [NinthDecimal] + {"hash":"7c86152a561c4b4b","prefixes":{"*":{"product":1162,"type":1}}}, // [NinthDecimal] + {"hash":"ec998efdf99b0c51","prefixes":{"*":{"product":1163,"type":0}}}, // [RICH MEDIA STUDIO] + {"hash":"e83c01ec741a261e","prefixes":{"":{"product":1164,"type":0}}}, // [TenMax Co., Ltd.] + {"hash":"e333d70ac6d1acda","prefixes":{"":{"product":1165,"type":0}}}, // [twiago GmbH] + {"hash":"bb81d5fd8a052b7f","prefixes":{"":{"product":1166,"type":0}}}, // [Ad Dynamo International (Pty) Ltd] + {"hash":"55b2516509252adb","prefixes":{"":{"product":1166,"type":0}}}, // [Ad Dynamo International (Pty) Ltd] + {"hash":"59e4e15b4fe6dccd","prefixes":{"":{"product":1166,"type":0}}}, // [Ad Dynamo International (Pty) Ltd] + {"hash":"f5005d7a14ac0a47","prefixes":{"":{"product":1166,"type":0}}}, // [Ad Dynamo International (Pty) Ltd] + {"hash":"ecf3dd9926cbe25e","prefixes":{"":{"product":1166,"type":0}}}, // [Ad Dynamo International (Pty) Ltd] + {"hash":"2ccdffccbbf20e3f","prefixes":{"":{"product":1167,"type":1}}}, // [Swarm Enterprises Inc] + {"hash":"bf0dd6fdbc53dfee","prefixes":{"":{"product":112,"type":0}}}, // [Quixey] + {"hash":"ac6a75f10f9f0391","prefixes":{"":{"product":1168,"type":0}}}, // [Media Forum] + {"hash":"2b5f5e731d08116b","prefixes":{"":{"product":1168,"type":0}}}, // [Media Forum] + {"hash":"8bf2fe7f00b3c760","prefixes":{"":{"product":1169,"type":0}}}, // [Beeswax.io] + {"hash":"480bd3bc762861ae","prefixes":{"":{"product":1170,"type":0}}}, // [Varick Media Management] + {"hash":"d9faa36410c39273","prefixes":{"":{"product":1170,"type":0}}}, // [Varick Media Management] + {"hash":"6114cbf7f45fd639","prefixes":{"":{"product":1171,"type":0}}}, // [JD] + {"hash":"739568f083f383e2","prefixes":{"":{"product":1171,"type":0}}}, // [JD] + {"hash":"1fc63d36c1d330fa","prefixes":{"":{"product":1171,"type":0}}}, // [JD] + {"hash":"bdb07c050de0bbd2","prefixes":{"":{"product":1171,"type":0}}}, // [JD] + {"hash":"6b6a891a61b05435","prefixes":{"":{"product":1172,"type":0}}}, // [Lotlinx Inc.] + {"hash":"b7831e02a1168f7b","prefixes":{"":{"product":1172,"type":0}}}, // [Lotlinx Inc.] {"hash":"78f18ca9103e6031","prefixes":{"":{"product":1173}}}, // [Lotlinx Inc] - {"hash":"9a1f751c74a01145","prefixes":{"":{"product":40}}}, // [F# Inc.] - {"hash":"09ddf4e3268e6597","prefixes":{"":{"product":1174}}}, // [Ingenio, LLC] - {"hash":"c5dd0849ac2febc6","prefixes":{"":{"product":1175}}}, // [MVMT Watches] - {"hash":"3b471f8f08410883","prefixes":{"":{"product":1176}}}, // [C1X Inc] - {"hash":"1bb74ab211a41c9c","prefixes":{"":{"product":1177}}}, // [Vitro Agency] - {"hash":"96c0acfcd81b2dd4","prefixes":{"":{"product":1178}}}, // [Kabbage] - {"hash":"0e5b93a6bd6f704b","prefixes":{"":{"product":1179}}}, // [Redbranch, Inc. (dba Fraudlogix)] - {"hash":"a810be7236bf948f","prefixes":{"":{"product":1180}}}, // [AutoWeb, Inc.] - {"hash":"ffe13e4342fd9a35","prefixes":{"":{"product":1180}}}, // [AutoWeb, Inc.] - {"hash":"91d97869f45df6e0","prefixes":{"":{"product":1180}}}, // [AutoWeb, Inc.] - {"hash":"c9f1716ec9d29c4b","prefixes":{"":{"product":1180}}}, // [AutoWeb, Inc.] - {"hash":"4a9148e717cb46a9","prefixes":{"":{"product":1180}}}, // [AutoWeb, Inc.] - {"hash":"9b57b296c2edd01c","prefixes":{"":{"product":1180}}}, // [AutoWeb, Inc.] - {"hash":"1db72ea880eb28dc","prefixes":{"":{"product":1180}}}, // [AutoWeb, Inc.] - {"hash":"61889d0078dd40a7","prefixes":{"":{"product":1180}}}, // [AutoWeb, Inc.] - {"hash":"fd8f5971bf862430","prefixes":{"":{"product":1180}}}, // [AutoWeb, Inc.] - {"hash":"d0da5b57fc3b9611","prefixes":{"":{"product":1180}}}, // [AutoWeb, Inc.] - {"hash":"00449172b70d520c","prefixes":{"":{"product":1180}}}, // [AutoWeb, Inc.] - {"hash":"7b3027f5a6cb4f20","prefixes":{"":{"product":1181}}}, // [Aimee Soft Ltd.] - {"hash":"c29f58ba8b9fccc8","prefixes":{"":{"product":1181}}}, // [Aimee Soft Ltd.] - {"hash":"e8cb0d7824f08de4","prefixes":{"":{"product":1181}}}, // [Aimee Soft Ltd.] - {"hash":"97efe77626897346","prefixes":{"":{"product":1181}}}, // [Aimee Soft Ltd.] - {"hash":"78afe44858076c81","prefixes":{"":{"product":1181}}}, // [Aimee Soft Ltd.] - {"hash":"f5162869e573dcd7","prefixes":{"":{"product":1182}}}, // [SAS Azameo] - {"hash":"3d35f5eb2971f5fe","prefixes":{"":{"product":17}}}, // [iJento] - {"hash":"b98ddad6854c87b1","prefixes":{"":{"product":1183}}}, // [Keyade] - {"hash":"65aab53cd46ccc7f","prefixes":{"":{"product":1184}}}, // [Digital To Store (DTS)] - {"hash":"e1e5e1a4c7857257","prefixes":{"":{"product":1184}}}, // [Digital To Store (DTS)] - {"hash":"c9f6517091430433","prefixes":{"":{"product":1184}}}, // [Digital To Store (DTS)] - {"hash":"76d9ee307388af98","prefixes":{"":{"product":1184}}}, // [Digital To Store (DTS)] - {"hash":"8fdb48d3b5466119","prefixes":{"":{"product":1184}}}, // [Digital To Store (DTS)] - {"hash":"bd53e2fe0c663545","prefixes":{"":{"product":1185}}}, // [Media iQ Digital] - {"hash":"58b54a485703f6ba","prefixes":{"":{"product":1185}}}, // [Media iQ Digital] - {"hash":"35616fb4ea0feb94","prefixes":{"":{"product":1185}}}, // [Media iQ Digital] - {"hash":"0a1563142096ed40","prefixes":{"":{"product":1186}}}, // [Ingenious Technologies] - {"hash":"427d170b486c74e6","prefixes":{"":{"product":1186}}}, // [Ingenious Technologies] - {"hash":"79480a2b5de32430","prefixes":{"":{"product":1186}}}, // [Ingenious Technologies] - {"hash":"aaf44b046fb5c10d","prefixes":{"":{"product":1187}}}, // [Sonicmoov co.,ltd] - {"hash":"e5d30ca87b591280","prefixes":{"":{"product":1187}}}, // [Sonicmoov co.,ltd] - {"hash":"9ec9f8d7f0fc8c4a","prefixes":{"":{"product":1187}}}, // [Sonicmoov co.,ltd] - {"hash":"dd0bf16db1e39f59","prefixes":{"":{"product":1187}}}, // [Sonicmoov co.,ltd] - {"hash":"b32a4da2bc7363a0","prefixes":{"":{"product":1188}}}, // [Bonadza LLC] - {"hash":"66a81343ae0223df","prefixes":{"":{"product":1188}}}, // [Bonadza LLC] - {"hash":"ae76287d25b463d2","prefixes":{"":{"product":1188}}}, // [Bonadza LLC] - {"hash":"7429b926177d09a6","prefixes":{"":{"product":1188}}}, // [Bonadza LLC] - {"hash":"170cc20a9af99287","prefixes":{"":{"product":1189}}}, // [Axis Shift Limited] - {"hash":"6e94333e674450ec","prefixes":{"":{"product":1190}}}, // [TreSensa, Inc.] - {"hash":"8fac335d75d968fd","prefixes":{"":{"product":1190}}}, // [TreSensa, Inc.] - {"hash":"eec936c95af6b31f","prefixes":{"":{"product":1190}}}, // [TreSensa, Inc.] - {"hash":"3c744b206f15c46d","prefixes":{"":{"product":1190}}}, // [TreSensa, Inc.] - {"hash":"049a71c722403987","prefixes":{"":{"product":1191}}}, // [Media Logic Group LLC dba AerisWeather LLC] - {"hash":"efa6686cf4b6b73c","prefixes":{"":{"product":57}}}, // [DeinDeal AG] - {"hash":"847219545b169784","prefixes":{"":{"product":1192}}}, // [Fugumobile] - {"hash":"790ab0ec39724b71","prefixes":{"":{"product":1193}}}, // [Localstars Ltd] - {"hash":"0133a556a80fd808","prefixes":{"":{"product":1194}}}, // [Fluidads] - {"hash":"fc8901303bada188","prefixes":{"":{"product":1194}}}, // [Fluidads] - {"hash":"ba549c39b1f43523","prefixes":{"*":{"product":1195}}}, // [Wayfair LLC] - {"hash":"5d0b84261f7b6d5c","prefixes":{"*":{"product":1195}}}, // [Wayfair LLC] - {"hash":"d48dde21b5917906","prefixes":{"*":{"product":1195}}}, // [Wayfair LLC] - {"hash":"337dabe98702ae52","prefixes":{"*":{"product":1195}}}, // [Wayfair LLC] - {"hash":"efad84d0a4dd4e46","prefixes":{"*":{"product":1195}}}, // [Wayfair LLC] - {"hash":"019c3ee24427b355","prefixes":{"*":{"product":1195}}}, // [Wayfair LLC] - {"hash":"ec79c848ccf2d648","prefixes":{"*":{"product":1195}}}, // [Wayfair LLC] - {"hash":"ccf7fd5647b92698","prefixes":{"*":{"product":1195}}}, // [Wayfair LLC] - {"hash":"3b03a24eea2a6345","prefixes":{"":{"product":1196}}}, // [VCCORP CORPORATION] - {"hash":"f7f53c88139460cf","prefixes":{"":{"product":1197}}}, // [IGAWorks] - {"hash":"93b9518285f54887","prefixes":{"":{"product":1198}}}, // [Cellcom Ltd] - {"hash":"f59e6427783c3da0","prefixes":{"*":{"product":1199}}}, // [Upsolver] - {"hash":"adb55d98bb4aef6e","prefixes":{"":{"product":1199}}}, // [Upsolver] - {"hash":"7efba976eeea2d41","prefixes":{"":{"product":1199}}}, // [Upsolver] - {"hash":"cdde375c1240991d","prefixes":{"":{"product":935}}}, // [Channel Factory, LLC] - {"hash":"79c4dc57905857aa","prefixes":{"":{"product":1200}}}, // [Phluidmedia, Inc.] - {"hash":"4948ea141d1a72e1","prefixes":{"":{"product":1200}}}, // [Phluidmedia, Inc.] - {"hash":"e4aed5bf5c295c3a","prefixes":{"":{"product":1201}}}, // [Roy Morgan Research Ltd] - {"hash":"547734f17effda77","prefixes":{"":{"product":1202}}}, // [TapSense, Inc.] - {"hash":"96289aeef06d0a9f","prefixes":{"":{"product":1203}}}, // [Southwest Airlines] - {"hash":"de497c6fbed4588d","prefixes":{"":{"product":794}}}, // [Hatena Co., Ltd] - {"hash":"91412d534d321cb4","prefixes":{"":{"product":1204}}}, // [Market Points, Inc.] - {"hash":"97aab20dd873dd2c","prefixes":{"":{"product":1205}}}, // [UberMedia Inc.] - {"hash":"73cadeea8e1bd9e8","prefixes":{"":{"product":1205}}}, // [UberMedia Inc.] - {"hash":"0e1bd2938a06a2e6","prefixes":{"":{"product":1206}}}, // [Kadam SIA] - {"hash":"aa9658253aa81e62","prefixes":{"":{"product":1206}}}, // [Kadam SIA] - {"hash":"75f1eab33abfa4f9","prefixes":{"":{"product":1206}}}, // [Kadam SIA] - {"hash":"59f64b09b8e430ae","prefixes":{"":{"product":1206}}}, // [Kadam SIA] - {"hash":"61947a042af2e3e8","prefixes":{"":{"product":1207}}}, // [Alveo Platform (VMM own bidder)] - {"hash":"62c095e8dfbb0458","prefixes":{"":{"product":1208}}}, // [Adbalancer EDV-DienstleistungsgesellschaftgmbH] - {"hash":"5cc57103c26df76f","prefixes":{"":{"product":1208}}}, // [Adbalancer EDV-DienstleistungsgesellschaftgmbH] - {"hash":"53685a43fc711ea4","prefixes":{"":{"product":1209}}}, // [JWPlayer] - {"hash":"53bdf03af7a44e2c","prefixes":{"":{"product":1209}}}, // [JWPlayer] - {"hash":"eaff21a1a9591dab","prefixes":{"":{"product":1209}}}, // [JWPlayer] - {"hash":"1d5626ba7394e6a1","prefixes":{"":{"product":1209}}}, // [JWPlayer] - {"hash":"2e106bd1d1d064c6","prefixes":{"":{"product":1209}}}, // [JWPlayer] - {"hash":"9f7691306b0805ea","prefixes":{"":{"product":1209}}}, // [JWPlayer] - {"hash":"909df8f91bd33085","prefixes":{"*":{"product":1210}}}, // [Adiquity Technologies Pvt Ltd] - {"hash":"d1eca614d3cc8883","prefixes":{"":{"product":1211}}}, // [Smart Digital GmbH] - {"hash":"53d8de6b018c1793","prefixes":{"":{"product":1212}}}, // [Auditorius LLC] - {"hash":"fd9a420ade305e17","prefixes":{"":{"product":1213}}}, // [Treepodia] - {"hash":"c9fd06f055d4af40","prefixes":{"":{"product":1213}}}, // [Treepodia] - {"hash":"6eb24d470a6f1018","prefixes":{"":{"product":1213}}}, // [Treepodia] - {"hash":"e35bb07367786d4c","prefixes":{"":{"product":1214}}}, // [Adamatic] - {"hash":"3943df18ad20915d","prefixes":{"":{"product":1214}}}, // [Adamatic] - {"hash":"341d248dc25e4ea7","prefixes":{"":{"product":1214}}}, // [Adamatic] - {"hash":"ad1f1681bab5cc6b","prefixes":{"":{"product":1215}}}, // [SAS Web2ROI] - {"hash":"532b5bfa711f405e","prefixes":{"":{"product":1216}}}, // [Cardlytics] + {"hash":"9a1f751c74a01145","prefixes":{"":{"product":40,"type":0}}}, // [F# Inc.] + {"hash":"09ddf4e3268e6597","prefixes":{"":{"product":1174,"type":1}}}, // [Ingenio, LLC] + {"hash":"c5dd0849ac2febc6","prefixes":{"":{"product":1175,"type":0}}}, // [MVMT Watches] + {"hash":"3b471f8f08410883","prefixes":{"":{"product":1176,"type":0}}}, // [C1X Inc] + {"hash":"1bb74ab211a41c9c","prefixes":{"":{"product":1177,"type":0}}}, // [Vitro Agency] + {"hash":"96c0acfcd81b2dd4","prefixes":{"":{"product":1178,"type":0}}}, // [Kabbage] + {"hash":"0e5b93a6bd6f704b","prefixes":{"":{"product":1179,"type":1}}}, // [Redbranch, Inc. (dba Fraudlogix)] + {"hash":"a810be7236bf948f","prefixes":{"":{"product":1180,"type":0}}}, // [AutoWeb, Inc.] + {"hash":"ffe13e4342fd9a35","prefixes":{"":{"product":1180,"type":0}}}, // [AutoWeb, Inc.] + {"hash":"91d97869f45df6e0","prefixes":{"":{"product":1180,"type":0}}}, // [AutoWeb, Inc.] + {"hash":"c9f1716ec9d29c4b","prefixes":{"":{"product":1180,"type":0}}}, // [AutoWeb, Inc.] + {"hash":"4a9148e717cb46a9","prefixes":{"":{"product":1180,"type":0}}}, // [AutoWeb, Inc.] + {"hash":"9b57b296c2edd01c","prefixes":{"":{"product":1180,"type":0}}}, // [AutoWeb, Inc.] + {"hash":"1db72ea880eb28dc","prefixes":{"":{"product":1180,"type":0}}}, // [AutoWeb, Inc.] + {"hash":"61889d0078dd40a7","prefixes":{"":{"product":1180,"type":0}}}, // [AutoWeb, Inc.] + {"hash":"fd8f5971bf862430","prefixes":{"":{"product":1180,"type":0}}}, // [AutoWeb, Inc.] + {"hash":"d0da5b57fc3b9611","prefixes":{"":{"product":1180,"type":0}}}, // [AutoWeb, Inc.] + {"hash":"00449172b70d520c","prefixes":{"":{"product":1180,"type":0}}}, // [AutoWeb, Inc.] + {"hash":"7b3027f5a6cb4f20","prefixes":{"":{"product":1181,"type":0}}}, // [Aimee Soft Ltd.] + {"hash":"c29f58ba8b9fccc8","prefixes":{"":{"product":1181,"type":0}}}, // [Aimee Soft Ltd.] + {"hash":"e8cb0d7824f08de4","prefixes":{"":{"product":1181,"type":0}}}, // [Aimee Soft Ltd.] + {"hash":"97efe77626897346","prefixes":{"":{"product":1181,"type":0}}}, // [Aimee Soft Ltd.] + {"hash":"78afe44858076c81","prefixes":{"":{"product":1181,"type":0}}}, // [Aimee Soft Ltd.] + {"hash":"f5162869e573dcd7","prefixes":{"":{"product":1182,"type":1}}}, // [SAS Azameo] + {"hash":"3d35f5eb2971f5fe","prefixes":{"":{"product":17,"type":1}}}, // [iJento] + {"hash":"b98ddad6854c87b1","prefixes":{"":{"product":1183,"type":1}}}, // [Keyade] + {"hash":"65aab53cd46ccc7f","prefixes":{"":{"product":1184,"type":0}}}, // [Digital To Store (DTS)] + {"hash":"e1e5e1a4c7857257","prefixes":{"":{"product":1184,"type":0}}}, // [Digital To Store (DTS)] + {"hash":"c9f6517091430433","prefixes":{"":{"product":1184,"type":0}}}, // [Digital To Store (DTS)] + {"hash":"76d9ee307388af98","prefixes":{"":{"product":1184,"type":0}}}, // [Digital To Store (DTS)] + {"hash":"8fdb48d3b5466119","prefixes":{"":{"product":1184,"type":0}}}, // [Digital To Store (DTS)] + {"hash":"bd53e2fe0c663545","prefixes":{"":{"product":1185,"type":0}}}, // [Media iQ Digital] + {"hash":"58b54a485703f6ba","prefixes":{"":{"product":1185,"type":0}}}, // [Media iQ Digital] + {"hash":"35616fb4ea0feb94","prefixes":{"":{"product":1185,"type":0}}}, // [Media iQ Digital] + {"hash":"0a1563142096ed40","prefixes":{"":{"product":1186,"type":1}}}, // [Ingenious Technologies] + {"hash":"427d170b486c74e6","prefixes":{"":{"product":1186,"type":1}}}, // [Ingenious Technologies] + {"hash":"79480a2b5de32430","prefixes":{"":{"product":1186,"type":1}}}, // [Ingenious Technologies] + {"hash":"aaf44b046fb5c10d","prefixes":{"":{"product":1187,"type":0}}}, // [Sonicmoov co.,ltd] + {"hash":"e5d30ca87b591280","prefixes":{"":{"product":1187,"type":0}}}, // [Sonicmoov co.,ltd] + {"hash":"9ec9f8d7f0fc8c4a","prefixes":{"":{"product":1187,"type":0}}}, // [Sonicmoov co.,ltd] + {"hash":"dd0bf16db1e39f59","prefixes":{"":{"product":1187,"type":0}}}, // [Sonicmoov co.,ltd] + {"hash":"b32a4da2bc7363a0","prefixes":{"":{"product":1188,"type":0}}}, // [Bonadza LLC] + {"hash":"66a81343ae0223df","prefixes":{"":{"product":1188,"type":0}}}, // [Bonadza LLC] + {"hash":"ae76287d25b463d2","prefixes":{"":{"product":1188,"type":0}}}, // [Bonadza LLC] + {"hash":"7429b926177d09a6","prefixes":{"":{"product":1188,"type":0}}}, // [Bonadza LLC] + {"hash":"170cc20a9af99287","prefixes":{"":{"product":1189,"type":0}}}, // [Axis Shift Limited] + {"hash":"6e94333e674450ec","prefixes":{"":{"product":1190,"type":0}}}, // [TreSensa, Inc.] + {"hash":"8fac335d75d968fd","prefixes":{"":{"product":1190,"type":0}}}, // [TreSensa, Inc.] + {"hash":"eec936c95af6b31f","prefixes":{"":{"product":1190,"type":0}}}, // [TreSensa, Inc.] + {"hash":"3c744b206f15c46d","prefixes":{"":{"product":1190,"type":0}}}, // [TreSensa, Inc.] + {"hash":"049a71c722403987","prefixes":{"":{"product":1191,"type":1}}}, // [Media Logic Group LLC dba AerisWeather LLC] + {"hash":"efa6686cf4b6b73c","prefixes":{"":{"product":57,"type":1}}}, // [DeinDeal AG] + {"hash":"847219545b169784","prefixes":{"":{"product":1192,"type":0}}}, // [Fugumobile] + {"hash":"790ab0ec39724b71","prefixes":{"":{"product":1193,"type":0}}}, // [Localstars Ltd] + {"hash":"0133a556a80fd808","prefixes":{"":{"product":1194,"type":0}}}, // [Fluidads] + {"hash":"fc8901303bada188","prefixes":{"":{"product":1194,"type":0}}}, // [Fluidads] + {"hash":"ba549c39b1f43523","prefixes":{"*":{"product":1195,"type":0}}}, // [Wayfair LLC] + {"hash":"5d0b84261f7b6d5c","prefixes":{"*":{"product":1195,"type":0}}}, // [Wayfair LLC] + {"hash":"d48dde21b5917906","prefixes":{"*":{"product":1195,"type":0}}}, // [Wayfair LLC] + {"hash":"337dabe98702ae52","prefixes":{"*":{"product":1195,"type":0}}}, // [Wayfair LLC] + {"hash":"efad84d0a4dd4e46","prefixes":{"*":{"product":1195,"type":0}}}, // [Wayfair LLC] + {"hash":"019c3ee24427b355","prefixes":{"*":{"product":1195,"type":0}}}, // [Wayfair LLC] + {"hash":"ec79c848ccf2d648","prefixes":{"*":{"product":1195,"type":0}}}, // [Wayfair LLC] + {"hash":"ccf7fd5647b92698","prefixes":{"*":{"product":1195,"type":0}}}, // [Wayfair LLC] + {"hash":"3b03a24eea2a6345","prefixes":{"":{"product":1196,"type":0}}}, // [VCCORP CORPORATION] + {"hash":"f7f53c88139460cf","prefixes":{"":{"product":1197,"type":0}}}, // [IGAWorks] + {"hash":"93b9518285f54887","prefixes":{"":{"product":1198,"type":0}}}, // [Cellcom Ltd] + {"hash":"f59e6427783c3da0","prefixes":{"*":{"product":1199,"type":0}}}, // [Upsolver] + {"hash":"adb55d98bb4aef6e","prefixes":{"":{"product":1199,"type":0}}}, // [Upsolver] + {"hash":"7efba976eeea2d41","prefixes":{"":{"product":1199,"type":0}}}, // [Upsolver] + {"hash":"cdde375c1240991d","prefixes":{"":{"product":935,"type":1}}}, // [Channel Factory, LLC] + {"hash":"79c4dc57905857aa","prefixes":{"":{"product":1200,"type":0}}}, // [Phluidmedia, Inc.] + {"hash":"4948ea141d1a72e1","prefixes":{"":{"product":1200,"type":0}}}, // [Phluidmedia, Inc.] + {"hash":"e4aed5bf5c295c3a","prefixes":{"":{"product":1201,"type":1}}}, // [Roy Morgan Research Ltd] + {"hash":"547734f17effda77","prefixes":{"":{"product":1202,"type":0}}}, // [TapSense, Inc.] + {"hash":"96289aeef06d0a9f","prefixes":{"":{"product":1203,"type":0}}}, // [Southwest Airlines] + {"hash":"de497c6fbed4588d","prefixes":{"":{"product":794,"type":1}}}, // [Hatena Co., Ltd] + {"hash":"91412d534d321cb4","prefixes":{"":{"product":1204,"type":1}}}, // [Market Points, Inc.] + {"hash":"97aab20dd873dd2c","prefixes":{"":{"product":1205,"type":0}}}, // [UberMedia Inc.] + {"hash":"73cadeea8e1bd9e8","prefixes":{"":{"product":1205,"type":0}}}, // [UberMedia Inc.] + {"hash":"0e1bd2938a06a2e6","prefixes":{"":{"product":1206,"type":0}}}, // [Kadam SIA] + {"hash":"aa9658253aa81e62","prefixes":{"":{"product":1206,"type":0}}}, // [Kadam SIA] + {"hash":"75f1eab33abfa4f9","prefixes":{"":{"product":1206,"type":0}}}, // [Kadam SIA] + {"hash":"59f64b09b8e430ae","prefixes":{"":{"product":1206,"type":0}}}, // [Kadam SIA] + {"hash":"61947a042af2e3e8","prefixes":{"":{"product":1207,"type":0}}}, // [Alveo Platform (VMM own bidder)] + {"hash":"62c095e8dfbb0458","prefixes":{"":{"product":1208,"type":0}}}, // [Adbalancer EDV-DienstleistungsgesellschaftgmbH] + {"hash":"5cc57103c26df76f","prefixes":{"":{"product":1208,"type":0}}}, // [Adbalancer EDV-DienstleistungsgesellschaftgmbH] + {"hash":"53685a43fc711ea4","prefixes":{"":{"product":1209,"type":0}}}, // [JWPlayer] + {"hash":"53bdf03af7a44e2c","prefixes":{"":{"product":1209,"type":0}}}, // [JWPlayer] + {"hash":"eaff21a1a9591dab","prefixes":{"":{"product":1209,"type":0}}}, // [JWPlayer] + {"hash":"1d5626ba7394e6a1","prefixes":{"":{"product":1209,"type":0}}}, // [JWPlayer] + {"hash":"2e106bd1d1d064c6","prefixes":{"":{"product":1209,"type":0}}}, // [JWPlayer] + {"hash":"9f7691306b0805ea","prefixes":{"":{"product":1209,"type":0}}}, // [JWPlayer] + {"hash":"909df8f91bd33085","prefixes":{"*":{"product":1210,"type":0}}}, // [Adiquity Technologies Pvt Ltd] + {"hash":"d1eca614d3cc8883","prefixes":{"":{"product":1211,"type":1}}}, // [Smart Digital GmbH] + {"hash":"53d8de6b018c1793","prefixes":{"":{"product":1212,"type":0}}}, // [Auditorius LLC] + {"hash":"fd9a420ade305e17","prefixes":{"":{"product":1213,"type":0}}}, // [Treepodia] + {"hash":"c9fd06f055d4af40","prefixes":{"":{"product":1213,"type":0}}}, // [Treepodia] + {"hash":"6eb24d470a6f1018","prefixes":{"":{"product":1213,"type":0}}}, // [Treepodia] + {"hash":"e35bb07367786d4c","prefixes":{"":{"product":1214,"type":0}}}, // [Adamatic] + {"hash":"3943df18ad20915d","prefixes":{"":{"product":1214,"type":0}}}, // [Adamatic] + {"hash":"341d248dc25e4ea7","prefixes":{"":{"product":1214,"type":0}}}, // [Adamatic] + {"hash":"ad1f1681bab5cc6b","prefixes":{"":{"product":1215,"type":1}}}, // [SAS Web2ROI] + {"hash":"532b5bfa711f405e","prefixes":{"":{"product":1216,"type":1}}}, // [Cardlytics] {"hash":"799c283a6f1c8ece","prefixes":{"":{"product":1217}}}, // [MyFonts Inc.] - {"hash":"4448bee927dde7e6","prefixes":{"*":{"product":1218}}}, // [Bluecore, Inc.] - {"hash":"a0bd7b7a099833b6","prefixes":{"":{"product":1218}}}, // [Bluecore, Inc.] - {"hash":"fa3e77058c021551","prefixes":{"*":{"product":1218}}}, // [Bluecore, Inc.] - {"hash":"4761d233715098ce","prefixes":{"":{"product":1219}}}, // [EverQuote, Inc.] - {"hash":"35694b7df8059b22","prefixes":{"":{"product":1219}}}, // [EverQuote, Inc.] - {"hash":"0740880077130a2d","prefixes":{"":{"product":1220}}}, // [Optimize LCC D.B.A Genius Monkey] - {"hash":"bfe2c1b41278b804","prefixes":{"":{"product":1220}}}, // [Optimize LCC D.B.A Genius Monkey] - {"hash":"6dd3f6dcd500314e","prefixes":{"":{"product":1220}}}, // [Optimize LCC D.B.A Genius Monkey] - {"hash":"2f3f7cacd3fe0763","prefixes":{"*":{"product":1221}}}, // [EverString Technology Ltd] - {"hash":"bca80e9becb74dcb","prefixes":{"*":{"product":1221}}}, // [EverString Technology Ltd] - {"hash":"46edf29e9ba4ff96","prefixes":{"":{"product":1222}}}, // [Axonix Limited] - {"hash":"98961093c86583f5","prefixes":{"":{"product":1223}}}, // [Ubimo Ltd.] + {"hash":"4448bee927dde7e6","prefixes":{"*":{"product":1218,"type":0}}}, // [Bluecore, Inc.] + {"hash":"a0bd7b7a099833b6","prefixes":{"":{"product":1218,"type":0}}}, // [Bluecore, Inc.] + {"hash":"fa3e77058c021551","prefixes":{"*":{"product":1218,"type":0}}}, // [Bluecore, Inc.] + {"hash":"4761d233715098ce","prefixes":{"":{"product":1219,"type":0}}}, // [EverQuote, Inc.] + {"hash":"35694b7df8059b22","prefixes":{"":{"product":1219,"type":0}}}, // [EverQuote, Inc.] + {"hash":"0740880077130a2d","prefixes":{"":{"product":1220,"type":1}}}, // [Optimize LCC D.B.A Genius Monkey] + {"hash":"bfe2c1b41278b804","prefixes":{"":{"product":1220,"type":1}}}, // [Optimize LCC D.B.A Genius Monkey] + {"hash":"6dd3f6dcd500314e","prefixes":{"":{"product":1220,"type":1}}}, // [Optimize LCC D.B.A Genius Monkey] + {"hash":"2f3f7cacd3fe0763","prefixes":{"*":{"product":1221,"type":0}}}, // [EverString Technology Ltd] + {"hash":"bca80e9becb74dcb","prefixes":{"*":{"product":1221,"type":0}}}, // [EverString Technology Ltd] + {"hash":"46edf29e9ba4ff96","prefixes":{"":{"product":1222,"type":0}}}, // [Axonix Limited] + {"hash":"98961093c86583f5","prefixes":{"":{"product":1223,"type":0}}}, // [Ubimo Ltd.] {"hash":"1110ef291b2bd2e8","prefixes":{"":{"product":1224}}}, // [gskinner.com,Inc] - {"hash":"e36b044e9f38bad6","prefixes":{"":{"product":1225}}}, // [PlaceIQ, Inc.] - {"hash":"fe5b89fe7dbbd534","prefixes":{"":{"product":1226}}}, // [DataBerries] - {"hash":"ddf083a57d484592","prefixes":{"":{"product":1227}}}, // [Otto (GmbH & Co KG)] - {"hash":"7975f7864f4fa759","prefixes":{"":{"product":1228}}}, // [Beijing ADirects Technology Corporation Limited] - {"hash":"657d40c4d7322985","prefixes":{"":{"product":1229}}}, // [MagicGroup Asia Pte. Ltd.] - {"hash":"f5559eee02dd33ad","prefixes":{"":{"product":1229}}}, // [MagicGroup Asia Pte. Ltd.] - {"hash":"e81aa2815c378230","prefixes":{"":{"product":1229}}}, // [MagicGroup Asia Pte. Ltd.] - {"hash":"49269f9273c66c00","prefixes":{"":{"product":1230}}}, // [Local Content, Inc.] - {"hash":"210fa7d8376be47a","prefixes":{"":{"product":1230}}}, // [Local Content, Inc.] - {"hash":"e4ba8ed4e3abc143","prefixes":{"":{"product":1231}}}, // [Flavia] - {"hash":"269e0d49e8a941b8","prefixes":{"":{"product":43}}}, // [Transout Inc.] - {"hash":"b9cd0135bbe2cf40","prefixes":{"":{"product":43}}}, // [Transout Inc.] - {"hash":"e4b01f2271c4171a","prefixes":{"":{"product":44}}}, // [ADZIP] - {"hash":"e5b4daaa6c4ae231","prefixes":{"":{"product":44}}}, // [ADZIP] - {"hash":"cfb3a28bf24f27aa","prefixes":{"":{"product":44}}}, // [ADZIP] - {"hash":"db9ed30c0cbece36","prefixes":{"":{"product":44}}}, // [ADZIP] - {"hash":"dd0d7f22eaea16dd","prefixes":{"":{"product":44}}}, // [ADZIP] - {"hash":"4f3fc6e6fa75b1e8","prefixes":{"":{"product":44}}}, // [ADZIP] + {"hash":"e36b044e9f38bad6","prefixes":{"":{"product":1225,"type":0}}}, // [PlaceIQ, Inc.] + {"hash":"fe5b89fe7dbbd534","prefixes":{"":{"product":1226,"type":0}}}, // [DataBerries] + {"hash":"ddf083a57d484592","prefixes":{"":{"product":1227,"type":1}}}, // [Otto (GmbH & Co KG)] + {"hash":"7975f7864f4fa759","prefixes":{"":{"product":1228,"type":0}}}, // [Beijing ADirects Technology Corporation Limited] + {"hash":"657d40c4d7322985","prefixes":{"":{"product":1229,"type":0}}}, // [MagicGroup Asia Pte. Ltd.] + {"hash":"f5559eee02dd33ad","prefixes":{"":{"product":1229,"type":0}}}, // [MagicGroup Asia Pte. Ltd.] + {"hash":"e81aa2815c378230","prefixes":{"":{"product":1229,"type":0}}}, // [MagicGroup Asia Pte. Ltd.] + {"hash":"49269f9273c66c00","prefixes":{"":{"product":1230,"type":0}}}, // [Local Content, Inc.] + {"hash":"210fa7d8376be47a","prefixes":{"":{"product":1230,"type":0}}}, // [Local Content, Inc.] + {"hash":"e4ba8ed4e3abc143","prefixes":{"":{"product":1231,"type":0}}}, // [Flavia] + {"hash":"269e0d49e8a941b8","prefixes":{"":{"product":43,"type":0}}}, // [Transout Inc.] + {"hash":"b9cd0135bbe2cf40","prefixes":{"":{"product":43,"type":0}}}, // [Transout Inc.] + {"hash":"e4b01f2271c4171a","prefixes":{"":{"product":44,"type":0}}}, // [ADZIP] + {"hash":"e5b4daaa6c4ae231","prefixes":{"":{"product":44,"type":0}}}, // [ADZIP] + {"hash":"cfb3a28bf24f27aa","prefixes":{"":{"product":44,"type":0}}}, // [ADZIP] + {"hash":"db9ed30c0cbece36","prefixes":{"":{"product":44,"type":0}}}, // [ADZIP] + {"hash":"dd0d7f22eaea16dd","prefixes":{"":{"product":44,"type":0}}}, // [ADZIP] + {"hash":"4f3fc6e6fa75b1e8","prefixes":{"":{"product":44,"type":0}}}, // [ADZIP] {"hash":"17a3e1cbc6818d71","prefixes":{"*":{"product":1232}}}, // [Webtype] - {"hash":"39697008117e49f0","prefixes":{"":{"product":1233}}}, // [Aditor] - {"hash":"50bd67909486f9f5","prefixes":{"":{"product":1233}}}, // [Aditor] - {"hash":"d58ef2e47a1b5b3b","prefixes":{"":{"product":1234}}}, // [YCmedia] - {"hash":"fc8e2c447edda6c9","prefixes":{"":{"product":1235}}}, // [Addwish Aps] - {"hash":"d5ac956c9f185ddc","prefixes":{"":{"product":1236}}}, // [AIDO TECHNOLOGY INC.] - {"hash":"24015d44b9900d67","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"460c0600751cbd60","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"77050f5bbccffdb1","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"cdf17fb674f06ff0","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"8fb430c8ece16b19","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"c9d79e6f1f2694cd","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"80c75e37374a2ef0","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"5f9ca3a706ea1a32","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"2839cda166e75a72","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"762d13ee90c23c96","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"c0ea3a6ac5a15ff4","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"70c0b65944772c14","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"06d5db93059745e1","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"ea0e52e08087883d","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"dd48f2110336efda","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"bac37ceef6479f6b","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"a16d986f3ad09790","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"44addae7b850b89f","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"ef08ba4268518e6e","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"1f2560020ac4a5dd","prefixes":{"":{"product":1237}}}, // [Herolens Group LLC] - {"hash":"67339d8f9c205d19","prefixes":{"":{"product":1238}}}, // [Fuisz Media, Inc.] - {"hash":"b3ebdb16675afb79","prefixes":{"":{"product":1238}}}, // [Fuisz Media, Inc.] - {"hash":"33e8b1a10d6cf9bb","prefixes":{"":{"product":1238}}}, // [Fuisz Media, Inc.] - {"hash":"33c97b2942fbfb43","prefixes":{"":{"product":1239}}}, // [Bucksense, Inc.] - {"hash":"f7be89ec6f521ed4","prefixes":{"":{"product":664}}}, // [Adiant] - {"hash":"8ad32c44e7f009d9","prefixes":{"":{"product":1240}}}, // [Taylor Nelson Sofres Ukraine LLC] + {"hash":"39697008117e49f0","prefixes":{"":{"product":1233,"type":0}}}, // [Aditor] + {"hash":"50bd67909486f9f5","prefixes":{"":{"product":1233,"type":0}}}, // [Aditor] + {"hash":"d58ef2e47a1b5b3b","prefixes":{"":{"product":1234,"type":0}}}, // [YCmedia] + {"hash":"fc8e2c447edda6c9","prefixes":{"":{"product":1235,"type":0}}}, // [Addwish Aps] + {"hash":"d5ac956c9f185ddc","prefixes":{"":{"product":1236,"type":0}}}, // [AIDO TECHNOLOGY INC.] + {"hash":"24015d44b9900d67","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"460c0600751cbd60","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"77050f5bbccffdb1","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"cdf17fb674f06ff0","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"8fb430c8ece16b19","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"c9d79e6f1f2694cd","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"80c75e37374a2ef0","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"5f9ca3a706ea1a32","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"2839cda166e75a72","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"762d13ee90c23c96","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"c0ea3a6ac5a15ff4","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"70c0b65944772c14","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"06d5db93059745e1","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"ea0e52e08087883d","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"dd48f2110336efda","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"bac37ceef6479f6b","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"a16d986f3ad09790","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"44addae7b850b89f","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"ef08ba4268518e6e","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"1f2560020ac4a5dd","prefixes":{"":{"product":1237,"type":0}}}, // [Herolens Group LLC] + {"hash":"67339d8f9c205d19","prefixes":{"":{"product":1238,"type":0}}}, // [Fuisz Media, Inc.] + {"hash":"b3ebdb16675afb79","prefixes":{"":{"product":1238,"type":0}}}, // [Fuisz Media, Inc.] + {"hash":"33e8b1a10d6cf9bb","prefixes":{"":{"product":1238,"type":0}}}, // [Fuisz Media, Inc.] + {"hash":"33c97b2942fbfb43","prefixes":{"":{"product":1239,"type":0}}}, // [Bucksense, Inc.] + {"hash":"f7be89ec6f521ed4","prefixes":{"":{"product":664,"type":0}}}, // [Adiant] + {"hash":"8ad32c44e7f009d9","prefixes":{"":{"product":1240,"type":1}}}, // [Taylor Nelson Sofres Ukraine LLC] {"hash":"9913ba5c46add495","prefixes":{"*":{"product":1241}}}, // [MotionLead] - {"hash":"ed341f6ed9722885","prefixes":{"":{"product":1242}}}, // [CJSC Recomendatsii tovarov i uslug] - {"hash":"b84298a2bc76c877","prefixes":{"":{"product":1242}}}, // [CJSC Recomendatsii tovarov i uslug] - {"hash":"d7bd450b5571f32e","prefixes":{"":{"product":1242}}}, // [CJSC Recomendatsii tovarov i uslug] - {"hash":"788739abab822f20","prefixes":{"":{"product":1242}}}, // [CJSC Recomendatsii tovarov i uslug] - {"hash":"5119113b90253a71","prefixes":{"":{"product":1242}}}, // [CJSC Recomendatsii tovarov i uslug] + {"hash":"ed341f6ed9722885","prefixes":{"":{"product":1242,"type":0}}}, // [CJSC Recomendatsii tovarov i uslug] + {"hash":"b84298a2bc76c877","prefixes":{"":{"product":1242,"type":0}}}, // [CJSC Recomendatsii tovarov i uslug] + {"hash":"d7bd450b5571f32e","prefixes":{"":{"product":1242,"type":0}}}, // [CJSC Recomendatsii tovarov i uslug] + {"hash":"788739abab822f20","prefixes":{"":{"product":1242,"type":0}}}, // [CJSC Recomendatsii tovarov i uslug] + {"hash":"5119113b90253a71","prefixes":{"":{"product":1242,"type":0}}}, // [CJSC Recomendatsii tovarov i uslug] {"hash":"8391f54ef2dd8235","prefixes":{"":{"product":1243}}}, // [Adobe Edge] {"hash":"ecbec0da60be727e","prefixes":{"":{"product":1243}}}, // [Adobe Edge] {"hash":"45df05b3b1fd2039","prefixes":{"":{"product":1243}}}, // [Adobe Edge] - {"hash":"7f8b63980ada138f","prefixes":{"":{"product":1244}}}, // [Bizible] - {"hash":"fcff0eb6c45bdf72","prefixes":{"":{"product":1245}}}, // [Adludio Limited] - {"hash":"58ae271664061630","prefixes":{"":{"product":1245}}}, // [Adludio Limited] - {"hash":"19795a3ce2a7e620","prefixes":{"":{"product":1245}}}, // [Adludio Limited] - {"hash":"aa3822d449c78db7","prefixes":{"":{"product":1245}}}, // [Adludio Limited] - {"hash":"b1269cde121b05a1","prefixes":{"":{"product":1245}}}, // [Adludio Limited] - {"hash":"1581c4afe0d48fa2","prefixes":{"":{"product":1246}}}, // [Ally Financial] - {"hash":"2e171be7640cf4cd","prefixes":{"":{"product":1247}}}, // [AIAd Ltd.] - {"hash":"ae7e973c225c0a01","prefixes":{"":{"product":1248}}}, // [Petplan] - {"hash":"78db497564cd4bf9","prefixes":{"bis":{"product":1249},"":{"product":1249},"openrtb":{"product":1249}}}, // [Vidazoo Ltd.] [Vidazoo Ltd.] [Vidazoo Ltd.] - {"hash":"c0fe1ea55404bcbb","prefixes":{"bis":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"f7fbe362db50024a","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"55abab5eb4ff10bd","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"e542a9dea283be31","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"a49f5bf572a22bae","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"7e02810393b6fe89","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"89c0cbd03222de92","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"31a98e1d5bba9ae8","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"15010236a7d3b5a4","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"9f927848d0417d12","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"7a2f5d3665e9a31a","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"02fb27611632d82c","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"0b95d00c8ef095ae","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"2d42c2d0a5ab84ae","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"5e405c19a402590e","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"d037ae4b54d7e7ec","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"fa3f8d822f471c8e","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"1fd9bf19c5906c01","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"f989a4e87da3e6d9","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"26937f461d535e88","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"755c357326a37b3f","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"aac0686686b2d53c","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"3ce944fa0cf0291a","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"7302f12cc4ace16b","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"52816f3d4542b887","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"59bf7df499fa52b5","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"ebabd6c7d62c634c","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"53ac53e2f538f2e2","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"3ed73abadb9c898a","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"9574295460ce8d22","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"d591fdb6045eb90f","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"8b39993907ef0e90","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"fff9c91a1d02e69d","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"d086a625516bdfc4","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"dedb3c41790f0b92","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"d9d28815b7351be9","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"0eceb2a8a6aa5014","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"c3cd28d4911901ef","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"906300510974cf1a","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"6bbcc411e84396ce","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"18f5beb4c7518ce0","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"445bbe1950cddd7b","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"2b7cc0f2bdc9e984","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"2e1ee42fbe53923e","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"0d75de8359eb1e90","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"5439763db9182a6c","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"924a269d7fa953ef","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"56592bc98da7add7","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"e350307b97e81944","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"62d2d232adb7f5ce","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"9dbd1f71df681f87","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"60aa872cca3ea408","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"574290c159276582","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"520b03b31ba99ffe","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"8927dc4db3ffd9a0","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"cea75e5e1bcb3e75","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"00fc1e5ba5cf11e1","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"241443df62a11bdb","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"958852e67d999446","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"d7dde4fdd1b42ac2","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"b9a6386a13d1f59c","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"1b00c21eb7dca0ba","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"3b5a0569a91c1f27","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"07b3c413dcf0891e","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"4b15aef39cd29476","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"25743e7a87ec9352","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"2fe16a518eee6e23","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"a154647a02beff09","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"73a06806ded66bc0","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"a82c6297f56276f8","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"514b9e5dcf88791d","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"80e10fe664c9676b","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"788de2248f446546","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"e1e58f0b49a0e5c7","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"c56afa9dadaace8c","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"4084c6a05941d212","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"fafe943a3ce4b828","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"00cfc10d1f469dfc","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"cdb86fef4fddecdd","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"97b3473c7082a4c8","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"99973a84d3bda612","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"ba67aff057d8dc5d","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"a3c0da72dbefc878","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"5925a6291dd2ab40","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"34129d9457495ffd","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"e2505c6002184e33","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"9bcac0e9fd77ddc6","prefixes":{"":{"product":1249}}}, // [Vidazoo Ltd.] - {"hash":"737c1868e55d5b37","prefixes":{"":{"product":1250}}}, // [RTBstar LLC] - {"hash":"302ec6d6755746d6","prefixes":{"*":{"product":1251}}}, // [Chalk Media Holdings] - {"hash":"202f611d1eab4195","prefixes":{"*":{"product":1251}}}, // [Chalk Media Holdings] - {"hash":"a6ab491761f03a1c","prefixes":{"":{"product":1252}}}, // [Oxford Biochronometrics] - {"hash":"3f8968d2bc62134f","prefixes":{"":{"product":1252}}}, // [Oxford Biochronometrics] - {"hash":"fbe6ab3bc9d21558","prefixes":{"":{"product":1252}}}, // [Oxford Biochronometrics] - {"hash":"769529a9ad14a9b6","prefixes":{"":{"product":1253}}}, // [SGN Games, Inc.] - {"hash":"f1a29a10c1ad80be","prefixes":{"*":{"product":1254}}}, // [Crutchfield New Media, LLC] - {"hash":"930e98a126b97c02","prefixes":{"":{"product":113}}}, // [YOOX NET-A-PORTER GROUP SPA] - {"hash":"915e8620d61e782c","prefixes":{"":{"product":113}}}, // [YOOX NET-A-PORTER GROUP SPA] - {"hash":"0492037eab3835e9","prefixes":{"":{"product":113}}}, // [YOOX NET-A-PORTER GROUP SPA] - {"hash":"5eee79daa9337871","prefixes":{"":{"product":1255}}}, // [Laserlike Inc] + {"hash":"7f8b63980ada138f","prefixes":{"":{"product":1244,"type":1}}}, // [Bizible] + {"hash":"fcff0eb6c45bdf72","prefixes":{"":{"product":1245,"type":0}}}, // [Adludio Limited] + {"hash":"58ae271664061630","prefixes":{"":{"product":1245,"type":0}}}, // [Adludio Limited] + {"hash":"19795a3ce2a7e620","prefixes":{"":{"product":1245,"type":0}}}, // [Adludio Limited] + {"hash":"aa3822d449c78db7","prefixes":{"":{"product":1245,"type":0}}}, // [Adludio Limited] + {"hash":"b1269cde121b05a1","prefixes":{"":{"product":1245,"type":0}}}, // [Adludio Limited] + {"hash":"1581c4afe0d48fa2","prefixes":{"":{"product":1246,"type":0}}}, // [Ally Financial] + {"hash":"2e171be7640cf4cd","prefixes":{"":{"product":1247,"type":0}}}, // [AIAd Ltd.] + {"hash":"ae7e973c225c0a01","prefixes":{"":{"product":1248,"type":0}}}, // [Petplan] + {"hash":"78db497564cd4bf9","prefixes":{"bis":{"product":1249,"type":0},"":{"product":1249,"type":0},"openrtb":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] [Vidazoo Ltd.] [Vidazoo Ltd.] + {"hash":"c0fe1ea55404bcbb","prefixes":{"bis":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"f7fbe362db50024a","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"55abab5eb4ff10bd","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"e542a9dea283be31","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"a49f5bf572a22bae","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"7e02810393b6fe89","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"89c0cbd03222de92","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"31a98e1d5bba9ae8","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"15010236a7d3b5a4","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"9f927848d0417d12","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"7a2f5d3665e9a31a","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"02fb27611632d82c","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"0b95d00c8ef095ae","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"2d42c2d0a5ab84ae","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"5e405c19a402590e","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"d037ae4b54d7e7ec","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"fa3f8d822f471c8e","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"1fd9bf19c5906c01","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"f989a4e87da3e6d9","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"26937f461d535e88","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"755c357326a37b3f","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"aac0686686b2d53c","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"3ce944fa0cf0291a","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"7302f12cc4ace16b","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"52816f3d4542b887","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"59bf7df499fa52b5","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"ebabd6c7d62c634c","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"53ac53e2f538f2e2","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"3ed73abadb9c898a","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"9574295460ce8d22","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"d591fdb6045eb90f","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"8b39993907ef0e90","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"fff9c91a1d02e69d","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"d086a625516bdfc4","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"dedb3c41790f0b92","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"d9d28815b7351be9","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"0eceb2a8a6aa5014","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"c3cd28d4911901ef","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"906300510974cf1a","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"6bbcc411e84396ce","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"18f5beb4c7518ce0","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"445bbe1950cddd7b","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"2b7cc0f2bdc9e984","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"2e1ee42fbe53923e","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"0d75de8359eb1e90","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"5439763db9182a6c","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"924a269d7fa953ef","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"56592bc98da7add7","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"e350307b97e81944","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"62d2d232adb7f5ce","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"9dbd1f71df681f87","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"60aa872cca3ea408","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"574290c159276582","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"520b03b31ba99ffe","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"8927dc4db3ffd9a0","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"cea75e5e1bcb3e75","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"00fc1e5ba5cf11e1","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"241443df62a11bdb","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"958852e67d999446","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"d7dde4fdd1b42ac2","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"b9a6386a13d1f59c","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"1b00c21eb7dca0ba","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"3b5a0569a91c1f27","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"07b3c413dcf0891e","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"4b15aef39cd29476","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"25743e7a87ec9352","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"2fe16a518eee6e23","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"a154647a02beff09","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"73a06806ded66bc0","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"a82c6297f56276f8","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"514b9e5dcf88791d","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"80e10fe664c9676b","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"788de2248f446546","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"e1e58f0b49a0e5c7","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"c56afa9dadaace8c","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"4084c6a05941d212","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"fafe943a3ce4b828","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"00cfc10d1f469dfc","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"cdb86fef4fddecdd","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"97b3473c7082a4c8","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"99973a84d3bda612","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"ba67aff057d8dc5d","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"a3c0da72dbefc878","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"5925a6291dd2ab40","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"34129d9457495ffd","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"e2505c6002184e33","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"9bcac0e9fd77ddc6","prefixes":{"":{"product":1249,"type":0}}}, // [Vidazoo Ltd.] + {"hash":"737c1868e55d5b37","prefixes":{"":{"product":1250,"type":0}}}, // [RTBstar LLC] + {"hash":"302ec6d6755746d6","prefixes":{"*":{"product":1251,"type":0}}}, // [Chalk Media Holdings] + {"hash":"202f611d1eab4195","prefixes":{"*":{"product":1251,"type":0}}}, // [Chalk Media Holdings] + {"hash":"a6ab491761f03a1c","prefixes":{"":{"product":1252,"type":1}}}, // [Oxford Biochronometrics] + {"hash":"3f8968d2bc62134f","prefixes":{"":{"product":1252,"type":1}}}, // [Oxford Biochronometrics] + {"hash":"fbe6ab3bc9d21558","prefixes":{"":{"product":1252,"type":1}}}, // [Oxford Biochronometrics] + {"hash":"769529a9ad14a9b6","prefixes":{"":{"product":1253,"type":0}}}, // [SGN Games, Inc.] + {"hash":"f1a29a10c1ad80be","prefixes":{"*":{"product":1254,"type":1}}}, // [Crutchfield New Media, LLC] + {"hash":"930e98a126b97c02","prefixes":{"":{"product":113,"type":0}}}, // [YOOX NET-A-PORTER GROUP SPA] + {"hash":"915e8620d61e782c","prefixes":{"":{"product":113,"type":0}}}, // [YOOX NET-A-PORTER GROUP SPA] + {"hash":"0492037eab3835e9","prefixes":{"":{"product":113,"type":0}}}, // [YOOX NET-A-PORTER GROUP SPA] + {"hash":"5eee79daa9337871","prefixes":{"":{"product":1255,"type":0}}}, // [Laserlike Inc] {"hash":"3262121ae456ec62","prefixes":{"":{"product":1256}}}, // [Adtile Technologies Inc.] {"hash":"eefeb24c8c0df59f","prefixes":{"":{"product":1256}}}, // [Adtile Technologies Inc.] {"hash":"2f77e3292a158b3c","prefixes":{"":{"product":1256}}}, // [Adtile Technologies Inc.] - {"hash":"ed04984091cd6edc","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"63c7ce8ea1112262","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"842d35d55c520fe2","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"3fb91c004caeeba4","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"4673bf1b8fb41012","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"60c5047efc444089","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"9daf201eb861bd5a","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"8fb045042ba8dab7","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"b5c5f11aa533f8f8","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"e69760fd18a7e847","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"afdb50efeb58adb3","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"54ade0c2fc33d554","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"980a9356a0a0604b","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"0d064f41dd06b071","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"4e9cc6d069d0700f","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"abc81c5ff7313f61","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"4d8e54db683834b5","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"958c891ea7a22760","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"02b0aa7dbed4dc70","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"cd655ca6f3e7c5b4","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"117f6d5c385c0fbf","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"974b3e895eb889a1","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"2315e038cabe7cf3","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"256e6db135713c95","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"44b4921e1dd83428","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"2ececb465fbab022","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"b3a40f1c056c981d","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"c4f8f640f24e3592","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"0a6e85210f1d99c3","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"d12573269a748046","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"deabc924d996a1ca","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"cfae73045c7b29a6","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"c97db9d5ee0b71c7","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"ca6bb3442fa58646","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"f38fbdc9759c0ef4","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"6db47cd08bed3122","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"86c0634020121d1e","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"98c1045cd61f979d","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"7bdc1a49cf0ccc1d","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"cdceb4fead43eafb","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"b8a7ac4ace0ce6e9","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"081ccef35be56b36","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"e29de726004b6e06","prefixes":{"":{"product":1257}}}, // [Adgravity] - {"hash":"3044eb15f0757788","prefixes":{"":{"product":1258}}}, // [Protected Media LTD] - {"hash":"675f561d3f31df38","prefixes":{"":{"product":1258}}}, // [Protected Media LTD] - {"hash":"506fa56f8b748a67","prefixes":{"":{"product":1259}}}, // [Media Detect GmbH] - {"hash":"d8795d8df3c0b355","prefixes":{"":{"product":1260}}}, // [Centro CDN] - {"hash":"92690e6cf2068609","prefixes":{"":{"product":1261}}}, // [DeltaX] - {"hash":"bcb296520399e855","prefixes":{"":{"product":1261}}}, // [DeltaX] - {"hash":"eeba4d486f2a193f","prefixes":{"":{"product":1261}}}, // [DeltaX] - {"hash":"36ba79aa125ace1d","prefixes":{"":{"product":1261}}}, // [DeltaX] - {"hash":"755e0fb3a6d853e7","prefixes":{"":{"product":1261}}}, // [DeltaX] - {"hash":"926c7d8c47cdc6a4","prefixes":{"":{"product":1261}}}, // [DeltaX] - {"hash":"112f8b5a749d05e9","prefixes":{"":{"product":1261}}}, // [DeltaX] + {"hash":"ed04984091cd6edc","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"63c7ce8ea1112262","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"842d35d55c520fe2","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"3fb91c004caeeba4","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"4673bf1b8fb41012","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"60c5047efc444089","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"9daf201eb861bd5a","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"8fb045042ba8dab7","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"b5c5f11aa533f8f8","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"e69760fd18a7e847","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"afdb50efeb58adb3","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"54ade0c2fc33d554","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"980a9356a0a0604b","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"0d064f41dd06b071","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"4e9cc6d069d0700f","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"abc81c5ff7313f61","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"4d8e54db683834b5","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"958c891ea7a22760","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"02b0aa7dbed4dc70","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"cd655ca6f3e7c5b4","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"117f6d5c385c0fbf","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"974b3e895eb889a1","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"2315e038cabe7cf3","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"256e6db135713c95","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"44b4921e1dd83428","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"2ececb465fbab022","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"b3a40f1c056c981d","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"c4f8f640f24e3592","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"0a6e85210f1d99c3","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"d12573269a748046","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"deabc924d996a1ca","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"cfae73045c7b29a6","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"c97db9d5ee0b71c7","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"ca6bb3442fa58646","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"f38fbdc9759c0ef4","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"6db47cd08bed3122","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"86c0634020121d1e","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"98c1045cd61f979d","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"7bdc1a49cf0ccc1d","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"cdceb4fead43eafb","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"b8a7ac4ace0ce6e9","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"081ccef35be56b36","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"e29de726004b6e06","prefixes":{"":{"product":1257,"type":1}}}, // [Adgravity] + {"hash":"3044eb15f0757788","prefixes":{"":{"product":1258,"type":1}}}, // [Protected Media LTD] + {"hash":"675f561d3f31df38","prefixes":{"":{"product":1258,"type":1}}}, // [Protected Media LTD] + {"hash":"506fa56f8b748a67","prefixes":{"":{"product":1259,"type":1}}}, // [Media Detect GmbH] + {"hash":"d8795d8df3c0b355","prefixes":{"":{"product":1260,"type":0}}}, // [Centro CDN] + {"hash":"92690e6cf2068609","prefixes":{"":{"product":1261,"type":0}}}, // [DeltaX] + {"hash":"bcb296520399e855","prefixes":{"":{"product":1261,"type":0}}}, // [DeltaX] + {"hash":"eeba4d486f2a193f","prefixes":{"":{"product":1261,"type":0}}}, // [DeltaX] + {"hash":"36ba79aa125ace1d","prefixes":{"":{"product":1261,"type":0}}}, // [DeltaX] + {"hash":"755e0fb3a6d853e7","prefixes":{"":{"product":1261,"type":0}}}, // [DeltaX] + {"hash":"926c7d8c47cdc6a4","prefixes":{"":{"product":1261,"type":0}}}, // [DeltaX] + {"hash":"112f8b5a749d05e9","prefixes":{"":{"product":1261,"type":0}}}, // [DeltaX] {"hash":"9a9421d022c231d0","prefixes":{"":{"product":1262}}}, // [jQuery] - {"hash":"7ed84366898b6e95","prefixes":{"":{"product":1263}}}, // [SoMo Audience Corp.] - {"hash":"7b7b8f4fea812106","prefixes":{"":{"product":1263}}}, // [SoMo Audience Corp.] - {"hash":"cd27a627925b605e","prefixes":{"":{"product":1263}}}, // [SoMo Audience Corp.] - {"hash":"8de4d0c2e5a785d3","prefixes":{"":{"product":1263}}}, // [SoMo Audience Corp.] - {"hash":"dd090795aa41d39d","prefixes":{"":{"product":1263}}}, // [SoMo Audience Corp.] - {"hash":"a792d2d9ef8b7d44","prefixes":{"":{"product":1264}}}, // [Distribute Ltd] - {"hash":"a41d8bffbb4dde29","prefixes":{"c":{"product":1264}}}, // [Distribute Ltd] - {"hash":"cb03110aa3eafbc3","prefixes":{"":{"product":1264}}}, // [Distribute Ltd] - {"hash":"f8d5c1c3c0137b95","prefixes":{"":{"product":1264}}}, // [Distribute Ltd] - {"hash":"fdbd7675a0a4e4d2","prefixes":{"":{"product":1264}}}, // [Distribute Ltd] - {"hash":"c152daf3639bfd61","prefixes":{"":{"product":1265}}}, // [Poppin] - {"hash":"77afc197a9ed3c55","prefixes":{"":{"product":1266}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] - {"hash":"f000d51ba83c9b81","prefixes":{"":{"product":1266}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] - {"hash":"e6b0bd562a8a6c44","prefixes":{"":{"product":1266}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] - {"hash":"b67bb576e01ff3b8","prefixes":{"":{"product":1266}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] - {"hash":"b74cae0d407627c6","prefixes":{"":{"product":1266}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] - {"hash":"d02ca334243aeff6","prefixes":{"":{"product":1266}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] - {"hash":"27c4aebe8feb1d61","prefixes":{"":{"product":1266}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] - {"hash":"cffac58b1fe6a120","prefixes":{"":{"product":1266}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] - {"hash":"060b85b3672a94b9","prefixes":{"":{"product":1266}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] - {"hash":"993dbbd9a4428116","prefixes":{"":{"product":1266}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] - {"hash":"5d08c05fd8f3e6b6","prefixes":{"":{"product":1266}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] - {"hash":"733a8e48aa3496c3","prefixes":{"":{"product":1266}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] - {"hash":"6dfff15240319d9a","prefixes":{"":{"product":1267}}}, // [Art of Click Pte. Ltd] - {"hash":"3771e4f81d75a524","prefixes":{"":{"product":45}}}, // [Adways SAS] - {"hash":"b2d089ed26249e9c","prefixes":{"":{"product":45}}}, // [Adways SAS] - {"hash":"6cb0920968e42462","prefixes":{"":{"product":45}}}, // [Adways SAS] - {"hash":"779587babf9a845a","prefixes":{"":{"product":45}}}, // [Adways SAS] - {"hash":"21fd838e467abf9e","prefixes":{"":{"product":45}}}, // [Adways SAS] - {"hash":"f35db5d8e41be046","prefixes":{"":{"product":1268}}}, // [Quantasy LLC] - {"hash":"fb881e61783803db","prefixes":{"":{"product":1269}}}, // [Wavenet Technology Co., Ltd.] - {"hash":"4a5a7154d849b6df","prefixes":{"":{"product":1270}}}, // [ENVISIONX LTD] - {"hash":"4c0fc55e8fe8be51","prefixes":{"":{"product":1271}}}, // [Adhood] - {"hash":"62b3383734c496fb","prefixes":{"":{"product":1271}}}, // [Adhood] - {"hash":"27e40c1642b59b0e","prefixes":{"":{"product":1271}}}, // [Adhood] - {"hash":"b7bcec8f502b24cf","prefixes":{"":{"product":1271}}}, // [Adhood] - {"hash":"b8885905bf9e213f","prefixes":{"":{"product":1271}}}, // [Adhood] - {"hash":"8238d8729bb3748c","prefixes":{"":{"product":1272}}}, // [Telogical Systems, LLC] - {"hash":"92dbc0e618f7816a","prefixes":{"":{"product":1272}}}, // [Telogical Systems, LLC] - {"hash":"d3be8ee2ff24c8dd","prefixes":{"":{"product":1272}}}, // [Telogical Systems, LLC] - {"hash":"0767b016186f9908","prefixes":{"":{"product":1273}}}, // [twyn group IT solutions & marketing services G] - {"hash":"1bf7b44093f4c0b5","prefixes":{"":{"product":1274}}}, // [Marchex Sales, LLC] - {"hash":"b60099c5a3ff5579","prefixes":{"":{"product":1275}}}, // [SmartyAds LLP] - {"hash":"e1e5cbc69ff27126","prefixes":{"":{"product":1275}}}, // [SmartyAds LLP] - {"hash":"01e34dcf6356f25b","prefixes":{"":{"product":1275}}}, // [SmartyAds LLP] - {"hash":"0587980840cbad28","prefixes":{"":{"product":1275}}}, // [SmartyAds LLP] - {"hash":"c13574923293d7c7","prefixes":{"":{"product":1276}}}, // [Reach150 Social, Inc.] - {"hash":"e87358da2b6ad070","prefixes":{"":{"product":1277}}}, // [Leadmill ApS] - {"hash":"2a24bd7dfe371075","prefixes":{"":{"product":1277}}}, // [Leadmill ApS] - {"hash":"3f6b6ba536add909","prefixes":{"":{"product":1278}}}, // [TapHeaven, Inc.] - {"hash":"050f2328d34461a7","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"a66968f05d34f468","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"2c309ae9bbbe9384","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"fec9fa0c1f3ffe6e","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"49989970caa95c3d","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"32eb6e39519c6d65","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"5ecf91c30b7a0a6a","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"6394e1f93c660614","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"3c6f41d29f5df8e7","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"cda46d94d7efda5c","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"164782d64f732408","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"af8c779439f17da0","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"0394176d4d575a93","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"c9a808631e01ad1a","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"1478be442db9d539","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"171f00354c5c6b43","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"521c6ad185dff69d","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"a7c6cb92086909f4","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"efb2ad70cb64944c","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"35e50ce841196503","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"683154a56472f3e2","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"6664d0e4be1a2011","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"efefa03759c8eb89","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"20477544dc10c916","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"922d2397edef5dbd","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"a9591e706ed0da18","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"c073c895bf061908","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"8a7804498832f633","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"45c2a9f766453c46","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"2a167f8c5d41c9de","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"0992810376313bba","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"e4588caa0c232726","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"73fbee089a438309","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"48743ee797fa8c98","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"22561af78d8aeebe","prefixes":{"":{"product":1279}}}, // [spring GmbH & Co. KG] - {"hash":"ee6f381082694c53","prefixes":{"":{"product":1280}}}, // [Roq.ad GmbH] - {"hash":"606e92e46118e68c","prefixes":{"":{"product":1281}}}, // [AdKernel LLC] - {"hash":"5dd554237e590e7a","prefixes":{"":{"product":1281}}}, // [AdKernel LLC] - {"hash":"47c55cdc2352963b","prefixes":{"":{"product":1281}}}, // [AdKernel LLC] - {"hash":"698477bb42f577d9","prefixes":{"":{"product":1281}}}, // [AdKernel LLC] - {"hash":"4d35613bf3c5608c","prefixes":{"":{"product":1281}}}, // [AdKernel LLC] - {"hash":"8bbcbb68e24aba75","prefixes":{"":{"product":1281}}}, // [AdKernel LLC] - {"hash":"b5d289baee77f3bb","prefixes":{"":{"product":1281}}}, // [AdKernel LLC] - {"hash":"1eab99893ccb6812","prefixes":{"":{"product":1281}}}, // [AdKernel LLC] - {"hash":"2d38a36747a2e4c8","prefixes":{"":{"product":1281}}}, // [AdKernel LLC] - {"hash":"2aaee44de4212440","prefixes":{"":{"product":1281}}}, // [AdKernel LLC] - {"hash":"720594080864ccd0","prefixes":{"":{"product":1281}}}, // [AdKernel LLC] - {"hash":"8cf8db96c95ad703","prefixes":{"":{"product":1282}}}, // [Uprise Technologies] - {"hash":"bdc43b963f1225e2","prefixes":{"":{"product":1283}}}, // [Sled, Inc.] - {"hash":"bd39b2a3b45ba87e","prefixes":{"":{"product":1284}}}, // [Pengtai Interactive Advertising Co.Ltd] - {"hash":"987e96fd53ac3377","prefixes":{"":{"product":1284}}}, // [Pengtai Interactive Advertising Co.Ltd] - {"hash":"ae49bd17dd4ead54","prefixes":{"":{"product":1284}}}, // [Pengtai Interactive Advertising Co.Ltd] - {"hash":"8d132f34a86f51b3","prefixes":{"":{"product":1284}}}, // [Pengtai Interactive Advertising Co.Ltd] - {"hash":"4210564496763546","prefixes":{"":{"product":1284}}}, // [Pengtai Interactive Advertising Co.Ltd] - {"hash":"c395c961fb4a60ae","prefixes":{"":{"product":1284}}}, // [Pengtai Interactive Advertising Co.Ltd] - {"hash":"2f37a86d54dbe4f9","prefixes":{"":{"product":1284}}}, // [Pengtai Interactive Advertising Co.Ltd] - {"hash":"04730e3fb984e716","prefixes":{"":{"product":1284}}}, // [Pengtai Interactive Advertising Co.Ltd] - {"hash":"8e040ece0573e008","prefixes":{"":{"product":1284}}}, // [Pengtai Interactive Advertising Co.Ltd] - {"hash":"a2aafd8d622f674d","prefixes":{"":{"product":1284}}}, // [Pengtai Interactive Advertising Co.Ltd] - {"hash":"4da566f98e41e44f","prefixes":{"":{"product":1285}}}, // [Adello Group AG] - {"hash":"469779ba0b2d7340","prefixes":{"":{"product":1286}}}, // [BitGravity] - {"hash":"bfa6d675fa0c17c3","prefixes":{"":{"product":1287}}}, // [44 Interactive] + {"hash":"7ed84366898b6e95","prefixes":{"":{"product":1263,"type":0}}}, // [SoMo Audience Corp.] + {"hash":"7b7b8f4fea812106","prefixes":{"":{"product":1263,"type":0}}}, // [SoMo Audience Corp.] + {"hash":"cd27a627925b605e","prefixes":{"":{"product":1263,"type":0}}}, // [SoMo Audience Corp.] + {"hash":"8de4d0c2e5a785d3","prefixes":{"":{"product":1263,"type":0}}}, // [SoMo Audience Corp.] + {"hash":"dd090795aa41d39d","prefixes":{"":{"product":1263,"type":0}}}, // [SoMo Audience Corp.] + {"hash":"a792d2d9ef8b7d44","prefixes":{"":{"product":1264,"type":0}}}, // [Distribute Ltd] + {"hash":"a41d8bffbb4dde29","prefixes":{"c":{"product":1264,"type":0}}}, // [Distribute Ltd] + {"hash":"cb03110aa3eafbc3","prefixes":{"":{"product":1264,"type":0}}}, // [Distribute Ltd] + {"hash":"f8d5c1c3c0137b95","prefixes":{"":{"product":1264,"type":0}}}, // [Distribute Ltd] + {"hash":"fdbd7675a0a4e4d2","prefixes":{"":{"product":1264,"type":0}}}, // [Distribute Ltd] + {"hash":"c152daf3639bfd61","prefixes":{"":{"product":1265,"type":0}}}, // [Poppin] + {"hash":"77afc197a9ed3c55","prefixes":{"":{"product":1266,"type":0}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] + {"hash":"f000d51ba83c9b81","prefixes":{"":{"product":1266,"type":0}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] + {"hash":"e6b0bd562a8a6c44","prefixes":{"":{"product":1266,"type":0}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] + {"hash":"b67bb576e01ff3b8","prefixes":{"":{"product":1266,"type":0}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] + {"hash":"b74cae0d407627c6","prefixes":{"":{"product":1266,"type":0}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] + {"hash":"d02ca334243aeff6","prefixes":{"":{"product":1266,"type":0}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] + {"hash":"27c4aebe8feb1d61","prefixes":{"":{"product":1266,"type":0}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] + {"hash":"cffac58b1fe6a120","prefixes":{"":{"product":1266,"type":0}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] + {"hash":"060b85b3672a94b9","prefixes":{"":{"product":1266,"type":0}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] + {"hash":"993dbbd9a4428116","prefixes":{"":{"product":1266,"type":0}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] + {"hash":"5d08c05fd8f3e6b6","prefixes":{"":{"product":1266,"type":0}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] + {"hash":"733a8e48aa3496c3","prefixes":{"":{"product":1266,"type":0}}}, // [EUROZEST MEDIA LIMITED/Avid Ad Server] + {"hash":"6dfff15240319d9a","prefixes":{"":{"product":1267,"type":0}}}, // [Art of Click Pte. Ltd] + {"hash":"3771e4f81d75a524","prefixes":{"":{"product":45,"type":0}}}, // [Adways SAS] + {"hash":"b2d089ed26249e9c","prefixes":{"":{"product":45,"type":0}}}, // [Adways SAS] + {"hash":"6cb0920968e42462","prefixes":{"":{"product":45,"type":0}}}, // [Adways SAS] + {"hash":"779587babf9a845a","prefixes":{"":{"product":45,"type":0}}}, // [Adways SAS] + {"hash":"21fd838e467abf9e","prefixes":{"":{"product":45,"type":0}}}, // [Adways SAS] + {"hash":"f35db5d8e41be046","prefixes":{"":{"product":1268,"type":0}}}, // [Quantasy LLC] + {"hash":"fb881e61783803db","prefixes":{"":{"product":1269,"type":0}}}, // [Wavenet Technology Co., Ltd.] + {"hash":"4a5a7154d849b6df","prefixes":{"":{"product":1270,"type":0}}}, // [ENVISIONX LTD] + {"hash":"4c0fc55e8fe8be51","prefixes":{"":{"product":1271,"type":0}}}, // [Adhood] + {"hash":"62b3383734c496fb","prefixes":{"":{"product":1271,"type":0}}}, // [Adhood] + {"hash":"27e40c1642b59b0e","prefixes":{"":{"product":1271,"type":0}}}, // [Adhood] + {"hash":"b7bcec8f502b24cf","prefixes":{"":{"product":1271,"type":0}}}, // [Adhood] + {"hash":"b8885905bf9e213f","prefixes":{"":{"product":1271,"type":0}}}, // [Adhood] + {"hash":"8238d8729bb3748c","prefixes":{"":{"product":1272,"type":0}}}, // [Telogical Systems, LLC] + {"hash":"92dbc0e618f7816a","prefixes":{"":{"product":1272,"type":0}}}, // [Telogical Systems, LLC] + {"hash":"d3be8ee2ff24c8dd","prefixes":{"":{"product":1272,"type":0}}}, // [Telogical Systems, LLC] + {"hash":"0767b016186f9908","prefixes":{"":{"product":1273,"type":0}}}, // [twyn group IT solutions & marketing services G] + {"hash":"1bf7b44093f4c0b5","prefixes":{"":{"product":1274,"type":1}}}, // [Marchex Sales, LLC] + {"hash":"b60099c5a3ff5579","prefixes":{"":{"product":1275,"type":0}}}, // [SmartyAds LLP] + {"hash":"e1e5cbc69ff27126","prefixes":{"":{"product":1275,"type":0}}}, // [SmartyAds LLP] + {"hash":"01e34dcf6356f25b","prefixes":{"":{"product":1275,"type":0}}}, // [SmartyAds LLP] + {"hash":"0587980840cbad28","prefixes":{"":{"product":1275,"type":0}}}, // [SmartyAds LLP] + {"hash":"c13574923293d7c7","prefixes":{"":{"product":1276,"type":0}}}, // [Reach150 Social, Inc.] + {"hash":"e87358da2b6ad070","prefixes":{"":{"product":1277,"type":1}}}, // [Leadmill ApS] + {"hash":"2a24bd7dfe371075","prefixes":{"":{"product":1277,"type":1}}}, // [Leadmill ApS] + {"hash":"3f6b6ba536add909","prefixes":{"":{"product":1278,"type":0}}}, // [TapHeaven, Inc.] + {"hash":"050f2328d34461a7","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"a66968f05d34f468","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"2c309ae9bbbe9384","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"fec9fa0c1f3ffe6e","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"49989970caa95c3d","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"32eb6e39519c6d65","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"5ecf91c30b7a0a6a","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"6394e1f93c660614","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"3c6f41d29f5df8e7","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"cda46d94d7efda5c","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"164782d64f732408","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"af8c779439f17da0","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"0394176d4d575a93","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"c9a808631e01ad1a","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"1478be442db9d539","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"171f00354c5c6b43","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"521c6ad185dff69d","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"a7c6cb92086909f4","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"efb2ad70cb64944c","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"35e50ce841196503","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"683154a56472f3e2","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"6664d0e4be1a2011","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"efefa03759c8eb89","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"20477544dc10c916","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"922d2397edef5dbd","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"a9591e706ed0da18","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"c073c895bf061908","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"8a7804498832f633","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"45c2a9f766453c46","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"2a167f8c5d41c9de","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"0992810376313bba","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"e4588caa0c232726","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"73fbee089a438309","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"48743ee797fa8c98","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"22561af78d8aeebe","prefixes":{"":{"product":1279,"type":1}}}, // [spring GmbH & Co. KG] + {"hash":"ee6f381082694c53","prefixes":{"":{"product":1280,"type":0}}}, // [Roq.ad GmbH] + {"hash":"606e92e46118e68c","prefixes":{"":{"product":1281,"type":0}}}, // [AdKernel LLC] + {"hash":"5dd554237e590e7a","prefixes":{"":{"product":1281,"type":0}}}, // [AdKernel LLC] + {"hash":"47c55cdc2352963b","prefixes":{"":{"product":1281,"type":0}}}, // [AdKernel LLC] + {"hash":"698477bb42f577d9","prefixes":{"":{"product":1281,"type":0}}}, // [AdKernel LLC] + {"hash":"4d35613bf3c5608c","prefixes":{"":{"product":1281,"type":0}}}, // [AdKernel LLC] + {"hash":"8bbcbb68e24aba75","prefixes":{"":{"product":1281,"type":0}}}, // [AdKernel LLC] + {"hash":"b5d289baee77f3bb","prefixes":{"":{"product":1281,"type":0}}}, // [AdKernel LLC] + {"hash":"1eab99893ccb6812","prefixes":{"":{"product":1281,"type":0}}}, // [AdKernel LLC] + {"hash":"2d38a36747a2e4c8","prefixes":{"":{"product":1281,"type":0}}}, // [AdKernel LLC] + {"hash":"2aaee44de4212440","prefixes":{"":{"product":1281,"type":0}}}, // [AdKernel LLC] + {"hash":"720594080864ccd0","prefixes":{"":{"product":1281,"type":0}}}, // [AdKernel LLC] + {"hash":"8cf8db96c95ad703","prefixes":{"":{"product":1282,"type":0}}}, // [Uprise Technologies] + {"hash":"bdc43b963f1225e2","prefixes":{"":{"product":1283,"type":0}}}, // [Sled, Inc.] + {"hash":"bd39b2a3b45ba87e","prefixes":{"":{"product":1284,"type":1}}}, // [Pengtai Interactive Advertising Co.Ltd] + {"hash":"987e96fd53ac3377","prefixes":{"":{"product":1284,"type":1}}}, // [Pengtai Interactive Advertising Co.Ltd] + {"hash":"ae49bd17dd4ead54","prefixes":{"":{"product":1284,"type":1}}}, // [Pengtai Interactive Advertising Co.Ltd] + {"hash":"8d132f34a86f51b3","prefixes":{"":{"product":1284,"type":1}}}, // [Pengtai Interactive Advertising Co.Ltd] + {"hash":"4210564496763546","prefixes":{"":{"product":1284,"type":1}}}, // [Pengtai Interactive Advertising Co.Ltd] + {"hash":"c395c961fb4a60ae","prefixes":{"":{"product":1284,"type":1}}}, // [Pengtai Interactive Advertising Co.Ltd] + {"hash":"2f37a86d54dbe4f9","prefixes":{"":{"product":1284,"type":1}}}, // [Pengtai Interactive Advertising Co.Ltd] + {"hash":"04730e3fb984e716","prefixes":{"":{"product":1284,"type":1}}}, // [Pengtai Interactive Advertising Co.Ltd] + {"hash":"8e040ece0573e008","prefixes":{"":{"product":1284,"type":1}}}, // [Pengtai Interactive Advertising Co.Ltd] + {"hash":"a2aafd8d622f674d","prefixes":{"":{"product":1284,"type":1}}}, // [Pengtai Interactive Advertising Co.Ltd] + {"hash":"4da566f98e41e44f","prefixes":{"":{"product":1285,"type":0}}}, // [Adello Group AG] + {"hash":"469779ba0b2d7340","prefixes":{"":{"product":1286,"type":2}}}, // [BitGravity] + {"hash":"bfa6d675fa0c17c3","prefixes":{"":{"product":1287,"type":1}}}, // [44 Interactive] {"hash":"ac3b5f670d7fd934","prefixes":{"*":{"product":1288}}}, // [KeyCDN] {"hash":"1058dbbc2bdc3042","prefixes":{"*":{"product":1288}}}, // [KeyCDN] - {"hash":"d36cc93ea8fd1701","prefixes":{"":{"product":1289}}}, // [Shopalyst Technologies Pvt Ltd] - {"hash":"95ad856091f4bc84","prefixes":{"":{"product":1289}}}, // [Shopalyst Technologies Pvt Ltd] - {"hash":"848239e92ef8cdab","prefixes":{"":{"product":1290}}}, // [Total Access Communication Public Company Limited] - {"hash":"0607ff309fec62de","prefixes":{"":{"product":1291}}}, // [TACTIC Real-time marketing AS] - {"hash":"abcc33d7fb9de6d9","prefixes":{"":{"product":1292}}}, // [Mobilewalla, Inc] - {"hash":"c7bbc2be78119074","prefixes":{"":{"product":1293}}}, // [Nuviad Ltd] + {"hash":"d36cc93ea8fd1701","prefixes":{"":{"product":1289,"type":0}}}, // [Shopalyst Technologies Pvt Ltd] + {"hash":"95ad856091f4bc84","prefixes":{"":{"product":1289,"type":0}}}, // [Shopalyst Technologies Pvt Ltd] + {"hash":"848239e92ef8cdab","prefixes":{"":{"product":1290,"type":0}}}, // [Total Access Communication Public Company Limited] + {"hash":"0607ff309fec62de","prefixes":{"":{"product":1291,"type":0}}}, // [TACTIC Real-time marketing AS] + {"hash":"abcc33d7fb9de6d9","prefixes":{"":{"product":1292,"type":0}}}, // [Mobilewalla, Inc] + {"hash":"c7bbc2be78119074","prefixes":{"":{"product":1293,"type":0}}}, // [Nuviad Ltd] {"hash":"63da29d5b072ec2a","prefixes":{"*":{"product":1294}}}, // [AmberData LLC] - {"hash":"6c2f34d23d272f4b","prefixes":{"":{"product":1295}}}, // [Aedgency] - {"hash":"2da837b490e2d01c","prefixes":{"":{"product":1296}}}, // [MobPartner, Inc.] - {"hash":"900c7f6444e6ccdd","prefixes":{"":{"product":1297}}}, // [AdTriba GmbH] - {"hash":"9110b2853fbfc1f4","prefixes":{"":{"product":1297}}}, // [AdTriba GmbH] - {"hash":"0a9e29016a6f697e","prefixes":{"":{"product":1298}}}, // [DISH Network L.L.C.] + {"hash":"6c2f34d23d272f4b","prefixes":{"":{"product":1295,"type":0}}}, // [Aedgency] + {"hash":"2da837b490e2d01c","prefixes":{"":{"product":1296,"type":0}}}, // [MobPartner, Inc.] + {"hash":"900c7f6444e6ccdd","prefixes":{"":{"product":1297,"type":1}}}, // [AdTriba GmbH] + {"hash":"9110b2853fbfc1f4","prefixes":{"":{"product":1297,"type":1}}}, // [AdTriba GmbH] + {"hash":"0a9e29016a6f697e","prefixes":{"":{"product":1298,"type":1}}}, // [DISH Network L.L.C.] {"hash":"8c7746484c824908","prefixes":{"":{"product":1299}}}, // [Monotype Imaging Inc.] {"hash":"11826b3490b70597","prefixes":{"":{"product":1299}}}, // [Monotype Imaging Inc.] {"hash":"55b9261efb54de8c","prefixes":{"":{"product":1299}}}, // [Monotype Imaging Inc.] {"hash":"57f3bae0dc69937f","prefixes":{"":{"product":1299}}}, // [Monotype Imaging Inc.] - {"hash":"b5158a795c80a5a2","prefixes":{"":{"product":1300}}}, // [MEDIAN Ltd.] - {"hash":"e79098d30fde1a28","prefixes":{"":{"product":1301}}}, // [ClickForce Inc.] - {"hash":"36739070f3c0ff16","prefixes":{"":{"product":1301}}}, // [ClickForce Inc.] - {"hash":"40febfb412ba6ddb","prefixes":{"":{"product":1302}}}, // [Zemanta Inc.] - {"hash":"80e8d865a27bacac","prefixes":{"":{"product":237}}}, // [Hostelworld.com Limited] - {"hash":"2a3acfae7d4bdd9b","prefixes":{"":{"product":861}}}, // [Barometric] - {"hash":"a48dde8fab3a9ca1","prefixes":{"*":{"product":1303}}}, // [jsdelivr.com] - {"hash":"82b544dbc2fdd536","prefixes":{"*":{"product":1304}}}, // [Adssets AB] - {"hash":"46106972e3ebaddb","prefixes":{"":{"product":1305}}}, // [Sellpoints Inc.] - {"hash":"bbc8c43681364c14","prefixes":{"":{"product":46}}}, // [Opera Mediaworks Inc.] - {"hash":"a3ff6df6612f21df","prefixes":{"":{"product":46}}}, // [Opera Mediaworks Inc.] - {"hash":"759162b5823db802","prefixes":{"":{"product":1306}}}, // [HockeyCurve Growth Solutions Pvt Ltd] - {"hash":"b3f9f03fb2c77a95","prefixes":{"":{"product":1307}}}, // [HockeyCurve Growth Solutions Pyt Ltd] - {"hash":"0dcbeed5fe35278e","prefixes":{"":{"product":1307}}}, // [HockeyCurve Growth Solutions Pyt Ltd] - {"hash":"e6898006d78eca08","prefixes":{"":{"product":1308}}}, // [Umeng Plus Beijing Technology Limited Company] - {"hash":"c2ecb9f34950ae64","prefixes":{"":{"product":1308}}}, // [Umeng Plus Beijing Technology Limited Company] - {"hash":"e530de1f6ff8ed8c","prefixes":{"":{"product":1308}}}, // [Umeng Plus Beijing Technology Limited Company] - {"hash":"ef9efb2dfd9b223f","prefixes":{"":{"product":1308}}}, // [Umeng Plus Beijing Technology Limited Company] - {"hash":"8dad79c9e968f7ca","prefixes":{"":{"product":1309}}}, // [Survata, Inc.] - {"hash":"7a5110db80c0493f","prefixes":{"":{"product":1309}}}, // [Survata, Inc.] - {"hash":"e8cb0ee7c430e881","prefixes":{"":{"product":1310}}}, // [JustWatch GmbH] - {"hash":"c85404f2f558dbd2","prefixes":{"":{"product":1310}}}, // [JustWatch GmbH] - {"hash":"b44b63d6e81094e4","prefixes":{"":{"product":1310}}}, // [JustWatch GmbH] - {"hash":"e1614140e3cef4fd","prefixes":{"":{"product":1310}}}, // [JustWatch GmbH] - {"hash":"2cfd0204e2673c60","prefixes":{"":{"product":1311}}}, // [Interactive Tracker Next] + {"hash":"b5158a795c80a5a2","prefixes":{"":{"product":1300,"type":1}}}, // [MEDIAN Ltd.] + {"hash":"e79098d30fde1a28","prefixes":{"":{"product":1301,"type":0}}}, // [ClickForce Inc.] + {"hash":"36739070f3c0ff16","prefixes":{"":{"product":1301,"type":0}}}, // [ClickForce Inc.] + {"hash":"40febfb412ba6ddb","prefixes":{"":{"product":1302,"type":0}}}, // [Zemanta Inc.] + {"hash":"80e8d865a27bacac","prefixes":{"":{"product":237,"type":0}}}, // [Hostelworld.com Limited] + {"hash":"2a3acfae7d4bdd9b","prefixes":{"":{"product":861,"type":0}}}, // [Barometric] + {"hash":"a48dde8fab3a9ca1","prefixes":{"*":{"product":1303,"type":0}}}, // [jsdelivr.com] + {"hash":"82b544dbc2fdd536","prefixes":{"*":{"product":1304,"type":0}}}, // [Adssets AB] + {"hash":"46106972e3ebaddb","prefixes":{"":{"product":1305,"type":1}}}, // [Sellpoints Inc.] + {"hash":"bbc8c43681364c14","prefixes":{"":{"product":46,"type":0}}}, // [Opera Mediaworks Inc.] + {"hash":"a3ff6df6612f21df","prefixes":{"":{"product":46,"type":0}}}, // [Opera Mediaworks Inc.] + {"hash":"759162b5823db802","prefixes":{"":{"product":1306,"type":0}}}, // [HockeyCurve Growth Solutions Pvt Ltd] + {"hash":"b3f9f03fb2c77a95","prefixes":{"":{"product":1307,"type":1}}}, // [HockeyCurve Growth Solutions Pyt Ltd] + {"hash":"0dcbeed5fe35278e","prefixes":{"":{"product":1307,"type":1}}}, // [HockeyCurve Growth Solutions Pyt Ltd] + {"hash":"e6898006d78eca08","prefixes":{"":{"product":1308,"type":1}}}, // [Umeng Plus Beijing Technology Limited Company] + {"hash":"c2ecb9f34950ae64","prefixes":{"":{"product":1308,"type":1}}}, // [Umeng Plus Beijing Technology Limited Company] + {"hash":"e530de1f6ff8ed8c","prefixes":{"":{"product":1308,"type":1}}}, // [Umeng Plus Beijing Technology Limited Company] + {"hash":"ef9efb2dfd9b223f","prefixes":{"":{"product":1308,"type":1}}}, // [Umeng Plus Beijing Technology Limited Company] + {"hash":"8dad79c9e968f7ca","prefixes":{"":{"product":1309,"type":1}}}, // [Survata, Inc.] + {"hash":"7a5110db80c0493f","prefixes":{"":{"product":1309,"type":1}}}, // [Survata, Inc.] + {"hash":"e8cb0ee7c430e881","prefixes":{"":{"product":1310,"type":1}}}, // [JustWatch GmbH] + {"hash":"c85404f2f558dbd2","prefixes":{"":{"product":1310,"type":1}}}, // [JustWatch GmbH] + {"hash":"b44b63d6e81094e4","prefixes":{"":{"product":1310,"type":1}}}, // [JustWatch GmbH] + {"hash":"e1614140e3cef4fd","prefixes":{"":{"product":1310,"type":1}}}, // [JustWatch GmbH] + {"hash":"2cfd0204e2673c60","prefixes":{"":{"product":1311,"type":1}}}, // [Interactive Tracker Next] {"hash":"1c5f8f88ce98b360","prefixes":{"":{"product":1312}}}, // [Unisport A/S] {"hash":"fbac71ab5dbe5025","prefixes":{"":{"product":1312}}}, // [Unisport A/S] {"hash":"4e08c60f61b1ac87","prefixes":{"":{"product":1312}}}, // [Unisport A/S] @@ -6242,11 +6240,11 @@ {"hash":"d0d20b9b53b41e58","prefixes":{"":{"product":1312}}}, // [Unisport A/S] {"hash":"ff37598c00132a2a","prefixes":{"":{"product":1312}}}, // [Unisport A/S] {"hash":"daae3b285b4abeee","prefixes":{"":{"product":1312}}}, // [Unisport A/S] - {"hash":"20cdb1f9a8066fe2","prefixes":{"":{"product":1313}}}, // [OPTDCOM TEKNOLOJİ YATIRIM ANONİM ŞİRKETİ] - {"hash":"a53281df69681314","prefixes":{"":{"product":1313}}}, // [OPTDCOM TEKNOLOJİ YATIRIM ANONİM ŞİRKETİ] - {"hash":"f25344f6f85b0f61","prefixes":{"":{"product":1313}}}, // [OPTDCOM TEKNOLOJİ YATIRIM ANONİM ŞİRKETİ] - {"hash":"b544d72a6726ee1d","prefixes":{"":{"product":1314}}}, // [Softcube Inc.] - {"hash":"d924c399f5813397","prefixes":{"":{"product":1315}}}, // [YOptima Media Solutions Pvt. Ltd] + {"hash":"20cdb1f9a8066fe2","prefixes":{"":{"product":1313,"type":0}}}, // [OPTDCOM TEKNOLOJİ YATIRIM ANONİM ŞİRKETİ] + {"hash":"a53281df69681314","prefixes":{"":{"product":1313,"type":0}}}, // [OPTDCOM TEKNOLOJİ YATIRIM ANONİM ŞİRKETİ] + {"hash":"f25344f6f85b0f61","prefixes":{"":{"product":1313,"type":0}}}, // [OPTDCOM TEKNOLOJİ YATIRIM ANONİM ŞİRKETİ] + {"hash":"b544d72a6726ee1d","prefixes":{"":{"product":1314,"type":0}}}, // [Softcube Inc.] + {"hash":"d924c399f5813397","prefixes":{"":{"product":1315,"type":0}}}, // [YOptima Media Solutions Pvt. Ltd] {"hash":"3405e57b3b784a16","prefixes":{"":{"product":1316}}}, // [ZMAGS INC] {"hash":"8a5251fd38cf1d3b","prefixes":{"":{"product":1316}}}, // [ZMAGS INC] {"hash":"039987610c50338a","prefixes":{"":{"product":1316}}}, // [ZMAGS INC] @@ -6254,31 +6252,31 @@ {"hash":"77f81cf76bb9bd07","prefixes":{"":{"product":1316}}}, // [ZMAGS INC] {"hash":"ec6a93785f45f030","prefixes":{"":{"product":1316}}}, // [ZMAGS INC] {"hash":"3fcf5b9a36bb776b","prefixes":{"":{"product":1316}}}, // [ZMAGS INC] - {"hash":"b81945950b163ad1","prefixes":{"":{"product":1307}}}, // [HockeyCurve Growth Solutions Pyt Ltd] - {"hash":"36c7ea48fdc42362","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"a3bfc331d20ba3e8","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"64a6cb69505f47a8","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"e7d85f73b7514aa9","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"0263af098607c6d6","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"5c911e8fdb9b3507","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"665d12aaa10c1858","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"206d02e9bc6dc66f","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"681210fb48272cc7","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"f42b80ceeefbc2e4","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"9b951656519bc7f0","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"f615949643fdcebb","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"814934c13235b868","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"d451d289ed990ba0","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"b2de6bb8607f747e","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"fa9dba37389c8a9e","prefixes":{"":{"product":691}}}, // [Aniview LTD.] + {"hash":"b81945950b163ad1","prefixes":{"":{"product":1307,"type":1}}}, // [HockeyCurve Growth Solutions Pyt Ltd] + {"hash":"36c7ea48fdc42362","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"a3bfc331d20ba3e8","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"64a6cb69505f47a8","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"e7d85f73b7514aa9","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"0263af098607c6d6","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"5c911e8fdb9b3507","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"665d12aaa10c1858","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"206d02e9bc6dc66f","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"681210fb48272cc7","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"f42b80ceeefbc2e4","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"9b951656519bc7f0","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"f615949643fdcebb","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"814934c13235b868","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"d451d289ed990ba0","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"b2de6bb8607f747e","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"fa9dba37389c8a9e","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] {"hash":"fe776ee0016175b8","prefixes":{"":{"product":691}}}, // [Aniview LTD.] {"hash":"1a561a0db871620b","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"84440122e5725865","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"f98baedc7354d85b","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"cedef135a07c2d1b","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"b7196f696d55352b","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"90c8f9118f9c2653","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"7ec460729f94a446","prefixes":{"":{"product":1317}}}, // [Realtag] + {"hash":"84440122e5725865","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"f98baedc7354d85b","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"cedef135a07c2d1b","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"b7196f696d55352b","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"90c8f9118f9c2653","prefixes":{"":{"product":691,"type":0}}}, // [Aniview LTD.] + {"hash":"7ec460729f94a446","prefixes":{"":{"product":1317,"type":1}}}, // [Realtag] {"hash":"c84baed94e3d3a6c","prefixes":{"":{"product":1318}}}, // [Bitsngo.net] {"hash":"88c72a0edf15af94","prefixes":{"":{"product":1318}}}, // [Bitsngo.net] {"hash":"8ffa9e7ae82fdaf3","prefixes":{"":{"product":1318}}}, // [Bitsngo.net] @@ -6286,105 +6284,105 @@ {"hash":"1249b88e4ce20439","prefixes":{"":{"product":1318}}}, // [Bitsngo.net] {"hash":"9555623f08217ce6","prefixes":{"":{"product":1318}}}, // [Bitsngo.net] {"hash":"0358d164ffcdc51b","prefixes":{"":{"product":1318}}}, // [Bitsngo.net] - {"hash":"d27b1458c8f91a54","prefixes":{"":{"product":1319}}}, // [AdCanvas] - {"hash":"5fd4bc3f3699146f","prefixes":{"":{"product":1319}}}, // [AdCanvas] - {"hash":"62f35089b9876ae5","prefixes":{"":{"product":1319}}}, // [AdCanvas] - {"hash":"92d701b4810ee717","prefixes":{"":{"product":1319}}}, // [AdCanvas] - {"hash":"3f927191adac8a66","prefixes":{"":{"product":1319}}}, // [AdCanvas] - {"hash":"051c9e70f0515e04","prefixes":{"":{"product":1320}}}, // [Happyfication, Inc.] - {"hash":"13580fc82945639c","prefixes":{"":{"product":1320}}}, // [Happyfication, Inc.] - {"hash":"914acd1211445b65","prefixes":{"":{"product":1320}}}, // [Happyfication, Inc.] - {"hash":"046e11a0cbc2124d","prefixes":{"":{"product":1320}}}, // [Happyfication, Inc.] + {"hash":"d27b1458c8f91a54","prefixes":{"":{"product":1319,"type":0}}}, // [AdCanvas] + {"hash":"5fd4bc3f3699146f","prefixes":{"":{"product":1319,"type":0}}}, // [AdCanvas] + {"hash":"62f35089b9876ae5","prefixes":{"":{"product":1319,"type":0}}}, // [AdCanvas] + {"hash":"92d701b4810ee717","prefixes":{"":{"product":1319,"type":0}}}, // [AdCanvas] + {"hash":"3f927191adac8a66","prefixes":{"":{"product":1319,"type":0}}}, // [AdCanvas] + {"hash":"051c9e70f0515e04","prefixes":{"":{"product":1320,"type":0}}}, // [Happyfication, Inc.] + {"hash":"13580fc82945639c","prefixes":{"":{"product":1320,"type":0}}}, // [Happyfication, Inc.] + {"hash":"914acd1211445b65","prefixes":{"":{"product":1320,"type":0}}}, // [Happyfication, Inc.] + {"hash":"046e11a0cbc2124d","prefixes":{"":{"product":1320,"type":0}}}, // [Happyfication, Inc.] {"hash":"df5483bdd241c0b5","prefixes":{"":{"product":258}}}, // [HQ GmbH] - {"hash":"8ee2f36b1789e47d","prefixes":{"":{"product":1321},"*":{"product":1322}}}, // [Cinarra Systems Japan株式会社] [Cinarra Systems Japan] - {"hash":"92d76828c2bc5e86","prefixes":{"":{"product":959}}}, // [MotoMiner] - {"hash":"014c99288a655e93","prefixes":{"":{"product":1323}}}, // [CUBED Attribution] - {"hash":"34d44a28a42c30fc","prefixes":{"":{"product":1323}}}, // [CUBED Attribution] - {"hash":"6525e4a55892b035","prefixes":{"":{"product":1324}}}, // [StackAdapt Inc.] - {"hash":"9108433b6be75366","prefixes":{"":{"product":1324}}}, // [StackAdapt Inc.] - {"hash":"ca5914cdc3f95c5a","prefixes":{"":{"product":1324}}}, // [StackAdapt Inc.] - {"hash":"e25d7e6b7298b655","prefixes":{"":{"product":1325}}}, // [Statiq Ltd] - {"hash":"63a988f83e509eca","prefixes":{"":{"product":47}}}, // [DistroScale Inc.] - {"hash":"e6c8188134efb49f","prefixes":{"":{"product":47}}}, // [DistroScale Inc.] - {"hash":"eab29bab9fd4b969","prefixes":{"":{"product":47}}}, // [DistroScale Inc.] - {"hash":"c24f6dcb16cfd4e4","prefixes":{"":{"product":47}}}, // [DistroScale Inc.] - {"hash":"e6a95c6bb8d6efd4","prefixes":{"":{"product":1326}}}, // [Tagular Analytics, LLC] - {"hash":"9c2dcc6473dee219","prefixes":{"":{"product":1326}}}, // [Tagular Analytics, LLC] - {"hash":"986af10dd127ff07","prefixes":{"":{"product":1326}}}, // [Tagular Analytics, LLC] - {"hash":"f74107ff21d433e9","prefixes":{"":{"product":1326}}}, // [Tagular Analytics, LLC] - {"hash":"ce5c1378f1f941f6","prefixes":{"":{"product":1327}}}, // [ComboTag Technologies Ltd.] - {"hash":"879f914a15df34e0","prefixes":{"":{"product":1328}}}, // [Juice Mobile] - {"hash":"17e1300dbcc39afb","prefixes":{"":{"product":1328}}}, // [Juice Mobile] - {"hash":"d22e60c27d37cebc","prefixes":{"":{"product":1328}}}, // [Juice Mobile] - {"hash":"80d91748976f3124","prefixes":{"":{"product":1328}}}, // [Juice Mobile] - {"hash":"74478806654499c0","prefixes":{"":{"product":1328}}}, // [Juice Mobile] - {"hash":"1b02f5c5bfc0039d","prefixes":{"":{"product":1328}}}, // [Juice Mobile] - {"hash":"ee644eb69f62cdec","prefixes":{"":{"product":1329}}}, // [Bebe] - {"hash":"8fb13ead8b0754fb","prefixes":{"":{"product":1330}}}, // [Augur] - {"hash":"cfbc4ef83efc3949","prefixes":{"*":{"product":1331}}}, // [Seracast Digital LLC] + {"hash":"8ee2f36b1789e47d","prefixes":{"":{"product":1321,"type":0},"*":{"product":1322,"type":0}}}, // [Cinarra Systems Japan株式会社] [Cinarra Systems Japan] + {"hash":"92d76828c2bc5e86","prefixes":{"":{"product":959,"type":0}}}, // [MotoMiner] + {"hash":"014c99288a655e93","prefixes":{"":{"product":1323,"type":1}}}, // [CUBED Attribution] + {"hash":"34d44a28a42c30fc","prefixes":{"":{"product":1323,"type":1}}}, // [CUBED Attribution] + {"hash":"6525e4a55892b035","prefixes":{"":{"product":1324,"type":0}}}, // [StackAdapt Inc.] + {"hash":"9108433b6be75366","prefixes":{"":{"product":1324,"type":0}}}, // [StackAdapt Inc.] + {"hash":"ca5914cdc3f95c5a","prefixes":{"":{"product":1324,"type":0}}}, // [StackAdapt Inc.] + {"hash":"e25d7e6b7298b655","prefixes":{"":{"product":1325,"type":1}}}, // [Statiq Ltd] + {"hash":"63a988f83e509eca","prefixes":{"":{"product":47,"type":0}}}, // [DistroScale Inc.] + {"hash":"e6c8188134efb49f","prefixes":{"":{"product":47,"type":0}}}, // [DistroScale Inc.] + {"hash":"eab29bab9fd4b969","prefixes":{"":{"product":47,"type":0}}}, // [DistroScale Inc.] + {"hash":"c24f6dcb16cfd4e4","prefixes":{"":{"product":47,"type":0}}}, // [DistroScale Inc.] + {"hash":"e6a95c6bb8d6efd4","prefixes":{"":{"product":1326,"type":1}}}, // [Tagular Analytics, LLC] + {"hash":"9c2dcc6473dee219","prefixes":{"":{"product":1326,"type":1}}}, // [Tagular Analytics, LLC] + {"hash":"986af10dd127ff07","prefixes":{"":{"product":1326,"type":1}}}, // [Tagular Analytics, LLC] + {"hash":"f74107ff21d433e9","prefixes":{"":{"product":1326,"type":1}}}, // [Tagular Analytics, LLC] + {"hash":"ce5c1378f1f941f6","prefixes":{"":{"product":1327,"type":0}}}, // [ComboTag Technologies Ltd.] + {"hash":"879f914a15df34e0","prefixes":{"":{"product":1328,"type":0}}}, // [Juice Mobile] + {"hash":"17e1300dbcc39afb","prefixes":{"":{"product":1328,"type":0}}}, // [Juice Mobile] + {"hash":"d22e60c27d37cebc","prefixes":{"":{"product":1328,"type":0}}}, // [Juice Mobile] + {"hash":"80d91748976f3124","prefixes":{"":{"product":1328,"type":0}}}, // [Juice Mobile] + {"hash":"74478806654499c0","prefixes":{"":{"product":1328,"type":0}}}, // [Juice Mobile] + {"hash":"1b02f5c5bfc0039d","prefixes":{"":{"product":1328,"type":0}}}, // [Juice Mobile] + {"hash":"ee644eb69f62cdec","prefixes":{"":{"product":1329,"type":0}}}, // [Bebe] + {"hash":"8fb13ead8b0754fb","prefixes":{"":{"product":1330,"type":1}}}, // [Augur] + {"hash":"cfbc4ef83efc3949","prefixes":{"*":{"product":1331,"type":0}}}, // [Seracast Digital LLC] {"hash":"a8285782e9e5e7e8","prefixes":{"*":{"product":1331}}}, // [Seracast Digital LLC] - {"hash":"3a9b5e5bcd74ba27","prefixes":{"":{"product":1332}}}, // [AerServ LLC] + {"hash":"3a9b5e5bcd74ba27","prefixes":{"":{"product":1332,"type":0}}}, // [AerServ LLC] {"hash":"dd4e82ee18499196","prefixes":{"":{"product":1332}}}, // [AerServ LLC] - {"hash":"2163ccdaf0c7ac04","prefixes":{"*":{"product":1321}}}, // [Cinarra Systems Japan株式会社] - {"hash":"e16e6171a3e50ef3","prefixes":{"":{"product":1333}}}, // [PT. Tokopedia] - {"hash":"74b1225f4470815b","prefixes":{"":{"product":1334}}}, // [Terapeak, Inc.] + {"hash":"2163ccdaf0c7ac04","prefixes":{"*":{"product":1321,"type":0}}}, // [Cinarra Systems Japan株式会社] + {"hash":"e16e6171a3e50ef3","prefixes":{"":{"product":1333,"type":0}}}, // [PT. Tokopedia] + {"hash":"74b1225f4470815b","prefixes":{"":{"product":1334,"type":0}}}, // [Terapeak, Inc.] {"hash":"7eb7af632c622616","prefixes":{"*":{"product":1335}}}, // [OpenStreetMap France] - {"hash":"63c3a3e6536f0b7f","prefixes":{"*":{"product":1336}}}, // [Front Porch, Inc] - {"hash":"2c6aaec84cacd716","prefixes":{"*":{"product":1336}}}, // [Front Porch, Inc] - {"hash":"6f469a516e0ea586","prefixes":{"":{"product":1337}}}, // [Vertamedia] - {"hash":"d06485ea48298b7e","prefixes":{"":{"product":1338}}}, // [Codewise (VoluumDSP)] - {"hash":"7a43b35e42bcef39","prefixes":{"":{"product":1339}}}, // [Virool Inc.] - {"hash":"4ff7c90f1d23d419","prefixes":{"":{"product":1340}}}, // [SpringServe LLC] - {"hash":"7f06352affc07566","prefixes":{"":{"product":1340}}}, // [SpringServe LLC] - {"hash":"96ea998589a3f7ab","prefixes":{"":{"product":1340}}}, // [SpringServe LLC] - {"hash":"32ec7c3af8d6ee95","prefixes":{"":{"product":1340}}}, // [SpringServe LLC] - {"hash":"294e9804817557ed","prefixes":{"":{"product":1340}}}, // [SpringServe LLC] - {"hash":"e9c681d4af45ad2c","prefixes":{"":{"product":1341}}}, // [Intimate Merger] - {"hash":"68cc07724e870731","prefixes":{"":{"product":1341}}}, // [Intimate Merger] - {"hash":"60f3c72e07bc4431","prefixes":{"":{"product":1342}}}, // [Telecoming Connectivity S.A.] - {"hash":"22081b94e890803c","prefixes":{"":{"product":1343}}}, // [Webssup] - {"hash":"00e22da76abf1e12","prefixes":{"":{"product":1343}}}, // [Webssup] - {"hash":"498495a391901f22","prefixes":{"":{"product":1344}}}, // [INCUBIQ Solutions Ltd] - {"hash":"606c712ed1507693","prefixes":{"":{"product":1344}}}, // [INCUBIQ Solutions Ltd] + {"hash":"63c3a3e6536f0b7f","prefixes":{"*":{"product":1336,"type":0}}}, // [Front Porch, Inc] + {"hash":"2c6aaec84cacd716","prefixes":{"*":{"product":1336,"type":0}}}, // [Front Porch, Inc] + {"hash":"6f469a516e0ea586","prefixes":{"":{"product":1337,"type":0}}}, // [Vertamedia] + {"hash":"d06485ea48298b7e","prefixes":{"":{"product":1338,"type":0}}}, // [Codewise (VoluumDSP)] + {"hash":"7a43b35e42bcef39","prefixes":{"":{"product":1339,"type":0}}}, // [Virool Inc.] + {"hash":"4ff7c90f1d23d419","prefixes":{"":{"product":1340,"type":0}}}, // [SpringServe LLC] + {"hash":"7f06352affc07566","prefixes":{"":{"product":1340,"type":0}}}, // [SpringServe LLC] + {"hash":"96ea998589a3f7ab","prefixes":{"":{"product":1340,"type":0}}}, // [SpringServe LLC] + {"hash":"32ec7c3af8d6ee95","prefixes":{"":{"product":1340,"type":0}}}, // [SpringServe LLC] + {"hash":"294e9804817557ed","prefixes":{"":{"product":1340,"type":0}}}, // [SpringServe LLC] + {"hash":"e9c681d4af45ad2c","prefixes":{"":{"product":1341,"type":1}}}, // [Intimate Merger] + {"hash":"68cc07724e870731","prefixes":{"":{"product":1341,"type":1}}}, // [Intimate Merger] + {"hash":"60f3c72e07bc4431","prefixes":{"":{"product":1342,"type":0}}}, // [Telecoming Connectivity S.A.] + {"hash":"22081b94e890803c","prefixes":{"":{"product":1343,"type":0}}}, // [Webssup] + {"hash":"00e22da76abf1e12","prefixes":{"":{"product":1343,"type":0}}}, // [Webssup] + {"hash":"498495a391901f22","prefixes":{"":{"product":1344,"type":1}}}, // [INCUBIQ Solutions Ltd] + {"hash":"606c712ed1507693","prefixes":{"":{"product":1344,"type":1}}}, // [INCUBIQ Solutions Ltd] {"hash":"a9af6bbd9a022211","prefixes":{"*":{"product":1336}}}, // [Front Porch, Inc] - {"hash":"5ad9370da8c17992","prefixes":{"":{"product":1345}}}, // [ADSpend] + {"hash":"5ad9370da8c17992","prefixes":{"":{"product":1345,"type":0}}}, // [ADSpend] {"hash":"fdd6cbfd0c4ad857","prefixes":{"":{"product":1346}}}, // [AdTradr Corporation] {"hash":"81b9923f85553957","prefixes":{"":{"product":1346}}}, // [AdTradr Corporation] {"hash":"a145ad19f618929c","prefixes":{"":{"product":1346}}}, // [AdTradr Corporation] {"hash":"b1930e60745f4b68","prefixes":{"":{"product":1346}}}, // [AdTradr Corporation] {"hash":"57f97d99aaf44ad1","prefixes":{"":{"product":1346}}}, // [AdTradr Corporation] - {"hash":"99143cae9fe8dcb7","prefixes":{"":{"product":1347}}}, // [Quint Growth Inc.] - {"hash":"eb5cead7881dc3da","prefixes":{"":{"product":1348}}}, // [ZAPR] + {"hash":"99143cae9fe8dcb7","prefixes":{"":{"product":1347,"type":0}}}, // [Quint Growth Inc.] + {"hash":"eb5cead7881dc3da","prefixes":{"":{"product":1348,"type":0}}}, // [ZAPR] {"hash":"2fe0bb9349d1959b","prefixes":{"":{"product":1348}}}, // [ZAPR] - {"hash":"b959bccbc132d322","prefixes":{"":{"product":20}}}, // [On Device Research Ltd.] + {"hash":"b959bccbc132d322","prefixes":{"":{"product":20,"type":1}}}, // [On Device Research Ltd.] {"hash":"8a8c554522b206ad","prefixes":{"":{"product":1349}}}, // [1trn LLC] - {"hash":"45dfdbe509539a3b","prefixes":{"":{"product":1349}}}, // [1trn LLC] - {"hash":"6265ceee0906cac8","prefixes":{"":{"product":1350}}}, // [Matiro] - {"hash":"279177f20ce276af","prefixes":{"":{"product":1350}}}, // [Matiro] - {"hash":"b90e8e5f5f114049","prefixes":{"":{"product":1350}}}, // [Matiro] - {"hash":"68519953a094dc0c","prefixes":{"":{"product":1350}}}, // [Matiro] - {"hash":"2c9356fdc6a3d512","prefixes":{"":{"product":1350}}}, // [Matiro] - {"hash":"486312e316f3d301","prefixes":{"":{"product":1350}}}, // [Matiro] - {"hash":"0dea0840245a2dd2","prefixes":{"*":{"product":1351}}}, // [Inspired Mobile Ltd.] - {"hash":"e1e444909b156b50","prefixes":{"*":{"product":1351}}}, // [Inspired Mobile Ltd.] - {"hash":"ba50b6623ecf06b7","prefixes":{"":{"product":1352}}}, // [Selectmedia International LTD.] - {"hash":"bb2433b4d9ceaf93","prefixes":{"":{"product":1352}}}, // [Selectmedia International LTD.] - {"hash":"752e7bd32ca03e2b","prefixes":{"":{"product":1352}}}, // [Selectmedia International LTD.] - {"hash":"fecd6600c1d54571","prefixes":{"":{"product":1352}}}, // [Selectmedia International LTD.] - {"hash":"e2f5a8707a39a63f","prefixes":{"":{"product":1352}}}, // [Selectmedia International LTD.] - {"hash":"6e7cd3eb7639d09a","prefixes":{"":{"product":1352}}}, // [Selectmedia International LTD.] - {"hash":"e0afc2f779238a59","prefixes":{"":{"product":1352}}}, // [Selectmedia International LTD.] - {"hash":"51c4028642a5ca4c","prefixes":{"":{"product":1352}}}, // [Selectmedia International LTD.] + {"hash":"45dfdbe509539a3b","prefixes":{"":{"product":1349,"type":0}}}, // [1trn LLC] + {"hash":"6265ceee0906cac8","prefixes":{"":{"product":1350,"type":0}}}, // [Matiro] + {"hash":"279177f20ce276af","prefixes":{"":{"product":1350,"type":0}}}, // [Matiro] + {"hash":"b90e8e5f5f114049","prefixes":{"":{"product":1350,"type":0}}}, // [Matiro] + {"hash":"68519953a094dc0c","prefixes":{"":{"product":1350,"type":0}}}, // [Matiro] + {"hash":"2c9356fdc6a3d512","prefixes":{"":{"product":1350,"type":0}}}, // [Matiro] + {"hash":"486312e316f3d301","prefixes":{"":{"product":1350,"type":0}}}, // [Matiro] + {"hash":"0dea0840245a2dd2","prefixes":{"*":{"product":1351,"type":0}}}, // [Inspired Mobile Ltd.] + {"hash":"e1e444909b156b50","prefixes":{"*":{"product":1351,"type":0}}}, // [Inspired Mobile Ltd.] + {"hash":"ba50b6623ecf06b7","prefixes":{"":{"product":1352,"type":0}}}, // [Selectmedia International LTD.] + {"hash":"bb2433b4d9ceaf93","prefixes":{"":{"product":1352,"type":0}}}, // [Selectmedia International LTD.] + {"hash":"752e7bd32ca03e2b","prefixes":{"":{"product":1352,"type":0}}}, // [Selectmedia International LTD.] + {"hash":"fecd6600c1d54571","prefixes":{"":{"product":1352,"type":0}}}, // [Selectmedia International LTD.] + {"hash":"e2f5a8707a39a63f","prefixes":{"":{"product":1352,"type":0}}}, // [Selectmedia International LTD.] + {"hash":"6e7cd3eb7639d09a","prefixes":{"":{"product":1352,"type":0}}}, // [Selectmedia International LTD.] + {"hash":"e0afc2f779238a59","prefixes":{"":{"product":1352,"type":0}}}, // [Selectmedia International LTD.] + {"hash":"51c4028642a5ca4c","prefixes":{"":{"product":1352,"type":0}}}, // [Selectmedia International LTD.] {"hash":"1640e1eeb06df964","prefixes":{"":{"product":1352}}}, // [Selectmedia International LTD.] {"hash":"6c8c2f363cf647b5","prefixes":{"":{"product":1352}}}, // [Selectmedia International LTD.] {"hash":"d9f31e1a90e8fb75","prefixes":{"":{"product":1352}}}, // [Selectmedia International LTD.] {"hash":"845fb9c6387bef97","prefixes":{"":{"product":1352}}}, // [Selectmedia International LTD.] {"hash":"0459341df70cc072","prefixes":{"":{"product":1352}}}, // [Selectmedia International LTD.] - {"hash":"be68419b316ae4c5","prefixes":{"":{"product":1353}}}, // [Internet Billboard, a. s] - {"hash":"ba9be76fe6cba556","prefixes":{"":{"product":1353}}}, // [Internet Billboard, a. s] - {"hash":"ec3aa5f11c754de6","prefixes":{"":{"product":1353}}}, // [Internet Billboard, a. s] - {"hash":"5023d333c14740b4","prefixes":{"":{"product":1353}}}, // [Internet Billboard, a. s] - {"hash":"eab4b496bc09743b","prefixes":{"":{"product":1354}}}, // [Volvelle] + {"hash":"be68419b316ae4c5","prefixes":{"":{"product":1353,"type":0}}}, // [Internet Billboard, a. s] + {"hash":"ba9be76fe6cba556","prefixes":{"":{"product":1353,"type":0}}}, // [Internet Billboard, a. s] + {"hash":"ec3aa5f11c754de6","prefixes":{"":{"product":1353,"type":0}}}, // [Internet Billboard, a. s] + {"hash":"5023d333c14740b4","prefixes":{"":{"product":1353,"type":0}}}, // [Internet Billboard, a. s] + {"hash":"eab4b496bc09743b","prefixes":{"":{"product":1354,"type":0}}}, // [Volvelle] {"hash":"2afdaf8d1bad3cb9","prefixes":{"":{"product":1355}}}, // [StreamRail Ltd.] {"hash":"c2367faa0f667908","prefixes":{"":{"product":1355}}}, // [StreamRail Ltd.] {"hash":"ed58e98b46833296","prefixes":{"":{"product":1355}}}, // [StreamRail Ltd.] @@ -6404,227 +6402,227 @@ {"hash":"cdeee95936c4dbc6","prefixes":{"":{"product":1355}}}, // [StreamRail Ltd.] {"hash":"812ac20217e10e22","prefixes":{"":{"product":1355}}}, // [StreamRail Ltd.] {"hash":"a20318efcc942b0c","prefixes":{"":{"product":1355}}}, // [StreamRail Ltd.] - {"hash":"7ba3379a648cbc77","prefixes":{"":{"product":1356}}}, // [E-Contenta] - {"hash":"faca10de01f9747f","prefixes":{"":{"product":1356}}}, // [E-Contenta] - {"hash":"c4bada2290c2b41f","prefixes":{"":{"product":1356}}}, // [E-Contenta] - {"hash":"7e8290508a81ecfd","prefixes":{"":{"product":1356}}}, // [E-Contenta] - {"hash":"415fbdfa7cf95914","prefixes":{"":{"product":1356}}}, // [E-Contenta] - {"hash":"97322010e9179343","prefixes":{"":{"product":1356}}}, // [E-Contenta] - {"hash":"07549a667fcd0003","prefixes":{"":{"product":1356}}}, // [E-Contenta] - {"hash":"f5359f09115e5a08","prefixes":{"":{"product":1357}}}, // [Bath and Body Works] + {"hash":"7ba3379a648cbc77","prefixes":{"":{"product":1356,"type":0}}}, // [E-Contenta] + {"hash":"faca10de01f9747f","prefixes":{"":{"product":1356,"type":0}}}, // [E-Contenta] + {"hash":"c4bada2290c2b41f","prefixes":{"":{"product":1356,"type":0}}}, // [E-Contenta] + {"hash":"7e8290508a81ecfd","prefixes":{"":{"product":1356,"type":0}}}, // [E-Contenta] + {"hash":"415fbdfa7cf95914","prefixes":{"":{"product":1356,"type":0}}}, // [E-Contenta] + {"hash":"97322010e9179343","prefixes":{"":{"product":1356,"type":0}}}, // [E-Contenta] + {"hash":"07549a667fcd0003","prefixes":{"":{"product":1356,"type":0}}}, // [E-Contenta] + {"hash":"f5359f09115e5a08","prefixes":{"":{"product":1357,"type":0}}}, // [Bath and Body Works] {"hash":"93931937deeacde2","prefixes":{"":{"product":1160}}}, // [KuaiziTech] {"hash":"885efbcb155efd68","prefixes":{"":{"product":691}}}, // [Aniview LTD.] {"hash":"8515f5e803de693b","prefixes":{"":{"product":691}}}, // [Aniview LTD.] {"hash":"7990fea9b4cdbdf9","prefixes":{"":{"product":691}}}, // [Aniview LTD.] {"hash":"a6632e804a3dc853","prefixes":{"":{"product":691}}}, // [Aniview LTD.] {"hash":"ae4745b0fd104fbb","prefixes":{"":{"product":691}}}, // [Aniview LTD.] - {"hash":"956dc47eeadd36f7","prefixes":{"":{"product":1358}}}, // [WooTag Pte Ltd] - {"hash":"091b478316a2c133","prefixes":{"":{"product":1358}}}, // [WooTag Pte Ltd] - {"hash":"dc8fa04b592b8307","prefixes":{"":{"product":1358}}}, // [WooTag Pte Ltd] + {"hash":"956dc47eeadd36f7","prefixes":{"":{"product":1358,"type":0}}}, // [WooTag Pte Ltd] + {"hash":"091b478316a2c133","prefixes":{"":{"product":1358,"type":0}}}, // [WooTag Pte Ltd] + {"hash":"dc8fa04b592b8307","prefixes":{"":{"product":1358,"type":0}}}, // [WooTag Pte Ltd] {"hash":"fe0e326ac7dc8d7c","prefixes":{"":{"product":1358}}}, // [WooTag Pte Ltd] - {"hash":"410a107d660ab1cd","prefixes":{"":{"product":1359}}}, // [Cint AB] - {"hash":"b294fa0e55fcd2f4","prefixes":{"":{"product":1359}}}, // [Cint AB] - {"hash":"5519fa5da5e57ad1","prefixes":{"":{"product":1360}}}, // [Stein Mart] - {"hash":"7277d1fc5bc3c416","prefixes":{"":{"product":1361}}}, // [Sift Media, Inc.] - {"hash":"4b89510469e15939","prefixes":{"":{"product":1362}}}, // [StartApp Inc.] - {"hash":"d3b5600174198250","prefixes":{"":{"product":1362}}}, // [StartApp Inc.] - {"hash":"5597070a34018ed8","prefixes":{"":{"product":1362}}}, // [StartApp Inc.] - {"hash":"17f290970639d124","prefixes":{"":{"product":1363}}}, // [Pxene - DSP] - {"hash":"263ee2028bc08b39","prefixes":{"":{"product":1363}}}, // [Pxene - DSP] - {"hash":"da0f3a897355dd67","prefixes":{"":{"product":1363}}}, // [Pxene - DSP] - {"hash":"9ca84ba93389421b","prefixes":{"":{"product":1363}}}, // [Pxene - DSP] - {"hash":"4d5f045a10baa819","prefixes":{"":{"product":1364}}}, // [Integral Marketing] + {"hash":"410a107d660ab1cd","prefixes":{"":{"product":1359,"type":1}}}, // [Cint AB] + {"hash":"b294fa0e55fcd2f4","prefixes":{"":{"product":1359,"type":1}}}, // [Cint AB] + {"hash":"5519fa5da5e57ad1","prefixes":{"":{"product":1360,"type":0}}}, // [Stein Mart] + {"hash":"7277d1fc5bc3c416","prefixes":{"":{"product":1361,"type":0}}}, // [Sift Media, Inc.] + {"hash":"4b89510469e15939","prefixes":{"":{"product":1362,"type":0}}}, // [StartApp Inc.] + {"hash":"d3b5600174198250","prefixes":{"":{"product":1362,"type":0}}}, // [StartApp Inc.] + {"hash":"5597070a34018ed8","prefixes":{"":{"product":1362,"type":0}}}, // [StartApp Inc.] + {"hash":"17f290970639d124","prefixes":{"":{"product":1363,"type":0}}}, // [Pxene - DSP] + {"hash":"263ee2028bc08b39","prefixes":{"":{"product":1363,"type":0}}}, // [Pxene - DSP] + {"hash":"da0f3a897355dd67","prefixes":{"":{"product":1363,"type":0}}}, // [Pxene - DSP] + {"hash":"9ca84ba93389421b","prefixes":{"":{"product":1363,"type":0}}}, // [Pxene - DSP] + {"hash":"4d5f045a10baa819","prefixes":{"":{"product":1364,"type":0}}}, // [Integral Marketing] {"hash":"50bc395b6101613b","prefixes":{"":{"product":1364}}}, // [Integral Marketing] - {"hash":"3affd533937e3000","prefixes":{"":{"product":48}}}, // [Enzymic Consultancy] - {"hash":"971d313a32301476","prefixes":{"":{"product":48}}}, // [Enzymic Consultancy] - {"hash":"c5351f32e51be2fe","prefixes":{"":{"product":48}}}, // [Enzymic Consultancy] - {"hash":"4d91e6834270bed5","prefixes":{"":{"product":48}}}, // [Enzymic Consultancy] - {"hash":"5d662bce285c4f62","prefixes":{"":{"product":48}}}, // [Enzymic Consultancy] + {"hash":"3affd533937e3000","prefixes":{"":{"product":48,"type":0}}}, // [Enzymic Consultancy] + {"hash":"971d313a32301476","prefixes":{"":{"product":48,"type":0}}}, // [Enzymic Consultancy] + {"hash":"c5351f32e51be2fe","prefixes":{"":{"product":48,"type":0}}}, // [Enzymic Consultancy] + {"hash":"4d91e6834270bed5","prefixes":{"":{"product":48,"type":0}}}, // [Enzymic Consultancy] + {"hash":"5d662bce285c4f62","prefixes":{"":{"product":48,"type":0}}}, // [Enzymic Consultancy] {"hash":"acf96648fc83494b","prefixes":{"":{"product":48}}}, // [Enzymic Consultancy] {"hash":"ea62a03194f9fd95","prefixes":{"":{"product":1365}}}, // [Expedia, Inc.] - {"hash":"d3ff1633dded1329","prefixes":{"":{"product":1366}}}, // [DeepIntent, Inc] - {"hash":"2b5d6ad4574423ab","prefixes":{"":{"product":1366}}}, // [DeepIntent, Inc] - {"hash":"dd8c5b641bb2871c","prefixes":{"":{"product":1366}}}, // [DeepIntent, Inc] - {"hash":"4ba3d981f5073f12","prefixes":{"":{"product":1366}}}, // [DeepIntent, Inc] - {"hash":"92f845f3cbfc83ca","prefixes":{"":{"product":181}}}, // [Rakuten Attribution] - {"hash":"ff93f30e29dd79ce","prefixes":{"":{"product":1367}}}, // [OmniVirt] - {"hash":"1219256c57d362c2","prefixes":{"":{"product":1367}}}, // [OmniVirt] - {"hash":"588a30ada75d3716","prefixes":{"":{"product":1367}}}, // [OmniVirt] - {"hash":"f99b3a1ad217ec24","prefixes":{"":{"product":1367}}}, // [OmniVirt] - {"hash":"cffe29c52b1b73c5","prefixes":{"":{"product":1367}}}, // [OmniVirt] - {"hash":"f03d942c23c65a90","prefixes":{"":{"product":1367}}}, // [OmniVirt] - {"hash":"272d4c035a088de6","prefixes":{"":{"product":1367}}}, // [OmniVirt] - {"hash":"724568d0c3fc08a4","prefixes":{"":{"product":1368}}}, // ["Index20" LLC] - {"hash":"be108323d132726d","prefixes":{"":{"product":1369}}}, // [Conversion Logic, Inc.] + {"hash":"d3ff1633dded1329","prefixes":{"":{"product":1366,"type":0}}}, // [DeepIntent, Inc] + {"hash":"2b5d6ad4574423ab","prefixes":{"":{"product":1366,"type":0}}}, // [DeepIntent, Inc] + {"hash":"dd8c5b641bb2871c","prefixes":{"":{"product":1366,"type":0}}}, // [DeepIntent, Inc] + {"hash":"4ba3d981f5073f12","prefixes":{"":{"product":1366,"type":0}}}, // [DeepIntent, Inc] + {"hash":"92f845f3cbfc83ca","prefixes":{"":{"product":181,"type":1}}}, // [Rakuten Attribution] + {"hash":"ff93f30e29dd79ce","prefixes":{"":{"product":1367,"type":0}}}, // [OmniVirt] + {"hash":"1219256c57d362c2","prefixes":{"":{"product":1367,"type":0}}}, // [OmniVirt] + {"hash":"588a30ada75d3716","prefixes":{"":{"product":1367,"type":0}}}, // [OmniVirt] + {"hash":"f99b3a1ad217ec24","prefixes":{"":{"product":1367,"type":0}}}, // [OmniVirt] + {"hash":"cffe29c52b1b73c5","prefixes":{"":{"product":1367,"type":0}}}, // [OmniVirt] + {"hash":"f03d942c23c65a90","prefixes":{"":{"product":1367,"type":0}}}, // [OmniVirt] + {"hash":"272d4c035a088de6","prefixes":{"":{"product":1367,"type":0}}}, // [OmniVirt] + {"hash":"724568d0c3fc08a4","prefixes":{"":{"product":1368,"type":0}}}, // ["Index20" LLC] + {"hash":"be108323d132726d","prefixes":{"":{"product":1369,"type":1}}}, // [Conversion Logic, Inc.] {"hash":"9fc3b91614502933","prefixes":{"":{"product":1370}}}, // [Collegehumor] {"hash":"bb96895ad0b3fb46","prefixes":{"":{"product":1370}}}, // [Collegehumor] {"hash":"830074aed1a53d22","prefixes":{"":{"product":1370}}}, // [Collegehumor] - {"hash":"db32b2c0136553c9","prefixes":{"":{"product":775}}}, // [Netflix, Inc.] - {"hash":"47df197461b802d5","prefixes":{"":{"product":775}}}, // [Netflix, Inc.] - {"hash":"acbf0ad8badc6915","prefixes":{"":{"product":775}}}, // [Netflix, Inc.] - {"hash":"c0b6c8d5b1736dc3","prefixes":{"":{"product":775}}}, // [Netflix, Inc.] - {"hash":"05dd2a6c687d34c0","prefixes":{"":{"product":1371}}}, // [Silence Media Limited] - {"hash":"cea7d6ed17648fbf","prefixes":{"":{"product":1371}}}, // [Silence Media Limited] - {"hash":"ad7149f316532231","prefixes":{"":{"product":1372}}}, // [Zuuvi Aps] - {"hash":"693751faddbb5801","prefixes":{"":{"product":1372}}}, // [Zuuvi Aps] - {"hash":"8da87b729d579d09","prefixes":{"":{"product":1372}}}, // [Zuuvi Aps] - {"hash":"ab5cc3951d346c77","prefixes":{"":{"product":1372}}}, // [Zuuvi Aps] - {"hash":"f41a4b1ac6a3bfb2","prefixes":{"":{"product":1373}}}, // [SoftBank Corp.] - {"hash":"1d0977195dc18825","prefixes":{"":{"product":1374}}}, // [ConnectOM, Inc.] - {"hash":"912365bfc81f780a","prefixes":{"":{"product":1374}}}, // [ConnectOM, Inc.] - {"hash":"7434a888611cfaf2","prefixes":{"":{"product":1374}}}, // [ConnectOM, Inc.] - {"hash":"1d73404a4d6b3cda","prefixes":{"":{"product":49}}}, // [Fluct Inc.] - {"hash":"938fa93131d63045","prefixes":{"":{"product":49}}}, // [Fluct Inc.] - {"hash":"67f35499d1bf5216","prefixes":{"":{"product":1375}}}, // [Skillup Video Technologies Corporation] - {"hash":"c8e2c0c42c388ceb","prefixes":{"":{"product":1375}}}, // [Skillup Video Technologies Corporation] + {"hash":"db32b2c0136553c9","prefixes":{"":{"product":775,"type":0}}}, // [Netflix, Inc.] + {"hash":"47df197461b802d5","prefixes":{"":{"product":775,"type":0}}}, // [Netflix, Inc.] + {"hash":"acbf0ad8badc6915","prefixes":{"":{"product":775,"type":0}}}, // [Netflix, Inc.] + {"hash":"c0b6c8d5b1736dc3","prefixes":{"":{"product":775,"type":0}}}, // [Netflix, Inc.] + {"hash":"05dd2a6c687d34c0","prefixes":{"":{"product":1371,"type":0}}}, // [Silence Media Limited] + {"hash":"cea7d6ed17648fbf","prefixes":{"":{"product":1371,"type":0}}}, // [Silence Media Limited] + {"hash":"ad7149f316532231","prefixes":{"":{"product":1372,"type":0}}}, // [Zuuvi Aps] + {"hash":"693751faddbb5801","prefixes":{"":{"product":1372,"type":0}}}, // [Zuuvi Aps] + {"hash":"8da87b729d579d09","prefixes":{"":{"product":1372,"type":0}}}, // [Zuuvi Aps] + {"hash":"ab5cc3951d346c77","prefixes":{"":{"product":1372,"type":0}}}, // [Zuuvi Aps] + {"hash":"f41a4b1ac6a3bfb2","prefixes":{"":{"product":1373,"type":1}}}, // [SoftBank Corp.] + {"hash":"1d0977195dc18825","prefixes":{"":{"product":1374,"type":0}}}, // [ConnectOM, Inc.] + {"hash":"912365bfc81f780a","prefixes":{"":{"product":1374,"type":0}}}, // [ConnectOM, Inc.] + {"hash":"7434a888611cfaf2","prefixes":{"":{"product":1374,"type":0}}}, // [ConnectOM, Inc.] + {"hash":"1d73404a4d6b3cda","prefixes":{"":{"product":49,"type":0}}}, // [Fluct Inc.] + {"hash":"938fa93131d63045","prefixes":{"":{"product":49,"type":0}}}, // [Fluct Inc.] + {"hash":"67f35499d1bf5216","prefixes":{"":{"product":1375,"type":0}}}, // [Skillup Video Technologies Corporation] + {"hash":"c8e2c0c42c388ceb","prefixes":{"":{"product":1375,"type":0}}}, // [Skillup Video Technologies Corporation] {"hash":"0800074e9a8aa9e0","prefixes":{"":{"product":1375}}}, // [Skillup Video Technologies Corporation] - {"hash":"f6853fba1d5c8366","prefixes":{"":{"product":1376}}}, // [Adara Impact Analytics] - {"hash":"7d5aa0875b5b03ee","prefixes":{"":{"product":1376}}}, // [Adara Impact Analytics] - {"hash":"e1a55205d635d049","prefixes":{"":{"product":1376}}}, // [Adara Impact Analytics] - {"hash":"b5ea51bb0aec174c","prefixes":{"":{"product":1376}}}, // [Adara Impact Analytics] - {"hash":"e4140b78afda4fb4","prefixes":{"":{"product":1376}}}, // [Adara Impact Analytics] - {"hash":"a4c74032025e0589","prefixes":{"":{"product":1377}}}, // [TabMo SAS] - {"hash":"d9638d78485cff41","prefixes":{"":{"product":1377}}}, // [TabMo SAS] - {"hash":"6ea3e003ed64d138","prefixes":{"":{"product":58}}}, // [Sixt Leasing SE] - {"hash":"22ae0beb131c4b8c","prefixes":{"":{"product":1378}}}, // [Casale Media] - {"hash":"29d1aaca6b9e6edd","prefixes":{"":{"product":1378}}}, // [Casale Media] - {"hash":"7d1380d196e0f347","prefixes":{"":{"product":1379}}}, // [StickyADStv] - {"hash":"147ac7b767355a32","prefixes":{"":{"product":1380}}}, // [Teads Technology SAS] - {"hash":"4b60266ba860a4c5","prefixes":{"":{"product":1381}}}, // [Anomaly Communications, LLC] - {"hash":"296893a9570ca935","prefixes":{"*":{"product":1382}}}, // [ClickTicker, LTD] - {"hash":"094df71f27ebd6f1","prefixes":{"":{"product":1383}}}, // [Tremour] + {"hash":"f6853fba1d5c8366","prefixes":{"":{"product":1376,"type":1}}}, // [Adara Impact Analytics] + {"hash":"7d5aa0875b5b03ee","prefixes":{"":{"product":1376,"type":1}}}, // [Adara Impact Analytics] + {"hash":"e1a55205d635d049","prefixes":{"":{"product":1376,"type":1}}}, // [Adara Impact Analytics] + {"hash":"b5ea51bb0aec174c","prefixes":{"":{"product":1376,"type":1}}}, // [Adara Impact Analytics] + {"hash":"e4140b78afda4fb4","prefixes":{"":{"product":1376,"type":1}}}, // [Adara Impact Analytics] + {"hash":"a4c74032025e0589","prefixes":{"":{"product":1377,"type":0}}}, // [TabMo SAS] + {"hash":"d9638d78485cff41","prefixes":{"":{"product":1377,"type":0}}}, // [TabMo SAS] + {"hash":"6ea3e003ed64d138","prefixes":{"":{"product":58,"type":1}}}, // [Sixt Leasing SE] + {"hash":"22ae0beb131c4b8c","prefixes":{"":{"product":1378,"type":0}}}, // [Casale Media] + {"hash":"29d1aaca6b9e6edd","prefixes":{"":{"product":1378,"type":0}}}, // [Casale Media] + {"hash":"7d1380d196e0f347","prefixes":{"":{"product":1379,"type":0}}}, // [StickyADStv] + {"hash":"147ac7b767355a32","prefixes":{"":{"product":1380,"type":0}}}, // [Teads Technology SAS] + {"hash":"4b60266ba860a4c5","prefixes":{"":{"product":1381,"type":1}}}, // [Anomaly Communications, LLC] + {"hash":"296893a9570ca935","prefixes":{"*":{"product":1382,"type":0}}}, // [ClickTicker, LTD] + {"hash":"094df71f27ebd6f1","prefixes":{"":{"product":1383,"type":0}}}, // [Tremour] {"hash":"a1119d262b86de34","prefixes":{"":{"product":1384}}}, // [Roket Media LTD] {"hash":"b1ed20b79d8a43cb","prefixes":{"":{"product":152}}}, // [e-Planning] - {"hash":"5bd05c801bb32096","prefixes":{"":{"product":1385}}}, // [Video Jam (MauDau LTD)] - {"hash":"dacf613410c17f5e","prefixes":{"":{"product":1385}}}, // [Video Jam (MauDau LTD)] + {"hash":"5bd05c801bb32096","prefixes":{"":{"product":1385,"type":0}}}, // [Video Jam (MauDau LTD)] + {"hash":"dacf613410c17f5e","prefixes":{"":{"product":1385,"type":0}}}, // [Video Jam (MauDau LTD)] {"hash":"561f104ba38d6e64","prefixes":{"":{"product":1385}}}, // [Video Jam (MauDau LTD)] - {"hash":"a43509d6a08d1777","prefixes":{"":{"product":1386}}}, // [MINIMOB (CY) LTD] - {"hash":"b66514ac6530a3fd","prefixes":{"":{"product":1387}}}, // [Snitcher B.V.] - {"hash":"79b3660bde132ba1","prefixes":{"":{"product":1387}}}, // [Snitcher B.V.] - {"hash":"aaf7781b800509ba","prefixes":{"":{"product":1387}}}, // [Snitcher B.V.] - {"hash":"8fec6c672f5b204a","prefixes":{"":{"product":1387}}}, // [Snitcher B.V.] - {"hash":"825e7df4dfb9bae0","prefixes":{"":{"product":1387}}}, // [Snitcher B.V.] - {"hash":"379899626d07c3b5","prefixes":{"":{"product":1388}}}, // [Analights] - {"hash":"664ce6265f73ec6a","prefixes":{"":{"product":1388}}}, // [Analights] - {"hash":"ab33f6650feb44c2","prefixes":{"":{"product":1388}}}, // [Analights] - {"hash":"557404c787c545cb","prefixes":{"":{"product":1388}}}, // [Analights] - {"hash":"0c881f692e8ec0de","prefixes":{"":{"product":1388}}}, // [Analights] - {"hash":"36c7264c1d06cc29","prefixes":{"":{"product":1388}}}, // [Analights] - {"hash":"2f7b75786675821b","prefixes":{"":{"product":1388}}}, // [Analights] - {"hash":"714fd218f12fce7a","prefixes":{"":{"product":1388}}}, // [Analights] - {"hash":"d140a5f747a666f1","prefixes":{"":{"product":1388}}}, // [Analights] - {"hash":"cbcfd9d592f2d19d","prefixes":{"":{"product":1388}}}, // [Analights] - {"hash":"a214f6ac537cafa2","prefixes":{"":{"product":1389}}}, // [Romir Panel Ltd.] - {"hash":"84fe21a8c3ba3818","prefixes":{"":{"product":1390}}}, // [Dievision] - {"hash":"c709bff0d2284ecc","prefixes":{"":{"product":1391}}}, // [Ignite Technologies] - {"hash":"3510f10ff5914868","prefixes":{"*":{"product":1392}}}, // [Navegg] - {"hash":"ea594377060cafc6","prefixes":{"":{"product":1393}}}, // [Adalyser] - {"hash":"631a68a191554bae","prefixes":{"":{"product":1393}}}, // [Adalyser] - {"hash":"8d9638d9355607ba","prefixes":{"":{"product":1393}}}, // [Adalyser] - {"hash":"d6e288fc5cf14c83","prefixes":{"":{"product":1393}}}, // [Adalyser] - {"hash":"90ec5cb29381e1ca","prefixes":{"":{"product":1393}}}, // [Adalyser] - {"hash":"3debdfa22ee00230","prefixes":{"":{"product":1393}}}, // [Adalyser] - {"hash":"45852dff86c0a7e0","prefixes":{"":{"product":1394}}}, // [Nordic Factory International Inc.] - {"hash":"063e04585364c0e5","prefixes":{"":{"product":719}}}, // [E-Plus Mobilfunk GmbH & Co. KG] - {"hash":"aa4bfba1bb15cb76","prefixes":{"":{"product":719}}}, // [E-Plus Mobilfunk GmbH & Co. KG] - {"hash":"3f43b05864c28c77","prefixes":{"":{"product":1395}}}, // [Addition Plus Ltd] - {"hash":"9e1057ca77b6610c","prefixes":{"":{"product":1395}}}, // [Addition Plus Ltd] - {"hash":"a6278ebdf3ca7bce","prefixes":{"":{"product":1396}}}, // [Karmatech Mediaworks Pvt Ltd] - {"hash":"954044969f047c6c","prefixes":{"":{"product":1396}}}, // [Karmatech Mediaworks Pvt Ltd] - {"hash":"ca32fcf3a3101ca0","prefixes":{"":{"product":1397}}}, // [Mediatropy Pte Ltd] - {"hash":"54a24d41044c0730","prefixes":{"":{"product":26}}}, // [FSN ASIA PRIVATE LIMITED] + {"hash":"a43509d6a08d1777","prefixes":{"":{"product":1386,"type":0}}}, // [MINIMOB (CY) LTD] + {"hash":"b66514ac6530a3fd","prefixes":{"":{"product":1387,"type":0}}}, // [Snitcher B.V.] + {"hash":"79b3660bde132ba1","prefixes":{"":{"product":1387,"type":0}}}, // [Snitcher B.V.] + {"hash":"aaf7781b800509ba","prefixes":{"":{"product":1387,"type":0}}}, // [Snitcher B.V.] + {"hash":"8fec6c672f5b204a","prefixes":{"":{"product":1387,"type":0}}}, // [Snitcher B.V.] + {"hash":"825e7df4dfb9bae0","prefixes":{"":{"product":1387,"type":0}}}, // [Snitcher B.V.] + {"hash":"379899626d07c3b5","prefixes":{"":{"product":1388,"type":1}}}, // [Analights] + {"hash":"664ce6265f73ec6a","prefixes":{"":{"product":1388,"type":1}}}, // [Analights] + {"hash":"ab33f6650feb44c2","prefixes":{"":{"product":1388,"type":1}}}, // [Analights] + {"hash":"557404c787c545cb","prefixes":{"":{"product":1388,"type":1}}}, // [Analights] + {"hash":"0c881f692e8ec0de","prefixes":{"":{"product":1388,"type":1}}}, // [Analights] + {"hash":"36c7264c1d06cc29","prefixes":{"":{"product":1388,"type":1}}}, // [Analights] + {"hash":"2f7b75786675821b","prefixes":{"":{"product":1388,"type":1}}}, // [Analights] + {"hash":"714fd218f12fce7a","prefixes":{"":{"product":1388,"type":1}}}, // [Analights] + {"hash":"d140a5f747a666f1","prefixes":{"":{"product":1388,"type":1}}}, // [Analights] + {"hash":"cbcfd9d592f2d19d","prefixes":{"":{"product":1388,"type":1}}}, // [Analights] + {"hash":"a214f6ac537cafa2","prefixes":{"":{"product":1389,"type":1}}}, // [Romir Panel Ltd.] + {"hash":"84fe21a8c3ba3818","prefixes":{"":{"product":1390,"type":0}}}, // [Dievision] + {"hash":"c709bff0d2284ecc","prefixes":{"":{"product":1391,"type":1}}}, // [Ignite Technologies] + {"hash":"3510f10ff5914868","prefixes":{"*":{"product":1392,"type":1}}}, // [Navegg] + {"hash":"ea594377060cafc6","prefixes":{"":{"product":1393,"type":1}}}, // [Adalyser] + {"hash":"631a68a191554bae","prefixes":{"":{"product":1393,"type":1}}}, // [Adalyser] + {"hash":"8d9638d9355607ba","prefixes":{"":{"product":1393,"type":1}}}, // [Adalyser] + {"hash":"d6e288fc5cf14c83","prefixes":{"":{"product":1393,"type":1}}}, // [Adalyser] + {"hash":"90ec5cb29381e1ca","prefixes":{"":{"product":1393,"type":1}}}, // [Adalyser] + {"hash":"3debdfa22ee00230","prefixes":{"":{"product":1393,"type":1}}}, // [Adalyser] + {"hash":"45852dff86c0a7e0","prefixes":{"":{"product":1394,"type":0}}}, // [Nordic Factory International Inc.] + {"hash":"063e04585364c0e5","prefixes":{"":{"product":719,"type":0}}}, // [E-Plus Mobilfunk GmbH & Co. KG] + {"hash":"aa4bfba1bb15cb76","prefixes":{"":{"product":719,"type":0}}}, // [E-Plus Mobilfunk GmbH & Co. KG] + {"hash":"3f43b05864c28c77","prefixes":{"":{"product":1395,"type":1}}}, // [Addition Plus Ltd] + {"hash":"9e1057ca77b6610c","prefixes":{"":{"product":1395,"type":1}}}, // [Addition Plus Ltd] + {"hash":"a6278ebdf3ca7bce","prefixes":{"":{"product":1396,"type":0}}}, // [Karmatech Mediaworks Pvt Ltd] + {"hash":"954044969f047c6c","prefixes":{"":{"product":1396,"type":0}}}, // [Karmatech Mediaworks Pvt Ltd] + {"hash":"ca32fcf3a3101ca0","prefixes":{"":{"product":1397,"type":0}}}, // [Mediatropy Pte Ltd] + {"hash":"54a24d41044c0730","prefixes":{"":{"product":26,"type":0}}}, // [FSN ASIA PRIVATE LIMITED] {"hash":"b3302c4e4fc23cb8","prefixes":{"":{"product":856}}}, // [Adman Interactive SL] - {"hash":"328eed54ff330e78","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"98ed7d7c1ae050b7","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"226e8c98a3e2e091","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"9e777471181caa70","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"9df613858a859407","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"37af06459214925d","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"0fdc04aa3cd4e402","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"f33f14a479b17a13","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"535ad6947981986b","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"0db16a6e891b1ff5","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"11b3c502d4eb1fa3","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"001bd6970eef2bbe","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"93505db1f9bf4a47","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"a1c9ac37054fc828","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"f4f375e269f34a60","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"e61b3b137beecfbc","prefixes":{"":{"product":1398}}}, // [Wayve Limited] - {"hash":"07bf22fe56be8d20","prefixes":{"*":{"product":1399}}}, // [Kreditech Holding SSL GmbH] - {"hash":"619e27568b55894c","prefixes":{"*":{"product":1399}}}, // [Kreditech Holding SSL GmbH] - {"hash":"374b60567f3c7f8b","prefixes":{"*":{"product":1399}}}, // [Kreditech Holding SSL GmbH] - {"hash":"af11cb377f269b3b","prefixes":{"*":{"product":1399}}}, // [Kreditech Holding SSL GmbH] - {"hash":"6bd694da478fa87b","prefixes":{"*":{"product":1399}}}, // [Kreditech Holding SSL GmbH] - {"hash":"75c4aedcbc945c91","prefixes":{"*":{"product":1399}}}, // [Kreditech Holding SSL GmbH] - {"hash":"71e8a51762fe81b6","prefixes":{"*":{"product":1399}}}, // [Kreditech Holding SSL GmbH] - {"hash":"5412f8017660207b","prefixes":{"*":{"product":1399}}}, // [Kreditech Holding SSL GmbH] - {"hash":"ba29363e3e139066","prefixes":{"*":{"product":1399}}}, // [Kreditech Holding SSL GmbH] - {"hash":"05de1e7e9f3271c3","prefixes":{"*":{"product":1399}}}, // [Kreditech Holding SSL GmbH] - {"hash":"5d73b4b9b8705846","prefixes":{"*":{"product":1399}}}, // [Kreditech Holding SSL GmbH] - {"hash":"711d9c4ce084aa7d","prefixes":{"*":{"product":1399}}}, // [Kreditech Holding SSL GmbH] - {"hash":"1ed6fde4c65ef6f7","prefixes":{"*":{"product":269}}}, // [DePauli AG] - {"hash":"4a6b1490dc059d0b","prefixes":{"*":{"product":269}}}, // [DePauli AG] - {"hash":"cab81dbe20c0957f","prefixes":{"*":{"product":269}}}, // [DePauli AG] - {"hash":"af1f3ce39e3b4862","prefixes":{"*":{"product":269}}}, // [DePauli AG] - {"hash":"19e97b139ae15342","prefixes":{"*":{"product":269}}}, // [DePauli AG] - {"hash":"fb46fee1ceef4719","prefixes":{"*":{"product":269}}}, // [DePauli AG] - {"hash":"798bda76da15abeb","prefixes":{"*":{"product":21}}}, // [SuperVista AG] - {"hash":"38bf7a598ad0c498","prefixes":{"*":{"product":21}}}, // [SuperVista AG] - {"hash":"48651b09d312b814","prefixes":{"*":{"product":21}}}, // [SuperVista AG] - {"hash":"bb2482d6022a94ba","prefixes":{"*":{"product":21}}}, // [SuperVista AG] - {"hash":"d58f8af9ff4e691e","prefixes":{"":{"product":1400}}}, // [Yengo] + {"hash":"328eed54ff330e78","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"98ed7d7c1ae050b7","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"226e8c98a3e2e091","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"9e777471181caa70","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"9df613858a859407","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"37af06459214925d","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"0fdc04aa3cd4e402","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"f33f14a479b17a13","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"535ad6947981986b","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"0db16a6e891b1ff5","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"11b3c502d4eb1fa3","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"001bd6970eef2bbe","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"93505db1f9bf4a47","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"a1c9ac37054fc828","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"f4f375e269f34a60","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"e61b3b137beecfbc","prefixes":{"":{"product":1398,"type":0}}}, // [Wayve Limited] + {"hash":"07bf22fe56be8d20","prefixes":{"*":{"product":1399,"type":1}}}, // [Kreditech Holding SSL GmbH] + {"hash":"619e27568b55894c","prefixes":{"*":{"product":1399,"type":1}}}, // [Kreditech Holding SSL GmbH] + {"hash":"374b60567f3c7f8b","prefixes":{"*":{"product":1399,"type":1}}}, // [Kreditech Holding SSL GmbH] + {"hash":"af11cb377f269b3b","prefixes":{"*":{"product":1399,"type":1}}}, // [Kreditech Holding SSL GmbH] + {"hash":"6bd694da478fa87b","prefixes":{"*":{"product":1399,"type":1}}}, // [Kreditech Holding SSL GmbH] + {"hash":"75c4aedcbc945c91","prefixes":{"*":{"product":1399,"type":1}}}, // [Kreditech Holding SSL GmbH] + {"hash":"71e8a51762fe81b6","prefixes":{"*":{"product":1399,"type":1}}}, // [Kreditech Holding SSL GmbH] + {"hash":"5412f8017660207b","prefixes":{"*":{"product":1399,"type":1}}}, // [Kreditech Holding SSL GmbH] + {"hash":"ba29363e3e139066","prefixes":{"*":{"product":1399,"type":1}}}, // [Kreditech Holding SSL GmbH] + {"hash":"05de1e7e9f3271c3","prefixes":{"*":{"product":1399,"type":1}}}, // [Kreditech Holding SSL GmbH] + {"hash":"5d73b4b9b8705846","prefixes":{"*":{"product":1399,"type":1}}}, // [Kreditech Holding SSL GmbH] + {"hash":"711d9c4ce084aa7d","prefixes":{"*":{"product":1399,"type":1}}}, // [Kreditech Holding SSL GmbH] + {"hash":"1ed6fde4c65ef6f7","prefixes":{"*":{"product":269,"type":1}}}, // [DePauli AG] + {"hash":"4a6b1490dc059d0b","prefixes":{"*":{"product":269,"type":1}}}, // [DePauli AG] + {"hash":"cab81dbe20c0957f","prefixes":{"*":{"product":269,"type":1}}}, // [DePauli AG] + {"hash":"af1f3ce39e3b4862","prefixes":{"*":{"product":269,"type":1}}}, // [DePauli AG] + {"hash":"19e97b139ae15342","prefixes":{"*":{"product":269,"type":1}}}, // [DePauli AG] + {"hash":"fb46fee1ceef4719","prefixes":{"*":{"product":269,"type":1}}}, // [DePauli AG] + {"hash":"798bda76da15abeb","prefixes":{"*":{"product":21,"type":1}}}, // [SuperVista AG] + {"hash":"38bf7a598ad0c498","prefixes":{"*":{"product":21,"type":1}}}, // [SuperVista AG] + {"hash":"48651b09d312b814","prefixes":{"*":{"product":21,"type":1}}}, // [SuperVista AG] + {"hash":"bb2482d6022a94ba","prefixes":{"*":{"product":21,"type":1}}}, // [SuperVista AG] + {"hash":"d58f8af9ff4e691e","prefixes":{"":{"product":1400,"type":0}}}, // [Yengo] {"hash":"8e9bee1bb54d54ee","prefixes":{"":{"product":1400}}}, // [Yengo] - {"hash":"06689ed650e2b8c3","prefixes":{"":{"product":1401}}}, // [DANtrack] - {"hash":"96c97b30a03579ac","prefixes":{"":{"product":1401}}}, // [DANtrack] - {"hash":"407face2b2c27397","prefixes":{"":{"product":1402}}}, // [Integral Markt- und Meinungsforschungsges.m.b.H.] - {"hash":"184f80ef53a0f178","prefixes":{"":{"product":1402}}}, // [Integral Markt- und Meinungsforschungsges.m.b.H.] - {"hash":"076a460590b496bf","prefixes":{"":{"product":1403}}}, // [Millemedia GmbH] - {"hash":"9febeed138f5f2ce","prefixes":{"":{"product":1404}}}, // [Hiro-Media] - {"hash":"dd35fc0a5f5fa07b","prefixes":{"":{"product":1404}}}, // [Hiro-Media] - {"hash":"b22687a0d4bd341f","prefixes":{"":{"product":1404}}}, // [Hiro-Media] - {"hash":"1625640192348305","prefixes":{"*":{"product":1405}}}, // [Simplaex Gmbh] - {"hash":"444356542461e7d2","prefixes":{"":{"product":1405}}}, // [Simplaex Gmbh] - {"hash":"b9edac442e488ddf","prefixes":{"":{"product":1405}}}, // [Simplaex Gmbh] - {"hash":"afed9502218fc1cd","prefixes":{"":{"product":1406}}}, // [Telekom Deutschland GmbH] - {"hash":"286d994374ce8a57","prefixes":{"":{"product":1407}}}, // [Infernotions Technologies Limited] - {"hash":"385225c96e123b3f","prefixes":{"":{"product":1408}}}, // [Goldfish Media LLC] - {"hash":"19c11b9ad47802f9","prefixes":{"":{"product":1365}}}, // [Expedia, Inc.] - {"hash":"d710ea66b904cd82","prefixes":{"":{"product":1409}}}, // [Smartology Limited] - {"hash":"24bbec831a84a114","prefixes":{"":{"product":1409}}}, // [Smartology Limited] - {"hash":"9c3279986e25304c","prefixes":{"":{"product":1409}}}, // [Smartology Limited] - {"hash":"8ce94299572dc9b8","prefixes":{"":{"product":1409}}}, // [Smartology Limited] - {"hash":"e51f784e66ceb1cb","prefixes":{"":{"product":1410}}}, // [GroupM] - {"hash":"72bd4ec98dea633b","prefixes":{"":{"product":1410}}}, // [GroupM] - {"hash":"0836c753510a4fd6","prefixes":{"*":{"product":1411}}}, // [Haystagg Inc.] - {"hash":"4a13b1d65c372006","prefixes":{"*":{"product":1411}}}, // [Haystagg Inc.] - {"hash":"14ec018232a87385","prefixes":{"":{"product":1412}}}, // [Digital Turbine Media, Inc] - {"hash":"fdabfb7535e313a7","prefixes":{"":{"product":1412}}}, // [Digital Turbine Media, Inc] - {"hash":"cddef42a99b1f0e2","prefixes":{"":{"product":1413}}}, // [MDSP INC] - {"hash":"1bcc84762c0f2df8","prefixes":{"":{"product":1414}}}, // [Quadas (YiDong Data Inc.)] - {"hash":"6c46a69428837566","prefixes":{"":{"product":1415}}}, // [Recruit Career Co., Ltd.] - {"hash":"17319e35b3b89b68","prefixes":{"":{"product":1416}}}, // [R2Net Inc.] - {"hash":"0825a9da5dd17373","prefixes":{"":{"product":1416}}}, // [R2Net Inc.] - {"hash":"aaa00ce722ea0d35","prefixes":{"":{"product":1416}}}, // [R2Net Inc.] - {"hash":"40b683cc8c061f6f","prefixes":{"":{"product":1417}}}, // [Madberry OY] - {"hash":"ea76804ad8af9b5c","prefixes":{"":{"product":1417}}}, // [Madberry OY] - {"hash":"985cce26aeab90d8","prefixes":{"":{"product":1417}}}, // [Madberry OY] - {"hash":"d67d98cbb9553a81","prefixes":{"":{"product":1417}}}, // [Madberry OY] - {"hash":"ee1c2ae2ffdaa754","prefixes":{"":{"product":1417}}}, // [Madberry OY] - {"hash":"8c162379b63896e6","prefixes":{"":{"product":1418}}}, // [QVC] - {"hash":"4c23d567b98e413f","prefixes":{"*":{"product":1419}}}, // [Micro Cube Digital Limited] + {"hash":"06689ed650e2b8c3","prefixes":{"":{"product":1401,"type":1}}}, // [DANtrack] + {"hash":"96c97b30a03579ac","prefixes":{"":{"product":1401,"type":1}}}, // [DANtrack] + {"hash":"407face2b2c27397","prefixes":{"":{"product":1402,"type":1}}}, // [Integral Markt- und Meinungsforschungsges.m.b.H.] + {"hash":"184f80ef53a0f178","prefixes":{"":{"product":1402,"type":1}}}, // [Integral Markt- und Meinungsforschungsges.m.b.H.] + {"hash":"076a460590b496bf","prefixes":{"":{"product":1403,"type":0}}}, // [Millemedia GmbH] + {"hash":"9febeed138f5f2ce","prefixes":{"":{"product":1404,"type":0}}}, // [Hiro-Media] + {"hash":"dd35fc0a5f5fa07b","prefixes":{"":{"product":1404,"type":0}}}, // [Hiro-Media] + {"hash":"b22687a0d4bd341f","prefixes":{"":{"product":1404,"type":0}}}, // [Hiro-Media] + {"hash":"1625640192348305","prefixes":{"*":{"product":1405,"type":0}}}, // [Simplaex Gmbh] + {"hash":"444356542461e7d2","prefixes":{"":{"product":1405,"type":0}}}, // [Simplaex Gmbh] + {"hash":"b9edac442e488ddf","prefixes":{"":{"product":1405,"type":0}}}, // [Simplaex Gmbh] + {"hash":"afed9502218fc1cd","prefixes":{"":{"product":1406,"type":0}}}, // [Telekom Deutschland GmbH] + {"hash":"286d994374ce8a57","prefixes":{"":{"product":1407,"type":1}}}, // [Infernotions Technologies Limited] + {"hash":"385225c96e123b3f","prefixes":{"":{"product":1408,"type":0}}}, // [Goldfish Media LLC] + {"hash":"19c11b9ad47802f9","prefixes":{"":{"product":1365,"type":1}}}, // [Expedia, Inc.] + {"hash":"d710ea66b904cd82","prefixes":{"":{"product":1409,"type":0}}}, // [Smartology Limited] + {"hash":"24bbec831a84a114","prefixes":{"":{"product":1409,"type":0}}}, // [Smartology Limited] + {"hash":"9c3279986e25304c","prefixes":{"":{"product":1409,"type":0}}}, // [Smartology Limited] + {"hash":"8ce94299572dc9b8","prefixes":{"":{"product":1409,"type":0}}}, // [Smartology Limited] + {"hash":"e51f784e66ceb1cb","prefixes":{"":{"product":1410,"type":0}}}, // [GroupM] + {"hash":"72bd4ec98dea633b","prefixes":{"":{"product":1410,"type":0}}}, // [GroupM] + {"hash":"0836c753510a4fd6","prefixes":{"*":{"product":1411,"type":0}}}, // [Haystagg Inc.] + {"hash":"4a13b1d65c372006","prefixes":{"*":{"product":1411,"type":0}}}, // [Haystagg Inc.] + {"hash":"14ec018232a87385","prefixes":{"":{"product":1412,"type":0}}}, // [Digital Turbine Media, Inc] + {"hash":"fdabfb7535e313a7","prefixes":{"":{"product":1412,"type":0}}}, // [Digital Turbine Media, Inc] + {"hash":"cddef42a99b1f0e2","prefixes":{"":{"product":1413,"type":0}}}, // [MDSP INC] + {"hash":"1bcc84762c0f2df8","prefixes":{"":{"product":1414,"type":0}}}, // [Quadas (YiDong Data Inc.)] + {"hash":"6c46a69428837566","prefixes":{"":{"product":1415,"type":1}}}, // [Recruit Career Co., Ltd.] + {"hash":"17319e35b3b89b68","prefixes":{"":{"product":1416,"type":1}}}, // [R2Net Inc.] + {"hash":"0825a9da5dd17373","prefixes":{"":{"product":1416,"type":1}}}, // [R2Net Inc.] + {"hash":"aaa00ce722ea0d35","prefixes":{"":{"product":1416,"type":1}}}, // [R2Net Inc.] + {"hash":"40b683cc8c061f6f","prefixes":{"":{"product":1417,"type":0}}}, // [Madberry OY] + {"hash":"ea76804ad8af9b5c","prefixes":{"":{"product":1417,"type":0}}}, // [Madberry OY] + {"hash":"985cce26aeab90d8","prefixes":{"":{"product":1417,"type":0}}}, // [Madberry OY] + {"hash":"d67d98cbb9553a81","prefixes":{"":{"product":1417,"type":0}}}, // [Madberry OY] + {"hash":"ee1c2ae2ffdaa754","prefixes":{"":{"product":1417,"type":0}}}, // [Madberry OY] + {"hash":"8c162379b63896e6","prefixes":{"":{"product":1418,"type":0}}}, // [QVC] + {"hash":"4c23d567b98e413f","prefixes":{"*":{"product":1419,"type":0}}}, // [Micro Cube Digital Limited] {"hash":"9e74e9e50b7e6116","prefixes":{"":{"product":1420}}}, // [egg.de GmbH] - {"hash":"8242efdacea6ca14","prefixes":{"":{"product":1421}}}, // [Headway Mexico] - {"hash":"82b90117a5beb869","prefixes":{"":{"product":1422}}}, // [RTBiQ Inc.] - {"hash":"7d4bc30e9d495d00","prefixes":{"":{"product":1194}}}, // [Fluidads] - {"hash":"44305a81af328854","prefixes":{"":{"product":1194}}}, // [Fluidads] - {"hash":"f5d44df23b5b7f0a","prefixes":{"":{"product":1423}}}, // [SCIBIDS TECHNOLOGY S.A.S.] - {"hash":"e86f56889ef213b9","prefixes":{"*":{"product":1424}}}, // [Kyocera Communication Systems] - {"hash":"e4f3abfdd94fbb95","prefixes":{"":{"product":1425}}}, // [Cortex Media Group] - {"hash":"7525243b1d665de2","prefixes":{"":{"product":1426}}}, // [appTV] - {"hash":"f27453a19aa2370e","prefixes":{"":{"product":1426}}}, // [appTV] - {"hash":"8156979d25af9817","prefixes":{"":{"product":1427}}}, // [ProgSol, Programmatic Solution, s.r.o.] - {"hash":"888e465d14dbfeb5","prefixes":{"":{"product":1427}}}, // [ProgSol, Programmatic Solution, s.r.o.] - {"hash":"6bcdb8e4cf28b730","prefixes":{"":{"product":1427}}}, // [ProgSol, Programmatic Solution, s.r.o.] + {"hash":"8242efdacea6ca14","prefixes":{"":{"product":1421,"type":0}}}, // [Headway Mexico] + {"hash":"82b90117a5beb869","prefixes":{"":{"product":1422,"type":0}}}, // [RTBiQ Inc.] + {"hash":"7d4bc30e9d495d00","prefixes":{"":{"product":1194,"type":0}}}, // [Fluidads] + {"hash":"44305a81af328854","prefixes":{"":{"product":1194,"type":0}}}, // [Fluidads] + {"hash":"f5d44df23b5b7f0a","prefixes":{"":{"product":1423,"type":1}}}, // [SCIBIDS TECHNOLOGY S.A.S.] + {"hash":"e86f56889ef213b9","prefixes":{"*":{"product":1424,"type":0}}}, // [Kyocera Communication Systems] + {"hash":"e4f3abfdd94fbb95","prefixes":{"":{"product":1425,"type":0}}}, // [Cortex Media Group] + {"hash":"7525243b1d665de2","prefixes":{"":{"product":1426,"type":0}}}, // [appTV] + {"hash":"f27453a19aa2370e","prefixes":{"":{"product":1426,"type":0}}}, // [appTV] + {"hash":"8156979d25af9817","prefixes":{"":{"product":1427,"type":0}}}, // [ProgSol, Programmatic Solution, s.r.o.] + {"hash":"888e465d14dbfeb5","prefixes":{"":{"product":1427,"type":0}}}, // [ProgSol, Programmatic Solution, s.r.o.] + {"hash":"6bcdb8e4cf28b730","prefixes":{"":{"product":1427,"type":0}}}, // [ProgSol, Programmatic Solution, s.r.o.] {"hash":"cc229228113699d8","prefixes":{"":{"product":1428}}}, // [Rezonence] {"hash":"fd7695df1dfe9f20","prefixes":{"":{"product":1429}}}, // [LKQD Platform] {"hash":"fbee76565472bc95","prefixes":{"":{"product":1429}}}, // [LKQD Platform] @@ -6636,198 +6634,198 @@ {"hash":"ea6157fcb7c5c718","prefixes":{"":{"product":1429}}}, // [LKQD Platform] {"hash":"6063abef39fb89be","prefixes":{"":{"product":1429}}}, // [LKQD Platform] {"hash":"8a3b3647f6fae243","prefixes":{"":{"product":1429}}}, // [LKQD Platform] - {"hash":"25b652ead7abb3b0","prefixes":{"":{"product":1059}}}, // [Bidtellect] - {"hash":"ff03eb40846eaa12","prefixes":{"":{"product":1059}}}, // [Bidtellect] - {"hash":"649ada5375fff936","prefixes":{"":{"product":1059}}}, // [Bidtellect] - {"hash":"79b86a55d8f149ef","prefixes":{"":{"product":1430}}}, // [target value GmbH] - {"hash":"a6e4ebed7d417fec","prefixes":{"":{"product":1430}}}, // [target value GmbH] - {"hash":"e7a27d73288188b6","prefixes":{"":{"product":1430}}}, // [target value GmbH] - {"hash":"24028ce468194c75","prefixes":{"":{"product":1430}}}, // [target value GmbH] - {"hash":"d7f89ed8a6431a69","prefixes":{"":{"product":1430}}}, // [target value GmbH] - {"hash":"079f75aa60b736a9","prefixes":{"":{"product":1430}}}, // [target value GmbH] - {"hash":"55ab38530ebcb2e7","prefixes":{"":{"product":1430}}}, // [target value GmbH] - {"hash":"244a99d8deb4343c","prefixes":{"":{"product":1430}}}, // [target value GmbH] - {"hash":"02afdba2d61c6d76","prefixes":{"":{"product":1430}}}, // [target value GmbH] - {"hash":"50fcadafe2e2734b","prefixes":{"":{"product":1430}}}, // [target value GmbH] - {"hash":"0a5d998860b7968b","prefixes":{"":{"product":1430}}}, // [target value GmbH] - {"hash":"ff1ef9a23c2bdf51","prefixes":{"":{"product":1430}}}, // [target value GmbH] - {"hash":"b7be02479c9268a9","prefixes":{"":{"product":1431}}}, // [Firecracker] - {"hash":"2841b43a0e0ddb37","prefixes":{"":{"product":1431}}}, // [Firecracker] - {"hash":"ea77ccf69493306c","prefixes":{"":{"product":1431}}}, // [Firecracker] - {"hash":"786060a6ba793b32","prefixes":{"":{"product":1431}}}, // [Firecracker] - {"hash":"af58243a5817c930","prefixes":{"":{"product":1431}}}, // [Firecracker] - {"hash":"b90ffee242259e26","prefixes":{"":{"product":1432}}}, // [MADGIC] - {"hash":"037e84a783130203","prefixes":{"":{"product":1433}}}, // [Digiseg] - {"hash":"724c85c96cc72a57","prefixes":{"":{"product":1433}}}, // [Digiseg] - {"hash":"df235ed188c82f5b","prefixes":{"":{"product":1433}}}, // [Digiseg] - {"hash":"df21bf354a2570e1","prefixes":{"":{"product":1433}}}, // [Digiseg] - {"hash":"52a9b224dd3e1b02","prefixes":{"":{"product":1433}}}, // [Digiseg] - {"hash":"ef749fa483d558a9","prefixes":{"":{"product":1433}}}, // [Digiseg] - {"hash":"a6b20df6c2ce3063","prefixes":{"":{"product":1433}}}, // [Digiseg] - {"hash":"7e7e73dfe402883c","prefixes":{"":{"product":1433}}}, // [Digiseg] - {"hash":"1cafe416eb8d746c","prefixes":{"":{"product":1433}}}, // [Digiseg] - {"hash":"45c0ef64ecfb6525","prefixes":{"":{"product":1434}}}, // [Bulbit Inc.] + {"hash":"25b652ead7abb3b0","prefixes":{"":{"product":1059,"type":0}}}, // [Bidtellect] + {"hash":"ff03eb40846eaa12","prefixes":{"":{"product":1059,"type":0}}}, // [Bidtellect] + {"hash":"649ada5375fff936","prefixes":{"":{"product":1059,"type":0}}}, // [Bidtellect] + {"hash":"79b86a55d8f149ef","prefixes":{"":{"product":1430,"type":0}}}, // [target value GmbH] + {"hash":"a6e4ebed7d417fec","prefixes":{"":{"product":1430,"type":0}}}, // [target value GmbH] + {"hash":"e7a27d73288188b6","prefixes":{"":{"product":1430,"type":0}}}, // [target value GmbH] + {"hash":"24028ce468194c75","prefixes":{"":{"product":1430,"type":0}}}, // [target value GmbH] + {"hash":"d7f89ed8a6431a69","prefixes":{"":{"product":1430,"type":0}}}, // [target value GmbH] + {"hash":"079f75aa60b736a9","prefixes":{"":{"product":1430,"type":0}}}, // [target value GmbH] + {"hash":"55ab38530ebcb2e7","prefixes":{"":{"product":1430,"type":0}}}, // [target value GmbH] + {"hash":"244a99d8deb4343c","prefixes":{"":{"product":1430,"type":0}}}, // [target value GmbH] + {"hash":"02afdba2d61c6d76","prefixes":{"":{"product":1430,"type":0}}}, // [target value GmbH] + {"hash":"50fcadafe2e2734b","prefixes":{"":{"product":1430,"type":0}}}, // [target value GmbH] + {"hash":"0a5d998860b7968b","prefixes":{"":{"product":1430,"type":0}}}, // [target value GmbH] + {"hash":"ff1ef9a23c2bdf51","prefixes":{"":{"product":1430,"type":0}}}, // [target value GmbH] + {"hash":"b7be02479c9268a9","prefixes":{"":{"product":1431,"type":0}}}, // [Firecracker] + {"hash":"2841b43a0e0ddb37","prefixes":{"":{"product":1431,"type":0}}}, // [Firecracker] + {"hash":"ea77ccf69493306c","prefixes":{"":{"product":1431,"type":0}}}, // [Firecracker] + {"hash":"786060a6ba793b32","prefixes":{"":{"product":1431,"type":0}}}, // [Firecracker] + {"hash":"af58243a5817c930","prefixes":{"":{"product":1431,"type":0}}}, // [Firecracker] + {"hash":"b90ffee242259e26","prefixes":{"":{"product":1432,"type":0}}}, // [MADGIC] + {"hash":"037e84a783130203","prefixes":{"":{"product":1433,"type":1}}}, // [Digiseg] + {"hash":"724c85c96cc72a57","prefixes":{"":{"product":1433,"type":1}}}, // [Digiseg] + {"hash":"df235ed188c82f5b","prefixes":{"":{"product":1433,"type":1}}}, // [Digiseg] + {"hash":"df21bf354a2570e1","prefixes":{"":{"product":1433,"type":1}}}, // [Digiseg] + {"hash":"52a9b224dd3e1b02","prefixes":{"":{"product":1433,"type":1}}}, // [Digiseg] + {"hash":"ef749fa483d558a9","prefixes":{"":{"product":1433,"type":1}}}, // [Digiseg] + {"hash":"a6b20df6c2ce3063","prefixes":{"":{"product":1433,"type":1}}}, // [Digiseg] + {"hash":"7e7e73dfe402883c","prefixes":{"":{"product":1433,"type":1}}}, // [Digiseg] + {"hash":"1cafe416eb8d746c","prefixes":{"":{"product":1433,"type":1}}}, // [Digiseg] + {"hash":"45c0ef64ecfb6525","prefixes":{"":{"product":1434,"type":0}}}, // [Bulbit Inc.] {"hash":"d3710c2900e90f84","prefixes":{"":{"product":1434}}}, // [Bulbit Inc.] - {"hash":"fed8a97b9e855887","prefixes":{"":{"product":1435}}}, // [Lost My Name] - {"hash":"5c18434d5d721456","prefixes":{"":{"product":1436}}}, // [People Media] - {"hash":"fd4a671d34b4c76c","prefixes":{"":{"product":1436}}}, // [People Media] - {"hash":"181b385a8ea5a687","prefixes":{"":{"product":1437}}}, // [Platform.io] + {"hash":"fed8a97b9e855887","prefixes":{"":{"product":1435,"type":1}}}, // [Lost My Name] + {"hash":"5c18434d5d721456","prefixes":{"":{"product":1436,"type":0}}}, // [People Media] + {"hash":"fd4a671d34b4c76c","prefixes":{"":{"product":1436,"type":0}}}, // [People Media] + {"hash":"181b385a8ea5a687","prefixes":{"":{"product":1437,"type":0}}}, // [Platform.io] {"hash":"00393673ca5c1d8a","prefixes":{"":{"product":1437}}}, // [Platform.io] - {"hash":"6479d1c5a241da2f","prefixes":{"":{"product":1438}}}, // [Bidspeaker] - {"hash":"f30e44d5503f39c4","prefixes":{"":{"product":1439}}}, // [YouGov PLC] - {"hash":"4f07a6c89151a2eb","prefixes":{"":{"product":1440}}}, // [SAP SE] - {"hash":"519e46f12c141c48","prefixes":{"":{"product":1440}}}, // [SAP SE] - {"hash":"413cdfaa8215b8f5","prefixes":{"":{"product":1440}}}, // [SAP SE] - {"hash":"dd8e150b503eb12f","prefixes":{"":{"product":1441}}}, // [Adchex] - {"hash":"58e19248782ce688","prefixes":{"":{"product":1442}}}, // [Smart Bid Limited] - {"hash":"8ccc1dd45e305817","prefixes":{"":{"product":1443}}}, // [UAd Exchange] + {"hash":"6479d1c5a241da2f","prefixes":{"":{"product":1438,"type":0}}}, // [Bidspeaker] + {"hash":"f30e44d5503f39c4","prefixes":{"":{"product":1439,"type":1}}}, // [YouGov PLC] + {"hash":"4f07a6c89151a2eb","prefixes":{"":{"product":1440,"type":0}}}, // [SAP SE] + {"hash":"519e46f12c141c48","prefixes":{"":{"product":1440,"type":0}}}, // [SAP SE] + {"hash":"413cdfaa8215b8f5","prefixes":{"":{"product":1440,"type":0}}}, // [SAP SE] + {"hash":"dd8e150b503eb12f","prefixes":{"":{"product":1441,"type":1}}}, // [Adchex] + {"hash":"58e19248782ce688","prefixes":{"":{"product":1442,"type":0}}}, // [Smart Bid Limited] + {"hash":"8ccc1dd45e305817","prefixes":{"":{"product":1443,"type":0}}}, // [UAd Exchange] {"hash":"9543cb4330fa1d6e","prefixes":{"":{"product":1444}}}, // [UAd Exchange - IBV] - {"hash":"fc1a7604d6ced7c3","prefixes":{"":{"product":1445}}}, // [esc mediagroup GmbH] - {"hash":"90c354743de0b811","prefixes":{"":{"product":1446}}}, // [defacto smart reach GmbH] - {"hash":"0d8f41278d702251","prefixes":{"":{"product":1447}}}, // [Research and Analysis of Media in Sweden AB] - {"hash":"607c4919b3c8d5cd","prefixes":{"":{"product":1447}}}, // [Research and Analysis of Media in Sweden AB] - {"hash":"d0d7647dc2ea9dd9","prefixes":{"":{"product":1448}}}, // [OnAudience.com] - {"hash":"3c0c99d90a16804f","prefixes":{"":{"product":1449}}}, // [OneTag] - {"hash":"a50e8a4129f160c8","prefixes":{"":{"product":1449}}}, // [OneTag] + {"hash":"fc1a7604d6ced7c3","prefixes":{"":{"product":1445,"type":0}}}, // [esc mediagroup GmbH] + {"hash":"90c354743de0b811","prefixes":{"":{"product":1446,"type":0}}}, // [defacto smart reach GmbH] + {"hash":"0d8f41278d702251","prefixes":{"":{"product":1447,"type":1}}}, // [Research and Analysis of Media in Sweden AB] + {"hash":"607c4919b3c8d5cd","prefixes":{"":{"product":1447,"type":1}}}, // [Research and Analysis of Media in Sweden AB] + {"hash":"d0d7647dc2ea9dd9","prefixes":{"":{"product":1448,"type":1}}}, // [OnAudience.com] + {"hash":"3c0c99d90a16804f","prefixes":{"":{"product":1449,"type":0}}}, // [OneTag] + {"hash":"a50e8a4129f160c8","prefixes":{"":{"product":1449,"type":0}}}, // [OneTag] {"hash":"62105b8204658950","prefixes":{"":{"product":1449}}}, // [OneTag] - {"hash":"8069afc9a94b92b9","prefixes":{"*":{"product":1349}}}, // [1trn LLC] - {"hash":"c9cc947471099a0e","prefixes":{"":{"product":59}}}, // [Air Berlin] - {"hash":"516352d734faa684","prefixes":{"":{"product":1450}}}, // [Fiverr International Ltd.] - {"hash":"562a3da1a81ae4ec","prefixes":{"":{"product":1450}}}, // [Fiverr International Ltd.] - {"hash":"1ba262fef7c9b94b","prefixes":{"":{"product":1451}}}, // [Adikteev] - {"hash":"cd63e73725fa2b8d","prefixes":{"":{"product":1451}}}, // [Adikteev] - {"hash":"f24819f2edd93c69","prefixes":{"":{"product":1451}}}, // [Adikteev] - {"hash":"e3b1538bced5ec72","prefixes":{"":{"product":1451}}}, // [Adikteev] - {"hash":"341df4e708fbbc07","prefixes":{"":{"product":1452}}}, // [CenterPoint Media] - {"hash":"1f984187723f0399","prefixes":{"":{"product":1452}}}, // [CenterPoint Media] - {"hash":"6ed35b33de5147be","prefixes":{"":{"product":1452}}}, // [CenterPoint Media] - {"hash":"d3f04891cabd56f8","prefixes":{"":{"product":1453}}}, // [Digital Trace] - {"hash":"8429b5e7c7905de9","prefixes":{"":{"product":1453}}}, // [Digital Trace] - {"hash":"eadb7778a29b9617","prefixes":{"":{"product":1453}}}, // [Digital Trace] - {"hash":"15595532c38662ea","prefixes":{"":{"product":1453}}}, // [Digital Trace] - {"hash":"ce365566d66a72ee","prefixes":{"":{"product":1453}}}, // [Digital Trace] - {"hash":"60ef24e820a6a881","prefixes":{"":{"product":1453}}}, // [Digital Trace] - {"hash":"176be2434ca2f68b","prefixes":{"":{"product":1453}}}, // [Digital Trace] - {"hash":"3f72f2b4ec7f816e","prefixes":{"":{"product":1453}}}, // [Digital Trace] - {"hash":"bcc519027914bd79","prefixes":{"":{"product":1453}}}, // [Digital Trace] - {"hash":"86628b5f01332c66","prefixes":{"":{"product":1453}}}, // [Digital Trace] - {"hash":"1c34c62a587e6c1e","prefixes":{"":{"product":1454}}}, // [Pure Cobalt] - {"hash":"a30f9c646772cf0f","prefixes":{"":{"product":60}}}, // [Aegon ESPAÑA, S.A. de Seguros y Reaseguros, Uniper] + {"hash":"8069afc9a94b92b9","prefixes":{"*":{"product":1349,"type":0}}}, // [1trn LLC] + {"hash":"c9cc947471099a0e","prefixes":{"":{"product":59,"type":1}}}, // [Air Berlin] + {"hash":"516352d734faa684","prefixes":{"":{"product":1450,"type":1}}}, // [Fiverr International Ltd.] + {"hash":"562a3da1a81ae4ec","prefixes":{"":{"product":1450,"type":1}}}, // [Fiverr International Ltd.] + {"hash":"1ba262fef7c9b94b","prefixes":{"":{"product":1451,"type":0}}}, // [Adikteev] + {"hash":"cd63e73725fa2b8d","prefixes":{"":{"product":1451,"type":0}}}, // [Adikteev] + {"hash":"f24819f2edd93c69","prefixes":{"":{"product":1451,"type":0}}}, // [Adikteev] + {"hash":"e3b1538bced5ec72","prefixes":{"":{"product":1451,"type":0}}}, // [Adikteev] + {"hash":"341df4e708fbbc07","prefixes":{"":{"product":1452,"type":0}}}, // [CenterPoint Media] + {"hash":"1f984187723f0399","prefixes":{"":{"product":1452,"type":0}}}, // [CenterPoint Media] + {"hash":"6ed35b33de5147be","prefixes":{"":{"product":1452,"type":0}}}, // [CenterPoint Media] + {"hash":"d3f04891cabd56f8","prefixes":{"":{"product":1453,"type":0}}}, // [Digital Trace] + {"hash":"8429b5e7c7905de9","prefixes":{"":{"product":1453,"type":0}}}, // [Digital Trace] + {"hash":"eadb7778a29b9617","prefixes":{"":{"product":1453,"type":0}}}, // [Digital Trace] + {"hash":"15595532c38662ea","prefixes":{"":{"product":1453,"type":0}}}, // [Digital Trace] + {"hash":"ce365566d66a72ee","prefixes":{"":{"product":1453,"type":0}}}, // [Digital Trace] + {"hash":"60ef24e820a6a881","prefixes":{"":{"product":1453,"type":0}}}, // [Digital Trace] + {"hash":"176be2434ca2f68b","prefixes":{"":{"product":1453,"type":0}}}, // [Digital Trace] + {"hash":"3f72f2b4ec7f816e","prefixes":{"":{"product":1453,"type":0}}}, // [Digital Trace] + {"hash":"bcc519027914bd79","prefixes":{"":{"product":1453,"type":0}}}, // [Digital Trace] + {"hash":"86628b5f01332c66","prefixes":{"":{"product":1453,"type":0}}}, // [Digital Trace] + {"hash":"1c34c62a587e6c1e","prefixes":{"":{"product":1454,"type":0}}}, // [Pure Cobalt] + {"hash":"a30f9c646772cf0f","prefixes":{"":{"product":60,"type":1}}}, // [Aegon ESPAÑA, S.A. de Seguros y Reaseguros, Uniper] {"hash":"b23d960b2ea25b51","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"030115e352ac8e99","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"77da2d98a4da970f","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"aa0555e19cf5d6cc","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"badc121e99935aa5","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"115df78aa77ac9c4","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"04713a193ed96cc0","prefixes":{"s":{"product":1455}}}, // [Cedato] + {"hash":"030115e352ac8e99","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"77da2d98a4da970f","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"aa0555e19cf5d6cc","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"badc121e99935aa5","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"115df78aa77ac9c4","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"04713a193ed96cc0","prefixes":{"s":{"product":1455,"type":0}}}, // [Cedato] {"hash":"fd6fd1f29de71285","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"c5de6239a6efe818","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"4c0be33a1c14428d","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"09eaafed5beae0e1","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"ff987bad618809e7","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"2b50033d06870385","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"8b399204d27d07c0","prefixes":{"s":{"product":1455}}}, // [Cedato] + {"hash":"c5de6239a6efe818","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"4c0be33a1c14428d","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"09eaafed5beae0e1","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"ff987bad618809e7","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"2b50033d06870385","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"8b399204d27d07c0","prefixes":{"s":{"product":1455,"type":0}}}, // [Cedato] {"hash":"5f78d380fa9514b1","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"c4912c3d8f04b948","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"361fa6df6bb3216e","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"b18ab9dfb513f02b","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"de511a44653105ea","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"f990d873e1622766","prefixes":{"":{"product":1455}}}, // [Cedato] - {"hash":"f53618fe52956dbf","prefixes":{"s":{"product":1455}}}, // [Cedato] - {"hash":"96ed69252978cab9","prefixes":{"cdn":{"product":1455}}}, // [Cedato] - {"hash":"f38b31b7e204355c","prefixes":{"":{"product":943}}}, // [Admetrics GmbH] - {"hash":"895a9c8a3b52c95f","prefixes":{"":{"product":943}}}, // [Admetrics GmbH] - {"hash":"62ba002fe91498c3","prefixes":{"":{"product":943}}}, // [Admetrics GmbH] - {"hash":"30fe524e700bd89f","prefixes":{"":{"product":943}}}, // [Admetrics GmbH] - {"hash":"6ce86e7a47d6dfbc","prefixes":{"":{"product":1456}}}, // [Jonsden Properties Limited] - {"hash":"8bed3db3f252b657","prefixes":{"":{"product":1457}}}, // [Realytics] + {"hash":"c4912c3d8f04b948","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"361fa6df6bb3216e","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"b18ab9dfb513f02b","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"de511a44653105ea","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"f990d873e1622766","prefixes":{"":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"f53618fe52956dbf","prefixes":{"s":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"96ed69252978cab9","prefixes":{"cdn":{"product":1455,"type":0}}}, // [Cedato] + {"hash":"f38b31b7e204355c","prefixes":{"":{"product":943,"type":0}}}, // [Admetrics GmbH] + {"hash":"895a9c8a3b52c95f","prefixes":{"":{"product":943,"type":0}}}, // [Admetrics GmbH] + {"hash":"62ba002fe91498c3","prefixes":{"":{"product":943,"type":0}}}, // [Admetrics GmbH] + {"hash":"30fe524e700bd89f","prefixes":{"":{"product":943,"type":0}}}, // [Admetrics GmbH] + {"hash":"6ce86e7a47d6dfbc","prefixes":{"":{"product":1456,"type":0}}}, // [Jonsden Properties Limited] + {"hash":"8bed3db3f252b657","prefixes":{"":{"product":1457,"type":1}}}, // [Realytics] {"hash":"c2dcbb4796436e89","prefixes":{"":{"product":1458}}}, // [Twinpine] {"hash":"97a8b5033c272f3c","prefixes":{"":{"product":1458}}}, // [Twinpine] - {"hash":"3d39eae9e2370c3e","prefixes":{"":{"product":1459}}}, // [Mopedo AB] - {"hash":"38a9bfae76c9b2f1","prefixes":{"*":{"product":1460}}}, // [Netsales] - {"hash":"9b1148932500d0b5","prefixes":{"":{"product":1461}}}, // [ViewersLogic LTD] - {"hash":"901b2f7c0272451b","prefixes":{"":{"product":1461}}}, // [ViewersLogic LTD] - {"hash":"7d45cf386f5c3f27","prefixes":{"":{"product":1462}}}, // [ADMAN] - {"hash":"e68e2f7630af032b","prefixes":{"":{"product":1462}}}, // [ADMAN] - {"hash":"79dc640f62208944","prefixes":{"":{"product":1462}}}, // [ADMAN] - {"hash":"4d6e312d6aba1117","prefixes":{"":{"product":1462}}}, // [ADMAN] + {"hash":"3d39eae9e2370c3e","prefixes":{"":{"product":1459,"type":0}}}, // [Mopedo AB] + {"hash":"38a9bfae76c9b2f1","prefixes":{"*":{"product":1460,"type":1}}}, // [Netsales] + {"hash":"9b1148932500d0b5","prefixes":{"":{"product":1461,"type":1}}}, // [ViewersLogic LTD] + {"hash":"901b2f7c0272451b","prefixes":{"":{"product":1461,"type":1}}}, // [ViewersLogic LTD] + {"hash":"7d45cf386f5c3f27","prefixes":{"":{"product":1462,"type":0}}}, // [ADMAN] + {"hash":"e68e2f7630af032b","prefixes":{"":{"product":1462,"type":0}}}, // [ADMAN] + {"hash":"79dc640f62208944","prefixes":{"":{"product":1462,"type":0}}}, // [ADMAN] + {"hash":"4d6e312d6aba1117","prefixes":{"":{"product":1462,"type":0}}}, // [ADMAN] {"hash":"29e85c5af35e3751","prefixes":{"":{"product":1462}}}, // [ADMAN] - {"hash":"e5f2b6b92cc6daa3","prefixes":{"":{"product":1463}}}, // [Hyper] - {"hash":"f867e04c6dde165d","prefixes":{"":{"product":1464}}}, // [Hurra Communications] - {"hash":"8353a34ee35ff30c","prefixes":{"":{"product":1464}}}, // [Hurra Communications] - {"hash":"cc7f69fa55a7518f","prefixes":{"":{"product":1465}}}, // [Groundhog TW] - {"hash":"95ba2d10b1b0675c","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"e8f62a52edbdf4bd","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"321a7e08d4b4fd55","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"c6f272ed0a206999","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"bd34d2733467c1af","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"1b49f6113458dc63","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"58b83e3b3a97943e","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"814bcd9589533387","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"9465fc7c156593f4","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"7c1c219e78b2f270","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"9d376bb5982319b0","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"12ec9a0b2888a4a9","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"f3d7dfcb60972b0c","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"460cac48ec149c6d","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"2614d3ffa05e19a5","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"1f9b770c08378ced","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"054864ff1578657a","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"a5505306000e20f2","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"12cae8bbd22d8673","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"d7724f8a49b96fa6","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"3013078a26f31e2f","prefixes":{"":{"product":1466}}}, // [ImediaMax] - {"hash":"80193dea6eb67372","prefixes":{"":{"product":1467}}}, // [Flixbus] + {"hash":"e5f2b6b92cc6daa3","prefixes":{"":{"product":1463,"type":0}}}, // [Hyper] + {"hash":"f867e04c6dde165d","prefixes":{"":{"product":1464,"type":1}}}, // [Hurra Communications] + {"hash":"8353a34ee35ff30c","prefixes":{"":{"product":1464,"type":1}}}, // [Hurra Communications] + {"hash":"cc7f69fa55a7518f","prefixes":{"":{"product":1465,"type":0}}}, // [Groundhog TW] + {"hash":"95ba2d10b1b0675c","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"e8f62a52edbdf4bd","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"321a7e08d4b4fd55","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"c6f272ed0a206999","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"bd34d2733467c1af","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"1b49f6113458dc63","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"58b83e3b3a97943e","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"814bcd9589533387","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"9465fc7c156593f4","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"7c1c219e78b2f270","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"9d376bb5982319b0","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"12ec9a0b2888a4a9","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"f3d7dfcb60972b0c","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"460cac48ec149c6d","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"2614d3ffa05e19a5","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"1f9b770c08378ced","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"054864ff1578657a","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"a5505306000e20f2","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"12cae8bbd22d8673","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"d7724f8a49b96fa6","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"3013078a26f31e2f","prefixes":{"":{"product":1466,"type":0}}}, // [ImediaMax] + {"hash":"80193dea6eb67372","prefixes":{"":{"product":1467,"type":1}}}, // [Flixbus] {"hash":"02c439b9cc7e33b5","prefixes":{"":{"product":1468}}}, // [AudienceTV] - {"hash":"fcb4adbb2bc559e7","prefixes":{"":{"product":1469}}}, // [b34106183_test] - {"hash":"b08446a676a287b4","prefixes":{"":{"product":1469}}}, // [b34106183_test] - {"hash":"12105a6cc17c32e7","prefixes":{"":{"product":1470}}}, // [Netscore] - {"hash":"036d15c3ad4a0735","prefixes":{"":{"product":1470}}}, // [Netscore] - {"hash":"c0c40e6f63813be1","prefixes":{"":{"product":1471}}}, // [Chu Technology Limited] - {"hash":"4c434a52325c0b6e","prefixes":{"":{"product":1472}}}, // [SmartyAds LLC] - {"hash":"825a99c46b61053a","prefixes":{"":{"product":1473}}}, // [dbupdate1] - {"hash":"31ab5366866e8622","prefixes":{"":{"product":1473}}}, // [dbupdate1] + {"hash":"fcb4adbb2bc559e7","prefixes":{"":{"product":1469,"type":0}}}, // [b34106183_test] + {"hash":"b08446a676a287b4","prefixes":{"":{"product":1469,"type":0}}}, // [b34106183_test] + {"hash":"12105a6cc17c32e7","prefixes":{"":{"product":1470,"type":1}}}, // [Netscore] + {"hash":"036d15c3ad4a0735","prefixes":{"":{"product":1470,"type":1}}}, // [Netscore] + {"hash":"c0c40e6f63813be1","prefixes":{"":{"product":1471,"type":0}}}, // [Chu Technology Limited] + {"hash":"4c434a52325c0b6e","prefixes":{"":{"product":1472,"type":1}}}, // [SmartyAds LLC] + {"hash":"825a99c46b61053a","prefixes":{"":{"product":1473,"type":0}}}, // [dbupdate1] + {"hash":"31ab5366866e8622","prefixes":{"":{"product":1473,"type":0}}}, // [dbupdate1] {"hash":"32a21f3a47cb8ddc","prefixes":{"":{"product":128}}}, // [ConvertMedia Ltd.] - {"hash":"44a7af6d373bd713","prefixes":{"":{"product":985}}}, // [Lodeo] + {"hash":"44a7af6d373bd713","prefixes":{"":{"product":985,"type":0}}}, // [Lodeo] {"hash":"36d8680483227de8","prefixes":{"":{"product":985}}}, // [Lodeo] {"hash":"9709c6b69d2e3e90","prefixes":{"":{"product":985}}}, // [Lodeo] - {"hash":"5efefb78ec9b146f","prefixes":{"":{"product":1474}}}, // [The Big Willow Inc.] - {"hash":"3e5b3c0010f7172f","prefixes":{"":{"product":1475}}}, // [LiveIntent Inc] + {"hash":"5efefb78ec9b146f","prefixes":{"":{"product":1474,"type":0}}}, // [The Big Willow Inc.] + {"hash":"3e5b3c0010f7172f","prefixes":{"":{"product":1475,"type":0}}}, // [LiveIntent Inc] {"hash":"07bf09263d039040","prefixes":{"":{"product":1476}}}, // [OpenLedger ApS] - {"hash":"db879c71876741d0","prefixes":{"":{"product":1477}}}, // [Whichit] - {"hash":"4a6caded0a4565d9","prefixes":{"":{"product":1477}}}, // [Whichit] - {"hash":"05e0b02a9af28e89","prefixes":{"":{"product":1477}}}, // [Whichit] - {"hash":"3aca7ac4649f240c","prefixes":{"":{"product":1477}}}, // [Whichit] - {"hash":"81abe9587250fab1","prefixes":{"":{"product":1477}}}, // [Whichit] - {"hash":"a3b6bac891e57819","prefixes":{"":{"product":1478}}}, // [ParkDIA] - {"hash":"ddc3507bc6f79de4","prefixes":{"":{"product":1479}}}, // [Atedra Inc.] - {"hash":"881c2002027de2ec","prefixes":{"":{"product":1479}}}, // [Atedra Inc.] - {"hash":"28084881f4e51f6c","prefixes":{"":{"product":1480}}}, // [Digital Forest OÜ] - {"hash":"d563745e0fed92f4","prefixes":{"":{"product":1481}}}, // [Isobar Werbeagentur GmbH] - {"hash":"d6d13ce525771ba4","prefixes":{"":{"product":1482}}}, // [Valuepotion Pte. Ltd.] - {"hash":"446766a73edf76a2","prefixes":{"":{"product":1483}}}, // [Vuble Inc] - {"hash":"0753aa310a2a75aa","prefixes":{"":{"product":1484}}}, // [adlocal.net] - {"hash":"772284fa4bfb8e5a","prefixes":{"":{"product":1484}}}, // [adlocal.net] - {"hash":"0dd444b76d1727ab","prefixes":{"":{"product":1484}}}, // [adlocal.net] - {"hash":"1db1fc299e2dc73a","prefixes":{"":{"product":1484}}}, // [adlocal.net] - {"hash":"169447ab5f0b2b32","prefixes":{"":{"product":1485}}}, // [Freckle IoT] - {"hash":"143b45f2e52d871c","prefixes":{"":{"product":1486}}}, // [Personalization LLC] - {"hash":"bdc55693a2c62858","prefixes":{"":{"product":1487}}}, // [ThoughtLeadr Inc.] - {"hash":"e69058fe073a8d07","prefixes":{"":{"product":1487}}}, // [ThoughtLeadr Inc.] - {"hash":"ded94145085d34ed","prefixes":{"":{"product":1487}}}, // [ThoughtLeadr Inc.] - {"hash":"ef66f2e1bb6a3605","prefixes":{"":{"product":1487}}}, // [ThoughtLeadr Inc.] - {"hash":"5f62ecd0eec6b82a","prefixes":{"":{"product":1487}}}, // [ThoughtLeadr Inc.] - {"hash":"45281cea83398309","prefixes":{"":{"product":1488},"web":{"product":1488},"app":{"product":1488},"cdn":{"product":1488},"api":{"product":1488},"p":{"product":1488},"mobpages":{"product":1488}}}, // [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] - {"hash":"7ea0c7c8484fb7b4","prefixes":{"cdn":{"product":1488}}}, // [Noqoush Mobile Media Group FZ-LLC] - {"hash":"6839ebcbc8dce175","prefixes":{"":{"product":1488},"p":{"product":1488}}}, // [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] - {"hash":"c338016e1aa2a5f7","prefixes":{"":{"product":1489}}}, // [G-Core Labs] - {"hash":"3bb879b5ab17cbeb","prefixes":{"":{"product":1490}}}, // [Haensel AMS GmbH] - {"hash":"26627407df51f73d","prefixes":{"t":{"product":1490},"d":{"product":1490},"s":{"product":1490}}}, // [Haensel AMS GmbH] [Haensel AMS GmbH] [Haensel AMS GmbH] - {"hash":"44e07e9341e20fd0","prefixes":{"":{"product":1491}}}, // [LemonPI] - {"hash":"71d7abda3a6093b3","prefixes":{"":{"product":1491}}}, // [LemonPI] - {"hash":"f57717e6df039cd1","prefixes":{"":{"product":1491}}}, // [LemonPI] - {"hash":"0ae0087cfa7b79c3","prefixes":{"":{"product":1491}}}, // [LemonPI] - {"hash":"59afc0d091a22f58","prefixes":{"":{"product":1492}}}, // [4Info, Inc.] - {"hash":"fd299e0138ad90c1","prefixes":{"":{"product":1492}}}, // [4Info, Inc.] - {"hash":"1e408d2e9033a6e2","prefixes":{"":{"product":1492}}} // [4Info, Inc.] + {"hash":"db879c71876741d0","prefixes":{"":{"product":1477,"type":0}}}, // [Whichit] + {"hash":"4a6caded0a4565d9","prefixes":{"":{"product":1477,"type":0}}}, // [Whichit] + {"hash":"05e0b02a9af28e89","prefixes":{"":{"product":1477,"type":0}}}, // [Whichit] + {"hash":"3aca7ac4649f240c","prefixes":{"":{"product":1477,"type":0}}}, // [Whichit] + {"hash":"81abe9587250fab1","prefixes":{"":{"product":1477,"type":0}}}, // [Whichit] + {"hash":"a3b6bac891e57819","prefixes":{"":{"product":1478,"type":0}}}, // [ParkDIA] + {"hash":"ddc3507bc6f79de4","prefixes":{"":{"product":1479,"type":0}}}, // [Atedra Inc.] + {"hash":"881c2002027de2ec","prefixes":{"":{"product":1479,"type":0}}}, // [Atedra Inc.] + {"hash":"28084881f4e51f6c","prefixes":{"":{"product":1480,"type":0}}}, // [Digital Forest OÜ] + {"hash":"d563745e0fed92f4","prefixes":{"":{"product":1481,"type":2}}}, // [Isobar Werbeagentur GmbH] + {"hash":"d6d13ce525771ba4","prefixes":{"":{"product":1482,"type":0}}}, // [Valuepotion Pte. Ltd.] + {"hash":"446766a73edf76a2","prefixes":{"":{"product":1483,"type":0}}}, // [Vuble Inc] + {"hash":"0753aa310a2a75aa","prefixes":{"":{"product":1484,"type":0}}}, // [adlocal.net] + {"hash":"772284fa4bfb8e5a","prefixes":{"":{"product":1484,"type":0}}}, // [adlocal.net] + {"hash":"0dd444b76d1727ab","prefixes":{"":{"product":1484,"type":0}}}, // [adlocal.net] + {"hash":"1db1fc299e2dc73a","prefixes":{"":{"product":1484,"type":0}}}, // [adlocal.net] + {"hash":"169447ab5f0b2b32","prefixes":{"":{"product":1485,"type":1}}}, // [Freckle IoT] + {"hash":"143b45f2e52d871c","prefixes":{"":{"product":1486,"type":0}}}, // [Personalization LLC] + {"hash":"bdc55693a2c62858","prefixes":{"":{"product":1487,"type":0}}}, // [ThoughtLeadr Inc.] + {"hash":"e69058fe073a8d07","prefixes":{"":{"product":1487,"type":0}}}, // [ThoughtLeadr Inc.] + {"hash":"ded94145085d34ed","prefixes":{"":{"product":1487,"type":0}}}, // [ThoughtLeadr Inc.] + {"hash":"ef66f2e1bb6a3605","prefixes":{"":{"product":1487,"type":0}}}, // [ThoughtLeadr Inc.] + {"hash":"5f62ecd0eec6b82a","prefixes":{"":{"product":1487,"type":0}}}, // [ThoughtLeadr Inc.] + {"hash":"45281cea83398309","prefixes":{"":{"product":1488,"type":0},"web":{"product":1488,"type":0},"app":{"product":1488,"type":0},"cdn":{"product":1488,"type":0},"api":{"product":1488,"type":0},"p":{"product":1488,"type":0},"mobpages":{"product":1488,"type":0}}}, // [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] + {"hash":"7ea0c7c8484fb7b4","prefixes":{"cdn":{"product":1488,"type":0}}}, // [Noqoush Mobile Media Group FZ-LLC] + {"hash":"6839ebcbc8dce175","prefixes":{"":{"product":1488,"type":0},"p":{"product":1488,"type":0}}}, // [Noqoush Mobile Media Group FZ-LLC] [Noqoush Mobile Media Group FZ-LLC] + {"hash":"c338016e1aa2a5f7","prefixes":{"":{"product":1489,"type":2}}}, // [G-Core Labs] + {"hash":"3bb879b5ab17cbeb","prefixes":{"":{"product":1490,"type":1}}}, // [Haensel AMS GmbH] + {"hash":"26627407df51f73d","prefixes":{"t":{"product":1490,"type":1},"d":{"product":1490,"type":1},"s":{"product":1490,"type":1}}}, // [Haensel AMS GmbH] [Haensel AMS GmbH] [Haensel AMS GmbH] + {"hash":"44e07e9341e20fd0","prefixes":{"":{"product":1491,"type":2}}}, // [LemonPI] + {"hash":"71d7abda3a6093b3","prefixes":{"":{"product":1491,"type":2}}}, // [LemonPI] + {"hash":"f57717e6df039cd1","prefixes":{"":{"product":1491,"type":2}}}, // [LemonPI] + {"hash":"0ae0087cfa7b79c3","prefixes":{"":{"product":1491,"type":2}}}, // [LemonPI] + {"hash":"59afc0d091a22f58","prefixes":{"":{"product":1492,"type":0}}}, // [4Info, Inc.] + {"hash":"fd299e0138ad90c1","prefixes":{"":{"product":1492,"type":0}}}, // [4Info, Inc.] + {"hash":"1e408d2e9033a6e2","prefixes":{"":{"product":1492,"type":0}}} // [4Info, Inc.] ]);
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js index 267faad..725c84c 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js
@@ -297,7 +297,7 @@ waitingEntry.createChild('span').textContent = Common.UIString('#%s waiting to activate', waiting.id); createLink(waitingEntry, Common.UIString('skipWaiting'), this._skipButtonClicked.bind(this)); waitingEntry.createChild('div', 'service-worker-subtitle').textContent = - new Date(waiting.scriptResponseTime * 1000).toLocaleString(); + Common.UIString('Received %s', new Date(waiting.scriptResponseTime * 1000).toLocaleString()); if (!this._targetForVersionId(waiting.id) && (waiting.isRunning() || waiting.isStarting())) createLink(waitingEntry, Common.UIString('inspect'), this._inspectButtonClicked.bind(this, waiting.id)); } @@ -306,7 +306,7 @@ installingEntry.createChild('div', 'service-worker-installing-circle'); installingEntry.createChild('span').textContent = Common.UIString('#%s installing', installing.id); installingEntry.createChild('div', 'service-worker-subtitle').textContent = - new Date(installing.scriptResponseTime * 1000).toLocaleString(); + Common.UIString('Received %s', new Date(installing.scriptResponseTime * 1000).toLocaleString()); if (!this._targetForVersionId(installing.id) && (installing.isRunning() || installing.isStarting())) createLink(installingEntry, Common.UIString('inspect'), this._inspectButtonClicked.bind(this, installing.id)); }
diff --git a/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css b/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css index 27b5118..004fa99 100644 --- a/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css +++ b/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css
@@ -336,7 +336,8 @@ content: " "; } -.CodeMirror .text-editor-coverage-used-marker { +.CodeMirror .text-editor-coverage-used-marker, +.CodeMirror .text-editor-coverage-mixed-marker { text-align: right; padding-right: 2px; background-color: #81C784; @@ -346,14 +347,6 @@ content: " "; } -.CodeMirror .text-editor-coverage-mixed-marker { - text-align: right; - padding-right: 2px; - background-repeat: repeat; - background-size: 5px 5px; - background-image: linear-gradient(0, #81C784 0px, #81C784 2.5px, #E57373 2.5px, #E57373 5px); -} - .CodeMirror .text-editor-coverage-mixed-marker::after { content: " "; }
diff --git a/third_party/WebKit/Source/devtools/scripts/convert-3pas-product-registry.js b/third_party/WebKit/Source/devtools/scripts/convert-3pas-product-registry.js index 79d63d3c..2d450c1 100644 --- a/third_party/WebKit/Source/devtools/scripts/convert-3pas-product-registry.js +++ b/third_party/WebKit/Source/devtools/scripts/convert-3pas-product-registry.js
@@ -23,10 +23,10 @@ const chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ const typeClassifications = new Map([ - ['cdn_provider', 'CDN'], ['cdn_commercial_owner', 'CDN'], ['cdn_creative_agency', 'CDN'], ['ad_blocking', 'Ad'], - ['ad_exchange', 'Ad'], ['ad_server_ad_network', 'Ad'], ['ad_server_advertiser', 'Ad'], ['demand_side_platform', 'Ad'], - ['vast_provider', 'Ad'], ['data_management_platform', 'Tracking'], ['research_analytics', 'Tracking'], - ['research_verification', 'Tracking'], ['research_brand_lift', 'Tracking'] + ['cdn_provider', 0], ['cdn_commercial_owner', 2], ['cdn_creative_agency', 2], ['ad_blocking', 0], ['ad_exchange', 0], + ['ad_server_ad_network', 0], ['ad_server_advertiser', 0], ['demand_side_platform', 0], ['vast_provider', 0], + ['data_management_platform', 1], ['research_analytics', 1], ['research_verification', 1], + ['research_brand_lift', 1] ]); var data = fs.readFileSync('3pas.csv', 'utf8'); @@ -124,7 +124,6 @@ } var outputProducts = []; -var outputTypes = []; var outputObj = new Map(); for (var [baseDomain, subdomains] of map) { for (var prefixes of subdomains.values()) { @@ -177,12 +176,6 @@ '// clang-format off\n' + '/* eslint-disable */\n' + 'ProductRegistry.register(['); -if (outputTypes.length) { - var data = JSON.stringify(outputTypes).replace(/","/g, '",\n "'); - console.log(' ' + data.substring(1, data.length - 1)); -} -console.log('],'); -console.log('['); var data = JSON.stringify(outputProducts).replace(/","/g, '",\n "'); console.log(' ' + data.substring(1, data.length - 1)); console.log('],'); @@ -192,14 +185,8 @@ var obj = outputObjArray[i]; var lineEnding = (i === outputObjArray.length - 1) ? '' : ','; var comments = []; - for (var prefix in obj.prefixes) { - var typeName = outputTypes[obj.prefixes[prefix].type]; - if (!typeName) - typeName = ''; - else - typeName = ':' + typeName; - comments.push('[' + outputProducts[obj.prefixes[prefix].product] + typeName + ']'); - } + for (var prefix in obj.prefixes) + comments.push('[' + outputProducts[obj.prefixes[prefix].product] + ']'); console.log(' ' + JSON.stringify(obj) + lineEnding + ' // ' + comments.join(' ')); } console.log(']);'); @@ -226,14 +213,9 @@ } function registerOutputType(type) { - var name = typeClassifications.get(type); - if (!name) + var index = typeClassifications.get(type); + if (index === undefined) return -1; - var index = outputTypes.indexOf(name); - if (index === -1) { - outputTypes.push(name); - return outputTypes.length - 1; - } return index; }
diff --git a/third_party/WebKit/Source/modules/notifications/BUILD.gn b/third_party/WebKit/Source/modules/notifications/BUILD.gn index 020ba073..f171a72b 100644 --- a/third_party/WebKit/Source/modules/notifications/BUILD.gn +++ b/third_party/WebKit/Source/modules/notifications/BUILD.gn
@@ -24,6 +24,6 @@ "ServiceWorkerRegistrationNotifications.h", ] deps = [ - "//device/vibration:mojo_bindings_blink", + "//services/device/public/interfaces:interfaces_blink", ] }
diff --git a/third_party/WebKit/Source/modules/vibration/BUILD.gn b/third_party/WebKit/Source/modules/vibration/BUILD.gn index fe86e081..6bd9648 100644 --- a/third_party/WebKit/Source/modules/vibration/BUILD.gn +++ b/third_party/WebKit/Source/modules/vibration/BUILD.gn
@@ -13,8 +13,8 @@ ] deps = [ - "//device/vibration:mojo_bindings_blink", "//services/device/public/interfaces:constants_blink", + "//services/device/public/interfaces:interfaces_blink", "//services/service_manager/public/cpp", ] }
diff --git a/third_party/WebKit/Source/modules/vibration/DEPS b/third_party/WebKit/Source/modules/vibration/DEPS index 413de98..c6fb24e 100644 --- a/third_party/WebKit/Source/modules/vibration/DEPS +++ b/third_party/WebKit/Source/modules/vibration/DEPS
@@ -1,7 +1,7 @@ include_rules = [ - "+device/vibration/vibration_manager.mojom-blink.h", "-modules", "+modules/ModulesExport.h", "+modules/vibration", "+services/device/public/interfaces/constants.mojom-blink.h", + "+services/device/public/interfaces/vibration_manager.mojom-blink.h", ]
diff --git a/third_party/WebKit/Source/modules/vibration/VibrationController.h b/third_party/WebKit/Source/modules/vibration/VibrationController.h index 6da7754..46dd923 100644 --- a/third_party/WebKit/Source/modules/vibration/VibrationController.h +++ b/third_party/WebKit/Source/modules/vibration/VibrationController.h
@@ -22,13 +22,13 @@ #include "core/dom/ContextLifecycleObserver.h" #include "core/page/PageVisibilityObserver.h" -#include "device/vibration/vibration_manager.mojom-blink.h" #include "modules/ModulesExport.h" #include "platform/Timer.h" #include "platform/heap/GarbageCollected.h" #include "platform/heap/Handle.h" #include "platform/wtf/Noncopyable.h" #include "platform/wtf/Vector.h" +#include "services/device/public/interfaces/vibration_manager.mojom-blink.h" namespace blink {
diff --git a/third_party/WebKit/Source/modules/webusb/USB.cpp b/third_party/WebKit/Source/modules/webusb/USB.cpp index cbe3e04..4faf249be6 100644 --- a/third_party/WebKit/Source/modules/webusb/USB.cpp +++ b/third_party/WebKit/Source/modules/webusb/USB.cpp
@@ -21,15 +21,17 @@ #include "public/platform/InterfaceProvider.h" #include "public/platform/Platform.h" -namespace usb = device::usb::blink; +using device::mojom::blink::UsbDeviceFilterPtr; +using device::mojom::blink::UsbDeviceInfoPtr; +using device::mojom::blink::UsbDevicePtr; namespace blink { namespace { const char kNoDeviceSelected[] = "No device selected."; -usb::DeviceFilterPtr ConvertDeviceFilter(const USBDeviceFilter& filter) { - auto mojo_filter = usb::DeviceFilter::New(); +UsbDeviceFilterPtr ConvertDeviceFilter(const USBDeviceFilter& filter) { + auto mojo_filter = device::mojom::blink::UsbDeviceFilter::New(); mojo_filter->has_vendor_id = filter.hasVendorId(); if (mojo_filter->has_vendor_id) mojo_filter->vendor_id = filter.vendorId(); @@ -107,7 +109,7 @@ kSecurityError, "Must be handling a user gesture to show a permission request.")); } else { - Vector<usb::DeviceFilterPtr> filters; + Vector<UsbDeviceFilterPtr> filters; if (options.hasFilters()) { filters.ReserveCapacity(options.filters().size()); for (const auto& filter : options.filters()) @@ -137,11 +139,11 @@ chooser_service_requests_.Clear(); } -USBDevice* USB::GetOrCreateDevice(usb::DeviceInfoPtr device_info) { +USBDevice* USB::GetOrCreateDevice(UsbDeviceInfoPtr device_info) { USBDevice* device = device_cache_.at(device_info->guid); if (!device) { String guid = device_info->guid; - usb::DevicePtr pipe; + UsbDevicePtr pipe; device_manager_->GetDevice(guid, mojo::MakeRequest(&pipe)); device = USBDevice::Create(std::move(device_info), std::move(pipe), GetExecutionContext()); @@ -151,7 +153,7 @@ } void USB::OnGetDevices(ScriptPromiseResolver* resolver, - Vector<usb::DeviceInfoPtr> device_infos) { + Vector<UsbDeviceInfoPtr> device_infos) { auto request_entry = device_manager_requests_.Find(resolver); if (request_entry == device_manager_requests_.end()) return; @@ -165,7 +167,7 @@ } void USB::OnGetPermission(ScriptPromiseResolver* resolver, - usb::DeviceInfoPtr device_info) { + UsbDeviceInfoPtr device_info) { auto request_entry = chooser_service_requests_.Find(resolver); if (request_entry == chooser_service_requests_.end()) return; @@ -180,7 +182,7 @@ } } -void USB::OnDeviceAdded(usb::DeviceInfoPtr device_info) { +void USB::OnDeviceAdded(UsbDeviceInfoPtr device_info) { if (!device_manager_) return; @@ -188,7 +190,7 @@ EventTypeNames::connect, GetOrCreateDevice(std::move(device_info)))); } -void USB::OnDeviceRemoved(usb::DeviceInfoPtr device_info) { +void USB::OnDeviceRemoved(UsbDeviceInfoPtr device_info) { String guid = device_info->guid; USBDevice* device = device_cache_.at(guid); if (!device) {
diff --git a/third_party/WebKit/Source/modules/webusb/USB.h b/third_party/WebKit/Source/modules/webusb/USB.h index efbde77..c75353b 100644 --- a/third_party/WebKit/Source/modules/webusb/USB.h +++ b/third_party/WebKit/Source/modules/webusb/USB.h
@@ -24,7 +24,7 @@ class USB final : public EventTargetWithInlineData, public ContextLifecycleObserver, - public device::usb::blink::DeviceManagerClient { + public device::mojom::blink::UsbDeviceManagerClient { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(USB); USING_PRE_FINALIZER(USB, Dispose); @@ -49,20 +49,20 @@ // ContextLifecycleObserver overrides. void ContextDestroyed(ExecutionContext*) override; - USBDevice* GetOrCreateDevice(device::usb::blink::DeviceInfoPtr); + USBDevice* GetOrCreateDevice(device::mojom::blink::UsbDeviceInfoPtr); - device::usb::blink::DeviceManager* GetDeviceManager() const { + device::mojom::blink::UsbDeviceManager* GetDeviceManager() const { return device_manager_.get(); } void OnGetDevices(ScriptPromiseResolver*, - Vector<device::usb::blink::DeviceInfoPtr>); + Vector<device::mojom::blink::UsbDeviceInfoPtr>); void OnGetPermission(ScriptPromiseResolver*, - device::usb::blink::DeviceInfoPtr); + device::mojom::blink::UsbDeviceInfoPtr); // DeviceManagerClient implementation. - void OnDeviceAdded(device::usb::blink::DeviceInfoPtr); - void OnDeviceRemoved(device::usb::blink::DeviceInfoPtr); + void OnDeviceAdded(device::mojom::blink::UsbDeviceInfoPtr); + void OnDeviceRemoved(device::mojom::blink::UsbDeviceInfoPtr); void OnDeviceManagerConnectionError(); void OnChooserServiceConnectionError(); @@ -79,11 +79,11 @@ void EnsureDeviceManagerConnection(); - device::usb::blink::DeviceManagerPtr device_manager_; + device::mojom::blink::UsbDeviceManagerPtr device_manager_; HeapHashSet<Member<ScriptPromiseResolver>> device_manager_requests_; - device::usb::blink::ChooserServicePtr chooser_service_; + device::mojom::blink::UsbChooserServicePtr chooser_service_; HeapHashSet<Member<ScriptPromiseResolver>> chooser_service_requests_; - mojo::Binding<device::usb::blink::DeviceManagerClient> client_binding_; + mojo::Binding<device::mojom::blink::UsbDeviceManagerClient> client_binding_; HeapHashMap<String, WeakMember<USBDevice>> device_cache_; };
diff --git a/third_party/WebKit/Source/modules/webusb/USBAlternateInterface.cpp b/third_party/WebKit/Source/modules/webusb/USBAlternateInterface.cpp index e9ff870..8b6d8f7 100644 --- a/third_party/WebKit/Source/modules/webusb/USBAlternateInterface.cpp +++ b/third_party/WebKit/Source/modules/webusb/USBAlternateInterface.cpp
@@ -36,9 +36,10 @@ ASSERT(alternate_index_ < interface_->Info().alternates.size()); } -const device::usb::blink::AlternateInterfaceInfo& USBAlternateInterface::Info() - const { - const device::usb::blink::InterfaceInfo& interface_info = interface_->Info(); +const device::mojom::blink::UsbAlternateInterfaceInfo& +USBAlternateInterface::Info() const { + const device::mojom::blink::UsbInterfaceInfo& interface_info = + interface_->Info(); ASSERT(alternate_index_ < interface_info.alternates.size()); return *interface_info.alternates[alternate_index_]; }
diff --git a/third_party/WebKit/Source/modules/webusb/USBAlternateInterface.h b/third_party/WebKit/Source/modules/webusb/USBAlternateInterface.h index 6e2c8b6..91d21a9 100644 --- a/third_party/WebKit/Source/modules/webusb/USBAlternateInterface.h +++ b/third_party/WebKit/Source/modules/webusb/USBAlternateInterface.h
@@ -28,7 +28,7 @@ USBAlternateInterface(const USBInterface*, size_t alternate_index); - const device::usb::blink::AlternateInterfaceInfo& Info() const; + const device::mojom::blink::UsbAlternateInterfaceInfo& Info() const; uint8_t alternateSetting() const { return Info().alternate_setting; } uint8_t interfaceClass() const { return Info().class_code; }
diff --git a/third_party/WebKit/Source/modules/webusb/USBConfiguration.cpp b/third_party/WebKit/Source/modules/webusb/USBConfiguration.cpp index cab418af..9623955 100644 --- a/third_party/WebKit/Source/modules/webusb/USBConfiguration.cpp +++ b/third_party/WebKit/Source/modules/webusb/USBConfiguration.cpp
@@ -43,7 +43,8 @@ return configuration_index_; } -const device::usb::blink::ConfigurationInfo& USBConfiguration::Info() const { +const device::mojom::blink::UsbConfigurationInfo& USBConfiguration::Info() + const { return *device_->Info().configurations[configuration_index_]; }
diff --git a/third_party/WebKit/Source/modules/webusb/USBConfiguration.h b/third_party/WebKit/Source/modules/webusb/USBConfiguration.h index 9912ac0..67c45056 100644 --- a/third_party/WebKit/Source/modules/webusb/USBConfiguration.h +++ b/third_party/WebKit/Source/modules/webusb/USBConfiguration.h
@@ -29,7 +29,7 @@ const USBDevice* Device() const; size_t Index() const; - const device::usb::blink::ConfigurationInfo& Info() const; + const device::mojom::blink::UsbConfigurationInfo& Info() const; uint8_t configurationValue() const { return Info().configuration_value; } String configurationName() const { return Info().configuration_name; }
diff --git a/third_party/WebKit/Source/modules/webusb/USBDevice.cpp b/third_party/WebKit/Source/modules/webusb/USBDevice.cpp index df77227d..d8f5b71 100644 --- a/third_party/WebKit/Source/modules/webusb/USBDevice.cpp +++ b/third_party/WebKit/Source/modules/webusb/USBDevice.cpp
@@ -21,7 +21,15 @@ #include "platform/wtf/Assertions.h" #include "public/platform/Platform.h" -namespace usb = device::usb::blink; +using device::mojom::blink::UsbControlTransferParamsPtr; +using device::mojom::blink::UsbControlTransferType; +using device::mojom::blink::UsbControlTransferRecipient; +using device::mojom::blink::UsbDeviceInfoPtr; +using device::mojom::blink::UsbDevicePtr; +using device::mojom::blink::UsbIsochronousPacketPtr; +using device::mojom::blink::UsbOpenDeviceError; +using device::mojom::blink::UsbTransferDirection; +using device::mojom::blink::UsbTransferStatus; namespace blink { @@ -37,24 +45,24 @@ "An operation that changes interface state is in progress."; const char kOpenRequired[] = "The device must be opened first."; -DOMException* ConvertFatalTransferStatus(const usb::TransferStatus& status) { +DOMException* ConvertFatalTransferStatus(const UsbTransferStatus& status) { switch (status) { - case usb::TransferStatus::TRANSFER_ERROR: + case UsbTransferStatus::TRANSFER_ERROR: return DOMException::Create(kNetworkError, "A transfer error has occured."); - case usb::TransferStatus::PERMISSION_DENIED: + case UsbTransferStatus::PERMISSION_DENIED: return DOMException::Create(kSecurityError, "The transfer was not allowed."); - case usb::TransferStatus::TIMEOUT: + case UsbTransferStatus::TIMEOUT: return DOMException::Create(kTimeoutError, "The transfer timed out."); - case usb::TransferStatus::CANCELLED: + case UsbTransferStatus::CANCELLED: return DOMException::Create(kAbortError, "The transfer was cancelled."); - case usb::TransferStatus::DISCONNECT: + case UsbTransferStatus::DISCONNECT: return DOMException::Create(kNotFoundError, kDeviceUnavailable); - case usb::TransferStatus::COMPLETED: - case usb::TransferStatus::STALLED: - case usb::TransferStatus::BABBLE: - case usb::TransferStatus::SHORT_PACKET: + case UsbTransferStatus::COMPLETED: + case UsbTransferStatus::STALLED: + case UsbTransferStatus::BABBLE: + case UsbTransferStatus::SHORT_PACKET: return nullptr; default: ASSERT_NOT_REACHED(); @@ -62,14 +70,14 @@ } } -String ConvertTransferStatus(const usb::TransferStatus& status) { +String ConvertTransferStatus(const UsbTransferStatus& status) { switch (status) { - case usb::TransferStatus::COMPLETED: - case usb::TransferStatus::SHORT_PACKET: + case UsbTransferStatus::COMPLETED: + case UsbTransferStatus::SHORT_PACKET: return "ok"; - case usb::TransferStatus::STALLED: + case UsbTransferStatus::STALLED: return "stall"; - case usb::TransferStatus::BABBLE: + case UsbTransferStatus::BABBLE: return "babble"; default: ASSERT_NOT_REACHED(); @@ -93,8 +101,8 @@ } // namespace -USBDevice::USBDevice(usb::DeviceInfoPtr device_info, - usb::DevicePtr device, +USBDevice::USBDevice(UsbDeviceInfoPtr device_info, + UsbDevicePtr device, ExecutionContext* context) : ContextLifecycleObserver(context), device_info_(std::move(device_info)), @@ -580,17 +588,17 @@ return false; } -usb::ControlTransferParamsPtr USBDevice::ConvertControlTransferParameters( +UsbControlTransferParamsPtr USBDevice::ConvertControlTransferParameters( const USBControlTransferParameters& parameters, ScriptPromiseResolver* resolver) const { - auto mojo_parameters = usb::ControlTransferParams::New(); + auto mojo_parameters = device::mojom::blink::UsbControlTransferParams::New(); if (parameters.requestType() == "standard") { - mojo_parameters->type = usb::ControlTransferType::STANDARD; + mojo_parameters->type = UsbControlTransferType::STANDARD; } else if (parameters.requestType() == "class") { - mojo_parameters->type = usb::ControlTransferType::CLASS; + mojo_parameters->type = UsbControlTransferType::CLASS; } else if (parameters.requestType() == "vendor") { - mojo_parameters->type = usb::ControlTransferType::VENDOR; + mojo_parameters->type = UsbControlTransferType::VENDOR; } else { resolver->Reject(DOMException::Create( kTypeMismatchError, @@ -599,20 +607,20 @@ } if (parameters.recipient() == "device") { - mojo_parameters->recipient = usb::ControlTransferRecipient::DEVICE; + mojo_parameters->recipient = UsbControlTransferRecipient::DEVICE; } else if (parameters.recipient() == "interface") { size_t interface_number = parameters.index() & 0xff; if (!EnsureInterfaceClaimed(interface_number, resolver)) return nullptr; - mojo_parameters->recipient = usb::ControlTransferRecipient::INTERFACE; + mojo_parameters->recipient = UsbControlTransferRecipient::INTERFACE; } else if (parameters.recipient() == "endpoint") { bool in_transfer = parameters.index() & 0x80; size_t endpoint_number = parameters.index() & 0x0f; if (!EnsureEndpointAvailable(in_transfer, endpoint_number, resolver)) return nullptr; - mojo_parameters->recipient = usb::ControlTransferRecipient::ENDPOINT; + mojo_parameters->recipient = UsbControlTransferRecipient::ENDPOINT; } else if (parameters.recipient() == "other") { - mojo_parameters->recipient = usb::ControlTransferRecipient::OTHER; + mojo_parameters->recipient = UsbControlTransferRecipient::OTHER; } else { resolver->Reject(DOMException::Create( kTypeMismatchError, @@ -635,7 +643,7 @@ uint8_t endpoint_number = endpoint->endpoint_number; if (endpoint_number == 0 || endpoint_number >= 16) continue; // Ignore endpoints with invalid indices. - auto& bit_vector = endpoint->direction == usb::TransferDirection::INBOUND + auto& bit_vector = endpoint->direction == UsbTransferDirection::INBOUND ? in_endpoints_ : out_endpoints_; if (set) @@ -646,19 +654,19 @@ } void USBDevice::AsyncOpen(ScriptPromiseResolver* resolver, - usb::OpenDeviceError error) { + UsbOpenDeviceError error) { if (!MarkRequestComplete(resolver)) return; switch (error) { - case usb::OpenDeviceError::ALREADY_OPEN: + case UsbOpenDeviceError::ALREADY_OPEN: ASSERT_NOT_REACHED(); // fall through - case usb::OpenDeviceError::OK: + case UsbOpenDeviceError::OK: OnDeviceOpenedOrClosed(true /* opened */); resolver->Resolve(); return; - case usb::OpenDeviceError::ACCESS_DENIED: + case UsbOpenDeviceError::ACCESS_DENIED: OnDeviceOpenedOrClosed(false /* not opened */); resolver->Reject(DOMException::Create(kSecurityError, "Access denied.")); return; @@ -776,7 +784,7 @@ } void USBDevice::AsyncControlTransferIn(ScriptPromiseResolver* resolver, - usb::TransferStatus status, + UsbTransferStatus status, const Optional<Vector<uint8_t>>& data) { if (!MarkRequestComplete(resolver)) return; @@ -792,7 +800,7 @@ void USBDevice::AsyncControlTransferOut(unsigned transfer_length, ScriptPromiseResolver* resolver, - usb::TransferStatus status) { + UsbTransferStatus status) { if (!MarkRequestComplete(resolver)) return; @@ -817,7 +825,7 @@ } void USBDevice::AsyncTransferIn(ScriptPromiseResolver* resolver, - usb::TransferStatus status, + UsbTransferStatus status, const Optional<Vector<uint8_t>>& data) { if (!MarkRequestComplete(resolver)) return; @@ -833,7 +841,7 @@ void USBDevice::AsyncTransferOut(unsigned transfer_length, ScriptPromiseResolver* resolver, - usb::TransferStatus status) { + UsbTransferStatus status) { if (!MarkRequestComplete(resolver)) return; @@ -849,7 +857,7 @@ void USBDevice::AsyncIsochronousTransferIn( ScriptPromiseResolver* resolver, const Optional<Vector<uint8_t>>& data, - Vector<usb::IsochronousPacketPtr> mojo_packets) { + Vector<UsbIsochronousPacketPtr> mojo_packets) { if (!MarkRequestComplete(resolver)) return; @@ -878,7 +886,7 @@ void USBDevice::AsyncIsochronousTransferOut( ScriptPromiseResolver* resolver, - Vector<usb::IsochronousPacketPtr> mojo_packets) { + Vector<UsbIsochronousPacketPtr> mojo_packets) { if (!MarkRequestComplete(resolver)) return;
diff --git a/third_party/WebKit/Source/modules/webusb/USBDevice.h b/third_party/WebKit/Source/modules/webusb/USBDevice.h index 4139ebb..e864f3b 100644 --- a/third_party/WebKit/Source/modules/webusb/USBDevice.h +++ b/third_party/WebKit/Source/modules/webusb/USBDevice.h
@@ -28,18 +28,20 @@ DEFINE_WRAPPERTYPEINFO(); public: - static USBDevice* Create(device::usb::blink::DeviceInfoPtr device_info, - device::usb::blink::DevicePtr device, + static USBDevice* Create(device::mojom::blink::UsbDeviceInfoPtr device_info, + device::mojom::blink::UsbDevicePtr device, ExecutionContext* context) { return new USBDevice(std::move(device_info), std::move(device), context); } - explicit USBDevice(device::usb::blink::DeviceInfoPtr, - device::usb::blink::DevicePtr, + explicit USBDevice(device::mojom::blink::UsbDeviceInfoPtr, + device::mojom::blink::UsbDevicePtr, ExecutionContext*); virtual ~USBDevice(); - const device::usb::blink::DeviceInfo& Info() const { return *device_info_; } + const device::mojom::blink::UsbDeviceInfo& Info() const { + return *device_info_; + } bool IsInterfaceClaimed(size_t configuration_index, size_t interface_index) const; size_t SelectedAlternateInterface(size_t interface_index) const; @@ -117,12 +119,13 @@ uint8_t endpoint_number, ScriptPromiseResolver*) const; bool AnyInterfaceChangeInProgress() const; - device::usb::blink::ControlTransferParamsPtr ConvertControlTransferParameters( - const USBControlTransferParameters&, - ScriptPromiseResolver*) const; + device::mojom::blink::UsbControlTransferParamsPtr + ConvertControlTransferParameters(const USBControlTransferParameters&, + ScriptPromiseResolver*) const; void SetEndpointsForInterface(size_t interface_index, bool set); - void AsyncOpen(ScriptPromiseResolver*, device::usb::blink::OpenDeviceError); + void AsyncOpen(ScriptPromiseResolver*, + device::mojom::blink::UsbOpenDeviceError); void AsyncClose(ScriptPromiseResolver*); void OnDeviceOpenedOrClosed(bool); void AsyncSelectConfiguration(size_t configuration_index, @@ -141,32 +144,32 @@ ScriptPromiseResolver*, bool success); void AsyncControlTransferIn(ScriptPromiseResolver*, - device::usb::blink::TransferStatus, + device::mojom::blink::UsbTransferStatus, const Optional<Vector<uint8_t>>&); void AsyncControlTransferOut(unsigned, ScriptPromiseResolver*, - device::usb::blink::TransferStatus); + device::mojom::blink::UsbTransferStatus); void AsyncClearHalt(ScriptPromiseResolver*, bool success); void AsyncTransferIn(ScriptPromiseResolver*, - device::usb::blink::TransferStatus, + device::mojom::blink::UsbTransferStatus, const Optional<Vector<uint8_t>>&); void AsyncTransferOut(unsigned, ScriptPromiseResolver*, - device::usb::blink::TransferStatus); + device::mojom::blink::UsbTransferStatus); void AsyncIsochronousTransferIn( ScriptPromiseResolver*, const Optional<Vector<uint8_t>>&, - Vector<device::usb::blink::IsochronousPacketPtr>); + Vector<device::mojom::blink::UsbIsochronousPacketPtr>); void AsyncIsochronousTransferOut( ScriptPromiseResolver*, - Vector<device::usb::blink::IsochronousPacketPtr>); + Vector<device::mojom::blink::UsbIsochronousPacketPtr>); void AsyncReset(ScriptPromiseResolver*, bool success); void OnConnectionError(); bool MarkRequestComplete(ScriptPromiseResolver*); - device::usb::blink::DeviceInfoPtr device_info_; - device::usb::blink::DevicePtr device_; + device::mojom::blink::UsbDeviceInfoPtr device_info_; + device::mojom::blink::UsbDevicePtr device_; HeapHashSet<Member<ScriptPromiseResolver>> device_requests_; bool opened_; bool device_state_change_in_progress_;
diff --git a/third_party/WebKit/Source/modules/webusb/USBEndpoint.cpp b/third_party/WebKit/Source/modules/webusb/USBEndpoint.cpp index 8a71cda..16babb28 100644 --- a/third_party/WebKit/Source/modules/webusb/USBEndpoint.cpp +++ b/third_party/WebKit/Source/modules/webusb/USBEndpoint.cpp
@@ -9,18 +9,18 @@ #include "device/usb/public/interfaces/device.mojom-blink.h" #include "modules/webusb/USBAlternateInterface.h" -using device::usb::blink::EndpointType; -using device::usb::blink::TransferDirection; +using device::mojom::blink::UsbEndpointType; +using device::mojom::blink::UsbTransferDirection; namespace blink { namespace { -String ConvertDirectionToEnum(const TransferDirection& direction) { +String ConvertDirectionToEnum(const UsbTransferDirection& direction) { switch (direction) { - case TransferDirection::INBOUND: + case UsbTransferDirection::INBOUND: return "in"; - case TransferDirection::OUTBOUND: + case UsbTransferDirection::OUTBOUND: return "out"; default: ASSERT_NOT_REACHED(); @@ -28,13 +28,13 @@ } } -String ConvertTypeToEnum(const EndpointType& type) { +String ConvertTypeToEnum(const UsbEndpointType& type) { switch (type) { - case EndpointType::BULK: + case UsbEndpointType::BULK: return "bulk"; - case EndpointType::INTERRUPT: + case UsbEndpointType::INTERRUPT: return "interrupt"; - case EndpointType::ISOCHRONOUS: + case UsbEndpointType::ISOCHRONOUS: return "isochronous"; default: ASSERT_NOT_REACHED(); @@ -53,9 +53,9 @@ size_t endpoint_number, const String& direction, ExceptionState& exception_state) { - TransferDirection mojo_direction = direction == "in" - ? TransferDirection::INBOUND - : TransferDirection::OUTBOUND; + UsbTransferDirection mojo_direction = direction == "in" + ? UsbTransferDirection::INBOUND + : UsbTransferDirection::OUTBOUND; const auto& endpoints = alternate->Info().endpoints; for (size_t i = 0; i < endpoints.size(); ++i) { const auto& endpoint = endpoints[i]; @@ -75,8 +75,8 @@ ASSERT(endpoint_index_ < alternate_->Info().endpoints.size()); } -const device::usb::blink::EndpointInfo& USBEndpoint::Info() const { - const device::usb::blink::AlternateInterfaceInfo& alternate_info = +const device::mojom::blink::UsbEndpointInfo& USBEndpoint::Info() const { + const device::mojom::blink::UsbAlternateInterfaceInfo& alternate_info = alternate_->Info(); ASSERT(endpoint_index_ < alternate_info.endpoints.size()); return *alternate_info.endpoints[endpoint_index_];
diff --git a/third_party/WebKit/Source/modules/webusb/USBEndpoint.h b/third_party/WebKit/Source/modules/webusb/USBEndpoint.h index 2c2ee78..a95b3863 100644 --- a/third_party/WebKit/Source/modules/webusb/USBEndpoint.h +++ b/third_party/WebKit/Source/modules/webusb/USBEndpoint.h
@@ -28,7 +28,7 @@ USBEndpoint(const USBAlternateInterface*, size_t endpoint_index); - const device::usb::blink::EndpointInfo& Info() const; + const device::mojom::blink::UsbEndpointInfo& Info() const; uint8_t endpointNumber() const { return Info().endpoint_number; } String direction() const;
diff --git a/third_party/WebKit/Source/modules/webusb/USBInterface.cpp b/third_party/WebKit/Source/modules/webusb/USBInterface.cpp index 783cdde7..b4c0de8 100644 --- a/third_party/WebKit/Source/modules/webusb/USBInterface.cpp +++ b/third_party/WebKit/Source/modules/webusb/USBInterface.cpp
@@ -43,7 +43,7 @@ device_->Info().configurations[configuration_index_]->interfaces.size()); } -const device::usb::blink::InterfaceInfo& USBInterface::Info() const { +const device::mojom::blink::UsbInterfaceInfo& USBInterface::Info() const { return *device_->Info() .configurations[configuration_index_] ->interfaces[interface_index_];
diff --git a/third_party/WebKit/Source/modules/webusb/USBInterface.h b/third_party/WebKit/Source/modules/webusb/USBInterface.h index dc24029..b1f91bd 100644 --- a/third_party/WebKit/Source/modules/webusb/USBInterface.h +++ b/third_party/WebKit/Source/modules/webusb/USBInterface.h
@@ -30,7 +30,7 @@ size_t configuration_index, size_t interface_index); - const device::usb::blink::InterfaceInfo& Info() const; + const device::mojom::blink::UsbInterfaceInfo& Info() const; uint8_t interfaceNumber() const { return Info().interface_number; } USBAlternateInterface* alternate() const;
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py index 2b910bc..670b728 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py
@@ -56,9 +56,6 @@ def communicate(self, *_): return (self.stdout.getvalue(), self.stderr.getvalue()) - def kill(self): - return - class MockExecutive(object): PIPE = 'MOCK PIPE'
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py index 6b261b5..6a792fc 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
@@ -325,8 +325,6 @@ self._delete_dirs(results_directories[:-self.ARCHIVED_RESULTS_LIMIT]) def _set_up_run(self, test_names): - exit_code = self._port.setup_test_run() - self._printer.write_update("Checking build ...") if self._options.build: exit_code = self._port.check_build(self._needs_servers(test_names), self._printer) @@ -334,6 +332,13 @@ _log.error("Build check failed") return exit_code + # Check that the system dependencies (themes, fonts, ...) are correct. + if not self._options.nocheck_sys_deps: + self._printer.write_update("Checking system dependencies ...") + exit_code = self._port.check_sys_deps(self._needs_servers(test_names)) + if exit_code: + return exit_code + if self._options.clobber_old_results: self._clobber_old_results() elif self._filesystem.exists(self._results_directory): @@ -344,13 +349,7 @@ # Create the output directory if it doesn't already exist. self._port.host.filesystem.maybe_make_directory(self._results_directory) - # Check that the system dependencies (themes, fonts, ...) are correct. - if not self._options.nocheck_sys_deps: - self._printer.write_update("Checking system dependencies ...") - exit_code = self._port.check_sys_deps(self._needs_servers(test_names)) - if exit_code: - return exit_code - + self._port.setup_test_run() return exit_codes.OK_EXIT_STATUS def _run_tests(self, tests_to_run, tests_to_skip, repeat_each, iterations,
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux.py index da1121b..28c22b4 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux.py
@@ -65,7 +65,6 @@ if not self.get_option('disable_breakpad'): self._dump_reader = DumpReaderLinux(host, self._build_path()) self._original_home = None - self._xvfb_process = None def additional_driver_flag(self): flags = super(LinuxPort, self).additional_driver_flag() @@ -105,12 +104,10 @@ def setup_test_run(self): super(LinuxPort, self).setup_test_run() - self._start_xvfb() self._setup_dummy_home_dir() def clean_up_test_run(self): super(LinuxPort, self).clean_up_test_run() - self._stop_xvfb() self._clean_up_dummy_home_dir() # @@ -145,45 +142,6 @@ self._filesystem.rmtree(dummy_home) self.host.environ['HOME'] = self._original_home - def _start_xvfb(self): - display = self._find_display() - if not display: - _log.warn('Failed to find a free display to start Xvfb.') - return - - _log.info('Starting Xvfb with display "%s".', display) - self._xvfb_process = self.host.executive.popen( - ['Xvfb', display, '-screen', '0', '1280x800x24', '-ac', '-dpi', '96'], - stderr=self.host.executive.DEVNULL) - - # By setting DISPLAY here, the individual worker processes will - # get the right DISPLAY. Note, if this environment could be passed - # when creating workers, then we wouldn't need to modify DISPLAY here. - self.host.environ['DISPLAY'] = display - - # The poll() method will return None if the process has not terminated: - # https://docs.python.org/2/library/subprocess.html#subprocess.Popen.poll - if self._xvfb_process.poll() is not None: - _log.warn('Failed to start Xvfb on display "%s."', display) - - def _find_display(self): - """Tries to find a free X display, looping if necessary.""" - # The "xvfb-run" command uses :99 by default. - for display_number in range(99, 120): - display = ':%d' % display_number - exit_code = self.host.executive.run_command( - ['xdpyinfo', '-display', display], return_exit_code=True) - if exit_code == 1: - return display - return None - - def _stop_xvfb(self): - if not self._xvfb_process: - return - _log.debug('Killing Xvfb process pid %d.', self._xvfb_process.pid) - self._xvfb_process.kill() - self._xvfb_process.wait() - def _path_to_driver(self, target=None): binary_name = self.driver_name() return self._build_path_with_target(target, binary_name)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux_unittest.py index 9b6a25e5..fe363f7 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux_unittest.py
@@ -114,33 +114,3 @@ port.clean_up_test_run() self.assertEqual(port.host.environ['HOME'], '/home/user') self.assertFalse(port.host.filesystem.exists(temp_home_dir)) - - def test_setup_test_run_starts_xvfb(self): - port = self.make_port() - port.host.executive = MockExecutive(exit_code=1) - port.setup_test_run() - self.assertEqual( - port.host.executive.calls, - [ - ['xdpyinfo', '-display', ':99'], - ['Xvfb', ':99', '-screen', '0', '1280x800x24', '-ac', '-dpi', '96'], - ]) - env = port.setup_environ_for_server() - self.assertEqual(env['DISPLAY'], ':99') - - def test_setup_test_runs_finds_free_display(self): - port = self.make_port() - port.host.executive = MockExecutive( - run_command_fn=lambda args: 1 if ':102' in args else 0) - port.setup_test_run() - self.assertEqual( - port.host.executive.calls, - [ - ['xdpyinfo', '-display', ':99'], - ['xdpyinfo', '-display', ':100'], - ['xdpyinfo', '-display', ':101'], - ['xdpyinfo', '-display', ':102'], - ['Xvfb', ':102', '-screen', '0', '1280x800x24', '-ac', '-dpi', '96'], - ]) - env = port.setup_environ_for_server() - self.assertEqual(env['DISPLAY'], ':102')
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py index f1e4f7e..4760610 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py
@@ -20,7 +20,7 @@ def __init__(self, host, gh_user, gh_token, gerrit_user, gerrit_token, dry_run=False): self.host = host - self.wpt_github = WPTGitHub(host, gh_user, gh_token) + self.wpt_github = WPTGitHub(host, gh_user, gh_token, pr_history_window=PR_HISTORY_WINDOW) self.gerrit = Gerrit(self.host, gerrit_user, gerrit_token) @@ -33,13 +33,12 @@ The exporter will look in chronological order at every commit in Chromium. """ - pull_requests = self.wpt_github.all_pull_requests(limit=PR_HISTORY_WINDOW) open_gerrit_cls = self.gerrit.query_open_cls() - self.process_gerrit_cls(open_gerrit_cls, pull_requests) + self.process_gerrit_cls(open_gerrit_cls) exportable_commits = self.get_exportable_commits(limit=COMMIT_HISTORY_WINDOW) for exportable_commit in exportable_commits: - pull_request = self.pr_with_position(exportable_commit.position, pull_requests) + pull_request = self.wpt_github.pr_with_position(exportable_commit.position) if pull_request: if pull_request.state == 'open': self.merge_pull_request(pull_request) @@ -49,7 +48,7 @@ else: self.create_pull_request(exportable_commit) - def process_gerrit_cls(self, gerrit_cls, pull_requests): + def process_gerrit_cls(self, gerrit_cls): """Iterates through Gerrit CLs and prints their statuses. Right now this method does nothing. In the future it will create PRs for CLs and help @@ -60,7 +59,7 @@ _log.info('Found Gerrit in-flight CL: "%s" %s', cl['subject'], cl_url) # Check if CL already has a corresponding PR - pull_request = self.pr_with_change_id(cl['change_id'], pull_requests) + pull_request = self.wpt_github.pr_with_change_id(cl['change_id']) if pull_request: pr_url = '{}pull/{}'.format(WPT_URL, pull_request.number) @@ -68,25 +67,6 @@ else: _log.info('No in-flight PR found for CL.') - def pr_with_position(self, position, pull_requests): - for pull_request in pull_requests: - pr_commit_position = self._extract_metadata('Cr-Commit-Position: ', pull_request.body) - if position == pr_commit_position: - return pull_request - return None - - def pr_with_change_id(self, target_change_id, pull_requests): - for pull_request in pull_requests: - change_id = self._extract_metadata('Change-Id: ', pull_request.body) - if change_id == target_change_id: - return pull_request - return None - - def _extract_metadata(self, tag, commit_body): - for line in commit_body.splitlines(): - if line.startswith(tag): - return line[len(tag):] - return None def get_exportable_commits(self, limit): return exportable_commits_over_last_n_commits(limit, self.host, self.local_wpt)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter_unittest.py index c4634c4..73b01179 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter_unittest.py
@@ -36,7 +36,11 @@ ] test_exporter.run() - self.assertEqual(test_exporter.wpt_github.calls, ['all_pull_requests']) + self.assertEqual(test_exporter.wpt_github.calls, [ + 'pr_with_position', + 'pr_with_position', + 'pr_with_position', + ]) def test_creates_pull_request_for_all_exportable_commits(self): host = MockHost() @@ -71,9 +75,11 @@ test_exporter.run() self.assertEqual(test_exporter.wpt_github.calls, [ - 'all_pull_requests', + 'pr_with_position', 'create_pr', + 'pr_with_position', 'create_pr', + 'pr_with_position', 'create_pr', ]) self.assertEqual(test_exporter.wpt_github.pull_requests_created, [ @@ -122,10 +128,13 @@ ] test_exporter.run() self.assertEqual(test_exporter.wpt_github.calls, [ - 'all_pull_requests', + 'pr_with_position', 'get_pr_branch', 'merge_pull_request', + 'pr_with_position', 'create_pr', + 'pr_with_position', + 'pr_with_position', 'get_pr_branch', 'merge_pull_request', 'delete_remote_branch',
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py index 86d09b4..26ce818 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
@@ -361,12 +361,9 @@ try_results = self.git_cl.wait_for_try_jobs( poll_delay_seconds=POLL_DELAY_SECONDS, timeout_seconds=TIMEOUT_SECONDS) - if not try_results: - _log.error('No try job results.') - self.git_cl.run(['set-close']) - return False + _log.info('Try results: %s', try_results) - # If the CQ passes, then the issue will be closed. + # If the CQ passed, then the issue will be closed already. status = self.git_cl.run(['status' '--field', 'status']).strip() _log.info('CL status: "%s"', status) if status not in ('lgtm', 'closed'):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py index 365e65b..2c4c37ca 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py
@@ -8,6 +8,7 @@ import urllib2 from collections import namedtuple +from webkitpy.common.memoized import memoized _log = logging.getLogger(__name__) @@ -17,12 +18,14 @@ class WPTGitHub(object): - def __init__(self, host, user, token): + def __init__(self, host, user, token, pr_history_window=30): self.host = host self.user = user self.token = token assert self.user and self.token + self._pr_history_window = pr_history_window + def auth_token(self): return base64.b64encode('{}:{}'.format(self.user, self.token)) @@ -94,9 +97,14 @@ body=item['body'], state=item['state']) - def all_pull_requests(self, limit=30): - assert limit <= 100, 'Maximum GitHub page size exceeded.' - path = '/search/issues?q=repo:w3c/web-platform-tests%20type:pr%20label:{}&page=1&per_page={}'.format(EXPORT_LABEL, limit) + @memoized + def all_pull_requests(self): + # TODO(jeffcarp): Add pagination to fetch >99 PRs + assert self._pr_history_window <= 100, 'Maximum GitHub page size exceeded.' + path = ('/search/issues' + '?q=repo:w3c/web-platform-tests%20type:pr%20label:{}' + '&page=1' + '&per_page={}').format(EXPORT_LABEL, self._pr_history_window) data, status_code = self.request(path, method='GET') if status_code == 200: return [self.make_pr_from_item(item) for item in data['items']] @@ -143,6 +151,27 @@ return data + def pr_with_change_id(self, target_change_id): + for pull_request in self.all_pull_requests(): + change_id = self._extract_metadata('Change-Id: ', pull_request.body) + if change_id == target_change_id: + return pull_request + return None + + def pr_with_position(self, position): + for pull_request in self.all_pull_requests(): + pr_commit_position = self._extract_metadata('Cr-Commit-Position: ', pull_request.body) + if position == pr_commit_position: + return pull_request + return None + + def _extract_metadata(self, tag, commit_body): + for line in commit_body.splitlines(): + if line.startswith(tag): + return line[len(tag):] + return None + + class MergeError(Exception): """An error specifically for when a PR cannot be merged.
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github_mock.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github_mock.py index 54f2ac1ef..69abba4 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github_mock.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github_mock.py
@@ -49,3 +49,15 @@ def get_pr_branch(self, number): self.calls.append('get_pr_branch') return 'fake branch for PR {}'.format(number) + + def pr_with_position(self, position): + self.calls.append('pr_with_position') + for pr in self.pull_requests: + if position in pr.body: + return pr + + def pr_with_change_id(self, change_id): + self.calls.append('pr_with_change_id') + for pr in self.pull_requests: + if change_id in pr.body: + return pr
diff --git a/tools/gn/bin/roll_gn.py b/tools/gn/bin/roll_gn.py index 91dad7e..7436f4ec 100755 --- a/tools/gn/bin/roll_gn.py +++ b/tools/gn/bin/roll_gn.py
@@ -186,8 +186,7 @@ print('Checking build') results = self.CheckBuild() - while (len(results) < 3 or - any(r['state'] in ('pending', 'started') + while (any(r['state'] in ('pending', 'started') for r in results.values())): print() print('Sleeping for 30 seconds') @@ -228,16 +227,18 @@ rpc_server = upload.GetRpcServer(CODE_REVIEW_SERVER, email) try: props = json.loads(rpc_server.Send('/api/%d' % issue)) - except Exception as _e: - raise + except Exception as e: + print('Failed to load patch data: %s' % e) + return {} patchset = int(props['patchsets'][-1]) try: try_job_results = json.loads(rpc_server.Send( '/api/%d/%d/try_job_results' % (issue, patchset))) - except Exception as _e: - raise + except Exception as e: + print('Failed to load try job results: %s' % e) + return {} if not try_job_results: print('No try jobs found on most recent patchset') @@ -266,8 +267,15 @@ results.setdefault(platform, {'build': -1, 'sha1': '', 'url': url_str}) if state == 'success': - jsurl = url_str.replace('/builders/', '/json/builders/') - fp = urllib2.urlopen(jsurl) + jsurl = url_str.replace('http://build.chromium.org/', + 'http://chrome-build-extract.appspot.com/') + jsurl = jsurl + '?json=1' + try: + fp = urllib2.urlopen(jsurl) + except urllib2.HTTPError as e: + print('Failed to open %s: %s' % (jsurl, e)) + return {} + js = json.loads(fp.read()) fp.close() sha1_step_name = 'gn sha1' @@ -460,7 +468,7 @@ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, cwd=(cwd or self.chromium_src_dir)) out, err = proc.communicate() - return proc.returncode, out, err + return proc.returncode, out or '', err or '' if __name__ == '__main__':
diff --git a/tools/gn/command_path.cc b/tools/gn/command_path.cc index f6a4e69a..daa22004 100644 --- a/tools/gn/command_path.cc +++ b/tools/gn/command_path.cc
@@ -403,10 +403,10 @@ stats.total_paths(), path_annotation), DECORATION_YELLOW); if (!options.public_only) { - OutputString(base::StringPrintf(" %d of them are public.\n", - stats.public_paths)); + OutputString( + base::StringPrintf(" %d of them are public.", stats.public_paths)); } - OutputString("Use --all to print all paths.\n"); + OutputString("\nUse --all to print all paths.\n"); } } return 0;
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 4f1ec4167..97b63fd 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -30179,6 +30179,17 @@ </summary> </histogram> +<histogram base="true" name="MobileDownload.ResumptionsCount"> + <owner>qinmin@chromium.org</owner> + <summary> + Android: Records the number of resumptions for a download by resumption + type. For all resumption types, this is recorded when a download is + finished, completed or cancelled. For automatic resumptions, it is also + recorded when user manually resumes the download to clear the auto retry + count. + </summary> +</histogram> + <histogram name="MobileFre.Progress" enum="MobileFreProgress"> <owner>gogerald@chromium.org</owner> <summary> @@ -74346,6 +74357,24 @@ </summary> </histogram> +<histogram name="Translate.LanguageDetectionConflict" + enum="EnCrossCLD3LanguageCode"> + <owner>yyushkina@chromium.org</owner> + <summary> + This metric logs CLD3-detected languages for pages that specify a + conflicting English language in their markup. In these cases, we must decide + on a language source to favor. + + Bucket names are of the form "x,y", where x is the common English + language code specified in the page markup (or "other" if the + English language code is uncommon), and y is the CLD3-detected language. + + This histogram only logs detection conflicts. Hence, "matching" + buckets (e.g. "en,en", "en-AU,en") will never be + populated. + </summary> +</histogram> + <histogram name="Translate.LanguageDetectionTiming" enum="TranslateLanguageDetectionTiming"> <owner>andrewhayden@chromium.org</owner> @@ -90365,6 +90394,1014 @@ <int value="36" label="windows-874"/> </enum> +<enum name="EnCrossCLD3LanguageCode" type="int"> + <summary> + Hash values for strings of the form "x,y", where x is either a + common English language BCP47 code or "other", and y is a language + code supported by CLD3. Used to report conflicts between HTML language tags + and CLD3 language detection. + </summary> + <int value="-2124369431" label="en-IN,sk"/> + <int value="-2116468187" label="en-GB,lv"/> + <int value="-2113557848" label="en-NZ,zh-Latn"/> + <int value="-2111057442" label="en-AU,eu"/> + <int value="-2109862064" label="en-GB,co"/> + <int value="-2107569712" label="en-US,mn"/> + <int value="-2104732247" label="en-GB,kn"/> + <int value="-2095143481" label="en-IN,bg-Latn"/> + <int value="-2093238145" label="en-NZ,ru"/> + <int value="-2092755960" label="en-GB,pt"/> + <int value="-2086002903" label="en-GB,iw"/> + <int value="-2083244205" label="en-ZA,is"/> + <int value="-2079128291" label="en-CA,pt"/> + <int value="-2074513011" label="en-AU,hr"/> + <int value="-2070318208" label="en-ZA,zh-Latn"/> + <int value="-2067222357" label="en-GB,eu"/> + <int value="-2064855342" label="en-CA,uz"/> + <int value="-2058651483" label="en-GB,tg"/> + <int value="-2056749569" label="other,su"/> + <int value="-2050363884" label="en,ps"/> + <int value="-2048564427" label="en-US,ceb"/> + <int value="-2048426575" label="en,ne"/> + <int value="-2044913616" label="en-AU,zu"/> + <int value="-2043655475" label="en-IN,sr"/> + <int value="-2040518330" label="en-US,is"/> + <int value="-2038890712" label="en,is"/> + <int value="-2032827489" label="en-US,bn"/> + <int value="-2031322000" label="en-US,eo"/> + <int value="-2029035680" label="en-ZA,ny"/> + <int value="-2028938496" label="en-GB,no"/> + <int value="-2024091344" label="en-ZA,no"/> + <int value="-2023903582" label="en,de"/> + <int value="-2022075322" label="en-ZA,iw"/> + <int value="-2016934602" label="other,fi"/> + <int value="-2013534235" label="en-IN,cs"/> + <int value="-2012682082" label="en,so"/> + <int value="-2009823796" label="other,en"/> + <int value="-2006294893" label="en-ZA,mi"/> + <int value="-2003513780" label="en-CA,ru-Latn"/> + <int value="-2000117527" label="en-AU,sl"/> + <int value="-1997617048" label="other,yi"/> + <int value="-1993954446" label="en-AU,ms"/> + <int value="-1985817663" label="en,km"/> + <int value="-1982939971" label="en,ku"/> + <int value="-1981060640" label="en-NZ,pa"/> + <int value="-1969945476" label="en,kk"/> + <int value="-1968768037" label="en,be"/> + <int value="-1944914110" label="en-CA,tr"/> + <int value="-1944124391" label="en-NZ,lt"/> + <int value="-1938634095" label="en-AU,ur"/> + <int value="-1937334700" label="en-CA,fil"/> + <int value="-1936297420" label="en-ZA,th"/> + <int value="-1912635719" label="en-IN,hr"/> + <int value="-1911121699" label="en-NZ,iw"/> + <int value="-1907190634" label="en-GB,sk"/> + <int value="-1907045054" label="other,ca"/> + <int value="-1902746237" label="en,mr"/> + <int value="-1897496014" label="en-NZ,ja"/> + <int value="-1896281532" label="en-GB,mr"/> + <int value="-1894796887" label="other,uz"/> + <int value="-1893186684" label="en-CA,sq"/> + <int value="-1888655601" label="en-AU,hmn"/> + <int value="-1879363959" label="en-CA,el-Latn"/> + <int value="-1873453878" label="en-US,ht"/> + <int value="-1869637891" label="en-CA,te"/> + <int value="-1868526533" label="en,zu"/> + <int value="-1864675515" label="en-NZ,mr"/> + <int value="-1864404923" label="en-NZ,haw"/> + <int value="-1863564796" label="en-AU,mg"/> + <int value="-1862175609" label="en-US,az"/> + <int value="-1860719141" label="en-GB,ja-Latn"/> + <int value="-1858480480" label="en,su"/> + <int value="-1848050043" label="en-AU,zh"/> + <int value="-1844339140" label="en-NZ,bg"/> + <int value="-1837172785" label="en,fy"/> + <int value="-1830369415" label="en-AU,sn"/> + <int value="-1820239738" label="en-ZA,so"/> + <int value="-1814241674" label="en-IN,gu"/> + <int value="-1787888508" label="en-NZ,gd"/> + <int value="-1786621097" label="other,sd"/> + <int value="-1785254801" label="en-AU,fr"/> + <int value="-1772875851" label="en-IN,zu"/> + <int value="-1771902729" label="en,ar"/> + <int value="-1769596689" label="en-AU,si"/> + <int value="-1759968348" label="en,und"/> + <int value="-1751988881" label="en-AU,ta"/> + <int value="-1747832209" label="en-NZ,uz"/> + <int value="-1729190557" label="en-ZA,ig"/> + <int value="-1728146239" label="en,ta"/> + <int value="-1717781349" label="en-GB,st"/> + <int value="-1713672416" label="en-CA,sv"/> + <int value="-1712698203" label="en-ZA,sd"/> + <int value="-1708467253" label="en-CA,unknown"/> + <int value="-1705664959" label="en-US,yo"/> + <int value="-1705158339" label="en-NZ,ka"/> + <int value="-1704290230" label="en-AU,be"/> + <int value="-1698540007" label="en-GB,ny"/> + <int value="-1698336319" label="en-NZ,unknown"/> + <int value="-1694265672" label="en-ZA,sn"/> + <int value="-1694050683" label="en,tg"/> + <int value="-1691613931" label="other,ja-Latn"/> + <int value="-1684149366" label="en-CA,mt"/> + <int value="-1665646354" label="en-ZA,fil"/> + <int value="-1664646506" label="en-IN,ar"/> + <int value="-1652807707" label="en-GB,mt"/> + <int value="-1647274992" label="en-IN,ta"/> + <int value="-1647174837" label="en-US,ps"/> + <int value="-1634052364" label="en-NZ,ml"/> + <int value="-1633713836" label="en-IN,sq"/> + <int value="-1633251487" label="en-US,jv"/> + <int value="-1630949789" label="en-NZ,ca"/> + <int value="-1630270728" label="en-NZ,de"/> + <int value="-1628320800" label="en-CA,ko"/> + <int value="-1623073820" label="en,ru"/> + <int value="-1623056651" label="en-ZA,sq"/> + <int value="-1616849585" label="en-AU,co"/> + <int value="-1615127115" label="en-AU,cy"/> + <int value="-1611671963" label="en-IN,lb"/> + <int value="-1611623912" label="other,fil"/> + <int value="-1607077769" label="en-GB,xh"/> + <int value="-1604279981" label="en-IN,hi-Latn"/> + <int value="-1596875594" label="other,ky"/> + <int value="-1592890693" label="en-GB,ceb"/> + <int value="-1592738004" label="en-CA,sr"/> + <int value="-1589728436" label="other,lo"/> + <int value="-1570014714" label="other,iw"/> + <int value="-1564093181" label="en-GB,el"/> + <int value="-1556572633" label="en-CA,am"/> + <int value="-1554730193" label="en-US,mi"/> + <int value="-1552949884" label="en-US,mg"/> + <int value="-1549687917" label="en-US,iw"/> + <int value="-1544924120" label="en,tr"/> + <int value="-1522200631" label="en-NZ,ht"/> + <int value="-1520721572" label="en-US,my"/> + <int value="-1520389273" label="other,da"/> + <int value="-1516606179" label="en-ZA,ko"/> + <int value="-1514674113" label="en,th"/> + <int value="-1514217919" label="en-AU,uz"/> + <int value="-1514197491" label="en-AU,ka"/> + <int value="-1513794730" label="en-US,ca"/> + <int value="-1511712239" label="en-GB,sl"/> + <int value="-1507434828" label="en-IN,hmn"/> + <int value="-1498956183" label="en-CA,sk"/> + <int value="-1496658087" label="en-NZ,cy"/> + <int value="-1486809235" label="en-IN,mt"/> + <int value="-1479227188" label="en-AU,ky"/> + <int value="-1476856301" label="en-US,lb"/> + <int value="-1469669231" label="en-GB,sq"/> + <int value="-1468074483" label="en-CA,af"/> + <int value="-1462099981" label="en-IN,jv"/> + <int value="-1457647003" label="en-NZ,eu"/> + <int value="-1450386960" label="en-CA,nl"/> + <int value="-1446631159" label="en-NZ,el-Latn"/> + <int value="-1422491922" label="en-US,ka"/> + <int value="-1420298629" label="en-ZA,fy"/> + <int value="-1416903380" label="en-ZA,be"/> + <int value="-1403910050" label="en-ZA,pl"/> + <int value="-1402845617" label="en-GB,fr"/> + <int value="-1399351496" label="en-ZA,gl"/> + <int value="-1398520733" label="en-US,ro"/> + <int value="-1390125648" label="en-CA,no"/> + <int value="-1388486986" label="en-CA,eo"/> + <int value="-1385835372" label="other,ta"/> + <int value="-1383130458" label="en-US,gd"/> + <int value="-1382832620" label="en-AU,mr"/> + <int value="-1382630626" label="en-US,hi"/> + <int value="-1376708570" label="en-GB,lb"/> + <int value="-1372289390" label="en-GB,nl"/> + <int value="-1370590322" label="en,pt"/> + <int value="-1369722574" label="en-GB,ig"/> + <int value="-1367992379" label="en-ZA,it"/> + <int value="-1366543906" label="en-AU,unknown"/> + <int value="-1360539588" label="en-ZA,mk"/> + <int value="-1357419592" label="en-CA,ig"/> + <int value="-1353345099" label="en-CA,cs"/> + <int value="-1346503932" label="en,fa"/> + <int value="-1346156856" label="en-IN,pl"/> + <int value="-1343690599" label="en-CA,zh-Latn"/> + <int value="-1331214321" label="en-ZA,unknown"/> + <int value="-1329522963" label="other,sv"/> + <int value="-1324503751" label="other,hmn"/> + <int value="-1310042673" label="other,it"/> + <int value="-1309690314" label="other,nl"/> + <int value="-1301792573" label="en-US,pa"/> + <int value="-1298978218" label="en-ZA,ru"/> + <int value="-1298210853" label="en-AU,ru-Latn"/> + <int value="-1295927056" label="en-ZA,nl"/> + <int value="-1292209370" label="en-AU,hi"/> + <int value="-1290497188" label="en-GB,ru-Latn"/> + <int value="-1290070339" label="en-AU,ja"/> + <int value="-1283031458" label="en-AU,ht"/> + <int value="-1281458280" label="en,el-Latn"/> + <int value="-1278516305" label="en-US,ml"/> + <int value="-1263108473" label="en-IN,ru-Latn"/> + <int value="-1259042225" label="other,pl"/> + <int value="-1238995224" label="en-US,hy"/> + <int value="-1238591345" label="en-NZ,kk"/> + <int value="-1233706328" label="en,en"/> + <int value="-1228999462" label="en-AU,es"/> + <int value="-1227601505" label="en-US,ky"/> + <int value="-1224781996" label="en-IN,te"/> + <int value="-1224753420" label="en-US,fy"/> + <int value="-1219920190" label="en-ZA,hmn"/> + <int value="-1217746309" label="en-GB,hmn"/> + <int value="-1213938554" label="en-AU,ne"/> + <int value="-1213583239" label="en,da"/> + <int value="-1209455268" label="en-IN,la"/> + <int value="-1208444202" label="en-US,co"/> + <int value="-1207597587" label="other,bs"/> + <int value="-1196089827" label="en-GB,te"/> + <int value="-1194882730" label="en-CA,bs"/> + <int value="-1182285832" label="en-AU,ar"/> + <int value="-1180706012" label="en-US,ku"/> + <int value="-1176858165" label="en-NZ,es"/> + <int value="-1161664630" label="en-CA,so"/> + <int value="-1150612958" label="en-GB,ml"/> + <int value="-1149861387" label="other,el-Latn"/> + <int value="-1146067341" label="en-US,fil"/> + <int value="-1134207512" label="en-NZ,lb"/> + <int value="-1133970848" label="en-CA,ht"/> + <int value="-1131269514" label="en-NZ,km"/> + <int value="-1122870775" label="en-IN,ga"/> + <int value="-1119552856" label="en-GB,hy"/> + <int value="-1118006347" label="en-NZ,su"/> + <int value="-1111896399" label="en-ZA,cs"/> + <int value="-1111659918" label="en-ZA,bn"/> + <int value="-1109349887" label="en-US,bs"/> + <int value="-1104794613" label="en-ZA,eo"/> + <int value="-1102200262" label="en-AU,bg"/> + <int value="-1087479434" label="en-NZ,gu"/> + <int value="-1086494101" label="en-IN,en"/> + <int value="-1083832142" label="en-ZA,fr"/> + <int value="-1082841040" label="en-AU,no"/> + <int value="-1078817533" label="en-IN,ja-Latn"/> + <int value="-1061831796" label="other,sw"/> + <int value="-1060276304" label="en-AU,ml"/> + <int value="-1058009879" label="en-AU,ku"/> + <int value="-1049361969" label="en-CA,yo"/> + <int value="-1048166271" label="en-IN,ceb"/> + <int value="-1042239713" label="en-ZA,ne"/> + <int value="-1041196877" label="en-NZ,lo"/> + <int value="-1039980655" label="en-GB,et"/> + <int value="-1039749771" label="en-GB,so"/> + <int value="-1038109255" label="en,mk"/> + <int value="-1035837896" label="en-AU,su"/> + <int value="-1033591490" label="en-AU,sv"/> + <int value="-1030469686" label="en-IN,haw"/> + <int value="-1028065279" label="en-GB,und"/> + <int value="-1026066097" label="en-IN,vi"/> + <int value="-1026028202" label="other,fr"/> + <int value="-1014607888" label="en-GB,ps"/> + <int value="-1009703136" label="en-US,gu"/> + <int value="-999407605" label="en-AU,sr"/> + <int value="-998551972" label="other,st"/> + <int value="-997491813" label="other,no"/> + <int value="-997355335" label="en-IN,hy"/> + <int value="-996302242" label="en-US,sn"/> + <int value="-994546623" label="en,gd"/> + <int value="-981430978" label="en-IN,zh-Latn"/> + <int value="-980040557" label="en,ky"/> + <int value="-973176337" label="en-ZA,am"/> + <int value="-969434649" label="en-CA,ro"/> + <int value="-965565591" label="en-ZA,bg"/> + <int value="-963786426" label="en-GB,ha"/> + <int value="-961625891" label="en-NZ,et"/> + <int value="-955553888" label="en-ZA,mg"/> + <int value="-952843725" label="en-US,mk"/> + <int value="-949401757" label="en,my"/> + <int value="-942062362" label="en-US,zh-Latn"/> + <int value="-931047164" label="en-IN,cy"/> + <int value="-922858301" label="en-GB,gu"/> + <int value="-921098649" label="en-CA,ja-Latn"/> + <int value="-919289357" label="en-AU,vi"/> + <int value="-918912162" label="en-CA,co"/> + <int value="-916808527" label="other,ko"/> + <int value="-911043903" label="en,fil"/> + <int value="-906245796" label="en-IN,su"/> + <int value="-899190372" label="en-GB,unknown"/> + <int value="-897318896" label="en-IN,af"/> + <int value="-894681263" label="en-CA,fy"/> + <int value="-888512967" label="other,kk"/> + <int value="-888161970" label="en-ZA,az"/> + <int value="-884692633" label="en-GB,ru"/> + <int value="-867330946" label="en-GB,sm"/> + <int value="-858362606" label="en-IN,nl"/> + <int value="-856399552" label="en-ZA,yi"/> + <int value="-855471302" label="en-US,ta"/> + <int value="-843023273" label="en-ZA,eu"/> + <int value="-836893384" label="en-AU,xh"/> + <int value="-836276118" label="en-ZA,my"/> + <int value="-832538906" label="en-ZA,el-Latn"/> + <int value="-829280752" label="en-US,es"/> + <int value="-825403216" label="other,ar"/> + <int value="-822848490" label="en-IN,mn"/> + <int value="-821693819" label="en-GB,ms"/> + <int value="-815159881" label="other,pa"/> + <int value="-809183331" label="en-ZA,ga"/> + <int value="-807570056" label="en-CA,yi"/> + <int value="-804692123" label="en-NZ,fr"/> + <int value="-802011698" label="en-CA,ka"/> + <int value="-800653639" label="en-NZ,ny"/> + <int value="-799944497" label="en-IN,ml"/> + <int value="-786069036" label="en,hy"/> + <int value="-781392865" label="en-AU,fy"/> + <int value="-774741229" label="en-US,uk"/> + <int value="-774705893" label="en,ru-Latn"/> + <int value="-771415808" label="en-NZ,sm"/> + <int value="-770599199" label="en-NZ,la"/> + <int value="-769370804" label="en-ZA,ht"/> + <int value="-766020458" label="en,sl"/> + <int value="-761784084" label="other,si"/> + <int value="-755296599" label="en-AU,ca"/> + <int value="-749134072" label="en-CA,be"/> + <int value="-747589726" label="en-CA,pl"/> + <int value="-746521712" label="en-AU,te"/> + <int value="-730553903" label="en-IN,st"/> + <int value="-718567737" label="en,uk"/> + <int value="-712484664" label="en-NZ,mn"/> + <int value="-711855661" label="en-US,el-Latn"/> + <int value="-703823200" label="en-US,sm"/> + <int value="-697784898" label="en-US,sd"/> + <int value="-693708098" label="en-IN,hu"/> + <int value="-689084995" label="en-AU,nl"/> + <int value="-687121797" label="en-IN,ms"/> + <int value="-683936001" label="en-GB,fil"/> + <int value="-681691326" label="en-IN,eu"/> + <int value="-677909491" label="other,de"/> + <int value="-664749191" label="en,zh-Latn"/> + <int value="-664666756" label="en-NZ,yi"/> + <int value="-659037096" label="en-CA,az"/> + <int value="-653328792" label="en,la"/> + <int value="-651792270" label="en-CA,ga"/> + <int value="-647724785" label="en-IN,hi"/> + <int value="-640995328" label="en-NZ,bn"/> + <int value="-629813533" label="en-IN,kn"/> + <int value="-618249296" label="en-IN,bg"/> + <int value="-615263868" label="en-GB,gl"/> + <int value="-614537549" label="en-AU,mn"/> + <int value="-608103664" label="en-CA,es"/> + <int value="-599897624" label="en-IN,tr"/> + <int value="-580470151" label="en-IN,sm"/> + <int value="-579152612" label="en-ZA,id"/> + <int value="-578031600" label="en,sk"/> + <int value="-576525627" label="en-AU,ps"/> + <int value="-569450071" label="other,ur"/> + <int value="-564888613" label="en-IN,eo"/> + <int value="-562158532" label="other,zh-Latn"/> + <int value="-560384338" label="en-CA,sd"/> + <int value="-557565099" label="en-NZ,ha"/> + <int value="-556698502" label="en-GB,pa"/> + <int value="-555419731" label="en-US,gl"/> + <int value="-552151539" label="en-AU,fi"/> + <int value="-548315734" label="en-IN,ka"/> + <int value="-544980397" label="en-AU,mt"/> + <int value="-542018328" label="other,es"/> + <int value="-534482286" label="en-ZA,ro"/> + <int value="-533872798" label="en-AU,zh-Latn"/> + <int value="-533834685" label="en-IN,de"/> + <int value="-522871017" label="en-ZA,lv"/> + <int value="-519390252" label="en-GB,hi-Latn"/> + <int value="-512294090" label="en,hr"/> + <int value="-506627221" label="en-IN,si"/> + <int value="-505475005" label="en-ZA,et"/> + <int value="-496363418" label="en-NZ,mk"/> + <int value="-495925829" label="en-GB,cy"/> + <int value="-494116460" label="en-AU,yo"/> + <int value="-492538502" label="en-ZA,lo"/> + <int value="-489487792" label="en-NZ,hi-Latn"/> + <int value="-488070282" label="en-NZ,sd"/> + <int value="-484244598" label="other,sk"/> + <int value="-479580786" label="en-GB,mn"/> + <int value="-477712301" label="en-CA,ru"/> + <int value="-473350786" label="en-AU,lo"/> + <int value="-469999914" label="en-GB,la"/> + <int value="-469484616" label="en-IN,co"/> + <int value="-464923601" label="en-US,mt"/> + <int value="-463472731" label="other,sq"/> + <int value="-462215397" label="en-CA,lb"/> + <int value="-460414518" label="en-US,la"/> + <int value="-449171923" label="en-IN,mk"/> + <int value="-438919066" label="en-AU,ru"/> + <int value="-437634847" label="other,ku"/> + <int value="-429170059" label="en-ZA,jv"/> + <int value="-428711284" label="other,hr"/> + <int value="-426218528" label="en-US,lt"/> + <int value="-419753035" label="en-US,lo"/> + <int value="-418116563" label="en-AU,so"/> + <int value="-416557773" label="en-IN,km"/> + <int value="-409223124" label="en-NZ,cs"/> + <int value="-408820412" label="en-IN,no"/> + <int value="-406936471" label="en,mi"/> + <int value="-404916241" label="en-GB,ne"/> + <int value="-403948453" label="en-IN,lv"/> + <int value="-398623564" label="en-GB,id"/> + <int value="-396833557" label="en-AU,ig"/> + <int value="-396028589" label="en,hmn"/> + <int value="-378569290" label="en-US,zh"/> + <int value="-368423696" label="en,uz"/> + <int value="-366405340" label="en,ko"/> + <int value="-362116022" label="en-US,ar"/> + <int value="-358433124" label="en-ZA,en"/> + <int value="-356540717" label="en-ZA,ml"/> + <int value="-355403459" label="en-NZ,ne"/> + <int value="-354189899" label="en-US,lv"/> + <int value="-350618888" label="en,bs"/> + <int value="-348068803" label="en-US,el"/> + <int value="-347968268" label="en-IN,pa"/> + <int value="-344950263" label="en-US,sv"/> + <int value="-340173781" label="en,sw"/> + <int value="-337628003" label="en-ZA,xh"/> + <int value="-328800060" label="en-ZA,ceb"/> + <int value="-328614553" label="en-ZA,da"/> + <int value="-327839206" label="en-CA,is"/> + <int value="-318840877" label="en-NZ,yo"/> + <int value="-309531049" label="en,gu"/> + <int value="-308798721" label="en-IN,sl"/> + <int value="-307369173" label="en-US,hi-Latn"/> + <int value="-300476925" label="en,ml"/> + <int value="-291188106" label="en-GB,th"/> + <int value="-289299006" label="en-US,ny"/> + <int value="-286225855" label="en-ZA,sr"/> + <int value="-284562486" label="en-ZA,ky"/> + <int value="-279786682" label="en-US,und"/> + <int value="-273619891" label="en-CA,ne"/> + <int value="-266075643" label="en-CA,tg"/> + <int value="-244658645" label="en-CA,cy"/> + <int value="-243735299" label="en-AU,lt"/> + <int value="-238154724" label="en-US,ms"/> + <int value="-238083370" label="other,ka"/> + <int value="-236445557" label="en-US,ne"/> + <int value="-234681308" label="en,mt"/> + <int value="-227668781" label="en-IN,kk"/> + <int value="-226564202" label="en-AU,iw"/> + <int value="-212757062" label="en-ZA,mt"/> + <int value="-212529805" label="en-CA,de"/> + <int value="-210208396" label="en-IN,ky"/> + <int value="-195613326" label="en-US,xh"/> + <int value="-194304961" label="en-AU,ha"/> + <int value="-183211755" label="en-NZ,ga"/> + <int value="-180588871" label="other,uk"/> + <int value="-176562730" label="en-ZA,la"/> + <int value="-175945266" label="en-ZA,ta"/> + <int value="-175546622" label="en,ga"/> + <int value="-172830708" label="en-GB,fa"/> + <int value="-170360146" label="en-CA,fi"/> + <int value="-169367928" label="en-ZA,sw"/> + <int value="-158046757" label="en-CA,hu"/> + <int value="-157371194" label="en-ZA,hi-Latn"/> + <int value="-151899928" label="en-NZ,hi"/> + <int value="-147938422" label="en-IN,el"/> + <int value="-145185628" label="en-CA,ps"/> + <int value="-143554786" label="en-GB,si"/> + <int value="-129286720" label="en-IN,yo"/> + <int value="-127996003" label="en-GB,yi"/> + <int value="-126871272" label="en-CA,my"/> + <int value="-123482448" label="other,te"/> + <int value="-119609134" label="en-AU,my"/> + <int value="-116594264" label="en-IN,fr"/> + <int value="-111605959" label="en-IN,my"/> + <int value="-92573461" label="en-US,haw"/> + <int value="-82976780" label="en-NZ,und"/> + <int value="-78204086" label="en-IN,es"/> + <int value="-76540753" label="en-GB,ht"/> + <int value="-75045139" label="en-AU,haw"/> + <int value="-73112949" label="en-GB,be"/> + <int value="-72394213" label="other,vi"/> + <int value="-69623762" label="en-NZ,zh"/> + <int value="-69356326" label="other,id"/> + <int value="-56300824" label="en-CA,sw"/> + <int value="-53596266" label="other,bg"/> + <int value="-52394574" label="other,ru"/> + <int value="-50281907" label="en-GB,mi"/> + <int value="-39535324" label="en,yo"/> + <int value="-28950181" label="en,jv"/> + <int value="-26764693" label="other,ru-Latn"/> + <int value="-24388218" label="en-US,unknown"/> + <int value="-15862101" label="en-IN,et"/> + <int value="-15388410" label="en,lt"/> + <int value="-8240870" label="en-ZA,pa"/> + <int value="-7019923" label="en-ZA,sm"/> + <int value="-2212741" label="en-AU,az"/> + <int value="393297" label="other,eo"/> + <int value="571301" label="en-US,fi"/> + <int value="2586472" label="en,hi"/> + <int value="11142866" label="en-IN,gd"/> + <int value="12962928" label="en-US,hr"/> + <int value="32976640" label="en-IN,und"/> + <int value="34221237" label="other,haw"/> + <int value="34572536" label="en-NZ,bg-Latn"/> + <int value="35868033" label="other,mg"/> + <int value="37620184" label="en-AU,mk"/> + <int value="37790914" label="en-NZ,ko"/> + <int value="40545721" label="en-IN,ht"/> + <int value="41189157" label="other,hi"/> + <int value="42657077" label="en-IN,mr"/> + <int value="43554136" label="en-CA,zu"/> + <int value="46974212" label="en-US,et"/> + <int value="55397648" label="en-ZA,hr"/> + <int value="59721356" label="en,st"/> + <int value="61120844" label="other,gu"/> + <int value="61901143" label="en-CA,lo"/> + <int value="69561606" label="en-NZ,mt"/> + <int value="80248107" label="en-NZ,ky"/> + <int value="80343050" label="other,unknown"/> + <int value="96729755" label="en-IN,ig"/> + <int value="106556254" label="en-IN,fi"/> + <int value="106824120" label="other,ig"/> + <int value="109858538" label="other,kn"/> + <int value="110814535" label="en-US,sl"/> + <int value="111512557" label="en-CA,ca"/> + <int value="111639146" label="en-US,ko"/> + <int value="118312454" label="en,pl"/> + <int value="122516567" label="en-ZA,sk"/> + <int value="124014428" label="en-CA,uk"/> + <int value="125937660" label="en-US,de"/> + <int value="130279541" label="en-AU,hu"/> + <int value="131823616" label="en-CA,ur"/> + <int value="134776967" label="en-CA,sl"/> + <int value="137726805" label="en-NZ,el"/> + <int value="137743856" label="other,my"/> + <int value="138088365" label="en-AU,bn"/> + <int value="143906557" label="en,sq"/> + <int value="148633933" label="en-US,su"/> + <int value="149249801" label="en-ZA,vi"/> + <int value="149254673" label="en-NZ,hu"/> + <int value="159338274" label="en-CA,haw"/> + <int value="160108056" label="en-CA,th"/> + <int value="173175536" label="en-ZA,ur"/> + <int value="174638312" label="other,sr"/> + <int value="176692935" label="en-AU,en"/> + <int value="177507595" label="en-ZA,es"/> + <int value="179820951" label="en-CA,zh"/> + <int value="183621141" label="other,yo"/> + <int value="189106370" label="en-US,eu"/> + <int value="194694507" label="en-NZ,sq"/> + <int value="204011687" label="en-CA,ml"/> + <int value="206430050" label="en-GB,es"/> + <int value="210100759" label="en-CA,xh"/> + <int value="211459852" label="en,vi"/> + <int value="212244145" label="other,af"/> + <int value="217457619" label="en-CA,ha"/> + <int value="226603980" label="en-IN,it"/> + <int value="228447752" label="en-CA,gl"/> + <int value="229522242" label="en-AU,id"/> + <int value="231593443" label="en-CA,mg"/> + <int value="233491613" label="en-NZ,sl"/> + <int value="238615518" label="en-NZ,ru-Latn"/> + <int value="240447639" label="en-NZ,ig"/> + <int value="241686897" label="other,co"/> + <int value="248618927" label="en-AU,el-Latn"/> + <int value="255346854" label="en-GB,gd"/> + <int value="262272920" label="en,sm"/> + <int value="262946543" label="en-US,am"/> + <int value="264871477" label="en-CA,kn"/> + <int value="266556636" label="en-ZA,zh"/> + <int value="273592672" label="en,sv"/> + <int value="279930804" label="other,und"/> + <int value="281605263" label="en,ja"/> + <int value="297068506" label="en-AU,hi-Latn"/> + <int value="307890939" label="en-ZA,ka"/> + <int value="311580662" label="en-AU,pl"/> + <int value="314700048" label="en-GB,fy"/> + <int value="321957105" label="en-AU,fil"/> + <int value="330092459" label="en,no"/> + <int value="333750610" label="en-NZ,ur"/> + <int value="338185331" label="en,bg-Latn"/> + <int value="340118597" label="en-ZA,ms"/> + <int value="346399527" label="other,pt"/> + <int value="346807260" label="en-GB,az"/> + <int value="351405982" label="other,lb"/> + <int value="352829367" label="other,ro"/> + <int value="354495805" label="en-AU,ja-Latn"/> + <int value="360333241" label="en,pa"/> + <int value="360482886" label="other,km"/> + <int value="361147661" label="en-GB,ja"/> + <int value="369729502" label="en-IN,ur"/> + <int value="374070776" label="en-GB,yo"/> + <int value="382794171" label="other,az"/> + <int value="385029378" label="en-ZA,hu"/> + <int value="386122260" label="en,ig"/> + <int value="390230115" label="en,xh"/> + <int value="390230404" label="en-ZA,bg-Latn"/> + <int value="395804990" label="en-NZ,sk"/> + <int value="403914044" label="en-ZA,uz"/> + <int value="409408505" label="en-AU,lb"/> + <int value="413238463" label="other,mn"/> + <int value="415649361" label="en-US,th"/> + <int value="416845327" label="en-ZA,co"/> + <int value="421338918" label="other,mi"/> + <int value="425550335" label="en-US,cy"/> + <int value="426525808" label="en-IN,da"/> + <int value="427905069" label="en,bg"/> + <int value="428418059" label="en-US,hu"/> + <int value="433730304" label="other,sm"/> + <int value="435389133" label="en-ZA,hi"/> + <int value="435774878" label="en-ZA,lt"/> + <int value="438943486" label="en,sn"/> + <int value="441009234" label="en-AU,und"/> + <int value="446363395" label="en-NZ,is"/> + <int value="446396562" label="en-CA,en"/> + <int value="448777481" label="en-US,da"/> + <int value="453143797" label="en-IN,ru"/> + <int value="455023577" label="en-AU,kk"/> + <int value="464193252" label="en-GB,bn"/> + <int value="469426247" label="en-NZ,da"/> + <int value="470968744" label="en-IN,am"/> + <int value="471525594" label="en-GB,bg-Latn"/> + <int value="477790180" label="other,bn"/> + <int value="481497515" label="other,ga"/> + <int value="482150171" label="en-GB,uz"/> + <int value="484422880" label="en-IN,sw"/> + <int value="486304785" label="en-NZ,ar"/> + <int value="486576942" label="en-CA,et"/> + <int value="504950639" label="en-IN,pt"/> + <int value="507474490" label="other,mr"/> + <int value="511298624" label="en-AU,bg-Latn"/> + <int value="519370622" label="other,hi-Latn"/> + <int value="519539246" label="en-NZ,te"/> + <int value="523832586" label="en-ZA,ha"/> + <int value="527153503" label="en-AU,uk"/> + <int value="529364835" label="other,hu"/> + <int value="535527955" label="en-IN,ko"/> + <int value="539528919" label="en-GB,is"/> + <int value="549589790" label="en-IN,az"/> + <int value="550300686" label="en,yi"/> + <int value="559874907" label="en-ZA,lb"/> + <int value="571750049" label="en-CA,pa"/> + <int value="578680520" label="en-GB,vi"/> + <int value="584050776" label="other,ne"/> + <int value="586304261" label="en,fr"/> + <int value="586492233" label="en-ZA,haw"/> + <int value="595670153" label="other,be"/> + <int value="595917413" label="en-CA,id"/> + <int value="599526823" label="en-IN,ku"/> + <int value="605876339" label="other,lt"/> + <int value="612847367" label="en-ZA,te"/> + <int value="614830922" label="other,ml"/> + <int value="616504159" label="en-GB,jv"/> + <int value="621990796" label="other,sl"/> + <int value="624672740" label="en-GB,zh"/> + <int value="626970505" label="en,ht"/> + <int value="628097668" label="en-IN,sd"/> + <int value="640262038" label="en-AU,sm"/> + <int value="641686626" label="en-US,ru"/> + <int value="646613899" label="en-IN,sn"/> + <int value="647296114" label="en-US,ur"/> + <int value="648256160" label="other,gl"/> + <int value="648502016" label="en-CA,fr"/> + <int value="651467435" label="en-AU,pt"/> + <int value="653336951" label="en,bn"/> + <int value="659151888" label="en,unknown"/> + <int value="659781560" label="en-GB,eo"/> + <int value="661495710" label="en,am"/> + <int value="668031905" label="en,nl"/> + <int value="670118633" label="en-GB,ro"/> + <int value="672889168" label="en-NZ,sw"/> + <int value="676999142" label="other,ms"/> + <int value="678632750" label="other,ja"/> + <int value="680060380" label="en-US,yi"/> + <int value="680453726" label="en,hi-Latn"/> + <int value="682029315" label="other,tg"/> + <int value="683983274" label="en-IN,ha"/> + <int value="687124847" label="en,cs"/> + <int value="705544038" label="en-IN,ca"/> + <int value="712186903" label="en-IN,lo"/> + <int value="724168729" label="en-IN,fy"/> + <int value="737198162" label="en-GB,sd"/> + <int value="739427185" label="en-GB,bs"/> + <int value="744516660" label="en,gl"/> + <int value="756534358" label="en-IN,bn"/> + <int value="758976688" label="en-IN,gl"/> + <int value="759357339" label="en,sd"/> + <int value="762656539" label="en-US,ig"/> + <int value="794132649" label="en-IN,sv"/> + <int value="796385096" label="en-GB,bg"/> + <int value="796611332" label="en-ZA,kn"/> + <int value="798691984" label="en-US,ha"/> + <int value="799101140" label="en-IN,ny"/> + <int value="801133153" label="en-GB,mg"/> + <int value="804316451" label="other,el"/> + <int value="807787788" label="en-ZA,gd"/> + <int value="809250169" label="en-US,cs"/> + <int value="816096178" label="en-GB,my"/> + <int value="824645258" label="en-US,sk"/> + <int value="826558712" label="en-ZA,sv"/> + <int value="849084143" label="en,it"/> + <int value="850862273" label="en-AU,de"/> + <int value="853352499" label="other,so"/> + <int value="854823242" label="en-ZA,ku"/> + <int value="855074740" label="en-CA,el"/> + <int value="857152633" label="en-CA,hi"/> + <int value="857603803" label="other,et"/> + <int value="859133433" label="en-NZ,sn"/> + <int value="865348028" label="en,ha"/> + <int value="880686769" label="en-GB,ku"/> + <int value="880915916" label="other,ht"/> + <int value="882319904" label="en-CA,sn"/> + <int value="889210765" label="en-CA,gd"/> + <int value="899191103" label="en-CA,mr"/> + <int value="904203484" label="en-NZ,co"/> + <int value="906138796" label="en-US,bg-Latn"/> + <int value="909977985" label="en-GB,ga"/> + <int value="911105608" label="en-CA,lv"/> + <int value="912157886" label="en-NZ,ceb"/> + <int value="912705685" label="en-ZA,el"/> + <int value="918457519" label="en-NZ,sr"/> + <int value="923188761" label="en-US,bg"/> + <int value="923423627" label="en,mn"/> + <int value="926439457" label="en-IN,unknown"/> + <int value="928679325" label="en-CA,ny"/> + <int value="931138724" label="en,eu"/> + <int value="934631232" label="other,ny"/> + <int value="937631019" label="en-US,ru-Latn"/> + <int value="938838496" label="en-CA,hmn"/> + <int value="948185011" label="en-CA,lt"/> + <int value="955180290" label="en-CA,si"/> + <int value="956064637" label="en-ZA,af"/> + <int value="960562184" label="en-NZ,si"/> + <int value="965503536" label="en-CA,hr"/> + <int value="966547063" label="en-CA,iw"/> + <int value="967746332" label="en-NZ,ja-Latn"/> + <int value="973763517" label="en-US,sq"/> + <int value="974585410" label="en-IN,is"/> + <int value="977145120" label="other,la"/> + <int value="977677962" label="en-NZ,lv"/> + <int value="982872922" label="en-IN,mi"/> + <int value="987399566" label="en-ZA,mr"/> + <int value="990147394" label="other,gd"/> + <int value="991829124" label="en-AU,gu"/> + <int value="998803921" label="en-GB,fi"/> + <int value="1002420538" label="en-CA,fa"/> + <int value="1008823931" label="en-NZ,am"/> + <int value="1013384242" label="en-ZA,hy"/> + <int value="1015585848" label="en-CA,ku"/> + <int value="1017943799" label="en-ZA,tr"/> + <int value="1020968666" label="en-US,so"/> + <int value="1021819779" label="en-US,si"/> + <int value="1022348319" label="other,fy"/> + <int value="1022666993" label="en-IN,be"/> + <int value="1023969309" label="en-AU,pa"/> + <int value="1029598412" label="en-GB,hu"/> + <int value="1038405709" label="en-ZA,pt"/> + <int value="1041158278" label="other,zh"/> + <int value="1041314309" label="en-GB,sv"/> + <int value="1041843225" label="en-AU,mi"/> + <int value="1044512953" label="en-IN,bs"/> + <int value="1047774851" label="en-NZ,th"/> + <int value="1047990359" label="en-CA,st"/> + <int value="1055706381" label="other,mt"/> + <int value="1058027180" label="en-NZ,ps"/> + <int value="1062243141" label="en-AU,el"/> + <int value="1063843295" label="en-IN,el-Latn"/> + <int value="1070881406" label="en-IN,iw"/> + <int value="1072572125" label="en,az"/> + <int value="1076247598" label="en-NZ,uk"/> + <int value="1077340584" label="en-NZ,mi"/> + <int value="1078066471" label="en-NZ,my"/> + <int value="1086284012" label="other,th"/> + <int value="1088333377" label="en-NZ,fi"/> + <int value="1099612922" label="en-ZA,und"/> + <int value="1100066240" label="en-AU,gl"/> + <int value="1101277515" label="en-AU,bs"/> + <int value="1102196185" label="en-GB,zh-Latn"/> + <int value="1102359128" label="en,co"/> + <int value="1104996635" label="en-GB,ka"/> + <int value="1109268156" label="en-AU,sd"/> + <int value="1113936347" label="en-US,ga"/> + <int value="1116909928" label="en-ZA,km"/> + <int value="1128555043" label="en-NZ,be"/> + <int value="1135410106" label="en-CA,it"/> + <int value="1135936276" label="en,af"/> + <int value="1139383998" label="en,haw"/> + <int value="1155102742" label="en-AU,sq"/> + <int value="1163093350" label="en-ZA,ar"/> + <int value="1167163022" label="en-GB,kk"/> + <int value="1168246222" label="en-US,tg"/> + <int value="1169881078" label="en,id"/> + <int value="1170715716" label="en-ZA,zu"/> + <int value="1174248653" label="en-GB,zu"/> + <int value="1175423418" label="other,ha"/> + <int value="1175589237" label="en-IN,zh"/> + <int value="1175618948" label="en-US,no"/> + <int value="1178260016" label="en-AU,lv"/> + <int value="1178359238" label="en,hu"/> + <int value="1181212519" label="en,mg"/> + <int value="1182312689" label="other,lv"/> + <int value="1185020245" label="en-CA,mn"/> + <int value="1192415688" label="en-AU,ga"/> + <int value="1197096620" label="en-IN,fa"/> + <int value="1198326653" label="en-US,af"/> + <int value="1201895414" label="en,sr"/> + <int value="1204411090" label="en-GB,sr"/> + <int value="1206951812" label="en-NZ,en"/> + <int value="1207559379" label="other,ceb"/> + <int value="1207746876" label="en-GB,ar"/> + <int value="1210191695" label="en-GB,hr"/> + <int value="1210299740" label="en-US,fa"/> + <int value="1218130469" label="en-IN,yi"/> + <int value="1233341588" label="en-AU,da"/> + <int value="1239978088" label="en,el"/> + <int value="1256797102" label="en-ZA,fa"/> + <int value="1260927179" label="en-GB,ur"/> + <int value="1262922540" label="en-ZA,uk"/> + <int value="1264329857" label="en-NZ,tg"/> + <int value="1278539454" label="en-US,hmn"/> + <int value="1280510255" label="en-NZ,hr"/> + <int value="1280736521" label="en-ZA,sl"/> + <int value="1286376309" label="en-IN,xh"/> + <int value="1292870564" label="en-ZA,ru-Latn"/> + <int value="1300968709" label="en-GB,it"/> + <int value="1302667839" label="en-NZ,bs"/> + <int value="1306008814" label="en-NZ,pt"/> + <int value="1307519081" label="other,fa"/> + <int value="1310524684" label="en-AU,tg"/> + <int value="1311997351" label="en-NZ,ku"/> + <int value="1317436581" label="en,ka"/> + <int value="1326944743" label="en-AU,tr"/> + <int value="1329589180" label="en-NZ,zu"/> + <int value="1333183401" label="en,te"/> + <int value="1335991765" label="en-NZ,af"/> + <int value="1340188273" label="en,kn"/> + <int value="1344361345" label="en-ZA,ps"/> + <int value="1345672063" label="en-GB,lt"/> + <int value="1354542174" label="other,hy"/> + <int value="1354544720" label="en-CA,sm"/> + <int value="1366667779" label="en-AU,la"/> + <int value="1368223495" label="other,is"/> + <int value="1375141921" label="en-NZ,mg"/> + <int value="1375516436" label="other,jv"/> + <int value="1377425950" label="en-NZ,az"/> + <int value="1382586179" label="en-GB,ko"/> + <int value="1384498167" label="en-CA,ja"/> + <int value="1389280901" label="en-AU,eo"/> + <int value="1393996692" label="en-CA,mi"/> + <int value="1395222628" label="en-IN,lt"/> + <int value="1398402282" label="en-GB,de"/> + <int value="1402000053" label="en-GB,ky"/> + <int value="1416181656" label="en,ny"/> + <int value="1418241073" label="en-NZ,sv"/> + <int value="1420980063" label="en-AU,ro"/> + <int value="1422442520" label="en-AU,jv"/> + <int value="1430525845" label="en-AU,sk"/> + <int value="1440048775" label="en-GB,ca"/> + <int value="1440610021" label="other,cs"/> + <int value="1448954659" label="en-AU,yi"/> + <int value="1454462350" label="en-US,tr"/> + <int value="1455512265" label="en-CA,da"/> + <int value="1455668867" label="en-US,sr"/> + <int value="1464251629" label="en-GB,uk"/> + <int value="1468669496" label="en-GB,su"/> + <int value="1468930251" label="en-ZA,tg"/> + <int value="1473595362" label="en,et"/> + <int value="1475867184" label="other,ps"/> + <int value="1479752599" label="en-NZ,so"/> + <int value="1486918374" label="en-CA,gu"/> + <int value="1492342066" label="en-IN,ro"/> + <int value="1494396409" label="en-NZ,tr"/> + <int value="1502339637" label="en,ms"/> + <int value="1512489951" label="en-US,kk"/> + <int value="1516505763" label="en-IN,uk"/> + <int value="1525021570" label="en-GB,hi"/> + <int value="1529621431" label="en-IN,mg"/> + <int value="1534291662" label="en,fi"/> + <int value="1541318518" label="en-CA,ar"/> + <int value="1545921996" label="en,cy"/> + <int value="1547798712" label="en-CA,hy"/> + <int value="1554560505" label="en,iw"/> + <int value="1556599784" label="en-US,zu"/> + <int value="1560108635" label="en-CA,bg"/> + <int value="1569869322" label="en,lv"/> + <int value="1571010464" label="other,tr"/> + <int value="1574218451" label="en,ja-Latn"/> + <int value="1574455066" label="en-NZ,hy"/> + <int value="1577813196" label="en-ZA,ja-Latn"/> + <int value="1583748372" label="en-US,uz"/> + <int value="1584277030" label="en,lo"/> + <int value="1586371836" label="en-GB,haw"/> + <int value="1587065378" label="en-CA,ceb"/> + <int value="1587149206" label="en-AU,is"/> + <int value="1587448881" label="other,bg-Latn"/> + <int value="1595122469" label="en-GB,am"/> + <int value="1599809239" label="en-NZ,eo"/> + <int value="1602933018" label="en-AU,km"/> + <int value="1606599170" label="en-GB,af"/> + <int value="1616893188" label="en-GB,en"/> + <int value="1617301307" label="en-US,vi"/> + <int value="1620733201" label="en-ZA,st"/> + <int value="1622221024" label="en-NZ,st"/> + <int value="1625230863" label="en-ZA,ca"/> + <int value="1627858810" label="en-CA,su"/> + <int value="1631878770" label="en-CA,eu"/> + <int value="1633252733" label="en-CA,und"/> + <int value="1640305574" label="en-CA,ms"/> + <int value="1649537917" label="en-NZ,id"/> + <int value="1650086272" label="en-IN,ja"/> + <int value="1654964809" label="en-GB,ta"/> + <int value="1658068744" label="en-ZA,si"/> + <int value="1674861874" label="en-AU,af"/> + <int value="1674862709" label="en-AU,ko"/> + <int value="1678320412" label="en-US,sw"/> + <int value="1682821330" label="en,ro"/> + <int value="1685893517" label="en-IN,so"/> + <int value="1688465225" label="en-NZ,gl"/> + <int value="1693278011" label="en-US,pt"/> + <int value="1697603371" label="en,si"/> + <int value="1700824821" label="en-GB,tr"/> + <int value="1717190578" label="en-CA,bn"/> + <int value="1721644578" label="en-NZ,nl"/> + <int value="1723571120" label="en-NZ,ta"/> + <int value="1725099187" label="en,zh"/> + <int value="1737627322" label="en-ZA,cy"/> + <int value="1740225427" label="en-GB,cs"/> + <int value="1742804144" label="en-US,te"/> + <int value="1744275224" label="en-ZA,fi"/> + <int value="1749696454" label="other,cy"/> + <int value="1753505573" label="en-ZA,mn"/> + <int value="1772273660" label="other,am"/> + <int value="1787055860" label="en-CA,ta"/> + <int value="1795956429" label="en-AU,ny"/> + <int value="1797503688" label="en-NZ,jv"/> + <int value="1805209460" label="en-IN,th"/> + <int value="1825180324" label="en-GB,pl"/> + <int value="1826276933" label="en-US,km"/> + <int value="1837257554" label="en-IN,id"/> + <int value="1839203236" label="en-CA,la"/> + <int value="1840601524" label="en-US,pl"/> + <int value="1843812704" label="en-US,en"/> + <int value="1845750026" label="en-GB,mk"/> + <int value="1850895272" label="en-ZA,su"/> + <int value="1858092254" label="en-NZ,fy"/> + <int value="1859062446" label="en-NZ,ms"/> + <int value="1864323264" label="en-NZ,hmn"/> + <int value="1879419731" label="en-NZ,fil"/> + <int value="1887245165" label="en-IN,ne"/> + <int value="1887547959" label="en-AU,hy"/> + <int value="1896229543" label="en-AU,st"/> + <int value="1897866500" label="en-AU,cs"/> + <int value="1914113466" label="en-GB,sn"/> + <int value="1916036344" label="en-AU,th"/> + <int value="1921346058" label="en-NZ,kn"/> + <int value="1921468722" label="en-GB,lo"/> + <int value="1922305307" label="en,ca"/> + <int value="1923055656" label="other,sn"/> + <int value="1929310230" label="en-IN,tg"/> + <int value="1935021242" label="en-GB,el-Latn"/> + <int value="1947337323" label="en-GB,sw"/> + <int value="1950716531" label="en,lb"/> + <int value="1953379543" label="en-ZA,yo"/> + <int value="1954146782" label="en-IN,ps"/> + <int value="1955147896" label="en-US,ja"/> + <int value="1960593815" label="en-IN,uz"/> + <int value="1971945016" label="en-AU,am"/> + <int value="1972836537" label="en-GB,km"/> + <int value="1975943948" label="en-AU,gd"/> + <int value="1981144369" label="en-US,be"/> + <int value="1990402435" label="en-ZA,ja"/> + <int value="1991206873" label="en,es"/> + <int value="1992336755" label="en-NZ,xh"/> + <int value="1993640855" label="en-CA,jv"/> + <int value="1998909729" label="en-ZA,kk"/> + <int value="2008193378" label="en-NZ,it"/> + <int value="2009383888" label="other,xh"/> + <int value="2019528786" label="en-CA,bg-Latn"/> + <int value="2019768967" label="other,eu"/> + <int value="2028809726" label="en-CA,km"/> + <int value="2031218406" label="en,ur"/> + <int value="2036627878" label="en-CA,mk"/> + <int value="2041001332" label="en-NZ,no"/> + <int value="2044661620" label="en-AU,sw"/> + <int value="2045704410" label="en-AU,it"/> + <int value="2047493862" label="en-CA,ky"/> + <int value="2048503615" label="en,eo"/> + <int value="2050034631" label="en-US,mr"/> + <int value="2052081632" label="en-AU,ceb"/> + <int value="2058678293" label="en-US,kn"/> + <int value="2063559514" label="en-US,st"/> + <int value="2069198284" label="en-IN,fil"/> + <int value="2070565410" label="en-ZA,de"/> + <int value="2075422927" label="en-AU,fa"/> + <int value="2077918936" label="en-AU,kn"/> + <int value="2078538264" label="en-AU,et"/> + <int value="2078639052" label="en-US,nl"/> + <int value="2083592559" label="en-US,it"/> + <int value="2087547308" label="en-GB,da"/> + <int value="2088017334" label="en-CA,hi-Latn"/> + <int value="2088167089" label="en-NZ,vi"/> + <int value="2095083633" label="en-ZA,gu"/> + <int value="2095959023" label="en-NZ,pl"/> + <int value="2099045123" label="en-NZ,ro"/> + <int value="2100025793" label="en-US,id"/> + <int value="2115803061" label="en-CA,kk"/> + <int value="2116112642" label="en-US,fr"/> + <int value="2116383804" label="en,ceb"/> + <int value="2121668277" label="en-CA,vi"/> + <int value="2123533843" label="other,zu"/> + <int value="2132483133" label="en-US,ja-Latn"/> + <int value="2137580597" label="en-NZ,fa"/> + <int value="2141671912" label="other,mk"/> + <int value="2144565498" label="en-ZA,bs"/> +</enum> + <enum name="EnhancedBookmarkViewMode" type="int"> <obsolete> Deprecated 9/2015. @@ -101726,7 +102763,6 @@ <int value="-1310737697" label="MaterialDesignSettings:enabled"/> <int value="-1302904242" label="enable-navigation-tracing"/> <int value="-1289678848" label="SystemDownloadManager:enabled"/> - <int value="-1289373013" label="ui-show-layer-borders"/> <int value="-1285021473" label="save-page-as-mhtml"/> <int value="-1276912933" label="enable-quick-unlock-pin"/> <int value="-1271563519" label="enable-appcontainer"/> @@ -101783,6 +102819,7 @@ <int value="-1075089382" label="enable-physical-web"/> <int value="-1073479583" label="ShowArcFilesApp:disabled"/> <int value="-1067635248" label="SpeculativeResourcePrefetching:disabled"/> + <int value="-1064733740" label="ui-show-composited-layer-borders"/> <int value="-1062119671" label="enable-password-force-saving"/> <int value="-1056310158" label="disable-memory-pressure-chromeos"/> <int value="-1052782474" label="enable-cloud-devices"/> @@ -120754,6 +121791,13 @@ <affected-histogram name="MobileDownload.InterruptionsCount"/> </histogram_suffixes> +<histogram_suffixes name="MobileDownloadResumptionsCountTypes" separator="."> + <suffix name="Automatic"/> + <suffix name="Manual"/> + <suffix name="Total"/> + <affected-histogram name="MobileDownload.ResumptionsCount"/> +</histogram_suffixes> + <histogram_suffixes name="MobileFreEntryType" separator="."> <suffix name="MainIntent" label="Icon click"/> <suffix name="ViewIntent" label="VIEW intent"/>
diff --git a/tools/perf/chrome_telemetry_build/BUILD.gn b/tools/perf/chrome_telemetry_build/BUILD.gn index 98f28d9..02fd611 100644 --- a/tools/perf/chrome_telemetry_build/BUILD.gn +++ b/tools/perf/chrome_telemetry_build/BUILD.gn
@@ -20,6 +20,7 @@ } data = [ + "//tools/perf/core/", # chrome_telemetry_build/ depends on core/ "//tools/perf/chrome_telemetry_build/", "//third_party/catapult/", "//components/crash/content/tools/generate_breakpad_symbols.py",
diff --git a/tools/perf/chrome_telemetry_build/chromium_config.py b/tools/perf/chrome_telemetry_build/chromium_config.py index a39dca92..77887a63 100644 --- a/tools/perf/chrome_telemetry_build/chromium_config.py +++ b/tools/perf/chrome_telemetry_build/chromium_config.py
@@ -2,25 +2,14 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import logging import os -import sys - -def GetChromiumSrcDir(): - return os.path.abspath( - os.path.join(os.path.abspath(__file__), '..', '..', '..', '..')) - - -def GetTelemetryDir(): - return os.path.join(GetChromiumSrcDir(), 'third_party', 'catapult', - 'telemetry') - +from core import path_util CLIENT_CONFIG_PATH = os.path.join( os.path.dirname(os.path.abspath(__file__)), 'binary_dependencies.json') -sys.path.insert(1, os.path.join(GetTelemetryDir())) +path_util.AddTelemetryToPath() from telemetry import project_config @@ -28,20 +17,11 @@ class ChromiumConfig(project_config.ProjectConfig): def __init__(self, top_level_dir=None, benchmark_dirs=None, - client_configs=None, - default_chrome_root=GetChromiumSrcDir()): + client_configs=None, default_chrome_root=None): if client_configs is None: client_configs = [CLIENT_CONFIG_PATH] - - perf_dir = os.path.join(GetChromiumSrcDir(), 'tools', 'perf') - if not benchmark_dirs: - benchmark_dirs = [os.path.join(perf_dir, 'benchmarks')] - logging.info('No benchmark directories specified. Defaulting to %s', - benchmark_dirs) - if not top_level_dir: - top_level_dir = perf_dir - logging.info('No top level directory specified. Defaulting to %s', - top_level_dir) + if default_chrome_root is None: + default_chrome_root = path_util.GetChromiumSrcDir() super(ChromiumConfig, self).__init__( top_level_dir=top_level_dir, benchmark_dirs=benchmark_dirs,
diff --git a/tools/perf/core/path_util.py b/tools/perf/core/path_util.py index 27ea09c1..dcfcd08 100644 --- a/tools/perf/core/path_util.py +++ b/tools/perf/core/path_util.py
@@ -5,18 +5,15 @@ import os import sys -sys.path.insert(1, os.path.join(os.path.abspath(__file__), '..', '..')) - -from chrome_telemetry_build import chromium_config - def GetChromiumSrcDir(): - return chromium_config.GetChromiumSrcDir() - + return os.path.abspath(os.path.join( + os.path.dirname(__file__), '..', '..', '..')) def GetTelemetryDir(): - return chromium_config.GetTelemetryDir() + return os.path.join( + GetChromiumSrcDir(), 'third_party', 'catapult', 'telemetry') def GetPerfDir():
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index b4b42eca..4f7672e 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -16,9 +16,9 @@ import sys import sets -from chrome_telemetry_build import chromium_config +from core import path_util +path_util.AddTelemetryToPath() -sys.path.append(chromium_config.GetTelemetryDir()) from telemetry import benchmark as benchmark_module from telemetry import decorators from telemetry.core import discover @@ -189,7 +189,8 @@ 'os': 'Android', 'android_devices': '1', 'device_ids': [ - 'build245-m4--device1', 'build245-m4--device2', + #'build245-m4--device1', offline, see http://crbug.com/705135 + 'build245-m4--device2', 'build245-m4--device3', 'build245-m4--device4', 'build245-m4--device5', 'build245-m4--device6', 'build245-m4--device7', 'build248-m4--device1', @@ -760,6 +761,8 @@ benchmark_sharding_map['5'] = shard_benchmarks(5, all_benchmarks) benchmark_sharding_map['1'] = shard_benchmarks(1, all_benchmarks) benchmark_sharding_map['21'] = shard_benchmarks(21, all_benchmarks) + # Added because of temporary removal of device in http://crbug.com/705135 + benchmark_sharding_map['20'] = shard_benchmarks(20, all_benchmarks) for name, config in waterfall['testers'].iteritems(): use_whitelist = config['use_whitelist']
diff --git a/tools/perf/page_sets/system_health/searching_stories.py b/tools/perf/page_sets/system_health/searching_stories.py index ac1666af..0f52f95 100644 --- a/tools/perf/page_sets/system_health/searching_stories.py +++ b/tools/perf/page_sets/system_health/searching_stories.py
@@ -43,6 +43,7 @@ action_runner.tab.WaitForDocumentReadyStateToBeComplete() +@decorators.Disabled('android-webview') # Webview does not have omnibox class SearchOmniboxStory(system_health_story.SystemHealthStory): """Story that peforms search by using omnibox search provider
diff --git a/tools/perf/record_android_profile.py b/tools/perf/record_android_profile.py index 8247615..da7d3e4 100755 --- a/tools/perf/record_android_profile.py +++ b/tools/perf/record_android_profile.py
@@ -7,8 +7,8 @@ import sys import tempfile -from chrome_telemetry_build import chromium_config -sys.path.insert(1, chromium_config.GetTelemetryDir()) +from core import path_util +path_util.AddTelemetryToPath() from telemetry.internal.browser import browser_finder from telemetry.internal.browser import browser_options
diff --git a/tools/perf/record_wpr b/tools/perf/record_wpr index a87bc14..178e1af 100755 --- a/tools/perf/record_wpr +++ b/tools/perf/record_wpr
@@ -7,7 +7,8 @@ from chrome_telemetry_build import chromium_config -sys.path.append(chromium_config.GetTelemetryDir()) +from core import path_util +path_util.AddTelemetryToPath() from telemetry import record_wpr @@ -33,4 +34,7 @@ if __name__ == '__main__': if sys.version_info < (2, 7, 9): _WarnPythonVersion() - sys.exit(record_wpr.Main(environment=chromium_config.ChromiumConfig())) + config = chromium_config.ChromiumConfig( + benchmark_dirs=[path_util.GetPerfBenchmarksDir()], + top_level_dir=path_util.GetPerfDir()) + sys.exit(record_wpr.Main(environment=config))
diff --git a/tools/perf/run_benchmark b/tools/perf/run_benchmark index 228405ff..00fb6af 100755 --- a/tools/perf/run_benchmark +++ b/tools/perf/run_benchmark
@@ -15,8 +15,11 @@ def main(): - config = chromium_config.ChromiumConfig() + config = chromium_config.ChromiumConfig( + benchmark_dirs=[path_util.GetPerfBenchmarksDir()], + top_level_dir=path_util.GetPerfDir()) return benchmark_runner.main(config, [trybot_command.Trybot]) + if __name__ == '__main__': sys.exit(main())
diff --git a/tools/perf/run_telemetry_tests b/tools/perf/run_telemetry_tests index 699cf63f..0abbd8a 100755 --- a/tools/perf/run_telemetry_tests +++ b/tools/perf/run_telemetry_tests
@@ -13,18 +13,18 @@ import sys from chrome_telemetry_build import chromium_config +from core import path_util +path_util.AddTelemetryToPath() - -sys.path.append(chromium_config.GetTelemetryDir()) from telemetry.testing import unittest_runner def main(): telemetry_test_config = os.path.join( - chromium_config.GetTelemetryDir(), 'telemetry', + path_util.GetTelemetryDir(), 'telemetry', 'telemetry_unittest_deps.json') project_config = chromium_config.ChromiumConfig( - top_level_dir=chromium_config.GetTelemetryDir(), + top_level_dir=path_util.GetTelemetryDir(), client_configs=[chromium_config.CLIENT_CONFIG_PATH, telemetry_test_config] ) return unittest_runner.Run(
diff --git a/tools/perf/run_tests b/tools/perf/run_tests index c9486fe3..152fa85 100755 --- a/tools/perf/run_tests +++ b/tools/perf/run_tests
@@ -20,7 +20,8 @@ def main(): - project_config = chromium_config.ChromiumConfig() + project_config = chromium_config.ChromiumConfig( + top_level_dir=path_util.GetPerfDir()) return unittest_runner.Run(project_config) if __name__ == '__main__':
diff --git a/tools/win/CreateTempFilesPerfEvaluation/.gitignore b/tools/win/CreateTempFilesPerfEvaluation/.gitignore new file mode 100644 index 0000000..499cde1 --- /dev/null +++ b/tools/win/CreateTempFilesPerfEvaluation/.gitignore
@@ -0,0 +1,4 @@ +Release/ +Debug/ +ipch/ +x64/ \ No newline at end of file
diff --git a/tools/win/CreateTempFilesPerfEvaluation/CreateTempFilesPerfEval.cc b/tools/win/CreateTempFilesPerfEvaluation/CreateTempFilesPerfEval.cc new file mode 100644 index 0000000..c427ff9f --- /dev/null +++ b/tools/win/CreateTempFilesPerfEvaluation/CreateTempFilesPerfEval.cc
@@ -0,0 +1,272 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <windows.h> + +#include <shlwapi.h> +#include <stdio.h> +#include <tchar.h> + +#include <algorithm> +#include <iostream> +#include <sstream> +#include <string> + +#pragma warning(disable : 4996) + +// Create |count| number of temp files at |folder_path| using GUID based method. +// The time cost in millisecond of creating every 500 temp files or all the +// files if |count| < 500 is printed to the console. +bool CreateFilesUsingGuid(UINT count, const char* folder_path); + +// Create |count| number of temp files at |folder_path| using GetTempFileName() +// API. The time cost in millisecond of creating every 500 temp files or all the +// files if |count| < 500 is printed to the console. +bool CreateFilesUsingGetTempFileName(UINT count, const char* folder_path); + +// This method converts GUID to a string. +char* ConvertGuidToString(const GUID* id, char* out); + +// If |folder_path| doesn't exist, creat it, otherwise check if it is empty. +bool CreateOrValidateTempDirectory(const char* folder_path); + +// Deletes all the content in |folder_path|. +void DeleteDirectoryContent(const char* folder_path); + +// Deletes |folder_path| including its contents and the raw directory. +bool DeleteDirectory(const char* folder_path); + +// Deletes |folder_path| including its contents and the raw directory, and print +// the delete status to the console. +void DeleteDirectoryAndPrintMsg(const char* folder_path); + +// Prints the elapsed time at current step for the latest cycle. +void FormatPrintElapsedTime(UINT cur_step, + UINT total_step, + const LARGE_INTEGER& elapsed_ms); + +// Maximum number of temp files allowed to create. This is limited by the +// implementation of GetTempFileName(). +// "This limits GetTempFileName to a maximum of 65,535 unique file names if the +// lpPathName and lpPrefixString parameters remain the same." +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364991(v=vs.85).aspx +UINT kMaxFileCreate = 65535; + +// Query the time cost each time when this amount of temp files are created. +UINT kFileCountPerMetric = 500; + +int main() { + // Gets the temp path env string. + DWORD temp_path_ret = 0; + CHAR temp_folder_path[MAX_PATH]; + temp_path_ret = ::GetTempPathA(MAX_PATH, temp_folder_path); + if (temp_path_ret > MAX_PATH || temp_path_ret == 0) { + std::cout << "GetTempPath failed" << std::endl; + return 0; + } + + // A temporary directory where the new temp files created by GetTempFileName() + // are written. + std::string temp_dir_gettempfilename( + std::string(temp_folder_path).append("TempDirGetTempFileName\\")); + + // A temporary directory where the new temp files created by Guid-based method + // are written. + std::string temp_dir_guid( + std::string(temp_folder_path).append("TempDirGuid\\")); + + UINT file_create_count; + std::string user_input; + + while (true) { + std::cout << "\nPlease enter # of files to create (maximum " + << kMaxFileCreate << "), or \"quit\" to end the program : "; + std::getline(std::cin, user_input); + + std::transform(user_input.begin(), user_input.end(), user_input.begin(), + ::tolower); + if (user_input == "quit") + break; + + std::cout << std::endl; + std::stringstream ss(user_input); + + if (ss >> file_create_count && file_create_count <= kMaxFileCreate) { + std::cout << "\nPlease select method to create temp file names,\n" + << "\"t\" for GetTempFileName \n" + << "\"g\" for GUID-based \n" + << "\"b\" for both \n" + << "or \"quit\" to end the program : "; + std::getline(std::cin, user_input); + + std::transform(user_input.begin(), user_input.end(), user_input.begin(), + ::tolower); + if (user_input == "quit") + break; + + if (user_input == "t" || user_input == "b") { + std::cout << "\nGetTempFileName Performance:\n [start - end] / total " + "--- time " + "cost in ms" + << std::endl; + if (CreateFilesUsingGetTempFileName(file_create_count, + temp_dir_gettempfilename.c_str())) { + std::cout << "File creation succeeds at " << temp_dir_gettempfilename + << ", now clean all of them!" << std::endl; + } + DeleteDirectoryAndPrintMsg(temp_dir_gettempfilename.c_str()); + } + + if (user_input == "g" || user_input == "b") { + std::cout << "\nGUID-based Performance:\n [start - end] / total --- " + "time cost in ms" + << std::endl; + if (CreateFilesUsingGuid(file_create_count, temp_dir_guid.c_str())) { + std::cout << "File creation succeeds at " << temp_dir_guid + << ", now clean all of them!" << std::endl; + } + DeleteDirectoryAndPrintMsg(temp_dir_guid.c_str()); + } + } else { + std::cout << "Input number is invalid, please enter # of files to create " + "(maximum " + << kMaxFileCreate << "), or \"quit\" to end the program : "; + } + std::cout << std::endl; + } + return 0; +} + +bool CreateFilesUsingGuid(UINT count, const char* dir_path) { + if (!CreateOrValidateTempDirectory(dir_path)) + return false; + + LARGE_INTEGER starting_time, ending_time, elapsed_ms; + ::QueryPerformanceCounter(&starting_time); + LARGE_INTEGER frequency; + ::QueryPerformanceFrequency(&frequency); + + for (UINT i = 1; i <= count; ++i) { + GUID guid; + ::CoCreateGuid(&guid); + char buffer[37]; + ConvertGuidToString(&guid, buffer); + std::string temp_name = std::string(dir_path).append(buffer).append(".tmp"); + + HANDLE file_handle = + ::CreateFileA(temp_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + ::CloseHandle(file_handle); + + if (i % kFileCountPerMetric == 0 || i == count) { + ::QueryPerformanceCounter(&ending_time); + // Convert the elapsed number of ticks to milliseconds. + elapsed_ms.QuadPart = (ending_time.QuadPart - starting_time.QuadPart) * + 1000 / frequency.QuadPart; + + FormatPrintElapsedTime(i, count, elapsed_ms); + + ::QueryPerformanceCounter(&starting_time); + } + } + return true; +} + +bool CreateFilesUsingGetTempFileName(UINT count, const char* dir_path) { + if (!CreateOrValidateTempDirectory(dir_path)) + return false; + + CHAR temp_name[MAX_PATH]; + LARGE_INTEGER starting_time, ending_time, elapsed_ms; + ::QueryPerformanceCounter(&starting_time); + LARGE_INTEGER frequency; + ::QueryPerformanceFrequency(&frequency); + + for (UINT i = 1; i <= count; ++i) { + ::GetTempFileNameA(dir_path, "", 0, temp_name); + if (i % kFileCountPerMetric == 0 || i == count) { + ::QueryPerformanceCounter(&ending_time); + // Convert the elapsed number of ticks to milliseconds. + elapsed_ms.QuadPart = (ending_time.QuadPart - starting_time.QuadPart) * + 1000 / frequency.QuadPart; + + FormatPrintElapsedTime(i, count, elapsed_ms); + + ::QueryPerformanceCounter(&starting_time); + } + } + return true; +} + +char* ConvertGuidToString(const GUID* id, char* out) { + int i; + char* ret = out; + out += sprintf(out, "%.8lX-%.4hX-%.4hX-", id->Data1, id->Data2, id->Data3); + for (i = 0; i < sizeof(id->Data4); ++i) { + out += sprintf(out, "%.2hhX", id->Data4[i]); + if (i == 1) + *(out++) = '-'; + } + return ret; +} + +bool CreateOrValidateTempDirectory(const char* folder_path) { + if (::PathFileExistsA(folder_path)) { + if (!::PathIsDirectoryEmptyA(folder_path)) { + std::cout << folder_path + << " directory is not empty, please remove all its content."; + return false; + } + return true; + } else if (::CreateDirectoryA(folder_path, NULL) == 0) { + std::cout << folder_path << "directory creation fails."; + return false; + } else { + return true; + } +} + +void DeleteDirectoryContent(const char* folder_path) { + char file_found[MAX_PATH]; + WIN32_FIND_DATAA info; + HANDLE hp; + sprintf(file_found, "%s\\*.*", folder_path); + hp = ::FindFirstFileA(file_found, &info); + do { + if ((strcmp(info.cFileName, ".") == 0) || + (strcmp(info.cFileName, "..") == 0)) { + continue; + } + sprintf(file_found, "%s\\%s", folder_path, info.cFileName); + ::DeleteFileA(file_found); + } while (::FindNextFileA(hp, &info)); + ::FindClose(hp); +} + +bool DeleteDirectory(const char* folder_path) { + DeleteDirectoryContent(folder_path); + return ::RemoveDirectoryA(folder_path) != 0; +} + +void DeleteDirectoryAndPrintMsg(const char* folder_path) { + if (DeleteDirectory(folder_path)) { + std::cout << folder_path << " directory is deleted!" << std::endl; + } else { + std::cout << "[Attention] " << folder_path + << " directory's deletion fails, please take a look by yourself!" + << std::endl; + } +} + +void FormatPrintElapsedTime(UINT cur_step, + UINT total_step, + const LARGE_INTEGER& elapsed_ms) { + UINT count_prev = 0; + if (cur_step % kFileCountPerMetric == 0) + count_prev = cur_step + 1 - kFileCountPerMetric; + else if (cur_step > kFileCountPerMetric) + count_prev = cur_step / kFileCountPerMetric * kFileCountPerMetric + 1; + printf(" [%5d - %5d] / %d --- %lld\n", count_prev, cur_step, total_step, + elapsed_ms.QuadPart); +}
diff --git a/tools/win/CreateTempFilesPerfEvaluation/CreateTempFilesPerfEval.sln b/tools/win/CreateTempFilesPerfEvaluation/CreateTempFilesPerfEval.sln new file mode 100644 index 0000000..f08404b3 --- /dev/null +++ b/tools/win/CreateTempFilesPerfEvaluation/CreateTempFilesPerfEval.sln
@@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CreateTempFilesPerfEval", "CreateTempFilesPerfEval.vcxproj", "{34BAA4C1-8DC7-4FF0-88B3-E1B1ABB4A11C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {34BAA4C1-8DC7-4FF0-88B3-E1B1ABB4A11C}.Debug|x64.ActiveCfg = Debug|x64 + {34BAA4C1-8DC7-4FF0-88B3-E1B1ABB4A11C}.Debug|x64.Build.0 = Debug|x64 + {34BAA4C1-8DC7-4FF0-88B3-E1B1ABB4A11C}.Debug|x86.ActiveCfg = Debug|Win32 + {34BAA4C1-8DC7-4FF0-88B3-E1B1ABB4A11C}.Debug|x86.Build.0 = Debug|Win32 + {34BAA4C1-8DC7-4FF0-88B3-E1B1ABB4A11C}.Release|x64.ActiveCfg = Release|x64 + {34BAA4C1-8DC7-4FF0-88B3-E1B1ABB4A11C}.Release|x64.Build.0 = Release|x64 + {34BAA4C1-8DC7-4FF0-88B3-E1B1ABB4A11C}.Release|x86.ActiveCfg = Release|Win32 + {34BAA4C1-8DC7-4FF0-88B3-E1B1ABB4A11C}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal
diff --git a/tools/win/CreateTempFilesPerfEvaluation/CreateTempFilesPerfEval.vcxproj b/tools/win/CreateTempFilesPerfEvaluation/CreateTempFilesPerfEval.vcxproj new file mode 100644 index 0000000..15307cd --- /dev/null +++ b/tools/win/CreateTempFilesPerfEvaluation/CreateTempFilesPerfEval.vcxproj
@@ -0,0 +1,153 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{34BAA4C1-8DC7-4FF0-88B3-E1B1ABB4A11C}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>CreateTempFilesPerfEval</RootNamespace> + <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v140</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>Shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader>Use</PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>Shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="CreateTempFilesPerfEval.cc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file
diff --git a/tools/win/CreateTempFilesPerfEvaluation/GetTempFileNamePerfExample.txt b/tools/win/CreateTempFilesPerfEvaluation/GetTempFileNamePerfExample.txt new file mode 100644 index 0000000..383b6ce --- /dev/null +++ b/tools/win/CreateTempFilesPerfEvaluation/GetTempFileNamePerfExample.txt
@@ -0,0 +1,134 @@ +GetTempFileName Performance: + [start - end] / total --- time cost in ms + [ 1 - 500] / 65535 --- 410 + [ 501 - 1000] / 65535 --- 412 + [ 1001 - 1500] / 65535 --- 416 + [ 1501 - 2000] / 65535 --- 409 + [ 2001 - 2500] / 65535 --- 411 + [ 2501 - 3000] / 65535 --- 409 + [ 3001 - 3500] / 65535 --- 417 + [ 3501 - 4000] / 65535 --- 416 + [ 4001 - 4500] / 65535 --- 407 + [ 4501 - 5000] / 65535 --- 402 + [ 5001 - 5500] / 65535 --- 420 + [ 5501 - 6000] / 65535 --- 415 + [ 6001 - 6500] / 65535 --- 404 + [ 6501 - 7000] / 65535 --- 386 + [ 7001 - 7500] / 65535 --- 414 + [ 7501 - 8000] / 65535 --- 388 + [ 8001 - 8500] / 65535 --- 401 + [ 8501 - 9000] / 65535 --- 391 + [ 9001 - 9500] / 65535 --- 389 + [ 9501 - 10000] / 65535 --- 393 + [10001 - 10500] / 65535 --- 429 + [10501 - 11000] / 65535 --- 395 + [11001 - 11500] / 65535 --- 396 + [11501 - 12000] / 65535 --- 391 + [12001 - 12500] / 65535 --- 389 + [12501 - 13000] / 65535 --- 393 + [13001 - 13500] / 65535 --- 416 + [13501 - 14000] / 65535 --- 393 + [14001 - 14500] / 65535 --- 430 + [14501 - 15000] / 65535 --- 393 + [15001 - 15500] / 65535 --- 401 + [15501 - 16000] / 65535 --- 410 + [16001 - 16500] / 65535 --- 392 + [16501 - 17000] / 65535 --- 394 + [17001 - 17500] / 65535 --- 389 + [17501 - 18000] / 65535 --- 398 + [18001 - 18500] / 65535 --- 414 + [18501 - 19000] / 65535 --- 390 + [19001 - 19500] / 65535 --- 384 + [19501 - 20000] / 65535 --- 386 + [20001 - 20500] / 65535 --- 389 + [20501 - 21000] / 65535 --- 412 + [21001 - 21500] / 65535 --- 396 + [21501 - 22000] / 65535 --- 384 + [22001 - 22500] / 65535 --- 393 + [22501 - 23000] / 65535 --- 402 + [23001 - 23500] / 65535 --- 414 + [23501 - 24000] / 65535 --- 394 + [24001 - 24500] / 65535 --- 391 + [24501 - 25000] / 65535 --- 390 + [25001 - 25500] / 65535 --- 391 + [25501 - 26000] / 65535 --- 397 + [26001 - 26500] / 65535 --- 430 + [26501 - 27000] / 65535 --- 422 + [27001 - 27500] / 65535 --- 401 + [27501 - 28000] / 65535 --- 403 + [28001 - 28500] / 65535 --- 425 + [28501 - 29000] / 65535 --- 400 + [29001 - 29500] / 65535 --- 412 + [29501 - 30000] / 65535 --- 400 + [30001 - 30500] / 65535 --- 396 + [30501 - 31000] / 65535 --- 427 + [31001 - 31500] / 65535 --- 414 + [31501 - 32000] / 65535 --- 395 + [32001 - 32500] / 65535 --- 397 + [32501 - 33000] / 65535 --- 414 + [33001 - 33500] / 65535 --- 423 + [33501 - 34000] / 65535 --- 396 + [34001 - 34500] / 65535 --- 433 + [34501 - 35000] / 65535 --- 411 + [35001 - 35500] / 65535 --- 402 + [35501 - 36000] / 65535 --- 409 + [36001 - 36500] / 65535 --- 944 + [36501 - 37000] / 65535 --- 1381 + [37001 - 37500] / 65535 --- 1424 + [37501 - 38000] / 65535 --- 1449 + [38001 - 38500] / 65535 --- 1321 + [38501 - 39000] / 65535 --- 1398 + [39001 - 39500] / 65535 --- 1643 + [39501 - 40000] / 65535 --- 1817 + [40001 - 40500] / 65535 --- 1693 + [40501 - 41000] / 65535 --- 1607 + [41001 - 41500] / 65535 --- 1601 + [41501 - 42000] / 65535 --- 1875 + [42001 - 42500] / 65535 --- 1671 + [42501 - 43000] / 65535 --- 1673 + [43001 - 43500] / 65535 --- 1781 + [43501 - 44000] / 65535 --- 1667 + [44001 - 44500] / 65535 --- 1785 + [44501 - 45000] / 65535 --- 1938 + [45001 - 45500] / 65535 --- 1882 + [45501 - 46000] / 65535 --- 2054 + [46001 - 46500] / 65535 --- 1743 + [46501 - 47000] / 65535 --- 1701 + [47001 - 47500] / 65535 --- 1429 + [47501 - 48000] / 65535 --- 1410 + [48001 - 48500] / 65535 --- 1541 + [48501 - 49000] / 65535 --- 1567 + [49001 - 49500] / 65535 --- 1502 + [49501 - 50000] / 65535 --- 1583 + [50001 - 50500] / 65535 --- 1500 + [50501 - 51000] / 65535 --- 1517 + [51001 - 51500] / 65535 --- 1597 + [51501 - 52000] / 65535 --- 2789 + [52001 - 52500] / 65535 --- 3829 + [52501 - 53000] / 65535 --- 3877 + [53001 - 53500] / 65535 --- 3323 + [53501 - 54000] / 65535 --- 3331 + [54001 - 54500] / 65535 --- 3547 + [54501 - 55000] / 65535 --- 3435 + [55001 - 55500] / 65535 --- 3576 + [55501 - 56000] / 65535 --- 3425 + [56001 - 56500] / 65535 --- 3500 + [56501 - 57000] / 65535 --- 3422 + [57001 - 57500] / 65535 --- 3669 + [57501 - 58000] / 65535 --- 3597 + [58001 - 58500] / 65535 --- 3801 + [58501 - 59000] / 65535 --- 3820 + [59001 - 59500] / 65535 --- 3599 + [59501 - 60000] / 65535 --- 5531 + [60001 - 60500] / 65535 --- 6807 + [60501 - 61000] / 65535 --- 6201 + [61001 - 61500] / 65535 --- 6053 + [61501 - 62000] / 65535 --- 5327 + [62001 - 62500] / 65535 --- 5273 + [62501 - 63000] / 65535 --- 4553 + [63001 - 63500] / 65535 --- 5655 + [63501 - 64000] / 65535 --- 6247 + [64001 - 64500] / 65535 --- 5907 + [64501 - 65000] / 65535 --- 21143 + [65001 - 65500] / 65535 --- 43495 + [65501 - 65535] / 65535 --- 44300 \ No newline at end of file
diff --git a/tools/win/CreateTempFilesPerfEvaluation/GuidPerfExample.txt b/tools/win/CreateTempFilesPerfEvaluation/GuidPerfExample.txt new file mode 100644 index 0000000..c2285e47 --- /dev/null +++ b/tools/win/CreateTempFilesPerfEvaluation/GuidPerfExample.txt
@@ -0,0 +1,134 @@ +GUID-based Performance: + [start - end] / total --- time cost in ms + [ 1 - 500] / 65535 --- 401 + [ 501 - 1000] / 65535 --- 402 + [ 1001 - 1500] / 65535 --- 395 + [ 1501 - 2000] / 65535 --- 396 + [ 2001 - 2500] / 65535 --- 403 + [ 2501 - 3000] / 65535 --- 402 + [ 3001 - 3500] / 65535 --- 406 + [ 3501 - 4000] / 65535 --- 400 + [ 4001 - 4500] / 65535 --- 419 + [ 4501 - 5000] / 65535 --- 400 + [ 5001 - 5500] / 65535 --- 406 + [ 5501 - 6000] / 65535 --- 400 + [ 6001 - 6500] / 65535 --- 398 + [ 6501 - 7000] / 65535 --- 411 + [ 7001 - 7500] / 65535 --- 402 + [ 7501 - 8000] / 65535 --- 404 + [ 8001 - 8500] / 65535 --- 412 + [ 8501 - 9000] / 65535 --- 396 + [ 9001 - 9500] / 65535 --- 436 + [ 9501 - 10000] / 65535 --- 397 + [10001 - 10500] / 65535 --- 417 + [10501 - 11000] / 65535 --- 399 + [11001 - 11500] / 65535 --- 397 + [11501 - 12000] / 65535 --- 397 + [12001 - 12500] / 65535 --- 401 + [12501 - 13000] / 65535 --- 460 + [13001 - 13500] / 65535 --- 396 + [13501 - 14000] / 65535 --- 408 + [14001 - 14500] / 65535 --- 416 + [14501 - 15000] / 65535 --- 399 + [15001 - 15500] / 65535 --- 398 + [15501 - 16000] / 65535 --- 438 + [16001 - 16500] / 65535 --- 401 + [16501 - 17000] / 65535 --- 418 + [17001 - 17500] / 65535 --- 398 + [17501 - 18000] / 65535 --- 402 + [18001 - 18500] / 65535 --- 399 + [18501 - 19000] / 65535 --- 398 + [19001 - 19500] / 65535 --- 475 + [19501 - 20000] / 65535 --- 398 + [20001 - 20500] / 65535 --- 397 + [20501 - 21000] / 65535 --- 407 + [21001 - 21500] / 65535 --- 398 + [21501 - 22000] / 65535 --- 420 + [22001 - 22500] / 65535 --- 398 + [22501 - 23000] / 65535 --- 461 + [23001 - 23500] / 65535 --- 405 + [23501 - 24000] / 65535 --- 413 + [24001 - 24500] / 65535 --- 453 + [24501 - 25000] / 65535 --- 400 + [25001 - 25500] / 65535 --- 399 + [25501 - 26000] / 65535 --- 478 + [26001 - 26500] / 65535 --- 400 + [26501 - 27000] / 65535 --- 495 + [27001 - 27500] / 65535 --- 398 + [27501 - 28000] / 65535 --- 421 + [28001 - 28500] / 65535 --- 397 + [28501 - 29000] / 65535 --- 401 + [29001 - 29500] / 65535 --- 458 + [29501 - 30000] / 65535 --- 399 + [30001 - 30500] / 65535 --- 422 + [30501 - 31000] / 65535 --- 455 + [31001 - 31500] / 65535 --- 399 + [31501 - 32000] / 65535 --- 399 + [32001 - 32500] / 65535 --- 425 + [32501 - 33000] / 65535 --- 425 + [33001 - 33500] / 65535 --- 395 + [33501 - 34000] / 65535 --- 401 + [34001 - 34500] / 65535 --- 402 + [34501 - 35000] / 65535 --- 400 + [35001 - 35500] / 65535 --- 507 + [35501 - 36000] / 65535 --- 399 + [36001 - 36500] / 65535 --- 436 + [36501 - 37000] / 65535 --- 400 + [37001 - 37500] / 65535 --- 415 + [37501 - 38000] / 65535 --- 426 + [38001 - 38500] / 65535 --- 398 + [38501 - 39000] / 65535 --- 402 + [39001 - 39500] / 65535 --- 401 + [39501 - 40000] / 65535 --- 399 + [40001 - 40500] / 65535 --- 501 + [40501 - 41000] / 65535 --- 432 + [41001 - 41500] / 65535 --- 399 + [41501 - 42000] / 65535 --- 399 + [42001 - 42500] / 65535 --- 399 + [42501 - 43000] / 65535 --- 496 + [43001 - 43500] / 65535 --- 398 + [43501 - 44000] / 65535 --- 448 + [44001 - 44500] / 65535 --- 497 + [44501 - 45000] / 65535 --- 425 + [45001 - 45500] / 65535 --- 395 + [45501 - 46000] / 65535 --- 430 + [46001 - 46500] / 65535 --- 420 + [46501 - 47000] / 65535 --- 497 + [47001 - 47500] / 65535 --- 424 + [47501 - 48000] / 65535 --- 409 + [48001 - 48500] / 65535 --- 421 + [48501 - 49000] / 65535 --- 400 + [49001 - 49500] / 65535 --- 489 + [49501 - 50000] / 65535 --- 439 + [50001 - 50500] / 65535 --- 424 + [50501 - 51000] / 65535 --- 399 + [51001 - 51500] / 65535 --- 401 + [51501 - 52000] / 65535 --- 400 + [52001 - 52500] / 65535 --- 400 + [52501 - 53000] / 65535 --- 432 + [53001 - 53500] / 65535 --- 511 + [53501 - 54000] / 65535 --- 397 + [54001 - 54500] / 65535 --- 398 + [54501 - 55000] / 65535 --- 429 + [55001 - 55500] / 65535 --- 396 + [55501 - 56000] / 65535 --- 493 + [56001 - 56500] / 65535 --- 424 + [56501 - 57000] / 65535 --- 397 + [57001 - 57500] / 65535 --- 425 + [57501 - 58000] / 65535 --- 417 + [58001 - 58500] / 65535 --- 491 + [58501 - 59000] / 65535 --- 398 + [59001 - 59500] / 65535 --- 463 + [59501 - 60000] / 65535 --- 424 + [60001 - 60500] / 65535 --- 399 + [60501 - 61000] / 65535 --- 397 + [61001 - 61500] / 65535 --- 441 + [61501 - 62000] / 65535 --- 401 + [62001 - 62500] / 65535 --- 590 + [62501 - 63000] / 65535 --- 392 + [63001 - 63500] / 65535 --- 423 + [63501 - 64000] / 65535 --- 397 + [64001 - 64500] / 65535 --- 397 + [64501 - 65000] / 65535 --- 392 + [65001 - 65500] / 65535 --- 399 + [65501 - 65535] / 65535 --- 28 \ No newline at end of file
diff --git a/tools/win/CreateTempFilesPerfEvaluation/ReadMe.txt b/tools/win/CreateTempFilesPerfEvaluation/ReadMe.txt new file mode 100644 index 0000000..c510d8a --- /dev/null +++ b/tools/win/CreateTempFilesPerfEvaluation/ReadMe.txt
@@ -0,0 +1,55 @@ +[Motivation] +This tool is to compare the time cost of creating temporary files between using +GetTempFileName() Windows API and using the GUID-based method, especially when +there are already tens of thousands of temporary files in the target directory. + +The problem setting can be referred to +https://bugs.chromium.org/p/chromium/issues/detail?id=711534 + +[How to use it] +Please download the files (.cc, .sln, .vcxproj) and compile the code in Visual +Studio. Run "CreateTempFilesPerfEval.exe" either from the build directory or +from Visual Studio. No parameters are needed. This tool allows interaction with +the users. Once launched, you will see the following message on the console: + +"Please enter # of files to create +(maximum 65535), or "quit" to end the program :" + +Simply type in a number less than 65536 (e.g. 1000) and you will see: + +"Please select method to create temp file names, +"t" for GetTempFileName +"g" for GUID-based +"b" for both +or "quit" to end the program :" + +Just select the method(s) you want to try (e.g., "b"), and you will get output +like below: + +GetTempFileName Performance: +created / total --- time cost in ms + 500 / 1000 --- 403 + 1000 / 1000 --- 402 +File creation succeeds at +C:\Users\chengx\AppData\Local\Temp\TempDirGetTempFileName\, now clean all of them! +C:\Users\chengx\AppData\Local\Temp\TempDirGetTempFileName\ directory is deleted! + +GUID-based Performance: +created / total --- time cost in ms + 500 / 1000 --- 412 + 1000 / 1000 --- 411 +File creation succeeds at +C:\Users\chengx\AppData\Local\Temp\TempDirGuid\, now clean all of them! +C:\Users\chengx\AppData\Local\Temp\TempDirGuid\ directory is deleted! + +It shows the time cost of creating every 500 temp files in milliseconds. + +The temporary directories are created in the "Temp" directory as shown above. +The temp files are then created in the newly created temporary directories. +All of them are deleted by the program automatically. If the deletion fails for +some reason, you will see: + +"[Attention] C:\Users\chengx\AppData\Local\Temp\TempDirGuid\ directory's deletion +fails, please take a look by yourself!" + +
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index e703233..9aa621d 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -184,7 +184,7 @@ return nullptr; base::win::ScopedComPtr<AXPlatformNodeWin> ax_platform_node; accessible->QueryInterface(ax_platform_node.Receive()); - return ax_platform_node.get(); + return ax_platform_node.Get(); } // @@ -258,7 +258,7 @@ if (S_OK == parent_accessible->get_accChild(childid_index, child_dispatch.Receive()) && S_OK == child_dispatch.QueryInterface(child_accessible.Receive())) { - if (child_accessible.get() == this) + if (child_accessible.Get() == this) return index - 1; } }
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc index 85f9940..5dcfb79 100644 --- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -95,9 +95,9 @@ ScopedComPtr<IAccessible2> ToIAccessible2( ScopedComPtr<IAccessible> accessible) { - CHECK(accessible.get()); + CHECK(accessible.Get()); ScopedComPtr<IServiceProvider> service_provider; - service_provider.QueryFrom(accessible.get()); + service_provider.QueryFrom(accessible.Get()); ScopedComPtr<IAccessible2> result; CHECK(SUCCEEDED( service_provider->QueryService(IID_IAccessible2, result.Receive()))); @@ -291,21 +291,21 @@ { ScopedComPtr<IDispatch> result; EXPECT_EQ(S_OK, root_iaccessible->get_accChild(SELF, result.Receive())); - EXPECT_EQ(result.get(), root_iaccessible); + EXPECT_EQ(result.Get(), root_iaccessible); } { ScopedComPtr<IDispatch> result; ScopedVariant child1(1); EXPECT_EQ(S_OK, root_iaccessible->get_accChild(child1, result.Receive())); - EXPECT_EQ(result.get(), button_iaccessible); + EXPECT_EQ(result.Get(), button_iaccessible); } { ScopedComPtr<IDispatch> result; ScopedVariant child2(2); EXPECT_EQ(S_OK, root_iaccessible->get_accChild(child2, result.Receive())); - EXPECT_EQ(result.get(), checkbox_iaccessible); + EXPECT_EQ(result.Get(), checkbox_iaccessible); } { @@ -327,7 +327,7 @@ ScopedVariant button_id_variant(button_unique_id); EXPECT_EQ(S_OK, root_iaccessible->get_accChild(button_id_variant, result.Receive())); - EXPECT_EQ(result.get(), button_iaccessible); + EXPECT_EQ(result.Get(), button_iaccessible); } // We shouldn't be able to ask for the root node by its unique ID @@ -348,13 +348,13 @@ { ScopedComPtr<IDispatch> result; EXPECT_EQ(S_OK, button_iaccessible->get_accParent(result.Receive())); - EXPECT_EQ(result.get(), root_iaccessible); + EXPECT_EQ(result.Get(), root_iaccessible); } { ScopedComPtr<IDispatch> result; EXPECT_EQ(S_OK, checkbox_iaccessible->get_accParent(result.Receive())); - EXPECT_EQ(result.get(), root_iaccessible); + EXPECT_EQ(result.Get(), root_iaccessible); } { @@ -409,7 +409,7 @@ ScopedComPtr<IAccessible2> ia2_text_field = ToIAccessible2(GetRootIAccessible()); ScopedComPtr<IAccessibleText> text_field; - text_field.QueryFrom(ia2_text_field.get()); + text_field.QueryFrom(ia2_text_field.Get()); ASSERT_NE(nullptr, text_field); EXPECT_HRESULT_SUCCEEDED(text_field->setSelection(0, 0, 1));
diff --git a/ui/app_list/app_list_model.cc b/ui/app_list/app_list_model.cc index cb001bc..db59138 100644 --- a/ui/app_list/app_list_model.cc +++ b/ui/app_list/app_list_model.cc
@@ -361,6 +361,11 @@ observer.OnSearchEngineIsGoogleChanged(is_google); } +void AppListModel::SetSearchAnswerAvailable(bool has_answer) { + for (auto& observer : observers_) + observer.OnSearchAnswerAvailableChanged(has_answer); +} + // Private methods void AppListModel::OnListItemMoved(size_t from_index,
diff --git a/ui/app_list/app_list_model.h b/ui/app_list/app_list_model.h index 1d0644a7..2a413e7 100644 --- a/ui/app_list/app_list_model.h +++ b/ui/app_list/app_list_model.h
@@ -166,6 +166,8 @@ void SetSearchEngineIsGoogle(bool is_google); bool search_engine_is_google() const { return search_engine_is_google_; } + void SetSearchAnswerAvailable(bool has_answer); + // Filters the given |results| by |display_type|. The returned list is // truncated to |max_results|. static std::vector<SearchResult*> FilterSearchResultsByDisplayType(
diff --git a/ui/app_list/app_list_model_observer.h b/ui/app_list/app_list_model_observer.h index 09cccc0..fafa2c3 100644 --- a/ui/app_list/app_list_model_observer.h +++ b/ui/app_list/app_list_model_observer.h
@@ -39,6 +39,9 @@ // Triggered when the search engine is changed to and from Google. virtual void OnSearchEngineIsGoogleChanged(bool is_google) {} + // Triggered when the availability of the search answer is changed. + virtual void OnSearchAnswerAvailableChanged(bool has_answer) {} + protected: virtual ~AppListModelObserver() {} };
diff --git a/ui/app_list/app_list_switches.cc b/ui/app_list/app_list_switches.cc index 3d16aa6..19bcc41 100644 --- a/ui/app_list/app_list_switches.cc +++ b/ui/app_list/app_list_switches.cc
@@ -10,6 +10,10 @@ namespace app_list { namespace switches { +// If empty, search answers in the app app list are disabled, otherwise the URL +// of the answer server. +const char kAnswerServerUrl[] = "answer-server-url"; + // Specifies the chrome-extension:// URL for the contents of an additional page // added to the app launcher. const char kCustomLauncherPage[] = "custom-launcher-page"; @@ -74,5 +78,10 @@ return true; } +std::string AnswerServerUrl() { + return base::CommandLine::ForCurrentProcess()->GetSwitchValueNative( + kAnswerServerUrl); +} + } // namespace switches } // namespace app_list
diff --git a/ui/app_list/app_list_switches.h b/ui/app_list/app_list_switches.h index 487d84d..3964f3ed 100644 --- a/ui/app_list/app_list_switches.h +++ b/ui/app_list/app_list_switches.h
@@ -5,6 +5,8 @@ #ifndef UI_APP_LIST_APP_LIST_SWITCHES_H_ #define UI_APP_LIST_APP_LIST_SWITCHES_H_ +#include <string> + #include "build/build_config.h" #include "ui/app_list/app_list_export.h" @@ -12,6 +14,7 @@ namespace switches { // Please keep these flags sorted (but keep enable/disable pairs together). +APP_LIST_EXPORT extern const char kAnswerServerUrl[]; APP_LIST_EXPORT extern const char kCustomLauncherPage[]; APP_LIST_EXPORT extern const char kDisableAppListDismissOnBlur[]; APP_LIST_EXPORT extern const char kEnableAppList[]; @@ -34,6 +37,8 @@ bool APP_LIST_EXPORT IsDriveSearchInChromeLauncherEnabled(); +std::string APP_LIST_EXPORT AnswerServerUrl(); + } // namespace switches } // namespace app_list
diff --git a/ui/app_list/app_list_view_delegate.h b/ui/app_list/app_list_view_delegate.h index 3d61cb1..9bdf665 100644 --- a/ui/app_list/app_list_view_delegate.h +++ b/ui/app_list/app_list_view_delegate.h
@@ -83,6 +83,10 @@ virtual std::vector<views::View*> CreateCustomPageWebViews( const gfx::Size& size) = 0; + // Gets the web view for the search answer. The caller doesn't take the + // ownership of the returned view. + virtual views::View* GetSearchAnswerWebView() = 0; + // Invoked when the custom launcher page's animation changes. virtual void CustomLauncherPageAnimationChanged(double progress) = 0;
diff --git a/ui/app_list/test/app_list_test_view_delegate.cc b/ui/app_list/test/app_list_test_view_delegate.cc index 9202127b..efef3e22 100644 --- a/ui/app_list/test/app_list_test_view_delegate.cc +++ b/ui/app_list/test/app_list_test_view_delegate.cc
@@ -80,6 +80,10 @@ return std::vector<views::View*>(); } +views::View* AppListTestViewDelegate::GetSearchAnswerWebView() { + return nullptr; +} + bool AppListTestViewDelegate::IsSpeechRecognitionEnabled() { return false; }
diff --git a/ui/app_list/test/app_list_test_view_delegate.h b/ui/app_list/test/app_list_test_view_delegate.h index 5cafa04f..1d4c242 100644 --- a/ui/app_list/test/app_list_test_view_delegate.h +++ b/ui/app_list/test/app_list_test_view_delegate.h
@@ -68,6 +68,7 @@ views::View* CreateStartPageWebView(const gfx::Size& size) override; std::vector<views::View*> CreateCustomPageWebViews( const gfx::Size& size) override; + views::View* GetSearchAnswerWebView() override; void CustomLauncherPageAnimationChanged(double progress) override {} void CustomLauncherPagePopSubpage() override {} bool IsSpeechRecognitionEnabled() override;
diff --git a/ui/app_list/views/contents_view.cc b/ui/app_list/views/contents_view.cc index 6ee2eb2..5316ace 100644 --- a/ui/app_list/views/contents_view.cc +++ b/ui/app_list/views/contents_view.cc
@@ -23,16 +23,19 @@ #include "ui/app_list/views/start_page_view.h" #include "ui/events/event.h" #include "ui/resources/grit/ui_resources.h" +#include "ui/views/layout/box_layout.h" #include "ui/views/view_model.h" #include "ui/views/widget/widget.h" namespace app_list { ContentsView::ContentsView(AppListMainView* app_list_main_view) - : apps_container_view_(nullptr), + : model_(nullptr), + apps_container_view_(nullptr), search_results_page_view_(nullptr), start_page_view_(nullptr), custom_page_view_(nullptr), + search_answer_container_view_(nullptr), app_list_main_view_(app_list_main_view), page_before_search_(0) { pagination_model_.SetTransitionDurations(kPageTransitionDurationInMs, @@ -42,10 +45,13 @@ ContentsView::~ContentsView() { pagination_model_.RemoveObserver(this); + if (model_) + model_->RemoveObserver(this); } void ContentsView::Init(AppListModel* model) { DCHECK(model); + model_ = model; AppListViewDelegate* view_delegate = app_list_main_view_->view_delegate(); @@ -67,6 +73,19 @@ // Search results UI. search_results_page_view_ = new SearchResultPageView(); + // Search answer container UI. + search_answer_container_view_ = new views::View; + search_answer_container_view_->SetVisible(false); + views::BoxLayout* answer_container_layout = + new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0); + answer_container_layout->set_main_axis_alignment( + views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); + search_answer_container_view_->SetLayoutManager(answer_container_layout); + views::View* search_answer_view = view_delegate->GetSearchAnswerWebView(); + if (search_answer_view) + search_answer_container_view_->AddChildView(search_answer_view); + search_results_page_view_->AddChildView(search_answer_container_view_); + AppListModel::SearchResults* results = view_delegate->GetModel()->results(); search_results_page_view_->AddSearchResultContainerView( results, new SearchResultListView(app_list_main_view_, view_delegate)); @@ -96,6 +115,8 @@ pagination_model_.SelectPage(initial_page_index, false); ActivePageChanged(); + + model_->AddObserver(this); } void ContentsView::CancelDrag() { @@ -472,4 +493,12 @@ UpdatePageBounds(); } +void ContentsView::OnSearchAnswerAvailableChanged(bool has_answer) { + if (has_answer == search_answer_container_view_->visible()) + return; + + search_answer_container_view_->SetVisible(has_answer); + search_results_page_view_->Layout(); +} + } // namespace app_list
diff --git a/ui/app_list/views/contents_view.h b/ui/app_list/views/contents_view.h index 3946e6d..81e02d0 100644 --- a/ui/app_list/views/contents_view.h +++ b/ui/app_list/views/contents_view.h
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "ui/app_list/app_list_export.h" #include "ui/app_list/app_list_model.h" +#include "ui/app_list/app_list_model_observer.h" #include "ui/app_list/pagination_model.h" #include "ui/app_list/pagination_model_observer.h" #include "ui/views/view.h" @@ -42,7 +43,8 @@ // interface for switching between launcher pages, and animates the transition // between them. class APP_LIST_EXPORT ContentsView : public views::View, - public PaginationModelObserver { + public PaginationModelObserver, + public AppListModelObserver { public: explicit ContentsView(AppListMainView* app_list_main_view); ~ContentsView() override; @@ -133,6 +135,9 @@ void TransitionStarted() override; void TransitionChanged() override; + // Overridden from AppListModelObserver: + void OnSearchAnswerAvailableChanged(bool has_answer) override; + private: // Sets the active launcher page, accounting for whether the change is for // search results. @@ -175,12 +180,19 @@ // launcher-page pagination. PaginationModel* GetAppsPaginationModel(); + // Unowned pointer to application list model. + AppListModel* model_; + // Sub-views of the ContentsView. All owned by the views hierarchy. AppsContainerView* apps_container_view_; SearchResultPageView* search_results_page_view_; StartPageView* start_page_view_; CustomLauncherPageView* custom_page_view_; + // Unowned pointer to the container of the search answer web view. This + // container view is a sub-view of search_results_page_view_. + View* search_answer_container_view_; + // The child page views. Owned by the views hierarchy. std::vector<AppListPage*> app_list_pages_;
diff --git a/ui/aura/mus/window_manager_delegate.cc b/ui/aura/mus/window_manager_delegate.cc index 017d8319..e2f42eb 100644 --- a/ui/aura/mus/window_manager_delegate.cc +++ b/ui/aura/mus/window_manager_delegate.cc
@@ -6,6 +6,8 @@ namespace aura { +void WindowManagerDelegate::OnWmConnected() {} + ui::mojom::EventResult WindowManagerDelegate::OnAccelerator( uint32_t id, const ui::Event& event,
diff --git a/ui/aura/mus/window_manager_delegate.h b/ui/aura/mus/window_manager_delegate.h index 81189a15..6e5b269f 100644 --- a/ui/aura/mus/window_manager_delegate.h +++ b/ui/aura/mus/window_manager_delegate.h
@@ -79,6 +79,9 @@ // the WindowManager. virtual void SetWindowManagerClient(WindowManagerClient* client) = 0; + // Called when the connection to mus has been fully established. + virtual void OnWmConnected(); + // A client requested the bounds of |window| to change to |bounds|. virtual void OnWmSetBounds(Window* window, const gfx::Rect& bounds) = 0;
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc index e96dc13..76187294 100644 --- a/ui/aura/mus/window_tree_client.cc +++ b/ui/aura/mus/window_tree_client.cc
@@ -1422,6 +1422,8 @@ void WindowTreeClient::OnConnect(ClientSpecificId client_id) { client_id_ = client_id; + if (window_manager_delegate_) + window_manager_delegate_->OnWmConnected(); } void WindowTreeClient::WmNewDisplayAdded(
diff --git a/ui/aura/test/aura_test_base.cc b/ui/aura/test/aura_test_base.cc index 81b4a3e..17ce8daf3 100644 --- a/ui/aura/test/aura_test_base.cc +++ b/ui/aura/test/aura_test_base.cc
@@ -157,6 +157,8 @@ void AuraTestBase::SetWindowManagerClient(WindowManagerClient* client) {} +void AuraTestBase::OnWmConnected() {} + void AuraTestBase::OnWmSetBounds(Window* window, const gfx::Rect& bounds) {} bool AuraTestBase::OnWmSetProperty(
diff --git a/ui/aura/test/aura_test_base.h b/ui/aura/test/aura_test_base.h index fec3ac3..f2cb56e3 100644 --- a/ui/aura/test/aura_test_base.h +++ b/ui/aura/test/aura_test_base.h
@@ -97,6 +97,7 @@ // WindowManagerDelegate: void SetWindowManagerClient(WindowManagerClient* client) override; + void OnWmConnected() override; void OnWmSetBounds(Window* window, const gfx::Rect& bounds) override; bool OnWmSetProperty( Window* window,
diff --git a/ui/aura/test/mus/window_tree_client_private.cc b/ui/aura/test/mus/window_tree_client_private.cc index c1ca30b..da7ab00 100644 --- a/ui/aura/test/mus/window_tree_client_private.cc +++ b/ui/aura/test/mus/window_tree_client_private.cc
@@ -81,6 +81,11 @@ old_capture ? WindowPortMus::Get(old_capture)->server_id() : 0); } +void WindowTreeClientPrivate::CallOnConnect() { + const ClientSpecificId client_id = 1; + tree_client_impl_->OnConnect(client_id); +} + void WindowTreeClientPrivate::SetTreeAndClientId( ui::mojom::WindowTree* window_tree, ClientSpecificId client_id) {
diff --git a/ui/aura/test/mus/window_tree_client_private.h b/ui/aura/test/mus/window_tree_client_private.h index e600127b..3c2279d 100644 --- a/ui/aura/test/mus/window_tree_client_private.h +++ b/ui/aura/test/mus/window_tree_client_private.h
@@ -55,6 +55,8 @@ void CallOnCaptureChanged(Window* new_capture, Window* old_capture); + void CallOnConnect(); + // Sets the WindowTree and client id. void SetTreeAndClientId(ui::mojom::WindowTree* window_tree, ClientSpecificId client_id);
diff --git a/ui/base/dragdrop/os_exchange_data_provider_win.cc b/ui/base/dragdrop/os_exchange_data_provider_win.cc index 4a23569..44e6cb6 100644 --- a/ui/base/dragdrop/os_exchange_data_provider_win.cc +++ b/ui/base/dragdrop/os_exchange_data_provider_win.cc
@@ -404,7 +404,7 @@ } bool OSExchangeDataProviderWin::GetString(base::string16* data) const { - return ClipboardUtil::GetPlainText(source_object_.get(), data); + return ClipboardUtil::GetPlainText(source_object_.Get(), data); } bool OSExchangeDataProviderWin::GetURLAndTitle( @@ -413,12 +413,12 @@ base::string16* title) const { base::string16 url_str; bool success = ClipboardUtil::GetUrl( - source_object_.get(), url, title, + source_object_.Get(), url, title, policy == OSExchangeData::CONVERT_FILENAMES ? true : false); if (success) { DCHECK(url->is_valid()); return true; - } else if (GetPlainTextURL(source_object_.get(), url)) { + } else if (GetPlainTextURL(source_object_.Get(), url)) { if (url->is_valid()) *title = net::GetSuggestedFilename(*url, "", "", "", "", std::string()); else @@ -430,7 +430,7 @@ bool OSExchangeDataProviderWin::GetFilename(base::FilePath* path) const { std::vector<base::string16> filenames; - bool success = ClipboardUtil::GetFilenames(source_object_.get(), &filenames); + bool success = ClipboardUtil::GetFilenames(source_object_.Get(), &filenames); if (success) *path = base::FilePath(filenames[0]); return success; @@ -440,7 +440,7 @@ std::vector<FileInfo>* filenames) const { std::vector<base::string16> filenames_local; bool success = - ClipboardUtil::GetFilenames(source_object_.get(), &filenames_local); + ClipboardUtil::GetFilenames(source_object_.Get(), &filenames_local); if (success) { for (size_t i = 0; i < filenames_local.size(); ++i) filenames->push_back( @@ -472,7 +472,7 @@ base::FilePath* filename, std::string* file_contents) const { base::string16 filename_str; - if (!ClipboardUtil::GetFileContents(source_object_.get(), &filename_str, + if (!ClipboardUtil::GetFileContents(source_object_.Get(), &filename_str, file_contents)) { return false; } @@ -483,34 +483,34 @@ bool OSExchangeDataProviderWin::GetHtml(base::string16* html, GURL* base_url) const { std::string url; - bool success = ClipboardUtil::GetHtml(source_object_.get(), html, &url); + bool success = ClipboardUtil::GetHtml(source_object_.Get(), html, &url); if (success) *base_url = GURL(url); return success; } bool OSExchangeDataProviderWin::HasString() const { - return ClipboardUtil::HasPlainText(source_object_.get()); + return ClipboardUtil::HasPlainText(source_object_.Get()); } bool OSExchangeDataProviderWin::HasURL( OSExchangeData::FilenameToURLPolicy policy) const { return (ClipboardUtil::HasUrl( - source_object_.get(), + source_object_.Get(), policy == OSExchangeData::CONVERT_FILENAMES ? true : false) || - HasPlainTextURL(source_object_.get())); + HasPlainTextURL(source_object_.Get())); } bool OSExchangeDataProviderWin::HasFile() const { - return ClipboardUtil::HasFilenames(source_object_.get()); + return ClipboardUtil::HasFilenames(source_object_.Get()); } bool OSExchangeDataProviderWin::HasFileContents() const { - return ClipboardUtil::HasFileContents(source_object_.get()); + return ClipboardUtil::HasFileContents(source_object_.Get()); } bool OSExchangeDataProviderWin::HasHtml() const { - return ClipboardUtil::HasHtml(source_object_.get()); + return ClipboardUtil::HasHtml(source_object_.Get()); } bool OSExchangeDataProviderWin::HasCustomFormat(
diff --git a/ui/base/dragdrop/os_exchange_data_win_unittest.cc b/ui/base/dragdrop/os_exchange_data_win_unittest.cc index 15ee9635..51eae0a 100644 --- a/ui/base/dragdrop/os_exchange_data_win_unittest.cc +++ b/ui/base/dragdrop/os_exchange_data_win_unittest.cc
@@ -104,7 +104,7 @@ medium.pUnkForRelease = NULL; EXPECT_EQ(S_OK, com_data->SetData(&format_etc, &medium, TRUE)); } - EXPECT_EQ(1u, static_cast<DataObjectImpl*>(com_data.get())->size()); + EXPECT_EQ(1u, static_cast<DataObjectImpl*>(com_data.Get())->size()); // Construct a new object with the old object so that we can use our access // APIs. @@ -184,7 +184,7 @@ base::win::ScopedComPtr<IDataObject> com_data( OSExchangeDataProviderWin::GetIDataObject(data)); base::win::ScopedComPtr<IEnumFORMATETC> enumerator; - EXPECT_EQ(S_OK, com_data.get()->EnumFormatEtc(DATADIR_GET, + EXPECT_EQ(S_OK, com_data.Get()->EnumFormatEtc(DATADIR_GET, enumerator.Receive())); // Test that we can get one item. @@ -238,8 +238,8 @@ EXPECT_EQ(S_OK, enumerator->Reset()); EXPECT_EQ(S_OK, enumerator->Skip(1)); base::win::ScopedComPtr<IEnumFORMATETC> cloned_enumerator; - EXPECT_EQ(S_OK, enumerator.get()->Clone(cloned_enumerator.Receive())); - EXPECT_EQ(S_OK, enumerator.get()->Reset()); + EXPECT_EQ(S_OK, enumerator.Get()->Clone(cloned_enumerator.Receive())); + EXPECT_EQ(S_OK, enumerator.Get()->Reset()); { ULONG retrieved = 0;
diff --git a/ui/base/win/shell.cc b/ui/base/win/shell.cc index cdc0a8d..8d06fc2 100644 --- a/ui/base/win/shell.cc +++ b/ui/base/win/shell.cc
@@ -109,7 +109,7 @@ return false; return base::win::SetBooleanValueForPropertyStore( - pps.get(), PKEY_AppUserModel_PreventPinning, true); + pps.Get(), PKEY_AppUserModel_PreventPinning, true); } // TODO(calamity): investigate moving this out of the UI thread as COM @@ -132,24 +132,24 @@ return; if (!app_id.empty()) - base::win::SetAppIdForPropertyStore(pps.get(), app_id.c_str()); + base::win::SetAppIdForPropertyStore(pps.Get(), app_id.c_str()); if (!app_icon_path.empty()) { // Always add the icon index explicitly to prevent bad interaction with the // index notation when file path has commas. base::win::SetStringValueForPropertyStore( - pps.get(), PKEY_AppUserModel_RelaunchIconResource, + pps.Get(), PKEY_AppUserModel_RelaunchIconResource, base::StringPrintf(L"%ls,%d", app_icon_path.value().c_str(), app_icon_index) .c_str()); } if (!relaunch_command.empty()) { base::win::SetStringValueForPropertyStore( - pps.get(), PKEY_AppUserModel_RelaunchCommand, + pps.Get(), PKEY_AppUserModel_RelaunchCommand, relaunch_command.c_str()); } if (!relaunch_display_name.empty()) { base::win::SetStringValueForPropertyStore( - pps.get(), PKEY_AppUserModel_RelaunchDisplayNameResource, + pps.Get(), PKEY_AppUserModel_RelaunchDisplayNameResource, relaunch_display_name.c_str()); } }
diff --git a/ui/events/blink/blink_event_util.cc b/ui/events/blink/blink_event_util.cc index 6d9ccce..7b3ee48 100644 --- a/ui/events/blink/blink_event_util.cc +++ b/ui/events/blink/blink_event_util.cc
@@ -343,6 +343,7 @@ event->moved_beyond_slop_region |= old_event.moved_beyond_slop_region; event->dispatch_type = MergeDispatchTypes(old_event.dispatch_type, event_to_coalesce.dispatch_type); + event->unique_touch_event_id = old_event.unique_touch_event_id; } bool CanCoalesce(const WebGestureEvent& event_to_coalesce,
diff --git a/ui/file_manager/file_manager/foreground/js/compiled_resources2.gyp b/ui/file_manager/file_manager/foreground/js/compiled_resources2.gyp index 12419df3..62e471e 100644 --- a/ui/file_manager/file_manager/foreground/js/compiled_resources2.gyp +++ b/ui/file_manager/file_manager/foreground/js/compiled_resources2.gyp
@@ -33,10 +33,15 @@ # 'target_name': 'app_state_controller', # 'includes': ['../../../compile_js2.gypi'], # }, -# { -# 'target_name': 'column_visibility_controller', -# 'includes': ['../../../compile_js2.gypi'], -# }, + { + 'target_name': 'column_visibility_controller', + 'dependencies': [ + '../../common/js/compiled_resources2.gyp:volume_manager_common', + 'directory_model', + 'ui/compiled_resources2.gyp:file_manager_ui', + ], + 'includes': ['../../../compile_js2.gypi'], + }, { 'target_name': 'constants', 'includes': ['../../../compile_js2.gypi'], @@ -82,14 +87,22 @@ # 'target_name': 'directory_tree_naming_controller', # 'includes': ['../../../compile_js2.gypi'], # }, -# { -# 'target_name': 'elements_importer', -# 'includes': ['../../../compile_js2.gypi'], -# }, -# { -# 'target_name': 'empty_folder_controller', -# 'includes': ['../../../compile_js2.gypi'], -# }, + { + 'target_name': 'elements_importer', + 'dependencies': [ + '<(EXTERNS_GYP):metrics_private', + ], + 'includes': ['../../../compile_js2.gypi'], + }, + { + 'target_name': 'empty_folder_controller', + 'dependencies': [ + 'directory_model', + 'file_list_model', + 'ui/compiled_resources2.gyp:empty_folder', + ], + 'includes': ['../../../compile_js2.gypi'], + }, { 'target_name': 'file_list_model', 'dependencies': [ @@ -111,17 +124,26 @@ # { # 'target_name': 'file_selection', # 'dependencies': [ +# '../../common/js/compiled_resources2.gyp:file_type', # '../../common/js/compiled_resources2.gyp:util', # '../../common/js/compiled_resources2.gyp:volume_manager_common', # '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', # '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', +# 'constants', +# 'file_manager', # ], # 'includes': ['../../../compile_js2.gypi'], # }, -# { -# 'target_name': 'file_tasks', -# 'includes': ['../../../compile_js2.gypi'], -# }, + { + 'target_name': 'file_tasks', + 'dependencies': [ + 'directory_model', + 'metadata/compiled_resources2.gyp:metadata_model', + 'ui/compiled_resources2.gyp:file_manager_ui', + 'volume_manager_wrapper', + ], + 'includes': ['../../../compile_js2.gypi'], + }, # { # 'target_name': 'file_transfer_controller', # 'includes': ['../../../compile_js2.gypi'], @@ -197,10 +219,13 @@ # 'target_name': 'metadata_update_controller', # 'includes': ['../../../compile_js2.gypi'], # }, -# { -# 'target_name': 'metrics_start', -# 'includes': ['../../../compile_js2.gypi'], -# }, + { + 'target_name': 'metrics_start', + 'dependencies': [ + '../../common/js/compiled_resources2.gyp:metrics', + ], + 'includes': ['../../../compile_js2.gypi'], + }, { 'target_name': 'mouse_inactivity_watcher', 'includes': ['../../../compile_js2.gypi'], @@ -249,10 +274,16 @@ ], 'includes': ['../../../compile_js2.gypi'], }, -# { -# 'target_name': 'quick_view_uma', -# 'includes': ['../../../compile_js2.gypi'], -# }, + { + 'target_name': 'quick_view_uma', + 'dependencies': [ + '../../common/js/compiled_resources2.gyp:file_type', + 'dialog_type', + 'file_tasks', + 'volume_manager_wrapper', + ], + 'includes': ['../../../compile_js2.gypi'], + }, # { # 'target_name': 'scan_controller', # 'includes': ['../../../compile_js2.gypi'], @@ -276,14 +307,22 @@ ], 'includes': ['../../../compile_js2.gypi'], }, -# { -# 'target_name': 'sort_menu_controller', -# 'includes': ['../../../compile_js2.gypi'], -# }, -# { -# 'target_name': 'spinner_controller', -# 'includes': ['../../../compile_js2.gypi'], -# }, + { + 'target_name': 'sort_menu_controller', + 'dependencies': [ + '../elements/compiled_resources2.gyp:files_toggle_ripple', + '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:context_menu_button', + 'file_list_model', + ], + 'includes': ['../../../compile_js2.gypi'], + }, + { + 'target_name': 'spinner_controller', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/cr/compiled_resources2.gyp:event_target', + ], + 'includes': ['../../../compile_js2.gypi'], + }, # { # 'target_name': 'task_controller', # 'includes': ['../../../compile_js2.gypi'],
diff --git a/ui/gfx/font_fallback_win.cc b/ui/gfx/font_fallback_win.cc index 8af5604..6352cfe 100644 --- a/ui/gfx/font_fallback_win.cc +++ b/ui/gfx/font_fallback_win.cc
@@ -387,7 +387,7 @@ : DWRITE_READING_DIRECTION_LEFT_TO_RIGHT; if (FAILED(Microsoft::WRL::MakeAndInitialize<gfx::win::TextAnalysisSource>( text_analysis.Receive(), text, locale.c_str(), - number_substitution.get(), reading_direction))) { + number_substitution.Get(), reading_direction))) { return false; } base::string16 original_name = base::UTF8ToUTF16(font.GetFontName()); @@ -395,7 +395,7 @@ if (font.GetStyle() & Font::ITALIC) font_style = DWRITE_FONT_STYLE_ITALIC; if (FAILED(fallback->MapCharacters( - text_analysis.get(), 0, text_length, nullptr, original_name.c_str(), + text_analysis.Get(), 0, text_length, nullptr, original_name.c_str(), static_cast<DWRITE_FONT_WEIGHT>(font.GetWeight()), font_style, DWRITE_FONT_STRETCH_NORMAL, &mapped_length, mapped_font.Receive(), &scale))) { @@ -404,7 +404,7 @@ if (mapped_font) { base::string16 name; - if (FAILED(GetFamilyNameFromDirectWriteFont(mapped_font.get(), &name))) + if (FAILED(GetFamilyNameFromDirectWriteFont(mapped_font.Get(), &name))) return false; *result = Font(base::UTF16ToUTF8(name), font.GetFontSize() * scale); return true;
diff --git a/ui/gfx/linux/client_native_pixmap_dmabuf.cc b/ui/gfx/linux/client_native_pixmap_dmabuf.cc index d656c338..1bb441dc 100644 --- a/ui/gfx/linux/client_native_pixmap_dmabuf.cc +++ b/ui/gfx/linux/client_native_pixmap_dmabuf.cc
@@ -7,36 +7,35 @@ #include <fcntl.h> #include <linux/version.h> #include <stddef.h> +#include <sys/ioctl.h> #include <sys/mman.h> #include <xf86drm.h> #include "base/debug/crash_logging.h" #include "base/memory/ptr_util.h" +#include "base/posix/eintr_wrapper.h" #include "base/process/memory.h" #include "base/process/process_metrics.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) +#include <linux/dma-buf.h> +#else #include <linux/types.h> -struct local_dma_buf_sync { +struct dma_buf_sync { __u64 flags; }; -#define LOCAL_DMA_BUF_SYNC_READ (1 << 0) -#define LOCAL_DMA_BUF_SYNC_WRITE (2 << 0) -#define LOCAL_DMA_BUF_SYNC_RW \ - (LOCAL_DMA_BUF_SYNC_READ | LOCAL_DMA_BUF_SYNC_WRITE) -#define LOCAL_DMA_BUF_SYNC_START (0 << 2) -#define LOCAL_DMA_BUF_SYNC_END (1 << 2) +#define DMA_BUF_SYNC_READ (1 << 0) +#define DMA_BUF_SYNC_WRITE (2 << 0) +#define DMA_BUF_SYNC_RW (DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE) +#define DMA_BUF_SYNC_START (0 << 2) +#define DMA_BUF_SYNC_END (1 << 2) -#define LOCAL_DMA_BUF_BASE 'b' -#define LOCAL_DMA_BUF_IOCTL_SYNC \ - _IOW(LOCAL_DMA_BUF_BASE, 0, struct local_dma_buf_sync) - -#else -#include <linux/dma-buf.h> +#define DMA_BUF_BASE 'b' +#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync) #endif namespace gfx { @@ -44,25 +43,19 @@ namespace { void PrimeSyncStart(int dmabuf_fd) { - struct local_dma_buf_sync sync_start = {0}; + struct dma_buf_sync sync_start = {0}; - sync_start.flags = LOCAL_DMA_BUF_SYNC_START | LOCAL_DMA_BUF_SYNC_RW; -#if DCHECK_IS_ON() - int rv = -#endif - drmIoctl(dmabuf_fd, LOCAL_DMA_BUF_IOCTL_SYNC, &sync_start); - DPLOG_IF(ERROR, rv) << "Failed DMA_BUF_SYNC_START"; + sync_start.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW; + int rv = HANDLE_EINTR(ioctl(dmabuf_fd, DMA_BUF_IOCTL_SYNC, &sync_start)); + PLOG_IF(ERROR, rv) << "Failed DMA_BUF_SYNC_START"; } void PrimeSyncEnd(int dmabuf_fd) { - struct local_dma_buf_sync sync_end = {0}; + struct dma_buf_sync sync_end = {0}; - sync_end.flags = LOCAL_DMA_BUF_SYNC_END | LOCAL_DMA_BUF_SYNC_RW; -#if DCHECK_IS_ON() - int rv = -#endif - drmIoctl(dmabuf_fd, LOCAL_DMA_BUF_IOCTL_SYNC, &sync_end); - DPLOG_IF(ERROR, rv) << "Failed DMA_BUF_SYNC_END"; + sync_end.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW; + int rv = HANDLE_EINTR(ioctl(dmabuf_fd, DMA_BUF_IOCTL_SYNC, &sync_end)); + PLOG_IF(ERROR, rv) << "Failed DMA_BUF_SYNC_END"; } } // namespace
diff --git a/ui/gfx/platform_font_win.cc b/ui/gfx/platform_font_win.cc index e8cf245..e3bbd20 100644 --- a/ui/gfx/platform_font_win.cc +++ b/ui/gfx/platform_font_win.cc
@@ -111,9 +111,9 @@ return hr; LOGFONT converted_font = {0}; - hr = gdi_interop->ConvertFontFaceToLOGFONT(font_face.get(), &converted_font); + hr = gdi_interop->ConvertFontFaceToLOGFONT(font_face.Get(), &converted_font); if (SUCCEEDED(hr)) { - hr = font_collection->GetFontFromFontFace(font_face.get(), dwrite_font); + hr = font_collection->GetFontFromFontFace(font_face.Get(), dwrite_font); if (SUCCEEDED(hr)) { wcscpy_s(font_info->lfFaceName, arraysize(font_info->lfFaceName), converted_font.lfFaceName);
diff --git a/ui/gfx/win/direct_manipulation.cc b/ui/gfx/win/direct_manipulation.cc index f391f07..c6572f9 100644 --- a/ui/gfx/win/direct_manipulation.cc +++ b/ui/gfx/win/direct_manipulation.cc
@@ -44,13 +44,13 @@ hr = manager_->GetUpdateManager(IID_PPV_ARGS(update_manager_.Receive())); CHECK(SUCCEEDED(hr)); - hr = compositor_->SetUpdateManager(update_manager_.get()); + hr = compositor_->SetUpdateManager(update_manager_.Get()); CHECK(SUCCEEDED(hr)); - hr = frame_info_.QueryFrom(compositor_.get()); + hr = frame_info_.QueryFrom(compositor_.Get()); CHECK(SUCCEEDED(hr)); - hr = manager_->CreateViewport(frame_info_.get(), window, + hr = manager_->CreateViewport(frame_info_.Get(), window, IID_PPV_ARGS(view_port_outer_.Receive())); CHECK(SUCCEEDED(hr)); @@ -79,7 +79,7 @@ CHECK(SUCCEEDED(hr)); base::win::ScopedComPtr<IDirectManipulationContent> content_outer; - hr = content_outer.QueryFrom(primary_content_outer.get()); + hr = content_outer.QueryFrom(primary_content_outer.Get()); CHECK(SUCCEEDED(hr)); RECT rect = bounds.ToRECT();
diff --git a/ui/gfx/win/direct_write.cc b/ui/gfx/win/direct_write.cc index 05ec863..8645ae85 100644 --- a/ui/gfx/win/direct_write.cc +++ b/ui/gfx/win/direct_write.cc
@@ -55,11 +55,11 @@ // interface fails with E_INVALIDARG on certain Windows 7 gold versions // (6.1.7600.*). We should just use GDI in these cases. sk_sp<SkFontMgr> direct_write_font_mgr = - SkFontMgr_New_DirectWrite(factory.get()); + SkFontMgr_New_DirectWrite(factory.Get()); if (!direct_write_font_mgr) return; SetDefaultSkiaFactory(std::move(direct_write_font_mgr)); - gfx::PlatformFontWin::SetDirectWriteFactory(factory.get()); + gfx::PlatformFontWin::SetDirectWriteFactory(factory.Get()); } } // namespace win
diff --git a/ui/gl/gl_angle_util_win.cc b/ui/gl/gl_angle_util_win.cc index 6bd8faab0..00cef7f 100644 --- a/ui/gl/gl_angle_util_win.cc +++ b/ui/gl/gl_angle_util_win.cc
@@ -97,7 +97,7 @@ if (!d3d11_device) return dcomp_device; - UINT data_size = sizeof(dcomp_device.get()); + UINT data_size = sizeof(dcomp_device.Get()); HRESULT hr = d3d11_device->GetPrivateData(kDirectCompositionGUID, &data_size, dcomp_device.ReceiveVoid()); if (SUCCEEDED(hr) && dcomp_device) @@ -119,7 +119,7 @@ base::win::ScopedComPtr<IDXGIDevice> dxgi_device; d3d11_device.QueryInterface(dxgi_device.Receive()); base::win::ScopedComPtr<IDCompositionDesktopDevice> desktop_device; - hr = create_device_function(dxgi_device.get(), + hr = create_device_function(dxgi_device.Get(), IID_PPV_ARGS(desktop_device.Receive())); if (FAILED(hr)) return dcomp_device; @@ -127,7 +127,7 @@ hr = desktop_device.QueryInterface(dcomp_device.Receive()); CHECK(SUCCEEDED(hr)); d3d11_device->SetPrivateDataInterface(kDirectCompositionGUID, - dcomp_device.get()); + dcomp_device.Get()); return dcomp_device; }
diff --git a/ui/views/accessibility/native_view_accessibility_win_unittest.cc b/ui/views/accessibility/native_view_accessibility_win_unittest.cc index 2cf7144..3265ee7 100644 --- a/ui/views/accessibility/native_view_accessibility_win_unittest.cc +++ b/ui/views/accessibility/native_view_accessibility_win_unittest.cc
@@ -132,7 +132,7 @@ child_widget_sibling_dispatch = V_DISPATCH(result.ptr()); ASSERT_EQ(S_OK, child_widget_sibling_dispatch.QueryInterface( child_widget_sibling_accessible.Receive())); - ASSERT_EQ(child_view_accessible.get(), child_widget_sibling_accessible.get()); + ASSERT_EQ(child_view_accessible.Get(), child_widget_sibling_accessible.Get()); ScopedComPtr<IDispatch> child_widget_parent_dispatch; ScopedComPtr<IAccessible> child_widget_parent_accessible; @@ -140,7 +140,7 @@ child_widget_parent_dispatch.Receive())); ASSERT_EQ(S_OK, child_widget_parent_dispatch.QueryInterface( child_widget_parent_accessible.Receive())); - ASSERT_EQ(root_view_accessible.get(), child_widget_parent_accessible.get()); + ASSERT_EQ(root_view_accessible.Get(), child_widget_parent_accessible.Get()); } // Flaky on Windows: https://crbug.com/461837.